tutuca 0.9.115 → 0.11.0

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 (53) hide show
  1. package/README.md +16 -16
  2. package/dist/immer.js +1261 -0
  3. package/dist/tutuca-cli.js +2056 -4798
  4. package/dist/tutuca-components.js +206 -442
  5. package/dist/tutuca-dev.ext.js +878 -944
  6. package/dist/tutuca-dev.js +1679 -5298
  7. package/dist/tutuca-dev.min.js +5 -5
  8. package/dist/tutuca-extra.ext.js +740 -695
  9. package/dist/tutuca-extra.js +1403 -4925
  10. package/dist/tutuca-extra.min.js +3 -3
  11. package/dist/tutuca-storybook.js +226 -210
  12. package/dist/tutuca.ext.js +740 -695
  13. package/dist/tutuca.js +1403 -4925
  14. package/dist/tutuca.min.js +3 -3
  15. package/package.json +7 -11
  16. package/skill/tutuca/SKILL.md +4 -8
  17. package/skill/tutuca/advanced.md +13 -5
  18. package/skill/tutuca/cli.md +8 -9
  19. package/skill/tutuca/component-design.md +50 -47
  20. package/skill/tutuca/core.md +134 -117
  21. package/skill/tutuca/iteration.md +2 -2
  22. package/skill/tutuca/macros.md +1 -1
  23. package/skill/tutuca/messages-and-intents.md +399 -0
  24. package/skill/tutuca/patterns/README.md +1 -1
  25. package/skill/tutuca/patterns/add-a-story.md +2 -2
  26. package/skill/tutuca/patterns/bind-text-and-attributes.md +1 -1
  27. package/skill/tutuca/patterns/conditional-attribute-value.md +1 -1
  28. package/skill/tutuca/patterns/coordinate-components.md +41 -18
  29. package/skill/tutuca/patterns/file-input.md +8 -8
  30. package/skill/tutuca/patterns/filter-and-paginate.md +1 -1
  31. package/skill/tutuca/patterns/handle-events.md +11 -9
  32. package/skill/tutuca/patterns/switch-between-views.md +1 -1
  33. package/skill/tutuca/patterns/tabbed-interface.md +10 -5
  34. package/skill/tutuca/semantics.md +41 -35
  35. package/skill/tutuca/storybook.md +34 -27
  36. package/skill/tutuca/testing.md +75 -64
  37. package/skill/tutuca-source/tutuca.ext.js +740 -695
  38. package/dist/immutable.js +0 -4331
  39. package/skill/immutable-js/SKILL.md +0 -78
  40. package/skill/immutable-js/references/collection.md +0 -346
  41. package/skill/immutable-js/references/conversions.md +0 -99
  42. package/skill/immutable-js/references/deep-updates.md +0 -172
  43. package/skill/immutable-js/references/equality.md +0 -95
  44. package/skill/immutable-js/references/list.md +0 -266
  45. package/skill/immutable-js/references/map.md +0 -300
  46. package/skill/immutable-js/references/predicates.md +0 -93
  47. package/skill/immutable-js/references/range-repeat.md +0 -55
  48. package/skill/immutable-js/references/record.md +0 -196
  49. package/skill/immutable-js/references/seq.md +0 -248
  50. package/skill/immutable-js/references/set.md +0 -270
  51. package/skill/immutable-js/references/shallow-functional.md +0 -99
  52. package/skill/immutable-js/references/stack.md +0 -210
  53. package/skill/tutuca/request-response.md +0 -341
@@ -1,8 +1,5 @@
1
1
  // src/components/data/data.js
2
- import { component as component3, html as html3 } from "tutuca";
3
-
4
- // src/components/data/immutable-inspector.js
5
- import { component as component2, html as html2, IMap, ISet, List, OMap, OrderedSet, Record, Seq, Stack } from "tutuca";
2
+ import { component as component2, html as html2 } from "tutuca";
6
3
 
7
4
  // src/components/data/json.js
8
5
  import { component, html } from "tutuca";
@@ -72,19 +69,19 @@ var compositeMethods = {
72
69
  return this.isExpanded ? "▼" : "▶";
73
70
  },
74
71
  isItemsEmpty() {
75
- return this.items.size === 0;
72
+ return this.items.length === 0;
76
73
  },
77
74
  pageCount() {
78
- return Math.max(1, Math.ceil(this.items.size / this.itemsPerPage));
75
+ return Math.max(1, Math.ceil(this.items.length / this.itemsPerPage));
79
76
  },
80
77
  pageStart() {
81
78
  return this.currentPage * this.itemsPerPage;
82
79
  },
83
80
  pageEnd() {
84
- return Math.min(this.items.size, this.pageStart() + this.itemsPerPage);
81
+ return Math.min(this.items.length, this.pageStart() + this.itemsPerPage);
85
82
  },
86
83
  hasPagination() {
87
- return this.items.size > this.itemsPerPage;
84
+ return this.items.length > this.itemsPerPage;
88
85
  },
89
86
  showPagination() {
90
87
  return this.isExpanded && this.hasPagination();
@@ -97,12 +94,18 @@ var compositeMethods = {
97
94
  },
98
95
  pageIndicatorText() {
99
96
  return `${this.currentPage + 1} / ${this.pageCount()}`;
97
+ }
98
+ };
99
+ var compositeReceive = {
100
+ toggleIsExpanded(draft) {
101
+ draft.isExpanded = !draft.isExpanded;
100
102
  },
101
- prevPage() {
102
- return this.currentPage > 0 ? this.setCurrentPage(this.currentPage - 1) : this;
103
+ prevPage(draft) {
104
+ if (draft.currentPage > 0) draft.currentPage--;
103
105
  },
104
- nextPage() {
105
- return this.currentPage < this.pageCount() - 1 ? this.setCurrentPage(this.currentPage + 1) : this;
106
+ nextPage(draft) {
107
+ const pageCount = Math.max(1, Math.ceil(draft.items.length / draft.itemsPerPage));
108
+ if (draft.currentPage < pageCount - 1) draft.currentPage++;
106
109
  }
107
110
  };
108
111
  var compositeAlter = {
@@ -113,7 +116,7 @@ var compositeAlter = {
113
116
  function makeCompositeView({
114
117
  typeClass = "",
115
118
  borderClass = "border-base-content/10",
116
- toggleHandler = "$toggleIsExpanded"
119
+ toggleHandler = "toggleIsExpanded"
117
120
  } = {}) {
118
121
  return html`<span class="font-mono text-sm leading-tight inline-block">
119
122
  <span class="inline-flex items-center gap-2">
@@ -132,7 +135,7 @@ function makeCompositeView({
132
135
  type="button"
133
136
  class="join-item btn btn-xs"
134
137
  :disabled="$cannotPrevPage"
135
- @on.click="$prevPage"
138
+ @on.click="prevPage"
136
139
  >
137
140
  «
138
141
  </button>
@@ -144,7 +147,7 @@ function makeCompositeView({
144
147
  type="button"
145
148
  class="join-item btn btn-xs"
146
149
  :disabled="$cannotNextPage"
147
- @on.click="$nextPage"
150
+ @on.click="nextPage"
148
151
  >
149
152
  »
150
153
  </button>
@@ -168,9 +171,10 @@ var JsonArray = component({
168
171
  return "Array";
169
172
  },
170
173
  countText() {
171
- return `(${this.items.size})`;
174
+ return `(${this.items.length})`;
172
175
  }
173
176
  },
177
+ receive: compositeReceive,
174
178
  alter: compositeAlter,
175
179
  view: compositeView
176
180
  });
@@ -183,9 +187,10 @@ var JsonObject = component({
183
187
  return "Object";
184
188
  },
185
189
  countText() {
186
- return `{${this.items.size}}`;
190
+ return `{${this.items.length}}`;
187
191
  }
188
192
  },
193
+ receive: compositeReceive,
189
194
  alter: compositeAlter,
190
195
  view: compositeView
191
196
  });
@@ -201,11 +206,7 @@ var JsonProperty = component({
201
206
  <x render=".child"></x>
202
207
  </div>`
203
208
  });
204
- var valueWrapperMethods = {
205
- toggleIsExpanded() {
206
- return typeof this.value?.toggleIsExpanded === "function" ? this.setValue(this.value.toggleIsExpanded()) : this;
207
- }
208
- };
209
+ var valueWrapperMethods = {};
209
210
  var valueWrapperView = html`<span class="contents"><x render=".value"></x></span>`;
210
211
  function makeValueInspector({ name, fromData }) {
211
212
  return component({
@@ -272,11 +273,7 @@ function getComponents() {
272
273
  ];
273
274
  }
274
275
 
275
- // src/components/data/immutable-inspector.js
276
- var immutableContainerView = makeCompositeView({
277
- typeClass: "text-accent",
278
- borderClass: "border-accent"
279
- });
276
+ // src/components/data/data.js
280
277
  function fmtAnyKey(k) {
281
278
  if (k === null) return "null";
282
279
  if (k === void 0) return "undefined";
@@ -288,232 +285,18 @@ function fmtAnyKey(k) {
288
285
  if (k instanceof Map) return `Map(${k.size})`;
289
286
  if (k instanceof Set) return `Set(${k.size})`;
290
287
  if (k instanceof Date) return k.toISOString();
291
- if (List.isList(k)) return `List[${k.size}]`;
292
- if (OMap.isOrderedMap(k)) return `OrderedMap[${k.size}]`;
293
- if (IMap.isMap(k)) return `Map[${k.size}]`;
294
- if (OrderedSet.isOrderedSet(k)) return `OrderedSet[${k.size}]`;
295
- if (ISet.isSet(k)) return `Set[${k.size}]`;
296
288
  const ctor = k.constructor?.name;
297
289
  return ctor && ctor !== "Object" ? `${ctor} {…}` : Object.prototype.toString.call(k);
298
290
  }
299
- var fromIndexedData = {
300
- fromData(coll, recurse) {
301
- const items = coll.toArray().map((v, i) => ImEntry.make({ key: String(i), child: recurse(v) }));
302
- return this.make({ items });
303
- }
304
- };
305
- var fromKeyedData = {
306
- fromData(map, recurse) {
307
- const items = [];
308
- map.forEach((v, k) => {
309
- items.push(ImEntry.make({ key: fmtAnyKey(k), child: recurse(v) }));
310
- });
311
- return this.make({ items });
312
- }
313
- };
314
- var fromSetData = {
315
- fromData(set, recurse) {
316
- const items = set.toArray().map((v) => ImEntry.make({ key: "", showKey: false, child: recurse(v) }));
317
- return this.make({ items });
318
- }
319
- };
320
- var ImEntry = component2({
321
- name: "ImEntry",
322
- fields: { key: "", child: null, showKey: true },
323
- view: html2`<div class="flex items-center gap-2 leading-tight">
324
- <span
325
- @show=".showKey"
326
- class="text-base-content/60 font-mono text-sm"
327
- @text=".key"
328
- ></span>
329
- <span @show=".showKey" class="text-base-content/30">:</span>
330
- <x render=".child"></x>
331
- </div>`
332
- });
333
- var ImList = component2({
334
- name: "ImList",
335
- fields: compositeFields,
336
- methods: {
337
- ...compositeMethods,
338
- typeText() {
339
- return "List";
340
- },
341
- countText() {
342
- return `[${this.items.size}]`;
343
- }
344
- },
345
- alter: compositeAlter,
346
- statics: fromIndexedData,
347
- view: immutableContainerView
348
- });
349
- var ImStack = component2({
350
- name: "ImStack",
351
- fields: compositeFields,
352
- methods: {
353
- ...compositeMethods,
354
- typeText() {
355
- return "Stack";
356
- },
357
- countText() {
358
- return `[${this.items.size}]`;
359
- }
360
- },
361
- alter: compositeAlter,
362
- statics: fromIndexedData,
363
- view: immutableContainerView
364
- });
365
- var ImMap = component2({
366
- name: "ImMap",
367
- fields: compositeFields,
368
- methods: {
369
- ...compositeMethods,
370
- typeText() {
371
- return "Map";
372
- },
373
- countText() {
374
- return `{${this.items.size}}`;
375
- }
376
- },
377
- alter: compositeAlter,
378
- statics: fromKeyedData,
379
- view: immutableContainerView
380
- });
381
- var ImOMap = component2({
382
- name: "ImOMap",
383
- fields: compositeFields,
384
- methods: {
385
- ...compositeMethods,
386
- typeText() {
387
- return "OrderedMap";
388
- },
389
- countText() {
390
- return `{${this.items.size}}`;
391
- }
392
- },
393
- alter: compositeAlter,
394
- statics: fromKeyedData,
395
- view: immutableContainerView
396
- });
397
- var ImSet = component2({
398
- name: "ImSet",
399
- fields: compositeFields,
400
- methods: {
401
- ...compositeMethods,
402
- typeText() {
403
- return "Set";
404
- },
405
- countText() {
406
- return `{${this.items.size}}`;
407
- }
408
- },
409
- alter: compositeAlter,
410
- statics: fromSetData,
411
- view: immutableContainerView
412
- });
413
- var ImOSet = component2({
414
- name: "ImOSet",
415
- fields: compositeFields,
416
- methods: {
417
- ...compositeMethods,
418
- typeText() {
419
- return "OrderedSet";
420
- },
421
- countText() {
422
- return `{${this.items.size}}`;
423
- }
424
- },
425
- alter: compositeAlter,
426
- statics: fromSetData,
427
- view: immutableContainerView
428
- });
429
- var ImRecord = component2({
430
- name: "ImRecord",
431
- fields: { ...compositeFields, recordName: "" },
432
- methods: {
433
- ...compositeMethods,
434
- typeText() {
435
- return this.recordName ? `Record ${this.recordName}` : "Record";
436
- },
437
- countText() {
438
- return `{${this.items.size}}`;
439
- }
440
- },
441
- alter: compositeAlter,
442
- statics: {
443
- fromData(rec, recurse) {
444
- const recordName = rec._name || rec.constructor.name || "Record";
445
- const items = [];
446
- rec.toSeq().forEach((v, k) => {
447
- items.push(ImEntry.make({ key: String(k), child: recurse(v) }));
448
- });
449
- return this.make({ recordName, items });
450
- }
451
- },
452
- view: immutableContainerView
453
- });
454
- var ImRange = component2({
455
- name: "ImRange",
456
- fields: { rangeText: "" },
457
- statics: {
458
- fromData(seq) {
459
- const { _start: start, _end: end, _step: step } = seq;
460
- const rangeText = step === 1 ? `${start}…${end}` : `${start}…${end} by ${step}`;
461
- return this.make({ rangeText });
462
- }
463
- },
464
- view: html2`<span
465
- class="font-mono text-sm leading-tight inline-flex items-center gap-1"
466
- >
467
- <span class="font-mono text-accent">Range</span>
468
- <span class="text-base-content/70" @text=".rangeText"></span>
469
- </span>`
470
- });
471
- var ImInspector = makeValueInspector({
472
- name: "ImInspector",
473
- fromData(data) {
474
- return this.make({ value: dispatch(data) });
475
- }
476
- });
477
- function classifyImmutable(data, recurse) {
478
- if (Seq.isSeq(data) && data._start !== void 0 && data._end !== void 0 && data._step !== void 0) {
479
- return ImRange.Class.fromData(data, recurse);
480
- }
481
- if (Record.isRecord(data)) return ImRecord.Class.fromData(data, recurse);
482
- if (List.isList(data)) return ImList.Class.fromData(data, recurse);
483
- if (Stack.isStack(data)) return ImStack.Class.fromData(data, recurse);
484
- if (OMap.isOrderedMap(data)) return ImOMap.Class.fromData(data, recurse);
485
- if (IMap.isMap(data)) return ImMap.Class.fromData(data, recurse);
486
- if (OrderedSet.isOrderedSet(data)) return ImOSet.Class.fromData(data, recurse);
487
- if (ISet.isSet(data)) return ImSet.Class.fromData(data, recurse);
488
- return null;
489
- }
490
- var dispatch = chain(classifyImmutable, classifyData);
491
- function getComponents2() {
492
- return [
493
- ImInspector,
494
- ImEntry,
495
- ImList,
496
- ImStack,
497
- ImMap,
498
- ImOMap,
499
- ImSet,
500
- ImOSet,
501
- ImRecord,
502
- ImRange,
503
- ...getComponents()
504
- ];
505
- }
506
-
507
- // src/components/data/data.js
508
- var JsUndefined = component3({
291
+ var JsUndefined = component2({
509
292
  name: "JsUndefined",
510
293
  fields: {},
511
- view: html3`<span
294
+ view: html2`<span
512
295
  class="font-mono text-sm leading-tight text-warning italic"
513
296
  >undefined</span
514
297
  >`
515
298
  });
516
- var JsBigInt = component3({
299
+ var JsBigInt = component2({
517
300
  name: "JsBigInt",
518
301
  fields: { value: "" },
519
302
  methods: {
@@ -521,21 +304,21 @@ var JsBigInt = component3({
521
304
  return `${this.value}n`;
522
305
  }
523
306
  },
524
- view: html3`<span
307
+ view: html2`<span
525
308
  class="font-mono text-sm leading-tight text-info"
526
309
  @text="$text"
527
310
  ></span>`
528
311
  });
529
- var JsSymbol = component3({
312
+ var JsSymbol = component2({
530
313
  name: "JsSymbol",
531
314
  fields: { description: "" },
532
- view: html3`<span class="font-mono text-sm leading-tight"
315
+ view: html2`<span class="font-mono text-sm leading-tight"
533
316
  ><span class="text-info">Symbol</span
534
317
  ><span class="text-base-content/40">: </span
535
318
  ><span @text=".description"></span
536
319
  ></span>`
537
320
  });
538
- var JsFunction = component3({
321
+ var JsFunction = component2({
539
322
  name: "JsFunction",
540
323
  fields: { name: "", kind: "function" },
541
324
  methods: {
@@ -552,7 +335,7 @@ var JsFunction = component3({
552
335
  return "() { … }";
553
336
  }
554
337
  },
555
- view: html3`<span class="font-mono text-sm leading-tight"
338
+ view: html2`<span class="font-mono text-sm leading-tight"
556
339
  ><span class="text-base-content/40" @text="$prefixText"></span
557
340
  ><span
558
341
  class="text-info"
@@ -566,27 +349,27 @@ var JsFunction = component3({
566
349
  ></span
567
350
  ></span>`
568
351
  });
569
- var JsDate = component3({
352
+ var JsDate = component2({
570
353
  name: "JsDate",
571
354
  fields: { value: "" },
572
- view: html3`<span class="font-mono text-sm leading-tight"
355
+ view: html2`<span class="font-mono text-sm leading-tight"
573
356
  ><span class="text-info">Date</span
574
357
  ><span class="text-base-content/40">: </span
575
358
  ><span @text=".value"></span
576
359
  ></span>`
577
360
  });
578
- var JsRegExp = component3({
361
+ var JsRegExp = component2({
579
362
  name: "JsRegExp",
580
363
  fields: { value: "" },
581
- view: html3`<span
364
+ view: html2`<span
582
365
  class="font-mono text-sm leading-tight text-error"
583
366
  @text=".value"
584
367
  ></span>`
585
368
  });
586
- var JsError = component3({
369
+ var JsError = component2({
587
370
  name: "JsError",
588
371
  fields: { errorName: "Error", message: "" },
589
- view: html3`<span class="font-mono text-sm leading-tight"
372
+ view: html2`<span class="font-mono text-sm leading-tight"
590
373
  ><span class="text-info" @text=".errorName"></span
591
374
  ><span class="text-base-content/40">: </span
592
375
  ><span
@@ -596,14 +379,14 @@ var JsError = component3({
596
379
  ></span
597
380
  ></span>`
598
381
  });
599
- var JsSetItem = component3({
382
+ var JsSetItem = component2({
600
383
  name: "JsSetItem",
601
384
  fields: { child: null },
602
- view: html3`<div class="flex items-center gap-2 leading-tight">
385
+ view: html2`<div class="flex items-center gap-2 leading-tight">
603
386
  <x render=".child"></x>
604
387
  </div>`
605
388
  });
606
- var JsMap = component3({
389
+ var JsMap = component2({
607
390
  name: "JsMap",
608
391
  fields: compositeFields,
609
392
  methods: {
@@ -612,9 +395,10 @@ var JsMap = component3({
612
395
  return "Map";
613
396
  },
614
397
  countText() {
615
- return `(${this.items.size})`;
398
+ return `(${this.items.length})`;
616
399
  }
617
400
  },
401
+ receive: compositeReceive,
618
402
  alter: compositeAlter,
619
403
  statics: {
620
404
  fromData(map, recurse) {
@@ -627,7 +411,7 @@ var JsMap = component3({
627
411
  },
628
412
  view: compositeView
629
413
  });
630
- var JsSet = component3({
414
+ var JsSet = component2({
631
415
  name: "JsSet",
632
416
  fields: compositeFields,
633
417
  methods: {
@@ -636,9 +420,10 @@ var JsSet = component3({
636
420
  return "Set";
637
421
  },
638
422
  countText() {
639
- return `(${this.items.size})`;
423
+ return `(${this.items.length})`;
640
424
  }
641
425
  },
426
+ receive: compositeReceive,
642
427
  alter: compositeAlter,
643
428
  statics: {
644
429
  fromData(set, recurse) {
@@ -648,7 +433,7 @@ var JsSet = component3({
648
433
  },
649
434
  view: compositeView
650
435
  });
651
- var JsClassInstance = component3({
436
+ var JsClassInstance = component2({
652
437
  name: "JsClassInstance",
653
438
  fields: { ...compositeFields, className: "Object" },
654
439
  methods: {
@@ -657,9 +442,10 @@ var JsClassInstance = component3({
657
442
  return this.className;
658
443
  },
659
444
  countText() {
660
- return `{${this.items.size}}`;
445
+ return `{${this.items.length}}`;
661
446
  }
662
447
  },
448
+ receive: compositeReceive,
663
449
  alter: compositeAlter,
664
450
  statics: {
665
451
  fromData(obj, recurse) {
@@ -704,14 +490,14 @@ function classifyJsExtra(data, recurse) {
704
490
  }
705
491
  return null;
706
492
  }
707
- var dispatch2 = chain(classifyImmutable, classifyJsExtra, classifyJson);
493
+ var dispatch = chain(classifyJsExtra, classifyJson);
708
494
  var DataInspector = makeValueInspector({
709
495
  name: "DataInspector",
710
496
  fromData(data) {
711
- return this.make({ value: dispatch2(data) });
497
+ return this.make({ value: dispatch(data) });
712
498
  }
713
499
  });
714
- function getComponents3() {
500
+ function getComponents2() {
715
501
  return [
716
502
  DataInspector,
717
503
  JsUndefined,
@@ -725,12 +511,12 @@ function getComponents3() {
725
511
  JsSet,
726
512
  JsClassInstance,
727
513
  JsSetItem,
728
- ...getComponents2()
514
+ ...getComponents()
729
515
  ];
730
516
  }
731
517
 
732
518
  // src/components/data/json-schema.js
733
- import { component as component4, html as html4 } from "tutuca";
519
+ import { component as component3, html as html3 } from "tutuca";
734
520
  var schemaNodeFields = {
735
521
  ...compositeFields,
736
522
  typeLabel: "",
@@ -748,27 +534,27 @@ function schemaNodeMethods(extra = {}) {
748
534
  ...extra
749
535
  };
750
536
  }
751
- var GRID_BODY = html4`<div
537
+ var GRID_BODY = html3`<div
752
538
  @show=".isExpanded"
753
539
  class="ml-1 grid gap-x-2 gap-y-0.5 items-baseline border-l border-base-content/10 pl-2 mt-0.5"
754
540
  style="grid-template-columns: auto 1fr"
755
541
  >
756
542
  <x render-each=".items" @loop-with="getPageRange"></x>
757
543
  </div>`;
758
- var LIST_BODY = html4`<div
544
+ var LIST_BODY = html3`<div
759
545
  @show=".isExpanded"
760
546
  class="ml-1 flex flex-col gap-0.5 border-l border-base-content/10 pl-2 mt-0.5"
761
547
  >
762
548
  <x render-each=".items" @loop-with="getPageRange"></x>
763
549
  </div>`;
764
550
  function makeSchemaView(accent, body = GRID_BODY) {
765
- return html4`<span class="font-mono text-sm leading-tight inline-block">
551
+ return html3`<span class="font-mono text-sm leading-tight inline-block">
766
552
  <span class="inline-flex items-center gap-2 flex-wrap">
767
553
  <button
768
554
  type="button"
769
555
  class="cursor-pointer text-base-content/70 hover:text-base-content inline-flex items-center gap-1"
770
556
  :disabled="$isItemsEmpty"
771
- @on.click="$toggleIsExpanded"
557
+ @on.click="toggleIsExpanded"
772
558
  >
773
559
  <span @hide="$isItemsEmpty" @text="$arrowText"></span>
774
560
  <span class="${accent} font-semibold" @text="$typeText"></span>
@@ -787,7 +573,7 @@ function makeSchemaView(accent, body = GRID_BODY) {
787
573
  type="button"
788
574
  class="join-item btn btn-xs"
789
575
  :disabled="$cannotPrevPage"
790
- @on.click="$prevPage"
576
+ @on.click="prevPage"
791
577
  >
792
578
  «
793
579
  </button>
@@ -799,7 +585,7 @@ function makeSchemaView(accent, body = GRID_BODY) {
799
585
  type="button"
800
586
  class="join-item btn btn-xs"
801
587
  :disabled="$cannotNextPage"
802
- @on.click="$nextPage"
588
+ @on.click="nextPage"
803
589
  >
804
590
  »
805
591
  </button>
@@ -925,12 +711,12 @@ function collectExtras(schema, recurse, primary) {
925
711
  }
926
712
  return rows;
927
713
  }
928
- var SchemaProperty = component4({
714
+ var SchemaProperty = component3({
929
715
  name: "SchemaProperty",
930
716
  fields: { key: "", child: null, required: false },
931
717
  // `contents` so the key cell and value cell land directly in the parent's
932
718
  // grid, aligning values across rows.
933
- view: html4`<div class="contents">
719
+ view: html3`<div class="contents">
934
720
  <span class="font-mono text-sm flex items-center gap-1 leading-tight">
935
721
  <span class="text-base-content/60" @text=".key"></span>
936
722
  <span @show=".required" class="text-error font-bold" title="required"
@@ -941,7 +727,7 @@ var SchemaProperty = component4({
941
727
  <x render=".child"></x>
942
728
  </div>`
943
729
  });
944
- var SchemaBranch = component4({
730
+ var SchemaBranch = component3({
945
731
  name: "SchemaBranch",
946
732
  fields: { label: "", child: null, labelClass: "text-accent" },
947
733
  methods: {
@@ -951,7 +737,7 @@ var SchemaBranch = component4({
951
737
  },
952
738
  // `contents` so the label cell and value cell land directly in the parent's
953
739
  // grid, aligning values across rows.
954
- view: html4`<div class="contents">
740
+ view: html3`<div class="contents">
955
741
  <span class="flex items-center gap-1 leading-tight">
956
742
  <span :class="$labelCssClass" @text=".label"></span>
957
743
  <span class="text-base-content/30">:</span>
@@ -961,12 +747,12 @@ var SchemaBranch = component4({
961
747
  views: {
962
748
  // Decoy: labelClass colours are chosen in JS, so they never appear as
963
749
  // literals for the margaui scanner.
964
- _margauiClasses: html4`<p
750
+ _margauiClasses: html3`<p
965
751
  class="text-accent text-secondary text-info text-error"
966
752
  ></p>`
967
753
  }
968
754
  });
969
- var SchemaScalar = component4({
755
+ var SchemaScalar = component3({
970
756
  name: "SchemaScalar",
971
757
  fields: schemaNodeFields,
972
758
  methods: schemaNodeMethods({
@@ -974,6 +760,7 @@ var SchemaScalar = component4({
974
760
  return "";
975
761
  }
976
762
  }),
763
+ receive: compositeReceive,
977
764
  alter: compositeAlter,
978
765
  statics: {
979
766
  fromData(schema, recurse) {
@@ -987,14 +774,15 @@ var SchemaScalar = component4({
987
774
  },
988
775
  view: makeSchemaView("text-success")
989
776
  });
990
- var SchemaObject = component4({
777
+ var SchemaObject = component3({
991
778
  name: "SchemaObject",
992
779
  fields: schemaNodeFields,
993
780
  methods: schemaNodeMethods({
994
781
  countText() {
995
- return this.items.size > 0 ? `{${this.items.size}}` : "";
782
+ return this.items.length > 0 ? `{${this.items.length}}` : "";
996
783
  }
997
784
  }),
785
+ receive: compositeReceive,
998
786
  alter: compositeAlter,
999
787
  statics: {
1000
788
  fromData(schema, recurse) {
@@ -1051,14 +839,15 @@ var SchemaObject = component4({
1051
839
  },
1052
840
  view: makeSchemaView("text-primary")
1053
841
  });
1054
- var SchemaArray = component4({
842
+ var SchemaArray = component3({
1055
843
  name: "SchemaArray",
1056
844
  fields: schemaNodeFields,
1057
845
  methods: schemaNodeMethods({
1058
846
  countText() {
1059
- return this.items.size > 0 ? `[${this.items.size}]` : "";
847
+ return this.items.length > 0 ? `[${this.items.length}]` : "";
1060
848
  }
1061
849
  }),
850
+ receive: compositeReceive,
1062
851
  alter: compositeAlter,
1063
852
  statics: {
1064
853
  fromData(schema, recurse) {
@@ -1097,14 +886,15 @@ var SchemaArray = component4({
1097
886
  },
1098
887
  view: makeSchemaView("text-primary")
1099
888
  });
1100
- var SchemaEnum = component4({
889
+ var SchemaEnum = component3({
1101
890
  name: "SchemaEnum",
1102
891
  fields: schemaNodeFields,
1103
892
  methods: schemaNodeMethods({
1104
893
  countText() {
1105
- return this.items.size > 0 ? `(${this.items.size})` : "";
894
+ return this.items.length > 0 ? `(${this.items.length})` : "";
1106
895
  }
1107
896
  }),
897
+ receive: compositeReceive,
1108
898
  alter: compositeAlter,
1109
899
  statics: {
1110
900
  fromData(schema, recurse) {
@@ -1122,7 +912,7 @@ var SchemaEnum = component4({
1122
912
  // list layout: each enum member is a single value rendered one per line.
1123
913
  view: makeSchemaView("text-info", LIST_BODY)
1124
914
  });
1125
- var SchemaConst = component4({
915
+ var SchemaConst = component3({
1126
916
  name: "SchemaConst",
1127
917
  fields: { value: null },
1128
918
  statics: {
@@ -1130,7 +920,7 @@ var SchemaConst = component4({
1130
920
  return this.make({ value: JsonViewer.Class.fromData(schema.const) });
1131
921
  }
1132
922
  },
1133
- view: html4`<span
923
+ view: html3`<span
1134
924
  class="font-mono text-sm leading-tight inline-flex items-center gap-2"
1135
925
  >
1136
926
  <span class="text-info font-semibold">const</span>
@@ -1138,14 +928,15 @@ var SchemaConst = component4({
1138
928
  <x render=".value"></x>
1139
929
  </span>`
1140
930
  });
1141
- var SchemaCombinator = component4({
931
+ var SchemaCombinator = component3({
1142
932
  name: "SchemaCombinator",
1143
933
  fields: schemaNodeFields,
1144
934
  methods: schemaNodeMethods({
1145
935
  countText() {
1146
- return this.items.size > 0 ? `(${this.items.size})` : "";
936
+ return this.items.length > 0 ? `(${this.items.length})` : "";
1147
937
  }
1148
938
  }),
939
+ receive: compositeReceive,
1149
940
  alter: compositeAlter,
1150
941
  statics: {
1151
942
  fromData(schema, recurse) {
@@ -1169,7 +960,7 @@ var SchemaCombinator = component4({
1169
960
  // list layout: members are full schema nodes listed one per line, no keys.
1170
961
  view: makeSchemaView("text-accent", LIST_BODY)
1171
962
  });
1172
- var SchemaConditional = component4({
963
+ var SchemaConditional = component3({
1173
964
  name: "SchemaConditional",
1174
965
  fields: {
1175
966
  ifNode: null,
@@ -1189,7 +980,7 @@ var SchemaConditional = component4({
1189
980
  });
1190
981
  }
1191
982
  },
1192
- view: html4`<span class="font-mono text-sm leading-tight inline-block">
983
+ view: html3`<span class="font-mono text-sm leading-tight inline-block">
1193
984
  <span class="inline-flex items-center gap-2 flex-wrap">
1194
985
  <span class="text-accent font-semibold">conditional</span>
1195
986
  <span @show=".deprecated" class="badge badge-xs badge-warning"
@@ -1234,7 +1025,7 @@ var SchemaConditional = component4({
1234
1025
  </div>
1235
1026
  </span>`
1236
1027
  });
1237
- var SchemaNot = component4({
1028
+ var SchemaNot = component3({
1238
1029
  name: "SchemaNot",
1239
1030
  fields: { child: null },
1240
1031
  statics: {
@@ -1242,7 +1033,7 @@ var SchemaNot = component4({
1242
1033
  return this.make({ child: recurse(schema.not) });
1243
1034
  }
1244
1035
  },
1245
- view: html4`<span
1036
+ view: html3`<span
1246
1037
  class="font-mono text-sm leading-tight inline-flex items-center gap-2"
1247
1038
  >
1248
1039
  <span class="text-error font-semibold">not</span>
@@ -1250,7 +1041,7 @@ var SchemaNot = component4({
1250
1041
  <x render=".child"></x>
1251
1042
  </span>`
1252
1043
  });
1253
- var SchemaBoolean = component4({
1044
+ var SchemaBoolean = component3({
1254
1045
  name: "SchemaBoolean",
1255
1046
  fields: { value: true },
1256
1047
  methods: {
@@ -1262,21 +1053,21 @@ var SchemaBoolean = component4({
1262
1053
  return `${base} ${this.value ? "text-success" : "text-error"}`;
1263
1054
  }
1264
1055
  },
1265
- view: html4`<span :class="$cssClass" @text="$text"></span>`,
1056
+ view: html3`<span :class="$cssClass" @text="$text"></span>`,
1266
1057
  views: {
1267
1058
  // Decoy: cssClass() builds these at runtime, so they never appear as
1268
1059
  // literals the margaui scanner can find.
1269
- _margauiClasses: html4`<p class="text-success text-error"></p>`
1060
+ _margauiClasses: html3`<p class="text-success text-error"></p>`
1270
1061
  }
1271
1062
  });
1272
- var SchemaRef = component4({
1063
+ var SchemaRef = component3({
1273
1064
  name: "SchemaRef",
1274
1065
  fields: { target: "" },
1275
- view: html4`<span class="font-mono text-sm leading-tight text-secondary"
1066
+ view: html3`<span class="font-mono text-sm leading-tight text-secondary"
1276
1067
  >→ <span @text=".target"></span
1277
1068
  ></span>`
1278
1069
  });
1279
- var SchemaViewer = component4({
1070
+ var SchemaViewer = component3({
1280
1071
  name: "SchemaViewer",
1281
1072
  fields: {
1282
1073
  value: null,
@@ -1293,17 +1084,22 @@ var SchemaViewer = component4({
1293
1084
  statics: {
1294
1085
  fromData(schema) {
1295
1086
  return this.make({
1296
- value: dispatch3(schema),
1087
+ value: dispatch2(schema),
1297
1088
  raw: JsonViewer.Class.fromData(schema),
1298
1089
  rawSchema: schema
1299
1090
  });
1300
1091
  }
1301
1092
  },
1302
- view: html4`<div class="inline-flex flex-col items-start gap-1">
1093
+ receive: {
1094
+ toggleShowRaw(draft) {
1095
+ draft.showRaw = !draft.showRaw;
1096
+ }
1097
+ },
1098
+ view: html3`<div class="inline-flex flex-col items-start gap-1">
1303
1099
  <button
1304
1100
  type="button"
1305
1101
  class="btn btn-xs btn-ghost self-end"
1306
- @on.click="$toggleShowRaw"
1102
+ @on.click="toggleShowRaw"
1307
1103
  @text="$toggleLabel"
1308
1104
  ></button>
1309
1105
  <x render=".value" @hide=".showRaw"></x>
@@ -1335,8 +1131,8 @@ function classifySchema(schema, recurse = classifySchema) {
1335
1131
  return SchemaConditional.Class.fromData(schema, recurse);
1336
1132
  return SchemaScalar.Class.fromData(schema, recurse);
1337
1133
  }
1338
- var dispatch3 = chain(classifySchema);
1339
- function getComponents4() {
1134
+ var dispatch2 = chain(classifySchema);
1135
+ function getComponents3() {
1340
1136
  return [
1341
1137
  SchemaViewer,
1342
1138
  SchemaScalar,
@@ -1356,13 +1152,13 @@ function getComponents4() {
1356
1152
  }
1357
1153
 
1358
1154
  // src/components/tutuca/activity-inspector.js
1359
- import { component as component9, html as html9 } from "tutuca";
1155
+ import { component as component8, html as html8 } from "tutuca";
1360
1156
 
1361
1157
  // src/components/tutuca/instance-inspector.js
1362
- import { component as component8, html as html8, isRecord } from "tutuca";
1158
+ import { component as component7, html as html7 } from "tutuca";
1363
1159
 
1364
1160
  // src/components/tutuca/component-inspector.js
1365
- import { component as component5, html as html5 } from "tutuca";
1161
+ import { component as component4, html as html4 } from "tutuca";
1366
1162
  function introspectComponent(comp) {
1367
1163
  const { fields, methods } = comp.Class.getMetaClass();
1368
1164
  return {
@@ -1374,10 +1170,8 @@ function introspectComponent(comp) {
1374
1170
  defaultValue: f.defaultValue
1375
1171
  })),
1376
1172
  methods: Object.keys(methods),
1377
- input: Object.keys(comp.input ?? {}),
1378
1173
  receive: Object.keys(comp.receive ?? {}),
1379
- bubble: Object.keys(comp.bubble ?? {}),
1380
- response: Object.keys(comp.response ?? {}),
1174
+ intent: Object.keys(comp.intent ?? {}),
1381
1175
  alter: Object.keys(comp.alter ?? {}),
1382
1176
  statics: Object.keys(comp.spec?.statics ?? {}),
1383
1177
  views: Object.values(comp.views ?? {}).map((v) => ({
@@ -1395,18 +1189,18 @@ var sectionView = makeCompositeView({
1395
1189
  // inspector can toggle every section at once.
1396
1190
  toggleHandler: "toggle isCtrl"
1397
1191
  });
1398
- var CompName = component5({
1192
+ var CompName = component4({
1399
1193
  name: "CompName",
1400
1194
  fields: { name: "" },
1401
- view: html5`<span
1195
+ view: html4`<span
1402
1196
  class="font-mono text-sm leading-tight badge badge-sm badge-ghost"
1403
1197
  @text=".name"
1404
1198
  ></span>`
1405
1199
  });
1406
- var CompField = component5({
1200
+ var CompField = component4({
1407
1201
  name: "CompField",
1408
1202
  fields: { name: "", typeName: "", child: null },
1409
- view: html5`<div class="flex items-center gap-2 leading-tight">
1203
+ view: html4`<div class="flex items-center gap-2 leading-tight">
1410
1204
  <span class="text-base-content/70 font-mono text-sm" @text=".name"></span>
1411
1205
  <span class="text-base-content/30">:</span>
1412
1206
  <span class="text-base-content/50 font-mono text-xs" @text=".typeName"></span>
@@ -1414,7 +1208,7 @@ var CompField = component5({
1414
1208
  <x render=".child"></x>
1415
1209
  </div>`
1416
1210
  });
1417
- var CompView = component5({
1211
+ var CompView = component4({
1418
1212
  name: "CompView",
1419
1213
  fields: { name: "", rawView: "", isExpanded: false },
1420
1214
  methods: {
@@ -1422,16 +1216,17 @@ var CompView = component5({
1422
1216
  return this.isExpanded ? "▼" : "▶";
1423
1217
  }
1424
1218
  },
1425
- input: {
1426
- toggle(isCtrl, ctx) {
1219
+ receive: {
1220
+ ...compositeReceive,
1221
+ toggle(draft, isCtrl, ctx) {
1427
1222
  if (isCtrl) {
1428
- ctx.bubble("toggleAllViews", [!this.isExpanded]);
1223
+ ctx.intent("toggleAllViews", [!this.isExpanded], { route: ["dyn"] });
1429
1224
  return this;
1430
1225
  }
1431
- return this.toggleIsExpanded();
1226
+ draft.isExpanded = !draft.isExpanded;
1432
1227
  }
1433
1228
  },
1434
- view: html5`<div class="flex flex-col gap-0.5 leading-tight">
1229
+ view: html4`<div class="flex flex-col gap-0.5 leading-tight">
1435
1230
  <button
1436
1231
  type="button"
1437
1232
  class="cursor-pointer text-base-content/70 hover:text-base-content inline-flex items-center gap-1 self-start"
@@ -1446,7 +1241,7 @@ var CompView = component5({
1446
1241
  ><code @text=".rawView"></code></pre>
1447
1242
  </div>`
1448
1243
  });
1449
- var CompSection = component5({
1244
+ var CompSection = component4({
1450
1245
  name: "CompSection",
1451
1246
  fields: { ...compositeFields, label: "" },
1452
1247
  methods: {
@@ -1455,57 +1250,37 @@ var CompSection = component5({
1455
1250
  return this.label;
1456
1251
  },
1457
1252
  countText() {
1458
- return `(${this.items.size})`;
1253
+ return `(${this.items.length})`;
1459
1254
  }
1460
1255
  },
1461
- input: {
1462
- toggle(isCtrl, ctx) {
1256
+ receive: {
1257
+ ...compositeReceive,
1258
+ toggle(draft, isCtrl, ctx) {
1463
1259
  if (isCtrl) {
1464
- ctx.bubble("toggleAllSections", [!this.isExpanded]);
1260
+ ctx.intent("toggleAllSections", [!this.isExpanded], { route: ["dyn"] });
1465
1261
  return this;
1466
1262
  }
1467
- return this.toggleIsExpanded();
1263
+ draft.isExpanded = !draft.isExpanded;
1468
1264
  }
1469
1265
  },
1470
1266
  alter: compositeAlter,
1471
1267
  view: sectionView
1472
1268
  });
1473
- var ComponentInspector = component5({
1269
+ var ComponentInspector = component4({
1474
1270
  name: "ComponentInspector",
1475
1271
  fields: { compName: "", compId: 0, sections: [] },
1476
1272
  methods: {
1477
1273
  idText() {
1478
1274
  return `#${this.compId}`;
1479
- },
1480
- setAllSections(state) {
1481
- return this.setSections(this.sections.map((s) => s.setIsExpanded(state)));
1482
- },
1483
- expandAll() {
1484
- return this.setAllSections(true);
1485
- },
1486
- collapseAll() {
1487
- return this.setAllSections(false);
1488
- },
1489
- setAllViews(state) {
1490
- return this.setSections(
1491
- this.sections.map(
1492
- (s) => s.label === "Views" ? s.setItems(s.items.map((v) => v.setIsExpanded(state))) : s
1493
- )
1494
- );
1495
- },
1496
- expandAllViews() {
1497
- return this.setAllViews(true);
1498
- },
1499
- collapseAllViews() {
1500
- return this.setAllViews(false);
1501
1275
  }
1502
1276
  },
1503
- bubble: {
1504
- toggleAllSections(state) {
1505
- return this.setAllSections(state);
1277
+ intent: {
1278
+ toggleAllSections(draft, state) {
1279
+ for (const section of draft.sections) section.isExpanded = state;
1506
1280
  },
1507
- toggleAllViews(state) {
1508
- return this.setAllViews(state);
1281
+ toggleAllViews(draft, state) {
1282
+ const section = draft.sections.find((candidate) => candidate.label === "Views");
1283
+ if (section) for (const view of section.items) view.isExpanded = state;
1509
1284
  }
1510
1285
  },
1511
1286
  statics: {
@@ -1524,16 +1299,14 @@ var ComponentInspector = component5({
1524
1299
  (f) => CompField.make({
1525
1300
  name: f.name,
1526
1301
  typeName: f.type,
1527
- child: ImInspector.Class.fromData(f.defaultValue)
1302
+ child: DataInspector.Class.fromData(f.defaultValue)
1528
1303
  })
1529
1304
  ),
1530
1305
  true
1531
1306
  );
1532
1307
  add("Methods", names(d.methods));
1533
- add("Input", names(d.input));
1534
1308
  add("Receive", names(d.receive));
1535
- add("Bubble", names(d.bubble));
1536
- add("Response", names(d.response));
1309
+ add("Intent", names(d.intent));
1537
1310
  add("Alter", names(d.alter));
1538
1311
  add("Statics", names(d.statics));
1539
1312
  add(
@@ -1543,7 +1316,7 @@ var ComponentInspector = component5({
1543
1316
  return this.make({ compName: d.name, compId: d.id, sections });
1544
1317
  }
1545
1318
  },
1546
- view: html5`<div class="font-mono text-sm leading-tight flex flex-col gap-1">
1319
+ view: html4`<div class="font-mono text-sm leading-tight flex flex-col gap-1">
1547
1320
  <div class="inline-flex items-center gap-2">
1548
1321
  <span class="font-semibold" @text=".compName"></span>
1549
1322
  <span class="text-base-content/40 text-xs" @text="$idText"></span>
@@ -1551,12 +1324,12 @@ var ComponentInspector = component5({
1551
1324
  <x render-each=".sections"></x>
1552
1325
  </div>`
1553
1326
  });
1554
- function getComponents5() {
1327
+ function getComponents4() {
1555
1328
  return [ComponentInspector, CompSection, CompField, CompName, CompView, ...getComponents2()];
1556
1329
  }
1557
1330
 
1558
1331
  // src/components/tutuca/lint-inspector.js
1559
- import { component as component6, html as html6 } from "tutuca";
1332
+ import { component as component5, html as html5 } from "tutuca";
1560
1333
  var tagDisplay = (tag) => tag ? String(tag).toLowerCase() : "";
1561
1334
  function originSuffix(info) {
1562
1335
  if (!info) return "";
@@ -1598,12 +1371,10 @@ function lintMessage(id, info = {}) {
1598
1371
  return `Method '$${info.name}' is not defined${originSuffix(info)}`;
1599
1372
  case "METHOD_VAL_IS_FIELD":
1600
1373
  return `'$${info.name}' calls a method, but '${info.name}' is a field — use '.${info.name}'${originSuffix(info)}`;
1601
- case "INPUT_HANDLER_NOT_IMPLEMENTED":
1602
- return `Input handler '${info.name}' is not implemented${eventSuffix(info)}`;
1603
- case "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED":
1604
- return `Method '$${info.name}' is not implemented${eventSuffix(info)}`;
1605
- case "INPUT_HANDLER_NOT_REFERENCED":
1606
- return `Input handler '${info.name}' is defined but never used`;
1374
+ case "RECEIVE_HANDLER_NOT_IMPLEMENTED":
1375
+ return `Receive handler '${info.name}' is not implemented${eventSuffix(info)}`;
1376
+ case "EVENT_HANDLER_METHOD_NOT_ALLOWED":
1377
+ return `Event handler '$${info.name}' is a method reference — move it to receive and use '${info.name}'`;
1607
1378
  case "ALT_HANDLER_NOT_DEFINED":
1608
1379
  return `Alter handler '${info.name}' is not defined${originSuffix(info)}`;
1609
1380
  case "DYN_VAL_NOT_DEFINED":
@@ -1637,7 +1408,7 @@ var componentView = makeCompositeView({
1637
1408
  typeClass: "font-semibold",
1638
1409
  borderClass: "border-base-content/15"
1639
1410
  });
1640
- var LintFinding = component6({
1411
+ var LintFinding = component5({
1641
1412
  name: "LintFinding",
1642
1413
  fields: { id: "", level: "", message: "", suggestion: "", detail: null },
1643
1414
  methods: {
@@ -1661,11 +1432,11 @@ var LintFinding = component6({
1661
1432
  },
1662
1433
  // Decoy so the runtime-built soft badge colours survive the class scan.
1663
1434
  views: {
1664
- _palette: html6`<span
1435
+ _palette: html5`<span
1665
1436
  class="badge-soft badge-error badge-warning badge-neutral"
1666
1437
  ></span>`
1667
1438
  },
1668
- view: html6`<div class="flex flex-col gap-1.5 py-1.5 leading-snug">
1439
+ view: html5`<div class="flex flex-col gap-1.5 py-1.5 leading-snug">
1669
1440
  <div class="flex items-baseline gap-2 flex-wrap">
1670
1441
  <span :class="$levelBadgeClass" @text=".level"></span>
1671
1442
  <span class="text-sm text-base-content/90" @text=".message"></span>
@@ -1688,10 +1459,10 @@ function buildFinding(f) {
1688
1459
  level: f.level ?? "",
1689
1460
  message: lintMessage(f.id, info),
1690
1461
  suggestion: suggestionText(f.suggestion),
1691
- detail: ImInspector.Class.fromData({ id: f.id, info, context: ctx })
1462
+ detail: DataInspector.Class.fromData({ id: f.id, info, context: ctx })
1692
1463
  });
1693
1464
  }
1694
- var LintComponent = component6({
1465
+ var LintComponent = component5({
1695
1466
  name: "LintComponent",
1696
1467
  fields: { ...compositeFields, componentName: "", errors: 0, warns: 0, hints: 0 },
1697
1468
  methods: {
@@ -1707,10 +1478,11 @@ var LintComponent = component6({
1707
1478
  return parts.length ? parts.join(", ") : "ok";
1708
1479
  }
1709
1480
  },
1481
+ receive: compositeReceive,
1710
1482
  alter: compositeAlter,
1711
1483
  view: componentView
1712
1484
  });
1713
- var LintReport = component6({
1485
+ var LintReport = component5({
1714
1486
  name: "LintReport",
1715
1487
  fields: {
1716
1488
  title: "",
@@ -1781,11 +1553,11 @@ var LintReport = component6({
1781
1553
  },
1782
1554
  // Decoy so the runtime-absent soft tally colours are emitted.
1783
1555
  views: {
1784
- _palette: html6`<span
1556
+ _palette: html5`<span
1785
1557
  class="badge-soft badge-error badge-warning badge-neutral badge-success"
1786
1558
  ></span>`
1787
1559
  },
1788
- view: html6`<div class="font-mono text-sm leading-snug flex flex-col gap-3">
1560
+ view: html5`<div class="font-mono text-sm leading-snug flex flex-col gap-3">
1789
1561
  <div class="flex items-center gap-2 flex-wrap">
1790
1562
  <span class="font-semibold" @text=".title"></span>
1791
1563
  <span class="text-base-content/40 text-xs" @text=".path"></span>
@@ -1813,12 +1585,12 @@ var LintReport = component6({
1813
1585
  <x render-each=".components"></x>
1814
1586
  </div>`
1815
1587
  });
1816
- function getComponents6() {
1588
+ function getComponents5() {
1817
1589
  return [LintReport, LintComponent, LintFinding, ...getComponents2()];
1818
1590
  }
1819
1591
 
1820
1592
  // src/components/tutuca/test-inspector.js
1821
- import { component as component7, html as html7 } from "tutuca";
1593
+ import { component as component6, html as html6 } from "tutuca";
1822
1594
  function collectTests(getTests) {
1823
1595
  const root = { children: [] };
1824
1596
  const stack = [root];
@@ -1851,7 +1623,7 @@ var suiteView = makeCompositeView({
1851
1623
  // it can expand/collapse every suite at once (like the component inspector).
1852
1624
  toggleHandler: "toggle isCtrl"
1853
1625
  });
1854
- var TestCase = component7({
1626
+ var TestCase = component6({
1855
1627
  name: "TestCase",
1856
1628
  fields: { title: "", status: "", durationMs: 0, message: "", detail: null },
1857
1629
  methods: {
@@ -1890,9 +1662,9 @@ var TestCase = component7({
1890
1662
  },
1891
1663
  // Decoy so the runtime-built mark colors survive the margaui class scan.
1892
1664
  views: {
1893
- _palette: html7`<span class="text-success text-error text-base-content/40"></span>`
1665
+ _palette: html6`<span class="text-success text-error text-base-content/40"></span>`
1894
1666
  },
1895
- view: html7`<div class="flex flex-col gap-0.5 leading-tight">
1667
+ view: html6`<div class="flex flex-col gap-0.5 leading-tight">
1896
1668
  <div class="flex items-center gap-2">
1897
1669
  <span :class="$markClass" @text="$mark"></span>
1898
1670
  <span class="font-mono text-sm" @text=".title"></span>
@@ -1902,7 +1674,7 @@ var TestCase = component7({
1902
1674
  <div @show="$hasDetail" class="ml-5"><x render=".detail"></x></div>
1903
1675
  </div>`
1904
1676
  });
1905
- var TestSuite = component7({
1677
+ var TestSuite = component6({
1906
1678
  name: "TestSuite",
1907
1679
  fields: { ...compositeFields, title: "", summary: "" },
1908
1680
  methods: {
@@ -1911,24 +1683,26 @@ var TestSuite = component7({
1911
1683
  return this.title;
1912
1684
  },
1913
1685
  countText() {
1914
- return this.summary || `(${this.items.size})`;
1686
+ return this.summary || `(${this.items.length})`;
1915
1687
  }
1916
1688
  },
1917
- input: {
1918
- toggle(isCtrl, ctx) {
1689
+ receive: {
1690
+ ...compositeReceive,
1691
+ toggle(draft, isCtrl, ctx) {
1919
1692
  if (isCtrl) {
1920
- ctx.bubble("toggleAll", [!this.isExpanded]);
1693
+ ctx.intent("toggleAll", [!this.isExpanded], { route: ["dyn"] });
1921
1694
  return this;
1922
1695
  }
1923
- return this.toggleIsExpanded();
1696
+ draft.isExpanded = !draft.isExpanded;
1924
1697
  }
1925
1698
  },
1926
1699
  alter: compositeAlter,
1927
1700
  view: suiteView
1928
1701
  });
1929
1702
  function setSuiteTreeExpanded(node, state) {
1930
- if (typeof node.setIsExpanded !== "function") return node;
1931
- return node.setIsExpanded(state).setItems(node.items.map((c) => setSuiteTreeExpanded(c, state)));
1703
+ if (!("isExpanded" in node)) return;
1704
+ node.isExpanded = state;
1705
+ for (const child of node.items) setSuiteTreeExpanded(child, state);
1932
1706
  }
1933
1707
  function buildDefNode(node) {
1934
1708
  if (Array.isArray(node.children)) {
@@ -1962,7 +1736,7 @@ function buildResultNode(node) {
1962
1736
  status,
1963
1737
  durationMs: node.durationMs ?? 0,
1964
1738
  message: err?.message ?? "",
1965
- detail: hasDiff ? ImInspector.Class.fromData({ expected: err.expected, actual: err.actual }) : null
1739
+ detail: hasDiff ? DataInspector.Class.fromData({ expected: err.expected, actual: err.actual }) : null
1966
1740
  });
1967
1741
  return {
1968
1742
  comp,
@@ -1971,7 +1745,7 @@ function buildResultNode(node) {
1971
1745
  skip: status === "skip" ? 1 : 0
1972
1746
  };
1973
1747
  }
1974
- var TestReport = component7({
1748
+ var TestReport = component6({
1975
1749
  name: "TestReport",
1976
1750
  fields: {
1977
1751
  title: "",
@@ -1997,15 +1771,12 @@ var TestReport = component7({
1997
1771
  },
1998
1772
  hasSkips() {
1999
1773
  return this.hasCounts && this.skip > 0;
2000
- },
2001
- setAllSuites(state) {
2002
- return this.setSuites(this.suites.map((s) => setSuiteTreeExpanded(s, state)));
2003
1774
  }
2004
1775
  },
2005
- bubble: {
1776
+ intent: {
2006
1777
  // ctrl/cmd-click on any suite expands/collapses the whole tree at once.
2007
- toggleAll(state) {
2008
- return this.setAllSuites(state);
1778
+ toggleAll(draft, state) {
1779
+ for (const suite of draft.suites) setSuiteTreeExpanded(suite, state);
2009
1780
  }
2010
1781
  },
2011
1782
  statics: {
@@ -2032,7 +1803,7 @@ var TestReport = component7({
2032
1803
  });
2033
1804
  }
2034
1805
  },
2035
- view: html7`<div class="font-mono text-sm leading-tight flex flex-col gap-1">
1806
+ view: html6`<div class="font-mono text-sm leading-tight flex flex-col gap-1">
2036
1807
  <div class="flex items-center gap-2 flex-wrap">
2037
1808
  <span class="font-semibold" @text=".title"></span>
2038
1809
  <span class="text-base-content/40 text-xs" @text=".path"></span>
@@ -2055,17 +1826,17 @@ var TestReport = component7({
2055
1826
  <x render-each=".suites"></x>
2056
1827
  </div>`
2057
1828
  });
2058
- function getComponents7() {
1829
+ function getComponents6() {
2059
1830
  return [TestReport, TestSuite, TestCase, ...getComponents2()];
2060
1831
  }
2061
1832
 
2062
1833
  // src/components/tutuca/instance-inspector.js
2063
- var isComponentInstance = (v) => isRecord(v) && typeof v?.constructor?.getMetaClass === "function";
1834
+ var isComponentInstance = (v) => v !== null && typeof v === "object" && typeof v?.constructor?.getMetaClass === "function";
2064
1835
  var fieldsView = makeCompositeView({
2065
1836
  typeClass: "font-semibold",
2066
1837
  borderClass: "border-base-content/15"
2067
1838
  });
2068
- var InstanceFields = component8({
1839
+ var InstanceFields = component7({
2069
1840
  name: "InstanceFields",
2070
1841
  fields: { ...compositeFields, typeName: "" },
2071
1842
  methods: {
@@ -2074,17 +1845,18 @@ var InstanceFields = component8({
2074
1845
  return this.typeName;
2075
1846
  },
2076
1847
  countText() {
2077
- return `{${this.items.size}}`;
1848
+ return `{${this.items.length}}`;
2078
1849
  }
2079
1850
  },
1851
+ receive: compositeReceive,
2080
1852
  alter: compositeAlter,
2081
1853
  statics: {
2082
1854
  fromData(instance, comp) {
2083
1855
  const d = introspectComponent(comp);
2084
1856
  const items = d.fields.map(
2085
- (f) => ImEntry.make({
1857
+ (f) => JsonProperty.make({
2086
1858
  key: f.name,
2087
- child: ImInspector.Class.fromData(instance.get(f.name))
1859
+ child: DataInspector.Class.fromData(instance[f.name])
2088
1860
  })
2089
1861
  );
2090
1862
  return this.make({ typeName: d.name, items, isExpanded: true });
@@ -2095,7 +1867,7 @@ var InstanceFields = component8({
2095
1867
  var InstanceInspector = makeValueInspector({
2096
1868
  name: "InstanceInspector",
2097
1869
  fromData(instance, comp) {
2098
- const value = comp && isComponentInstance(instance) ? InstanceFields.Class.fromData(instance, comp) : ImInspector.Class.fromData(instance);
1870
+ const value = comp && isComponentInstance(instance) ? InstanceFields.Class.fromData(instance, comp) : DataInspector.Class.fromData(instance);
2099
1871
  return this.make({ value });
2100
1872
  }
2101
1873
  });
@@ -2107,7 +1879,7 @@ function asLintView(lint) {
2107
1879
  if (lint == null) return null;
2108
1880
  return isComponentInstance(lint) ? lint : LintReport.Class.fromData(lint);
2109
1881
  }
2110
- var InstanceExplorer = component8({
1882
+ var InstanceExplorer = component7({
2111
1883
  name: "InstanceExplorer",
2112
1884
  fields: {
2113
1885
  activeTab: "instance",
@@ -2134,14 +1906,19 @@ var InstanceExplorer = component8({
2134
1906
  });
2135
1907
  }
2136
1908
  },
2137
- view: html8`<div class="font-mono text-sm leading-snug flex flex-col gap-3">
1909
+ receive: {
1910
+ setActiveTab(draft, value) {
1911
+ draft.activeTab = value;
1912
+ }
1913
+ },
1914
+ view: html7`<div class="font-mono text-sm leading-snug flex flex-col gap-3">
2138
1915
  <div role="tablist" class="tabs">
2139
1916
  <a
2140
1917
  role="tab"
2141
1918
  @if.class="equals? .activeTab 'instance'"
2142
1919
  @then="'tab tab-active'"
2143
1920
  @else="'tab'"
2144
- @on.click="$setActiveTab 'instance'"
1921
+ @on.click="setActiveTab 'instance'"
2145
1922
  >
2146
1923
  Instance
2147
1924
  </a>
@@ -2151,7 +1928,7 @@ var InstanceExplorer = component8({
2151
1928
  @if.class="equals? .activeTab 'component'"
2152
1929
  @then="'tab tab-active'"
2153
1930
  @else="'tab'"
2154
- @on.click="$setActiveTab 'component'"
1931
+ @on.click="setActiveTab 'component'"
2155
1932
  >
2156
1933
  Component
2157
1934
  </a>
@@ -2161,7 +1938,7 @@ var InstanceExplorer = component8({
2161
1938
  @if.class="equals? .activeTab 'tests'"
2162
1939
  @then="'tab tab-active'"
2163
1940
  @else="'tab'"
2164
- @on.click="$setActiveTab 'tests'"
1941
+ @on.click="setActiveTab 'tests'"
2165
1942
  >
2166
1943
  Tests
2167
1944
  </a>
@@ -2171,7 +1948,7 @@ var InstanceExplorer = component8({
2171
1948
  @if.class="equals? .activeTab 'lint'"
2172
1949
  @then="'tab tab-active'"
2173
1950
  @else="'tab'"
2174
- @on.click="$setActiveTab 'lint'"
1951
+ @on.click="setActiveTab 'lint'"
2175
1952
  >
2176
1953
  Lint
2177
1954
  </a>
@@ -2193,14 +1970,14 @@ var InstanceExplorer = component8({
2193
1970
  </div>
2194
1971
  </div>`
2195
1972
  });
2196
- function getComponents8() {
1973
+ function getComponents7() {
2197
1974
  const all = [
2198
1975
  InstanceExplorer,
2199
1976
  InstanceInspector,
2200
1977
  InstanceFields,
2201
- ...getComponents5(),
2202
- ...getComponents7(),
2203
- ...getComponents6()
1978
+ ...getComponents4(),
1979
+ ...getComponents6(),
1980
+ ...getComponents5()
2204
1981
  ];
2205
1982
  const seen = /* @__PURE__ */ new Set();
2206
1983
  return all.filter((c) => {
@@ -2212,7 +1989,7 @@ function getComponents8() {
2212
1989
 
2213
1990
  // src/components/tutuca/activity-inspector.js
2214
1991
  var ACTIVITY_CAP = 50;
2215
- var ActivityEntry = component9({
1992
+ var ActivityEntry = component8({
2216
1993
  name: "ActivityEntry",
2217
1994
  fields: {
2218
1995
  kind: "",
@@ -2225,7 +2002,7 @@ var ActivityEntry = component9({
2225
2002
  after: null,
2226
2003
  hasAfter: true
2227
2004
  },
2228
- view: html9`<div
2005
+ view: html8`<div
2229
2006
  class="rounded border border-base-content/15 p-2 text-sm flex flex-col gap-1"
2230
2007
  >
2231
2008
  <div class="flex items-center gap-2 flex-wrap">
@@ -2274,15 +2051,13 @@ var ActivityEntry = component9({
2274
2051
  </div>
2275
2052
  </div>`
2276
2053
  });
2277
- var ActivityLog = component9({
2054
+ var ActivityLog = component8({
2278
2055
  name: "ActivityLog",
2279
2056
  fields: { events: [], hasEvents: false },
2280
- methods: {
2281
- appendEntry(entry) {
2282
- return this.setEvents(this.events.unshift(entry).slice(0, ACTIVITY_CAP)).setHasEvents(true);
2283
- }
2057
+ statics: {
2058
+ cap: ACTIVITY_CAP
2284
2059
  },
2285
- view: html9`<div class="p-3 flex flex-col gap-2 max-h-[60vh] overflow-y-auto">
2060
+ view: html8`<div class="p-3 flex flex-col gap-2 max-h-[60vh] overflow-y-auto">
2286
2061
  <div class="text-xs opacity-40" @hide=".hasEvents">
2287
2062
  No activity yet — interact with the component.
2288
2063
  </div>
@@ -2320,7 +2095,7 @@ function recordToEntry(record, { inspect, pathLabel = pathKeysLabel } = {}) {
2320
2095
  hasAfter
2321
2096
  });
2322
2097
  }
2323
- function getComponents9() {
2098
+ function getComponents8() {
2324
2099
  return [ActivityLog, ActivityEntry];
2325
2100
  }
2326
2101
 
@@ -2362,16 +2137,15 @@ async function buildInspectorViews(value, scope, { getTests = null, components =
2362
2137
  }
2363
2138
 
2364
2139
  // src/components/index.js
2365
- function getComponents10() {
2140
+ function getComponents9() {
2366
2141
  const all = [
2367
- ...getComponents9(),
2368
- ...getComponents5(),
2369
2142
  ...getComponents8(),
2370
- ...getComponents6(),
2371
- ...getComponents7(),
2372
- ...getComponents3(),
2373
2143
  ...getComponents4(),
2144
+ ...getComponents7(),
2145
+ ...getComponents5(),
2146
+ ...getComponents6(),
2374
2147
  ...getComponents2(),
2148
+ ...getComponents3(),
2375
2149
  ...getComponents()
2376
2150
  ];
2377
2151
  const seen = /* @__PURE__ */ new Set();
@@ -2390,16 +2164,6 @@ export {
2390
2164
  CompView,
2391
2165
  ComponentInspector,
2392
2166
  DataInspector,
2393
- ImEntry,
2394
- ImInspector,
2395
- ImList,
2396
- ImMap,
2397
- ImOMap,
2398
- ImOSet,
2399
- ImRange,
2400
- ImRecord,
2401
- ImSet,
2402
- ImStack,
2403
2167
  InstanceExplorer,
2404
2168
  InstanceFields,
2405
2169
  InstanceInspector,
@@ -2444,7 +2208,6 @@ export {
2444
2208
  buildInspectorViews,
2445
2209
  chain,
2446
2210
  classifyData,
2447
- classifyImmutable,
2448
2211
  classifyJsExtra,
2449
2212
  classifyJson,
2450
2213
  classifySchema,
@@ -2452,10 +2215,11 @@ export {
2452
2215
  compositeAlter,
2453
2216
  compositeFields,
2454
2217
  compositeMethods,
2218
+ compositeReceive,
2455
2219
  compositeView,
2456
2220
  fmtActivityTime,
2457
2221
  fmtAnyKey,
2458
- getComponents10 as getComponents,
2222
+ getComponents9 as getComponents,
2459
2223
  introspectComponent,
2460
2224
  isComponentInstance,
2461
2225
  lintMessage,