tutuca 0.13.2 → 0.14.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/tutuca-cli.js +611 -458
- package/dist/tutuca-dev.ext.js +642 -486
- package/dist/tutuca-dev.js +653 -497
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +625 -451
- package/dist/tutuca-extra.js +632 -458
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +625 -451
- package/dist/tutuca.js +632 -458
- package/dist/tutuca.min.js +3 -3
- package/package.json +1 -1
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +48 -17
- package/skill/tutuca/component-design.md +2 -2
- package/skill/tutuca/core.md +7 -1
- package/skill/tutuca/messages-and-intents.md +1 -1
- package/skill/tutuca/patterns/README.md +1 -1
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +11 -6
- package/skill/tutuca/patterns/share-state-across-the-tree.md +18 -3
- package/skill/tutuca/semantics.md +43 -28
- package/skill/tutuca-source/tutuca.ext.js +625 -451
package/dist/tutuca-extra.ext.js
CHANGED
|
@@ -76,8 +76,11 @@ var Step = class {
|
|
|
76
76
|
}
|
|
77
77
|
setDraftValue(_root, _v) {
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
80
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
81
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
82
|
+
enterFrame(stack, next, renderPath) {
|
|
83
|
+
return stack.enter(next, {}, true, renderPath);
|
|
81
84
|
}
|
|
82
85
|
toAbstractPathStep() {
|
|
83
86
|
return this;
|
|
@@ -102,8 +105,8 @@ var BindStep = class _BindStep extends Step {
|
|
|
102
105
|
lookup(v, _dval) {
|
|
103
106
|
return v;
|
|
104
107
|
}
|
|
105
|
-
enterFrame(stack, next) {
|
|
106
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
108
|
+
enterFrame(stack, next, renderPath) {
|
|
109
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
107
110
|
}
|
|
108
111
|
withIndex(i) {
|
|
109
112
|
return new _BindStep({ ...this.binds, key: i });
|
|
@@ -120,9 +123,9 @@ var ScopeBindStep = class _ScopeBindStep extends BindStep {
|
|
|
120
123
|
super(binds);
|
|
121
124
|
this.val = val;
|
|
122
125
|
}
|
|
123
|
-
enterFrame(stack, next) {
|
|
126
|
+
enterFrame(stack, next, renderPath) {
|
|
124
127
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
125
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
128
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
126
129
|
}
|
|
127
130
|
withIndex(i) {
|
|
128
131
|
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
@@ -165,8 +168,8 @@ var SeqStep = class extends Step {
|
|
|
165
168
|
const seq = readKey(root, this.field, null);
|
|
166
169
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
167
170
|
}
|
|
168
|
-
enterFrame(stack, next) {
|
|
169
|
-
return stack.enter(next, { key: this.key }, true);
|
|
171
|
+
enterFrame(stack, next, renderPath) {
|
|
172
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
170
173
|
}
|
|
171
174
|
toKey() {
|
|
172
175
|
return { field: this.field, key: this.key };
|
|
@@ -212,60 +215,52 @@ var EachBindStep = class extends Step {
|
|
|
212
215
|
}
|
|
213
216
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
214
217
|
// so a rebuilt stack matches the one @each rendered with.
|
|
215
|
-
enterFrame(stack, next) {
|
|
216
|
-
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false);
|
|
218
|
+
enterFrame(stack, next, renderPath) {
|
|
219
|
+
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false, renderPath);
|
|
217
220
|
}
|
|
218
221
|
toAbstractPathStep() {
|
|
219
222
|
return null;
|
|
220
223
|
}
|
|
221
224
|
};
|
|
222
225
|
var EachRenderItStep = class extends SeqStep {
|
|
223
|
-
enterFrame(stack, next) {
|
|
224
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
226
|
+
enterFrame(stack, next, renderPath) {
|
|
227
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
225
228
|
}
|
|
226
229
|
toAbstractPathStep() {
|
|
227
230
|
return new SeqStep(this.field, this.key);
|
|
228
231
|
}
|
|
229
232
|
};
|
|
230
|
-
function
|
|
231
|
-
|
|
233
|
+
function stepToJson(step) {
|
|
234
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
235
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
236
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
237
|
+
return null;
|
|
232
238
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
warnRawDynStep("lookup", this);
|
|
246
|
-
return dval;
|
|
247
|
-
}
|
|
248
|
-
enterFrame(stack, _next) {
|
|
249
|
-
warnRawDynStep("enterFrame", this);
|
|
250
|
-
return stack;
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
var DynEachStep = class extends DynStep {
|
|
254
|
-
constructor(producerCompId, producerSteps, key) {
|
|
255
|
-
super(producerCompId, producerSteps);
|
|
256
|
-
this.key = key;
|
|
257
|
-
}
|
|
258
|
-
teleportSteps() {
|
|
259
|
-
const { producerSteps, key } = this;
|
|
260
|
-
if (producerSteps.length === 0) return producerSteps;
|
|
261
|
-
const last = producerSteps[producerSteps.length - 1];
|
|
262
|
-
if (!(last instanceof FieldStep)) {
|
|
263
|
-
console.warn("DynEachStep: seq-access dynamic cannot be iterated", this);
|
|
264
|
-
return producerSteps;
|
|
265
|
-
}
|
|
266
|
-
return producerSteps.slice(0, -1).concat(new SeqStep(last.field, key));
|
|
239
|
+
function stepFromJson(j) {
|
|
240
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
241
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
242
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
243
|
+
return new FieldStep(j.f);
|
|
244
|
+
}
|
|
245
|
+
function pathToJson(path2) {
|
|
246
|
+
const out = [];
|
|
247
|
+
for (const step of path2.steps) {
|
|
248
|
+
const j = stepToJson(step);
|
|
249
|
+
if (j === null) return null;
|
|
250
|
+
out.push(j);
|
|
267
251
|
}
|
|
268
|
-
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
function pathFromJson(j) {
|
|
255
|
+
if (!Array.isArray(j)) return null;
|
|
256
|
+
const steps = [];
|
|
257
|
+
for (const item of j) {
|
|
258
|
+
const step = stepFromJson(item);
|
|
259
|
+
if (step === null) return null;
|
|
260
|
+
steps.push(step);
|
|
261
|
+
}
|
|
262
|
+
return new Path(steps);
|
|
263
|
+
}
|
|
269
264
|
var Path = class _Path {
|
|
270
265
|
constructor(steps = []) {
|
|
271
266
|
this.steps = steps;
|
|
@@ -276,40 +271,13 @@ var Path = class _Path {
|
|
|
276
271
|
popStep() {
|
|
277
272
|
return new _Path(this.steps.slice(0, -1));
|
|
278
273
|
}
|
|
279
|
-
//
|
|
280
|
-
//
|
|
274
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
275
|
+
// result bubbles through every component.
|
|
281
276
|
compact() {
|
|
282
277
|
const out = [];
|
|
283
278
|
for (const step of this.steps) {
|
|
284
279
|
const s = step.toAbstractPathStep();
|
|
285
|
-
if (s !== null)
|
|
286
|
-
if (s !== step) s._originCid = step._originCid;
|
|
287
|
-
out.push(s);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return new _Path(out);
|
|
291
|
-
}
|
|
292
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
293
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
294
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
295
|
-
// location. A path with no DynStep is returned unchanged.
|
|
296
|
-
toTransactionPath() {
|
|
297
|
-
let hasDyn = false;
|
|
298
|
-
for (const step of this.steps)
|
|
299
|
-
if (step instanceof DynStep) {
|
|
300
|
-
hasDyn = true;
|
|
301
|
-
break;
|
|
302
|
-
}
|
|
303
|
-
if (!hasDyn) return this;
|
|
304
|
-
const out = [];
|
|
305
|
-
for (const step of this.steps) {
|
|
306
|
-
if (step instanceof DynStep) {
|
|
307
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
308
|
-
for (const ts of step.teleportSteps()) {
|
|
309
|
-
ts._originCid = step.producerCompId;
|
|
310
|
-
out.push(ts);
|
|
311
|
-
}
|
|
312
|
-
} else out.push(step);
|
|
280
|
+
if (s !== null) out.push(s);
|
|
313
281
|
}
|
|
314
282
|
return new _Path(out);
|
|
315
283
|
}
|
|
@@ -317,7 +285,6 @@ var Path = class _Path {
|
|
|
317
285
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
318
286
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
319
287
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
320
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
321
288
|
pinKeys(root) {
|
|
322
289
|
let curVal = root;
|
|
323
290
|
let out = null;
|
|
@@ -340,8 +307,8 @@ var Path = class _Path {
|
|
|
340
307
|
}
|
|
341
308
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
342
309
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
343
|
-
// unresolvable step.
|
|
344
|
-
//
|
|
310
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
311
|
+
// (filter via Components.getCompFor).
|
|
345
312
|
resolveChain(root) {
|
|
346
313
|
const out = [root];
|
|
347
314
|
let curVal = root;
|
|
@@ -355,7 +322,7 @@ var Path = class _Path {
|
|
|
355
322
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
356
323
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
357
324
|
// activity log) can identify which subtree a transaction touched without
|
|
358
|
-
// depending on Step internals.
|
|
325
|
+
// depending on Step internals.
|
|
359
326
|
toKeys() {
|
|
360
327
|
const out = [];
|
|
361
328
|
for (const step of this.steps) {
|
|
@@ -376,62 +343,147 @@ var Path = class _Path {
|
|
|
376
343
|
});
|
|
377
344
|
}
|
|
378
345
|
buildStack(stack) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
346
|
+
return walkItems(stack, this.steps, stack.renderPath ?? new DispatchPath(), this)?.[0] ?? null;
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
function walkItems(stack, items, renderPath, path2) {
|
|
350
|
+
let prev = stack.it;
|
|
351
|
+
for (const step of items) {
|
|
352
|
+
const next = step.lookup(prev, NONE);
|
|
353
|
+
if (next === NONE) {
|
|
354
|
+
console.warn("bad PathItem", { root: stack.it, step, path: path2 });
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
renderPath = renderPath.pushItem(step);
|
|
358
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
359
|
+
prev = next;
|
|
360
|
+
}
|
|
361
|
+
return [stack, renderPath];
|
|
362
|
+
}
|
|
363
|
+
var EMPTY_PATH = new Path([]);
|
|
364
|
+
var DispatchPath = class _DispatchPath {
|
|
365
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
366
|
+
this.frames = frames;
|
|
367
|
+
}
|
|
368
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
369
|
+
// by "this position" when it has no continuation of its own.
|
|
370
|
+
static ofSteps(steps) {
|
|
371
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
372
|
+
}
|
|
373
|
+
get top() {
|
|
374
|
+
return this.frames[this.frames.length - 1];
|
|
375
|
+
}
|
|
376
|
+
_withTopItems(items) {
|
|
377
|
+
const frames = this.frames.slice();
|
|
378
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
379
|
+
return new _DispatchPath(frames);
|
|
380
|
+
}
|
|
381
|
+
concat(steps) {
|
|
382
|
+
if (this.frames.length === 0) return _DispatchPath.ofSteps(steps);
|
|
383
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
384
|
+
}
|
|
385
|
+
pushItem(step) {
|
|
386
|
+
return this.concat([step]);
|
|
387
|
+
}
|
|
388
|
+
pushFrame(base) {
|
|
389
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
390
|
+
}
|
|
391
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
392
|
+
// visual caller underneath it.
|
|
393
|
+
canPop() {
|
|
394
|
+
const n = this.frames.length;
|
|
395
|
+
return n > 1 || n === 1 && this.frames[0].items.length > 0;
|
|
396
|
+
}
|
|
397
|
+
isRoot() {
|
|
398
|
+
return this.toTransactionPath().steps.length === 0;
|
|
399
|
+
}
|
|
400
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
401
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
402
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
403
|
+
popStep() {
|
|
404
|
+
const n = this.frames.length;
|
|
405
|
+
if (n === 0) return this;
|
|
406
|
+
const top = this.frames[n - 1];
|
|
407
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
408
|
+
if (n > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
409
|
+
return this;
|
|
410
|
+
}
|
|
411
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
412
|
+
// already addressing-only.
|
|
413
|
+
compact() {
|
|
414
|
+
return new _DispatchPath(
|
|
415
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
419
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
420
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
421
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
422
|
+
// that differ only in binds do render the same subtree.
|
|
423
|
+
get addressKey() {
|
|
424
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
425
|
+
return this._addressKey;
|
|
426
|
+
}
|
|
427
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
428
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
429
|
+
toTransactionPath() {
|
|
430
|
+
const top = this.top;
|
|
431
|
+
return top === void 0 ? EMPTY_PATH : top.base.concat(top.items);
|
|
432
|
+
}
|
|
433
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
434
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
435
|
+
// render performed — and then walks its ordinary items.
|
|
436
|
+
buildStack(stack) {
|
|
437
|
+
let renderPath = new _DispatchPath();
|
|
438
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
439
|
+
const { base, items } = this.frames[i];
|
|
440
|
+
if (i > 0 || base.steps.length > 0) {
|
|
441
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
442
|
+
if (baseValue === NONE) {
|
|
443
|
+
console.warn("bad frame base", { base, path: this });
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
renderPath = renderPath.pushFrame(base);
|
|
447
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
385
448
|
}
|
|
386
|
-
|
|
387
|
-
|
|
449
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
450
|
+
if (walked === null) return null;
|
|
451
|
+
[stack, renderPath] = walked;
|
|
388
452
|
}
|
|
389
453
|
return stack;
|
|
390
454
|
}
|
|
391
455
|
static fromNodeAndEventName(node, eventName, rootNode, maxDepth, comps, stopOnNoEvent = true) {
|
|
392
|
-
const
|
|
393
|
-
const pendingDyns = [];
|
|
456
|
+
const parts = [];
|
|
394
457
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
395
458
|
let depth = 0;
|
|
396
459
|
let eventIds = [];
|
|
397
460
|
let handlers = null;
|
|
398
|
-
let
|
|
461
|
+
let nodeRefs = [];
|
|
399
462
|
let isLeafComponent = true;
|
|
400
463
|
const crossComponent = (cidNum, vid) => {
|
|
401
464
|
const comp = comps.getComponentForId(cidNum);
|
|
402
|
-
let
|
|
465
|
+
let pushPart = true;
|
|
403
466
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
404
467
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
405
468
|
if (handlers === null) {
|
|
406
469
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
407
470
|
} else if (!isLeafComponent) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
pushStep = false;
|
|
471
|
+
parts.length = 0;
|
|
472
|
+
pushPart = false;
|
|
411
473
|
}
|
|
412
474
|
}
|
|
413
475
|
isLeafComponent = false;
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (step) {
|
|
418
|
-
step._originCid = cidNum;
|
|
419
|
-
pathSteps.push(step);
|
|
420
|
-
if (step instanceof DynStep) {
|
|
421
|
-
step.interiorCids.add(cidNum);
|
|
422
|
-
pendingDyns.push(step);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
476
|
+
if (pushPart) {
|
|
477
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
478
|
+
if (part) parts.push(part);
|
|
425
479
|
}
|
|
426
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
427
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
428
480
|
eventIds = [];
|
|
429
|
-
|
|
481
|
+
nodeRefs = [];
|
|
430
482
|
return true;
|
|
431
483
|
};
|
|
432
484
|
while (node && node !== rootNode && depth < maxDepth) {
|
|
433
485
|
if (node?.dataset) {
|
|
434
|
-
const { eid, cid, vid } = node.dataset;
|
|
486
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
435
487
|
if (eid !== void 0) eventIds.push(eid);
|
|
436
488
|
const metas = metaChain(node.previousSibling);
|
|
437
489
|
let sawComp = false;
|
|
@@ -439,21 +491,47 @@ var Path = class _Path {
|
|
|
439
491
|
if (m.$ === "Comp") {
|
|
440
492
|
sawComp = true;
|
|
441
493
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
442
|
-
|
|
494
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
443
495
|
} else {
|
|
444
|
-
|
|
496
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (!sawComp && cid !== void 0) {
|
|
500
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
501
|
+
if (rp !== void 0) {
|
|
502
|
+
const base = parseRenderPath(rp);
|
|
503
|
+
if (base !== null) nodeRefs.push({ base });
|
|
445
504
|
}
|
|
446
505
|
}
|
|
447
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
448
506
|
}
|
|
449
507
|
depth += 1;
|
|
450
508
|
node = node.parentNode;
|
|
451
509
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
510
|
+
parts.reverse();
|
|
511
|
+
let path2 = new _DispatchPath();
|
|
512
|
+
for (const part of parts)
|
|
513
|
+
path2 = part.base !== void 0 ? path2.pushFrame(part.base) : path2.pushItem(part.step);
|
|
514
|
+
return [path2, handlers];
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
function keyedPath(path2, key) {
|
|
518
|
+
const steps = path2.steps;
|
|
519
|
+
const last = steps[steps.length - 1];
|
|
520
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
521
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
function renderPathText(path2) {
|
|
525
|
+
return JSON.stringify(pathToJson(path2));
|
|
526
|
+
}
|
|
527
|
+
function parseRenderPath(text) {
|
|
528
|
+
try {
|
|
529
|
+
return pathFromJson(JSON.parse(text));
|
|
530
|
+
} catch (err) {
|
|
531
|
+
console.warn("bad render path", err, text);
|
|
532
|
+
return null;
|
|
455
533
|
}
|
|
456
|
-
}
|
|
534
|
+
}
|
|
457
535
|
function metaChain(n) {
|
|
458
536
|
const out = [];
|
|
459
537
|
while (n?.nodeType === 8 && n.textContent[0] === "§") {
|
|
@@ -506,20 +584,27 @@ var StepCtx = class _StepCtx {
|
|
|
506
584
|
return pi;
|
|
507
585
|
}
|
|
508
586
|
};
|
|
509
|
-
function
|
|
510
|
-
for (let i = 0; i <
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
if (
|
|
587
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
588
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
589
|
+
const ref = nodeRefs[i];
|
|
590
|
+
if (ref.base != null) return { base: ref.base };
|
|
591
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
592
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
593
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
594
|
+
if (step !== null) return { step };
|
|
514
595
|
}
|
|
515
596
|
return null;
|
|
516
597
|
}
|
|
517
598
|
var NO_EVENT_INFO = [null, null];
|
|
518
599
|
var BUBBLING_EVENTS = /* @__PURE__ */ new Set(["drop"]);
|
|
600
|
+
var path = () => new PathBuilder();
|
|
519
601
|
var PathBuilder = class {
|
|
520
602
|
constructor() {
|
|
521
603
|
this.pathChanges = [];
|
|
522
604
|
}
|
|
605
|
+
toPath() {
|
|
606
|
+
return new Path(this.pathChanges);
|
|
607
|
+
}
|
|
523
608
|
add(pathChange) {
|
|
524
609
|
this.pathChanges.push(pathChange);
|
|
525
610
|
return this;
|
|
@@ -656,31 +741,14 @@ function parseBool(s, px) {
|
|
|
656
741
|
const val = parseToken(tokens[0], px);
|
|
657
742
|
return val !== null && kindOf(val) & G_BOOL ? val : null;
|
|
658
743
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
}
|
|
668
|
-
function parseField(s, px) {
|
|
669
|
-
return _parseSingle(s, px, G_FIELD);
|
|
670
|
-
}
|
|
671
|
-
function parseProvide(s, px) {
|
|
672
|
-
return _parseSingle(s, px, G_PROVIDE);
|
|
673
|
-
}
|
|
674
|
-
function parseMacroAttr(s, px) {
|
|
675
|
-
return _parseSingle(s, px, G_ALL);
|
|
676
|
-
}
|
|
677
|
-
function parseReceiveHandler(s, px) {
|
|
678
|
-
return _parseHandler(s, px, "receive", true, true, false);
|
|
679
|
-
}
|
|
680
|
-
function parseAlterHandler(s, px) {
|
|
681
|
-
const r = _parseHandler(s, px, "alter", false, false, true);
|
|
682
|
-
return r === null ? null : r.handlerVal;
|
|
683
|
-
}
|
|
744
|
+
var parseText = (s, px) => _parseSingle(s, px, G_TEXT);
|
|
745
|
+
var parseComponent = (s, px) => _parseSingle(s, px, G_COMPONENT);
|
|
746
|
+
var parseSequence = (s, px) => _parseSingle(s, px, G_SEQUENCE);
|
|
747
|
+
var parseField = (s, px) => _parseSingle(s, px, G_FIELD);
|
|
748
|
+
var parseProvide = (s, px) => _parseSingle(s, px, G_PROVIDE);
|
|
749
|
+
var parseMacroAttr = (s, px) => _parseSingle(s, px, G_ALL);
|
|
750
|
+
var parseReceiveHandler = (s, px) => _parseHandler(s, px, "receive", true, true, false);
|
|
751
|
+
var parseAlterHandler = (s, px) => _parseHandler(s, px, "alter", false, false, true)?.handlerVal ?? null;
|
|
684
752
|
function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
|
|
685
753
|
const tokens = tokenizeValue(s.trim());
|
|
686
754
|
const headTok = tokens[0] ?? "";
|
|
@@ -1369,19 +1437,9 @@ function childOpts(vnode, ns, opts) {
|
|
|
1369
1437
|
const target = ns === SVG_NS && isForeignObject(vnode.tag) ? null : ns;
|
|
1370
1438
|
return target === (opts.namespace ?? null) ? opts : { ...opts, namespace: target };
|
|
1371
1439
|
}
|
|
1372
|
-
var NEVER_ASSIGN =
|
|
1373
|
-
"width"
|
|
1374
|
-
|
|
1375
|
-
"href",
|
|
1376
|
-
"list",
|
|
1377
|
-
"form",
|
|
1378
|
-
"tabIndex",
|
|
1379
|
-
"download",
|
|
1380
|
-
"rowSpan",
|
|
1381
|
-
"colSpan",
|
|
1382
|
-
"role",
|
|
1383
|
-
"popover"
|
|
1384
|
-
]);
|
|
1440
|
+
var NEVER_ASSIGN = new Set(
|
|
1441
|
+
"width height href list form tabIndex download rowSpan colSpan role popover".split(" ")
|
|
1442
|
+
);
|
|
1385
1443
|
var PROP_ATTR_NAME = { className: "class", htmlFor: "for" };
|
|
1386
1444
|
function applyProperties(node, props) {
|
|
1387
1445
|
const namespaced = isNamespaced(node);
|
|
@@ -1660,6 +1718,10 @@ function morphChildren(parentDom, oldChilds, newChilds, opts) {
|
|
|
1660
1718
|
if (!used[i] && domNodes[i].parentNode === parentDom) parentDom.removeChild(domNodes[i]);
|
|
1661
1719
|
}
|
|
1662
1720
|
function render(vnode, container, options, prev) {
|
|
1721
|
+
if (vnode == null) {
|
|
1722
|
+
container.replaceChildren();
|
|
1723
|
+
return { vnode: null, dom: null };
|
|
1724
|
+
}
|
|
1663
1725
|
const isFragment = vnode instanceof VFragment;
|
|
1664
1726
|
if (prev && prev.vnode instanceof VFragment === isFragment) {
|
|
1665
1727
|
const oldDom = isFragment ? container : prev.dom;
|
|
@@ -1699,13 +1761,16 @@ function h(tagName, properties, children, namespace) {
|
|
|
1699
1761
|
}
|
|
1700
1762
|
|
|
1701
1763
|
// src/anode.js
|
|
1702
|
-
function
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1764
|
+
function renderTarget(val, stack) {
|
|
1765
|
+
if (val instanceof DynVal) {
|
|
1766
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
1767
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
1768
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
1769
|
+
}
|
|
1770
|
+
const step = val.toPathItem?.() ?? null;
|
|
1771
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
1772
|
+
const path2 = stack.renderPath.pushItem(step);
|
|
1773
|
+
return [val.eval(stack), path2, stack.pendingFrame ? path2.toTransactionPath() : null];
|
|
1709
1774
|
}
|
|
1710
1775
|
var BaseNode = class {
|
|
1711
1776
|
render(_stack, _rx) {
|
|
@@ -2027,33 +2092,31 @@ var RenderViewId = class extends ANode {
|
|
|
2027
2092
|
setDataAttr(_key, _val) {
|
|
2028
2093
|
}
|
|
2029
2094
|
};
|
|
2030
|
-
function dynRenderStep(comp, name, key) {
|
|
2031
|
-
const p = resolveDynProducer(comp, name);
|
|
2032
|
-
if (!p) return null;
|
|
2033
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2034
|
-
}
|
|
2035
2095
|
var RenderNode = class extends RenderViewId {
|
|
2036
2096
|
render(stack, rx) {
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2097
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
2098
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
2099
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
2039
2100
|
}
|
|
2101
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
2102
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
2040
2103
|
toPathStep(ctx) {
|
|
2041
|
-
if (this.val instanceof DynVal) return
|
|
2104
|
+
if (this.val instanceof DynVal) return null;
|
|
2042
2105
|
return super.toPathStep(ctx);
|
|
2043
2106
|
}
|
|
2044
2107
|
};
|
|
2045
2108
|
var RenderItNode = class extends RenderViewId {
|
|
2046
2109
|
render(stack, rx) {
|
|
2047
|
-
const
|
|
2048
|
-
|
|
2110
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
2111
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
2112
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
2049
2113
|
}
|
|
2050
2114
|
toPathStep(ctx) {
|
|
2051
2115
|
const next = ctx.next();
|
|
2052
2116
|
if (next === null) return null;
|
|
2053
2117
|
const nextNode = next.resolveNode();
|
|
2054
2118
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
2055
|
-
if (nextNode.val instanceof DynVal)
|
|
2056
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
2119
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
2057
2120
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
2058
2121
|
}
|
|
2059
2122
|
return null;
|
|
@@ -2155,11 +2218,19 @@ var EachNode = class extends WrapperNode {
|
|
|
2155
2218
|
this.iterInfo = new IterInfo(val, null, null, null);
|
|
2156
2219
|
}
|
|
2157
2220
|
render(stack, rx) {
|
|
2158
|
-
return rx.renderEachWhen(stack, this
|
|
2221
|
+
return rx.renderEachWhen(stack, this);
|
|
2159
2222
|
}
|
|
2160
2223
|
toPathStep(ctx) {
|
|
2161
2224
|
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
2162
2225
|
}
|
|
2226
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
2227
|
+
// whether or not the body is a component, so the position moves either way and
|
|
2228
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
2229
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
2230
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
2231
|
+
itemStep(key) {
|
|
2232
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
2233
|
+
}
|
|
2163
2234
|
static register = true;
|
|
2164
2235
|
};
|
|
2165
2236
|
var IterInfo = class {
|
|
@@ -2420,6 +2491,215 @@ function compileModifiers(eventName, names) {
|
|
|
2420
2491
|
};
|
|
2421
2492
|
}
|
|
2422
2493
|
|
|
2494
|
+
// src/stack.js
|
|
2495
|
+
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
2496
|
+
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
2497
|
+
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
2498
|
+
function routeLookup(route, lex, dyn) {
|
|
2499
|
+
for (let i = 0; i < route.length; i++) {
|
|
2500
|
+
const leg = route[i];
|
|
2501
|
+
if (leg === "dyn") {
|
|
2502
|
+
const v = dyn();
|
|
2503
|
+
if (v != null) return v;
|
|
2504
|
+
} else if (leg === "lex") {
|
|
2505
|
+
const v = lex();
|
|
2506
|
+
if (v != null) return v;
|
|
2507
|
+
} else {
|
|
2508
|
+
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
return null;
|
|
2512
|
+
}
|
|
2513
|
+
var isTypeName = (s) => {
|
|
2514
|
+
const c = s.charCodeAt(0);
|
|
2515
|
+
return c >= 65 && c <= 90;
|
|
2516
|
+
};
|
|
2517
|
+
function lookup(chain, name, dv = null) {
|
|
2518
|
+
let n = chain;
|
|
2519
|
+
while (n !== null) {
|
|
2520
|
+
const r = n[0].lookup(name);
|
|
2521
|
+
if (r === STOP) return dv;
|
|
2522
|
+
if (r !== NEXT) return r;
|
|
2523
|
+
n = n[1];
|
|
2524
|
+
}
|
|
2525
|
+
return dv;
|
|
2526
|
+
}
|
|
2527
|
+
var BindFrame = class {
|
|
2528
|
+
constructor(it, binds, isFrame) {
|
|
2529
|
+
this.it = it;
|
|
2530
|
+
this.binds = binds;
|
|
2531
|
+
this.isFrame = isFrame;
|
|
2532
|
+
}
|
|
2533
|
+
lookup(name) {
|
|
2534
|
+
const v = this.binds[name];
|
|
2535
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
var DynFrame = class {
|
|
2539
|
+
constructor(binds, types) {
|
|
2540
|
+
this.binds = binds;
|
|
2541
|
+
this.types = types;
|
|
2542
|
+
}
|
|
2543
|
+
lookup(name) {
|
|
2544
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
2545
|
+
return v === void 0 ? NEXT : v;
|
|
2546
|
+
}
|
|
2547
|
+
};
|
|
2548
|
+
function computeViewsId(views) {
|
|
2549
|
+
let s = "";
|
|
2550
|
+
let n = views;
|
|
2551
|
+
while (n !== null) {
|
|
2552
|
+
s += n[0];
|
|
2553
|
+
n = n[1];
|
|
2554
|
+
}
|
|
2555
|
+
return s === "main" ? "" : s;
|
|
2556
|
+
}
|
|
2557
|
+
var Stack = class _Stack {
|
|
2558
|
+
constructor(fields) {
|
|
2559
|
+
Object.assign(this, fields);
|
|
2560
|
+
}
|
|
2561
|
+
_with(patch) {
|
|
2562
|
+
return new _Stack({ ...this, ...patch });
|
|
2563
|
+
}
|
|
2564
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
2565
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
2566
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
2567
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
2568
|
+
// frame's other map. No-op with no provides.
|
|
2569
|
+
_pushProvides() {
|
|
2570
|
+
const comp = this.comps.getCompFor(this.it);
|
|
2571
|
+
if (comp == null) return this;
|
|
2572
|
+
const { provide, provideType } = comp;
|
|
2573
|
+
const binds = {};
|
|
2574
|
+
const types = {};
|
|
2575
|
+
let has = false;
|
|
2576
|
+
const base = this._publishBase();
|
|
2577
|
+
for (const k in provide) {
|
|
2578
|
+
const step = provide[k].val.toPathItem?.() ?? null;
|
|
2579
|
+
if (step === null) continue;
|
|
2580
|
+
const value = provide[k].val.eval(this);
|
|
2581
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
2582
|
+
has = true;
|
|
2583
|
+
}
|
|
2584
|
+
for (const k in provideType) {
|
|
2585
|
+
types[k] = provideType[k];
|
|
2586
|
+
has = true;
|
|
2587
|
+
}
|
|
2588
|
+
if (!has) return this;
|
|
2589
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
2590
|
+
}
|
|
2591
|
+
// The absolute address of the component being entered, or null when this
|
|
2592
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
2593
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
2594
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
2595
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
2596
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
2597
|
+
//
|
|
2598
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
2599
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
2600
|
+
// editing whatever happens to live at the address we guessed.
|
|
2601
|
+
_publishBase() {
|
|
2602
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
2603
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
2604
|
+
}
|
|
2605
|
+
static root(comps, it, ctx = null) {
|
|
2606
|
+
return new _Stack({
|
|
2607
|
+
comps,
|
|
2608
|
+
root: it,
|
|
2609
|
+
it,
|
|
2610
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
2611
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
2612
|
+
views: ["main", null],
|
|
2613
|
+
viewsId: "",
|
|
2614
|
+
renderPath: new DispatchPath(),
|
|
2615
|
+
pendingFrame: false,
|
|
2616
|
+
ctx
|
|
2617
|
+
})._pushProvides();
|
|
2618
|
+
}
|
|
2619
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
2620
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
2621
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
2622
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
2623
|
+
const stack = this._with({
|
|
2624
|
+
it,
|
|
2625
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
2626
|
+
renderPath,
|
|
2627
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
2628
|
+
});
|
|
2629
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
2630
|
+
}
|
|
2631
|
+
pushViewName(name) {
|
|
2632
|
+
const views = [name, this.views];
|
|
2633
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
2634
|
+
}
|
|
2635
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
2636
|
+
// the cache key covers values alone.
|
|
2637
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
2638
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
2639
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
2640
|
+
}
|
|
2641
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
2642
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
2643
|
+
// scope, else this component's declared default, else null.
|
|
2644
|
+
//
|
|
2645
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
2646
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
2647
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
2648
|
+
// consulted only after the whole chain has missed.
|
|
2649
|
+
lookupDynamicLocated(name) {
|
|
2650
|
+
if (isTypeName(name)) return null;
|
|
2651
|
+
const v = lookup(this.dynBinds, name);
|
|
2652
|
+
if (v != null) return v;
|
|
2653
|
+
const comp = this.comps.getCompFor(this.it);
|
|
2654
|
+
if (comp == null) return null;
|
|
2655
|
+
const path2 = comp.scope?.lookupPath?.(name) ?? null;
|
|
2656
|
+
if (path2 !== null) {
|
|
2657
|
+
const value2 = path2.lookup(this.root, NOT_FOUND);
|
|
2658
|
+
if (value2 !== NOT_FOUND) return { value: value2, path: path2 };
|
|
2659
|
+
}
|
|
2660
|
+
const dval = comp.lookup[name]?.val ?? null;
|
|
2661
|
+
if (dval === null) return null;
|
|
2662
|
+
const step = dval.toPathItem?.() ?? null;
|
|
2663
|
+
const value = dval.eval(this);
|
|
2664
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
2665
|
+
}
|
|
2666
|
+
lookupDynamic(name) {
|
|
2667
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
2668
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
2669
|
+
}
|
|
2670
|
+
lookupBind(name) {
|
|
2671
|
+
return lookup(this.binds, name);
|
|
2672
|
+
}
|
|
2673
|
+
lookupFieldRaw(name) {
|
|
2674
|
+
return this.it[name] ?? null;
|
|
2675
|
+
}
|
|
2676
|
+
lookupMethod(name) {
|
|
2677
|
+
const fn = this.it[name];
|
|
2678
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
2679
|
+
}
|
|
2680
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
2681
|
+
// `e.<member>` handler args. Null outside a live event transaction.
|
|
2682
|
+
lookupEvent() {
|
|
2683
|
+
return this.ctx?.event ?? null;
|
|
2684
|
+
}
|
|
2685
|
+
lookupDragInfo() {
|
|
2686
|
+
return this.ctx?.dragInfo ?? null;
|
|
2687
|
+
}
|
|
2688
|
+
getHandlerFor(name, key) {
|
|
2689
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
2690
|
+
}
|
|
2691
|
+
lookupBestView(views, defaultViewName) {
|
|
2692
|
+
let n = this.views;
|
|
2693
|
+
while (n !== null) {
|
|
2694
|
+
const view = views[n[0]];
|
|
2695
|
+
if (view !== void 0) return view;
|
|
2696
|
+
n = n[1];
|
|
2697
|
+
}
|
|
2698
|
+
return views[defaultViewName];
|
|
2699
|
+
}
|
|
2700
|
+
};
|
|
2701
|
+
var NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
2702
|
+
|
|
2423
2703
|
// src/components.js
|
|
2424
2704
|
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
2425
2705
|
var Components = class {
|
|
@@ -2458,12 +2738,14 @@ var ComponentStack = class _ComponentStack {
|
|
|
2458
2738
|
this.byName = {};
|
|
2459
2739
|
this.intentsByName = {};
|
|
2460
2740
|
this.macros = {};
|
|
2741
|
+
this.paths = {};
|
|
2461
2742
|
}
|
|
2462
2743
|
enter() {
|
|
2463
2744
|
return new _ComponentStack(this.comps, this);
|
|
2464
2745
|
}
|
|
2465
2746
|
registerComponents(comps, opts) {
|
|
2466
|
-
const { aliases = {} } = opts ?? {};
|
|
2747
|
+
const { aliases = {}, paths } = opts ?? {};
|
|
2748
|
+
if (paths) this.registerPaths(paths);
|
|
2467
2749
|
for (let i = 0; i < comps.length; i++) {
|
|
2468
2750
|
const Comp = comps[i];
|
|
2469
2751
|
Comp[COMPONENT].scope = this.enter();
|
|
@@ -2477,6 +2759,27 @@ var ComponentStack = class _ComponentStack {
|
|
|
2477
2759
|
else console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
2478
2760
|
}
|
|
2479
2761
|
}
|
|
2762
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
2763
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
2764
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
2765
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
2766
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
2767
|
+
// scope to narrow a name; nearest registration wins.
|
|
2768
|
+
//
|
|
2769
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
2770
|
+
// answers, and a type has no path.
|
|
2771
|
+
registerPaths(paths) {
|
|
2772
|
+
for (const name in paths) {
|
|
2773
|
+
if (isTypeName(name)) {
|
|
2774
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
2775
|
+
continue;
|
|
2776
|
+
}
|
|
2777
|
+
this.paths[name] = paths[name].toPath?.() ?? paths[name];
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
lookupPath(name) {
|
|
2781
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
2782
|
+
}
|
|
2480
2783
|
registerMacros(macros) {
|
|
2481
2784
|
for (const key in macros) {
|
|
2482
2785
|
const lower = key.toLowerCase();
|
|
@@ -2508,17 +2811,16 @@ var ComponentStack = class _ComponentStack {
|
|
|
2508
2811
|
lookupComponent(name) {
|
|
2509
2812
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
2510
2813
|
}
|
|
2511
|
-
//
|
|
2512
|
-
// names
|
|
2513
|
-
//
|
|
2514
|
-
//
|
|
2515
|
-
//
|
|
2516
|
-
|
|
2814
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
2815
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
2816
|
+
// there is no producer to identify — several components may publish one name and
|
|
2817
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
2818
|
+
// be satisfied from one that never will be.
|
|
2819
|
+
hasProvider(name) {
|
|
2517
2820
|
for (const compName in this.byName) {
|
|
2518
|
-
|
|
2519
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
2821
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
2520
2822
|
}
|
|
2521
|
-
return this.parent?.
|
|
2823
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
2522
2824
|
}
|
|
2523
2825
|
lookupMacro(name) {
|
|
2524
2826
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
@@ -2535,10 +2837,6 @@ var LookupInfo = class {
|
|
|
2535
2837
|
}
|
|
2536
2838
|
};
|
|
2537
2839
|
var isString = (v) => typeof v === "string";
|
|
2538
|
-
var isTypeName = (s) => {
|
|
2539
|
-
const c = s.charCodeAt(0);
|
|
2540
|
-
return c >= 65 && c <= 90;
|
|
2541
|
-
};
|
|
2542
2840
|
var _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
2543
2841
|
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
2544
2842
|
var _compId = 0;
|
|
@@ -2611,160 +2909,6 @@ var Component = class {
|
|
|
2611
2909
|
}
|
|
2612
2910
|
};
|
|
2613
2911
|
|
|
2614
|
-
// src/stack.js
|
|
2615
|
-
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
2616
|
-
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
2617
|
-
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
2618
|
-
function routeLookup(route, lex, dyn) {
|
|
2619
|
-
for (let i = 0; i < route.length; i++) {
|
|
2620
|
-
const leg = route[i];
|
|
2621
|
-
if (leg === "dyn") {
|
|
2622
|
-
const v = dyn();
|
|
2623
|
-
if (v != null) return v;
|
|
2624
|
-
} else if (leg === "lex") {
|
|
2625
|
-
const v = lex();
|
|
2626
|
-
if (v != null) return v;
|
|
2627
|
-
} else {
|
|
2628
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
|
-
return null;
|
|
2632
|
-
}
|
|
2633
|
-
function lookup(chain, name, dv = null) {
|
|
2634
|
-
let n = chain;
|
|
2635
|
-
while (n !== null) {
|
|
2636
|
-
const r = n[0].lookup(name);
|
|
2637
|
-
if (r === STOP) return dv;
|
|
2638
|
-
if (r !== NEXT) return r;
|
|
2639
|
-
n = n[1];
|
|
2640
|
-
}
|
|
2641
|
-
return dv;
|
|
2642
|
-
}
|
|
2643
|
-
var BindFrame = class {
|
|
2644
|
-
constructor(it, binds, isFrame) {
|
|
2645
|
-
this.it = it;
|
|
2646
|
-
this.binds = binds;
|
|
2647
|
-
this.isFrame = isFrame;
|
|
2648
|
-
}
|
|
2649
|
-
lookup(name) {
|
|
2650
|
-
const v = this.binds[name];
|
|
2651
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
2652
|
-
}
|
|
2653
|
-
};
|
|
2654
|
-
var ObjectFrame = class {
|
|
2655
|
-
constructor(binds) {
|
|
2656
|
-
this.binds = binds;
|
|
2657
|
-
}
|
|
2658
|
-
lookup(key) {
|
|
2659
|
-
const v = this.binds[key];
|
|
2660
|
-
return v === void 0 ? NEXT : v;
|
|
2661
|
-
}
|
|
2662
|
-
};
|
|
2663
|
-
function computeViewsId(views) {
|
|
2664
|
-
let s = "";
|
|
2665
|
-
let n = views;
|
|
2666
|
-
while (n !== null) {
|
|
2667
|
-
s += n[0];
|
|
2668
|
-
n = n[1];
|
|
2669
|
-
}
|
|
2670
|
-
return s === "main" ? "" : s;
|
|
2671
|
-
}
|
|
2672
|
-
var Stack = class _Stack {
|
|
2673
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
2674
|
-
this.comps = comps;
|
|
2675
|
-
this.it = it;
|
|
2676
|
-
this.binds = binds;
|
|
2677
|
-
this.dynBinds = dynBinds;
|
|
2678
|
-
this.views = views;
|
|
2679
|
-
this.viewsId = viewsId;
|
|
2680
|
-
this.ctx = ctx;
|
|
2681
|
-
}
|
|
2682
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
2683
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
2684
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
2685
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
2686
|
-
_pushProvides() {
|
|
2687
|
-
const comp = this.comps.getCompFor(this.it);
|
|
2688
|
-
if (comp == null) return this;
|
|
2689
|
-
const { provide, provideType } = comp;
|
|
2690
|
-
const dynObj = {};
|
|
2691
|
-
let has = false;
|
|
2692
|
-
for (const k in provide) {
|
|
2693
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
2694
|
-
has = true;
|
|
2695
|
-
}
|
|
2696
|
-
for (const k in provideType) {
|
|
2697
|
-
dynObj[k] = provideType[k];
|
|
2698
|
-
has = true;
|
|
2699
|
-
}
|
|
2700
|
-
if (!has) return this;
|
|
2701
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
2702
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
2703
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
2704
|
-
}
|
|
2705
|
-
static root(comps, it, ctx) {
|
|
2706
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
2707
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
2708
|
-
const views = ["main", null];
|
|
2709
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
2710
|
-
}
|
|
2711
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
2712
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
2713
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
2714
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
2715
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
2716
|
-
}
|
|
2717
|
-
pushViewName(name) {
|
|
2718
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
2719
|
-
const newViews = [name, views];
|
|
2720
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
2721
|
-
}
|
|
2722
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
2723
|
-
// the cache key covers values alone.
|
|
2724
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
2725
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
2726
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
2727
|
-
}
|
|
2728
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
2729
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
2730
|
-
lookupDynamic(name) {
|
|
2731
|
-
const v = lookup(this.dynBinds, name);
|
|
2732
|
-
if (v != null) return v;
|
|
2733
|
-
const comp = this.comps.getCompFor(this.it);
|
|
2734
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
2735
|
-
}
|
|
2736
|
-
lookupBind(name) {
|
|
2737
|
-
return lookup(this.binds, name);
|
|
2738
|
-
}
|
|
2739
|
-
lookupFieldRaw(name) {
|
|
2740
|
-
return this.it[name] ?? null;
|
|
2741
|
-
}
|
|
2742
|
-
lookupMethod(name) {
|
|
2743
|
-
const fn = this.it[name];
|
|
2744
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
2745
|
-
}
|
|
2746
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
2747
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
2748
|
-
lookupEvent() {
|
|
2749
|
-
return this.ctx?.event ?? null;
|
|
2750
|
-
}
|
|
2751
|
-
lookupDragInfo() {
|
|
2752
|
-
return this.ctx?.dragInfo ?? null;
|
|
2753
|
-
}
|
|
2754
|
-
getHandlerFor(name, key) {
|
|
2755
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
2756
|
-
}
|
|
2757
|
-
lookupBestView(views, defaultViewName) {
|
|
2758
|
-
let n = this.views;
|
|
2759
|
-
while (n !== null) {
|
|
2760
|
-
const view = views[n[0]];
|
|
2761
|
-
if (view !== void 0) return view;
|
|
2762
|
-
n = n[1];
|
|
2763
|
-
}
|
|
2764
|
-
return views[defaultViewName];
|
|
2765
|
-
}
|
|
2766
|
-
};
|
|
2767
|
-
|
|
2768
2912
|
// src/oo.js
|
|
2769
2913
|
var BAD_VALUE = /* @__PURE__ */ Symbol("BadValue");
|
|
2770
2914
|
var nullCoercer = (v) => v;
|
|
@@ -2797,9 +2941,22 @@ var CHECK_TYPE_LIST = Array.isArray;
|
|
|
2797
2941
|
var CHECK_TYPE_OBJECT = isPlainObject;
|
|
2798
2942
|
var CHECK_TYPE_MAP = (v) => v instanceof Map;
|
|
2799
2943
|
var CHECK_TYPE_SET = (v) => v instanceof Set;
|
|
2944
|
+
var COERCE_NONE = (_v) => null;
|
|
2945
|
+
var COERCE_BOOL = (v) => !!v;
|
|
2946
|
+
var COERCE_STRING = (v) => v?.toString?.() ?? "";
|
|
2947
|
+
var COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
|
|
2948
|
+
var COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
|
|
2949
|
+
var COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
|
|
2950
|
+
var COERCE_MAP = (v) => {
|
|
2951
|
+
if (v instanceof Map) return new Map(v);
|
|
2952
|
+
if (Array.isArray(v) || isPlainObject(v))
|
|
2953
|
+
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
2954
|
+
return null;
|
|
2955
|
+
};
|
|
2956
|
+
var COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
|
|
2800
2957
|
var FieldBool = class extends Field {
|
|
2801
2958
|
constructor(name, defaultValue = false) {
|
|
2802
|
-
super("bool", name, CHECK_TYPE_BOOL,
|
|
2959
|
+
super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
|
|
2803
2960
|
}
|
|
2804
2961
|
};
|
|
2805
2962
|
var FieldAny = class extends Field {
|
|
@@ -2809,23 +2966,17 @@ var FieldAny = class extends Field {
|
|
|
2809
2966
|
};
|
|
2810
2967
|
var FieldString = class extends Field {
|
|
2811
2968
|
constructor(name, defaultValue = "") {
|
|
2812
|
-
super("text", name, CHECK_TYPE_STRING,
|
|
2969
|
+
super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
|
|
2813
2970
|
}
|
|
2814
2971
|
};
|
|
2815
2972
|
var FieldInt = class extends Field {
|
|
2816
2973
|
constructor(name, defaultValue = 0) {
|
|
2817
|
-
super(
|
|
2818
|
-
"int",
|
|
2819
|
-
name,
|
|
2820
|
-
CHECK_TYPE_INT,
|
|
2821
|
-
(v) => Number.isFinite(v) ? Math.trunc(v) : null,
|
|
2822
|
-
defaultValue
|
|
2823
|
-
);
|
|
2974
|
+
super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
|
|
2824
2975
|
}
|
|
2825
2976
|
};
|
|
2826
2977
|
var FieldFloat = class extends Field {
|
|
2827
2978
|
constructor(name, defaultValue = 0) {
|
|
2828
|
-
super("float", name, CHECK_TYPE_FLOAT,
|
|
2979
|
+
super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
|
|
2829
2980
|
}
|
|
2830
2981
|
};
|
|
2831
2982
|
var metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
|
|
@@ -2838,45 +2989,22 @@ var FieldComp = class extends Field {
|
|
|
2838
2989
|
};
|
|
2839
2990
|
var FieldList = class extends Field {
|
|
2840
2991
|
constructor(name, defaultValue = []) {
|
|
2841
|
-
super("list", name, CHECK_TYPE_LIST,
|
|
2992
|
+
super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
|
|
2842
2993
|
}
|
|
2843
2994
|
};
|
|
2844
2995
|
var FieldObject = class extends Field {
|
|
2845
2996
|
constructor(name, defaultValue = {}) {
|
|
2846
|
-
super(
|
|
2847
|
-
"object",
|
|
2848
|
-
name,
|
|
2849
|
-
CHECK_TYPE_OBJECT,
|
|
2850
|
-
(v) => isPlainObject(v) ? { ...v } : null,
|
|
2851
|
-
defaultValue
|
|
2852
|
-
);
|
|
2997
|
+
super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
|
|
2853
2998
|
}
|
|
2854
2999
|
};
|
|
2855
3000
|
var FieldMap = class extends Field {
|
|
2856
3001
|
constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
|
|
2857
|
-
super(
|
|
2858
|
-
"map",
|
|
2859
|
-
name,
|
|
2860
|
-
CHECK_TYPE_MAP,
|
|
2861
|
-
(v) => {
|
|
2862
|
-
if (v instanceof Map) return new Map(v);
|
|
2863
|
-
if (Array.isArray(v) || isPlainObject(v))
|
|
2864
|
-
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
2865
|
-
return null;
|
|
2866
|
-
},
|
|
2867
|
-
defaultValue
|
|
2868
|
-
);
|
|
3002
|
+
super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
|
|
2869
3003
|
}
|
|
2870
3004
|
};
|
|
2871
3005
|
var FieldSet = class extends Field {
|
|
2872
3006
|
constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
|
|
2873
|
-
super(
|
|
2874
|
-
"set",
|
|
2875
|
-
name,
|
|
2876
|
-
CHECK_TYPE_SET,
|
|
2877
|
-
(v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
|
|
2878
|
-
defaultValue
|
|
2879
|
-
);
|
|
3007
|
+
super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
|
|
2880
3008
|
}
|
|
2881
3009
|
};
|
|
2882
3010
|
function mkCompField(field, scope, args) {
|
|
@@ -2974,8 +3102,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
2974
3102
|
const value = fields[field];
|
|
2975
3103
|
const type = typeof value;
|
|
2976
3104
|
if (type === "string") b.addField(field, value, FieldString);
|
|
2977
|
-
else if (type === "number")
|
|
2978
|
-
b.addField(field, value, Number.isInteger(value) ? FieldInt : FieldFloat);
|
|
3105
|
+
else if (type === "number") b.addField(field, value, FieldFloat);
|
|
2979
3106
|
else if (type === "boolean") b.addField(field, value, FieldBool);
|
|
2980
3107
|
else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
|
|
2981
3108
|
else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
|
|
@@ -3127,9 +3254,9 @@ var Transactor = class {
|
|
|
3127
3254
|
// `.a[.selId]` render target reconstructed from a DOM event) against the root the
|
|
3128
3255
|
// handler read, so pathKeys carries concrete keys instead of dropping the dynamic
|
|
3129
3256
|
// step. No-op when nobody is observing.
|
|
3130
|
-
_emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
3257
|
+
_emitRecord(root, { kind, name, args, path: path2, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
3131
3258
|
if (this._observers.length === 0) return;
|
|
3132
|
-
const pinned =
|
|
3259
|
+
const pinned = path2.pinKeys(root);
|
|
3133
3260
|
this._emit({
|
|
3134
3261
|
kind,
|
|
3135
3262
|
name,
|
|
@@ -3180,18 +3307,20 @@ var Transactor = class {
|
|
|
3180
3307
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
3181
3308
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
3182
3309
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
3183
|
-
pushSend(
|
|
3184
|
-
const t = new SendEvent(
|
|
3185
|
-
t.
|
|
3310
|
+
pushSend(path2, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
3311
|
+
const t = new SendEvent(path2, this, name, args, parent);
|
|
3312
|
+
t.txnPath = txnPath;
|
|
3313
|
+
t.origin = origin;
|
|
3314
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
3186
3315
|
this.pushTransaction(t);
|
|
3187
3316
|
return this._link(t, parent);
|
|
3188
3317
|
}
|
|
3189
3318
|
// Raise an intent: a job the sender did not address, walked along a route until
|
|
3190
3319
|
// something answers. `opts.route` is a list of legs (see DEFAULT_ROUTE) and
|
|
3191
3320
|
// `opts.livePath` opts out of pinning the answer's destination keys.
|
|
3192
|
-
pushIntent(
|
|
3321
|
+
pushIntent(path2, name, args = [], opts = {}, parent = null) {
|
|
3193
3322
|
const release = parent ? parent.completion.track() : null;
|
|
3194
|
-
const walk = new IntentWalk(this,
|
|
3323
|
+
const walk = new IntentWalk(this, path2, name, args, opts, parent, release);
|
|
3195
3324
|
walk.advance();
|
|
3196
3325
|
return walk;
|
|
3197
3326
|
}
|
|
@@ -3225,16 +3354,17 @@ var Transactor = class {
|
|
|
3225
3354
|
transaction._completion?.releaseSelf();
|
|
3226
3355
|
}
|
|
3227
3356
|
}
|
|
3228
|
-
transactInputNow(
|
|
3229
|
-
this.transact(new InputEvent(
|
|
3357
|
+
transactInputNow(path2, event, eventHandler, dragInfo) {
|
|
3358
|
+
this.transact(new InputEvent(path2, event, eventHandler, this, dragInfo));
|
|
3230
3359
|
}
|
|
3231
3360
|
};
|
|
3232
3361
|
function nullHandler() {
|
|
3233
3362
|
return this;
|
|
3234
3363
|
}
|
|
3235
3364
|
var Transaction = class {
|
|
3236
|
-
constructor(
|
|
3237
|
-
this.path =
|
|
3365
|
+
constructor(path2, transactor, parentTransaction = null) {
|
|
3366
|
+
this.path = path2;
|
|
3367
|
+
this.txnPath = null;
|
|
3238
3368
|
this.transactor = transactor;
|
|
3239
3369
|
this.parentTransaction = parentTransaction;
|
|
3240
3370
|
this._completion = null;
|
|
@@ -3283,9 +3413,11 @@ var Transaction = class {
|
|
|
3283
3413
|
getHandlerAndArgs(_root, _instance, _comps) {
|
|
3284
3414
|
return null;
|
|
3285
3415
|
}
|
|
3286
|
-
// The path used to apply the mutation
|
|
3287
|
-
//
|
|
3416
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
3417
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
3418
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
3288
3419
|
getTransactionPath() {
|
|
3420
|
+
if (this.txnPath !== null) return this.txnPath;
|
|
3289
3421
|
return this.path.toTransactionPath().compact();
|
|
3290
3422
|
}
|
|
3291
3423
|
run(curRoot, comps) {
|
|
@@ -3303,15 +3435,16 @@ var Transaction = class {
|
|
|
3303
3435
|
}
|
|
3304
3436
|
};
|
|
3305
3437
|
var InputEvent = class extends Transaction {
|
|
3306
|
-
constructor(
|
|
3307
|
-
super(
|
|
3438
|
+
constructor(path2, e, handler, transactor, dragInfo) {
|
|
3439
|
+
super(path2, transactor);
|
|
3308
3440
|
this.e = e;
|
|
3309
3441
|
this.handler = handler;
|
|
3310
3442
|
this.dragInfo = dragInfo;
|
|
3311
3443
|
this._dispatchPath = null;
|
|
3312
3444
|
}
|
|
3313
|
-
// Frame steps removed,
|
|
3314
|
-
//
|
|
3445
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
3446
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
3447
|
+
// then returns to the caller that wrote the `*name`.
|
|
3315
3448
|
get dispatchPath() {
|
|
3316
3449
|
this._dispatchPath ??= this.path.compact();
|
|
3317
3450
|
return this._dispatchPath;
|
|
@@ -3346,11 +3479,11 @@ var InputEvent = class extends Transaction {
|
|
|
3346
3479
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
3347
3480
|
}
|
|
3348
3481
|
getHandlerAndArgs(root, _instance, comps) {
|
|
3349
|
-
const stack = this.path.
|
|
3482
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
3350
3483
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
3351
3484
|
this._handlerArgs = [...args];
|
|
3352
|
-
const
|
|
3353
|
-
args.push(new EventContext(
|
|
3485
|
+
const path2 = this.dispatchPath;
|
|
3486
|
+
args.push(new EventContext(path2, this.transactor, this));
|
|
3354
3487
|
return [handler, args];
|
|
3355
3488
|
}
|
|
3356
3489
|
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
@@ -3361,11 +3494,11 @@ var InputEvent = class extends Transaction {
|
|
|
3361
3494
|
}
|
|
3362
3495
|
};
|
|
3363
3496
|
var NameArgsTransaction = class extends Transaction {
|
|
3364
|
-
constructor(
|
|
3365
|
-
super(
|
|
3497
|
+
constructor(path2, transactor, name, args, parentTransaction) {
|
|
3498
|
+
super(path2, transactor, parentTransaction);
|
|
3366
3499
|
this.name = name;
|
|
3367
3500
|
this.args = args;
|
|
3368
|
-
this.targetPath =
|
|
3501
|
+
this.targetPath = path2;
|
|
3369
3502
|
}
|
|
3370
3503
|
handlerProp = null;
|
|
3371
3504
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
@@ -3422,8 +3555,8 @@ var SendEvent = class extends NameArgsTransaction {
|
|
|
3422
3555
|
};
|
|
3423
3556
|
var IntentEvent = class extends NameArgsTransaction {
|
|
3424
3557
|
handlerProp = "intent";
|
|
3425
|
-
constructor(
|
|
3426
|
-
super(
|
|
3558
|
+
constructor(path2, transactor, walk) {
|
|
3559
|
+
super(path2, transactor, walk.name, walk.args, walk.parent);
|
|
3427
3560
|
this.walk = walk;
|
|
3428
3561
|
this.targetPath = walk.origin;
|
|
3429
3562
|
}
|
|
@@ -3450,17 +3583,17 @@ var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
|
3450
3583
|
var REFUSAL_RING_CAP = 200;
|
|
3451
3584
|
var INTENT_DEPTH = 64;
|
|
3452
3585
|
var IntentWalk = class {
|
|
3453
|
-
constructor(transactor,
|
|
3586
|
+
constructor(transactor, path2, name, args, opts, parent, release) {
|
|
3454
3587
|
this.transactor = transactor;
|
|
3455
3588
|
this.name = name;
|
|
3456
3589
|
this.args = args;
|
|
3457
3590
|
this.route = opts?.route ?? DEFAULT_ROUTE;
|
|
3458
3591
|
this.parent = parent;
|
|
3459
3592
|
this.release = release;
|
|
3460
|
-
this.origin =
|
|
3461
|
-
this.answerPath = opts?.livePath ? null :
|
|
3593
|
+
this.origin = path2;
|
|
3594
|
+
this.answerPath = opts?.livePath ? null : path2.toTransactionPath().pinKeys(transactor.state.val);
|
|
3462
3595
|
this.legIndex = 0;
|
|
3463
|
-
this.dynAt =
|
|
3596
|
+
this.dynAt = path2;
|
|
3464
3597
|
this.hops = 0;
|
|
3465
3598
|
this.ended = false;
|
|
3466
3599
|
}
|
|
@@ -3472,7 +3605,7 @@ var IntentWalk = class {
|
|
|
3472
3605
|
while (this.legIndex < this.route.length) {
|
|
3473
3606
|
const leg = this.route[this.legIndex];
|
|
3474
3607
|
if (leg === "dyn") {
|
|
3475
|
-
if (this.dynAt.
|
|
3608
|
+
if (!this.dynAt.canPop()) {
|
|
3476
3609
|
this.legIndex++;
|
|
3477
3610
|
continue;
|
|
3478
3611
|
}
|
|
@@ -3569,8 +3702,8 @@ var IntentWalk = class {
|
|
|
3569
3702
|
if (this.ended) return;
|
|
3570
3703
|
this.ended = true;
|
|
3571
3704
|
if (name === null) return this.release?.();
|
|
3572
|
-
const
|
|
3573
|
-
|
|
3705
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
3706
|
+
t.txnPath = this.answerPath;
|
|
3574
3707
|
t._isAnswer = true;
|
|
3575
3708
|
this.transactor.pushTransaction(t);
|
|
3576
3709
|
if (this.release) t.completion.whenSubtreeSettled().then(this.release);
|
|
@@ -3636,8 +3769,8 @@ var Completion = class {
|
|
|
3636
3769
|
}
|
|
3637
3770
|
};
|
|
3638
3771
|
var Dispatcher = class {
|
|
3639
|
-
constructor(
|
|
3640
|
-
this.path =
|
|
3772
|
+
constructor(path2, transactor, parentTransaction, root = transactor.state.val) {
|
|
3773
|
+
this.path = path2;
|
|
3641
3774
|
this.transactor = transactor;
|
|
3642
3775
|
this.parent = parentTransaction;
|
|
3643
3776
|
this.root = root;
|
|
@@ -3665,7 +3798,9 @@ var Dispatcher = class {
|
|
|
3665
3798
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
3666
3799
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
3667
3800
|
_stack() {
|
|
3668
|
-
this._stackMemo ??= this.path.
|
|
3801
|
+
this._stackMemo ??= this.path.buildStack(
|
|
3802
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
3803
|
+
);
|
|
3669
3804
|
return this._stackMemo;
|
|
3670
3805
|
}
|
|
3671
3806
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
@@ -3679,14 +3814,19 @@ var Dispatcher = class {
|
|
|
3679
3814
|
);
|
|
3680
3815
|
}
|
|
3681
3816
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
3682
|
-
// running, which is the leaf of this ctx's path.
|
|
3817
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
3818
|
+
// component registered under it; a value name to a path registered under it
|
|
3819
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
3683
3820
|
_lookupLex(name) {
|
|
3684
3821
|
let Comp = null;
|
|
3685
3822
|
this.walkPath((c) => {
|
|
3686
3823
|
Comp = c;
|
|
3687
3824
|
return false;
|
|
3688
3825
|
});
|
|
3689
|
-
|
|
3826
|
+
const scope = Comp?.scope;
|
|
3827
|
+
if (scope == null) return null;
|
|
3828
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
3829
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
3690
3830
|
}
|
|
3691
3831
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
3692
3832
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -3708,8 +3848,8 @@ var Dispatcher = class {
|
|
|
3708
3848
|
send(name, args) {
|
|
3709
3849
|
return this.sendAtPath(this.path, name, args);
|
|
3710
3850
|
}
|
|
3711
|
-
sendAtPath(
|
|
3712
|
-
return this.transactor.pushSend(
|
|
3851
|
+
sendAtPath(path2, name, args) {
|
|
3852
|
+
return this.transactor.pushSend(path2, name, args, this.parent, this.path);
|
|
3713
3853
|
}
|
|
3714
3854
|
// An intent is ROUTED: it names a job and walks until something answers. The verb
|
|
3715
3855
|
// does not decide which scope answers — `opts.route` does, written here at the call
|
|
@@ -3717,8 +3857,8 @@ var Dispatcher = class {
|
|
|
3717
3857
|
intent(name, args, opts) {
|
|
3718
3858
|
return this.intentAtPath(this.path, name, args, opts);
|
|
3719
3859
|
}
|
|
3720
|
-
intentAtPath(
|
|
3721
|
-
return this.transactor.pushIntent(
|
|
3860
|
+
intentAtPath(path2, name, args, opts) {
|
|
3861
|
+
return this.transactor.pushIntent(path2, name, args, opts, this.parent);
|
|
3722
3862
|
}
|
|
3723
3863
|
};
|
|
3724
3864
|
var EventContext = class extends Dispatcher {
|
|
@@ -3747,7 +3887,14 @@ var EventContext = class extends Dispatcher {
|
|
|
3747
3887
|
this.transactor.refuse("NO_SENDER", { name });
|
|
3748
3888
|
return null;
|
|
3749
3889
|
}
|
|
3750
|
-
return this.
|
|
3890
|
+
return this.transactor.pushSend(
|
|
3891
|
+
origin,
|
|
3892
|
+
name,
|
|
3893
|
+
args,
|
|
3894
|
+
this.parent,
|
|
3895
|
+
this.path,
|
|
3896
|
+
this.parent.originPinned
|
|
3897
|
+
);
|
|
3751
3898
|
}
|
|
3752
3899
|
// End the walk answering nothing — "served, and no answer".
|
|
3753
3900
|
stop() {
|
|
@@ -3779,7 +3926,7 @@ var PathChanges = class extends PathBuilder {
|
|
|
3779
3926
|
}
|
|
3780
3927
|
};
|
|
3781
3928
|
function rootDispatcher(transactor) {
|
|
3782
|
-
return new Dispatcher(new
|
|
3929
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
3783
3930
|
}
|
|
3784
3931
|
|
|
3785
3932
|
// src/app.js
|
|
@@ -3820,7 +3967,7 @@ var App = class {
|
|
|
3820
3967
|
const { type } = e;
|
|
3821
3968
|
const isDrag = type === "dragover" || type === "dragstart" || type === "dragend" || type === "drop";
|
|
3822
3969
|
const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
|
|
3823
|
-
const [
|
|
3970
|
+
const [path2, handlers] = DispatchPath.fromNodeAndEventName(
|
|
3824
3971
|
e.target,
|
|
3825
3972
|
type,
|
|
3826
3973
|
root,
|
|
@@ -3828,9 +3975,9 @@ var App = class {
|
|
|
3828
3975
|
comps,
|
|
3829
3976
|
!isDrag
|
|
3830
3977
|
);
|
|
3831
|
-
if (isDrag) this._handleDragEvent(e, type,
|
|
3832
|
-
if (
|
|
3833
|
-
for (const handler of handlers) transactor.transactInputNow(
|
|
3978
|
+
if (isDrag) this._handleDragEvent(e, type, path2);
|
|
3979
|
+
if (path2 !== null && handlers !== null)
|
|
3980
|
+
for (const handler of handlers) transactor.transactInputNow(path2, e, handler, this.dragInfo);
|
|
3834
3981
|
}
|
|
3835
3982
|
_handleTouchEvent(e) {
|
|
3836
3983
|
const { type } = e;
|
|
@@ -3873,7 +4020,7 @@ var App = class {
|
|
|
3873
4020
|
this._touch = null;
|
|
3874
4021
|
}
|
|
3875
4022
|
}
|
|
3876
|
-
_handleDragEvent(e, type,
|
|
4023
|
+
_handleDragEvent(e, type, path2) {
|
|
3877
4024
|
if (type === "dragover") {
|
|
3878
4025
|
const dropTarget = getClosestDropTarget(e.target, this.rootNode, Infinity);
|
|
3879
4026
|
if (dropTarget !== null) {
|
|
@@ -3885,10 +4032,10 @@ var App = class {
|
|
|
3885
4032
|
} else if (type === "dragstart") {
|
|
3886
4033
|
e.target.dataset.dragging = 1;
|
|
3887
4034
|
const rootValue = this.state.val;
|
|
3888
|
-
const txnPath =
|
|
4035
|
+
const txnPath = path2.compact().toTransactionPath();
|
|
3889
4036
|
const value = txnPath.lookup(rootValue);
|
|
3890
4037
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
3891
|
-
const stack =
|
|
4038
|
+
const stack = path2.buildStack(this.makeStack(rootValue));
|
|
3892
4039
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
3893
4040
|
} else if (type === "drop") {
|
|
3894
4041
|
e.preventDefault();
|
|
@@ -3963,7 +4110,7 @@ var App = class {
|
|
|
3963
4110
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
3964
4111
|
}
|
|
3965
4112
|
sendAtRoot(name, args) {
|
|
3966
|
-
this.transactor.pushSend(new
|
|
4113
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
3967
4114
|
}
|
|
3968
4115
|
registerComponents(comps, opts) {
|
|
3969
4116
|
const scope = this.compStack.enter();
|
|
@@ -4181,7 +4328,20 @@ var WeakMapDomCache = class {
|
|
|
4181
4328
|
};
|
|
4182
4329
|
|
|
4183
4330
|
// src/renderer.js
|
|
4184
|
-
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
4331
|
+
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk", "rp"];
|
|
4332
|
+
function stampRenderBase(vdom, text) {
|
|
4333
|
+
if (vdom instanceof VNode)
|
|
4334
|
+
return new VNode(
|
|
4335
|
+
vdom.tag,
|
|
4336
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
4337
|
+
vdom.childs,
|
|
4338
|
+
vdom.key,
|
|
4339
|
+
vdom.namespace
|
|
4340
|
+
);
|
|
4341
|
+
if (vdom instanceof VFragment)
|
|
4342
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
4343
|
+
return vdom;
|
|
4344
|
+
}
|
|
4185
4345
|
var Renderer = class {
|
|
4186
4346
|
constructor(comps) {
|
|
4187
4347
|
this.comps = comps;
|
|
@@ -4218,17 +4378,17 @@ var Renderer = class {
|
|
|
4218
4378
|
if (comp === null) return null;
|
|
4219
4379
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
4220
4380
|
}
|
|
4221
|
-
renderIt(stack, node, key, viewName) {
|
|
4381
|
+
renderIt(stack, node, key, viewName, base = null) {
|
|
4222
4382
|
const comp = this.comps.getCompFor(stack.it);
|
|
4223
|
-
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
4383
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName, base) : null;
|
|
4224
4384
|
}
|
|
4225
4385
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
4226
4386
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
4227
4387
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
4228
4388
|
// single view, so the same value rendered by two components (e.g. through a
|
|
4229
4389
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
4230
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
4231
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
4390
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
4391
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
4232
4392
|
const cachePath = [node, val];
|
|
4233
4393
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
4234
4394
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -4236,30 +4396,43 @@ var Renderer = class {
|
|
|
4236
4396
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
4237
4397
|
const body = this.renderView(view, stack);
|
|
4238
4398
|
if (body == null) return null;
|
|
4399
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
4239
4400
|
const meta = this._renderMetadata({
|
|
4240
4401
|
$: "Comp",
|
|
4241
4402
|
nid: node?.nodeId ?? null,
|
|
4242
4403
|
cid: comp.id,
|
|
4243
|
-
vid: view.name
|
|
4404
|
+
vid: view.name,
|
|
4405
|
+
...baseJson === null ? null : { base: baseJson }
|
|
4244
4406
|
});
|
|
4245
|
-
const dom = new VFragment([
|
|
4407
|
+
const dom = new VFragment([
|
|
4408
|
+
meta,
|
|
4409
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
4410
|
+
]);
|
|
4246
4411
|
this.cache.set(cachePath, cacheKey, dom);
|
|
4247
4412
|
return dom;
|
|
4248
4413
|
}
|
|
4249
4414
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
4250
4415
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
4251
4416
|
}
|
|
4252
|
-
renderEachWhen(stack,
|
|
4417
|
+
renderEachWhen(stack, each) {
|
|
4418
|
+
const { iterInfo, node: view, nodeId: nid } = each;
|
|
4253
4419
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
4420
|
+
const seqPath = iterInfo.val instanceof DynVal ? stack.lookupDynamicLocated(iterInfo.val.name)?.path ?? null : null;
|
|
4254
4421
|
const r = [];
|
|
4255
4422
|
const it = stack.it;
|
|
4256
4423
|
const renderOne = (key, value, attrName, binds) => {
|
|
4424
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
4425
|
+
const itemStep = itemBase === null ? each.itemStep(key) : null;
|
|
4426
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
4257
4427
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
4258
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
4428
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
4259
4429
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
4260
4430
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
4261
4431
|
else {
|
|
4262
|
-
const dom = this.renderView(
|
|
4432
|
+
const dom = this.renderView(
|
|
4433
|
+
view,
|
|
4434
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
4435
|
+
);
|
|
4263
4436
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
4264
4437
|
this.cache.set(cachePath, cacheKey, dom);
|
|
4265
4438
|
}
|
|
@@ -4371,6 +4544,7 @@ export {
|
|
|
4371
4544
|
html,
|
|
4372
4545
|
injectCss,
|
|
4373
4546
|
macro,
|
|
4547
|
+
path,
|
|
4374
4548
|
phaseOps,
|
|
4375
4549
|
resolveArgs,
|
|
4376
4550
|
rootDispatcher,
|