@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.
- package/LICENSE.md +100 -0
- package/Readme.md +77 -0
- package/dist/cjs/helpers.d.ts +179 -0
- package/dist/cjs/helpers.d.ts.map +1 -0
- package/dist/cjs/helpers.js +1635 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/observables.d.ts +10 -0
- package/dist/cjs/observables.d.ts.map +1 -0
- package/dist/cjs/observables.js +90 -0
- package/dist/cjs/profiling/batch-profile.spec.d.ts +2 -0
- package/dist/cjs/profiling/batch-profile.spec.d.ts.map +1 -0
- package/dist/cjs/profiling/batch-profile.spec.js +175 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/cjs/types.d.ts +62 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/use-yspreadsheet-v2.d.ts +152 -0
- package/dist/cjs/use-yspreadsheet-v2.d.ts.map +1 -0
- package/dist/cjs/use-yspreadsheet-v2.js +980 -0
- package/dist/cjs/use-yspreadsheet.d.ts +39 -0
- package/dist/cjs/use-yspreadsheet.d.ts.map +1 -0
- package/dist/cjs/use-yspreadsheet.js +430 -0
- package/dist/cjs/vitest.config.d.ts +3 -0
- package/dist/cjs/vitest.config.d.ts.map +1 -0
- package/dist/cjs/vitest.config.js +23 -0
- package/dist/esm/helpers.d.ts +179 -0
- package/dist/esm/helpers.d.ts.map +1 -0
- package/dist/esm/helpers.js +1346 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/observables.d.ts +10 -0
- package/dist/esm/observables.d.ts.map +1 -0
- package/dist/esm/observables.js +51 -0
- package/dist/esm/profiling/batch-profile.spec.d.ts +2 -0
- package/dist/esm/profiling/batch-profile.spec.d.ts.map +1 -0
- package/dist/esm/profiling/batch-profile.spec.js +131 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +62 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/use-yspreadsheet-v2.d.ts +152 -0
- package/dist/esm/use-yspreadsheet-v2.d.ts.map +1 -0
- package/dist/esm/use-yspreadsheet-v2.js +814 -0
- package/dist/esm/use-yspreadsheet.d.ts +39 -0
- package/dist/esm/use-yspreadsheet.d.ts.map +1 -0
- package/dist/esm/use-yspreadsheet.js +304 -0
- package/dist/esm/vitest.config.d.ts +3 -0
- package/dist/esm/vitest.config.d.ts.map +1 -0
- package/dist/esm/vitest.config.js +21 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./use-yspreadsheet"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./use-yspreadsheet-v2"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./helpers"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./observables"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Patch } from "immer";
|
|
2
|
+
import { Observable } from "rxjs";
|
|
3
|
+
import type * as Y from "yjs";
|
|
4
|
+
import type { PatchCoordinate, PatchDocument } from "./types";
|
|
5
|
+
import type { YSheetData } from "./use-yspreadsheet-v2";
|
|
6
|
+
export declare const createSheetDataObservable: (ySheetData: Y.Map<YSheetData>) => Observable<Y.YEvent<any>[]>;
|
|
7
|
+
export declare const getPatchDeltasFromEvent: <S extends PatchCoordinate | Patch, T extends PatchDocument<S>>(event: Y.YArrayEvent<T>) => S[];
|
|
8
|
+
export declare const createObservable: <T = PatchDocument>(yArr: Y.Array<T>) => Observable<Y.YArrayEvent<T>>;
|
|
9
|
+
export declare const createDeepObservable: (yArr: Y.Array<any>) => Observable<Y.YEvent<any>[]>;
|
|
10
|
+
//# sourceMappingURL=observables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observables.d.ts","sourceRoot":"","sources":["../../observables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,KAAK,KAAK,CAAC,MAAM,KAAK,CAAC;AAE9B,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,eAAO,MAAM,yBAAyB,GAAI,YAAY,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,gCAYtE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,CAAC,SAAS,eAAe,GAAG,KAAK,EACjC,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAE1B,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAiBxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,aAAa,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iCAYnE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,gCAYtD,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDeepObservable = exports.createObservable = exports.getPatchDeltasFromEvent = exports.createSheetDataObservable = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var rxjs_1 = require("rxjs");
|
|
6
|
+
var createSheetDataObservable = function (ySheetData) {
|
|
7
|
+
return new rxjs_1.Observable(function (observer) {
|
|
8
|
+
var callback = function (events) {
|
|
9
|
+
observer.next(events);
|
|
10
|
+
};
|
|
11
|
+
ySheetData.observeDeep(callback);
|
|
12
|
+
return function () {
|
|
13
|
+
ySheetData.unobserveDeep(callback);
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
exports.createSheetDataObservable = createSheetDataObservable;
|
|
18
|
+
var getPatchDeltasFromEvent = function (event) {
|
|
19
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
20
|
+
var patches = [];
|
|
21
|
+
if (event.transaction.origin !== "local") {
|
|
22
|
+
try {
|
|
23
|
+
for (var _d = tslib_1.__values(event.changes.delta), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
24
|
+
var changes = _e.value;
|
|
25
|
+
for (var type in changes) {
|
|
26
|
+
if (type === "insert" && changes[type] !== undefined) {
|
|
27
|
+
try {
|
|
28
|
+
for (var _f = (e_2 = void 0, tslib_1.__values(changes[type])), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
29
|
+
var userPatches = _g.value.patches;
|
|
30
|
+
try {
|
|
31
|
+
for (var _h = (e_3 = void 0, tslib_1.__values(userPatches)), _j = _h.next(); !_j.done; _j = _h.next()) {
|
|
32
|
+
var patch = _j.value;
|
|
33
|
+
patches.push(patch);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
37
|
+
finally {
|
|
38
|
+
try {
|
|
39
|
+
if (_j && !_j.done && (_c = _h.return)) _c.call(_h);
|
|
40
|
+
}
|
|
41
|
+
finally { if (e_3) throw e_3.error; }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
46
|
+
finally {
|
|
47
|
+
try {
|
|
48
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
49
|
+
}
|
|
50
|
+
finally { if (e_2) throw e_2.error; }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
57
|
+
finally {
|
|
58
|
+
try {
|
|
59
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
60
|
+
}
|
|
61
|
+
finally { if (e_1) throw e_1.error; }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return patches;
|
|
65
|
+
};
|
|
66
|
+
exports.getPatchDeltasFromEvent = getPatchDeltasFromEvent;
|
|
67
|
+
var createObservable = function (yArr) {
|
|
68
|
+
return new rxjs_1.Observable(function (observer) {
|
|
69
|
+
var callback = function (event) {
|
|
70
|
+
observer.next(event);
|
|
71
|
+
};
|
|
72
|
+
yArr.observe(callback);
|
|
73
|
+
return function () {
|
|
74
|
+
yArr.unobserve(callback);
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
exports.createObservable = createObservable;
|
|
79
|
+
var createDeepObservable = function (yArr) {
|
|
80
|
+
return new rxjs_1.Observable(function (observer) {
|
|
81
|
+
var callback = function (event) {
|
|
82
|
+
observer.next(event);
|
|
83
|
+
};
|
|
84
|
+
yArr.observeDeep(callback);
|
|
85
|
+
return function () {
|
|
86
|
+
yArr.unobserveDeep(callback);
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
exports.createDeepObservable = createDeepObservable;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-profile.spec.d.ts","sourceRoot":"","sources":["../../../profiling/batch-profile.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
/* @vitest-environment jsdom */
|
|
5
|
+
var react_1 = require("@testing-library/react");
|
|
6
|
+
var vitest_1 = require("vitest");
|
|
7
|
+
var Y = tslib_1.__importStar(require("yjs"));
|
|
8
|
+
var use_yspreadsheet_v2_1 = require("../use-yspreadsheet-v2");
|
|
9
|
+
vitest_1.vi.mock("@rowsncolumns/utils", function (importOriginal) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
10
|
+
var actual;
|
|
11
|
+
return tslib_1.__generator(this, function (_a) {
|
|
12
|
+
switch (_a.label) {
|
|
13
|
+
case 0: return [4 /*yield*/, importOriginal()];
|
|
14
|
+
case 1:
|
|
15
|
+
actual = _a.sent();
|
|
16
|
+
return [2 /*return*/, tslib_1.__assign(tslib_1.__assign({}, actual), { scheduleAfterPaint: function (callback) {
|
|
17
|
+
if (typeof requestAnimationFrame === "function") {
|
|
18
|
+
var frameId_1 = requestAnimationFrame(function () { return callback(); });
|
|
19
|
+
return function () {
|
|
20
|
+
if (typeof cancelAnimationFrame === "function") {
|
|
21
|
+
cancelAnimationFrame(frameId_1);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var timeoutId = setTimeout(callback, 0);
|
|
26
|
+
return function () { return clearTimeout(timeoutId); };
|
|
27
|
+
} })];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}); });
|
|
31
|
+
var parseEnvNumber = function (key, fallback) {
|
|
32
|
+
var value = Number(process.env[key]);
|
|
33
|
+
return Number.isFinite(value) ? value : fallback;
|
|
34
|
+
};
|
|
35
|
+
var testTimeoutMs = parseEnvNumber("PROFILE_TEST_TIMEOUT_MS", 30000);
|
|
36
|
+
var now = function () {
|
|
37
|
+
return typeof performance !== "undefined" && typeof performance.now === "function"
|
|
38
|
+
? performance.now()
|
|
39
|
+
: Date.now();
|
|
40
|
+
};
|
|
41
|
+
var createSheetDataPatchBatch = function (sheetId, startRow, rows, columns) {
|
|
42
|
+
var patches = [];
|
|
43
|
+
var _loop_1 = function (rowIndex) {
|
|
44
|
+
var absoluteRow = startRow + rowIndex;
|
|
45
|
+
var values = Array.from({ length: columns }, function (_, columnIndex) { return ({
|
|
46
|
+
value: "R".concat(absoluteRow, "C").concat(columnIndex),
|
|
47
|
+
}); });
|
|
48
|
+
patches.push([
|
|
49
|
+
{
|
|
50
|
+
sheetData: {
|
|
51
|
+
patches: [
|
|
52
|
+
{
|
|
53
|
+
op: "add",
|
|
54
|
+
path: [sheetId, absoluteRow],
|
|
55
|
+
value: { values: values },
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
inversePatches: [],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
undefined,
|
|
62
|
+
]);
|
|
63
|
+
};
|
|
64
|
+
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
65
|
+
_loop_1(rowIndex);
|
|
66
|
+
}
|
|
67
|
+
return patches;
|
|
68
|
+
};
|
|
69
|
+
var waitForCondition = function (condition_1, timeoutMs_1) {
|
|
70
|
+
var args_1 = [];
|
|
71
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
72
|
+
args_1[_i - 2] = arguments[_i];
|
|
73
|
+
}
|
|
74
|
+
return tslib_1.__awaiter(void 0, tslib_1.__spreadArray([condition_1, timeoutMs_1], tslib_1.__read(args_1), false), void 0, function (condition, timeoutMs, intervalMs) {
|
|
75
|
+
var start;
|
|
76
|
+
if (intervalMs === void 0) { intervalMs = 25; }
|
|
77
|
+
return tslib_1.__generator(this, function (_a) {
|
|
78
|
+
switch (_a.label) {
|
|
79
|
+
case 0:
|
|
80
|
+
start = Date.now();
|
|
81
|
+
_a.label = 1;
|
|
82
|
+
case 1:
|
|
83
|
+
if (!(Date.now() - start < timeoutMs)) return [3 /*break*/, 3];
|
|
84
|
+
if (condition()) {
|
|
85
|
+
return [2 /*return*/];
|
|
86
|
+
}
|
|
87
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, intervalMs); })];
|
|
88
|
+
case 2:
|
|
89
|
+
_a.sent();
|
|
90
|
+
return [3 /*break*/, 1];
|
|
91
|
+
case 3: throw new Error("Profiling timed out while waiting for condition.");
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
(0, vitest_1.describe)("profiling: staggered broadcast patches", function () {
|
|
97
|
+
(0, vitest_1.it)("profiles large batch updates without data loss", function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
98
|
+
var sheetId, rowsPerCall, calls, columns, timeoutMs, totalRows, totalPatches, doc, transactSpy, result, memStart, enqueueStart, _loop_2, i, enqueueMs, applyStart, applyMs, sheetData, lastRow, lastValues, lastCell, memEnd, report;
|
|
99
|
+
var _a, _b;
|
|
100
|
+
return tslib_1.__generator(this, function (_c) {
|
|
101
|
+
switch (_c.label) {
|
|
102
|
+
case 0:
|
|
103
|
+
vitest_1.vi.useRealTimers();
|
|
104
|
+
sheetId = parseEnvNumber("PROFILE_SHEET_ID", 1);
|
|
105
|
+
rowsPerCall = parseEnvNumber("PROFILE_ROWS_PER_CALL", 150);
|
|
106
|
+
calls = parseEnvNumber("PROFILE_CALLS", 10);
|
|
107
|
+
columns = parseEnvNumber("PROFILE_COLUMNS", 20);
|
|
108
|
+
timeoutMs = parseEnvNumber("PROFILE_TIMEOUT_MS", 20000);
|
|
109
|
+
totalRows = rowsPerCall * calls;
|
|
110
|
+
totalPatches = totalRows;
|
|
111
|
+
doc = new Y.Doc();
|
|
112
|
+
transactSpy = vitest_1.vi.spyOn(doc, "transact");
|
|
113
|
+
result = (0, react_1.renderHook)(function () {
|
|
114
|
+
return (0, use_yspreadsheet_v2_1.useYSpreadsheetV2)({
|
|
115
|
+
userId: "user-1",
|
|
116
|
+
title: "Profiler",
|
|
117
|
+
sheetId: sheetId,
|
|
118
|
+
doc: doc,
|
|
119
|
+
calculateNow: vitest_1.vi.fn(),
|
|
120
|
+
initialSheets: [],
|
|
121
|
+
onChangeSheetData: vitest_1.vi.fn(),
|
|
122
|
+
onChangeSheets: vitest_1.vi.fn(),
|
|
123
|
+
onChangeTables: vitest_1.vi.fn(),
|
|
124
|
+
enqueueCalculation: vitest_1.vi.fn(),
|
|
125
|
+
enqueueGraphOperation: vitest_1.vi.fn(),
|
|
126
|
+
});
|
|
127
|
+
}).result;
|
|
128
|
+
memStart = (_a = process === null || process === void 0 ? void 0 : process.memoryUsage) === null || _a === void 0 ? void 0 : _a.call(process).heapUsed;
|
|
129
|
+
enqueueStart = now();
|
|
130
|
+
_loop_2 = function (i) {
|
|
131
|
+
var batch = createSheetDataPatchBatch(sheetId, i * rowsPerCall, rowsPerCall, columns);
|
|
132
|
+
(0, react_1.act)(function () {
|
|
133
|
+
result.current.onBroadcastPatch(batch);
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
for (i = 0; i < calls; i++) {
|
|
137
|
+
_loop_2(i);
|
|
138
|
+
}
|
|
139
|
+
enqueueMs = now() - enqueueStart;
|
|
140
|
+
applyStart = now();
|
|
141
|
+
return [4 /*yield*/, waitForCondition(function () {
|
|
142
|
+
var sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
143
|
+
return (sheetData === null || sheetData === void 0 ? void 0 : sheetData.length) === totalRows;
|
|
144
|
+
}, timeoutMs)];
|
|
145
|
+
case 1:
|
|
146
|
+
_c.sent();
|
|
147
|
+
applyMs = now() - applyStart;
|
|
148
|
+
sheetData = doc.getMap("sheetDataV2").get(String(sheetId));
|
|
149
|
+
lastRow = sheetData === null || sheetData === void 0 ? void 0 : sheetData.get(totalRows - 1);
|
|
150
|
+
lastValues = lastRow === null || lastRow === void 0 ? void 0 : lastRow.get("values");
|
|
151
|
+
lastCell = lastValues === null || lastValues === void 0 ? void 0 : lastValues.get(columns - 1);
|
|
152
|
+
if (!lastCell || lastCell.value !== "R".concat(totalRows - 1, "C").concat(columns - 1)) {
|
|
153
|
+
throw new Error("Data loss detected: last cell value mismatch.");
|
|
154
|
+
}
|
|
155
|
+
memEnd = (_b = process === null || process === void 0 ? void 0 : process.memoryUsage) === null || _b === void 0 ? void 0 : _b.call(process).heapUsed;
|
|
156
|
+
report = {
|
|
157
|
+
sheetId: sheetId,
|
|
158
|
+
calls: calls,
|
|
159
|
+
rowsPerCall: rowsPerCall,
|
|
160
|
+
columns: columns,
|
|
161
|
+
totalRows: totalRows,
|
|
162
|
+
totalPatches: totalPatches,
|
|
163
|
+
enqueueMs: Math.round(enqueueMs),
|
|
164
|
+
applyMs: Math.round(applyMs),
|
|
165
|
+
transactBatches: transactSpy.mock.calls.length,
|
|
166
|
+
heapDeltaMB: typeof memStart === "number" && typeof memEnd === "number"
|
|
167
|
+
? Math.round(((memEnd - memStart) / 1024 / 1024) * 100) / 100
|
|
168
|
+
: "n/a",
|
|
169
|
+
};
|
|
170
|
+
console.table(report);
|
|
171
|
+
return [2 /*return*/];
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}); }, testTimeoutMs);
|
|
175
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../../helpers.ts","../../index.ts","../../observables.ts","../../types.ts","../../use-yspreadsheet-v2.ts","../../use-yspreadsheet.ts","../../vitest.config.ts","../../profiling/batch-profile.spec.ts"],"version":"5.8.3"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Patch } from "immer";
|
|
2
|
+
import type { RecalcCellCoordinate } from "@rowsncolumns/spreadsheet-state";
|
|
3
|
+
import type { CellData } from "@rowsncolumns/spreadsheet";
|
|
4
|
+
export type PatchDocument<T = Patch> = {
|
|
5
|
+
userId: string | number;
|
|
6
|
+
patches: T[];
|
|
7
|
+
};
|
|
8
|
+
export type PatchRecalcCells = PatchDocument<PatchCoordinate>;
|
|
9
|
+
export type PatchCoordinate = [
|
|
10
|
+
key: string,
|
|
11
|
+
position: RecalcCellCoordinate,
|
|
12
|
+
/**
|
|
13
|
+
* This is a temporary solution
|
|
14
|
+
* 1. If source is agent => Agent generates patches for cells that needs recalculation. The UI can recalculate the cells and its dependents
|
|
15
|
+
* 2. If source is backend => Agent sets effective value of a cell -> The UI recalculate its dependents | Back-end is only to update a formula result
|
|
16
|
+
* 3. If source is user => Nothing happens Business as usual
|
|
17
|
+
*/
|
|
18
|
+
source?: "agent" | "user" | "backend"
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* V3 Data Structure Types
|
|
22
|
+
*
|
|
23
|
+
* V3 uses a flat Map structure for sheet data storage:
|
|
24
|
+
* - Key format: `${sheetId}!${A1Address}` (e.g., "1!A1", "2!B5")
|
|
25
|
+
* - Value: CellDataV3 containing cell data and position
|
|
26
|
+
*
|
|
27
|
+
* Benefits:
|
|
28
|
+
* - O(1) cell lookups by key
|
|
29
|
+
* - Sparse storage (no null padding for empty cells)
|
|
30
|
+
* - More efficient for large spreadsheets with sparse data
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* V3 cell data structure containing value and flattened position
|
|
34
|
+
* - value: The cell data
|
|
35
|
+
* - sId: Sheet ID
|
|
36
|
+
* - r: Row index (1-based)
|
|
37
|
+
* - c: Column index (1-based)
|
|
38
|
+
*/
|
|
39
|
+
export type CellDataV3<T extends CellData = CellData> = {
|
|
40
|
+
value: T;
|
|
41
|
+
/** Sheet ID */
|
|
42
|
+
sId: number;
|
|
43
|
+
/** Row index (1-based) */
|
|
44
|
+
r: number;
|
|
45
|
+
/** Column index (1-based) */
|
|
46
|
+
c: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* V3 cell key format: `${sheetId}!${A1Address}`
|
|
50
|
+
* Examples: "1!A1", "2!B5", "1!AA100"
|
|
51
|
+
*/
|
|
52
|
+
export type CellKeyV3 = string;
|
|
53
|
+
/**
|
|
54
|
+
* Parsed cell key containing sheet ID and position information
|
|
55
|
+
*/
|
|
56
|
+
export type ParsedCellKeyV3 = {
|
|
57
|
+
sheetId: number;
|
|
58
|
+
address: string;
|
|
59
|
+
rowIndex: number;
|
|
60
|
+
columnIndex: number;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,KAAK,IAAI;IACrC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,OAAO,EAAE,CAAC,EAAE,CAAC;CACd,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAC9D,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM;IACX,QAAQ,EAAE,oBAAoB;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;CACtC,CAAC;AAEF;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IACtD,KAAK,EAAE,CAAC,CAAC;IACT,eAAe;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,6BAA6B;IAC7B,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { HocuspocusProvider } from "@hocuspocus/provider";
|
|
2
|
+
import type { Citation } from "@rowsncolumns/common-types";
|
|
3
|
+
import type { CellInterface, SelectionArea } from "@rowsncolumns/grid";
|
|
4
|
+
import { PivotTable, type CellData, type Collaborator, type ConditionalFormatRule, type DataValidationRuleRecord, type EmbeddedChart, type EmbeddedObject, type NamedRange, type ProtectedRange, type Sheet, type TableView } from "@rowsncolumns/spreadsheet";
|
|
5
|
+
import { type CalculateNowOptions, type CalculationOperation, type CellXfs, type HistoryType, type SheetData, type SharedStrings, type SpreadsheetPatch } from "@rowsncolumns/spreadsheet-state";
|
|
6
|
+
import type { Patch } from "immer";
|
|
7
|
+
import type { WebsocketProvider } from "y-websocket";
|
|
8
|
+
import * as Y from "yjs";
|
|
9
|
+
export type UseYSpreadsheetPropsV2<T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject> = {
|
|
10
|
+
/**
|
|
11
|
+
* Scopes awareness updates to a single document.
|
|
12
|
+
*
|
|
13
|
+
* Multiple Athena editors (sheets, slides, docs) can share a single
|
|
14
|
+
* awareness channel by writing a `docGuid` field to their local state.
|
|
15
|
+
* When `awarenessScopeId` is set, this hook:
|
|
16
|
+
* - emits `docGuid: awarenessScopeId` on the local state
|
|
17
|
+
* - filters incoming states whose `docGuid` does not match
|
|
18
|
+
* - states with **no** `docGuid` are treated as a wildcard and accepted
|
|
19
|
+
* (so REST writers or older clients that don't set docGuid still
|
|
20
|
+
* appear as collaborators)
|
|
21
|
+
*
|
|
22
|
+
* Olympus and pptx-studio set this to the asset id; keep the same
|
|
23
|
+
* convention to remain wire-compatible.
|
|
24
|
+
*/
|
|
25
|
+
awarenessScopeId?: string;
|
|
26
|
+
userId: string | number;
|
|
27
|
+
title: string;
|
|
28
|
+
sheetId: number;
|
|
29
|
+
activeCell?: CellInterface;
|
|
30
|
+
/**
|
|
31
|
+
* Distinguishes human vs. agent presence. Surfaced on `Collaborator.kind`
|
|
32
|
+
* so renderers can style agent cursors differently.
|
|
33
|
+
*/
|
|
34
|
+
kind?: "human" | "agent";
|
|
35
|
+
/**
|
|
36
|
+
* For `kind === "agent"`, identifies the human who initiated the agent run
|
|
37
|
+
* (e.g. "Brendon"). Used to deduplicate agent cursors by initiator and to
|
|
38
|
+
* label "Athena · Brendon's run" in presence stacks.
|
|
39
|
+
*/
|
|
40
|
+
agentInitiator?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Current selection range(s). When set, collaborators rendered in the grid
|
|
43
|
+
* receive a range-shaped highlight in addition to the activeCell pin —
|
|
44
|
+
* needed so agents touching A1:E10 don't appear to be sitting on A1.
|
|
45
|
+
*/
|
|
46
|
+
selections?: SelectionArea[];
|
|
47
|
+
provider?: HocuspocusProvider | WebsocketProvider | any;
|
|
48
|
+
doc: Y.Doc;
|
|
49
|
+
calculateNow(options?: CalculateNowOptions): Promise<void>;
|
|
50
|
+
initialSheets: S[];
|
|
51
|
+
/**
|
|
52
|
+
* Enable V3 data structure (flat Map<cellKey, CellDataV3>)
|
|
53
|
+
* V3 uses a sparse map structure with keys like "1!A1" instead of nested arrays
|
|
54
|
+
* This provides better performance for sparse spreadsheets
|
|
55
|
+
*/
|
|
56
|
+
useV3?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Current data version stored in the document ("v2" or "v3")
|
|
59
|
+
* If using V3 but version is "v2" or undefined, migration will occur
|
|
60
|
+
* This should be provided by the backend/server
|
|
61
|
+
*/
|
|
62
|
+
sheetDataVersion?: "v2" | "v3";
|
|
63
|
+
/**
|
|
64
|
+
* Called after migration completes so backend can persist the new version
|
|
65
|
+
*/
|
|
66
|
+
onMigrationComplete?: (newVersion: "v3") => void;
|
|
67
|
+
/**
|
|
68
|
+
* Delete V2 data after migrating to V3
|
|
69
|
+
* Only applies when useV3 is true and migration occurs
|
|
70
|
+
* Default: false (keeps V2 data for rollback safety)
|
|
71
|
+
*/
|
|
72
|
+
deleteV2AfterMigration?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Skip the initial sync process
|
|
75
|
+
* When true, setupInitialSync will not be called on sync
|
|
76
|
+
* Useful when you want to handle initial state loading externally
|
|
77
|
+
* Default: false
|
|
78
|
+
*/
|
|
79
|
+
skipInitialSync?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Enable support for legacy shared strings stored as Y.Array.
|
|
82
|
+
* When enabled, observes both Y.Map (new format) and Y.Array (legacy format)
|
|
83
|
+
* and merges them into the shared strings state.
|
|
84
|
+
* Default: false (only observe Y.Map format)
|
|
85
|
+
*/
|
|
86
|
+
supportLegacySharedStringsArray?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Get user entered value of a cell
|
|
89
|
+
* @param sheetId
|
|
90
|
+
* @param rowIndex
|
|
91
|
+
* @param columnIndex
|
|
92
|
+
*/
|
|
93
|
+
getUserEnteredValue?(sheetId: number, rowIndex: number, columnIndex: number): string | undefined | null;
|
|
94
|
+
/**
|
|
95
|
+
* Client only functions
|
|
96
|
+
*/
|
|
97
|
+
clientOnlyFunctionPattern?: RegExp;
|
|
98
|
+
onChangeActiveSheet?(sheetId: number): void;
|
|
99
|
+
onChangeSheetData: React.Dispatch<React.SetStateAction<SheetData<T>>>;
|
|
100
|
+
onChangeTables: React.Dispatch<React.SetStateAction<TableView[]>>;
|
|
101
|
+
onChangeSheets: React.Dispatch<React.SetStateAction<S[]>>;
|
|
102
|
+
onChangeCharts?: React.Dispatch<React.SetStateAction<C[]>>;
|
|
103
|
+
onChangeEmbeds?: React.Dispatch<React.SetStateAction<O[]>>;
|
|
104
|
+
onChangeNamedRanges?: React.Dispatch<React.SetStateAction<NamedRange[]>>;
|
|
105
|
+
onChangePivotTables?: React.Dispatch<React.SetStateAction<PivotTable[]>>;
|
|
106
|
+
onChangeCellXfs?: React.Dispatch<React.SetStateAction<CellXfs | null | undefined>>;
|
|
107
|
+
onChangeSharedStrings?: React.Dispatch<React.SetStateAction<SharedStrings>>;
|
|
108
|
+
onChangeProtectedRanges?: React.Dispatch<React.SetStateAction<ProtectedRange[]>>;
|
|
109
|
+
onChangeConditionalFormats?: React.Dispatch<React.SetStateAction<ConditionalFormatRule[]>>;
|
|
110
|
+
onChangeDataValidations?: React.Dispatch<React.SetStateAction<DataValidationRuleRecord[]>>;
|
|
111
|
+
onChangeCitations?: React.Dispatch<React.SetStateAction<Citation[]>>;
|
|
112
|
+
/**
|
|
113
|
+
* Called synchronously right after a batch of local patches has been written to the
|
|
114
|
+
* shared document, inside `onBroadcastPatch` and before it returns to the caller. It
|
|
115
|
+
* receives the patches that were applied and the document. Purely observational: it
|
|
116
|
+
* does not alter the write or the patches. Useful for integrity checks, reconciliation,
|
|
117
|
+
* or telemetry that need to compare local state against the resulting document state at
|
|
118
|
+
* the moment a local edit is committed. Not called when the broadcast is skipped (e.g.
|
|
119
|
+
* a non-leader recalc patch). Default: no-op.
|
|
120
|
+
*/
|
|
121
|
+
onAfterBroadcastPatch?: (patches: [
|
|
122
|
+
patch: SpreadsheetPatch<Patch>,
|
|
123
|
+
type?: HistoryType | undefined | null
|
|
124
|
+
][], doc: Y.Doc) => void;
|
|
125
|
+
recalcCellsMaxEntries?: number;
|
|
126
|
+
enqueueCalculation: (operation: CalculationOperation) => void;
|
|
127
|
+
enqueueGraphOperation: (operation: CalculationOperation) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Re-derives conditional-format / data-validation results for changed
|
|
130
|
+
* cells (`useSpreadsheetState.reevaluateDerivationsForCells`). Agent- and
|
|
131
|
+
* backend-sourced recalc patches carry PRE-COMPUTED cell values, so they
|
|
132
|
+
* only update the dependency graph (no evaluation) — but CF/DV results are
|
|
133
|
+
* client-owned and the backend never writes them, so without this the
|
|
134
|
+
* changed cells' conditional formatting stays stale until the user
|
|
135
|
+
* re-saves a rule in the dialog.
|
|
136
|
+
*/
|
|
137
|
+
reevaluateDerivationsForCells?: (cells: Array<{
|
|
138
|
+
sheetId: number;
|
|
139
|
+
rowIndex: number;
|
|
140
|
+
columnIndex: number;
|
|
141
|
+
}>) => void;
|
|
142
|
+
};
|
|
143
|
+
export type YRowData = Y.Map<Y.Array<CellData | null>>;
|
|
144
|
+
export type YSheetData = Y.Array<YRowData | null>;
|
|
145
|
+
export declare const useYSpreadsheetV2: <T extends CellData, S extends Sheet, C extends EmbeddedChart, O extends EmbeddedObject>({ onChangeSheetData, onChangeSheets, onChangeTables, onChangeCharts, onChangeEmbeds, onChangeConditionalFormats, onChangeDataValidations, onChangeCitations, onAfterBroadcastPatch, recalcCellsMaxEntries, onChangeNamedRanges, onChangeProtectedRanges, onChangePivotTables, enqueueCalculation, enqueueGraphOperation, reevaluateDerivationsForCells, onChangeCellXfs, onChangeSharedStrings, calculateNow, onChangeActiveSheet, clientOnlyFunctionPattern, initialSheets, awarenessScopeId, userId, title, sheetId, activeCell, kind, agentInitiator, selections, doc, provider, useV3, sheetDataVersion, onMigrationComplete, deleteV2AfterMigration, skipInitialSync, supportLegacySharedStringsArray, }: UseYSpreadsheetPropsV2<T, S, C, O>) => {
|
|
146
|
+
synced: boolean;
|
|
147
|
+
users: Collaborator[];
|
|
148
|
+
onBroadcastPatch: (patches: [patch: SpreadsheetPatch<Patch>, type?: HistoryType | undefined | null][]) => void;
|
|
149
|
+
isLeader: boolean;
|
|
150
|
+
setupInitialSync: () => void;
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=use-yspreadsheet-v2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-yspreadsheet-v2.d.ts","sourceRoot":"","sources":["../../use-yspreadsheet-v2.ts"],"names":[],"mappings":"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"}
|