@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,129 @@
1
+ import React, { type ComponentType, type PropsWithChildren } from 'react';
2
+ import { type ScrollAreaRootProps } from '@dxos/react-ui';
3
+ import { type Message } from '@dxos/types';
4
+ import { type XmlWidgetRegistry } from '@dxos/ui-editor';
5
+ import { type FeedNavigation } from '../../hooks';
6
+ import { type FeedModel, type ItemContent, type MessageRenderer } from '../../model';
7
+ /** Per-message chrome (avatar, timestamp, fork/rewind/reply controls), supplied by the host. */
8
+ export type MessageChromeProps = PropsWithChildren<{
9
+ message: Message.Message;
10
+ index: number;
11
+ selected: boolean;
12
+ onSelect: (id: string, additive: boolean) => void;
13
+ }>;
14
+ export type MessageRange = {
15
+ startIndex: number;
16
+ endIndex: number;
17
+ };
18
+ export type ScrollToOptions = {
19
+ align?: 'start' | 'center' | 'end';
20
+ behavior?: 'auto' | 'smooth';
21
+ };
22
+ /**
23
+ * The list's state and scroll controls, for parts that live outside the viewport — a toolbar's
24
+ * find-next, a statusbar's range readout.
25
+ */
26
+ export declare const useMessageList: (consumerName?: string) => {
27
+ range: MessageRange | undefined;
28
+ currentIndex: number;
29
+ navigation: FeedNavigation;
30
+ mountedRows: number;
31
+ mountedWidgets: number;
32
+ jumps: {
33
+ count: number;
34
+ worst: number;
35
+ };
36
+ shifts: number;
37
+ breaks: number;
38
+ resetShifts: () => void;
39
+ model: FeedModel;
40
+ count: number;
41
+ scrollToIndex: (index: number, options?: ScrollToOptions) => void;
42
+ scrollToBottom: (options?: ScrollToOptions) => void;
43
+ };
44
+ export type MessageListRootProps = PropsWithChildren<{
45
+ /**
46
+ * The feed's model (SPEC F-7): messages and identity, the stops policy, the streaming tail, and
47
+ * iteration (`loadBefore`/`loadAfter`, consumed when the window reaches an edge). `fromMessages`
48
+ * adapts a plain array; ECHO/queue bindings adapt outside this package.
49
+ *
50
+ * What is NOT here, deliberately: search hits (decorations — `DecorationsProvider` + an item's
51
+ * `useDecorations`), selection (`ItemSelectionProvider` + `useItemSelection`), `streamingId` and
52
+ * `isAnchor` (model concerns). The list neither knows nor routes cross-cutting per-item data.
53
+ */
54
+ model: FeedModel;
55
+ renderer?: MessageRenderer;
56
+ registry?: XmlWidgetRegistry;
57
+ /**
58
+ * Chrome wrapper; receives the item as `children`. Defaults to a bare frame.
59
+ * Chrome must be layout-stable: a control that changes a row's height on hover or focus
60
+ * re-triggers measurement, and a pointer travelling down the list mid-scroll then shifts every
61
+ * row below it. Toggle such affordances with opacity, or take them out of flow.
62
+ */
63
+ Chrome?: ComponentType<MessageChromeProps>;
64
+ /**
65
+ * Renders a `custom` item. The engine's own kinds are documents — markdown in CodeMirror, HTML —
66
+ * and both build their content asynchronously enough to be measured wrong once. A host component
67
+ * whose height is settled at first paint is the control case: if a feed of those still moves, the
68
+ * fault is the list; if it does not, the fault is in what the item is building.
69
+ */
70
+ Custom?: ComponentType<{
71
+ content: ItemContent & {
72
+ kind: 'custom';
73
+ };
74
+ message: Message.Message;
75
+ }>;
76
+ /**
77
+ * Outline each item and the blocks inside it, so what the layout is measuring is visible.
78
+ */
79
+ debug?: boolean;
80
+ /**
81
+ * Estimated row height before measurement. A function is worth supplying whenever the feed's
82
+ * rows differ widely — a one-line prompt beside a long answer — because a single number is wrong
83
+ * for both.
84
+ */
85
+ estimateSize?: number | ((message: Message.Message, index: number) => number);
86
+ /**
87
+ * Pin to the bottom as messages arrive, and as a streaming message grows (chat behaviour).
88
+ */
89
+ stickyBottom?: boolean;
90
+ /**
91
+ * Reserve empty space below the last row, so that any message — including the last — can be
92
+ * brought to the top of the viewport. A number in the sizer, not a mode the list has (§7).
93
+ */
94
+ scrollPastEnd?: boolean;
95
+ overscan?: number;
96
+ onRangeChange?: (range: MessageRange) => void;
97
+ }>;
98
+ declare function MessageListRoot({ children, model, renderer, registry, Chrome, Custom, debug, estimateSize, stickyBottom, scrollPastEnd, overscan, onRangeChange }: MessageListRootProps): React.JSX.Element;
99
+ declare namespace MessageListRoot {
100
+ var displayName: string;
101
+ }
102
+ type MessageListViewportExtra = Pick<ScrollAreaRootProps, 'autoHide' | 'centered' | 'native' | 'padding' | 'scrollbars' | 'thin'> & {
103
+ /**
104
+ * Gutter size for the three-track layout each row is laid out on (`gutter | content | gutter`).
105
+ *
106
+ * The tracks live inside the row rather than on the container, because the rows are laid out by
107
+ * the browser inside one placed parent and cannot be items of an outer grid. Chrome that wants the
108
+ * gutters — a fork control, an avatar, a resolve toggle — opts in with `Column.Row`; everything
109
+ * else sits in the centre track.
110
+ */
111
+ gutter?: 'sm' | 'md' | 'lg';
112
+ };
113
+ type MessageListItemExtra = {
114
+ message: Message.Message;
115
+ };
116
+ export declare const MessageList: {
117
+ Root: {
118
+ ({ children, model, renderer, registry, Chrome, Custom, debug, estimateSize, stickyBottom, scrollPastEnd, overscan, onRangeChange, }: MessageListRootProps): React.JSX.Element;
119
+ displayName: string;
120
+ };
121
+ Viewport: React.ForwardRefExoticComponent<Omit<MessageListViewportExtra, "className"> & {
122
+ classNames?: import("@dxos/ui-types").ClassNameValue;
123
+ } & Pick<React.HTMLAttributes<Element>, "children" | "role" | "style"> & React.RefAttributes<HTMLDivElement>>;
124
+ Item: React.ForwardRefExoticComponent<Omit<MessageListItemExtra, "className"> & {
125
+ classNames?: import("@dxos/ui-types").ClassNameValue;
126
+ } & Pick<React.HTMLAttributes<Element>, "children" | "role" | "style"> & React.RefAttributes<HTMLDivElement>>;
127
+ };
128
+ export type { MessageListItemExtra as MessageListItemProps, MessageListViewportExtra as MessageListViewportProps };
129
+ //# sourceMappingURL=MessageList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../../../src/components/MessageList/MessageList.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAMvB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAsB,KAAK,mBAAmB,EAAuC,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,KAAK,cAAc,EAAuE,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAmB,MAAM,aAAa,CAAC;AAoBtG,gGAAgG;AAChG,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;IACjD,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD,CAAC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAwCpE,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC9B,CAAC;AAIF;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;eA7BT,MAAM;eAAS,MAAM;;;;uBAIlB,IAAI;;;2BAUA,MAAM,YAAY,eAAe,KAAK,IAAI;+BACtC,eAAe,KAAK,IAAI;CA4CpD,CAAC;AAMF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;IACnD;;;;;;;;OAQG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC3C;;;;;OAKG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,WAAW,GAAG;YAAE,IAAI,EAAE,QAAQ,CAAA;SAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;KAAE,CAAC,CAAC;IAChG;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAC9E;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC/C,CAAC,CAAC;iCAYsB,EACvB,QAAQ,EACR,KAAK,EACL,QAA0B,EAC1B,QAAQ,EACR,MAAsB,EACtB,MAAM,EACN,KAAK,EACL,YAA+B,EAC/B,YAAoB,EACpB,aAAqB,EACrB,QAAY,EACZ,aAAa,EACd,EAAE,oBAAoB;;;;AAgRvB,KAAK,wBAAwB,GAAG,IAAI,CAClC,mBAAmB,EACnB,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CACvE,GAAG;IACF;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC7B,CAAC;AA8FF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;CAC1B,CAAC;AAmDF,eAAO,MAAM,WAAW;IACtB,IAAI;8IAjbH,oBAAoB;;;IAkbrB,QAAQ;;;IACR,IAAI;;;CACL,CAAC;AAEF,YAAY,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,wBAAwB,IAAI,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ import { type FeedStoryProps } from '../../testing';
3
+ declare const meta: Meta<FeedStoryProps>;
4
+ export default meta;
5
+ type Story = StoryObj<FeedStoryProps>;
6
+ /** Passive: the assistant-shaped feed under the shared harness. */
7
+ export declare const Default: Story;
8
+ export declare const Small: Story;
9
+ export declare const Medium: Story;
10
+ /**
11
+ * Scroll-quality case: the deciding criterion is smoothness here, not at 200.
12
+ *
13
+ * The statusbar's right-hand readout is `fps · worst frame · hitches`, sampled from animation
14
+ * frames and reset by clicking it. It has to be read at a real keyboard — an agent's browser
15
+ * throttles `requestAnimationFrame`, so any number collected there describes the harness.
16
+ *
17
+ * Test:
18
+ * 1. Click the frame readout to reset it, then fling-scroll the list from top to bottom twice.
19
+ * 2. Read `fps` while the scroll is running: it should hold near the display's rate.
20
+ * 3. Read `worst` and `hitches` after it settles — one 200ms stall reads as smooth in an average
21
+ * and as broken to a reader, which is why they are reported separately.
22
+ * 4. Watch the scrollbar thumb during the fling: it should not jump backwards as rows measure.
23
+ */
24
+ export declare const Large: Story;
25
+ /**
26
+ * A bad height estimate is what scrollbar drift looks like; compare against `Large`.
27
+ *
28
+ * Test:
29
+ * 1. Reset the frame readout and fling-scroll to the middle of the list.
30
+ * 2. Compare `worst` and `hitches` against `Large` — the cost of measurement correction is the
31
+ * difference between the two stories, since nothing else changes.
32
+ * 3. Hold at one position for a second: the rows must not creep once measurement catches up.
33
+ */
34
+ export declare const BadEstimate: Story;
35
+ /**
36
+ * A model answering into the tail, from nothing, until stopped. The answer arrives in word chunks
37
+ * and re-parses as markdown (heading, list, code fence) while the row it lives in grows.
38
+ *
39
+ * Test:
40
+ * 1. Reset the frame readout and let three or four turns arrive.
41
+ * 2. Read `fps` while the tail grows — the follow runs on animation frames, so it competes with
42
+ * the item re-parsing its markdown, and this is where they collide.
43
+ * 3. Scroll away mid-answer: the follow must stop and stay stopped.
44
+ * 4. Scroll back to the tail: it must resume following without a jump.
45
+ */
46
+ export declare const Streaming: Story;
47
+ //# sourceMappingURL=MessageList.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/MessageList/MessageList.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,cAAc,CAa9B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;AAStC,mEAAmE;AACnE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAKpB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './MessageList';
2
+ export * from './position-log';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/MessageList/index.ts"],"names":[],"mappings":"AAIA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,73 @@
1
+ export type PositionStats = {
2
+ /** Rows whose offset changed after they were laid out — every one of these is a visible flicker. */
3
+ shifts: number;
4
+ /** Windows where offsets did not increase with index; a row was placed over its neighbour. */
5
+ breaks: number;
6
+ /** The most recent shift, for reading in the console while scrolling. */
7
+ last?: PositionShift;
8
+ };
9
+ export type PositionShift = {
10
+ index: number;
11
+ from: number;
12
+ to: number;
13
+ delta: number;
14
+ };
15
+ /** `key` is the virtualizer's item key — the message id, via `getItemKey`. */
16
+ export type PositionKey = number | string | bigint;
17
+ export type PositionEntry = {
18
+ key: PositionKey;
19
+ index: number;
20
+ start: number;
21
+ };
22
+ /** Movement of the viewport itself between samples, which every row is expected to follow. */
23
+ export type PositionFrame = {
24
+ scrollOffset: number;
25
+ };
26
+ /**
27
+ * Records where each row was placed, and reports when a row moves.
28
+ *
29
+ * A virtualized list is only still if a row's offset, once laid out, does not change: rows above the
30
+ * reader are measured as they mount, and any correction there pushes everything below it. Scrolling
31
+ * **up** is where this shows, because that is the direction in which unmeasured rows enter — going
32
+ * down, the rows above have already been measured.
33
+ *
34
+ * Positions are recorded **relative to the viewport** (`start - scrollOffset`), not as absolute
35
+ * document offsets, because those two answer different questions. Measuring a row for the first time
36
+ * re-lays every row below it, and the virtualizer compensates by moving `scrollTop` the same
37
+ * distance — the offsets all change and the reader sees nothing. What a reader sees is a row landing
38
+ * somewhere else on screen, which is what this counts.
39
+ *
40
+ * Two invariants:
41
+ *
42
+ * 1. a row keyed by message id holds its place on screen for as long as it stays mounted;
43
+ * 2. positions within the mounted window increase strictly with index.
44
+ *
45
+ * The count is what a reader means by "flicker". Deliberately kept as a count rather than a log:
46
+ * a scroll produces thousands of samples, and the number is the signal.
47
+ */
48
+ /**
49
+ * Watches for jumps in what was actually painted, once per animation frame.
50
+ *
51
+ * The counting above is done per React render, which cannot separate a row moving from the sampling
52
+ * happening at a different moment than the layout. This reads the scroll and every row's box in the
53
+ * **same** frame and compares each row's travel against the scroll's: a row that keeps its place in
54
+ * the document travels exactly as far as the scroll did, so anything else is the reader seeing a
55
+ * jump. It is the in-page form of measuring a screen recording frame by frame, and it is what a
56
+ * developer should have running while working on the list.
57
+ */
58
+ export declare const useJumpDetector: (viewport: HTMLElement | null, enabled?: boolean) => {
59
+ count: number;
60
+ worst: number;
61
+ };
62
+ export declare const usePositionLog: () => {
63
+ /** Rows whose offset changed after they were laid out — every one of these is a visible flicker. */
64
+ shifts: number;
65
+ /** Windows where offsets did not increase with index; a row was placed over its neighbour. */
66
+ breaks: number;
67
+ /** The most recent shift, for reading in the console while scrolling. */
68
+ last?: PositionShift;
69
+ trace: import("react").RefObject<PositionShift[]>;
70
+ record: (entries: readonly PositionEntry[], { scrollOffset }: PositionFrame) => void;
71
+ reset: () => void;
72
+ };
73
+ //# sourceMappingURL=position-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"position-log.d.ts","sourceRoot":"","sources":["../../../../../src/components/MessageList/position-log.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GAAG;IAC1B,oGAAoG;IACpG,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAKvF,8EAA8E;AAC9E,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG;IAAE,GAAG,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,8FAA8F;AAC9F,MAAM,MAAM,aAAa,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,aAAc,WAAW,GAAG,IAAI;;;CA8C3D,CAAC;AAEF,eAAO,MAAM,cAAc;IAvGzB,oGAAoG;YAC5F,MAAM;IACd,8FAA8F;YACtF,MAAM;IACd,yEAAyE;WAClE,aAAa;;sBA+GiB,SAAS,aAAa,EAAE,oBAAoB,aAAa;;CAwC/F,CAAC"}
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { type ThemedClassName } from '@dxos/react-ui';
3
+ import { type WindowState } from '../../virtualizer';
4
+ /**
5
+ * The whole list at a glance: what exists, what is mounted, and what the reader can see.
6
+ *
7
+ * Drawn in **content space**, not in indices. The three quantities a virtualized list can get wrong
8
+ * are where the mounted rows are, how big the reader's slice of them is, and whether the total the
9
+ * thumb is scaled against is honest — and none of those are visible from a row count. Here they are
10
+ * three bars on one track, so a mounted range that has drifted away from the viewport, or a total
11
+ * that jumps while nothing scrolls, is a picture rather than a number to be noticed.
12
+ *
13
+ * Debug only. It reads the state the window publishes and draws it (§2); it does not participate.
14
+ */
15
+ export type MinimapProps = ThemedClassName<{
16
+ state?: WindowState;
17
+ /** Width of the rail, in px. @default 32 (2rem) */
18
+ width?: number;
19
+ /**
20
+ * Jump to where the reader pointed, as a fraction of the whole list.
21
+ *
22
+ * A fraction and not an index: the map is drawn in content space, so what a click names is a
23
+ * position, and turning that into a row is the host's business — it has the count.
24
+ */
25
+ onSelect?: (fraction: number) => void;
26
+ }>;
27
+ export declare const Minimap: ({ classNames, state, width, onSelect }: MinimapProps) => React.JSX.Element;
28
+ //# sourceMappingURL=Minimap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minimap.d.ts","sourceRoot":"","sources":["../../../../../src/components/Minimap/Minimap.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GAAG,eAAe,CAAC;IACzC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC,CAAC;AAEH,eAAO,MAAM,OAAO,2CAA4D,YAAY,sBA6C3F,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
2
+ /**
3
+ * The minimap against a live window, because its whole job is to draw what the window publishes:
4
+ * the track is the document, the faint band the mounted rows, the solid band the viewport. Scroll
5
+ * the list and the bands move; click the rail and the list jumps to that fraction.
6
+ */
7
+ type StoryArgs = {
8
+ count?: number;
9
+ width?: number;
10
+ };
11
+ declare const meta: Meta<StoryArgs>;
12
+ export default meta;
13
+ type Story = StoryObj<StoryArgs>;
14
+ /** Scroll the list, watch the bands; click the rail, the list jumps. No play. */
15
+ export declare const Default: Story;
16
+ /**
17
+ * The viewport band stays inside the mounted band — a viewport showing rows that are not mounted
18
+ * would mean the reader is looking at nothing — and a click moves the list to that fraction.
19
+ */
20
+ export declare const Tracks: Story;
21
+ //# sourceMappingURL=Minimap.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minimap.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/Minimap/Minimap.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAUjE;;;;GAIG;AACH,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA2CF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,CAMzB,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEjC,iFAAiF;AACjF,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAUjC;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,KAoCpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './Minimap';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Minimap/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC"}
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { type ThemedClassName } from '@dxos/react-ui';
3
+ /**
4
+ * A single anchor marker within the mapped document.
5
+ * `range` is expressed in the document's own position space (e.g. CodeMirror offsets).
6
+ */
7
+ export type OutlineMarker = {
8
+ id: string;
9
+ title: string;
10
+ description?: string;
11
+ range: {
12
+ from: number;
13
+ to: number;
14
+ };
15
+ };
16
+ export type OutlineProps = ThemedClassName<{
17
+ markers: OutlineMarker[];
18
+ /** Currently-visible document range; markers intersecting it render brighter ("active"). */
19
+ visibleRange?: {
20
+ from: number;
21
+ to: number;
22
+ };
23
+ /**
24
+ * Height of one tick, in px.
25
+ *
26
+ * Fixed rather than shared out over the rail's height: ticks that stretch to fill make a short
27
+ * document's markers enormous and a long one's hairline, so the same rail reads as a different
28
+ * control depending on what is in it. A fixed pitch means the rail thins to what fits and every
29
+ * tick looks the same. @default 8
30
+ */
31
+ tickSize?: number;
32
+ /** Width of the rail, in px, which is also how far a tick extends at the peak of the wave. @default 32 (2rem) */
33
+ width?: number;
34
+ onSelect?: (marker: OutlineMarker, index: number) => void;
35
+ /**
36
+ * Step one item, in whatever the host counts items in.
37
+ *
38
+ * Not one tick: the rail thins its markers to what fits, so the next tick can be ten items away,
39
+ * and a reader pressing an arrow means "the next one" rather than "the next thing I can see". The
40
+ * host steps it with the same mechanism its toolbar uses, which is why this is a callback rather
41
+ * than something the rail decides.
42
+ */
43
+ onNavigate?: (delta: number) => void;
44
+ }>;
45
+ export declare const Outline: ({ classNames, markers, visibleRange, tickSize, width, onSelect, onNavigate, }: OutlineProps) => React.JSX.Element;
46
+ //# sourceMappingURL=Outline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Outline.d.ts","sourceRoot":"","sources":["../../../../../src/components/Outline/Outline.tsx"],"names":[],"mappings":"AAIA,OAAO,KAQN,MAAM,OAAO,CAAC;AAEf,OAAO,EAAW,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAgB/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,eAAe,CAAC;IACzC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,4FAA4F;IAC5F,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iHAAiH;IACjH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,CAAC,CAAC;AAkCH,eAAO,MAAM,OAAO,kFAQjB,YAAY,sBAkRd,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { type StoryObj } from '@storybook/react-vite';
2
+ import React from 'react';
3
+ import { type OutlineProps } from './Outline';
4
+ declare const meta: {
5
+ title: string;
6
+ component: ({ classNames, markers, visibleRange, tickSize, width, onSelect, onNavigate, }: OutlineProps) => React.JSX.Element;
7
+ render: ({ markers, ...props }: OutlineProps) => React.JSX.Element;
8
+ decorators: import("@storybook/react").Decorator[];
9
+ };
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+ export declare const Default: Story;
13
+ export declare const Empty: Story;
14
+ /**
15
+ * A click does not leave a position asserted behind it.
16
+ *
17
+ * Clicking a tick focuses it, and the card was gated on focus — so the reader clicked, moved away,
18
+ * and a keyboard position they never asked for kept it up. What may assert a position is the pointer
19
+ * being over a tick, or the keyboard having *navigated* to one; focus is neither, and a click
20
+ * confers focus as a side effect.
21
+ *
22
+ * What this does **not** cover is the pointer actually leaving, because React synthesises enter and
23
+ * leave from over/out pairs and three attempts to drive that from dispatched events did not reach
24
+ * the handler — the state was still set afterwards whether or not the component was right. Asserting
25
+ * it here would be asserting the probe. It needs a real pointer; see `chat-ui/TASKS.md`.
26
+ */
27
+ export declare const Dismissal: Story;
28
+ /**
29
+ * The arrows take the card over from the pointer, and pointing takes it back.
30
+ *
31
+ * A reader clicks a tick and then presses an arrow without moving the mouse — which is the whole
32
+ * point of clicking one. The pointer is still resting on the tick they clicked, so a rule of
33
+ * "the pointer always wins" pins the card to a place they have already left, and the feed scrolls
34
+ * under a card describing somewhere else. Reported from a real session as "card does not move".
35
+ */
36
+ export declare const KeyboardTakeover: Story;
37
+ //# sourceMappingURL=Outline.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Outline.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/Outline/Outline.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD,OAAO,EAA+B,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAoE3E,QAAA,MAAM,IAAI;;;oCAhDmC,YAAY;;CAqDzB,CAAC;eAElB,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAInB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,EAAE,KAuBvB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAgD9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './Outline';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Outline/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './Block';
2
+ export * from './MessageList';
3
+ export * from './Minimap';
4
+ export * from './Outline';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { type ThemedClassName } from '@dxos/react-ui';
3
+ export type DebugProps = ThemedClassName<{
4
+ /** Readouts side by side. @default 1 */
5
+ columns?: number;
6
+ title?: string;
7
+ }>;
8
+ /**
9
+ * The table over whatever probes are registered (SPEC follow-up: generic debug mechanism, built
10
+ * once and reused by future react-ui components rather than re-invented per surface).
11
+ *
12
+ * Values are sampled once per animation frame while mounted — the model is not reactive over
13
+ * values by design, so the table is the only thing paying for sixty reads a second. Grouped by the
14
+ * probe's `group`, in fixed tracks so a changing digit moves nothing beside it.
15
+ */
16
+ export declare const Debug: ({ columns, title, classNames }: DebugProps) => React.JSX.Element | null;
17
+ //# sourceMappingURL=Debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Debug.d.ts","sourceRoot":"","sources":["../../../../src/debug/Debug.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAEhF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAOtD,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC;IACvC,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,mCAAwC,UAAU,6BA8DnE,CAAC"}
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { type ThemedClassName } from '@dxos/react-ui';
3
+ /** Readouts are mostly counts, but a range (`463–499`) is one reading and reads as one cell. */
4
+ export type StatValue = number | string;
5
+ export type Stat = {
6
+ id: string;
7
+ label?: string;
8
+ unit?: string;
9
+ /** Emphasis for a value that means something is wrong; called with the current value. */
10
+ classNames?: (value: StatValue) => string | false | undefined;
11
+ };
12
+ export type StatsProps = ThemedClassName<{
13
+ 'stats': Stat[];
14
+ 'values': Record<string, StatValue>;
15
+ /** Readouts side by side, for a panel that is wider than it is tall. @default 1 */
16
+ 'columns'?: number;
17
+ 'title'?: string;
18
+ 'data-testid'?: string;
19
+ }>;
20
+ /**
21
+ * A block of readouts, in fixed tracks.
22
+ *
23
+ * Every number here changes while the feed scrolls, so the value and unit columns are given widths
24
+ * rather than sized to their contents: a column that fits itself to `4` and then to `1054` moves
25
+ * every digit beside it, and an instrument that moves cannot be read at a glance.
26
+ */
27
+ export declare const Stats: ({ stats, values, columns, classNames, title, ...props }: StatsProps) => React.JSX.Element;
28
+ /** Anything above zero is a defect, not a reading. */
29
+ export declare const warnAbove: (value: StatValue) => "text-warning-text" | false;
30
+ //# sourceMappingURL=Stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stats.d.ts","sourceRoot":"","sources":["../../../../src/debug/Stats.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,gGAAgG;AAChG,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExC,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC;IACvC,OAAO,EAAE,IAAI,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,4DAAiE,UAAU,sBAiB5F,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,SAAS,UAAW,SAAS,gCAA6C,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * One live readout: a name and how to read it. Reading must be cheap — the table reads every probe
3
+ * once per animation frame while it is shown.
4
+ */
5
+ export type DebugProbe = {
6
+ id: string;
7
+ /** Probes render grouped; a group is a component's or an aspect's set. */
8
+ group?: string;
9
+ label?: string;
10
+ unit?: string;
11
+ read: () => number | string;
12
+ /** Emphasis when the value means something is wrong. */
13
+ alarm?: (value: number | string) => boolean;
14
+ };
15
+ /**
16
+ * A registry of live readouts, so a debug table can render *whatever is currently instrumented*
17
+ * rather than a hard-coded panel per surface (SPEC follow-up: the generic debug mechanism).
18
+ *
19
+ * Deliberately not reactive state: probes are read by whoever renders them, per frame, and a value
20
+ * that changed sixty times a second is not worth sixty renders of anything but the table itself.
21
+ * Registration is the only event.
22
+ */
23
+ export declare class DebugModel {
24
+ #private;
25
+ register(probe: DebugProbe): () => void;
26
+ probes(): DebugProbe[];
27
+ /** Every probe's current value, in one pass. */
28
+ read(): Record<string, number | string>;
29
+ /** Fires on registration changes only, never on values. */
30
+ subscribe(listener: () => void): () => void;
31
+ }
32
+ //# sourceMappingURL=debug-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-model.d.ts","sourceRoot":"","sources":["../../../../src/debug/debug-model.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,MAAM,GAAG,MAAM,CAAC;IAC5B,wDAAwD;IACxD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,OAAO,CAAC;CAC7C,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,UAAU;;IAIrB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,IAAI,CAOtC;IAED,MAAM,IAAI,UAAU,EAAE,CAErB;IAED,gDAAgD;IAChD,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAOtC;IAED,2DAA2D;IAC3D,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG1C;CAOF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debug-model.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-model.test.d.ts","sourceRoot":"","sources":["../../../../src/debug/debug-model.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ export type FrameStats = {
2
+ /** Frames per second over the last reporting window — what the eye checks while a gesture runs. */
3
+ fps: number;
4
+ /** Rate at the median frame: the pass's typical smoothness. */
5
+ p50: number;
6
+ /** Rate at the 95th-percentile (slowest) frame: what the pass felt like at its worst fifth. */
7
+ p95: number;
8
+ /** Longest frame (ms) since the pass began. */
9
+ worst: number;
10
+ /** Frames over {@link HITCH_MS} since the pass began. */
11
+ hitches: number;
12
+ /** Frames sampled, so a reading of zero hitches can be weighed against how long it was measured. */
13
+ frames: number;
14
+ /** Length of the pass so far (ms). */
15
+ duration: number;
16
+ };
17
+ /**
18
+ * Rate (fps) at the frame standing at `quantile` of a pass, counting from the fast end — so 0.95 is
19
+ * the slow tail, the fifth of the pass a reader would call the stutter.
20
+ *
21
+ * `buckets` counts frames by their duration in whole milliseconds. Exported for its test: this is
22
+ * the number the engine's verdict rests on, and an off-by-one in the walk would flatter it.
23
+ */
24
+ export declare const rateAtQuantile: (buckets: Uint32Array, frames: number, quantile: number) => number;
25
+ export type FrameMeterOptions = {
26
+ /** Names the pass in the recorded line — the story's arguments, since they are what varies. */
27
+ label?: string;
28
+ };
29
+ /** Live statistics plus the control that ends one pass and begins the next. */
30
+ export type FrameMeter = FrameStats & {
31
+ label?: string;
32
+ record: () => string;
33
+ };
34
+ /**
35
+ * Samples animation-frame intervals and records a pass on demand.
36
+ *
37
+ * This exists because scroll smoothness is the deciding criterion for the feed engine and no
38
+ * automated harness can report it: an agent's browser throttles `requestAnimationFrame`, so any
39
+ * number collected there describes the harness. Averages hide the defect — a scroll that holds
40
+ * 60fps and stalls once for 200ms reads as smooth in a mean and as broken to a reader — so the
41
+ * percentiles, the worst frame and the hitch count are reported together, and each hitch is traced
42
+ * to the console as it happens so a bad number can be turned into a cause.
43
+ *
44
+ * Durations are bucketed by the millisecond rather than kept, so a pass costs the same however long
45
+ * it runs; percentiles come out of the histogram.
46
+ */
47
+ export declare const useFrameMeter: ({ label }?: FrameMeterOptions) => FrameMeter;
48
+ //# sourceMappingURL=frame-meter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-meter.d.ts","sourceRoot":"","sources":["../../../../src/debug/frame-meter.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,UAAU,GAAG;IACvB,mGAAmG;IACnG,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,+FAA+F;IAC/F,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,YAAa,WAAW,UAAU,MAAM,YAAY,MAAM,KAAG,MAevF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,MAAM,CAAA;CAAE,CAAC;AAE/E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,eAAe,iBAAiB,KAAQ,UAoGjE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=frame-meter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-meter.test.d.ts","sourceRoot":"","sources":["../../../../src/debug/frame-meter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export * from './Debug';
2
+ export * from './debug-model';
3
+ export * from './frame-meter';
4
+ export * from './Stats';
5
+ export * from './use-debug';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/debug/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}