diff --git a/src/Cell.tsx b/src/Cell.tsx index 7bf79e08..33e4f80e 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -57,6 +57,14 @@ export const Cell: React.FC = ({ [setCellDimensions, select, dragging, point] ); + // Report dimensions on initial render + React.useEffect(() => { + const root = rootRef.current; + if (root) { + setCellDimensions(point, getOffsetRect(root)); + } + }, [setCellDimensions, point]); + React.useEffect(() => { const root = rootRef.current; if (selected && root) { diff --git a/src/FloatingRect.tsx b/src/FloatingRect.tsx index f0f65f23..17e3a45f 100644 --- a/src/FloatingRect.tsx +++ b/src/FloatingRect.tsx @@ -7,6 +7,7 @@ export type Props = { dimensions?: Types.Dimensions | null | undefined; hidden?: boolean; dragging?: boolean; + additionalClasses?: string[], }; const FloatingRect: React.FC = ({ @@ -14,11 +15,12 @@ const FloatingRect: React.FC = ({ dragging, hidden, variant, + additionalClasses, }) => { const { width, height, top, left } = dimensions || {}; return (
= ({ highlight }) => { + const dimensions = useSelector( + (state) => + highlight && + getHighlightedDimensions( + state.rowDimensions, + state.columnDimensions, + state.model.data, + highlight + ) + ); + + const dragging = useSelector((state) => state.dragging); + return ( +
), diff --git a/src/actions.ts b/src/actions.ts index cade0c6c..e9dcedc1 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -4,7 +4,7 @@ import { CellBase, Dimensions, CommitChanges, - CreateFormulaParser, + CreateFormulaParser, Highlight, } from "./types"; import { Selection } from "./selection"; @@ -14,6 +14,7 @@ export const SELECT_ENTIRE_ROW = "SELECT_ENTIRE_ROW"; export const SELECT_ENTIRE_COLUMN = "SELECT_ENTIRE_COLUMN"; export const SELECT_ENTIRE_WORKSHEET = "SELECT_ENTIRE_WORKSHEET"; export const SET_SELECTION = "SET_SELECTION"; +export const SET_HIGHLIGHTS = "SET_HIGHLIGHTS"; export const SELECT = "SELECT"; export const ACTIVATE = "ACTIVATE"; export const SET_CELL_DATA = "SET_CELL_DATA"; @@ -132,6 +133,25 @@ export function select(point: Point): SelectAction { }; } +export type SetHighlightsAction = BaseAction & { + payload: { + highlights: Highlight[]; + }; +}; + +export function setHighlights(highlights: Highlight[]): SetHighlightsAction { + return { + type: SET_HIGHLIGHTS, + payload: { highlights }, + }; +} + +export type HighlightAction = BaseAction & { + payload: { + highlights: Highlight[]; + }; +} + export type ActivateAction = BaseAction & { payload: { point: Point; @@ -284,6 +304,7 @@ export type Action = | SelectEntireWorksheetAction | SetSelectionAction | SelectAction + | HighlightAction | ActivateAction | SetCellDataAction | SetCellDimensionsAction diff --git a/src/reducer.ts b/src/reducer.ts index b9cc59c2..76453ef3 100644 --- a/src/reducer.ts +++ b/src/reducer.ts @@ -25,6 +25,7 @@ export const INITIAL_STATE: Types.StoreState = { dragging: false, model: new Model(createFormulaParser, []), selected: new EmptySelection(), + highlights: [], copied: null, lastCommit: null, }; @@ -103,6 +104,13 @@ export default function reducer( mode: "view", }; } + case Actions.SET_HIGHLIGHTS: { + const { highlights } = action.payload; + return { + ...state, + highlights, + }; + } case Actions.SELECT: { const { point } = action.payload; if (state.active && !isActive(state.active, point)) { diff --git a/src/stories/Spreadsheet.stories.tsx b/src/stories/Spreadsheet.stories.tsx index fc17249f..d7040afb 100644 --- a/src/stories/Spreadsheet.stories.tsx +++ b/src/stories/Spreadsheet.stories.tsx @@ -17,6 +17,8 @@ import CustomCell from "./CustomCell"; import { RangeEdit, RangeView } from "./RangeDataComponents"; import { SelectEdit, SelectView } from "./SelectDataComponents"; import { CustomCornerIndicator } from "./CustomCornerIndicator"; +import {Highlight} from "../types"; +import {useEffect} from "react"; type StringCell = CellBase; type NumberCell = CellBase; @@ -61,6 +63,26 @@ const meta: Meta> = { } }} > + ), @@ -286,6 +308,8 @@ export const ControlledSelection: StoryFn> = (props) => { const [selected, setSelected] = React.useState( new EmptySelection() ); + const [running, setRunning] = React.useState(false); + const [highlighted, setHighlighted] = React.useState>([]); const handleSelect = React.useCallback((selection: Selection) => { setSelected(selection); }, []); @@ -302,16 +326,53 @@ export const ControlledSelection: StoryFn> = (props) => { setSelected(new EntireWorksheetSelection()); }, []); + useEffect(() => { + if (!running) { + return; + } + setTimeout(() => { + if (highlighted.length < 4) { + setHighlighted([ + ...highlighted, + { + selection: new EntireColumnsSelection(highlighted.length, highlighted.length), + classNames: ["cell-highlight-red", "cell-highlight-blue", "cell-highlight-green", "cell-highlight-yellow"].slice(highlighted.length, highlighted.length + 1) + }, + ]) + } else { + setHighlighted([]); + } + }, 1000); + }, [highlighted, running]); + return (
+

Selection

+

Highlighting

+ + +
- ; +
+ ;
); }; diff --git a/src/types.ts b/src/types.ts index fa47a46a..d3e6b3b5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -45,9 +45,16 @@ export type Dimensions = { left: number; }; +/* List of highlighted cells */ +export type Highlight = { + classNames: string[]; + selection: Selection; +} + export type StoreState = { model: Model; selected: Selection; + highlights: Highlight[]; copied: PointRange | null; hasPasted: boolean; cut: boolean;