@dxos/react-ui-feed 0.11.1

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 (230) hide show
  1. package/LICENSE +105 -0
  2. package/dist/lib/chunk-src.mjs +2228 -0
  3. package/dist/lib/chunk-src.mjs.map +1 -0
  4. package/dist/lib/index.mjs +2 -0
  5. package/dist/lib/testing.mjs +1923 -0
  6. package/dist/lib/testing.mjs.map +1 -0
  7. package/dist/types/src/components/Block/HtmlBlock.d.ts +14 -0
  8. package/dist/types/src/components/Block/HtmlBlock.d.ts.map +1 -0
  9. package/dist/types/src/components/Block/MarkdownBlock.d.ts +24 -0
  10. package/dist/types/src/components/Block/MarkdownBlock.d.ts.map +1 -0
  11. package/dist/types/src/components/Block/block.stories.d.ts +21 -0
  12. package/dist/types/src/components/Block/block.stories.d.ts.map +1 -0
  13. package/dist/types/src/components/Block/construction.d.ts +36 -0
  14. package/dist/types/src/components/Block/construction.d.ts.map +1 -0
  15. package/dist/types/src/components/Block/extensions.d.ts +23 -0
  16. package/dist/types/src/components/Block/extensions.d.ts.map +1 -0
  17. package/dist/types/src/components/Block/highlight.d.ts +14 -0
  18. package/dist/types/src/components/Block/highlight.d.ts.map +1 -0
  19. package/dist/types/src/components/Block/index.d.ts +6 -0
  20. package/dist/types/src/components/Block/index.d.ts.map +1 -0
  21. package/dist/types/src/components/Block/selection-group.d.ts +21 -0
  22. package/dist/types/src/components/Block/selection-group.d.ts.map +1 -0
  23. package/dist/types/src/components/Block/widget-state.d.ts +33 -0
  24. package/dist/types/src/components/Block/widget-state.d.ts.map +1 -0
  25. package/dist/types/src/components/MessageList/MessageList.d.ts +129 -0
  26. package/dist/types/src/components/MessageList/MessageList.d.ts.map +1 -0
  27. package/dist/types/src/components/MessageList/MessageList.stories.d.ts +47 -0
  28. package/dist/types/src/components/MessageList/MessageList.stories.d.ts.map +1 -0
  29. package/dist/types/src/components/MessageList/index.d.ts +3 -0
  30. package/dist/types/src/components/MessageList/index.d.ts.map +1 -0
  31. package/dist/types/src/components/MessageList/position-log.d.ts +73 -0
  32. package/dist/types/src/components/MessageList/position-log.d.ts.map +1 -0
  33. package/dist/types/src/components/Minimap/Minimap.d.ts +28 -0
  34. package/dist/types/src/components/Minimap/Minimap.d.ts.map +1 -0
  35. package/dist/types/src/components/Minimap/Minimap.stories.d.ts +21 -0
  36. package/dist/types/src/components/Minimap/Minimap.stories.d.ts.map +1 -0
  37. package/dist/types/src/components/Minimap/index.d.ts +2 -0
  38. package/dist/types/src/components/Minimap/index.d.ts.map +1 -0
  39. package/dist/types/src/components/Outline/Outline.d.ts +46 -0
  40. package/dist/types/src/components/Outline/Outline.d.ts.map +1 -0
  41. package/dist/types/src/components/Outline/Outline.stories.d.ts +37 -0
  42. package/dist/types/src/components/Outline/Outline.stories.d.ts.map +1 -0
  43. package/dist/types/src/components/Outline/index.d.ts +2 -0
  44. package/dist/types/src/components/Outline/index.d.ts.map +1 -0
  45. package/dist/types/src/components/index.d.ts +5 -0
  46. package/dist/types/src/components/index.d.ts.map +1 -0
  47. package/dist/types/src/debug/Debug.d.ts +17 -0
  48. package/dist/types/src/debug/Debug.d.ts.map +1 -0
  49. package/dist/types/src/debug/Stats.d.ts +30 -0
  50. package/dist/types/src/debug/Stats.d.ts.map +1 -0
  51. package/dist/types/src/debug/debug-model.d.ts +32 -0
  52. package/dist/types/src/debug/debug-model.d.ts.map +1 -0
  53. package/dist/types/src/debug/debug-model.test.d.ts +2 -0
  54. package/dist/types/src/debug/debug-model.test.d.ts.map +1 -0
  55. package/dist/types/src/debug/frame-meter.d.ts +48 -0
  56. package/dist/types/src/debug/frame-meter.d.ts.map +1 -0
  57. package/dist/types/src/debug/frame-meter.test.d.ts +2 -0
  58. package/dist/types/src/debug/frame-meter.test.d.ts.map +1 -0
  59. package/dist/types/src/debug/index.d.ts +6 -0
  60. package/dist/types/src/debug/index.d.ts.map +1 -0
  61. package/dist/types/src/debug/use-debug.d.ts +19 -0
  62. package/dist/types/src/debug/use-debug.d.ts.map +1 -0
  63. package/dist/types/src/hooks/follow.d.ts +89 -0
  64. package/dist/types/src/hooks/follow.d.ts.map +1 -0
  65. package/dist/types/src/hooks/follow.stories.d.ts +25 -0
  66. package/dist/types/src/hooks/follow.stories.d.ts.map +1 -0
  67. package/dist/types/src/hooks/follow.test.d.ts +2 -0
  68. package/dist/types/src/hooks/follow.test.d.ts.map +1 -0
  69. package/dist/types/src/hooks/index.d.ts +6 -0
  70. package/dist/types/src/hooks/index.d.ts.map +1 -0
  71. package/dist/types/src/hooks/useDecorations.d.ts +31 -0
  72. package/dist/types/src/hooks/useDecorations.d.ts.map +1 -0
  73. package/dist/types/src/hooks/useFeedNavigation.d.ts +44 -0
  74. package/dist/types/src/hooks/useFeedNavigation.d.ts.map +1 -0
  75. package/dist/types/src/hooks/useFollow.d.ts +46 -0
  76. package/dist/types/src/hooks/useFollow.d.ts.map +1 -0
  77. package/dist/types/src/hooks/useItemSelection.d.ts +34 -0
  78. package/dist/types/src/hooks/useItemSelection.d.ts.map +1 -0
  79. package/dist/types/src/index.d.ts +4 -0
  80. package/dist/types/src/index.d.ts.map +1 -0
  81. package/dist/types/src/model/feed-model.d.ts +67 -0
  82. package/dist/types/src/model/feed-model.d.ts.map +1 -0
  83. package/dist/types/src/model/feed-model.test.d.ts +2 -0
  84. package/dist/types/src/model/feed-model.test.d.ts.map +1 -0
  85. package/dist/types/src/model/feed.d.ts +66 -0
  86. package/dist/types/src/model/feed.d.ts.map +1 -0
  87. package/dist/types/src/model/feed.test.d.ts +2 -0
  88. package/dist/types/src/model/feed.test.d.ts.map +1 -0
  89. package/dist/types/src/model/index.d.ts +5 -0
  90. package/dist/types/src/model/index.d.ts.map +1 -0
  91. package/dist/types/src/model/list-model.d.ts +61 -0
  92. package/dist/types/src/model/list-model.d.ts.map +1 -0
  93. package/dist/types/src/model/list-model.test.d.ts +2 -0
  94. package/dist/types/src/model/list-model.test.d.ts.map +1 -0
  95. package/dist/types/src/model/useListModel.d.ts +22 -0
  96. package/dist/types/src/model/useListModel.d.ts.map +1 -0
  97. package/dist/types/src/stories/assistant.stories.d.ts +38 -0
  98. package/dist/types/src/stories/assistant.stories.d.ts.map +1 -0
  99. package/dist/types/src/stories/baseline.stories.d.ts +32 -0
  100. package/dist/types/src/stories/baseline.stories.d.ts.map +1 -0
  101. package/dist/types/src/stories/bridge.stories.d.ts +72 -0
  102. package/dist/types/src/stories/bridge.stories.d.ts.map +1 -0
  103. package/dist/types/src/stories/construction.stories.d.ts +17 -0
  104. package/dist/types/src/stories/construction.stories.d.ts.map +1 -0
  105. package/dist/types/src/stories/fill.stories.d.ts +51 -0
  106. package/dist/types/src/stories/fill.stories.d.ts.map +1 -0
  107. package/dist/types/src/stories/horizontal.stories.d.ts +17 -0
  108. package/dist/types/src/stories/horizontal.stories.d.ts.map +1 -0
  109. package/dist/types/src/stories/mount.stories.d.ts +19 -0
  110. package/dist/types/src/stories/mount.stories.d.ts.map +1 -0
  111. package/dist/types/src/stories/navigation.stories.d.ts +33 -0
  112. package/dist/types/src/stories/navigation.stories.d.ts.map +1 -0
  113. package/dist/types/src/stories/streaming.stories.d.ts +17 -0
  114. package/dist/types/src/stories/streaming.stories.d.ts.map +1 -0
  115. package/dist/types/src/stories/tail.stories.d.ts +47 -0
  116. package/dist/types/src/stories/tail.stories.d.ts.map +1 -0
  117. package/dist/types/src/stories/widget.stories.d.ts +16 -0
  118. package/dist/types/src/stories/widget.stories.d.ts.map +1 -0
  119. package/dist/types/src/testing/FeedStory.d.ts +30 -0
  120. package/dist/types/src/testing/FeedStory.d.ts.map +1 -0
  121. package/dist/types/src/testing/MessageWindow.d.ts +48 -0
  122. package/dist/types/src/testing/MessageWindow.d.ts.map +1 -0
  123. package/dist/types/src/testing/controls.d.ts +46 -0
  124. package/dist/types/src/testing/controls.d.ts.map +1 -0
  125. package/dist/types/src/testing/debug/FeedStats.d.ts +18 -0
  126. package/dist/types/src/testing/debug/FeedStats.d.ts.map +1 -0
  127. package/dist/types/src/testing/debug/index.d.ts +4 -0
  128. package/dist/types/src/testing/debug/index.d.ts.map +1 -0
  129. package/dist/types/src/testing/debug/sweep.d.ts +18 -0
  130. package/dist/types/src/testing/debug/sweep.d.ts.map +1 -0
  131. package/dist/types/src/testing/debug/use-feed-debug.d.ts +33 -0
  132. package/dist/types/src/testing/debug/use-feed-debug.d.ts.map +1 -0
  133. package/dist/types/src/testing/generator.d.ts +16 -0
  134. package/dist/types/src/testing/generator.d.ts.map +1 -0
  135. package/dist/types/src/testing/index.d.ts +10 -0
  136. package/dist/types/src/testing/index.d.ts.map +1 -0
  137. package/dist/types/src/testing/scenarios.d.ts +58 -0
  138. package/dist/types/src/testing/scenarios.d.ts.map +1 -0
  139. package/dist/types/src/testing/stream.d.ts +22 -0
  140. package/dist/types/src/testing/stream.d.ts.map +1 -0
  141. package/dist/types/src/testing/turn.d.ts +21 -0
  142. package/dist/types/src/testing/turn.d.ts.map +1 -0
  143. package/dist/types/src/testing/widgets.d.ts +3 -0
  144. package/dist/types/src/testing/widgets.d.ts.map +1 -0
  145. package/dist/types/src/virtualizer/Window.d.ts +137 -0
  146. package/dist/types/src/virtualizer/Window.d.ts.map +1 -0
  147. package/dist/types/src/virtualizer/Window.stories.d.ts +112 -0
  148. package/dist/types/src/virtualizer/Window.stories.d.ts.map +1 -0
  149. package/dist/types/src/virtualizer/index.d.ts +3 -0
  150. package/dist/types/src/virtualizer/index.d.ts.map +1 -0
  151. package/dist/types/src/virtualizer/placement.d.ts +188 -0
  152. package/dist/types/src/virtualizer/placement.d.ts.map +1 -0
  153. package/dist/types/src/virtualizer/placement.test.d.ts +2 -0
  154. package/dist/types/src/virtualizer/placement.test.d.ts.map +1 -0
  155. package/dist/types/tsconfig.tsbuildinfo +1 -0
  156. package/package.json +72 -0
  157. package/src/components/Block/HtmlBlock.tsx +26 -0
  158. package/src/components/Block/MarkdownBlock.tsx +157 -0
  159. package/src/components/Block/block.stories.tsx +140 -0
  160. package/src/components/Block/construction.ts +77 -0
  161. package/src/components/Block/extensions.ts +95 -0
  162. package/src/components/Block/highlight.ts +53 -0
  163. package/src/components/Block/index.ts +10 -0
  164. package/src/components/Block/selection-group.ts +53 -0
  165. package/src/components/Block/widget-state.tsx +75 -0
  166. package/src/components/MessageList/MessageList.stories.tsx +111 -0
  167. package/src/components/MessageList/MessageList.tsx +647 -0
  168. package/src/components/MessageList/index.ts +6 -0
  169. package/src/components/MessageList/position-log.ts +167 -0
  170. package/src/components/Minimap/Minimap.stories.tsx +129 -0
  171. package/src/components/Minimap/Minimap.tsx +84 -0
  172. package/src/components/Minimap/index.ts +5 -0
  173. package/src/components/Outline/Outline.stories.tsx +196 -0
  174. package/src/components/Outline/Outline.tsx +383 -0
  175. package/src/components/Outline/index.ts +5 -0
  176. package/src/components/index.ts +8 -0
  177. package/src/debug/Debug.tsx +90 -0
  178. package/src/debug/Stats.tsx +57 -0
  179. package/src/debug/debug-model.test.ts +36 -0
  180. package/src/debug/debug-model.ts +66 -0
  181. package/src/debug/frame-meter.test.ts +49 -0
  182. package/src/debug/frame-meter.ts +188 -0
  183. package/src/debug/index.ts +9 -0
  184. package/src/debug/use-debug.tsx +41 -0
  185. package/src/hooks/follow.stories.tsx +200 -0
  186. package/src/hooks/follow.test.ts +105 -0
  187. package/src/hooks/follow.ts +241 -0
  188. package/src/hooks/index.ts +9 -0
  189. package/src/hooks/useDecorations.tsx +54 -0
  190. package/src/hooks/useFeedNavigation.ts +90 -0
  191. package/src/hooks/useFollow.ts +258 -0
  192. package/src/hooks/useItemSelection.tsx +53 -0
  193. package/src/index.ts +7 -0
  194. package/src/model/feed-model.test.ts +84 -0
  195. package/src/model/feed-model.ts +214 -0
  196. package/src/model/feed.test.ts +65 -0
  197. package/src/model/feed.ts +157 -0
  198. package/src/model/index.ts +8 -0
  199. package/src/model/list-model.test.ts +71 -0
  200. package/src/model/list-model.ts +152 -0
  201. package/src/model/useListModel.ts +53 -0
  202. package/src/stories/assistant.stories.tsx +425 -0
  203. package/src/stories/baseline.stories.tsx +78 -0
  204. package/src/stories/bridge.stories.tsx +376 -0
  205. package/src/stories/construction.stories.tsx +147 -0
  206. package/src/stories/fill.stories.tsx +271 -0
  207. package/src/stories/horizontal.stories.tsx +129 -0
  208. package/src/stories/mount.stories.tsx +233 -0
  209. package/src/stories/navigation.stories.tsx +145 -0
  210. package/src/stories/streaming.stories.tsx +132 -0
  211. package/src/stories/tail.stories.tsx +149 -0
  212. package/src/stories/widget.stories.tsx +107 -0
  213. package/src/testing/FeedStory.tsx +452 -0
  214. package/src/testing/MessageWindow.tsx +139 -0
  215. package/src/testing/controls.tsx +96 -0
  216. package/src/testing/debug/FeedStats.tsx +182 -0
  217. package/src/testing/debug/index.ts +16 -0
  218. package/src/testing/debug/sweep.ts +85 -0
  219. package/src/testing/debug/use-feed-debug.ts +91 -0
  220. package/src/testing/generator.ts +90 -0
  221. package/src/testing/index.ts +13 -0
  222. package/src/testing/scenarios.tsx +552 -0
  223. package/src/testing/stream.ts +70 -0
  224. package/src/testing/turn.ts +91 -0
  225. package/src/testing/widgets.tsx +183 -0
  226. package/src/virtualizer/Window.stories.tsx +683 -0
  227. package/src/virtualizer/Window.tsx +435 -0
  228. package/src/virtualizer/index.ts +6 -0
  229. package/src/virtualizer/placement.test.ts +312 -0
  230. package/src/virtualizer/placement.ts +403 -0
@@ -0,0 +1,38 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ /**
3
+ * The plugin-assistant use case, end to end: a reader typing prompts into a conversation while an
4
+ * agent streams multi-block answers into its tail — status, reasoning, a tool call and its result,
5
+ * then the answer, exactly the block sequence a model emits (`streamTurn`).
6
+ *
7
+ * Everything here goes through the shipping path and the model's *told* APIs: a typed prompt is
8
+ * `model.append`, the agent's turn mutates one identity via `model.stream`, and the follow keeps
9
+ * the tail at rest because the reader is there — scrolling up withdraws it, returning restores it.
10
+ * The `debug` arg turns on the generic Debug table (`@dxos/react-ui-feed/debug`), with probes over
11
+ * the frame rate, the model, the window and the widget census — every aspect readable live.
12
+ */
13
+ type StoryArgs = {
14
+ count?: number;
15
+ debug?: boolean;
16
+ scrollPastEnd?: boolean;
17
+ wordsPerChunk?: number;
18
+ chunkDelay?: number;
19
+ };
20
+ declare const meta: Meta<StoryArgs>;
21
+ export default meta;
22
+ type Story = StoryObj<StoryArgs>;
23
+ /** The loop, hands on: type a prompt, or press ▶ and watch. No play — this one is for people. */
24
+ export declare const Default: Story;
25
+ /**
26
+ * The whole conversation loop, driven as a reader would drive it.
27
+ *
28
+ * A prompt is typed and entered; the agent answers in blocks; the tail stays at rest through the
29
+ * stream (the follow at work); scrolling up mid-answer withdraws the follow and the feed holds
30
+ * still under a growing document.
31
+ */
32
+ export declare const Assistant: Story;
33
+ /**
34
+ * Scrolling away mid-answer stops the follow, and it stays stopped: a reader looking at history is
35
+ * not dragged back by the stream. Returning to the tail opts back in.
36
+ */
37
+ export declare const Interrupted: Story;
38
+ //# sourceMappingURL=assistant.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/assistant.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAcjE;;;;;;;;;;GAUG;AACH,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAiPF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAUzB,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAiBjC,iGAAiG;AACjG,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,KA+DvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAsCzB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * The bisection ladder for scroll stability.
5
+ *
6
+ * Each rung adds one thing to the one before it, so a defect can be attributed rather than guessed
7
+ * at: if a rung is still and the next one moves, the difference between them is the cause. The
8
+ * statusbar's `jumps` (rows moving on screen against the scroll, sampled per frame) and `shifts`
9
+ * (rows whose offset changed after layout) are the readings; both should be zero on a still feed.
10
+ *
11
+ * 1. **Plain** — no editor at all, every row a fixed height declared in advance. Nothing here can be
12
+ * measured wrong, so any movement belongs to the list itself.
13
+ * 2. **Uniform** — one editor per row, every row the identical document, so a single estimate is
14
+ * exactly right for all of them. What this adds over Plain is CodeMirror construction.
15
+ * 3. **Varied** — one editor per row, contents of different lengths, so the estimate is wrong for
16
+ * most rows and the list corrects as it goes. What this adds is measurement error.
17
+ *
18
+ * Above the ladder sit the call-site stories (`MessageList/Assistant` and friends), which add
19
+ * per-message renderers, block widgets and streaming.
20
+ */
21
+ declare const meta: Meta<FeedStoryProps>;
22
+ export default meta;
23
+ type Story = StoryObj<FeedStoryProps>;
24
+ /** The feed at rest — the varied rung, which is the one that matters. No play. */
25
+ export declare const Default: Story;
26
+ /** Rung 1: fixed heights, no editor. If this moves, the list is at fault. */
27
+ export declare const Plain: Story;
28
+ /** Rung 2: an editor per row, all identical — adds CodeMirror construction. */
29
+ export declare const Uniform: Story;
30
+ /** Rung 3: an editor per row, varied lengths — adds measurement error. */
31
+ export declare const Varied: Story;
32
+ //# sourceMappingURL=baseline.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/baseline.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAmB9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAEtC,kFAAkF;AAClF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,KAAK,EAAE,KAInB,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,MAAM,EAAE,KAIpB,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import React from 'react';
3
+ import { type FeedScenario } from '../testing';
4
+ declare const DefaultStory: ({ scenario, count, sticky, scrollPastEnd, }: {
5
+ scenario: FeedScenario;
6
+ count: number;
7
+ sticky?: boolean;
8
+ scrollPastEnd?: boolean;
9
+ }) => React.JSX.Element;
10
+ declare const meta: Meta<typeof DefaultStory>;
11
+ export default meta;
12
+ type Story = StoryObj<typeof DefaultStory>;
13
+ /** The bridge passively: real messages on the window, nothing asserted. */
14
+ export declare const Default: Story;
15
+ /** Fixed-height rows, no editor: whatever moves here is the placement and nothing else. */
16
+ export declare const Plain: Story;
17
+ /** One editor per row, all identical. */
18
+ export declare const Uniform: Story;
19
+ /** A chat's shape: per-message renderers, block widgets, a per-message estimate. */
20
+ export declare const Assistant: Story;
21
+ /**
22
+ * A chat's tail: the last message rests on the bottom, and stays there as answers arrive.
23
+ *
24
+ * The invariant `baseline/tail` holds the current engine to, pointed at the new one. Read from the
25
+ * last row's own bottom edge rather than the scroll offset: an offset can be at the document's end
26
+ * while the last message is nowhere near the screen, which is what both of that story's defects
27
+ * looked like from outside.
28
+ *
29
+ * It failed for a while, and what it caught was not the tail arithmetic either time. First a stale
30
+ * `getId` — `Window` held the closure it was constructed with, so an appended row's measurement was
31
+ * filed under one id and read back under another and the row was re-measured every commit, which
32
+ * React ends by exceeding the update limit. Then a follow re-derived from proximity, which its own
33
+ * corrections disengage. Both presented as "the tail is in the wrong place".
34
+ */
35
+ export declare const Tail: Story;
36
+ /**
37
+ * The tail, with a viewport's worth of space reserved past it.
38
+ *
39
+ * The case the old engine cannot do at all: its reserve is a DOM spacer, so the element and the
40
+ * virtualizer disagree about where the document ends and an offset inside the reserve is beyond the
41
+ * virtualizer's maximum, where `scrollToOffset` declines to move. The feed opened at the document's
42
+ * end with its last message near the top of an empty screen — reported from a real session, and the
43
+ * reason `baseline/tail` has no `VariedPastEnd`.
44
+ *
45
+ * Here the reserve is a term in the sizer and `endOffset` is the last row's own end, so "the end of
46
+ * the content" and "the end of the document" are two numbers in one coordinate system rather than
47
+ * two systems.
48
+ */
49
+ export declare const VariedPastEnd: Story;
50
+ /**
51
+ * Scrolling moves the content by exactly what was scrolled, and by nothing else.
52
+ *
53
+ * Reported from a real session as the feed "jumping as soon as it starts to scroll". Measurement
54
+ * *is* allowed to move things — a row that turns out taller pushes the rows after it, and that is
55
+ * the list working — so the reading is the row the reader is looking at: whatever is under the top
56
+ * of the viewport when a step begins must be exactly one step higher when it ends.
57
+ *
58
+ * That is what a re-base breaks and what an anchor cannot: re-basing the document rewrites every
59
+ * position including the ones above the reader, so a correction anywhere lands as a jump here.
60
+ */
61
+ export declare const Scrolling: Story;
62
+ /**
63
+ * The top of the conversation exists.
64
+ *
65
+ * A feed opened at its tail derives every position above the reader from estimates; rows measuring
66
+ * taller than assumed push row 0 negative, where no scroll can reach it — the reader arrives at the
67
+ * top and the first messages are simply not there (seen live: the flagship opened with its first
68
+ * prompt missing). The start edge is repaid by shifting content and scroll together, so this drives
69
+ * to the top and asks the one absolute fact of content space: row 0 starts at zero.
70
+ */
71
+ export declare const Top: Story;
72
+ //# sourceMappingURL=bridge.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/bridge.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAA+C,MAAM,OAAO,CAAC;AAOpE,OAAO,EAAE,KAAK,YAAY,EAAiC,MAAM,YAAY,CAAC;AAmB9E,QAAA,MAAM,YAAY,gDAKf;IACD,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,sBA+DA,CAAC;AAEF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAKnC,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAkE3C,2EAA2E;AAC3E,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,KAAK,EAAE,KAAgC,CAAC;AAErD,yCAAyC;AACzC,eAAO,MAAM,OAAO,EAAE,KAAkC,CAAC;AAEzD,oFAAoF;AACpF,eAAO,MAAM,SAAS,EAAE,KAAoC,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,IAAI,EAAE,KA8BlB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,KA6B3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,KA4CvB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,EAAE,KAwBjB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import React from 'react';
3
+ declare const ConstructionProfile: ({ runs }: {
4
+ runs?: number;
5
+ }) => React.JSX.Element;
6
+ declare const meta: Meta<typeof ConstructionProfile>;
7
+ export default meta;
8
+ type Story = StoryObj<typeof ConstructionProfile>;
9
+ /**
10
+ * How long one item takes to build, by extension set.
11
+ *
12
+ * The first fill mounts a viewport of rows in one go, so the `×22 rows` column is the wall-clock
13
+ * cost of that fill — the number to compare against the >1s `baseline/Uniform` takes to appear.
14
+ * Read it from the story, or from the `[item construction]` line the storybook test run prints.
15
+ */
16
+ export declare const Default: Story;
17
+ //# sourceMappingURL=construction.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"construction.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/construction.stories.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAsC,MAAM,OAAO,CAAC;AA4E3D,QAAA,MAAM,mBAAmB,aAAmB;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,sBA6B5D,CAAC;AAgBF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAK1C,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * How long the first fill takes, and what it spends the time on.
5
+ *
6
+ * `baseline/Uniform` visibly fills from the bottom up over more than a second, which construction
7
+ * cost does not explain — `stories/construction` measures one item at ~0.4ms, so a viewport of them
8
+ * is ~8ms. The remaining explanation is the number of *passes*: every measured row changes the
9
+ * offsets below it, and each correction the virtualizer makes costs a frame. This samples the DOM
10
+ * once per animation frame and reports how many frames the list took to stop changing.
11
+ */
12
+ declare const meta: Meta<FeedStoryProps>;
13
+ export default meta;
14
+ type Story = StoryObj<FeedStoryProps>;
15
+ /** Passive: the first fill, watched rather than measured. */
16
+ export declare const Default: Story;
17
+ /** No editor at all: the floor, and what every other case is compared against. */
18
+ export declare const Plain: Story;
19
+ /**
20
+ * The same feed, a tenth the length.
21
+ *
22
+ * A virtualized list mounts a viewport's worth of rows either way, so a cost that follows the count
23
+ * belongs to the model — building the messages, projecting them — and a cost that does not belongs
24
+ * to the rows on screen. Which one it is decides where the fix goes.
25
+ */
26
+ export declare const PlainShort: Story;
27
+ /** One editor per row, all identical — construction, and nothing else, added to `Plain`. */
28
+ export declare const Uniform: Story;
29
+ /**
30
+ * The same feed with space reserved past the end.
31
+ *
32
+ * The reserved space is part of the document, so everything that reads the element's own maximum —
33
+ * the tail test, the follow's target, the opening offset — has to stop short of it instead. This is
34
+ * where that is checked.
35
+ */
36
+ /** Tall uneven rows and space past the end: the case where the opening jump is most wrong. */
37
+ export declare const PlainPastEnd: Story;
38
+ export declare const UniformPastEnd: Story;
39
+ export declare const UniformShort: Story;
40
+ /**
41
+ * Contents of different lengths, so the estimate is wrong for most rows.
42
+ *
43
+ * The one rung where the rebuild is still not atomic: the reader is put back by index, and with rows
44
+ * of every height the offsets around the landing point are mostly estimates, so the virtualizer
45
+ * retries across a frame and the page is seen to move in it. Restoring by offset instead lands in
46
+ * one frame and then spends a second correcting itself — measured at 69–96 of 150 frames changing,
47
+ * against one here. Recorded in `chat-ui/TASKS.md`; the allowance is what is measured today, so a
48
+ * regression past it still fails.
49
+ */
50
+ export declare const Varied: Story;
51
+ //# sourceMappingURL=fill.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/fill.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;;GAQG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAK9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AA2KtC,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,KAAK,EAAE,KAGnB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,KAGxB,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,OAAO,EAAE,KAGrB,CAAC;AAEF;;;;;;GAMG;AACH,8FAA8F;AAC9F,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAQ5B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,EAAE,KAGpB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import React from 'react';
3
+ declare const DefaultStory: () => React.JSX.Element;
4
+ declare const meta: Meta<typeof DefaultStory>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof DefaultStory>;
7
+ /** The horizontal strip, passively. No play. */
8
+ export declare const Default: Story;
9
+ /**
10
+ * The block-axis invariants, on the inline axis, with editors.
11
+ *
12
+ * Nothing here names a direction the arithmetic could hide behind: rows are tracked by index, a
13
+ * scroll must move them by what was scrolled, and the far end must be reachable — the same three
14
+ * readings `bridge/*` takes vertically.
15
+ */
16
+ export declare const InlineContent: Story;
17
+ //# sourceMappingURL=horizontal.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"horizontal.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/horizontal.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAA0B,MAAM,OAAO,CAAC;AA6B/C,QAAA,MAAM,YAAY,yBAyBjB,CAAC;AAEF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAKnC,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAU3C,gDAAgD;AAChD,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,KAsC3B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ type MountProfileProps = {
3
+ count?: number;
4
+ runs?: number;
5
+ };
6
+ declare const meta: Meta<MountProfileProps>;
7
+ export default meta;
8
+ type Story = StoryObj<MountProfileProps>;
9
+ /**
10
+ * Per-row mount cost up the ladder.
11
+ *
12
+ * `plain` has no editor at all, `uniform` adds one identical editor per row, `assistant` adds
13
+ * per-message renderers and block widgets. `ms/row` is the number that decides whether the first
14
+ * fill is worth optimizing in the item or in the list.
15
+ */
16
+ export declare const Default: Story;
17
+ /** The same rows in a shorter feed: anything that changes here scales with the model, not the view. */
18
+ export declare const Short: Story;
19
+ //# sourceMappingURL=mount.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/mount.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAyDjE,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA4IF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAKjC,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,KAAsD,CAAC;AAE7E,uGAAuG;AACvG,eAAO,MAAM,KAAK,EAAE,KAAqD,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * Arrow keys step between the feed's stops, one press one stop.
5
+ *
6
+ * The property under test is that a press always moves, and always to the adjacent stop: a smooth
7
+ * scroll passes through every range between here and its target, and the cursor follows the range
8
+ * whenever the reader scrolls past it — so a navigation that does not defend its destination
9
+ * overwrites it mid-flight and the next press steps from a row the animation was crossing. The
10
+ * symptom is an arrow that sometimes moves and sometimes returns to the row it just left.
11
+ */
12
+ declare const meta: Meta<FeedStoryProps>;
13
+ export default meta;
14
+ type Story = StoryObj<FeedStoryProps>;
15
+ /** Passive: the feed with its stops, for driving by hand. */
16
+ export declare const Default: Story;
17
+ /**
18
+ * Every press moves, and lands on a stop.
19
+ *
20
+ * `assistant` makes every second message a prompt and only prompts are stops, so a stop is an even
21
+ * index — which is what makes "landed on a stop" checkable rather than merely "moved". The first
22
+ * press is the odd one out: the feed opens on the last message, an answer, so the nearest stop above
23
+ * it is one index away where every step afterwards is two.
24
+ */
25
+ export declare const Arrows: Story;
26
+ /**
27
+ * The same property where every message is a stop.
28
+ *
29
+ * `plain` names no `isAnchor`, so a press steps one message — and its rows are tall and unequal,
30
+ * which is the case where the offset moves furthest between two stops.
31
+ */
32
+ export declare const Plain: Story;
33
+ //# sourceMappingURL=navigation.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/navigation.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;;GAQG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAK9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AA4CtC,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,KAmCpB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAenB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * The deciding case: a model answering into the tail while the reader watches.
5
+ *
6
+ * Every other rung measures a feed that has stopped. This one measures the feed doing the thing it
7
+ * exists for — a row growing on every frame, re-parsing its markdown as it goes, while the list
8
+ * follows the tail it keeps moving. Streaming is where the follow, the measurement and the item's
9
+ * reconciliation all run at once, and it is the only place their interaction shows.
10
+ */
11
+ declare const meta: Meta<FeedStoryProps>;
12
+ export default meta;
13
+ type Story = StoryObj<FeedStoryProps>;
14
+ /** Passive: press ▶ yourself. */
15
+ export declare const Default: Story;
16
+ export declare const Streaming: Story;
17
+ //# sourceMappingURL=streaming.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/streaming.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAQ9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAkEtC,iCAAiC;AACjC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,SAAS,EAAE,KA+BvB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * A feed opened at its tail shows its last message, and stays there.
5
+ *
6
+ * Both halves matter and both have been broken. The feed has landed at the tail the *estimate*
7
+ * predicted — 60,000px into a document that measured 71,565 — and been marked positioned there, so
8
+ * it opened part-way up the conversation and crept the rest of the way at two rows a second. And
9
+ * with space reserved past the end it has scrolled straight through the last message into the blank
10
+ * area below it, because the follow chased the element's own maximum rather than the last row.
11
+ *
12
+ * So the reading here is the **last row's own bottom edge**, measured against the viewport's, rather
13
+ * than the scroll offset: an offset can be at the document's end while the last message is nowhere
14
+ * near the screen. It has to arrive there, and it has to stop.
15
+ */
16
+ declare const meta: Meta<FeedStoryProps>;
17
+ export default meta;
18
+ type Story = StoryObj<FeedStoryProps>;
19
+ /** Passive: open at the tail and look. */
20
+ export declare const Default: Story;
21
+ /** Tall, uneven rows: the case where the estimate is furthest from the truth. */
22
+ export declare const Plain: Story;
23
+ export declare const PlainPastEnd: Story;
24
+ /** Short rows, all identical: the estimate is right, so the tail should be right immediately. */
25
+ export declare const Uniform: Story;
26
+ export declare const UniformPastEnd: Story;
27
+ /** A chat's shape: per-message renderers, block widgets, and a per-row estimate. */
28
+ export declare const Assistant: Story;
29
+ export declare const AssistantPastEnd: Story;
30
+ /**
31
+ * The rung the reader actually opened: an editor per row, contents of different lengths.
32
+ *
33
+ * `plain` and `uniform` are estimates that happen to be right, and `assistant` is 200 rows rather
34
+ * than 500. This is the one where the estimate is wrong for nearly every row *and* the document is
35
+ * long.
36
+ *
37
+ * Its `scrollPastEnd` twin is **not** here, and deliberately. It fails, and what it fails on is not
38
+ * fixable in this engine: the reserved space is a DOM spacer, so it is in the element's
39
+ * `scrollHeight` and not in the virtualizer's total, and an offset inside it is beyond the
40
+ * virtualizer's own maximum — `scrollToOffset` then silently declines to move (verified: the element
41
+ * stayed exactly where it was). The feed opens at the document's end with its last message near the
42
+ * top of an empty screen. Two coordinate systems for one document is the defect the placement layer
43
+ * exists to remove, so the requirement is stated where it can be met: `bridge/VariedPastEnd`.
44
+ */
45
+ export declare const Varied: Story;
46
+ export declare const VariedPastEnd: Story;
47
+ //# sourceMappingURL=tail.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tail.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/tail.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAK9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAsDtC,0CAA0C;AAC1C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,KAAK,EAAE,KAGnB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,OAAO,EAAE,KAGrB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAG5B,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAG9B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,EAAE,KAGpB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAG3B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../testing';
3
+ /**
4
+ * A widget the reader opened stays open when its row leaves the window and comes back.
5
+ *
6
+ * This is the one blocker on retrofitting `plugin-assistant`, whose tool panels are exactly this: a
7
+ * disclosure whose open flag is React state inside the widget, which dies with the item. In a
8
+ * thread that is one long document the question never arises, because nothing ever unmounts.
9
+ */
10
+ declare const meta: Meta<FeedStoryProps>;
11
+ export default meta;
12
+ type Story = StoryObj<FeedStoryProps>;
13
+ /** Passive: toggle the panels by hand. */
14
+ export declare const Default: Story;
15
+ export declare const Reopened: Story;
16
+ //# sourceMappingURL=widget.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/widget.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;GAMG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAM9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAkBtC,0CAA0C;AAC1C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAuDtB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { type FeedScenario } from './scenarios';
3
+ export type FeedStoryProps = {
4
+ /**
5
+ * Which downstream call site to approximate. Each supplies its own renderer, chrome and follow
6
+ * behaviour; everything else — the list, virtualization, selection, search — is the same engine.
7
+ * Omitted, the story runs the synthetic mixed feed the measurements were taken against.
8
+ */
9
+ scenario?: FeedScenario;
10
+ /** Messages of seeded history; 0 starts empty. */
11
+ count?: number;
12
+ /** Outline every item and every block inside it; the toolbar toggles it too. */
13
+ debug?: boolean;
14
+ /** Begin streaming turns on mount. */
15
+ streaming?: boolean;
16
+ wordsPerChunk?: number;
17
+ chunkDelay?: number;
18
+ estimateSize?: number;
19
+ /** Reserve space below the last row so any message can be brought to the top. */
20
+ scrollPastEnd?: boolean;
21
+ };
22
+ /**
23
+ * The one renderer every `MessageList` story uses; the stories differ only by args.
24
+ *
25
+ * Seeded history, a search over the model, message-set selection, and a play control that streams
26
+ * turns into the tail until stopped — one harness, so a story is a set of arguments rather than
27
+ * another component to keep in step.
28
+ */
29
+ export declare const FeedStory: ({ scenario, scrollPastEnd, count, debug: debugProp, streaming: streamingProp, wordsPerChunk, chunkDelay, estimateSize, }: FeedStoryProps) => React.JSX.Element;
30
+ //# sourceMappingURL=FeedStory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeedStory.d.ts","sourceRoot":"","sources":["../../../../src/testing/FeedStory.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAazE,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,aAAa,CAAC;AAmFhE,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,6HASnB,cAAc,sBA+LhB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import React, { type ComponentType } from 'react';
2
+ import { type Message } from '@dxos/types';
3
+ import { type MessageChromeProps } from '../components';
4
+ import { type MessageRenderer } from '../model';
5
+ import { type WindowController, type WindowState } from '../virtualizer';
6
+ /**
7
+ * A feed of real messages placed by `Window`, and nothing else.
8
+ *
9
+ * The bridge between the placement layer and the thing it has to replace. `placement/*` proves the
10
+ * shape against boxes that cannot lie about their size; `baseline/*` proves the current engine
11
+ * against real editors. This is where those meet: the same messages, the same renderer and the same
12
+ * chrome as a feed, but placed by the new module — so the baseline invariants can be pointed at it
13
+ * and answer whether the replacement is ready, rather than the question being settled by argument.
14
+ *
15
+ * Deliberately *not* wired into `MessageList.Root`. Root owns the follow, the sticky tail, the
16
+ * anchors and the cursor as well as the virtualizer, so swapping the placement inside it is not a
17
+ * swap but a reimplementation — and doing that before this exists would leave nothing to check it
18
+ * against.
19
+ */
20
+ export type MessageWindowProps = {
21
+ messages: Message.Message[];
22
+ renderer?: MessageRenderer;
23
+ Chrome?: ComponentType<MessageChromeProps>;
24
+ Custom?: ComponentType<{
25
+ content: any;
26
+ message: Message.Message;
27
+ }>;
28
+ /** Extent of a row before it has been measured; a function where rows differ widely. */
29
+ estimateSize?: number | ((message: Message.Message, index: number) => number);
30
+ gutter?: 'sm' | 'md' | 'lg';
31
+ /** Keep the last message against the bottom as content arrives — a chat's standing intent. */
32
+ sticky?: boolean;
33
+ /**
34
+ * Empty extent after the last row, so it can be brought to the top of the viewport.
35
+ *
36
+ * A number, computed by the host from its own container. Not a `scrollPastEnd` mode: with the
37
+ * window placed rather than the rows, the reserve is a term in the sizer and nothing else in the
38
+ * engine knows about it (§7) — which is what the old engine could not say, since its reserve was
39
+ * a DOM spacer outside the virtualizer's coordinate space.
40
+ */
41
+ reserve?: number;
42
+ onChange?: (state: WindowState) => void;
43
+ controllerRef?: React.Ref<WindowController>;
44
+ };
45
+ export declare const MessageWindow: ({ messages, renderer, Chrome, Custom, estimateSize, gutter, sticky, reserve, onChange, controllerRef, }: MessageWindowProps) => React.JSX.Element;
46
+ /** Kept for the stories that drive it; the ref is the same handle `placement/*` uses. */
47
+ export declare const useMessageWindow: () => React.RefObject<WindowController | null>;
48
+ //# sourceMappingURL=MessageWindow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageWindow.d.ts","sourceRoot":"","sources":["../../../../src/testing/MessageWindow.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAA0C,MAAM,OAAO,CAAC;AAG1F,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EAAE,KAAK,eAAe,EAAmB,MAAM,UAAU,CAAC;AACjE,OAAO,EAAU,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEjF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;KAAE,CAAC,CAAC;IACnE,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAC9E,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC5B,8FAA8F;IAC9F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,aAAa,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7C,CAAC;AAIF,eAAO,MAAM,aAAa,4GAWvB,kBAAkB,sBA+CpB,CAAC;AA0BF,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,gDAAuC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { type Message } from '@dxos/types';
3
+ /**
4
+ * Controls for attributing what a row costs to mount.
5
+ *
6
+ * `baseline/mount` measures a whole feed with its fixtures already built and finds ~2ms for a row
7
+ * with no editor against ~15ms for a row with one — while the same editor constructed into an
8
+ * offscreen container costs 0.4ms (`baseline/construction`). These render the *same* rows through
9
+ * the same chrome, differing only in what is inside them, so the gap can be attributed rather than
10
+ * argued about.
11
+ */
12
+ export type ControlContent = {
13
+ data?: unknown;
14
+ };
15
+ /** The floor: the row's text, and no editor at all. */
16
+ export declare const TextItem: ({ content }: {
17
+ content: ControlContent;
18
+ message: Message.Message;
19
+ }) => React.JSX.Element;
20
+ export declare const BareEditorItem: ({ content }: {
21
+ content: ControlContent;
22
+ message: Message.Message;
23
+ }) => React.JSX.Element;
24
+ export declare const ThemedEditorItem: ({ content }: {
25
+ content: ControlContent;
26
+ message: Message.Message;
27
+ }) => React.JSX.Element;
28
+ export declare const MarkdownEditorItem: ({ content }: {
29
+ content: ControlContent;
30
+ message: Message.Message;
31
+ }) => React.JSX.Element;
32
+ export declare const DecoratedEditorItem: ({ content }: {
33
+ content: ControlContent;
34
+ message: Message.Message;
35
+ }) => React.JSX.Element;
36
+ /**
37
+ * The real item, reached the same way the probes are.
38
+ *
39
+ * The rung that separates *what the editor is configured with* from *what the component does around
40
+ * it*: everything outside this component is identical to `uniform-decorated`.
41
+ */
42
+ export declare const MarkdownProbeItem: ({ content }: {
43
+ content: ControlContent;
44
+ message: Message.Message;
45
+ }) => React.JSX.Element;
46
+ //# sourceMappingURL=controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../../../../src/testing/controls.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAU3C;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhD,uDAAuD;AACvD,eAAO,MAAM,QAAQ,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAE1F,CAAC;AAiBF,eAAO,MAAM,cAAc,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAEhG,CAAC;AAEF,eAAO,MAAM,gBAAgB,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAElG,CAAC;AAEF,eAAO,MAAM,kBAAkB,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAEpG,CAAC;AAEF,eAAO,MAAM,mBAAmB,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAErG,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,gBAAiB;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;CAAE,sBAEnG,CAAC"}
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { type ThemedClassName } from '@dxos/react-ui';
3
+ import { type FrameMeter } from '../../debug';
4
+ export type FeedStatsProps = ThemedClassName<{
5
+ meter: FrameMeter;
6
+ streaming?: boolean;
7
+ selected?: number;
8
+ hits?: number;
9
+ }>;
10
+ /**
11
+ * Everything measured about a feed, floating over it.
12
+ *
13
+ * It sits above the viewport rather than in a statusbar because a statusbar is part of the layout
14
+ * being measured: a block of readouts that grows or wraps changes the height of the scroll
15
+ * container, and every number in it would then describe a viewport the readouts themselves resized.
16
+ */
17
+ export declare const FeedStats: ({ classNames, meter, streaming, selected, hits }: FeedStatsProps) => React.JSX.Element;
18
+ //# sourceMappingURL=FeedStats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeedStats.d.ts","sourceRoot":"","sources":["../../../../../src/testing/debug/FeedStats.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAE9D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIlE,OAAO,EAAE,KAAK,UAAU,EAA+B,MAAM,aAAa,CAAC;AA8E3E,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;IAC3C,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,qDAA8D,cAAc,sBA+EjG,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './FeedStats';
2
+ export * from './sweep';
3
+ export * from './use-feed-debug';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/testing/debug/index.ts"],"names":[],"mappings":"AAYA,cAAc,aAAa,CAAC;AAE5B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,18 @@
1
+ export type SweepOptions = {
2
+ /** Travel speed in px/s. @default 3000 */
3
+ velocity?: number;
4
+ /** Time for one leg (ms). @default 5000 */
5
+ duration?: number;
6
+ /** Called once the return leg lands, or when cancelled. */
7
+ onDone?: () => void;
8
+ };
9
+ /**
10
+ * Scrolls an element down and back at a fixed speed.
11
+ *
12
+ * A measured pass has to be one repeatable gesture or the numbers cannot be compared between
13
+ * stories, and a 2,000-row feed is far too long to fling by hand. Fixed speed for a fixed time —
14
+ * rather than a fixed fraction of the document — so the two stories being compared travel the same
15
+ * distance even though they disagree about how tall the document is until their rows have measured.
16
+ */
17
+ export declare const sweepScroll: (element: HTMLElement, { velocity, duration, onDone }?: SweepOptions) => () => void;
18
+ //# sourceMappingURL=sweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.d.ts","sourceRoot":"","sources":["../../../../../src/testing/debug/sweep.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,YAAY,GAAG;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,YACb,WAAW,mCACsC,YAAY,eA+CvE,CAAC"}