Builded first version of package
This commit is contained in:
parent
0ed3bfe324
commit
19bc67f9f2
|
|
@ -8,7 +8,6 @@ pnpm-debug.log*
|
|||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import { Position } from "../modules/cell";
|
||||
export declare class Editor {
|
||||
element: HTMLInputElement;
|
||||
root: Spreadsheet;
|
||||
constructor(root: Spreadsheet);
|
||||
hide(): void;
|
||||
show(position: Position): void;
|
||||
handleKeydown: (event: KeyboardEvent) => void;
|
||||
handleClickOutside: (event: MouseEvent) => void;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
export declare class Header {
|
||||
element: HTMLHeadElement;
|
||||
root: Spreadsheet;
|
||||
constructor(root: Spreadsheet);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
export interface ViewportRect {
|
||||
top: number;
|
||||
left: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
}
|
||||
export declare class Scroller {
|
||||
element: HTMLDivElement;
|
||||
private verticalScroller;
|
||||
private horizontalScroller;
|
||||
private root;
|
||||
private isSelecting;
|
||||
constructor(root: Spreadsheet);
|
||||
private handleMouseMove;
|
||||
private handleMouseUp;
|
||||
private handleDoubleClick;
|
||||
private handleKeydown;
|
||||
private handleClick;
|
||||
private handleScroll;
|
||||
getViewportBoundlingRect(): ViewportRect;
|
||||
private buildComponent;
|
||||
private getActualHeight;
|
||||
private getActualWidth;
|
||||
updateScrollerSize(): void;
|
||||
private setScrollerHeight;
|
||||
private setScrollerWidth;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import { Position } from "../modules/cell";
|
||||
/**
|
||||
* Display (CANVAS) element where cells render
|
||||
*/
|
||||
export declare class Sheet {
|
||||
element: HTMLCanvasElement;
|
||||
ctx: CanvasRenderingContext2D;
|
||||
root: Spreadsheet;
|
||||
constructor(root: Spreadsheet);
|
||||
getCellByCoords(x: number, y: number): Position;
|
||||
renderCell(position: Position): void;
|
||||
renderSheet(): void;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
import { ViewProperties } from "../modules/config";
|
||||
/** Base (root) component */
|
||||
export declare class Table {
|
||||
element: HTMLDivElement;
|
||||
root: Spreadsheet;
|
||||
constructor(root: Spreadsheet);
|
||||
changeElementSizes(sizes: ViewProperties): void;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
export declare class Toolbar {
|
||||
element: HTMLDivElement;
|
||||
root: Spreadsheet;
|
||||
constructor(root: Spreadsheet);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,43 @@
|
|||
import { Cell, CellConstructorProps, Position } from "./modules/cell";
|
||||
import { Config, ViewProperties } from "./modules/config";
|
||||
import { RangeSelectionType, Selection } from "./modules/selection";
|
||||
import { Styles } from "./modules/styles";
|
||||
import { Viewport } from "./modules/viewport";
|
||||
import './scss/main.scss';
|
||||
import { Cache } from "./modules/cache";
|
||||
interface SpreadsheetConstructorProperties {
|
||||
config?: Omit<Config, 'view'>;
|
||||
view?: ViewProperties;
|
||||
}
|
||||
export declare class Spreadsheet {
|
||||
private table;
|
||||
private scroller;
|
||||
private toolbar;
|
||||
private header;
|
||||
private sheet;
|
||||
private editor;
|
||||
styles: Styles;
|
||||
config: Config;
|
||||
data: Cell[][];
|
||||
viewport: Viewport;
|
||||
selection: Selection;
|
||||
cache: Cache;
|
||||
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties);
|
||||
private getInitialCache;
|
||||
private buildComponent;
|
||||
private appendTableToTarget;
|
||||
get ctx(): CanvasRenderingContext2D;
|
||||
get viewProps(): ViewProperties;
|
||||
focusTable(): void;
|
||||
getCellByCoords(x: number, y: number): Position;
|
||||
getCell(position: Position): Cell;
|
||||
changeCellValues(position: Position, values: Partial<Omit<CellConstructorProps, 'position'>>): void;
|
||||
applyActionToRange(range: RangeSelectionType, callback: (cell: Cell) => any): void;
|
||||
deleteSelectedCellsValues(): void;
|
||||
showEditor(position: Position): void;
|
||||
renderSheet(): void;
|
||||
renderCell(row: number, col: number): void;
|
||||
loadData(data: Cell[][]): void;
|
||||
private makeConfigFromData;
|
||||
}
|
||||
export {};
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
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");
|
||||
o(this, "y");
|
||||
o(this, "width");
|
||||
o(this, "height");
|
||||
this.x = this.getXCoord(e.column, t), this.y = this.getYCoord(e.row, t), this.width = t.columns[e.column].width, this.height = t.rows[e.row].height;
|
||||
}
|
||||
getXCoord(t, e) {
|
||||
let s = 0;
|
||||
for (let l = 0; l < t; l++)
|
||||
s += e.columns[l].width;
|
||||
return s;
|
||||
}
|
||||
getYCoord(t, e) {
|
||||
let s = 0;
|
||||
for (let l = 0; l < t; l++)
|
||||
s += e.rows[l].height;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
class v {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
o(this, "handleKeydown", (t) => {
|
||||
const { key: e } = t;
|
||||
switch (e) {
|
||||
case "Escape": {
|
||||
this.hide();
|
||||
break;
|
||||
}
|
||||
case "Enter":
|
||||
this.root.changeCellValues(this.root.selection.selectedCell, {
|
||||
value: this.element.value,
|
||||
displayValue: this.element.value
|
||||
}), this.hide();
|
||||
}
|
||||
});
|
||||
o(this, "handleClickOutside", (t) => {
|
||||
const e = t.target;
|
||||
this.element.contains(e) || this.hide();
|
||||
});
|
||||
this.root = t;
|
||||
const e = document.createElement("input");
|
||||
e.classList.add("editor"), this.element = e, this.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();
|
||||
}
|
||||
show(t) {
|
||||
const { height: e, width: s, x: l, y: n } = new w(this.root.config, t), i = this.root.getCell(t);
|
||||
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 S {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
this.root = t;
|
||||
const e = document.createElement("header");
|
||||
e.classList.add(), this.element = e;
|
||||
}
|
||||
}
|
||||
class x {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "verticalScroller");
|
||||
o(this, "horizontalScroller");
|
||||
o(this, "root");
|
||||
o(this, "isSelecting", !1);
|
||||
o(this, "handleMouseMove", (t) => {
|
||||
if (!this.isSelecting)
|
||||
return;
|
||||
const { offsetX: e, offsetY: s } = t, l = this.root.getCellByCoords(e, s);
|
||||
this.root.selection.selectedRange && (this.root.selection.selectedRange.to = l), this.root.renderSheet();
|
||||
});
|
||||
o(this, "handleMouseUp", () => {
|
||||
this.isSelecting = !1, this.root.selection.selectedRange && this.root.selection.selectedRange.from.row === this.root.selection.selectedRange.to.row && this.root.selection.selectedRange.from.column === this.root.selection.selectedRange.to.column && (this.root.selection.selectedRange = null), this.root.renderSheet();
|
||||
});
|
||||
o(this, "handleDoubleClick", (t) => {
|
||||
t.preventDefault();
|
||||
const e = this.root.getCellByCoords(t.offsetX, t.offsetY);
|
||||
this.root.showEditor(e);
|
||||
});
|
||||
o(this, "handleKeydown", (t) => {
|
||||
if (console.log(t), ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(t.key))
|
||||
switch (t.preventDefault(), this.root.selection.selectedRange = null, t.key) {
|
||||
case "ArrowLeft": {
|
||||
this.root.selection.selectedCell && this.root.selection.selectedCell.column > 0 && (console.log("tick"), this.root.selection.selectedCell.column -= 1, this.root.renderSheet());
|
||||
break;
|
||||
}
|
||||
case "ArrowRight": {
|
||||
this.root.selection.selectedCell && this.root.selection.selectedCell.column < this.root.config.columns.length - 1 && (this.root.selection.selectedCell.column += 1, this.root.renderSheet());
|
||||
break;
|
||||
}
|
||||
case "ArrowUp": {
|
||||
this.root.selection.selectedCell && this.root.selection.selectedCell.row > 0 && (this.root.selection.selectedCell.row -= 1, this.root.renderSheet());
|
||||
break;
|
||||
}
|
||||
case "ArrowDown": {
|
||||
this.root.selection.selectedCell && this.root.selection.selectedCell.row < this.root.config.rows.length - 1 && (this.root.selection.selectedCell.row += 1, this.root.renderSheet());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!t.metaKey && !t.ctrlKey && (t.key === "F2" || /^([a-z]|[а-я])$/.test(t.key.toLowerCase()))) {
|
||||
if (t.preventDefault(), !this.root.selection.selectedCell)
|
||||
return;
|
||||
this.root.showEditor(this.root.selection.selectedCell);
|
||||
}
|
||||
t.key === "Delete" && (t.preventDefault(), this.root.deleteSelectedCellsValues(), this.root.renderSheet());
|
||||
});
|
||||
o(this, "handleClick", (t) => {
|
||||
if (t.button !== 0)
|
||||
return;
|
||||
const { offsetX: e, offsetY: s } = t, l = this.root.getCellByCoords(e, s);
|
||||
this.isSelecting = !0, this.root.selection.selectedRange = {
|
||||
from: l,
|
||||
to: l
|
||||
}, this.root.selection.selectedCell = l, this.root.renderSheet();
|
||||
});
|
||||
o(this, "handleScroll", () => {
|
||||
const t = this.getViewportBoundlingRect();
|
||||
this.root.viewport.updateValues(t), this.root.renderSheet();
|
||||
});
|
||||
this.root = t;
|
||||
const { horizontalScroller: e, scroller: s, verticalScroller: l } = this.buildComponent();
|
||||
this.element = s, this.verticalScroller = l, this.horizontalScroller = e, this.element.style.height = this.root.config.view.height + "px", this.element.style.width = this.root.config.view.width + "px", this.element.tabIndex = -1, this.updateScrollerSize(), this.element.addEventListener("scroll", this.handleScroll), this.element.addEventListener("mousedown", this.handleClick), this.element.addEventListener("mousemove", this.handleMouseMove), this.element.addEventListener("mouseup", this.handleMouseUp), this.element.addEventListener("dblclick", this.handleDoubleClick), this.element.addEventListener("keydown", this.handleKeydown);
|
||||
}
|
||||
getViewportBoundlingRect() {
|
||||
const { scrollTop: t, scrollLeft: e } = this.element, { height: s, width: l } = this.element.getBoundingClientRect(), n = t + s, i = e + l;
|
||||
return {
|
||||
top: t,
|
||||
left: e,
|
||||
bottom: n,
|
||||
right: i
|
||||
};
|
||||
}
|
||||
buildComponent() {
|
||||
const t = document.createElement("div"), e = document.createElement("div"), s = document.createElement("div"), l = document.createElement("div"), n = document.createElement("div");
|
||||
return e.style.width = "0px", e.style.pointerEvents = "none", s.style.pointerEvents = "none", l.style.display = "flex", n.appendChild(e), n.appendChild(s), l.appendChild(n), this.verticalScroller = e, this.horizontalScroller = s, t.appendChild(l), t.classList.add("scroller"), { scroller: t, verticalScroller: e, horizontalScroller: s };
|
||||
}
|
||||
getActualHeight() {
|
||||
return this.root.config.rows.reduce((t, e) => (t += e.height, t), 0);
|
||||
}
|
||||
getActualWidth() {
|
||||
return this.root.config.columns.reduce((t, e) => (t += e.width, t), 0);
|
||||
}
|
||||
updateScrollerSize() {
|
||||
const t = this.getActualHeight(), e = this.getActualWidth();
|
||||
this.setScrollerHeight(t), this.setScrollerWidth(e);
|
||||
}
|
||||
setScrollerHeight(t) {
|
||||
this.verticalScroller.style.height = t + "px";
|
||||
}
|
||||
setScrollerWidth(t) {
|
||||
this.horizontalScroller.style.width = t + "px";
|
||||
}
|
||||
}
|
||||
class R {
|
||||
constructor(t) {
|
||||
o(this, "fontSize", 16);
|
||||
o(this, "fontColor", "black");
|
||||
o(this, "background", "white");
|
||||
o(this, "borderColor", "black");
|
||||
o(this, "selectedBackground", "#4287f5");
|
||||
o(this, "selectedFontColor", "#ffffff");
|
||||
t && Object.assign(this, t);
|
||||
}
|
||||
}
|
||||
class b {
|
||||
constructor(t, e) {
|
||||
o(this, "row");
|
||||
o(this, "column");
|
||||
this.row = t, this.column = e;
|
||||
}
|
||||
}
|
||||
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 R());
|
||||
this.value = t.value, this.displayValue = t.displayValue, this.resultValue = t.resultValue, this.position = t.position;
|
||||
}
|
||||
changeValues(t) {
|
||||
Object.assign(this, t);
|
||||
}
|
||||
isCellInRange(t) {
|
||||
const { column: e, row: s } = this.position, { selectedRange: l } = t.selection;
|
||||
if (!l)
|
||||
return !1;
|
||||
const n = s >= Math.min(l.from.row, l.to.row) && s <= Math.max(l.to.row, l.from.row);
|
||||
return e >= Math.min(l.from.column, l.to.column) && e <= Math.max(l.to.column, l.from.column) && n;
|
||||
}
|
||||
render(t) {
|
||||
var a;
|
||||
let { height: e, width: s, x: l, y: n } = new w(t.config, this.position);
|
||||
const { ctx: i } = t, c = ((a = t.selection.selectedCell) == null ? void 0 : a.row) === this.position.row && t.selection.selectedCell.column === this.position.column, h = this.isCellInRange(t);
|
||||
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, s);
|
||||
}
|
||||
}
|
||||
class E {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "ctx");
|
||||
o(this, "root");
|
||||
this.root = t;
|
||||
const e = document.createElement("canvas");
|
||||
e.classList.add("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", this.element = e;
|
||||
const s = this.element.getContext("2d");
|
||||
if (!s)
|
||||
throw new Error("Enable hardware acceleration");
|
||||
this.ctx = s;
|
||||
}
|
||||
getCellByCoords(t, e) {
|
||||
let s = 0, l = 0;
|
||||
for (; l <= e && (l += this.root.config.rows[s].height, !(l >= e)); )
|
||||
s++;
|
||||
let n = 0, i = 0;
|
||||
for (; i <= t && (i += this.root.config.columns[n].width, !(i >= t)); )
|
||||
n++;
|
||||
return new b(s, n);
|
||||
}
|
||||
renderCell(t) {
|
||||
const { column: e, row: s } = t;
|
||||
this.root.data[s][e].render(this.root);
|
||||
}
|
||||
renderSheet() {
|
||||
const t = this.root.viewport.firstRow, e = this.root.viewport.lastCol + 3, s = this.root.viewport.lastRow + 3, l = this.root.viewport.firstCol;
|
||||
for (let n = t; n <= s; n++)
|
||||
for (let i = l; i <= e && !(!this.root.config.columns[i] || !this.root.config.rows[n]); i++)
|
||||
this.renderCell({ column: i, row: n });
|
||||
}
|
||||
}
|
||||
class I {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
this.root = t;
|
||||
const e = document.createElement("div");
|
||||
e.classList.add("spreadsheet_container"), this.element = e, this.changeElementSizes(this.root.viewProps);
|
||||
}
|
||||
changeElementSizes(t) {
|
||||
const { height: e, width: s } = t;
|
||||
this.element.style.width = s + "px", this.element.style.height = e + "px";
|
||||
}
|
||||
}
|
||||
class V {
|
||||
constructor(t) {
|
||||
o(this, "element");
|
||||
o(this, "root");
|
||||
this.root = t;
|
||||
const e = document.createElement("div");
|
||||
e.classList.add("toolbar"), this.element = e;
|
||||
}
|
||||
}
|
||||
class d {
|
||||
constructor(t) {
|
||||
o(this, "rows");
|
||||
o(this, "columns");
|
||||
o(this, "view", {
|
||||
width: 800,
|
||||
height: 600
|
||||
});
|
||||
this.columns = t.columns, this.rows = t.rows, this.view = t.view;
|
||||
}
|
||||
}
|
||||
class L {
|
||||
constructor() {
|
||||
o(this, "selectedCell", null);
|
||||
o(this, "selectedRange", null);
|
||||
}
|
||||
}
|
||||
class B {
|
||||
}
|
||||
class u {
|
||||
constructor(t, e) {
|
||||
o(this, "root");
|
||||
o(this, "top");
|
||||
o(this, "left");
|
||||
o(this, "right");
|
||||
o(this, "bottom");
|
||||
o(this, "firstRow");
|
||||
o(this, "lastRow");
|
||||
o(this, "firstCol");
|
||||
o(this, "lastCol");
|
||||
this.root = t, this.top = e.top, this.left = e.left, this.right = e.right, this.bottom = e.bottom, this.firstRow = this.getFirstRow(), this.lastCol = this.getFirstRow();
|
||||
//!Temp
|
||||
this.firstCol = this.getFirstRow();
|
||||
//!Temp
|
||||
this.lastRow = this.getLastRow(), this.updateValues({
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: this.root.viewProps.width,
|
||||
bottom: this.root.viewProps.height
|
||||
});
|
||||
}
|
||||
updateValues(t) {
|
||||
this.top = t.top, this.left = t.left, this.right = t.right, this.bottom = t.bottom, this.firstRow = this.getFirstRow(), this.lastRow = this.getLastRow(), this.firstCol = this.getFirstCol(), this.lastCol = this.getLastCol();
|
||||
}
|
||||
/** Get index of first row in viewport */
|
||||
getFirstRow() {
|
||||
return this.root.cache.getRowByYCoord(this.top);
|
||||
}
|
||||
getLastRow() {
|
||||
return this.root.cache.getRowByYCoord(this.bottom);
|
||||
}
|
||||
getFirstCol() {
|
||||
return this.root.cache.getColumnByXCoord(this.left);
|
||||
}
|
||||
getLastCol() {
|
||||
return this.root.cache.getColumnByXCoord(this.right);
|
||||
}
|
||||
}
|
||||
class m {
|
||||
constructor(t) {
|
||||
o(this, "width");
|
||||
o(this, "title");
|
||||
this.width = t.width, this.title = t.title;
|
||||
}
|
||||
}
|
||||
class g {
|
||||
constructor(t) {
|
||||
o(this, "height");
|
||||
o(this, "title");
|
||||
this.height = t.height, this.title = t.title;
|
||||
}
|
||||
}
|
||||
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 k({
|
||||
displayValue: c,
|
||||
resultValue: c,
|
||||
value: c,
|
||||
position: {
|
||||
column: i,
|
||||
row: l
|
||||
}
|
||||
});
|
||||
n.push(h);
|
||||
}
|
||||
s.push(n);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function A(r, t) {
|
||||
const e = [];
|
||||
for (let n = 0; n <= r; n++) {
|
||||
const i = new g({
|
||||
height: 40,
|
||||
title: String(n)
|
||||
});
|
||||
e.push(i);
|
||||
}
|
||||
const s = [];
|
||||
for (let n = 0; n <= t; n++) {
|
||||
const i = new m({
|
||||
title: String(n),
|
||||
width: 150
|
||||
});
|
||||
s.push(i);
|
||||
}
|
||||
return new d({
|
||||
columns: s,
|
||||
rows: e,
|
||||
view: {
|
||||
height: 600,
|
||||
width: 800
|
||||
}
|
||||
});
|
||||
}
|
||||
class M {
|
||||
constructor(t) {
|
||||
o(this, "xPos");
|
||||
o(this, "colIdx");
|
||||
this.xPos = t.xPos, this.colIdx = t.colIdx;
|
||||
}
|
||||
}
|
||||
class T {
|
||||
constructor(t) {
|
||||
o(this, "yPos");
|
||||
o(this, "rowIdx");
|
||||
this.yPos = t.yPos, this.rowIdx = t.rowIdx;
|
||||
}
|
||||
}
|
||||
class D {
|
||||
constructor(t) {
|
||||
o(this, "columns");
|
||||
o(this, "rows");
|
||||
this.columns = t.columns, this.rows = t.rows;
|
||||
}
|
||||
getRowByYCoord(t) {
|
||||
let e = 0;
|
||||
for (let s = 0; s < this.rows.length; s++)
|
||||
if (t <= this.rows[s].yPos) {
|
||||
e = s;
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
getColumnByXCoord(t) {
|
||||
let e = 0;
|
||||
for (let s = 0; s < this.columns.length; s++)
|
||||
if (t <= this.columns[s].xPos) {
|
||||
e = s;
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
class z {
|
||||
constructor(t, e) {
|
||||
o(this, "table");
|
||||
o(this, "scroller");
|
||||
o(this, "toolbar");
|
||||
o(this, "header");
|
||||
o(this, "sheet");
|
||||
o(this, "editor");
|
||||
o(this, "styles");
|
||||
o(this, "config");
|
||||
o(this, "data");
|
||||
o(this, "viewport");
|
||||
o(this, "selection");
|
||||
o(this, "cache");
|
||||
const s = A(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 S(this), this.editor = new v(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 = [];
|
||||
let e = 0;
|
||||
for (let i = 0; i <= this.config.columns.length - 1; i++) {
|
||||
const c = this.config.columns[i];
|
||||
e += c.width;
|
||||
const h = new M({
|
||||
xPos: e,
|
||||
colIdx: i
|
||||
});
|
||||
t.push(h);
|
||||
}
|
||||
const s = [];
|
||||
let l = 0;
|
||||
for (let i = 0; i <= this.config.rows.length - 1; i++) {
|
||||
const c = this.config.rows[i];
|
||||
l += c.height;
|
||||
const h = new T({
|
||||
yPos: l,
|
||||
rowIdx: i
|
||||
});
|
||||
s.push(h);
|
||||
}
|
||||
const n = new D({
|
||||
columns: t,
|
||||
rows: s
|
||||
});
|
||||
return console.log("CACHE: ", n), console.log("CONFIG: ", this.config), n;
|
||||
}
|
||||
buildComponent() {
|
||||
const t = document.createElement("div");
|
||||
t.appendChild(this.header.element), t.appendChild(this.sheet.element), t.classList.add("content"), this.table.element.appendChild(this.toolbar.element), this.table.element.appendChild(t), this.table.element.appendChild(this.scroller.element), this.table.element.append(this.editor.element);
|
||||
}
|
||||
appendTableToTarget(t) {
|
||||
if (typeof t == "string") {
|
||||
const e = document.querySelector(t);
|
||||
if (!e)
|
||||
throw new Error(`Element with selector ${t} is not finded in DOM.
|
||||
Make sure it exists.`);
|
||||
e == null || e.appendChild(this.table.element);
|
||||
}
|
||||
t instanceof HTMLElement && t.append(this.table.element);
|
||||
}
|
||||
get ctx() {
|
||||
return this.sheet.ctx;
|
||||
}
|
||||
get viewProps() {
|
||||
return this.config.view;
|
||||
}
|
||||
focusTable() {
|
||||
this.scroller.element.focus();
|
||||
}
|
||||
getCellByCoords(t, e) {
|
||||
return this.sheet.getCellByCoords(t, e);
|
||||
}
|
||||
getCell(t) {
|
||||
const { column: e, row: s } = t;
|
||||
return this.data[s][e];
|
||||
}
|
||||
changeCellValues(t, e) {
|
||||
const { column: s, row: l } = t;
|
||||
this.data[l][s].changeValues(e), this.renderCell(l, s);
|
||||
}
|
||||
applyActionToRange(t, e) {
|
||||
const s = Math.min(t.from.row, t.to.row), l = Math.max(t.from.row, t.to.row), n = Math.min(t.from.column, t.to.column), i = Math.max(t.from.column, t.to.column);
|
||||
for (let c = s; c <= l; c++)
|
||||
for (let h = n; h <= i; h++) {
|
||||
const a = this.data[c][h];
|
||||
e(a);
|
||||
}
|
||||
}
|
||||
deleteSelectedCellsValues() {
|
||||
if (this.selection.selectedRange !== null)
|
||||
this.applyActionToRange(this.selection.selectedRange, (t) => {
|
||||
this.changeCellValues(t.position, {
|
||||
displayValue: "",
|
||||
resultValue: "",
|
||||
value: ""
|
||||
});
|
||||
});
|
||||
else {
|
||||
if (!this.selection.selectedCell)
|
||||
return;
|
||||
this.changeCellValues(this.selection.selectedCell, {
|
||||
displayValue: "",
|
||||
resultValue: "",
|
||||
value: ""
|
||||
});
|
||||
}
|
||||
}
|
||||
showEditor(t) {
|
||||
this.editor.show(t);
|
||||
}
|
||||
renderSheet() {
|
||||
this.sheet.renderSheet();
|
||||
}
|
||||
renderCell(t, e) {
|
||||
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();
|
||||
}
|
||||
makeConfigFromData(t, e) {
|
||||
const s = t.length - 1, l = t[0] ? t[0].length : 0, n = [];
|
||||
for (let h = 0; h < s; h++)
|
||||
n.push(new g({
|
||||
height: 40,
|
||||
title: String(h)
|
||||
}));
|
||||
const i = [];
|
||||
for (let h = 0; h < l; h++)
|
||||
i.push(new m({
|
||||
width: 150,
|
||||
title: String(h)
|
||||
}));
|
||||
return new d({
|
||||
view: e,
|
||||
rows: n,
|
||||
columns: i
|
||||
});
|
||||
}
|
||||
}
|
||||
const C = new z("#spreadsheet", {
|
||||
view: {
|
||||
height: 768,
|
||||
width: 1366
|
||||
}
|
||||
}), F = f(45, 45, !0);
|
||||
C.changeCellValues({ column: 2, row: 2 }, {
|
||||
displayValue: "Loading...",
|
||||
resultValue: "Loading...",
|
||||
value: "Loading..."
|
||||
});
|
||||
setTimeout(() => {
|
||||
C.loadData(F);
|
||||
}, 2e3);
|
||||
export {
|
||||
z as Spreadsheet
|
||||
};
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"src/main.ts": {
|
||||
"file": "main.js",
|
||||
"isEntry": true,
|
||||
"src": "src/main.ts"
|
||||
},
|
||||
"style.css": {
|
||||
"file": "style.css",
|
||||
"src": "style.css"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
export interface CachedColumnProperties {
|
||||
xPos: number;
|
||||
colIdx: number;
|
||||
}
|
||||
export declare class CachedColumn {
|
||||
xPos: number;
|
||||
colIdx: number;
|
||||
constructor(props: CachedColumnProperties);
|
||||
}
|
||||
export interface CachedRowProperties {
|
||||
yPos: number;
|
||||
rowIdx: number;
|
||||
}
|
||||
export declare class CachedRow {
|
||||
yPos: number;
|
||||
rowIdx: number;
|
||||
constructor(props: CachedRowProperties);
|
||||
}
|
||||
export interface CacheConstructorProps {
|
||||
columns: CachedColumn[];
|
||||
rows: CachedRow[];
|
||||
}
|
||||
export declare class Cache {
|
||||
columns: CachedColumn[];
|
||||
rows: CachedRow[];
|
||||
constructor(initial: CacheConstructorProps);
|
||||
getRowByYCoord(y: number): number;
|
||||
getColumnByXCoord(x: number): number;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
export type CellConstructorProps = {
|
||||
value: string;
|
||||
displayValue: string;
|
||||
resultValue: string;
|
||||
position: Position;
|
||||
};
|
||||
interface CellStylesConstructorProps {
|
||||
fontSize: number;
|
||||
fontColor: string;
|
||||
background: string;
|
||||
borderColor: string;
|
||||
selectedBackground: string;
|
||||
selectedFontColor: string;
|
||||
}
|
||||
export declare class CellStyles {
|
||||
fontSize: number;
|
||||
fontColor: string;
|
||||
background: string;
|
||||
borderColor: string;
|
||||
selectedBackground: string;
|
||||
selectedFontColor: string;
|
||||
constructor(props?: CellStylesConstructorProps);
|
||||
}
|
||||
export declare class Position {
|
||||
row: number;
|
||||
column: number;
|
||||
constructor(row: number, column: number);
|
||||
}
|
||||
export declare class Cell {
|
||||
value: string;
|
||||
displayValue: string;
|
||||
/** This refers to the values that were obtained by calculations, for example, after calculating the formula */
|
||||
resultValue: string;
|
||||
position: Position;
|
||||
style: CellStyles;
|
||||
constructor(props: CellConstructorProps);
|
||||
changeValues(values: Partial<Omit<CellConstructorProps, 'position'>>): void;
|
||||
private isCellInRange;
|
||||
render(root: Spreadsheet): void;
|
||||
}
|
||||
export {};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export type ColumnConstructorProperties = {
|
||||
width: number;
|
||||
title: string;
|
||||
};
|
||||
export declare class Column {
|
||||
width: number;
|
||||
title: string;
|
||||
constructor(props: ColumnConstructorProperties);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import { Column } from "./column";
|
||||
import { Row } from "./row";
|
||||
export interface ViewProperties {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
export type ConfigProperties = {
|
||||
/** Please, end it with '_' symbol.
|
||||
*
|
||||
* *Example:*
|
||||
*
|
||||
* 'test_'
|
||||
* 'google_' */
|
||||
rows: Row[];
|
||||
columns: Column[];
|
||||
view: ViewProperties;
|
||||
};
|
||||
export type SheetConfigConstructorProps = {
|
||||
rows: Row[];
|
||||
columns: Column[];
|
||||
};
|
||||
export declare class Config {
|
||||
rows: Row[];
|
||||
columns: Column[];
|
||||
view: ViewProperties;
|
||||
constructor(props: ConfigProperties);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { Position } from "./cell";
|
||||
import { Config } from "./config";
|
||||
export declare class RenderBox {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
constructor(config: Config, cellPosition: Position);
|
||||
private getXCoord;
|
||||
private getYCoord;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export type RowConstructorProps = {
|
||||
height: number;
|
||||
title: string;
|
||||
};
|
||||
export declare class Row {
|
||||
height: number;
|
||||
title: string;
|
||||
constructor(props: RowConstructorProps);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export type BaseSelectionType = {
|
||||
row: number;
|
||||
column: number;
|
||||
};
|
||||
export type RangeSelectionType = {
|
||||
from: BaseSelectionType;
|
||||
to: BaseSelectionType;
|
||||
};
|
||||
export declare class Selection {
|
||||
selectedCell: BaseSelectionType | null;
|
||||
selectedRange: RangeSelectionType | null;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export declare class Styles {
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { Spreadsheet } from "../main";
|
||||
export type ViewportConstructorProps = {
|
||||
top: number;
|
||||
left: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
};
|
||||
export declare class Viewport {
|
||||
root: Spreadsheet;
|
||||
top: number;
|
||||
left: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
firstRow: number;
|
||||
lastRow: number;
|
||||
firstCol: number;
|
||||
lastCol: number;
|
||||
constructor(root: Spreadsheet, props: ViewportConstructorProps);
|
||||
updateValues(props: ViewportConstructorProps): void;
|
||||
/** Get index of first row in viewport */
|
||||
private getFirstRow;
|
||||
private getLastRow;
|
||||
private getFirstCol;
|
||||
private getLastCol;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
body{padding:0;margin:0}.content{position:absolute;top:0;left:0}.spreadsheet_container{position:relative;isolation:isolate;border:2px solid black}.sheet{display:block;contain:strict}.scroller{overflow:scroll;box-sizing:border-box;transform:translateZ(0)}.scroller:focus{outline:none}.editor{position:absolute;box-sizing:border-box;font-size:16px;font-family:Arial,Helvetica,sans-serif}.hide{visibility:hidden}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
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 = {
|
||||
config: Config;
|
||||
data: Cell[][];
|
||||
};
|
||||
export declare function makeSpreadsheetConfigAndData(rows: number, columns: number): SpreadsheetConfigAndDataReturnType;
|
||||
export {};
|
||||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
19
package.json
19
package.json
|
|
@ -1,22 +1,39 @@
|
|||
{
|
||||
"name": "spreadsheet",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.1",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/main.js",
|
||||
"require": "./dist/main.cjs.js"
|
||||
}
|
||||
},
|
||||
"main": "./dist/main.cjs.js",
|
||||
"module": "./dist/main.es.js",
|
||||
"typings": "./dist/main.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"homepage": "https://yazmeyaa.github.io/spreadsheet_2",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"build:watch": "tsc && vite build --watch",
|
||||
"preview": "vite preview",
|
||||
"predeploy": "npm run dist",
|
||||
"deploy": "gh-pages -d dist"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^11.1.2",
|
||||
"gh-pages": "^5.0.0",
|
||||
"rollup-plugin-typescript-paths": "^1.4.0",
|
||||
"tslib": "^2.6.0",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^20.4.4",
|
||||
"sass": "^1.63.6"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
108
pnpm-lock.yaml
108
pnpm-lock.yaml
|
|
@ -5,20 +5,32 @@ settings:
|
|||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.4.4
|
||||
version: 20.4.4
|
||||
sass:
|
||||
specifier: ^1.63.6
|
||||
version: 1.63.6
|
||||
|
||||
devDependencies:
|
||||
'@rollup/plugin-typescript':
|
||||
specifier: ^11.1.2
|
||||
version: 11.1.2(tslib@2.6.0)(typescript@5.0.2)
|
||||
gh-pages:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
rollup-plugin-typescript-paths:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0(typescript@5.0.2)
|
||||
tslib:
|
||||
specifier: ^2.6.0
|
||||
version: 2.6.0
|
||||
typescript:
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
vite:
|
||||
specifier: ^4.4.0
|
||||
version: 4.4.0(sass@1.63.6)
|
||||
version: 4.4.0(@types/node@20.4.4)(sass@1.63.6)
|
||||
|
||||
packages:
|
||||
|
||||
|
|
@ -220,6 +232,46 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/plugin-typescript@11.1.2(tslib@2.6.0)(typescript@5.0.2):
|
||||
resolution: {integrity: sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^2.14.0||^3.0.0
|
||||
tslib: '*'
|
||||
typescript: '>=3.7.0'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
tslib:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.0.2
|
||||
resolve: 1.22.2
|
||||
tslib: 2.6.0
|
||||
typescript: 5.0.2
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@5.0.2:
|
||||
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/estree': 1.0.1
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/@types/estree@1.0.1:
|
||||
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
||||
dev: true
|
||||
|
||||
/@types/node@20.4.4:
|
||||
resolution: {integrity: sha512-CukZhumInROvLq3+b5gLev+vgpsIqC2D0deQr/yS1WnxvmYLlJXZpaQrQiseMY+6xusl79E04UjWoqyr+t1/Ew==}
|
||||
|
||||
/anymatch@3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
@ -329,6 +381,10 @@ packages:
|
|||
engines: {node: '>=0.8.0'}
|
||||
dev: true
|
||||
|
||||
/estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
|
||||
/filename-reserved-regex@2.0.0:
|
||||
resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -386,6 +442,10 @@ packages:
|
|||
requiresBuild: true
|
||||
optional: true
|
||||
|
||||
/function-bind@1.1.1:
|
||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||
dev: true
|
||||
|
||||
/gh-pages@5.0.0:
|
||||
resolution: {integrity: sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -432,6 +492,13 @@ packages:
|
|||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
dev: true
|
||||
|
||||
/has@1.0.3:
|
||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
dev: true
|
||||
|
||||
/immutable@4.3.1:
|
||||
resolution: {integrity: sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==}
|
||||
|
||||
|
|
@ -452,6 +519,12 @@ packages:
|
|||
dependencies:
|
||||
binary-extensions: 2.2.0
|
||||
|
||||
/is-core-module@2.12.1:
|
||||
resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==}
|
||||
dependencies:
|
||||
has: 1.0.3
|
||||
dev: true
|
||||
|
||||
/is-extglob@2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -542,6 +615,10 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/path-parse@1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
dev: true
|
||||
|
||||
/picocolors@1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
dev: true
|
||||
|
|
@ -589,6 +666,23 @@ packages:
|
|||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
/resolve@1.22.2:
|
||||
resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
is-core-module: 2.12.1
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-typescript-paths@1.4.0(typescript@5.0.2):
|
||||
resolution: {integrity: sha512-6EgeLRjTVmymftEyCuYu91XzY5XMB5lR0YrJkeT0D7OG2RGSdbNL+C/hfPIdc/sjMa9Sl5NLsxIr6C/+/5EUpA==}
|
||||
peerDependencies:
|
||||
typescript: '>=3.4'
|
||||
dependencies:
|
||||
typescript: 5.0.2
|
||||
dev: true
|
||||
|
||||
/rollup@3.26.3:
|
||||
resolution: {integrity: sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==}
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
|
|
@ -622,6 +716,11 @@ packages:
|
|||
escape-string-regexp: 1.0.5
|
||||
dev: true
|
||||
|
||||
/supports-preserve-symlinks-flag@1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
|
@ -635,6 +734,10 @@ packages:
|
|||
escape-string-regexp: 1.0.5
|
||||
dev: true
|
||||
|
||||
/tslib@2.6.0:
|
||||
resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==}
|
||||
dev: true
|
||||
|
||||
/typescript@5.0.2:
|
||||
resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
|
@ -646,7 +749,7 @@ packages:
|
|||
engines: {node: '>= 4.0.0'}
|
||||
dev: true
|
||||
|
||||
/vite@4.4.0(sass@1.63.6):
|
||||
/vite@4.4.0(@types/node@20.4.4)(sass@1.63.6):
|
||||
resolution: {integrity: sha512-Wf+DCEjuM8aGavEYiF77hnbxEZ+0+/jC9nABR46sh5Xi+GYeSvkeEFRiVuI3x+tPjxgZeS91h1jTAQTPFgePpA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
|
|
@ -674,6 +777,7 @@ packages:
|
|||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/node': 20.4.4
|
||||
esbuild: 0.18.14
|
||||
postcss: 8.4.26
|
||||
rollup: 3.26.3
|
||||
|
|
|
|||
60
src/main.ts
60
src/main.ts
|
|
@ -12,6 +12,8 @@ import { Viewport } from "./modules/viewport";
|
|||
import './scss/main.scss'
|
||||
import { createSampleConfig, createSampleData } from "./utils/createData";
|
||||
import { Cache, CachedColumn, CachedRow } from "./modules/cache";
|
||||
import { Row } from "./modules/row";
|
||||
import { Column } from "./modules/column";
|
||||
|
||||
/*
|
||||
! Component structure
|
||||
|
|
@ -73,7 +75,7 @@ export class Spreadsheet {
|
|||
private getInitialCache(): Cache {
|
||||
const cachedCols: CachedColumn[] = []
|
||||
let currentWidth = 0
|
||||
for(let i = 0; i <= this.config.columns.length - 1; i++) {
|
||||
for (let i = 0; i <= this.config.columns.length - 1; i++) {
|
||||
const col = this.config.columns[i]
|
||||
currentWidth += col.width
|
||||
const cacheCol = new CachedColumn({
|
||||
|
|
@ -85,7 +87,7 @@ export class Spreadsheet {
|
|||
|
||||
const cachedRows: CachedRow[] = []
|
||||
let currentHeight = 0
|
||||
for(let i = 0; i <= this.config.rows.length - 1; i++) {
|
||||
for (let i = 0; i <= this.config.rows.length - 1; i++) {
|
||||
const row = this.config.rows[i]
|
||||
currentHeight += row.height
|
||||
const cacheRow = new CachedRow({
|
||||
|
|
@ -206,14 +208,62 @@ export class Spreadsheet {
|
|||
renderCell(row: number, col: number) {
|
||||
this.data[row][col].render(this)
|
||||
}
|
||||
|
||||
public loadData(data: Cell[][]): void {
|
||||
this.data = data
|
||||
this.config = this.makeConfigFromData(data, this.config.view)
|
||||
this.cache = this.getInitialCache()
|
||||
this.scroller.updateScrollerSize()
|
||||
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
|
||||
this.renderSheet()
|
||||
}
|
||||
|
||||
private makeConfigFromData(data: Cell[][], view: ViewProperties): Config {
|
||||
const lastRowIdx = data.length - 1
|
||||
const lastColIdx = data[0] ? data[0].length : 0
|
||||
|
||||
const rows: Row[] = []
|
||||
for (let row = 0; row < lastRowIdx; row++) {
|
||||
rows.push(new Row({
|
||||
height: 40,
|
||||
title: String(row)
|
||||
}))
|
||||
}
|
||||
|
||||
const columns: Column[] = []
|
||||
|
||||
for (let col = 0; col < lastColIdx; col++) {
|
||||
columns.push(new Column({
|
||||
width: 150,
|
||||
title: String(col)
|
||||
}))
|
||||
}
|
||||
|
||||
const config = new Config({
|
||||
view,
|
||||
rows,
|
||||
columns
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const spreadsheet = new Spreadsheet('#spreadsheet', {
|
||||
view: {
|
||||
height: 768,
|
||||
width: 1366
|
||||
},
|
||||
})
|
||||
console.log(spreadsheet)
|
||||
|
||||
const data = createSampleData(45, 45, true)
|
||||
|
||||
spreadsheet.changeCellValues({column: 2, row: 2}, {
|
||||
displayValue: 'Loading...',
|
||||
resultValue: 'Loading...',
|
||||
value: 'Loading...'
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
spreadsheet.loadData(data)
|
||||
}, 2000)
|
||||
|
|
@ -3,13 +3,13 @@ import { Column } from "../modules/column";
|
|||
import { Config } from "../modules/config";
|
||||
import { Row } from "../modules/row";
|
||||
|
||||
export function createSampleData(rows: number, columns: number): Cell[][] {
|
||||
export function createSampleData(rows: number, columns: number, fillCellsByCoords: boolean = false): Cell[][] {
|
||||
const data: Cell[][] = []
|
||||
|
||||
for (let row = 0; row <= rows; row++) {
|
||||
const innerRow: Cell[] = []
|
||||
for (let col = 0; col <= columns; col++) {
|
||||
const value = `${row}:${col}`
|
||||
const value = fillCellsByCoords ? `${row}:${col}` : ''
|
||||
|
||||
const cell = new Cell({
|
||||
displayValue: value,
|
||||
|
|
@ -31,7 +31,7 @@ export function createSampleData(rows: number, columns: number): Cell[][] {
|
|||
export function createSampleConfig(rows: number, columns: number): Config {
|
||||
|
||||
const rowsArr: Row[] = []
|
||||
for(let i = 0; i <= rows; i++) {
|
||||
for (let i = 0; i <= rows; i++) {
|
||||
const rowItem = new Row({
|
||||
height: 40,
|
||||
title: String(i)
|
||||
|
|
@ -40,7 +40,7 @@ export function createSampleConfig(rows: number, columns: number): Config {
|
|||
}
|
||||
|
||||
const colsArr: Column[] = []
|
||||
for(let i = 0; i <= columns; i++) {
|
||||
for (let i = 0; i <= columns; i++) {
|
||||
const colItem = new Column({
|
||||
title: String(i),
|
||||
width: 150
|
||||
|
|
@ -69,5 +69,5 @@ export function makeSpreadsheetConfigAndData(rows: number, columns: number): Spr
|
|||
const data = createSampleData(rows, columns)
|
||||
const config = createSampleConfig(rows, columns)
|
||||
|
||||
return {data, config}
|
||||
return { data, config }
|
||||
}
|
||||
|
|
@ -1,23 +1,30 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"target": "ESNext",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"types": ["vite/client", "node"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
|
||||
"useDefineForClassFields": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"allowImportingTsExtensions": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,37 @@
|
|||
import {defineConfig} from 'vite'
|
||||
import { defineConfig } from 'vite'
|
||||
import path from 'path'
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import { typescriptPaths } from "rollup-plugin-typescript-paths";
|
||||
|
||||
|
||||
export default defineConfig({
|
||||
base: '/spreadsheet_2/'
|
||||
base: '/spreadsheet_2/',
|
||||
plugins: [],
|
||||
resolve: {},
|
||||
server: {
|
||||
port: 3000
|
||||
},
|
||||
build: {
|
||||
manifest: true,
|
||||
minify: true,
|
||||
reportCompressedSize: true,
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, "src/main.ts"),
|
||||
fileName: "main",
|
||||
formats: ["es", "cjs"],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [],
|
||||
plugins: [
|
||||
typescriptPaths({
|
||||
preserveExtensions: true
|
||||
}),
|
||||
typescript({
|
||||
sourceMap: false,
|
||||
declaration: true,
|
||||
outDir: 'dist'
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
Loading…
Reference in New Issue