tutuca 0.9.97 → 0.9.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/tutuca-cli.js +208 -69
- package/dist/tutuca-components.js +2444 -0
- package/dist/tutuca-dev.ext.js +92 -45
- package/dist/tutuca-dev.js +92 -45
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +56 -28
- package/dist/tutuca-extra.js +56 -28
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +136 -10
- package/dist/tutuca.ext.js +56 -28
- package/dist/tutuca.js +56 -28
- package/dist/tutuca.min.js +2 -2
- package/package.json +5 -3
- package/skill/tutuca/advanced.md +14 -5
- package/skill/tutuca/cli.md +10 -68
- package/skill/tutuca/core.md +103 -89
- package/skill/tutuca/margaui.md +25 -13
- package/skill/tutuca/patterns/README.md +1 -0
- package/skill/tutuca/patterns/filter-a-list.md +3 -1
- package/skill/tutuca/patterns/filter-and-paginate.md +116 -0
- package/skill/tutuca/patterns/paginate-a-list.md +3 -1
- package/skill/tutuca/semantics.md +4 -3
- package/skill/tutuca/storybook.md +7 -2
- package/skill/tutuca/testing.md +14 -6
- package/skill/tutuca-source/tutuca.ext.js +56 -28
package/dist/tutuca-storybook.js
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
|
-
// src/storybook.js
|
|
2
|
-
import { component, dispatchPhase, html, injectCss, tutuca } from "tutuca";
|
|
1
|
+
// src/storybook/index.js
|
|
2
|
+
import { component, dispatchPhase, html, injectCss, phaseHasBubble, tutuca } from "tutuca";
|
|
3
|
+
import { getComponents as getInspectorComponents } from "tutuca/components";
|
|
4
|
+
|
|
5
|
+
// src/storybook/inspect.js
|
|
6
|
+
import { buildInspectorViews, isComponentInstance } from "tutuca/components";
|
|
7
|
+
function buildTestIndex(modules) {
|
|
8
|
+
const index = new Map;
|
|
9
|
+
for (const m of modules) {
|
|
10
|
+
if (typeof m.getTests !== "function")
|
|
11
|
+
continue;
|
|
12
|
+
const components = m.getComponents?.() ?? [];
|
|
13
|
+
for (const c of components) {
|
|
14
|
+
if (!index.has(c.name))
|
|
15
|
+
index.set(c.name, { getTests: m.getTests, components });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return index;
|
|
19
|
+
}
|
|
20
|
+
async function buildExampleInspectors(example, scope, testIndex, dev) {
|
|
21
|
+
const value = example.value;
|
|
22
|
+
const comp = isComponentInstance(value) ? scope.getCompFor(value) : null;
|
|
23
|
+
const entry = comp ? testIndex.get(comp.name) : null;
|
|
24
|
+
const views = await buildInspectorViews(value, scope, {
|
|
25
|
+
getTests: entry?.getTests ?? null,
|
|
26
|
+
components: entry?.components ?? [],
|
|
27
|
+
dev
|
|
28
|
+
});
|
|
29
|
+
return example.setInstanceView(views.instanceView).setComponentView(views.componentView).setLintView(views.lintView).setTestView(views.testView).setHasInspect(views.hasInspect).setHasComponent(views.hasComponent).setHasLint(views.hasLint).setHasTest(views.hasTest);
|
|
30
|
+
}
|
|
31
|
+
async function attachInspectorViews(root, scope, modules, dev = null) {
|
|
32
|
+
const testIndex = buildTestIndex(modules);
|
|
33
|
+
let sections = root.sections;
|
|
34
|
+
for (let si = 0;si < sections.size; si++) {
|
|
35
|
+
const section = sections.get(si);
|
|
36
|
+
let items = section.items;
|
|
37
|
+
for (let ii = 0;ii < items.size; ii++) {
|
|
38
|
+
items = items.set(ii, await buildExampleInspectors(items.get(ii), scope, testIndex, dev));
|
|
39
|
+
}
|
|
40
|
+
sections = sections.set(si, section.setItems(items));
|
|
41
|
+
}
|
|
42
|
+
return root.setSections(sections);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/storybook/index.js
|
|
3
46
|
var Storybook = component({
|
|
4
47
|
name: "Storybook",
|
|
5
48
|
fields: {
|
|
@@ -247,7 +290,16 @@ var Example = component({
|
|
|
247
290
|
value: null,
|
|
248
291
|
view: "main",
|
|
249
292
|
requestHandlers: null,
|
|
250
|
-
on: null
|
|
293
|
+
on: null,
|
|
294
|
+
activeTab: "preview",
|
|
295
|
+
hasInspect: false,
|
|
296
|
+
hasComponent: false,
|
|
297
|
+
hasLint: false,
|
|
298
|
+
hasTest: false,
|
|
299
|
+
componentView: null,
|
|
300
|
+
instanceView: null,
|
|
301
|
+
lintView: null,
|
|
302
|
+
testView: null
|
|
251
303
|
},
|
|
252
304
|
requestOverridesField: "requestHandlers",
|
|
253
305
|
statics: {
|
|
@@ -274,18 +326,25 @@ var Example = component({
|
|
|
274
326
|
},
|
|
275
327
|
receive: {
|
|
276
328
|
init(ctx) {
|
|
277
|
-
|
|
329
|
+
this.runPhase(ctx, "init", this.on?.init);
|
|
278
330
|
return this;
|
|
279
331
|
},
|
|
280
332
|
resume(ctx) {
|
|
281
|
-
|
|
333
|
+
this.runPhase(ctx, "resume", this.on?.resume);
|
|
282
334
|
return this;
|
|
283
335
|
},
|
|
284
336
|
suspend(ctx) {
|
|
285
|
-
|
|
337
|
+
this.runPhase(ctx, "suspend", this.on?.suspend);
|
|
286
338
|
return this;
|
|
287
339
|
}
|
|
288
340
|
},
|
|
341
|
+
methods: {
|
|
342
|
+
runPhase(ctx, name, phase) {
|
|
343
|
+
if (phaseHasBubble(phase))
|
|
344
|
+
console.warn(`storybook on.${name}: a \`bubble\` action leaves this example and is received by the storybook engine, so your component's bubble handler won't run. Use send/request/input to drive a preset state.`);
|
|
345
|
+
dispatchPhase(ctx, ctx.at.field("value").buildPath(), phase, this.value);
|
|
346
|
+
}
|
|
347
|
+
},
|
|
289
348
|
input: {
|
|
290
349
|
onLogSelected() {
|
|
291
350
|
console.log(this.value);
|
|
@@ -310,8 +369,72 @@ var Example = component({
|
|
|
310
369
|
</div>
|
|
311
370
|
</h2>
|
|
312
371
|
<p class="text-md italic opacity-60" @text=".description"></p>
|
|
313
|
-
<div class="
|
|
314
|
-
<
|
|
372
|
+
<div role="tablist" class="tabs tabs-border" @show=".hasInspect">
|
|
373
|
+
<a
|
|
374
|
+
role="tab"
|
|
375
|
+
@if.class="equals? .activeTab 'preview'"
|
|
376
|
+
@then="'tab tab-active'"
|
|
377
|
+
@else="'tab'"
|
|
378
|
+
@on.click="$setActiveTab 'preview'"
|
|
379
|
+
>
|
|
380
|
+
Preview
|
|
381
|
+
</a>
|
|
382
|
+
<a
|
|
383
|
+
role="tab"
|
|
384
|
+
@show=".hasComponent"
|
|
385
|
+
@if.class="equals? .activeTab 'component'"
|
|
386
|
+
@then="'tab tab-active'"
|
|
387
|
+
@else="'tab'"
|
|
388
|
+
@on.click="$setActiveTab 'component'"
|
|
389
|
+
>
|
|
390
|
+
Component
|
|
391
|
+
</a>
|
|
392
|
+
<a
|
|
393
|
+
role="tab"
|
|
394
|
+
@if.class="equals? .activeTab 'instance'"
|
|
395
|
+
@then="'tab tab-active'"
|
|
396
|
+
@else="'tab'"
|
|
397
|
+
@on.click="$setActiveTab 'instance'"
|
|
398
|
+
>
|
|
399
|
+
Instance
|
|
400
|
+
</a>
|
|
401
|
+
<a
|
|
402
|
+
role="tab"
|
|
403
|
+
@show=".hasLint"
|
|
404
|
+
@if.class="equals? .activeTab 'lint'"
|
|
405
|
+
@then="'tab tab-active'"
|
|
406
|
+
@else="'tab'"
|
|
407
|
+
@on.click="$setActiveTab 'lint'"
|
|
408
|
+
>
|
|
409
|
+
Lint
|
|
410
|
+
</a>
|
|
411
|
+
<a
|
|
412
|
+
role="tab"
|
|
413
|
+
@show=".hasTest"
|
|
414
|
+
@if.class="equals? .activeTab 'test'"
|
|
415
|
+
@then="'tab tab-active'"
|
|
416
|
+
@else="'tab'"
|
|
417
|
+
@on.click="$setActiveTab 'test'"
|
|
418
|
+
>
|
|
419
|
+
Test
|
|
420
|
+
</a>
|
|
421
|
+
</div>
|
|
422
|
+
<div @show="equals? .activeTab 'preview'">
|
|
423
|
+
<div class="bg-base-100 p-3" @push-view=".view">
|
|
424
|
+
<x render=".value"></x>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
<div class="p-3" @show="equals? .activeTab 'component'">
|
|
428
|
+
<x render=".componentView"></x>
|
|
429
|
+
</div>
|
|
430
|
+
<div class="p-3" @show="equals? .activeTab 'instance'">
|
|
431
|
+
<x render=".instanceView"></x>
|
|
432
|
+
</div>
|
|
433
|
+
<div class="p-3" @show="equals? .activeTab 'lint'">
|
|
434
|
+
<x render=".lintView"></x>
|
|
435
|
+
</div>
|
|
436
|
+
<div class="p-3" @show="equals? .activeTab 'test'">
|
|
437
|
+
<x render=".testView"></x>
|
|
315
438
|
</div>
|
|
316
439
|
</div>
|
|
317
440
|
</div>`
|
|
@@ -353,7 +476,7 @@ function buildStorybook(modules) {
|
|
|
353
476
|
return Array.isArray(raw) ? raw : [raw];
|
|
354
477
|
});
|
|
355
478
|
const sections = rawSections.map((s) => Section.Class.fromData(s)).sort((a, b) => a.title.localeCompare(b.title));
|
|
356
|
-
const components = new Set([Storybook, Section, Example]);
|
|
479
|
+
const components = new Set([Storybook, Section, Example, ...getInspectorComponents()]);
|
|
357
480
|
const macros = {};
|
|
358
481
|
const requestHandlers = {};
|
|
359
482
|
const overrideNames = new Set;
|
|
@@ -406,7 +529,7 @@ function buildExampleRequestHandlers({ requestHandlers: reals, overrideNames })
|
|
|
406
529
|
handlers[name] = makeMeta(name);
|
|
407
530
|
return handlers;
|
|
408
531
|
}
|
|
409
|
-
async function mountStorybook(selector, modules, { compileCss, root, persistUrl = true } = {}) {
|
|
532
|
+
async function mountStorybook(selector, modules, { compileCss, root, persistUrl = true, dev = null } = {}) {
|
|
410
533
|
const app = tutuca(selector);
|
|
411
534
|
const built = buildStorybook(modules);
|
|
412
535
|
app.state.set(root ?? built.root);
|
|
@@ -417,6 +540,9 @@ async function mountStorybook(selector, modules, { compileCss, root, persistUrl
|
|
|
417
540
|
if (persistUrl) {
|
|
418
541
|
scope.registerRequestHandlers({ persistState });
|
|
419
542
|
}
|
|
543
|
+
if (dev && app.state.val?.sections) {
|
|
544
|
+
app.state.set(await attachInspectorViews(app.state.val, scope, modules, dev));
|
|
545
|
+
}
|
|
420
546
|
if (compileCss) {
|
|
421
547
|
injectCss("tutuca-storybook", await compileCss(app));
|
|
422
548
|
}
|
package/dist/tutuca.ext.js
CHANGED
|
@@ -1744,37 +1744,47 @@ class Renderer {
|
|
|
1744
1744
|
renderEach(stack, iterInfo, node, viewName) {
|
|
1745
1745
|
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
1746
1746
|
const r = [];
|
|
1747
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1747
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
1748
|
+
const renderOne = (key, value, attrName) => {
|
|
1749
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
1750
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
1751
|
+
};
|
|
1752
|
+
if (keys)
|
|
1753
|
+
imKeysIter(seq, renderOne, keys);
|
|
1754
|
+
else
|
|
1755
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1756
|
+
if (filter.call(stack.it, key, value, iterData))
|
|
1757
|
+
renderOne(key, value, attrName);
|
|
1758
|
+
}, start, end);
|
|
1754
1759
|
return r;
|
|
1755
1760
|
}
|
|
1756
1761
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
1757
1762
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
1758
1763
|
const r = [];
|
|
1759
1764
|
const it = stack.it;
|
|
1760
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
1775
|
-
}
|
|
1765
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
|
|
1766
|
+
const renderOne = (key, value, attrName) => {
|
|
1767
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
1768
|
+
const binds = { key, value };
|
|
1769
|
+
const cacheKey = `${nid}-${key}`;
|
|
1770
|
+
if (enricher)
|
|
1771
|
+
enricher.call(it, binds, key, value, iterData);
|
|
1772
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
1773
|
+
if (cachedNode)
|
|
1774
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
1775
|
+
else {
|
|
1776
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
1777
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
1778
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
1776
1779
|
}
|
|
1777
|
-
}
|
|
1780
|
+
};
|
|
1781
|
+
if (keys)
|
|
1782
|
+
imKeysIter(seq, renderOne, keys);
|
|
1783
|
+
else
|
|
1784
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
1785
|
+
if (filter.call(it, key, value, iterData))
|
|
1786
|
+
renderOne(key, value, attrName);
|
|
1787
|
+
}, start, end);
|
|
1778
1788
|
return r;
|
|
1779
1789
|
}
|
|
1780
1790
|
renderView(view, stack) {
|
|
@@ -1810,8 +1820,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
|
1810
1820
|
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
1811
1821
|
var unpackLoopResult = (result, seq) => {
|
|
1812
1822
|
const r = result ?? {};
|
|
1813
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
1823
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
1824
|
+
};
|
|
1825
|
+
var imKeysIter = (seq, visit, keys) => {
|
|
1826
|
+
const attrName = isIndexed(seq) ? "si" : "sk";
|
|
1827
|
+
for (const key of keys)
|
|
1828
|
+
visit(key, seq.get(key), attrName);
|
|
1814
1829
|
};
|
|
1830
|
+
var makeLoopCtx = (stack, filter) => ({
|
|
1831
|
+
lookup: (name) => stack.lookupBind(name),
|
|
1832
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
1833
|
+
});
|
|
1815
1834
|
var imIndexedIter = (seq, visit, start, end) => {
|
|
1816
1835
|
const [s, e] = normalizeRange(start, end, seq.size);
|
|
1817
1836
|
for (let i = s;i < e; i++)
|
|
@@ -2359,11 +2378,11 @@ class IterInfo {
|
|
|
2359
2378
|
return { seq, filter, loopWith, enricher };
|
|
2360
2379
|
}
|
|
2361
2380
|
enrichBinds(stack, key) {
|
|
2362
|
-
const { seq, loopWith, enricher } = this.eval(stack);
|
|
2381
|
+
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
2363
2382
|
const value = seq?.get ? seq.get(key, null) : null;
|
|
2364
2383
|
const binds = { key, value };
|
|
2365
2384
|
if (enricher) {
|
|
2366
|
-
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
2385
|
+
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
2367
2386
|
enricher.call(stack.it, binds, key, value, iterData);
|
|
2368
2387
|
}
|
|
2369
2388
|
return binds;
|
|
@@ -3714,6 +3733,13 @@ function phaseOps(phase) {
|
|
|
3714
3733
|
function resolveArgs(args, self) {
|
|
3715
3734
|
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
3716
3735
|
}
|
|
3736
|
+
function phaseHasBubble(phase) {
|
|
3737
|
+
if (!phase)
|
|
3738
|
+
return false;
|
|
3739
|
+
if (phase.bubble?.length)
|
|
3740
|
+
return true;
|
|
3741
|
+
return (phase.do ?? []).some((op) => op.type === "bubble");
|
|
3742
|
+
}
|
|
3717
3743
|
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
3718
3744
|
if (!phase)
|
|
3719
3745
|
return;
|
|
@@ -4007,7 +4033,8 @@ class FieldSet extends Field {
|
|
|
4007
4033
|
}
|
|
4008
4034
|
function mkCompField(field, scope, args) {
|
|
4009
4035
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
4010
|
-
|
|
4036
|
+
if (Comp === null)
|
|
4037
|
+
console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
|
|
4011
4038
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
4012
4039
|
}
|
|
4013
4040
|
|
|
@@ -4156,6 +4183,7 @@ export {
|
|
|
4156
4183
|
removeIn,
|
|
4157
4184
|
remove,
|
|
4158
4185
|
phaseOps,
|
|
4186
|
+
phaseHasBubble,
|
|
4159
4187
|
mergeWith,
|
|
4160
4188
|
mergeDeepWith,
|
|
4161
4189
|
mergeDeep,
|
package/dist/tutuca.js
CHANGED
|
@@ -6114,37 +6114,47 @@ class Renderer {
|
|
|
6114
6114
|
renderEach(stack, iterInfo, node, viewName) {
|
|
6115
6115
|
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
6116
6116
|
const r = [];
|
|
6117
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6117
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
6118
|
+
const renderOne = (key, value, attrName) => {
|
|
6119
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
6120
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
6121
|
+
};
|
|
6122
|
+
if (keys)
|
|
6123
|
+
imKeysIter(seq, renderOne, keys);
|
|
6124
|
+
else
|
|
6125
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
6126
|
+
if (filter.call(stack.it, key, value, iterData))
|
|
6127
|
+
renderOne(key, value, attrName);
|
|
6128
|
+
}, start, end);
|
|
6124
6129
|
return r;
|
|
6125
6130
|
}
|
|
6126
6131
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
6127
6132
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
6128
6133
|
const r = [];
|
|
6129
6134
|
const it = stack.it;
|
|
6130
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
6145
|
-
}
|
|
6135
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
|
|
6136
|
+
const renderOne = (key, value, attrName) => {
|
|
6137
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
6138
|
+
const binds = { key, value };
|
|
6139
|
+
const cacheKey = `${nid}-${key}`;
|
|
6140
|
+
if (enricher)
|
|
6141
|
+
enricher.call(it, binds, key, value, iterData);
|
|
6142
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
6143
|
+
if (cachedNode)
|
|
6144
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
6145
|
+
else {
|
|
6146
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
6147
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
6148
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
6146
6149
|
}
|
|
6147
|
-
}
|
|
6150
|
+
};
|
|
6151
|
+
if (keys)
|
|
6152
|
+
imKeysIter(seq, renderOne, keys);
|
|
6153
|
+
else
|
|
6154
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
6155
|
+
if (filter.call(it, key, value, iterData))
|
|
6156
|
+
renderOne(key, value, attrName);
|
|
6157
|
+
}, start, end);
|
|
6148
6158
|
return r;
|
|
6149
6159
|
}
|
|
6150
6160
|
renderView(view, stack) {
|
|
@@ -6180,8 +6190,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
|
6180
6190
|
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
6181
6191
|
var unpackLoopResult = (result, seq) => {
|
|
6182
6192
|
const r = result ?? {};
|
|
6183
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
6193
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
6184
6194
|
};
|
|
6195
|
+
var imKeysIter = (seq, visit, keys) => {
|
|
6196
|
+
const attrName = isIndexed(seq) ? "si" : "sk";
|
|
6197
|
+
for (const key of keys)
|
|
6198
|
+
visit(key, seq.get(key), attrName);
|
|
6199
|
+
};
|
|
6200
|
+
var makeLoopCtx = (stack, filter) => ({
|
|
6201
|
+
lookup: (name) => stack.lookupBind(name),
|
|
6202
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
6203
|
+
});
|
|
6185
6204
|
var imIndexedIter = (seq, visit, start, end) => {
|
|
6186
6205
|
const [s, e] = normalizeRange(start, end, seq.size);
|
|
6187
6206
|
for (let i = s;i < e; i++)
|
|
@@ -6729,11 +6748,11 @@ class IterInfo {
|
|
|
6729
6748
|
return { seq, filter, loopWith, enricher };
|
|
6730
6749
|
}
|
|
6731
6750
|
enrichBinds(stack, key) {
|
|
6732
|
-
const { seq, loopWith, enricher } = this.eval(stack);
|
|
6751
|
+
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
6733
6752
|
const value = seq?.get ? seq.get(key, null) : null;
|
|
6734
6753
|
const binds = { key, value };
|
|
6735
6754
|
if (enricher) {
|
|
6736
|
-
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
6755
|
+
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
6737
6756
|
enricher.call(stack.it, binds, key, value, iterData);
|
|
6738
6757
|
}
|
|
6739
6758
|
return binds;
|
|
@@ -8028,6 +8047,13 @@ function phaseOps(phase) {
|
|
|
8028
8047
|
function resolveArgs(args, self) {
|
|
8029
8048
|
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
8030
8049
|
}
|
|
8050
|
+
function phaseHasBubble(phase) {
|
|
8051
|
+
if (!phase)
|
|
8052
|
+
return false;
|
|
8053
|
+
if (phase.bubble?.length)
|
|
8054
|
+
return true;
|
|
8055
|
+
return (phase.do ?? []).some((op) => op.type === "bubble");
|
|
8056
|
+
}
|
|
8031
8057
|
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
8032
8058
|
if (!phase)
|
|
8033
8059
|
return;
|
|
@@ -8320,7 +8346,8 @@ class FieldSet extends Field {
|
|
|
8320
8346
|
}
|
|
8321
8347
|
function mkCompField(field, scope, args) {
|
|
8322
8348
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
8323
|
-
|
|
8349
|
+
if (Comp === null)
|
|
8350
|
+
console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
|
|
8324
8351
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
8325
8352
|
}
|
|
8326
8353
|
|
|
@@ -8469,6 +8496,7 @@ export {
|
|
|
8469
8496
|
removeIn,
|
|
8470
8497
|
remove,
|
|
8471
8498
|
phaseOps,
|
|
8499
|
+
phaseHasBubble,
|
|
8472
8500
|
mergeWith$1 as mergeWith,
|
|
8473
8501
|
mergeDeepWith$1 as mergeDeepWith,
|
|
8474
8502
|
mergeDeep$1 as mergeDeep,
|