diff --git a/README.md b/README.md index 085b25d..b61383d 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,34 @@ function loadData() { } ``` +## Supported events +- onCellClick +- onSelectionChange +- onCellChange + +### Using events examples +```ts +import Spreadsheet, { SpreadsheetConstructorProperties } from "./main"; + +const options: SpreadsheetConstructorProperties = { + onCellClick: (event, cell) => { + console.log('Cell click', event, cell) + }, + onSelectionChange: (selection) => { + console.log("Changed selection: ", selection) + }, + onCellChange(cell) { + console.log("Cell changed: ", cell) + }, +} + +const sheet = new Spreadsheet("#spreadsheet", options); +``` + ## Roadmap - ~~Rows number and columns heading render~~ -- Custom event functions (ex.: onSelectionChange, onCellEdit...). Full list of supported events will available on this page +- ~~Custom event functions (ex.: onSelectionChange, onCellEdit...). Full list of supported events will available on this page~~ - Rows and columns resizing - Toolbar - Context menu diff --git a/src/components/editor.ts b/src/components/editor.ts index 6d2f1b7..0ade2d6 100644 --- a/src/components/editor.ts +++ b/src/components/editor.ts @@ -1,5 +1,6 @@ import Spreadsheet, { CSS_PREFIX } from "../main"; import { Position } from "../modules/cell"; +import { EventTypes } from "../modules/events"; import { RenderBox } from "../modules/renderBox"; export class Editor { @@ -52,10 +53,17 @@ export class Editor { break; } case "Enter": { - this.root.changeCellValues(this.root.selection.selectedCell!, { - value: this.element.value, - displayValue: this.element.value, - }); + if (!this.root.selection.selectedCell) return; + + this.root.events.dispatch({ + type: EventTypes.CELL_CHANGE, + cell: this.root.getCell(this.root.selection.selectedCell), + values: { + value: this.element.value, + displayValue: this.element.value, + } + }) + this.hide(); } } diff --git a/src/components/scroller.ts b/src/components/scroller.ts index ef51fee..9e502ff 100644 --- a/src/components/scroller.ts +++ b/src/components/scroller.ts @@ -59,7 +59,7 @@ export class Scroller { if (isRangeChanged) { this.root.selection.selectedRange.to = lastSelectedCell; this.root.events.dispatch({ - type: EventTypes.CHANGE_SELECTION, + type: EventTypes.SELECTION_CHANGE, selection: this.root.selection, enableCallback: true }) @@ -78,7 +78,7 @@ export class Scroller { ) { newSelection.selectedRange = null; this.root.events.dispatch({ - type: EventTypes.CHANGE_SELECTION, + type: EventTypes.SELECTION_CHANGE, selection: newSelection, enableCallback: false }) @@ -148,7 +148,7 @@ export class Scroller { } } this.root.events.dispatch({ - type: EventTypes.CHANGE_SELECTION, + type: EventTypes.SELECTION_CHANGE, selection: this.root.selection, enableCallback: true }) diff --git a/src/index.ts b/src/index.ts index 3b0838a..f3b9beb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,11 +2,14 @@ import Spreadsheet, { SpreadsheetConstructorProperties } from "./main"; const options: SpreadsheetConstructorProperties = { onCellClick: (event, cell) => { - console.log('Callback from instance', event, cell) + console.log('Cell click', event, cell) }, onSelectionChange: (selection) => { console.log("Changed selection: ", selection) - } + }, + onCellChange(cell) { + console.log("Cell changed: ", cell) + }, } const sheet = new Spreadsheet("#spreadsheet", options); diff --git a/src/main.ts b/src/main.ts index c20432c..63bad1b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,7 +10,7 @@ import { Position, SerializableCell, } from "./modules/cell"; -import { Config, ViewProperties } from "./modules/config"; +import { CellChangeEvent, CellClickEvent, Config, SelectionChangeEvent, ViewProperties } from "./modules/config"; import { RangeSelectionType, Selection } from "./modules/selection"; import { Styles } from "./modules/styles"; import { Viewport } from "./modules/viewport"; @@ -37,8 +37,9 @@ import { Events } from "./modules/events"; export interface SpreadsheetConstructorProperties { view?: ViewProperties; - onCellClick?: ((event: MouseEvent, cell: Cell) => void) | null - onSelectionChange?: ((selection: Selection) => void) | null + onCellClick?: CellClickEvent | null + onSelectionChange?: SelectionChangeEvent | null + onCellChange?: CellChangeEvent | null } export const CSS_PREFIX = "modern_sc_"; @@ -76,6 +77,7 @@ export default class Spreadsheet { this.config.onCellClick = props?.onCellClick ?? null this.config.onSelectonChange = props?.onSelectionChange ?? null + this.config.onCellChange = props?.onCellChange ?? null this.rowsBar = new RowsBar(this); this.columnsBar = new ColumnsBar(this); diff --git a/src/modules/config.ts b/src/modules/config.ts index e16f922..f3d36a9 100644 --- a/src/modules/config.ts +++ b/src/modules/config.ts @@ -7,6 +7,9 @@ export interface ViewProperties { width: number; height: number; } +export type CellClickEvent = (event: MouseEvent, cell: Cell) => void +export type SelectionChangeEvent = (selection: Selection) => void +export type CellChangeEvent = (cell: Cell) => void export type ConfigProperties = { /** Please, end it with '_' symbol. @@ -18,8 +21,9 @@ export type ConfigProperties = { rows: Row[]; columns: Column[]; view: ViewProperties; - onCellClick?: ((event: MouseEvent, cell: Cell) => void) | null - onSelectionChange?: ((selection: Selection) => void) | null + onCellClick?: CellClickEvent | null + onSelectionChange?: SelectionChangeEvent | null + onCellChange?: CellChangeEvent | null }; export type SheetConfigConstructorProps = { @@ -35,8 +39,9 @@ export class Config { height: 600, }; - onCellClick: ( (event: MouseEvent, cell: Cell) => void ) | null = null - onSelectonChange: ((selection: Selection) => void) | null = null + onCellClick: ((event: MouseEvent, cell: Cell) => void) | null = null + onSelectonChange: SelectionChangeEvent | null = null + onCellChange: CellChangeEvent | null = null constructor(props: ConfigProperties) { this.columns = props.columns; @@ -45,5 +50,6 @@ export class Config { this.onCellClick = props.onCellClick ?? null this.onSelectonChange = props.onSelectionChange ?? null + this.onCellChange = props.onCellChange ?? null } } diff --git a/src/modules/events.ts b/src/modules/events.ts index be158de..00b5ea6 100644 --- a/src/modules/events.ts +++ b/src/modules/events.ts @@ -1,9 +1,10 @@ import { Scroller } from "../components/scroller"; -import Spreadsheet, { Selection } from "../main"; +import Spreadsheet, { Cell, CellConstructorProps, Selection } from "../main"; export enum EventTypes { CELL_CLICK = "CELL_CLICK", - CHANGE_SELECTION = "CHANGE_SELECTION" + SELECTION_CHANGE = "CHANGE_SELECTION", + CELL_CHANGE = "CELL_CHANGE" } export type CellClickEvent = { @@ -13,12 +14,18 @@ export type CellClickEvent = { } export type ChangeSelectionEvent = { - type: EventTypes.CHANGE_SELECTION, + type: EventTypes.SELECTION_CHANGE, selection: Selection enableCallback?: boolean } -export type ActionTypes = CellClickEvent | ChangeSelectionEvent +export type ChangeCellEvent = { + type: EventTypes.CELL_CHANGE, + cell: Cell, + values: Partial> +} + +export type ActionTypes = CellClickEvent | ChangeSelectionEvent | ChangeCellEvent export class Events { @@ -32,16 +39,31 @@ export class Events { switch (action.type) { case EventTypes.CELL_CLICK: { const { event, scroller } = action + // + //* Here may be side effects + // this.cellClick(event, scroller) break; } - case EventTypes.CHANGE_SELECTION: { + case EventTypes.SELECTION_CHANGE: { const { selection, enableCallback } = action + // + //* Here may be side effects + // this.changeSelection(selection, enableCallback) break; } + case EventTypes.CELL_CHANGE: { + const { cell, values } = action + // + //* Here may be side effects + // + this.changeCellValues(cell, values) + break; + } + default: { break; } @@ -77,4 +99,9 @@ export class Events { this.root.renderRowsBar(); } + private changeCellValues(cell: Cell, values: Partial>) { + this.root.changeCellValues(cell.position, values) + + this.root.config.onCellChange?.(cell) + } } \ No newline at end of file