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.
- package/dist/tutuca-cli.js +264 -361
- package/dist/tutuca-components.js +175 -175
- package/dist/tutuca-dev.ext.js +250 -323
- package/dist/tutuca-dev.js +250 -323
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +55 -46
- package/dist/tutuca-extra.js +55 -46
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca-storybook.js +29 -29
- package/dist/tutuca.ext.js +55 -46
- package/dist/tutuca.js +55 -46
- package/dist/tutuca.min.js +3 -3
- package/package.json +4 -3
- package/skill/margaui/SKILL.md +0 -105
- package/skill/margaui/components/accordion.md +0 -127
- package/skill/margaui/components/alert.md +0 -174
- package/skill/margaui/components/aura.md +0 -97
- package/skill/margaui/components/avatar.md +0 -220
- package/skill/margaui/components/badge.md +0 -193
- package/skill/margaui/components/breadcrumbs.md +0 -103
- package/skill/margaui/components/button.md +0 -322
- package/skill/margaui/components/calendar.md +0 -67
- package/skill/margaui/components/card.md +0 -373
- package/skill/margaui/components/carousel.md +0 -387
- package/skill/margaui/components/chat.md +0 -171
- package/skill/margaui/components/checkbox.md +0 -101
- package/skill/margaui/components/collapse.md +0 -172
- package/skill/margaui/components/countdown.md +0 -165
- package/skill/margaui/components/diff.md +0 -53
- package/skill/margaui/components/divider.md +0 -107
- package/skill/margaui/components/dock.md +0 -173
- package/skill/margaui/components/drawer.md +0 -184
- package/skill/margaui/components/dropdown.md +0 -388
- package/skill/margaui/components/fab.md +0 -346
- package/skill/margaui/components/fieldset.md +0 -88
- package/skill/margaui/components/file-input.md +0 -84
- package/skill/margaui/components/filter.md +0 -52
- package/skill/margaui/components/footer.md +0 -583
- package/skill/margaui/components/hero.md +0 -135
- package/skill/margaui/components/hover-3d.md +0 -129
- package/skill/margaui/components/hover-gallery.md +0 -49
- package/skill/margaui/components/indicator.md +0 -265
- package/skill/margaui/components/input.md +0 -389
- package/skill/margaui/components/join.md +0 -100
- package/skill/margaui/components/kbd.md +0 -127
- package/skill/margaui/components/label.md +0 -102
- package/skill/margaui/components/link.md +0 -96
- package/skill/margaui/components/list.md +0 -182
- package/skill/margaui/components/loading.md +0 -105
- package/skill/margaui/components/mask.md +0 -168
- package/skill/margaui/components/megamenu.md +0 -131
- package/skill/margaui/components/menu.md +0 -887
- package/skill/margaui/components/mockup-browser.md +0 -39
- package/skill/margaui/components/mockup-code.md +0 -81
- package/skill/margaui/components/mockup-phone.md +0 -39
- package/skill/margaui/components/mockup-window.md +0 -33
- package/skill/margaui/components/modal.md +0 -196
- package/skill/margaui/components/navbar.md +0 -282
- package/skill/margaui/components/otp.md +0 -171
- package/skill/margaui/components/pagination.md +0 -122
- package/skill/margaui/components/progress.md +0 -135
- package/skill/margaui/components/radial-progress.md +0 -67
- package/skill/margaui/components/radio.md +0 -133
- package/skill/margaui/components/range.md +0 -134
- package/skill/margaui/components/rating.md +0 -170
- package/skill/margaui/components/select.md +0 -225
- package/skill/margaui/components/skeleton.md +0 -64
- package/skill/margaui/components/stack.md +0 -142
- package/skill/margaui/components/stat.md +0 -254
- package/skill/margaui/components/status.md +0 -73
- package/skill/margaui/components/steps.md +0 -138
- package/skill/margaui/components/swap.md +0 -152
- package/skill/margaui/components/tab.md +0 -248
- package/skill/margaui/components/table.md +0 -1018
- package/skill/margaui/components/text-rotate.md +0 -91
- package/skill/margaui/components/textarea.md +0 -85
- package/skill/margaui/components/theme-controller.md +0 -266
- package/skill/margaui/components/timeline.md +0 -1356
- package/skill/margaui/components/toast.md +0 -165
- package/skill/margaui/components/toggle.md +0 -135
- package/skill/margaui/components/tooltip.md +0 -181
- package/skill/margaui/components/validator.md +0 -163
- package/skill/tutuca/SKILL.md +0 -56
- package/skill/tutuca/advanced.md +0 -212
- package/skill/tutuca/cli.md +0 -239
- package/skill/tutuca/component-design.md +0 -168
- package/skill/tutuca/core.md +0 -908
- package/skill/tutuca/iteration.md +0 -207
- package/skill/tutuca/macros.md +0 -86
- package/skill/tutuca/margaui.md +0 -175
- package/skill/tutuca/messages-and-intents.md +0 -399
- package/skill/tutuca/patterns/README.md +0 -48
- package/skill/tutuca/patterns/add-a-story.md +0 -26
- package/skill/tutuca/patterns/bind-text-and-attributes.md +0 -30
- package/skill/tutuca/patterns/conditional-attribute-value.md +0 -29
- package/skill/tutuca/patterns/coordinate-components.md +0 -54
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +0 -27
- package/skill/tutuca/patterns/enrich-each-item.md +0 -25
- package/skill/tutuca/patterns/file-input.md +0 -39
- package/skill/tutuca/patterns/filter-a-list.md +0 -25
- package/skill/tutuca/patterns/filter-and-paginate.md +0 -60
- package/skill/tutuca/patterns/handle-events.md +0 -38
- package/skill/tutuca/patterns/iterate-a-list.md +0 -18
- package/skill/tutuca/patterns/paginate-a-list.md +0 -29
- package/skill/tutuca/patterns/render-a-child-component.md +0 -21
- package/skill/tutuca/patterns/reuse-markup-with-macros.md +0 -36
- package/skill/tutuca/patterns/share-state-across-the-tree.md +0 -38
- package/skill/tutuca/patterns/show-or-hide-content.md +0 -23
- package/skill/tutuca/patterns/switch-between-views.md +0 -30
- package/skill/tutuca/patterns/tabbed-interface.md +0 -43
- package/skill/tutuca/semantics.md +0 -195
- package/skill/tutuca/storybook.md +0 -270
- package/skill/tutuca/styles.md +0 -48
- package/skill/tutuca/testing.md +0 -346
- package/skill/tutuca-source/SKILL.md +0 -33
- package/skill/tutuca-source/tutuca.ext.js +0 -4235
package/dist/tutuca-storybook.js
CHANGED
|
@@ -52,13 +52,6 @@ var Storybook = component({
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
|
-
alter: {
|
|
56
|
-
// The sidebar render-each shows only visible groups (kept positional via `when`
|
|
57
|
-
// so a click resolves to the right group — see SidebarGroup.rowVisible).
|
|
58
|
-
groupVisible(_key, group) {
|
|
59
|
-
return group.visible;
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
55
|
receive: {
|
|
63
56
|
onApplyFilter(draft, value, ctx) {
|
|
64
57
|
ctx.intent("persistState", [this.toUrlState({ sectionFilter: value }), this, false], {
|
|
@@ -160,6 +153,13 @@ var Storybook = component({
|
|
|
160
153
|
setSelectedSectionFilter(draft, value);
|
|
161
154
|
}
|
|
162
155
|
},
|
|
156
|
+
alter: {
|
|
157
|
+
// The sidebar render-each shows only visible groups (kept positional via `when`
|
|
158
|
+
// so a click resolves to the right group — see SidebarGroup.rowVisible).
|
|
159
|
+
groupVisible(_key, group) {
|
|
160
|
+
return group.visible;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
163
|
view: html`<div>
|
|
164
164
|
<div class="flex flex-col gap-3 p-3 h-screen" @show="truthy? .focusExample">
|
|
165
165
|
<div class="flex justify-end">
|
|
@@ -250,15 +250,10 @@ var Section = component({
|
|
|
250
250
|
// ignored here (rendered ungrouped) rather than coerced; the normalize layer
|
|
251
251
|
// (tools/core/module.js) reports it as a shape error.
|
|
252
252
|
group: typeof group === "string" ? group : "",
|
|
253
|
-
items: items.map((v) => Example.
|
|
253
|
+
items: items.map((v) => Example.fromData(v))
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
},
|
|
257
|
-
alter: {
|
|
258
|
-
filterItem(_key, item) {
|
|
259
|
-
return this.filter === "" || fuzzyMatch(this.filter, `${item.title} ${item.description}`);
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
257
|
receive: {
|
|
263
258
|
onApplyFilter(draft, value, ctx) {
|
|
264
259
|
ctx.intent("exampleFilterChanged", [value], { route: ["dyn"] });
|
|
@@ -282,6 +277,11 @@ var Section = component({
|
|
|
282
277
|
return this;
|
|
283
278
|
}
|
|
284
279
|
},
|
|
280
|
+
alter: {
|
|
281
|
+
filterItem(_key, item) {
|
|
282
|
+
return this.filter === "" || fuzzyMatch(this.filter, `${item.title} ${item.description}`);
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
285
|
view: html`<section class="flex flex-col gap-3">
|
|
286
286
|
<div class="sticky top-0 z-10 bg-base-100 pt-1 pb-2 shadow-sm">
|
|
287
287
|
<h2 class="text-lg font-bold" @text=".title"></h2>
|
|
@@ -323,6 +323,12 @@ var SidebarEntry = component({
|
|
|
323
323
|
var SidebarGroup = component({
|
|
324
324
|
name: "SidebarGroup",
|
|
325
325
|
fields: { name: "", collapsed: false, visible: true, rows: [] },
|
|
326
|
+
receive: {
|
|
327
|
+
onToggle(draft, ctx) {
|
|
328
|
+
ctx.intent("groupToggled", [this.name], { route: ["dyn"] });
|
|
329
|
+
return this;
|
|
330
|
+
}
|
|
331
|
+
},
|
|
326
332
|
// Visibility drives the render-each `when` predicates (not `@show` on the items):
|
|
327
333
|
// a `when` filter renders only visible rows while keeping each row's positional key,
|
|
328
334
|
// so an event's path resolves to the right row. `@show` on a render-each item would
|
|
@@ -332,12 +338,6 @@ var SidebarGroup = component({
|
|
|
332
338
|
return row.visible;
|
|
333
339
|
}
|
|
334
340
|
},
|
|
335
|
-
receive: {
|
|
336
|
-
onToggle(draft, ctx) {
|
|
337
|
-
ctx.intent("groupToggled", [this.name], { route: ["dyn"] });
|
|
338
|
-
return this;
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
341
|
view: html`<div class="flex flex-col">
|
|
342
342
|
<div
|
|
343
343
|
class="list-row cursor-pointer hover:bg-base-200 font-semibold flex items-center gap-1"
|
|
@@ -411,6 +411,14 @@ var Example = component({
|
|
|
411
411
|
});
|
|
412
412
|
}
|
|
413
413
|
},
|
|
414
|
+
methods: {
|
|
415
|
+
// An `intent` on the `dyn` leg leaves the example and walks into the storybook
|
|
416
|
+
// engine's own components. Nothing to warn about: if nothing answers, the walk
|
|
417
|
+
// runs out and the example hears `<name>Unhandled`.
|
|
418
|
+
runPhase(ctx, phase) {
|
|
419
|
+
dispatchPhase(ctx, ctx.at.field("value").buildPath(), phase, this.value);
|
|
420
|
+
}
|
|
421
|
+
},
|
|
414
422
|
// Lifecycle hooks: the section forwards init/resume/suspend here; each runs the
|
|
415
423
|
// matching `on` phase's actions against this example's component (`.value`).
|
|
416
424
|
receive: {
|
|
@@ -446,14 +454,6 @@ var Example = component({
|
|
|
446
454
|
draft.activeTab = value;
|
|
447
455
|
}
|
|
448
456
|
},
|
|
449
|
-
methods: {
|
|
450
|
-
// An `intent` on the `dyn` leg leaves the example and walks into the storybook
|
|
451
|
-
// engine's own components. Nothing to warn about: if nothing answers, the walk
|
|
452
|
-
// runs out and the example hears `<name>Unhandled`.
|
|
453
|
-
runPhase(ctx, phase) {
|
|
454
|
-
dispatchPhase(ctx, ctx.at.field("value").buildPath(), phase, this.value);
|
|
455
|
-
}
|
|
456
|
-
},
|
|
457
457
|
view: html`<div class="card card-border bg-base-100 shadow-md">
|
|
458
458
|
<div class="card-body">
|
|
459
459
|
<h2 class="card-title flex justify-between">
|
|
@@ -678,7 +678,7 @@ function buildStorybook(modules) {
|
|
|
678
678
|
if (raw == null) return [];
|
|
679
679
|
return Array.isArray(raw) ? raw : [raw];
|
|
680
680
|
});
|
|
681
|
-
const sections = rawSections.map((s) => Section.
|
|
681
|
+
const sections = rawSections.map((s) => Section.fromData(s)).sort((a, b) => a.title.localeCompare(b.title));
|
|
682
682
|
const engineComponents = [
|
|
683
683
|
Storybook,
|
|
684
684
|
Section,
|
|
@@ -713,7 +713,7 @@ function buildStorybook(modules) {
|
|
|
713
713
|
}
|
|
714
714
|
const components = [.../* @__PURE__ */ new Set([...engineComponents, ...moduleComponents.flat()])];
|
|
715
715
|
return {
|
|
716
|
-
root: Storybook.
|
|
716
|
+
root: Storybook.withSections(sections),
|
|
717
717
|
components,
|
|
718
718
|
engineComponents,
|
|
719
719
|
moduleComponents,
|
package/dist/tutuca.ext.js
CHANGED
|
@@ -2076,13 +2076,12 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
2076
2076
|
const a = attrs[i];
|
|
2077
2077
|
const aName = a.name;
|
|
2078
2078
|
if (consumed.has(aName)) continue;
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
continue;
|
|
2079
|
+
if (wrappable && aName.charCodeAt(0) === 64) {
|
|
2080
|
+
const wrapper = X_OPS[aName.slice(1)]?.wrapper;
|
|
2081
|
+
if (wrapper) {
|
|
2082
|
+
wrappers.push([wrapper, parseBool(a.value, px)]);
|
|
2083
|
+
continue;
|
|
2084
|
+
}
|
|
2086
2085
|
}
|
|
2087
2086
|
const issueInfo = { op: opName, name: aName, value: a.value };
|
|
2088
2087
|
px.onParseIssue("unknown-x-attr", issueInfo);
|
|
@@ -2094,9 +2093,6 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
2094
2093
|
}
|
|
2095
2094
|
return node;
|
|
2096
2095
|
}
|
|
2097
|
-
function maybeDeprecateBareXDirective(px, opName, name) {
|
|
2098
|
-
px.onDeprecatedSyntax("bare-x-directive", { op: opName, name });
|
|
2099
|
-
}
|
|
2100
2096
|
function wrap(node, px, wrappers) {
|
|
2101
2097
|
if (wrappers) {
|
|
2102
2098
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
@@ -2218,17 +2214,10 @@ function parseRenderEach(px, value, as, attrs) {
|
|
|
2218
2214
|
const attrParser = getAttrParser(px);
|
|
2219
2215
|
const eachAttr = attrParser.pushWrapper("each", value, seqVal);
|
|
2220
2216
|
attrParser.eachAttr = eachAttr;
|
|
2221
|
-
const when = attrs.getNamedItem("@when")
|
|
2222
|
-
if (when)
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
}
|
|
2226
|
-
const lWith = attrs.getNamedItem("@loop-with") ?? attrs.getNamedItem("loop-with");
|
|
2227
|
-
if (lWith) {
|
|
2228
|
-
if (lWith.name.charCodeAt(0) !== 64)
|
|
2229
|
-
maybeDeprecateBareXDirective(px, "render-each", "loop-with");
|
|
2230
|
-
attrParser._parseLoopWith(lWith.value);
|
|
2231
|
-
}
|
|
2217
|
+
const when = attrs.getNamedItem("@when");
|
|
2218
|
+
if (when) attrParser._parseWhen(when.value);
|
|
2219
|
+
const lWith = attrs.getNamedItem("@loop-with");
|
|
2220
|
+
if (lWith) attrParser._parseLoopWith(lWith.value);
|
|
2232
2221
|
const each = px.addNodeIf(EachNode, seqVal);
|
|
2233
2222
|
each.iterInfo.whenVal = eachAttr.whenVal ?? null;
|
|
2234
2223
|
each.iterInfo.loopWithVal = eachAttr.loopWithVal ?? null;
|
|
@@ -2366,10 +2355,8 @@ var X_OPS = {
|
|
|
2366
2355
|
render: xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
2367
2356
|
"render-it": xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
2368
2357
|
// `@when`/`@loop-with` are consumed here (handled in parseRenderEach) so
|
|
2369
|
-
// `processXExtras` does not flag them as unknown attrs.
|
|
2370
|
-
|
|
2371
|
-
// maybeDeprecateBareXDirective (added 2026-07-08).
|
|
2372
|
-
"render-each": xOp(["as", "when", "loop-with", "@when", "@loop-with"], {
|
|
2358
|
+
// `processXExtras` does not flag them as unknown attrs.
|
|
2359
|
+
"render-each": xOp(["as", "@when", "@loop-with"], {
|
|
2373
2360
|
wrappable: true,
|
|
2374
2361
|
ignoresChildren: true
|
|
2375
2362
|
}),
|
|
@@ -2460,10 +2447,6 @@ var ParseContext = class _ParseContext {
|
|
|
2460
2447
|
onParseIssue(kind, info) {
|
|
2461
2448
|
console.warn(`tutuca parse issue [${kind}]`, info);
|
|
2462
2449
|
}
|
|
2463
|
-
// Lint-only channel for deprecation nudges on still-valid syntax; the base
|
|
2464
|
-
// (runtime) context ignores them so live apps stay quiet. See LintParseContext.
|
|
2465
|
-
onDeprecatedSyntax(_kind, _info) {
|
|
2466
|
-
}
|
|
2467
2450
|
};
|
|
2468
2451
|
var _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";
|
|
2469
2452
|
var HTML_BLOCK_TAGS = new Set(_htmlBlockTags.split(","));
|
|
@@ -2600,20 +2583,20 @@ function compileModifiers(eventName, names) {
|
|
|
2600
2583
|
}
|
|
2601
2584
|
|
|
2602
2585
|
// src/components.js
|
|
2586
|
+
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
2603
2587
|
var Components = class {
|
|
2604
2588
|
constructor() {
|
|
2605
|
-
this.getComponentSymbol = /* @__PURE__ */ Symbol("getComponent");
|
|
2606
2589
|
this.byId = /* @__PURE__ */ new Map();
|
|
2607
2590
|
}
|
|
2608
|
-
registerComponent(
|
|
2609
|
-
|
|
2610
|
-
this.byId.set(comp.id, comp);
|
|
2591
|
+
registerComponent(Comp) {
|
|
2592
|
+
this.byId.set(Comp[COMPONENT].id, Comp);
|
|
2611
2593
|
}
|
|
2612
2594
|
getComponentForId(id) {
|
|
2613
2595
|
return this.byId.get(id) ?? null;
|
|
2614
2596
|
}
|
|
2615
2597
|
getCompFor(v) {
|
|
2616
|
-
|
|
2598
|
+
const Comp = v?.constructor;
|
|
2599
|
+
return Comp?.[COMPONENT] ? Comp : null;
|
|
2617
2600
|
}
|
|
2618
2601
|
getHandlerFor(v, name, key) {
|
|
2619
2602
|
return this.getCompFor(v)?.[key][name] ?? null;
|
|
@@ -2644,11 +2627,10 @@ var ComponentStack = class _ComponentStack {
|
|
|
2644
2627
|
registerComponents(comps, opts) {
|
|
2645
2628
|
const { aliases = {} } = opts ?? {};
|
|
2646
2629
|
for (let i = 0; i < comps.length; i++) {
|
|
2647
|
-
const
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
this.
|
|
2651
|
-
this.byName[comp.name] = comp;
|
|
2630
|
+
const Comp = comps[i];
|
|
2631
|
+
Comp[COMPONENT].scope = this.enter();
|
|
2632
|
+
this.comps.registerComponent(Comp);
|
|
2633
|
+
this.byName[Comp.name] = Comp;
|
|
2652
2634
|
}
|
|
2653
2635
|
for (const alias in aliases) {
|
|
2654
2636
|
const comp = this.byName[aliases[alias]];
|
|
@@ -3032,7 +3014,7 @@ var FieldFloat = class extends Field {
|
|
|
3032
3014
|
super("float", name, CHECK_TYPE_FLOAT, (_) => null, defaultValue);
|
|
3033
3015
|
}
|
|
3034
3016
|
};
|
|
3035
|
-
var getTypeName = (v) => v?.constructor?.getMetaClass?.()?.name;
|
|
3017
|
+
var getTypeName = (v) => v?.constructor?.[COMPONENT]?.name ?? v?.constructor?.getMetaClass?.()?.name ?? null;
|
|
3036
3018
|
var CheckTypeName = class {
|
|
3037
3019
|
constructor(typeName) {
|
|
3038
3020
|
this.typeName = typeName;
|
|
@@ -3133,7 +3115,7 @@ var ClassBuilder = class {
|
|
|
3133
3115
|
getMetaClass: () => metaClass,
|
|
3134
3116
|
make(inArgs = {}, opts = {}) {
|
|
3135
3117
|
const args = {};
|
|
3136
|
-
const scope = opts.scope ?? this.scope;
|
|
3118
|
+
const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
|
|
3137
3119
|
for (const key in inArgs) {
|
|
3138
3120
|
const field = fields[key];
|
|
3139
3121
|
if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
@@ -3213,7 +3195,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
3213
3195
|
return b.build();
|
|
3214
3196
|
}
|
|
3215
3197
|
function validateDraftFields(current, draft) {
|
|
3216
|
-
const meta = current?.constructor?.getMetaClass?.();
|
|
3198
|
+
const meta = current?.constructor?.[COMPONENT] ?? current?.constructor?.getMetaClass?.();
|
|
3217
3199
|
if (!meta) return;
|
|
3218
3200
|
for (const [name, field] of Object.entries(meta.fields)) {
|
|
3219
3201
|
const value = draft[name];
|
|
@@ -3226,7 +3208,33 @@ function validateDraftFields(current, draft) {
|
|
|
3226
3208
|
}
|
|
3227
3209
|
}
|
|
3228
3210
|
}
|
|
3229
|
-
|
|
3211
|
+
var META_KEYS = "name id fields methods views receive intent alter provide lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
3212
|
+
" "
|
|
3213
|
+
);
|
|
3214
|
+
Component.fromSpec = (opts) => {
|
|
3215
|
+
const Class = classFromData(opts.name, opts);
|
|
3216
|
+
const comp = new Component(Class, opts);
|
|
3217
|
+
const metaClass = Class.getMetaClass();
|
|
3218
|
+
comp.fields = metaClass.fields;
|
|
3219
|
+
comp.methods = metaClass.methods;
|
|
3220
|
+
Class.getMetaClass = () => comp;
|
|
3221
|
+
Class[COMPONENT] = comp;
|
|
3222
|
+
for (const key of META_KEYS)
|
|
3223
|
+
if (!Object.hasOwn(Class, key))
|
|
3224
|
+
Object.defineProperty(Class, key, {
|
|
3225
|
+
get() {
|
|
3226
|
+
return comp[key];
|
|
3227
|
+
},
|
|
3228
|
+
set(v) {
|
|
3229
|
+
comp[key] = v;
|
|
3230
|
+
},
|
|
3231
|
+
configurable: true
|
|
3232
|
+
});
|
|
3233
|
+
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
3234
|
+
if (key !== "constructor" && key !== "make" && !Object.hasOwn(Class, key))
|
|
3235
|
+
Class[key] = (...args) => comp[key](...args);
|
|
3236
|
+
return Class;
|
|
3237
|
+
};
|
|
3230
3238
|
var component = (opts) => Component.fromSpec(opts);
|
|
3231
3239
|
|
|
3232
3240
|
// src/transactor.js
|
|
@@ -3381,8 +3389,8 @@ var Transaction = class {
|
|
|
3381
3389
|
whenSettled() {
|
|
3382
3390
|
return this.completion.whenSettled();
|
|
3383
3391
|
}
|
|
3384
|
-
// Resolves once this transaction AND all transitively-derived work (sends
|
|
3385
|
-
//
|
|
3392
|
+
// Resolves once this transaction AND all transitively-derived work (sends and
|
|
3393
|
+
// intents, including the answers they produce, recursively) have settled.
|
|
3386
3394
|
whenSubtreeSettled() {
|
|
3387
3395
|
return this.completion.whenSubtreeSettled();
|
|
3388
3396
|
}
|
|
@@ -3556,7 +3564,7 @@ var NameArgsTransaction = class extends Transaction {
|
|
|
3556
3564
|
}
|
|
3557
3565
|
handlerProp = null;
|
|
3558
3566
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
3559
|
-
// receive /
|
|
3567
|
+
// receive / intent.
|
|
3560
3568
|
get observeKind() {
|
|
3561
3569
|
return this.handlerProp;
|
|
3562
3570
|
}
|
|
@@ -4215,6 +4223,7 @@ function tutuca(nodeOrSelector) {
|
|
|
4215
4223
|
return new App(rootNode, comps, renderer, ParseContext);
|
|
4216
4224
|
}
|
|
4217
4225
|
export {
|
|
4226
|
+
COMPONENT,
|
|
4218
4227
|
FIELD_CLASS,
|
|
4219
4228
|
PASS,
|
|
4220
4229
|
ParseContext,
|
package/dist/tutuca.js
CHANGED
|
@@ -2779,13 +2779,12 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
2779
2779
|
const a = attrs[i];
|
|
2780
2780
|
const aName = a.name;
|
|
2781
2781
|
if (consumed.has(aName)) continue;
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
continue;
|
|
2782
|
+
if (wrappable && aName.charCodeAt(0) === 64) {
|
|
2783
|
+
const wrapper = X_OPS[aName.slice(1)]?.wrapper;
|
|
2784
|
+
if (wrapper) {
|
|
2785
|
+
wrappers.push([wrapper, parseBool(a.value, px)]);
|
|
2786
|
+
continue;
|
|
2787
|
+
}
|
|
2789
2788
|
}
|
|
2790
2789
|
const issueInfo = { op: opName, name: aName, value: a.value };
|
|
2791
2790
|
px.onParseIssue("unknown-x-attr", issueInfo);
|
|
@@ -2797,9 +2796,6 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
2797
2796
|
}
|
|
2798
2797
|
return node;
|
|
2799
2798
|
}
|
|
2800
|
-
function maybeDeprecateBareXDirective(px, opName, name) {
|
|
2801
|
-
px.onDeprecatedSyntax("bare-x-directive", { op: opName, name });
|
|
2802
|
-
}
|
|
2803
2799
|
function wrap(node, px, wrappers) {
|
|
2804
2800
|
if (wrappers) {
|
|
2805
2801
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
@@ -2921,17 +2917,10 @@ function parseRenderEach(px, value, as, attrs) {
|
|
|
2921
2917
|
const attrParser = getAttrParser(px);
|
|
2922
2918
|
const eachAttr = attrParser.pushWrapper("each", value, seqVal);
|
|
2923
2919
|
attrParser.eachAttr = eachAttr;
|
|
2924
|
-
const when = attrs.getNamedItem("@when")
|
|
2925
|
-
if (when)
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
}
|
|
2929
|
-
const lWith = attrs.getNamedItem("@loop-with") ?? attrs.getNamedItem("loop-with");
|
|
2930
|
-
if (lWith) {
|
|
2931
|
-
if (lWith.name.charCodeAt(0) !== 64)
|
|
2932
|
-
maybeDeprecateBareXDirective(px, "render-each", "loop-with");
|
|
2933
|
-
attrParser._parseLoopWith(lWith.value);
|
|
2934
|
-
}
|
|
2920
|
+
const when = attrs.getNamedItem("@when");
|
|
2921
|
+
if (when) attrParser._parseWhen(when.value);
|
|
2922
|
+
const lWith = attrs.getNamedItem("@loop-with");
|
|
2923
|
+
if (lWith) attrParser._parseLoopWith(lWith.value);
|
|
2935
2924
|
const each2 = px.addNodeIf(EachNode, seqVal);
|
|
2936
2925
|
each2.iterInfo.whenVal = eachAttr.whenVal ?? null;
|
|
2937
2926
|
each2.iterInfo.loopWithVal = eachAttr.loopWithVal ?? null;
|
|
@@ -3069,10 +3058,8 @@ var X_OPS = {
|
|
|
3069
3058
|
render: xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
3070
3059
|
"render-it": xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
3071
3060
|
// `@when`/`@loop-with` are consumed here (handled in parseRenderEach) so
|
|
3072
|
-
// `processXExtras` does not flag them as unknown attrs.
|
|
3073
|
-
|
|
3074
|
-
// maybeDeprecateBareXDirective (added 2026-07-08).
|
|
3075
|
-
"render-each": xOp(["as", "when", "loop-with", "@when", "@loop-with"], {
|
|
3061
|
+
// `processXExtras` does not flag them as unknown attrs.
|
|
3062
|
+
"render-each": xOp(["as", "@when", "@loop-with"], {
|
|
3076
3063
|
wrappable: true,
|
|
3077
3064
|
ignoresChildren: true
|
|
3078
3065
|
}),
|
|
@@ -3163,10 +3150,6 @@ var ParseContext = class _ParseContext {
|
|
|
3163
3150
|
onParseIssue(kind, info) {
|
|
3164
3151
|
console.warn(`tutuca parse issue [${kind}]`, info);
|
|
3165
3152
|
}
|
|
3166
|
-
// Lint-only channel for deprecation nudges on still-valid syntax; the base
|
|
3167
|
-
// (runtime) context ignores them so live apps stay quiet. See LintParseContext.
|
|
3168
|
-
onDeprecatedSyntax(_kind, _info) {
|
|
3169
|
-
}
|
|
3170
3153
|
};
|
|
3171
3154
|
var _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";
|
|
3172
3155
|
var HTML_BLOCK_TAGS = new Set(_htmlBlockTags.split(","));
|
|
@@ -3303,20 +3286,20 @@ function compileModifiers(eventName, names) {
|
|
|
3303
3286
|
}
|
|
3304
3287
|
|
|
3305
3288
|
// src/components.js
|
|
3289
|
+
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
3306
3290
|
var Components = class {
|
|
3307
3291
|
constructor() {
|
|
3308
|
-
this.getComponentSymbol = /* @__PURE__ */ Symbol("getComponent");
|
|
3309
3292
|
this.byId = /* @__PURE__ */ new Map();
|
|
3310
3293
|
}
|
|
3311
|
-
registerComponent(
|
|
3312
|
-
|
|
3313
|
-
this.byId.set(comp.id, comp);
|
|
3294
|
+
registerComponent(Comp) {
|
|
3295
|
+
this.byId.set(Comp[COMPONENT].id, Comp);
|
|
3314
3296
|
}
|
|
3315
3297
|
getComponentForId(id) {
|
|
3316
3298
|
return this.byId.get(id) ?? null;
|
|
3317
3299
|
}
|
|
3318
3300
|
getCompFor(v) {
|
|
3319
|
-
|
|
3301
|
+
const Comp = v?.constructor;
|
|
3302
|
+
return Comp?.[COMPONENT] ? Comp : null;
|
|
3320
3303
|
}
|
|
3321
3304
|
getHandlerFor(v, name, key) {
|
|
3322
3305
|
return this.getCompFor(v)?.[key][name] ?? null;
|
|
@@ -3347,11 +3330,10 @@ var ComponentStack = class _ComponentStack {
|
|
|
3347
3330
|
registerComponents(comps, opts) {
|
|
3348
3331
|
const { aliases = {} } = opts ?? {};
|
|
3349
3332
|
for (let i = 0; i < comps.length; i++) {
|
|
3350
|
-
const
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
this.
|
|
3354
|
-
this.byName[comp.name] = comp;
|
|
3333
|
+
const Comp = comps[i];
|
|
3334
|
+
Comp[COMPONENT].scope = this.enter();
|
|
3335
|
+
this.comps.registerComponent(Comp);
|
|
3336
|
+
this.byName[Comp.name] = Comp;
|
|
3355
3337
|
}
|
|
3356
3338
|
for (const alias in aliases) {
|
|
3357
3339
|
const comp = this.byName[aliases[alias]];
|
|
@@ -3735,7 +3717,7 @@ var FieldFloat = class extends Field {
|
|
|
3735
3717
|
super("float", name, CHECK_TYPE_FLOAT, (_) => null, defaultValue);
|
|
3736
3718
|
}
|
|
3737
3719
|
};
|
|
3738
|
-
var getTypeName = (v) => v?.constructor?.getMetaClass?.()?.name;
|
|
3720
|
+
var getTypeName = (v) => v?.constructor?.[COMPONENT]?.name ?? v?.constructor?.getMetaClass?.()?.name ?? null;
|
|
3739
3721
|
var CheckTypeName = class {
|
|
3740
3722
|
constructor(typeName) {
|
|
3741
3723
|
this.typeName = typeName;
|
|
@@ -3836,7 +3818,7 @@ var ClassBuilder = class {
|
|
|
3836
3818
|
getMetaClass: () => metaClass,
|
|
3837
3819
|
make(inArgs = {}, opts = {}) {
|
|
3838
3820
|
const args = {};
|
|
3839
|
-
const scope = opts.scope ?? this.scope;
|
|
3821
|
+
const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
|
|
3840
3822
|
for (const key in inArgs) {
|
|
3841
3823
|
const field = fields[key];
|
|
3842
3824
|
if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
@@ -3916,7 +3898,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
3916
3898
|
return b.build();
|
|
3917
3899
|
}
|
|
3918
3900
|
function validateDraftFields(current2, draft) {
|
|
3919
|
-
const meta = current2?.constructor?.getMetaClass?.();
|
|
3901
|
+
const meta = current2?.constructor?.[COMPONENT] ?? current2?.constructor?.getMetaClass?.();
|
|
3920
3902
|
if (!meta) return;
|
|
3921
3903
|
for (const [name, field] of Object.entries(meta.fields)) {
|
|
3922
3904
|
const value = draft[name];
|
|
@@ -3929,7 +3911,33 @@ function validateDraftFields(current2, draft) {
|
|
|
3929
3911
|
}
|
|
3930
3912
|
}
|
|
3931
3913
|
}
|
|
3932
|
-
|
|
3914
|
+
var META_KEYS = "name id fields methods views receive intent alter provide lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
3915
|
+
" "
|
|
3916
|
+
);
|
|
3917
|
+
Component.fromSpec = (opts) => {
|
|
3918
|
+
const Class = classFromData(opts.name, opts);
|
|
3919
|
+
const comp = new Component(Class, opts);
|
|
3920
|
+
const metaClass = Class.getMetaClass();
|
|
3921
|
+
comp.fields = metaClass.fields;
|
|
3922
|
+
comp.methods = metaClass.methods;
|
|
3923
|
+
Class.getMetaClass = () => comp;
|
|
3924
|
+
Class[COMPONENT] = comp;
|
|
3925
|
+
for (const key of META_KEYS)
|
|
3926
|
+
if (!Object.hasOwn(Class, key))
|
|
3927
|
+
Object.defineProperty(Class, key, {
|
|
3928
|
+
get() {
|
|
3929
|
+
return comp[key];
|
|
3930
|
+
},
|
|
3931
|
+
set(v) {
|
|
3932
|
+
comp[key] = v;
|
|
3933
|
+
},
|
|
3934
|
+
configurable: true
|
|
3935
|
+
});
|
|
3936
|
+
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
3937
|
+
if (key !== "constructor" && key !== "make" && !Object.hasOwn(Class, key))
|
|
3938
|
+
Class[key] = (...args) => comp[key](...args);
|
|
3939
|
+
return Class;
|
|
3940
|
+
};
|
|
3933
3941
|
var component = (opts) => Component.fromSpec(opts);
|
|
3934
3942
|
|
|
3935
3943
|
// src/transactor.js
|
|
@@ -4084,8 +4092,8 @@ var Transaction = class {
|
|
|
4084
4092
|
whenSettled() {
|
|
4085
4093
|
return this.completion.whenSettled();
|
|
4086
4094
|
}
|
|
4087
|
-
// Resolves once this transaction AND all transitively-derived work (sends
|
|
4088
|
-
//
|
|
4095
|
+
// Resolves once this transaction AND all transitively-derived work (sends and
|
|
4096
|
+
// intents, including the answers they produce, recursively) have settled.
|
|
4089
4097
|
whenSubtreeSettled() {
|
|
4090
4098
|
return this.completion.whenSubtreeSettled();
|
|
4091
4099
|
}
|
|
@@ -4259,7 +4267,7 @@ var NameArgsTransaction = class extends Transaction {
|
|
|
4259
4267
|
}
|
|
4260
4268
|
handlerProp = null;
|
|
4261
4269
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
4262
|
-
// receive /
|
|
4270
|
+
// receive / intent.
|
|
4263
4271
|
get observeKind() {
|
|
4264
4272
|
return this.handlerProp;
|
|
4265
4273
|
}
|
|
@@ -4918,6 +4926,7 @@ function tutuca(nodeOrSelector) {
|
|
|
4918
4926
|
return new App(rootNode, comps, renderer, ParseContext);
|
|
4919
4927
|
}
|
|
4920
4928
|
export {
|
|
4929
|
+
COMPONENT,
|
|
4921
4930
|
FIELD_CLASS,
|
|
4922
4931
|
PASS,
|
|
4923
4932
|
ParseContext,
|