logisheets-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/dist/assets/logisheets_wasm_server_bg.wasm +0 -0
- package/dist/assets/worker-DtAa7uxj.js +4205 -0
- package/dist/logisheets-engine.css +1 -0
- package/dist/logisheets-engine.es.js +14095 -0
- package/dist/logisheets-engine.umd.js +1 -0
- package/dist/types/lib/adapters/index.d.ts +5 -0
- package/dist/types/lib/adapters/react.d.ts +88 -0
- package/dist/types/lib/block/enum_set_manager.d.ts +118 -0
- package/dist/types/lib/block/field_manager.d.ts +236 -0
- package/dist/types/lib/block/index.d.ts +7 -0
- package/dist/types/lib/block/manager.d.ts +25 -0
- package/dist/types/lib/block/value_formula.d.ts +47 -0
- package/dist/types/lib/clients/index.d.ts +3 -0
- package/dist/types/lib/clients/offscreen.d.ts +23 -0
- package/dist/types/lib/clients/service.d.ts +48 -0
- package/dist/types/lib/clients/workbook.d.ts +184 -0
- package/dist/types/lib/components/contextMenuTypes.d.ts +39 -0
- package/dist/types/lib/components/index.d.ts +8 -0
- package/dist/types/lib/components/utils.d.ts +33 -0
- package/dist/types/lib/engine.d.ts +242 -0
- package/dist/types/lib/global.d.ts +36 -0
- package/dist/types/lib/index.d.ts +15 -0
- package/dist/types/lib/license/index.d.ts +26 -0
- package/dist/types/lib/worker/border_helper.d.ts +24 -0
- package/dist/types/lib/worker/index.d.ts +3 -0
- package/dist/types/lib/worker/license.d.ts +27 -0
- package/dist/types/lib/worker/offscreen.worker.d.ts +35 -0
- package/dist/types/lib/worker/painter.d.ts +23 -0
- package/dist/types/lib/worker/pool.d.ts +26 -0
- package/dist/types/lib/worker/render.d.ts +24 -0
- package/dist/types/lib/worker/standable.d.ts +119 -0
- package/dist/types/lib/worker/types.d.ts +122 -0
- package/dist/types/lib/worker/view_manager.d.ts +59 -0
- package/dist/types/lib/worker/workbook.worker.d.ts +163 -0
- package/dist/types/lib/worker/worker.d.ts +5 -0
- package/dist/types/types/index.d.ts +115 -0
- package/package.json +40 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workbook Client - communicates with the worker for workbook operations.
|
|
3
|
+
*/
|
|
4
|
+
import type { SheetInfo, CellInfo, CellPosition, SheetDimension, MergeCell, BlockInfo, FormulaDisplayInfo, CellCoordinate, SheetCellId, Callback, CellIdCallback, ErrorMessage, AppData, BlockField, TempStatusDiff, ShadowCellInfo } from "logisheets-web";
|
|
5
|
+
type Resp<T> = Promise<T | ErrorMessage>;
|
|
6
|
+
export declare class WorkbookClient {
|
|
7
|
+
private _worker;
|
|
8
|
+
private _resolvers;
|
|
9
|
+
private _id;
|
|
10
|
+
private _ready;
|
|
11
|
+
private _cellUpdatedCallbacks;
|
|
12
|
+
private _sheetUpdatedCallbacks;
|
|
13
|
+
private _headerUpdatedCallbacks;
|
|
14
|
+
private _cellValueChangedCallbacks;
|
|
15
|
+
private _cellRemovedCallbacks;
|
|
16
|
+
constructor(worker: Worker);
|
|
17
|
+
getAllSheetInfo(): Resp<readonly SheetInfo[]>;
|
|
18
|
+
getSheetDimension(sheetIdx: number): Resp<SheetDimension>;
|
|
19
|
+
getSheetIdx(params: {
|
|
20
|
+
sheetId: number;
|
|
21
|
+
}): Resp<number>;
|
|
22
|
+
getSheetId(params: {
|
|
23
|
+
sheetIdx: number;
|
|
24
|
+
}): Resp<number>;
|
|
25
|
+
getSheetNameByIdx(idx: number): Resp<string>;
|
|
26
|
+
getCell(params: {
|
|
27
|
+
sheetIdx: number;
|
|
28
|
+
row: number;
|
|
29
|
+
col: number;
|
|
30
|
+
}): Resp<CellInfo>;
|
|
31
|
+
getCells(params: {
|
|
32
|
+
sheetIdx: number;
|
|
33
|
+
startRow: number;
|
|
34
|
+
startCol: number;
|
|
35
|
+
endRow: number;
|
|
36
|
+
endCol: number;
|
|
37
|
+
}): Resp<readonly CellInfo[]>;
|
|
38
|
+
getCellPosition(params: {
|
|
39
|
+
sheetIdx: number;
|
|
40
|
+
row: number;
|
|
41
|
+
col: number;
|
|
42
|
+
}): Resp<CellPosition>;
|
|
43
|
+
getCellId(params: {
|
|
44
|
+
sheetIdx: number;
|
|
45
|
+
rowIdx: number;
|
|
46
|
+
colIdx: number;
|
|
47
|
+
}): Resp<SheetCellId>;
|
|
48
|
+
batchGetCellInfoById(params: {
|
|
49
|
+
ids: readonly SheetCellId[];
|
|
50
|
+
}): Resp<readonly CellInfo[]>;
|
|
51
|
+
getNextVisibleCell(params: {
|
|
52
|
+
sheetIdx: number;
|
|
53
|
+
rowIdx: number;
|
|
54
|
+
colIdx: number;
|
|
55
|
+
direction: "up" | "down" | "left" | "right";
|
|
56
|
+
}): Resp<CellCoordinate>;
|
|
57
|
+
getBlockInfo(params: {
|
|
58
|
+
sheetId: number;
|
|
59
|
+
blockId: number;
|
|
60
|
+
}): Resp<BlockInfo>;
|
|
61
|
+
getAvailableBlockId(params: {
|
|
62
|
+
sheetIdx: number;
|
|
63
|
+
}): Resp<number>;
|
|
64
|
+
/**
|
|
65
|
+
* Enumerate blocks fully contained in a row/col range. Use a large
|
|
66
|
+
* range (e.g. derived from `getSheetDimension`) to enumerate every
|
|
67
|
+
* block on the sheet — useful for "jump to" lookups that need block
|
|
68
|
+
* schemas before any rendering has populated them into a Grid.
|
|
69
|
+
*/
|
|
70
|
+
getFullyCoveredBlocks(params: {
|
|
71
|
+
sheetIdx: number;
|
|
72
|
+
rowIdx: number;
|
|
73
|
+
colIdx: number;
|
|
74
|
+
rowCnt: number;
|
|
75
|
+
colCnt: number;
|
|
76
|
+
}): Resp<readonly BlockInfo[]>;
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a (refName, key, field) triple to a concrete cell id — same
|
|
79
|
+
* lookup the BLOCKREF formula does at evaluation time. Pair with
|
|
80
|
+
* `registerCellValueChangedCallback` to subscribe by block ref instead
|
|
81
|
+
* of (sheet, row, col).
|
|
82
|
+
*/
|
|
83
|
+
getCellIdByBlockRef(params: {
|
|
84
|
+
refName: string;
|
|
85
|
+
key: string;
|
|
86
|
+
field: string;
|
|
87
|
+
}): Resp<SheetCellId>;
|
|
88
|
+
/**
|
|
89
|
+
* Snapshot of all cell-value differences between the active temp
|
|
90
|
+
* branch and the committed (fork) status. Used by the diff layer.
|
|
91
|
+
*/
|
|
92
|
+
getTempStatusChanges(): Resp<TempStatusDiff>;
|
|
93
|
+
getMergedCells(params: {
|
|
94
|
+
sheetIdx: number;
|
|
95
|
+
startRow: number;
|
|
96
|
+
startCol: number;
|
|
97
|
+
endRow: number;
|
|
98
|
+
endCol: number;
|
|
99
|
+
}): Resp<readonly MergeCell[]>;
|
|
100
|
+
/**
|
|
101
|
+
* Host-side observers that get every payload flowing through
|
|
102
|
+
* {@link handleTransaction} (or its no-events sibling). Used so the
|
|
103
|
+
* host can react to schema-shaping payloads — e.g. auto-stamping
|
|
104
|
+
* `bindFormSchema.refName` onto FieldManager — without crafts having
|
|
105
|
+
* to call a second API.
|
|
106
|
+
*
|
|
107
|
+
* Observers run synchronously *before* the payload is forwarded to the
|
|
108
|
+
* worker. They must not throw (errors are caught & logged) and should
|
|
109
|
+
* stay fast — they sit on the critical path of every transaction.
|
|
110
|
+
*/
|
|
111
|
+
private _payloadObservers;
|
|
112
|
+
registerPayloadObserver(fn: (payload: any) => void): () => void;
|
|
113
|
+
private _notifyPayloadObservers;
|
|
114
|
+
handleTransaction(params: {
|
|
115
|
+
transaction: any;
|
|
116
|
+
temp: boolean;
|
|
117
|
+
}): Resp<void>;
|
|
118
|
+
handleTransactionWithoutEvents(params: {
|
|
119
|
+
transaction: any;
|
|
120
|
+
temp: boolean;
|
|
121
|
+
}): Resp<any>;
|
|
122
|
+
undo(): Resp<void>;
|
|
123
|
+
redo(): Resp<void>;
|
|
124
|
+
commitTempStatus(): Resp<void>;
|
|
125
|
+
cleanTempStatus(): Resp<void>;
|
|
126
|
+
loadWorkbook(params: {
|
|
127
|
+
content: Uint8Array;
|
|
128
|
+
name: string;
|
|
129
|
+
}): Resp<void>;
|
|
130
|
+
save(params: {
|
|
131
|
+
appData?: string;
|
|
132
|
+
}): Resp<any>;
|
|
133
|
+
getDisplayUnitsOfFormula(f: string): Resp<FormulaDisplayInfo>;
|
|
134
|
+
checkFormula(params: {
|
|
135
|
+
formula: string;
|
|
136
|
+
}): Resp<boolean>;
|
|
137
|
+
getAppData(): Resp<readonly AppData[]>;
|
|
138
|
+
getAllBlockFields(): Resp<readonly BlockField[]>;
|
|
139
|
+
getShadowCellId(params: {
|
|
140
|
+
sheetIdx: number;
|
|
141
|
+
rowIdx: number;
|
|
142
|
+
colIdx: number;
|
|
143
|
+
/**
|
|
144
|
+
* Which derived computation this shadow represents. Optional for
|
|
145
|
+
* backward compatibility — omitting it defaults to the
|
|
146
|
+
* long-standing Validation kind. Other kinds (e.g. `'userEditable'`)
|
|
147
|
+
* let widgets request their own per-cell shadow without colliding
|
|
148
|
+
* with validation's slot.
|
|
149
|
+
*/
|
|
150
|
+
kind?: "validation" | "userEditable";
|
|
151
|
+
}): Resp<SheetCellId>;
|
|
152
|
+
/**
|
|
153
|
+
* Read the current value of a shadow ephemeral cell by its id.
|
|
154
|
+
* Used by widgets that install a per-cell formula (validation /
|
|
155
|
+
* userEditable / future kinds) and need to read the computed bool
|
|
156
|
+
* back. Subscribe to changes via
|
|
157
|
+
* {@link registerCellValueChangedByCellId} against the shadow's
|
|
158
|
+
* `SheetCellId`.
|
|
159
|
+
*
|
|
160
|
+
* Param shape matches the autogenerated `Client` interface from
|
|
161
|
+
* `logisheets-web` (params object, not raw `number`) — divergence
|
|
162
|
+
* here used to crash crafts that imported `Client` but ran against
|
|
163
|
+
* a `WorkbookClient` instance: the raw-number form re-wrapped the
|
|
164
|
+
* passed object into another `{shadowId}` envelope, serde failed
|
|
165
|
+
* to populate `GetShadowInfoByIdParams { shadow_id: u32 }`, and
|
|
166
|
+
* the call returned `undefined` silently.
|
|
167
|
+
*/
|
|
168
|
+
getShadowInfoById(params: {
|
|
169
|
+
shadowId: number;
|
|
170
|
+
}): Resp<ShadowCellInfo>;
|
|
171
|
+
registerCellUpdatedCallback(f: Callback, _callbackId?: number): void;
|
|
172
|
+
registerSheetUpdatedCallback(f: Callback): void;
|
|
173
|
+
registerHeaderUpdatedCallback(f: (sheetIdxes: readonly number[]) => void): void;
|
|
174
|
+
registerCellValueChangedCallback(sheetIdx: number, rowIdx: number, colIdx: number, callback: CellIdCallback): Resp<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Like {@link registerCellValueChangedCallback} but takes a pre-resolved
|
|
177
|
+
* `SheetCellId` — useful when paired with {@link getCellIdByBlockRef}
|
|
178
|
+
* (subscribing by block ref) or other id-producing lookups, since it
|
|
179
|
+
* skips the redundant (sheet,row,col) → id round-trip.
|
|
180
|
+
*/
|
|
181
|
+
registerCellValueChangedByCellId(cellId: SheetCellId, callback: CellIdCallback): void;
|
|
182
|
+
private _call;
|
|
183
|
+
}
|
|
184
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SelectedData } from "logisheets-web";
|
|
2
|
+
/**
|
|
3
|
+
* Context menu item definition
|
|
4
|
+
*/
|
|
5
|
+
export interface ContextMenuItem {
|
|
6
|
+
/** Unique identifier for the menu item */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Display label */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Optional icon (emoji or text) */
|
|
11
|
+
icon?: string;
|
|
12
|
+
/** Whether the item is disabled */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Whether to show a separator after this item */
|
|
15
|
+
separator?: boolean;
|
|
16
|
+
/** Keyboard shortcut hint (display only) */
|
|
17
|
+
shortcut?: string;
|
|
18
|
+
/** Sub-menu items (if any) */
|
|
19
|
+
children?: ContextMenuItem[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The target type where context menu was triggered
|
|
23
|
+
*/
|
|
24
|
+
export type ContextMenuTarget = "cell" | "row" | "column";
|
|
25
|
+
/**
|
|
26
|
+
* Context passed to menu item click handlers
|
|
27
|
+
*/
|
|
28
|
+
export interface ContextMenuContext {
|
|
29
|
+
/** The selected data when menu was triggered */
|
|
30
|
+
selectedData: SelectedData;
|
|
31
|
+
/** What was clicked - cell, row header, or column header */
|
|
32
|
+
target: ContextMenuTarget;
|
|
33
|
+
/** Row index if a specific row was clicked */
|
|
34
|
+
row?: number;
|
|
35
|
+
/** Column index if a specific column was clicked */
|
|
36
|
+
col?: number;
|
|
37
|
+
/** The original mouse event */
|
|
38
|
+
event: MouseEvent;
|
|
39
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as Spreadsheet } from "./Spreadsheet.svelte";
|
|
2
|
+
export { default as ColumnHeaders } from "./ColumnHeaders.svelte";
|
|
3
|
+
export { default as RowHeaders } from "./RowHeaders.svelte";
|
|
4
|
+
export { default as Selector } from "./Selector.svelte";
|
|
5
|
+
export { default as SheetTabs } from "./SheetTabs.svelte";
|
|
6
|
+
export { default as Scrollbar } from "./Scrollbar.svelte";
|
|
7
|
+
export { default as ContextMenu } from "./ContextMenu.svelte";
|
|
8
|
+
export { match, xForColStart, xForColEnd, yForRowStart, yForRowEnd, getPosition, getSelectedCellRange, getSelectedRows, getSelectedColumns, getSelectedLines, findVisibleRowIdxRange, findVisibleColIdxRange, buildSelectedDataFromCell, buildSelectedDataFromCellRange, ptToPx, pxToPt, pxToWidth, simpleUuid, } from "./utils";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for the canvas component.
|
|
3
|
+
*/
|
|
4
|
+
import type { Grid } from "$types/index";
|
|
5
|
+
import { Cell } from "$types/index";
|
|
6
|
+
export declare const xForColStart: (colIdx: number, grid: Grid) => number;
|
|
7
|
+
export declare const xForColEnd: (colIdx: number, grid: Grid) => number;
|
|
8
|
+
export declare const yForRowStart: (rowIdx: number, grid: Grid) => number;
|
|
9
|
+
export declare const yForRowEnd: (rowIdx: number, grid: Grid) => number;
|
|
10
|
+
export declare const getPosition: (rowIdx: number, colIdx: number, grid: Grid) => {
|
|
11
|
+
startX: number;
|
|
12
|
+
startY: number;
|
|
13
|
+
endX: number;
|
|
14
|
+
endY: number;
|
|
15
|
+
};
|
|
16
|
+
export declare const findVisibleRowIdxRange: (anchor: number, height: number, grid: Grid) => [number, number];
|
|
17
|
+
export declare const findVisibleColIdxRange: (anchor: number, width: number, grid: Grid) => [number, number];
|
|
18
|
+
export declare function match(canvasX: number, canvasY: number, anchorX: number, anchorY: number, data: Grid): Cell;
|
|
19
|
+
import type { SelectedData, SelectedCellRange, SelectedLines } from "logisheets-web";
|
|
20
|
+
export declare function getSelectedCellRange(v: SelectedData): SelectedCellRange | undefined;
|
|
21
|
+
export declare function getSelectedLines(v: SelectedData): SelectedLines | undefined;
|
|
22
|
+
export declare function buildSelectedDataFromCell(row: number, col: number, source: "editbar" | "none"): SelectedData;
|
|
23
|
+
export declare function buildSelectedDataFromCellRange(startRow: number, startCol: number, endRow: number, endCol: number, source: "editbar" | "none"): SelectedData;
|
|
24
|
+
export declare function buildSelectedDataFromLines(start: number, end: number, type: "row" | "col", source: "editbar" | "none"): SelectedData;
|
|
25
|
+
export declare function getSelectedRows(v: SelectedData): number[];
|
|
26
|
+
export declare function getSelectedColumns(v: SelectedData): number[];
|
|
27
|
+
export declare function toA1notation(col: number): string;
|
|
28
|
+
export declare function getReferenceString(v: SelectedData): string;
|
|
29
|
+
export declare function ptToPx(pt: number): number;
|
|
30
|
+
export declare function pxToPt(px: number): number;
|
|
31
|
+
export declare function widthToPx(w: number): number;
|
|
32
|
+
export declare function pxToWidth(px: number): number;
|
|
33
|
+
export declare function simpleUuid(): string;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LogiSheets Engine - Core engine class providing UI mounting and workbook access.
|
|
3
|
+
* This is the main entry point for using the spreadsheet engine in any framework.
|
|
4
|
+
*
|
|
5
|
+
* The Engine does NOT re-invent the workbook API. Instead, it:
|
|
6
|
+
* 1. Creates and manages the Worker and DataService
|
|
7
|
+
* 2. Provides mount()/unmount() for UI rendering
|
|
8
|
+
* 3. Exposes getWorkbook() to access the original logisheets-web API
|
|
9
|
+
*/
|
|
10
|
+
import type { SheetInfo, SelectedData, CellLayout } from "logisheets-web";
|
|
11
|
+
import { DataService } from "./clients/service";
|
|
12
|
+
import { WorkbookClient } from "./clients/workbook";
|
|
13
|
+
import { BlockManager } from "./block";
|
|
14
|
+
import type { Grid, EngineConfig } from "$types/index";
|
|
15
|
+
import type { ContextMenuItem } from "./components/contextMenuTypes";
|
|
16
|
+
export type EngineEventType = "ready" | "sheetChange" | "cellChange" | "selectionChange" | "error" | "gridChange" | "activeSheetChange" | "startEdit" | "invalidFormula";
|
|
17
|
+
export interface EngineEventMap {
|
|
18
|
+
ready: void;
|
|
19
|
+
sheetChange: readonly SheetInfo[];
|
|
20
|
+
cellChange: void;
|
|
21
|
+
selectionChange: SelectedData;
|
|
22
|
+
error: Error;
|
|
23
|
+
gridChange: Grid | null;
|
|
24
|
+
activeSheetChange: number;
|
|
25
|
+
startEdit: {
|
|
26
|
+
row: number;
|
|
27
|
+
col: number;
|
|
28
|
+
initialText: string;
|
|
29
|
+
};
|
|
30
|
+
invalidFormula: void;
|
|
31
|
+
}
|
|
32
|
+
type EventCallback<T extends EngineEventType> = (data: EngineEventMap[T]) => void;
|
|
33
|
+
export interface EngineMountOptions {
|
|
34
|
+
/** Show sheet tabs at bottom */
|
|
35
|
+
showSheetTabs?: boolean;
|
|
36
|
+
/** Show scrollbars */
|
|
37
|
+
showScrollbars?: boolean;
|
|
38
|
+
/** Custom context menu items */
|
|
39
|
+
contextMenuItems?: ContextMenuItem[];
|
|
40
|
+
/** Cell layouts for custom rendering */
|
|
41
|
+
cellLayouts?: CellLayout[];
|
|
42
|
+
/** Getter for whether a formula is being edited (prevents canvas from taking focus) */
|
|
43
|
+
getIsEditingFormula?: () => boolean;
|
|
44
|
+
/** Callback when an invalid formula is entered */
|
|
45
|
+
onInvalidFormula?: () => void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* LogiSheets Engine - The main interface for the spreadsheet.
|
|
49
|
+
*
|
|
50
|
+
* Usage:
|
|
51
|
+
* ```javascript
|
|
52
|
+
* import { Engine } from 'logisheets-engine';
|
|
53
|
+
*
|
|
54
|
+
* // Create engine instance
|
|
55
|
+
* const engine = new Engine();
|
|
56
|
+
*
|
|
57
|
+
* // Wait for ready
|
|
58
|
+
* engine.on('ready', async () => {
|
|
59
|
+
* // Mount the UI to a container
|
|
60
|
+
* engine.mount(document.getElementById('spreadsheet'));
|
|
61
|
+
*
|
|
62
|
+
* // Access the workbook API (same as logisheets-web)
|
|
63
|
+
* const workbook = engine.getWorkbook();
|
|
64
|
+
*
|
|
65
|
+
* // Load a file
|
|
66
|
+
* await workbook.loadWorkbook({ content: buffer, name: 'file.xlsx' });
|
|
67
|
+
*
|
|
68
|
+
* // Use original logisheets-web API
|
|
69
|
+
* const sheets = await workbook.getAllSheetInfo();
|
|
70
|
+
* const cell = await workbook.getCell({ sheetIdx: 0, row: 0, col: 0 });
|
|
71
|
+
*
|
|
72
|
+
* // Execute transactions
|
|
73
|
+
* await workbook.handleTransaction({ transaction: tx, temp: false });
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare class Engine {
|
|
78
|
+
private _dataService;
|
|
79
|
+
private _worker;
|
|
80
|
+
private _blockManager;
|
|
81
|
+
private _config;
|
|
82
|
+
private _ready;
|
|
83
|
+
private _currentSheetIdx;
|
|
84
|
+
private _grid;
|
|
85
|
+
private _selectedData;
|
|
86
|
+
private _sheets;
|
|
87
|
+
private _mountedComponent;
|
|
88
|
+
private _mountContainer;
|
|
89
|
+
private _listeners;
|
|
90
|
+
constructor(config?: Partial<EngineConfig>);
|
|
91
|
+
/**
|
|
92
|
+
* Mount the spreadsheet UI to a container element.
|
|
93
|
+
* @param container - The HTML element to mount the spreadsheet into
|
|
94
|
+
* @param options - Mount options
|
|
95
|
+
*/
|
|
96
|
+
mount(container: HTMLElement, options?: EngineMountOptions): void;
|
|
97
|
+
/**
|
|
98
|
+
* Unmount the spreadsheet UI.
|
|
99
|
+
*/
|
|
100
|
+
unmount(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Check if the UI is mounted.
|
|
103
|
+
*/
|
|
104
|
+
isMounted(): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Get the mount container element.
|
|
107
|
+
*/
|
|
108
|
+
getMountContainer(): HTMLElement | null;
|
|
109
|
+
/**
|
|
110
|
+
* Initialize offscreen canvas for headless rendering.
|
|
111
|
+
* Only needed if you want to render without mounting UI.
|
|
112
|
+
* @param canvas - The canvas element for offscreen rendering
|
|
113
|
+
*/
|
|
114
|
+
initOffscreen(canvas: HTMLCanvasElement): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Destroy the engine and release all resources.
|
|
117
|
+
*/
|
|
118
|
+
destroy(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Subscribe to an event.
|
|
121
|
+
*/
|
|
122
|
+
on<T extends EngineEventType>(type: T, callback: EventCallback<T>): void;
|
|
123
|
+
/**
|
|
124
|
+
* Unsubscribe from an event.
|
|
125
|
+
*/
|
|
126
|
+
off<T extends EngineEventType>(type: T, callback: EventCallback<T>): void;
|
|
127
|
+
private _emit;
|
|
128
|
+
/**
|
|
129
|
+
* Get the workbook client for all workbook operations.
|
|
130
|
+
* This provides access to the original logisheets-web API.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```javascript
|
|
134
|
+
* const workbook = engine.getWorkbook();
|
|
135
|
+
*
|
|
136
|
+
* // Load file
|
|
137
|
+
* await workbook.loadWorkbook({ content: buffer, name: 'file.xlsx' });
|
|
138
|
+
*
|
|
139
|
+
* // Get sheets
|
|
140
|
+
* const sheets = await workbook.getAllSheetInfo();
|
|
141
|
+
*
|
|
142
|
+
* // Get cell
|
|
143
|
+
* const cell = await workbook.getCell({ sheetIdx: 0, row: 0, col: 0 });
|
|
144
|
+
*
|
|
145
|
+
* // Execute transaction
|
|
146
|
+
* await workbook.handleTransaction({ transaction: tx, temp: false });
|
|
147
|
+
*
|
|
148
|
+
* // Undo/Redo
|
|
149
|
+
* await workbook.undo();
|
|
150
|
+
* await workbook.redo();
|
|
151
|
+
*
|
|
152
|
+
* // Save
|
|
153
|
+
* const result = await workbook.save({});
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
getWorkbook(): WorkbookClient;
|
|
157
|
+
/**
|
|
158
|
+
* Get the data service for rendering operations.
|
|
159
|
+
* Use this for render(), resize(), and other display-related operations.
|
|
160
|
+
*/
|
|
161
|
+
getDataService(): DataService;
|
|
162
|
+
/**
|
|
163
|
+
* Get the block manager for field/enum management.
|
|
164
|
+
*/
|
|
165
|
+
getBlockManager(): BlockManager;
|
|
166
|
+
/**
|
|
167
|
+
* Load a workbook from a file buffer.
|
|
168
|
+
* Convenience wrapper for getWorkbook().loadWorkbook()
|
|
169
|
+
*/
|
|
170
|
+
loadFile(buffer: Uint8Array, filename: string): Promise<Grid | null>;
|
|
171
|
+
/**
|
|
172
|
+
* Render the spreadsheet.
|
|
173
|
+
* Note: When UI is mounted, rendering is handled automatically.
|
|
174
|
+
*/
|
|
175
|
+
render(anchorX?: number, anchorY?: number): Promise<Grid | null>;
|
|
176
|
+
/**
|
|
177
|
+
* Resize the canvas.
|
|
178
|
+
* Note: When UI is mounted, resizing is handled automatically.
|
|
179
|
+
*/
|
|
180
|
+
resize(width: number, height: number): Promise<Grid | null>;
|
|
181
|
+
/**
|
|
182
|
+
* Get the current grid data.
|
|
183
|
+
*/
|
|
184
|
+
getGrid(): Grid | null;
|
|
185
|
+
/**
|
|
186
|
+
* Get current selection.
|
|
187
|
+
*/
|
|
188
|
+
getSelection(): SelectedData;
|
|
189
|
+
/**
|
|
190
|
+
* Set current selection.
|
|
191
|
+
*/
|
|
192
|
+
setSelection(selection: SelectedData): void;
|
|
193
|
+
/**
|
|
194
|
+
* Get current sheet index.
|
|
195
|
+
*/
|
|
196
|
+
getCurrentSheetIndex(): number;
|
|
197
|
+
/**
|
|
198
|
+
* Set current sheet by index.
|
|
199
|
+
*/
|
|
200
|
+
setCurrentSheetIndex(index: number): void;
|
|
201
|
+
/**
|
|
202
|
+
* Get cached sheet info.
|
|
203
|
+
*/
|
|
204
|
+
getSheets(): readonly SheetInfo[];
|
|
205
|
+
/**
|
|
206
|
+
* Get engine configuration.
|
|
207
|
+
*/
|
|
208
|
+
getConfig(): EngineConfig;
|
|
209
|
+
/**
|
|
210
|
+
* Check if engine is ready.
|
|
211
|
+
*/
|
|
212
|
+
isReady(): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Set the license key (API key) to activate the engine.
|
|
215
|
+
* If valid, the watermark will be removed.
|
|
216
|
+
*
|
|
217
|
+
* License validation happens INSIDE the worker - cannot be bypassed.
|
|
218
|
+
*
|
|
219
|
+
* @param apiKey - The license key provided to customers
|
|
220
|
+
* @returns License validation status
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```javascript
|
|
224
|
+
* const status = await engine.setLicense('eyJkb21haW4i...');
|
|
225
|
+
* if (status.valid) {
|
|
226
|
+
* console.log('License activated!');
|
|
227
|
+
* } else {
|
|
228
|
+
* console.log('License invalid:', status.reason);
|
|
229
|
+
* }
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
setLicense(apiKey: string): Promise<{
|
|
233
|
+
valid: boolean;
|
|
234
|
+
reason?: string;
|
|
235
|
+
}>;
|
|
236
|
+
/**
|
|
237
|
+
* Clear the current license and show watermark again.
|
|
238
|
+
*/
|
|
239
|
+
clearLicense(): void;
|
|
240
|
+
private _ensureReady;
|
|
241
|
+
}
|
|
242
|
+
export default Engine;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LogiSheets Engine - Global entry point
|
|
3
|
+
*
|
|
4
|
+
* This file exposes the entire engine API to the global `window.LogiSheetsEngine` object.
|
|
5
|
+
* It can be used in any framework or vanilla JavaScript.
|
|
6
|
+
*
|
|
7
|
+
* Usage in browser:
|
|
8
|
+
* ```html
|
|
9
|
+
* <script src="logisheets-engine.umd.js"></script>
|
|
10
|
+
* <script>
|
|
11
|
+
* const engine = new LogiSheetsEngine.Engine();
|
|
12
|
+
* await engine.init(document.getElementById('canvas'));
|
|
13
|
+
* </script>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Usage as ES module:
|
|
17
|
+
* ```javascript
|
|
18
|
+
* import { Engine, Transaction, CellInputBuilder } from 'logisheets-engine';
|
|
19
|
+
* const engine = new Engine();
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export { Engine, default } from "./engine";
|
|
23
|
+
export type { EngineEventType, EngineEventMap } from "./engine";
|
|
24
|
+
export type { License, LicenseStatus } from "./license";
|
|
25
|
+
export { DataService, WorkbookClient, OffscreenClient } from "./clients";
|
|
26
|
+
export { WorkbookWorkerService, OffscreenWorkerService } from "./worker";
|
|
27
|
+
export { BlockManager, EnumSetManager, FieldManager, LOGISHEETS_BUILTIN_CRAFT_ID, FIELD_AND_VALIDATION_TAG, expandFieldFormula, colIdxToLetters, } from "./block";
|
|
28
|
+
export type { EnumInfo, EnumVariant, FieldInfo, FieldTypeEnum } from "./block";
|
|
29
|
+
export type { Grid, Row, Column, Range, Cell, SelectorStyle, CellLayout, CanvasProps, EngineConfig, } from "$types/index";
|
|
30
|
+
export { DEFAULT_ENGINE_CONFIG, Range as RangeClass, Cell as CellClass, } from "$types/index";
|
|
31
|
+
export * from "logisheets-web";
|
|
32
|
+
export { match, xForColStart, xForColEnd, yForRowStart, yForRowEnd, getPosition, getSelectedCellRange, getSelectedLines, getSelectedRows, getSelectedColumns, findVisibleRowIdxRange, findVisibleColIdxRange, buildSelectedDataFromCell, buildSelectedDataFromCellRange, buildSelectedDataFromLines, getReferenceString, ptToPx, pxToPt, pxToWidth, simpleUuid, } from "./components/utils";
|
|
33
|
+
export type { ContextMenuItem, ContextMenuContext, } from "./components/contextMenuTypes";
|
|
34
|
+
export { convertCanvasPropsToAdapterProps } from "./adapters";
|
|
35
|
+
export type { SpreadsheetAdapterProps, CanvasAdapterProps, UseSpreadsheetConfig, UseSpreadsheetReturn, } from "./adapters";
|
|
36
|
+
export { Spreadsheet, ColumnHeaders, RowHeaders, Selector, SheetTabs, Scrollbar, ContextMenu, } from "./components";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Spreadsheet, ColumnHeaders, RowHeaders, Selector, SheetTabs, Scrollbar, ContextMenu, match, xForColStart, xForColEnd, yForRowStart, yForRowEnd, getPosition, getSelectedCellRange, getSelectedRows, getSelectedColumns, getSelectedLines, findVisibleRowIdxRange, findVisibleColIdxRange, buildSelectedDataFromCell, buildSelectedDataFromCellRange, ptToPx, pxToPt, pxToWidth, simpleUuid, } from "./components";
|
|
2
|
+
export type { ContextMenuItem, ContextMenuContext, } from "./components/contextMenuTypes";
|
|
3
|
+
export { DataService, WorkbookClient, OffscreenClient } from "./clients";
|
|
4
|
+
export { WorkbookWorkerService, OffscreenWorkerService } from "./worker";
|
|
5
|
+
export { BlockManager, EnumSetManager, FieldManager, LOGISHEETS_BUILTIN_CRAFT_ID, FIELD_AND_VALIDATION_TAG, expandFieldFormula, colIdxToLetters, } from "./block";
|
|
6
|
+
export type { EnumInfo, EnumVariant, FieldInfo, FieldTypeEnum } from "./block";
|
|
7
|
+
export type { Grid, Row, Column, Range, Cell, SelectorStyle, CellLayout, CanvasProps, EngineConfig, } from "$types/index";
|
|
8
|
+
export { DEFAULT_ENGINE_CONFIG } from "$types/index";
|
|
9
|
+
export { Range as RangeClass, Cell as CellClass } from "$types/index";
|
|
10
|
+
export { Engine, default as EngineDefault } from "./engine";
|
|
11
|
+
export type { EngineEventType, EngineEventMap, EngineMountOptions, } from "./engine";
|
|
12
|
+
export type { SelectedData, Transaction, Payload, SheetInfo, } from "logisheets-web";
|
|
13
|
+
export { isErrorMessage, getFirstCell, } from "logisheets-web";
|
|
14
|
+
export { convertCanvasPropsToAdapterProps } from "./adapters";
|
|
15
|
+
export type { SpreadsheetAdapterProps, CanvasAdapterProps, UseSpreadsheetConfig, UseSpreadsheetReturn, } from "./adapters";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License verification module using WebCrypto API (zero dependencies)
|
|
3
|
+
* Uses ECDSA P-256 for signature verification
|
|
4
|
+
*/
|
|
5
|
+
export interface License {
|
|
6
|
+
domain: string;
|
|
7
|
+
issuedAt: number;
|
|
8
|
+
validDays: number;
|
|
9
|
+
signature: string;
|
|
10
|
+
}
|
|
11
|
+
export interface LicenseStatus {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
reason?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse and validate a license key
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateLicense(apiKey: string): Promise<LicenseStatus>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if license is currently valid
|
|
21
|
+
*/
|
|
22
|
+
export declare function isLicenseValid(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Clear current license
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearLicense(): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BorderHelper is used to generate the continuous borders. Drawing borders
|
|
3
|
+
* cell by cell will make the borders discontinuous.
|
|
4
|
+
*/
|
|
5
|
+
import type { BorderPr } from "logisheets-web";
|
|
6
|
+
import type { CellView } from "./view_manager";
|
|
7
|
+
export interface BorderSegment {
|
|
8
|
+
pr: BorderPr | undefined;
|
|
9
|
+
from: number;
|
|
10
|
+
to: number;
|
|
11
|
+
start: number;
|
|
12
|
+
coordinateX: number;
|
|
13
|
+
coordinateY: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class BorderHelper {
|
|
16
|
+
private readonly _data;
|
|
17
|
+
private _rowBorderStore;
|
|
18
|
+
private _colBorderStore;
|
|
19
|
+
constructor(_data: CellView);
|
|
20
|
+
generateRowBorder(r: number): BorderSegment[];
|
|
21
|
+
generateColBorder(c: number): BorderSegment[];
|
|
22
|
+
private _setRowBorder;
|
|
23
|
+
private _setColBorder;
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License verification module for Worker context
|
|
3
|
+
* Uses WebCrypto API (zero dependencies)
|
|
4
|
+
* Uses ECDSA P-256 for signature verification
|
|
5
|
+
*
|
|
6
|
+
* This module runs INSIDE the worker, so license validation cannot be bypassed
|
|
7
|
+
* by sending direct messages to the worker.
|
|
8
|
+
*
|
|
9
|
+
* PUBLIC KEY OBFUSCATION:
|
|
10
|
+
* The public key is stored as encoded fragments to prevent easy discovery.
|
|
11
|
+
* Run `node scripts/license-cli.mjs generate-keys` to get the fragments.
|
|
12
|
+
*/
|
|
13
|
+
export interface License {
|
|
14
|
+
domain: string;
|
|
15
|
+
issuedAt: number;
|
|
16
|
+
validDays: number;
|
|
17
|
+
signature: string;
|
|
18
|
+
}
|
|
19
|
+
export interface LicenseStatus {
|
|
20
|
+
valid: boolean;
|
|
21
|
+
reason?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validate a license key and return the status
|
|
25
|
+
* This is called inside the worker - no way to bypass it
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateLicenseInWorker(apiKey: string, currentDomain: string): Promise<LicenseStatus>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offscreen worker service - handles rendering operations in a Web Worker.
|
|
3
|
+
*/
|
|
4
|
+
import type { Grid, AppropriateHeight } from "$types/index";
|
|
5
|
+
import type { IWorkbookWorker, Result } from "./types";
|
|
6
|
+
import { type LicenseStatus } from "./license";
|
|
7
|
+
export declare class OffscreenWorkerService {
|
|
8
|
+
private readonly _workbook;
|
|
9
|
+
private readonly _ctx;
|
|
10
|
+
constructor(_workbook: IWorkbookWorker, _ctx: Worker);
|
|
11
|
+
private _canvas;
|
|
12
|
+
private _dpr;
|
|
13
|
+
private _painter;
|
|
14
|
+
private _sheetId;
|
|
15
|
+
private _anchorX;
|
|
16
|
+
private _anchorY;
|
|
17
|
+
init(canvas: OffscreenCanvas, dpr: number): void;
|
|
18
|
+
/**
|
|
19
|
+
* Set license - validates the license inside the worker
|
|
20
|
+
* This is the ONLY way to hide the watermark - no bypass possible
|
|
21
|
+
*/
|
|
22
|
+
setLicense(apiKey: string, domain: string): Promise<LicenseStatus>;
|
|
23
|
+
/**
|
|
24
|
+
* Clear license and show watermark again
|
|
25
|
+
*/
|
|
26
|
+
clearLicense(): void;
|
|
27
|
+
resize(width: number, height: number, dpr: number): Result<Grid>;
|
|
28
|
+
render(sheetId: number, anchorX: number, anchorY: number): Result<Grid>;
|
|
29
|
+
getAppropriateHeights(sheetId: number, anchorX: number, anchorY: number): Result<AppropriateHeight[]>;
|
|
30
|
+
handleRequest(request: {
|
|
31
|
+
m: string;
|
|
32
|
+
args: any;
|
|
33
|
+
rid: number;
|
|
34
|
+
}): void;
|
|
35
|
+
}
|