@geomak/ui 7.10.0 → 7.11.0
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/index.cjs +72 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +72 -23
- package/dist/index.js.map +1 -1
- package/dist/styles.css +9 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6503,6 +6503,7 @@ function DataGrid({
|
|
|
6503
6503
|
virtualize = true,
|
|
6504
6504
|
overscan = 4,
|
|
6505
6505
|
rowNumbers = true,
|
|
6506
|
+
trailingRows = 0,
|
|
6506
6507
|
onCellEdit,
|
|
6507
6508
|
className = "",
|
|
6508
6509
|
style,
|
|
@@ -6539,7 +6540,9 @@ function DataGrid({
|
|
|
6539
6540
|
if (sortProp === void 0) setInternalSort(next);
|
|
6540
6541
|
onSortChange?.(next);
|
|
6541
6542
|
};
|
|
6542
|
-
const
|
|
6543
|
+
const displayRowCount = rows.length + Math.max(0, trailingRows);
|
|
6544
|
+
const totalHeight = displayRowCount * rowHeight;
|
|
6545
|
+
const rowIndexForDisp = (disp) => disp < rows.length ? order[disp] : disp;
|
|
6543
6546
|
React36.useEffect(() => {
|
|
6544
6547
|
const el = scrollRef.current;
|
|
6545
6548
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
@@ -6551,7 +6554,7 @@ function DataGrid({
|
|
|
6551
6554
|
}, []);
|
|
6552
6555
|
const bodyH = (viewport.h || (typeof height === "number" ? height : 480)) - headerHeight;
|
|
6553
6556
|
const rowStart = virtualize ? Math.max(0, Math.floor(scroll.top / rowHeight) - overscan) : 0;
|
|
6554
|
-
const rowEnd = virtualize ? Math.min(
|
|
6557
|
+
const rowEnd = virtualize ? Math.min(displayRowCount, Math.ceil((scroll.top + bodyH) / rowHeight) + overscan) : displayRowCount;
|
|
6555
6558
|
let colStart = 0;
|
|
6556
6559
|
let colEnd = columns.length;
|
|
6557
6560
|
if (virtualize && viewport.w) {
|
|
@@ -6569,13 +6572,14 @@ function DataGrid({
|
|
|
6569
6572
|
const commit = React36.useCallback(() => {
|
|
6570
6573
|
if (!editing) return;
|
|
6571
6574
|
const col = columns[editing.col];
|
|
6572
|
-
|
|
6575
|
+
const ri = editing.disp < rows.length ? order[editing.disp] : editing.disp;
|
|
6576
|
+
onCellEdit?.({ row: ri, column: col.key, value: draft });
|
|
6573
6577
|
setEditing(null);
|
|
6574
|
-
}, [editing, columns, draft, onCellEdit, order]);
|
|
6578
|
+
}, [editing, columns, draft, onCellEdit, order, rows.length]);
|
|
6575
6579
|
const startEdit = (disp, col) => {
|
|
6576
6580
|
const c = columns[col];
|
|
6577
6581
|
if (!(c.editable ?? editable)) return;
|
|
6578
|
-
setDraft(displayValue(rows[
|
|
6582
|
+
setDraft(displayValue(rows[rowIndexForDisp(disp)]?.[c.key] ?? ""));
|
|
6579
6583
|
setEditing({ disp, col });
|
|
6580
6584
|
};
|
|
6581
6585
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6638,7 +6642,7 @@ function DataGrid({
|
|
|
6638
6642
|
`g-${disp}`
|
|
6639
6643
|
)),
|
|
6640
6644
|
visibleRows.map((disp) => {
|
|
6641
|
-
const ri =
|
|
6645
|
+
const ri = rowIndexForDisp(disp);
|
|
6642
6646
|
return visibleCols.map((ci) => {
|
|
6643
6647
|
const c = columns[ci];
|
|
6644
6648
|
const isEditing = editing?.disp === disp && editing?.col === ci;
|
|
@@ -6681,7 +6685,7 @@ function DataGrid({
|
|
|
6681
6685
|
});
|
|
6682
6686
|
})
|
|
6683
6687
|
] }),
|
|
6684
|
-
|
|
6688
|
+
displayRowCount === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-foreground-muted", style: { top: headerHeight }, children: emptyState })
|
|
6685
6689
|
]
|
|
6686
6690
|
}
|
|
6687
6691
|
);
|
|
@@ -6699,6 +6703,18 @@ function cellValue(v) {
|
|
|
6699
6703
|
if (v != null && typeof v === "object" && "value" in v) return v.value;
|
|
6700
6704
|
return v;
|
|
6701
6705
|
}
|
|
6706
|
+
function columnLetter(i) {
|
|
6707
|
+
let s = "";
|
|
6708
|
+
let n = i;
|
|
6709
|
+
do {
|
|
6710
|
+
s = String.fromCharCode(65 + n % 26) + s;
|
|
6711
|
+
n = Math.floor(n / 26) - 1;
|
|
6712
|
+
} while (n >= 0);
|
|
6713
|
+
return s;
|
|
6714
|
+
}
|
|
6715
|
+
function blankSheet(name, cols = 8) {
|
|
6716
|
+
return { name, columns: Array.from({ length: cols }, (_, i) => ({ key: columnLetter(i), label: columnLetter(i) })), rows: [] };
|
|
6717
|
+
}
|
|
6702
6718
|
function toPlainRows(sheet, columns) {
|
|
6703
6719
|
return sheet.rows.map((row) => {
|
|
6704
6720
|
const out = {};
|
|
@@ -6731,11 +6747,14 @@ function Spreadsheet({
|
|
|
6731
6747
|
fileName,
|
|
6732
6748
|
virtualize = true,
|
|
6733
6749
|
sortable = true,
|
|
6750
|
+
emptyRows = 50,
|
|
6751
|
+
allowAddSheet,
|
|
6734
6752
|
height = 480,
|
|
6735
6753
|
width,
|
|
6736
6754
|
className = "",
|
|
6737
6755
|
style
|
|
6738
6756
|
}) {
|
|
6757
|
+
const canAddSheet = allowAddSheet ?? editable;
|
|
6739
6758
|
const [sheets, setSheets] = React36.useState(Array.isArray(source) ? source : null);
|
|
6740
6759
|
const [active, setActive] = React36.useState(0);
|
|
6741
6760
|
const [status, setStatus] = React36.useState(Array.isArray(source) ? "ready" : "loading");
|
|
@@ -6795,6 +6814,7 @@ function Spreadsheet({
|
|
|
6795
6814
|
if (!prev) return prev;
|
|
6796
6815
|
const next = prev.map((s, i) => i === active ? { ...s, rows: s.rows.map((r) => ({ ...r })) } : s);
|
|
6797
6816
|
const target = next[active];
|
|
6817
|
+
while (target.rows.length <= row) target.rows.push({});
|
|
6798
6818
|
const existing = target.rows[row]?.[column];
|
|
6799
6819
|
const prevValue = cellValue(existing);
|
|
6800
6820
|
coerced = coerceToCellType(prevValue, value);
|
|
@@ -6808,6 +6828,18 @@ function Spreadsheet({
|
|
|
6808
6828
|
});
|
|
6809
6829
|
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value: coerced });
|
|
6810
6830
|
}, [active, onCellEdit, onChange, sheets]);
|
|
6831
|
+
const addSheet = React36.useCallback(() => {
|
|
6832
|
+
setSheets((prev) => {
|
|
6833
|
+
const list = prev ?? [];
|
|
6834
|
+
const used = new Set(list.map((s) => s.name));
|
|
6835
|
+
let n = list.length + 1;
|
|
6836
|
+
while (used.has(`Sheet ${n}`)) n++;
|
|
6837
|
+
const next = [...list, blankSheet(`Sheet ${n}`)];
|
|
6838
|
+
setActive(next.length - 1);
|
|
6839
|
+
onChange?.(next);
|
|
6840
|
+
return next;
|
|
6841
|
+
});
|
|
6842
|
+
}, [onChange]);
|
|
6811
6843
|
const baseName = React36.useMemo(
|
|
6812
6844
|
() => (fileName || (typeof source === "object" && "name" in source ? sourceName(source) : null) || "spreadsheet").replace(/\.[^.]+$/, ""),
|
|
6813
6845
|
[fileName, source]
|
|
@@ -6936,28 +6968,45 @@ function Spreadsheet({
|
|
|
6936
6968
|
editable,
|
|
6937
6969
|
sortable,
|
|
6938
6970
|
virtualize,
|
|
6971
|
+
trailingRows: emptyRows,
|
|
6939
6972
|
onCellEdit: handleCellEdit,
|
|
6940
6973
|
height: "100%",
|
|
6941
6974
|
className: "!rounded-none !border-0"
|
|
6942
6975
|
},
|
|
6943
6976
|
active
|
|
6944
6977
|
) }),
|
|
6945
|
-
sheets.length > 1 && /* @__PURE__ */ jsxRuntime.
|
|
6946
|
-
"
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6978
|
+
(sheets.length > 1 || canAddSheet) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-shrink-0 items-center gap-1 border-t border-border bg-surface px-2 py-1", children: [
|
|
6979
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto", children: sheets.map((s, i) => {
|
|
6980
|
+
const activeTab = i === active;
|
|
6981
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6982
|
+
"button",
|
|
6983
|
+
{
|
|
6984
|
+
role: "tab",
|
|
6985
|
+
type: "button",
|
|
6986
|
+
"aria-selected": activeTab,
|
|
6987
|
+
onClick: () => setActive(i),
|
|
6988
|
+
className: cx(
|
|
6989
|
+
"flex-shrink-0 rounded-t-md border-t-2 px-3 py-1 text-xs transition-colors",
|
|
6990
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
6991
|
+
activeTab ? "border-t-accent bg-surface-raised font-semibold text-foreground shadow-sm" : "border-t-transparent font-medium text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
|
|
6992
|
+
),
|
|
6993
|
+
children: s.name || `Sheet ${i + 1}`
|
|
6994
|
+
},
|
|
6995
|
+
`${s.name}-${i}`
|
|
6996
|
+
);
|
|
6997
|
+
}) }),
|
|
6998
|
+
canAddSheet && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6999
|
+
"button",
|
|
7000
|
+
{
|
|
7001
|
+
type: "button",
|
|
7002
|
+
onClick: addSheet,
|
|
7003
|
+
title: "Add sheet",
|
|
7004
|
+
"aria-label": "Add sheet",
|
|
7005
|
+
className: "flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md text-foreground-muted transition-colors hover:bg-surface-raised hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
7006
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M12 5v14M5 12h14" }) })
|
|
7007
|
+
}
|
|
7008
|
+
)
|
|
7009
|
+
] })
|
|
6961
7010
|
] });
|
|
6962
7011
|
}
|
|
6963
7012
|
var DownloadIcon2 = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
|