@deepseek-ai/dsh-client-ui-chat 0.1.7-alpha.1 → 0.1.7-alpha.2

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.
@@ -1,5 +1,6 @@
1
1
  import type { ChatScrollPosition, ChatViewSlotProps } from '../contract/slots.ts';
2
2
  import type { ChatViewport, ViewportLanding, ViewportScroll } from './use-chat-viewport.ts';
3
+ import { type ScrollFollow } from './use-scroll-follow.ts';
3
4
  /** Reading facts that affect Chat chrome and initial rail placement. */
4
5
  export interface ChatReadingState {
5
6
  readonly initialized: boolean;
@@ -19,10 +20,11 @@ export declare class ChatReading {
19
20
  private store;
20
21
  private state;
21
22
  private readonly onChange;
23
+ private readonly follow;
22
24
  private sampleTimer;
23
25
  private probeFrame;
24
26
  private sampled;
25
- constructor(viewport: ChatViewport, store: PositionStore, state: ChatReadingState, onChange: (state: ChatReadingState) => void);
27
+ constructor(viewport: ChatViewport, store: PositionStore, state: ChatReadingState, onChange: (state: ChatReadingState) => void, follow: ScrollFollow);
26
28
  /**
27
29
  * Expose pending reader ownership to navigation and resize handlers.
28
30
  * @returns whether reader input still awaits interval or scrollend sampling.
@@ -73,7 +75,6 @@ export declare class ChatReading {
73
75
  onResize(): void;
74
76
  /** Resolve the active turn from tail ownership or a coalesced reading-line probe. */
75
77
  refreshActiveTurn(): void;
76
- private nearBottom;
77
78
  private commit;
78
79
  private publish;
79
80
  private cancelPending;
@@ -2,12 +2,8 @@
2
2
  import { type RefObject } from 'react';
3
3
  import type { ChatScrollPosition } from '../contract/slots.ts';
4
4
  import type { ChatSnapshot } from '../contract/snapshot.ts';
5
- /** Scroll position, maximum top, and viewport height from one geometry read. */
6
- export interface ViewportMetrics {
7
- readonly top: number;
8
- readonly floor: number;
9
- readonly height: number;
10
- }
5
+ import { ScrollFollow, type ViewportMetrics } from './use-scroll-follow.ts';
6
+ export type { ViewportMetrics } from './use-scroll-follow.ts';
11
7
  /** Scroll geometry attributed against the last acknowledged position. */
12
8
  export interface ViewportScroll {
13
9
  readonly metrics: ViewportMetrics;
@@ -120,14 +116,16 @@ export declare class ChatViewport {
120
116
  get preserving(): boolean;
121
117
  /**
122
118
  * Compensate inner scrolling first, then the outer scrollport, within their actual scroll ranges.
119
+ * An inner write pauses its bound follow controller so the reading anchor takes priority.
123
120
  * @returns the actual landing, or null when no visible retained row remains.
124
121
  */
125
122
  preserve(): ViewportLanding | null;
126
123
  /**
127
124
  * Align the scrollport with its current floor.
125
+ * @param follow - independent follow intent and scrolling controller.
128
126
  * @returns the actual floor landing, or null while detached.
129
127
  */
130
- scrollToBottom(): ViewportLanding | null;
128
+ scrollToBottom(follow: ScrollFollow): ViewportLanding | null;
131
129
  private align;
132
130
  private write;
133
131
  private readonly onScroll;
@@ -143,5 +141,4 @@ export declare function useChatViewport(): {
143
141
  listRef: RefObject<HTMLDivElement>;
144
142
  columnRef: RefObject<HTMLDivElement>;
145
143
  };
146
- export {};
147
144
  //# sourceMappingURL=use-chat-viewport.d.ts.map
@@ -0,0 +1,23 @@
1
+ /** Capped process-group scrolling and fades over the shared follow controller. */
2
+ import { type DOMAttributes, type RefObject } from 'react';
3
+ interface ScrollEdges {
4
+ readonly canScrollUp: boolean;
5
+ readonly canScrollDown: boolean;
6
+ }
7
+ /**
8
+ * Observe one group's body and content without coupling its follow intent to the outer transcript.
9
+ * Wheel, touchstart, any pointerdown, and unprevented scroll keys interrupt active animations,
10
+ * including events from editable controls; subsequent position sampling determines follow intent.
11
+ * @param bodyRef - capped scrolling body.
12
+ * @param contentRef - uncapped content whose size reports growth.
13
+ * @param open - local disclosure state.
14
+ * @param grouped - whether the display mode retains the group's height cap.
15
+ * @returns edge fades, DOM event bindings, and one-shot positioning for manual opening.
16
+ */
17
+ export declare function useProcessScroll(bodyRef: RefObject<HTMLDivElement>, contentRef: RefObject<HTMLDivElement>, open: boolean, grouped: boolean): {
18
+ edges: ScrollEdges;
19
+ events: Pick<DOMAttributes<HTMLDivElement>, 'onScroll' | 'onWheel' | 'onTouchStart' | 'onPointerDown' | 'onKeyDown'>;
20
+ initialize: (position: 'top' | 'bottom') => void;
21
+ };
22
+ export {};
23
+ //# sourceMappingURL=use-process-scroll.d.ts.map
@@ -0,0 +1,105 @@
1
+ /** Scroll position, maximum top, and viewport height from one geometry read. */
2
+ export interface ViewportMetrics {
3
+ readonly top: number;
4
+ readonly floor: number;
5
+ readonly height: number;
6
+ }
7
+ /**
8
+ * Read one scrollport without measuring its children.
9
+ * @param element - scrolling element.
10
+ * @returns current position and range.
11
+ */
12
+ export declare function scrollMetrics(element: HTMLElement): ViewportMetrics;
13
+ /** One scrollport's follow intent; native animation progress does not count as reader movement. */
14
+ export declare class ScrollFollow {
15
+ private following;
16
+ private readonly threshold;
17
+ private static readonly owners;
18
+ private target;
19
+ private sampledTop;
20
+ /**
21
+ * @param following - initial follow intent.
22
+ * @param threshold - accepted distance from the floor, in pixels.
23
+ */
24
+ constructor(following: boolean, threshold: number);
25
+ /**
26
+ * Find the mounted controller for reading-position compensation.
27
+ * @param element - scrollport with an optional follow owner.
28
+ * @returns its controller, when bound.
29
+ */
30
+ static forElement(element: HTMLElement): ScrollFollow | undefined;
31
+ /**
32
+ * Share this controller with reading-position compensation for the same scrollport.
33
+ * @param element - owned scrollport.
34
+ * @returns release the association on unmount or close.
35
+ */
36
+ bind(element: HTMLElement): () => void;
37
+ /**
38
+ * Expose follow intent independently of the current offset.
39
+ * @returns whether content growth should follow the floor.
40
+ */
41
+ get active(): boolean;
42
+ /**
43
+ * Expose outstanding native motion before accepting reader input.
44
+ * @returns whether a native follow animation has an outstanding target.
45
+ */
46
+ get animating(): boolean;
47
+ /**
48
+ * Classify bottom arrivals using this scrollport's own tolerance.
49
+ * @param metrics - current scroll geometry.
50
+ * @returns whether the position is within the follow threshold.
51
+ */
52
+ nearBottom(metrics: ViewportMetrics): boolean;
53
+ /**
54
+ * Commit caller-owned follow decisions without moving the scrollport.
55
+ * @param active - externally committed follow intent.
56
+ */
57
+ setFollowing(active: boolean): void;
58
+ /** Adopt the next visible layout as a fresh reader position. */
59
+ reset(): void;
60
+ /**
61
+ * Adopt delivered scrolling while retaining intent during native animation.
62
+ * @param metrics - current geometry.
63
+ * @param movedByReader - caller attribution; omitted callers compare the last sampled position.
64
+ * @returns updated follow intent.
65
+ */
66
+ sample(metrics: ViewportMetrics, movedByReader?: boolean): boolean;
67
+ /**
68
+ * Settle native scrolling; an off-target stop releases follow intent.
69
+ * @param metrics - actual geometry delivered at scrollend.
70
+ * @returns follow intent after completing or interrupting native motion.
71
+ */
72
+ settle(metrics: ViewportMetrics): boolean;
73
+ /**
74
+ * Position immediately and adopt the resulting follow intent.
75
+ * @param element - scrolling element.
76
+ * @param metrics - geometry before positioning.
77
+ * @param top - requested offset, clamped to the measured range.
78
+ * @returns geometry after positioning.
79
+ */
80
+ jump(element: HTMLElement, metrics: ViewportMetrics, top: number): ViewportMetrics;
81
+ /**
82
+ * Follow the measured floor, respecting reduced motion for smooth requests.
83
+ * An outstanding smooth target finishes before another is issued.
84
+ * Within-tolerance positioning is immediate while no animation is outstanding.
85
+ * @param element - scrolling element.
86
+ * @param metrics - current geometry.
87
+ * @param behavior - native animation for growth, or immediate positioning.
88
+ * @returns current geometry; smooth requests retain their starting position until native scroll delivery.
89
+ */
90
+ toBottom(element: HTMLElement, metrics: ViewportMetrics, behavior: 'instant' | 'smooth'): ViewportMetrics;
91
+ /**
92
+ * Cancel native motion before a reader gesture; only subsequent actual movement changes follow intent.
93
+ * @param element - scrolling element.
94
+ * @param metrics - position at interruption.
95
+ */
96
+ interrupt(element: HTMLElement, metrics: ViewportMetrics): void;
97
+ }
98
+ /**
99
+ * Retain one independent follow controller without React updates for scroll samples.
100
+ * @param initial - initial follow intent.
101
+ * @param threshold - accepted distance from the floor, in pixels.
102
+ * @returns the stable controller shared by the caller's scroll and resize handlers.
103
+ */
104
+ export declare function useScrollFollow(initial: boolean, threshold: number): ScrollFollow;
105
+ //# sourceMappingURL=use-scroll-follow.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-chat",
3
3
  "description": "Chat Conversation target, node definitions, renderers, and details surface",
4
- "version": "0.1.7-alpha.1",
4
+ "version": "0.1.7-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "license": "MIT",
47
47
  "peerDependencies": {
48
- "@deepseek-ai/cordis": "^4.0.3"
48
+ "@deepseek-ai/cordis": "~4.0.4"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@tanstack/react-virtual": "^3.14.9",
@@ -53,45 +53,45 @@
53
53
  "@types/react-dom": "~18.3.0",
54
54
  "react": "^18.2.0",
55
55
  "react-dom": "^18.2.0",
56
- "@deepseek-ai/cordis": "^4.0.3",
57
- "@deepseek-ai/dsh-agent": "^0.1.7-alpha.1",
58
- "@deepseek-ai/dsh-api-session-controller": "^0.1.7-alpha.1",
59
- "@deepseek-ai/dsh-api-workspace-controller": "^0.1.7-alpha.1",
60
- "@deepseek-ai/dsh-api-workspace-files": "^0.1.7-alpha.1",
61
- "@deepseek-ai/dsh-client-locale": "^0.1.7-alpha.1",
62
- "@deepseek-ai/dsh-brand": "^0.1.7-alpha.1",
63
- "@deepseek-ai/dsh-client-store": "^0.1.7-alpha.1",
64
- "@deepseek-ai/dsh-client-ui-approval": "^0.1.7-alpha.1",
65
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-alpha.1",
66
- "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.7-alpha.1",
67
- "@deepseek-ai/dsh-api-remotes": "^0.1.7-alpha.1",
68
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.7-alpha.1",
69
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-alpha.1",
70
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-alpha.1",
71
- "@deepseek-ai/dsh-client-ui-session": "^0.1.7-alpha.1",
72
- "@deepseek-ai/dsh-client-ui-sidebar-browser": "^0.1.7-alpha.1",
73
- "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "^0.1.7-alpha.1",
74
- "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.7-alpha.1",
75
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-alpha.1",
76
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.7-alpha.1",
77
- "@deepseek-ai/dsh-compaction": "^0.1.7-alpha.1",
78
- "@deepseek-ai/dsh-attachment": "^0.1.7-alpha.1",
79
- "@deepseek-ai/dsh-session": "^0.1.7-alpha.1",
80
- "@deepseek-ai/dsh-session-stats": "^0.1.7-alpha.1",
81
- "@deepseek-ai/dsh-session-turn-outline": "^0.1.7-alpha.1",
82
- "@deepseek-ai/dsh-subagent": "^0.1.7-alpha.1",
83
- "@deepseek-ai/dsh-token-meter": "^0.1.7-alpha.1",
84
- "@deepseek-ai/dsh-tools": "^0.1.7-alpha.1",
85
- "@deepseek-ai/dsh-util-workspace-path": "^0.1.7-alpha.1",
86
- "@deepseek-ai/dsh-commands": "^0.1.7-alpha.1",
87
- "@deepseek-ai/dsh-settings": "^0.1.7-alpha.1",
88
- "@deepseek-ai/dsh-client-ui-workspace": "^0.1.7-alpha.1",
89
- "@deepseek-ai/dsh-util-values": "^0.1.7-alpha.1",
90
- "@deepseek-ai/dsh-llm-retry": "^0.1.7-alpha.1",
91
- "@deepseek-ai/dsh-llm": "^0.1.7-alpha.1"
56
+ "@deepseek-ai/cordis": "~4.0.4",
57
+ "@deepseek-ai/dsh-agent": "0.1.7-alpha.2",
58
+ "@deepseek-ai/dsh-api-remotes": "0.1.7-alpha.2",
59
+ "@deepseek-ai/dsh-api-workspace-controller": "0.1.7-alpha.2",
60
+ "@deepseek-ai/dsh-api-session-controller": "0.1.7-alpha.2",
61
+ "@deepseek-ai/dsh-attachment": "0.1.7-alpha.2",
62
+ "@deepseek-ai/dsh-brand": "0.1.7-alpha.2",
63
+ "@deepseek-ai/dsh-api-workspace-files": "0.1.7-alpha.2",
64
+ "@deepseek-ai/dsh-client-locale": "0.1.7-alpha.2",
65
+ "@deepseek-ai/dsh-client-store": "0.1.7-alpha.2",
66
+ "@deepseek-ai/dsh-client-ui-approval": "0.1.7-alpha.2",
67
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-alpha.2",
68
+ "@deepseek-ai/dsh-client-ui-layout": "0.1.7-alpha.2",
69
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-alpha.2",
70
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-alpha.2",
71
+ "@deepseek-ai/dsh-client-ui-session": "0.1.7-alpha.2",
72
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-alpha.2",
73
+ "@deepseek-ai/dsh-client-ui-sidebar-browser": "0.1.7-alpha.2",
74
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.1.7-alpha.2",
75
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-alpha.2",
76
+ "@deepseek-ai/dsh-client-ui-workspace": "0.1.7-alpha.2",
77
+ "@deepseek-ai/dsh-commands": "0.1.7-alpha.2",
78
+ "@deepseek-ai/dsh-compaction": "0.1.7-alpha.2",
79
+ "@deepseek-ai/dsh-llm": "0.1.7-alpha.2",
80
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.1.7-alpha.2",
81
+ "@deepseek-ai/dsh-session-stats": "0.1.7-alpha.2",
82
+ "@deepseek-ai/dsh-session-turn-outline": "0.1.7-alpha.2",
83
+ "@deepseek-ai/dsh-subagent": "0.1.7-alpha.2",
84
+ "@deepseek-ai/dsh-token-meter": "0.1.7-alpha.2",
85
+ "@deepseek-ai/dsh-tools": "0.1.7-alpha.2",
86
+ "@deepseek-ai/dsh-session": "0.1.7-alpha.2",
87
+ "@deepseek-ai/dsh-util-workspace-path": "0.1.7-alpha.2",
88
+ "@deepseek-ai/dsh-llm-retry": "0.1.7-alpha.2",
89
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.7-alpha.2",
90
+ "@deepseek-ai/dsh-util-values": "0.1.7-alpha.2",
91
+ "@deepseek-ai/dsh-settings": "0.1.7-alpha.2"
92
92
  },
93
93
  "dependencies": {
94
- "@deepseek-ai/schemastery": "^3.18.3"
94
+ "@deepseek-ai/schemastery": "~3.18.4"
95
95
  },
96
96
  "files": [
97
97
  "lib/index.js",