@kuzuma/colwork 0.1.0 → 0.2.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 +140 -0
- package/dist/colwork.js +1775 -1188
- package/dist/colwork.umd.cjs +6 -7
- package/dist/index.d.ts +174 -93
- package/dist/model-merges.d.cts +3 -0
- package/dist/model-merges.d.ts +3 -0
- package/dist/model-schema.d.cts +80 -0
- package/dist/model-schema.d.ts +80 -0
- package/dist/model-validation.d.cts +7 -0
- package/dist/model-validation.d.ts +7 -0
- package/dist/model.cjs +1 -0
- package/dist/model.d.cts +18 -0
- package/dist/model.d.ts +18 -0
- package/dist/model.js +259 -0
- package/dist/range.d.cts +15 -0
- package/dist/range.d.ts +15 -0
- package/dist/yjsArchive.d.cts +28 -0
- package/dist/yjsArchive.d.ts +28 -0
- package/dist/yjsRebuild.d.cts +2 -0
- package/dist/yjsRebuild.d.ts +2 -0
- package/package.json +18 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
|
+
import { Awareness } from 'y-protocols/awareness';
|
|
2
|
+
import * as Y from 'yjs';
|
|
3
|
+
|
|
1
4
|
export declare type AwarenessSelection = {
|
|
2
5
|
anchor?: CellPosition;
|
|
3
6
|
focus?: CellPosition;
|
|
4
7
|
mode?: SelectionMode_2;
|
|
5
8
|
};
|
|
6
9
|
|
|
10
|
+
export declare type BuiltInCollaborationOptions = CommonOptions & {
|
|
11
|
+
room: string;
|
|
12
|
+
transport?: 'webrtc' | 'websocket';
|
|
13
|
+
collaboration?: never;
|
|
14
|
+
signalingUrl?: string;
|
|
15
|
+
websocketUrl?: string;
|
|
16
|
+
peerOpts?: Record<string, unknown>;
|
|
17
|
+
initializeAfterSync?: boolean;
|
|
18
|
+
rows?: string[][];
|
|
19
|
+
snapshot?: Uint8Array;
|
|
20
|
+
updates?: Uint8Array[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export declare type CellBorder = {
|
|
24
|
+
top?: boolean;
|
|
25
|
+
right?: boolean;
|
|
26
|
+
bottom?: boolean;
|
|
27
|
+
left?: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
7
30
|
export declare function cellKey(position: CellPosition): string;
|
|
8
31
|
|
|
32
|
+
export declare type CellLock = '1' | PasswordLock;
|
|
33
|
+
|
|
9
34
|
export declare type CellPosition = {
|
|
10
35
|
row: number;
|
|
11
36
|
column: number;
|
|
@@ -16,16 +41,49 @@ export declare type CellRange = {
|
|
|
16
41
|
end: CellPosition;
|
|
17
42
|
};
|
|
18
43
|
|
|
44
|
+
export declare type CellStyle = {
|
|
45
|
+
bold?: boolean;
|
|
46
|
+
italic?: boolean;
|
|
47
|
+
underline?: boolean;
|
|
48
|
+
strike?: boolean;
|
|
49
|
+
wrap?: boolean;
|
|
50
|
+
border?: CellBorder;
|
|
51
|
+
fontSize?: number;
|
|
52
|
+
color?: string;
|
|
53
|
+
background?: string;
|
|
54
|
+
align?: 'left' | 'center' | 'right';
|
|
55
|
+
format?: 'general' | 'number' | 'date' | 'percent';
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export declare const COLWORK_MAP_NAMES: Readonly<{
|
|
59
|
+
readonly cells: "cells";
|
|
60
|
+
readonly styles: "styles";
|
|
61
|
+
readonly rowHeights: "rowHeights";
|
|
62
|
+
readonly columnWidths: "columnWidths";
|
|
63
|
+
readonly merges: "merges";
|
|
64
|
+
readonly locks: "locks";
|
|
65
|
+
readonly metadata: "colwork-metadata";
|
|
66
|
+
}>;
|
|
67
|
+
|
|
68
|
+
/** The existing version-one wire format. Missing metadata is valid legacy data. */
|
|
69
|
+
export declare const COLWORK_SCHEMA_VERSION: 1;
|
|
70
|
+
|
|
19
71
|
export declare class ColworkTable {
|
|
72
|
+
private readonly session;
|
|
20
73
|
private readonly doc;
|
|
74
|
+
private readonly sheet;
|
|
21
75
|
private readonly cells;
|
|
22
76
|
private readonly styles;
|
|
23
77
|
private readonly rowHeights;
|
|
24
78
|
private readonly columnWidths;
|
|
25
79
|
private readonly locks;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
80
|
+
private readonly pointer;
|
|
81
|
+
private readonly clipboard;
|
|
82
|
+
private readonly selection;
|
|
83
|
+
private readonly formatting;
|
|
84
|
+
private readonly dialogs;
|
|
28
85
|
private destroyed;
|
|
86
|
+
private editEpoch;
|
|
29
87
|
private frozenRows;
|
|
30
88
|
private frozenColumns;
|
|
31
89
|
private readonly merges;
|
|
@@ -34,27 +92,21 @@ export declare class ColworkTable {
|
|
|
34
92
|
private readonly awareness;
|
|
35
93
|
private readonly root;
|
|
36
94
|
private readonly options;
|
|
95
|
+
private readonly toolbar;
|
|
37
96
|
private readonly table;
|
|
38
97
|
private readonly viewportResizeObserver;
|
|
39
98
|
private readonly viewport;
|
|
40
99
|
private readonly frozenBoundaryLayer;
|
|
41
100
|
private protectionMenuButton?;
|
|
42
|
-
private
|
|
43
|
-
private pendingCellContext?;
|
|
44
|
-
private rightButtonReleased;
|
|
45
|
-
private rightMouseUpPoint?;
|
|
46
|
-
private rightDrag?;
|
|
101
|
+
private readonly menu;
|
|
47
102
|
private undoButton?;
|
|
48
103
|
private redoButton?;
|
|
49
|
-
private
|
|
50
|
-
private columnCountValue;
|
|
104
|
+
private readonly dimensions;
|
|
51
105
|
private zoomRatio;
|
|
52
106
|
private showGridLines;
|
|
53
107
|
private bandedRows;
|
|
54
|
-
private
|
|
55
|
-
private
|
|
56
|
-
private updateSequence;
|
|
57
|
-
private readonly updateLog;
|
|
108
|
+
private readOnly;
|
|
109
|
+
private readonly archive;
|
|
58
110
|
private resizing?;
|
|
59
111
|
private readonly onCellsChange;
|
|
60
112
|
private readonly onStylesChange;
|
|
@@ -72,42 +124,26 @@ export declare class ColworkTable {
|
|
|
72
124
|
private readonly onWindowBlur;
|
|
73
125
|
private readonly onWindowMouseMove;
|
|
74
126
|
private readonly onHistoryChange;
|
|
75
|
-
private
|
|
76
|
-
private editingKey?;
|
|
77
|
-
private editingOriginal;
|
|
78
|
-
private selectedKey?;
|
|
79
|
-
private selectionAnchor?;
|
|
80
|
-
private selectionFocus?;
|
|
81
|
-
private selectionMode?;
|
|
82
|
-
private selecting;
|
|
83
|
-
private headerSelecting?;
|
|
84
|
-
private pendingAwarenessCursor?;
|
|
85
|
-
private readonly loggedPeers;
|
|
86
|
-
private readonly loggedSignals;
|
|
87
|
-
private readonly onDocUpdate;
|
|
88
|
-
private readonly onAwarenessUpdate;
|
|
127
|
+
private readonly editing;
|
|
89
128
|
constructor(root: HTMLElement, options: ColworkTableOptions);
|
|
90
129
|
private log;
|
|
91
130
|
private undo;
|
|
92
131
|
private redo;
|
|
93
132
|
private refreshHistoryButtons;
|
|
133
|
+
/** Changes local editing affordances. Hosts enforce actual document permissions. */
|
|
134
|
+
setReadOnly(readOnly: boolean): void;
|
|
135
|
+
/** Explicitly commits the active cell draft before a host publishes or exports. */
|
|
136
|
+
commitEditing(): void;
|
|
137
|
+
/** Discards an active draft while preserving the current shared document value. */
|
|
138
|
+
cancelEditing(): void;
|
|
94
139
|
getYjsSnapshot(): YjsSnapshotFile;
|
|
95
140
|
getYjsUpdateLog(): YjsUpdateLogFile;
|
|
96
|
-
/** Freeze a leading prefix
|
|
141
|
+
/** Freeze a leading prefix in this local view. */
|
|
97
142
|
setFrozenPanes(rows: number, columns: number): boolean;
|
|
98
|
-
private hasPartialMerge;
|
|
99
143
|
private crossesFrozenBoundary;
|
|
100
144
|
private freezeSelection;
|
|
101
|
-
private rangeHasLocks;
|
|
102
|
-
private isCellLocked;
|
|
103
|
-
private isCellPasswordLocked;
|
|
104
145
|
private selectionHasLocks;
|
|
105
|
-
private isAxisLocked;
|
|
106
|
-
/** Passwords are optional for legacy/plain locks; protected locks require verification. */
|
|
107
146
|
setSelectionLocked(locked: boolean, password?: string): Promise<void>;
|
|
108
|
-
private requestSelectionLock;
|
|
109
|
-
private closeLockMessage;
|
|
110
|
-
private showLockMessage;
|
|
111
147
|
private get rowCount();
|
|
112
148
|
private get columnCount();
|
|
113
149
|
private get rowHeaderWidth();
|
|
@@ -116,100 +152,145 @@ export declare class ColworkTable {
|
|
|
116
152
|
private getColumnWidth;
|
|
117
153
|
private beginResize;
|
|
118
154
|
private addResizeHandle;
|
|
119
|
-
private selectRange;
|
|
120
|
-
private hideContextMenu;
|
|
121
|
-
private showContextMenu;
|
|
122
|
-
private protectionActions;
|
|
123
|
-
private hasHeaderSelection;
|
|
124
|
-
private openRowContextMenu;
|
|
125
|
-
private openColumnContextMenu;
|
|
126
|
-
private mergeKey;
|
|
127
|
-
private parseMergeKey;
|
|
128
|
-
private getMergeRanges;
|
|
129
|
-
private expandSelectionToMerges;
|
|
130
|
-
private getMergeStartingAt;
|
|
131
|
-
private isMergeCovered;
|
|
132
155
|
private mergeSelection;
|
|
133
156
|
private unmergeSelection;
|
|
134
157
|
private modifyAxis;
|
|
135
158
|
private deleteRows;
|
|
136
159
|
private deleteColumns;
|
|
137
|
-
private selectHeaderRange;
|
|
138
|
-
private selectHeaderSpan;
|
|
139
|
-
private addHeaderSelection;
|
|
140
160
|
private expandLogicalSpace;
|
|
141
|
-
private publishSelection;
|
|
142
|
-
private updateAwareness;
|
|
143
161
|
private expandForRemoteSelections;
|
|
144
|
-
private getSelectionBounds;
|
|
145
|
-
private selectCell;
|
|
146
|
-
private isPositionSelected;
|
|
147
|
-
private selectionToClipboard;
|
|
148
|
-
private selectionToText;
|
|
149
|
-
private copySelection;
|
|
150
162
|
private clearSelectionContents;
|
|
151
|
-
private showCellContextMenu;
|
|
152
|
-
private openCellContextMenu;
|
|
153
|
-
private sendAwareness;
|
|
154
|
-
private onCopy;
|
|
155
|
-
private onPaste;
|
|
156
|
-
private logChunk;
|
|
157
|
-
private inspectConnections;
|
|
158
|
-
private seed;
|
|
159
|
-
private seedDemoFormatting;
|
|
160
163
|
private expandLogicalSizeFromDocument;
|
|
161
164
|
private render;
|
|
162
|
-
private refreshFrozenBoundaries;
|
|
163
165
|
private refreshValues;
|
|
164
166
|
private refreshSelection;
|
|
165
167
|
private refreshCursors;
|
|
166
|
-
private addSelectionOverlay;
|
|
167
|
-
private addCursorLabel;
|
|
168
|
-
private startEdit;
|
|
169
|
-
private readStyle;
|
|
170
|
-
private applyStyle;
|
|
171
|
-
private displayValue;
|
|
172
|
-
private toggleFormat;
|
|
173
|
-
private clearFormatting;
|
|
174
|
-
private toggleBorder;
|
|
175
|
-
private setStyle;
|
|
176
168
|
private refreshStyles;
|
|
177
|
-
private
|
|
169
|
+
private refreshView;
|
|
178
170
|
destroy(): void;
|
|
179
171
|
}
|
|
180
172
|
|
|
181
|
-
export declare type ColworkTableOptions =
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
export declare type ColworkTableOptions = ExternalCollaborationOptions | BuiltInCollaborationOptions;
|
|
174
|
+
|
|
175
|
+
declare type CommonOptions = {
|
|
184
176
|
user: string;
|
|
185
|
-
|
|
177
|
+
userColor?: string;
|
|
186
178
|
rowCount?: number;
|
|
187
179
|
columnCount?: number;
|
|
188
180
|
onLog?: (message: string) => void;
|
|
189
|
-
userColor?: string;
|
|
190
|
-
peerOpts?: Record<string, unknown>;
|
|
191
|
-
transport?: 'webrtc' | 'websocket';
|
|
192
|
-
websocketUrl?: string;
|
|
193
|
-
initializeAfterSync?: boolean;
|
|
194
181
|
readOnly?: boolean;
|
|
195
|
-
|
|
196
|
-
updates?: Uint8Array[];
|
|
182
|
+
onEditingChange?: (state: EditingState) => void;
|
|
197
183
|
};
|
|
198
184
|
|
|
199
185
|
export declare function containsPosition(range: CellRange, position: CellPosition): boolean;
|
|
200
186
|
|
|
187
|
+
export declare type EditingState = {
|
|
188
|
+
editing: boolean;
|
|
189
|
+
dirty: boolean;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export declare function exportYjsSnapshot(document: Y.Doc, options?: {
|
|
193
|
+
room?: string;
|
|
194
|
+
sequence?: number;
|
|
195
|
+
}): YjsSnapshotFile;
|
|
196
|
+
|
|
197
|
+
export declare type ExternalCollaborationOptions = CommonOptions & {
|
|
198
|
+
transport: 'external';
|
|
199
|
+
collaboration: {
|
|
200
|
+
document: Y.Doc;
|
|
201
|
+
awareness: Awareness;
|
|
202
|
+
};
|
|
203
|
+
room?: string;
|
|
204
|
+
rows?: never;
|
|
205
|
+
snapshot?: never;
|
|
206
|
+
updates?: never;
|
|
207
|
+
initializeAfterSync?: false;
|
|
208
|
+
signalingUrl?: never;
|
|
209
|
+
websocketUrl?: never;
|
|
210
|
+
peerOpts?: never;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/** Materializes named Y.Map roots, preserving the version-one encoding. */
|
|
214
|
+
export declare function getSheetMaps(document: Y.Doc): SheetMaps;
|
|
215
|
+
|
|
216
|
+
/** Initializes an empty document without demo cells, headers, styles, or network access. */
|
|
217
|
+
export declare function initializeBlankSheet(document: Y.Doc): void;
|
|
218
|
+
|
|
219
|
+
export declare function mergeKey(range: CellRange): string;
|
|
220
|
+
|
|
201
221
|
export declare function normalizeRange(start: CellPosition, end: CellPosition): CellRange;
|
|
202
222
|
|
|
223
|
+
export declare function parseCellKey(key: string): {
|
|
224
|
+
row: number;
|
|
225
|
+
column: number;
|
|
226
|
+
} | undefined;
|
|
227
|
+
|
|
228
|
+
export declare function parseMergeKey(key: string): CellRange | undefined;
|
|
229
|
+
|
|
230
|
+
export declare type PasswordLock = {
|
|
231
|
+
version: 1;
|
|
232
|
+
algorithm: 'PBKDF2-SHA-256';
|
|
233
|
+
iterations: 600000;
|
|
234
|
+
salt: string;
|
|
235
|
+
verifier: string;
|
|
236
|
+
};
|
|
237
|
+
|
|
203
238
|
export declare function rangeSize(range: CellRange): {
|
|
204
239
|
rows: number;
|
|
205
240
|
columns: number;
|
|
206
241
|
};
|
|
207
242
|
|
|
243
|
+
/** Reads a deterministic sparse sheet without loading a renderer, browser globals, or CSS. */
|
|
244
|
+
export declare function readSheetSnapshot(document: Y.Doc, limits?: SheetValidationLimits): SheetSnapshot;
|
|
245
|
+
|
|
246
|
+
/** Decodes a Yjs state update and releases its temporary document after export. */
|
|
247
|
+
export declare function readSheetSnapshotUpdate(update: Uint8Array, limits?: SheetValidationLimits): SheetSnapshot;
|
|
248
|
+
|
|
208
249
|
export declare function rebuildYjsSnapshot(snapshotText?: string, updateLogText?: string): YjsSnapshotFile;
|
|
209
250
|
|
|
210
251
|
declare type SelectionMode_2 = 'row' | 'column' | 'all';
|
|
211
252
|
export { SelectionMode_2 as SelectionMode }
|
|
212
253
|
|
|
254
|
+
export declare type SheetMaps = {
|
|
255
|
+
cells: Y.Map<string>;
|
|
256
|
+
styles: Y.Map<string>;
|
|
257
|
+
rowHeights: Y.Map<number>;
|
|
258
|
+
columnWidths: Y.Map<number>;
|
|
259
|
+
merges: Y.Map<string>;
|
|
260
|
+
locks: Y.Map<string>;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/** Sparse, JSON-serializable logical sheet. Dimensions are derived from stored data. */
|
|
264
|
+
export declare type SheetSnapshot = {
|
|
265
|
+
schemaVersion: typeof COLWORK_SCHEMA_VERSION;
|
|
266
|
+
rowCount: number;
|
|
267
|
+
columnCount: number;
|
|
268
|
+
cells: Record<string, string>;
|
|
269
|
+
styles: Record<string, CellStyle>;
|
|
270
|
+
rowHeights: Record<string, number>;
|
|
271
|
+
columnWidths: Record<string, number>;
|
|
272
|
+
merges: CellRange[];
|
|
273
|
+
locks: Record<string, CellLock>;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export declare type SheetValidationIssue = {
|
|
277
|
+
path: string;
|
|
278
|
+
message: string;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/** Optional host policy. Omitted numeric limits impose no application-specific cap. */
|
|
282
|
+
export declare type SheetValidationLimits = {
|
|
283
|
+
maxRows?: number;
|
|
284
|
+
maxColumns?: number;
|
|
285
|
+
maxEntries?: number;
|
|
286
|
+
maxStringLength?: number;
|
|
287
|
+
maxMergeArea?: number;
|
|
288
|
+
maxMerges?: number;
|
|
289
|
+
allowUnknownRoots?: boolean;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export declare function validateSheetDocument(document: Y.Doc, limits?: SheetValidationLimits): SheetValidationIssue[];
|
|
293
|
+
|
|
213
294
|
export declare type YjsArchiveFile = {
|
|
214
295
|
format: 'colwork.archive';
|
|
215
296
|
version: 1;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CellRange } from './range.cjs';
|
|
2
|
+
import type * as Y from 'yjs';
|
|
3
|
+
/** The existing version-one wire format. Missing metadata is valid legacy data. */
|
|
4
|
+
export declare const COLWORK_SCHEMA_VERSION: 1;
|
|
5
|
+
export declare const COLWORK_MAP_NAMES: Readonly<{
|
|
6
|
+
readonly cells: "cells";
|
|
7
|
+
readonly styles: "styles";
|
|
8
|
+
readonly rowHeights: "rowHeights";
|
|
9
|
+
readonly columnWidths: "columnWidths";
|
|
10
|
+
readonly merges: "merges";
|
|
11
|
+
readonly locks: "locks";
|
|
12
|
+
readonly metadata: "colwork-metadata";
|
|
13
|
+
}>;
|
|
14
|
+
export type CellBorder = {
|
|
15
|
+
top?: boolean;
|
|
16
|
+
right?: boolean;
|
|
17
|
+
bottom?: boolean;
|
|
18
|
+
left?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type CellStyle = {
|
|
21
|
+
bold?: boolean;
|
|
22
|
+
italic?: boolean;
|
|
23
|
+
underline?: boolean;
|
|
24
|
+
strike?: boolean;
|
|
25
|
+
wrap?: boolean;
|
|
26
|
+
border?: CellBorder;
|
|
27
|
+
fontSize?: number;
|
|
28
|
+
color?: string;
|
|
29
|
+
background?: string;
|
|
30
|
+
align?: 'left' | 'center' | 'right';
|
|
31
|
+
format?: 'general' | 'number' | 'date' | 'percent';
|
|
32
|
+
};
|
|
33
|
+
export type PasswordLock = {
|
|
34
|
+
version: 1;
|
|
35
|
+
algorithm: 'PBKDF2-SHA-256';
|
|
36
|
+
iterations: 600000;
|
|
37
|
+
salt: string;
|
|
38
|
+
verifier: string;
|
|
39
|
+
};
|
|
40
|
+
export type CellLock = '1' | PasswordLock;
|
|
41
|
+
export type SheetMaps = {
|
|
42
|
+
cells: Y.Map<string>;
|
|
43
|
+
styles: Y.Map<string>;
|
|
44
|
+
rowHeights: Y.Map<number>;
|
|
45
|
+
columnWidths: Y.Map<number>;
|
|
46
|
+
merges: Y.Map<string>;
|
|
47
|
+
locks: Y.Map<string>;
|
|
48
|
+
};
|
|
49
|
+
/** Sparse, JSON-serializable logical sheet. Dimensions are derived from stored data. */
|
|
50
|
+
export type SheetSnapshot = {
|
|
51
|
+
schemaVersion: typeof COLWORK_SCHEMA_VERSION;
|
|
52
|
+
rowCount: number;
|
|
53
|
+
columnCount: number;
|
|
54
|
+
cells: Record<string, string>;
|
|
55
|
+
styles: Record<string, CellStyle>;
|
|
56
|
+
rowHeights: Record<string, number>;
|
|
57
|
+
columnWidths: Record<string, number>;
|
|
58
|
+
merges: CellRange[];
|
|
59
|
+
locks: Record<string, CellLock>;
|
|
60
|
+
};
|
|
61
|
+
export type SheetValidationIssue = {
|
|
62
|
+
path: string;
|
|
63
|
+
message: string;
|
|
64
|
+
};
|
|
65
|
+
export declare function parseCellKey(key: string): {
|
|
66
|
+
row: number;
|
|
67
|
+
column: number;
|
|
68
|
+
} | undefined;
|
|
69
|
+
export declare function mergeKey(range: CellRange): string;
|
|
70
|
+
export declare function parseMergeKey(key: string): CellRange | undefined;
|
|
71
|
+
/** Optional host policy. Omitted numeric limits impose no application-specific cap. */
|
|
72
|
+
export type SheetValidationLimits = {
|
|
73
|
+
maxRows?: number;
|
|
74
|
+
maxColumns?: number;
|
|
75
|
+
maxEntries?: number;
|
|
76
|
+
maxStringLength?: number;
|
|
77
|
+
maxMergeArea?: number;
|
|
78
|
+
maxMerges?: number;
|
|
79
|
+
allowUnknownRoots?: boolean;
|
|
80
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CellRange } from './range.js';
|
|
2
|
+
import type * as Y from 'yjs';
|
|
3
|
+
/** The existing version-one wire format. Missing metadata is valid legacy data. */
|
|
4
|
+
export declare const COLWORK_SCHEMA_VERSION: 1;
|
|
5
|
+
export declare const COLWORK_MAP_NAMES: Readonly<{
|
|
6
|
+
readonly cells: "cells";
|
|
7
|
+
readonly styles: "styles";
|
|
8
|
+
readonly rowHeights: "rowHeights";
|
|
9
|
+
readonly columnWidths: "columnWidths";
|
|
10
|
+
readonly merges: "merges";
|
|
11
|
+
readonly locks: "locks";
|
|
12
|
+
readonly metadata: "colwork-metadata";
|
|
13
|
+
}>;
|
|
14
|
+
export type CellBorder = {
|
|
15
|
+
top?: boolean;
|
|
16
|
+
right?: boolean;
|
|
17
|
+
bottom?: boolean;
|
|
18
|
+
left?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type CellStyle = {
|
|
21
|
+
bold?: boolean;
|
|
22
|
+
italic?: boolean;
|
|
23
|
+
underline?: boolean;
|
|
24
|
+
strike?: boolean;
|
|
25
|
+
wrap?: boolean;
|
|
26
|
+
border?: CellBorder;
|
|
27
|
+
fontSize?: number;
|
|
28
|
+
color?: string;
|
|
29
|
+
background?: string;
|
|
30
|
+
align?: 'left' | 'center' | 'right';
|
|
31
|
+
format?: 'general' | 'number' | 'date' | 'percent';
|
|
32
|
+
};
|
|
33
|
+
export type PasswordLock = {
|
|
34
|
+
version: 1;
|
|
35
|
+
algorithm: 'PBKDF2-SHA-256';
|
|
36
|
+
iterations: 600000;
|
|
37
|
+
salt: string;
|
|
38
|
+
verifier: string;
|
|
39
|
+
};
|
|
40
|
+
export type CellLock = '1' | PasswordLock;
|
|
41
|
+
export type SheetMaps = {
|
|
42
|
+
cells: Y.Map<string>;
|
|
43
|
+
styles: Y.Map<string>;
|
|
44
|
+
rowHeights: Y.Map<number>;
|
|
45
|
+
columnWidths: Y.Map<number>;
|
|
46
|
+
merges: Y.Map<string>;
|
|
47
|
+
locks: Y.Map<string>;
|
|
48
|
+
};
|
|
49
|
+
/** Sparse, JSON-serializable logical sheet. Dimensions are derived from stored data. */
|
|
50
|
+
export type SheetSnapshot = {
|
|
51
|
+
schemaVersion: typeof COLWORK_SCHEMA_VERSION;
|
|
52
|
+
rowCount: number;
|
|
53
|
+
columnCount: number;
|
|
54
|
+
cells: Record<string, string>;
|
|
55
|
+
styles: Record<string, CellStyle>;
|
|
56
|
+
rowHeights: Record<string, number>;
|
|
57
|
+
columnWidths: Record<string, number>;
|
|
58
|
+
merges: CellRange[];
|
|
59
|
+
locks: Record<string, CellLock>;
|
|
60
|
+
};
|
|
61
|
+
export type SheetValidationIssue = {
|
|
62
|
+
path: string;
|
|
63
|
+
message: string;
|
|
64
|
+
};
|
|
65
|
+
export declare function parseCellKey(key: string): {
|
|
66
|
+
row: number;
|
|
67
|
+
column: number;
|
|
68
|
+
} | undefined;
|
|
69
|
+
export declare function mergeKey(range: CellRange): string;
|
|
70
|
+
export declare function parseMergeKey(key: string): CellRange | undefined;
|
|
71
|
+
/** Optional host policy. Omitted numeric limits impose no application-specific cap. */
|
|
72
|
+
export type SheetValidationLimits = {
|
|
73
|
+
maxRows?: number;
|
|
74
|
+
maxColumns?: number;
|
|
75
|
+
maxEntries?: number;
|
|
76
|
+
maxStringLength?: number;
|
|
77
|
+
maxMergeArea?: number;
|
|
78
|
+
maxMerges?: number;
|
|
79
|
+
allowUnknownRoots?: boolean;
|
|
80
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CellStyle, PasswordLock, SheetMaps, SheetValidationIssue, SheetValidationLimits } from './model-schema.cjs';
|
|
2
|
+
import * as Y from 'yjs';
|
|
3
|
+
export declare function isPasswordLock(value: unknown): value is PasswordLock;
|
|
4
|
+
export declare function isCellStyle(value: unknown): value is CellStyle;
|
|
5
|
+
/** Materializes named Y.Map roots, preserving the version-one encoding. */
|
|
6
|
+
export declare function getSheetMaps(document: Y.Doc): SheetMaps;
|
|
7
|
+
export declare function validateSheetDocument(document: Y.Doc, limits?: SheetValidationLimits): SheetValidationIssue[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CellStyle, PasswordLock, SheetMaps, SheetValidationIssue, SheetValidationLimits } from './model-schema.js';
|
|
2
|
+
import * as Y from 'yjs';
|
|
3
|
+
export declare function isPasswordLock(value: unknown): value is PasswordLock;
|
|
4
|
+
export declare function isCellStyle(value: unknown): value is CellStyle;
|
|
5
|
+
/** Materializes named Y.Map roots, preserving the version-one encoding. */
|
|
6
|
+
export declare function getSheetMaps(document: Y.Doc): SheetMaps;
|
|
7
|
+
export declare function validateSheetDocument(document: Y.Doc, limits?: SheetValidationLimits): SheetValidationIssue[];
|
package/dist/model.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("yjs");function _(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const g=_(I),y=1,p=Object.freeze({cells:"cells",styles:"styles",rowHeights:"rowHeights",columnWidths:"columnWidths",merges:"merges",locks:"locks",metadata:"colwork-metadata"});function S(e){if(!/^(0|[1-9]\d*):(0|[1-9]\d*)$/.test(e))return;const[t,r]=e.split(":").map(Number);return Number.isSafeInteger(t)&&Number.isSafeInteger(r)?{row:t,column:r}:void 0}function R(e){return`${e.start.row}:${e.start.column}-${e.end.row}:${e.end.column}`}function E(e){const t=e.split("-");if(t.length!==2)return;const r=S(t[0]),n=S(t[1]);if(!(!r||!n||r.row>n.row||r.column>n.column))return{start:r,end:n}}function z(e){for(const t of e){const r=t.codePointAt(0);if(r>=55296&&r<=57343)return!1}return!0}function U(e){if(e.length<2)return!1;const t=[...new Set(e.flatMap(i=>[i.start.column,i.end.column+1]))].sort((i,m)=>i-m),r=new Map(t.map((i,m)=>[i,m])),n=e.flatMap(i=>[{row:i.start.row,left:r.get(i.start.column),right:r.get(i.end.column+1)-1,delta:1},{row:i.end.row+1,left:r.get(i.start.column),right:r.get(i.end.column+1)-1,delta:-1}]).sort((i,m)=>i.row-m.row||i.delta-m.delta),f=new Int32Array(t.length*4),d=new Int32Array(t.length*4),u=(i,m,c,l,o,s)=>{if(l<=m&&c<=o){f[i]+=s,d[i]+=s;return}const a=Math.floor((m+c)/2);l<=a&&u(i*2,m,a,l,o,s),o>a&&u(i*2+1,a+1,c,l,o,s),f[i]=d[i]+Math.max(f[i*2],f[i*2+1])};for(const i of n)if(u(1,0,t.length-2,i.left,i.right,i.delta),f[1]>1)return!0;return!1}const x=e=>!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype,k=(e,t)=>Object.keys(e).every(r=>t.includes(r));function q(e){return x(e)&&k(e,["version","algorithm","iterations","salt","verifier"])&&e.version===1&&e.algorithm==="PBKDF2-SHA-256"&&e.iterations===6e5&&typeof e.salt=="string"&&/^[0-9a-f]{32}$/.test(e.salt)&&typeof e.verifier=="string"&&/^[0-9a-f]{64}$/.test(e.verifier)}function K(e){if(!x(e)||!k(e,["bold","italic","underline","strike","wrap","border","fontSize","color","background","align","format"]))return!1;for(const t of["bold","italic","underline","strike","wrap"])if(t in e&&typeof e[t]!="boolean")return!1;for(const t of["color","background"])if(t in e&&(typeof e[t]!="string"||!z(e[t])))return!1;if("fontSize"in e&&(typeof e.fontSize!="number"||!Number.isFinite(e.fontSize)||e.fontSize<=0)||"align"in e&&(typeof e.align!="string"||!["left","center","right"].includes(e.align))||"format"in e&&(typeof e.format!="string"||!["general","number","date","percent"].includes(e.format)))return!1;if("border"in e){if(!x(e.border)||!k(e.border,["top","right","bottom","left"]))return!1;for(const t of Object.keys(e.border))if(typeof e.border[t]!="boolean")return!1}return!0}function M(e){return{cells:e.getMap(p.cells),styles:e.getMap(p.styles),rowHeights:e.getMap(p.rowHeights),columnWidths:e.getMap(p.columnWidths),merges:e.getMap(p.merges),locks:e.getMap(p.locks)}}function O(e,t={}){for(const o of["maxRows","maxColumns","maxEntries","maxStringLength","maxMergeArea","maxMerges"]){const s=t[o];if(s!==void 0&&(!Number.isSafeInteger(s)||s<0))throw new RangeError(`${o} must be a non-negative safe integer`)}const r=[];(e.store.pendingStructs!==null||e.store.pendingDs!==null)&&r.push({path:"$",message:"Document contains unresolved Yjs update dependencies"});const n=(o,s)=>{r.push({path:o,message:s})};if(!t.allowUnknownRoots)for(const o of e.share.keys())Object.values(p).includes(o)||n(o,"Unknown document root");let f,d;try{f=M(e),d=e.getMap(p.metadata)}catch{return[...r,{path:"$",message:"Sheet roots must be Y.Map values"}]}for(const[o,s]of[...Object.entries(f),["metadata",d]])(!(s instanceof g.Map)||s._start!==null)&&n(o,"Expected map entries without sequence content");const u=Object.values(f).reduce((o,s)=>o+s.size,d.size);t.maxEntries!==void 0&&u>t.maxEntries&&n("$","Document exceeds maxEntries");const i=(o,s)=>o<Number.MAX_SAFE_INTEGER&&s<Number.MAX_SAFE_INTEGER&&(t.maxRows===void 0||o<t.maxRows)&&(t.maxColumns===void 0||s<t.maxColumns),m=(o,s)=>{if(typeof o!="string")return!1;try{return s(JSON.parse(o))}catch{return!1}},c=(o,s,a)=>{typeof a=="string"&&t.maxStringLength!==void 0&&a.length>t.maxStringLength&&n(`${o}.${s}`,"String exceeds maxStringLength")};for(const o of["cells","styles","locks"])f[o].forEach((s,a)=>{const h=S(a);(!h||!i(h.row,h.column))&&n(`${o}.${a}`,"Invalid or out-of-bounds row:column key"),c(o,a,s),o==="cells"&&(typeof s!="string"||!z(s))&&n(`${o}.${a}`,"Cell values must be strings"),o==="styles"&&!m(s,K)&&n(`${o}.${a}`,"Expected a JSON CellStyle object"),o==="locks"&&s!=="1"&&!m(s,q)&&n(`${o}.${a}`,"Expected a plain lock or version-one password verifier")});for(const o of["rowHeights","columnWidths"])f[o].forEach((s,a)=>{const h=Number(a),N=o==="rowHeights"?t.maxRows:t.maxColumns;(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(h)||h>=Number.MAX_SAFE_INTEGER||N!==void 0&&h>=N)&&n(`${o}.${a}`,"Invalid or out-of-bounds index"),(typeof s!="number"||!Number.isFinite(s)||s<=0)&&n(`${o}.${a}`,"Sizes must be finite positive numbers")});t.maxMerges!==void 0&&f.merges.size>t.maxMerges&&n("merges","Document exceeds maxMerges");const l=[];return f.merges.forEach((o,s)=>{const a=E(s);!a||o!=="1"||!i(a.end.row,a.end.column)?n(`merges.${s}`,"Invalid or out-of-bounds merge range"):(t.maxMergeArea!==void 0&&a.end.row-a.start.row+1>t.maxMergeArea/(a.end.column-a.start.column+1)&&n(`merges.${s}`,"Merge exceeds maxMergeArea"),l.push(a))}),U(l)&&n("merges","Merge ranges must not overlap"),d.forEach((o,s)=>{s==="schemaVersion"?o!==y&&n("metadata.schemaVersion","Unsupported schema version"):s==="initialized"?typeof o!="boolean"&&n("metadata.initialized","Expected a boolean"):n(`metadata.${s}`,"Unknown metadata field")}),r}function w(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}function $(e){const t=atob(e);return Uint8Array.from(t,r=>r.charCodeAt(0))}function j(e){if(e!=null&&e.trim())return JSON.parse(e)}function V(e){if(!(!e||e.format==="colwork.update-log"))return e.format==="colwork.archive"?e.snapshot:e}function A(e){return!e||e.format==="colwork.snapshot"?[]:e.updates??[]}function H(e,t){const r=j(e),n=j(t),f=V(r),d=[...A(r),...A(n)],u=new g.Doc;try{f!=null&&f.snapshot&&g.applyUpdate(u,$(f.snapshot));const i=Number((f==null?void 0:f.sequence)??0),m=new Set,c=new Set;let l=i;for(const o of d.sort((s,a)=>Number(s.seq)-Number(a.seq))){const s=Number(o.seq);!Number.isInteger(s)||typeof o.update!="string"||s<=i||m.has(s)||c.has(o.update)||(g.applyUpdate(u,$(o.update)),m.add(s),c.add(o.update),l=Math.max(l,s))}return{format:"colwork.snapshot",version:1,room:f==null?void 0:f.room,sequence:l,snapshot:w(g.encodeStateAsUpdate(u)),stateVector:w(g.encodeStateVector(u))}}finally{u.destroy()}}function W(e,t){const r=e.split(":").map(Number),n=t.split(":").map(Number);return r[0]-n[0]||(r[1]??0)-(n[1]??0)}function b(e){return[...e].sort(([t],[r])=>W(t,r))}function D(e){const t={};for(const r of["bold","italic","underline","strike","wrap","fontSize","color","background","align","format"])e[r]!==void 0&&(t[r]=e[r]);if(e.border!==void 0){const r={};for(const n of["top","right","bottom","left"])e.border[n]!==void 0&&(r[n]=e.border[n]);t.border=r}return t}function C(e,t){const r=O(e,t);if(r.length)throw new TypeError(`Invalid Colwork document at ${r[0].path}: ${r[0].message}`);const n=M(e),f=Object.fromEntries(b(n.styles).map(([c,l])=>[c,D(JSON.parse(l))])),d=Object.fromEntries(b(n.locks).map(([c,l])=>{if(l==="1")return[c,"1"];const o=JSON.parse(l);return[c,{version:o.version,algorithm:o.algorithm,iterations:o.iterations,salt:o.salt,verifier:o.verifier}]})),u=[...n.merges.keys()].map(c=>E(c)).sort((c,l)=>c.start.row-l.start.row||c.start.column-l.start.column||c.end.row-l.end.row||c.end.column-l.end.column);let i=1,m=1;for(const c of[...n.cells.keys(),...n.styles.keys(),...n.locks.keys()]){const l=S(c);i=Math.max(i,l.row+1),m=Math.max(m,l.column+1)}for(const c of u)i=Math.max(i,c.end.row+1),m=Math.max(m,c.end.column+1);for(const c of n.rowHeights.keys())i=Math.max(i,Number(c)+1);for(const c of n.columnWidths.keys())m=Math.max(m,Number(c)+1);return{schemaVersion:y,rowCount:i,columnCount:m,cells:Object.fromEntries(b(n.cells)),styles:f,rowHeights:Object.fromEntries(b(n.rowHeights)),columnWidths:Object.fromEntries(b(n.columnWidths)),merges:u,locks:d}}function L(e){const t=O(e);if(t.length)throw new TypeError(`Invalid Colwork document at ${t[0].path}: ${t[0].message}`);if(Object.values(M(e)).some(n=>n.size>0))throw new Error("Blank initialization requires an empty sheet");const r=e.getMap(p.metadata);e.transact(()=>{r.set("schemaVersion",y),r.set("initialized",!0)})}function P(e,t={}){const r=t.sequence??0;if(!Number.isSafeInteger(r)||r<0)throw new RangeError("sequence must be a non-negative safe integer");return{format:"colwork.snapshot",version:1,room:t.room,sequence:r,snapshot:w(g.encodeStateAsUpdate(e)),stateVector:w(g.encodeStateVector(e))}}function T(e,t){const r=new g.Doc;try{return g.applyUpdate(r,e),C(r,t)}finally{r.destroy()}}exports.COLWORK_MAP_NAMES=p;exports.COLWORK_SCHEMA_VERSION=y;exports.exportYjsSnapshot=P;exports.getSheetMaps=M;exports.initializeBlankSheet=L;exports.mergeKey=R;exports.parseCellKey=S;exports.parseMergeKey=E;exports.readSheetSnapshot=C;exports.readSheetSnapshotUpdate=T;exports.rebuildYjsSnapshot=H;exports.validateSheetDocument=O;
|
package/dist/model.d.cts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SheetSnapshot, SheetValidationLimits } from './model-schema.cjs';
|
|
2
|
+
import { YjsSnapshotFile } from './yjsArchive.cjs';
|
|
3
|
+
import * as Y from 'yjs';
|
|
4
|
+
export * from './model-schema.cjs';
|
|
5
|
+
export type { CellPosition, CellRange } from './range.cjs';
|
|
6
|
+
export { getSheetMaps, validateSheetDocument } from './model-validation.cjs';
|
|
7
|
+
export { rebuildYjsSnapshot } from './yjsRebuild.cjs';
|
|
8
|
+
export type { YjsArchiveFile, YjsSnapshotFile, YjsUpdateLogFile, YjsUpdateRecord } from './yjsArchive.cjs';
|
|
9
|
+
/** Reads a deterministic sparse sheet without loading a renderer, browser globals, or CSS. */
|
|
10
|
+
export declare function readSheetSnapshot(document: Y.Doc, limits?: SheetValidationLimits): SheetSnapshot;
|
|
11
|
+
/** Initializes an empty document without demo cells, headers, styles, or network access. */
|
|
12
|
+
export declare function initializeBlankSheet(document: Y.Doc): void;
|
|
13
|
+
export declare function exportYjsSnapshot(document: Y.Doc, options?: {
|
|
14
|
+
room?: string;
|
|
15
|
+
sequence?: number;
|
|
16
|
+
}): YjsSnapshotFile;
|
|
17
|
+
/** Decodes a Yjs state update and releases its temporary document after export. */
|
|
18
|
+
export declare function readSheetSnapshotUpdate(update: Uint8Array, limits?: SheetValidationLimits): SheetSnapshot;
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SheetSnapshot, SheetValidationLimits } from './model-schema.js';
|
|
2
|
+
import { YjsSnapshotFile } from './yjsArchive.js';
|
|
3
|
+
import * as Y from 'yjs';
|
|
4
|
+
export * from './model-schema.js';
|
|
5
|
+
export type { CellPosition, CellRange } from './range.js';
|
|
6
|
+
export { getSheetMaps, validateSheetDocument } from './model-validation.js';
|
|
7
|
+
export { rebuildYjsSnapshot } from './yjsRebuild.js';
|
|
8
|
+
export type { YjsArchiveFile, YjsSnapshotFile, YjsUpdateLogFile, YjsUpdateRecord } from './yjsArchive.js';
|
|
9
|
+
/** Reads a deterministic sparse sheet without loading a renderer, browser globals, or CSS. */
|
|
10
|
+
export declare function readSheetSnapshot(document: Y.Doc, limits?: SheetValidationLimits): SheetSnapshot;
|
|
11
|
+
/** Initializes an empty document without demo cells, headers, styles, or network access. */
|
|
12
|
+
export declare function initializeBlankSheet(document: Y.Doc): void;
|
|
13
|
+
export declare function exportYjsSnapshot(document: Y.Doc, options?: {
|
|
14
|
+
room?: string;
|
|
15
|
+
sequence?: number;
|
|
16
|
+
}): YjsSnapshotFile;
|
|
17
|
+
/** Decodes a Yjs state update and releases its temporary document after export. */
|
|
18
|
+
export declare function readSheetSnapshotUpdate(update: Uint8Array, limits?: SheetValidationLimits): SheetSnapshot;
|