@keenaioc/data-view 0.0.0-poc.1 → 0.2.0-alpha.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 +105 -0
- package/DATA-PRIVACY.md +20 -0
- package/INTEGRATION.md +178 -0
- package/KNOWN-LIMITATIONS.md +34 -0
- package/LICENSE +21 -0
- package/README.md +67 -5
- package/dist/contracts.d.ts +33 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +83 -0
- package/dist/contracts.js.map +1 -0
- package/dist/data-view.d.ts +3 -0
- package/dist/data-view.d.ts.map +1 -0
- package/dist/data-view.js +822 -0
- package/dist/data-view.js.map +1 -0
- package/dist/engine.d.ts +34 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +307 -0
- package/dist/engine.js.map +1 -0
- package/dist/gantt-bar.d.ts +17 -0
- package/dist/gantt-bar.d.ts.map +1 -0
- package/dist/gantt-bar.js +142 -0
- package/dist/gantt-bar.js.map +1 -0
- package/dist/gantt-dependencies.d.ts +27 -0
- package/dist/gantt-dependencies.d.ts.map +1 -0
- package/dist/gantt-dependencies.js +218 -0
- package/dist/gantt-dependencies.js.map +1 -0
- package/dist/gantt-dependency-ui.d.ts +37 -0
- package/dist/gantt-dependency-ui.d.ts.map +1 -0
- package/dist/gantt-dependency-ui.js +79 -0
- package/dist/gantt-dependency-ui.js.map +1 -0
- package/dist/gantt-grid.d.ts +27 -0
- package/dist/gantt-grid.d.ts.map +1 -0
- package/dist/gantt-grid.js +72 -0
- package/dist/gantt-grid.js.map +1 -0
- package/dist/gantt-operations.d.ts +14 -0
- package/dist/gantt-operations.d.ts.map +1 -0
- package/dist/gantt-operations.js +103 -0
- package/dist/gantt-operations.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/operations.d.ts +11 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +117 -0
- package/dist/operations.js.map +1 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +465 -0
- package/dist/registry.js.map +1 -0
- package/dist/remote-data.d.ts +19 -0
- package/dist/remote-data.d.ts.map +1 -0
- package/dist/remote-data.js +67 -0
- package/dist/remote-data.js.map +1 -0
- package/dist/row-move.d.ts +7 -0
- package/dist/row-move.d.ts.map +1 -0
- package/dist/row-move.js +27 -0
- package/dist/row-move.js.map +1 -0
- package/dist/schedule-view.d.ts +27 -0
- package/dist/schedule-view.d.ts.map +1 -0
- package/dist/schedule-view.js +122 -0
- package/dist/schedule-view.js.map +1 -0
- package/dist/schedule.d.ts +28 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +97 -0
- package/dist/schedule.js.map +1 -0
- package/dist/style.css +986 -0
- package/dist/timeline.d.ts +25 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +58 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toolbar.d.ts +10 -0
- package/dist/toolbar.d.ts.map +1 -0
- package/dist/toolbar.js +31 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/types.d.ts +472 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/use-remote-data.d.ts +18 -0
- package/dist/use-remote-data.d.ts.map +1 -0
- package/dist/use-remote-data.js +12 -0
- package/dist/use-remote-data.js.map +1 -0
- package/dist/use-row-move.d.ts +12 -0
- package/dist/use-row-move.d.ts.map +1 -0
- package/dist/use-row-move.js +151 -0
- package/dist/use-row-move.js.map +1 -0
- package/dist/v2-panels.d.ts +37 -0
- package/dist/v2-panels.d.ts.map +1 -0
- package/dist/v2-panels.js +108 -0
- package/dist/v2-panels.js.map +1 -0
- package/dist/view-state.d.ts +30 -0
- package/dist/view-state.d.ts.map +1 -0
- package/dist/view-state.js +94 -0
- package/dist/view-state.js.map +1 -0
- package/dist/view-workspace.d.ts +3 -0
- package/dist/view-workspace.d.ts.map +1 -0
- package/dist/view-workspace.js +95 -0
- package/dist/view-workspace.js.map +1 -0
- package/dist/virtual-list.d.ts +12 -0
- package/dist/virtual-list.d.ts.map +1 -0
- package/dist/virtual-list.js +46 -0
- package/dist/virtual-list.js.map +1 -0
- package/package.json +19 -16
- package/index.d.ts +0 -2
- package/index.js +0 -5
- package/react.d.ts +0 -2
- package/react.js +0 -8
- package/style.css +0 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { normalizeViewConfig } from "./engine.js";
|
|
2
|
+
/** Settings only: row data, callbacks and dependencies never enter this document. */
|
|
3
|
+
export function createViewCollection(fields, initial) {
|
|
4
|
+
const config = normalizeViewConfig(fields, initial);
|
|
5
|
+
return { schemaVersion: 1, activeViewId: "default", views: [{ id: "default", name: "預設視圖", config }] };
|
|
6
|
+
}
|
|
7
|
+
export function normalizeViewCollection(fields, input) {
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
const views = (Array.isArray(input?.views) ? input.views : []).slice(0, 50).flatMap((v) => {
|
|
10
|
+
if (!v || typeof v.id !== "string" || !v.id || seen.has(v.id))
|
|
11
|
+
return [];
|
|
12
|
+
seen.add(v.id);
|
|
13
|
+
return [{ id: v.id, name: String(v.name || "未命名視圖").trim().slice(0, 60), config: normalizeViewConfig(fields, v.config) }];
|
|
14
|
+
});
|
|
15
|
+
if (!views.length)
|
|
16
|
+
return createViewCollection(fields);
|
|
17
|
+
return { schemaVersion: 1, views, activeViewId: views.some((v) => v.id === input.activeViewId) ? input.activeViewId : views[0].id };
|
|
18
|
+
}
|
|
19
|
+
export function changeViewCollection(current, action) {
|
|
20
|
+
if (action.type === "select") {
|
|
21
|
+
if (!current.views.some((v) => v.id === action.id))
|
|
22
|
+
throw new Error("視圖不存在");
|
|
23
|
+
return { ...current, activeViewId: action.id };
|
|
24
|
+
}
|
|
25
|
+
if (action.type === "delete") {
|
|
26
|
+
if (current.views.length === 1)
|
|
27
|
+
throw new Error("至少保留一個視圖");
|
|
28
|
+
const views = current.views.filter((v) => v.id !== action.id);
|
|
29
|
+
return { ...current, views, activeViewId: current.activeViewId === action.id ? views[0].id : current.activeViewId };
|
|
30
|
+
}
|
|
31
|
+
if (action.type === "update")
|
|
32
|
+
return { ...current, views: current.views.map((v) => v.id === action.id ? { ...v, config: action.config } : v) };
|
|
33
|
+
const name = action.name.trim();
|
|
34
|
+
if (!name || name.length > 60)
|
|
35
|
+
throw new Error("視圖名稱需為 1–60 個字");
|
|
36
|
+
if (current.views.some((v) => v.name === name && (action.type !== "rename" || v.id !== action.id)))
|
|
37
|
+
throw new Error("已有同名視圖,請換一個名稱");
|
|
38
|
+
if (action.type === "rename")
|
|
39
|
+
return { ...current, views: current.views.map((v) => v.id === action.id ? { ...v, name } : v) };
|
|
40
|
+
if (current.views.length >= 50)
|
|
41
|
+
throw new Error("目前最多 50 個視圖");
|
|
42
|
+
if (current.views.some((v) => v.id === action.id))
|
|
43
|
+
throw new Error("視圖識別碼重複");
|
|
44
|
+
const source = current.views.find((v) => v.id === current.activeViewId);
|
|
45
|
+
const config = JSON.parse(JSON.stringify(source.config));
|
|
46
|
+
if (action.type === "add") {
|
|
47
|
+
config.viewType = action.viewType ?? "table";
|
|
48
|
+
config.location = undefined;
|
|
49
|
+
}
|
|
50
|
+
return { ...current, activeViewId: action.id, views: [...current.views, { id: action.id, name, config }] };
|
|
51
|
+
}
|
|
52
|
+
/** No debounce timer: invokes sync storage before returning; async writes are serialized.
|
|
53
|
+
* A queued snapshot supersedes older queued snapshots, and includes ALL named views.
|
|
54
|
+
* Promises settle only when their snapshot or a newer one has been persisted. */
|
|
55
|
+
export function createSnapshotWriter(save) {
|
|
56
|
+
let running = false;
|
|
57
|
+
let queued;
|
|
58
|
+
function pump() {
|
|
59
|
+
if (running || !queued)
|
|
60
|
+
return;
|
|
61
|
+
const job = queued;
|
|
62
|
+
queued = undefined;
|
|
63
|
+
running = true;
|
|
64
|
+
let result;
|
|
65
|
+
try {
|
|
66
|
+
result = save(job.value);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
finish(e, true);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
Promise.resolve(result).then(() => finish(undefined, false), (e) => finish(e, true));
|
|
73
|
+
function finish(error, failed) {
|
|
74
|
+
running = false;
|
|
75
|
+
for (const w of job.waiters) {
|
|
76
|
+
if (failed)
|
|
77
|
+
w.reject(error);
|
|
78
|
+
else
|
|
79
|
+
w.resolve();
|
|
80
|
+
}
|
|
81
|
+
pump();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return (value) => new Promise((resolve, reject) => {
|
|
85
|
+
if (queued) {
|
|
86
|
+
queued.value = value;
|
|
87
|
+
queued.waiters.push({ resolve, reject });
|
|
88
|
+
}
|
|
89
|
+
else
|
|
90
|
+
queued = { value, waiters: [{ resolve, reject }] };
|
|
91
|
+
pump();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=view-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-state.js","sourceRoot":"","sources":["../src/view-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-workspace.d.ts","sourceRoot":"","sources":["../src/view-workspace.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAsB,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE7E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,sBAAsB,CAAC,GAAG,CAAC,2CAAgF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { DataView } from "./data-view.js";
|
|
5
|
+
import { DataViewDialog } from "./v2-panels.js";
|
|
6
|
+
import { changeViewCollection, createSnapshotWriter, normalizeViewCollection } from "./view-state.js";
|
|
7
|
+
import { newOperationId } from "./operations.js";
|
|
8
|
+
export function DataViewWorkspace(props) { return _jsx(WorkspaceInner, { ...props }, props.identityKey ?? "default"); }
|
|
9
|
+
function WorkspaceInner({ initialViews, onViewsChange, views, onActiveViewChange, runtimeStates, onViewRuntimeChange, ...props }) {
|
|
10
|
+
const [collection, setCollection] = useState(() => normalizeViewCollection(props.fields, views ?? initialViews));
|
|
11
|
+
const current = useRef(collection);
|
|
12
|
+
const callback = useRef(onViewsChange);
|
|
13
|
+
useEffect(() => { callback.current = onViewsChange; }, [onViewsChange]);
|
|
14
|
+
const writer = useRef(null);
|
|
15
|
+
const [status, setStatus] = useState("");
|
|
16
|
+
const [failed, setFailed] = useState(false);
|
|
17
|
+
const dirty = useRef(false);
|
|
18
|
+
const seq = useRef(0);
|
|
19
|
+
const [dialog, setDialog] = useState(null);
|
|
20
|
+
const [name, setName] = useState("");
|
|
21
|
+
const [type, setType] = useState("table");
|
|
22
|
+
const [error, setError] = useState("");
|
|
23
|
+
const dataPending = useRef(0);
|
|
24
|
+
const [dataBusy, setDataBusy] = useState(false);
|
|
25
|
+
const [dataMessage, setDataMessage] = useState("");
|
|
26
|
+
async function writeData(action) {
|
|
27
|
+
dataPending.current++;
|
|
28
|
+
setDataBusy(true);
|
|
29
|
+
setDataMessage("");
|
|
30
|
+
try {
|
|
31
|
+
await action();
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
setDataMessage(e instanceof Error ? e.message : "資料儲存失敗");
|
|
35
|
+
throw e;
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
dataPending.current--;
|
|
39
|
+
setDataBusy(dataPending.current > 0);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const active = collection.views.find((v) => v.id === collection.activeViewId);
|
|
43
|
+
const configurable = props.permissions?.canConfigureView !== false && props.features?.viewManagement !== false;
|
|
44
|
+
useEffect(() => { if (!views || dataPending.current || dirty.current)
|
|
45
|
+
return; const next = normalizeViewCollection(props.fields, views); current.current = next; setCollection(next); }, [views, props.fields]);
|
|
46
|
+
useEffect(() => { const leave = (e) => { if (dirty.current) {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
e.returnValue = "";
|
|
49
|
+
} }; window.addEventListener("beforeunload", leave); return () => window.removeEventListener("beforeunload", leave); }, []);
|
|
50
|
+
function persist(next) {
|
|
51
|
+
current.current = next;
|
|
52
|
+
setCollection(next);
|
|
53
|
+
if (!callback.current) {
|
|
54
|
+
setStatus("本次工作階段");
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
const n = ++seq.current;
|
|
58
|
+
dirty.current = true;
|
|
59
|
+
setFailed(false);
|
|
60
|
+
setStatus("視圖儲存中…");
|
|
61
|
+
if (!writer.current)
|
|
62
|
+
writer.current = createSnapshotWriter((v) => callback.current?.(v));
|
|
63
|
+
return writer.current(next).then(() => { if (seq.current === n) {
|
|
64
|
+
dirty.current = false;
|
|
65
|
+
setStatus("視圖已儲存");
|
|
66
|
+
} }, (e) => { if (seq.current === n) {
|
|
67
|
+
setFailed(true);
|
|
68
|
+
setStatus(e instanceof Error ? e.message : "視圖儲存失敗");
|
|
69
|
+
} throw e; });
|
|
70
|
+
}
|
|
71
|
+
function apply(action) {
|
|
72
|
+
if (dataPending.current)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
const next = changeViewCollection(current.current, action);
|
|
76
|
+
if (action.type === "select" && onActiveViewChange) {
|
|
77
|
+
current.current = next;
|
|
78
|
+
setCollection(next);
|
|
79
|
+
void Promise.resolve(onActiveViewChange(next.activeViewId)).catch((e) => { setFailed(true); setStatus(e instanceof Error ? e.message : "視圖切換未保存"); });
|
|
80
|
+
}
|
|
81
|
+
else
|
|
82
|
+
void persist(next).catch(() => { });
|
|
83
|
+
setDialog(null);
|
|
84
|
+
setError("");
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
setError(e instanceof Error ? e.message : "無法修改視圖");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function open(mode) { setDialog(mode); setName(mode === "rename" ? active.name : mode === "copy" ? `${active.name} 副本` : ""); setType("table"); setError(""); }
|
|
91
|
+
if (props.access === "denied" || props.loading || props.error)
|
|
92
|
+
return _jsx(DataView, { ...props, initialView: active.config });
|
|
93
|
+
return _jsxs("div", { className: `hy-dv-workspace chrome-${props.chrome ?? "standard"} ${props.height !== undefined ? "has-total-height" : ""}`, style: { height: props.height }, children: [_jsxs("nav", { className: "hy-dv-named-tabs", "aria-label": "\u547D\u540D\u8996\u5716", children: [collection.views.map((v) => _jsxs("button", { disabled: dataBusy || props.permissions?.canSwitchView === false, "aria-pressed": v.id === active.id, onClick: () => apply({ type: "select", id: v.id }), children: [v.config.viewType === "gantt" ? "▥" : v.config.viewType === "calendar" ? "▦" : "▤", " ", v.name] }, v.id)), configurable && !dataBusy && _jsxs(_Fragment, { children: [_jsx("button", { onClick: () => open("add"), children: "\uFF0B \u65B0\u589E\u8996\u5716" }), _jsx("button", { onClick: () => open("rename"), children: "\u91CD\u65B0\u547D\u540D" }), _jsx("button", { onClick: () => open("copy"), children: "\u8907\u88FD\u8996\u5716" }), _jsx("button", { disabled: collection.views.length === 1, onClick: () => open("delete"), children: "\u522A\u9664\u8996\u5716" })] })] }), _jsxs("div", { className: "hy-dv-view-save", role: failed ? "alert" : "status", children: [status, failed && _jsx("button", { onClick: () => void persist(current.current).catch(() => { }), children: "\u91CD\u8A66\u5132\u5B58" })] }), dataMessage && _jsx("p", { className: "hy-dv-view-save", role: "alert", children: dataMessage }), _jsx(DataView, { ...props, height: props.height !== undefined ? "100%" : undefined, hideViewSaveStatus: !!onViewsChange && !onViewRuntimeChange, runtimeState: runtimeStates?.[active.id] ?? props.runtimeState, onRuntimeChange: onViewRuntimeChange ? (state) => onViewRuntimeChange(active.id, state) : props.onRuntimeChange, onCellCommit: props.onCellCommit ? (c) => writeData(() => props.onCellCommit(c)) : undefined, onBatchCommit: props.onBatchCommit ? (c) => writeData(() => props.onBatchCommit(c)) : undefined, onFieldChange: props.onFieldChange ? (c) => writeData(() => props.onFieldChange(c)) : undefined, onGanttDependencyChange: props.onGanttDependencyChange ? (c) => writeData(() => props.onGanttDependencyChange(c)) : undefined, onRequestAttachment: props.onRequestAttachment ? (c) => writeData(() => props.onRequestAttachment(c)) : undefined, view: active.config, onViewChange: (config) => persist(changeViewCollection(current.current, { type: "update", id: active.id, config })) }, active.id), dialog && _jsxs(DataViewDialog, { title: dialog === "delete" ? "刪除視圖" : dialog === "rename" ? "重新命名視圖" : dialog === "copy" ? "複製視圖" : "新增視圖", onClose: () => setDialog(null), children: [dialog === "delete" ? _jsxs(_Fragment, { children: [_jsxs("p", { children: ["\u522A\u9664\u300C", active.name, "\u300D\u7684\u5448\u73FE\u8A2D\u5B9A\u3002\u539F\u59CB\u8CC7\u6599\u8207\u6B04\u4F4D\u6703\u4FDD\u7559\u3002"] }), _jsx("button", { onClick: () => apply({ type: "delete", id: active.id }), children: "\u78BA\u8A8D\u522A\u9664\u6B64\u8996\u5716" })] }) : _jsxs("form", { className: "hy-dv-form", onSubmit: (e) => { e.preventDefault(); apply(dialog === "rename" ? { type: "rename", id: active.id, name } : { type: dialog, id: newOperationId(), name, viewType: type }); }, children: [_jsxs("label", { children: ["\u8996\u5716\u540D\u7A31", _jsx("input", { autoFocus: true, required: true, maxLength: 60, value: name, onChange: (e) => setName(e.target.value) })] }), dialog === "add" && _jsxs("label", { children: ["\u5448\u73FE\u65B9\u5F0F", _jsxs("select", { value: type, onChange: (e) => setType(e.target.value), children: [_jsx("option", { value: "table", children: "\u8CC7\u6599\u8868\u683C" }), _jsx("option", { value: "gantt", children: "\u7518\u7279\u5716" }), _jsx("option", { value: "calendar", children: "\u884C\u4E8B\u66C6" })] })] }), _jsx("p", { children: dialog === "add" ? "沿用目前欄位、篩選與排序;之後可各自調整。" : "只複製呈現設定,不會複製資料。" }), _jsx("button", { type: "submit", children: "\u78BA\u8A8D" })] }), error && _jsx("p", { role: "alert", children: error })] })] });
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=view-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-workspace.js","sourceRoot":"","sources":["../src/view-workspace.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,uBAAuB,EAAmB,MAAM,iBAAiB,CAAC;AACvH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,UAAU,iBAAiB,CAAM,KAAkC,IAAI,OAAO,KAAC,cAAc,OAA0C,KAAK,IAAzC,KAAK,CAAC,WAAW,IAAI,SAAS,CAAe,CAAC,CAAC,CAAC;AACzJ,SAAS,cAAc,CAAM,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,mBAAmB,EAAE,GAAG,KAAK,EAA+B;IAChK,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC;IACjH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IAC3E,SAAS,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,CAAqE,IAAI,CAAC,CAAC;IAChG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAAC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAAC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1I,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA8C,IAAI,CAAC,CAAC;IACxF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAiC,OAAO,CAAC,CAAC;IAChH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnI,KAAK,UAAU,SAAS,CAAC,MAAkC;QACzD,WAAW,CAAC,OAAO,EAAE,CAAC;QAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC;YAAC,MAAM,MAAM,EAAE,CAAC;QAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YAAC,cAAc,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAAC,MAAM,CAAC,CAAC;QAAC,CAAC;gBACjG,CAAC;YAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAAC,WAAW,CAAC,WAAW,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAAC,CAAC;IAC1E,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,YAAY,CAAE,CAAC;IAC/E,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,EAAE,gBAAgB,KAAK,KAAK,IAAI,KAAK,CAAC,QAAQ,EAAE,cAAc,KAAK,KAAK,CAAC;IAC/G,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,CAAC,MAAM,IAAI,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAChN,SAAS,CAAC,GAAG,EAAE,GAAG,MAAM,KAAK,GAAG,CAAC,CAAoB,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAAC,CAAC,CAAC,cAAc,EAAE,CAAC;QAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC;IAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrP,SAAS,OAAO,CAAC,IAAwB;QACvC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAAC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAAC,CAAC;QACzE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC;QAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrF,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,CAAC,OAAO,GAAG,oBAAoB,CAAqB,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7G,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;YAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAAC,SAAS,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3O,CAAC;IACD,SAAS,KAAK,CAAC,MAAkB;QAC/B,IAAI,WAAW,CAAC,OAAO;YAAE,OAAO;QAChC,IAAI,CAAC;YAAC,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAAC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,kBAAkB,EAAE,CAAC;gBAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAAC,KAAK,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;;gBAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;QACvY,OAAO,CAAC,EAAE,CAAC;YAAC,QAAQ,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAC,CAAC;IACpE,CAAC;IACD,SAAS,IAAI,CAAC,IAAmB,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9K,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,KAAC,QAAQ,OAAK,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,GAAI,CAAC;IAC1H,OAAO,eAAK,SAAS,EAAE,0BAA0B,KAAK,CAAC,MAAM,IAAI,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,aACpK,eAAK,SAAS,EAAC,kBAAkB,gBAAY,0BAAM,aAAE,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAmB,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,WAAW,EAAE,aAAa,KAAK,KAAK,kBAAgB,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,aAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAG,CAAC,CAAC,IAAI,KAA1P,CAAC,CAAC,EAAE,CAAgQ,CAAC,EAChW,YAAY,IAAI,CAAC,QAAQ,IAAI,8BAAE,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gDAAiB,EAAA,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,yCAAe,EAAA,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,yCAAe,EAAA,iBAAQ,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,yCAAe,IAAG,IACrR,EACN,eAAK,SAAS,EAAC,iBAAiB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,aAAG,MAAM,EAAE,MAAM,IAAI,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,yCAAe,IAAO,EAChL,WAAW,IAAI,YAAG,SAAS,EAAC,iBAAiB,EAAC,IAAI,EAAC,OAAO,YAAE,WAAW,GAAK,EAC7E,KAAC,QAAQ,OAAqB,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC,mBAAmB,EACvJ,YAAY,EAAE,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,YAAY,EAC9D,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAC/G,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,YAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAC7F,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,aAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAChG,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,aAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAChG,uBAAuB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,uBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAC9H,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,IAP/O,MAAM,CAAC,EAAE,CAO0O,EACjQ,MAAM,IAAI,MAAC,cAAc,IAAC,KAAK,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,aAClK,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,8BAAE,8CAAO,MAAM,CAAC,IAAI,oHAAuB,EAAA,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,2DAAkB,IAAG,CAAC,CAAC,CAAC,gBAAM,SAAS,EAAC,YAAY,EAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,aACjW,wDAAW,gBAAO,SAAS,QAAC,QAAQ,QAAC,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,IAAQ,EACpH,MAAM,KAAK,KAAK,IAAI,wDAAW,kBAAQ,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAoB,CAAC,aAAE,iBAAQ,KAAK,EAAC,OAAO,yCAAc,EAAA,iBAAQ,KAAK,EAAC,OAAO,mCAAa,EAAA,iBAAQ,KAAK,EAAC,UAAU,mCAAa,IAAS,IAAQ,EACzO,sBAAI,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,iBAAiB,GAAK,EAAA,iBAAQ,IAAI,EAAC,QAAQ,6BAAY,IACnG,EAAE,KAAK,IAAI,YAAG,IAAI,EAAC,OAAO,YAAE,KAAK,GAAK,IAC9B,IACb,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/** Variable-height card virtualization; measured heights keep previous scroll anchors. */
|
|
3
|
+
export declare function VirtualList<T>({ items, itemKey, renderItem, estimate, initialTop, className, onScroll }: {
|
|
4
|
+
items: T[];
|
|
5
|
+
itemKey: (item: T) => string;
|
|
6
|
+
renderItem: (item: T) => ReactNode;
|
|
7
|
+
estimate: (item: T) => number;
|
|
8
|
+
initialTop?: number;
|
|
9
|
+
className?: string;
|
|
10
|
+
onScroll?: (element: HTMLDivElement) => void;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=virtual-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-list.d.ts","sourceRoot":"","sources":["../src/virtual-list.tsx"],"names":[],"mappings":"AACA,OAAO,EAAwC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7E,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;IAC5G,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAAC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC5G,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;CACvF,2CA8BA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { virtualWindow } from "./contracts.js";
|
|
5
|
+
/** Variable-height card virtualization; measured heights keep previous scroll anchors. */
|
|
6
|
+
export function VirtualList({ items, itemKey, renderItem, estimate, initialTop = 0, className, onScroll }) {
|
|
7
|
+
const root = useRef(null);
|
|
8
|
+
const [top, setTop] = useState(initialTop), [viewport, setViewport] = useState(560);
|
|
9
|
+
const [sizes, setSizes] = useState({});
|
|
10
|
+
const keys = useMemo(() => items.map(itemKey), [items, itemKey]);
|
|
11
|
+
const heights = keys.map((key, i) => sizes[key] ?? estimate(items[i]));
|
|
12
|
+
const windowed = virtualWindow(heights, top, viewport);
|
|
13
|
+
const initial = useRef(initialTop);
|
|
14
|
+
useEffect(() => { const el = root.current; if (!el)
|
|
15
|
+
return; el.scrollTop = initial.current; const observer = new ResizeObserver(() => setViewport(el.clientHeight)); observer.observe(el); return () => observer.disconnect(); }, []);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const el = root.current;
|
|
18
|
+
if (!el)
|
|
19
|
+
return;
|
|
20
|
+
const observer = new ResizeObserver((entries) => {
|
|
21
|
+
const changed = {};
|
|
22
|
+
let shift = 0;
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const key = entry.target.dataset.virtualKey;
|
|
25
|
+
const size = Math.ceil(entry.borderBoxSize[0]?.blockSize ?? entry.target.getBoundingClientRect().height);
|
|
26
|
+
const i = keys.indexOf(key);
|
|
27
|
+
if (!size || i < 0 || sizes[key] === size)
|
|
28
|
+
continue;
|
|
29
|
+
if (windowed.offsets[i + 1] <= el.scrollTop)
|
|
30
|
+
shift += size - heights[i];
|
|
31
|
+
changed[key] = size;
|
|
32
|
+
}
|
|
33
|
+
if (Object.keys(changed).length) {
|
|
34
|
+
setSizes((s) => ({ ...s, ...changed }));
|
|
35
|
+
if (shift) {
|
|
36
|
+
el.scrollTop += shift;
|
|
37
|
+
setTop(el.scrollTop);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
el.querySelectorAll("[data-virtual-key]").forEach((node) => observer.observe(node));
|
|
42
|
+
return () => observer.disconnect();
|
|
43
|
+
}, [items, windowed.start, windowed.end, sizes]);
|
|
44
|
+
return _jsxs("div", { ref: root, className: className, onScroll: (e) => { setTop(e.currentTarget.scrollTop); onScroll?.(e.currentTarget); }, children: [_jsx("div", { "aria-hidden": true, style: { height: windowed.before } }), items.slice(windowed.start, windowed.end).map((item, index) => _jsx("div", { "data-virtual-key": keys[windowed.start + index], children: renderItem(item) }, keys[windowed.start + index])), _jsx("div", { "aria-hidden": true, style: { height: windowed.after } })] });
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=virtual-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-list.js","sourceRoot":"","sources":["../src/virtual-list.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,0FAA0F;AAC1F,MAAM,UAAU,WAAW,CAAI,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAGzG;IACC,MAAM,IAAI,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAyB,EAAE,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACnC,SAAS,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtO,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,OAAO;QACzC,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9C,MAAM,OAAO,GAA2B,EAAE,CAAC;YAAC,IAAI,KAAK,GAAG,CAAC,CAAC;YAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAI,KAAK,CAAC,MAAsB,CAAC,OAAO,CAAC,UAAW,CAAC;gBAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC;gBACzG,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI;oBAAE,SAAS;gBACjF,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,SAAS;oBAAE,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;gBAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC;gBAAC,IAAI,KAAK,EAAE,CAAC;oBAAC,EAAE,CAAC,SAAS,IAAI,KAAK,CAAC;oBAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;gBAAC,CAAC;YAAC,CAAC;QAC3I,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,gBAAgB,CAAc,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjG,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACjD,OAAO,eAAK,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAC/H,mCAAiB,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAI,EACtD,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,kCAA0D,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,YAAG,UAAU,CAAC,IAAI,CAAC,IAA/F,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,CAA0E,CAAC,EACjL,mCAAiB,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAI,IAClD,CAAC;AACT,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keenaioc/data-view",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "HomeYa shared data-view engine
|
|
3
|
+
"version": "0.2.0-alpha.8",
|
|
4
|
+
"description": "HomeYa shared data-view engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
@@ -10,27 +10,30 @@
|
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"types": "./index.d.ts",
|
|
14
|
-
"import": "./index.js"
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
15
|
},
|
|
16
|
-
"./
|
|
17
|
-
"types": "./react.d.ts",
|
|
18
|
-
"import": "./react.js"
|
|
19
|
-
},
|
|
20
|
-
"./style.css": "./style.css"
|
|
16
|
+
"./style.css": "./dist/style.css"
|
|
21
17
|
},
|
|
22
18
|
"files": [
|
|
23
19
|
"README.md",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
20
|
+
"CHANGELOG.md",
|
|
21
|
+
"INTEGRATION.md",
|
|
22
|
+
"KNOWN-LIMITATIONS.md",
|
|
23
|
+
"DATA-PRIVACY.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"dist"
|
|
29
26
|
],
|
|
30
27
|
"sideEffects": [
|
|
31
|
-
"
|
|
28
|
+
"./dist/style.css"
|
|
32
29
|
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "node scripts/build.mjs",
|
|
32
|
+
"test": "node --test tests/*.test.mjs",
|
|
33
|
+
"prepack": "npm run build && node ../../scripts/check-public-release.mjs",
|
|
34
|
+
"prepublishOnly": "node ../../scripts/check-public-release.mjs --built"
|
|
35
|
+
},
|
|
33
36
|
"peerDependencies": {
|
|
34
|
-
"react": "
|
|
37
|
+
"react": ">=18.2 <20"
|
|
35
38
|
}
|
|
36
39
|
}
|
package/index.d.ts
DELETED
package/index.js
DELETED
package/react.d.ts
DELETED
package/react.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {createElement, useState} from "react";
|
|
3
|
-
import {normalizeColumnWidth} from "./index.js";
|
|
4
|
-
// Feasibility probe only; not the final table component.
|
|
5
|
-
export function WidthProbe() {
|
|
6
|
-
const [width,setWidth]=useState(220);
|
|
7
|
-
return createElement("label",{className:"hy-width-probe"},"欄寬測試 ",createElement("input",{type:"number",value:width,min:56,max:600,onChange:e=>setWidth(normalizeColumnWidth(Number(e.target.value)))}));
|
|
8
|
-
}
|
package/style.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.hy-width-probe{display:block;font-size:1rem;color:#18334d}.hy-width-probe input{width:6rem;border:1px solid #64748b;padding:0.5rem}
|