@geomak/ui 7.14.0 → 7.15.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 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +72 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6537,6 +6537,7 @@ function DataGrid({
|
|
|
6537
6537
|
onInsertRow,
|
|
6538
6538
|
onDeleteRow,
|
|
6539
6539
|
onInsertColumn,
|
|
6540
|
+
onHeaderEdit,
|
|
6540
6541
|
className = "",
|
|
6541
6542
|
style,
|
|
6542
6543
|
emptyState = "No data"
|
|
@@ -6549,6 +6550,8 @@ function DataGrid({
|
|
|
6549
6550
|
const [ctxTarget, setCtxTarget] = React36.useState(null);
|
|
6550
6551
|
const [editing, setEditing] = React36.useState(null);
|
|
6551
6552
|
const [draft, setDraft] = React36.useState("");
|
|
6553
|
+
const [editingHeader, setEditingHeader] = React36.useState(null);
|
|
6554
|
+
const [headerDraft, setHeaderDraft] = React36.useState("");
|
|
6552
6555
|
const [internalSort, setInternalSort] = React36.useState(null);
|
|
6553
6556
|
const sort = sortProp !== void 0 ? sortProp : internalSort;
|
|
6554
6557
|
const gutter = rowNumbers ? GUTTER : 0;
|
|
@@ -6625,6 +6628,17 @@ function DataGrid({
|
|
|
6625
6628
|
setDraft(displayValue(rows[rowIndexForDisp(disp)]?.[c.key] ?? ""));
|
|
6626
6629
|
setEditing({ disp, col });
|
|
6627
6630
|
};
|
|
6631
|
+
const startHeaderEdit = (col) => {
|
|
6632
|
+
if (!onHeaderEdit) return;
|
|
6633
|
+
const c = cols[col];
|
|
6634
|
+
setHeaderDraft(typeof c.label === "string" ? c.label : String(c.key));
|
|
6635
|
+
setEditingHeader(col);
|
|
6636
|
+
};
|
|
6637
|
+
const commitHeader = () => {
|
|
6638
|
+
if (editingHeader == null) return;
|
|
6639
|
+
onHeaderEdit?.(editingHeader, headerDraft);
|
|
6640
|
+
setEditingHeader(null);
|
|
6641
|
+
};
|
|
6628
6642
|
const cellText = (sel) => displayValue(rows[rowIndexForDisp(sel.disp)]?.[cols[sel.col].key] ?? "");
|
|
6629
6643
|
const copyCell = React36.useCallback(async () => {
|
|
6630
6644
|
if (!selected) return;
|
|
@@ -6652,7 +6666,8 @@ function DataGrid({
|
|
|
6652
6666
|
if (ctxTarget?.kind === "header") {
|
|
6653
6667
|
const ci = ctxTarget.col;
|
|
6654
6668
|
return [
|
|
6655
|
-
{ key: "
|
|
6669
|
+
{ key: "rename", value: "Rename column", disabled: !onHeaderEdit, onClick: () => startHeaderEdit(ci) },
|
|
6670
|
+
{ key: "left", value: "Add column to the left", disabled: !onInsertColumn, separatorBefore: true, onClick: () => onInsertColumn?.(ci) },
|
|
6656
6671
|
{ key: "right", value: "Add column to the right", disabled: !onInsertColumn, onClick: () => onInsertColumn?.(ci + 1) }
|
|
6657
6672
|
];
|
|
6658
6673
|
}
|
|
@@ -6670,7 +6685,7 @@ function DataGrid({
|
|
|
6670
6685
|
{ key: "cut", value: "Cut", disabled: !editable, onClick: () => void cutCell() },
|
|
6671
6686
|
{ key: "paste", value: "Paste", disabled: !editable, onClick: () => void pasteCell() }
|
|
6672
6687
|
];
|
|
6673
|
-
}, [ctxTarget, rows.length, editable, onInsertRow, onDeleteRow, onInsertColumn, copyCell, cutCell, pasteCell, order]);
|
|
6688
|
+
}, [ctxTarget, rows.length, editable, onInsertRow, onDeleteRow, onInsertColumn, onHeaderEdit, copyCell, cutCell, pasteCell, order]);
|
|
6674
6689
|
const rowHighlighted = (disp) => hoveredRow === disp || selected?.disp === disp;
|
|
6675
6690
|
const gridInner = /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: gutter + totalWidth + END_PAD, height: headerHeight + totalHeight + END_PAD }, children: [
|
|
6676
6691
|
rowNumbers && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6684,16 +6699,20 @@ function DataGrid({
|
|
|
6684
6699
|
const c = cols[ci];
|
|
6685
6700
|
const sortDir = sort?.key === c.key ? sort.dir : null;
|
|
6686
6701
|
const canSort = colSortable(c);
|
|
6687
|
-
|
|
6702
|
+
const renamable = !!onHeaderEdit;
|
|
6703
|
+
const isEditingHeader = editingHeader === ci;
|
|
6704
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6688
6705
|
"div",
|
|
6689
6706
|
{
|
|
6690
6707
|
role: "columnheader",
|
|
6691
6708
|
"aria-sort": sortDir ? sortDir === "asc" ? "ascending" : "descending" : void 0,
|
|
6692
|
-
onClick: canSort ? () => toggleSort(c.key) : void 0,
|
|
6709
|
+
onClick: canSort && !renamable ? () => toggleSort(c.key) : void 0,
|
|
6710
|
+
onDoubleClick: renamable ? () => startHeaderEdit(ci) : void 0,
|
|
6693
6711
|
onContextMenu: contextMenu ? () => setCtxTarget({ kind: "header", col: ci }) : void 0,
|
|
6694
6712
|
className: cx(
|
|
6695
6713
|
"flex items-center gap-1 border-b border-r border-border bg-surface px-3 font-medium text-foreground-secondary",
|
|
6696
|
-
canSort && "cursor-pointer select-none hover:text-foreground"
|
|
6714
|
+
canSort && !renamable && "cursor-pointer select-none hover:text-foreground",
|
|
6715
|
+
renamable && "cursor-default select-none"
|
|
6697
6716
|
),
|
|
6698
6717
|
style: {
|
|
6699
6718
|
position: "absolute",
|
|
@@ -6704,10 +6723,27 @@ function DataGrid({
|
|
|
6704
6723
|
zIndex: 2,
|
|
6705
6724
|
justifyContent: c.align === "right" ? "flex-end" : c.align === "center" ? "center" : "flex-start"
|
|
6706
6725
|
},
|
|
6707
|
-
children:
|
|
6726
|
+
children: isEditingHeader ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6727
|
+
"input",
|
|
6728
|
+
{
|
|
6729
|
+
autoFocus: true,
|
|
6730
|
+
value: headerDraft,
|
|
6731
|
+
onChange: (e) => setHeaderDraft(e.target.value),
|
|
6732
|
+
onBlur: commitHeader,
|
|
6733
|
+
onClick: (e) => e.stopPropagation(),
|
|
6734
|
+
onKeyDown: (e) => {
|
|
6735
|
+
if (e.key === "Enter") commitHeader();
|
|
6736
|
+
else if (e.key === "Escape") setEditingHeader(null);
|
|
6737
|
+
},
|
|
6738
|
+
className: "h-full w-full bg-transparent font-medium text-foreground outline-none"
|
|
6739
|
+
}
|
|
6740
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6708
6741
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: c.label ?? c.key }),
|
|
6709
|
-
canSort && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6710
|
-
|
|
6742
|
+
canSort && (renamable ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", title: "Sort", onClick: (e) => {
|
|
6743
|
+
e.stopPropagation();
|
|
6744
|
+
toggleSort(c.key);
|
|
6745
|
+
}, className: "flex-shrink-0 rounded hover:text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(SortCaret, { dir: sortDir }) }) : /* @__PURE__ */ jsxRuntime.jsx(SortCaret, { dir: sortDir }))
|
|
6746
|
+
] })
|
|
6711
6747
|
},
|
|
6712
6748
|
`h-${c.key}`
|
|
6713
6749
|
);
|
|
@@ -6944,12 +6980,21 @@ function Spreadsheet({
|
|
|
6944
6980
|
const sheet = sheets?.[active];
|
|
6945
6981
|
const columns = React36.useMemo(() => sheet ? toColumns(sheet.columns) : [], [sheet]);
|
|
6946
6982
|
const plainRows = React36.useMemo(() => sheet ? toPlainRows(sheet, columns) : [], [sheet, columns]);
|
|
6983
|
+
const displayColumns = React36.useMemo(
|
|
6984
|
+
() => [...columns, ...makeColumns(columns, Math.max(0, emptyCols)).map((c) => ({ ...c, sortable: false }))],
|
|
6985
|
+
[columns, emptyCols]
|
|
6986
|
+
);
|
|
6987
|
+
const isSlackKey = (key) => !columns.some((c) => c.key === key);
|
|
6947
6988
|
const handleCellEdit = React36.useCallback(({ row, column, value }) => {
|
|
6948
6989
|
let coerced = value;
|
|
6949
6990
|
setSheets((prev) => {
|
|
6950
6991
|
if (!prev) return prev;
|
|
6951
|
-
const next = prev.map((s, i) => i === active ? { ...s, rows: s.rows.map((r) => ({ ...r })) } : s);
|
|
6992
|
+
const next = prev.map((s, i) => i === active ? { ...s, columns: toColumns(s.columns), rows: s.rows.map((r) => ({ ...r })) } : s);
|
|
6952
6993
|
const target = next[active];
|
|
6994
|
+
if (isSlackKey(column)) {
|
|
6995
|
+
const j = displayColumns.findIndex((c) => c.key === column);
|
|
6996
|
+
if (j >= 0) target.columns = displayColumns.slice(0, j + 1).map((c) => ({ key: c.key, label: c.label }));
|
|
6997
|
+
}
|
|
6953
6998
|
while (target.rows.length <= row) target.rows.push({});
|
|
6954
6999
|
const existing = target.rows[row]?.[column];
|
|
6955
7000
|
const prevValue = cellValue(existing);
|
|
@@ -6963,7 +7008,22 @@ function Spreadsheet({
|
|
|
6963
7008
|
return next;
|
|
6964
7009
|
});
|
|
6965
7010
|
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value: coerced });
|
|
6966
|
-
}, [active, onCellEdit, onChange, sheets]);
|
|
7011
|
+
}, [active, onCellEdit, onChange, sheets, displayColumns, columns]);
|
|
7012
|
+
const renameColumn = React36.useCallback((index, label) => {
|
|
7013
|
+
setSheets((prev) => {
|
|
7014
|
+
if (!prev) return prev;
|
|
7015
|
+
const next = prev.map((s, i) => i === active ? { ...s, columns: toColumns(s.columns) } : s);
|
|
7016
|
+
const target = next[active];
|
|
7017
|
+
let tcols = target.columns;
|
|
7018
|
+
if (index >= tcols.length) {
|
|
7019
|
+
tcols = displayColumns.slice(0, index + 1).map((c) => ({ key: c.key, label: c.label }));
|
|
7020
|
+
target.columns = tcols;
|
|
7021
|
+
}
|
|
7022
|
+
if (tcols[index]) tcols[index] = { ...tcols[index], label };
|
|
7023
|
+
onChange?.(next);
|
|
7024
|
+
return next;
|
|
7025
|
+
});
|
|
7026
|
+
}, [active, onChange, displayColumns]);
|
|
6967
7027
|
const addSheet = React36.useCallback(() => {
|
|
6968
7028
|
setSheets((prev) => {
|
|
6969
7029
|
const list = prev ?? [];
|
|
@@ -7181,17 +7241,17 @@ function Spreadsheet({
|
|
|
7181
7241
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7182
7242
|
DataGrid,
|
|
7183
7243
|
{
|
|
7184
|
-
columns,
|
|
7244
|
+
columns: displayColumns,
|
|
7185
7245
|
rows: plainRows,
|
|
7186
7246
|
editable,
|
|
7187
7247
|
sortable,
|
|
7188
7248
|
virtualize,
|
|
7189
7249
|
trailingRows: emptyRows,
|
|
7190
|
-
trailingCols: emptyCols,
|
|
7191
7250
|
contextMenu: true,
|
|
7192
7251
|
onInsertRow: editable ? insertRow : void 0,
|
|
7193
7252
|
onDeleteRow: editable ? deleteRow : void 0,
|
|
7194
7253
|
onInsertColumn: editable ? insertColumn : void 0,
|
|
7254
|
+
onHeaderEdit: editable ? renameColumn : void 0,
|
|
7195
7255
|
onCellEdit: handleCellEdit,
|
|
7196
7256
|
height: "100%",
|
|
7197
7257
|
className: "!rounded-none !border-0"
|