@floegence/floe-webapp-core 0.86.53 → 0.86.55
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/dist/assets/markdown.worker-CDm-uCXT.js +1602 -0
- package/dist/chat.js +29 -27
- package/dist/components/chat/hooks/index.d.ts +1 -1
- package/dist/components/chat/hooks/useMarkdown.js +73 -53
- package/dist/components/chat/hooks/useVirtualList.d.ts +7 -6
- package/dist/components/chat/hooks/useVirtualList.js +99 -128
- package/dist/components/chat/hooks/virtualListLayout.d.ts +27 -0
- package/dist/components/chat/hooks/virtualListLayout.js +82 -0
- package/dist/components/chat/index.d.ts +1 -1
- package/dist/components/chat/markdown/createSessionWorker.d.ts +2 -0
- package/dist/components/chat/markdown/createSessionWorker.js +10 -0
- package/dist/components/chat/markdown/workerSession.d.ts +56 -0
- package/dist/components/chat/markdown/workerSession.js +126 -0
- package/dist/components/ui/SurfaceAnchoredLayer.d.ts +7 -1
- package/dist/components/ui/SurfaceAnchoredLayer.js +91 -64
- package/dist/full.js +176 -174
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.js +9 -4
- package/package.json +1 -1
- package/dist/assets/markdown.worker-CcdiAiK-.js +0 -1303
package/dist/chat.js
CHANGED
|
@@ -11,12 +11,12 @@ import { DEFAULT_VIRTUAL_LIST_CONFIG as w } from "./components/chat/types.js";
|
|
|
11
11
|
import { FileBlock as W } from "./components/chat/blocks/FileBlock.js";
|
|
12
12
|
import { ImageBlock as D } from "./components/chat/blocks/ImageBlock.js";
|
|
13
13
|
import { MarkdownBlock as I } from "./components/chat/blocks/MarkdownBlock.js";
|
|
14
|
-
import { MarkdownMedia as
|
|
15
|
-
import { MermaidBlock as
|
|
14
|
+
import { MarkdownMedia as v } from "./components/chat/blocks/MarkdownMedia.js";
|
|
15
|
+
import { MermaidBlock as T } from "./components/chat/blocks/MermaidBlock.js";
|
|
16
16
|
import { MessageActions as b } from "./components/chat/message/MessageActions.js";
|
|
17
17
|
import { MessageAvatar as H } from "./components/chat/message/MessageAvatar.js";
|
|
18
|
-
import { MessageBubble as
|
|
19
|
-
import { MessageItem as
|
|
18
|
+
import { MessageBubble as V } from "./components/chat/message/MessageBubble.js";
|
|
19
|
+
import { MessageItem as U } from "./components/chat/message/MessageItem.js";
|
|
20
20
|
import { MessageMeta as N } from "./components/chat/message/MessageMeta.js";
|
|
21
21
|
import { ShellBlock as K } from "./components/chat/blocks/ShellBlock.js";
|
|
22
22
|
import { StreamingCursor as j } from "./components/chat/status/StreamingCursor.js";
|
|
@@ -29,13 +29,14 @@ import { WorkingIndicator as tr } from "./components/chat/status/WorkingIndicato
|
|
|
29
29
|
import { buildAssistantNoticeEvents as ir, createStreamEventBuilder as fr, isStreamEvent as mr } from "./components/chat/streamEvents.js";
|
|
30
30
|
import { computeCodeDiff as kr, computeCodeDiffSync as dr, configureDiffWorker as pr, createDiffWorker as xr, hasDiffWorker as cr, terminateDiffWorker as lr, waitForDiffWorker as sr } from "./components/chat/hooks/useCodeDiff.js";
|
|
31
31
|
import { configureMarkdownWorker as ur, createMarkdownWorker as gr, hasMarkdownWorker as hr, renderMarkdown as Cr, renderMarkdownSync as wr, terminateMarkdownWorker as Br, waitForMarkdownWorker as Wr } from "./components/chat/hooks/useMarkdown.js";
|
|
32
|
-
import { configureMermaidWorker as Dr, configureSyncMermaid as Ar, renderMermaid as Ir, terminateMermaidWorker as
|
|
33
|
-
import { configureShikiWorker as
|
|
34
|
-
import { createInputHistoryController as
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
32
|
+
import { configureMermaidWorker as Dr, configureSyncMermaid as Ar, renderMermaid as Ir, terminateMermaidWorker as Lr, useMermaid as vr } from "./components/chat/hooks/useMermaid.js";
|
|
33
|
+
import { configureShikiWorker as Tr, configureSyncHighlighter as Fr, highlightCode as br, terminateShikiWorker as Er, useCodeHighlight as Hr } from "./components/chat/hooks/useCodeHighlight.js";
|
|
34
|
+
import { createInputHistoryController as Vr } from "./components/chat/input/createInputHistoryController.js";
|
|
35
|
+
import { createVirtualListLayout as Ur } from "./components/chat/hooks/virtualListLayout.js";
|
|
36
|
+
import { markdownMediaKind as Nr, markdownMediaPlaceholder as Gr, readMarkdownMediaPlaceholder as Kr, safeMarkdownMediaURL as Or, sandboxedMarkdownHtml as jr } from "./components/chat/markdown/media.js";
|
|
37
|
+
import { useAttachments as zr } from "./components/chat/hooks/useAttachments.js";
|
|
38
|
+
import { useAutoScroll as Qr } from "./components/chat/hooks/useAutoScroll.js";
|
|
39
|
+
import { useVirtualList as Yr } from "./components/chat/hooks/useVirtualList.js";
|
|
39
40
|
export {
|
|
40
41
|
o as AttachmentPreview,
|
|
41
42
|
a as BlockRenderer,
|
|
@@ -50,12 +51,12 @@ export {
|
|
|
50
51
|
W as FileBlock,
|
|
51
52
|
D as ImageBlock,
|
|
52
53
|
I as MarkdownBlock,
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
v as MarkdownMedia,
|
|
55
|
+
T as MermaidBlock,
|
|
55
56
|
b as MessageActions,
|
|
56
57
|
H as MessageAvatar,
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
V as MessageBubble,
|
|
59
|
+
U as MessageItem,
|
|
59
60
|
N as MessageMeta,
|
|
60
61
|
K as ShellBlock,
|
|
61
62
|
j as StreamingCursor,
|
|
@@ -71,35 +72,36 @@ export {
|
|
|
71
72
|
pr as configureDiffWorker,
|
|
72
73
|
ur as configureMarkdownWorker,
|
|
73
74
|
Dr as configureMermaidWorker,
|
|
74
|
-
|
|
75
|
+
Tr as configureShikiWorker,
|
|
75
76
|
Fr as configureSyncHighlighter,
|
|
76
77
|
Ar as configureSyncMermaid,
|
|
77
78
|
xr as createDiffWorker,
|
|
78
|
-
|
|
79
|
+
Vr as createInputHistoryController,
|
|
79
80
|
gr as createMarkdownWorker,
|
|
80
81
|
fr as createStreamEventBuilder,
|
|
82
|
+
Ur as createVirtualListLayout,
|
|
81
83
|
cr as hasDiffWorker,
|
|
82
84
|
hr as hasMarkdownWorker,
|
|
83
85
|
br as highlightCode,
|
|
84
86
|
mr as isStreamEvent,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
Nr as markdownMediaKind,
|
|
88
|
+
Gr as markdownMediaPlaceholder,
|
|
89
|
+
Kr as readMarkdownMediaPlaceholder,
|
|
88
90
|
Cr as renderMarkdown,
|
|
89
91
|
wr as renderMarkdownSync,
|
|
90
92
|
Ir as renderMermaid,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
Or as safeMarkdownMediaURL,
|
|
94
|
+
jr as sandboxedMarkdownHtml,
|
|
93
95
|
lr as terminateDiffWorker,
|
|
94
96
|
Br as terminateMarkdownWorker,
|
|
95
|
-
|
|
97
|
+
Lr as terminateMermaidWorker,
|
|
96
98
|
Er as terminateShikiWorker,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
zr as useAttachments,
|
|
100
|
+
Qr as useAutoScroll,
|
|
99
101
|
p as useChatContext,
|
|
100
102
|
Hr as useCodeHighlight,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
vr as useMermaid,
|
|
104
|
+
Yr as useVirtualList,
|
|
103
105
|
sr as waitForDiffWorker,
|
|
104
106
|
Wr as waitForMarkdownWorker
|
|
105
107
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useVirtualList, type UseVirtualListOptions, type UseVirtualListReturn, type VirtualItem } from './useVirtualList';
|
|
1
|
+
export { useVirtualList, createVirtualListLayout, type VirtualListAnchor, type VirtualListLayout, type UseVirtualListOptions, type UseVirtualListReturn, type VirtualItem } from './useVirtualList';
|
|
2
2
|
export { useCodeHighlight, highlightCode, terminateShikiWorker, configureShikiWorker, configureSyncHighlighter } from './useCodeHighlight';
|
|
3
3
|
export { useMermaid, renderMermaid, terminateMermaidWorker, configureMermaidWorker, configureSyncMermaid } from './useMermaid';
|
|
4
4
|
export { createMarkdownWorker, configureMarkdownWorker, hasMarkdownWorker, waitForMarkdownWorker, renderMarkdown, renderMarkdownSync, terminateMarkdownWorker, } from './useMarkdown';
|
|
@@ -1,78 +1,98 @@
|
|
|
1
|
-
import { secureRandomUUID as
|
|
2
|
-
import { renderMarkdownToHtml as
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
1
|
+
import { secureRandomUUID as E } from "../../../utils/secureRandom.js";
|
|
2
|
+
import { renderMarkdownToHtml as y } from "../markdown/markdown.js";
|
|
3
|
+
import { createMarkdownSessionWorker as v } from "../markdown/createSessionWorker.js";
|
|
4
|
+
const h = 15e3, W = 200, g = 16 * 1024 * 1024;
|
|
5
|
+
let n = null, f = !1, w = null, M, d, u = 0;
|
|
6
|
+
const k = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
7
|
+
function A() {
|
|
6
8
|
if (typeof Worker > "u") return null;
|
|
7
9
|
try {
|
|
8
|
-
return
|
|
9
|
-
/* @vite-ignore */
|
|
10
|
-
"" + new URL("../../../assets/markdown.worker-CcdiAiK-.js", import.meta.url).href,
|
|
11
|
-
import.meta.url
|
|
12
|
-
), { type: "module" });
|
|
10
|
+
return v();
|
|
13
11
|
} catch {
|
|
14
12
|
return null;
|
|
15
13
|
}
|
|
16
14
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
function c(r) {
|
|
16
|
+
const e = n;
|
|
17
|
+
n = null, f = !1, d !== void 0 && clearTimeout(d), d = void 0, M?.(r), M = void 0, w = null, e && (e.onmessage = null, e.onerror = null, e.onmessageerror = null, e.terminate());
|
|
18
|
+
for (const t of k.values())
|
|
19
|
+
clearTimeout(t.timer), t.reject(r);
|
|
20
|
+
k.clear();
|
|
21
|
+
}
|
|
22
|
+
function b(r) {
|
|
23
|
+
return c(new Error("Markdown worker replaced")), n = r, w = new Promise((e, t) => {
|
|
24
|
+
M = t, d = setTimeout(() => c(new Error("Markdown worker initialization timed out")), h), r.onmessage = (o) => {
|
|
25
|
+
if (n !== r) return;
|
|
26
|
+
if (!o.data || typeof o.data != "object") {
|
|
27
|
+
c(new Error("Invalid Markdown worker response"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if ("type" in o.data && o.data.type === "ready") {
|
|
31
|
+
d !== void 0 && clearTimeout(d), d = void 0, M = void 0, f = !0, e();
|
|
22
32
|
return;
|
|
23
33
|
}
|
|
24
|
-
const { id:
|
|
25
|
-
s && (
|
|
26
|
-
},
|
|
27
|
-
|
|
34
|
+
const { id: i, html: l, error: m } = o.data, s = k.get(i);
|
|
35
|
+
s && (k.delete(i), clearTimeout(s.timer), m ? s.reject(new Error(m)) : typeof l != "string" ? s.reject(new Error("Markdown worker omitted its result")) : s.resolve(l));
|
|
36
|
+
}, r.onerror = r.onmessageerror = () => {
|
|
37
|
+
n === r && c(new Error("Markdown worker failed"));
|
|
28
38
|
};
|
|
29
|
-
}),
|
|
39
|
+
}), w.catch(() => {
|
|
40
|
+
}), w;
|
|
30
41
|
}
|
|
31
|
-
function
|
|
42
|
+
function q() {
|
|
32
43
|
return !!n;
|
|
33
44
|
}
|
|
34
|
-
async function
|
|
35
|
-
return n ?
|
|
45
|
+
async function T() {
|
|
46
|
+
return n ? f ? !0 : (await w, !!n && f) : !1;
|
|
36
47
|
}
|
|
37
48
|
function R(r) {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
const
|
|
41
|
-
return
|
|
49
|
+
const e = a.get(r);
|
|
50
|
+
if (e !== void 0) return e;
|
|
51
|
+
const t = y(r);
|
|
52
|
+
return p(r, t), t;
|
|
42
53
|
}
|
|
43
|
-
async function
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
l.set(i, {
|
|
54
|
+
async function z(r) {
|
|
55
|
+
const e = a.get(r);
|
|
56
|
+
if (e !== void 0) return e;
|
|
57
|
+
const t = n;
|
|
58
|
+
if (!t) return R(r);
|
|
59
|
+
if (await T(), n !== t || !f) throw new Error("Markdown worker changed during initialization");
|
|
60
|
+
return new Promise((o, i) => {
|
|
61
|
+
const l = E(), m = setTimeout(() => c(new Error("Markdown worker request timed out")), h);
|
|
62
|
+
k.set(l, {
|
|
53
63
|
resolve: (s) => {
|
|
54
|
-
|
|
64
|
+
p(r, s), o(s);
|
|
55
65
|
},
|
|
56
|
-
reject:
|
|
57
|
-
|
|
66
|
+
reject: i,
|
|
67
|
+
timer: m
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
t.postMessage({ id: l, content: r });
|
|
71
|
+
} catch {
|
|
72
|
+
c(new Error("Markdown worker request could not be sent"));
|
|
73
|
+
}
|
|
58
74
|
});
|
|
59
75
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
76
|
+
function C() {
|
|
77
|
+
c(new Error("Markdown worker closed")), a.clear(), u = 0;
|
|
62
78
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
function p(r, e) {
|
|
80
|
+
const t = (r.length + e.length) * 2;
|
|
81
|
+
if (t > g) return;
|
|
82
|
+
const o = a.get(r);
|
|
83
|
+
for (o !== void 0 && (u -= (r.length + o.length) * 2, a.delete(r)); a.size >= W || u + t > g; ) {
|
|
84
|
+
const i = a.entries().next().value;
|
|
85
|
+
if (!i) break;
|
|
86
|
+
u -= (i[0].length + i[1].length) * 2, a.delete(i[0]);
|
|
67
87
|
}
|
|
68
|
-
a.set(r, t
|
|
88
|
+
a.set(r, e), u += t;
|
|
69
89
|
}
|
|
70
90
|
export {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
b as configureMarkdownWorker,
|
|
92
|
+
A as createMarkdownWorker,
|
|
93
|
+
q as hasMarkdownWorker,
|
|
94
|
+
z as renderMarkdown,
|
|
75
95
|
R as renderMarkdownSync,
|
|
76
|
-
|
|
77
|
-
|
|
96
|
+
C as terminateMarkdownWorker,
|
|
97
|
+
T as waitForMarkdownWorker
|
|
78
98
|
};
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { type Accessor } from 'solid-js';
|
|
2
2
|
import type { VirtualListConfig } from '../types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
start: number;
|
|
6
|
-
size: number;
|
|
7
|
-
key: string;
|
|
8
|
-
}
|
|
3
|
+
import { type VirtualItem, type VirtualListAnchor } from './virtualListLayout';
|
|
4
|
+
export { createVirtualListLayout, type VirtualItem, type VirtualListAnchor, type VirtualListLayout } from './virtualListLayout';
|
|
9
5
|
export interface UseVirtualListOptions {
|
|
10
6
|
count: Accessor<number>;
|
|
11
7
|
getItemKey: (index: number) => string;
|
|
12
8
|
getItemHeight: (index: number) => number;
|
|
13
9
|
config: VirtualListConfig;
|
|
10
|
+
/** Explicit ordered identities for prepend, eviction and same-count replacement. */
|
|
11
|
+
itemKeys?: Accessor<readonly string[]>;
|
|
14
12
|
}
|
|
15
13
|
export interface UseVirtualListReturn {
|
|
16
14
|
containerRef: (el: HTMLElement) => void;
|
|
@@ -33,5 +31,8 @@ export interface UseVirtualListReturn {
|
|
|
33
31
|
* Call this from a ResizeObserver for visible items.
|
|
34
32
|
*/
|
|
35
33
|
setItemHeight: (index: number, height: number) => void;
|
|
34
|
+
setItemHeightByKey: (key: string, height: number) => void;
|
|
35
|
+
captureAnchor: () => VirtualListAnchor | undefined;
|
|
36
|
+
anchorOffset: (anchor: VirtualListAnchor) => number | undefined;
|
|
36
37
|
}
|
|
37
38
|
export declare function useVirtualList(options: UseVirtualListOptions): UseVirtualListReturn;
|
|
@@ -1,152 +1,123 @@
|
|
|
1
|
-
import { createSignal as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
let e = 0;
|
|
14
|
-
for (let o = t; o > 0; o -= o & -o)
|
|
15
|
-
e += m[o];
|
|
16
|
-
return e;
|
|
17
|
-
}, O = (t) => {
|
|
18
|
-
let e = 1;
|
|
19
|
-
for (; e << 1 <= t; ) e <<= 1;
|
|
20
|
-
return e;
|
|
21
|
-
}, k = (t, e) => {
|
|
22
|
-
if (e <= 0 || t <= 0) return 0;
|
|
23
|
-
const o = i(e);
|
|
24
|
-
if (t >= o) return e - 1;
|
|
25
|
-
let s = 0, n = 0;
|
|
26
|
-
for (let l = O(e); l !== 0; l >>= 1) {
|
|
27
|
-
const h = s + l;
|
|
28
|
-
h <= e && n + m[h] < t && (n += m[h], s = h);
|
|
29
|
-
}
|
|
30
|
-
return Math.max(0, Math.min(e - 1, s));
|
|
31
|
-
}, [p, C] = b(0);
|
|
32
|
-
let I = !1;
|
|
33
|
-
const z = () => {
|
|
34
|
-
if (I) return;
|
|
35
|
-
I = !0;
|
|
1
|
+
import { createSignal as d, createMemo as c, untrack as _, onMount as j, onCleanup as D } from "solid-js";
|
|
2
|
+
import { createVirtualListLayout as G } from "./virtualListLayout.js";
|
|
3
|
+
function U(A) {
|
|
4
|
+
const { count: y, getItemKey: x, getItemHeight: z, config: m } = A;
|
|
5
|
+
let f = null, r = null;
|
|
6
|
+
const [k, w] = d(0), [H, F] = d(0), [R, M] = d(!0);
|
|
7
|
+
let i = null;
|
|
8
|
+
const o = G(m.defaultItemHeight), [a, S] = d(0);
|
|
9
|
+
let T = !1, h, g, v = !1;
|
|
10
|
+
const q = () => {
|
|
11
|
+
if (v || T) return;
|
|
12
|
+
T = !0;
|
|
36
13
|
const t = () => {
|
|
37
|
-
|
|
14
|
+
T = !1, h = void 0, g = void 0, !v && S((e) => e + 1);
|
|
38
15
|
};
|
|
39
16
|
if (typeof requestAnimationFrame > "u") {
|
|
40
|
-
setTimeout(t, 0);
|
|
17
|
+
g = setTimeout(t, 0);
|
|
41
18
|
return;
|
|
42
19
|
}
|
|
43
|
-
requestAnimationFrame(t);
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return { start: l, end: h };
|
|
63
|
-
}), K = d(() => {
|
|
64
|
-
const { start: t, end: e } = H(), o = [];
|
|
65
|
-
let s = i(t);
|
|
66
|
-
for (let n = t; n < e; n += 1) {
|
|
67
|
-
const l = f[n] ?? a.defaultItemHeight;
|
|
68
|
-
o.push({
|
|
69
|
-
index: n,
|
|
70
|
-
start: s,
|
|
71
|
-
size: l,
|
|
72
|
-
key: w(n)
|
|
73
|
-
}), s += l;
|
|
20
|
+
h = requestAnimationFrame(t);
|
|
21
|
+
}, u = c(() => {
|
|
22
|
+
const t = y();
|
|
23
|
+
if (!Number.isInteger(t) || t < 0) throw new Error("Virtual list count must be a non-negative integer");
|
|
24
|
+
const e = A.itemKeys?.();
|
|
25
|
+
if (e && e.length !== t) throw new Error("Virtual list keys must match count");
|
|
26
|
+
return _(() => o.reset(e ?? Array.from({ length: t }, (n, l) => x(l)), z)), {};
|
|
27
|
+
}), p = c(() => (u(), a(), o.range(k(), H(), m.overscan))), E = c(() => {
|
|
28
|
+
u(), a();
|
|
29
|
+
const { start: t, end: e } = p(), n = [];
|
|
30
|
+
let l = o.prefix(t);
|
|
31
|
+
for (let s = t; s < e; s += 1) {
|
|
32
|
+
const V = o.item(s)?.size ?? m.defaultItemHeight;
|
|
33
|
+
n.push({
|
|
34
|
+
index: s,
|
|
35
|
+
start: l,
|
|
36
|
+
size: V,
|
|
37
|
+
key: o.item(s).key
|
|
38
|
+
}), l += V;
|
|
74
39
|
}
|
|
75
|
-
return
|
|
76
|
-
}),
|
|
77
|
-
|
|
78
|
-
const t =
|
|
79
|
-
return Math.max(0,
|
|
80
|
-
}),
|
|
81
|
-
if (r &&
|
|
40
|
+
return n;
|
|
41
|
+
}), K = c(() => (u(), a(), o.total())), L = c(() => (u(), a(), o.prefix(p().start))), O = c(() => {
|
|
42
|
+
u(), a();
|
|
43
|
+
const t = y(), e = p().end;
|
|
44
|
+
return Math.max(0, o.total() - o.prefix(Math.min(t, e)));
|
|
45
|
+
}), I = () => {
|
|
46
|
+
if (r && i === null) {
|
|
82
47
|
if (typeof requestAnimationFrame > "u") {
|
|
83
48
|
const t = r.scrollTop;
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
49
|
+
w(t);
|
|
50
|
+
const n = r.scrollHeight - t - r.clientHeight < 50;
|
|
51
|
+
M(n);
|
|
87
52
|
return;
|
|
88
53
|
}
|
|
89
|
-
|
|
90
|
-
if (
|
|
54
|
+
i = requestAnimationFrame(() => {
|
|
55
|
+
if (i = null, !r) return;
|
|
91
56
|
const t = r.scrollTop;
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
57
|
+
w(t);
|
|
58
|
+
const n = r.scrollHeight - t - r.clientHeight < 50;
|
|
59
|
+
M(n);
|
|
95
60
|
});
|
|
96
61
|
}
|
|
97
62
|
};
|
|
98
|
-
let
|
|
99
|
-
|
|
100
|
-
|
|
63
|
+
let b = null;
|
|
64
|
+
j(() => {
|
|
65
|
+
f && (b = new ResizeObserver((t) => {
|
|
101
66
|
for (const e of t)
|
|
102
|
-
|
|
103
|
-
}),
|
|
104
|
-
}),
|
|
105
|
-
v?.disconnect(),
|
|
106
|
-
})
|
|
67
|
+
F(e.contentRect.height);
|
|
68
|
+
}), b.observe(f), F(f.clientHeight)), I();
|
|
69
|
+
}), D(() => {
|
|
70
|
+
v = !0, b?.disconnect(), h !== void 0 && cancelAnimationFrame(h), g !== void 0 && clearTimeout(g), i !== null && typeof cancelAnimationFrame < "u" && (cancelAnimationFrame(i), i = null);
|
|
71
|
+
});
|
|
72
|
+
const C = (t, e = "start") => {
|
|
73
|
+
if (!r) return;
|
|
74
|
+
const n = y();
|
|
75
|
+
if (t < 0 || t >= n) return;
|
|
76
|
+
const l = o.item(t)?.size ?? m.defaultItemHeight;
|
|
77
|
+
let s;
|
|
78
|
+
switch (e) {
|
|
79
|
+
case "start":
|
|
80
|
+
s = o.prefix(t);
|
|
81
|
+
break;
|
|
82
|
+
case "center":
|
|
83
|
+
s = o.prefix(t) - H() / 2 + l / 2;
|
|
84
|
+
break;
|
|
85
|
+
case "end":
|
|
86
|
+
s = o.prefix(t + 1) - H();
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
r.scrollTo({ top: Math.max(0, s), behavior: "smooth" });
|
|
90
|
+
}, N = () => {
|
|
91
|
+
r && r.scrollTo({ top: r.scrollHeight, behavior: "smooth" });
|
|
92
|
+
}, B = (t, e) => {
|
|
93
|
+
o.measure(t, e) && q();
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
107
96
|
containerRef: (t) => {
|
|
108
|
-
|
|
97
|
+
f = t;
|
|
109
98
|
},
|
|
110
99
|
scrollRef: (t) => {
|
|
111
|
-
r = t,
|
|
112
|
-
},
|
|
113
|
-
onScroll: M,
|
|
114
|
-
virtualItems: K,
|
|
115
|
-
totalHeight: N,
|
|
116
|
-
paddingTop: P,
|
|
117
|
-
paddingBottom: j,
|
|
118
|
-
scrollToIndex: (t, e = "start") => {
|
|
119
|
-
if (!r) return;
|
|
120
|
-
const o = c();
|
|
121
|
-
if (t < 0 || t >= o) return;
|
|
122
|
-
const s = f[t] ?? a.defaultItemHeight;
|
|
123
|
-
let n;
|
|
124
|
-
switch (e) {
|
|
125
|
-
case "start":
|
|
126
|
-
n = i(t);
|
|
127
|
-
break;
|
|
128
|
-
case "center":
|
|
129
|
-
n = i(t) - T() / 2 + s / 2;
|
|
130
|
-
break;
|
|
131
|
-
case "end":
|
|
132
|
-
n = i(t + 1) - T();
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
r.scrollTo({ top: Math.max(0, n), behavior: "smooth" });
|
|
100
|
+
r = t, I();
|
|
136
101
|
},
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
102
|
+
onScroll: I,
|
|
103
|
+
virtualItems: E,
|
|
104
|
+
totalHeight: K,
|
|
105
|
+
paddingTop: L,
|
|
106
|
+
paddingBottom: O,
|
|
107
|
+
scrollToIndex: C,
|
|
108
|
+
scrollToBottom: N,
|
|
109
|
+
isAtBottom: R,
|
|
110
|
+
visibleRange: p,
|
|
142
111
|
setItemHeight: (t, e) => {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
112
|
+
const n = o.item(t);
|
|
113
|
+
n && B(n.key, e);
|
|
114
|
+
},
|
|
115
|
+
setItemHeightByKey: B,
|
|
116
|
+
captureAnchor: () => o.anchor(r?.scrollTop ?? k()),
|
|
117
|
+
anchorOffset: (t) => o.offset(t)
|
|
148
118
|
};
|
|
149
119
|
}
|
|
150
120
|
export {
|
|
151
|
-
|
|
121
|
+
G as createVirtualListLayout,
|
|
122
|
+
U as useVirtualList
|
|
152
123
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface VirtualItem {
|
|
2
|
+
index: number;
|
|
3
|
+
start: number;
|
|
4
|
+
size: number;
|
|
5
|
+
key: string;
|
|
6
|
+
}
|
|
7
|
+
export interface VirtualListAnchor {
|
|
8
|
+
key: string;
|
|
9
|
+
offset: number;
|
|
10
|
+
}
|
|
11
|
+
/** Geometry only: the host remains the sole owner of scroll writes. */
|
|
12
|
+
export declare function createVirtualListLayout(defaultItemHeight: number): {
|
|
13
|
+
reset: (nextKeys: readonly string[], estimate: (index: number) => number) => void;
|
|
14
|
+
measure: (key: string, height: number) => boolean;
|
|
15
|
+
item: (index: number) => VirtualItem | undefined;
|
|
16
|
+
range: (scrollTop: number, viewportHeight: number, overscan?: number) => {
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
};
|
|
20
|
+
anchor: (scrollTop: number) => VirtualListAnchor | undefined;
|
|
21
|
+
offset: (anchor: VirtualListAnchor) => number | undefined;
|
|
22
|
+
prefix: (end: number) => number;
|
|
23
|
+
total: () => number;
|
|
24
|
+
count: () => number;
|
|
25
|
+
measuredCount: () => number;
|
|
26
|
+
};
|
|
27
|
+
export type VirtualListLayout = ReturnType<typeof createVirtualListLayout>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
function y(m) {
|
|
2
|
+
const x = Number.isFinite(m) && m > 0 ? Math.max(1, Math.round(m)) : 80;
|
|
3
|
+
let s = [], u = [], f = [0], c = /* @__PURE__ */ new Map();
|
|
4
|
+
const l = /* @__PURE__ */ new Map(), g = (t) => Number.isFinite(t) && t > 0 ? Math.max(1, Math.round(t)) : x;
|
|
5
|
+
function h(t) {
|
|
6
|
+
let r = 0;
|
|
7
|
+
const i = Number.isFinite(t) ? Math.trunc(t) : t === 1 / 0 ? s.length : 0;
|
|
8
|
+
for (let n = Math.max(0, Math.min(s.length, i)); n > 0; n -= n & -n) r += f[n];
|
|
9
|
+
return r;
|
|
10
|
+
}
|
|
11
|
+
function M(t) {
|
|
12
|
+
if (!s.length || t <= 0) return 0;
|
|
13
|
+
let r = 0, i = 0, n = 1;
|
|
14
|
+
for (; n * 2 <= s.length; ) n *= 2;
|
|
15
|
+
for (; n > 0; n = Math.floor(n / 2)) {
|
|
16
|
+
const o = r + n;
|
|
17
|
+
o <= s.length && i + f[o] <= t && (i += f[o], r = o);
|
|
18
|
+
}
|
|
19
|
+
return Math.min(s.length - 1, r);
|
|
20
|
+
}
|
|
21
|
+
function b(t, r) {
|
|
22
|
+
const i = /* @__PURE__ */ new Map();
|
|
23
|
+
for (let e = 0; e < t.length; e++) {
|
|
24
|
+
const a = t[e];
|
|
25
|
+
if (i.has(a)) throw new Error("Virtual list keys must be unique");
|
|
26
|
+
i.set(a, e);
|
|
27
|
+
}
|
|
28
|
+
const n = t.map((e, a) => l.get(e) ?? g(r(a))), o = [0, ...n];
|
|
29
|
+
for (let e = 1; e < o.length; e++) {
|
|
30
|
+
const a = e + (e & -e);
|
|
31
|
+
a < o.length && (o[a] += o[e]);
|
|
32
|
+
}
|
|
33
|
+
s = [...t], u = n, f = o, c = i;
|
|
34
|
+
for (const e of l.keys()) c.has(e) || l.delete(e);
|
|
35
|
+
}
|
|
36
|
+
function p(t, r) {
|
|
37
|
+
const i = c.get(t);
|
|
38
|
+
if (i === void 0) return !1;
|
|
39
|
+
const n = g(r);
|
|
40
|
+
l.set(t, n);
|
|
41
|
+
const o = u[i];
|
|
42
|
+
if (n === o) return !1;
|
|
43
|
+
u[i] = n;
|
|
44
|
+
for (let e = i + 1; e < f.length; e += e & -e) f[e] += n - o;
|
|
45
|
+
return !0;
|
|
46
|
+
}
|
|
47
|
+
function N(t) {
|
|
48
|
+
if (!(t < 0 || t >= s.length || !Number.isInteger(t)))
|
|
49
|
+
return { index: t, key: s[t], start: h(t), size: u[t] };
|
|
50
|
+
}
|
|
51
|
+
function k(t, r, i = 0) {
|
|
52
|
+
if (!s.length) return { start: 0, end: 0 };
|
|
53
|
+
const n = Number.isFinite(t) ? Math.max(0, t) : 0, o = Number.isFinite(r) ? Math.max(0, r) : 0, e = Number.isFinite(i) ? Math.max(0, Math.trunc(i)) : 0;
|
|
54
|
+
return { start: Math.max(0, M(n) - e), end: Math.min(s.length, M(n + o) + 1 + e) };
|
|
55
|
+
}
|
|
56
|
+
function F(t) {
|
|
57
|
+
if (!s.length) return;
|
|
58
|
+
const r = Number.isFinite(t) ? Math.max(0, t) : 0, i = M(r);
|
|
59
|
+
return { key: s[i], offset: Math.max(0, Math.min(u[i], r - h(i))) };
|
|
60
|
+
}
|
|
61
|
+
function d(t) {
|
|
62
|
+
const r = c.get(t.key);
|
|
63
|
+
if (r === void 0) return;
|
|
64
|
+
const i = Number.isFinite(t.offset) ? t.offset : 0;
|
|
65
|
+
return h(r) + Math.max(0, Math.min(u[r], i));
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
reset: b,
|
|
69
|
+
measure: p,
|
|
70
|
+
item: N,
|
|
71
|
+
range: k,
|
|
72
|
+
anchor: F,
|
|
73
|
+
offset: d,
|
|
74
|
+
prefix: h,
|
|
75
|
+
total: () => h(s.length),
|
|
76
|
+
count: () => s.length,
|
|
77
|
+
measuredCount: () => l.size
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
y as createVirtualListLayout
|
|
82
|
+
};
|