FIX: Do not loose focus when clicking on the formula we are editing
This commit is contained in:
@@ -193,7 +193,7 @@ const Editor = (options: EditorOptions) => {
|
|||||||
const isCellEditing = workbookState.getEditingCell() !== null;
|
const isCellEditing = workbookState.getEditingCell() !== null;
|
||||||
|
|
||||||
const showEditor =
|
const showEditor =
|
||||||
isCellEditing && (display || type === "formula-bar") ? "block" : "none";
|
(isCellEditing && display) || type === "formula-bar" ? "block" : "none";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -229,13 +229,18 @@ const Editor = (options: EditorOptions) => {
|
|||||||
resize: "none",
|
resize: "none",
|
||||||
border: "none",
|
border: "none",
|
||||||
height,
|
height,
|
||||||
display: display ? "block" : "none",
|
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
defaultValue={text}
|
defaultValue={text}
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
onBlur={onChange}
|
onBlur={onChange}
|
||||||
|
onClick={(event) => {
|
||||||
|
// Prevents this from bubbling up and focusing on the spreadsheet
|
||||||
|
if (isCellEditing && type === "cell") {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { Model } from "@ironcalc/wasm";
|
import type { Model } from "@ironcalc/wasm";
|
||||||
import { Button, styled } from "@mui/material";
|
import { Button, styled } from "@mui/material";
|
||||||
import { ChevronDown } from "lucide-react";
|
import { ChevronDown } from "lucide-react";
|
||||||
import { useState } from "react";
|
|
||||||
import { Fx } from "../icons";
|
import { Fx } from "../icons";
|
||||||
import Editor from "./editor/editor";
|
import Editor from "./editor/editor";
|
||||||
import type { WorkbookState } from "./workbookState";
|
import type { WorkbookState } from "./workbookState";
|
||||||
@@ -27,9 +26,6 @@ function FormulaBar(properties: FormulaBarProps) {
|
|||||||
onTextUpdated,
|
onTextUpdated,
|
||||||
workbookState,
|
workbookState,
|
||||||
} = properties;
|
} = properties;
|
||||||
|
|
||||||
const [display, setDisplay] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<AddressContainer>
|
<AddressContainer>
|
||||||
@@ -55,7 +51,6 @@ function FormulaBar(properties: FormulaBarProps) {
|
|||||||
focus: "formula-bar",
|
focus: "formula-bar",
|
||||||
activeRanges: [],
|
activeRanges: [],
|
||||||
});
|
});
|
||||||
setDisplay(true);
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}}
|
}}
|
||||||
@@ -63,13 +58,12 @@ function FormulaBar(properties: FormulaBarProps) {
|
|||||||
<Editor
|
<Editor
|
||||||
minimalWidth={"100%"}
|
minimalWidth={"100%"}
|
||||||
minimalHeight={"100%"}
|
minimalHeight={"100%"}
|
||||||
display={display}
|
display={true}
|
||||||
expand={false}
|
expand={false}
|
||||||
originalText={formulaValue}
|
originalText={formulaValue}
|
||||||
model={model}
|
model={model}
|
||||||
workbookState={workbookState}
|
workbookState={workbookState}
|
||||||
onEditEnd={() => {
|
onEditEnd={() => {
|
||||||
setDisplay(false);
|
|
||||||
onChange();
|
onChange();
|
||||||
}}
|
}}
|
||||||
onTextUpdated={onTextUpdated}
|
onTextUpdated={onTextUpdated}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { Model } from "@ironcalc/wasm";
|
||||||
import { type PointerEvent, type RefObject, useCallback, useRef } from "react";
|
import { type PointerEvent, type RefObject, useCallback, useRef } from "react";
|
||||||
import type WorksheetCanvas from "./WorksheetCanvas/worksheetCanvas";
|
import type WorksheetCanvas from "./WorksheetCanvas/worksheetCanvas";
|
||||||
import {
|
import {
|
||||||
@@ -5,6 +6,7 @@ import {
|
|||||||
headerRowHeight,
|
headerRowHeight,
|
||||||
} from "./WorksheetCanvas/worksheetCanvas";
|
} from "./WorksheetCanvas/worksheetCanvas";
|
||||||
import type { Cell } from "./types";
|
import type { Cell } from "./types";
|
||||||
|
import type { WorkbookState } from "./workbookState";
|
||||||
|
|
||||||
interface PointerSettings {
|
interface PointerSettings {
|
||||||
canvasElement: RefObject<HTMLCanvasElement>;
|
canvasElement: RefObject<HTMLCanvasElement>;
|
||||||
@@ -15,6 +17,8 @@ interface PointerSettings {
|
|||||||
onAreaSelected: () => void;
|
onAreaSelected: () => void;
|
||||||
onExtendToCell: (cell: Cell) => void;
|
onExtendToCell: (cell: Cell) => void;
|
||||||
onExtendToEnd: () => void;
|
onExtendToEnd: () => void;
|
||||||
|
model: Model;
|
||||||
|
workbookState: WorkbookState;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PointerEvents {
|
interface PointerEvents {
|
||||||
@@ -99,7 +103,13 @@ const usePointer = (options: PointerSettings): PointerEvents => {
|
|||||||
(event: PointerEvent) => {
|
(event: PointerEvent) => {
|
||||||
let x = event.clientX;
|
let x = event.clientX;
|
||||||
let y = event.clientY;
|
let y = event.clientY;
|
||||||
const { canvasElement, worksheetElement, worksheetCanvas } = options;
|
const {
|
||||||
|
canvasElement,
|
||||||
|
model,
|
||||||
|
worksheetElement,
|
||||||
|
worksheetCanvas,
|
||||||
|
workbookState,
|
||||||
|
} = options;
|
||||||
const worksheet = worksheetCanvas.current;
|
const worksheet = worksheetCanvas.current;
|
||||||
const canvas = canvasElement.current;
|
const canvas = canvasElement.current;
|
||||||
const worksheetWrapper = worksheetElement.current;
|
const worksheetWrapper = worksheetElement.current;
|
||||||
@@ -132,8 +142,28 @@ const usePointer = (options: PointerSettings): PointerEvents => {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// if we are editing a cell finish that
|
||||||
|
const editingCell = workbookState.getEditingCell();
|
||||||
|
|
||||||
const cell = worksheet.getCellByCoordinates(x, y);
|
const cell = worksheet.getCellByCoordinates(x, y);
|
||||||
if (cell) {
|
if (cell) {
|
||||||
|
if (editingCell) {
|
||||||
|
if (
|
||||||
|
cell.row === editingCell.row &&
|
||||||
|
cell.column === editingCell.column
|
||||||
|
) {
|
||||||
|
// We are clicking on the cell we are editing
|
||||||
|
// we do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
workbookState.clearEditingCell();
|
||||||
|
model.setUserInput(
|
||||||
|
editingCell.sheet,
|
||||||
|
editingCell.row,
|
||||||
|
editingCell.column,
|
||||||
|
editingCell.text,
|
||||||
|
);
|
||||||
|
}
|
||||||
options.onCellSelected(cell, event);
|
options.onCellSelected(cell, event);
|
||||||
isSelecting.current = true;
|
isSelecting.current = true;
|
||||||
worksheetWrapper.setPointerCapture(event.pointerId);
|
worksheetWrapper.setPointerCapture(event.pointerId);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { BorderOptions, Model, WorksheetProperties } from "@ironcalc/wasm";
|
import type { BorderOptions, Model, WorksheetProperties } from "@ironcalc/wasm";
|
||||||
import { styled } from "@mui/material/styles";
|
import { styled } from "@mui/material/styles";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { LAST_COLUMN } from "./WorksheetCanvas/constants";
|
import { LAST_COLUMN } from "./WorksheetCanvas/constants";
|
||||||
import FormulaBar from "./formulabar";
|
import FormulaBar from "./formulabar";
|
||||||
import Navigation from "./navigation/navigation";
|
import Navigation from "./navigation/navigation";
|
||||||
@@ -262,26 +262,33 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cellAddress = useCallback(() => {
|
||||||
const {
|
const {
|
||||||
sheet,
|
|
||||||
row,
|
row,
|
||||||
column,
|
column,
|
||||||
range: [rowStart, columnStart, rowEnd, columnEnd],
|
range: [rowStart, columnStart, rowEnd, columnEnd],
|
||||||
} = model.getSelectedView();
|
} = model.getSelectedView();
|
||||||
|
return getCellAddress(
|
||||||
const cellAddress = getCellAddress(
|
|
||||||
{ rowStart, rowEnd, columnStart, columnEnd },
|
{ rowStart, rowEnd, columnStart, columnEnd },
|
||||||
{ row, column },
|
{ row, column },
|
||||||
);
|
);
|
||||||
const formulaValue = (() => {
|
}, [model]);
|
||||||
|
|
||||||
|
const formulaValue = () => {
|
||||||
const cell = workbookState.getEditingCell();
|
const cell = workbookState.getEditingCell();
|
||||||
if (cell) {
|
if (cell) {
|
||||||
return cell.text;
|
return cell.text;
|
||||||
}
|
}
|
||||||
|
const { sheet, row, column } = model.getSelectedView();
|
||||||
return model.getCellContent(sheet, row, column);
|
return model.getCellContent(sheet, row, column);
|
||||||
})();
|
};
|
||||||
|
|
||||||
const style = model.getCellStyle(sheet, row, column);
|
const getCellStyle = useCallback(() => {
|
||||||
|
const { sheet, row, column } = model.getSelectedView();
|
||||||
|
return model.getCellStyle(sheet, row, column);
|
||||||
|
}, [model]);
|
||||||
|
|
||||||
|
const style = getCellStyle();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
@@ -339,15 +346,16 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
|
|||||||
verticalAlign={style.alignment ? style.alignment.vertical : "center"}
|
verticalAlign={style.alignment ? style.alignment.vertical : "center"}
|
||||||
canEdit={true}
|
canEdit={true}
|
||||||
numFmt={style.num_fmt}
|
numFmt={style.num_fmt}
|
||||||
showGridLines={model.getShowGridLines(sheet)}
|
showGridLines={model.getShowGridLines(model.getSelectedSheet())}
|
||||||
onToggleShowGridLines={(show) => {
|
onToggleShowGridLines={(show) => {
|
||||||
|
const sheet = model.getSelectedSheet();
|
||||||
model.setShowGridLines(sheet, show);
|
model.setShowGridLines(sheet, show);
|
||||||
setRedrawId((id) => id + 1);
|
setRedrawId((id) => id + 1);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<FormulaBar
|
<FormulaBar
|
||||||
cellAddress={cellAddress}
|
cellAddress={cellAddress()}
|
||||||
formulaValue={formulaValue}
|
formulaValue={formulaValue()}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
setRedrawId((id) => id + 1);
|
setRedrawId((id) => id + 1);
|
||||||
rootRef.current?.focus();
|
rootRef.current?.focus();
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ function Worksheet(props: {
|
|||||||
|
|
||||||
const ignoreScrollEventRef = useRef(false);
|
const ignoreScrollEventRef = useRef(false);
|
||||||
|
|
||||||
const [display, setDisplay] = useState(false);
|
|
||||||
const [originalText, setOriginalText] = useState("");
|
const [originalText, setOriginalText] = useState("");
|
||||||
|
|
||||||
const { model, workbookState, refresh } = props;
|
const { model, workbookState, refresh } = props;
|
||||||
@@ -143,6 +142,8 @@ function Worksheet(props: {
|
|||||||
onPointerUp,
|
onPointerUp,
|
||||||
// onContextMenu,
|
// onContextMenu,
|
||||||
} = usePointer({
|
} = usePointer({
|
||||||
|
model,
|
||||||
|
workbookState,
|
||||||
onCellSelected: (cell: Cell, event: React.MouseEvent) => {
|
onCellSelected: (cell: Cell, event: React.MouseEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -315,18 +316,11 @@ function Worksheet(props: {
|
|||||||
<SheetContainer
|
<SheetContainer
|
||||||
className="sheet-container"
|
className="sheet-container"
|
||||||
ref={worksheetElement}
|
ref={worksheetElement}
|
||||||
onPointerDown={(event) => {
|
onPointerDown={onPointerDown}
|
||||||
// if we are editing a cell finish that
|
|
||||||
const cell = workbookState.getEditingCell();
|
|
||||||
if (cell) {
|
|
||||||
workbookState.clearEditingCell();
|
|
||||||
model.setUserInput(cell.sheet, cell.row, cell.column, cell.text);
|
|
||||||
}
|
|
||||||
onPointerDown(event);
|
|
||||||
}}
|
|
||||||
onPointerMove={onPointerMove}
|
onPointerMove={onPointerMove}
|
||||||
onPointerUp={onPointerUp}
|
onPointerUp={onPointerUp}
|
||||||
onDoubleClick={(event) => {
|
onDoubleClick={(event) => {
|
||||||
|
// Starts editing cell
|
||||||
const { sheet, row, column } = model.getSelectedView();
|
const { sheet, row, column } = model.getSelectedView();
|
||||||
const text = model.getCellContent(sheet, row, column) || "";
|
const text = model.getCellContent(sheet, row, column) || "";
|
||||||
workbookState.setEditingCell({
|
workbookState.setEditingCell({
|
||||||
@@ -334,11 +328,10 @@ function Worksheet(props: {
|
|||||||
row,
|
row,
|
||||||
column,
|
column,
|
||||||
text,
|
text,
|
||||||
cursor: 0,
|
cursor: text.length,
|
||||||
focus: "cell",
|
focus: "cell",
|
||||||
activeRanges: [],
|
activeRanges: [],
|
||||||
});
|
});
|
||||||
setDisplay(true);
|
|
||||||
setOriginalText(text);
|
setOriginalText(text);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -354,7 +347,6 @@ function Worksheet(props: {
|
|||||||
expand={true}
|
expand={true}
|
||||||
originalText={workbookState.getEditingCell()?.text || originalText}
|
originalText={workbookState.getEditingCell()?.text || originalText}
|
||||||
onEditEnd={(): void => {
|
onEditEnd={(): void => {
|
||||||
setDisplay(false);
|
|
||||||
props.refresh();
|
props.refresh();
|
||||||
}}
|
}}
|
||||||
onTextUpdated={(): void => {
|
onTextUpdated={(): void => {
|
||||||
|
|||||||
Reference in New Issue
Block a user