Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/ActiveCell.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,10 @@ const DISPATCH_MOCK = jest.fn();
const STATE_WITH_ACTIVE: Types.StoreState = {
...INITIAL_STATE,
active: Point.ORIGIN,
rowDimensions: {
0: {
dimensions: {
"0:0": {
height: 42,
top: 42,
},
},
columnDimensions: {
0: {
width: 42,
left: 42,
},
Expand Down
4 changes: 1 addition & 3 deletions src/ActiveCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ const ActiveCell: React.FC<Props> = (props) => {
state.active ? Matrix.get(state.active, state.model.data) : undefined
);
const dimensions = useSelector((state) =>
active
? getCellDimensions(active, state.rowDimensions, state.columnDimensions)
: undefined
active ? getCellDimensions(active, state.dimensions) : undefined
);
const hidden = React.useMemo(
() => !active || !dimensions,
Expand Down
4 changes: 1 addition & 3 deletions src/Copied.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import useSelector from "./use-selector";
const Copied: React.FC = () => {
const range = useSelector((state) => state.copied);
const dimensions = useSelector(
(state) =>
range &&
getRangeDimensions(state.rowDimensions, state.columnDimensions, range)
(state) => range && getRangeDimensions(state.dimensions, range)
);
const hidden = range === null;

Expand Down
7 changes: 1 addition & 6 deletions src/Selected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ const Selected: React.FC = () => {
const dimensions = useSelector(
(state) =>
selected &&
getSelectedDimensions(
state.rowDimensions,
state.columnDimensions,
state.model.data,
state.selected
)
getSelectedDimensions(state.dimensions, state.model.data, state.selected)
);
const dragging = useSelector((state) => state.dragging);
const hidden = useSelector(
Expand Down
8 changes: 2 additions & 6 deletions src/reducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,10 @@ describe("reducer", () => {
Actions.setCellDimensions(Point.ORIGIN, EXAMPLE_DIMENSIONS),
{
...INITIAL_STATE,
rowDimensions: {
[Point.ORIGIN.row]: {
dimensions: {
[`${Point.ORIGIN.row}:${Point.ORIGIN.column}`]: {
height: EXAMPLE_DIMENSIONS.height,
top: EXAMPLE_DIMENSIONS.top,
},
},
columnDimensions: {
[Point.ORIGIN.column]: {
width: EXAMPLE_DIMENSIONS.width,
left: EXAMPLE_DIMENSIONS.left,
},
Expand Down
32 changes: 15 additions & 17 deletions src/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import { Model, updateCellValue, createFormulaParser } from "./engine";
export const INITIAL_STATE: Types.StoreState = {
active: null,
mode: "view",
rowDimensions: {},
columnDimensions: {},
dimensions: {},
lastChanged: null,
hasPasted: false,
cut: false,
Expand Down Expand Up @@ -136,27 +135,26 @@ export default function reducer(
}
case Actions.SET_CELL_DIMENSIONS: {
const { point, dimensions } = action.payload;
const prevRowDimensions = state.rowDimensions[point.row];
const prevColumnDimensions = state.columnDimensions[point.column];
const prevDimensions = state.dimensions[`${point.row}:${point.column}`];
if (
prevRowDimensions &&
prevColumnDimensions &&
prevRowDimensions.top === dimensions.top &&
prevRowDimensions.height === dimensions.height &&
prevColumnDimensions.left === dimensions.left &&
prevColumnDimensions.width === dimensions.width
prevDimensions &&
prevDimensions.top === dimensions.top &&
prevDimensions.height === dimensions.height &&
prevDimensions.left === dimensions.left &&
prevDimensions.width === dimensions.width
) {
return state;
}
return {
...state,
rowDimensions: {
...state.rowDimensions,
[point.row]: { top: dimensions.top, height: dimensions.height },
},
columnDimensions: {
...state.columnDimensions,
[point.column]: { left: dimensions.left, width: dimensions.width },
dimensions: {
...state.dimensions,
[`${point.row}:${point.column}`]: {
top: dimensions.top,
height: dimensions.height,
left: dimensions.left,
width: dimensions.width,
},
},
};
}
Expand Down
113 changes: 87 additions & 26 deletions src/stories/CustomCell.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/**
* Example custom cell component
*/

import * as React from "react";
import React, {
createRef,
useCallback,
useEffect,
useState,
MouseEvent,
} from "react";
import classnames from "classnames";
import { CellComponent } from "..";

const HEIGHT = 30;
const WIDTH = 96;

const CustomCell: CellComponent = ({
export const CustomCell: CellComponent = ({
column,
row,
setCellDimensions,
Expand All @@ -23,28 +22,88 @@ const CustomCell: CellComponent = ({
DataViewer,
setCellData,
}) => {
const rootRef = React.createRef<HTMLTableCellElement>();
const rootRef = createRef<HTMLTableCellElement>();
const [dimension, setDimension] = useState({
width: 0,
height: 0,
top: 0,
left: 0,
});

React.useEffect(() => {
setCellDimensions(
{ row, column },
{
height: HEIGHT,
width: WIDTH,
left: WIDTH * (column + 1),
top: HEIGHT * (row + 1),
}
);
}, [setCellDimensions, column, row]);
const getColumnRangeSplit = (str: string) => {
if (!str) return {};
const regex = /([A-Za-z]+)(\d+):([A-Za-z]+)(\d+)/;
const matches = str.match(regex);
if (matches) {
const [, startColumn, startRow, endColumn, endRow] = matches;
return { startColumn, startRow, endColumn, endRow };
} else {
console.log("No match found.");
return {};
}
};
const getColumnRange = (columnRange: string) => {
if (!columnRange) {
return { colspan: undefined, rowspan: undefined };
}
const { startColumn, startRow, endColumn, endRow } =
getColumnRangeSplit(columnRange);
const colspan =
(endColumn?.charCodeAt(0) ?? 0) - (startColumn?.charCodeAt(0) ?? 0);
const rowspan = parseInt(endRow ?? "") - parseInt(startRow ?? "");

return {
colspan: colspan === 0 ? undefined : colspan,
rowspan: rowspan === 0 ? undefined : rowspan,
};
};

useEffect(() => {
const observer = new ResizeObserver((entries) => {
console.log("resize", {
width: entries[0].target.getBoundingClientRect().width,
height: entries[0].target.getBoundingClientRect().height,
top: entries[0].target.getBoundingClientRect().top - 16,
left: entries[0].target.getBoundingClientRect().left - 16,
});
setDimension({
width: entries[0].target.getBoundingClientRect().width,
height: entries[0].target.getBoundingClientRect().height,
top: entries[0].target.getBoundingClientRect().top - 16,
left: entries[0].target.getBoundingClientRect().left - 16,
});
});
if (rootRef.current) {
observer.observe(rootRef.current);
}
return () => {
rootRef.current && observer.unobserve(rootRef.current);
};
}, []);

useEffect(() => {
if (rootRef.current) {
setDimension({
width: rootRef.current.getBoundingClientRect().width,
height: rootRef.current.getBoundingClientRect().height,
top: rootRef.current.getBoundingClientRect().top - 16,
left: rootRef.current.getBoundingClientRect().left - 16,
});
}
}, []);

useEffect(() => {
setCellDimensions({ row, column }, dimension);
}, [setCellDimensions, dimension, column, row]);

React.useEffect(() => {
useEffect(() => {
if (rootRef.current && active && mode === "view") {
rootRef.current.focus();
}
}, [rootRef, active, mode]);

const handleMouseDown = React.useCallback(
(event) => {
const handleMouseDown = useCallback(
(event: MouseEvent) => {
if (mode === "view") {
if (event.shiftKey) {
select({ row, column });
Expand All @@ -54,10 +113,10 @@ const CustomCell: CellComponent = ({
activate({ row, column });
}
},
[select, activate, column, mode, row]
[select, activate, column, mode, row, dimension]
);

const handleMouseOver = React.useCallback(() => {
const handleMouseOver = useCallback(() => {
if (dragging) {
select({ row, column });
}
Expand All @@ -81,6 +140,8 @@ const CustomCell: CellComponent = ({
tabIndex={0}
onMouseOver={handleMouseOver}
onMouseDown={handleMouseDown}
colSpan={getColumnRange(data?.mergeRange ?? "").colspan}
rowSpan={getColumnRange(data?.mergeRange ?? "").rowspan}
>
<DataViewer
row={row}
Expand Down
Loading