New features: serialize and load data
Fixed imports in modules
This commit is contained in:
parent
73645c14f6
commit
11376f13ac
|
|
@ -14,4 +14,7 @@ const target = document.getElementById('spreadsheet')
|
|||
|
||||
const sheet = new Spreadsheet(target)
|
||||
```
|
||||
|
||||
<span>Load data</span>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
import { Position } from "../modules/cell";
|
||||
export declare class Editor {
|
||||
element: HTMLInputElement;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
export declare class Header {
|
||||
element: HTMLHeadElement;
|
||||
root: Spreadsheet;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
export interface ViewportRect {
|
||||
top: number;
|
||||
left: number;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
import { Position } from "../modules/cell";
|
||||
/**
|
||||
* Display (CANVAS) element where cells render
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
import { ViewProperties } from "../modules/config";
|
||||
/** Base (root) component */
|
||||
export declare class Table {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
export declare class Toolbar {
|
||||
element: HTMLDivElement;
|
||||
root: Spreadsheet;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -9,7 +9,7 @@ interface SpreadsheetConstructorProperties {
|
|||
config?: Omit<Config, 'view'>;
|
||||
view?: ViewProperties;
|
||||
}
|
||||
export declare class Spreadsheet {
|
||||
export default class Spreadsheet {
|
||||
private table;
|
||||
private scroller;
|
||||
private toolbar;
|
||||
|
|
@ -37,7 +37,16 @@ export declare class Spreadsheet {
|
|||
showEditor(position: Position): void;
|
||||
renderSheet(): void;
|
||||
renderCell(row: number, col: number): void;
|
||||
loadData(data: Cell[][]): void;
|
||||
loadData(data: Cell[][]): Spreadsheet;
|
||||
private makeConfigFromData;
|
||||
}
|
||||
export {};
|
||||
export * from './modules/cache';
|
||||
export * from './modules/cell';
|
||||
export * from './modules/column';
|
||||
export * from './modules/config';
|
||||
export * from './modules/renderBox';
|
||||
export * from './modules/row';
|
||||
export * from './modules/selection';
|
||||
export * from './modules/styles';
|
||||
export * from './modules/viewport';
|
||||
export * from './utils/createData';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
var f = Object.defineProperty;
|
||||
var C = (r, t, e) => t in r ? f(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
|
||||
var o = (r, t, e) => (C(r, typeof t != "symbol" ? t + "" : t, e), e);
|
||||
var p = Object.defineProperty;
|
||||
var y = (r, t, e) => t in r ? p(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
|
||||
var o = (r, t, e) => (y(r, typeof t != "symbol" ? t + "" : t, e), e);
|
||||
class w {
|
||||
constructor(t, e) {
|
||||
o(this, "x");
|
||||
|
|
@ -22,7 +22,7 @@ class w {
|
|||
return s;
|
||||
}
|
||||
}
|
||||
class p {
|
||||
class S {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
|
|
@ -56,7 +56,7 @@ class p {
|
|||
this.element.classList.remove("hide"), this.element.style.top = n - this.root.viewport.top + "px", this.element.style.left = l - this.root.viewport.left + "px", this.element.style.width = s + "px", this.element.style.height = e + "px", this.element.style.display = "block", window.addEventListener("click", this.handleClickOutside), this.element.addEventListener("keydown", this.handleKeydown), this.element.value = i.value, this.element.focus(), this.element.select();
|
||||
}
|
||||
}
|
||||
class y {
|
||||
class v {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
|
|
@ -65,7 +65,7 @@ class y {
|
|||
e.classList.add(), this.element = e;
|
||||
}
|
||||
}
|
||||
class v {
|
||||
class x {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "verticalScroller");
|
||||
|
|
@ -160,7 +160,7 @@ class v {
|
|||
this.horizontalScroller.style.width = t + "px";
|
||||
}
|
||||
}
|
||||
class S {
|
||||
class R {
|
||||
constructor(t) {
|
||||
o(this, "fontSize", 16);
|
||||
o(this, "fontColor", "black");
|
||||
|
|
@ -171,21 +171,21 @@ class S {
|
|||
t && Object.assign(this, t);
|
||||
}
|
||||
}
|
||||
class x {
|
||||
class b {
|
||||
constructor(t, e) {
|
||||
o(this, "row");
|
||||
o(this, "column");
|
||||
this.row = t, this.column = e;
|
||||
}
|
||||
}
|
||||
class R {
|
||||
class k {
|
||||
constructor(t) {
|
||||
o(this, "value");
|
||||
o(this, "displayValue");
|
||||
/** This refers to the values that were obtained by calculations, for example, after calculating the formula */
|
||||
o(this, "resultValue");
|
||||
o(this, "position");
|
||||
o(this, "style", new S());
|
||||
o(this, "style", new R());
|
||||
this.value = t.value, this.displayValue = t.displayValue, this.resultValue = t.resultValue, this.position = t.position;
|
||||
}
|
||||
changeValues(t) {
|
||||
|
|
@ -205,7 +205,7 @@ class R {
|
|||
n -= t.viewport.top, l -= t.viewport.left, i.clearRect(l, n, s, e), i.fillStyle = c || h ? this.style.selectedBackground : this.style.background, i.strokeStyle = "black", i.fillRect(l, n, s - 1, e - 1), i.strokeRect(l, n, s, e), i.fillStyle = c || h ? this.style.selectedFontColor : this.style.fontColor, i.textAlign = "left", i.font = `${this.style.fontSize}px Arial`, i.textBaseline = "middle", i.fillText(this.displayValue, l + 2, n + e / 2);
|
||||
}
|
||||
}
|
||||
class b {
|
||||
class E {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "ctx");
|
||||
|
|
@ -225,7 +225,7 @@ class b {
|
|||
let n = 0, i = 0;
|
||||
for (; i <= t && (i += this.root.config.columns[n].width, !(i >= t)); )
|
||||
n++;
|
||||
return new x(s, n);
|
||||
return new b(s, n);
|
||||
}
|
||||
renderCell(t) {
|
||||
const { column: e, row: s } = t;
|
||||
|
|
@ -238,7 +238,7 @@ class b {
|
|||
this.renderCell({ column: i, row: n });
|
||||
}
|
||||
}
|
||||
class k {
|
||||
class I {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
|
|
@ -251,7 +251,7 @@ class k {
|
|||
this.element.style.width = s + "px", this.element.style.height = e + "px";
|
||||
}
|
||||
}
|
||||
class E {
|
||||
class V {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
|
|
@ -271,13 +271,13 @@ class d {
|
|||
this.columns = t.columns, this.rows = t.rows, this.view = t.view;
|
||||
}
|
||||
}
|
||||
class I {
|
||||
class L {
|
||||
constructor() {
|
||||
o(this, "selectedCell", null);
|
||||
o(this, "selectedRange", null);
|
||||
}
|
||||
}
|
||||
class V {
|
||||
class B {
|
||||
}
|
||||
class u {
|
||||
constructor(t, e) {
|
||||
|
|
@ -332,12 +332,12 @@ class g {
|
|||
this.height = t.height, this.title = t.title;
|
||||
}
|
||||
}
|
||||
function L(r, t, e = !1) {
|
||||
function f(r, t, e = !1) {
|
||||
const s = [];
|
||||
for (let l = 0; l <= r; l++) {
|
||||
const n = [];
|
||||
for (let i = 0; i <= t; i++) {
|
||||
const c = e ? `${l}:${i}` : "", h = new R({
|
||||
const c = e ? `${l}:${i}` : "", h = new k({
|
||||
displayValue: c,
|
||||
resultValue: c,
|
||||
value: c,
|
||||
|
|
@ -352,7 +352,7 @@ function L(r, t, e = !1) {
|
|||
}
|
||||
return s;
|
||||
}
|
||||
function B(r, t) {
|
||||
function C(r, t) {
|
||||
const e = [];
|
||||
for (let n = 0; n <= r; n++) {
|
||||
const i = new g({
|
||||
|
|
@ -378,6 +378,10 @@ function B(r, t) {
|
|||
}
|
||||
});
|
||||
}
|
||||
function z(r, t) {
|
||||
const e = f(r, t), s = C(r, t);
|
||||
return { data: e, config: s };
|
||||
}
|
||||
class A {
|
||||
constructor(t) {
|
||||
o(this, "xPos");
|
||||
|
|
@ -392,7 +396,7 @@ class M {
|
|||
this.yPos = t.yPos, this.rowIdx = t.rowIdx;
|
||||
}
|
||||
}
|
||||
class T {
|
||||
class D {
|
||||
constructor(t) {
|
||||
o(this, "columns");
|
||||
o(this, "rows");
|
||||
|
|
@ -417,7 +421,7 @@ class T {
|
|||
return e;
|
||||
}
|
||||
}
|
||||
class D {
|
||||
class F {
|
||||
constructor(t, e) {
|
||||
o(this, "table");
|
||||
o(this, "scroller");
|
||||
|
|
@ -431,10 +435,10 @@ class D {
|
|||
o(this, "viewport");
|
||||
o(this, "selection");
|
||||
o(this, "cache");
|
||||
const s = B(500, 500);
|
||||
e != null && e.view && (s.view = e.view), this.config = new d(s), this.sheet = new b(this);
|
||||
const l = L(500, 500);
|
||||
this.table = new k(this), this.scroller = new v(this), this.toolbar = new E(this), this.header = new y(this), this.editor = new p(this), this.cache = this.getInitialCache(), this.viewport = new u(this, this.scroller.getViewportBoundlingRect()), this.selection = new I(), this.data = l, this.styles = new V(), this.buildComponent(), this.appendTableToTarget(t), this.renderSheet();
|
||||
const s = C(500, 500);
|
||||
e != null && e.view && (s.view = e.view), this.config = new d(s), this.sheet = new E(this);
|
||||
const l = f(500, 500);
|
||||
this.table = new I(this), this.scroller = new x(this), this.toolbar = new V(this), this.header = new v(this), this.editor = new S(this), this.cache = this.getInitialCache(), this.viewport = new u(this, this.scroller.getViewportBoundlingRect()), this.selection = new L(), this.data = l, this.styles = new B(), this.buildComponent(), this.appendTableToTarget(t), this.renderSheet();
|
||||
}
|
||||
getInitialCache() {
|
||||
const t = [];
|
||||
|
|
@ -459,7 +463,7 @@ class D {
|
|||
});
|
||||
s.push(h);
|
||||
}
|
||||
const n = new T({
|
||||
const n = new D({
|
||||
columns: t,
|
||||
rows: s
|
||||
});
|
||||
|
|
@ -536,7 +540,7 @@ class D {
|
|||
this.data[t][e].render(this);
|
||||
}
|
||||
loadData(t) {
|
||||
this.data = t, this.config = this.makeConfigFromData(t, this.config.view), this.cache = this.getInitialCache(), this.scroller.updateScrollerSize(), this.viewport = new u(this, this.scroller.getViewportBoundlingRect()), this.renderSheet();
|
||||
return this.data = t, this.config = this.makeConfigFromData(t, this.config.view), this.cache = this.getInitialCache(), this.scroller.updateScrollerSize(), this.viewport = new u(this, this.scroller.getViewportBoundlingRect()), this.renderSheet(), this;
|
||||
}
|
||||
makeConfigFromData(t, e) {
|
||||
const s = t.length - 1, l = t[0] ? t[0].length : 0, n = [];
|
||||
|
|
@ -559,6 +563,22 @@ class D {
|
|||
}
|
||||
}
|
||||
export {
|
||||
D as Spreadsheet
|
||||
D as Cache,
|
||||
A as CachedColumn,
|
||||
M as CachedRow,
|
||||
k as Cell,
|
||||
R as CellStyles,
|
||||
m as Column,
|
||||
d as Config,
|
||||
b as Position,
|
||||
w as RenderBox,
|
||||
g as Row,
|
||||
L as Selection,
|
||||
B as Styles,
|
||||
u as Viewport,
|
||||
C as createSampleConfig,
|
||||
f as createSampleData,
|
||||
F as default,
|
||||
z as makeSpreadsheetConfigAndData
|
||||
};
|
||||
//# sourceMappingURL=main.js.map
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
export type CellConstructorProps = {
|
||||
value: string;
|
||||
displayValue: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
export type ViewportConstructorProps = {
|
||||
top: number;
|
||||
left: number;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ import { Cell } from "../modules/cell";
|
|||
import { Config } from "../modules/config";
|
||||
export declare function createSampleData(rows: number, columns: number, fillCellsByCoords?: boolean): Cell[][];
|
||||
export declare function createSampleConfig(rows: number, columns: number): Config;
|
||||
type SpreadsheetConfigAndDataReturnType = {
|
||||
export type SpreadsheetConfigAndDataReturnType = {
|
||||
config: Config;
|
||||
data: Cell[][];
|
||||
};
|
||||
export declare function makeSpreadsheetConfigAndData(rows: number, columns: number): SpreadsheetConfigAndDataReturnType;
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="spreadsheet"></div>
|
||||
<button id="save_button">Save sheet</button>
|
||||
<button id="load_button">Load sheet</button>
|
||||
<script type="module" src="/src/index.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "modern_spreadsheet",
|
||||
"private": false,
|
||||
"version": "0.0.19",
|
||||
"version": "0.0.20",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/main.js",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import Spreadsheet from "../main";
|
||||
import { Position } from "../modules/cell";
|
||||
import { RenderBox } from "../modules/renderBox";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
|
||||
export class Header {
|
||||
element: HTMLHeadElement
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
|
||||
export interface ViewportRect {
|
||||
top: number
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
import { Position } from "../modules/cell"
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
import { ViewProperties } from "../modules/config"
|
||||
|
||||
/** Base (root) component */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
|
||||
export class Toolbar {
|
||||
element: HTMLDivElement
|
||||
|
|
|
|||
24
src/index.ts
24
src/index.ts
|
|
@ -1,5 +1,23 @@
|
|||
import Spreadsheet, { createSampleData, } from './main'
|
||||
import Spreadsheet from './main'
|
||||
|
||||
const sheet = new Spreadsheet('#spreadsheet').loadData(createSampleData(20, 20, true))
|
||||
const saveButton = document.querySelector('#save_button')
|
||||
const loadButton = document.querySelector('#load_button')
|
||||
|
||||
console.log(sheet)
|
||||
if(!saveButton || !loadButton) throw new Error("LOST")
|
||||
|
||||
const sheet = new Spreadsheet('#spreadsheet')
|
||||
|
||||
function saveDataToLS() {
|
||||
const serializableData = sheet.serializeData()
|
||||
localStorage.setItem('sheet', JSON.stringify(serializableData))
|
||||
}
|
||||
|
||||
function loadDataFromLS() {
|
||||
const data = localStorage.getItem('sheet')
|
||||
if(!data) return
|
||||
const json = JSON.parse(data)
|
||||
sheet.loadData(json)
|
||||
}
|
||||
|
||||
saveButton.addEventListener('click', saveDataToLS)
|
||||
loadButton.addEventListener('click', loadDataFromLS)
|
||||
53
src/main.ts
53
src/main.ts
|
|
@ -4,7 +4,7 @@ import { Scroller } from "./components/scroller";
|
|||
import { Sheet } from "./components/sheet";
|
||||
import { Table } from "./components/table";
|
||||
import { Toolbar } from "./components/toolbar";
|
||||
import { Cell, CellConstructorProps, Position } from "./modules/cell";
|
||||
import { Cell, CellConstructorProps, Position, SerializableCell } from "./modules/cell";
|
||||
import { Config, ViewProperties } from "./modules/config";
|
||||
import { RangeSelectionType, Selection } from "./modules/selection";
|
||||
import { Styles } from "./modules/styles";
|
||||
|
|
@ -47,14 +47,15 @@ export default class Spreadsheet {
|
|||
public cache: Cache
|
||||
|
||||
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
|
||||
const config = createSampleConfig(500, 500)
|
||||
const data = createSampleData(40, 40)
|
||||
const config = this.makeConfigFromData(data, props?.view ?? { height: 600, width: 800 })
|
||||
if (props?.view) {
|
||||
config.view = props.view
|
||||
}
|
||||
|
||||
this.config = new Config(config)
|
||||
this.sheet = new Sheet(this)
|
||||
const data = createSampleData(500, 500)
|
||||
|
||||
this.table = new Table(this)
|
||||
this.scroller = new Scroller(this)
|
||||
this.toolbar = new Toolbar(this)
|
||||
|
|
@ -209,9 +210,32 @@ export default class Spreadsheet {
|
|||
this.data[row][col].render(this)
|
||||
}
|
||||
|
||||
public loadData(data: Cell[][]): Spreadsheet {
|
||||
this.data = data
|
||||
this.config = this.makeConfigFromData(data, this.config.view)
|
||||
public loadData(data: Cell[][] | SerializableCell[][]): Spreadsheet {
|
||||
const rowsLength = data.length
|
||||
const colsLength = data[0] ? this.data[0].length : 0
|
||||
this.data = []
|
||||
|
||||
const formattedData: Cell[][] = []
|
||||
|
||||
for (let row = 0; row < rowsLength; row++) {
|
||||
const innerRow: Cell[] = []
|
||||
for (let col = 0; col < colsLength; col++) {
|
||||
const cell = data[row][col]
|
||||
innerRow.push(new Cell({
|
||||
displayValue: cell.displayValue,
|
||||
position: cell.position,
|
||||
resultValue: cell.resultValue,
|
||||
value: cell.value
|
||||
}))
|
||||
}
|
||||
formattedData.push(innerRow)
|
||||
}
|
||||
|
||||
this.data = formattedData
|
||||
|
||||
this.selection.selectedCell = null
|
||||
this.selection.selectedRange = null
|
||||
this.config = this.makeConfigFromData(formattedData, this.config.view)
|
||||
this.cache = this.getInitialCache()
|
||||
this.scroller.updateScrollerSize()
|
||||
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
|
||||
|
|
@ -249,6 +273,23 @@ export default class Spreadsheet {
|
|||
|
||||
return config
|
||||
}
|
||||
|
||||
public serializeData(): SerializableCell[][] {
|
||||
const rowsLength = this.data.length
|
||||
const colsLength = this.data[0] ? this.data[0].length : 0
|
||||
|
||||
const cellsArray: SerializableCell[][] = []
|
||||
|
||||
for (let row = 0; row < rowsLength; row++) {
|
||||
const innerRow: SerializableCell[] = []
|
||||
for (let col = 0; col < colsLength; col++) {
|
||||
innerRow.push(this.data[row][col].getSerializableCell())
|
||||
}
|
||||
cellsArray.push(innerRow)
|
||||
}
|
||||
|
||||
return cellsArray
|
||||
}
|
||||
}
|
||||
|
||||
export * from './modules/cache'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
import { RenderBox } from "./renderBox"
|
||||
|
||||
export type CellConstructorProps = {
|
||||
|
|
@ -43,6 +43,21 @@ export class Position {
|
|||
}
|
||||
}
|
||||
|
||||
export class SerializableCell {
|
||||
value: string
|
||||
displayValue: string
|
||||
resultValue: string
|
||||
position: Position
|
||||
style: CellStyles
|
||||
constructor(props: SerializableCell | SerializableCell) {
|
||||
this.value = props.value
|
||||
this.displayValue = props.displayValue
|
||||
this.resultValue = props.resultValue
|
||||
this.position = props.position
|
||||
this.style = props.style
|
||||
}
|
||||
}
|
||||
|
||||
export class Cell {
|
||||
value: string
|
||||
displayValue: string
|
||||
|
|
@ -58,6 +73,17 @@ export class Cell {
|
|||
this.position = props.position
|
||||
}
|
||||
|
||||
public getSerializableCell(): SerializableCell {
|
||||
const cell:SerializableCell = new SerializableCell({
|
||||
displayValue: this.displayValue,
|
||||
position: this.position,
|
||||
resultValue: this.resultValue,
|
||||
style: this.style,
|
||||
value: this.value
|
||||
})
|
||||
return cell
|
||||
}
|
||||
|
||||
changeValues(values: Partial<Omit<CellConstructorProps, 'position'>>) {
|
||||
Object.assign(this, values)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
import Spreadsheet from "../main"
|
||||
|
||||
export type ViewportConstructorProps = {
|
||||
top: number
|
||||
|
|
|
|||
Loading…
Reference in New Issue