chore: use produceWithPatches universally for op extracting and history recording

This commit is contained in:
zyc9012 2022-04-04 21:35:26 +08:00
parent cde439db0b
commit 6757b973a5
18 changed files with 499 additions and 596 deletions

View File

@ -1,10 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./lib",
"rootDir": "./src",
"baseUrl": "./",
"composite": true
},
"include": ["./src"]
}

View File

@ -6,7 +6,6 @@ import React, {
useState, useState,
useLayoutEffect, useLayoutEffect,
} from "react"; } from "react";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import "./index.css"; import "./index.css";
import Menu from "./Menu"; import Menu from "./Menu";
@ -68,12 +67,10 @@ const SheetTabContextMenu: React.FC<Props> = ({
> >
<Menu <Menu
onClick={() => { onClick={() => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => { deleteSheet(draftCtx, sheet.index!);
deleteSheet(draftCtx, sheet.index);
onClose?.(); onClose?.();
}) });
);
}} }}
> >
{sheetconfig.delete} {sheetconfig.delete}

View File

@ -7,7 +7,6 @@ import {
} from "@fortune-sheet/core"; } from "@fortune-sheet/core";
import _ from "lodash"; import _ from "lodash";
import React, { useContext, useMemo, useRef, useLayoutEffect } from "react"; import React, { useContext, useMemo, useRef, useLayoutEffect } from "react";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import "./index.css"; import "./index.css";
import Menu from "./Menu"; import Menu from "./Menu";
@ -24,12 +23,10 @@ const ContextMenu: React.FC = () => {
<Menu <Menu
key="copy" key="copy"
onClick={() => { onClick={() => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleCopy(draftCtx); handleCopy(draftCtx);
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
{rightclick.copy} {rightclick.copy}
@ -39,12 +36,10 @@ const ContextMenu: React.FC = () => {
<Menu <Menu
key="paste" key="paste"
onClick={() => { onClick={() => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handlePasteByClick(draftCtx); handlePasteByClick(draftCtx);
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
{rightclick.paste} {rightclick.paste}
@ -56,8 +51,7 @@ const ContextMenu: React.FC = () => {
<Menu <Menu
key={`add-col-${dir}`} key={`add-col-${dir}`}
onClick={(e) => { onClick={(e) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
const position = const position =
draftCtx.luckysheet_select_save?.[0]?.column?.[0]; draftCtx.luckysheet_select_save?.[0]?.column?.[0];
if (position == null) return; if (position == null) return;
@ -76,8 +70,7 @@ const ContextMenu: React.FC = () => {
draftCtx.currentSheetIndex draftCtx.currentSheetIndex
); );
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
<> <>
@ -106,8 +99,7 @@ const ContextMenu: React.FC = () => {
<Menu <Menu
key={`add-row-${dir}`} key={`add-row-${dir}`}
onClick={(e, container) => { onClick={(e, container) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
const position = const position =
draftCtx.luckysheet_select_save?.[0]?.row?.[0]; draftCtx.luckysheet_select_save?.[0]?.row?.[0];
if (position == null) return; if (position == null) return;
@ -124,8 +116,7 @@ const ContextMenu: React.FC = () => {
draftCtx.currentSheetIndex draftCtx.currentSheetIndex
); );
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
<> <>
@ -154,12 +145,10 @@ const ContextMenu: React.FC = () => {
onClick={() => { onClick={() => {
if (!selection) return; if (!selection) return;
const [st_index, ed_index] = selection.column; const [st_index, ed_index] = selection.column;
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
deleteRowCol(draftCtx, "column", st_index, ed_index); deleteRowCol(draftCtx, "column", st_index, ed_index);
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
{rightclick.deleteSelected} {rightclick.deleteSelected}
@ -172,12 +161,10 @@ const ContextMenu: React.FC = () => {
onClick={() => { onClick={() => {
if (!selection) return; if (!selection) return;
const [st_index, ed_index] = selection.row; const [st_index, ed_index] = selection.row;
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
deleteRowCol(draftCtx, "row", st_index, ed_index); deleteRowCol(draftCtx, "row", st_index, ed_index);
draftCtx.contextMenu = undefined; draftCtx.contextMenu = undefined;
}) });
);
}} }}
> >
{rightclick.deleteSelected} {rightclick.deleteSelected}
@ -214,12 +201,10 @@ const ContextMenu: React.FC = () => {
hasOverflow = true; hasOverflow = true;
} }
if (hasOverflow) { if (hasOverflow) {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
draftCtx.contextMenu.x = left; draftCtx.contextMenu.x = left;
draftCtx.contextMenu.y = top; draftCtx.contextMenu.y = top;
}) });
);
} }
}, [contextMenu, setContext]); }, [contextMenu, setContext]);

View File

@ -17,7 +17,6 @@ import React, {
useEffect, useEffect,
useRef, useRef,
} from "react"; } from "react";
import produce from "immer";
import "./index.css"; import "./index.css";
import _ from "lodash"; import _ from "lodash";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
@ -65,8 +64,7 @@ const FxEditor: React.FC = () => {
const onFocus = useCallback(() => { const onFocus = useCallback(() => {
if ((context.luckysheet_select_save?.length ?? 0) > 0) { if ((context.luckysheet_select_save?.length ?? 0) > 0) {
setFocused(true); setFocused(true);
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
const last = const last =
draftCtx.luckysheet_select_save![ draftCtx.luckysheet_select_save![
draftCtx.luckysheet_select_save!.length - 1 draftCtx.luckysheet_select_save!.length - 1
@ -78,8 +76,7 @@ const FxEditor: React.FC = () => {
draftCtx.luckysheetCellUpdate = [row_index, col_index]; draftCtx.luckysheetCellUpdate = [row_index, col_index];
refs.globalCache.doNotFocus = true; refs.globalCache.doNotFocus = true;
// formula.rangeResizeTo = $("#luckysheet-functionbox-cell"); // formula.rangeResizeTo = $("#luckysheet-functionbox-cell");
}) });
);
} }
}, [context.luckysheet_select_save, refs.globalCache, setContext]); }, [context.luckysheet_select_save, refs.globalCache, setContext]);
@ -90,8 +87,7 @@ const FxEditor: React.FC = () => {
// return; // return;
// } // }
lastKeyDownEventRef.current = e; lastKeyDownEventRef.current = e;
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
if (context.luckysheetCellUpdate.length > 0) { if (context.luckysheetCellUpdate.length > 0) {
switch (e.key) { switch (e.key) {
case "Enter": { case "Enter": {
@ -194,8 +190,7 @@ const FxEditor: React.FC = () => {
break; break;
} }
} }
}) });
);
}, },
[context.luckysheetCellUpdate.length, refs.fxInput, setContext] [context.luckysheetCellUpdate.length, refs.fxInput, setContext]
); );
@ -222,16 +217,14 @@ const FxEditor: React.FC = () => {
kcode === 46 || kcode === 46 ||
(e.ctrlKey && kcode === 86) (e.ctrlKey && kcode === 86)
) { ) {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleFormulaInput( handleFormulaInput(
draftCtx, draftCtx,
refs.cellInput.current!, refs.cellInput.current!,
refs.fxInput.current!, refs.fxInput.current!,
kcode kcode
); );
}) });
);
} }
}, [refs.cellInput, refs.fxInput, setContext]); }, [refs.cellInput, refs.fxInput, setContext]);

View File

@ -9,7 +9,6 @@ import {
} from "@fortune-sheet/core"; } from "@fortune-sheet/core";
import "./index.css"; import "./index.css";
import type { CellMatrix } from "@fortune-sheet/core"; import type { CellMatrix } from "@fortune-sheet/core";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import SheetOverlay from "../SheetOverlay"; import SheetOverlay from "../SheetOverlay";
@ -25,16 +24,14 @@ const Sheet: React.FC<Props> = ({ data }) => {
useEffect(() => { useEffect(() => {
function resize() { function resize() {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
updateContextWithSheetData(draftCtx, data); updateContextWithSheetData(draftCtx, data);
updateContextWithCanvas( updateContextWithCanvas(
draftCtx, draftCtx,
canvasRef.current!, canvasRef.current!,
placeholderRef.current! placeholderRef.current!
); );
}) });
);
} }
window.addEventListener("resize", resize); window.addEventListener("resize", resize);
return () => { return () => {
@ -43,30 +40,24 @@ const Sheet: React.FC<Props> = ({ data }) => {
}, [data, setContext]); }, [data, setContext]);
useEffect(() => { useEffect(() => {
setContext( setContext((draftCtx) => updateContextWithSheetData(draftCtx, data));
produce((draftCtx) => updateContextWithSheetData(draftCtx, data))
);
}, [context.config?.rowlen, context.config?.columnlen, data, setContext]); }, [context.config?.rowlen, context.config?.columnlen, data, setContext]);
useEffect(() => { useEffect(() => {
setContext( setContext((draftCtx) =>
produce((draftCtx) =>
updateContextWithCanvas( updateContextWithCanvas(
draftCtx, draftCtx,
canvasRef.current!, canvasRef.current!,
placeholderRef.current! placeholderRef.current!
) )
)
); );
}, [setContext]); }, [setContext]);
useEffect(() => { useEffect(() => {
if (hasGroupValuesRefreshData()) { if (hasGroupValuesRefreshData()) {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
groupValuesRefresh(draftCtx); groupValuesRefresh(draftCtx);
}) });
);
} }
}, [context.luckysheetfile, context.currentSheetIndex, setContext]); }, [context.luckysheetfile, context.currentSheetIndex, setContext]);
@ -82,8 +73,7 @@ const Sheet: React.FC<Props> = ({ data }) => {
const onWheel = useCallback( const onWheel = useCallback(
(e: WheelEvent) => { (e: WheelEvent) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleGlobalWheel( handleGlobalWheel(
draftCtx, draftCtx,
e, e,
@ -91,8 +81,7 @@ const Sheet: React.FC<Props> = ({ data }) => {
refs.scrollbarX.current!, refs.scrollbarX.current!,
refs.scrollbarY.current! refs.scrollbarY.current!
); );
}) });
);
}, },
[refs.globalCache, refs.scrollbarX, refs.scrollbarY, setContext] [refs.globalCache, refs.scrollbarX, refs.scrollbarY, setContext]
); );

View File

@ -15,7 +15,6 @@ import React, {
useCallback, useCallback,
useEffect, useEffect,
} from "react"; } from "react";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
const ColumnHeader: React.FC = () => { const ColumnHeader: React.FC = () => {
@ -55,15 +54,13 @@ const ColumnHeader: React.FC = () => {
const onMouseDown = useCallback( const onMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleColumnHeaderMouseDown( handleColumnHeaderMouseDown(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
containerRef.current! containerRef.current!
); );
}) });
);
}, },
[setContext] [setContext]
); );
@ -77,16 +74,14 @@ const ColumnHeader: React.FC = () => {
const onColSizeHandleMouseDown = useCallback( const onColSizeHandleMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleColSizeHandleMouseDown( handleColSizeHandleMouseDown(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
containerRef.current!, containerRef.current!,
refs.cellArea.current! refs.cellArea.current!
); );
}) });
);
e.stopPropagation(); e.stopPropagation();
}, },
[refs.cellArea, setContext] [refs.cellArea, setContext]
@ -94,16 +89,14 @@ const ColumnHeader: React.FC = () => {
const onContextMenu = useCallback( const onContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleContextMenu( handleContextMenu(
draftCtx, draftCtx,
settings, settings,
e.nativeEvent, e.nativeEvent,
refs.workbookContainer.current! refs.workbookContainer.current!
); );
}) });
);
}, },
[refs.workbookContainer, setContext, settings] [refs.workbookContainer, setContext, settings]
); );

View File

@ -19,7 +19,6 @@ import React, {
useLayoutEffect, useLayoutEffect,
} from "react"; } from "react";
import _ from "lodash"; import _ from "lodash";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import ContentEditable from "./ContentEditable"; import ContentEditable from "./ContentEditable";
import FormulaSearch from "./FormulaSearch"; import FormulaSearch from "./FormulaSearch";
@ -107,8 +106,7 @@ const InputBox: React.FC = () => {
// return; // return;
// } // }
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
if (e.key === "Escape" && draftCtx.luckysheetCellUpdate.length > 0) { if (e.key === "Escape" && draftCtx.luckysheetCellUpdate.length > 0) {
cancelNormalSelected(draftCtx); cancelNormalSelected(draftCtx);
moveHighlightCell(draftCtx, "down", 0, "rangeOfSelect"); moveHighlightCell(draftCtx, "down", 0, "rangeOfSelect");
@ -152,10 +150,7 @@ const InputBox: React.FC = () => {
// } // }
e.preventDefault(); e.preventDefault();
} else if ( } else if (e.key === "F4" && draftCtx.luckysheetCellUpdate.length > 0) {
e.key === "F4" &&
draftCtx.luckysheetCellUpdate.length > 0
) {
// formula.setfreezonFuc(event); // formula.setfreezonFuc(event);
e.preventDefault(); e.preventDefault();
} /* else if ( } /* else if (
@ -179,8 +174,7 @@ const InputBox: React.FC = () => {
) { ) {
formulaMoveEvent("right", ctrlKey, shiftKey, event); formulaMoveEvent("right", ctrlKey, shiftKey, event);
} */ } */
}) });
);
}, },
[setContext] [setContext]
); );
@ -213,8 +207,7 @@ const InputBox: React.FC = () => {
kcode === 46 || kcode === 46 ||
(e.ctrlKey && kcode === 86) (e.ctrlKey && kcode === 86)
) { ) {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
// if(event.target.id!="luckysheet-input-box" && event.target.id!="luckysheet-rich-text-editor"){ // if(event.target.id!="luckysheet-input-box" && event.target.id!="luckysheet-rich-text-editor"){
handleFormulaInput( handleFormulaInput(
draftCtx, draftCtx,
@ -233,8 +226,7 @@ const InputBox: React.FC = () => {
// draftCtx.flowdata // draftCtx.flowdata
// ); // );
// } // }
}) });
);
} }
}, [refs.cellInput, refs.fxInput, setContext]); }, [refs.cellInput, refs.fxInput, setContext]);

View File

@ -15,7 +15,6 @@ import React, {
useCallback, useCallback,
useEffect, useEffect,
} from "react"; } from "react";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
const RowHeader: React.FC = () => { const RowHeader: React.FC = () => {
@ -55,15 +54,13 @@ const RowHeader: React.FC = () => {
const onMouseDown = useCallback( const onMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleRowHeaderMouseDown( handleRowHeaderMouseDown(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
containerRef.current! containerRef.current!
); );
}) });
);
}, },
[setContext] [setContext]
); );
@ -77,16 +74,14 @@ const RowHeader: React.FC = () => {
const onRowSizeHandleMouseDown = useCallback( const onRowSizeHandleMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleRowSizeHandleMouseDown( handleRowSizeHandleMouseDown(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
containerRef.current!, containerRef.current!,
refs.cellArea.current! refs.cellArea.current!
); );
}) });
);
e.stopPropagation(); e.stopPropagation();
}, },
[refs.cellArea, setContext] [refs.cellArea, setContext]
@ -94,16 +89,14 @@ const RowHeader: React.FC = () => {
const onContextMenu = useCallback( const onContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleContextMenu( handleContextMenu(
draftCtx, draftCtx,
settings, settings,
e.nativeEvent, e.nativeEvent,
refs.workbookContainer.current! refs.workbookContainer.current!
); );
}) });
);
}, },
[refs.workbookContainer, setContext, settings] [refs.workbookContainer, setContext, settings]
); );

View File

@ -7,7 +7,7 @@ type Props = {
}; };
const ScrollBar: React.FC<Props> = ({ axis }) => { const ScrollBar: React.FC<Props> = ({ axis }) => {
const { context, refs, setContextValue } = useContext(WorkbookContext); const { context, refs, setContext } = useContext(WorkbookContext);
useEffect(() => { useEffect(() => {
if (axis === "x") { if (axis === "x") {
@ -24,9 +24,13 @@ const ScrollBar: React.FC<Props> = ({ axis }) => {
className={`luckysheet-scrollbars luckysheet-scrollbar-ltr luckysheet-scrollbar-${axis}`} className={`luckysheet-scrollbars luckysheet-scrollbar-ltr luckysheet-scrollbar-${axis}`}
onScroll={() => { onScroll={() => {
if (axis === "x") { if (axis === "x") {
setContextValue("scrollLeft", refs.scrollbarX.current!.scrollLeft); setContext((draftCtx) => {
draftCtx.scrollLeft = refs.scrollbarX.current!.scrollLeft;
});
} else { } else {
setContextValue("scrollTop", refs.scrollbarY.current!.scrollTop); setContext((draftCtx) => {
draftCtx.scrollTop = refs.scrollbarY.current!.scrollTop;
});
} }
}} }}
> >

View File

@ -1,6 +1,5 @@
import React, { useContext, useCallback, useRef, useEffect } from "react"; import React, { useContext, useCallback, useRef, useEffect } from "react";
import "./index.css"; import "./index.css";
import produce from "immer";
import { import {
handleCellAreaDoubleClick, handleCellAreaDoubleClick,
handleCellAreaMouseDown, handleCellAreaMouseDown,
@ -20,56 +19,49 @@ const SheetOverlay: React.FC = () => {
const cellAreaMouseDown = useCallback( const cellAreaMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleCellAreaMouseDown( handleCellAreaMouseDown(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
refs.cellInput.current!, refs.cellInput.current!,
refs.cellArea.current! refs.cellArea.current!
); );
}) });
);
}, },
[refs.cellArea, refs.cellInput, setContext] [refs.cellArea, refs.cellInput, setContext]
); );
const cellAreaContextMenu = useCallback( const cellAreaContextMenu = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleContextMenu( handleContextMenu(
draftCtx, draftCtx,
settings, settings,
e.nativeEvent, e.nativeEvent,
refs.workbookContainer.current! refs.workbookContainer.current!
); );
}) });
);
}, },
[refs.workbookContainer, setContext, settings] [refs.workbookContainer, setContext, settings]
); );
const cellAreaDoubleClick = useCallback( const cellAreaDoubleClick = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleCellAreaDoubleClick( handleCellAreaDoubleClick(
draftCtx, draftCtx,
settings, settings,
e.nativeEvent, e.nativeEvent,
refs.cellArea.current! refs.cellArea.current!
); );
}) });
);
}, },
[refs.cellArea, setContext, settings] [refs.cellArea, setContext, settings]
); );
const onMouseMove = useCallback( const onMouseMove = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleOverlayMouseMove( handleOverlayMouseMove(
draftCtx, draftCtx,
e.nativeEvent, e.nativeEvent,
@ -77,24 +69,21 @@ const SheetOverlay: React.FC = () => {
refs.scrollbarY.current!, refs.scrollbarY.current!,
containerRef.current! containerRef.current!
); );
}) });
);
}, },
[refs.scrollbarX, refs.scrollbarY, setContext] [refs.scrollbarX, refs.scrollbarY, setContext]
); );
const onMouseUp = useCallback( const onMouseUp = useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleOverlayMouseUp( handleOverlayMouseUp(
draftCtx, draftCtx,
settings, settings,
e.nativeEvent, e.nativeEvent,
containerRef.current! containerRef.current!
); );
}) });
);
}, },
[setContext, settings] [setContext, settings]
); );

View File

@ -6,7 +6,6 @@ import React, {
useRef, useRef,
useCallback, useCallback,
} from "react"; } from "react";
import produce from "immer";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import SheetTabContextMenu from "../ContextMenu/SheetTab"; import SheetTabContextMenu from "../ContextMenu/SheetTab";
@ -15,7 +14,7 @@ type Props = {
}; };
const SheetItem: React.FC<Props> = ({ sheet }) => { const SheetItem: React.FC<Props> = ({ sheet }) => {
const { context, setContext, setContextValue } = useContext(WorkbookContext); const { context, setContext } = useContext(WorkbookContext);
const [editing, setEditing] = useState(false); const [editing, setEditing] = useState(false);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const editable = useRef<HTMLSpanElement>(null); const editable = useRef<HTMLSpanElement>(null);
@ -53,11 +52,9 @@ const SheetItem: React.FC<Props> = ({ sheet }) => {
}, [editing]); }, [editing]);
const onBlur = useCallback(() => { const onBlur = useCallback(() => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
handleSheetTabOnBlur(draftCtx, editable.current!); handleSheetTabOnBlur(draftCtx, editable.current!);
}) });
);
setEditing(false); setEditing(false);
}, [setContext]); }, [setContext]);
@ -71,7 +68,9 @@ const SheetItem: React.FC<Props> = ({ sheet }) => {
: "" : ""
}`} }`}
onClick={() => { onClick={() => {
setContextValue("currentSheetIndex", sheet.index); setContext((draftCtx) => {
draftCtx.currentSheetIndex = sheet.index!;
});
}} }}
onContextMenu={(e) => { onContextMenu={(e) => {
const rect = containerRef.current!.getBoundingClientRect(); const rect = containerRef.current!.getBoundingClientRect();

View File

@ -1,5 +1,4 @@
import React, { useContext, useRef } from "react"; import React, { useContext, useRef } from "react";
import produce from "immer";
import { updateCell, addSheet } from "@fortune-sheet/core"; import { updateCell, addSheet } from "@fortune-sheet/core";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
import SVGIcon from "../SVGIcon"; import SVGIcon from "../SVGIcon";
@ -21,8 +20,7 @@ const SheetTab: React.FC = () => {
<div <div
className="fortune-sheettab-button" className="fortune-sheettab-button"
onClick={() => { onClick={() => {
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
if (draftCtx.luckysheetCellUpdate.length > 0) { if (draftCtx.luckysheetCellUpdate.length > 0) {
updateCell( updateCell(
draftCtx, draftCtx,
@ -32,8 +30,7 @@ const SheetTab: React.FC = () => {
); );
} }
addSheet(draftCtx); addSheet(draftCtx);
}) });
);
}} }}
> >
<SVGIcon name="plus" width={16} height={16} /> <SVGIcon name="plus" width={16} height={16} />

View File

@ -1,5 +1,4 @@
import React, { useContext, useCallback, useRef } from "react"; import React, { useContext, useCallback, useRef } from "react";
import produce from "immer";
import { import {
getToolbarItemClickHandler, getToolbarItemClickHandler,
handleTextBackground, handleTextBackground,
@ -32,14 +31,12 @@ const Toolbar: React.FC = () => {
} }
if (["text-color", "text-background"].includes(name)) { if (["text-color", "text-background"].includes(name)) {
const pick = (color: string) => { const pick = (color: string) => {
setContext( setContext((draftCtx) =>
produce((draftCtx) =>
(name === "text-color" ? handleTextColor : handleTextBackground)( (name === "text-color" ? handleTextColor : handleTextBackground)(
draftCtx, draftCtx,
refs.cellInput.current!, refs.cellInput.current!,
color color
) )
)
); );
if (name === "text-color") { if (name === "text-color") {
refs.globalCache.recentTextColor = color; refs.globalCache.recentTextColor = color;
@ -103,14 +100,12 @@ const Toolbar: React.FC = () => {
<Option <Option
key={num} key={num}
onClick={() => { onClick={() => {
setContext( setContext((draftContext) =>
produce((draftContext) =>
handleTextSize( handleTextSize(
draftContext, draftContext,
refs.cellInput.current!, refs.cellInput.current!,
num num
) )
)
); );
setOpen(false); setOpen(false);
}} }}
@ -129,14 +124,12 @@ const Toolbar: React.FC = () => {
tooltip={name} tooltip={name}
key={name} key={name}
onClick={() => onClick={() =>
setContext( setContext((draftCtx) => {
produce((draftCtx) => {
getToolbarItemClickHandler(name)?.( getToolbarItemClickHandler(name)?.(
draftCtx, draftCtx,
refs.cellInput.current! refs.cellInput.current!
); );
}) })
)
} }
/> />
); );

View File

@ -20,7 +20,7 @@ import React, {
useRef, useRef,
} from "react"; } from "react";
import "./index.css"; import "./index.css";
import produce from "immer"; import { enablePatches, produceWithPatches } from "immer";
import _, { assign } from "lodash"; import _, { assign } from "lodash";
import Sheet from "../Sheet"; import Sheet from "../Sheet";
import WorkbookContext from "../../context"; import WorkbookContext from "../../context";
@ -30,6 +30,8 @@ import SheetTab from "../SheetTab";
import ContextMenu from "../ContextMenu"; import ContextMenu from "../ContextMenu";
import SVGDefines from "../SVGDefines"; import SVGDefines from "../SVGDefines";
enablePatches();
const Workbook: React.FC< const Workbook: React.FC<
Settings & { onChange?: (data: SheetType[]) => void } Settings & { onChange?: (data: SheetType[]) => void }
> = ({ onChange, ...props }) => { > = ({ onChange, ...props }) => {
@ -45,21 +47,21 @@ const Workbook: React.FC<
() => assign(defaultSettings, props) as Required<Settings>, () => assign(defaultSettings, props) as Required<Settings>,
[props] [props]
); );
const setContextValue = useCallback(
<K extends keyof Context>(key: K, value: Context[K]) => { const setContextWithProduce = useCallback(
setContext( (recipe: (ctx: Context) => void) => {
produce((draftCtx) => { setContext((ctx_) => {
draftCtx[key] = value; const [result] = produceWithPatches(ctx_, recipe);
}) return result;
); });
}, },
[] []
); );
const providerValue = useMemo( const providerValue = useMemo(
() => ({ () => ({
context, context,
setContext, setContext: setContextWithProduce,
setContextValue,
settings: mergedSettings, settings: mergedSettings,
refs: { refs: {
globalCache: globalCache.current, globalCache: globalCache.current,
@ -71,7 +73,7 @@ const Workbook: React.FC<
workbookContainer, workbookContainer,
}, },
}), }),
[context, mergedSettings, setContextValue] [context, mergedSettings, setContextWithProduce]
); );
useEffect(() => { useEffect(() => {
@ -79,8 +81,7 @@ const Workbook: React.FC<
}, [context.luckysheetfile, onChange]); }, [context.luckysheetfile, onChange]);
useEffect(() => { useEffect(() => {
setContext( setContextWithProduce((draftCtx) => {
produce((draftCtx) => {
if (_.isEmpty(draftCtx.luckysheetfile)) { if (_.isEmpty(draftCtx.luckysheetfile)) {
// mergedSettings.data at this time may be immutable, causing following modifications to fail, // mergedSettings.data at this time may be immutable, causing following modifications to fail,
// clone it to make it mutable // clone it to make it mutable
@ -121,9 +122,8 @@ const Workbook: React.FC<
const lastRowNum = lastRow?.r || draftCtx.defaultrowNum; const lastRowNum = lastRow?.r || draftCtx.defaultrowNum;
const lastColNum = lastCol?.c || draftCtx.defaultcolumnNum; const lastColNum = lastCol?.c || draftCtx.defaultcolumnNum;
if (lastRowNum && lastColNum) { if (lastRowNum && lastColNum) {
const expandedData: SheetType["data"] = _.times( const expandedData: SheetType["data"] = _.times(lastRowNum + 1, () =>
lastRowNum + 1, _.times(lastColNum + 1, () => null)
() => _.times(lastColNum + 1, () => null)
); );
cellData?.forEach((d) => { cellData?.forEach((d) => {
// TODO setCellValue(draftCtx, d.r, d.c, expandedData, d.v); // TODO setCellValue(draftCtx, d.r, d.c, expandedData, d.v);
@ -196,12 +196,11 @@ const Workbook: React.FC<
if (!_.isNil(mergedSettings.lang)) { if (!_.isNil(mergedSettings.lang)) {
localStorage.setItem("lang", mergedSettings.lang); localStorage.setItem("lang", mergedSettings.lang);
} }
}) });
);
}, [ }, [
mergedSettings.data, mergedSettings.data,
context.currentSheetIndex, context.currentSheetIndex,
context.luckysheetfile?.length, context.luckysheetfile.length,
mergedSettings.defaultRowHeight, mergedSettings.defaultRowHeight,
mergedSettings.defaultColWidth, mergedSettings.defaultColWidth,
mergedSettings.column, mergedSettings.column,
@ -212,11 +211,12 @@ const Workbook: React.FC<
mergedSettings.allowEdit, mergedSettings.allowEdit,
mergedSettings.limitSheetNameLength, mergedSettings.limitSheetNameLength,
mergedSettings.defaultSheetNameMaxLength, mergedSettings.defaultSheetNameMaxLength,
setContextWithProduce,
]); ]);
const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => { const onKeyDown = useCallback(
setContext( (e: React.KeyboardEvent<HTMLDivElement>) => {
produce((draftCtx) => { setContextWithProduce((draftCtx) => {
handleGlobalKeyDown( handleGlobalKeyDown(
draftCtx, draftCtx,
cellInput.current!, cellInput.current!,
@ -224,17 +224,19 @@ const Workbook: React.FC<
e.nativeEvent, e.nativeEvent,
globalCache.current! globalCache.current!
); );
}) });
},
[setContextWithProduce]
); );
}, []);
const onPaste = useCallback((e: ClipboardEvent) => { const onPaste = useCallback(
setContext( (e: ClipboardEvent) => {
produce((draftCtx) => { setContextWithProduce((draftCtx) => {
handlePaste(draftCtx, e); handlePaste(draftCtx, e);
}) });
},
[setContextWithProduce]
); );
}, []);
useEffect(() => { useEffect(() => {
document.addEventListener("paste", onPaste); document.addEventListener("paste", onPaste);
@ -270,7 +272,9 @@ const Workbook: React.FC<
{!_.isEmpty(context.contextMenu) && ( {!_.isEmpty(context.contextMenu) && (
<div <div
onMouseDown={() => { onMouseDown={() => {
setContextValue("contextMenu", undefined); setContextWithProduce((draftCtx) => {
draftCtx.contextMenu = undefined;
});
}} }}
onMouseMove={(e) => e.stopPropagation()} onMouseMove={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()} onMouseUp={(e) => e.stopPropagation()}

View File

@ -19,15 +19,13 @@ type RefValues = {
const WorkbookContext = React.createContext<{ const WorkbookContext = React.createContext<{
context: Context; context: Context;
setContext: React.Dispatch<React.SetStateAction<Context>>; setContext: (recipe: (ctx: Context) => void) => void;
// eslint-disable-next-line // eslint-disable-next-line
setContextValue: <K extends keyof Context>(key: K, value: Context[K]) => void;
settings: Required<Settings>; settings: Required<Settings>;
refs: RefValues; refs: RefValues;
}>({ }>({
context: defaultContext(), context: defaultContext(),
setContext: () => {}, setContext: () => {},
setContextValue: () => {},
settings: defaultSettings, settings: defaultSettings,
refs: { refs: {
globalCache: {}, globalCache: {},

View File

@ -1,16 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDirs": ["./src", "../core/src"],
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"@fortune-sheet/core": ["../core/src"]
},
"composite": true
},
"include": [
"./src"
],
"references": [{ "path": "../core" }]
}

View File

@ -11,6 +11,7 @@ export default {
} as ComponentMeta<typeof Workbook>; } as ComponentMeta<typeof Workbook>;
const Template: ComponentStory<typeof Workbook> = ({ const Template: ComponentStory<typeof Workbook> = ({
// eslint-disable-next-line react/prop-types
data: data0, data: data0,
...args ...args
}) => { }) => {
@ -26,13 +27,16 @@ const Template: ComponentStory<typeof Workbook> = ({
}; };
export const Basic = Template.bind({}); export const Basic = Template.bind({});
// @ts-ignore
Basic.args = { data: [cell] }; Basic.args = { data: [cell] };
export const Formula = Template.bind({}); export const Formula = Template.bind({});
// @ts-ignore
Formula.args = { data: [formula] }; Formula.args = { data: [formula] };
export const Empty = Template.bind({}); export const Empty = Template.bind({});
Empty.args = { data: [empty] }; Empty.args = { data: [empty] };
export const Tabs = Template.bind({}); export const Tabs = Template.bind({});
// @ts-ignore
Tabs.args = { data: [cell, formula] }; Tabs.args = { data: [cell, formula] };

View File

@ -19,7 +19,6 @@
"@fortune-sheet/react": ["packages/react/src"] "@fortune-sheet/react": ["packages/react/src"]
} }
}, },
"references": [{ "path": "./packages/core" }, { "path": "./packages/react" }],
"include": ["packages/*/src", "stories/"], "include": ["packages/*/src", "stories/"],
"exclude": [ "exclude": [
"node_modules", "node_modules",