@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.
- package/LICENSE +105 -0
- package/dist/lib/chunk-src.mjs +2228 -0
- package/dist/lib/chunk-src.mjs.map +1 -0
- package/dist/lib/index.mjs +2 -0
- package/dist/lib/testing.mjs +1923 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/types/src/components/Block/HtmlBlock.d.ts +14 -0
- package/dist/types/src/components/Block/HtmlBlock.d.ts.map +1 -0
- package/dist/types/src/components/Block/MarkdownBlock.d.ts +24 -0
- package/dist/types/src/components/Block/MarkdownBlock.d.ts.map +1 -0
- package/dist/types/src/components/Block/block.stories.d.ts +21 -0
- package/dist/types/src/components/Block/block.stories.d.ts.map +1 -0
- package/dist/types/src/components/Block/construction.d.ts +36 -0
- package/dist/types/src/components/Block/construction.d.ts.map +1 -0
- package/dist/types/src/components/Block/extensions.d.ts +23 -0
- package/dist/types/src/components/Block/extensions.d.ts.map +1 -0
- package/dist/types/src/components/Block/highlight.d.ts +14 -0
- package/dist/types/src/components/Block/highlight.d.ts.map +1 -0
- package/dist/types/src/components/Block/index.d.ts +6 -0
- package/dist/types/src/components/Block/index.d.ts.map +1 -0
- package/dist/types/src/components/Block/selection-group.d.ts +21 -0
- package/dist/types/src/components/Block/selection-group.d.ts.map +1 -0
- package/dist/types/src/components/Block/widget-state.d.ts +33 -0
- package/dist/types/src/components/Block/widget-state.d.ts.map +1 -0
- package/dist/types/src/components/MessageList/MessageList.d.ts +129 -0
- package/dist/types/src/components/MessageList/MessageList.d.ts.map +1 -0
- package/dist/types/src/components/MessageList/MessageList.stories.d.ts +47 -0
- package/dist/types/src/components/MessageList/MessageList.stories.d.ts.map +1 -0
- package/dist/types/src/components/MessageList/index.d.ts +3 -0
- package/dist/types/src/components/MessageList/index.d.ts.map +1 -0
- package/dist/types/src/components/MessageList/position-log.d.ts +73 -0
- package/dist/types/src/components/MessageList/position-log.d.ts.map +1 -0
- package/dist/types/src/components/Minimap/Minimap.d.ts +28 -0
- package/dist/types/src/components/Minimap/Minimap.d.ts.map +1 -0
- package/dist/types/src/components/Minimap/Minimap.stories.d.ts +21 -0
- package/dist/types/src/components/Minimap/Minimap.stories.d.ts.map +1 -0
- package/dist/types/src/components/Minimap/index.d.ts +2 -0
- package/dist/types/src/components/Minimap/index.d.ts.map +1 -0
- package/dist/types/src/components/Outline/Outline.d.ts +46 -0
- package/dist/types/src/components/Outline/Outline.d.ts.map +1 -0
- package/dist/types/src/components/Outline/Outline.stories.d.ts +37 -0
- package/dist/types/src/components/Outline/Outline.stories.d.ts.map +1 -0
- package/dist/types/src/components/Outline/index.d.ts +2 -0
- package/dist/types/src/components/Outline/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +5 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/debug/Debug.d.ts +17 -0
- package/dist/types/src/debug/Debug.d.ts.map +1 -0
- package/dist/types/src/debug/Stats.d.ts +30 -0
- package/dist/types/src/debug/Stats.d.ts.map +1 -0
- package/dist/types/src/debug/debug-model.d.ts +32 -0
- package/dist/types/src/debug/debug-model.d.ts.map +1 -0
- package/dist/types/src/debug/debug-model.test.d.ts +2 -0
- package/dist/types/src/debug/debug-model.test.d.ts.map +1 -0
- package/dist/types/src/debug/frame-meter.d.ts +48 -0
- package/dist/types/src/debug/frame-meter.d.ts.map +1 -0
- package/dist/types/src/debug/frame-meter.test.d.ts +2 -0
- package/dist/types/src/debug/frame-meter.test.d.ts.map +1 -0
- package/dist/types/src/debug/index.d.ts +6 -0
- package/dist/types/src/debug/index.d.ts.map +1 -0
- package/dist/types/src/debug/use-debug.d.ts +19 -0
- package/dist/types/src/debug/use-debug.d.ts.map +1 -0
- package/dist/types/src/hooks/follow.d.ts +89 -0
- package/dist/types/src/hooks/follow.d.ts.map +1 -0
- package/dist/types/src/hooks/follow.stories.d.ts +25 -0
- package/dist/types/src/hooks/follow.stories.d.ts.map +1 -0
- package/dist/types/src/hooks/follow.test.d.ts +2 -0
- package/dist/types/src/hooks/follow.test.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +6 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useDecorations.d.ts +31 -0
- package/dist/types/src/hooks/useDecorations.d.ts.map +1 -0
- package/dist/types/src/hooks/useFeedNavigation.d.ts +44 -0
- package/dist/types/src/hooks/useFeedNavigation.d.ts.map +1 -0
- package/dist/types/src/hooks/useFollow.d.ts +46 -0
- package/dist/types/src/hooks/useFollow.d.ts.map +1 -0
- package/dist/types/src/hooks/useItemSelection.d.ts +34 -0
- package/dist/types/src/hooks/useItemSelection.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/model/feed-model.d.ts +67 -0
- package/dist/types/src/model/feed-model.d.ts.map +1 -0
- package/dist/types/src/model/feed-model.test.d.ts +2 -0
- package/dist/types/src/model/feed-model.test.d.ts.map +1 -0
- package/dist/types/src/model/feed.d.ts +66 -0
- package/dist/types/src/model/feed.d.ts.map +1 -0
- package/dist/types/src/model/feed.test.d.ts +2 -0
- package/dist/types/src/model/feed.test.d.ts.map +1 -0
- package/dist/types/src/model/index.d.ts +5 -0
- package/dist/types/src/model/index.d.ts.map +1 -0
- package/dist/types/src/model/list-model.d.ts +61 -0
- package/dist/types/src/model/list-model.d.ts.map +1 -0
- package/dist/types/src/model/list-model.test.d.ts +2 -0
- package/dist/types/src/model/list-model.test.d.ts.map +1 -0
- package/dist/types/src/model/useListModel.d.ts +22 -0
- package/dist/types/src/model/useListModel.d.ts.map +1 -0
- package/dist/types/src/stories/assistant.stories.d.ts +38 -0
- package/dist/types/src/stories/assistant.stories.d.ts.map +1 -0
- package/dist/types/src/stories/baseline.stories.d.ts +32 -0
- package/dist/types/src/stories/baseline.stories.d.ts.map +1 -0
- package/dist/types/src/stories/bridge.stories.d.ts +72 -0
- package/dist/types/src/stories/bridge.stories.d.ts.map +1 -0
- package/dist/types/src/stories/construction.stories.d.ts +17 -0
- package/dist/types/src/stories/construction.stories.d.ts.map +1 -0
- package/dist/types/src/stories/fill.stories.d.ts +51 -0
- package/dist/types/src/stories/fill.stories.d.ts.map +1 -0
- package/dist/types/src/stories/horizontal.stories.d.ts +17 -0
- package/dist/types/src/stories/horizontal.stories.d.ts.map +1 -0
- package/dist/types/src/stories/mount.stories.d.ts +19 -0
- package/dist/types/src/stories/mount.stories.d.ts.map +1 -0
- package/dist/types/src/stories/navigation.stories.d.ts +33 -0
- package/dist/types/src/stories/navigation.stories.d.ts.map +1 -0
- package/dist/types/src/stories/streaming.stories.d.ts +17 -0
- package/dist/types/src/stories/streaming.stories.d.ts.map +1 -0
- package/dist/types/src/stories/tail.stories.d.ts +47 -0
- package/dist/types/src/stories/tail.stories.d.ts.map +1 -0
- package/dist/types/src/stories/widget.stories.d.ts +16 -0
- package/dist/types/src/stories/widget.stories.d.ts.map +1 -0
- package/dist/types/src/testing/FeedStory.d.ts +30 -0
- package/dist/types/src/testing/FeedStory.d.ts.map +1 -0
- package/dist/types/src/testing/MessageWindow.d.ts +48 -0
- package/dist/types/src/testing/MessageWindow.d.ts.map +1 -0
- package/dist/types/src/testing/controls.d.ts +46 -0
- package/dist/types/src/testing/controls.d.ts.map +1 -0
- package/dist/types/src/testing/debug/FeedStats.d.ts +18 -0
- package/dist/types/src/testing/debug/FeedStats.d.ts.map +1 -0
- package/dist/types/src/testing/debug/index.d.ts +4 -0
- package/dist/types/src/testing/debug/index.d.ts.map +1 -0
- package/dist/types/src/testing/debug/sweep.d.ts +18 -0
- package/dist/types/src/testing/debug/sweep.d.ts.map +1 -0
- package/dist/types/src/testing/debug/use-feed-debug.d.ts +33 -0
- package/dist/types/src/testing/debug/use-feed-debug.d.ts.map +1 -0
- package/dist/types/src/testing/generator.d.ts +16 -0
- package/dist/types/src/testing/generator.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +10 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/scenarios.d.ts +58 -0
- package/dist/types/src/testing/scenarios.d.ts.map +1 -0
- package/dist/types/src/testing/stream.d.ts +22 -0
- package/dist/types/src/testing/stream.d.ts.map +1 -0
- package/dist/types/src/testing/turn.d.ts +21 -0
- package/dist/types/src/testing/turn.d.ts.map +1 -0
- package/dist/types/src/testing/widgets.d.ts +3 -0
- package/dist/types/src/testing/widgets.d.ts.map +1 -0
- package/dist/types/src/virtualizer/Window.d.ts +137 -0
- package/dist/types/src/virtualizer/Window.d.ts.map +1 -0
- package/dist/types/src/virtualizer/Window.stories.d.ts +112 -0
- package/dist/types/src/virtualizer/Window.stories.d.ts.map +1 -0
- package/dist/types/src/virtualizer/index.d.ts +3 -0
- package/dist/types/src/virtualizer/index.d.ts.map +1 -0
- package/dist/types/src/virtualizer/placement.d.ts +188 -0
- package/dist/types/src/virtualizer/placement.d.ts.map +1 -0
- package/dist/types/src/virtualizer/placement.test.d.ts +2 -0
- package/dist/types/src/virtualizer/placement.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +72 -0
- package/src/components/Block/HtmlBlock.tsx +26 -0
- package/src/components/Block/MarkdownBlock.tsx +157 -0
- package/src/components/Block/block.stories.tsx +140 -0
- package/src/components/Block/construction.ts +77 -0
- package/src/components/Block/extensions.ts +95 -0
- package/src/components/Block/highlight.ts +53 -0
- package/src/components/Block/index.ts +10 -0
- package/src/components/Block/selection-group.ts +53 -0
- package/src/components/Block/widget-state.tsx +75 -0
- package/src/components/MessageList/MessageList.stories.tsx +111 -0
- package/src/components/MessageList/MessageList.tsx +647 -0
- package/src/components/MessageList/index.ts +6 -0
- package/src/components/MessageList/position-log.ts +167 -0
- package/src/components/Minimap/Minimap.stories.tsx +129 -0
- package/src/components/Minimap/Minimap.tsx +84 -0
- package/src/components/Minimap/index.ts +5 -0
- package/src/components/Outline/Outline.stories.tsx +196 -0
- package/src/components/Outline/Outline.tsx +383 -0
- package/src/components/Outline/index.ts +5 -0
- package/src/components/index.ts +8 -0
- package/src/debug/Debug.tsx +90 -0
- package/src/debug/Stats.tsx +57 -0
- package/src/debug/debug-model.test.ts +36 -0
- package/src/debug/debug-model.ts +66 -0
- package/src/debug/frame-meter.test.ts +49 -0
- package/src/debug/frame-meter.ts +188 -0
- package/src/debug/index.ts +9 -0
- package/src/debug/use-debug.tsx +41 -0
- package/src/hooks/follow.stories.tsx +200 -0
- package/src/hooks/follow.test.ts +105 -0
- package/src/hooks/follow.ts +241 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/useDecorations.tsx +54 -0
- package/src/hooks/useFeedNavigation.ts +90 -0
- package/src/hooks/useFollow.ts +258 -0
- package/src/hooks/useItemSelection.tsx +53 -0
- package/src/index.ts +7 -0
- package/src/model/feed-model.test.ts +84 -0
- package/src/model/feed-model.ts +214 -0
- package/src/model/feed.test.ts +65 -0
- package/src/model/feed.ts +157 -0
- package/src/model/index.ts +8 -0
- package/src/model/list-model.test.ts +71 -0
- package/src/model/list-model.ts +152 -0
- package/src/model/useListModel.ts +53 -0
- package/src/stories/assistant.stories.tsx +425 -0
- package/src/stories/baseline.stories.tsx +78 -0
- package/src/stories/bridge.stories.tsx +376 -0
- package/src/stories/construction.stories.tsx +147 -0
- package/src/stories/fill.stories.tsx +271 -0
- package/src/stories/horizontal.stories.tsx +129 -0
- package/src/stories/mount.stories.tsx +233 -0
- package/src/stories/navigation.stories.tsx +145 -0
- package/src/stories/streaming.stories.tsx +132 -0
- package/src/stories/tail.stories.tsx +149 -0
- package/src/stories/widget.stories.tsx +107 -0
- package/src/testing/FeedStory.tsx +452 -0
- package/src/testing/MessageWindow.tsx +139 -0
- package/src/testing/controls.tsx +96 -0
- package/src/testing/debug/FeedStats.tsx +182 -0
- package/src/testing/debug/index.ts +16 -0
- package/src/testing/debug/sweep.ts +85 -0
- package/src/testing/debug/use-feed-debug.ts +91 -0
- package/src/testing/generator.ts +90 -0
- package/src/testing/index.ts +13 -0
- package/src/testing/scenarios.tsx +552 -0
- package/src/testing/stream.ts +70 -0
- package/src/testing/turn.ts +91 -0
- package/src/testing/widgets.tsx +183 -0
- package/src/virtualizer/Window.stories.tsx +683 -0
- package/src/virtualizer/Window.tsx +435 -0
- package/src/virtualizer/index.ts +6 -0
- package/src/virtualizer/placement.test.ts +312 -0
- package/src/virtualizer/placement.ts +403 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React, { type PropsWithChildren } from 'react';
|
|
2
|
+
import { DebugModel, type DebugProbe } from './debug-model';
|
|
3
|
+
export type DebugProviderProps = PropsWithChildren<{
|
|
4
|
+
model?: DebugModel;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Scope for probes. Anything under it may instrument itself; a `Debug` table under the same
|
|
8
|
+
* provider renders whatever registered. No provider, no cost: the hooks below no-op.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DebugProvider: ({ model: provided, children }: DebugProviderProps) => React.JSX.Element;
|
|
11
|
+
export declare const useDebugModel: () => DebugModel | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Register live readouts for as long as the component is mounted.
|
|
14
|
+
*
|
|
15
|
+
* The probe reads state through a closure, so the component never re-renders for the table's sake;
|
|
16
|
+
* `deps` re-registers when the closure would go stale (a rebuilt model, a new element).
|
|
17
|
+
*/
|
|
18
|
+
export declare const useDebugProbes: (probes: () => DebugProbe[], deps?: unknown[]) => void;
|
|
19
|
+
//# sourceMappingURL=use-debug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-debug.d.ts","sourceRoot":"","sources":["../../../../src/debug/use-debug.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAiD,MAAM,OAAO,CAAC;AAErG,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAI5D,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;IAAE,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAE3E;;;GAGG;AACH,eAAO,MAAM,aAAa,kCAAmC,kBAAkB,sBAG9E,CAAC;AAEF,eAAO,MAAM,aAAa,QAAO,UAAU,GAAG,SAAqC,CAAC;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,WAAY,MAAM,UAAU,EAAE,SAAQ,OAAO,EAAE,KAAQ,IAWjF,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Speeds are expressed in **rows**, not pixels: a feed of tall messages and one of short replies
|
|
3
|
+
* should travel at the same perceived rate, and only a row-relative unit gives that.
|
|
4
|
+
*/
|
|
5
|
+
export type FollowOptions = {
|
|
6
|
+
/** Ceiling on travel speed, rows/s. */
|
|
7
|
+
maxSpeed?: number;
|
|
8
|
+
/** Rate the speed ramps up, rows/s². */
|
|
9
|
+
acceleration?: number;
|
|
10
|
+
/** Rate the speed sheds on approach, rows/s². Lower than `acceleration` gives a longer landing. */
|
|
11
|
+
deceleration?: number;
|
|
12
|
+
/** Height of a row in px, sampled each frame so a measured list can refine it. */
|
|
13
|
+
rowHeight?: () => number;
|
|
14
|
+
/** Empty space reserved below the last row, which the follow must stop short of. */
|
|
15
|
+
trailing?: () => number;
|
|
16
|
+
};
|
|
17
|
+
/** The physics runs in pixels; rows are converted at the boundary by {@link ScrollFollower}. */
|
|
18
|
+
export type VelocityStep = {
|
|
19
|
+
/** Current speed, px/s. */
|
|
20
|
+
velocity: number;
|
|
21
|
+
/** Remaining distance to the target, px. */
|
|
22
|
+
distance: number;
|
|
23
|
+
/** Elapsed time since the last step, seconds. */
|
|
24
|
+
dt: number;
|
|
25
|
+
/** Ceiling, px/s. */
|
|
26
|
+
maxSpeed: number;
|
|
27
|
+
/** Ramp-up rate, px/s². */
|
|
28
|
+
acceleration: number;
|
|
29
|
+
/** Approach rate, px/s². Defaults to `acceleration`. */
|
|
30
|
+
deceleration?: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Speed for the next frame of a follow.
|
|
34
|
+
*
|
|
35
|
+
* Ramps up to `maxSpeed` and back down so the travel starts and ends gently rather than jumping.
|
|
36
|
+
* The cap is whichever is lower: the ceiling, or the speed from which the remaining distance can
|
|
37
|
+
* still be shed at `acceleration` (`v = sqrt(2·a·d)`) — that second term is what turns the arrival
|
|
38
|
+
* into a deceleration instead of a stop, and what keeps a growing target at cruise speed.
|
|
39
|
+
*
|
|
40
|
+
* Acceleration is rate-limited so a start is gradual; **deceleration is not**, because the braking
|
|
41
|
+
* curve is already a smooth ramp to zero and easing onto it instead leaves the speed above the
|
|
42
|
+
* curve for the whole approach — the follow then runs out of distance while still moving and the
|
|
43
|
+
* arrival reads as a stop rather than a landing.
|
|
44
|
+
*/
|
|
45
|
+
export declare const stepVelocity: ({ velocity, distance, dt, maxSpeed, acceleration, deceleration, }: VelocityStep) => number;
|
|
46
|
+
/**
|
|
47
|
+
* **Not wired into `MessageList` at present.** The placement engine follows the tail by holding an
|
|
48
|
+
* intent and correcting the offset, which arrives instantly; this class is the animated travel the
|
|
49
|
+
* old engine used, kept with its tests because the glide is worth having back and nothing about it
|
|
50
|
+
* was wrong. Wiring it is a decision about feel, not a repair.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* Keeps an element scrolled to its bottom while its content grows.
|
|
54
|
+
*
|
|
55
|
+
* Native `scrollTo({ behavior: 'smooth' })` restarts its easing on every call, so a target that
|
|
56
|
+
* moves every chunk never leaves the start of the curve — the motion reads as a stutter. This
|
|
57
|
+
* carries velocity across frames instead: it accelerates as a stream begins, cruises while content
|
|
58
|
+
* keeps arriving, and decelerates onto the tail when it stops.
|
|
59
|
+
*
|
|
60
|
+
* `@dxos/ui-editor`'s `createCrawler` follows a streaming CodeMirror document the same way, with a
|
|
61
|
+
* critically-damped spring. The two are deliberately separate: that one is bound to `view.scrollDOM`
|
|
62
|
+
* and driven by editor effects, where a feed owns its own scroll container. The models differ in
|
|
63
|
+
* feel — a spring's speed falls off with distance, where this holds a ceiling and brakes onto the
|
|
64
|
+
* target, which keeps a fast stream at a constant rate rather than an ever-widening lag.
|
|
65
|
+
*/
|
|
66
|
+
export declare class ScrollFollower {
|
|
67
|
+
#private;
|
|
68
|
+
private readonly _element;
|
|
69
|
+
constructor(_element: HTMLElement, { maxSpeed, acceleration, deceleration, rowHeight, trailing }?: FollowOptions);
|
|
70
|
+
get running(): boolean;
|
|
71
|
+
/** Current speed, rows/s. Exposed so a harness can show the ramp. */
|
|
72
|
+
get velocity(): number;
|
|
73
|
+
/** Starts (or continues) travelling towards the bottom. Safe to call on every content change. */
|
|
74
|
+
start(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Coasts to a halt, shedding speed at `deceleration` — what a stream ending or a stop control
|
|
77
|
+
* means. Cutting the animation instead would halt mid-glide, which is the one motion the reader
|
|
78
|
+
* cannot have caused and so reads as a fault.
|
|
79
|
+
*/
|
|
80
|
+
stop(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Halts immediately, discarding the velocity — the reader has taken over, or the list is going
|
|
83
|
+
* away. Coasting here would fight a hand already on the scrollbar.
|
|
84
|
+
*/
|
|
85
|
+
cancel(): void;
|
|
86
|
+
/** Jumps to the bottom with no animation. */
|
|
87
|
+
jump(): void;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.d.ts","sourceRoot":"","sources":["../../../../src/hooks/follow.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mGAAmG;IACnG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IACzB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;CACzB,CAAC;AAkBF,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG;IACzB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,sEAOtB,YAAY,KAAG,MAIjB,CAAC;AAEF;;;;;GAKG;AACH;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;;IAavB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAD3B,YACmB,QAAQ,EAAE,WAAW,EACtC,EACE,QAA4B,EAC5B,YAAmC,EACnC,YAAmC,EACnC,SAAoC,EACpC,QAAkB,EACnB,GAAE,aAAkB,EAOtB;IAaD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,qEAAqE;IACrE,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,iGAAiG;IACjG,KAAK,IAAI,IAAI,CAQZ;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,CAOX;IAED;;;OAGG;IACH,MAAM,IAAI,IAAI,CAOb;IAED,6CAA6C;IAC7C,IAAI,IAAI,IAAI,CAGX;CAkDF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
2
|
+
type StoryProps = {
|
|
3
|
+
count?: number;
|
|
4
|
+
/** rows/s */
|
|
5
|
+
maxSpeed?: number;
|
|
6
|
+
/** rows/s² */
|
|
7
|
+
acceleration?: number;
|
|
8
|
+
/** rows/s²; defaults to `acceleration` */
|
|
9
|
+
deceleration?: number;
|
|
10
|
+
/** Append an item every `growInterval` ms while following, to test a moving target. */
|
|
11
|
+
grow?: boolean;
|
|
12
|
+
growInterval?: number;
|
|
13
|
+
};
|
|
14
|
+
declare const meta: Meta<StoryProps>;
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<StoryProps>;
|
|
17
|
+
/** Fixed target: press play and watch it ramp up, cruise, then brake onto the last row. */
|
|
18
|
+
export declare const Default: Story;
|
|
19
|
+
/** Moving target: rows keep arriving, so the follow should hold its cruise speed rather than stutter. */
|
|
20
|
+
export declare const Growing: Story;
|
|
21
|
+
/** Slower and gentler — the dials, for comparing feel. */
|
|
22
|
+
export declare const Gentle: Story;
|
|
23
|
+
/** Brakes harder than it accelerates: a quick pick-up with a long, soft landing. */
|
|
24
|
+
export declare const LateBraking: Story;
|
|
25
|
+
//# sourceMappingURL=follow.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.stories.d.ts","sourceRoot":"","sources":["../../../../src/hooks/follow.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAYjE,KAAK,UAAU,GAAG;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAgJF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,CAM1B,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;AAElC,2FAA2F;AAC3F,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,yGAAyG;AACzG,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,MAAM,EAAE,KAEpB,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.test.d.ts","sourceRoot":"","sources":["../../../../src/hooks/follow.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React, { type PropsWithChildren } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A range of one item's rendered text that some producer wants painted (SPEC: Decoration).
|
|
4
|
+
*
|
|
5
|
+
* Search is ONE producer — mentions, lint results and diff spans are others — which is why this is
|
|
6
|
+
* not called a hit: the item painting the range does not care where it came from, and the list does
|
|
7
|
+
* not know it exists at all.
|
|
8
|
+
*/
|
|
9
|
+
export type Decoration = {
|
|
10
|
+
/** Item (message) id. */
|
|
11
|
+
id: string;
|
|
12
|
+
range: {
|
|
13
|
+
offset: number;
|
|
14
|
+
length: number;
|
|
15
|
+
};
|
|
16
|
+
/** Producer tag: 'search' | 'mention' | ... */
|
|
17
|
+
kind: string;
|
|
18
|
+
};
|
|
19
|
+
export type DecorationsProviderProps = PropsWithChildren<{
|
|
20
|
+
decorations?: readonly Decoration[];
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* THE PATTERN for cross-cutting per-item data (SPEC §Aspects), not a feed feature: a provider at
|
|
24
|
+
* the host carries what producers made, and an item asks for its own by id. The list neither knows
|
|
25
|
+
* nor routes — `hits` left its API entirely. Grouped once per change rather than filtered per item,
|
|
26
|
+
* so a long feed stays O(decorations).
|
|
27
|
+
*/
|
|
28
|
+
export declare const DecorationsProvider: ({ decorations, children }: DecorationsProviderProps) => React.JSX.Element;
|
|
29
|
+
/** An item's own decorations. Items work without a provider — they are simply undecorated. */
|
|
30
|
+
export declare const useDecorations: (id: string) => readonly Decoration[];
|
|
31
|
+
//# sourceMappingURL=useDecorations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDecorations.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useDecorations.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAsC,MAAM,OAAO,CAAC;AAE1F;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAIF,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;IACvD,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACrC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,8BAA+B,wBAAwB,sBAatF,CAAC;AAIF,8FAA8F;AAC9F,eAAO,MAAM,cAAc,OAAQ,MAAM,KAAG,SAAS,UAAU,EAE9D,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type Stop } from '../model';
|
|
3
|
+
import { type WindowController } from '../virtualizer';
|
|
4
|
+
export type UseFeedNavigationOptions = {
|
|
5
|
+
controller: RefObject<WindowController | null>;
|
|
6
|
+
/** The stops policy's current answer; asked per press, so a policy change needs no rewiring. */
|
|
7
|
+
stops: () => readonly Stop[];
|
|
8
|
+
/** The row containing the scroll offset — the cursor, derived and never set beside the scroll. */
|
|
9
|
+
current: () => number;
|
|
10
|
+
count: () => number;
|
|
11
|
+
/** Align the last stop to the end unless space is reserved past it (the reserve is scrollable). */
|
|
12
|
+
scrollPastEnd?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Told before every jump, with the target index — the follow's `onNavigate` goes here. Without
|
|
15
|
+
* it a navigation races the follow's correction effect, which runs before the jump's scroll
|
|
16
|
+
* event can withdraw the intent and snaps the reader straight back to the tail they just left.
|
|
17
|
+
* The follow may move the view only while content is arriving AND the reader has pinned
|
|
18
|
+
* themselves to the bottom; navigating into the feed un-pins by definition.
|
|
19
|
+
*/
|
|
20
|
+
onNavigate?: (index: number) => void;
|
|
21
|
+
};
|
|
22
|
+
export type FeedNavigation = {
|
|
23
|
+
/** Move by `delta` stops. Every press travels: see below. */
|
|
24
|
+
step: (delta: number) => void;
|
|
25
|
+
/** Jump to a stop (or a raw index), aligning the last row to the end where that is what it means. */
|
|
26
|
+
jumpTo: (index: number, behavior?: ScrollBehavior) => void;
|
|
27
|
+
first: () => void;
|
|
28
|
+
last: () => void;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The one navigation seam (SPEC: useFeedNavigation): toolbar buttons, arrow keys, the outline rail
|
|
32
|
+
* and the minimap all call this, so they cannot disagree about what a step is.
|
|
33
|
+
*
|
|
34
|
+
* Stepping is from the row containing the scroll offset. The stop above it begins strictly higher
|
|
35
|
+
* and the stop below strictly lower, so every press moves the viewport — an index compared against
|
|
36
|
+
* a position cannot promise that while positions are still being measured. Steps glide (corrections
|
|
37
|
+
* move the window, not the scroll, so nothing cancels the animation); far jumps are instant, since
|
|
38
|
+
* a glide across unmounted rows is a journey over a blank screen.
|
|
39
|
+
*
|
|
40
|
+
* Distinct from react-ui-list's `useListNavigation`, which is focus traversal over fully-mounted
|
|
41
|
+
* rows — a different problem in the same naming family.
|
|
42
|
+
*/
|
|
43
|
+
export declare const useFeedNavigation: ({ controller, stops, current, count, scrollPastEnd, onNavigate, }: UseFeedNavigationOptions) => FeedNavigation;
|
|
44
|
+
//# sourceMappingURL=useFeedNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFeedNavigation.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useFeedNavigation.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC/C,gGAAgG;IAChG,KAAK,EAAE,MAAM,SAAS,IAAI,EAAE,CAAC;IAC7B,kGAAkG;IAClG,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,mGAAmG;IACnG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,6DAA6D;IAC7D,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,qGAAqG;IACrG,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,sEAO3B,wBAAwB,KAAG,cAgC7B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type Placement } from '../virtualizer/placement';
|
|
3
|
+
export type FollowHandle = {
|
|
4
|
+
/**
|
|
5
|
+
* A navigation is the reader answering "do you want the tail?" — and it must answer *before* the
|
|
6
|
+
* scroll moves. The intent is otherwise withdrawn by the scroll event the jump raises, which is
|
|
7
|
+
* asynchronous: the correction effect can run in between, still believe the reader is following,
|
|
8
|
+
* and snap them straight back to the tail they just left. Found by the outline rail — a click
|
|
9
|
+
* near the top of a sticky feed moved the list a few pixels and no further.
|
|
10
|
+
*/
|
|
11
|
+
onNavigate: (index: number) => void;
|
|
12
|
+
};
|
|
13
|
+
export type UseFollowOptions = {
|
|
14
|
+
scrollerRef: RefObject<HTMLElement | null>;
|
|
15
|
+
/** The placement whose `endOffset` is the tail's resting place. */
|
|
16
|
+
placement: Placement;
|
|
17
|
+
/** Total content extent — the correction re-runs when it changes, which is how growth is noticed. */
|
|
18
|
+
extent: number;
|
|
19
|
+
count: number;
|
|
20
|
+
axis?: 'block' | 'inline';
|
|
21
|
+
/** Empty extent after the last row; the end the follow rests at is before it. */
|
|
22
|
+
reserve?: number;
|
|
23
|
+
/** The standing intent: off means this hook does nothing at all. */
|
|
24
|
+
enabled?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Travel to a moved tail instead of teleporting (DECIDED: default on).
|
|
27
|
+
*
|
|
28
|
+
* The glide only covers gaps up to a viewport: beyond that the reader could not have followed the
|
|
29
|
+
* motion anyway, and the travel would cross rows whose extents are still estimates.
|
|
30
|
+
*/
|
|
31
|
+
glide?: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The sticky tail as an intent (SPEC: useFollow) — a policy over the window, not part of it.
|
|
35
|
+
*
|
|
36
|
+
* Withdrawn by one thing only: a scroll that moves *backwards*. That is the reader; a correction
|
|
37
|
+
* never moves the offset back, it moves the end away. Re-deriving the intent from proximity on
|
|
38
|
+
* every commit cannot survive its own corrections — measuring the tail grows the document under a
|
|
39
|
+
* reader who has not moved, the gap opens past any threshold worth having, and the follow reads
|
|
40
|
+
* that as the reader leaving and disengages for good (`bridge/Tail`, the second defect).
|
|
41
|
+
*
|
|
42
|
+
* Reusable for any streaming container — transcripts, logs — because nothing here knows about
|
|
43
|
+
* messages: it needs a scroller, a placement, and the two numbers that say the content grew.
|
|
44
|
+
*/
|
|
45
|
+
export declare const useFollow: ({ scrollerRef, placement, extent, count, axis, reserve, enabled, glide, }: UseFollowOptions) => FollowHandle;
|
|
46
|
+
//# sourceMappingURL=useFollow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFollow.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useFollow.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAiD,MAAM,OAAO,CAAC;AAEtF,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAS1D,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C,mEAAmE;IACnE,SAAS,EAAE,SAAS,CAAC;IACrB,qGAAqG;IACrG,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,8EASnB,gBAAgB,KAAG,YA6LrB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { type MouseEvent, type PropsWithChildren } from 'react';
|
|
2
|
+
/** What an item can do about its own selection — the item-side face of the host's selection model. */
|
|
3
|
+
export type ItemSelection = {
|
|
4
|
+
selected: boolean;
|
|
5
|
+
/** Additive when the gesture says so (meta/ctrl); the mode is the provider's business. */
|
|
6
|
+
toggle: (additive?: boolean) => void;
|
|
7
|
+
};
|
|
8
|
+
export type ItemSelectionValue = {
|
|
9
|
+
selectedIds?: ReadonlySet<string>;
|
|
10
|
+
onSelect?: (id: string, additive: boolean) => void;
|
|
11
|
+
};
|
|
12
|
+
export type ItemSelectionProviderProps = PropsWithChildren<ItemSelectionValue>;
|
|
13
|
+
/**
|
|
14
|
+
* The item-side hook of the decoration pattern applied to selection (SPEC: useItemSelection): an
|
|
15
|
+
* item asks for its own `{ selected, toggle }` by id instead of the list threading `selectedIds`
|
|
16
|
+
* through props. Selection is model-space ids, so virtualization is untouched: an unmounted item is
|
|
17
|
+
* still selected, and mounts knowing it.
|
|
18
|
+
*
|
|
19
|
+
* The provider is deliberately the thinnest thing that works — a set and a callback. Mode policies
|
|
20
|
+
* (single | multi | range) belong to `react-ui-list`'s `useListSelection`, which a host composes
|
|
21
|
+
* *above* this provider; teaching this package about modes would be rebuilding that hook.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ItemSelectionProvider: ({ selectedIds, onSelect, children }: ItemSelectionProviderProps) => React.JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* The whole selection value, for a component that renders many items in one pass.
|
|
26
|
+
*
|
|
27
|
+
* A row loop cannot call `useItemSelection` per row — hooks do not run in loops — so the viewport
|
|
28
|
+
* reads the value once and derives per-row state; item-shaped components use the per-id hook.
|
|
29
|
+
*/
|
|
30
|
+
export declare const useItemSelectionValue: () => ItemSelectionValue;
|
|
31
|
+
export declare const useItemSelection: (id: string) => ItemSelection;
|
|
32
|
+
/** Reads the additive intent off a gesture, so callers do not each invent the modifier rule. */
|
|
33
|
+
export declare const isAdditive: (event: MouseEvent | globalThis.MouseEvent) => boolean;
|
|
34
|
+
//# sourceMappingURL=useItemSelection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useItemSelection.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useItemSelection.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAA0C,MAAM,OAAO,CAAC;AAE/G,sGAAsG;AACtG,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,0FAA0F;IAC1F,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD,CAAC;AAIF,MAAM,MAAM,0BAA0B,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAE/E;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,wCAAyC,0BAA0B,sBAEpG,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAO,kBAAsD,CAAC;AAEhG,eAAO,MAAM,gBAAgB,OAAQ,MAAM,KAAG,aAI7C,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,UAAU,UAAW,UAAU,GAAG,UAAU,CAAC,UAAU,KAAG,OACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type Message } from '@dxos/types';
|
|
2
|
+
/**
|
|
3
|
+
* What an item renders. The engine is renderer-agnostic: a message may resolve to a markdown
|
|
4
|
+
* document, to raw HTML (email bodies, which are not markdown and cannot be a CodeMirror document),
|
|
5
|
+
* or to a caller-supplied component.
|
|
6
|
+
*/
|
|
7
|
+
export type ItemContent = {
|
|
8
|
+
kind: 'markdown';
|
|
9
|
+
text: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'html';
|
|
12
|
+
html: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'custom';
|
|
15
|
+
key: string;
|
|
16
|
+
data?: unknown;
|
|
17
|
+
};
|
|
18
|
+
/** Resolves a message to the content its item renders. One per scenario (chat, email, …). */
|
|
19
|
+
export type MessageRenderer = (message: Message.Message) => ItemContent;
|
|
20
|
+
/**
|
|
21
|
+
* Default renderer: an `text/html` block wins (email), otherwise every block is flattened to
|
|
22
|
+
* markdown. Block kinds the engine does not know become fenced JSON so nothing renders as blank.
|
|
23
|
+
*/
|
|
24
|
+
export declare const defaultRenderer: MessageRenderer;
|
|
25
|
+
/**
|
|
26
|
+
* Assistant chat: as {@link defaultRenderer}, plus the reader's own turns marked with `<prompt>`.
|
|
27
|
+
*
|
|
28
|
+
* Separate because the tag is only meaningful where a widget registry knows it — a feed rendered
|
|
29
|
+
* without one would show the reader their own angle brackets, which is what a human chat, a
|
|
30
|
+
* transcript and a comment list all are.
|
|
31
|
+
*/
|
|
32
|
+
export declare const chatRenderer: MessageRenderer;
|
|
33
|
+
/** Plain text of a message, used by search and copy so both read the same projection. */
|
|
34
|
+
export declare const messageText: (message: Message.Message, renderer: MessageRenderer) => string;
|
|
35
|
+
export type SearchHit = {
|
|
36
|
+
messageId: string;
|
|
37
|
+
/** Index into the message list, so the virtualizer can scroll to it without a second lookup. */
|
|
38
|
+
index: number;
|
|
39
|
+
/** Offset into the message's rendered text. */
|
|
40
|
+
offset: number;
|
|
41
|
+
length: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Search the model rather than the DOM.
|
|
45
|
+
*
|
|
46
|
+
* Virtualization means most messages are not mounted, and a `viewType` filter can hide blocks that
|
|
47
|
+
* are still in the model — neither is reachable by a per-view CodeMirror search, so thread-wide find
|
|
48
|
+
* has to run over the projection.
|
|
49
|
+
*/
|
|
50
|
+
export declare const searchFeed: (messages: readonly Message.Message[], renderer: MessageRenderer, query: string) => SearchHit[];
|
|
51
|
+
/** A point in the feed: a message plus an offset into its rendered text. */
|
|
52
|
+
export type FeedAnchor = {
|
|
53
|
+
messageId: string;
|
|
54
|
+
offset: number;
|
|
55
|
+
};
|
|
56
|
+
export type FeedRange = {
|
|
57
|
+
from: FeedAnchor;
|
|
58
|
+
to: FeedAnchor;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Text between two anchors, spanning message boundaries.
|
|
62
|
+
*
|
|
63
|
+
* Native selection cannot span separate editor instances, and unmounted messages are not in the DOM
|
|
64
|
+
* at all, so cross-message copy is reconstructed from the model.
|
|
65
|
+
*/
|
|
66
|
+
export declare const sliceFeed: (messages: readonly Message.Message[], renderer: MessageRenderer, range: FeedRange) => string;
|
|
67
|
+
//# sourceMappingURL=feed-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-model.d.ts","sourceRoot":"","sources":["../../../../src/model/feed-model.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpD,6FAA6F;AAC7F,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,WAAW,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,eAA4D,CAAC;AAE3F;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,eAA2D,CAAC;AA2EvF,yFAAyF;AACzF,eAAO,MAAM,WAAW,YAAa,OAAO,CAAC,OAAO,YAAY,eAAe,KAAG,MAUjF,CAAC;AAaF,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,aACX,SAAS,OAAO,CAAC,OAAO,EAAE,YAC1B,eAAe,SAClB,MAAM,KACZ,SAAS,EAiBX,CAAC;AAMF,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,SAAS,aACV,SAAS,OAAO,CAAC,OAAO,EAAE,YAC1B,eAAe,SAClB,SAAS,KACf,MAwBF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-model.test.d.ts","sourceRoot":"","sources":["../../../../src/model/feed-model.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type Message } from '@dxos/types';
|
|
2
|
+
import { type MessageRenderer, type SearchHit } from './feed-model';
|
|
3
|
+
import { ListModel } from './list-model';
|
|
4
|
+
/**
|
|
5
|
+
* One position navigation can land on (SPEC: Stop).
|
|
6
|
+
*
|
|
7
|
+
* Produced by a pluggable policy over the model and consumed identically by every driver —
|
|
8
|
+
* toolbar, arrow keys, outliner, minimap — which is what keeps the rails and the keymap from
|
|
9
|
+
* growing parallel wiring.
|
|
10
|
+
*/
|
|
11
|
+
export type Stop = {
|
|
12
|
+
index: number;
|
|
13
|
+
id: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
};
|
|
16
|
+
/** The built-in policies; a host may hand a function instead. */
|
|
17
|
+
export type StopsPolicy = 'message' | 'prompt' | ((message: Message.Message, index: number) => boolean);
|
|
18
|
+
export type FeedModelOptions = {
|
|
19
|
+
messages?: readonly Message.Message[];
|
|
20
|
+
stops?: StopsPolicy;
|
|
21
|
+
/** Paged history: consumed when the window reaches the start edge. Paging is the model's business. */
|
|
22
|
+
loadBefore?: () => Promise<readonly Message.Message[]>;
|
|
23
|
+
/** The forward twin, for feeds that are windows into something longer. */
|
|
24
|
+
loadAfter?: () => Promise<readonly Message.Message[]>;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The native case, not an add-on (SPEC: FeedModel): a ListModel of messages carrying the feed's
|
|
28
|
+
* own semantics — the stops policy, the streaming tail, and iteration. The list consumes this and
|
|
29
|
+
* nothing else; `hits`, `isAnchor` and `streamingId` all left the props API and live here or in
|
|
30
|
+
* the decoration provider.
|
|
31
|
+
*
|
|
32
|
+
* ECHO/queue bindings adapt to this outside the package; `fromMessages` adapts the plain case.
|
|
33
|
+
*/
|
|
34
|
+
export declare class FeedModel extends ListModel<Message.Message> {
|
|
35
|
+
#private;
|
|
36
|
+
constructor({ messages, stops, loadBefore, loadAfter }?: FeedModelOptions);
|
|
37
|
+
get messages(): readonly Message.Message[];
|
|
38
|
+
/** The tail message reconciling by delta; its item must not remount per chunk. */
|
|
39
|
+
get streamingId(): string | undefined;
|
|
40
|
+
setStreaming(id: string | undefined): void;
|
|
41
|
+
/** A chunk arrived for the streaming tail: same identity, longer content. */
|
|
42
|
+
stream(id: string): void;
|
|
43
|
+
setStops(stops: StopsPolicy): void;
|
|
44
|
+
/**
|
|
45
|
+
* The positions navigation can land on, under the current policy.
|
|
46
|
+
*
|
|
47
|
+
* Recomputed on demand rather than cached: a policy is a predicate over the model, and the model
|
|
48
|
+
* knows when it changed — callers that want reactivity derive from `rowsAtom`.
|
|
49
|
+
*/
|
|
50
|
+
stops(): Stop[];
|
|
51
|
+
/**
|
|
52
|
+
* The window reached the start: ask the source for history.
|
|
53
|
+
*
|
|
54
|
+
* The model owns iteration (SPEC F-7.2) — the pages arrive as a prepend, which the virtualizer
|
|
55
|
+
* is told about, so nothing on screen moves (F-1.1). Serialized, because edges are reached once
|
|
56
|
+
* per frame while the reader sits on them.
|
|
57
|
+
*/
|
|
58
|
+
more(edge: 'start' | 'end'): Promise<boolean>;
|
|
59
|
+
/** Model-level search, since virtualization hides most items from any DOM search. */
|
|
60
|
+
search(query: string, renderer?: MessageRenderer): SearchHit[];
|
|
61
|
+
/** The rendered text of one message, for previews and rails. */
|
|
62
|
+
textOf(id: string, renderer?: MessageRenderer): string | undefined;
|
|
63
|
+
}
|
|
64
|
+
/** The plain case: a feed over an array the host already has. */
|
|
65
|
+
export declare const fromMessages: (messages: readonly Message.Message[], options?: Omit<FeedModelOptions, 'messages'>) => FeedModel;
|
|
66
|
+
//# sourceMappingURL=feed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../../../src/model/feed.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAA4C,MAAM,cAAc,CAAC;AAC9G,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AAExG,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,SAAS,OAAO,CAAC,OAAO,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvD,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACvD,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,SAAU,SAAQ,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;;IAOvD,YAAY,EAAE,QAAa,EAAE,KAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,GAAE,gBAAqB,EAK7F;IAED,IAAI,QAAQ,IAAI,SAAS,OAAO,CAAC,OAAO,EAAE,CAEzC;IAED,kFAAkF;IAClF,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CASzC;IAED,6EAA6E;IAC7E,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAEjC;IAED;;;;;OAKG;IACH,KAAK,IAAI,IAAI,EAAE,CAgBd;IAED;;;;;;OAMG;IACG,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBlD;IAED,qFAAqF;IACrF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,eAAiC,GAAG,SAAS,EAAE,CAE9E;IAED,gEAAgE;IAChE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,eAAiC,GAAG,MAAM,GAAG,SAAS,CAIlF;CACF;AAED,iEAAiE;AACjE,eAAO,MAAM,YAAY,aAAc,SAAS,OAAO,CAAC,OAAO,EAAE,YAAW,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,cACrE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed.test.d.ts","sourceRoot":"","sources":["../../../../src/model/feed.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/model/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as Atom from 'effect/unstable/reactivity/Atom';
|
|
2
|
+
/**
|
|
3
|
+
* What one change to the model actually was — told, never inferred.
|
|
4
|
+
*
|
|
5
|
+
* The virtualizer's anchor survives a prepend only if it knows the prepend happened (SPEC F-7.1);
|
|
6
|
+
* the engine used to reconstruct that by scanning for the previous first id, which is the model's
|
|
7
|
+
* knowledge recovered from its absence. Here the model says so. The identity scan still exists in
|
|
8
|
+
* exactly one place — `replace`, the adapter for hosts that hand over a whole new array — because
|
|
9
|
+
* that is the one caller that genuinely does not know.
|
|
10
|
+
*/
|
|
11
|
+
export type ListChange = {
|
|
12
|
+
prepended?: number;
|
|
13
|
+
appended?: number;
|
|
14
|
+
/** Ids whose content changed in place — a streaming tail, an edit. */
|
|
15
|
+
updated?: readonly string[];
|
|
16
|
+
};
|
|
17
|
+
export type ListModelOptions<T> = {
|
|
18
|
+
items?: readonly T[];
|
|
19
|
+
/** Identity of an item. Measurements, selection and decorations are all keyed by this. */
|
|
20
|
+
getId: (item: T) => string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The low-level reactive collection the virtualizer binds to (SPEC: ListModel).
|
|
24
|
+
*
|
|
25
|
+
* Two faces on one state, deliberately: a plain synchronous face (`count`, `at`, `subscribe`) that
|
|
26
|
+
* the virtualizer consumes without dragging an atom registry into every story and test, and an
|
|
27
|
+
* atom face (`rowsAtom`) for hosts that live in atom-land — derivations (stops, decorations,
|
|
28
|
+
* readouts) hang off the atom rather than becoming parallel props. Both are the same array; the
|
|
29
|
+
* subscribe face is not a fallback but the binding's contract.
|
|
30
|
+
*/
|
|
31
|
+
export declare class ListModel<T> {
|
|
32
|
+
#private;
|
|
33
|
+
/** The rows as an atom, for derivations. Registry-managed by whoever consumes it. */
|
|
34
|
+
readonly rowsAtom: Atom.Writable<readonly T[]>;
|
|
35
|
+
constructor({ items, getId }: ListModelOptions<T>);
|
|
36
|
+
get count(): number;
|
|
37
|
+
get items(): readonly T[];
|
|
38
|
+
getId: (index: number) => string;
|
|
39
|
+
at: (index: number) => T | undefined;
|
|
40
|
+
indexOf(id: string): number;
|
|
41
|
+
subscribe(listener: (change: ListChange) => void): () => void;
|
|
42
|
+
append(items: readonly T[]): void;
|
|
43
|
+
prepend(items: readonly T[]): void;
|
|
44
|
+
/** An item changed in place — same identity, new content. */
|
|
45
|
+
update(id: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Replace one item with a successor of the same identity — the streaming case for *frozen*
|
|
48
|
+
* items. An ECHO object mutates and `update` announces it; a schema-made message is frozen, so
|
|
49
|
+
* the chunk arrives as a fresh value under the old id. Same event either way: `updated`.
|
|
50
|
+
*/
|
|
51
|
+
patch(id: string, next: T): void;
|
|
52
|
+
/**
|
|
53
|
+
* The adapter for hosts that hand over a whole new array (a React prop, a query result).
|
|
54
|
+
*
|
|
55
|
+
* The one place the prepend inference survives, because this is the one caller that genuinely
|
|
56
|
+
* does not know what changed: the old first item is found in the new array, and everything before
|
|
57
|
+
* it was prepended. The virtualizer itself is always told (SPEC F-7.1).
|
|
58
|
+
*/
|
|
59
|
+
replace(items: readonly T[]): void;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=list-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-model.d.ts","sourceRoot":"","sources":["../../../../src/model/list-model.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,IAAI,MAAM,iCAAiC,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;IACrB,0FAA0F;IAC1F,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,SAAS,CAAC,CAAC;;IAKtB,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAG/C,YAAY,EAAE,KAAU,EAAE,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAOrD;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,IAAI,SAAS,CAAC,EAAE,CAExB;IAED,KAAK,UAAW,MAAM,KAAG,MAAM,CAG7B;IAEF,EAAE,UAAW,MAAM,KAAG,CAAC,GAAG,SAAS,CAAuB;IAE1D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1B;IAED,SAAS,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAG5D;IAED,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,IAAI,CAOhC;IAED,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,IAAI,CAOjC;IAED,6DAA6D;IAC7D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAQ/B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,IAAI,CAkBjC;CAQF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-model.test.d.ts","sourceRoot":"","sources":["../../../../src/model/list-model.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Message } from '@dxos/types';
|
|
2
|
+
import { FeedModel, type FeedModelOptions } from './feed';
|
|
3
|
+
import { ListModel } from './list-model';
|
|
4
|
+
/**
|
|
5
|
+
* A model over an array the host re-creates per render — the React-prop case.
|
|
6
|
+
*
|
|
7
|
+
* The model is stable; the array is folded into it with `replace`, which is where the prepend
|
|
8
|
+
* inference lives (and the only place — SPEC F-7.1). In an effect rather than during render: the
|
|
9
|
+
* model publishes synchronously to its subscribers, and a subscriber invalidating itself while the
|
|
10
|
+
* host is still rendering is a cross-component update React rejects. The window it opens is one
|
|
11
|
+
* frame, and the window's own subscription closes it.
|
|
12
|
+
*/
|
|
13
|
+
export declare const useListModel: <T>(items: readonly T[], getId: (item: T) => string) => ListModel<T>;
|
|
14
|
+
/**
|
|
15
|
+
* The feed-shaped twin, for a host that re-creates its message array per render.
|
|
16
|
+
*
|
|
17
|
+
* Streaming through this adapter is a `replace` whose length does not change; the model still
|
|
18
|
+
* publishes, so the window still re-renders, and the streaming item reconciles by document delta
|
|
19
|
+
* exactly as it would under a told update.
|
|
20
|
+
*/
|
|
21
|
+
export declare const useFeedModel: (messages: readonly Message.Message[], options?: Omit<FeedModelOptions, 'messages'>) => FeedModel;
|
|
22
|
+
//# sourceMappingURL=useListModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListModel.d.ts","sourceRoot":"","sources":["../../../../src/model/useListModel.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,SAAS,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,KAAG,SAAS,CAAC,CAAC,CAU5F,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,aACb,SAAS,OAAO,CAAC,OAAO,EAAE,YAC3B,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,KAC1C,SAUF,CAAC"}
|