@rowsncolumns/y-spreadsheet 14.0.32

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.
Files changed (53) hide show
  1. package/LICENSE.md +100 -0
  2. package/Readme.md +77 -0
  3. package/dist/cjs/helpers.d.ts +179 -0
  4. package/dist/cjs/helpers.d.ts.map +1 -0
  5. package/dist/cjs/helpers.js +1635 -0
  6. package/dist/cjs/index.d.ts +6 -0
  7. package/dist/cjs/index.d.ts.map +1 -0
  8. package/dist/cjs/index.js +8 -0
  9. package/dist/cjs/observables.d.ts +10 -0
  10. package/dist/cjs/observables.d.ts.map +1 -0
  11. package/dist/cjs/observables.js +90 -0
  12. package/dist/cjs/profiling/batch-profile.spec.d.ts +2 -0
  13. package/dist/cjs/profiling/batch-profile.spec.d.ts.map +1 -0
  14. package/dist/cjs/profiling/batch-profile.spec.js +175 -0
  15. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  16. package/dist/cjs/types.d.ts +62 -0
  17. package/dist/cjs/types.d.ts.map +1 -0
  18. package/dist/cjs/types.js +2 -0
  19. package/dist/cjs/use-yspreadsheet-v2.d.ts +152 -0
  20. package/dist/cjs/use-yspreadsheet-v2.d.ts.map +1 -0
  21. package/dist/cjs/use-yspreadsheet-v2.js +980 -0
  22. package/dist/cjs/use-yspreadsheet.d.ts +39 -0
  23. package/dist/cjs/use-yspreadsheet.d.ts.map +1 -0
  24. package/dist/cjs/use-yspreadsheet.js +430 -0
  25. package/dist/cjs/vitest.config.d.ts +3 -0
  26. package/dist/cjs/vitest.config.d.ts.map +1 -0
  27. package/dist/cjs/vitest.config.js +23 -0
  28. package/dist/esm/helpers.d.ts +179 -0
  29. package/dist/esm/helpers.d.ts.map +1 -0
  30. package/dist/esm/helpers.js +1346 -0
  31. package/dist/esm/index.d.ts +6 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +5 -0
  34. package/dist/esm/observables.d.ts +10 -0
  35. package/dist/esm/observables.d.ts.map +1 -0
  36. package/dist/esm/observables.js +51 -0
  37. package/dist/esm/profiling/batch-profile.spec.d.ts +2 -0
  38. package/dist/esm/profiling/batch-profile.spec.d.ts.map +1 -0
  39. package/dist/esm/profiling/batch-profile.spec.js +131 -0
  40. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  41. package/dist/esm/types.d.ts +62 -0
  42. package/dist/esm/types.d.ts.map +1 -0
  43. package/dist/esm/types.js +1 -0
  44. package/dist/esm/use-yspreadsheet-v2.d.ts +152 -0
  45. package/dist/esm/use-yspreadsheet-v2.d.ts.map +1 -0
  46. package/dist/esm/use-yspreadsheet-v2.js +814 -0
  47. package/dist/esm/use-yspreadsheet.d.ts +39 -0
  48. package/dist/esm/use-yspreadsheet.d.ts.map +1 -0
  49. package/dist/esm/use-yspreadsheet.js +304 -0
  50. package/dist/esm/vitest.config.d.ts +3 -0
  51. package/dist/esm/vitest.config.d.ts.map +1 -0
  52. package/dist/esm/vitest.config.js +21 -0
  53. package/package.json +54 -0
@@ -0,0 +1,179 @@
1
+ import { type CellData, type CellFormat, type Sheet } from "@rowsncolumns/spreadsheet";
2
+ import { type HistoryType, type SheetData, type SpreadsheetPatch } from "@rowsncolumns/spreadsheet-state";
3
+ import type { Patch } from "immer";
4
+ import * as Y from "yjs";
5
+ import type { YRowData, YSheetData } from "./use-yspreadsheet-v2";
6
+ import type { CellKeyV3, CellDataV3, ParsedCellKeyV3 } from "./types";
7
+ /**
8
+ * Simplified structure to pass event data synchronously
9
+ */
10
+ export type SheetDataEvent = {
11
+ path: (string | number)[];
12
+ delta?: {
13
+ insert?: any[] | number | string;
14
+ delete?: number;
15
+ retain?: number;
16
+ }[];
17
+ isYArrayEvent: boolean;
18
+ };
19
+ /**
20
+ * Apply patches to yjs
21
+ * @param doc
22
+ * @param userId
23
+ * @param patches
24
+ * @param source
25
+ * @param sheetDataVersion - Version of sheet data format ("v2" or "v3"). Falls back to docMeta if undefined.
26
+ */
27
+ export declare const applyPatchesToYDoc: (doc: Y.Doc, userId: string | number, patches: [patch: SpreadsheetPatch<Patch>, type?: HistoryType | undefined | null][], source?: "agent" | "user" | "backend", sheetDataVersion?: "v2" | "v3") => void;
28
+ /**
29
+ * Add sheet data to a yjs map using immer patches
30
+ *
31
+ * Optimized for bulk operations (paste, import) by consolidating cell-level
32
+ * patches before applying to Y.js. This reduces overhead by:
33
+ * 1. Deduplicating patches targeting the same cell (later patches win)
34
+ * 2. Grouping updates by sheet/row for efficient batch application
35
+ */
36
+ export declare const addSheetDataPatches: (ySheetData: Y.Map<YSheetData>, patches: Patch[]) => void;
37
+ export declare const getSheetFromYSheetData: (ySheetData: Y.Map<YSheetData>, sheetId: string | number) => YSheetData;
38
+ export declare const deleteSheetFromYSheetData: (ySheetData: Y.Map<YSheetData>, sheetId: string | number) => void;
39
+ export declare const getRowDataFromSheet: (ysheet: Y.Array<YRowData | null>, rowIndex: number | string) => Y.Array<CellData | null>;
40
+ export declare const setCellDataInRowData: (rowData: Y.Array<CellData | null>, columnIndex: number | string, cellData?: CellData | null) => void;
41
+ export declare const removeRowData: (ysheet: Y.Array<YRowData | null>, rowIndex: number | string) => void;
42
+ /**
43
+ * Read a cell's data from the V2 Y.js structure without creating any
44
+ * missing sheet/row/values containers (unlike getSheetFromYSheetData /
45
+ * getRowDataFromSheet, which lazily create them).
46
+ */
47
+ export declare const getCellDataFromYSheetData: (ySheetData: Y.Map<YSheetData>, sheetId: string | number, rowIndex: number | string, columnIndex: number | string) => CellData | null | undefined;
48
+ /**
49
+ * Extract the error effective value from cell data, if any.
50
+ * SheetCell.setErrorValue persists formula errors as
51
+ * `ev.ev = { type: "Error", name, message }` (legacy long form:
52
+ * `effectiveValue.errorValue`).
53
+ */
54
+ export declare const getCellDataErrorValue: (cellData?: CellData | null) => Record<string, any> | undefined;
55
+ /**
56
+ * Keep only the cell-level sheetData patches
57
+ * (`[sheetId, rowIndex, "values", columnIndex]`) whose new cell data carries
58
+ * an error effective value (#VALUE!, #NAME?, …). Used to let calc-result
59
+ * errors bypass the leader gate: errors must reach the Y.Doc even from
60
+ * non-leader clients, otherwise they render blank after reload.
61
+ */
62
+ export declare const filterErrorCellPatches: (patches: Patch[]) => Patch[];
63
+ /**
64
+ * Containment guard for the non-leader error-persistence path
65
+ * (use-yspreadsheet-v2 onBroadcastPatch, gated disableRecalc branch).
66
+ * A gated error cell patch may be written ONLY when all of these hold:
67
+ *
68
+ * 1. The incoming cell data carries an error effective value.
69
+ * 2. The current doc cell holds no effective value at all (the
70
+ * blank-after-reload case) or its effective value is itself an error.
71
+ * A non-error result (number/string/bool/formula result) is never
72
+ * overwritten — a stale non-leader error must not clobber a newer
73
+ * leader-written success.
74
+ * 3. If the doc cell exists, its user-entered value (`ue`, short or legacy
75
+ * key shape) matches the incoming patch's — a cell edited after the
76
+ * calculation started is never touched.
77
+ * 4. The persisted error differs from the incoming one (identical errors
78
+ * are dropped so concurrent non-leaders don't append redundant
79
+ * Y.js updates).
80
+ */
81
+ export declare const shouldPersistErrorCellPatch: (currentCellData: CellData | null | undefined, incomingCellData: CellData | null | undefined) => boolean;
82
+ /**
83
+ * Build the cell data to write for a gated error patch that passed
84
+ * shouldPersistErrorCellPatch. If the doc cell doesn't exist yet there is
85
+ * nothing to destroy and the incoming cell data is written as-is. If it
86
+ * does exist, ONLY the error effective value is merged in — every other
87
+ * field of the doc cell (ue, formats, notes, …) is preserved so this write
88
+ * path can never remove doc state it didn't produce. The effective value is
89
+ * written into whichever key shape(s) the doc cell already uses (short `ev`
90
+ * by default).
91
+ */
92
+ export declare const mergeErrorEffectiveValueIntoCellData: (currentCellData: CellData | null | undefined, incomingCellData: CellData) => CellData;
93
+ /**
94
+ * Update array type with immer patches
95
+ */
96
+ export declare const updateArrayType: (yarray: Y.Array<any>, patches: Patch[]) => void;
97
+ /**
98
+ * Validate and clean sheets data
99
+ */
100
+ export declare const validateSheets: <S extends Sheet>(sheets: S[]) => S[];
101
+ /**
102
+ * Map operations
103
+ */
104
+ export declare const applyMapPatches: <T = CellFormat>(yMap: Y.Map<T>, patches: Patch[]) => void;
105
+ /**
106
+ * Process events to find changes in sheet data
107
+ * Returns a new sheet data object with only the changes applied if possible, or null if a full reload is needed
108
+ */
109
+ export declare const processSheetDataEvents: (events: SheetDataEvent[], currentSheetData: SheetData<any>, ySheetDataV2: Y.Map<YSheetData>) => SheetData<any> | null;
110
+ /**
111
+ * Create a V3 cell key from sheet ID, row and column indices
112
+ * Format: `${sheetId}!${A1Address}` (e.g., "1!A1", "2!B5")
113
+ */
114
+ export declare const createCellKeyV3: (sheetId: number, rowIndex: number, columnIndex: number) => CellKeyV3;
115
+ /**
116
+ * Parse a V3 cell key to extract sheet ID and position information
117
+ * Example: parseCellKeyV3("1!A1") => { sheetId: 1, address: "A1", rowIndex: 1, columnIndex: 1 }
118
+ */
119
+ export declare const parseCellKeyV3: (cellKey: CellKeyV3) => ParsedCellKeyV3 | null;
120
+ /**
121
+ * Create a CellDataV3 object with position and sheetId
122
+ */
123
+ export declare const createCellDataV3: <T extends CellData>(value: T, sheetId: number, rowIndex: number, columnIndex: number) => CellDataV3<T>;
124
+ /**
125
+ * Type for Y.Map storing V3 cell data (flat structure)
126
+ * Key format: `${sheetId}!${A1Address}` (e.g., "1!A1", "2!B5")
127
+ */
128
+ export type YSheetDataV3 = Y.Map<CellDataV3>;
129
+ /**
130
+ * Convert V2 SheetData to V3 flat Map format
131
+ * V2: { sheetId: [rows with values arrays] }
132
+ * V3: Map<cellKey, CellDataV3>
133
+ */
134
+ export declare const sheetDataV2ToV3: <T extends CellData>(v2Data: SheetData<T>) => Map<string, CellDataV3<T>>;
135
+ /**
136
+ * Convert V3 flat Map format to V2 SheetData
137
+ * V3: Map<cellKey, CellDataV3>
138
+ * V2: { sheetId: [rows with values arrays] }
139
+ */
140
+ export declare const sheetDataV3ToV2: <T extends CellData>(v3Data: Map<string, CellDataV3<T>>) => SheetData<T>;
141
+ /**
142
+ * Get a cell from V3 flat structure
143
+ */
144
+ export declare const getCellV3: (ySheetDataV3: YSheetDataV3, sheetId: number, rowIndex: number, columnIndex: number) => CellDataV3 | undefined;
145
+ /**
146
+ * Set a cell in V3 flat structure
147
+ */
148
+ export declare const setCellV3: (ySheetDataV3: YSheetDataV3, sheetId: number, rowIndex: number, columnIndex: number, value: CellData) => void;
149
+ /**
150
+ * Delete a cell from V3 flat structure
151
+ */
152
+ export declare const deleteCellV3: (ySheetDataV3: YSheetDataV3, sheetId: number, rowIndex: number, columnIndex: number) => void;
153
+ /**
154
+ * Delete all cells for a sheet from V3 flat structure
155
+ */
156
+ export declare const deleteSheetV3: (ySheetDataV3: YSheetDataV3, sheetId: number) => void;
157
+ /**
158
+ * Get V3 sheet data map from Y.Doc
159
+ */
160
+ export declare const getSheetDataV3: (doc: Y.Doc) => YSheetDataV3;
161
+ /**
162
+ * Apply immer patches to V3 sheet data (flat map structure)
163
+ *
164
+ * Optimized for bulk operations (paste, import) by consolidating cell-level
165
+ * patches before applying to Y.js. This reduces overhead by:
166
+ * 1. Deduplicating patches targeting the same cell (later patches win)
167
+ * 2. Processing all cell updates in a single pass
168
+ */
169
+ export declare const addSheetDataPatchesV3: (ySheetDataV3: YSheetDataV3, patches: Patch[]) => void;
170
+ /**
171
+ * Process V3 events and return updated sheet data
172
+ * @param changedKeys - Pre-extracted changes from Yjs event
173
+ * @param currentSheetData - Current sheet data state
174
+ * @param ySheetDataV3 - The Y.Map for V3 data
175
+ */
176
+ export declare const processSheetDataEventsV3: <T extends CellData>(changedKeys: Map<string, {
177
+ action: "add" | "update" | "delete";
178
+ }>, currentSheetData: SheetData<T>, ySheetDataV3: YSheetDataV3) => SheetData<T> | null;
179
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../helpers.ts"],"names":[],"mappings":"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"}