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
package/README.md CHANGED
@@ -168,7 +168,7 @@ npx tutuca install-skill --dot-agents
168
168
  npx tutuca install-skill --force
169
169
  ```
170
170
 
171
- The skill content is generated from `docs/llm/`, so the same reference
171
+ The skill content is generated from `docs/skill/`, so the same reference
172
172
  runs locally (`tutuca lint <module>` + `tutuca render <module> --title …`)
173
173
  and inside Claude.
174
174
 
@@ -4779,6 +4779,9 @@ class ValParser {
4779
4779
  parseField(s, px) {
4780
4780
  return this._parseSingle(s, px, G_FIELD);
4781
4781
  }
4782
+ parseProvide(s, px) {
4783
+ return this._parseSingle(s, px, G_PROVIDE);
4784
+ }
4782
4785
  parseHandlerArg(s, px) {
4783
4786
  return this._parseSingle(s, px, G_HANDLER_ARG);
4784
4787
  }
@@ -4883,7 +4886,7 @@ class BaseVal {
4883
4886
  return this.eval(stack);
4884
4887
  }
4885
4888
  }
4886
- var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64, K_REQUEST = 128, K_SEQ = 256, K_STR = 512, K_METHOD = 1024, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_FIELD, G_VALUE, G_PRED_ARG, G_HANDLER_ARG, G_ALL, predTruthy = (v) => {
4889
+ var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64, K_REQUEST = 128, K_SEQ = 256, K_STR = 512, K_METHOD = 1024, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_PRED_ARG, G_HANDLER_ARG, G_ALL, predTruthy = (v) => {
4887
4890
  const n = sizeOf(v);
4888
4891
  return n === null ? !!v : n > 0;
4889
4892
  }, PREDICATES, ConstVal, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler = (type, name) => function(...args) {
@@ -4901,6 +4904,7 @@ var init_value = __esm(() => {
4901
4904
  G_TEXT = G_BOOL | K_STRTPL;
4902
4905
  G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
4903
4906
  G_SEQUENCE = K_FIELD | K_DYN;
4907
+ G_PROVIDE = K_FIELD | K_SEQ;
4904
4908
  G_FIELD = K_FIELD | K_METHOD | K_CONST | K_STR | K_SEQ;
4905
4909
  G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_REQUEST | K_CONST;
4906
4910
  G_PRED_ARG = G_BOOL | K_STR;
@@ -5764,21 +5768,22 @@ var init_vdom = __esm(() => {
5764
5768
  });
5765
5769
 
5766
5770
  // src/anode.js
5767
- function resolveDynProducer(comp, dynName) {
5768
- const dyn = comp?.dynamic?.[dynName];
5769
- if (dyn == null)
5770
- return null;
5771
- let producerComp, producerDyn;
5772
- if (dyn.compName != null) {
5773
- producerComp = comp.scope?.lookupComponent(dyn.compName);
5774
- producerDyn = producerComp?.dynamic?.[dyn.dynName];
5771
+ function resolveDynProducer(comp, name) {
5772
+ let producerComp, producerProvide;
5773
+ const lk = comp?.lookup?.[name];
5774
+ if (lk != null) {
5775
+ producerComp = comp.scope?.lookupComponent(lk.compName);
5776
+ producerProvide = producerComp?.provide?.[lk.provideName];
5775
5777
  } else {
5778
+ const p = comp?.provide?.[name];
5779
+ if (p == null)
5780
+ return null;
5776
5781
  producerComp = comp;
5777
- producerDyn = dyn;
5782
+ producerProvide = p;
5778
5783
  }
5779
- if (producerComp == null || producerDyn == null)
5784
+ if (producerComp == null || producerProvide == null)
5780
5785
  return null;
5781
- const pi = producerDyn.val?.toPathItem?.() ?? null;
5786
+ const pi = producerProvide.val?.toPathItem?.() ?? null;
5782
5787
  return { producerCompId: producerComp.id, producerSteps: pi ? [pi] : [] };
5783
5788
  }
5784
5789
 
@@ -8736,8 +8741,6 @@ function classifyBadValue(value) {
8736
8741
  const s = value.trim();
8737
8742
  if (s === "")
8738
8743
  return null;
8739
- if (/\{[^}]*\}/.test(s) && !s.startsWith("$'"))
8740
- return "legacy-template";
8741
8744
  if (/\s\?\s.+\s:\s/.test(s))
8742
8745
  return "ternary";
8743
8746
  if (/===|!==|==|!=|<=|>=|\s<\s|\s>\s/.test(s))
@@ -8752,6 +8755,8 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
8752
8755
  return lx.push({ componentName: Comp.name }, () => {
8753
8756
  checkUnknownSpecKeys(lx, Comp, wellKnownExtras);
8754
8757
  checkFieldDeclarations(lx, Comp);
8758
+ checkProvidesAreAddressable(lx, Comp);
8759
+ checkLookupShapes(lx, Comp);
8755
8760
  const referencedAlters = new Set;
8756
8761
  const referencedInputs = new Set;
8757
8762
  const referencedDynamics = new Set;
@@ -8907,10 +8912,11 @@ function checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedDyna
8907
8912
  }
8908
8913
  }
8909
8914
  function mkAttrValEnv(Comp, referencedAlters, referencedDynamics) {
8910
- const { scope, alter, dynamic, Class } = Comp;
8915
+ const { scope, alter, provide, lookup, Class } = Comp;
8911
8916
  const { prototype: proto } = Class;
8912
8917
  const { fields } = Class.getMetaClass();
8913
- return { fields, proto, scope, alter, referencedAlters, dynamicMap: dynamic, referencedDynamics };
8918
+ const dynamicMap = { ...provide, ...lookup };
8919
+ return { fields, proto, scope, alter, referencedAlters, dynamicMap, referencedDynamics };
8914
8920
  }
8915
8921
  function checkEventHandlersHaveImpls(lx, Comp, referencedInputs) {
8916
8922
  const { input, views, Class } = Comp;
@@ -9147,10 +9153,50 @@ function checkUnreferencedInputHandlers(lx, Comp, referencedInputs) {
9147
9153
  }
9148
9154
  }
9149
9155
  }
9156
+ function checkProvidesAreAddressable(lx, Comp) {
9157
+ for (const name in Comp._rawProvide) {
9158
+ if (Comp.provide[name] === undefined) {
9159
+ lx.error(PROVIDE_NOT_ADDRESSABLE, { name, value: Comp._rawProvide[name] });
9160
+ }
9161
+ }
9162
+ }
9163
+ function checkLookupShapes(lx, Comp) {
9164
+ for (const name in Comp._rawLookup) {
9165
+ const raw = Comp._rawLookup[name];
9166
+ let target;
9167
+ if (typeof raw === "string") {
9168
+ target = raw;
9169
+ } else if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
9170
+ lx.error(LOOKUP_BAD_SHAPE, {
9171
+ name,
9172
+ problem: 'must be a "Producer.provideName" string or a { for, default } object'
9173
+ });
9174
+ continue;
9175
+ } else {
9176
+ const extra = Object.keys(raw).filter((k) => !KNOWN_LOOKUP_KEYS.has(k));
9177
+ if (extra.length > 0) {
9178
+ lx.error(LOOKUP_BAD_SHAPE, { name, problem: `unknown key(s): ${extra.join(", ")}` });
9179
+ continue;
9180
+ }
9181
+ if (typeof raw.for !== "string") {
9182
+ lx.error(LOOKUP_BAD_SHAPE, { name, problem: "'for' is required and must be a string" });
9183
+ continue;
9184
+ }
9185
+ if (raw.default !== undefined && typeof raw.default !== "string") {
9186
+ lx.error(LOOKUP_BAD_SHAPE, { name, problem: "'default' must be a string" });
9187
+ continue;
9188
+ }
9189
+ target = raw.for;
9190
+ }
9191
+ const parts = target.split(".");
9192
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
9193
+ lx.error(LOOKUP_TARGET_MALFORMED, { name, target });
9194
+ }
9195
+ }
9196
+ }
9150
9197
  function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
9151
- for (const name in Comp.dynamic) {
9152
- const dyn = Comp.dynamic[name];
9153
- if (dyn.constructor.name === "DynamicAlias" && !referencedDynamics.has(name)) {
9198
+ for (const name in Comp.lookup) {
9199
+ if (!referencedDynamics.has(name)) {
9154
9200
  lx.hint(DYN_ALIAS_NOT_REFERENCED, { name });
9155
9201
  }
9156
9202
  }
@@ -9183,11 +9229,11 @@ class LintContext {
9183
9229
  this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
9184
9230
  }
9185
9231
  }
9186
- var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, LintParseContext;
9232
+ var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, KNOWN_LOOKUP_KEYS, LintParseContext;
9187
9233
  var init_lint_check = __esm(() => {
9188
9234
  init_anode();
9189
9235
  init_htmllinter();
9190
- KNOWN_COMPONENT_SPEC_KEYS = new Set("name view style commonStyle globalStyle input receive bubble response alter on views dynamic fields methods statics".split(" "));
9236
+ KNOWN_COMPONENT_SPEC_KEYS = new Set("name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics".split(" "));
9191
9237
  EMPTY_SET2 = new Set;
9192
9238
  KNOWN_DIRECTIVE_NAMES = new Set([
9193
9239
  "dangerouslysetinnerhtml",
@@ -9225,7 +9271,6 @@ var init_lint_check = __esm(() => {
9225
9271
  "bad-value": { id: BAD_VALUE }
9226
9272
  };
9227
9273
  UNSUPPORTED_EXPR_GUIDANCE = {
9228
- "legacy-template": "Unquoted {...} string templates are no longer supported. Wrap the value in $'...', e.g. $'flex {.color}'.",
9229
9274
  ternary: "Ternary expressions aren't supported in dynamic attributes. Define a method or computed field on the component that returns the value, then reference it as '$methodName'.",
9230
9275
  comparison: "Comparisons aren't supported in dynamic attributes. Define a method like 'isFooSelected' that returns the boolean, then reference it as '$isFooSelected'.",
9231
9276
  logical: "Logical operators aren't supported in dynamic attributes. Combine the conditions in a method on the component and reference it as '$methodName'.",
@@ -9332,6 +9377,7 @@ var init_lint_check = __esm(() => {
9332
9377
  HideNode: { originAttr: "<x hide>" },
9333
9378
  PushViewNameNode: { originAttr: "<x push-view>" }
9334
9379
  };
9380
+ KNOWN_LOOKUP_KEYS = new Set(["for", "default"]);
9335
9381
  LintParseContext = class LintParseContext extends ParseContext {
9336
9382
  constructor(document2, Text, Comment) {
9337
9383
  super(document2, Text, Comment);
@@ -9437,13 +9483,31 @@ var init_lint_rules = __esm(() => {
9437
9483
  code: DYN_VAL_NOT_DEFINED,
9438
9484
  level: "error",
9439
9485
  group: "Dynamic bindings",
9440
- summary: "`*name` references a dynamic binding not declared in `dynamic`."
9486
+ summary: "`*name` references a binding not declared in `provide` or `lookup`."
9441
9487
  },
9442
9488
  {
9443
9489
  code: DYN_ALIAS_NOT_REFERENCED,
9444
9490
  level: "hint",
9445
9491
  group: "Dynamic bindings",
9446
- summary: "`dynamic` alias is defined but never read as `*name` in a view."
9492
+ summary: "`lookup` entry is defined but never read as `*name` in a view."
9493
+ },
9494
+ {
9495
+ code: PROVIDE_NOT_ADDRESSABLE,
9496
+ level: "error",
9497
+ group: "Dynamic bindings",
9498
+ summary: "`provide` value must be a field (`.f`) or seq-access (`.s[.k]`) path."
9499
+ },
9500
+ {
9501
+ code: LOOKUP_BAD_SHAPE,
9502
+ level: "error",
9503
+ group: "Dynamic bindings",
9504
+ summary: "`lookup` entry must be a string or `{ for, default }` (known keys, string values)."
9505
+ },
9506
+ {
9507
+ code: LOOKUP_TARGET_MALFORMED,
9508
+ level: "error",
9509
+ group: "Dynamic bindings",
9510
+ summary: '`lookup` target must be `"Producer.provideName"` (string or `for`).'
9447
9511
  },
9448
9512
  {
9449
9513
  code: RENDER_IT_OUTSIDE_OF_LOOP,
@@ -13155,9 +13219,6 @@ function parseExample(raw, index, components, parentPath) {
13155
13219
  if (!raw || typeof raw !== "object") {
13156
13220
  throw shapeError(`example at ${where} is not an object`, where);
13157
13221
  }
13158
- if (raw.value === undefined && raw.item !== undefined) {
13159
- throw shapeError(`example at ${where} uses legacy "item" key; rename to "value"`, where);
13160
- }
13161
13222
  if (raw.value === undefined) {
13162
13223
  throw shapeError(`example at ${where} missing "value"`, where);
13163
13224
  }
@@ -13484,9 +13545,6 @@ class Components {
13484
13545
  getCompFor(v) {
13485
13546
  return v?.[this.getComponentSymbol]?.() ?? null;
13486
13547
  }
13487
- getOnEnterFor(v) {
13488
- return this.getCompFor(v)?.on.stackEnter ?? defaultOnStackEnter;
13489
- }
13490
13548
  getHandlerFor(v, name, key) {
13491
13549
  return this.getCompFor(v)?.[key][name] ?? null;
13492
13550
  }
@@ -13555,10 +13613,7 @@ class ComponentStack {
13555
13613
  return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
13556
13614
  }
13557
13615
  }
13558
- function defaultOnStackEnter() {
13559
- return null;
13560
- }
13561
- var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter on views dynamic fields methods statics", KNOWN_SPEC_KEYS;
13616
+ var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics", KNOWN_SPEC_KEYS;
13562
13617
  var init_components = __esm(() => {
13563
13618
  init_attribute();
13564
13619
  KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
@@ -13645,47 +13700,61 @@ class Stack2 {
13645
13700
  this.viewsId = viewsId;
13646
13701
  this.ctx = ctx;
13647
13702
  }
13648
- _enrichOnEnter() {
13649
- return this.withDynamicBinds(this.comps.getOnEnterFor(this.it).call(this.it));
13703
+ _pushProvides() {
13704
+ const provide = this.comps.getCompFor(this.it)?.provide;
13705
+ if (provide == null)
13706
+ return this;
13707
+ const dynObj = {};
13708
+ let has2 = false;
13709
+ for (const k in provide) {
13710
+ dynObj[provide[k].symbol] = provide[k].val.eval(this);
13711
+ has2 = true;
13712
+ }
13713
+ if (!has2)
13714
+ return this;
13715
+ const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
13716
+ const { comps, it, binds, views, viewsId, ctx } = this;
13717
+ return new Stack2(comps, it, binds, newDynBinds, views, viewsId, ctx);
13650
13718
  }
13651
13719
  static root(comps, it, ctx) {
13652
13720
  const binds = [new BindFrame(it, { it }, true), null];
13653
13721
  const dynBinds = [new ObjectFrame({}), null];
13654
13722
  const views = ["main", null];
13655
- return new Stack2(comps, it, binds, dynBinds, views, "", ctx)._enrichOnEnter();
13723
+ return new Stack2(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
13656
13724
  }
13657
13725
  enter(it, bindings = {}, isFrame = true) {
13658
13726
  const { comps, binds, dynBinds, views, viewsId, ctx } = this;
13659
13727
  const newBinds = [new BindFrame(it, bindings, isFrame), binds];
13660
13728
  const stack = new Stack2(comps, it, newBinds, dynBinds, views, viewsId, ctx);
13661
- return isFrame ? stack._enrichOnEnter() : stack;
13729
+ return isFrame ? stack._pushProvides() : stack;
13662
13730
  }
13663
13731
  pushViewName(name) {
13664
13732
  const { comps, it, binds, dynBinds, views, ctx } = this;
13665
13733
  const newViews = [name, views];
13666
13734
  return new Stack2(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
13667
13735
  }
13668
- withDynamicBinds(dynamics) {
13669
- if (dynamics == null || dynamics.length === 0)
13670
- return this;
13671
- const dynObj = {};
13672
- const comp = this.comps.getCompFor(this.it);
13673
- for (const dynName of dynamics)
13674
- comp.dynamic[dynName].evalAndBind(this, dynObj);
13675
- const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
13676
- const { comps, it, binds, views, viewsId, ctx } = this;
13677
- return new Stack2(comps, it, binds, newDynBinds, views, viewsId, ctx);
13736
+ _pushDynBindValuesToArray(arr, comp) {
13737
+ for (const k in comp.provide)
13738
+ arr.push(this._lookupProvide(comp.provide[k]));
13739
+ for (const k in comp.lookup)
13740
+ arr.push(this._lookupAlias(comp.lookup[k]));
13678
13741
  }
13679
- _pushDynBindValuesToArray(arr, dyns) {
13680
- for (const k in dyns)
13681
- arr.push(this._lookupDynamicWithDynVal(dyns[k]));
13742
+ _lookupProvide(p) {
13743
+ return lookup(this.dynBinds, p.symbol) ?? p.val.eval(this) ?? null;
13682
13744
  }
13683
- _lookupDynamicWithDynVal(d) {
13684
- return lookup(this.dynBinds, d.getSymbol(this)) ?? d.val?.eval(this) ?? null;
13745
+ _lookupAlias(lk) {
13746
+ const sym = lk.getProducerSymbol(this);
13747
+ return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
13685
13748
  }
13686
13749
  lookupDynamic(name) {
13687
- const d = this.comps.getCompFor(this.it)?.dynamic[name];
13688
- return d ? this._lookupDynamicWithDynVal(d) : null;
13750
+ const comp = this.comps.getCompFor(this.it);
13751
+ if (comp == null)
13752
+ return null;
13753
+ const lk = comp.lookup[name];
13754
+ if (lk !== undefined)
13755
+ return this._lookupAlias(lk);
13756
+ const p = comp.provide[name];
13757
+ return p !== undefined ? this._lookupProvide(p) : null;
13689
13758
  }
13690
13759
  lookupBind(name) {
13691
13760
  return lookup(this.binds, name);
@@ -14457,7 +14526,7 @@ class Renderer {
14457
14526
  _rValComp(stack, val, comp, node, key, viewName) {
14458
14527
  const cacheKey = `${viewName ?? stack.viewsId ?? ""}-${key}`;
14459
14528
  const cachePath = [node, val];
14460
- stack._pushDynBindValuesToArray(cachePath, comp.dynamic);
14529
+ stack._pushDynBindValuesToArray(cachePath, comp);
14461
14530
  const cachedNode = this.cache.get(cachePath, cacheKey);
14462
14531
  if (cachedNode)
14463
14532
  return cachedNode;
@@ -15078,7 +15147,13 @@ function lintIdToMessage(id, info) {
15078
15147
  case "DYN_VAL_NOT_DEFINED":
15079
15148
  return `Dynamic variable '*${info.name}' is not defined${fmtOriginSuffix(info)}`;
15080
15149
  case "DYN_ALIAS_NOT_REFERENCED":
15081
- return `Dynamic '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
15150
+ return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
15151
+ case "PROVIDE_NOT_ADDRESSABLE":
15152
+ return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a method/constant can't be a render target`;
15153
+ case "LOOKUP_BAD_SHAPE":
15154
+ return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
15155
+ case "LOOKUP_TARGET_MALFORMED":
15156
+ return `Lookup '${info.name}' target '${info.target}' must be 'Producer.provideName' (a string, or the 'for' of { for, default })`;
15082
15157
  case "UNKNOWN_MACRO_ARG":
15083
15158
  return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
15084
15159
  case "UNKNOWN_DIRECTIVE":
@@ -15194,7 +15269,6 @@ function htmlActionPhrase(action, tag, parent) {
15194
15269
  var UNSUPPORTED_EXPR_LABEL;
15195
15270
  var init_lint2 = __esm(() => {
15196
15271
  UNSUPPORTED_EXPR_LABEL = {
15197
- "legacy-template": "string template",
15198
15272
  ternary: "ternary expression",
15199
15273
  comparison: "comparison",
15200
15274
  logical: "logical expression",