@a3s-lab/office 0.15.0 → 0.16.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/COLLABORATION_ROADMAP.md +15 -5
- package/README.md +22 -1
- package/dist/0~6090.js +7 -8
- package/dist/0~spreadsheet-editor.js +2106 -438
- package/dist/2180.js +370 -34
- package/dist/4104.js +657 -22
- package/dist/5184.js +1 -1
- package/dist/8715.js +156 -156
- package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +2 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-validation-support.d.ts +6 -0
- package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +21 -1
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +4 -2
- package/dist/internal/features/work/editors/spreadsheet-table-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-table-conversion.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-table-dialog.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-table-limits.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-table-reconciliation.d.ts +21 -0
- package/dist/internal/features/work/editors/spreadsheet-table-render.d.ts +16 -0
- package/dist/internal/features/work/editors/spreadsheet-table-ribbon.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-table-style.d.ts +31 -0
- package/dist/internal/features/work/editors/spreadsheet-table.d.ts +55 -0
- package/dist/internal/features/work/editors/use-spreadsheet-table.d.ts +23 -0
- package/dist/internal/features/work/work-types.d.ts +100 -0
- package/dist/internal/features/work/work-xlsx-interop.d.ts +2 -0
- package/dist/internal/features/work/work-xlsx-table-filters.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-tables.d.ts +4 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +189 -0
- package/dist/work-spreadsheet-package-scan.worker.js +3 -2
- package/docs/latest/en/browser-editor-architecture.md +43 -0
- package/package.json +4 -1
package/dist/5184.js
CHANGED
package/dist/8715.js
CHANGED
|
@@ -1,4 +1,160 @@
|
|
|
1
1
|
import { createOfficeId as createWorkId, directChild, attribute } from "./5184.js";
|
|
2
|
+
const CELL_REFERENCE = /\$?([A-Z]{1,3})\$?([1-9]\d*)/i;
|
|
3
|
+
const CELL_OR_RANGE = new RegExp(`^${CELL_REFERENCE.source}(?::${CELL_REFERENCE.source})?$`, 'i');
|
|
4
|
+
const COLUMN_RANGE = /^\$?([A-Z]{1,3}):\$?([A-Z]{1,3})$/i;
|
|
5
|
+
const ROW_RANGE = /^\$?([1-9]\d*):\$?([1-9]\d*)$/;
|
|
6
|
+
const DEFINED_NAME = /^[\p{L}_\\][\p{L}\p{N}_.\\]*$/u;
|
|
7
|
+
function isValidSpreadsheetDefinedName(value) {
|
|
8
|
+
const name = value.trim();
|
|
9
|
+
if (!name || Array.from(name).length > 255 || !DEFINED_NAME.test(name) || /^_xlnm\./i.test(name)) return false;
|
|
10
|
+
if (/^[A-Z]{1,3}[1-9]\d*$/i.test(name) || /^R\d+C\d+$/i.test(name)) return false;
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
function normalizeSpreadsheetPrintArea(value) {
|
|
14
|
+
const parts = splitRangeList(value.trim().replace(/^=/, ''));
|
|
15
|
+
if (!parts.length) return null;
|
|
16
|
+
const normalized = parts.map((part)=>{
|
|
17
|
+
const reference = unqualifiedReference(part);
|
|
18
|
+
if (!CELL_OR_RANGE.test(reference) && !COLUMN_RANGE.test(reference) && !ROW_RANGE.test(reference)) return null;
|
|
19
|
+
return reference.replace(/[A-Z]+/gi, (column)=>column.toUpperCase());
|
|
20
|
+
});
|
|
21
|
+
return normalized.every((part)=>Boolean(part)) ? normalized.join(',') : null;
|
|
22
|
+
}
|
|
23
|
+
function normalizeSpreadsheetPrintTitleRows(value) {
|
|
24
|
+
const match = ROW_RANGE.exec(unqualifiedReference(value.trim().replace(/^=/, '')));
|
|
25
|
+
if (!match) return null;
|
|
26
|
+
const start = Number(match[1]);
|
|
27
|
+
const end = Number(match[2]);
|
|
28
|
+
return `$${Math.min(start, end)}:$${Math.max(start, end)}`;
|
|
29
|
+
}
|
|
30
|
+
function normalizeSpreadsheetPrintTitleColumns(value) {
|
|
31
|
+
const match = COLUMN_RANGE.exec(unqualifiedReference(value.trim().replace(/^=/, '')));
|
|
32
|
+
if (!match) return null;
|
|
33
|
+
const start = decodeColumn(match[1]);
|
|
34
|
+
const end = decodeColumn(match[2]);
|
|
35
|
+
return `$${encodeColumn(Math.min(start, end))}:$${encodeColumn(Math.max(start, end))}`;
|
|
36
|
+
}
|
|
37
|
+
function parseSpreadsheetPrintTitles(value) {
|
|
38
|
+
let rows;
|
|
39
|
+
let columns;
|
|
40
|
+
for (const part of splitRangeList(value.trim().replace(/^=/, ''))){
|
|
41
|
+
const rowReference = normalizeSpreadsheetPrintTitleRows(part);
|
|
42
|
+
if (rowReference) {
|
|
43
|
+
if (rows) return null;
|
|
44
|
+
const match = ROW_RANGE.exec(rowReference);
|
|
45
|
+
rows = [
|
|
46
|
+
Number(match[1]) - 1,
|
|
47
|
+
Number(match[2]) - 1
|
|
48
|
+
];
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const columnReference = normalizeSpreadsheetPrintTitleColumns(part);
|
|
52
|
+
if (!columnReference || columns) return null;
|
|
53
|
+
const match = COLUMN_RANGE.exec(columnReference);
|
|
54
|
+
columns = [
|
|
55
|
+
decodeColumn(match[1]),
|
|
56
|
+
decodeColumn(match[2])
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
return rows || columns ? {
|
|
60
|
+
rows,
|
|
61
|
+
columns
|
|
62
|
+
} : null;
|
|
63
|
+
}
|
|
64
|
+
function parseSpreadsheetCellRanges(value) {
|
|
65
|
+
const parts = splitRangeList(value.trim().replace(/^=/, ''));
|
|
66
|
+
if (!parts.length) return null;
|
|
67
|
+
const ranges = parts.map((part)=>{
|
|
68
|
+
const cells = CELL_OR_RANGE.exec(unqualifiedReference(part));
|
|
69
|
+
if (!cells) return null;
|
|
70
|
+
const first = decodeCell(cells[1], cells[2]);
|
|
71
|
+
const second = cells[3] && cells[4] ? decodeCell(cells[3], cells[4]) : first;
|
|
72
|
+
return {
|
|
73
|
+
row: [
|
|
74
|
+
Math.min(first.row, second.row),
|
|
75
|
+
Math.max(first.row, second.row)
|
|
76
|
+
],
|
|
77
|
+
column: [
|
|
78
|
+
Math.min(first.column, second.column),
|
|
79
|
+
Math.max(first.column, second.column)
|
|
80
|
+
]
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
return ranges.every((range)=>Boolean(range)) ? ranges : null;
|
|
84
|
+
}
|
|
85
|
+
function formatSpreadsheetCellRanges(ranges) {
|
|
86
|
+
return ranges.map((range)=>{
|
|
87
|
+
const start = encodeCell(range.row[0], range.column[0]);
|
|
88
|
+
const end = encodeCell(range.row[1], range.column[1]);
|
|
89
|
+
return start === end ? start : `${start}:${end}`;
|
|
90
|
+
}).join(',');
|
|
91
|
+
}
|
|
92
|
+
function qualifySpreadsheetRange(value, sheetName) {
|
|
93
|
+
const prefix = `'${sheetName.replaceAll("'", "''")}'!`;
|
|
94
|
+
return splitRangeList(value).map((part)=>part.includes('!') ? part.trim() : `${prefix}${part.trim()}`).join(',');
|
|
95
|
+
}
|
|
96
|
+
function stripSpreadsheetSheetQualifier(value, sheetName) {
|
|
97
|
+
const quotedPrefix = `'${sheetName.replaceAll("'", "''")}'!`;
|
|
98
|
+
const plainPrefix = `${sheetName}!`;
|
|
99
|
+
return splitRangeList(value.trim().replace(/^=/, '')).map((part)=>{
|
|
100
|
+
const reference = part.trim();
|
|
101
|
+
if (reference.toLowerCase().startsWith(quotedPrefix.toLowerCase())) return reference.slice(quotedPrefix.length);
|
|
102
|
+
if (reference.toLowerCase().startsWith(plainPrefix.toLowerCase())) return reference.slice(plainPrefix.length);
|
|
103
|
+
return reference;
|
|
104
|
+
}).join(',');
|
|
105
|
+
}
|
|
106
|
+
function splitRangeList(value) {
|
|
107
|
+
const parts = [];
|
|
108
|
+
let current = '';
|
|
109
|
+
let quoted = false;
|
|
110
|
+
for(let index = 0; index < value.length; index += 1){
|
|
111
|
+
const character = value[index];
|
|
112
|
+
if ("'" === character) {
|
|
113
|
+
if (quoted && "'" === value[index + 1]) {
|
|
114
|
+
current += "''";
|
|
115
|
+
index += 1;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
quoted = !quoted;
|
|
119
|
+
}
|
|
120
|
+
if (',' !== character || quoted) current += character;
|
|
121
|
+
else {
|
|
122
|
+
if (current.trim()) parts.push(current.trim());
|
|
123
|
+
current = '';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (current.trim()) parts.push(current.trim());
|
|
127
|
+
return parts;
|
|
128
|
+
}
|
|
129
|
+
function unqualifiedReference(value) {
|
|
130
|
+
const reference = value.trim().replace(/^=/, '');
|
|
131
|
+
const separator = reference.lastIndexOf('!');
|
|
132
|
+
return separator >= 0 ? reference.slice(separator + 1) : reference;
|
|
133
|
+
}
|
|
134
|
+
function decodeCell(column, row) {
|
|
135
|
+
return {
|
|
136
|
+
row: Math.max(0, Number(row) - 1),
|
|
137
|
+
column: decodeColumn(column)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function decodeColumn(value) {
|
|
141
|
+
let result = 0;
|
|
142
|
+
for (const character of value.toUpperCase())result = 26 * result + character.charCodeAt(0) - 64;
|
|
143
|
+
return Math.max(0, result - 1);
|
|
144
|
+
}
|
|
145
|
+
function encodeCell(row, column) {
|
|
146
|
+
return `${encodeColumn(column)}${Math.max(0, row) + 1}`;
|
|
147
|
+
}
|
|
148
|
+
function encodeColumn(column) {
|
|
149
|
+
let value = Math.max(0, column) + 1;
|
|
150
|
+
let label = '';
|
|
151
|
+
while(value > 0){
|
|
152
|
+
value -= 1;
|
|
153
|
+
label = String.fromCharCode(65 + value % 26) + label;
|
|
154
|
+
value = Math.floor(value / 26);
|
|
155
|
+
}
|
|
156
|
+
return label;
|
|
157
|
+
}
|
|
2
158
|
function sparseArrayIndexes(values) {
|
|
3
159
|
if (!values) return [];
|
|
4
160
|
return Object.keys(values).flatMap((key)=>{
|
|
@@ -323,162 +479,6 @@ function formatPivotNumber(value) {
|
|
|
323
479
|
function matchesPivotReportFilters(values, pivot) {
|
|
324
480
|
return (pivot.reportFilters ?? []).every((filter)=>void 0 === filter.selectedItem || spreadsheetPivotFilterValueKey(normalizeSpreadsheetPivotFilterValue(values[filter.fieldIndex])) === spreadsheetPivotFilterValueKey(filter.selectedItem));
|
|
325
481
|
}
|
|
326
|
-
const CELL_REFERENCE = /\$?([A-Z]{1,3})\$?([1-9]\d*)/i;
|
|
327
|
-
const CELL_OR_RANGE = new RegExp(`^${CELL_REFERENCE.source}(?::${CELL_REFERENCE.source})?$`, 'i');
|
|
328
|
-
const COLUMN_RANGE = /^\$?([A-Z]{1,3}):\$?([A-Z]{1,3})$/i;
|
|
329
|
-
const ROW_RANGE = /^\$?([1-9]\d*):\$?([1-9]\d*)$/;
|
|
330
|
-
const DEFINED_NAME = /^[\p{L}_\\][\p{L}\p{N}_.\\]*$/u;
|
|
331
|
-
function isValidSpreadsheetDefinedName(value) {
|
|
332
|
-
const name = value.trim();
|
|
333
|
-
if (!name || name.length > 255 || !DEFINED_NAME.test(name) || /^_xlnm\./i.test(name)) return false;
|
|
334
|
-
if (/^[A-Z]{1,3}[1-9]\d*$/i.test(name) || /^R\d+C\d+$/i.test(name)) return false;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
function normalizeSpreadsheetPrintArea(value) {
|
|
338
|
-
const parts = splitRangeList(value.trim().replace(/^=/, ''));
|
|
339
|
-
if (!parts.length) return null;
|
|
340
|
-
const normalized = parts.map((part)=>{
|
|
341
|
-
const reference = unqualifiedReference(part);
|
|
342
|
-
if (!CELL_OR_RANGE.test(reference) && !COLUMN_RANGE.test(reference) && !ROW_RANGE.test(reference)) return null;
|
|
343
|
-
return reference.replace(/[A-Z]+/gi, (column)=>column.toUpperCase());
|
|
344
|
-
});
|
|
345
|
-
return normalized.every((part)=>Boolean(part)) ? normalized.join(',') : null;
|
|
346
|
-
}
|
|
347
|
-
function normalizeSpreadsheetPrintTitleRows(value) {
|
|
348
|
-
const match = ROW_RANGE.exec(unqualifiedReference(value.trim().replace(/^=/, '')));
|
|
349
|
-
if (!match) return null;
|
|
350
|
-
const start = Number(match[1]);
|
|
351
|
-
const end = Number(match[2]);
|
|
352
|
-
return `$${Math.min(start, end)}:$${Math.max(start, end)}`;
|
|
353
|
-
}
|
|
354
|
-
function normalizeSpreadsheetPrintTitleColumns(value) {
|
|
355
|
-
const match = COLUMN_RANGE.exec(unqualifiedReference(value.trim().replace(/^=/, '')));
|
|
356
|
-
if (!match) return null;
|
|
357
|
-
const start = decodeColumn(match[1]);
|
|
358
|
-
const end = decodeColumn(match[2]);
|
|
359
|
-
return `$${encodeColumn(Math.min(start, end))}:$${encodeColumn(Math.max(start, end))}`;
|
|
360
|
-
}
|
|
361
|
-
function parseSpreadsheetPrintTitles(value) {
|
|
362
|
-
let rows;
|
|
363
|
-
let columns;
|
|
364
|
-
for (const part of splitRangeList(value.trim().replace(/^=/, ''))){
|
|
365
|
-
const rowReference = normalizeSpreadsheetPrintTitleRows(part);
|
|
366
|
-
if (rowReference) {
|
|
367
|
-
if (rows) return null;
|
|
368
|
-
const match = ROW_RANGE.exec(rowReference);
|
|
369
|
-
rows = [
|
|
370
|
-
Number(match[1]) - 1,
|
|
371
|
-
Number(match[2]) - 1
|
|
372
|
-
];
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
const columnReference = normalizeSpreadsheetPrintTitleColumns(part);
|
|
376
|
-
if (!columnReference || columns) return null;
|
|
377
|
-
const match = COLUMN_RANGE.exec(columnReference);
|
|
378
|
-
columns = [
|
|
379
|
-
decodeColumn(match[1]),
|
|
380
|
-
decodeColumn(match[2])
|
|
381
|
-
];
|
|
382
|
-
}
|
|
383
|
-
return rows || columns ? {
|
|
384
|
-
rows,
|
|
385
|
-
columns
|
|
386
|
-
} : null;
|
|
387
|
-
}
|
|
388
|
-
function parseSpreadsheetCellRanges(value) {
|
|
389
|
-
const parts = splitRangeList(value.trim().replace(/^=/, ''));
|
|
390
|
-
if (!parts.length) return null;
|
|
391
|
-
const ranges = parts.map((part)=>{
|
|
392
|
-
const cells = CELL_OR_RANGE.exec(unqualifiedReference(part));
|
|
393
|
-
if (!cells) return null;
|
|
394
|
-
const first = decodeCell(cells[1], cells[2]);
|
|
395
|
-
const second = cells[3] && cells[4] ? decodeCell(cells[3], cells[4]) : first;
|
|
396
|
-
return {
|
|
397
|
-
row: [
|
|
398
|
-
Math.min(first.row, second.row),
|
|
399
|
-
Math.max(first.row, second.row)
|
|
400
|
-
],
|
|
401
|
-
column: [
|
|
402
|
-
Math.min(first.column, second.column),
|
|
403
|
-
Math.max(first.column, second.column)
|
|
404
|
-
]
|
|
405
|
-
};
|
|
406
|
-
});
|
|
407
|
-
return ranges.every((range)=>Boolean(range)) ? ranges : null;
|
|
408
|
-
}
|
|
409
|
-
function formatSpreadsheetCellRanges(ranges) {
|
|
410
|
-
return ranges.map((range)=>{
|
|
411
|
-
const start = encodeCell(range.row[0], range.column[0]);
|
|
412
|
-
const end = encodeCell(range.row[1], range.column[1]);
|
|
413
|
-
return start === end ? start : `${start}:${end}`;
|
|
414
|
-
}).join(',');
|
|
415
|
-
}
|
|
416
|
-
function qualifySpreadsheetRange(value, sheetName) {
|
|
417
|
-
const prefix = `'${sheetName.replaceAll("'", "''")}'!`;
|
|
418
|
-
return splitRangeList(value).map((part)=>part.includes('!') ? part.trim() : `${prefix}${part.trim()}`).join(',');
|
|
419
|
-
}
|
|
420
|
-
function stripSpreadsheetSheetQualifier(value, sheetName) {
|
|
421
|
-
const quotedPrefix = `'${sheetName.replaceAll("'", "''")}'!`;
|
|
422
|
-
const plainPrefix = `${sheetName}!`;
|
|
423
|
-
return splitRangeList(value.trim().replace(/^=/, '')).map((part)=>{
|
|
424
|
-
const reference = part.trim();
|
|
425
|
-
if (reference.toLowerCase().startsWith(quotedPrefix.toLowerCase())) return reference.slice(quotedPrefix.length);
|
|
426
|
-
if (reference.toLowerCase().startsWith(plainPrefix.toLowerCase())) return reference.slice(plainPrefix.length);
|
|
427
|
-
return reference;
|
|
428
|
-
}).join(',');
|
|
429
|
-
}
|
|
430
|
-
function splitRangeList(value) {
|
|
431
|
-
const parts = [];
|
|
432
|
-
let current = '';
|
|
433
|
-
let quoted = false;
|
|
434
|
-
for(let index = 0; index < value.length; index += 1){
|
|
435
|
-
const character = value[index];
|
|
436
|
-
if ("'" === character) {
|
|
437
|
-
if (quoted && "'" === value[index + 1]) {
|
|
438
|
-
current += "''";
|
|
439
|
-
index += 1;
|
|
440
|
-
continue;
|
|
441
|
-
}
|
|
442
|
-
quoted = !quoted;
|
|
443
|
-
}
|
|
444
|
-
if (',' !== character || quoted) current += character;
|
|
445
|
-
else {
|
|
446
|
-
if (current.trim()) parts.push(current.trim());
|
|
447
|
-
current = '';
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
if (current.trim()) parts.push(current.trim());
|
|
451
|
-
return parts;
|
|
452
|
-
}
|
|
453
|
-
function unqualifiedReference(value) {
|
|
454
|
-
const reference = value.trim().replace(/^=/, '');
|
|
455
|
-
const separator = reference.lastIndexOf('!');
|
|
456
|
-
return separator >= 0 ? reference.slice(separator + 1) : reference;
|
|
457
|
-
}
|
|
458
|
-
function decodeCell(column, row) {
|
|
459
|
-
return {
|
|
460
|
-
row: Math.max(0, Number(row) - 1),
|
|
461
|
-
column: decodeColumn(column)
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
function decodeColumn(value) {
|
|
465
|
-
let result = 0;
|
|
466
|
-
for (const character of value.toUpperCase())result = 26 * result + character.charCodeAt(0) - 64;
|
|
467
|
-
return Math.max(0, result - 1);
|
|
468
|
-
}
|
|
469
|
-
function encodeCell(row, column) {
|
|
470
|
-
return `${encodeColumn(column)}${Math.max(0, row) + 1}`;
|
|
471
|
-
}
|
|
472
|
-
function encodeColumn(column) {
|
|
473
|
-
let value = Math.max(0, column) + 1;
|
|
474
|
-
let label = '';
|
|
475
|
-
while(value > 0){
|
|
476
|
-
value -= 1;
|
|
477
|
-
label = String.fromCharCode(65 + value % 26) + label;
|
|
478
|
-
value = Math.floor(value / 26);
|
|
479
|
-
}
|
|
480
|
-
return label;
|
|
481
|
-
}
|
|
482
482
|
const MAXIMUM_SOURCE_CELLS = 100000;
|
|
483
483
|
const MAXIMUM_OUTPUT_CELLS = 20000;
|
|
484
484
|
const MAXIMUM_XLSX_ROW = 1048575;
|
|
@@ -8,6 +8,8 @@ export declare const SPREADSHEET_RECORD_CHARTS = "charts";
|
|
|
8
8
|
export declare const SPREADSHEET_RECORD_CHART_ORDER = "chartOrder";
|
|
9
9
|
export declare const SPREADSHEET_RECORD_PIVOTS = "pivotTables";
|
|
10
10
|
export declare const SPREADSHEET_RECORD_PIVOT_ORDER = "pivotOrder";
|
|
11
|
+
export declare const SPREADSHEET_RECORD_TABLES = "tables";
|
|
12
|
+
export declare const SPREADSHEET_RECORD_TABLE_ORDER = "tableOrder";
|
|
11
13
|
export declare function initializeSpreadsheetSheetRecord(record: Y.Map<unknown>, sheet: WorkSpreadsheetSheet): void;
|
|
12
14
|
export declare function patchSpreadsheetSheetRecord(record: Y.Map<unknown>, previous: WorkSpreadsheetSheet | undefined, next: WorkSpreadsheetSheet): void;
|
|
13
15
|
export declare function readSpreadsheetSheetRecord(record: Y.Map<unknown>, id: string): WorkSpreadsheetSheet;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function requiredCoordinate(value: unknown, maximum: number, label: string, sheetId: string): number;
|
|
2
|
+
export declare function requiredInputRecord(value: unknown, label: string): Record<string, unknown>;
|
|
3
|
+
export declare function requiredIdentifier(value: unknown, label: string): string;
|
|
4
|
+
export declare function requiredNonEmptyString(value: unknown, label: string): string;
|
|
5
|
+
export declare function validateJsonRecord(value: Record<string, unknown>, label: string): Record<string, unknown>;
|
|
6
|
+
export declare function invalidWorkOfficeSpreadsheetInput(expected: string): never;
|
|
@@ -5,5 +5,6 @@ export interface SpreadsheetAutoFilterRange {
|
|
|
5
5
|
column: [number, number];
|
|
6
6
|
}
|
|
7
7
|
export declare function spreadsheetAutoFilterRange(sheet: WorkSpreadsheetSheet, selection: Selection): SpreadsheetAutoFilterRange | null;
|
|
8
|
+
export declare function spreadsheetSelectionOrCurrentRegion(sheet: WorkSpreadsheetSheet, selection: Selection): SpreadsheetAutoFilterRange | null;
|
|
8
9
|
export declare function spreadsheetAutoFilterHeaderColumn(sheet: WorkSpreadsheetSheet | undefined, selection: Selection): number | null;
|
|
9
10
|
export declare function toggleSpreadsheetAutoFilter(content: WorkSpreadsheetContent, sheetId: string, selection: Selection): WorkSpreadsheetContent | null;
|
|
@@ -21,7 +21,13 @@ export declare const spreadsheetRibbonTabs: readonly [{
|
|
|
21
21
|
readonly id: "view";
|
|
22
22
|
readonly label: "视图";
|
|
23
23
|
}];
|
|
24
|
-
export
|
|
24
|
+
export declare const spreadsheetTableDesignRibbonTab: {
|
|
25
|
+
readonly id: "tableDesign";
|
|
26
|
+
readonly label: "表格设计";
|
|
27
|
+
readonly compactLabel: "设计";
|
|
28
|
+
readonly contextual: true;
|
|
29
|
+
};
|
|
30
|
+
export type SpreadsheetRibbonTabId = (typeof spreadsheetRibbonTabs)[number]['id'] | typeof spreadsheetTableDesignRibbonTab.id;
|
|
25
31
|
export interface SpreadsheetCommandShortcut {
|
|
26
32
|
label: string;
|
|
27
33
|
aria: string;
|
|
@@ -757,6 +763,20 @@ export declare const spreadsheetCommandCatalog: {
|
|
|
757
763
|
readonly group: "charts";
|
|
758
764
|
};
|
|
759
765
|
};
|
|
766
|
+
readonly table: {
|
|
767
|
+
readonly id: "insert.table";
|
|
768
|
+
readonly label: "表格";
|
|
769
|
+
readonly location: {
|
|
770
|
+
readonly area: "ribbon";
|
|
771
|
+
readonly tab: "insert";
|
|
772
|
+
readonly group: "tables";
|
|
773
|
+
};
|
|
774
|
+
readonly shortcut: {
|
|
775
|
+
readonly label: "Cmd/Ctrl+T";
|
|
776
|
+
readonly aria: "Control+T Meta+T";
|
|
777
|
+
readonly editor: readonly ["Mod-t"];
|
|
778
|
+
};
|
|
779
|
+
};
|
|
760
780
|
readonly hyperlink: {
|
|
761
781
|
readonly id: "insert.hyperlink";
|
|
762
782
|
readonly label: "超链接";
|
|
@@ -18,6 +18,7 @@ import { type SpreadsheetKeyboardSelection, type SpreadsheetSelectionMove, type
|
|
|
18
18
|
import type { SpreadsheetPasteContent } from './spreadsheet-paste-special';
|
|
19
19
|
import { type SpreadsheetDecimalPlacesDirection } from './spreadsheet-number-format-command';
|
|
20
20
|
import { type SpreadsheetSheetMoveDirection } from './spreadsheet-sheet-model';
|
|
21
|
+
import type { SpreadsheetTableDesignPatch, SpreadsheetTableRequest, SpreadsheetTableTarget } from './spreadsheet-table';
|
|
21
22
|
export interface SpreadsheetWorkbookCommandPort {
|
|
22
23
|
autoFillCell: (copyRange: SpreadsheetCommandRange, applyRange: SpreadsheetCommandRange, direction: SpreadsheetCellFillDirection) => void;
|
|
23
24
|
batchCallApis: (apiCalls: Array<{
|
|
@@ -127,6 +128,10 @@ export interface SpreadsheetHyperlinkCommandPort {
|
|
|
127
128
|
canOpen: boolean;
|
|
128
129
|
open: (request: SpreadsheetHyperlinkCell) => boolean;
|
|
129
130
|
}
|
|
131
|
+
export interface SpreadsheetTableCommandPort {
|
|
132
|
+
canOpen: boolean;
|
|
133
|
+
open: (target: SpreadsheetTableTarget) => boolean;
|
|
134
|
+
}
|
|
130
135
|
export interface SpreadsheetNavigationCommandPort {
|
|
131
136
|
canOpenFind: boolean;
|
|
132
137
|
canOpenGoTo: boolean;
|
|
@@ -150,6 +155,7 @@ export interface SpreadsheetEditorCommands {
|
|
|
150
155
|
applyAutoSum: (functionName: SpreadsheetAutoSumFunction) => boolean;
|
|
151
156
|
applyFormatPainter: (target: SpreadsheetCommandSelection) => boolean;
|
|
152
157
|
applyHyperlink: (request: SpreadsheetHyperlinkRequest) => boolean;
|
|
158
|
+
applyTable: (request: SpreadsheetTableRequest) => boolean;
|
|
153
159
|
cancelFormatPainter: () => boolean;
|
|
154
160
|
clearSelectedCells: (mode?: SpreadsheetCellClearMode) => boolean;
|
|
155
161
|
copySelection: () => boolean;
|
|
@@ -170,6 +176,7 @@ export interface SpreadsheetEditorCommands {
|
|
|
170
176
|
openGoTo: () => boolean;
|
|
171
177
|
openHyperlink: () => boolean;
|
|
172
178
|
openPasteSpecial: () => boolean;
|
|
179
|
+
openTable: () => boolean;
|
|
173
180
|
pasteCells: (values: readonly (readonly unknown[])[]) => boolean;
|
|
174
181
|
pasteSelection: () => boolean;
|
|
175
182
|
pasteSpecial: (content: SpreadsheetPasteContent) => boolean;
|
|
@@ -190,6 +197,8 @@ export interface SpreadsheetEditorCommands {
|
|
|
190
197
|
setZoom: (percent: number) => boolean;
|
|
191
198
|
sortSelectedCells: (direction: SpreadsheetSortDirection) => boolean;
|
|
192
199
|
toggleAutoFilter: () => boolean;
|
|
200
|
+
updateTable: (sheetId: string, tableId: string, patch: SpreadsheetTableDesignPatch) => boolean;
|
|
201
|
+
convertTableToRange: (sheetId: string, tableId: string) => boolean;
|
|
193
202
|
undo: () => boolean;
|
|
194
203
|
}
|
|
195
204
|
export type SpreadsheetEditorCanCommands = OfficeEditorCanCommands<SpreadsheetEditorCommands>;
|
|
@@ -210,6 +219,7 @@ export interface SpreadsheetCommandContext {
|
|
|
210
219
|
navigation: SpreadsheetNavigationCommandPort;
|
|
211
220
|
onChange: (content: WorkSpreadsheetContent) => void;
|
|
212
221
|
selection: SpreadsheetCommandSelection | null;
|
|
222
|
+
table: SpreadsheetTableCommandPort;
|
|
213
223
|
targetSheetGridSize?: SpreadsheetGridSize | null;
|
|
214
224
|
targetSheetId: string;
|
|
215
225
|
toolbarCell: Cell | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Cell, Selection } from '@fortune-sheet/core';
|
|
2
|
-
import type { WorkSpreadsheetContent } from '../work-types';
|
|
2
|
+
import type { WorkSpreadsheetContent, WorkSpreadsheetTable } from '../work-types';
|
|
3
3
|
import type { SpreadsheetResolvedCellBorders } from './spreadsheet-cell-border';
|
|
4
4
|
import { type SpreadsheetRibbonTabId } from './spreadsheet-command-catalog';
|
|
5
5
|
import type { SpreadsheetEditorCanCommands, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
|
|
@@ -7,8 +7,10 @@ import type { SpreadsheetFormatPainterMode } from './spreadsheet-format-painter'
|
|
|
7
7
|
import type { SpreadsheetWorkbookPanelView } from './spreadsheet-workbook-panel';
|
|
8
8
|
import { type WorkOfficeFileAction } from './work-office-chrome';
|
|
9
9
|
export type { SpreadsheetRibbonTabId } from './spreadsheet-command-catalog';
|
|
10
|
-
export declare function SpreadsheetEditorRibbon({ activeTab, autoFilterActive, can, commands, content, fileActions, findOpen, formatPainterMode, freezePanesActive, freezePanesSelection, gridLinesVisible, panelId, onTabChange, onTogglePanel, panel, toolbarCell, toolbarCellBorders, }: {
|
|
10
|
+
export declare function SpreadsheetEditorRibbon({ activeTab, activeTable, activeTableSheetId, autoFilterActive, can, commands, content, fileActions, findOpen, formatPainterMode, freezePanesActive, freezePanesSelection, gridLinesVisible, panelId, onTabChange, onTogglePanel, panel, toolbarCell, toolbarCellBorders, }: {
|
|
11
11
|
activeTab: SpreadsheetRibbonTabId;
|
|
12
|
+
activeTable?: WorkSpreadsheetTable | null;
|
|
13
|
+
activeTableSheetId?: string;
|
|
12
14
|
autoFilterActive?: boolean;
|
|
13
15
|
can: SpreadsheetEditorCanCommands;
|
|
14
16
|
commands: SpreadsheetEditorCommands;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SpreadsheetCommandContext, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
|
|
2
|
+
import { type OfficeEditorExtension } from './office-editor-extension';
|
|
3
|
+
export declare function createSpreadsheetTableExtension(): OfficeEditorExtension<SpreadsheetCommandContext, SpreadsheetEditorCommands>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WorkSpreadsheetContent, WorkSpreadsheetTable } from '../work-types';
|
|
2
|
+
export declare function canMaterializeSpreadsheetTableAppearance(table: WorkSpreadsheetTable): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Convert to Range removes ListObject semantics, so the render-only style must
|
|
5
|
+
* become native cell formatting to preserve the appearance users confirmed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function materializeSpreadsheetTableAppearance(content: WorkSpreadsheetContent, sheetId: string, table: WorkSpreadsheetTable): WorkSpreadsheetContent | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SpreadsheetTableDialogSource, SpreadsheetTableDialogValue } from './spreadsheet-table';
|
|
2
|
+
export declare function SpreadsheetTableDialog({ source, restoreFocusTarget, onApply, onClose, onValidate, }: {
|
|
3
|
+
source: SpreadsheetTableDialogSource;
|
|
4
|
+
restoreFocusTarget: () => HTMLElement | null;
|
|
5
|
+
onApply: (value: SpreadsheetTableDialogValue) => boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
onValidate: (value: SpreadsheetTableDialogValue) => string | null;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MAX_SPREADSHEET_TABLE_CELLS = 100000;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Op } from '@fortune-sheet/core';
|
|
2
|
+
import type { WorkSpreadsheetSheet } from '../work-types';
|
|
3
|
+
export type SpreadsheetTableStructureChange = {
|
|
4
|
+
axis: 'column' | 'row';
|
|
5
|
+
count: number;
|
|
6
|
+
direction: 'lefttop' | 'rightbottom';
|
|
7
|
+
index: number;
|
|
8
|
+
kind: 'insert';
|
|
9
|
+
} | {
|
|
10
|
+
axis: 'column' | 'row';
|
|
11
|
+
end: number;
|
|
12
|
+
kind: 'delete';
|
|
13
|
+
start: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function canApplySpreadsheetTableStructureChange(sheet: WorkSpreadsheetSheet | undefined, change: SpreadsheetTableStructureChange): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Reconciles Fortune's cell and whole-row/column operation stream with the
|
|
18
|
+
* browser-owned ListObject model. Fortune preserves unknown sheet metadata,
|
|
19
|
+
* but it cannot update table ranges, column identities, or filter offsets.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reconcileSpreadsheetTablesAfterFortune(sheets: WorkSpreadsheetSheet[], sourceSheets: WorkSpreadsheetSheet[], operations?: readonly Op[]): WorkSpreadsheetSheet[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Cell } from '@fortune-sheet/core';
|
|
2
|
+
import type { SpreadsheetTableCellRenderStyle } from './spreadsheet-table-style';
|
|
3
|
+
export interface SpreadsheetTableRenderCellInfo {
|
|
4
|
+
column: number;
|
|
5
|
+
endX: number;
|
|
6
|
+
endY: number;
|
|
7
|
+
row: number;
|
|
8
|
+
startX: number;
|
|
9
|
+
startY: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SpreadsheetTableConditionalStyle {
|
|
12
|
+
cellColor?: string;
|
|
13
|
+
textColor?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function beginSpreadsheetTableCellRender(_cell: Cell | null, tableStyle: SpreadsheetTableCellRenderStyle | null, conditionalStyle: SpreadsheetTableConditionalStyle | undefined, context: CanvasRenderingContext2D): void;
|
|
16
|
+
export declare function finishSpreadsheetTableCellRender(_cell: Cell | null, cellInfo: SpreadsheetTableRenderCellInfo, tableStyle: SpreadsheetTableCellRenderStyle | null, context: CanvasRenderingContext2D): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WorkSpreadsheetTable } from '../work-types';
|
|
2
|
+
import type { SpreadsheetEditorCanCommands, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
|
|
3
|
+
export declare function SpreadsheetTableDesignRibbon({ can, commands, sheetId, table, }: {
|
|
4
|
+
can: SpreadsheetEditorCanCommands;
|
|
5
|
+
commands: SpreadsheetEditorCommands;
|
|
6
|
+
sheetId: string;
|
|
7
|
+
table: WorkSpreadsheetTable;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { WorkSpreadsheetTable, WorkSpreadsheetTableStyle } from '../work-types';
|
|
2
|
+
export interface SpreadsheetTableStylePalette {
|
|
3
|
+
border: string;
|
|
4
|
+
header: string;
|
|
5
|
+
headerText: string;
|
|
6
|
+
primaryRow: string;
|
|
7
|
+
secondaryRow: string;
|
|
8
|
+
stripeColumn: string;
|
|
9
|
+
text: string;
|
|
10
|
+
total: string;
|
|
11
|
+
totalText: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SpreadsheetTableStyleChoice {
|
|
14
|
+
label: string;
|
|
15
|
+
ooxmlName: string;
|
|
16
|
+
palette: SpreadsheetTableStylePalette;
|
|
17
|
+
style: Exclude<WorkSpreadsheetTableStyle, {
|
|
18
|
+
family: 'none';
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export interface SpreadsheetTableCellRenderStyle {
|
|
22
|
+
background: string;
|
|
23
|
+
bold: boolean;
|
|
24
|
+
borderColor: string;
|
|
25
|
+
role: 'body' | 'header' | 'totals';
|
|
26
|
+
tableId: string;
|
|
27
|
+
textColor: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function spreadsheetTableStyleChoices(): readonly SpreadsheetTableStyleChoice[];
|
|
30
|
+
export declare function spreadsheetTableStylePalette(style: WorkSpreadsheetTableStyle): SpreadsheetTableStylePalette | null;
|
|
31
|
+
export declare function createSpreadsheetTableRenderResolver(tables: readonly WorkSpreadsheetTable[]): (row: number, column: number) => SpreadsheetTableCellRenderStyle | null;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Selection } from '@fortune-sheet/core';
|
|
2
|
+
import type { WorkSpreadsheetContent, WorkSpreadsheetSheet, WorkSpreadsheetTable, WorkSpreadsheetTableStyle } from '../work-types';
|
|
3
|
+
import { type SpreadsheetCellRange } from './spreadsheet-cell-range';
|
|
4
|
+
export { MAX_SPREADSHEET_TABLE_CELLS } from './spreadsheet-table-limits';
|
|
5
|
+
export interface SpreadsheetTableTarget {
|
|
6
|
+
sheetId: string;
|
|
7
|
+
selection: Selection;
|
|
8
|
+
}
|
|
9
|
+
export interface SpreadsheetTableDialogValue {
|
|
10
|
+
headerRow: boolean;
|
|
11
|
+
rangeReference: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SpreadsheetTableDialogSource {
|
|
14
|
+
name: string;
|
|
15
|
+
range: SpreadsheetCellRange;
|
|
16
|
+
rangeReference: string;
|
|
17
|
+
sheetId: string;
|
|
18
|
+
sheetName: string;
|
|
19
|
+
value: SpreadsheetTableDialogValue;
|
|
20
|
+
}
|
|
21
|
+
export interface SpreadsheetTableRequest {
|
|
22
|
+
headerRow: boolean;
|
|
23
|
+
name: string;
|
|
24
|
+
range: SpreadsheetCellRange;
|
|
25
|
+
sheetId: string;
|
|
26
|
+
style?: WorkSpreadsheetTableStyle;
|
|
27
|
+
}
|
|
28
|
+
export type SpreadsheetTableValidation = {
|
|
29
|
+
columns: string[];
|
|
30
|
+
name: string;
|
|
31
|
+
ok: true;
|
|
32
|
+
range: SpreadsheetCellRange;
|
|
33
|
+
sheet: WorkSpreadsheetSheet;
|
|
34
|
+
} | {
|
|
35
|
+
code: SpreadsheetTableErrorCode;
|
|
36
|
+
message: string;
|
|
37
|
+
ok: false;
|
|
38
|
+
};
|
|
39
|
+
export type SpreadsheetTableErrorCode = 'auto-filter-overlap' | 'invalid-column-name' | 'invalid-name' | 'invalid-range' | 'invalid-style' | 'merged-range' | 'name-conflict' | 'out-of-bounds' | 'protected-range' | 'pivot-table' | 'range-too-large' | 'sheet-not-found' | 'table-overlap';
|
|
40
|
+
export interface SpreadsheetTableDesignPatch {
|
|
41
|
+
name?: string;
|
|
42
|
+
showColumnStripes?: boolean;
|
|
43
|
+
showFirstColumn?: boolean;
|
|
44
|
+
showLastColumn?: boolean;
|
|
45
|
+
showRowStripes?: boolean;
|
|
46
|
+
style?: WorkSpreadsheetTableStyle;
|
|
47
|
+
}
|
|
48
|
+
export declare function createSpreadsheetTableDialogSource(content: WorkSpreadsheetContent, target: SpreadsheetTableTarget): SpreadsheetTableDialogSource | null;
|
|
49
|
+
export declare function spreadsheetTableRangeFromText(value: string): SpreadsheetCellRange | null;
|
|
50
|
+
export declare function validateSpreadsheetTableRequest(content: WorkSpreadsheetContent, request: SpreadsheetTableRequest): SpreadsheetTableValidation;
|
|
51
|
+
export declare function applySpreadsheetTable(content: WorkSpreadsheetContent, request: SpreadsheetTableRequest): WorkSpreadsheetContent | null;
|
|
52
|
+
export declare function updateSpreadsheetTable(content: WorkSpreadsheetContent, sheetId: string, tableId: string, patch: SpreadsheetTableDesignPatch): WorkSpreadsheetContent | null;
|
|
53
|
+
export declare function convertSpreadsheetTableToRange(content: WorkSpreadsheetContent, sheetId: string, tableId: string): WorkSpreadsheetContent | null;
|
|
54
|
+
export declare function spreadsheetTableAtCell(sheet: WorkSpreadsheetSheet | undefined, row: number, column: number): WorkSpreadsheetTable | null;
|
|
55
|
+
export declare function spreadsheetTableFailureMessage(content: WorkSpreadsheetContent, request: SpreadsheetTableRequest): string | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Selection } from '@fortune-sheet/core';
|
|
2
|
+
import type { WorkSpreadsheetContent } from '../work-types';
|
|
3
|
+
import type { SpreadsheetEditorCommands, SpreadsheetTableCommandPort } from './spreadsheet-command-controller';
|
|
4
|
+
export interface SpreadsheetTableSelectionState {
|
|
5
|
+
selection: Selection;
|
|
6
|
+
sheetId: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function useSpreadsheetTable({ commandsRef, contentRef, focusGrid, getGridFocusTarget, getLiveSelection, preview, }: {
|
|
9
|
+
commandsRef: {
|
|
10
|
+
current: SpreadsheetEditorCommands | null;
|
|
11
|
+
};
|
|
12
|
+
contentRef: {
|
|
13
|
+
current: WorkSpreadsheetContent;
|
|
14
|
+
};
|
|
15
|
+
focusGrid: (focusOrigin: Element | null) => void;
|
|
16
|
+
getGridFocusTarget: () => HTMLElement | null;
|
|
17
|
+
getLiveSelection: () => Selection | undefined;
|
|
18
|
+
preview: boolean;
|
|
19
|
+
}): {
|
|
20
|
+
commandPort: SpreadsheetTableCommandPort;
|
|
21
|
+
selectionForChange: () => SpreadsheetTableSelectionState | null;
|
|
22
|
+
dialog: import("react").JSX.Element | null;
|
|
23
|
+
};
|