@khorsheed/dsh-message-timeline 0.2.7 → 0.2.8
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/CHANGELOG.md
CHANGED
package/lib/client.js
CHANGED
|
@@ -201,18 +201,12 @@ window.__ModuleLoader__.load({
|
|
|
201
201
|
}
|
|
202
202
|
return lastAbove;
|
|
203
203
|
}
|
|
204
|
-
|
|
205
|
-
* Scroll one user-message row to the top of the transcript scrollport.
|
|
206
|
-
* @param scrollport - the official conversation scrollport element.
|
|
207
|
-
* @param key - the target node's anchor key.
|
|
208
|
-
* @returns whether the row was found and scrolled.
|
|
209
|
-
*/
|
|
210
|
-
function jumpRow(scrollport, key) {
|
|
204
|
+
function jumpTarget(scrollport, key) {
|
|
211
205
|
const row = scrollport.querySelector(`[data-chat-anchor-key=${JSON.stringify(key)}]`);
|
|
212
|
-
if (row === null) return
|
|
206
|
+
if (row === null) return null;
|
|
213
207
|
const target = row.getBoundingClientRect().top - scrollport.getBoundingClientRect().top + scrollport.scrollTop - JUMP_OFFSET;
|
|
214
208
|
scrollport.scrollTop = Math.max(0, target);
|
|
215
|
-
return
|
|
209
|
+
return row;
|
|
216
210
|
}
|
|
217
211
|
/**
|
|
218
212
|
* Install the rail tracker: bind the current session's scrollport, publish
|
|
@@ -228,6 +222,7 @@ window.__ModuleLoader__.load({
|
|
|
228
222
|
let state = IDLE;
|
|
229
223
|
let activeSession;
|
|
230
224
|
let scrollport = null;
|
|
225
|
+
let landing = null;
|
|
231
226
|
let resizeObserver;
|
|
232
227
|
let rafPending = false;
|
|
233
228
|
let warned = false;
|
|
@@ -244,6 +239,7 @@ window.__ModuleLoader__.load({
|
|
|
244
239
|
const attach = (el) => {
|
|
245
240
|
if (scrollport !== null) scrollport.removeEventListener("scroll", onScroll);
|
|
246
241
|
resizeObserver?.disconnect();
|
|
242
|
+
landing = null;
|
|
247
243
|
scrollport = el;
|
|
248
244
|
scrollport.addEventListener("scroll", onScroll, { passive: true });
|
|
249
245
|
if (typeof ResizeObserver === "function") {
|
|
@@ -264,6 +260,7 @@ window.__ModuleLoader__.load({
|
|
|
264
260
|
}
|
|
265
261
|
const geometry = measureGeometry(el);
|
|
266
262
|
if (geometry === null) return;
|
|
263
|
+
if (landing !== null && (landing.top !== el.scrollTop || !el.contains(landing.row))) landing = null;
|
|
267
264
|
publish({
|
|
268
265
|
sessionId: activeSession,
|
|
269
266
|
ready: true,
|
|
@@ -272,7 +269,7 @@ window.__ModuleLoader__.load({
|
|
|
272
269
|
height: geometry.height,
|
|
273
270
|
scrollportWidth: geometry.width,
|
|
274
271
|
flowLeft: flowLeftX(el),
|
|
275
|
-
activeKey: activeRowKey(el, includeSteering),
|
|
272
|
+
activeKey: landing?.key ?? activeRowKey(el, includeSteering),
|
|
276
273
|
chatView: el.querySelector("[data-chat-flow]") !== null
|
|
277
274
|
});
|
|
278
275
|
};
|
|
@@ -291,6 +288,7 @@ window.__ModuleLoader__.load({
|
|
|
291
288
|
bindToken++;
|
|
292
289
|
if (scrollport !== null) scrollport.removeEventListener("scroll", onScroll);
|
|
293
290
|
scrollport = null;
|
|
291
|
+
landing = null;
|
|
294
292
|
resizeObserver?.disconnect();
|
|
295
293
|
resizeObserver = void 0;
|
|
296
294
|
rafPending = false;
|
|
@@ -347,7 +345,22 @@ window.__ModuleLoader__.load({
|
|
|
347
345
|
};
|
|
348
346
|
}
|
|
349
347
|
},
|
|
350
|
-
jumpTo: (key) =>
|
|
348
|
+
jumpTo: (key) => {
|
|
349
|
+
const el = scrollport;
|
|
350
|
+
if (el === null) return false;
|
|
351
|
+
const row = jumpTarget(el, key);
|
|
352
|
+
if (row === null) return false;
|
|
353
|
+
landing = {
|
|
354
|
+
key,
|
|
355
|
+
row,
|
|
356
|
+
top: el.scrollTop
|
|
357
|
+
};
|
|
358
|
+
publish({
|
|
359
|
+
...state,
|
|
360
|
+
activeKey: key
|
|
361
|
+
});
|
|
362
|
+
return true;
|
|
363
|
+
},
|
|
351
364
|
dispose: () => {
|
|
352
365
|
stopList();
|
|
353
366
|
stopProvide?.();
|
|
@@ -561,16 +574,16 @@ window.__ModuleLoader__.load({
|
|
|
561
574
|
document.head.appendChild(tag);
|
|
562
575
|
}
|
|
563
576
|
var TimelineRail_module_css_default = {
|
|
564
|
-
"itemFocused": "_8u17xW_itemFocused",
|
|
565
|
-
"itemText": "_8u17xW_itemText",
|
|
566
|
-
"railPending": "_8u17xW_railPending",
|
|
567
|
-
"tick": "_8u17xW_tick",
|
|
568
577
|
"panel": "_8u17xW_panel",
|
|
569
|
-
"itemCurrent": "_8u17xW_itemCurrent",
|
|
570
578
|
"itemPending": "_8u17xW_itemPending",
|
|
579
|
+
"railPending": "_8u17xW_railPending",
|
|
580
|
+
"item": "_8u17xW_item",
|
|
571
581
|
"panelNarrow": "_8u17xW_panelNarrow",
|
|
582
|
+
"tick": "_8u17xW_tick",
|
|
583
|
+
"itemCurrent": "_8u17xW_itemCurrent",
|
|
572
584
|
"tickCurrent": "_8u17xW_tickCurrent",
|
|
573
|
-
"
|
|
585
|
+
"itemText": "_8u17xW_itemText",
|
|
586
|
+
"itemFocused": "_8u17xW_itemFocused"
|
|
574
587
|
};
|
|
575
588
|
//#endregion
|
|
576
589
|
//#region src/client/TimelineRail.tsx
|
|
@@ -79,8 +79,9 @@ export interface RailTracker {
|
|
|
79
79
|
/** Live rail geometry and active marker for the current session. */
|
|
80
80
|
readonly state: HostObservable<TimelineRailState>;
|
|
81
81
|
/**
|
|
82
|
-
* Scroll
|
|
83
|
-
*
|
|
82
|
+
* Scroll to the message addressed by `key` and keep that landing active
|
|
83
|
+
* until the reading position moves or the row disappears.
|
|
84
|
+
* @returns whether the target row was found (false while unbound or missing).
|
|
84
85
|
*/
|
|
85
86
|
jumpTo(key: string): boolean;
|
|
86
87
|
/** Unbind every listener and observer. */
|
|
@@ -131,6 +131,15 @@ export function activeRowKey(scrollport, includeSteering) {
|
|
|
131
131
|
}
|
|
132
132
|
return lastAbove;
|
|
133
133
|
}
|
|
134
|
+
function jumpTarget(scrollport, key) {
|
|
135
|
+
const row = scrollport.querySelector(`[data-chat-anchor-key=${JSON.stringify(key)}]`);
|
|
136
|
+
if (row === null)
|
|
137
|
+
return null;
|
|
138
|
+
const target = row.getBoundingClientRect().top - scrollport.getBoundingClientRect().top
|
|
139
|
+
+ scrollport.scrollTop - JUMP_OFFSET;
|
|
140
|
+
scrollport.scrollTop = Math.max(0, target);
|
|
141
|
+
return row;
|
|
142
|
+
}
|
|
134
143
|
/**
|
|
135
144
|
* Scroll one user-message row to the top of the transcript scrollport.
|
|
136
145
|
* @param scrollport - the official conversation scrollport element.
|
|
@@ -138,13 +147,7 @@ export function activeRowKey(scrollport, includeSteering) {
|
|
|
138
147
|
* @returns whether the row was found and scrolled.
|
|
139
148
|
*/
|
|
140
149
|
export function jumpRow(scrollport, key) {
|
|
141
|
-
|
|
142
|
-
if (row === null)
|
|
143
|
-
return false;
|
|
144
|
-
const target = row.getBoundingClientRect().top - scrollport.getBoundingClientRect().top
|
|
145
|
-
+ scrollport.scrollTop - JUMP_OFFSET;
|
|
146
|
-
scrollport.scrollTop = Math.max(0, target);
|
|
147
|
-
return true;
|
|
150
|
+
return jumpTarget(scrollport, key) !== null;
|
|
148
151
|
}
|
|
149
152
|
/**
|
|
150
153
|
* Install the rail tracker: bind the current session's scrollport, publish
|
|
@@ -160,6 +163,7 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
160
163
|
let state = IDLE;
|
|
161
164
|
let activeSession;
|
|
162
165
|
let scrollport = null;
|
|
166
|
+
let landing = null;
|
|
163
167
|
let resizeObserver;
|
|
164
168
|
let rafPending = false;
|
|
165
169
|
let warned = false;
|
|
@@ -189,6 +193,7 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
189
193
|
if (scrollport !== null)
|
|
190
194
|
scrollport.removeEventListener('scroll', onScroll);
|
|
191
195
|
resizeObserver?.disconnect();
|
|
196
|
+
landing = null;
|
|
192
197
|
scrollport = el;
|
|
193
198
|
scrollport.addEventListener('scroll', onScroll, { passive: true });
|
|
194
199
|
if (typeof ResizeObserver === 'function') {
|
|
@@ -218,6 +223,8 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
218
223
|
const geometry = measureGeometry(el);
|
|
219
224
|
if (geometry === null)
|
|
220
225
|
return;
|
|
226
|
+
if (landing !== null && (landing.top !== el.scrollTop || !el.contains(landing.row)))
|
|
227
|
+
landing = null;
|
|
221
228
|
publish({
|
|
222
229
|
sessionId: activeSession,
|
|
223
230
|
ready: true,
|
|
@@ -226,7 +233,7 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
226
233
|
height: geometry.height,
|
|
227
234
|
scrollportWidth: geometry.width,
|
|
228
235
|
flowLeft: flowLeftX(el),
|
|
229
|
-
activeKey: activeRowKey(el, includeSteering),
|
|
236
|
+
activeKey: landing?.key ?? activeRowKey(el, includeSteering),
|
|
230
237
|
chatView: el.querySelector('[data-chat-flow]') !== null,
|
|
231
238
|
});
|
|
232
239
|
};
|
|
@@ -245,6 +252,7 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
245
252
|
if (scrollport !== null)
|
|
246
253
|
scrollport.removeEventListener('scroll', onScroll);
|
|
247
254
|
scrollport = null;
|
|
255
|
+
landing = null;
|
|
248
256
|
resizeObserver?.disconnect();
|
|
249
257
|
resizeObserver = undefined;
|
|
250
258
|
rafPending = false;
|
|
@@ -314,7 +322,17 @@ export function installRailTracker(ctx, includeSteering) {
|
|
|
314
322
|
return () => { listeners.delete(fn); };
|
|
315
323
|
},
|
|
316
324
|
},
|
|
317
|
-
jumpTo: (key) =>
|
|
325
|
+
jumpTo: (key) => {
|
|
326
|
+
const el = scrollport;
|
|
327
|
+
if (el === null)
|
|
328
|
+
return false;
|
|
329
|
+
const row = jumpTarget(el, key);
|
|
330
|
+
if (row === null)
|
|
331
|
+
return false;
|
|
332
|
+
landing = { key, row, top: el.scrollTop };
|
|
333
|
+
publish({ ...state, activeKey: key });
|
|
334
|
+
return true;
|
|
335
|
+
},
|
|
318
336
|
dispose: () => {
|
|
319
337
|
stopList();
|
|
320
338
|
stopProvide?.();
|
|
@@ -58,8 +58,9 @@ export interface TimelineRailInjected {
|
|
|
58
58
|
*/
|
|
59
59
|
loadThrough: ISession['loadThrough'];
|
|
60
60
|
/**
|
|
61
|
-
* Scroll
|
|
62
|
-
*
|
|
61
|
+
* Scroll to the user message addressed by `key` and keep that landing active
|
|
62
|
+
* until the reading position moves or the row disappears.
|
|
63
|
+
* @returns whether the target row was found (false while unbound or missing).
|
|
63
64
|
*/
|
|
64
65
|
jumpTo: (key: string) => boolean;
|
|
65
66
|
hooks: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khorsheed/dsh-message-timeline",
|
|
3
3
|
"description": "Message timeline: a flat floating list over the conversation scrollport that jumps to any user message, with a tick-only rest state",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|