tutuca 0.9.97 → 0.9.98
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 +190 -59
- package/dist/tutuca-dev.ext.js +76 -29
- package/dist/tutuca-dev.js +76 -29
- 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 +11 -4
- package/dist/tutuca.ext.js +56 -28
- package/dist/tutuca.js +56 -28
- package/dist/tutuca.min.js +2 -2
- package/package.json +3 -3
- package/skill/tutuca/advanced.md +14 -5
- package/skill/tutuca/core.md +78 -15
- 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/storybook.md +7 -2
- package/skill/tutuca/testing.md +11 -0
- package/skill/tutuca-source/tutuca.ext.js +56 -28
package/dist/tutuca-dev.js
CHANGED
|
@@ -9493,37 +9493,47 @@ class Renderer {
|
|
|
9493
9493
|
renderEach(stack, iterInfo, node, viewName) {
|
|
9494
9494
|
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
9495
9495
|
const r = [];
|
|
9496
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9496
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9497
|
+
const renderOne = (key, value, attrName) => {
|
|
9498
|
+
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
9499
|
+
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
9500
|
+
};
|
|
9501
|
+
if (keys)
|
|
9502
|
+
imKeysIter(seq, renderOne, keys);
|
|
9503
|
+
else
|
|
9504
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
9505
|
+
if (filter.call(stack.it, key, value, iterData))
|
|
9506
|
+
renderOne(key, value, attrName);
|
|
9507
|
+
}, start, end);
|
|
9503
9508
|
return r;
|
|
9504
9509
|
}
|
|
9505
9510
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
9506
9511
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
9507
9512
|
const r = [];
|
|
9508
9513
|
const it = stack.it;
|
|
9509
|
-
const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
9524
|
-
}
|
|
9514
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
|
|
9515
|
+
const renderOne = (key, value, attrName) => {
|
|
9516
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
9517
|
+
const binds = { key, value };
|
|
9518
|
+
const cacheKey = `${nid}-${key}`;
|
|
9519
|
+
if (enricher)
|
|
9520
|
+
enricher.call(it, binds, key, value, iterData);
|
|
9521
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
9522
|
+
if (cachedNode)
|
|
9523
|
+
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
9524
|
+
else {
|
|
9525
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
9526
|
+
this.pushEachEntry(r, nid, attrName, key, dom);
|
|
9527
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
9525
9528
|
}
|
|
9526
|
-
}
|
|
9529
|
+
};
|
|
9530
|
+
if (keys)
|
|
9531
|
+
imKeysIter(seq, renderOne, keys);
|
|
9532
|
+
else
|
|
9533
|
+
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
9534
|
+
if (filter.call(it, key, value, iterData))
|
|
9535
|
+
renderOne(key, value, attrName);
|
|
9536
|
+
}, start, end);
|
|
9527
9537
|
return r;
|
|
9528
9538
|
}
|
|
9529
9539
|
renderView(view, stack) {
|
|
@@ -9559,8 +9569,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
|
9559
9569
|
var nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
9560
9570
|
var unpackLoopResult = (result, seq) => {
|
|
9561
9571
|
const r = result ?? {};
|
|
9562
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
|
|
9572
|
+
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
9563
9573
|
};
|
|
9574
|
+
var imKeysIter = (seq, visit, keys) => {
|
|
9575
|
+
const attrName = isIndexed(seq) ? "si" : "sk";
|
|
9576
|
+
for (const key of keys)
|
|
9577
|
+
visit(key, seq.get(key), attrName);
|
|
9578
|
+
};
|
|
9579
|
+
var makeLoopCtx = (stack, filter) => ({
|
|
9580
|
+
lookup: (name) => stack.lookupBind(name),
|
|
9581
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
9582
|
+
});
|
|
9564
9583
|
var imIndexedIter = (seq, visit, start, end) => {
|
|
9565
9584
|
const [s, e] = normalizeRange(start, end, seq.size);
|
|
9566
9585
|
for (let i = s;i < e; i++)
|
|
@@ -10108,11 +10127,11 @@ class IterInfo {
|
|
|
10108
10127
|
return { seq, filter, loopWith, enricher };
|
|
10109
10128
|
}
|
|
10110
10129
|
enrichBinds(stack, key) {
|
|
10111
|
-
const { seq, loopWith, enricher } = this.eval(stack);
|
|
10130
|
+
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
10112
10131
|
const value = seq?.get ? seq.get(key, null) : null;
|
|
10113
10132
|
const binds = { key, value };
|
|
10114
10133
|
if (enricher) {
|
|
10115
|
-
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
|
|
10134
|
+
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
10116
10135
|
enricher.call(stack.it, binds, key, value, iterData);
|
|
10117
10136
|
}
|
|
10118
10137
|
return binds;
|
|
@@ -13691,6 +13710,13 @@ function phaseOps(phase) {
|
|
|
13691
13710
|
function resolveArgs(args, self) {
|
|
13692
13711
|
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
13693
13712
|
}
|
|
13713
|
+
function phaseHasBubble(phase) {
|
|
13714
|
+
if (!phase)
|
|
13715
|
+
return false;
|
|
13716
|
+
if (phase.bubble?.length)
|
|
13717
|
+
return true;
|
|
13718
|
+
return (phase.do ?? []).some((op) => op.type === "bubble");
|
|
13719
|
+
}
|
|
13694
13720
|
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
13695
13721
|
if (!phase)
|
|
13696
13722
|
return;
|
|
@@ -14627,6 +14653,8 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
14627
14653
|
const t = info?.transaction;
|
|
14628
14654
|
opts.onMessage({ kind: t?.handlerProp ?? "input", name: t?.name, args: t?.args, path: t?.path }, old, val);
|
|
14629
14655
|
});
|
|
14656
|
+
if (phaseHasBubble(phase))
|
|
14657
|
+
console.warn("drive(): a `bubble` action is a no-op here — drive originates at the root and bubbles travel child→parent, so there is no ancestor to receive it (and the root's own bubble handler is skipped). To exercise a bubble handler, call it directly.");
|
|
14630
14658
|
dispatchPhase(rootDispatcher(transactor), new Path([]), phase, value);
|
|
14631
14659
|
await transactor.settle();
|
|
14632
14660
|
return transactor.state.val;
|
|
@@ -15558,7 +15586,8 @@ class FieldSet extends Field {
|
|
|
15558
15586
|
}
|
|
15559
15587
|
function mkCompField(field, scope, args) {
|
|
15560
15588
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
15561
|
-
|
|
15589
|
+
if (Comp === null)
|
|
15590
|
+
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)`);
|
|
15562
15591
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
15563
15592
|
}
|
|
15564
15593
|
|
|
@@ -15732,13 +15761,30 @@ function resolveAlter(Comp, name) {
|
|
|
15732
15761
|
}
|
|
15733
15762
|
return fn;
|
|
15734
15763
|
}
|
|
15764
|
+
var seqGet = (seq, key) => Array.isArray(seq) ? seq[key] : seq.get ? seq.get(key) : seq[key];
|
|
15735
15765
|
function collectIterBindings(Comp, compInstance, seq, opts = {}) {
|
|
15736
15766
|
const whenFn = resolveAlter(Comp, opts.when) ?? filterAlwaysTrue;
|
|
15737
15767
|
const loopWithFn = resolveAlter(Comp, opts.loopWith) ?? nullLoopWith;
|
|
15738
15768
|
const enrichFn = resolveAlter(Comp, opts.enrichWith);
|
|
15769
|
+
const scopeEnrichFn = resolveAlter(Comp, opts.scopeEnrich);
|
|
15739
15770
|
const it = compInstance;
|
|
15740
|
-
const
|
|
15771
|
+
const scope = scopeEnrichFn ? scopeEnrichFn.call(it) ?? {} : opts.scope ?? {};
|
|
15772
|
+
const ctx = {
|
|
15773
|
+
lookup: (name) => scope[name],
|
|
15774
|
+
filter: (key, value, iterData2) => whenFn.call(it, key, value, iterData2)
|
|
15775
|
+
};
|
|
15776
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWithFn.call(it, seq, ctx), seq);
|
|
15741
15777
|
const out = [];
|
|
15778
|
+
if (keys) {
|
|
15779
|
+
for (const key of keys) {
|
|
15780
|
+
const value = seqGet(seq, key);
|
|
15781
|
+
const binds = { key, value };
|
|
15782
|
+
if (enrichFn)
|
|
15783
|
+
enrichFn.call(it, binds, key, value, iterData);
|
|
15784
|
+
out.push(binds);
|
|
15785
|
+
}
|
|
15786
|
+
return out;
|
|
15787
|
+
}
|
|
15742
15788
|
const iter = pickIter(seq);
|
|
15743
15789
|
iter(seq, (key, value) => {
|
|
15744
15790
|
if (!whenFn.call(it, key, value, iterData))
|
|
@@ -16002,6 +16048,7 @@ export {
|
|
|
16002
16048
|
removeIn,
|
|
16003
16049
|
remove,
|
|
16004
16050
|
phaseOps,
|
|
16051
|
+
phaseHasBubble,
|
|
16005
16052
|
mergeWith$1 as mergeWith,
|
|
16006
16053
|
mergeDeepWith$1 as mergeDeepWith,
|
|
16007
16054
|
mergeDeep$1 as mergeDeep,
|