foldkit 0.82.9 → 0.84.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 (129) hide show
  1. package/README.md +1 -1
  2. package/dist/devTools/overlay.d.ts.map +1 -1
  3. package/dist/devTools/overlay.js +66 -4
  4. package/dist/devTools/protocol.d.ts +19 -2
  5. package/dist/devTools/protocol.d.ts.map +1 -1
  6. package/dist/devTools/protocol.js +5 -2
  7. package/dist/devTools/serialize.d.ts.map +1 -1
  8. package/dist/devTools/serialize.js +2 -0
  9. package/dist/devTools/store.d.ts +5 -1
  10. package/dist/devTools/store.d.ts.map +1 -1
  11. package/dist/devTools/store.js +37 -1
  12. package/dist/devTools/webSocketBridge.js +1 -0
  13. package/dist/html/index.d.ts +11 -0
  14. package/dist/html/index.d.ts.map +1 -1
  15. package/dist/html/index.js +58 -39
  16. package/dist/mount/index.d.ts +14 -1
  17. package/dist/mount/index.d.ts.map +1 -1
  18. package/dist/mount/index.js +9 -1
  19. package/dist/mount/public.d.ts +1 -1
  20. package/dist/mount/public.d.ts.map +1 -1
  21. package/dist/mount/public.js +1 -1
  22. package/dist/runtime/runtime.d.ts.map +1 -1
  23. package/dist/runtime/runtime.js +38 -3
  24. package/dist/scene/public.d.ts +2 -0
  25. package/dist/scene/public.d.ts.map +1 -0
  26. package/dist/scene/public.js +1 -0
  27. package/dist/story/public.d.ts +2 -0
  28. package/dist/story/public.d.ts.map +1 -0
  29. package/dist/story/public.js +1 -0
  30. package/dist/test/apps/mountPanel.d.ts +42 -0
  31. package/dist/test/apps/mountPanel.d.ts.map +1 -0
  32. package/dist/test/apps/mountPanel.js +76 -0
  33. package/dist/test/internal.d.ts +38 -0
  34. package/dist/test/internal.d.ts.map +1 -1
  35. package/dist/test/internal.js +75 -0
  36. package/dist/test/scene.d.ts +37 -14
  37. package/dist/test/scene.d.ts.map +1 -1
  38. package/dist/test/scene.js +141 -8
  39. package/dist/test/story.d.ts +17 -13
  40. package/dist/test/story.d.ts.map +1 -1
  41. package/dist/test/story.js +19 -5
  42. package/dist/ui/anchor.d.ts +6 -0
  43. package/dist/ui/anchor.d.ts.map +1 -1
  44. package/dist/ui/anchor.js +27 -16
  45. package/dist/ui/animation/index.d.ts +4 -4
  46. package/dist/ui/animation/index.d.ts.map +1 -1
  47. package/dist/ui/button/index.d.ts +6 -6
  48. package/dist/ui/button/index.d.ts.map +1 -1
  49. package/dist/ui/calendar/index.js +2 -2
  50. package/dist/ui/checkbox/index.d.ts +10 -10
  51. package/dist/ui/checkbox/index.d.ts.map +1 -1
  52. package/dist/ui/checkbox/index.js +2 -2
  53. package/dist/ui/combobox/multi.d.ts +18 -14
  54. package/dist/ui/combobox/multi.d.ts.map +1 -1
  55. package/dist/ui/combobox/multi.js +2 -2
  56. package/dist/ui/combobox/public.d.ts +1 -1
  57. package/dist/ui/combobox/public.d.ts.map +1 -1
  58. package/dist/ui/combobox/public.js +1 -1
  59. package/dist/ui/combobox/shared.d.ts +44 -13
  60. package/dist/ui/combobox/shared.d.ts.map +1 -1
  61. package/dist/ui/combobox/shared.js +27 -4
  62. package/dist/ui/combobox/single.d.ts +18 -14
  63. package/dist/ui/combobox/single.d.ts.map +1 -1
  64. package/dist/ui/combobox/single.js +2 -2
  65. package/dist/ui/datePicker/index.d.ts +1 -1
  66. package/dist/ui/datePicker/index.js +2 -2
  67. package/dist/ui/dialog/index.d.ts +8 -8
  68. package/dist/ui/dialog/index.d.ts.map +1 -1
  69. package/dist/ui/dialog/index.js +2 -2
  70. package/dist/ui/disclosure/index.d.ts +8 -8
  71. package/dist/ui/disclosure/index.d.ts.map +1 -1
  72. package/dist/ui/disclosure/index.js +2 -2
  73. package/dist/ui/dragAndDrop/index.d.ts +5 -5
  74. package/dist/ui/dragAndDrop/index.d.ts.map +1 -1
  75. package/dist/ui/fieldset/index.d.ts +7 -7
  76. package/dist/ui/fieldset/index.d.ts.map +1 -1
  77. package/dist/ui/fileDrop/index.js +2 -2
  78. package/dist/ui/input/index.d.ts +8 -8
  79. package/dist/ui/input/index.d.ts.map +1 -1
  80. package/dist/ui/listbox/multi.d.ts +16 -12
  81. package/dist/ui/listbox/multi.d.ts.map +1 -1
  82. package/dist/ui/listbox/multi.js +2 -2
  83. package/dist/ui/listbox/public.d.ts +1 -1
  84. package/dist/ui/listbox/public.d.ts.map +1 -1
  85. package/dist/ui/listbox/public.js +1 -1
  86. package/dist/ui/listbox/shared.d.ts +35 -11
  87. package/dist/ui/listbox/shared.d.ts.map +1 -1
  88. package/dist/ui/listbox/shared.js +22 -3
  89. package/dist/ui/listbox/single.d.ts +16 -12
  90. package/dist/ui/listbox/single.d.ts.map +1 -1
  91. package/dist/ui/listbox/single.js +2 -2
  92. package/dist/ui/menu/index.d.ts +34 -12
  93. package/dist/ui/menu/index.d.ts.map +1 -1
  94. package/dist/ui/menu/index.js +24 -5
  95. package/dist/ui/menu/public.d.ts +1 -1
  96. package/dist/ui/menu/public.d.ts.map +1 -1
  97. package/dist/ui/menu/public.js +1 -1
  98. package/dist/ui/popover/index.d.ts +26 -10
  99. package/dist/ui/popover/index.d.ts.map +1 -1
  100. package/dist/ui/popover/index.js +20 -4
  101. package/dist/ui/popover/public.d.ts +1 -1
  102. package/dist/ui/popover/public.d.ts.map +1 -1
  103. package/dist/ui/popover/public.js +1 -1
  104. package/dist/ui/radioGroup/index.d.ts +13 -13
  105. package/dist/ui/radioGroup/index.d.ts.map +1 -1
  106. package/dist/ui/radioGroup/index.js +2 -2
  107. package/dist/ui/select/index.d.ts +8 -8
  108. package/dist/ui/select/index.d.ts.map +1 -1
  109. package/dist/ui/slider/index.d.ts +12 -12
  110. package/dist/ui/slider/index.d.ts.map +1 -1
  111. package/dist/ui/slider/index.js +2 -2
  112. package/dist/ui/switch/index.d.ts +10 -10
  113. package/dist/ui/switch/index.d.ts.map +1 -1
  114. package/dist/ui/switch/index.js +2 -2
  115. package/dist/ui/tabs/index.d.ts +11 -11
  116. package/dist/ui/tabs/index.d.ts.map +1 -1
  117. package/dist/ui/tabs/index.js +2 -2
  118. package/dist/ui/textarea/index.d.ts +8 -8
  119. package/dist/ui/textarea/index.d.ts.map +1 -1
  120. package/dist/ui/toast/index.js +2 -2
  121. package/dist/ui/tooltip/index.d.ts +14 -7
  122. package/dist/ui/tooltip/index.d.ts.map +1 -1
  123. package/dist/ui/tooltip/index.js +6 -3
  124. package/dist/ui/tooltip/public.d.ts +1 -1
  125. package/dist/ui/tooltip/public.d.ts.map +1 -1
  126. package/dist/ui/tooltip/public.js +1 -1
  127. package/dist/ui/virtualList/index.d.ts +4 -4
  128. package/dist/ui/virtualList/index.d.ts.map +1 -1
  129. package/package.json +9 -1
package/README.md CHANGED
@@ -153,7 +153,7 @@ Foldkit is a complete system, not a collection of libraries you stitch together.
153
153
  - **DevTools**: Built-in overlay for inspecting Messages, Model state, and Commands. Time-travel mode rewinds your UI to any past Model, Inspect mode browses snapshots without pausing, and Submodel drill-in filtering scopes the Message list to any nested module.
154
154
  - **DevTools MCP**: Expose a running Foldkit app to AI agents over the Model Context Protocol. Agents read the current Model, list and inspect Message history, rewind the UI to any past Model, and dispatch Messages into the runtime. To dispatch, agents read your application source to learn the Message Schema; the runtime decodes every payload against the Schema and returns a clean error if the shape does not match. One command sets it up: `npx @foldkit/devtools-mcp init`.
155
155
  - **Crash View and Reporting**: Configure `crash.view` to render a custom fallback UI when the update loop throws. A `crash.report` callback fires first with the error, Model, and triggering Message, so you can ship it straight to Sentry or your logger.
156
- - **Story Testing**: Exercise the update function directly. Send Messages, resolve Commands inline with `resolve` and `resolveAll`, and assert with focused helpers: `Story.model`, `Story.expectHasCommands`, `Story.expectExactCommands`, `Story.expectNoCommands`, and `Story.expectOutMessage`. No mocking libraries, no fake timers.
156
+ - **Story Testing**: Exercise the update function directly. Send Messages, resolve Commands inline with `Story.Command.resolve` and `Story.Command.resolveAll`, and assert with focused helpers: `Story.model`, `Story.Command.expectHas`, `Story.Command.expectExact`, `Story.Command.expectNone`, and `Story.expectOutMessage`. No mocking libraries, no fake timers.
157
157
  - **Scene Testing**: Drive your app the way a user does. Scene renders your real view, then clicks buttons, types into inputs, presses keys, and asserts on what's on screen. Accessible locators (`role`, `label`, `placeholder`, `altText`, `title`, `testId`, `displayValue`) with full options (`name`, `level`, `checked`, `selected`, `pressed`, `expanded`, `disabled`), multi-match `Scene.all` with `Scene.filter` and `Scene.nth`, scoped steps via `Scene.inside`, pointer events, event bubbling, and Vitest matchers like `toHaveText`, `toBeVisible`, `toHaveAccessibleName`, and `toHaveCount`. API parity with React Testing Library and Playwright, without a browser.
158
158
  - **Slow-View Monitoring**: Wire `slowView` on `makeProgram` to catch renders that exceed a threshold you set. The callback fires with the current Model, the triggering Message, and the render duration, so you can log it, sample it, or ship it to your observability tool.
159
159
  - **HMR**: Vite plugin with state-preserving hot module replacement. Change your view, keep your state.
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAGN,OAAO,EAGP,MAAM,EAUP,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAW9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAQ3E,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,YAAY,CAAA;AA4N5E,eAAO,MAAM,MAAM;;EAA0C,CAAA;AAC7D,eAAO,MAAM,YAAY;;;;;;EAGxB,CAAA;AACD,eAAO,MAAM,aAAa;;;;;;EAGzB,CAAA;AACD,eAAO,MAAM,MAAM;;EAA4C,CAAA;AAC/D,eAAO,MAAM,KAAK;;EAA0C,CAAA;AAC5D,eAAO,MAAM,UAAU;;EAA6C,CAAA;AACpE,eAAO,MAAM,YAAY;;EAAiD,CAAA;AAC1E,eAAO,MAAM,WAAW;;EAA+C,CAAA;AA+2CvE,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCAoDhC,CAAA"}
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAGN,OAAO,EAGP,MAAM,EAUP,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAW9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAQ3E,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,YAAY,CAAA;AAqO5E,eAAO,MAAM,MAAM;;EAA0C,CAAA;AAC7D,eAAO,MAAM,YAAY;;;;;;EAGxB,CAAA;AACD,eAAO,MAAM,aAAa;;;;;;EAGzB,CAAA;AACD,eAAO,MAAM,MAAM;;EAA4C,CAAA;AAC/D,eAAO,MAAM,KAAK;;EAA0C,CAAA;AAC5D,eAAO,MAAM,UAAU;;EAA6C,CAAA;AACpE,eAAO,MAAM,YAAY;;EAAiD,CAAA;AAC1E,eAAO,MAAM,WAAW;;EAA+C,CAAA;AAs9CvE,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCAoDhC,CAAA"}
@@ -20,6 +20,8 @@ const DisplayEntry = S.Struct({
20
20
  submodelPath: S.Array(S.String),
21
21
  maybeLeafTag: S.Option(S.String),
22
22
  commandNames: S.Array(S.String),
23
+ mountStartNames: S.Array(S.String),
24
+ mountEndNames: S.Array(S.String),
23
25
  timestamp: S.Number,
24
26
  isModelChanged: S.Boolean,
25
27
  });
@@ -48,6 +50,7 @@ const Model = S.Struct({
48
50
  isMobile: S.Boolean,
49
51
  entries: S.Array(DisplayEntry),
50
52
  initCommandNames: S.Array(S.String),
53
+ initMountStartNames: S.Array(S.String),
51
54
  startIndex: S.Number,
52
55
  isPaused: S.Boolean,
53
56
  pausedAtIndex: S.Number,
@@ -67,6 +70,7 @@ const Flags = S.Struct({
67
70
  isMobile: S.Boolean,
68
71
  entries: S.Array(DisplayEntry),
69
72
  initCommandNames: S.Array(S.String),
73
+ initMountStartNames: S.Array(S.String),
70
74
  startIndex: S.Number,
71
75
  isPaused: S.Boolean,
72
76
  pausedAtIndex: S.Number,
@@ -99,6 +103,7 @@ const GotInspectorTabsMessage = m('GotInspectorTabsMessage', {
99
103
  const ReceivedStoreUpdate = m('ReceivedStoreUpdate', {
100
104
  entries: S.Array(DisplayEntry),
101
105
  initCommandNames: S.Array(S.String),
106
+ initMountStartNames: S.Array(S.String),
102
107
  startIndex: S.Number,
103
108
  isPaused: S.Boolean,
104
109
  pausedAtIndex: S.Number,
@@ -137,6 +142,7 @@ const TREE_INDENT_PX = 12;
137
142
  const MAX_PREVIEW_KEYS = 3;
138
143
  const ALL_MESSAGES_VALUE = '';
139
144
  const NO_COMMANDS = [];
145
+ const NO_MOUNTS = [];
140
146
  const formatTimeDelta = (deltaMs) => M.value(deltaMs).pipe(M.when(0, () => '0ms'), M.when(Number_.isLessThan(MILLIS_PER_SECOND), ms => `+${Math.round(ms)}ms`), M.orElse(ms => `+${(ms / MILLIS_PER_SECOND).toFixed(1)}s`));
141
147
  const MESSAGE_LIST_SELECTOR = '.message-list';
142
148
  const computeSubmodelTags = (entries) => pipe(entries, Array_.flatMap(({ submodelPath }) => submodelPath), Array_.dedupe, Array_.sort(Order.String));
@@ -147,6 +153,8 @@ const toDisplayEntries = ({ entries }) => Array_.map(entries, entry => {
147
153
  submodelPath,
148
154
  maybeLeafTag,
149
155
  commandNames: entry.commandNames,
156
+ mountStartNames: entry.mountStartNames,
157
+ mountEndNames: entry.mountEndNames,
150
158
  timestamp: entry.timestamp,
151
159
  isModelChanged: entry.isModelChanged,
152
160
  };
@@ -154,6 +162,7 @@ const toDisplayEntries = ({ entries }) => Array_.map(entries, entry => {
154
162
  const toDisplayState = (state) => ({
155
163
  entries: toDisplayEntries(state),
156
164
  initCommandNames: state.initCommandNames,
165
+ initMountStartNames: state.initMountStartNames,
157
166
  startIndex: state.startIndex,
158
167
  isPaused: state.isPaused,
159
168
  pausedAtIndex: state.pausedAtIndex,
@@ -299,7 +308,7 @@ const makeUpdate = (store, shadow, mode) => {
299
308
  }),
300
309
  [],
301
310
  ],
302
- ReceivedStoreUpdate: ({ entries, initCommandNames, startIndex, isPaused, pausedAtIndex, }) => {
311
+ ReceivedStoreUpdate: ({ entries, initCommandNames, initMountStartNames, startIndex, isPaused, pausedAtIndex, }) => {
303
312
  const shouldFollowLatest = M.value(mode).pipe(M.when('TimeTravel', () => !isPaused), M.when('Inspect', () => model.isFollowingLatest), M.exhaustive);
304
313
  const latestIndex = Array_.match(entries, {
305
314
  onEmpty: () => INIT_INDEX,
@@ -311,6 +320,7 @@ const makeUpdate = (store, shadow, mode) => {
311
320
  evo(model, {
312
321
  entries: () => entries,
313
322
  initCommandNames: () => initCommandNames,
323
+ initMountStartNames: () => initMountStartNames,
314
324
  startIndex: () => startIndex,
315
325
  isPaused: () => isPaused,
316
326
  pausedAtIndex: () => pausedAtIndex,
@@ -547,6 +557,7 @@ const makeView = (position, mode, maybeBanner) => {
547
557
  'Model',
548
558
  'Message',
549
559
  'Commands',
560
+ 'Mounts',
550
561
  ];
551
562
  const noMessageView = div([
552
563
  Class('flex-1 flex items-center justify-center text-dt-muted text-2xs font-mono min-w-0'),
@@ -589,12 +600,15 @@ const makeView = (position, mode, maybeBanner) => {
589
600
  ]);
590
601
  },
591
602
  });
603
+ const selectedHistoryIndex = (model) => M.value(mode).pipe(M.when('TimeTravel', () => model.isPaused ? model.pausedAtIndex : INIT_INDEX), M.when('Inspect', () => model.selectedIndex), M.exhaustive);
592
604
  const selectedCommandNames = (model) => {
593
- const selectedIndex = M.value(mode).pipe(M.when('TimeTravel', () => model.isPaused ? model.pausedAtIndex : INIT_INDEX), M.when('Inspect', () => model.selectedIndex), M.exhaustive);
605
+ const selectedIndex = selectedHistoryIndex(model);
594
606
  if (selectedIndex === INIT_INDEX) {
595
607
  return model.initCommandNames;
596
608
  }
597
- return pipe(Array_.get(model.entries, selectedIndex - model.startIndex), Option.map(entry => entry.commandNames), Option.getOrElse(() => NO_COMMANDS));
609
+ else {
610
+ return pipe(model.entries, Array_.get(selectedIndex - model.startIndex), Option.map(entry => entry.commandNames), Option.getOrElse(() => NO_COMMANDS));
611
+ }
598
612
  };
599
613
  const commandsTabContent = (commandNames) => Array_.match(commandNames, {
600
614
  onEmpty: () => div([
@@ -609,6 +623,51 @@ const makeView = (position, mode, maybeBanner) => {
609
623
  span([Class('json-tag')], [name]),
610
624
  ]))),
611
625
  });
626
+ const selectedMountActivity = (model) => {
627
+ const selectedIndex = selectedHistoryIndex(model);
628
+ if (selectedIndex === INIT_INDEX) {
629
+ return { starts: model.initMountStartNames, ends: NO_MOUNTS };
630
+ }
631
+ else {
632
+ return pipe(model.entries, Array_.get(selectedIndex - model.startIndex), Option.match({
633
+ onNone: () => ({ starts: NO_MOUNTS, ends: NO_MOUNTS }),
634
+ onSome: entry => ({
635
+ starts: entry.mountStartNames,
636
+ ends: entry.mountEndNames,
637
+ }),
638
+ }));
639
+ }
640
+ };
641
+ const mountListSection = (label, names) => div([Class('flex flex-col shrink-0')], [
642
+ div([
643
+ Class('px-2 py-1 border-b text-2xs text-dt-muted font-mono shrink-0'),
644
+ ], [label]),
645
+ ...Array_.map(names, (name, index) => div([
646
+ Class('flex items-center px-2 py-1 text-base font-mono text-dt border-b gap-1.5'),
647
+ ], [
648
+ span([Class(indexClass)], [String(index + 1)]),
649
+ span([Class('json-tag')], [name]),
650
+ ])),
651
+ ]);
652
+ const mountsTabContent = (starts, ends) => {
653
+ const hasAny = Array_.isReadonlyArrayNonEmpty(starts) ||
654
+ Array_.isReadonlyArrayNonEmpty(ends);
655
+ if (!hasAny) {
656
+ return div([
657
+ Class('flex-1 flex items-center justify-center text-dt-muted text-2xs font-mono min-w-0'),
658
+ ], ['No Mounts during this render']);
659
+ }
660
+ return div([
661
+ Class('flex flex-col flex-1 min-h-0 min-w-0 overflow-auto overscroll-none'),
662
+ ], [
663
+ ...(Array_.isReadonlyArrayNonEmpty(starts)
664
+ ? [mountListSection('Started', starts)]
665
+ : []),
666
+ ...(Array_.isReadonlyArrayNonEmpty(ends)
667
+ ? [mountListSection('Ended', ends)]
668
+ : []),
669
+ ]);
670
+ };
612
671
  const inspectorTabContent = (model, tab, inspectedModel) => M.value(tab).pipe(M.when('Model', () => lazyTabContent('Model', modelTabContent, [
613
672
  inspectedModel,
614
673
  model.expandedPaths,
@@ -621,7 +680,10 @@ const makeView = (position, mode, maybeBanner) => {
621
680
  inspectedTimestamp(model),
622
681
  ])), M.when('Commands', () => lazyTabContent('Commands', commandsTabContent, [
623
682
  selectedCommandNames(model),
624
- ])), M.exhaustive);
683
+ ])), M.when('Mounts', () => {
684
+ const { starts, ends } = selectedMountActivity(model);
685
+ return lazyTabContent('Mounts', mountsTabContent, [starts, ends]);
686
+ }), M.exhaustive);
625
687
  const inspectorPaneView = (model) => div([
626
688
  Class('flex flex-col border-l min-w-0 min-h-0 flex-1 dt-inspector-pane'),
627
689
  ], [
@@ -1,10 +1,12 @@
1
1
  import { Schema as S } from 'effect';
2
- /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. */
2
+ /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. `mountStartNames` lists Mounts that fired during the render after this Message; `mountEndNames` lists Mounts whose elements were unmounted during that render. The Messages dispatched by mount Effects appear as their own entries elsewhere in history. */
3
3
  export declare const SerializedEntry: S.Struct<{
4
4
  readonly index: S.Number;
5
5
  readonly tag: S.String;
6
6
  readonly message: S.Unknown;
7
7
  readonly commandNames: S.$Array<S.String>;
8
+ readonly mountStartNames: S.$Array<S.String>;
9
+ readonly mountEndNames: S.$Array<S.String>;
8
10
  readonly timestamp: S.Number;
9
11
  readonly isModelChanged: S.Boolean;
10
12
  readonly changedPaths: S.$Array<S.String>;
@@ -99,6 +101,8 @@ export declare const ResponseMessages: import("../schema/index.js").CallableTagg
99
101
  readonly tag: S.String;
100
102
  readonly message: S.Unknown;
101
103
  readonly commandNames: S.$Array<S.String>;
104
+ readonly mountStartNames: S.$Array<S.String>;
105
+ readonly mountEndNames: S.$Array<S.String>;
102
106
  readonly timestamp: S.Number;
103
107
  readonly isModelChanged: S.Boolean;
104
108
  readonly changedPaths: S.$Array<S.String>;
@@ -115,6 +119,8 @@ export declare const ResponseMessage: import("../schema/index.js").CallableTagge
115
119
  readonly tag: S.String;
116
120
  readonly message: S.Unknown;
117
121
  readonly commandNames: S.$Array<S.String>;
122
+ readonly mountStartNames: S.$Array<S.String>;
123
+ readonly mountEndNames: S.$Array<S.String>;
118
124
  readonly timestamp: S.Number;
119
125
  readonly isModelChanged: S.Boolean;
120
126
  readonly changedPaths: S.$Array<S.String>;
@@ -147,10 +153,11 @@ export declare const ResponseRuntimes: import("../schema/index.js").CallableTagg
147
153
  readonly title: S.String;
148
154
  }>>;
149
155
  }>;
150
- /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. */
156
+ /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. `mountStartNames` lists the Mounts that fired during the initial render. */
151
157
  export declare const ResponseInit: import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
152
158
  maybeModel: S.OptionFromNullOr<S.Unknown>;
153
159
  commandNames: S.$Array<S.String>;
160
+ mountStartNames: S.$Array<S.String>;
154
161
  }>;
155
162
  /** Response carrying a snapshot of the runtime's DevTools state. `currentIndex` is the absolute index of the most recently recorded Message, or -1 when no Messages have been recorded yet. `startIndex` is the earliest absolute index still retained in the rolling buffer (older entries are evicted past `maxEntries`). `totalEntries` is the number of retained entries. `isPaused` is true while the runtime is paused at a replayed snapshot; `maybePausedAtIndex` is `Some(index)` then and `None` otherwise. `hasInitModel` is true once the runtime has finished initialising. */
156
163
  export declare const ResponseRuntimeState: import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
@@ -176,6 +183,8 @@ export declare const Response: S.Union<readonly [import("../schema/index.js").Ca
176
183
  readonly tag: S.String;
177
184
  readonly message: S.Unknown;
178
185
  readonly commandNames: S.$Array<S.String>;
186
+ readonly mountStartNames: S.$Array<S.String>;
187
+ readonly mountEndNames: S.$Array<S.String>;
179
188
  readonly timestamp: S.Number;
180
189
  readonly isModelChanged: S.Boolean;
181
190
  readonly changedPaths: S.$Array<S.String>;
@@ -190,6 +199,8 @@ export declare const Response: S.Union<readonly [import("../schema/index.js").Ca
190
199
  readonly tag: S.String;
191
200
  readonly message: S.Unknown;
192
201
  readonly commandNames: S.$Array<S.String>;
202
+ readonly mountStartNames: S.$Array<S.String>;
203
+ readonly mountEndNames: S.$Array<S.String>;
193
204
  readonly timestamp: S.Number;
194
205
  readonly isModelChanged: S.Boolean;
195
206
  readonly changedPaths: S.$Array<S.String>;
@@ -214,6 +225,7 @@ export declare const Response: S.Union<readonly [import("../schema/index.js").Ca
214
225
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
215
226
  maybeModel: S.OptionFromNullOr<S.Unknown>;
216
227
  commandNames: S.$Array<S.String>;
228
+ mountStartNames: S.$Array<S.String>;
217
229
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
218
230
  currentIndex: S.Number;
219
231
  startIndex: S.Number;
@@ -287,6 +299,8 @@ export declare const ResponseFrame: S.Struct<{
287
299
  readonly tag: S.String;
288
300
  readonly message: S.Unknown;
289
301
  readonly commandNames: S.$Array<S.String>;
302
+ readonly mountStartNames: S.$Array<S.String>;
303
+ readonly mountEndNames: S.$Array<S.String>;
290
304
  readonly timestamp: S.Number;
291
305
  readonly isModelChanged: S.Boolean;
292
306
  readonly changedPaths: S.$Array<S.String>;
@@ -301,6 +315,8 @@ export declare const ResponseFrame: S.Struct<{
301
315
  readonly tag: S.String;
302
316
  readonly message: S.Unknown;
303
317
  readonly commandNames: S.$Array<S.String>;
318
+ readonly mountStartNames: S.$Array<S.String>;
319
+ readonly mountEndNames: S.$Array<S.String>;
304
320
  readonly timestamp: S.Number;
305
321
  readonly isModelChanged: S.Boolean;
306
322
  readonly changedPaths: S.$Array<S.String>;
@@ -325,6 +341,7 @@ export declare const ResponseFrame: S.Struct<{
325
341
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseInit", {
326
342
  maybeModel: S.OptionFromNullOr<S.Unknown>;
327
343
  commandNames: S.$Array<S.String>;
344
+ mountStartNames: S.$Array<S.String>;
328
345
  }>, import("../schema/index.js").CallableTaggedStruct<"ResponseRuntimeState", {
329
346
  currentIndex: S.Number;
330
347
  startIndex: S.Number;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/devTools/protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/devTools/protocol.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,14 @@
1
1
  import { Schema as S } from 'effect';
2
2
  import { ts } from '../schema/index.js';
3
3
  // SHARED
4
- /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. */
4
+ /** A serialized history entry as it appears on the wire. `submodelPath` lists `Got<Child>Message` wrapper tags from outer to inner when the entry came up through a Submodel chain; `maybeLeafTag` is `Some` with the innermost child Message tag when one exists. `mountStartNames` lists Mounts that fired during the render after this Message; `mountEndNames` lists Mounts whose elements were unmounted during that render. The Messages dispatched by mount Effects appear as their own entries elsewhere in history. */
5
5
  export const SerializedEntry = S.Struct({
6
6
  index: S.Number,
7
7
  tag: S.String,
8
8
  message: S.Unknown,
9
9
  commandNames: S.Array(S.String),
10
+ mountStartNames: S.Array(S.String),
11
+ mountEndNames: S.Array(S.String),
10
12
  timestamp: S.Number,
11
13
  isModelChanged: S.Boolean,
12
14
  changedPaths: S.Array(S.String),
@@ -111,10 +113,11 @@ export const ResponseDispatched = ts('ResponseDispatched', {
111
113
  export const ResponseRuntimes = ts('ResponseRuntimes', {
112
114
  runtimes: S.Array(RuntimeInfo),
113
115
  });
114
- /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. */
116
+ /** Response carrying the recorded init data. `maybeModel` is `None` until the runtime has finished its first render and recorded init; once set it stays set for the rest of the runtime's life. `commandNames` lists the Commands returned from the application's `init` function in the order they were produced. `mountStartNames` lists the Mounts that fired during the initial render. */
115
117
  export const ResponseInit = ts('ResponseInit', {
116
118
  maybeModel: S.OptionFromNullOr(S.Unknown),
117
119
  commandNames: S.Array(S.String),
120
+ mountStartNames: S.Array(S.String),
118
121
  });
119
122
  /** Response carrying a snapshot of the runtime's DevTools state. `currentIndex` is the absolute index of the most recently recorded Message, or -1 when no Messages have been recorded yet. `startIndex` is the earliest absolute index still retained in the rolling buffer (older entries are evicted past `maxEntries`). `totalEntries` is the number of retained entries. `isPaused` is true while the runtime is paused at a replayed snapshot; `maybePausedAtIndex` is `Some(index)` then and `None` otherwise. `hasInitModel` is true once the runtime has finished initialising. */
120
123
  export const ResponseRuntimeState = ts('ResponseRuntimeState', {
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAwB9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OAUnD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,YAAY,EACnB,OAAO,MAAM,KACZ,eAkBF,CAAA"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAwB9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OAUnD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,YAAY,EACnB,OAAO,MAAM,KACZ,eAoBF,CAAA"}
@@ -52,6 +52,8 @@ export const toSerializedEntry = (entry, index) => {
52
52
  tag: entry.tag,
53
53
  message: toInspectableValue(entry.message),
54
54
  commandNames: entry.commandNames,
55
+ mountStartNames: entry.mountStartNames,
56
+ mountEndNames: entry.mountEndNames,
55
57
  timestamp: entry.timestamp,
56
58
  isModelChanged: entry.isModelChanged,
57
59
  changedPaths: Array_.fromIterable(entry.diff.changedPaths),
@@ -10,6 +10,8 @@ export type HistoryEntry = Readonly<{
10
10
  tag: string;
11
11
  message: unknown;
12
12
  commandNames: ReadonlyArray<string>;
13
+ mountStartNames: ReadonlyArray<string>;
14
+ mountEndNames: ReadonlyArray<string>;
13
15
  timestamp: number;
14
16
  isModelChanged: boolean;
15
17
  diff: DiffResult;
@@ -19,6 +21,7 @@ export type StoreState = Readonly<{
19
21
  keyframes: HashMap.HashMap<number, unknown>;
20
22
  maybeInitModel: Option.Option<unknown>;
21
23
  initCommandNames: ReadonlyArray<string>;
24
+ initMountStartNames: ReadonlyArray<string>;
22
25
  startIndex: number;
23
26
  isPaused: boolean;
24
27
  pausedAtIndex: number;
@@ -31,10 +34,11 @@ export type Bridge = Readonly<{
31
34
  }>;
32
35
  export declare const createDevToolsStore: (bridge: Bridge, maxEntries?: number) => Effect.Effect<DevToolsStore>;
33
36
  export type DevToolsStore = Readonly<{
34
- recordInit: (model: unknown, commandNames: ReadonlyArray<string>) => Effect.Effect<void>;
37
+ recordInit: (model: unknown, commandNames: ReadonlyArray<string>, mountStartNames?: ReadonlyArray<string>) => Effect.Effect<void>;
35
38
  recordMessage: (message: Readonly<{
36
39
  _tag: string;
37
40
  }>, modelBeforeUpdate: unknown, modelAfterUpdate: unknown, commandNames: ReadonlyArray<string>, isModelChanged: boolean) => Effect.Effect<void>;
41
+ attachRenderedMounts: (mountStartNames: ReadonlyArray<string>, mountEndNames: ReadonlyArray<string>) => Effect.Effect<void>;
38
42
  getModelAtIndex: (index: number) => Effect.Effect<unknown>;
39
43
  getMessageAtIndex: (index: number) => Effect.Effect<Option.Option<unknown>>;
40
44
  getDiffAtIndex: (index: number) => Effect.Effect<DiffResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/devTools/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/devTools/store.ts"],"names":[],"mappings":"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"}
@@ -68,6 +68,7 @@ const emptyState = {
68
68
  keyframes: HashMap.empty(),
69
69
  maybeInitModel: Option.none(),
70
70
  initCommandNames: [],
71
+ initMountStartNames: [],
71
72
  startIndex: 0,
72
73
  isPaused: false,
73
74
  pausedAtIndex: 0,
@@ -97,10 +98,11 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
97
98
  isPaused: state.isPaused && isPausedAtRetainedIndex,
98
99
  };
99
100
  };
100
- const recordInit = (model, commandNames) => SubscriptionRef.update(stateRef, state => ({
101
+ const recordInit = (model, commandNames, mountStartNames = []) => SubscriptionRef.update(stateRef, state => ({
101
102
  ...state,
102
103
  maybeInitModel: Option.some(model),
103
104
  initCommandNames: commandNames,
105
+ initMountStartNames: mountStartNames,
104
106
  keyframes: HashMap.set(state.keyframes, 0, model),
105
107
  maybeLatestModel: Option.some(model),
106
108
  }));
@@ -116,6 +118,8 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
116
118
  tag: message._tag,
117
119
  message,
118
120
  commandNames,
121
+ mountStartNames: [],
122
+ mountEndNames: [],
119
123
  timestamp: performance.now(),
120
124
  isModelChanged: hasChangedFields,
121
125
  diff,
@@ -127,6 +131,36 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
127
131
  ? evictOldestSegment(nextState)
128
132
  : nextState;
129
133
  });
134
+ /** Attaches Mount lifecycle events from the most recent render to the
135
+ * history entry that triggered the render. Mount events fire during
136
+ * snabbdom's `patch` (inside `render`), but the runtime's render loop
137
+ * is gated by `requestAnimationFrame`, so a render may fire after the
138
+ * Message that dirtied it has already been recorded. The runtime drains
139
+ * its mount buffer after each render and calls this to associate the
140
+ * events with the correct entry. When called before any Message has been
141
+ * recorded (only possible from the init render path), the starts attach
142
+ * to `initMountStartNames`; init has no `ends` because nothing existed
143
+ * to unmount. */
144
+ const attachRenderedMounts = (mountStartNames, mountEndNames) => SubscriptionRef.update(stateRef, state => {
145
+ if (Array.isReadonlyArrayEmpty(mountStartNames) &&
146
+ Array.isReadonlyArrayEmpty(mountEndNames)) {
147
+ return state;
148
+ }
149
+ return Array.match(state.entries, {
150
+ onEmpty: () => ({
151
+ ...state,
152
+ initMountStartNames: Array.appendAll(state.initMountStartNames, mountStartNames),
153
+ }),
154
+ onNonEmpty: entries => ({
155
+ ...state,
156
+ entries: Array.modifyLastNonEmpty(entries, (last) => ({
157
+ ...last,
158
+ mountStartNames: Array.appendAll(last.mountStartNames, mountStartNames),
159
+ mountEndNames: Array.appendAll(last.mountEndNames, mountEndNames),
160
+ })),
161
+ }),
162
+ });
163
+ });
130
164
  const latestEntryIndex = (state) => Array.match(state.entries, {
131
165
  onEmpty: () => INIT_INDEX,
132
166
  onNonEmpty: entries => state.startIndex + entries.length - 1,
@@ -164,6 +198,7 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
164
198
  ...emptyState,
165
199
  maybeInitModel: state.maybeInitModel,
166
200
  initCommandNames: state.initCommandNames,
201
+ initMountStartNames: state.initMountStartNames,
167
202
  keyframes: Option.match(state.maybeInitModel, {
168
203
  onNone: () => HashMap.empty(),
169
204
  onSome: model => HashMap.set(HashMap.empty(), 0, model),
@@ -183,6 +218,7 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
183
218
  return {
184
219
  recordInit,
185
220
  recordMessage,
221
+ attachRenderedMounts,
186
222
  getModelAtIndex,
187
223
  getMessageAtIndex,
188
224
  getDiffAtIndex,
@@ -169,6 +169,7 @@ const dispatchRequest = (store, dispatch, maybeMessageSchema, request) => Match.
169
169
  return ResponseInit({
170
170
  maybeModel: Option.map(state.maybeInitModel, toInspectableValue),
171
171
  commandNames: state.initCommandNames,
172
+ mountStartNames: state.initMountStartNames,
172
173
  });
173
174
  }),
174
175
  RequestGetRuntimeState: () => Effect.gen(function* () {
@@ -48,6 +48,17 @@ export type MountResult<Message> = Readonly<{
48
48
  message: Message;
49
49
  cleanup: () => void;
50
50
  }>;
51
+ /** Key under which the OnMount attribute stamps a `{ name }` marker on the
52
+ * snabbdom `VNodeData`. Snabbdom passes unknown data fields through without
53
+ * rendering them to the DOM, so the marker is invisible at runtime but
54
+ * observable by VNode walkers (Scene tests). */
55
+ export declare const FOLDKIT_MOUNT_KEY: "foldkitMount";
56
+ /** Marker stamped on `VNodeData[FOLDKIT_MOUNT_KEY]` for any element with an
57
+ * `OnMount` attribute. Carries the Mount Definition's name so test
58
+ * introspection can identify pending mounts. */
59
+ export type FoldkitMountMarker = Readonly<{
60
+ name: string;
61
+ }>;
51
62
  /** Union of all HTML, SVG, and MathML attributes a virtual DOM element can carry. */
52
63
  export type Attribute<Message> = Data.TaggedEnum<{
53
64
  Key: {