tutuca 0.11.0 → 0.11.2

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 (116) hide show
  1. package/dist/tutuca-cli.js +264 -361
  2. package/dist/tutuca-components.js +175 -175
  3. package/dist/tutuca-dev.ext.js +250 -323
  4. package/dist/tutuca-dev.js +250 -323
  5. package/dist/tutuca-dev.min.js +4 -4
  6. package/dist/tutuca-extra.ext.js +55 -46
  7. package/dist/tutuca-extra.js +55 -46
  8. package/dist/tutuca-extra.min.js +3 -3
  9. package/dist/tutuca-storybook.js +29 -29
  10. package/dist/tutuca.ext.js +55 -46
  11. package/dist/tutuca.js +55 -46
  12. package/dist/tutuca.min.js +3 -3
  13. package/package.json +4 -3
  14. package/skill/margaui/SKILL.md +0 -105
  15. package/skill/margaui/components/accordion.md +0 -127
  16. package/skill/margaui/components/alert.md +0 -174
  17. package/skill/margaui/components/aura.md +0 -97
  18. package/skill/margaui/components/avatar.md +0 -220
  19. package/skill/margaui/components/badge.md +0 -193
  20. package/skill/margaui/components/breadcrumbs.md +0 -103
  21. package/skill/margaui/components/button.md +0 -322
  22. package/skill/margaui/components/calendar.md +0 -67
  23. package/skill/margaui/components/card.md +0 -373
  24. package/skill/margaui/components/carousel.md +0 -387
  25. package/skill/margaui/components/chat.md +0 -171
  26. package/skill/margaui/components/checkbox.md +0 -101
  27. package/skill/margaui/components/collapse.md +0 -172
  28. package/skill/margaui/components/countdown.md +0 -165
  29. package/skill/margaui/components/diff.md +0 -53
  30. package/skill/margaui/components/divider.md +0 -107
  31. package/skill/margaui/components/dock.md +0 -173
  32. package/skill/margaui/components/drawer.md +0 -184
  33. package/skill/margaui/components/dropdown.md +0 -388
  34. package/skill/margaui/components/fab.md +0 -346
  35. package/skill/margaui/components/fieldset.md +0 -88
  36. package/skill/margaui/components/file-input.md +0 -84
  37. package/skill/margaui/components/filter.md +0 -52
  38. package/skill/margaui/components/footer.md +0 -583
  39. package/skill/margaui/components/hero.md +0 -135
  40. package/skill/margaui/components/hover-3d.md +0 -129
  41. package/skill/margaui/components/hover-gallery.md +0 -49
  42. package/skill/margaui/components/indicator.md +0 -265
  43. package/skill/margaui/components/input.md +0 -389
  44. package/skill/margaui/components/join.md +0 -100
  45. package/skill/margaui/components/kbd.md +0 -127
  46. package/skill/margaui/components/label.md +0 -102
  47. package/skill/margaui/components/link.md +0 -96
  48. package/skill/margaui/components/list.md +0 -182
  49. package/skill/margaui/components/loading.md +0 -105
  50. package/skill/margaui/components/mask.md +0 -168
  51. package/skill/margaui/components/megamenu.md +0 -131
  52. package/skill/margaui/components/menu.md +0 -887
  53. package/skill/margaui/components/mockup-browser.md +0 -39
  54. package/skill/margaui/components/mockup-code.md +0 -81
  55. package/skill/margaui/components/mockup-phone.md +0 -39
  56. package/skill/margaui/components/mockup-window.md +0 -33
  57. package/skill/margaui/components/modal.md +0 -196
  58. package/skill/margaui/components/navbar.md +0 -282
  59. package/skill/margaui/components/otp.md +0 -171
  60. package/skill/margaui/components/pagination.md +0 -122
  61. package/skill/margaui/components/progress.md +0 -135
  62. package/skill/margaui/components/radial-progress.md +0 -67
  63. package/skill/margaui/components/radio.md +0 -133
  64. package/skill/margaui/components/range.md +0 -134
  65. package/skill/margaui/components/rating.md +0 -170
  66. package/skill/margaui/components/select.md +0 -225
  67. package/skill/margaui/components/skeleton.md +0 -64
  68. package/skill/margaui/components/stack.md +0 -142
  69. package/skill/margaui/components/stat.md +0 -254
  70. package/skill/margaui/components/status.md +0 -73
  71. package/skill/margaui/components/steps.md +0 -138
  72. package/skill/margaui/components/swap.md +0 -152
  73. package/skill/margaui/components/tab.md +0 -248
  74. package/skill/margaui/components/table.md +0 -1018
  75. package/skill/margaui/components/text-rotate.md +0 -91
  76. package/skill/margaui/components/textarea.md +0 -85
  77. package/skill/margaui/components/theme-controller.md +0 -266
  78. package/skill/margaui/components/timeline.md +0 -1356
  79. package/skill/margaui/components/toast.md +0 -165
  80. package/skill/margaui/components/toggle.md +0 -135
  81. package/skill/margaui/components/tooltip.md +0 -181
  82. package/skill/margaui/components/validator.md +0 -163
  83. package/skill/tutuca/SKILL.md +0 -56
  84. package/skill/tutuca/advanced.md +0 -212
  85. package/skill/tutuca/cli.md +0 -239
  86. package/skill/tutuca/component-design.md +0 -168
  87. package/skill/tutuca/core.md +0 -908
  88. package/skill/tutuca/iteration.md +0 -207
  89. package/skill/tutuca/macros.md +0 -86
  90. package/skill/tutuca/margaui.md +0 -175
  91. package/skill/tutuca/messages-and-intents.md +0 -399
  92. package/skill/tutuca/patterns/README.md +0 -48
  93. package/skill/tutuca/patterns/add-a-story.md +0 -26
  94. package/skill/tutuca/patterns/bind-text-and-attributes.md +0 -30
  95. package/skill/tutuca/patterns/conditional-attribute-value.md +0 -29
  96. package/skill/tutuca/patterns/coordinate-components.md +0 -54
  97. package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +0 -27
  98. package/skill/tutuca/patterns/enrich-each-item.md +0 -25
  99. package/skill/tutuca/patterns/file-input.md +0 -39
  100. package/skill/tutuca/patterns/filter-a-list.md +0 -25
  101. package/skill/tutuca/patterns/filter-and-paginate.md +0 -60
  102. package/skill/tutuca/patterns/handle-events.md +0 -38
  103. package/skill/tutuca/patterns/iterate-a-list.md +0 -18
  104. package/skill/tutuca/patterns/paginate-a-list.md +0 -29
  105. package/skill/tutuca/patterns/render-a-child-component.md +0 -21
  106. package/skill/tutuca/patterns/reuse-markup-with-macros.md +0 -36
  107. package/skill/tutuca/patterns/share-state-across-the-tree.md +0 -38
  108. package/skill/tutuca/patterns/show-or-hide-content.md +0 -23
  109. package/skill/tutuca/patterns/switch-between-views.md +0 -30
  110. package/skill/tutuca/patterns/tabbed-interface.md +0 -43
  111. package/skill/tutuca/semantics.md +0 -195
  112. package/skill/tutuca/storybook.md +0 -270
  113. package/skill/tutuca/styles.md +0 -48
  114. package/skill/tutuca/testing.md +0 -346
  115. package/skill/tutuca-source/SKILL.md +0 -33
  116. package/skill/tutuca-source/tutuca.ext.js +0 -4235
@@ -2953,13 +2953,12 @@ function processXExtras(node, attrs, opName, startIdx, px) {
2953
2953
  const a = attrs[i];
2954
2954
  const aName = a.name;
2955
2955
  if (consumed.has(aName)) continue;
2956
- const atPrefixed = aName.charCodeAt(0) === 64;
2957
- const baseName = atPrefixed ? aName.slice(1) : aName;
2958
- const wrapper = wrappable ? X_OPS[baseName]?.wrapper : null;
2959
- if (wrapper) {
2960
- if (!atPrefixed) maybeDeprecateBareXDirective(px, opName, baseName);
2961
- wrappers.push([wrapper, parseBool(a.value, px)]);
2962
- continue;
2956
+ if (wrappable && aName.charCodeAt(0) === 64) {
2957
+ const wrapper = X_OPS[aName.slice(1)]?.wrapper;
2958
+ if (wrapper) {
2959
+ wrappers.push([wrapper, parseBool(a.value, px)]);
2960
+ continue;
2961
+ }
2963
2962
  }
2964
2963
  const issueInfo = { op: opName, name: aName, value: a.value };
2965
2964
  px.onParseIssue("unknown-x-attr", issueInfo);
@@ -2971,9 +2970,6 @@ function processXExtras(node, attrs, opName, startIdx, px) {
2971
2970
  }
2972
2971
  return node;
2973
2972
  }
2974
- function maybeDeprecateBareXDirective(px, opName, name) {
2975
- px.onDeprecatedSyntax("bare-x-directive", { op: opName, name });
2976
- }
2977
2973
  function wrap(node, px, wrappers) {
2978
2974
  if (wrappers) {
2979
2975
  for (let i = wrappers.length - 1; i >= 0; i--) {
@@ -3008,17 +3004,10 @@ function parseRenderEach(px, value, as, attrs) {
3008
3004
  const attrParser = getAttrParser(px);
3009
3005
  const eachAttr = attrParser.pushWrapper("each", value, seqVal);
3010
3006
  attrParser.eachAttr = eachAttr;
3011
- const when = attrs.getNamedItem("@when") ?? attrs.getNamedItem("when");
3012
- if (when) {
3013
- if (when.name.charCodeAt(0) !== 64) maybeDeprecateBareXDirective(px, "render-each", "when");
3014
- attrParser._parseWhen(when.value);
3015
- }
3016
- const lWith = attrs.getNamedItem("@loop-with") ?? attrs.getNamedItem("loop-with");
3017
- if (lWith) {
3018
- if (lWith.name.charCodeAt(0) !== 64)
3019
- maybeDeprecateBareXDirective(px, "render-each", "loop-with");
3020
- attrParser._parseLoopWith(lWith.value);
3021
- }
3007
+ const when = attrs.getNamedItem("@when");
3008
+ if (when) attrParser._parseWhen(when.value);
3009
+ const lWith = attrs.getNamedItem("@loop-with");
3010
+ if (lWith) attrParser._parseLoopWith(lWith.value);
3022
3011
  const each2 = px.addNodeIf(EachNode, seqVal);
3023
3012
  each2.iterInfo.whenVal = eachAttr.whenVal ?? null;
3024
3013
  each2.iterInfo.loopWithVal = eachAttr.loopWithVal ?? null;
@@ -3437,10 +3426,8 @@ var init_anode = __esm({
3437
3426
  render: xOp(["as"], { wrappable: true, ignoresChildren: true }),
3438
3427
  "render-it": xOp(["as"], { wrappable: true, ignoresChildren: true }),
3439
3428
  // `@when`/`@loop-with` are consumed here (handled in parseRenderEach) so
3440
- // `processXExtras` does not flag them as unknown attrs. TEMPORARY: the bare
3441
- // `when`/`loop-with` spellings are deprecated in favor of the `@` form — see
3442
- // maybeDeprecateBareXDirective (added 2026-07-08).
3443
- "render-each": xOp(["as", "when", "loop-with", "@when", "@loop-with"], {
3429
+ // `processXExtras` does not flag them as unknown attrs.
3430
+ "render-each": xOp(["as", "@when", "@loop-with"], {
3444
3431
  wrappable: true,
3445
3432
  ignoresChildren: true
3446
3433
  }),
@@ -3531,10 +3518,6 @@ var init_anode = __esm({
3531
3518
  onParseIssue(kind, info) {
3532
3519
  console.warn(`tutuca parse issue [${kind}]`, info);
3533
3520
  }
3534
- // Lint-only channel for deprecation nudges on still-valid syntax; the base
3535
- // (runtime) context ignores them so live apps stay quiet. See LintParseContext.
3536
- onDeprecatedSyntax(_kind, _info) {
3537
- }
3538
3521
  };
3539
3522
  _htmlBlockTags = "ADDRESS,ARTICLE,ASIDE,BLOCKQUOTE,CAPTION,COL,COLGROUP,DETAILS,DIALOG,DIV,DD,DL,DT,FIELDSET,FIGCAPTION,FIGURE,FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEADER,HGROUP,HR,LEGEND,LI,MAIN,MENU,NAV,OL,P,PRE,SECTION,SUMMARY,TABLE,TBODY,TD,TFOOT,TH,THEAD,TR,UL";
3540
3523
  HTML_BLOCK_TAGS = new Set(_htmlBlockTags.split(","));
@@ -3633,6 +3616,199 @@ var init_anode = __esm({
3633
3616
  }
3634
3617
  });
3635
3618
 
3619
+ // src/components.js
3620
+ var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
3621
+ var init_components = __esm({
3622
+ "src/components.js"() {
3623
+ init_anode();
3624
+ init_attribute();
3625
+ init_value();
3626
+ COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
3627
+ Components = class {
3628
+ constructor() {
3629
+ this.byId = /* @__PURE__ */ new Map();
3630
+ }
3631
+ registerComponent(Comp) {
3632
+ this.byId.set(Comp[COMPONENT].id, Comp);
3633
+ }
3634
+ getComponentForId(id) {
3635
+ return this.byId.get(id) ?? null;
3636
+ }
3637
+ getCompFor(v) {
3638
+ const Comp = v?.constructor;
3639
+ return Comp?.[COMPONENT] ? Comp : null;
3640
+ }
3641
+ getHandlerFor(v, name, key) {
3642
+ return this.getCompFor(v)?.[key][name] ?? null;
3643
+ }
3644
+ // The `lex` leg of an intent's route: the handlers registered on the scope chain of
3645
+ // the component that raised it, innermost first. A list, not a first match — see
3646
+ // ComponentStack.lookupIntentChain.
3647
+ getIntentChainFor(v, name) {
3648
+ return this.getCompFor(v)?.scope.lookupIntentChain(name) ?? [];
3649
+ }
3650
+ compileStyles() {
3651
+ const styles2 = [];
3652
+ for (const comp of this.byId.values()) styles2.push(comp.compileStyle());
3653
+ return styles2.join("\n");
3654
+ }
3655
+ };
3656
+ ComponentStack = class _ComponentStack {
3657
+ constructor(comps = new Components(), parent = null) {
3658
+ this.comps = comps;
3659
+ this.parent = parent;
3660
+ this.byName = {};
3661
+ this.intentsByName = {};
3662
+ this.macros = {};
3663
+ }
3664
+ enter() {
3665
+ return new _ComponentStack(this.comps, this);
3666
+ }
3667
+ registerComponents(comps, opts) {
3668
+ const { aliases: aliases2 = {} } = opts ?? {};
3669
+ for (let i = 0; i < comps.length; i++) {
3670
+ const Comp = comps[i];
3671
+ Comp[COMPONENT].scope = this.enter();
3672
+ this.comps.registerComponent(Comp);
3673
+ this.byName[Comp.name] = Comp;
3674
+ }
3675
+ for (const alias in aliases2) {
3676
+ const comp = this.byName[aliases2[alias]];
3677
+ console.assert(this.byName[alias] === void 0, "alias overrides component", alias);
3678
+ if (comp !== void 0) this.byName[alias] = comp;
3679
+ else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
3680
+ }
3681
+ }
3682
+ registerMacros(macros) {
3683
+ for (const key in macros) {
3684
+ const lower = key.toLowerCase();
3685
+ console.assert(this.macros[lower] === void 0, "macro key collision", lower);
3686
+ this.macros[lower] = macros[key];
3687
+ }
3688
+ }
3689
+ getCompFor(v) {
3690
+ return this.comps.getCompFor(v);
3691
+ }
3692
+ // Handlers that answer an intent's `lex` leg. A name maps to a LIST, because the leg
3693
+ // walks: a handler that returns PASS declines and hands the intent to the next one.
3694
+ // A bare function is accepted as a one-element list.
3695
+ registerIntentHandlers(handlers) {
3696
+ for (const name in handlers) {
3697
+ const fns = Array.isArray(handlers[name]) ? handlers[name] : [handlers[name]];
3698
+ this.intentsByName[name] = fns.map((fn) => new IntentHandler(name, fn));
3699
+ }
3700
+ }
3701
+ // Innermost scope first, then outward. Concatenated rather than first-match, so a
3702
+ // declining handler can hand the intent to one further up.
3703
+ lookupIntentChain(name) {
3704
+ const here = this.intentsByName[name] ?? [];
3705
+ const up = this.parent?.lookupIntentChain(name) ?? [];
3706
+ return up.length === 0 ? here : here.concat(up);
3707
+ }
3708
+ lookupComponent(name) {
3709
+ return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
3710
+ }
3711
+ lookupMacro(name) {
3712
+ return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
3713
+ }
3714
+ };
3715
+ ProvideInfo = class {
3716
+ constructor(name, val, symbol) {
3717
+ this.name = name;
3718
+ this.val = val;
3719
+ this.symbol = symbol;
3720
+ }
3721
+ };
3722
+ LookupInfo = class {
3723
+ constructor(name, compName, provideName, val) {
3724
+ this.name = name;
3725
+ this.compName = compName;
3726
+ this.provideName = provideName;
3727
+ this.val = val;
3728
+ this._sym = void 0;
3729
+ }
3730
+ getProducerSymbol(stack) {
3731
+ if (this._sym === void 0)
3732
+ this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
3733
+ return this._sym;
3734
+ }
3735
+ };
3736
+ isString = (v) => typeof v === "string";
3737
+ _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
3738
+ KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
3739
+ _compId = 0;
3740
+ Component = class {
3741
+ constructor(Class, o) {
3742
+ this.id = _compId++;
3743
+ this.name = o.name ?? "UnkComp";
3744
+ this.Class = Class;
3745
+ this.views = { main: new View("main", o.view, o.style) };
3746
+ this.commonStyle = o.commonStyle ?? "";
3747
+ this.globalStyle = o.globalStyle ?? "";
3748
+ this.receive = o.receive ?? {};
3749
+ this.intent = o.intent ?? {};
3750
+ this.alter = o.alter ?? {};
3751
+ for (const name in o.views ?? {}) {
3752
+ const v = o.views[name];
3753
+ const { view, style } = isString(v) ? { view: v } : v;
3754
+ this.views[name] = new View(name, view, style);
3755
+ }
3756
+ this._rawProvide = o.provide ?? {};
3757
+ this._rawLookup = o.lookup ?? {};
3758
+ this.provide = {};
3759
+ this.lookup = {};
3760
+ this.scope = null;
3761
+ this.spec = o;
3762
+ this.extra = {};
3763
+ for (const key of Object.keys(o)) if (!KNOWN_SPEC_KEYS.has(key)) this.extra[key] = o[key];
3764
+ }
3765
+ compile(ParseContext2) {
3766
+ for (const name in this.views)
3767
+ this.views[name].compile(new ParseContext2(), this.scope, this.id);
3768
+ const ctx = this.views.main.ctx;
3769
+ for (const key in this._rawProvide) {
3770
+ const val = parseProvide(this._rawProvide[key], ctx);
3771
+ if (val) this.provide[key] = new ProvideInfo(key, val, Symbol(key));
3772
+ }
3773
+ for (const key in this._rawLookup) {
3774
+ const linfo = this._rawLookup[key];
3775
+ const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
3776
+ const [compName, provideName] = forStr === null ? [] : forStr.split(".");
3777
+ if (!isString(compName) || !isString(provideName)) continue;
3778
+ const defStr = isString(linfo?.default) ? linfo.default : null;
3779
+ const val = defStr === null ? null : parseField(defStr, ctx);
3780
+ this.lookup[key] = new LookupInfo(key, compName, provideName, val);
3781
+ }
3782
+ for (const key in this.lookup)
3783
+ if (this.provide[key] !== void 0)
3784
+ console.warn("name declared in both provide and lookup", this.name, key);
3785
+ }
3786
+ make(args, opts) {
3787
+ return this.Class.make(args, opts ?? { scope: this.scope });
3788
+ }
3789
+ getView(name) {
3790
+ return this.views[name] ?? this.views.main;
3791
+ }
3792
+ getEventForId(id, name = "main") {
3793
+ return this.getView(name).ctx.getEventForId(id);
3794
+ }
3795
+ getNodeForId(id, name = "main") {
3796
+ return this.getView(name).ctx.getNodeForId(id);
3797
+ }
3798
+ compileStyle() {
3799
+ const { id, commonStyle, globalStyle, views } = this;
3800
+ const styles2 = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
3801
+ if (globalStyle !== "") styles2.push(globalStyle);
3802
+ for (const name in views) {
3803
+ const { style } = views[name];
3804
+ if (style !== "") styles2.push(`[data-cid="${id}"][data-vid="${name}"]{${style}}`);
3805
+ }
3806
+ return styles2.join("\n");
3807
+ }
3808
+ };
3809
+ }
3810
+ });
3811
+
3636
3812
  // tools/core/html-tokenizer.js
3637
3813
  function isWhitespace(c) {
3638
3814
  return c === CharCodes.Space || c === CharCodes.NewLine || c === CharCodes.Tab || c === CharCodes.FormFeed || c === CharCodes.CarriageReturn;
@@ -5970,8 +6146,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
5970
6146
  checkProvidesAreAddressable(lx, Comp);
5971
6147
  checkLookupShapes(lx, Comp);
5972
6148
  checkHandlersNotAsync(lx, Comp);
5973
- checkRetiredBuckets(lx, Comp);
5974
- checkRetiredCtxVerbs(lx, Comp);
5975
6149
  checkHandlerNameCollisions(lx, Comp);
5976
6150
  checkScopedStyleTopLevel(lx, Comp);
5977
6151
  const referencedAlters = /* @__PURE__ */ new Set();
@@ -6011,14 +6185,6 @@ function checkParseIssues(lx, view) {
6011
6185
  const issues = view.ctx.parseIssues;
6012
6186
  if (!issues) return;
6013
6187
  for (const { kind, info } of issues) {
6014
- if (kind === "deprecated:bare-x-directive") {
6015
- lx.warn(DEPRECATED_BARE_X_DIRECTIVE, info, {
6016
- kind: "add-prefix",
6017
- from: info.name,
6018
- to: `@${info.name}`
6019
- });
6020
- continue;
6021
- }
6022
6188
  if (kind === "x-op-ignores-children") {
6023
6189
  lx.warn(X_OP_IGNORES_CHILDREN, info, { kind: "remove", what: "the ignored children" });
6024
6190
  continue;
@@ -6129,7 +6295,7 @@ function checkEnrichProjection(lx, view, Comp) {
6129
6295
  if (node.constructor.name !== "EachNode") continue;
6130
6296
  const enrich = node.iterInfo?.enrichWithVal;
6131
6297
  if (!enrich?.name) continue;
6132
- const fn = enrich.constructor.name === "MethodVal" ? protoMethodValue(Comp.Class?.prototype, enrich.name) : Comp.alter?.[enrich.name];
6298
+ const fn = enrich.constructor.name === "MethodVal" ? protoMethodValue(Comp.prototype ?? Object.getPrototypeOf(Comp), enrich.name) : Comp.alter?.[enrich.name];
6133
6299
  if (typeof fn !== "function") continue;
6134
6300
  const members = pureProjectionBinds(fn);
6135
6301
  if (members === null) continue;
@@ -6225,15 +6391,14 @@ function checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedDyna
6225
6391
  }
6226
6392
  }
6227
6393
  function mkAttrValEnv(Comp, referencedAlters, referencedDynamics) {
6228
- const { scope, alter, provide, lookup: lookup2, Class } = Comp;
6229
- const { prototype: proto } = Class;
6230
- const { fields } = Class.getMetaClass();
6394
+ const { scope, alter, provide, lookup: lookup2, fields } = Comp;
6395
+ const proto = Comp.prototype ?? Object.getPrototypeOf(Comp);
6231
6396
  const dynamicMap = { ...provide, ...lookup2 };
6232
6397
  return { fields, proto, scope, alter, referencedAlters, dynamicMap, referencedDynamics };
6233
6398
  }
6234
6399
  function checkEventHandlersHaveImpls(lx, Comp, referencedInputs) {
6235
- const { receive: input, views, Class } = Comp;
6236
- const { prototype: proto } = Class;
6400
+ const { receive: input, views } = Comp;
6401
+ const proto = Comp.prototype ?? Object.getPrototypeOf(Comp);
6237
6402
  for (const viewName in views) {
6238
6403
  lx.push({ viewName }, () => {
6239
6404
  const view = views[viewName];
@@ -6400,31 +6565,6 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
6400
6565
  });
6401
6566
  }
6402
6567
  }
6403
- function checkRetiredBuckets(lx, Comp) {
6404
- const extra = Comp.extra;
6405
- if (!extra) return;
6406
- for (const key of Object.keys(extra)) {
6407
- if (!Object.hasOwn(RETIRED_BUCKETS, key)) continue;
6408
- const retired = RETIRED_BUCKETS[key];
6409
- const names = isPlainObj(extra[key]) ? Object.keys(extra[key]) : [];
6410
- lx.error(RETIRED_HANDLER_BUCKET, { key, to: retired.to, how: retired.how, names });
6411
- }
6412
- }
6413
- function checkRetiredCtxVerbs(lx, Comp) {
6414
- for (const bucket of ["receive", "intent", "alter", "methods", "statics"]) {
6415
- const block = bucket === "methods" || bucket === "statics" ? Comp.spec?.[bucket] : Comp[bucket];
6416
- if (!isPlainObj(block)) continue;
6417
- for (const name in block) {
6418
- const fn = block[name];
6419
- if (typeof fn !== "function") continue;
6420
- const src = String(fn);
6421
- for (const m of src.matchAll(RETIRED_CTX_RE)) {
6422
- const verb = m[1];
6423
- lx.error(RETIRED_CTX_VERB, { verb, to: RETIRED_CTX_VERBS[verb], bucket, name });
6424
- }
6425
- }
6426
- }
6427
- }
6428
6568
  function checkHandlerNameCollisions(lx, Comp) {
6429
6569
  const receive = Comp.receive ?? {};
6430
6570
  const intent = Comp.intent ?? {};
@@ -6450,7 +6590,6 @@ function checkUnknownSpecKeys(lx, Comp, wellKnownExtras) {
6450
6590
  let candidates = null;
6451
6591
  for (const key of Object.keys(extra)) {
6452
6592
  if (FRAMEWORK_WELL_KNOWN_EXTRAS.has(key) || wellKnownExtras.has(key)) continue;
6453
- if (Object.hasOwn(RETIRED_BUCKETS, key)) continue;
6454
6593
  candidates ??= [
6455
6594
  ...KNOWN_COMPONENT_SPEC_KEYS,
6456
6595
  ...FRAMEWORK_WELL_KNOWN_EXTRAS,
@@ -6460,7 +6599,7 @@ function checkUnknownSpecKeys(lx, Comp, wellKnownExtras) {
6460
6599
  }
6461
6600
  }
6462
6601
  function checkFieldDeclarations(lx, Comp) {
6463
- const fields = Comp.Class?.getMetaClass?.().fields;
6602
+ const fields = Comp[COMPONENT]?.fields;
6464
6603
  if (!fields) return;
6465
6604
  for (const fieldName in fields) {
6466
6605
  const field = fields[fieldName];
@@ -6483,7 +6622,7 @@ function checkFieldDeclarations(lx, Comp) {
6483
6622
  }
6484
6623
  }
6485
6624
  function checkFieldMethodNameCollisions(lx, Comp) {
6486
- const meta = Comp.Class?.getMetaClass?.();
6625
+ const meta = Comp[COMPONENT];
6487
6626
  if (!meta) return;
6488
6627
  for (const name in meta.fields)
6489
6628
  if (Object.hasOwn(meta.methods, name)) lx.error(FIELD_METHOD_NAME_COLLISION, { name });
@@ -6613,14 +6752,15 @@ function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
6613
6752
  }
6614
6753
  }
6615
6754
  }
6616
- var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, LOOKUP_BAD_SHAPE, LOOKUP_TARGET_MALFORMED, RENDER_IT_OUTSIDE_OF_LOOP, UNKNOWN_EVENT_MODIFIER, UNKNOWN_HANDLER_ARG_NAME, RECEIVE_HANDLER_NOT_IMPLEMENTED, EVENT_HANDLER_METHOD_NOT_ALLOWED, RETIRED_HANDLER_BUCKET, RETIRED_CTX_VERB, HANDLER_NAME_COLLISION, FIELD_VAL_NOT_DEFINED, FIELD_VAL_IS_METHOD, METHOD_VAL_NOT_DEFINED, METHOD_VAL_IS_FIELD, DUPLICATE_ATTR_DEFINITION, IF_NO_BRANCH_SET, UNKNOWN_COMPONENT_NAME, UNKNOWN_MACRO_ARG, UNKNOWN_DIRECTIVE, UNKNOWN_X_OP, UNKNOWN_X_ATTR, X_OP_IGNORES_CHILDREN, MAYBE_DROP_AT_PREFIX, MAYBE_ADD_AT_PREFIX, DEPRECATED_BARE_X_DIRECTIVE, BAD_VALUE, UNSUPPORTED_EXPR_SYNTAX, BINDING_MEMBER_TOO_DEEP, SUGGEST_BINDING_MEMBER, REDUNDANT_TEMPLATE_STRING, PLACEHOLDERLESS_TEMPLATE_STRING, CONSTANT_CONDITION, UNKNOWN_COMPONENT_SPEC_KEY, COMP_FIELD_BAD_SHAPE, ASYNC_HANDLER, TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE, GLOBAL_SELECTOR_IN_SCOPED_STYLE, FIELD_METHOD_NAME_COLLISION, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2, LEVEL_ERROR2, LEVEL_HINT, PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS2, ANY_EVENT_MODIFIERS, KNOWN_HANDLER_NAMES, fixTo, BOOL_CONDITION_ORIGINS, isBoolConditionCtx, ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, isPlainObj, RETIRED_BUCKETS, RETIRED_CTX_VERBS, RETIRED_CTX_RE, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun, STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintContext, LintParseContext;
6755
+ var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, LOOKUP_BAD_SHAPE, LOOKUP_TARGET_MALFORMED, RENDER_IT_OUTSIDE_OF_LOOP, UNKNOWN_EVENT_MODIFIER, UNKNOWN_HANDLER_ARG_NAME, RECEIVE_HANDLER_NOT_IMPLEMENTED, EVENT_HANDLER_METHOD_NOT_ALLOWED, HANDLER_NAME_COLLISION, FIELD_VAL_NOT_DEFINED, FIELD_VAL_IS_METHOD, METHOD_VAL_NOT_DEFINED, METHOD_VAL_IS_FIELD, DUPLICATE_ATTR_DEFINITION, IF_NO_BRANCH_SET, UNKNOWN_COMPONENT_NAME, UNKNOWN_MACRO_ARG, UNKNOWN_DIRECTIVE, UNKNOWN_X_OP, UNKNOWN_X_ATTR, X_OP_IGNORES_CHILDREN, MAYBE_DROP_AT_PREFIX, MAYBE_ADD_AT_PREFIX, BAD_VALUE, UNSUPPORTED_EXPR_SYNTAX, BINDING_MEMBER_TOO_DEEP, SUGGEST_BINDING_MEMBER, REDUNDANT_TEMPLATE_STRING, PLACEHOLDERLESS_TEMPLATE_STRING, CONSTANT_CONDITION, UNKNOWN_COMPONENT_SPEC_KEY, COMP_FIELD_BAD_SHAPE, ASYNC_HANDLER, TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE, GLOBAL_SELECTOR_IN_SCOPED_STYLE, FIELD_METHOD_NAME_COLLISION, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2, LEVEL_ERROR2, LEVEL_HINT, PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS2, ANY_EVENT_MODIFIERS, KNOWN_HANDLER_NAMES, fixTo, BOOL_CONDITION_ORIGINS, isBoolConditionCtx, ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun, STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintContext, LintParseContext;
6617
6756
  var init_lint_check = __esm({
6618
6757
  "tools/core/lint-check.js"() {
6619
6758
  init_anode();
6759
+ init_components();
6620
6760
  init_htmllinter();
6621
6761
  init_closest_name();
6622
6762
  KNOWN_COMPONENT_SPEC_KEYS = new Set(
6623
- "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics".split(
6763
+ "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics".split(
6624
6764
  " "
6625
6765
  )
6626
6766
  );
@@ -6652,8 +6792,6 @@ var init_lint_check = __esm({
6652
6792
  UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME";
6653
6793
  RECEIVE_HANDLER_NOT_IMPLEMENTED = "RECEIVE_HANDLER_NOT_IMPLEMENTED";
6654
6794
  EVENT_HANDLER_METHOD_NOT_ALLOWED = "EVENT_HANDLER_METHOD_NOT_ALLOWED";
6655
- RETIRED_HANDLER_BUCKET = "RETIRED_HANDLER_BUCKET";
6656
- RETIRED_CTX_VERB = "RETIRED_CTX_VERB";
6657
6795
  HANDLER_NAME_COLLISION = "HANDLER_NAME_COLLISION";
6658
6796
  FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED";
6659
6797
  FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD";
@@ -6669,7 +6807,6 @@ var init_lint_check = __esm({
6669
6807
  X_OP_IGNORES_CHILDREN = "X_OP_IGNORES_CHILDREN";
6670
6808
  MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX";
6671
6809
  MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX";
6672
- DEPRECATED_BARE_X_DIRECTIVE = "DEPRECATED_BARE_X_DIRECTIVE";
6673
6810
  BAD_VALUE = "BAD_VALUE";
6674
6811
  UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX";
6675
6812
  BINDING_MEMBER_TOO_DEEP = "BINDING_MEMBER_TOO_DEEP";
@@ -6847,32 +6984,6 @@ var init_lint_check = __esm({
6847
6984
  HideNode: { originAttr: "<x hide>" },
6848
6985
  PushViewNameNode: { originAttr: "<x push-view>" }
6849
6986
  };
6850
- isPlainObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
6851
- RETIRED_BUCKETS = {
6852
- input: {
6853
- to: "receive",
6854
- how: "rename the bucket to `receive` - a view's own @on.* name and a parent's ctx.send are the same message now, and nothing can tell them apart"
6855
- },
6856
- bubble: {
6857
- to: "intent",
6858
- how: "rename the bucket to `intent` - and note the walk changed: a handler that calls ctx.reply() ENDS it, where ctx.stopPropagation() used to be the only way to stop"
6859
- },
6860
- response: {
6861
- to: "receive",
6862
- how: "split each arm into `receive` arms named after the intent: <name>Ok takes the result alone, <name>Error takes the error alone, and the optional <name>Unhandled means nothing claimed it"
6863
- }
6864
- };
6865
- RETIRED_CTX_VERBS = {
6866
- bubble: 'ctx.intent(name, args, { route: ["dyn"] }) - the route says it walks the ancestors, where the verb used to',
6867
- request: 'ctx.intent(name, args, { route: ["lex"] }) - and the outcome comes back as a `receive` arm named <name>Ok / <name>Error / <name>Unhandled, so onOkName and onErrorName are gone',
6868
- stopPropagation: "ctx.stop()",
6869
- inputAtPath: "ctx.sendAtPath(path, name, args)",
6870
- requestAtPath: 'ctx.intentAtPath(path, name, args, { route: ["lex"] })'
6871
- };
6872
- RETIRED_CTX_RE = new RegExp(
6873
- `\\bctx\\.(${Object.keys(RETIRED_CTX_VERBS).join("|")})\\s*\\(`,
6874
- "g"
6875
- );
6876
6987
  HANDLER_CHANNELS = ["receive", "intent", "alter"];
6877
6988
  ASYNC_HANDLER_HELP = `Move the async work into a scope-registered intent handler and trigger it with ctx.intent("name", args, { route: ["lex"] }), then read the outcome in the synchronous \`receive\` arms named after it: <name>Ok, <name>Error and <name>Unhandled. To coordinate other components, keep the handler synchronous and use ctx.send to address one, or ctx.intent to let a route find one.`;
6878
6989
  NON_NESTABLE_AT_RULE = /(?:^|[\s;{}])@(?:-[a-z]+-)?(charset|import|namespace|font-face|keyframes|page|property|counter-style|font-feature-values|font-palette-values|view-transition)\b/gi;
@@ -6921,16 +7032,6 @@ var init_lint_check = __esm({
6921
7032
  const tag = this.currentTag;
6922
7033
  this.parseIssues.push({ kind, info: tag && info.tag === void 0 ? { ...info, tag } : info });
6923
7034
  }
6924
- // TEMPORARY (2026-07-08): record deprecation nudges on the same channel as
6925
- // parse issues so checkParseIssues can surface them as warnings. Remove with
6926
- // the bare `show`/`hide`/`when` spelling.
6927
- onDeprecatedSyntax(kind, info) {
6928
- const tag = this.currentTag;
6929
- this.parseIssues.push({
6930
- kind: `deprecated:${kind}`,
6931
- info: tag && info.tag === void 0 ? { ...info, tag } : info
6932
- });
6933
- }
6934
7035
  };
6935
7036
  }
6936
7037
  });
@@ -7110,15 +7211,6 @@ var init_lint_rules = __esm({
7110
7211
  group: "Templates / events",
7111
7212
  summary: "A directive name (`when`/`enrich-with`/`loop-with`/`show`/`hide`) was written as a plain attribute on a host element — add the `@` prefix."
7112
7213
  },
7113
- // TEMPORARY (added 2026-07-08): remove together with the bare
7114
- // `show`/`hide`/`when`/`loop-with` spelling on `<x>` ops.
7115
- {
7116
- code: DEPRECATED_BARE_X_DIRECTIVE,
7117
- level: "warn",
7118
- group: "Templates / events",
7119
- summary: "Bare `show`/`hide`/`when`/`loop-with` on an `<x>` op is deprecated — use the `@`-prefixed directive (`@show`/`@hide`/`@when`/`@loop-with`)."
7120
- },
7121
- // Value expressions
7122
7214
  {
7123
7215
  code: BAD_VALUE,
7124
7216
  level: "error",
@@ -7175,25 +7267,11 @@ var init_lint_rules = __esm({
7175
7267
  group: "Component spec",
7176
7268
  summary: "`component({...})` has an unrecognized key; its value is ignored at runtime."
7177
7269
  },
7178
- // Retired four-channel vocabulary (TEMPORARY remove a couple of releases after
7179
- // the two-channel change). These exist to drive the migration: the linter reports
7180
- // every site and says what replaces it, and a clean run IS the finished migration.
7181
- {
7182
- code: "RETIRED_HANDLER_BUCKET",
7183
- level: "error",
7184
- group: "Retired dispatch vocabulary",
7185
- summary: "`input`, `bubble` and `response` are no longer handler buckets — four dispatch channels became two, `receive` (addressed) and `intent` (routed)."
7186
- },
7187
- {
7188
- code: "RETIRED_CTX_VERB",
7189
- level: "error",
7190
- group: "Retired dispatch vocabulary",
7191
- summary: "`ctx.bubble`, `ctx.request` and `ctx.stopPropagation` are gone — one `ctx.intent` carries a route, and `ctx.stop()` ends a walk."
7192
- },
7270
+ // PERMANENT. Two hazards the merge created, both silent at runtime.
7193
7271
  {
7194
7272
  code: "HANDLER_NAME_COLLISION",
7195
7273
  level: "error",
7196
- group: "Retired dispatch vocabulary",
7274
+ group: "Handlers",
7197
7275
  summary: "Two handlers collapse onto one name, or a `receive` arm collides with an intent's derived answer name."
7198
7276
  },
7199
7277
  // Handler effects
@@ -7328,12 +7406,6 @@ function lintIdToMessage(id, info) {
7328
7406
  }
7329
7407
  case "UNKNOWN_HANDLER_ARG_NAME":
7330
7408
  return `Unknown handler argument '${info.name}'${fmtOriginSuffix(info)}`;
7331
- case "RETIRED_HANDLER_BUCKET": {
7332
- const which = info.names?.length ? ` (${info.names.join(", ")})` : "";
7333
- return `\`${info.key}\` is no longer a handler bucket${which} — ${info.how}`;
7334
- }
7335
- case "RETIRED_CTX_VERB":
7336
- return `ctx.${info.verb}() no longer exists — use ${info.to} (in \`${info.bucket}.${info.name}\`)`;
7337
7409
  case "HANDLER_NAME_COLLISION":
7338
7410
  return `${info.problem} — ${info.fix}`;
7339
7411
  case "RECEIVE_HANDLER_NOT_IMPLEMENTED":
@@ -7389,9 +7461,6 @@ function lintIdToMessage(id, info) {
7389
7461
  }
7390
7462
  case "MAYBE_ADD_AT_PREFIX":
7391
7463
  return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
7392
- // TEMPORARY (2026-07-08): remove with the bare `show`/`hide`/`when` spelling.
7393
- case "DEPRECATED_BARE_X_DIRECTIVE":
7394
- return `'${info.name}' on <x ${info.op}> is deprecated — write '@${info.name}' instead${fmtTagSuffix(info)}`;
7395
7464
  case "BAD_VALUE":
7396
7465
  return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
7397
7466
  case "UNSUPPORTED_EXPR_SYNTAX":
@@ -12354,7 +12423,7 @@ function isPlainObject3(v) {
12354
12423
  }
12355
12424
  function resolveComponentName(value, components) {
12356
12425
  for (const comp of components) {
12357
- if (value instanceof comp.Class) return comp.name;
12426
+ if (value instanceof comp) return comp.name;
12358
12427
  }
12359
12428
  return null;
12360
12429
  }
@@ -12733,8 +12802,7 @@ function serializeDefault(v) {
12733
12802
  return v;
12734
12803
  }
12735
12804
  function getComponentDoc(comp) {
12736
- const meta = comp.Class.getMetaClass();
12737
- const { fields, name, methods } = meta;
12805
+ const { fields, name, methods } = comp;
12738
12806
  const userMethods = Object.keys(methods).map((k) => ({
12739
12807
  name: k,
12740
12808
  sig: getSignature(k, methods[k])
@@ -12771,200 +12839,6 @@ var init_docs = __esm({
12771
12839
  }
12772
12840
  });
12773
12841
 
12774
- // src/components.js
12775
- var Components, ComponentStack, ProvideInfo, LookupInfo, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
12776
- var init_components = __esm({
12777
- "src/components.js"() {
12778
- init_anode();
12779
- init_attribute();
12780
- init_value();
12781
- Components = class {
12782
- constructor() {
12783
- this.getComponentSymbol = /* @__PURE__ */ Symbol("getComponent");
12784
- this.byId = /* @__PURE__ */ new Map();
12785
- }
12786
- registerComponent(comp) {
12787
- comp.Class.prototype[this.getComponentSymbol] = () => comp;
12788
- this.byId.set(comp.id, comp);
12789
- }
12790
- getComponentForId(id) {
12791
- return this.byId.get(id) ?? null;
12792
- }
12793
- getCompFor(v) {
12794
- return v?.[this.getComponentSymbol]?.() ?? null;
12795
- }
12796
- getHandlerFor(v, name, key) {
12797
- return this.getCompFor(v)?.[key][name] ?? null;
12798
- }
12799
- // The `lex` leg of an intent's route: the handlers registered on the scope chain of
12800
- // the component that raised it, innermost first. A list, not a first match — see
12801
- // ComponentStack.lookupIntentChain.
12802
- getIntentChainFor(v, name) {
12803
- return this.getCompFor(v)?.scope.lookupIntentChain(name) ?? [];
12804
- }
12805
- compileStyles() {
12806
- const styles2 = [];
12807
- for (const comp of this.byId.values()) styles2.push(comp.compileStyle());
12808
- return styles2.join("\n");
12809
- }
12810
- };
12811
- ComponentStack = class _ComponentStack {
12812
- constructor(comps = new Components(), parent = null) {
12813
- this.comps = comps;
12814
- this.parent = parent;
12815
- this.byName = {};
12816
- this.intentsByName = {};
12817
- this.macros = {};
12818
- }
12819
- enter() {
12820
- return new _ComponentStack(this.comps, this);
12821
- }
12822
- registerComponents(comps, opts) {
12823
- const { aliases: aliases2 = {} } = opts ?? {};
12824
- for (let i = 0; i < comps.length; i++) {
12825
- const comp = comps[i];
12826
- comp.scope = this.enter();
12827
- comp.Class.scope = comp.scope;
12828
- this.comps.registerComponent(comp);
12829
- this.byName[comp.name] = comp;
12830
- }
12831
- for (const alias in aliases2) {
12832
- const comp = this.byName[aliases2[alias]];
12833
- console.assert(this.byName[alias] === void 0, "alias overrides component", alias);
12834
- if (comp !== void 0) this.byName[alias] = comp;
12835
- else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
12836
- }
12837
- }
12838
- registerMacros(macros) {
12839
- for (const key in macros) {
12840
- const lower = key.toLowerCase();
12841
- console.assert(this.macros[lower] === void 0, "macro key collision", lower);
12842
- this.macros[lower] = macros[key];
12843
- }
12844
- }
12845
- getCompFor(v) {
12846
- return this.comps.getCompFor(v);
12847
- }
12848
- // Handlers that answer an intent's `lex` leg. A name maps to a LIST, because the leg
12849
- // walks: a handler that returns PASS declines and hands the intent to the next one.
12850
- // A bare function is accepted as a one-element list.
12851
- registerIntentHandlers(handlers) {
12852
- for (const name in handlers) {
12853
- const fns = Array.isArray(handlers[name]) ? handlers[name] : [handlers[name]];
12854
- this.intentsByName[name] = fns.map((fn) => new IntentHandler(name, fn));
12855
- }
12856
- }
12857
- // Innermost scope first, then outward. Concatenated rather than first-match, so a
12858
- // declining handler can hand the intent to one further up.
12859
- lookupIntentChain(name) {
12860
- const here = this.intentsByName[name] ?? [];
12861
- const up = this.parent?.lookupIntentChain(name) ?? [];
12862
- return up.length === 0 ? here : here.concat(up);
12863
- }
12864
- lookupComponent(name) {
12865
- return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
12866
- }
12867
- lookupMacro(name) {
12868
- return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
12869
- }
12870
- };
12871
- ProvideInfo = class {
12872
- constructor(name, val, symbol) {
12873
- this.name = name;
12874
- this.val = val;
12875
- this.symbol = symbol;
12876
- }
12877
- };
12878
- LookupInfo = class {
12879
- constructor(name, compName, provideName, val) {
12880
- this.name = name;
12881
- this.compName = compName;
12882
- this.provideName = provideName;
12883
- this.val = val;
12884
- this._sym = void 0;
12885
- }
12886
- getProducerSymbol(stack) {
12887
- if (this._sym === void 0)
12888
- this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
12889
- return this._sym;
12890
- }
12891
- };
12892
- isString = (v) => typeof v === "string";
12893
- _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
12894
- KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
12895
- _compId = 0;
12896
- Component = class {
12897
- constructor(Class, o) {
12898
- this.id = _compId++;
12899
- this.name = o.name ?? "UnkComp";
12900
- this.Class = Class;
12901
- this.views = { main: new View("main", o.view, o.style) };
12902
- this.commonStyle = o.commonStyle ?? "";
12903
- this.globalStyle = o.globalStyle ?? "";
12904
- this.receive = o.receive ?? {};
12905
- this.intent = o.intent ?? {};
12906
- this.alter = o.alter ?? {};
12907
- for (const name in o.views ?? {}) {
12908
- const v = o.views[name];
12909
- const { view, style } = isString(v) ? { view: v } : v;
12910
- this.views[name] = new View(name, view, style);
12911
- }
12912
- this._rawProvide = o.provide ?? {};
12913
- this._rawLookup = o.lookup ?? {};
12914
- this.provide = {};
12915
- this.lookup = {};
12916
- this.scope = null;
12917
- this.spec = o;
12918
- this.extra = {};
12919
- for (const key of Object.keys(o)) if (!KNOWN_SPEC_KEYS.has(key)) this.extra[key] = o[key];
12920
- }
12921
- compile(ParseContext2) {
12922
- for (const name in this.views)
12923
- this.views[name].compile(new ParseContext2(), this.scope, this.id);
12924
- const ctx = this.views.main.ctx;
12925
- for (const key in this._rawProvide) {
12926
- const val = parseProvide(this._rawProvide[key], ctx);
12927
- if (val) this.provide[key] = new ProvideInfo(key, val, Symbol(key));
12928
- }
12929
- for (const key in this._rawLookup) {
12930
- const linfo = this._rawLookup[key];
12931
- const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
12932
- const [compName, provideName] = forStr === null ? [] : forStr.split(".");
12933
- if (!isString(compName) || !isString(provideName)) continue;
12934
- const defStr = isString(linfo?.default) ? linfo.default : null;
12935
- const val = defStr === null ? null : parseField(defStr, ctx);
12936
- this.lookup[key] = new LookupInfo(key, compName, provideName, val);
12937
- }
12938
- for (const key in this.lookup)
12939
- if (this.provide[key] !== void 0)
12940
- console.warn("name declared in both provide and lookup", this.name, key);
12941
- }
12942
- make(args, opts) {
12943
- return this.Class.make(args, opts ?? { scope: this.scope });
12944
- }
12945
- getView(name) {
12946
- return this.views[name] ?? this.views.main;
12947
- }
12948
- getEventForId(id, name = "main") {
12949
- return this.getView(name).ctx.getEventForId(id);
12950
- }
12951
- getNodeForId(id, name = "main") {
12952
- return this.getView(name).ctx.getNodeForId(id);
12953
- }
12954
- compileStyle() {
12955
- const { id, commonStyle, globalStyle, views } = this;
12956
- const styles2 = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
12957
- if (globalStyle !== "") styles2.push(globalStyle);
12958
- for (const name in views) {
12959
- const { style } = views[name];
12960
- if (style !== "") styles2.push(`[data-cid="${id}"][data-vid="${name}"]{${style}}`);
12961
- }
12962
- return styles2.join("\n");
12963
- }
12964
- };
12965
- }
12966
- });
12967
-
12968
12842
  // tools/core/lint.js
12969
12843
  function lintComponents(normalized, { name = null, LintParseContextClass, wellKnownExtras = /* @__PURE__ */ new Set() }) {
12970
12844
  const comps = normalized.components;
@@ -12996,14 +12870,14 @@ var init_lint2 = __esm({
12996
12870
 
12997
12871
  // tools/core/list.js
12998
12872
  function summarize(comp) {
12999
- const meta = comp.Class.getMetaClass();
12873
+ const { fields: fieldMap, name } = comp;
13000
12874
  const fields = [];
13001
- for (const fieldName in meta.fields) {
13002
- const f = meta.fields[fieldName];
12875
+ for (const fieldName in fieldMap) {
12876
+ const f = fieldMap[fieldName];
13003
12877
  fields.push({ name: fieldName, type: f.type });
13004
12878
  }
13005
12879
  return new ComponentSummary({
13006
- name: comp.name,
12880
+ name,
13007
12881
  views: Object.keys(comp.views ?? {}),
13008
12882
  fields
13009
12883
  });
@@ -13231,7 +13105,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
13231
13105
  return b.build();
13232
13106
  }
13233
13107
  function validateDraftFields(current2, draft) {
13234
- const meta = current2?.constructor?.getMetaClass?.();
13108
+ const meta = current2?.constructor?.[COMPONENT] ?? current2?.constructor?.getMetaClass?.();
13235
13109
  if (!meta) return;
13236
13110
  for (const [name, field] of Object.entries(meta.fields)) {
13237
13111
  const value = draft[name];
@@ -13244,7 +13118,7 @@ function validateDraftFields(current2, draft) {
13244
13118
  }
13245
13119
  }
13246
13120
  }
13247
- var BAD_VALUE2, nullCoercer, isPlainObject4, Field, Check, CheckTypeAny, CHECK_TYPE_ANY, FnCheck, check, CHECK_TYPE_INT, CHECK_TYPE_FLOAT, CHECK_TYPE_BOOL, CHECK_TYPE_STRING, CHECK_TYPE_LIST, CHECK_TYPE_OBJECT, CHECK_TYPE_MAP, CHECK_TYPE_SET, FieldBool, FieldAny, FieldString, FieldInt, FieldFloat, getTypeName, CheckTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName;
13121
+ var BAD_VALUE2, nullCoercer, isPlainObject4, Field, Check, CheckTypeAny, CHECK_TYPE_ANY, FnCheck, check, CHECK_TYPE_INT, CHECK_TYPE_FLOAT, CHECK_TYPE_BOOL, CHECK_TYPE_STRING, CHECK_TYPE_LIST, CHECK_TYPE_OBJECT, CHECK_TYPE_MAP, CHECK_TYPE_SET, FieldBool, FieldAny, FieldString, FieldInt, FieldFloat, getTypeName, CheckTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName, META_KEYS;
13248
13122
  var init_oo = __esm({
13249
13123
  "src/oo.js"() {
13250
13124
  init_components();
@@ -13356,7 +13230,7 @@ var init_oo = __esm({
13356
13230
  super("float", name, CHECK_TYPE_FLOAT, (_) => null, defaultValue);
13357
13231
  }
13358
13232
  };
13359
- getTypeName = (v) => v?.constructor?.getMetaClass?.()?.name;
13233
+ getTypeName = (v) => v?.constructor?.[COMPONENT]?.name ?? v?.constructor?.getMetaClass?.()?.name ?? null;
13360
13234
  CheckTypeName = class {
13361
13235
  constructor(typeName) {
13362
13236
  this.typeName = typeName;
@@ -13449,7 +13323,7 @@ var init_oo = __esm({
13449
13323
  getMetaClass: () => metaClass,
13450
13324
  make(inArgs = {}, opts = {}) {
13451
13325
  const args = {};
13452
- const scope = opts.scope ?? this.scope;
13326
+ const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
13453
13327
  for (const key in inArgs) {
13454
13328
  const field = fields[key];
13455
13329
  if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
@@ -13496,7 +13370,33 @@ var init_oo = __esm({
13496
13370
  set: FieldSet,
13497
13371
  any: FieldAny
13498
13372
  };
13499
- Component.fromSpec = (opts) => new Component(classFromData(opts.name, opts), opts);
13373
+ META_KEYS = "name id fields methods views receive intent alter provide lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
13374
+ " "
13375
+ );
13376
+ Component.fromSpec = (opts) => {
13377
+ const Class = classFromData(opts.name, opts);
13378
+ const comp = new Component(Class, opts);
13379
+ const metaClass = Class.getMetaClass();
13380
+ comp.fields = metaClass.fields;
13381
+ comp.methods = metaClass.methods;
13382
+ Class.getMetaClass = () => comp;
13383
+ Class[COMPONENT] = comp;
13384
+ for (const key of META_KEYS)
13385
+ if (!Object.hasOwn(Class, key))
13386
+ Object.defineProperty(Class, key, {
13387
+ get() {
13388
+ return comp[key];
13389
+ },
13390
+ set(v) {
13391
+ comp[key] = v;
13392
+ },
13393
+ configurable: true
13394
+ });
13395
+ for (const key of Object.getOwnPropertyNames(Component.prototype))
13396
+ if (key !== "constructor" && key !== "make" && !Object.hasOwn(Class, key))
13397
+ Class[key] = (...args) => comp[key](...args);
13398
+ return Class;
13399
+ };
13500
13400
  }
13501
13401
  });
13502
13402
 
@@ -13669,8 +13569,8 @@ var init_transactor = __esm({
13669
13569
  whenSettled() {
13670
13570
  return this.completion.whenSettled();
13671
13571
  }
13672
- // Resolves once this transaction AND all transitively-derived work (sends, bubbles,
13673
- // requests and the responses they produce, recursively) have settled.
13572
+ // Resolves once this transaction AND all transitively-derived work (sends and
13573
+ // intents, including the answers they produce, recursively) have settled.
13674
13574
  whenSubtreeSettled() {
13675
13575
  return this.completion.whenSubtreeSettled();
13676
13576
  }
@@ -13841,7 +13741,7 @@ var init_transactor = __esm({
13841
13741
  }
13842
13742
  handlerProp = null;
13843
13743
  // NameArgs verbs map their handler bucket straight to the observed kind:
13844
- // receive / bubble / response / input.
13744
+ // receive / intent.
13845
13745
  get observeKind() {
13846
13746
  return this.handlerProp;
13847
13747
  }
@@ -14491,7 +14391,7 @@ var init_on = __esm({
14491
14391
  // src/util/render.js
14492
14392
  function reindexComponents(comps) {
14493
14393
  for (let i = 0; i < comps.length; i++) {
14494
- comps[i].id = i;
14394
+ comps[i][COMPONENT].id = i;
14495
14395
  }
14496
14396
  }
14497
14397
  function serializeContainer(container) {
@@ -14556,7 +14456,7 @@ var init_render = __esm({
14556
14456
  // tools/core/render.js
14557
14457
  function checkView2(value, components, viewName) {
14558
14458
  if (viewName === "main") return null;
14559
- const comp = components.find((c) => value instanceof c.Class);
14459
+ const comp = components.find((c) => value instanceof c);
14560
14460
  if (!comp || comp.views[viewName]) return null;
14561
14461
  const known = Object.keys(comp.views).sort().join(", ");
14562
14462
  return new Error(`view "${viewName}" is not defined on ${comp.name} (has: ${known})`);
@@ -14625,12 +14525,14 @@ var init_render2 = __esm({
14625
14525
 
14626
14526
  // tools/core/tests.js
14627
14527
  function isComponentObject(x) {
14628
- return x !== null && typeof x === "object" && typeof x.name === "string" && typeof x.Class === "function";
14528
+ if (x === null) return false;
14529
+ if (typeof x === "function") return x[COMPONENT] != null;
14530
+ return typeof x.name === "string" && typeof x.Class === "function";
14629
14531
  }
14630
14532
  function resolveComponentName2(arg, components) {
14631
14533
  if (isComponentObject(arg)) return arg.name;
14632
14534
  if (typeof arg === "function") {
14633
- for (const c of components) if (c.Class === arg) return c.name;
14535
+ for (const c of components) if (c === arg) return c.name;
14634
14536
  }
14635
14537
  return null;
14636
14538
  }
@@ -14710,6 +14612,7 @@ function makeCollector({ path = null, components = [] } = {}) {
14710
14612
  var Describe, Test, ModuleTests;
14711
14613
  var init_tests = __esm({
14712
14614
  "tools/core/tests.js"() {
14615
+ init_components();
14713
14616
  Describe = class {
14714
14617
  constructor({ title, componentName = null, parent = null }) {
14715
14618
  this.title = title;