tutuca 0.10.0 → 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 (48) hide show
  1. package/README.md +14 -14
  2. package/dist/immer.js +1261 -0
  3. package/dist/tutuca-cli.js +1603 -4573
  4. package/dist/tutuca-components.js +194 -424
  5. package/dist/tutuca-dev.ext.js +483 -757
  6. package/dist/tutuca-dev.js +1172 -4999
  7. package/dist/tutuca-dev.min.js +3 -3
  8. package/dist/tutuca-extra.ext.js +460 -547
  9. package/dist/tutuca-extra.js +1136 -4790
  10. package/dist/tutuca-extra.min.js +2 -2
  11. package/dist/tutuca-storybook.js +152 -143
  12. package/dist/tutuca.ext.js +460 -547
  13. package/dist/tutuca.js +1136 -4790
  14. package/dist/tutuca.min.js +2 -2
  15. package/package.json +7 -11
  16. package/skill/tutuca/SKILL.md +0 -4
  17. package/skill/tutuca/advanced.md +12 -4
  18. package/skill/tutuca/cli.md +8 -9
  19. package/skill/tutuca/component-design.md +18 -19
  20. package/skill/tutuca/core.md +83 -81
  21. package/skill/tutuca/iteration.md +2 -2
  22. package/skill/tutuca/macros.md +1 -1
  23. package/skill/tutuca/messages-and-intents.md +24 -23
  24. package/skill/tutuca/patterns/bind-text-and-attributes.md +1 -1
  25. package/skill/tutuca/patterns/conditional-attribute-value.md +1 -1
  26. package/skill/tutuca/patterns/coordinate-components.md +10 -8
  27. package/skill/tutuca/patterns/file-input.md +6 -6
  28. package/skill/tutuca/patterns/filter-and-paginate.md +1 -1
  29. package/skill/tutuca/patterns/handle-events.md +10 -8
  30. package/skill/tutuca/patterns/switch-between-views.md +1 -1
  31. package/skill/tutuca/patterns/tabbed-interface.md +10 -5
  32. package/skill/tutuca/testing.md +37 -28
  33. package/skill/tutuca-source/tutuca.ext.js +460 -547
  34. package/dist/immutable.js +0 -4331
  35. package/skill/immutable-js/SKILL.md +0 -78
  36. package/skill/immutable-js/references/collection.md +0 -346
  37. package/skill/immutable-js/references/conversions.md +0 -99
  38. package/skill/immutable-js/references/deep-updates.md +0 -172
  39. package/skill/immutable-js/references/equality.md +0 -95
  40. package/skill/immutable-js/references/list.md +0 -266
  41. package/skill/immutable-js/references/map.md +0 -300
  42. package/skill/immutable-js/references/predicates.md +0 -93
  43. package/skill/immutable-js/references/range-repeat.md +0 -55
  44. package/skill/immutable-js/references/record.md +0 -196
  45. package/skill/immutable-js/references/seq.md +0 -248
  46. package/skill/immutable-js/references/set.md +0 -270
  47. package/skill/immutable-js/references/shallow-functional.md +0 -99
  48. package/skill/immutable-js/references/stack.md +0 -210
@@ -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 {
@@ -1393,18 +1189,18 @@ var sectionView = makeCompositeView({
1393
1189
  // inspector can toggle every section at once.
1394
1190
  toggleHandler: "toggle isCtrl"
1395
1191
  });
1396
- var CompName = component5({
1192
+ var CompName = component4({
1397
1193
  name: "CompName",
1398
1194
  fields: { name: "" },
1399
- view: html5`<span
1195
+ view: html4`<span
1400
1196
  class="font-mono text-sm leading-tight badge badge-sm badge-ghost"
1401
1197
  @text=".name"
1402
1198
  ></span>`
1403
1199
  });
1404
- var CompField = component5({
1200
+ var CompField = component4({
1405
1201
  name: "CompField",
1406
1202
  fields: { name: "", typeName: "", child: null },
1407
- view: html5`<div class="flex items-center gap-2 leading-tight">
1203
+ view: html4`<div class="flex items-center gap-2 leading-tight">
1408
1204
  <span class="text-base-content/70 font-mono text-sm" @text=".name"></span>
1409
1205
  <span class="text-base-content/30">:</span>
1410
1206
  <span class="text-base-content/50 font-mono text-xs" @text=".typeName"></span>
@@ -1412,7 +1208,7 @@ var CompField = component5({
1412
1208
  <x render=".child"></x>
1413
1209
  </div>`
1414
1210
  });
1415
- var CompView = component5({
1211
+ var CompView = component4({
1416
1212
  name: "CompView",
1417
1213
  fields: { name: "", rawView: "", isExpanded: false },
1418
1214
  methods: {
@@ -1421,15 +1217,16 @@ var CompView = component5({
1421
1217
  }
1422
1218
  },
1423
1219
  receive: {
1424
- toggle(isCtrl, ctx) {
1220
+ ...compositeReceive,
1221
+ toggle(draft, isCtrl, ctx) {
1425
1222
  if (isCtrl) {
1426
1223
  ctx.intent("toggleAllViews", [!this.isExpanded], { route: ["dyn"] });
1427
1224
  return this;
1428
1225
  }
1429
- return this.toggleIsExpanded();
1226
+ draft.isExpanded = !draft.isExpanded;
1430
1227
  }
1431
1228
  },
1432
- 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">
1433
1230
  <button
1434
1231
  type="button"
1435
1232
  class="cursor-pointer text-base-content/70 hover:text-base-content inline-flex items-center gap-1 self-start"
@@ -1444,7 +1241,7 @@ var CompView = component5({
1444
1241
  ><code @text=".rawView"></code></pre>
1445
1242
  </div>`
1446
1243
  });
1447
- var CompSection = component5({
1244
+ var CompSection = component4({
1448
1245
  name: "CompSection",
1449
1246
  fields: { ...compositeFields, label: "" },
1450
1247
  methods: {
@@ -1453,57 +1250,37 @@ var CompSection = component5({
1453
1250
  return this.label;
1454
1251
  },
1455
1252
  countText() {
1456
- return `(${this.items.size})`;
1253
+ return `(${this.items.length})`;
1457
1254
  }
1458
1255
  },
1459
1256
  receive: {
1460
- toggle(isCtrl, ctx) {
1257
+ ...compositeReceive,
1258
+ toggle(draft, isCtrl, ctx) {
1461
1259
  if (isCtrl) {
1462
1260
  ctx.intent("toggleAllSections", [!this.isExpanded], { route: ["dyn"] });
1463
1261
  return this;
1464
1262
  }
1465
- return this.toggleIsExpanded();
1263
+ draft.isExpanded = !draft.isExpanded;
1466
1264
  }
1467
1265
  },
1468
1266
  alter: compositeAlter,
1469
1267
  view: sectionView
1470
1268
  });
1471
- var ComponentInspector = component5({
1269
+ var ComponentInspector = component4({
1472
1270
  name: "ComponentInspector",
1473
1271
  fields: { compName: "", compId: 0, sections: [] },
1474
1272
  methods: {
1475
1273
  idText() {
1476
1274
  return `#${this.compId}`;
1477
- },
1478
- setAllSections(state) {
1479
- return this.setSections(this.sections.map((s) => s.setIsExpanded(state)));
1480
- },
1481
- expandAll() {
1482
- return this.setAllSections(true);
1483
- },
1484
- collapseAll() {
1485
- return this.setAllSections(false);
1486
- },
1487
- setAllViews(state) {
1488
- return this.setSections(
1489
- this.sections.map(
1490
- (s) => s.label === "Views" ? s.setItems(s.items.map((v) => v.setIsExpanded(state))) : s
1491
- )
1492
- );
1493
- },
1494
- expandAllViews() {
1495
- return this.setAllViews(true);
1496
- },
1497
- collapseAllViews() {
1498
- return this.setAllViews(false);
1499
1275
  }
1500
1276
  },
1501
1277
  intent: {
1502
- toggleAllSections(state) {
1503
- return this.setAllSections(state);
1278
+ toggleAllSections(draft, state) {
1279
+ for (const section of draft.sections) section.isExpanded = state;
1504
1280
  },
1505
- toggleAllViews(state) {
1506
- 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;
1507
1284
  }
1508
1285
  },
1509
1286
  statics: {
@@ -1522,7 +1299,7 @@ var ComponentInspector = component5({
1522
1299
  (f) => CompField.make({
1523
1300
  name: f.name,
1524
1301
  typeName: f.type,
1525
- child: ImInspector.Class.fromData(f.defaultValue)
1302
+ child: DataInspector.Class.fromData(f.defaultValue)
1526
1303
  })
1527
1304
  ),
1528
1305
  true
@@ -1539,7 +1316,7 @@ var ComponentInspector = component5({
1539
1316
  return this.make({ compName: d.name, compId: d.id, sections });
1540
1317
  }
1541
1318
  },
1542
- 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">
1543
1320
  <div class="inline-flex items-center gap-2">
1544
1321
  <span class="font-semibold" @text=".compName"></span>
1545
1322
  <span class="text-base-content/40 text-xs" @text="$idText"></span>
@@ -1547,12 +1324,12 @@ var ComponentInspector = component5({
1547
1324
  <x render-each=".sections"></x>
1548
1325
  </div>`
1549
1326
  });
1550
- function getComponents5() {
1327
+ function getComponents4() {
1551
1328
  return [ComponentInspector, CompSection, CompField, CompName, CompView, ...getComponents2()];
1552
1329
  }
1553
1330
 
1554
1331
  // src/components/tutuca/lint-inspector.js
1555
- import { component as component6, html as html6 } from "tutuca";
1332
+ import { component as component5, html as html5 } from "tutuca";
1556
1333
  var tagDisplay = (tag) => tag ? String(tag).toLowerCase() : "";
1557
1334
  function originSuffix(info) {
1558
1335
  if (!info) return "";
@@ -1596,8 +1373,8 @@ function lintMessage(id, info = {}) {
1596
1373
  return `'$${info.name}' calls a method, but '${info.name}' is a field — use '.${info.name}'${originSuffix(info)}`;
1597
1374
  case "RECEIVE_HANDLER_NOT_IMPLEMENTED":
1598
1375
  return `Receive handler '${info.name}' is not implemented${eventSuffix(info)}`;
1599
- case "RECEIVE_HANDLER_METHOD_NOT_IMPLEMENTED":
1600
- return `Method '$${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}'`;
1601
1378
  case "ALT_HANDLER_NOT_DEFINED":
1602
1379
  return `Alter handler '${info.name}' is not defined${originSuffix(info)}`;
1603
1380
  case "DYN_VAL_NOT_DEFINED":
@@ -1631,7 +1408,7 @@ var componentView = makeCompositeView({
1631
1408
  typeClass: "font-semibold",
1632
1409
  borderClass: "border-base-content/15"
1633
1410
  });
1634
- var LintFinding = component6({
1411
+ var LintFinding = component5({
1635
1412
  name: "LintFinding",
1636
1413
  fields: { id: "", level: "", message: "", suggestion: "", detail: null },
1637
1414
  methods: {
@@ -1655,11 +1432,11 @@ var LintFinding = component6({
1655
1432
  },
1656
1433
  // Decoy so the runtime-built soft badge colours survive the class scan.
1657
1434
  views: {
1658
- _palette: html6`<span
1435
+ _palette: html5`<span
1659
1436
  class="badge-soft badge-error badge-warning badge-neutral"
1660
1437
  ></span>`
1661
1438
  },
1662
- 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">
1663
1440
  <div class="flex items-baseline gap-2 flex-wrap">
1664
1441
  <span :class="$levelBadgeClass" @text=".level"></span>
1665
1442
  <span class="text-sm text-base-content/90" @text=".message"></span>
@@ -1682,10 +1459,10 @@ function buildFinding(f) {
1682
1459
  level: f.level ?? "",
1683
1460
  message: lintMessage(f.id, info),
1684
1461
  suggestion: suggestionText(f.suggestion),
1685
- detail: ImInspector.Class.fromData({ id: f.id, info, context: ctx })
1462
+ detail: DataInspector.Class.fromData({ id: f.id, info, context: ctx })
1686
1463
  });
1687
1464
  }
1688
- var LintComponent = component6({
1465
+ var LintComponent = component5({
1689
1466
  name: "LintComponent",
1690
1467
  fields: { ...compositeFields, componentName: "", errors: 0, warns: 0, hints: 0 },
1691
1468
  methods: {
@@ -1701,10 +1478,11 @@ var LintComponent = component6({
1701
1478
  return parts.length ? parts.join(", ") : "ok";
1702
1479
  }
1703
1480
  },
1481
+ receive: compositeReceive,
1704
1482
  alter: compositeAlter,
1705
1483
  view: componentView
1706
1484
  });
1707
- var LintReport = component6({
1485
+ var LintReport = component5({
1708
1486
  name: "LintReport",
1709
1487
  fields: {
1710
1488
  title: "",
@@ -1775,11 +1553,11 @@ var LintReport = component6({
1775
1553
  },
1776
1554
  // Decoy so the runtime-absent soft tally colours are emitted.
1777
1555
  views: {
1778
- _palette: html6`<span
1556
+ _palette: html5`<span
1779
1557
  class="badge-soft badge-error badge-warning badge-neutral badge-success"
1780
1558
  ></span>`
1781
1559
  },
1782
- 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">
1783
1561
  <div class="flex items-center gap-2 flex-wrap">
1784
1562
  <span class="font-semibold" @text=".title"></span>
1785
1563
  <span class="text-base-content/40 text-xs" @text=".path"></span>
@@ -1807,12 +1585,12 @@ var LintReport = component6({
1807
1585
  <x render-each=".components"></x>
1808
1586
  </div>`
1809
1587
  });
1810
- function getComponents6() {
1588
+ function getComponents5() {
1811
1589
  return [LintReport, LintComponent, LintFinding, ...getComponents2()];
1812
1590
  }
1813
1591
 
1814
1592
  // src/components/tutuca/test-inspector.js
1815
- import { component as component7, html as html7 } from "tutuca";
1593
+ import { component as component6, html as html6 } from "tutuca";
1816
1594
  function collectTests(getTests) {
1817
1595
  const root = { children: [] };
1818
1596
  const stack = [root];
@@ -1845,7 +1623,7 @@ var suiteView = makeCompositeView({
1845
1623
  // it can expand/collapse every suite at once (like the component inspector).
1846
1624
  toggleHandler: "toggle isCtrl"
1847
1625
  });
1848
- var TestCase = component7({
1626
+ var TestCase = component6({
1849
1627
  name: "TestCase",
1850
1628
  fields: { title: "", status: "", durationMs: 0, message: "", detail: null },
1851
1629
  methods: {
@@ -1884,9 +1662,9 @@ var TestCase = component7({
1884
1662
  },
1885
1663
  // Decoy so the runtime-built mark colors survive the margaui class scan.
1886
1664
  views: {
1887
- _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>`
1888
1666
  },
1889
- 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">
1890
1668
  <div class="flex items-center gap-2">
1891
1669
  <span :class="$markClass" @text="$mark"></span>
1892
1670
  <span class="font-mono text-sm" @text=".title"></span>
@@ -1896,7 +1674,7 @@ var TestCase = component7({
1896
1674
  <div @show="$hasDetail" class="ml-5"><x render=".detail"></x></div>
1897
1675
  </div>`
1898
1676
  });
1899
- var TestSuite = component7({
1677
+ var TestSuite = component6({
1900
1678
  name: "TestSuite",
1901
1679
  fields: { ...compositeFields, title: "", summary: "" },
1902
1680
  methods: {
@@ -1905,24 +1683,26 @@ var TestSuite = component7({
1905
1683
  return this.title;
1906
1684
  },
1907
1685
  countText() {
1908
- return this.summary || `(${this.items.size})`;
1686
+ return this.summary || `(${this.items.length})`;
1909
1687
  }
1910
1688
  },
1911
1689
  receive: {
1912
- toggle(isCtrl, ctx) {
1690
+ ...compositeReceive,
1691
+ toggle(draft, isCtrl, ctx) {
1913
1692
  if (isCtrl) {
1914
1693
  ctx.intent("toggleAll", [!this.isExpanded], { route: ["dyn"] });
1915
1694
  return this;
1916
1695
  }
1917
- return this.toggleIsExpanded();
1696
+ draft.isExpanded = !draft.isExpanded;
1918
1697
  }
1919
1698
  },
1920
1699
  alter: compositeAlter,
1921
1700
  view: suiteView
1922
1701
  });
1923
1702
  function setSuiteTreeExpanded(node, state) {
1924
- if (typeof node.setIsExpanded !== "function") return node;
1925
- 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);
1926
1706
  }
1927
1707
  function buildDefNode(node) {
1928
1708
  if (Array.isArray(node.children)) {
@@ -1956,7 +1736,7 @@ function buildResultNode(node) {
1956
1736
  status,
1957
1737
  durationMs: node.durationMs ?? 0,
1958
1738
  message: err?.message ?? "",
1959
- 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
1960
1740
  });
1961
1741
  return {
1962
1742
  comp,
@@ -1965,7 +1745,7 @@ function buildResultNode(node) {
1965
1745
  skip: status === "skip" ? 1 : 0
1966
1746
  };
1967
1747
  }
1968
- var TestReport = component7({
1748
+ var TestReport = component6({
1969
1749
  name: "TestReport",
1970
1750
  fields: {
1971
1751
  title: "",
@@ -1991,15 +1771,12 @@ var TestReport = component7({
1991
1771
  },
1992
1772
  hasSkips() {
1993
1773
  return this.hasCounts && this.skip > 0;
1994
- },
1995
- setAllSuites(state) {
1996
- return this.setSuites(this.suites.map((s) => setSuiteTreeExpanded(s, state)));
1997
1774
  }
1998
1775
  },
1999
1776
  intent: {
2000
1777
  // ctrl/cmd-click on any suite expands/collapses the whole tree at once.
2001
- toggleAll(state) {
2002
- return this.setAllSuites(state);
1778
+ toggleAll(draft, state) {
1779
+ for (const suite of draft.suites) setSuiteTreeExpanded(suite, state);
2003
1780
  }
2004
1781
  },
2005
1782
  statics: {
@@ -2026,7 +1803,7 @@ var TestReport = component7({
2026
1803
  });
2027
1804
  }
2028
1805
  },
2029
- 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">
2030
1807
  <div class="flex items-center gap-2 flex-wrap">
2031
1808
  <span class="font-semibold" @text=".title"></span>
2032
1809
  <span class="text-base-content/40 text-xs" @text=".path"></span>
@@ -2049,17 +1826,17 @@ var TestReport = component7({
2049
1826
  <x render-each=".suites"></x>
2050
1827
  </div>`
2051
1828
  });
2052
- function getComponents7() {
1829
+ function getComponents6() {
2053
1830
  return [TestReport, TestSuite, TestCase, ...getComponents2()];
2054
1831
  }
2055
1832
 
2056
1833
  // src/components/tutuca/instance-inspector.js
2057
- var isComponentInstance = (v) => isRecord(v) && typeof v?.constructor?.getMetaClass === "function";
1834
+ var isComponentInstance = (v) => v !== null && typeof v === "object" && typeof v?.constructor?.getMetaClass === "function";
2058
1835
  var fieldsView = makeCompositeView({
2059
1836
  typeClass: "font-semibold",
2060
1837
  borderClass: "border-base-content/15"
2061
1838
  });
2062
- var InstanceFields = component8({
1839
+ var InstanceFields = component7({
2063
1840
  name: "InstanceFields",
2064
1841
  fields: { ...compositeFields, typeName: "" },
2065
1842
  methods: {
@@ -2068,17 +1845,18 @@ var InstanceFields = component8({
2068
1845
  return this.typeName;
2069
1846
  },
2070
1847
  countText() {
2071
- return `{${this.items.size}}`;
1848
+ return `{${this.items.length}}`;
2072
1849
  }
2073
1850
  },
1851
+ receive: compositeReceive,
2074
1852
  alter: compositeAlter,
2075
1853
  statics: {
2076
1854
  fromData(instance, comp) {
2077
1855
  const d = introspectComponent(comp);
2078
1856
  const items = d.fields.map(
2079
- (f) => ImEntry.make({
1857
+ (f) => JsonProperty.make({
2080
1858
  key: f.name,
2081
- child: ImInspector.Class.fromData(instance.get(f.name))
1859
+ child: DataInspector.Class.fromData(instance[f.name])
2082
1860
  })
2083
1861
  );
2084
1862
  return this.make({ typeName: d.name, items, isExpanded: true });
@@ -2089,7 +1867,7 @@ var InstanceFields = component8({
2089
1867
  var InstanceInspector = makeValueInspector({
2090
1868
  name: "InstanceInspector",
2091
1869
  fromData(instance, comp) {
2092
- 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);
2093
1871
  return this.make({ value });
2094
1872
  }
2095
1873
  });
@@ -2101,7 +1879,7 @@ function asLintView(lint) {
2101
1879
  if (lint == null) return null;
2102
1880
  return isComponentInstance(lint) ? lint : LintReport.Class.fromData(lint);
2103
1881
  }
2104
- var InstanceExplorer = component8({
1882
+ var InstanceExplorer = component7({
2105
1883
  name: "InstanceExplorer",
2106
1884
  fields: {
2107
1885
  activeTab: "instance",
@@ -2128,14 +1906,19 @@ var InstanceExplorer = component8({
2128
1906
  });
2129
1907
  }
2130
1908
  },
2131
- 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">
2132
1915
  <div role="tablist" class="tabs">
2133
1916
  <a
2134
1917
  role="tab"
2135
1918
  @if.class="equals? .activeTab 'instance'"
2136
1919
  @then="'tab tab-active'"
2137
1920
  @else="'tab'"
2138
- @on.click="$setActiveTab 'instance'"
1921
+ @on.click="setActiveTab 'instance'"
2139
1922
  >
2140
1923
  Instance
2141
1924
  </a>
@@ -2145,7 +1928,7 @@ var InstanceExplorer = component8({
2145
1928
  @if.class="equals? .activeTab 'component'"
2146
1929
  @then="'tab tab-active'"
2147
1930
  @else="'tab'"
2148
- @on.click="$setActiveTab 'component'"
1931
+ @on.click="setActiveTab 'component'"
2149
1932
  >
2150
1933
  Component
2151
1934
  </a>
@@ -2155,7 +1938,7 @@ var InstanceExplorer = component8({
2155
1938
  @if.class="equals? .activeTab 'tests'"
2156
1939
  @then="'tab tab-active'"
2157
1940
  @else="'tab'"
2158
- @on.click="$setActiveTab 'tests'"
1941
+ @on.click="setActiveTab 'tests'"
2159
1942
  >
2160
1943
  Tests
2161
1944
  </a>
@@ -2165,7 +1948,7 @@ var InstanceExplorer = component8({
2165
1948
  @if.class="equals? .activeTab 'lint'"
2166
1949
  @then="'tab tab-active'"
2167
1950
  @else="'tab'"
2168
- @on.click="$setActiveTab 'lint'"
1951
+ @on.click="setActiveTab 'lint'"
2169
1952
  >
2170
1953
  Lint
2171
1954
  </a>
@@ -2187,14 +1970,14 @@ var InstanceExplorer = component8({
2187
1970
  </div>
2188
1971
  </div>`
2189
1972
  });
2190
- function getComponents8() {
1973
+ function getComponents7() {
2191
1974
  const all = [
2192
1975
  InstanceExplorer,
2193
1976
  InstanceInspector,
2194
1977
  InstanceFields,
2195
- ...getComponents5(),
2196
- ...getComponents7(),
2197
- ...getComponents6()
1978
+ ...getComponents4(),
1979
+ ...getComponents6(),
1980
+ ...getComponents5()
2198
1981
  ];
2199
1982
  const seen = /* @__PURE__ */ new Set();
2200
1983
  return all.filter((c) => {
@@ -2206,7 +1989,7 @@ function getComponents8() {
2206
1989
 
2207
1990
  // src/components/tutuca/activity-inspector.js
2208
1991
  var ACTIVITY_CAP = 50;
2209
- var ActivityEntry = component9({
1992
+ var ActivityEntry = component8({
2210
1993
  name: "ActivityEntry",
2211
1994
  fields: {
2212
1995
  kind: "",
@@ -2219,7 +2002,7 @@ var ActivityEntry = component9({
2219
2002
  after: null,
2220
2003
  hasAfter: true
2221
2004
  },
2222
- view: html9`<div
2005
+ view: html8`<div
2223
2006
  class="rounded border border-base-content/15 p-2 text-sm flex flex-col gap-1"
2224
2007
  >
2225
2008
  <div class="flex items-center gap-2 flex-wrap">
@@ -2268,15 +2051,13 @@ var ActivityEntry = component9({
2268
2051
  </div>
2269
2052
  </div>`
2270
2053
  });
2271
- var ActivityLog = component9({
2054
+ var ActivityLog = component8({
2272
2055
  name: "ActivityLog",
2273
2056
  fields: { events: [], hasEvents: false },
2274
- methods: {
2275
- appendEntry(entry) {
2276
- return this.setEvents(this.events.unshift(entry).slice(0, ACTIVITY_CAP)).setHasEvents(true);
2277
- }
2057
+ statics: {
2058
+ cap: ACTIVITY_CAP
2278
2059
  },
2279
- 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">
2280
2061
  <div class="text-xs opacity-40" @hide=".hasEvents">
2281
2062
  No activity yet — interact with the component.
2282
2063
  </div>
@@ -2314,7 +2095,7 @@ function recordToEntry(record, { inspect, pathLabel = pathKeysLabel } = {}) {
2314
2095
  hasAfter
2315
2096
  });
2316
2097
  }
2317
- function getComponents9() {
2098
+ function getComponents8() {
2318
2099
  return [ActivityLog, ActivityEntry];
2319
2100
  }
2320
2101
 
@@ -2356,16 +2137,15 @@ async function buildInspectorViews(value, scope, { getTests = null, components =
2356
2137
  }
2357
2138
 
2358
2139
  // src/components/index.js
2359
- function getComponents10() {
2140
+ function getComponents9() {
2360
2141
  const all = [
2361
- ...getComponents9(),
2362
- ...getComponents5(),
2363
2142
  ...getComponents8(),
2364
- ...getComponents6(),
2365
- ...getComponents7(),
2366
- ...getComponents3(),
2367
2143
  ...getComponents4(),
2144
+ ...getComponents7(),
2145
+ ...getComponents5(),
2146
+ ...getComponents6(),
2368
2147
  ...getComponents2(),
2148
+ ...getComponents3(),
2369
2149
  ...getComponents()
2370
2150
  ];
2371
2151
  const seen = /* @__PURE__ */ new Set();
@@ -2384,16 +2164,6 @@ export {
2384
2164
  CompView,
2385
2165
  ComponentInspector,
2386
2166
  DataInspector,
2387
- ImEntry,
2388
- ImInspector,
2389
- ImList,
2390
- ImMap,
2391
- ImOMap,
2392
- ImOSet,
2393
- ImRange,
2394
- ImRecord,
2395
- ImSet,
2396
- ImStack,
2397
2167
  InstanceExplorer,
2398
2168
  InstanceFields,
2399
2169
  InstanceInspector,
@@ -2438,7 +2208,6 @@ export {
2438
2208
  buildInspectorViews,
2439
2209
  chain,
2440
2210
  classifyData,
2441
- classifyImmutable,
2442
2211
  classifyJsExtra,
2443
2212
  classifyJson,
2444
2213
  classifySchema,
@@ -2446,10 +2215,11 @@ export {
2446
2215
  compositeAlter,
2447
2216
  compositeFields,
2448
2217
  compositeMethods,
2218
+ compositeReceive,
2449
2219
  compositeView,
2450
2220
  fmtActivityTime,
2451
2221
  fmtAnyKey,
2452
- getComponents10 as getComponents,
2222
+ getComponents9 as getComponents,
2453
2223
  introspectComponent,
2454
2224
  isComponentInstance,
2455
2225
  lintMessage,