@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.
Files changed (109) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/DATA-PRIVACY.md +20 -0
  3. package/INTEGRATION.md +178 -0
  4. package/KNOWN-LIMITATIONS.md +34 -0
  5. package/LICENSE +21 -0
  6. package/README.md +67 -5
  7. package/dist/contracts.d.ts +33 -0
  8. package/dist/contracts.d.ts.map +1 -0
  9. package/dist/contracts.js +83 -0
  10. package/dist/contracts.js.map +1 -0
  11. package/dist/data-view.d.ts +3 -0
  12. package/dist/data-view.d.ts.map +1 -0
  13. package/dist/data-view.js +822 -0
  14. package/dist/data-view.js.map +1 -0
  15. package/dist/engine.d.ts +34 -0
  16. package/dist/engine.d.ts.map +1 -0
  17. package/dist/engine.js +307 -0
  18. package/dist/engine.js.map +1 -0
  19. package/dist/gantt-bar.d.ts +17 -0
  20. package/dist/gantt-bar.d.ts.map +1 -0
  21. package/dist/gantt-bar.js +142 -0
  22. package/dist/gantt-bar.js.map +1 -0
  23. package/dist/gantt-dependencies.d.ts +27 -0
  24. package/dist/gantt-dependencies.d.ts.map +1 -0
  25. package/dist/gantt-dependencies.js +218 -0
  26. package/dist/gantt-dependencies.js.map +1 -0
  27. package/dist/gantt-dependency-ui.d.ts +37 -0
  28. package/dist/gantt-dependency-ui.d.ts.map +1 -0
  29. package/dist/gantt-dependency-ui.js +79 -0
  30. package/dist/gantt-dependency-ui.js.map +1 -0
  31. package/dist/gantt-grid.d.ts +27 -0
  32. package/dist/gantt-grid.d.ts.map +1 -0
  33. package/dist/gantt-grid.js +72 -0
  34. package/dist/gantt-grid.js.map +1 -0
  35. package/dist/gantt-operations.d.ts +14 -0
  36. package/dist/gantt-operations.d.ts.map +1 -0
  37. package/dist/gantt-operations.js +103 -0
  38. package/dist/gantt-operations.js.map +1 -0
  39. package/dist/index.d.ts +17 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +17 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/operations.d.ts +11 -0
  44. package/dist/operations.d.ts.map +1 -0
  45. package/dist/operations.js +117 -0
  46. package/dist/operations.js.map +1 -0
  47. package/dist/registry.d.ts +13 -0
  48. package/dist/registry.d.ts.map +1 -0
  49. package/dist/registry.js +465 -0
  50. package/dist/registry.js.map +1 -0
  51. package/dist/remote-data.d.ts +19 -0
  52. package/dist/remote-data.d.ts.map +1 -0
  53. package/dist/remote-data.js +67 -0
  54. package/dist/remote-data.js.map +1 -0
  55. package/dist/row-move.d.ts +7 -0
  56. package/dist/row-move.d.ts.map +1 -0
  57. package/dist/row-move.js +27 -0
  58. package/dist/row-move.js.map +1 -0
  59. package/dist/schedule-view.d.ts +27 -0
  60. package/dist/schedule-view.d.ts.map +1 -0
  61. package/dist/schedule-view.js +122 -0
  62. package/dist/schedule-view.js.map +1 -0
  63. package/dist/schedule.d.ts +28 -0
  64. package/dist/schedule.d.ts.map +1 -0
  65. package/dist/schedule.js +97 -0
  66. package/dist/schedule.js.map +1 -0
  67. package/dist/style.css +986 -0
  68. package/dist/timeline.d.ts +25 -0
  69. package/dist/timeline.d.ts.map +1 -0
  70. package/dist/timeline.js +58 -0
  71. package/dist/timeline.js.map +1 -0
  72. package/dist/toolbar.d.ts +10 -0
  73. package/dist/toolbar.d.ts.map +1 -0
  74. package/dist/toolbar.js +31 -0
  75. package/dist/toolbar.js.map +1 -0
  76. package/dist/types.d.ts +472 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +22 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/use-remote-data.d.ts +18 -0
  81. package/dist/use-remote-data.d.ts.map +1 -0
  82. package/dist/use-remote-data.js +12 -0
  83. package/dist/use-remote-data.js.map +1 -0
  84. package/dist/use-row-move.d.ts +12 -0
  85. package/dist/use-row-move.d.ts.map +1 -0
  86. package/dist/use-row-move.js +151 -0
  87. package/dist/use-row-move.js.map +1 -0
  88. package/dist/v2-panels.d.ts +37 -0
  89. package/dist/v2-panels.d.ts.map +1 -0
  90. package/dist/v2-panels.js +108 -0
  91. package/dist/v2-panels.js.map +1 -0
  92. package/dist/view-state.d.ts +30 -0
  93. package/dist/view-state.d.ts.map +1 -0
  94. package/dist/view-state.js +94 -0
  95. package/dist/view-state.js.map +1 -0
  96. package/dist/view-workspace.d.ts +3 -0
  97. package/dist/view-workspace.d.ts.map +1 -0
  98. package/dist/view-workspace.js +95 -0
  99. package/dist/view-workspace.js.map +1 -0
  100. package/dist/virtual-list.d.ts +12 -0
  101. package/dist/virtual-list.d.ts.map +1 -0
  102. package/dist/virtual-list.js +46 -0
  103. package/dist/virtual-list.js.map +1 -0
  104. package/package.json +19 -16
  105. package/index.d.ts +0 -2
  106. package/index.js +0 -5
  107. package/react.d.ts +0 -2
  108. package/react.js +0 -8
  109. 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,3 @@
1
+ import type { DataViewWorkspaceProps } from "./types.js";
2
+ export declare function DataViewWorkspace<Row>(props: DataViewWorkspaceProps<Row>): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=view-workspace.d.ts.map
@@ -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":"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"}
@@ -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":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@keenaioc/data-view",
3
- "version": "0.0.0-poc.1",
4
- "description": "HomeYa shared data-view engine (feasibility preview)",
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
- "./react": {
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
- "index.js",
25
- "index.d.ts",
26
- "react.js",
27
- "react.d.ts",
28
- "style.css"
20
+ "CHANGELOG.md",
21
+ "INTEGRATION.md",
22
+ "KNOWN-LIMITATIONS.md",
23
+ "DATA-PRIVACY.md",
24
+ "LICENSE",
25
+ "dist"
29
26
  ],
30
27
  "sideEffects": [
31
- "*.css"
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": "^19.0.0"
37
+ "react": ">=18.2 <20"
35
38
  }
36
39
  }
package/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare function normalizeColumnWidth(width: number): number;
2
- export declare const dataViewVersion: string;
package/index.js DELETED
@@ -1,5 +0,0 @@
1
- export function normalizeColumnWidth(width) {
2
- const finiteWidth = Number.isFinite(width) ? width : 56;
3
- return Math.min(600, Math.max(56, Math.round(finiteWidth)));
4
- }
5
- export const dataViewVersion = "0.0.0-poc.1";
package/react.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import type {ReactElement} from "react";
2
- export declare function WidthProbe(): ReactElement;
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}