@pixerate/editor-react 0.17.0 → 0.18.1
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/README.md +3 -1
- package/dist/canvas/index.cjs +880 -193
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +214 -3
- package/dist/canvas/index.d.ts +214 -3
- package/dist/canvas/index.js +699 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-JR5ZBDR7.js → chunk-34HEZX7J.js} +206 -74
- package/dist/chunk-34HEZX7J.js.map +1 -0
- package/dist/index.cjs +1437 -1109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -5
- package/dist/index.d.ts +104 -5
- package/dist/index.js +350 -146
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +261 -135
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +39 -3
- package/dist/spreadsheet/index.d.ts +39 -3
- package/dist/spreadsheet/index.js +5 -3
- package/package.json +2 -2
- package/dist/chunk-JR5ZBDR7.js.map +0 -1
|
@@ -238,7 +238,7 @@ function useSpreadsheetEditor(options = {}) {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
// src/spreadsheet/SpreadsheetEditor.tsx
|
|
241
|
-
import { useRef as
|
|
241
|
+
import { useRef as useRef8, useState as useState8, useMemo as useMemo5, useEffect as useEffect6, useCallback as useCallback4 } from "react";
|
|
242
242
|
import {
|
|
243
243
|
indexToColName,
|
|
244
244
|
getSpreadsheetMenuItems,
|
|
@@ -328,6 +328,7 @@ var SpreadsheetContextMenu = ({ items, x, y, onClose, onOpenPanel, ariaLabel = "
|
|
|
328
328
|
};
|
|
329
329
|
|
|
330
330
|
// src/spreadsheet/SpreadsheetGroupRow.tsx
|
|
331
|
+
import React2 from "react";
|
|
331
332
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
332
333
|
var formatSummary = (value) => value === null ? "\u2013" : String(value);
|
|
333
334
|
var SpreadsheetGroupRow = ({
|
|
@@ -335,9 +336,14 @@ var SpreadsheetGroupRow = ({
|
|
|
335
336
|
columns,
|
|
336
337
|
groupColId,
|
|
337
338
|
onToggle,
|
|
338
|
-
trailingCell
|
|
339
|
+
trailingCell,
|
|
340
|
+
labelColumns = columns,
|
|
341
|
+
leadingColumns,
|
|
342
|
+
leftSpace = 0,
|
|
343
|
+
rightSpace = 0
|
|
339
344
|
}) => {
|
|
340
|
-
const labelColId =
|
|
345
|
+
const labelColId = labelColumns.some((c) => c.column.id === groupColId) ? groupColId : labelColumns[0]?.column.id;
|
|
346
|
+
const spacer = (key) => /* @__PURE__ */ jsx2("td", { "aria-hidden": "true", "data-spacer": "", style: { padding: 0 } }, key);
|
|
341
347
|
return /* @__PURE__ */ jsxs2("tr", { className: "border-b border-border bg-muted/40 font-semibold", "data-group-key": group.key, style: { height: 28 }, children: [
|
|
342
348
|
/* @__PURE__ */ jsx2("td", { className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted border-r border-border text-center", children: /* @__PURE__ */ jsx2(
|
|
343
349
|
"button",
|
|
@@ -353,18 +359,24 @@ var SpreadsheetGroupRow = ({
|
|
|
353
359
|
children: group.collapsed ? "\u25B8" : "\u25BE"
|
|
354
360
|
}
|
|
355
361
|
) }),
|
|
356
|
-
columns.map(({ column }) => {
|
|
362
|
+
columns.map(({ column }, i) => {
|
|
357
363
|
const summary = group.summaries[column.id];
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
/* @__PURE__ */
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
"
|
|
365
|
-
|
|
366
|
-
|
|
364
|
+
const before = leadingColumns !== void 0 && i === leadingColumns && leftSpace > 0 ? spacer("space:left") : null;
|
|
365
|
+
return /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
|
|
366
|
+
before,
|
|
367
|
+
/* @__PURE__ */ jsx2("td", { className: "border-r border-border px-2 py-1 truncate max-w-0 text-foreground", style: { maxWidth: 0, overflow: "hidden" }, children: column.id === labelColId ? /* @__PURE__ */ jsxs2("span", { className: "truncate", children: [
|
|
368
|
+
group.label,
|
|
369
|
+
" ",
|
|
370
|
+
/* @__PURE__ */ jsxs2("span", { className: "font-normal text-muted-foreground", children: [
|
|
371
|
+
"(",
|
|
372
|
+
group.rowIndices.length,
|
|
373
|
+
")"
|
|
374
|
+
] })
|
|
375
|
+
] }) : summary !== void 0 ? /* @__PURE__ */ jsx2("span", { className: "truncate", "data-summary": column.id, children: formatSummary(summary) }) : null })
|
|
376
|
+
] }, column.id);
|
|
367
377
|
}),
|
|
378
|
+
leadingColumns !== void 0 && leadingColumns >= columns.length && leftSpace > 0 && spacer("space:left"),
|
|
379
|
+
rightSpace > 0 && spacer("space:right"),
|
|
368
380
|
trailingCell && /* @__PURE__ */ jsx2("td", { className: "w-10 min-w-[2.5rem] bg-muted/10 border-r border-border" })
|
|
369
381
|
] });
|
|
370
382
|
};
|
|
@@ -768,25 +780,96 @@ var SpreadsheetDataValidationPanel = ({ state, onClose }) => {
|
|
|
768
780
|
] });
|
|
769
781
|
};
|
|
770
782
|
|
|
783
|
+
// src/spreadsheet/useSpreadsheetViewport.ts
|
|
784
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useRef as useRef5, useState as useState5 } from "react";
|
|
785
|
+
import {
|
|
786
|
+
fullSpreadsheetViewWindow,
|
|
787
|
+
getSpreadsheetScrollToCell,
|
|
788
|
+
getSpreadsheetViewWindow,
|
|
789
|
+
measureSpreadsheetView,
|
|
790
|
+
sameSpreadsheetViewWindow,
|
|
791
|
+
shouldVirtualizeSpreadsheet
|
|
792
|
+
} from "@pixerate/editor/spreadsheet";
|
|
793
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect2 : useEffect4;
|
|
794
|
+
function useSpreadsheetViewport(scrollRef, view, options = {}) {
|
|
795
|
+
const metrics = useMemo3(() => measureSpreadsheetView(view), [view]);
|
|
796
|
+
const virtual = shouldVirtualizeSpreadsheet(view, options.virtualize ?? "auto");
|
|
797
|
+
const [viewport, setViewport] = useState5({ scrollTop: 0, scrollLeft: 0, width: 0, height: 0 });
|
|
798
|
+
const windowOptions = useMemo3(
|
|
799
|
+
() => ({ merges: options.merges, overscanRows: options.overscanRows, overscanColumns: options.overscanColumns }),
|
|
800
|
+
[options.merges, options.overscanRows, options.overscanColumns]
|
|
801
|
+
);
|
|
802
|
+
const win = useMemo3(
|
|
803
|
+
() => virtual ? getSpreadsheetViewWindow(metrics, viewport, windowOptions) : fullSpreadsheetViewWindow(metrics),
|
|
804
|
+
[virtual, metrics, viewport, windowOptions]
|
|
805
|
+
);
|
|
806
|
+
const latest = useRef5({ metrics, viewport, virtual, windowOptions });
|
|
807
|
+
latest.current = { metrics, viewport, virtual, windowOptions };
|
|
808
|
+
const readViewport = useCallback3(() => {
|
|
809
|
+
const el = scrollRef.current;
|
|
810
|
+
if (!el) return null;
|
|
811
|
+
return { scrollTop: el.scrollTop, scrollLeft: el.scrollLeft, width: el.clientWidth, height: el.clientHeight };
|
|
812
|
+
}, [scrollRef]);
|
|
813
|
+
const updateViewport = useCallback3((next) => {
|
|
814
|
+
setViewport((prev) => {
|
|
815
|
+
const { metrics: m, virtual: v, windowOptions: o } = latest.current;
|
|
816
|
+
if (!v) return prev;
|
|
817
|
+
const same = prev.width === next.width && prev.height === next.height && sameSpreadsheetViewWindow(getSpreadsheetViewWindow(m, prev, o), getSpreadsheetViewWindow(m, next, o));
|
|
818
|
+
return same ? prev : next;
|
|
819
|
+
});
|
|
820
|
+
}, []);
|
|
821
|
+
const onScroll = useCallback3(() => {
|
|
822
|
+
const next = readViewport();
|
|
823
|
+
if (next) updateViewport(next);
|
|
824
|
+
}, [readViewport, updateViewport]);
|
|
825
|
+
useIsomorphicLayoutEffect(() => {
|
|
826
|
+
if (!virtual) return;
|
|
827
|
+
onScroll();
|
|
828
|
+
const el = scrollRef.current;
|
|
829
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
830
|
+
const observer = new ResizeObserver(() => onScroll());
|
|
831
|
+
observer.observe(el);
|
|
832
|
+
return () => observer.disconnect();
|
|
833
|
+
}, [virtual, onScroll, scrollRef]);
|
|
834
|
+
const activeRow = options.activeCell?.row;
|
|
835
|
+
const activeCol = options.activeCell?.col;
|
|
836
|
+
useIsomorphicLayoutEffect(() => {
|
|
837
|
+
if (!virtual || activeRow === void 0 || activeCol === void 0) return;
|
|
838
|
+
const el = scrollRef.current;
|
|
839
|
+
const current = latest.current.viewport;
|
|
840
|
+
const measured = readViewport();
|
|
841
|
+
const base = measured ? { ...measured, scrollTop: Math.max(measured.scrollTop, 0), scrollLeft: Math.max(measured.scrollLeft, 0) } : current;
|
|
842
|
+
const target = getSpreadsheetScrollToCell(latest.current.metrics, base, { row: activeRow, col: activeCol });
|
|
843
|
+
if (!target) return;
|
|
844
|
+
const next = { ...base, ...target };
|
|
845
|
+
if (el) {
|
|
846
|
+
if (target.scrollTop !== void 0) el.scrollTop = target.scrollTop;
|
|
847
|
+
if (target.scrollLeft !== void 0) el.scrollLeft = target.scrollLeft;
|
|
848
|
+
}
|
|
849
|
+
updateViewport(next);
|
|
850
|
+
}, [virtual, activeRow, activeCol]);
|
|
851
|
+
return { metrics, window: win, onScroll };
|
|
852
|
+
}
|
|
853
|
+
|
|
771
854
|
// src/spreadsheet/FormulaHints.tsx
|
|
772
|
-
import { useEffect as
|
|
855
|
+
import { useEffect as useEffect5, useLayoutEffect as useLayoutEffect3, useMemo as useMemo4, useRef as useRef6, useState as useState6 } from "react";
|
|
773
856
|
import { applyFormulaSuggestion, getFormulaHints } from "@pixerate/editor/spreadsheet";
|
|
774
857
|
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
775
858
|
var FormulaHints = ({ inputRef, value, onAccept, limit = 8, names }) => {
|
|
776
|
-
const [caret, setCaret] =
|
|
777
|
-
const [focused, setFocused] =
|
|
778
|
-
const [selected, setSelected] =
|
|
779
|
-
const [dismissed, setDismissed] =
|
|
780
|
-
const [position, setPosition] =
|
|
781
|
-
const pendingCaret =
|
|
782
|
-
const hints =
|
|
859
|
+
const [caret, setCaret] = useState6(null);
|
|
860
|
+
const [focused, setFocused] = useState6(false);
|
|
861
|
+
const [selected, setSelected] = useState6(0);
|
|
862
|
+
const [dismissed, setDismissed] = useState6(false);
|
|
863
|
+
const [position, setPosition] = useState6(null);
|
|
864
|
+
const pendingCaret = useRef6(null);
|
|
865
|
+
const hints = useMemo4(
|
|
783
866
|
() => getFormulaHints(value, caret ?? value.length, { limit, names }),
|
|
784
867
|
[value, caret, limit, names]
|
|
785
868
|
);
|
|
786
869
|
const suggestions = dismissed ? [] : hints.suggestions;
|
|
787
870
|
const selectedIndex = Math.max(0, Math.min(selected, suggestions.length - 1));
|
|
788
871
|
const visible = focused && value.trimStart().startsWith("=") && (suggestions.length > 0 || !!hints.activeCall);
|
|
789
|
-
const latest =
|
|
872
|
+
const latest = useRef6({ suggestions, selected: selectedIndex, value, caret, onAccept });
|
|
790
873
|
latest.current = { suggestions, selected: selectedIndex, value, caret, onAccept };
|
|
791
874
|
const accept = (index) => {
|
|
792
875
|
const { suggestions: list, value: current, caret: at, onAccept: commit } = latest.current;
|
|
@@ -796,7 +879,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8, names }) => {
|
|
|
796
879
|
pendingCaret.current = next.caret;
|
|
797
880
|
commit(next.value);
|
|
798
881
|
};
|
|
799
|
-
|
|
882
|
+
useEffect5(() => {
|
|
800
883
|
const input = inputRef.current;
|
|
801
884
|
if (!input) return;
|
|
802
885
|
const syncCaret = () => setCaret(input.selectionStart ?? input.value.length);
|
|
@@ -846,7 +929,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8, names }) => {
|
|
|
846
929
|
input.removeEventListener("keydown", onKeyDown);
|
|
847
930
|
};
|
|
848
931
|
}, [inputRef]);
|
|
849
|
-
|
|
932
|
+
useLayoutEffect3(() => {
|
|
850
933
|
const input = inputRef.current;
|
|
851
934
|
const at = pendingCaret.current;
|
|
852
935
|
if (!input || at === null || input.value !== value) return;
|
|
@@ -855,7 +938,7 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8, names }) => {
|
|
|
855
938
|
setCaret(at);
|
|
856
939
|
setSelected(0);
|
|
857
940
|
}, [value, inputRef]);
|
|
858
|
-
|
|
941
|
+
useLayoutEffect3(() => {
|
|
859
942
|
const input = inputRef.current;
|
|
860
943
|
if (!visible || !input) return;
|
|
861
944
|
const rect = input.getBoundingClientRect();
|
|
@@ -919,16 +1002,16 @@ var FormulaHints = ({ inputRef, value, onAccept, limit = 8, names }) => {
|
|
|
919
1002
|
};
|
|
920
1003
|
|
|
921
1004
|
// src/spreadsheet/SheetTabs.tsx
|
|
922
|
-
import { useRef as
|
|
1005
|
+
import { useRef as useRef7, useState as useState7 } from "react";
|
|
923
1006
|
import { getSheetTabMenuItems, sheetDropIndex } from "@pixerate/editor/spreadsheet";
|
|
924
1007
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
925
1008
|
var SheetTabs = ({ state, readOnly = false, className = "" }) => {
|
|
926
1009
|
const { controller, sheets } = state;
|
|
927
|
-
const [renaming, setRenaming] =
|
|
928
|
-
const [error, setError] =
|
|
929
|
-
const [menu, setMenu] =
|
|
930
|
-
const dragFrom =
|
|
931
|
-
const [dropTarget, setDropTarget] =
|
|
1010
|
+
const [renaming, setRenaming] = useState7(null);
|
|
1011
|
+
const [error, setError] = useState7(null);
|
|
1012
|
+
const [menu, setMenu] = useState7(null);
|
|
1013
|
+
const dragFrom = useRef7(null);
|
|
1014
|
+
const [dropTarget, setDropTarget] = useState7(null);
|
|
932
1015
|
const commitRename = (cancelOnError) => {
|
|
933
1016
|
if (!renaming) return;
|
|
934
1017
|
const sheet = sheets.find((s) => s.id === renaming.id);
|
|
@@ -1125,30 +1208,59 @@ var SpreadsheetEditor = ({
|
|
|
1125
1208
|
onAddColumnClick,
|
|
1126
1209
|
onColumnHeaderClick,
|
|
1127
1210
|
onColumnResize,
|
|
1128
|
-
showSheetTabs = false
|
|
1211
|
+
showSheetTabs = false,
|
|
1212
|
+
virtualize = "auto"
|
|
1129
1213
|
}) => {
|
|
1130
1214
|
const defaultState = useSpreadsheetEditor();
|
|
1131
1215
|
const state = externalState || defaultState;
|
|
1132
|
-
const gridRef =
|
|
1133
|
-
const
|
|
1134
|
-
const
|
|
1135
|
-
const
|
|
1136
|
-
const [
|
|
1137
|
-
const [
|
|
1138
|
-
const [
|
|
1216
|
+
const gridRef = useRef8(null);
|
|
1217
|
+
const scrollRef = useRef8(null);
|
|
1218
|
+
const formulaBarRef = useRef8(null);
|
|
1219
|
+
const cellInputRef = useRef8(null);
|
|
1220
|
+
const [resizingColId, setResizingColId] = useState8(null);
|
|
1221
|
+
const [hoveredColId, setHoveredColId] = useState8(null);
|
|
1222
|
+
const [resizeStartX, setResizeStartX] = useState8(0);
|
|
1223
|
+
const [resizeStartWidth, setResizeStartWidth] = useState8(0);
|
|
1139
1224
|
const view = state.viewModel;
|
|
1225
|
+
const { window: viewWindow, onScroll: handleGridScroll } = useSpreadsheetViewport(scrollRef, view, {
|
|
1226
|
+
virtualize,
|
|
1227
|
+
merges: state.document.table?.merges,
|
|
1228
|
+
activeCell: state.activeCell
|
|
1229
|
+
});
|
|
1230
|
+
const columnSlots = useMemo5(() => {
|
|
1231
|
+
const col = (viewCol) => ({ kind: "col", viewCol });
|
|
1232
|
+
if (!viewWindow.virtual) return view.columns.map(col);
|
|
1233
|
+
const slots = view.columns.slice(0, viewWindow.frozenColumns).map(col);
|
|
1234
|
+
if (viewWindow.leftSpace > 0) slots.push({ kind: "space", key: "space:left", width: viewWindow.leftSpace });
|
|
1235
|
+
for (let i = viewWindow.colStart; i < viewWindow.colEnd; i++) slots.push(col(view.columns[i]));
|
|
1236
|
+
if (viewWindow.rightSpace > 0) slots.push({ kind: "space", key: "space:right", width: viewWindow.rightSpace });
|
|
1237
|
+
return slots;
|
|
1238
|
+
}, [view, viewWindow]);
|
|
1239
|
+
const renderedColumns = useMemo5(
|
|
1240
|
+
() => columnSlots.flatMap((slot) => slot.kind === "col" ? [slot.viewCol] : []),
|
|
1241
|
+
[columnSlots]
|
|
1242
|
+
);
|
|
1243
|
+
const rowSlots = useMemo5(() => {
|
|
1244
|
+
const row = (viewRow) => ({ kind: "row", viewRow });
|
|
1245
|
+
if (!viewWindow.virtual) return view.rows.map(row);
|
|
1246
|
+
const slots = view.rows.slice(0, viewWindow.frozenRows).map(row);
|
|
1247
|
+
if (viewWindow.topSpace > 0) slots.push({ kind: "space", key: "space:top", height: viewWindow.topSpace });
|
|
1248
|
+
for (let i = viewWindow.rowStart; i < viewWindow.rowEnd; i++) slots.push(row(view.rows[i]));
|
|
1249
|
+
if (viewWindow.bottomSpace > 0) slots.push({ kind: "space", key: "space:bottom", height: viewWindow.bottomSpace });
|
|
1250
|
+
return slots;
|
|
1251
|
+
}, [view, viewWindow]);
|
|
1140
1252
|
const { copyShortcutFallback } = useSpreadsheetClipboard(gridRef, state, readOnly);
|
|
1141
1253
|
const { fillTarget, startFill, extendFill } = useFillHandle(state);
|
|
1142
|
-
const [menu, setMenu] =
|
|
1143
|
-
const [panel, setPanel] =
|
|
1144
|
-
const [listMenu, setListMenu] =
|
|
1254
|
+
const [menu, setMenu] = useState8(null);
|
|
1255
|
+
const [panel, setPanel] = useState8(null);
|
|
1256
|
+
const [listMenu, setListMenu] = useState8(null);
|
|
1145
1257
|
const overlay = state.conditionalFormatOverlay;
|
|
1146
1258
|
const filter = state.document.table?.filter;
|
|
1147
|
-
const filteredColIds =
|
|
1259
|
+
const filteredColIds = useMemo5(
|
|
1148
1260
|
() => new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []),
|
|
1149
1261
|
[filter]
|
|
1150
1262
|
);
|
|
1151
|
-
const handleCellContextMenu =
|
|
1263
|
+
const handleCellContextMenu = useCallback4((rIdx, cIdx, e) => {
|
|
1152
1264
|
if (readOnly) return;
|
|
1153
1265
|
e.preventDefault();
|
|
1154
1266
|
if (state.editingCell) state.commitEditing();
|
|
@@ -1157,33 +1269,33 @@ var SpreadsheetEditor = ({
|
|
|
1157
1269
|
}
|
|
1158
1270
|
setMenu({ x: e.clientX, y: e.clientY, items: getSpreadsheetMenuItems(state.controller, { row: rIdx, col: cIdx }) });
|
|
1159
1271
|
}, [readOnly, state]);
|
|
1160
|
-
const nameSuggestions =
|
|
1272
|
+
const nameSuggestions = useMemo5(
|
|
1161
1273
|
() => state.controller.getNameSuggestions(),
|
|
1162
1274
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1163
1275
|
[state.controller, state.document]
|
|
1164
1276
|
);
|
|
1165
|
-
const activeRawValue =
|
|
1277
|
+
const activeRawValue = useMemo5(() => {
|
|
1166
1278
|
if (!state.activeCell) return "";
|
|
1167
1279
|
const row = state.document.rows[state.activeCell.row];
|
|
1168
1280
|
const col = state.document.columns[state.activeCell.col];
|
|
1169
1281
|
if (!row || !col) return "";
|
|
1170
1282
|
return state.getCell(row.id, col.id).raw;
|
|
1171
1283
|
}, [state.activeCell, state.document]);
|
|
1172
|
-
const activeSpill =
|
|
1284
|
+
const activeSpill = useMemo5(
|
|
1173
1285
|
() => state.activeCell ? state.controller.getSpillAt(state.activeCell.row, state.activeCell.col) : null,
|
|
1174
1286
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1175
1287
|
[state.controller, state.activeCell, state.document]
|
|
1176
1288
|
);
|
|
1177
1289
|
const spillFormula = activeSpill && !activeRawValue && activeSpill.key !== coordKey(state.activeCell) ? activeSpill.formula : "";
|
|
1178
|
-
const coordLabel =
|
|
1290
|
+
const coordLabel = useMemo5(() => {
|
|
1179
1291
|
if (!state.activeCell) return "--";
|
|
1180
1292
|
const colName = indexToColName(state.activeCell.col);
|
|
1181
1293
|
return `${colName}${state.activeCell.row + 1}`;
|
|
1182
1294
|
}, [state.activeCell]);
|
|
1183
|
-
const [formulaDraft, setFormulaDraft] =
|
|
1295
|
+
const [formulaDraft, setFormulaDraft] = useState8(null);
|
|
1184
1296
|
const activeColumn = state.activeCell ? state.document.columns[state.activeCell.col] : void 0;
|
|
1185
1297
|
const formulaBarReadOnly = readOnly || !state.activeCell || !!activeColumn?.readOnly;
|
|
1186
|
-
|
|
1298
|
+
useEffect6(() => {
|
|
1187
1299
|
setFormulaDraft(null);
|
|
1188
1300
|
}, [state.activeCell?.row, state.activeCell?.col]);
|
|
1189
1301
|
const commitFormulaBar = () => {
|
|
@@ -1199,19 +1311,19 @@ var SpreadsheetEditor = ({
|
|
|
1199
1311
|
}
|
|
1200
1312
|
setFormulaDraft(null);
|
|
1201
1313
|
};
|
|
1202
|
-
const handleCellClick =
|
|
1314
|
+
const handleCellClick = useCallback4((rIdx, cIdx, e) => {
|
|
1203
1315
|
if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
|
|
1204
1316
|
state.commitEditing();
|
|
1205
1317
|
}
|
|
1206
1318
|
state.selectCell(rIdx, cIdx, e.shiftKey);
|
|
1207
1319
|
}, [state]);
|
|
1208
|
-
const handleCellDblClick =
|
|
1320
|
+
const handleCellDblClick = useCallback4((rIdx, cIdx) => {
|
|
1209
1321
|
if (readOnly) return;
|
|
1210
1322
|
const col = state.document.columns[cIdx];
|
|
1211
1323
|
if (col?.readOnly) return;
|
|
1212
1324
|
state.startEditing(rIdx, cIdx);
|
|
1213
1325
|
}, [readOnly, state]);
|
|
1214
|
-
const handleKeyDown =
|
|
1326
|
+
const handleKeyDown = useCallback4((e) => {
|
|
1215
1327
|
if (state.editingCell) {
|
|
1216
1328
|
if (e.key === "Enter") {
|
|
1217
1329
|
e.preventDefault();
|
|
@@ -1283,12 +1395,12 @@ var SpreadsheetEditor = ({
|
|
|
1283
1395
|
}
|
|
1284
1396
|
}
|
|
1285
1397
|
}, [readOnly, state, copyShortcutFallback]);
|
|
1286
|
-
const activeListValues =
|
|
1398
|
+
const activeListValues = useMemo5(
|
|
1287
1399
|
() => state.activeCell && !readOnly ? state.controller.getValidationListValues(state.activeCell.row, state.activeCell.col) : null,
|
|
1288
1400
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1289
1401
|
[state.controller, state.activeCell, state.document, readOnly]
|
|
1290
1402
|
);
|
|
1291
|
-
const activeRule =
|
|
1403
|
+
const activeRule = useMemo5(
|
|
1292
1404
|
() => state.activeCell ? state.controller.getDataValidationAt(state.activeCell.row, state.activeCell.col) : void 0,
|
|
1293
1405
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1294
1406
|
[state.controller, state.activeCell, state.document]
|
|
@@ -1302,7 +1414,7 @@ var SpreadsheetEditor = ({
|
|
|
1302
1414
|
const rect = td?.getBoundingClientRect();
|
|
1303
1415
|
setListMenu({ x: rect ? rect.left : 0, y: rect ? rect.bottom : 0, row, col, values });
|
|
1304
1416
|
}
|
|
1305
|
-
|
|
1417
|
+
useEffect6(() => {
|
|
1306
1418
|
if (!listMenu) return;
|
|
1307
1419
|
const close = (e) => {
|
|
1308
1420
|
if (!e.target?.closest?.('[aria-label="Allowed values"], .spreadsheet-list-arrow')) setListMenu(null);
|
|
@@ -1325,11 +1437,11 @@ var SpreadsheetEditor = ({
|
|
|
1325
1437
|
else gridRef.current?.focus();
|
|
1326
1438
|
});
|
|
1327
1439
|
};
|
|
1328
|
-
const stateRef =
|
|
1440
|
+
const stateRef = useRef8(state);
|
|
1329
1441
|
stateRef.current = state;
|
|
1330
|
-
const onColumnResizeRef =
|
|
1442
|
+
const onColumnResizeRef = useRef8(onColumnResize);
|
|
1331
1443
|
onColumnResizeRef.current = onColumnResize;
|
|
1332
|
-
|
|
1444
|
+
useEffect6(() => {
|
|
1333
1445
|
if (!resizingColId) return;
|
|
1334
1446
|
if (typeof document !== "undefined") {
|
|
1335
1447
|
document.body.style.cursor = "col-resize";
|
|
@@ -1380,7 +1492,7 @@ var SpreadsheetEditor = ({
|
|
|
1380
1492
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
1381
1493
|
};
|
|
1382
1494
|
}, [resizingColId, resizeStartX, resizeStartWidth]);
|
|
1383
|
-
const measureElementContentWidth =
|
|
1495
|
+
const measureElementContentWidth = useCallback4((el, container) => {
|
|
1384
1496
|
if (typeof document === "undefined") return 0;
|
|
1385
1497
|
let maxW = el.scrollWidth || 0;
|
|
1386
1498
|
const firstChild = el.firstElementChild;
|
|
@@ -1428,7 +1540,7 @@ var SpreadsheetEditor = ({
|
|
|
1428
1540
|
}
|
|
1429
1541
|
return maxW;
|
|
1430
1542
|
}, []);
|
|
1431
|
-
const autoFitColumn =
|
|
1543
|
+
const autoFitColumn = useCallback4((colId, colIndex) => {
|
|
1432
1544
|
const col = state.document.columns.find((c) => c.id === colId);
|
|
1433
1545
|
if (!col) return;
|
|
1434
1546
|
let calculatedWidth = 0;
|
|
@@ -1464,12 +1576,12 @@ var SpreadsheetEditor = ({
|
|
|
1464
1576
|
onColumnResize(updatedCol.id, updatedCol.width || 130);
|
|
1465
1577
|
}
|
|
1466
1578
|
}, [state, measureElementContentWidth, onColumnResize]);
|
|
1467
|
-
const handleResizeDblClick =
|
|
1579
|
+
const handleResizeDblClick = useCallback4((colId, colIndex, e) => {
|
|
1468
1580
|
e.preventDefault();
|
|
1469
1581
|
e.stopPropagation();
|
|
1470
1582
|
autoFitColumn(colId, colIndex);
|
|
1471
1583
|
}, [autoFitColumn]);
|
|
1472
|
-
const handleHeaderDblClick =
|
|
1584
|
+
const handleHeaderDblClick = useCallback4((colId, colIndex, e) => {
|
|
1473
1585
|
const target = e.currentTarget;
|
|
1474
1586
|
if (target) {
|
|
1475
1587
|
const rect = target.getBoundingClientRect();
|
|
@@ -1554,10 +1666,19 @@ var SpreadsheetEditor = ({
|
|
|
1554
1666
|
inputMessage.inputTitle && /* @__PURE__ */ jsx7("span", { className: "mr-1 font-semibold text-foreground", children: inputMessage.inputTitle }),
|
|
1555
1667
|
inputMessage.inputMessage
|
|
1556
1668
|
] }),
|
|
1557
|
-
/* @__PURE__ */ jsx7("div", { className: "relative flex-1 overflow-auto", children: /* @__PURE__ */ jsxs7("table", { className: "border-
|
|
1669
|
+
/* @__PURE__ */ jsx7("div", { ref: scrollRef, className: "relative flex-1 overflow-auto", onScroll: handleGridScroll, children: /* @__PURE__ */ jsxs7("table", { className: "border-separate border-spacing-0 table-fixed w-max min-w-full [&>*>tr:not([data-spacer])>*]:border-b [&>*>tr>*]:border-border", children: [
|
|
1558
1670
|
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs7("tr", { className: "h-7 bg-muted sticky top-0 z-20 border-b border-border shadow-xs", children: [
|
|
1559
1671
|
/* @__PURE__ */ jsx7("th", { className: "w-12 min-w-[3rem] sticky left-0 z-30 bg-muted border-r border-border text-center text-[10px] text-muted-foreground font-medium", children: "#" }),
|
|
1560
|
-
|
|
1672
|
+
columnSlots.map((slot) => slot.kind === "space" ? /* @__PURE__ */ jsx7(
|
|
1673
|
+
"th",
|
|
1674
|
+
{
|
|
1675
|
+
"aria-hidden": "true",
|
|
1676
|
+
"data-spacer": "",
|
|
1677
|
+
className: "p-0",
|
|
1678
|
+
style: { width: slot.width, minWidth: slot.width, maxWidth: slot.width, padding: 0 }
|
|
1679
|
+
},
|
|
1680
|
+
slot.key
|
|
1681
|
+
) : (({ column: col, index: cIdx, frozen, stickyLeft }) => /* @__PURE__ */ jsxs7(
|
|
1561
1682
|
"th",
|
|
1562
1683
|
{
|
|
1563
1684
|
"data-col": cIdx,
|
|
@@ -1616,7 +1737,7 @@ var SpreadsheetEditor = ({
|
|
|
1616
1737
|
]
|
|
1617
1738
|
},
|
|
1618
1739
|
col.id
|
|
1619
|
-
)),
|
|
1740
|
+
))(slot.viewCol)),
|
|
1620
1741
|
onAddColumnClick && /* @__PURE__ */ jsx7(
|
|
1621
1742
|
"th",
|
|
1622
1743
|
{
|
|
@@ -1627,13 +1748,21 @@ var SpreadsheetEditor = ({
|
|
|
1627
1748
|
}
|
|
1628
1749
|
)
|
|
1629
1750
|
] }) }),
|
|
1630
|
-
/* @__PURE__ */ jsx7("tbody", { children:
|
|
1751
|
+
/* @__PURE__ */ jsx7("tbody", { children: rowSlots.map((rowSlot) => {
|
|
1752
|
+
if (rowSlot.kind === "space") {
|
|
1753
|
+
return /* @__PURE__ */ jsx7("tr", { "aria-hidden": "true", "data-spacer": "", style: { height: rowSlot.height }, children: /* @__PURE__ */ jsx7("td", { colSpan: columnSlots.length + 2, style: { padding: 0, border: 0 } }) }, rowSlot.key);
|
|
1754
|
+
}
|
|
1755
|
+
const viewRow = rowSlot.viewRow;
|
|
1631
1756
|
if (viewRow.kind === "group") {
|
|
1632
1757
|
return /* @__PURE__ */ jsx7(
|
|
1633
1758
|
SpreadsheetGroupRow,
|
|
1634
1759
|
{
|
|
1635
1760
|
group: viewRow.group,
|
|
1636
|
-
columns:
|
|
1761
|
+
columns: renderedColumns,
|
|
1762
|
+
labelColumns: view.columns,
|
|
1763
|
+
leadingColumns: viewWindow.virtual ? viewWindow.frozenColumns : void 0,
|
|
1764
|
+
leftSpace: viewWindow.leftSpace,
|
|
1765
|
+
rightSpace: viewWindow.rightSpace,
|
|
1637
1766
|
groupColId: state.document.table?.grouping?.colId ?? "",
|
|
1638
1767
|
onToggle: state.toggleGroupCollapsed,
|
|
1639
1768
|
trailingCell: !!onAddColumnClick
|
|
@@ -1658,7 +1787,9 @@ var SpreadsheetEditor = ({
|
|
|
1658
1787
|
children: displayRowIndex + 1
|
|
1659
1788
|
}
|
|
1660
1789
|
),
|
|
1661
|
-
|
|
1790
|
+
columnSlots.map((slot) => {
|
|
1791
|
+
if (slot.kind === "space") return /* @__PURE__ */ jsx7("td", { "aria-hidden": "true", "data-spacer": "", style: { padding: 0 } }, slot.key);
|
|
1792
|
+
const viewCol = slot.viewCol;
|
|
1662
1793
|
const span = view.getCellSpan(displayRowIndex, viewCol.index);
|
|
1663
1794
|
if (!span) return null;
|
|
1664
1795
|
const rIdx = span.source.row;
|
|
@@ -1841,19 +1972,19 @@ var SpreadsheetEditor = ({
|
|
|
1841
1972
|
};
|
|
1842
1973
|
|
|
1843
1974
|
// src/spreadsheet/NameManager.tsx
|
|
1844
|
-
import { useMemo as
|
|
1975
|
+
import { useMemo as useMemo6, useState as useState9 } from "react";
|
|
1845
1976
|
import { getNameManagerRows, parseFormula } from "@pixerate/editor/spreadsheet";
|
|
1846
1977
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1847
1978
|
var EMPTY_DRAFT = { original: null, name: "", refersTo: "=", scope: "", comment: "" };
|
|
1848
1979
|
var NameManager = ({ state, readOnly = false, onClose, className = "" }) => {
|
|
1849
1980
|
const { controller, sheets } = state;
|
|
1850
|
-
const rows =
|
|
1981
|
+
const rows = useMemo6(
|
|
1851
1982
|
() => getNameManagerRows(controller),
|
|
1852
1983
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1853
1984
|
[controller, state.document, state.names]
|
|
1854
1985
|
);
|
|
1855
|
-
const [draft, setDraft] =
|
|
1856
|
-
const [error, setError] =
|
|
1986
|
+
const [draft, setDraft] = useState9(EMPTY_DRAFT);
|
|
1987
|
+
const [error, setError] = useState9(null);
|
|
1857
1988
|
const edit = (row) => {
|
|
1858
1989
|
setError(null);
|
|
1859
1990
|
setDraft({
|
|
@@ -2004,9 +2135,10 @@ export {
|
|
|
2004
2135
|
SpreadsheetValidationDialog,
|
|
2005
2136
|
SpreadsheetConditionalFormatPanel,
|
|
2006
2137
|
SpreadsheetDataValidationPanel,
|
|
2138
|
+
useSpreadsheetViewport,
|
|
2007
2139
|
FormulaHints,
|
|
2008
2140
|
SheetTabs,
|
|
2009
2141
|
SpreadsheetEditor,
|
|
2010
2142
|
NameManager
|
|
2011
2143
|
};
|
|
2012
|
-
//# sourceMappingURL=chunk-
|
|
2144
|
+
//# sourceMappingURL=chunk-34HEZX7J.js.map
|