tutuca 0.9.78 → 0.9.80

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.
Files changed (33) hide show
  1. package/README.md +1 -1
  2. package/dist/tutuca-cli.js +132 -58
  3. package/dist/tutuca-dev.ext.js +155 -83
  4. package/dist/tutuca-dev.js +155 -83
  5. package/dist/tutuca-dev.min.js +3 -3
  6. package/dist/tutuca-extra.ext.js +92 -72
  7. package/dist/tutuca-extra.js +92 -72
  8. package/dist/tutuca-extra.min.js +3 -3
  9. package/dist/tutuca.ext.js +93 -73
  10. package/dist/tutuca.js +92 -72
  11. package/dist/tutuca.min.js +3 -3
  12. package/package.json +1 -1
  13. package/skill/tutuca/SKILL.md +4 -3
  14. package/skill/tutuca/advanced.md +22 -18
  15. package/skill/tutuca/core.md +57 -2
  16. package/skill/tutuca/patterns/README.md +42 -0
  17. package/skill/tutuca/patterns/bind-text-and-attributes.md +30 -0
  18. package/skill/tutuca/patterns/conditional-attribute-value.md +29 -0
  19. package/skill/tutuca/patterns/coordinate-components.md +26 -0
  20. package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +27 -0
  21. package/skill/tutuca/patterns/enrich-each-item.md +25 -0
  22. package/skill/tutuca/patterns/filter-a-list.md +23 -0
  23. package/skill/tutuca/patterns/handle-events.md +27 -0
  24. package/skill/tutuca/patterns/iterate-a-list.md +18 -0
  25. package/skill/tutuca/patterns/paginate-a-list.md +27 -0
  26. package/skill/tutuca/patterns/render-a-child-component.md +20 -0
  27. package/skill/tutuca/patterns/reuse-markup-with-macros.md +35 -0
  28. package/skill/tutuca/patterns/share-state-without-prop-drilling.md +30 -0
  29. package/skill/tutuca/patterns/show-or-hide-content.md +22 -0
  30. package/skill/tutuca/patterns/switch-between-views.md +26 -0
  31. package/skill/tutuca/patterns/tabbed-interface.md +38 -0
  32. package/skill/tutuca/semantics.md +2 -2
  33. package/skill/tutuca-source/tutuca.ext.js +93 -73
@@ -474,6 +474,7 @@ var G_BOOL = K_FIELD | K_METHOD | K_BIND | K_DYN | K_CONST;
474
474
  var G_TEXT = G_BOOL | K_STRTPL;
475
475
  var G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
476
476
  var G_SEQUENCE = K_FIELD | K_DYN;
477
+ var G_PROVIDE = K_FIELD | K_SEQ;
477
478
  var G_FIELD = K_FIELD | K_METHOD | K_CONST | K_STR | K_SEQ;
478
479
  var G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_REQUEST | K_CONST;
479
480
  var G_PRED_ARG = G_BOOL | K_STR;
@@ -592,6 +593,9 @@ class ValParser {
592
593
  parseField(s, px) {
593
594
  return this._parseSingle(s, px, G_FIELD);
594
595
  }
596
+ parseProvide(s, px) {
597
+ return this._parseSingle(s, px, G_PROVIDE);
598
+ }
595
599
  parseHandlerArg(s, px) {
596
600
  return this._parseSingle(s, px, G_HANDLER_ARG);
597
601
  }
@@ -1578,21 +1582,22 @@ function h(tagName, properties, children, namespace) {
1578
1582
  }
1579
1583
 
1580
1584
  // src/anode.js
1581
- function resolveDynProducer(comp, dynName) {
1582
- const dyn = comp?.dynamic?.[dynName];
1583
- if (dyn == null)
1584
- return null;
1585
- let producerComp, producerDyn;
1586
- if (dyn.compName != null) {
1587
- producerComp = comp.scope?.lookupComponent(dyn.compName);
1588
- producerDyn = producerComp?.dynamic?.[dyn.dynName];
1585
+ function resolveDynProducer(comp, name) {
1586
+ let producerComp, producerProvide;
1587
+ const lk = comp?.lookup?.[name];
1588
+ if (lk != null) {
1589
+ producerComp = comp.scope?.lookupComponent(lk.compName);
1590
+ producerProvide = producerComp?.provide?.[lk.provideName];
1589
1591
  } else {
1592
+ const p = comp?.provide?.[name];
1593
+ if (p == null)
1594
+ return null;
1590
1595
  producerComp = comp;
1591
- producerDyn = dyn;
1596
+ producerProvide = p;
1592
1597
  }
1593
- if (producerComp == null || producerDyn == null)
1598
+ if (producerComp == null || producerProvide == null)
1594
1599
  return null;
1595
- const pi = producerDyn.val?.toPathItem?.() ?? null;
1600
+ const pi = producerProvide.val?.toPathItem?.() ?? null;
1596
1601
  return { producerCompId: producerComp.id, producerSteps: pi ? [pi] : [] };
1597
1602
  }
1598
1603
 
@@ -2335,9 +2340,6 @@ class Components {
2335
2340
  getCompFor(v) {
2336
2341
  return v?.[this.getComponentSymbol]?.() ?? null;
2337
2342
  }
2338
- getOnEnterFor(v) {
2339
- return this.getCompFor(v)?.on.stackEnter ?? defaultOnStackEnter;
2340
- }
2341
2343
  getHandlerFor(v, name, key) {
2342
2344
  return this.getCompFor(v)?.[key][name] ?? null;
2343
2345
  }
@@ -2407,36 +2409,30 @@ class ComponentStack {
2407
2409
  }
2408
2410
  }
2409
2411
 
2410
- class Dynamic {
2412
+ class ProvideInfo {
2411
2413
  constructor(name, val, symbol) {
2412
2414
  this.name = name;
2413
2415
  this.val = val;
2414
2416
  this.symbol = symbol;
2415
2417
  }
2416
- getSymbol(_stack) {
2417
- return this.symbol;
2418
- }
2419
- evalAndBind(stack, binds) {
2420
- binds[this.getSymbol(stack)] = this.val.eval(stack);
2421
- }
2422
2418
  }
2423
2419
 
2424
- class DynamicAlias extends Dynamic {
2425
- constructor(name, val, compName, dynName) {
2426
- super(name, val, null);
2420
+ class LookupInfo {
2421
+ constructor(name, compName, provideName, val) {
2422
+ this.name = name;
2427
2423
  this.compName = compName;
2428
- this.dynName = dynName;
2429
- }
2430
- _resolveSymbol(stack) {
2431
- return stack.lookupType(this.compName)?.dynamic[this.dynName]?.symbol ?? null;
2424
+ this.provideName = provideName;
2425
+ this.val = val;
2426
+ this._sym = undefined;
2432
2427
  }
2433
- getSymbol(stack) {
2434
- this.symbol ??= this._resolveSymbol(stack);
2435
- return this.symbol;
2428
+ getProducerSymbol(stack) {
2429
+ if (this._sym === undefined)
2430
+ this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
2431
+ return this._sym;
2436
2432
  }
2437
2433
  }
2438
2434
  var isString = (v) => typeof v === "string";
2439
- var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter on views dynamic fields methods statics";
2435
+ var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics";
2440
2436
  var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
2441
2437
  var _compId = 0;
2442
2438
 
@@ -2453,35 +2449,47 @@ class Component {
2453
2449
  this.bubble = o.bubble ?? {};
2454
2450
  this.response = o.response ?? {};
2455
2451
  this.alter = o.alter ?? {};
2456
- this.on = { stackEnter: o.on?.stackEnter ?? defaultOnStackEnter };
2457
2452
  for (const name in o.views ?? {}) {
2458
2453
  const v = o.views[name];
2459
2454
  const { view, style } = isString(v) ? { view: v } : v;
2460
2455
  this.views[name] = new View(name, view, style);
2461
2456
  }
2462
- this._rawDynamic = o.dynamic ?? {};
2463
- this.dynamic = {};
2457
+ this._rawProvide = o.provide ?? {};
2458
+ this._rawLookup = o.lookup ?? {};
2459
+ this.provide = {};
2460
+ this.lookup = {};
2464
2461
  this.scope = null;
2462
+ this.spec = o;
2465
2463
  this.extra = {};
2466
2464
  for (const key of Object.keys(o))
2467
2465
  if (!KNOWN_SPEC_KEYS.has(key))
2468
2466
  this.extra[key] = o[key];
2469
2467
  }
2468
+ clone() {
2469
+ return Component.fromSpec(this.spec);
2470
+ }
2470
2471
  compile(ParseContext2) {
2471
2472
  for (const name in this.views)
2472
2473
  this.views[name].compile(new ParseContext2, this.scope, this.id);
2473
- for (const key in this._rawDynamic) {
2474
- const dinfo = this._rawDynamic[key];
2475
- if (isString(dinfo)) {
2476
- const val = vp.parseField(dinfo, this.views.main.ctx);
2477
- this.dynamic[key] = new Dynamic(key, val, Symbol(key));
2478
- } else if (isString(dinfo?.default) && isString(dinfo?.for)) {
2479
- const val = vp.parseField(dinfo.default, this.views.main.ctx);
2480
- const [compName, dynName] = dinfo.for.split(".");
2481
- if (isString(compName) && isString(dynName))
2482
- this.dynamic[key] = new DynamicAlias(key, val, compName, dynName);
2483
- }
2474
+ const ctx = this.views.main.ctx;
2475
+ for (const key in this._rawProvide) {
2476
+ const val = vp.parseProvide(this._rawProvide[key], ctx);
2477
+ if (val)
2478
+ this.provide[key] = new ProvideInfo(key, val, Symbol(key));
2479
+ }
2480
+ for (const key in this._rawLookup) {
2481
+ const linfo = this._rawLookup[key];
2482
+ const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
2483
+ const [compName, provideName] = forStr === null ? [] : forStr.split(".");
2484
+ if (!isString(compName) || !isString(provideName))
2485
+ continue;
2486
+ const defStr = isString(linfo?.default) ? linfo.default : null;
2487
+ const val = defStr === null ? null : vp.parseField(defStr, ctx);
2488
+ this.lookup[key] = new LookupInfo(key, compName, provideName, val);
2484
2489
  }
2490
+ for (const key in this.lookup)
2491
+ if (this.provide[key] !== undefined)
2492
+ console.warn("name declared in both provide and lookup", this.name, key);
2485
2493
  }
2486
2494
  make(args, opts) {
2487
2495
  return this.Class.make(args, opts ?? { scope: this.scope });
@@ -2509,9 +2517,6 @@ class Component {
2509
2517
  `);
2510
2518
  }
2511
2519
  }
2512
- function defaultOnStackEnter() {
2513
- return null;
2514
- }
2515
2520
 
2516
2521
  // src/stack.js
2517
2522
  var STOP = Symbol("STOP");
@@ -2570,47 +2575,61 @@ class Stack {
2570
2575
  this.viewsId = viewsId;
2571
2576
  this.ctx = ctx;
2572
2577
  }
2573
- _enrichOnEnter() {
2574
- return this.withDynamicBinds(this.comps.getOnEnterFor(this.it).call(this.it));
2578
+ _pushProvides() {
2579
+ const provide = this.comps.getCompFor(this.it)?.provide;
2580
+ if (provide == null)
2581
+ return this;
2582
+ const dynObj = {};
2583
+ let has = false;
2584
+ for (const k in provide) {
2585
+ dynObj[provide[k].symbol] = provide[k].val.eval(this);
2586
+ has = true;
2587
+ }
2588
+ if (!has)
2589
+ return this;
2590
+ const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
2591
+ const { comps, it, binds, views, viewsId, ctx } = this;
2592
+ return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
2575
2593
  }
2576
2594
  static root(comps, it, ctx) {
2577
2595
  const binds = [new BindFrame(it, { it }, true), null];
2578
2596
  const dynBinds = [new ObjectFrame({}), null];
2579
2597
  const views = ["main", null];
2580
- return new Stack(comps, it, binds, dynBinds, views, "", ctx)._enrichOnEnter();
2598
+ return new Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
2581
2599
  }
2582
2600
  enter(it, bindings = {}, isFrame = true) {
2583
2601
  const { comps, binds, dynBinds, views, viewsId, ctx } = this;
2584
2602
  const newBinds = [new BindFrame(it, bindings, isFrame), binds];
2585
2603
  const stack = new Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
2586
- return isFrame ? stack._enrichOnEnter() : stack;
2604
+ return isFrame ? stack._pushProvides() : stack;
2587
2605
  }
2588
2606
  pushViewName(name) {
2589
2607
  const { comps, it, binds, dynBinds, views, ctx } = this;
2590
2608
  const newViews = [name, views];
2591
2609
  return new Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
2592
2610
  }
2593
- withDynamicBinds(dynamics) {
2594
- if (dynamics == null || dynamics.length === 0)
2595
- return this;
2596
- const dynObj = {};
2597
- const comp = this.comps.getCompFor(this.it);
2598
- for (const dynName of dynamics)
2599
- comp.dynamic[dynName].evalAndBind(this, dynObj);
2600
- const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
2601
- const { comps, it, binds, views, viewsId, ctx } = this;
2602
- return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
2611
+ _pushDynBindValuesToArray(arr, comp) {
2612
+ for (const k in comp.provide)
2613
+ arr.push(this._lookupProvide(comp.provide[k]));
2614
+ for (const k in comp.lookup)
2615
+ arr.push(this._lookupAlias(comp.lookup[k]));
2603
2616
  }
2604
- _pushDynBindValuesToArray(arr, dyns) {
2605
- for (const k in dyns)
2606
- arr.push(this._lookupDynamicWithDynVal(dyns[k]));
2617
+ _lookupProvide(p) {
2618
+ return lookup(this.dynBinds, p.symbol) ?? p.val.eval(this) ?? null;
2607
2619
  }
2608
- _lookupDynamicWithDynVal(d) {
2609
- return lookup(this.dynBinds, d.getSymbol(this)) ?? d.val?.eval(this) ?? null;
2620
+ _lookupAlias(lk) {
2621
+ const sym = lk.getProducerSymbol(this);
2622
+ return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
2610
2623
  }
2611
2624
  lookupDynamic(name) {
2612
- const d = this.comps.getCompFor(this.it)?.dynamic[name];
2613
- return d ? this._lookupDynamicWithDynVal(d) : null;
2625
+ const comp = this.comps.getCompFor(this.it);
2626
+ if (comp == null)
2627
+ return null;
2628
+ const lk = comp.lookup[name];
2629
+ if (lk !== undefined)
2630
+ return this._lookupAlias(lk);
2631
+ const p = comp.provide[name];
2632
+ return p !== undefined ? this._lookupProvide(p) : null;
2614
2633
  }
2615
2634
  lookupBind(name) {
2616
2635
  return lookup(this.binds, name);
@@ -3702,7 +3721,8 @@ function classFromData(name, { fields = {}, methods, statics }) {
3702
3721
  b.statics(statics);
3703
3722
  return b.build();
3704
3723
  }
3705
- var component = (opts) => new Component(classFromData(opts.name, opts), opts);
3724
+ Component.fromSpec = (opts) => new Component(classFromData(opts.name, opts), opts);
3725
+ var component = (opts) => Component.fromSpec(opts);
3706
3726
 
3707
3727
  // src/renderer.js
3708
3728
  import { isIndexed, isKeyed } from "immutable";
@@ -3824,7 +3844,7 @@ class Renderer {
3824
3844
  _rValComp(stack, val, comp, node, key, viewName) {
3825
3845
  const cacheKey = `${viewName ?? stack.viewsId ?? ""}-${key}`;
3826
3846
  const cachePath = [node, val];
3827
- stack._pushDynBindValuesToArray(cachePath, comp.dynamic);
3847
+ stack._pushDynBindValuesToArray(cachePath, comp);
3828
3848
  const cachedNode = this.cache.get(cachePath, cacheKey);
3829
3849
  if (cachedNode)
3830
3850
  return cachedNode;
@@ -4847,6 +4847,7 @@ var G_BOOL = K_FIELD | K_METHOD | K_BIND | K_DYN | K_CONST;
4847
4847
  var G_TEXT = G_BOOL | K_STRTPL;
4848
4848
  var G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
4849
4849
  var G_SEQUENCE = K_FIELD | K_DYN;
4850
+ var G_PROVIDE = K_FIELD | K_SEQ;
4850
4851
  var G_FIELD = K_FIELD | K_METHOD | K_CONST | K_STR | K_SEQ;
4851
4852
  var G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_REQUEST | K_CONST;
4852
4853
  var G_PRED_ARG = G_BOOL | K_STR;
@@ -4965,6 +4966,9 @@ class ValParser {
4965
4966
  parseField(s, px) {
4966
4967
  return this._parseSingle(s, px, G_FIELD);
4967
4968
  }
4969
+ parseProvide(s, px) {
4970
+ return this._parseSingle(s, px, G_PROVIDE);
4971
+ }
4968
4972
  parseHandlerArg(s, px) {
4969
4973
  return this._parseSingle(s, px, G_HANDLER_ARG);
4970
4974
  }
@@ -5951,21 +5955,22 @@ function h(tagName, properties, children, namespace) {
5951
5955
  }
5952
5956
 
5953
5957
  // src/anode.js
5954
- function resolveDynProducer(comp, dynName) {
5955
- const dyn = comp?.dynamic?.[dynName];
5956
- if (dyn == null)
5957
- return null;
5958
- let producerComp, producerDyn;
5959
- if (dyn.compName != null) {
5960
- producerComp = comp.scope?.lookupComponent(dyn.compName);
5961
- producerDyn = producerComp?.dynamic?.[dyn.dynName];
5958
+ function resolveDynProducer(comp, name) {
5959
+ let producerComp, producerProvide;
5960
+ const lk = comp?.lookup?.[name];
5961
+ if (lk != null) {
5962
+ producerComp = comp.scope?.lookupComponent(lk.compName);
5963
+ producerProvide = producerComp?.provide?.[lk.provideName];
5962
5964
  } else {
5965
+ const p = comp?.provide?.[name];
5966
+ if (p == null)
5967
+ return null;
5963
5968
  producerComp = comp;
5964
- producerDyn = dyn;
5969
+ producerProvide = p;
5965
5970
  }
5966
- if (producerComp == null || producerDyn == null)
5971
+ if (producerComp == null || producerProvide == null)
5967
5972
  return null;
5968
- const pi = producerDyn.val?.toPathItem?.() ?? null;
5973
+ const pi = producerProvide.val?.toPathItem?.() ?? null;
5969
5974
  return { producerCompId: producerComp.id, producerSteps: pi ? [pi] : [] };
5970
5975
  }
5971
5976
 
@@ -6708,9 +6713,6 @@ class Components {
6708
6713
  getCompFor(v) {
6709
6714
  return v?.[this.getComponentSymbol]?.() ?? null;
6710
6715
  }
6711
- getOnEnterFor(v) {
6712
- return this.getCompFor(v)?.on.stackEnter ?? defaultOnStackEnter;
6713
- }
6714
6716
  getHandlerFor(v, name, key) {
6715
6717
  return this.getCompFor(v)?.[key][name] ?? null;
6716
6718
  }
@@ -6780,36 +6782,30 @@ class ComponentStack {
6780
6782
  }
6781
6783
  }
6782
6784
 
6783
- class Dynamic {
6785
+ class ProvideInfo {
6784
6786
  constructor(name, val, symbol) {
6785
6787
  this.name = name;
6786
6788
  this.val = val;
6787
6789
  this.symbol = symbol;
6788
6790
  }
6789
- getSymbol(_stack) {
6790
- return this.symbol;
6791
- }
6792
- evalAndBind(stack, binds) {
6793
- binds[this.getSymbol(stack)] = this.val.eval(stack);
6794
- }
6795
6791
  }
6796
6792
 
6797
- class DynamicAlias extends Dynamic {
6798
- constructor(name, val, compName, dynName) {
6799
- super(name, val, null);
6793
+ class LookupInfo {
6794
+ constructor(name, compName, provideName, val) {
6795
+ this.name = name;
6800
6796
  this.compName = compName;
6801
- this.dynName = dynName;
6802
- }
6803
- _resolveSymbol(stack) {
6804
- return stack.lookupType(this.compName)?.dynamic[this.dynName]?.symbol ?? null;
6797
+ this.provideName = provideName;
6798
+ this.val = val;
6799
+ this._sym = undefined;
6805
6800
  }
6806
- getSymbol(stack) {
6807
- this.symbol ??= this._resolveSymbol(stack);
6808
- return this.symbol;
6801
+ getProducerSymbol(stack) {
6802
+ if (this._sym === undefined)
6803
+ this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
6804
+ return this._sym;
6809
6805
  }
6810
6806
  }
6811
6807
  var isString = (v) => typeof v === "string";
6812
- var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter on views dynamic fields methods statics";
6808
+ var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics";
6813
6809
  var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
6814
6810
  var _compId = 0;
6815
6811
 
@@ -6826,35 +6822,47 @@ class Component {
6826
6822
  this.bubble = o.bubble ?? {};
6827
6823
  this.response = o.response ?? {};
6828
6824
  this.alter = o.alter ?? {};
6829
- this.on = { stackEnter: o.on?.stackEnter ?? defaultOnStackEnter };
6830
6825
  for (const name in o.views ?? {}) {
6831
6826
  const v = o.views[name];
6832
6827
  const { view, style } = isString(v) ? { view: v } : v;
6833
6828
  this.views[name] = new View(name, view, style);
6834
6829
  }
6835
- this._rawDynamic = o.dynamic ?? {};
6836
- this.dynamic = {};
6830
+ this._rawProvide = o.provide ?? {};
6831
+ this._rawLookup = o.lookup ?? {};
6832
+ this.provide = {};
6833
+ this.lookup = {};
6837
6834
  this.scope = null;
6835
+ this.spec = o;
6838
6836
  this.extra = {};
6839
6837
  for (const key of Object.keys(o))
6840
6838
  if (!KNOWN_SPEC_KEYS.has(key))
6841
6839
  this.extra[key] = o[key];
6842
6840
  }
6841
+ clone() {
6842
+ return Component.fromSpec(this.spec);
6843
+ }
6843
6844
  compile(ParseContext2) {
6844
6845
  for (const name in this.views)
6845
6846
  this.views[name].compile(new ParseContext2, this.scope, this.id);
6846
- for (const key in this._rawDynamic) {
6847
- const dinfo = this._rawDynamic[key];
6848
- if (isString(dinfo)) {
6849
- const val = vp.parseField(dinfo, this.views.main.ctx);
6850
- this.dynamic[key] = new Dynamic(key, val, Symbol(key));
6851
- } else if (isString(dinfo?.default) && isString(dinfo?.for)) {
6852
- const val = vp.parseField(dinfo.default, this.views.main.ctx);
6853
- const [compName, dynName] = dinfo.for.split(".");
6854
- if (isString(compName) && isString(dynName))
6855
- this.dynamic[key] = new DynamicAlias(key, val, compName, dynName);
6856
- }
6847
+ const ctx = this.views.main.ctx;
6848
+ for (const key in this._rawProvide) {
6849
+ const val = vp.parseProvide(this._rawProvide[key], ctx);
6850
+ if (val)
6851
+ this.provide[key] = new ProvideInfo(key, val, Symbol(key));
6852
+ }
6853
+ for (const key in this._rawLookup) {
6854
+ const linfo = this._rawLookup[key];
6855
+ const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
6856
+ const [compName, provideName] = forStr === null ? [] : forStr.split(".");
6857
+ if (!isString(compName) || !isString(provideName))
6858
+ continue;
6859
+ const defStr = isString(linfo?.default) ? linfo.default : null;
6860
+ const val = defStr === null ? null : vp.parseField(defStr, ctx);
6861
+ this.lookup[key] = new LookupInfo(key, compName, provideName, val);
6857
6862
  }
6863
+ for (const key in this.lookup)
6864
+ if (this.provide[key] !== undefined)
6865
+ console.warn("name declared in both provide and lookup", this.name, key);
6858
6866
  }
6859
6867
  make(args, opts) {
6860
6868
  return this.Class.make(args, opts ?? { scope: this.scope });
@@ -6882,9 +6890,6 @@ class Component {
6882
6890
  `);
6883
6891
  }
6884
6892
  }
6885
- function defaultOnStackEnter() {
6886
- return null;
6887
- }
6888
6893
 
6889
6894
  // src/stack.js
6890
6895
  var STOP = Symbol("STOP");
@@ -6943,47 +6948,61 @@ class Stack2 {
6943
6948
  this.viewsId = viewsId;
6944
6949
  this.ctx = ctx;
6945
6950
  }
6946
- _enrichOnEnter() {
6947
- return this.withDynamicBinds(this.comps.getOnEnterFor(this.it).call(this.it));
6951
+ _pushProvides() {
6952
+ const provide = this.comps.getCompFor(this.it)?.provide;
6953
+ if (provide == null)
6954
+ return this;
6955
+ const dynObj = {};
6956
+ let has2 = false;
6957
+ for (const k in provide) {
6958
+ dynObj[provide[k].symbol] = provide[k].val.eval(this);
6959
+ has2 = true;
6960
+ }
6961
+ if (!has2)
6962
+ return this;
6963
+ const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
6964
+ const { comps, it, binds, views, viewsId, ctx } = this;
6965
+ return new Stack2(comps, it, binds, newDynBinds, views, viewsId, ctx);
6948
6966
  }
6949
6967
  static root(comps, it, ctx) {
6950
6968
  const binds = [new BindFrame(it, { it }, true), null];
6951
6969
  const dynBinds = [new ObjectFrame({}), null];
6952
6970
  const views = ["main", null];
6953
- return new Stack2(comps, it, binds, dynBinds, views, "", ctx)._enrichOnEnter();
6971
+ return new Stack2(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
6954
6972
  }
6955
6973
  enter(it, bindings = {}, isFrame = true) {
6956
6974
  const { comps, binds, dynBinds, views, viewsId, ctx } = this;
6957
6975
  const newBinds = [new BindFrame(it, bindings, isFrame), binds];
6958
6976
  const stack = new Stack2(comps, it, newBinds, dynBinds, views, viewsId, ctx);
6959
- return isFrame ? stack._enrichOnEnter() : stack;
6977
+ return isFrame ? stack._pushProvides() : stack;
6960
6978
  }
6961
6979
  pushViewName(name) {
6962
6980
  const { comps, it, binds, dynBinds, views, ctx } = this;
6963
6981
  const newViews = [name, views];
6964
6982
  return new Stack2(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
6965
6983
  }
6966
- withDynamicBinds(dynamics) {
6967
- if (dynamics == null || dynamics.length === 0)
6968
- return this;
6969
- const dynObj = {};
6970
- const comp = this.comps.getCompFor(this.it);
6971
- for (const dynName of dynamics)
6972
- comp.dynamic[dynName].evalAndBind(this, dynObj);
6973
- const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
6974
- const { comps, it, binds, views, viewsId, ctx } = this;
6975
- return new Stack2(comps, it, binds, newDynBinds, views, viewsId, ctx);
6984
+ _pushDynBindValuesToArray(arr, comp) {
6985
+ for (const k in comp.provide)
6986
+ arr.push(this._lookupProvide(comp.provide[k]));
6987
+ for (const k in comp.lookup)
6988
+ arr.push(this._lookupAlias(comp.lookup[k]));
6976
6989
  }
6977
- _pushDynBindValuesToArray(arr, dyns) {
6978
- for (const k in dyns)
6979
- arr.push(this._lookupDynamicWithDynVal(dyns[k]));
6990
+ _lookupProvide(p) {
6991
+ return lookup(this.dynBinds, p.symbol) ?? p.val.eval(this) ?? null;
6980
6992
  }
6981
- _lookupDynamicWithDynVal(d) {
6982
- return lookup(this.dynBinds, d.getSymbol(this)) ?? d.val?.eval(this) ?? null;
6993
+ _lookupAlias(lk) {
6994
+ const sym = lk.getProducerSymbol(this);
6995
+ return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
6983
6996
  }
6984
6997
  lookupDynamic(name) {
6985
- const d = this.comps.getCompFor(this.it)?.dynamic[name];
6986
- return d ? this._lookupDynamicWithDynVal(d) : null;
6998
+ const comp = this.comps.getCompFor(this.it);
6999
+ if (comp == null)
7000
+ return null;
7001
+ const lk = comp.lookup[name];
7002
+ if (lk !== undefined)
7003
+ return this._lookupAlias(lk);
7004
+ const p = comp.provide[name];
7005
+ return p !== undefined ? this._lookupProvide(p) : null;
6987
7006
  }
6988
7007
  lookupBind(name) {
6989
7008
  return lookup(this.binds, name);
@@ -8071,7 +8090,8 @@ function classFromData(name, { fields = {}, methods, statics }) {
8071
8090
  b.statics(statics);
8072
8091
  return b.build();
8073
8092
  }
8074
- var component = (opts) => new Component(classFromData(opts.name, opts), opts);
8093
+ Component.fromSpec = (opts) => new Component(classFromData(opts.name, opts), opts);
8094
+ var component = (opts) => Component.fromSpec(opts);
8075
8095
 
8076
8096
  // src/cache.js
8077
8097
  class NullDomCache {
@@ -8190,7 +8210,7 @@ class Renderer {
8190
8210
  _rValComp(stack, val, comp, node, key, viewName) {
8191
8211
  const cacheKey = `${viewName ?? stack.viewsId ?? ""}-${key}`;
8192
8212
  const cachePath = [node, val];
8193
- stack._pushDynBindValuesToArray(cachePath, comp.dynamic);
8213
+ stack._pushDynBindValuesToArray(cachePath, comp);
8194
8214
  const cachedNode = this.cache.get(cachePath, cacheKey);
8195
8215
  if (cachedNode)
8196
8216
  return cachedNode;