@pixerate/editor-react 0.10.1 → 0.10.2
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 +67 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +74 -51
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -223,7 +223,7 @@ declare function useSpreadsheetEditor(options?: SpreadsheetControllerOptions): {
|
|
|
223
223
|
registerDataSource: (ds: SpreadsheetDataSource) => void;
|
|
224
224
|
setPrimaryDataSource: (id: string | undefined) => void;
|
|
225
225
|
recalculateAll: () => void;
|
|
226
|
-
exportToTsv: () => string;
|
|
226
|
+
exportToTsv: (range?: CellRange | null) => string;
|
|
227
227
|
importFromTsv: (data: string) => void;
|
|
228
228
|
undo: () => void;
|
|
229
229
|
redo: () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -223,7 +223,7 @@ declare function useSpreadsheetEditor(options?: SpreadsheetControllerOptions): {
|
|
|
223
223
|
registerDataSource: (ds: SpreadsheetDataSource) => void;
|
|
224
224
|
setPrimaryDataSource: (id: string | undefined) => void;
|
|
225
225
|
recalculateAll: () => void;
|
|
226
|
-
exportToTsv: () => string;
|
|
226
|
+
exportToTsv: (range?: CellRange | null) => string;
|
|
227
227
|
importFromTsv: (data: string) => void;
|
|
228
228
|
undo: () => void;
|
|
229
229
|
redo: () => void;
|
package/dist/index.js
CHANGED
|
@@ -616,41 +616,37 @@ import {
|
|
|
616
616
|
} from "@pixerate/editor";
|
|
617
617
|
|
|
618
618
|
// src/spreadsheet/useSpreadsheetEditor.ts
|
|
619
|
-
import { useState as useState4,
|
|
619
|
+
import { useState as useState4, useRef as useRef5, useCallback as useCallback4 } from "react";
|
|
620
620
|
import {
|
|
621
621
|
SpreadsheetController
|
|
622
622
|
} from "@pixerate/editor";
|
|
623
623
|
function useSpreadsheetEditor(options = {}) {
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
cells: options.document?.cells || {},
|
|
630
|
-
createdAt: options.document?.createdAt || Date.now(),
|
|
631
|
-
updatedAt: options.document?.updatedAt || Date.now()
|
|
632
|
-
}));
|
|
633
|
-
const [activeCell, setActiveCell] = useState4(null);
|
|
634
|
-
const [selectedRange, setSelectedRange] = useState4(null);
|
|
635
|
-
const [editingCell, setEditingCell] = useState4(null);
|
|
636
|
-
const [draftValue, setDraftValue] = useState4("");
|
|
637
|
-
const controller = useMemo4(() => {
|
|
638
|
-
return new SpreadsheetController({
|
|
624
|
+
const optionsRef = useRef5(options);
|
|
625
|
+
optionsRef.current = options;
|
|
626
|
+
const settersRef = useRef5({});
|
|
627
|
+
const [controller] = useState4(
|
|
628
|
+
() => new SpreadsheetController({
|
|
639
629
|
...options,
|
|
640
630
|
onDocumentChange: (updated) => {
|
|
641
|
-
setDoc({ ...updated });
|
|
642
|
-
|
|
631
|
+
settersRef.current.setDoc?.({ ...updated });
|
|
632
|
+
optionsRef.current.onDocumentChange?.(updated);
|
|
643
633
|
},
|
|
644
634
|
onSelectionChange: (active, range) => {
|
|
645
|
-
setActiveCell(active);
|
|
646
|
-
setSelectedRange(range);
|
|
647
|
-
|
|
635
|
+
settersRef.current.setActiveCell?.(active);
|
|
636
|
+
settersRef.current.setSelectedRange?.(range);
|
|
637
|
+
optionsRef.current.onSelectionChange?.(active, range);
|
|
648
638
|
},
|
|
649
639
|
onCellCommit: (rowId, colId, raw, value) => {
|
|
650
|
-
|
|
640
|
+
optionsRef.current.onCellCommit?.(rowId, colId, raw, value);
|
|
651
641
|
}
|
|
652
|
-
})
|
|
653
|
-
|
|
642
|
+
})
|
|
643
|
+
);
|
|
644
|
+
const [doc, setDoc] = useState4(() => ({ ...controller.document }));
|
|
645
|
+
const [activeCell, setActiveCell] = useState4(controller.activeCell);
|
|
646
|
+
const [selectedRange, setSelectedRange] = useState4(controller.selectedRange);
|
|
647
|
+
const [editingCell, setEditingCell] = useState4(null);
|
|
648
|
+
const [draftValue, setDraftValue] = useState4("");
|
|
649
|
+
settersRef.current = { setDoc, setActiveCell, setSelectedRange };
|
|
654
650
|
const setCellValue = useCallback4((rowId, colId, raw) => {
|
|
655
651
|
controller.setCellValue(rowId, colId, raw);
|
|
656
652
|
setDoc({ ...controller.document });
|
|
@@ -768,7 +764,7 @@ function useSpreadsheetEditor(options = {}) {
|
|
|
768
764
|
registerDataSource,
|
|
769
765
|
setPrimaryDataSource,
|
|
770
766
|
recalculateAll,
|
|
771
|
-
exportToTsv: () => controller.exportToTsv(),
|
|
767
|
+
exportToTsv: (range) => controller.exportToTsv(range),
|
|
772
768
|
importFromTsv: (data) => {
|
|
773
769
|
controller.importFromTsv(data);
|
|
774
770
|
setDoc({ ...controller.document });
|
|
@@ -779,7 +775,7 @@ function useSpreadsheetEditor(options = {}) {
|
|
|
779
775
|
}
|
|
780
776
|
|
|
781
777
|
// src/spreadsheet/SpreadsheetEditor.tsx
|
|
782
|
-
import { useRef as
|
|
778
|
+
import { useRef as useRef6, useState as useState5, useMemo as useMemo4, useEffect as useEffect5, useCallback as useCallback5 } from "react";
|
|
783
779
|
import {
|
|
784
780
|
indexToColName
|
|
785
781
|
} from "@pixerate/editor";
|
|
@@ -794,23 +790,42 @@ var SpreadsheetEditor = ({
|
|
|
794
790
|
}) => {
|
|
795
791
|
const defaultState = useSpreadsheetEditor();
|
|
796
792
|
const state = externalState || defaultState;
|
|
797
|
-
const gridRef =
|
|
793
|
+
const gridRef = useRef6(null);
|
|
798
794
|
const [resizingColId, setResizingColId] = useState5(null);
|
|
799
795
|
const [hoveredColId, setHoveredColId] = useState5(null);
|
|
800
796
|
const [resizeStartX, setResizeStartX] = useState5(0);
|
|
801
797
|
const [resizeStartWidth, setResizeStartWidth] = useState5(0);
|
|
802
|
-
const activeRawValue =
|
|
798
|
+
const activeRawValue = useMemo4(() => {
|
|
803
799
|
if (!state.activeCell) return "";
|
|
804
800
|
const row = state.document.rows[state.activeCell.row];
|
|
805
801
|
const col = state.document.columns[state.activeCell.col];
|
|
806
802
|
if (!row || !col) return "";
|
|
807
803
|
return state.getCell(row.id, col.id).raw;
|
|
808
804
|
}, [state.activeCell, state.document]);
|
|
809
|
-
const coordLabel =
|
|
805
|
+
const coordLabel = useMemo4(() => {
|
|
810
806
|
if (!state.activeCell) return "--";
|
|
811
807
|
const colName = indexToColName(state.activeCell.col);
|
|
812
808
|
return `${colName}${state.activeCell.row + 1}`;
|
|
813
809
|
}, [state.activeCell]);
|
|
810
|
+
const [formulaDraft, setFormulaDraft] = useState5(null);
|
|
811
|
+
const activeColumn = state.activeCell ? state.document.columns[state.activeCell.col] : void 0;
|
|
812
|
+
const formulaBarReadOnly = readOnly || !state.activeCell || !!activeColumn?.readOnly;
|
|
813
|
+
useEffect5(() => {
|
|
814
|
+
setFormulaDraft(null);
|
|
815
|
+
}, [state.activeCell?.row, state.activeCell?.col]);
|
|
816
|
+
const commitFormulaBar = () => {
|
|
817
|
+
if (state.editingCell) {
|
|
818
|
+
state.commitEditing();
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
if (formulaDraft === null || !state.activeCell) return;
|
|
822
|
+
const row = state.document.rows[state.activeCell.row];
|
|
823
|
+
const col = state.document.columns[state.activeCell.col];
|
|
824
|
+
if (row && col && !formulaBarReadOnly && formulaDraft !== activeRawValue) {
|
|
825
|
+
state.setCellValue(row.id, col.id, formulaDraft);
|
|
826
|
+
}
|
|
827
|
+
setFormulaDraft(null);
|
|
828
|
+
};
|
|
814
829
|
const handleCellClick = useCallback5((rIdx, cIdx, e) => {
|
|
815
830
|
if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
|
|
816
831
|
state.commitEditing();
|
|
@@ -869,16 +884,19 @@ var SpreadsheetEditor = ({
|
|
|
869
884
|
e.preventDefault();
|
|
870
885
|
state.setCellValue(row.id, col.id, "");
|
|
871
886
|
}
|
|
872
|
-
} else if ((e.metaKey || e.ctrlKey) && e.key === "z") {
|
|
887
|
+
} else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
|
|
873
888
|
e.preventDefault();
|
|
874
889
|
if (e.shiftKey) {
|
|
875
890
|
state.redo();
|
|
876
891
|
} else {
|
|
877
892
|
state.undo();
|
|
878
893
|
}
|
|
879
|
-
} else if (
|
|
894
|
+
} else if (e.ctrlKey && !e.metaKey && e.key.toLowerCase() === "y") {
|
|
895
|
+
e.preventDefault();
|
|
896
|
+
state.redo();
|
|
897
|
+
} else if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "c") {
|
|
880
898
|
e.preventDefault();
|
|
881
|
-
const tsv = state.exportToTsv();
|
|
899
|
+
const tsv = state.exportToTsv(state.selectedRange);
|
|
882
900
|
navigator.clipboard?.writeText(tsv);
|
|
883
901
|
} else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
884
902
|
const col = state.document.columns[state.activeCell.col];
|
|
@@ -887,6 +905,10 @@ var SpreadsheetEditor = ({
|
|
|
887
905
|
}
|
|
888
906
|
}
|
|
889
907
|
}, [readOnly, state]);
|
|
908
|
+
const stateRef = useRef6(state);
|
|
909
|
+
stateRef.current = state;
|
|
910
|
+
const onColumnResizeRef = useRef6(onColumnResize);
|
|
911
|
+
onColumnResizeRef.current = onColumnResize;
|
|
890
912
|
useEffect5(() => {
|
|
891
913
|
if (!resizingColId) return;
|
|
892
914
|
if (typeof document !== "undefined") {
|
|
@@ -905,7 +927,7 @@ var SpreadsheetEditor = ({
|
|
|
905
927
|
if (rafId === null) {
|
|
906
928
|
rafId = requestAnimationFrame(() => {
|
|
907
929
|
rafId = null;
|
|
908
|
-
|
|
930
|
+
stateRef.current.setColumnWidth(resizingColId, pendingWidth);
|
|
909
931
|
});
|
|
910
932
|
}
|
|
911
933
|
};
|
|
@@ -915,11 +937,8 @@ var SpreadsheetEditor = ({
|
|
|
915
937
|
rafId = null;
|
|
916
938
|
}
|
|
917
939
|
if (hasDragged) {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
if (col && onColumnResize) {
|
|
921
|
-
onColumnResize(col.id, col.width || pendingWidth);
|
|
922
|
-
}
|
|
940
|
+
stateRef.current.setColumnWidth(resizingColId, pendingWidth);
|
|
941
|
+
onColumnResizeRef.current?.(resizingColId, pendingWidth);
|
|
923
942
|
}
|
|
924
943
|
setResizingColId(null);
|
|
925
944
|
if (typeof document !== "undefined") {
|
|
@@ -940,7 +959,7 @@ var SpreadsheetEditor = ({
|
|
|
940
959
|
window.removeEventListener("mousemove", handleMouseMove);
|
|
941
960
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
942
961
|
};
|
|
943
|
-
}, [resizingColId, resizeStartX, resizeStartWidth
|
|
962
|
+
}, [resizingColId, resizeStartX, resizeStartWidth]);
|
|
944
963
|
const measureElementContentWidth = useCallback5((el, container) => {
|
|
945
964
|
if (typeof document === "undefined") return 0;
|
|
946
965
|
let maxW = el.scrollWidth || 0;
|
|
@@ -1072,25 +1091,29 @@ var SpreadsheetEditor = ({
|
|
|
1072
1091
|
type: "text",
|
|
1073
1092
|
className: "flex-1 bg-transparent px-2 py-0.5 outline-none font-sans text-xs text-foreground placeholder:text-muted-foreground/60 focus:bg-background focus:ring-1 focus:ring-primary rounded",
|
|
1074
1093
|
placeholder: "Enter a value or formula (e.g. =SUM(A1:A5))",
|
|
1075
|
-
|
|
1094
|
+
"aria-label": "Formula bar",
|
|
1095
|
+
readOnly: formulaBarReadOnly,
|
|
1096
|
+
value: state.editingCell ? state.draftValue : formulaDraft ?? activeRawValue,
|
|
1097
|
+
onFocus: () => {
|
|
1098
|
+
if (!state.editingCell) setFormulaDraft(activeRawValue);
|
|
1099
|
+
},
|
|
1076
1100
|
onChange: (e) => {
|
|
1077
|
-
if (state.
|
|
1101
|
+
if (state.editingCell) {
|
|
1078
1102
|
state.setDraftValue(e.target.value);
|
|
1103
|
+
} else if (state.activeCell) {
|
|
1104
|
+
setFormulaDraft(e.target.value);
|
|
1079
1105
|
}
|
|
1080
1106
|
},
|
|
1107
|
+
onBlur: () => commitFormulaBar(),
|
|
1081
1108
|
onKeyDown: (e) => {
|
|
1109
|
+
e.stopPropagation();
|
|
1082
1110
|
if (e.key === "Enter") {
|
|
1083
1111
|
e.preventDefault();
|
|
1084
|
-
|
|
1085
|
-
const row = state.document.rows[state.activeCell.row];
|
|
1086
|
-
const col = state.document.columns[state.activeCell.col];
|
|
1087
|
-
if (row && col) {
|
|
1088
|
-
state.setCellValue(row.id, col.id, e.target.value);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1112
|
+
commitFormulaBar();
|
|
1091
1113
|
} else if (e.key === "Escape") {
|
|
1092
1114
|
e.preventDefault();
|
|
1093
|
-
|
|
1115
|
+
setFormulaDraft(null);
|
|
1116
|
+
if (state.editingCell) state.cancelEditing();
|
|
1094
1117
|
}
|
|
1095
1118
|
}
|
|
1096
1119
|
}
|
|
@@ -1216,7 +1239,7 @@ var SpreadsheetEditor = ({
|
|
|
1216
1239
|
};
|
|
1217
1240
|
|
|
1218
1241
|
// src/slots.tsx
|
|
1219
|
-
import { createContext, useContext, useMemo as
|
|
1242
|
+
import { createContext, useContext, useMemo as useMemo5 } from "react";
|
|
1220
1243
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1221
1244
|
var defaultSlots = {
|
|
1222
1245
|
Button: (props) => /* @__PURE__ */ jsx4(
|
|
@@ -1240,7 +1263,7 @@ var defaultSlots = {
|
|
|
1240
1263
|
};
|
|
1241
1264
|
var EditorSlotsContext = createContext(defaultSlots);
|
|
1242
1265
|
function EditorSlotsProvider({ slots, children }) {
|
|
1243
|
-
const mergedSlots =
|
|
1266
|
+
const mergedSlots = useMemo5(() => ({ ...defaultSlots, ...slots }), [slots]);
|
|
1244
1267
|
return /* @__PURE__ */ jsx4(EditorSlotsContext.Provider, { value: mergedSlots, children });
|
|
1245
1268
|
}
|
|
1246
1269
|
function useEditorSlots() {
|