parent
c26c166295
commit
ae0f8b49e6
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -12,7 +12,7 @@ class P {
|
||||||
var c, a;
|
var c, a;
|
||||||
if (t.button !== 0)
|
if (t.button !== 0)
|
||||||
return;
|
return;
|
||||||
const { offsetX: o, offsetY: l } = t, i = this.root.getCellByCoords(o, l), n = this.root.getCell(i), h = new v();
|
const { offsetX: o, offsetY: l } = t, i = this.root.getCellByCoords(o, l), n = this.root.getCell(i), h = new S();
|
||||||
h.selectedCell = i, h.selectedRange = {
|
h.selectedCell = i, h.selectedRange = {
|
||||||
from: i,
|
from: i,
|
||||||
to: i
|
to: i
|
||||||
|
|
@ -108,7 +108,7 @@ class T {
|
||||||
});
|
});
|
||||||
this.root = t;
|
this.root = t;
|
||||||
const e = document.createElement("input");
|
const e = document.createElement("input");
|
||||||
e.classList.add(f + "editor"), this.element = e, this.hide();
|
e.classList.add(C + "editor"), this.element = e, this.hide();
|
||||||
}
|
}
|
||||||
hide() {
|
hide() {
|
||||||
this.element.style.display = "none", this.element.classList.add("hide"), this.element.blur(), window.removeEventListener("click", this.handleClickOutside), this.element.removeEventListener("keydown", this.handleKeydown), this.root.focusTable();
|
this.element.style.display = "none", this.element.classList.add("hide"), this.element.blur(), window.removeEventListener("click", this.handleClickOutside), this.element.removeEventListener("keydown", this.handleKeydown), this.root.focusTable();
|
||||||
|
|
@ -118,7 +118,7 @@ class T {
|
||||||
this.element.classList.remove("hide"), this.element.style.top = n - this.root.viewport.top + this.root.columnsBarHeight + "px", this.element.style.left = i - this.root.viewport.left + this.root.rowsBarWidth + "px", this.element.style.width = l + "px", this.element.style.height = o + "px", this.element.style.display = "block", window.addEventListener("click", this.handleClickOutside), this.element.addEventListener("keydown", this.handleKeydown), this.element.value = e || h.value, this.element.focus(), e || this.element.select();
|
this.element.classList.remove("hide"), this.element.style.top = n - this.root.viewport.top + this.root.columnsBarHeight + "px", this.element.style.left = i - this.root.viewport.left + this.root.rowsBarWidth + "px", this.element.style.width = l + "px", this.element.style.height = o + "px", this.element.style.display = "block", window.addEventListener("click", this.handleClickOutside), this.element.addEventListener("keydown", this.handleKeydown), this.element.value = e || h.value, this.element.focus(), e || this.element.select();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function S(r, t) {
|
function v(r, t) {
|
||||||
return r.column === t.column && r.row === t.row;
|
return r.column === t.column && r.row === t.row;
|
||||||
}
|
}
|
||||||
class H {
|
class H {
|
||||||
|
|
@ -133,7 +133,7 @@ class H {
|
||||||
return;
|
return;
|
||||||
const { offsetX: e, offsetY: o } = t, l = this.root.getCellByCoords(e, o);
|
const { offsetX: e, offsetY: o } = t, l = this.root.getCellByCoords(e, o);
|
||||||
let i = !1;
|
let i = !1;
|
||||||
this.root.selection.selectedRange && (i = !S(this.root.selection.selectedRange.to, l), i && (this.root.selection.selectedRange.to = l, this.root.events.dispatch({
|
this.root.selection.selectedRange && (i = !v(this.root.selection.selectedRange.to, l), i && (this.root.selection.selectedRange.to = l, this.root.events.dispatch({
|
||||||
type: u.SELECTION_CHANGE,
|
type: u.SELECTION_CHANGE,
|
||||||
selection: this.root.selection,
|
selection: this.root.selection,
|
||||||
enableCallback: !0
|
enableCallback: !0
|
||||||
|
|
@ -142,7 +142,7 @@ class H {
|
||||||
s(this, "handleMouseUp", () => {
|
s(this, "handleMouseUp", () => {
|
||||||
this.isSelecting = !1;
|
this.isSelecting = !1;
|
||||||
const t = { ...this.root.selection };
|
const t = { ...this.root.selection };
|
||||||
this.root.selection.selectedRange && S(this.root.selection.selectedRange.from, this.root.selection.selectedRange.to) && (t.selectedRange = null, this.root.events.dispatch({
|
this.root.selection.selectedRange && v(this.root.selection.selectedRange.from, this.root.selection.selectedRange.to) && (t.selectedRange = null, this.root.events.dispatch({
|
||||||
type: u.SELECTION_CHANGE,
|
type: u.SELECTION_CHANGE,
|
||||||
selection: t,
|
selection: t,
|
||||||
enableCallback: !1
|
enableCallback: !1
|
||||||
|
|
@ -191,7 +191,7 @@ class H {
|
||||||
if (t.key === "Delete" && (t.preventDefault(), this.root.deleteSelectedCellsValues(), this.root.renderSheet()), t.metaKey || t.ctrlKey) {
|
if (t.key === "Delete" && (t.preventDefault(), this.root.deleteSelectedCellsValues(), this.root.renderSheet()), t.metaKey || t.ctrlKey) {
|
||||||
if (t.code === "KeyC") {
|
if (t.code === "KeyC") {
|
||||||
let o;
|
let o;
|
||||||
const l = new v();
|
const l = new S();
|
||||||
if (this.root.selection.selectedRange) {
|
if (this.root.selection.selectedRange) {
|
||||||
const { from: i, to: n } = this.root.selection.selectedRange;
|
const { from: i, to: n } = this.root.selection.selectedRange;
|
||||||
l.selectedRange = this.root.selection.selectedRange, o = [...this.root.data.slice(i.row, n.row + 1).map((a) => a.slice(i.column, n.column + 1))];
|
l.selectedRange = this.root.selection.selectedRange, o = [...this.root.data.slice(i.row, n.row + 1).map((a) => a.slice(i.column, n.column + 1))];
|
||||||
|
|
@ -240,7 +240,7 @@ class H {
|
||||||
}
|
}
|
||||||
buildComponent() {
|
buildComponent() {
|
||||||
const t = document.createElement("div"), e = document.createElement("div"), o = document.createElement("div"), l = document.createElement("div"), i = document.createElement("div");
|
const t = document.createElement("div"), e = document.createElement("div"), o = document.createElement("div"), l = document.createElement("div"), i = document.createElement("div");
|
||||||
return e.style.width = "0px", e.style.pointerEvents = "none", o.style.pointerEvents = "none", l.style.display = "flex", i.appendChild(e), i.appendChild(o), l.appendChild(i), this.verticalScroller = e, this.horizontalScroller = o, t.appendChild(l), t.contentEditable = "false", t.classList.add(f + "scroller"), { scroller: t, verticalScroller: e, horizontalScroller: o };
|
return e.style.width = "0px", e.style.pointerEvents = "none", o.style.pointerEvents = "none", l.style.display = "flex", i.appendChild(e), i.appendChild(o), l.appendChild(i), this.verticalScroller = e, this.horizontalScroller = o, t.appendChild(l), t.contentEditable = "false", t.classList.add(C + "scroller"), { scroller: t, verticalScroller: e, horizontalScroller: o };
|
||||||
}
|
}
|
||||||
getActualHeight() {
|
getActualHeight() {
|
||||||
return this.root.config.rows.reduce((t, e) => (t += e.height, t), 0);
|
return this.root.config.rows.reduce((t, e) => (t += e.height, t), 0);
|
||||||
|
|
@ -270,14 +270,14 @@ class R {
|
||||||
t && Object.assign(this, t);
|
t && Object.assign(this, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class D {
|
class M {
|
||||||
constructor(t, e) {
|
constructor(t, e) {
|
||||||
s(this, "row");
|
s(this, "row");
|
||||||
s(this, "column");
|
s(this, "column");
|
||||||
this.row = t, this.column = e;
|
this.row = t, this.column = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class M {
|
class _ {
|
||||||
constructor(t) {
|
constructor(t) {
|
||||||
s(this, "value");
|
s(this, "value");
|
||||||
s(this, "displayValue");
|
s(this, "displayValue");
|
||||||
|
|
@ -300,7 +300,7 @@ class p {
|
||||||
this.value = t.value, this.displayValue = t.displayValue, this.resultValue = t.resultValue, this.position = t.position, this.style = t.style;
|
this.value = t.value, this.displayValue = t.displayValue, this.resultValue = t.resultValue, this.position = t.position, this.style = t.style;
|
||||||
}
|
}
|
||||||
getSerializableCell() {
|
getSerializableCell() {
|
||||||
return new M({
|
return new _({
|
||||||
displayValue: this.displayValue,
|
displayValue: this.displayValue,
|
||||||
position: this.position,
|
position: this.position,
|
||||||
resultValue: this.resultValue,
|
resultValue: this.resultValue,
|
||||||
|
|
@ -335,14 +335,14 @@ class p {
|
||||||
h.clearRect(o, l, n, i), h.fillStyle = c.background, h.strokeStyle = "black", h.fillRect(o, l, n - 1, i - 1), h.strokeRect(o, l, n, i), h.fillStyle = c.fontColor, h.textAlign = "left", h.font = `${c.fontSize}px Arial`, h.textBaseline = "middle", h.fillText(this.displayValue, o + 2, l + i / 2);
|
h.clearRect(o, l, n, i), h.fillStyle = c.background, h.strokeStyle = "black", h.fillRect(o, l, n - 1, i - 1), h.strokeRect(o, l, n, i), h.fillStyle = c.fontColor, h.textAlign = "left", h.font = `${c.fontSize}px Arial`, h.textBaseline = "middle", h.fillText(this.displayValue, o + 2, l + i / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class _ {
|
class D {
|
||||||
constructor(t) {
|
constructor(t) {
|
||||||
s(this, "element");
|
s(this, "element");
|
||||||
s(this, "ctx");
|
s(this, "ctx");
|
||||||
s(this, "root");
|
s(this, "root");
|
||||||
this.root = t;
|
this.root = t;
|
||||||
const e = document.createElement("canvas");
|
const e = document.createElement("canvas");
|
||||||
e.classList.add(f + "sheet"), e.height = this.root.config.view.height, e.width = this.root.config.view.width, e.style.width = this.root.config.view.width + "px", e.style.height = this.root.config.view.height + "px", e.style.left = "0px", this.element = e;
|
e.classList.add(C + "sheet"), e.height = this.root.config.view.height, e.width = this.root.config.view.width, e.style.width = this.root.config.view.width + "px", e.style.height = this.root.config.view.height + "px", e.style.left = "0px", this.element = e;
|
||||||
const o = this.element.getContext("2d");
|
const o = this.element.getContext("2d");
|
||||||
if (!o)
|
if (!o)
|
||||||
throw new Error("Enable hardware acceleration");
|
throw new Error("Enable hardware acceleration");
|
||||||
|
|
@ -355,7 +355,7 @@ class _ {
|
||||||
let i = 0, n = 0;
|
let i = 0, n = 0;
|
||||||
for (; n <= t && (n += this.root.config.columns[i].width, !(n >= t)); )
|
for (; n <= t && (n += this.root.config.columns[i].width, !(n >= t)); )
|
||||||
i++;
|
i++;
|
||||||
return new D(o, i);
|
return new M(o, i);
|
||||||
}
|
}
|
||||||
renderCell(t) {
|
renderCell(t) {
|
||||||
const { column: e, row: o } = t;
|
const { column: e, row: o } = t;
|
||||||
|
|
@ -375,8 +375,8 @@ class _ {
|
||||||
let a = 0;
|
let a = 0;
|
||||||
for (let d = o; d <= i; d++)
|
for (let d = o; d <= i; d++)
|
||||||
a += this.root.config.rows[d].height;
|
a += this.root.config.rows[d].height;
|
||||||
const m = h.x - this.root.viewport.left, C = h.y - this.root.viewport.top;
|
const f = h.x - this.root.viewport.left, m = h.y - this.root.viewport.top;
|
||||||
return { x: m, y: C, height: a, width: c };
|
return { x: f, y: m, height: a, width: c };
|
||||||
}
|
}
|
||||||
if (!e && t) {
|
if (!e && t) {
|
||||||
const o = new g(this.root.config, t);
|
const o = new g(this.root.config, t);
|
||||||
|
|
@ -385,7 +385,7 @@ class _ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderSelectionRange(t, e, o, l) {
|
renderSelectionRange(t, e, o, l) {
|
||||||
this.ctx.save(), this.ctx.strokeStyle = "#47d1ff", this.ctx.lineWidth = 3, this.ctx.strokeRect(t, e, o, l), this.ctx.fillStyle = "#7da8ff50", this.ctx.fillRect(t, e, o, l), this.ctx.restore();
|
this.ctx.save(), this.ctx.strokeStyle = "#7da8ff", this.ctx.lineWidth = 3, this.ctx.strokeRect(t, e, o, l), this.ctx.fillStyle = "#7da8ff35", this.ctx.fillRect(t, e, o, l), this.ctx.restore();
|
||||||
}
|
}
|
||||||
renderSelection() {
|
renderSelection() {
|
||||||
const t = this.getSelectionRange();
|
const t = this.getSelectionRange();
|
||||||
|
|
@ -408,21 +408,21 @@ class z {
|
||||||
s(this, "root");
|
s(this, "root");
|
||||||
this.root = t;
|
this.root = t;
|
||||||
const e = document.createElement("div");
|
const e = document.createElement("div");
|
||||||
e.classList.add(f + "spreadsheet_container"), this.element = e, this.changeElementSizes(this.root.viewProps);
|
e.classList.add(C + "spreadsheet_container"), this.element = e, this.changeElementSizes(this.root.viewProps);
|
||||||
}
|
}
|
||||||
changeElementSizes(t) {
|
changeElementSizes(t) {
|
||||||
const { height: e, width: o } = t;
|
const { height: e, width: o } = t;
|
||||||
this.element.style.width = o + this.root.rowsBarWidth + "px", this.element.style.height = e + this.root.columnsBarHeight + "px";
|
this.element.style.width = o + this.root.rowsBarWidth + "px", this.element.style.height = e + this.root.columnsBarHeight + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class O {
|
class N {
|
||||||
constructor(t) {
|
constructor(t) {
|
||||||
s(this, "element");
|
s(this, "element");
|
||||||
s(this, "root");
|
s(this, "root");
|
||||||
s(this, "height", 0);
|
s(this, "height", 0);
|
||||||
this.root = t;
|
this.root = t;
|
||||||
const e = document.createElement("div");
|
const e = document.createElement("div");
|
||||||
e.classList.add(f + "toolbar"), this.element = e;
|
e.classList.add(C + "toolbar"), this.element = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class x {
|
class x {
|
||||||
|
|
@ -440,13 +440,13 @@ class x {
|
||||||
this.columns = t.columns, this.rows = t.rows, this.view = t.view, this.onCellClick = t.onCellClick ?? null, this.onSelectonChange = t.onSelectionChange ?? null, this.onCellChange = t.onCellChange ?? null, this.onCopy = t.onCopy ?? null;
|
this.columns = t.columns, this.rows = t.rows, this.view = t.view, this.onCellClick = t.onCellClick ?? null, this.onSelectonChange = t.onSelectionChange ?? null, this.onCellChange = t.onCellChange ?? null, this.onCopy = t.onCopy ?? null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class v {
|
class S {
|
||||||
constructor() {
|
constructor() {
|
||||||
s(this, "selectedCell", null);
|
s(this, "selectedCell", null);
|
||||||
s(this, "selectedRange", null);
|
s(this, "selectedRange", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class N {
|
class O {
|
||||||
constructor() {
|
constructor() {
|
||||||
s(this, "cells");
|
s(this, "cells");
|
||||||
this.cells = new R();
|
this.cells = new R();
|
||||||
|
|
@ -578,20 +578,14 @@ class Y {
|
||||||
}
|
}
|
||||||
getRowByYCoord(t) {
|
getRowByYCoord(t) {
|
||||||
let e = 0;
|
let e = 0;
|
||||||
for (let o = 0; o < this.rows.length; o++)
|
for (let o = 0; o < this.rows.length && (e = o, !(t <= this.rows[o].yPos)); o++)
|
||||||
if (t <= this.rows[o].yPos) {
|
;
|
||||||
e = o;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
getColumnByXCoord(t) {
|
getColumnByXCoord(t) {
|
||||||
let e = 0;
|
let e = 0;
|
||||||
for (let o = 0; o < this.columns.length; o++)
|
for (let o = 0; o < this.columns.length && (e = o, !(t <= this.columns[o].xPos)); o++)
|
||||||
if (t <= this.columns[o].xPos) {
|
;
|
||||||
e = o;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -736,9 +730,9 @@ class j {
|
||||||
value: w
|
value: w
|
||||||
};
|
};
|
||||||
return new p(y);
|
return new p(y);
|
||||||
})), m = a.length, C = a[0] ? a[0].length : 0;
|
})), f = a.length, m = a[0] ? a[0].length : 0;
|
||||||
for (let d = 0; d < m; d++)
|
for (let d = 0; d < f; d++)
|
||||||
for (let w = 0; w < C; w++) {
|
for (let w = 0; w < m; w++) {
|
||||||
const y = a[d][w], B = {
|
const y = a[d][w], B = {
|
||||||
column: e + w,
|
column: e + w,
|
||||||
row: o + d
|
row: o + d
|
||||||
|
|
@ -758,19 +752,19 @@ class j {
|
||||||
const i = this.saved.length, n = this.saved[0] ? this.saved[0].length : 0;
|
const i = this.saved.length, n = this.saved[0] ? this.saved[0].length : 0;
|
||||||
for (let h = 0; h < i; h++)
|
for (let h = 0; h < i; h++)
|
||||||
for (let c = 0; c < n; c++) {
|
for (let c = 0; c < n; c++) {
|
||||||
const a = this.saved[h][c], m = {
|
const a = this.saved[h][c], f = {
|
||||||
column: e + c,
|
column: e + c,
|
||||||
row: o + h
|
row: o + h
|
||||||
}, C = {
|
}, m = {
|
||||||
displayValue: a.displayValue,
|
displayValue: a.displayValue,
|
||||||
value: a.value,
|
value: a.value,
|
||||||
style: a.style
|
style: a.style
|
||||||
};
|
};
|
||||||
t.changeCellValues(m, C, !1);
|
t.changeCellValues(f, m, !1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const f = "modern_sc_";
|
const C = "modern_sc_";
|
||||||
class q {
|
class q {
|
||||||
constructor(t, e) {
|
constructor(t, e) {
|
||||||
s(this, "table");
|
s(this, "table");
|
||||||
|
|
@ -789,7 +783,7 @@ class q {
|
||||||
s(this, "events");
|
s(this, "events");
|
||||||
s(this, "clipboard");
|
s(this, "clipboard");
|
||||||
const o = L(40, 40), l = this.makeConfigFromData(o, (e == null ? void 0 : e.view) ?? { height: 600, width: 800 });
|
const o = L(40, 40), l = this.makeConfigFromData(o, (e == null ? void 0 : e.view) ?? { height: 600, width: 800 });
|
||||||
e != null && e.view && (l.view = e.view), this.config = new x(l), this.config.onCellClick = (e == null ? void 0 : e.onCellClick) ?? null, this.config.onSelectonChange = (e == null ? void 0 : e.onSelectionChange) ?? null, this.config.onCellChange = (e == null ? void 0 : e.onCellChange) ?? null, this.config.onCopy = (e == null ? void 0 : e.onCopy) ?? null, this.rowsBar = new X(this), this.columnsBar = new G(this), this.sheet = new _(this), this.table = new z(this), this.scroller = new H(this), this.toolbar = new O(this), this.editor = new T(this), this.cache = this.getInitialCache(), this.viewport = new b(this, this.scroller.getViewportBoundlingRect()), this.selection = new v(), this.events = new P(this), this.clipboard = new j(this), this.data = o, this.styles = new N(), this.buildComponent(), this.setElementsPositions(), this.appendTableToTarget(t), this.renderSheet(), this.renderColumnsBar(), this.renderRowsBar();
|
e != null && e.view && (l.view = e.view), this.config = new x(l), this.config.onCellClick = (e == null ? void 0 : e.onCellClick) ?? null, this.config.onSelectonChange = (e == null ? void 0 : e.onSelectionChange) ?? null, this.config.onCellChange = (e == null ? void 0 : e.onCellChange) ?? null, this.config.onCopy = (e == null ? void 0 : e.onCopy) ?? null, this.rowsBar = new X(this), this.columnsBar = new G(this), this.sheet = new D(this), this.table = new z(this), this.scroller = new H(this), this.toolbar = new N(this), this.editor = new T(this), this.cache = this.getInitialCache(), this.viewport = new b(this, this.scroller.getViewportBoundlingRect()), this.selection = new S(), this.events = new P(this), this.clipboard = new j(this), this.data = o, this.styles = new O(), this.buildComponent(), this.setElementsPositions(), this.appendTableToTarget(t), this.renderSheet(), this.renderColumnsBar(), this.renderRowsBar();
|
||||||
}
|
}
|
||||||
setRowsBarPosition() {
|
setRowsBarPosition() {
|
||||||
const t = this.columnsBar.height + this.toolbar.height, e = 0;
|
const t = this.columnsBar.height + this.toolbar.height, e = 0;
|
||||||
|
|
@ -832,7 +826,7 @@ class q {
|
||||||
}
|
}
|
||||||
buildComponent() {
|
buildComponent() {
|
||||||
const t = document.createElement("div");
|
const t = document.createElement("div");
|
||||||
t.style.top = this.columnsBarHeight + "px", t.style.left = this.rowsBarWidth + "px", t.appendChild(this.sheet.element), t.classList.add(f + "content"), this.table.element.appendChild(this.toolbar.element), this.table.element.appendChild(this.rowsBar.element), this.table.element.appendChild(this.columnsBar.element), this.table.element.appendChild(t), this.table.element.appendChild(this.scroller.element), this.table.element.append(this.editor.element);
|
t.style.top = this.columnsBarHeight + "px", t.style.left = this.rowsBarWidth + "px", t.appendChild(this.sheet.element), t.classList.add(C + "content"), this.table.element.appendChild(this.toolbar.element), this.table.element.appendChild(this.rowsBar.element), this.table.element.appendChild(this.columnsBar.element), this.table.element.appendChild(t), this.table.element.appendChild(this.scroller.element), this.table.element.append(this.editor.element);
|
||||||
}
|
}
|
||||||
/**Destroy spreadsheet DOM element.
|
/**Destroy spreadsheet DOM element.
|
||||||
*
|
*
|
||||||
|
|
@ -940,23 +934,24 @@ class q {
|
||||||
}
|
}
|
||||||
loadData(t) {
|
loadData(t) {
|
||||||
const e = t.length, o = t[0] ? t[0].length : 0;
|
const e = t.length, o = t[0] ? t[0].length : 0;
|
||||||
console.log("!!FORMATTED DATA", e, o, t[0]), this.data = [];
|
this.data = [];
|
||||||
const l = [];
|
const l = [];
|
||||||
for (let i = 0; i < e; i++) {
|
for (let n = 0; n < e; n++) {
|
||||||
const n = [];
|
const h = [];
|
||||||
for (let h = 0; h < o; h++) {
|
for (let c = 0; c < o; c++) {
|
||||||
const c = t[i][h];
|
const a = t[n][c];
|
||||||
n.push(new p({
|
h.push(new p({
|
||||||
displayValue: c.displayValue,
|
displayValue: a.displayValue,
|
||||||
position: c.position,
|
position: a.position,
|
||||||
resultValue: c.resultValue,
|
resultValue: a.resultValue,
|
||||||
value: c.value,
|
value: a.value,
|
||||||
style: c.style
|
style: a.style
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
l.push(n);
|
l.push(h);
|
||||||
}
|
}
|
||||||
return this.data = l, this.selection.selectedCell = null, this.selection.selectedRange = null, this.config = this.makeConfigFromData(l, this.config.view), this.cache = this.getInitialCache(), this.scroller.updateScrollerSize(), this.viewport = new b(this, this.scroller.getViewportBoundlingRect()), this.renderSheet(), this;
|
const i = this.makeConfigFromData(l, this.config.view);
|
||||||
|
return i.onCellChange = this.config.onCellChange, i.onCellClick = this.config.onCellClick, i.onCopy = this.config.onCopy, i.onSelectonChange = this.config.onSelectonChange, this.data = l, this.selection.selectedCell = null, this.selection.selectedRange = null, this.config = i, this.cache = this.getInitialCache(), this.scroller.updateScrollerSize(), this.viewport = new b(this, this.scroller.getViewportBoundlingRect()), this.renderSheet(), this;
|
||||||
}
|
}
|
||||||
makeConfigFromData(t, e) {
|
makeConfigFromData(t, e) {
|
||||||
const o = t.length - 1, l = t[0] ? t[0].length : 0, i = [];
|
const o = t.length - 1, l = t[0] ? t[0].length : 0, i = [];
|
||||||
|
|
@ -990,7 +985,7 @@ class q {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export {
|
export {
|
||||||
f as CSS_PREFIX,
|
C as CSS_PREFIX,
|
||||||
Y as Cache,
|
Y as Cache,
|
||||||
W as CachedColumn,
|
W as CachedColumn,
|
||||||
F as CachedRow,
|
F as CachedRow,
|
||||||
|
|
@ -998,12 +993,12 @@ export {
|
||||||
R as CellStyles,
|
R as CellStyles,
|
||||||
E as Column,
|
E as Column,
|
||||||
x as Config,
|
x as Config,
|
||||||
D as Position,
|
M as Position,
|
||||||
g as RenderBox,
|
g as RenderBox,
|
||||||
k as Row,
|
k as Row,
|
||||||
v as Selection,
|
S as Selection,
|
||||||
M as SerializableCell,
|
_ as SerializableCell,
|
||||||
N as Styles,
|
O as Styles,
|
||||||
b as Viewport,
|
b as Viewport,
|
||||||
K as createSampleConfig,
|
K as createSampleConfig,
|
||||||
L as createSampleData,
|
L as createSampleData,
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "modern_spreadsheet",
|
"name": "modern_spreadsheet",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "0.0.32",
|
"version": "0.0.33",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/main.js",
|
"import": "./dist/main.js",
|
||||||
|
|
@ -55,5 +55,8 @@
|
||||||
"tslib": "^2.6.0",
|
"tslib": "^2.6.0",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.4.0"
|
"vite": "^4.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"fast-formula-parser": "^1.0.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1511
pnpm-lock.yaml
1511
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -169,7 +169,7 @@ export class Scroller {
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Start typings
|
//* Start typings
|
||||||
const keysRegex = /^([a-z]|[а-я]|[0-9])$/;
|
const keysRegex = /^([a-z]|[а-я]|[0-9]|=)$/;
|
||||||
if (!event.metaKey && !event.ctrlKey) {
|
if (!event.metaKey && !event.ctrlKey) {
|
||||||
//* Prevent handle shortcutrs
|
//* Prevent handle shortcutrs
|
||||||
const isPressedLetterKey = keysRegex.test(event.key.toLowerCase());
|
const isPressedLetterKey = keysRegex.test(event.key.toLowerCase());
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import Spreadsheet, { SpreadsheetConstructorProperties, createSampleData } from "./main";
|
import Spreadsheet, { SpreadsheetConstructorProperties } from "./main";
|
||||||
|
|
||||||
const options: SpreadsheetConstructorProperties = {
|
const options: SpreadsheetConstructorProperties = {
|
||||||
onCellClick: (event, cell) => {
|
onCellClick: (event, cell) => {
|
||||||
|
|
@ -17,9 +17,6 @@ const options: SpreadsheetConstructorProperties = {
|
||||||
|
|
||||||
const sheet = new Spreadsheet("#spreadsheet", options);
|
const sheet = new Spreadsheet("#spreadsheet", options);
|
||||||
|
|
||||||
const data = createSampleData(600, 800, true)
|
|
||||||
sheet.loadData(data)
|
|
||||||
|
|
||||||
function saveDataToLS() {
|
function saveDataToLS() {
|
||||||
const serializableData = sheet.serializeData();
|
const serializableData = sheet.serializeData();
|
||||||
localStorage.setItem("sheet", JSON.stringify(serializableData));
|
localStorage.setItem("sheet", JSON.stringify(serializableData));
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import { ColumnsBar } from "./components/columnsBar";
|
||||||
import { RowsBar } from "./components/rowsBar";
|
import { RowsBar } from "./components/rowsBar";
|
||||||
import { EventTypes, Events } from "./modules/events";
|
import { EventTypes, Events } from "./modules/events";
|
||||||
import { Clipboard } from "./modules/clipboard";
|
import { Clipboard } from "./modules/clipboard";
|
||||||
|
import { FormulaParser } from "./modules/formulaParser";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
! Component structure
|
! Component structure
|
||||||
|
|
@ -69,6 +70,7 @@ export default class Spreadsheet {
|
||||||
public cache: Cache;
|
public cache: Cache;
|
||||||
public events: Events;
|
public events: Events;
|
||||||
public clipboard: Clipboard;
|
public clipboard: Clipboard;
|
||||||
|
public formulaParser: FormulaParser
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
target: string | HTMLElement,
|
target: string | HTMLElement,
|
||||||
|
|
@ -105,6 +107,7 @@ export default class Spreadsheet {
|
||||||
this.selection = new Selection();
|
this.selection = new Selection();
|
||||||
this.events = new Events(this);
|
this.events = new Events(this);
|
||||||
this.clipboard = new Clipboard(this);
|
this.clipboard = new Clipboard(this);
|
||||||
|
this.formulaParser = new FormulaParser(this)
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.styles = new Styles();
|
this.styles = new Styles();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import Spreadsheet from "../main";
|
import Spreadsheet from "../main";
|
||||||
|
import { FormulaParser } from "./formulaParser";
|
||||||
import { RenderBox } from "./renderBox";
|
import { RenderBox } from "./renderBox";
|
||||||
|
|
||||||
export type CellConstructorProps = {
|
export type CellConstructorProps = {
|
||||||
|
|
@ -69,6 +70,9 @@ export class Cell {
|
||||||
position: Position;
|
position: Position;
|
||||||
style: CellStyles | null = null;
|
style: CellStyles | null = null;
|
||||||
|
|
||||||
|
cellsDependsOnThisCell: Position[] = []
|
||||||
|
dependedFromCells: Position[] = []
|
||||||
|
|
||||||
constructor(props: CellConstructorProps) {
|
constructor(props: CellConstructorProps) {
|
||||||
this.value = props.value;
|
this.value = props.value;
|
||||||
this.displayValue = props.displayValue;
|
this.displayValue = props.displayValue;
|
||||||
|
|
@ -96,6 +100,15 @@ export class Cell {
|
||||||
Object.assign(this, values);
|
Object.assign(this, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evalFormula(parser: FormulaParser) {
|
||||||
|
if (this.value.substring(0, 1) !== '=') return;
|
||||||
|
|
||||||
|
this.resultValue = parser.parser.parse(this.value.slice(1), {
|
||||||
|
col: this.position.column,
|
||||||
|
row: this.position.row
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// private isCellInRange(root: Spreadsheet): boolean {
|
// private isCellInRange(root: Spreadsheet): boolean {
|
||||||
// const { column, row } = this.position;
|
// const { column, row } = this.position;
|
||||||
// const { selectedRange } = root.selection;
|
// const { selectedRange } = root.selection;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export type ActionTypes =
|
||||||
| ChangeCellEvent
|
| ChangeCellEvent
|
||||||
| CopyAction;
|
| CopyAction;
|
||||||
|
|
||||||
|
|
||||||
export class Events {
|
export class Events {
|
||||||
root: Spreadsheet;
|
root: Spreadsheet;
|
||||||
|
|
||||||
|
|
@ -46,7 +47,7 @@ export class Events {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(action: ActionTypes) {
|
async dispatch(action: ActionTypes) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case EventTypes.CELL_CLICK: {
|
case EventTypes.CELL_CLICK: {
|
||||||
const { event, scroller } = action;
|
const { event, scroller } = action;
|
||||||
|
|
@ -68,9 +69,20 @@ export class Events {
|
||||||
|
|
||||||
case EventTypes.CELL_CHANGE: {
|
case EventTypes.CELL_CHANGE: {
|
||||||
const { cell, enableCallback } = action;
|
const { cell, enableCallback } = action;
|
||||||
//
|
if (cell.value.substring(0, 1).startsWith('=')) {
|
||||||
//* Here may be side effects
|
try {
|
||||||
//
|
await cell.evalFormula(this.root.formulaParser)
|
||||||
|
cell.displayValue = cell.resultValue
|
||||||
|
this.root.renderCell(cell.position.row, cell.position.column)
|
||||||
|
this.changeCellValues(cell, enableCallback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.root.renderCell(cell.position.row, cell.position.column)
|
||||||
this.changeCellValues(cell, enableCallback);
|
this.changeCellValues(cell, enableCallback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import Parser, { DepParser } from 'fast-formula-parser'
|
||||||
|
import Spreadsheet from '../main'
|
||||||
|
|
||||||
|
export class FormulaParser {
|
||||||
|
parser: Parser
|
||||||
|
depParser: DepParser
|
||||||
|
root: Spreadsheet
|
||||||
|
constructor(root: Spreadsheet) {
|
||||||
|
this.root = root
|
||||||
|
|
||||||
|
this.parser = new Parser({
|
||||||
|
onCell: ({col, row}) => {
|
||||||
|
const cell = this.root.data[row - 1][col - 1]
|
||||||
|
const cellValue = cell.resultValue.length > 0 ? cell.resultValue : cell.value
|
||||||
|
if( cellValue && isNaN(Number(cellValue)) === false) return Number(cellValue)
|
||||||
|
return this.root.data[row - 1][col - 1].resultValue ?? ''
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
this.depParser = new DepParser({})
|
||||||
|
this.depParser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
declare module 'fast-formula-parser' {
|
||||||
|
export type PositionWithSheet = {
|
||||||
|
sheet?: string
|
||||||
|
row: number
|
||||||
|
col: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FunctionArgument = {
|
||||||
|
isArray: boolean
|
||||||
|
isCellRef: boolean
|
||||||
|
isRangeRef: boolean
|
||||||
|
value: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Position = {
|
||||||
|
col: number
|
||||||
|
row: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RangeReference = {
|
||||||
|
sheet?: string
|
||||||
|
from: Position,
|
||||||
|
to: Position
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Config = {
|
||||||
|
functions?: Record<string, (...args: FunctionArgument[]) => string>
|
||||||
|
functionsNeedContext?: (context: Parser, ...args: FunctionArgument[]) => string
|
||||||
|
onCell?: (position: PositionWithSheet) => number | string
|
||||||
|
onRange?: (ref) => Array<string|number>[]
|
||||||
|
onVariable?: (name: string, sheetName: string) => RangeReference
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Types = {
|
||||||
|
NUMBER: 0,
|
||||||
|
ARRAY: 1,
|
||||||
|
BOOLEAN: 2,
|
||||||
|
STRING: 3,
|
||||||
|
RANGE_REF: 4, // can be 'A:C' or '1:4', not only 'A1:C3'
|
||||||
|
CELL_REF: 5,
|
||||||
|
COLLECTIONS: 6, // Unions of references
|
||||||
|
NUMBER_NO_BOOLEAN: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Factorials: number[]
|
||||||
|
|
||||||
|
export default class Parser {
|
||||||
|
constructor(config: Config)
|
||||||
|
parse: (expression: string, position: PositionWithSheet) => string
|
||||||
|
parseAsync: (expression: string, position: PositionWithSheet) => Promise<string>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type FormulaHelpersType = {
|
||||||
|
accept: (param: FunctionArgument, type?: number, defValue?: number | string, flat?: boolean, allowSingleValue?: boolean) => number | string
|
||||||
|
type: (variable) => number
|
||||||
|
isRangeRef: (param) => boolean
|
||||||
|
isCellRef: (param) => boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DepParser {
|
||||||
|
constructor(config?: {onVariable?: (name: string, sheetName: string) => RangeReference})
|
||||||
|
parse(expression: string, position: PositionWithSheet): PositionWithSheet[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FormulaHelpers: FormulaHelpersType
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
"types": ["vite/client", "node"],
|
"types": ["vite/client", "node"],
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": false,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue