diff --git a/.gitignore b/.gitignore index 442d623..7b502b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea dist node_modules -configs/deploy/sftp-config.js +.gitignore +configs diff --git a/src/components/table/Table.ts b/src/components/table/Table.ts index 40653c1..44cfdd0 100644 --- a/src/components/table/Table.ts +++ b/src/components/table/Table.ts @@ -1,6 +1,7 @@ import { initialStyleState } from '../../constants'; import { $, Dom } from '../../core/dom'; import { ExcelComponent } from '../../core/ExcelComponent'; +import { parse } from '../../core/parse'; import { changeCurrentStyles } from '../../redux/actions'; import * as actions from '../../redux/actions'; import { resizeHandler } from './handlers/table.resize'; @@ -35,10 +36,11 @@ export class Table extends ExcelComponent { const $cell = this.$root.find('[data-id="0:0"]'); this.selection.select($cell); - this.$emit('table:select-cell', $cell.text); + this.$emit('table:select-cell', $cell.data.value); this.$on('formula:input', (data) => { - this.selection.current.text = data; + this.selection.current.attr('data-value', data); + this.selection.current.text = parse(data); this.updateCurrentTextInStore(data); }); @@ -73,6 +75,7 @@ export class Table extends ExcelComponent { const cols = this.$root.findAll(`[data-col="${key}"]`); cols.forEach(el => $(el as HTMLElement).css({ width: `${size.col[key]}px` })); }); + Object.keys(size.row).forEach(key => { const rows = this.$root.findAll(`[data-row="${key}"]`); rows.forEach(el => $(el as HTMLElement).css({ height: `${size.row[key]}px` })); @@ -88,13 +91,14 @@ export class Table extends ExcelComponent { const $cell = this.$root.find(`[data-id="${cellId}"]`); const styles = tableStyles[cellId]; - $cell.text = tableContent[cellId] || ''; + $cell.text = parse(tableContent[cellId]) || ''; + $cell.setData('value', tableContent[cellId]); $cell.css(styles); }); } emitSelectCallback() { - this.$emit('table:select-cell', this.selection.current.text); + this.$emit('table:select-cell', this.selection.current.data.value); const styles = this.selection.current?.getStyles(Object.keys(initialStyleState) as (keyof Partial)[]); this.$dispatch(changeCurrentStyles(styles)); diff --git a/src/constants.ts b/src/constants.ts index b28c754..854ad10 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -16,5 +16,5 @@ export const initialState: StateType = { stylesState: {}, title: 'New excel table', ...storage('excel-state'), - currentStyles: { ...storage('excel-state').stylesState['0:0'] }, + currentStyles: { ...storage('excel-state')?.stylesState?.['0:0'] }, }; diff --git a/src/core/dom.ts b/src/core/dom.ts index cda9284..a1370e0 100644 --- a/src/core/dom.ts +++ b/src/core/dom.ts @@ -72,6 +72,10 @@ export class Dom implements DomClass { return this.$el.dataset; } + setData(name: string, value: string) { + this.$el.setAttribute(`data-${name}`, value); + } + closest(selector: string) { return $(this.$el.closest(selector) as HTMLElement); } @@ -110,6 +114,15 @@ export class Dom implements DomClass { return res; }, {}); } + + attr(name: string, value: string) { + if (value) { + this.$el.setAttribute(name, value); + return this; + } + + return this.$el.getAttribute(name); + } } export function $(selector: SelectorType) { diff --git a/src/core/parse.ts b/src/core/parse.ts new file mode 100644 index 0000000..3b95b08 --- /dev/null +++ b/src/core/parse.ts @@ -0,0 +1,12 @@ +export function parse(value: string) { + if (value.startsWith('=')) { + try { + // eslint-disable-next-line no-eval + return eval(value.slice(1)); + } catch (e) { + return value; + } + } + + return value; +} diff --git a/src/core/utils.ts b/src/core/utils.ts index 2e37cca..128fa08 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -19,3 +19,17 @@ export function isEqual(a: any, b: any) { return a === b; } + +export function debounce(fn: (fnArgs?: any) => void, wait: number) { + let timeout: NodeJS.Timeout; + + return function (...args: any[]) { + const later = () => { + clearTimeout(timeout); + fn.apply(this, args); + }; + + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} diff --git a/src/index.ts b/src/index.ts index 2660e7f..6875c68 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,14 +5,17 @@ import { Table } from './components/table/Table'; import { Toolbar } from './components/toolbar/Toolbar'; import './styles/index.scss'; import { Store } from './core/createStore'; -import { storage } from './core/utils'; +import { debounce, storage } from './core/utils'; import { rootReducer } from './redux/rootReducer'; +import { StateType } from './redux/types'; const store = new Store(rootReducer); -store.subscribe(state => { +const stateListener = debounce((state: StateType) => { storage('excel-state', state); -}); +}, 300); + +store.subscribe(stateListener); const excel = new Excel('#app', { components: [Header, Toolbar, Formula, Table],