tutuca 0.9.110 → 0.9.111

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.
@@ -14456,16 +14456,23 @@ class Example {
14456
14456
  value,
14457
14457
  view = "main",
14458
14458
  componentName = null,
14459
- requestHandlerNames = []
14459
+ requestHandlers = null,
14460
+ requestHandlerNames = [],
14461
+ on = null
14460
14462
  }) {
14461
14463
  this.title = title;
14462
14464
  this.description = description;
14463
14465
  this.value = value;
14464
14466
  this.view = view;
14465
14467
  this.componentName = componentName;
14468
+ this.requestHandlers = requestHandlers;
14466
14469
  this.requestHandlerNames = requestHandlerNames;
14470
+ this.on = on;
14467
14471
  }
14468
14472
  }
14473
+ function isPlainObject2(v) {
14474
+ return v != null && typeof v === "object" && !Array.isArray(v);
14475
+ }
14469
14476
  function resolveComponentName(value, components) {
14470
14477
  for (const comp of components) {
14471
14478
  if (value instanceof comp.Class)
@@ -14512,13 +14519,29 @@ function parseExample(raw, index, components, parentPath) {
14512
14519
  if (rh != null && (typeof rh !== "object" || Array.isArray(rh))) {
14513
14520
  throw shapeError(`example at ${where} "requestHandlers" must be an object of functions`, where);
14514
14521
  }
14522
+ const on = raw.on;
14523
+ if (on != null) {
14524
+ if (!isPlainObject2(on)) {
14525
+ throw shapeError(`example at ${where} "on" must be an object of lifecycle phases (${PHASE_NAMES.join(", ")})`, where);
14526
+ }
14527
+ for (const key in on) {
14528
+ if (!PHASE_NAMES.includes(key)) {
14529
+ throw shapeError(`example at ${where} has unknown lifecycle phase "on.${key}"; expected one of ${PHASE_NAMES.join(", ")}`, where);
14530
+ }
14531
+ if (!isPlainObject2(on[key])) {
14532
+ throw shapeError(`example at ${where} "on.${key}" must be an object of actions (send, bubble, request, input, do)`, where);
14533
+ }
14534
+ }
14535
+ }
14515
14536
  return new Example({
14516
14537
  title: raw.title ?? `Example ${index + 1}`,
14517
14538
  description: raw.description ?? null,
14518
14539
  value: raw.value,
14519
14540
  view: raw.view ?? "main",
14520
14541
  componentName: resolveComponentName(raw.value, components),
14521
- requestHandlerNames: rh ? Object.keys(rh) : []
14542
+ requestHandlers: rh ?? null,
14543
+ requestHandlerNames: rh ? Object.keys(rh) : [],
14544
+ on: on ?? null
14522
14545
  });
14523
14546
  }
14524
14547
  function parseSection(raw, components, where) {
@@ -14612,7 +14635,10 @@ function findComponentNameConflicts(entries) {
14612
14635
  }
14613
14636
  return conflicts.sort((a, b) => a.name.localeCompare(b.name));
14614
14637
  }
14615
- var EXAMPLES_SHAPE_MISMATCH = "EXAMPLES_SHAPE_MISMATCH";
14638
+ var EXAMPLES_SHAPE_MISMATCH = "EXAMPLES_SHAPE_MISMATCH", PHASE_NAMES;
14639
+ var init_module = __esm(() => {
14640
+ PHASE_NAMES = ["init", "resume", "suspend"];
14641
+ });
14616
14642
 
14617
14643
  // tools/core/results.js
14618
14644
  class ModuleInfo {
@@ -14784,7 +14810,9 @@ function describeModule(mod, { path = null } = {}) {
14784
14810
  }
14785
14811
  return new ModuleInfo({ path, present, counts, warnings });
14786
14812
  }
14787
- var init_describe = () => {};
14813
+ var init_describe = __esm(() => {
14814
+ init_module();
14815
+ });
14788
14816
 
14789
14817
  // tools/core/docs.js
14790
14818
  function getSignature(name, fn) {
@@ -15822,6 +15850,7 @@ class App {
15822
15850
  this._compiled = false;
15823
15851
  this._renderOpts = { document: rootNode.ownerDocument };
15824
15852
  this._renderState = null;
15853
+ this.rootViewName = null;
15825
15854
  }
15826
15855
  get state() {
15827
15856
  return this.transactor.state;
@@ -15933,7 +15962,7 @@ class App {
15933
15962
  const root = this.state.val;
15934
15963
  const stack = this.makeStack(root);
15935
15964
  const { renderer, rootNode, _renderOpts, _renderState } = this;
15936
- const newState = render(renderer.renderRoot(stack, root), rootNode, _renderOpts, _renderState);
15965
+ const newState = render(renderer.renderRoot(stack, root, this.rootViewName), rootNode, _renderOpts, _renderState);
15937
15966
  this._renderState = newState;
15938
15967
  return newState.dom;
15939
15968
  }
@@ -16072,12 +16101,71 @@ var init_app = __esm(() => {
16072
16101
  _evs = "dragstart dragover dragend touchstart touchmove touchend touchcancel".split(" ");
16073
16102
  });
16074
16103
 
16104
+ // src/on.js
16105
+ function phaseOps(phase) {
16106
+ const ops = [];
16107
+ for (const type3 of OP_KINDS)
16108
+ for (const a of phase[type3] ?? [])
16109
+ ops.push({ type: type3, ...a });
16110
+ for (const a of phase.do ?? [])
16111
+ ops.push(a);
16112
+ return ops;
16113
+ }
16114
+ function resolveArgs(args, self) {
16115
+ return typeof args === "function" ? args(self) ?? [] : args ?? [];
16116
+ }
16117
+ function phaseHasBubble(phase) {
16118
+ if (!phase)
16119
+ return false;
16120
+ if (phase.bubble?.length)
16121
+ return true;
16122
+ return (phase.do ?? []).some((op) => op.type === "bubble");
16123
+ }
16124
+ function dispatchPhase(dispatcher, targetPath, phase, self) {
16125
+ if (!phase)
16126
+ return;
16127
+ for (const op of phaseOps(phase)) {
16128
+ const args = resolveArgs(op.args, self);
16129
+ switch (op.type) {
16130
+ case "send":
16131
+ dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
16132
+ break;
16133
+ case "bubble":
16134
+ dispatcher.sendAtPath(targetPath, op.name, args, {
16135
+ skipSelf: true,
16136
+ bubbles: true,
16137
+ ...op.opts
16138
+ });
16139
+ break;
16140
+ case "request":
16141
+ dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
16142
+ break;
16143
+ case "input":
16144
+ dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
16145
+ break;
16146
+ }
16147
+ }
16148
+ }
16149
+ var OP_KINDS;
16150
+ var init_on = __esm(() => {
16151
+ OP_KINDS = ["send", "bubble", "request", "input"];
16152
+ });
16153
+
16075
16154
  // src/util/render.js
16076
16155
  function reindexComponents(comps) {
16077
16156
  for (let i = 0;i < comps.length; i++) {
16078
16157
  comps[i].id = i;
16079
16158
  }
16080
16159
  }
16160
+ function serializeContainer(container) {
16161
+ for (const input of container.querySelectorAll("input")) {
16162
+ if (input.value)
16163
+ input.setAttribute("value", input.value);
16164
+ if (input.checked)
16165
+ input.setAttribute("checked", "");
16166
+ }
16167
+ return container.innerHTML;
16168
+ }
16081
16169
  function renderToHTMLNode(document2, components, macros, rootState, ParseContext2, opts = { noCache: true }) {
16082
16170
  const container = document2.createElement("div");
16083
16171
  document2.body.appendChild(container);
@@ -16088,14 +16176,11 @@ function renderToHTMLNode(document2, components, macros, rootState, ParseContext
16088
16176
  const scope = app.registerComponents(components);
16089
16177
  if (macros)
16090
16178
  scope.registerMacros(macros);
16179
+ if (opts.requestHandlers)
16180
+ scope.registerRequestHandlers(opts.requestHandlers);
16181
+ app.rootViewName = opts.view ?? null;
16091
16182
  app.transactor.state.set(rootState);
16092
16183
  app.start(opts);
16093
- for (const input of container.querySelectorAll("input")) {
16094
- if (input.value)
16095
- input.setAttribute("value", input.value);
16096
- if (input.checked)
16097
- input.setAttribute("checked", "");
16098
- }
16099
16184
  return {
16100
16185
  container,
16101
16186
  app,
@@ -16105,20 +16190,44 @@ function renderToHTMLNode(document2, components, macros, rootState, ParseContext
16105
16190
  }
16106
16191
  };
16107
16192
  }
16108
- function renderToHTML(document2, components, macros, rootState, ParseContext2) {
16109
- const { container, cleanup } = renderToHTMLNode(document2, components, macros, rootState, ParseContext2);
16110
- const html = container.innerHTML;
16111
- cleanup();
16112
- return html;
16193
+ async function renderToHTMLDriven(document2, components, macros, rootState, ParseContext2, { phase = null, requestHandlers = null, view = null, warn = console.warn } = {}) {
16194
+ const { container, app, cleanup } = renderToHTMLNode(document2, components, macros, rootState, ParseContext2, { noCache: true, requestHandlers, view });
16195
+ try {
16196
+ if (phase) {
16197
+ if (phaseHasBubble(phase))
16198
+ warn("render: a `bubble` action is a no-op here — the example's value is the render root, so there is no ancestor to receive it. Use send/request/input to drive a preset state.");
16199
+ dispatchPhase(rootDispatcher(app.transactor), new Path([]), phase, app.state.val);
16200
+ await app.transactor.settle();
16201
+ }
16202
+ return serializeContainer(container);
16203
+ } finally {
16204
+ cleanup();
16205
+ }
16113
16206
  }
16114
16207
  var init_render = __esm(() => {
16115
16208
  init_app();
16116
16209
  init_components();
16210
+ init_on();
16211
+ init_path();
16117
16212
  init_renderer();
16213
+ init_transactor();
16118
16214
  });
16119
16215
 
16120
16216
  // tools/core/render.js
16121
- function renderExamples(normalized, env, { name = null, title = null, view = null } = {}) {
16217
+ function checkView2(value, components, viewName) {
16218
+ if (viewName === "main")
16219
+ return null;
16220
+ const comp = components.find((c) => value instanceof c.Class);
16221
+ if (!comp || comp.views[viewName])
16222
+ return null;
16223
+ const known = Object.keys(comp.views).sort().join(", ");
16224
+ return new Error(`view "${viewName}" is not defined on ${comp.name} (has: ${known})`);
16225
+ }
16226
+ function handlersFor(normalized, example) {
16227
+ const merged = { ...normalized.requestHandlers ?? {}, ...example.requestHandlers ?? {} };
16228
+ return Object.keys(merged).length > 0 ? merged : null;
16229
+ }
16230
+ async function renderExamples(normalized, env, { name = null, title = null, view = null } = {}) {
16122
16231
  const sections = [];
16123
16232
  for (const section of normalized.sections) {
16124
16233
  const items = [];
@@ -16132,7 +16241,14 @@ function renderExamples(normalized, env, { name = null, title = null, view = nul
16132
16241
  let html = "";
16133
16242
  let error = null;
16134
16243
  try {
16135
- html = renderToHTML(env.document, normalized.components, normalized.macros, example.value, env.ParseContext);
16244
+ const bad = checkView2(example.value, normalized.components, viewName);
16245
+ if (bad)
16246
+ throw bad;
16247
+ html = await renderToHTMLDriven(env.document, normalized.components, normalized.macros, example.value, env.ParseContext, {
16248
+ phase: example.on?.init ?? null,
16249
+ requestHandlers: handlersFor(normalized, example),
16250
+ view: viewName
16251
+ });
16136
16252
  } catch (e) {
16137
16253
  error = { message: e.message, stack: e.stack };
16138
16254
  }
@@ -16159,56 +16275,6 @@ var init_render2 = __esm(() => {
16159
16275
  init_render();
16160
16276
  });
16161
16277
 
16162
- // src/on.js
16163
- function phaseOps(phase) {
16164
- const ops = [];
16165
- for (const type3 of OP_KINDS)
16166
- for (const a of phase[type3] ?? [])
16167
- ops.push({ type: type3, ...a });
16168
- for (const a of phase.do ?? [])
16169
- ops.push(a);
16170
- return ops;
16171
- }
16172
- function resolveArgs(args, self) {
16173
- return typeof args === "function" ? args(self) ?? [] : args ?? [];
16174
- }
16175
- function phaseHasBubble(phase) {
16176
- if (!phase)
16177
- return false;
16178
- if (phase.bubble?.length)
16179
- return true;
16180
- return (phase.do ?? []).some((op) => op.type === "bubble");
16181
- }
16182
- function dispatchPhase(dispatcher, targetPath, phase, self) {
16183
- if (!phase)
16184
- return;
16185
- for (const op of phaseOps(phase)) {
16186
- const args = resolveArgs(op.args, self);
16187
- switch (op.type) {
16188
- case "send":
16189
- dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
16190
- break;
16191
- case "bubble":
16192
- dispatcher.sendAtPath(targetPath, op.name, args, {
16193
- skipSelf: true,
16194
- bubbles: true,
16195
- ...op.opts
16196
- });
16197
- break;
16198
- case "request":
16199
- dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
16200
- break;
16201
- case "input":
16202
- dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
16203
- break;
16204
- }
16205
- }
16206
- }
16207
- var OP_KINDS;
16208
- var init_on = __esm(() => {
16209
- OP_KINDS = ["send", "bubble", "request", "input"];
16210
- });
16211
-
16212
16278
  // tools/core/tests.js
16213
16279
  class Describe {
16214
16280
  constructor({ title, componentName = null, parent = null }) {
@@ -17689,6 +17755,7 @@ async function run5(argv, opts = {}) {
17689
17755
  var describe5 = "Serve a storybook for the project's co-located *.dev.js modules (auto-discovered).", BOOTSTRAP_URL = "/__tutuca_storybook__.js", DIST_PREFIX = "/__tutuca__/", MARGAUI_PREFIX = "/__margaui__/", MIME, MARGAUI_CDN = "https://cdn.jsdelivr.net/npm/margaui/+esm", MARGAUI_THEME = "https://marianoguerra.github.io/margaui/themes/theme.css";
17690
17756
  var init_storybook = __esm(() => {
17691
17757
  init_chai2();
17758
+ init_module();
17692
17759
  init_test();
17693
17760
  init_env2();
17694
17761
  init_errors();
@@ -17867,6 +17934,7 @@ import { statSync as statSync2 } from "node:fs";
17867
17934
  import { parseArgs as parseArgs4 } from "node:util";
17868
17935
 
17869
17936
  // tools/cli/load.js
17937
+ init_module();
17870
17938
  import { existsSync as existsSync4 } from "node:fs";
17871
17939
  import { resolve as resolve6 } from "node:path";
17872
17940
  async function loadAndNormalize(modulePath) {
@@ -7645,6 +7645,7 @@ class App {
7645
7645
  this._compiled = false;
7646
7646
  this._renderOpts = { document: rootNode.ownerDocument };
7647
7647
  this._renderState = null;
7648
+ this.rootViewName = null;
7648
7649
  }
7649
7650
  get state() {
7650
7651
  return this.transactor.state;
@@ -7756,7 +7757,7 @@ class App {
7756
7757
  const root = this.state.val;
7757
7758
  const stack = this.makeStack(root);
7758
7759
  const { renderer, rootNode, _renderOpts, _renderState } = this;
7759
- const newState = render(renderer.renderRoot(stack, root), rootNode, _renderOpts, _renderState);
7760
+ const newState = render(renderer.renderRoot(stack, root, this.rootViewName), rootNode, _renderOpts, _renderState);
7760
7761
  this._renderState = newState;
7761
7762
  return newState.dom;
7762
7763
  }
@@ -15294,6 +15294,7 @@ class App {
15294
15294
  this._compiled = false;
15295
15295
  this._renderOpts = { document: rootNode.ownerDocument };
15296
15296
  this._renderState = null;
15297
+ this.rootViewName = null;
15297
15298
  }
15298
15299
  get state() {
15299
15300
  return this.transactor.state;
@@ -15405,7 +15406,7 @@ class App {
15405
15406
  const root = this.state.val;
15406
15407
  const stack = this.makeStack(root);
15407
15408
  const { renderer, rootNode, _renderOpts, _renderState } = this;
15408
- const newState = render(renderer.renderRoot(stack, root), rootNode, _renderOpts, _renderState);
15409
+ const newState = render(renderer.renderRoot(stack, root, this.rootViewName), rootNode, _renderOpts, _renderState);
15409
15410
  this._renderState = newState;
15410
15411
  return newState.dom;
15411
15412
  }