@a3s-lab/office 0.34.0 → 0.36.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 +44 -25
- package/dist/0~7048.js +497 -2
- package/dist/0~presentation-editor.js +19 -5
- package/dist/0~spreadsheet-editor.js +298 -32
- package/dist/0~work-office-diagnostics.js +1 -1
- package/dist/3266.js +189 -10
- package/dist/4121.js +257 -0
- package/dist/8715.js +299 -299
- package/dist/core.js +14 -4
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +2 -0
- package/dist/internal/features/work/editors/presentation-text-editor.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-calculation-model.d.ts +1 -1
- package/dist/internal/features/work/editors/spreadsheet-calculation-projection.d.ts +5 -2
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-command-selection.d.ts +22 -1
- package/dist/internal/features/work/editors/spreadsheet-table-calculated-columns.d.ts +42 -0
- package/dist/internal/features/work/editors/use-presentation-selection.d.ts +1 -1
- package/dist/internal/features/work/work-types.d.ts +5 -0
- package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -1
- package/dist/internal/kernel/office-kernel-spreadsheet-protocol.d.ts +18 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-structured-reference.d.ts +48 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +505 -2
- package/docs/latest/en/browser-editor-architecture.md +21 -8
- package/package.json +16 -13
|
@@ -6,7 +6,7 @@ import { Fragment as external_react_Fragment, cloneElement, memo, useCallback, u
|
|
|
6
6
|
import { convertSpanToShareString, genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
|
|
7
7
|
import { freezeImportedSpreadsheetCell, normalizeXlsxSemanticColorOrigin, spreadsheetMatrixProfile, withXlsxPatternFill, withoutEditableRange, normalizeSpreadsheetConditionalVisualOptions, xlsxSemanticColorMatchesValue, withXlsxGradientFill, effectiveSpreadsheetPageSetup, attachSpreadsheetShownCommentCells, normalizeXlsxPatternFill, withEditableRange, sameSpreadsheetHistoryValue, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, xlsxPatternFillTypes, sheetProtectionAuthority, normalizeXlsxGradientFill, xlsxGradientFillFallbackColor, editableRangeCellCount, unlockedCellCount, registerDerivedSpreadsheetMatrix, editableRangeRequiresCredentials, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSheetProtectionAuthority, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, spreadsheetConditionalThresholdsEqual } from "./9333.js";
|
|
8
8
|
import { workSpreadsheetChartSupportsGrouping, spreadsheetFormulaRangesForSelection, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleColumns, normalizeSpreadsheetPrintTitleRows, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, spreadsheetGridSize, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, cloneSparseMatrix, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, sparseArrayEntries, normalizeWorkSpreadsheetTrendline, effectiveSpreadsheetCalculationSettings, spreadsheetPivotIntersects, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotOutputContains, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, sparseArrayIndexes, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, reconcileSpreadsheetPivots, spreadsheetPivotCount, sparseMatrixColumnCount, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFilterItems, spreadsheetPivotFields, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
|
|
9
|
-
import {
|
|
9
|
+
import { reconcileSpreadsheetTableCalculatedColumns, spreadsheetTextOrientationFromChoice, xlsxRichTextCellText, isSpreadsheetTextOrientationId, spreadsheetTextOrientationFromAngle, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetCellValueWithDiagonalBorder, spreadsheetUnderlineCellValue, normalizeSpreadsheetDataValidationErrorStyle, normalizeXlsxRichTextEditSource, normalizeXlsxRichTextColor, isHighSurrogate, xlsxNativeFillCellKeys, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, boundedSpreadsheetDataValidationText, normalizeXlsxRichTextCell, activeXlsxNativeFill, spreadsheetUnderlineStyle, normalizeSpreadsheetDateValidationBoundary, deleteXlsxNativeFills, spreadsheetTextOrientationCellStyle, spreadsheetTextOrientationChoiceFromCell, normalizeXlsxRichTextRun, spreadsheetDiagonalBorderFromCellValue, sameXlsxRichTextRunStyle, isLowSurrogate, spreadsheetTextOrientationFromCell, coalesceXlsxRichTextRuns, patchSpreadsheetRichTextFontRuns, fillSpreadsheetTableCalculatedColumns, validXlsxRichText, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, isSpreadsheetUnderlineStyle, spreadsheetVisibleTextRotationFromCell } from "./3266.js";
|
|
10
10
|
import { moveOfficeMenuFocus, stepOfficeZoom, useOfficeRemoteParticipants, Popover, Dialog, officePresenceColor, useOfficePublishPresenceLocation, button_Button, icon_button_IconButton, moveOfficeGridMenuFocus, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~8136.js";
|
|
11
11
|
import { isOfficeKernelSpreadsheetError, normalizeCssColor, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, createOfficeId as createWorkId } from "./4121.js";
|
|
12
12
|
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
@@ -3769,12 +3769,22 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3769
3769
|
const sheetOperations = operations.filter((operation)=>operation.id === source.id);
|
|
3770
3770
|
let tables = source.tables;
|
|
3771
3771
|
const reconcileColumns = new Set();
|
|
3772
|
+
const calculatedColumnRows = new Map();
|
|
3772
3773
|
if (!operations.length) for (const table of tables)reconcileColumns.add(table.id);
|
|
3773
3774
|
for (const operation of sheetOperations){
|
|
3774
3775
|
const structure = spreadsheetTableStructureChangeFromOperation(operation);
|
|
3775
3776
|
if (structure) {
|
|
3777
|
+
transformCalculatedColumnRows(calculatedColumnRows, structure);
|
|
3776
3778
|
const transformed = [];
|
|
3777
3779
|
for (const table of tables){
|
|
3780
|
+
if ('row' === structure.axis && 'insert' === structure.kind) {
|
|
3781
|
+
const insertedRows = rowsInsertedIntoSpreadsheetTableBody(table, structure);
|
|
3782
|
+
if (insertedRows.length) {
|
|
3783
|
+
const rows = calculatedColumnRows.get(table.id) ?? new Set();
|
|
3784
|
+
for (const row of insertedRows)rows.add(row);
|
|
3785
|
+
calculatedColumnRows.set(table.id, rows);
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3778
3788
|
const next = transformSpreadsheetTableStructure(table, structure);
|
|
3779
3789
|
if (next) {
|
|
3780
3790
|
transformed.push(next);
|
|
@@ -3786,7 +3796,7 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3786
3796
|
}
|
|
3787
3797
|
const coordinate = spreadsheetCellCoordinateFromOperation(operation);
|
|
3788
3798
|
if (!coordinate) continue;
|
|
3789
|
-
const table = tables.find((candidate)=>candidate
|
|
3799
|
+
const table = tables.find((candidate)=>spreadsheetTableContainsCell(candidate, coordinate.row, coordinate.column));
|
|
3790
3800
|
if (table) reconcileColumns.add(table.id);
|
|
3791
3801
|
}
|
|
3792
3802
|
const updates = [];
|
|
@@ -3794,7 +3804,11 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3794
3804
|
tables = tables.map((table)=>{
|
|
3795
3805
|
if (!reconcileColumns.has(table.id)) return table;
|
|
3796
3806
|
const columns = canonicalSpreadsheetTableColumns(table, readCell);
|
|
3797
|
-
|
|
3807
|
+
const calculatedColumns = reconcileSpreadsheetTableCalculatedColumns(sheet, {
|
|
3808
|
+
...table,
|
|
3809
|
+
columns
|
|
3810
|
+
});
|
|
3811
|
+
if (table.headerRow) for (const [offset, column] of calculatedColumns.entries()){
|
|
3798
3812
|
const cellColumn = table.range.column[0] + offset;
|
|
3799
3813
|
if (spreadsheetCellText(readCell(table.range.row[0], cellColumn)) !== column.name) updates.push({
|
|
3800
3814
|
column: cellColumn,
|
|
@@ -3802,12 +3816,19 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3802
3816
|
row: table.range.row[0]
|
|
3803
3817
|
});
|
|
3804
3818
|
}
|
|
3805
|
-
return sameSpreadsheetTableColumns(table.columns,
|
|
3819
|
+
return sameSpreadsheetTableColumns(table.columns, calculatedColumns) ? table : {
|
|
3806
3820
|
...table,
|
|
3807
|
-
columns
|
|
3821
|
+
columns: calculatedColumns
|
|
3808
3822
|
};
|
|
3809
3823
|
});
|
|
3810
|
-
|
|
3824
|
+
let withCalculatedColumns = sheet;
|
|
3825
|
+
for (const table of tables){
|
|
3826
|
+
const rows = calculatedColumnRows.get(table.id);
|
|
3827
|
+
if (rows?.size) withCalculatedColumns = fillSpreadsheetTableCalculatedColumns(withCalculatedColumns, table, [
|
|
3828
|
+
...rows
|
|
3829
|
+
]);
|
|
3830
|
+
}
|
|
3831
|
+
const withHeaders = stampSpreadsheetTableHeaderCells(withCalculatedColumns, updates);
|
|
3811
3832
|
return {
|
|
3812
3833
|
...withHeaders,
|
|
3813
3834
|
tables: tables.length ? tables : void 0
|
|
@@ -3870,6 +3891,39 @@ function transformSpreadsheetTableStructure(table, change) {
|
|
|
3870
3891
|
filters: filtersAfterSpreadsheetTableColumnDeletion(table.filters, transformed.offset, removed)
|
|
3871
3892
|
};
|
|
3872
3893
|
}
|
|
3894
|
+
function spreadsheetTableContainsCell(table, row, column) {
|
|
3895
|
+
return row >= table.range.row[0] && row <= table.range.row[1] && column >= table.range.column[0] && column <= table.range.column[1];
|
|
3896
|
+
}
|
|
3897
|
+
function rowsInsertedIntoSpreadsheetTableBody(table, change) {
|
|
3898
|
+
if ('row' !== change.axis) return [];
|
|
3899
|
+
const transformed = transformSpreadsheetTableAxisForInsertion(table.range.row, change);
|
|
3900
|
+
if (!transformed.inside) return [];
|
|
3901
|
+
const insertion = change.index + ('rightbottom' === change.direction ? 1 : 0);
|
|
3902
|
+
const bodyStart = table.range.row[0] + Number(table.headerRow);
|
|
3903
|
+
if (insertion < bodyStart) return [];
|
|
3904
|
+
return Array.from({
|
|
3905
|
+
length: change.count
|
|
3906
|
+
}, (_, offset)=>insertion + offset);
|
|
3907
|
+
}
|
|
3908
|
+
function transformCalculatedColumnRows(rowsByTable, change) {
|
|
3909
|
+
if ('row' !== change.axis || !rowsByTable.size) return;
|
|
3910
|
+
if ('insert' === change.kind) {
|
|
3911
|
+
const insertion = change.index + ('rightbottom' === change.direction ? 1 : 0);
|
|
3912
|
+
for (const [tableId, rows] of rowsByTable){
|
|
3913
|
+
const next = new Set();
|
|
3914
|
+
for (const row of rows)next.add(row >= insertion ? row + change.count : row);
|
|
3915
|
+
rowsByTable.set(tableId, next);
|
|
3916
|
+
}
|
|
3917
|
+
return;
|
|
3918
|
+
}
|
|
3919
|
+
const count = change.end - change.start + 1;
|
|
3920
|
+
for (const [tableId, rows] of rowsByTable){
|
|
3921
|
+
const next = new Set();
|
|
3922
|
+
for (const row of rows)if (row < change.start) next.add(row);
|
|
3923
|
+
else if (row > change.end) next.add(row - count);
|
|
3924
|
+
rowsByTable.set(tableId, next);
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3873
3927
|
function transformSpreadsheetTableAxisForInsertion(axis, change) {
|
|
3874
3928
|
const start = axis[0] ?? 0;
|
|
3875
3929
|
const end = axis[1] ?? start;
|
|
@@ -4092,7 +4146,7 @@ function truncateSpreadsheetTableColumnName(value, maximum) {
|
|
|
4092
4146
|
return Array.from(value).slice(0, maximum).join('');
|
|
4093
4147
|
}
|
|
4094
4148
|
function sameSpreadsheetTableColumns(left, right) {
|
|
4095
|
-
return left.length === right.length && left.every((column, index)=>column.name === right[index]?.name);
|
|
4149
|
+
return left.length === right.length && left.every((column, index)=>column.name === right[index]?.name && column.calculatedFormula === right[index]?.calculatedFormula);
|
|
4096
4150
|
}
|
|
4097
4151
|
function spreadsheet_table_reconciliation_isRecord(value) {
|
|
4098
4152
|
return Boolean(value && 'object' == typeof value && !Array.isArray(value));
|
|
@@ -5315,6 +5369,70 @@ function spreadsheetCellFillRangeIsSafe(range) {
|
|
|
5315
5369
|
function sameSpreadsheetCellRange(left, right) {
|
|
5316
5370
|
return left.row[0] === right.row[0] && left.row[1] === right.row[1] && left.column[0] === right.column[0] && left.column[1] === right.column[1];
|
|
5317
5371
|
}
|
|
5372
|
+
function canEditSpreadsheetSelection(context) {
|
|
5373
|
+
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
5374
|
+
}
|
|
5375
|
+
function spreadsheetLiveCommandRange(context) {
|
|
5376
|
+
const selection = spreadsheetLiveCommandSelection(context);
|
|
5377
|
+
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
5378
|
+
}
|
|
5379
|
+
function spreadsheetLiveCommandSelection(context) {
|
|
5380
|
+
return spreadsheetLiveCommandSelections(context)?.at(-1);
|
|
5381
|
+
}
|
|
5382
|
+
function spreadsheetLiveCommandSelections(context) {
|
|
5383
|
+
const shadow = context.selectionRef?.current;
|
|
5384
|
+
if (shadow?.sheetId === context.targetSheetId) return [
|
|
5385
|
+
shadow.selection
|
|
5386
|
+
];
|
|
5387
|
+
return context.workbook?.getSelection();
|
|
5388
|
+
}
|
|
5389
|
+
function acceptSpreadsheetSelectionChange(selectionRef, sheetId, selection) {
|
|
5390
|
+
const nextSelection = finiteSpreadsheetSelection(selection);
|
|
5391
|
+
const requested = selectionRef.requested;
|
|
5392
|
+
if (requested && (requested.sheetId !== sheetId || !sameSpreadsheetSelectionValue(requested.selection, nextSelection))) return null;
|
|
5393
|
+
const next = {
|
|
5394
|
+
sheetId,
|
|
5395
|
+
selection: nextSelection
|
|
5396
|
+
};
|
|
5397
|
+
selectionRef.current = next;
|
|
5398
|
+
return next;
|
|
5399
|
+
}
|
|
5400
|
+
function rememberSpreadsheetCommandSelection(context, selection) {
|
|
5401
|
+
if (!context.selectionRef || !context.targetSheetId) return;
|
|
5402
|
+
const next = {
|
|
5403
|
+
...selection,
|
|
5404
|
+
row: [
|
|
5405
|
+
...selection.row
|
|
5406
|
+
],
|
|
5407
|
+
column: [
|
|
5408
|
+
...selection.column
|
|
5409
|
+
]
|
|
5410
|
+
};
|
|
5411
|
+
context.selectionRef.current = {
|
|
5412
|
+
sheetId: context.targetSheetId,
|
|
5413
|
+
selection: next
|
|
5414
|
+
};
|
|
5415
|
+
context.selectionRef.requested = {
|
|
5416
|
+
sheetId: context.targetSheetId,
|
|
5417
|
+
selection: {
|
|
5418
|
+
...next,
|
|
5419
|
+
row: [
|
|
5420
|
+
...next.row
|
|
5421
|
+
],
|
|
5422
|
+
column: [
|
|
5423
|
+
...next.column
|
|
5424
|
+
]
|
|
5425
|
+
}
|
|
5426
|
+
};
|
|
5427
|
+
}
|
|
5428
|
+
function releaseSpreadsheetSelectionRequest(selectionRef) {
|
|
5429
|
+
selectionRef.requested = null;
|
|
5430
|
+
}
|
|
5431
|
+
function sameSpreadsheetSelectionValue(left, right) {
|
|
5432
|
+
const normalizedLeft = finiteSpreadsheetSelection(left);
|
|
5433
|
+
const normalizedRight = finiteSpreadsheetSelection(right);
|
|
5434
|
+
return normalizedLeft.row[0] === normalizedRight.row[0] && normalizedLeft.row[1] === normalizedRight.row[1] && normalizedLeft.column[0] === normalizedRight.column[0] && normalizedLeft.column[1] === normalizedRight.column[1] && normalizedLeft.row_focus === normalizedRight.row_focus && normalizedLeft.column_focus === normalizedRight.column_focus;
|
|
5435
|
+
}
|
|
5318
5436
|
function createSpreadsheetCellFillExtension() {
|
|
5319
5437
|
return createOfficeEditorExtension({
|
|
5320
5438
|
name: 'spreadsheetCellFill',
|
|
@@ -5365,9 +5483,11 @@ function materializeSpreadsheetCellFillRows(sheet, plan) {
|
|
|
5365
5483
|
}
|
|
5366
5484
|
function spreadsheetSelectedCellFillPlan(context, direction) {
|
|
5367
5485
|
if (!context.editable || !context.workbook || !context.targetSheetId || context.targetSheetId !== context.activeSheetId) return null;
|
|
5368
|
-
const selections = context
|
|
5486
|
+
const selections = spreadsheetLiveCommandSelections(context);
|
|
5369
5487
|
if (selections?.length !== 1) return null;
|
|
5370
|
-
const
|
|
5488
|
+
const selection = selections[0];
|
|
5489
|
+
if (!selection) return null;
|
|
5490
|
+
const plan = planSpreadsheetCellFill(selection, direction);
|
|
5371
5491
|
if (!plan) return null;
|
|
5372
5492
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
5373
5493
|
return canApplySpreadsheetCellFill(sheet, plan) ? plan : null;
|
|
@@ -6323,13 +6443,6 @@ function applySelectedCellStyle(context, preset) {
|
|
|
6323
6443
|
function liveSpreadsheetCellStyleRange(context) {
|
|
6324
6444
|
return spreadsheetSingleRange(context.workbook?.getSelection()?.at(-1) ?? context.fallbackRange);
|
|
6325
6445
|
}
|
|
6326
|
-
function canEditSpreadsheetSelection(context) {
|
|
6327
|
-
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
6328
|
-
}
|
|
6329
|
-
function spreadsheetLiveCommandRange(context) {
|
|
6330
|
-
const selection = context.workbook?.getSelection()?.at(-1);
|
|
6331
|
-
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
6332
|
-
}
|
|
6333
6446
|
const MAX_SPREADSHEET_ROWS = 1048576;
|
|
6334
6447
|
const spreadsheetPasteContentOptions = [
|
|
6335
6448
|
{
|
|
@@ -8493,7 +8606,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8493
8606
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
8494
8607
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
8495
8608
|
if (!sheet) return false;
|
|
8496
|
-
const liveSelection = context
|
|
8609
|
+
const liveSelection = spreadsheetLiveCommandSelection(context) ?? context.fallbackRange;
|
|
8497
8610
|
const rememberedFocus = storage.focus;
|
|
8498
8611
|
const selection = rememberedFocus && spreadsheetSelectionContainsFocus(liveSelection, rememberedFocus) ? {
|
|
8499
8612
|
...liveSelection,
|
|
@@ -8507,6 +8620,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8507
8620
|
], {
|
|
8508
8621
|
id: context.targetSheetId
|
|
8509
8622
|
});
|
|
8623
|
+
rememberSpreadsheetCommandSelection(context, next);
|
|
8510
8624
|
storage.focus = {
|
|
8511
8625
|
row: next.row_focus ?? next.row[1] ?? next.row[0] ?? 0,
|
|
8512
8626
|
column: next.column_focus ?? next.column[1] ?? next.column[0] ?? 0
|
|
@@ -9318,7 +9432,7 @@ function applySpreadsheetTable(content, request) {
|
|
|
9318
9432
|
family: 'medium',
|
|
9319
9433
|
number: 2
|
|
9320
9434
|
};
|
|
9321
|
-
const
|
|
9435
|
+
const tableWithoutCalculatedColumns = {
|
|
9322
9436
|
id: createWorkId('spreadsheet-table'),
|
|
9323
9437
|
name: validation.name,
|
|
9324
9438
|
range: cloneRange(validation.range),
|
|
@@ -9334,6 +9448,10 @@ function applySpreadsheetTable(content, request) {
|
|
|
9334
9448
|
showRowStripes: 'none' !== style.family,
|
|
9335
9449
|
showColumnStripes: false
|
|
9336
9450
|
};
|
|
9451
|
+
const table = {
|
|
9452
|
+
...tableWithoutCalculatedColumns,
|
|
9453
|
+
columns: reconcileSpreadsheetTableCalculatedColumns(validation.sheet, tableWithoutCalculatedColumns)
|
|
9454
|
+
};
|
|
9337
9455
|
const nextSheet = request.headerRow ? stampSpreadsheetTableHeaders(validation.sheet, validation.range, validation.columns) : validation.sheet;
|
|
9338
9456
|
return replaceSpreadsheetTableSheet(content, {
|
|
9339
9457
|
...nextSheet,
|
|
@@ -10010,6 +10128,16 @@ function pasteCells(context, values) {
|
|
|
10010
10128
|
], {
|
|
10011
10129
|
id: context.targetSheetId
|
|
10012
10130
|
});
|
|
10131
|
+
rememberSpreadsheetCommandSelection(context, {
|
|
10132
|
+
row: [
|
|
10133
|
+
...range.row
|
|
10134
|
+
],
|
|
10135
|
+
column: [
|
|
10136
|
+
...range.column
|
|
10137
|
+
],
|
|
10138
|
+
row_focus: range.row[0],
|
|
10139
|
+
column_focus: range.column[0]
|
|
10140
|
+
});
|
|
10013
10141
|
} catch {}
|
|
10014
10142
|
syncSpreadsheetFormulaBar(context, data[0][0]);
|
|
10015
10143
|
return true;
|
|
@@ -10374,9 +10502,9 @@ function createSpreadsheetFormulaDiagnostics(content, { summary, locations }) {
|
|
|
10374
10502
|
});
|
|
10375
10503
|
if (summary.structuredReferenceCells) diagnostics.push({
|
|
10376
10504
|
code: 'formula.structured-references',
|
|
10377
|
-
severity: '
|
|
10505
|
+
severity: 'info',
|
|
10378
10506
|
title: '结构化引用',
|
|
10379
|
-
message: `${summary.structuredReferenceCells}
|
|
10507
|
+
message: `${summary.structuredReferenceCells} 个公式使用表格结构化引用;浏览器内核支持有界表名、显示名称、连续列范围以及常见标题、数据、汇总和当前行选择。不连续、外部或高级形式会保留公式与缓存值,交由兼容应用重算。`,
|
|
10380
10508
|
locations: locations.structured
|
|
10381
10509
|
});
|
|
10382
10510
|
if (summary.unsupportedFunctions.length) diagnostics.push({
|
|
@@ -21838,10 +21966,15 @@ function compileSpreadsheetKernelWorkbook(sheets, fallbackCells = []) {
|
|
|
21838
21966
|
cellCount += cells.length;
|
|
21839
21967
|
sheetIds.add(id);
|
|
21840
21968
|
sheetNames.add(normalizedName);
|
|
21969
|
+
const tables = spreadsheetKernelTables(sheet.tables);
|
|
21970
|
+
if (null === tables) return null;
|
|
21841
21971
|
sourceSheets.push({
|
|
21842
21972
|
id,
|
|
21843
21973
|
name,
|
|
21844
|
-
cells
|
|
21974
|
+
cells,
|
|
21975
|
+
...tables.length ? {
|
|
21976
|
+
tables
|
|
21977
|
+
} : {}
|
|
21845
21978
|
});
|
|
21846
21979
|
}
|
|
21847
21980
|
const compiled = sourceSheets.map((sheet)=>({
|
|
@@ -21884,7 +22017,8 @@ function spreadsheetKernelSourceState(sheets) {
|
|
|
21884
22017
|
sourceCells,
|
|
21885
22018
|
structureKey: JSON.stringify(sheets.map((sheet)=>({
|
|
21886
22019
|
id: sheet.id,
|
|
21887
|
-
name: sheet.name
|
|
22020
|
+
name: sheet.name,
|
|
22021
|
+
tables: sheet.tables ?? []
|
|
21888
22022
|
})))
|
|
21889
22023
|
};
|
|
21890
22024
|
}
|
|
@@ -21902,7 +22036,18 @@ function spreadsheetStructureKey(sheets) {
|
|
|
21902
22036
|
names.add(normalizedName);
|
|
21903
22037
|
structure.push({
|
|
21904
22038
|
id,
|
|
21905
|
-
name
|
|
22039
|
+
name,
|
|
22040
|
+
tables: (sheet.tables ?? []).map((table)=>({
|
|
22041
|
+
name: table.name,
|
|
22042
|
+
displayName: table.displayName,
|
|
22043
|
+
startRow: table.range.row[0],
|
|
22044
|
+
endRow: table.range.row[1],
|
|
22045
|
+
startColumn: table.range.column[0],
|
|
22046
|
+
endColumn: table.range.column[1],
|
|
22047
|
+
columns: table.columns.map((column)=>column.name),
|
|
22048
|
+
headerRow: table.headerRow,
|
|
22049
|
+
totalsRow: table.totalsRow
|
|
22050
|
+
}))
|
|
21906
22051
|
});
|
|
21907
22052
|
}
|
|
21908
22053
|
return JSON.stringify(structure);
|
|
@@ -21985,6 +22130,49 @@ function spreadsheetKernelInputCell(cell, fallback) {
|
|
|
21985
22130
|
const { formula: _formula, ...cachedCell } = cell;
|
|
21986
22131
|
return cachedCell;
|
|
21987
22132
|
}
|
|
22133
|
+
function spreadsheetKernelTables(tables) {
|
|
22134
|
+
if (!tables?.length) return [];
|
|
22135
|
+
const names = new Map();
|
|
22136
|
+
const ranges = [];
|
|
22137
|
+
for (const [tableIndex, table] of tables.entries()){
|
|
22138
|
+
const [startRow, endRow] = table.range.row;
|
|
22139
|
+
const [startColumn, endColumn] = table.range.column;
|
|
22140
|
+
if (!table.name?.trim() || utf8ByteLength(table.name) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES || void 0 !== table.displayName && (!table.displayName.trim() || utf8ByteLength(table.displayName) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES) || !isSpreadsheetCoordinateIndex(startRow, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(endRow, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(startColumn, 16384) || !isSpreadsheetCoordinateIndex(endColumn, 16384) || startRow > endRow || startColumn > endColumn || table.columns.length !== endColumn - startColumn + 1) return null;
|
|
22141
|
+
for (const alias of [
|
|
22142
|
+
table.name,
|
|
22143
|
+
table.displayName
|
|
22144
|
+
]){
|
|
22145
|
+
if (!alias) continue;
|
|
22146
|
+
const normalized = alias.toLocaleLowerCase();
|
|
22147
|
+
const previous = names.get(normalized);
|
|
22148
|
+
if (void 0 !== previous && previous !== tableIndex) return null;
|
|
22149
|
+
names.set(normalized, tableIndex);
|
|
22150
|
+
}
|
|
22151
|
+
const columnNames = new Set();
|
|
22152
|
+
for (const column of table.columns){
|
|
22153
|
+
if (!column.name?.trim() || utf8ByteLength(column.name) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES) return null;
|
|
22154
|
+
const normalized = column.name.toLocaleLowerCase();
|
|
22155
|
+
if (columnNames.has(normalized)) return null;
|
|
22156
|
+
columnNames.add(normalized);
|
|
22157
|
+
}
|
|
22158
|
+
const next = {
|
|
22159
|
+
name: table.name,
|
|
22160
|
+
...table.displayName ? {
|
|
22161
|
+
displayName: table.displayName
|
|
22162
|
+
} : {},
|
|
22163
|
+
startRow,
|
|
22164
|
+
endRow,
|
|
22165
|
+
startColumn,
|
|
22166
|
+
endColumn,
|
|
22167
|
+
columns: table.columns.map((column)=>column.name),
|
|
22168
|
+
headerRow: Boolean(table.headerRow),
|
|
22169
|
+
totalsRow: Boolean(table.totalsRow)
|
|
22170
|
+
};
|
|
22171
|
+
if (ranges.some((previous)=>next.startRow <= previous.endRow && next.endRow >= previous.startRow && next.startColumn <= previous.endColumn && next.endColumn >= previous.startColumn)) return null;
|
|
22172
|
+
ranges.push(next);
|
|
22173
|
+
}
|
|
22174
|
+
return ranges;
|
|
22175
|
+
}
|
|
21988
22176
|
function spreadsheetSheetsWithKernelChanges(sheets, changes) {
|
|
21989
22177
|
const changesBySheet = new Map();
|
|
21990
22178
|
for (const change of changes.values()){
|
|
@@ -22243,7 +22431,7 @@ function spreadsheetCalculationOps(sheets, calculatedCells) {
|
|
|
22243
22431
|
});
|
|
22244
22432
|
}
|
|
22245
22433
|
function sameSpreadsheetStructure(previous, current) {
|
|
22246
|
-
return previous.length === current.length && previous.every((sheet, index)=>sheet.id === current[index]?.id && sheet.name === current[index]?.name);
|
|
22434
|
+
return previous.length === current.length && previous.every((sheet, index)=>sheet.id === current[index]?.id && sheet.name === current[index]?.name && JSON.stringify(sheet.tables ?? []) === JSON.stringify(current[index]?.tables ?? []));
|
|
22247
22435
|
}
|
|
22248
22436
|
function cellWithCalculatedValue(cell, value) {
|
|
22249
22437
|
const next = {
|
|
@@ -25395,6 +25583,60 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25395
25583
|
const editorFocusOrigin = useOfficeEditorFocusOrigin();
|
|
25396
25584
|
const workbookRef = useRef(null);
|
|
25397
25585
|
const projectedWorkbookSheetsRef = useRef([]);
|
|
25586
|
+
useLayoutEffect(()=>{
|
|
25587
|
+
const container = spreadsheetCanvasRef.current;
|
|
25588
|
+
if (!container || preview) return;
|
|
25589
|
+
let pendingEditor = null;
|
|
25590
|
+
let pointerEnteredEditor = false;
|
|
25591
|
+
const moveEditorCaretToEnd = (editor)=>{
|
|
25592
|
+
if (document.activeElement !== editor || !editor.isConnected || !editor.textContent) return false;
|
|
25593
|
+
const selection = document.getSelection();
|
|
25594
|
+
if (!selection) return false;
|
|
25595
|
+
const range = document.createRange();
|
|
25596
|
+
range.selectNodeContents(editor);
|
|
25597
|
+
range.collapse(false);
|
|
25598
|
+
selection.removeAllRanges();
|
|
25599
|
+
selection.addRange(range);
|
|
25600
|
+
return true;
|
|
25601
|
+
};
|
|
25602
|
+
const handlePointerDown = (event)=>{
|
|
25603
|
+
pointerEnteredEditor = event.target instanceof Element && Boolean(event.target.closest('.luckysheet-cell-input'));
|
|
25604
|
+
};
|
|
25605
|
+
const handleFocusIn = (event)=>{
|
|
25606
|
+
const target = event.target;
|
|
25607
|
+
const editor = target instanceof Element ? target.closest('.luckysheet-cell-input') : null;
|
|
25608
|
+
if (!editor || pointerEnteredEditor) {
|
|
25609
|
+
pendingEditor = null;
|
|
25610
|
+
pointerEnteredEditor = false;
|
|
25611
|
+
return;
|
|
25612
|
+
}
|
|
25613
|
+
pendingEditor = editor;
|
|
25614
|
+
queueMicrotask(()=>{
|
|
25615
|
+
if (pendingEditor === editor && moveEditorCaretToEnd(editor)) pendingEditor = null;
|
|
25616
|
+
});
|
|
25617
|
+
};
|
|
25618
|
+
const observer = new MutationObserver(()=>{
|
|
25619
|
+
const editor = pendingEditor;
|
|
25620
|
+
if (!editor || document.activeElement !== editor) return;
|
|
25621
|
+
if (!editor.textContent) return;
|
|
25622
|
+
moveEditorCaretToEnd(editor);
|
|
25623
|
+
pendingEditor = null;
|
|
25624
|
+
});
|
|
25625
|
+
container.addEventListener('pointerdown', handlePointerDown, true);
|
|
25626
|
+
container.addEventListener('focusin', handleFocusIn, true);
|
|
25627
|
+
observer.observe(container, {
|
|
25628
|
+
characterData: true,
|
|
25629
|
+
childList: true,
|
|
25630
|
+
subtree: true
|
|
25631
|
+
});
|
|
25632
|
+
return ()=>{
|
|
25633
|
+
container.removeEventListener('pointerdown', handlePointerDown, true);
|
|
25634
|
+
container.removeEventListener('focusin', handleFocusIn, true);
|
|
25635
|
+
observer.disconnect();
|
|
25636
|
+
};
|
|
25637
|
+
}, [
|
|
25638
|
+
preview
|
|
25639
|
+
]);
|
|
25398
25640
|
const spreadsheetZoomRef = useRef(100);
|
|
25399
25641
|
const [workbookInstance, setWorkbookInstance] = useState(null);
|
|
25400
25642
|
const bindWorkbookInstance = useCallback((instance)=>{
|
|
@@ -25413,6 +25655,10 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25413
25655
|
const [panel, setPanel] = useState(null);
|
|
25414
25656
|
const panelTriggerRef = useRef(null);
|
|
25415
25657
|
const [selectionState, setSelectionState] = useState(null);
|
|
25658
|
+
const selectionStateRef = useRef({
|
|
25659
|
+
current: null,
|
|
25660
|
+
requested: null
|
|
25661
|
+
});
|
|
25416
25662
|
const formatPainterSelectionHandlerRef = useRef((_sheetId, _selection)=>void 0);
|
|
25417
25663
|
const [contextMenu, setContextMenu] = useState(null);
|
|
25418
25664
|
const [formatCellsDialog, setFormatCellsDialog] = useState(null);
|
|
@@ -25588,15 +25834,16 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25588
25834
|
collaborationView?.activateSheet(id);
|
|
25589
25835
|
if (previewRef.current) setPreviewActiveSheetId(id);
|
|
25590
25836
|
else setNavigationActiveSheetId(id);
|
|
25837
|
+
selectionStateRef.current.current = null;
|
|
25838
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25591
25839
|
setSelectionState(null);
|
|
25592
25840
|
},
|
|
25593
25841
|
afterSelectionChange: (sheetId, selection)=>{
|
|
25594
|
-
|
|
25595
|
-
|
|
25596
|
-
|
|
25597
|
-
|
|
25598
|
-
|
|
25599
|
-
formatPainterSelectionHandlerRef.current(sheetId, selection);
|
|
25842
|
+
const next = acceptSpreadsheetSelectionChange(selectionStateRef.current, sheetId, selection);
|
|
25843
|
+
if (!next) return;
|
|
25844
|
+
collaborationView?.select(sheetId, next.selection);
|
|
25845
|
+
setSelectionState(next);
|
|
25846
|
+
formatPainterSelectionHandlerRef.current(sheetId, next.selection);
|
|
25600
25847
|
},
|
|
25601
25848
|
beforeUpdateCell: (row, column)=>{
|
|
25602
25849
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
@@ -25876,6 +26123,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25876
26123
|
if (!sheet) return false;
|
|
25877
26124
|
activeSheetIdRef.current = sheetId;
|
|
25878
26125
|
if (collaborationView && !collaborationView.activateSheet(sheetId)) return false;
|
|
26126
|
+
selectionStateRef.current.current = null;
|
|
26127
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25879
26128
|
setSelectionState(null);
|
|
25880
26129
|
if (previewRef.current) setPreviewActiveSheetId(sheetId);
|
|
25881
26130
|
try {
|
|
@@ -25910,7 +26159,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25910
26159
|
targetRow: activeCell.row,
|
|
25911
26160
|
targetColumn: activeCell.column
|
|
25912
26161
|
});
|
|
25913
|
-
|
|
26162
|
+
const nextSelection = {
|
|
25914
26163
|
sheetId,
|
|
25915
26164
|
selection: {
|
|
25916
26165
|
row: [
|
|
@@ -25922,7 +26171,21 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25922
26171
|
row_focus: activeCell.row,
|
|
25923
26172
|
column_focus: activeCell.column
|
|
25924
26173
|
}
|
|
25925
|
-
}
|
|
26174
|
+
};
|
|
26175
|
+
selectionStateRef.current.current = nextSelection;
|
|
26176
|
+
selectionStateRef.current.requested = {
|
|
26177
|
+
sheetId,
|
|
26178
|
+
selection: {
|
|
26179
|
+
...nextSelection.selection,
|
|
26180
|
+
row: [
|
|
26181
|
+
...nextSelection.selection.row
|
|
26182
|
+
],
|
|
26183
|
+
column: [
|
|
26184
|
+
...nextSelection.selection.column
|
|
26185
|
+
]
|
|
26186
|
+
}
|
|
26187
|
+
};
|
|
26188
|
+
setSelectionState(nextSelection);
|
|
25926
26189
|
} catch {
|
|
25927
26190
|
return false;
|
|
25928
26191
|
}
|
|
@@ -26043,6 +26306,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26043
26306
|
toggle: (attribute)=>richTextSelectionRef.current?.toggle(contentRef.current, acceptSpreadsheetCommandChange, attribute) ?? false
|
|
26044
26307
|
},
|
|
26045
26308
|
selection: selectionState,
|
|
26309
|
+
selectionRef: selectionStateRef.current,
|
|
26046
26310
|
table: spreadsheetTable.commandPort,
|
|
26047
26311
|
targetSheetGridSize,
|
|
26048
26312
|
targetSheetId: toolbarSheetId,
|
|
@@ -26150,6 +26414,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26150
26414
|
if ('Escape' === event.key && isSpreadsheetCellEditingTarget(event.target)) requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
|
|
26151
26415
|
};
|
|
26152
26416
|
const handleSpreadsheetKeyDownCapture = (event)=>{
|
|
26417
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26153
26418
|
if ('Alt' === event.key && !event.repeat && event.target instanceof Element && event.target.closest('.fortune-sheet-overlay') && reserveAutoFilterAltKey()) {
|
|
26154
26419
|
event.preventDefault();
|
|
26155
26420
|
event.stopPropagation();
|
|
@@ -26158,6 +26423,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26158
26423
|
handleSpreadsheetEditingEscape(event);
|
|
26159
26424
|
};
|
|
26160
26425
|
const handleSpreadsheetPointerDownCapture = (event)=>{
|
|
26426
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26161
26427
|
const controller = richTextSelectionRef.current;
|
|
26162
26428
|
if (!controller) return;
|
|
26163
26429
|
if (!isSpreadsheetRichTextFormatPointerTarget(event.target)) return void controller.clear();
|
|
@@ -1950,7 +1950,7 @@ async function diagnoseXlsxFormulas(archive, importedFeatures, worksheetScans) {
|
|
|
1950
1950
|
if (dataTables) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.data-tables', `${dataTables} what-if data table(s), input references, and cached results are preserved, but Work does not recalculate scenario tables in the browser.`));
|
|
1951
1951
|
if (cachedErrors) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.cached-errors', `${cachedErrors} formula cell(s) contain cached Excel error values; the error type and displayed value are preserved in editing, preview, print, and export.`));
|
|
1952
1952
|
if (externalReferences.length) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.external-references', `${externalReferences.length} formula cell(s) reference external workbooks; formulas and cached values are preserved without refreshing external files.`));
|
|
1953
|
-
if (structuredReferences.length) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.structured-references', `${structuredReferences.length} formula cell(s) use structured table references;
|
|
1953
|
+
if (structuredReferences.length) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.structured-references', `${structuredReferences.length} formula cell(s) use structured table references; the browser kernel resolves bounded table names, display names, contiguous column ranges, and common row selectors. Disjoint, external, and advanced forms keep their source formula and cached value for compatible recalculation.`, 'info'));
|
|
1954
1954
|
if (unsupportedFunctions.size) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.unsupported-functions', `The current browser calculation engine does not evaluate ${Array.from(unsupportedFunctions).sort().join(', ')}; source formulas and cached results are preserved for compatible desktop recalculation.`));
|
|
1955
1955
|
if (volatileFormulas.length) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.volatile', `${volatileFormulas.length} volatile formula cell(s) can change when the workbook is explicitly recalculated.`, 'info'));
|
|
1956
1956
|
if (unsupportedFormulaAttributes.size) issues.push(work_xlsx_formula_diagnostics_issue('xlsx.formulas.attributes', `Advanced formula attributes are not represented by the editable model and normalize on export: ${Array.from(unsupportedFormulaAttributes).sort().join(', ')}.`));
|