@a3s-lab/office 0.11.0 → 0.12.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 +23 -1
- package/dist/0~spreadsheet-editor.js +189 -104
- package/dist/0~work-docx-import.js +2 -2
- package/dist/0~work-office-diagnostics.js +6 -4
- package/dist/0~work-pptx-import.js +2 -2
- package/dist/4104.js +329 -121
- package/dist/4476.js +82 -65
- package/dist/8715.js +41 -3
- package/dist/9356.js +126 -8
- package/dist/core.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +1 -0
- package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +2 -1
- package/dist/internal/features/work/spreadsheet-sparse.d.ts +5 -0
- package/dist/internal/features/work/work-document-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-docx-import.d.ts +2 -1
- package/dist/internal/features/work/work-file-data.d.ts +7 -1
- package/dist/internal/features/work/work-file-import.d.ts +28 -0
- package/dist/internal/features/work/work-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-markdown-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-office-diagnostics.d.ts +3 -2
- package/dist/internal/features/work/work-pptx-import.d.ts +1 -1
- package/dist/internal/features/work/work-presentation-file-io.d.ts +2 -1
- package/dist/internal/features/work/work-spreadsheet-protection.d.ts +2 -0
- package/dist/internal/features/work/work-types.d.ts +22 -0
- package/dist/internal/features/work/work-xlsx-interop.d.ts +4 -14
- package/dist/office-kernel.wasm +0 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -578,11 +578,32 @@ import {
|
|
|
578
578
|
importOfficeFile,
|
|
579
579
|
} from '@a3s-lab/office/core';
|
|
580
580
|
|
|
581
|
-
const
|
|
581
|
+
const controller = new AbortController();
|
|
582
|
+
const imported = await importOfficeFile(file, {
|
|
583
|
+
signal: controller.signal,
|
|
584
|
+
onProgress: ({ stage, progress }) => {
|
|
585
|
+
console.info(stage, `${Math.round(progress * 100)}%`);
|
|
586
|
+
},
|
|
587
|
+
});
|
|
582
588
|
const output = await createArtifactBlob(imported);
|
|
583
589
|
const blankDeck = createArtifact('blank-presentation');
|
|
584
590
|
```
|
|
585
591
|
|
|
592
|
+
Import progress advances monotonically through `reading`, `parsing`,
|
|
593
|
+
`analyzing`, and `finalizing`. Calling `controller.abort()` rejects with an
|
|
594
|
+
`AbortError`; large reads and parser checkpoints yield so a host can keep the
|
|
595
|
+
progress and Cancel controls responsive.
|
|
596
|
+
|
|
597
|
+
Spreadsheet import and export preserve sparse worksheets up to the XLSX limit
|
|
598
|
+
of 1,048,576 rows by 16,384 columns. The logical `data.length`, `row`, and
|
|
599
|
+
`column` dimensions can be large while only populated indexes are materialized.
|
|
600
|
+
Virtual scrolling never emits `onChange`, and editing a far blank row creates
|
|
601
|
+
only that row. Data-validation regions remain compact in
|
|
602
|
+
`dataValidationRanges`; direct `dataVerification` entries take precedence.
|
|
603
|
+
Protection ranges, passwordless editable ranges, and conditional formatting
|
|
604
|
+
also remain compact and round-trip through native XLSX records without
|
|
605
|
+
allocating every covered cell.
|
|
606
|
+
|
|
586
607
|
Use `downloadArtifact` to start a browser download or
|
|
587
608
|
`createArtifactBlob` when your application owns upload and persistence.
|
|
588
609
|
Imported DOCX artifacts are source-backed: safe source-only OPC parts,
|
|
@@ -1338,6 +1359,7 @@ without hard-coded return URLs.
|
|
|
1338
1359
|
|
|
1339
1360
|
- [Live Playground](https://a3s-lab.github.io/Office/)
|
|
1340
1361
|
- [Documentation center](https://a3s-lab.github.io/Office/docs/)
|
|
1362
|
+
- [A3S Office 0.12.0 documentation](https://a3s-lab.github.io/Office/docs/0.12.0/)
|
|
1341
1363
|
- [A3S Office 0.11.0 documentation](https://a3s-lab.github.io/Office/docs/0.11.0/)
|
|
1342
1364
|
- [A3S Office 0.10.0 documentation](https://a3s-lab.github.io/Office/docs/0.10.0/)
|
|
1343
1365
|
- [A3S Office 0.9.2 documentation](https://a3s-lab.github.io/Office/docs/0.9.2/)
|
|
@@ -4,12 +4,12 @@ import { Workbook } from "@fortune-sheet/react";
|
|
|
4
4
|
import { AlignCenter, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, BarChart3, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, Bookmark, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Columns3, Copy, CopyPlus, DecimalsArrowLeft, DecimalsArrowRight, Eraser, Eye, EyeOff, FileX2, Grid3X3, Italic, KeyRound, Layers2, Link2Off, ListFilter, Merge, MessageSquareX, MoveHorizontal, MoveVertical, Paintbrush, Palette, PanelLeft, PanelTop, PanelsTopLeft, Pencil, Percent, Plus, Printer, Redo2, RefreshCw, Rows3, Save, Scissors, Search, ShieldCheck, SortAsc, SortDesc, TableProperties, Trash2, Underline, Undo2, WrapText, X } from "lucide-react";
|
|
5
5
|
import { Fragment as external_react_Fragment, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
|
|
7
|
-
import { withoutEditableRange, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, editableRangeRequiresCredentials, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSpreadsheetConditionalVisualOptions, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, effectiveSpreadsheetPageSetup, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, withEditableRange, spreadsheetConditionalComparisonNeedsUpperValue, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, isSpreadsheetConditionalComparisonOperator, drawSpreadsheetConditionalIcon, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, sheetProtectionAuthority,
|
|
7
|
+
import { withoutEditableRange, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, editableRangeRequiresCredentials, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSpreadsheetConditionalVisualOptions, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, effectiveSpreadsheetPageSetup, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, withEditableRange, spreadsheetConditionalComparisonNeedsUpperValue, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, isSpreadsheetConditionalComparisonOperator, drawSpreadsheetConditionalIcon, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, sheetProtectionAuthority, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, editableRangeCellCount, unlockedCellCount } from "./4476.js";
|
|
8
|
+
import { workSpreadsheetChartSupportsGrouping, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleColumns, normalizeSpreadsheetPrintTitleRows, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, sparseArrayEntries, normalizeWorkSpreadsheetTrendline, spreadsheetPivotOutputContains, effectiveSpreadsheetCalculationSettings, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotIntersects, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, sparseArrayIndexes, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, spreadsheetPivotCount, reconcileSpreadsheetPivots, sparseMatrixColumnCount, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFields, spreadsheetPivotFilterItems, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
|
|
8
9
|
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
9
10
|
import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
|
|
10
11
|
import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
|
|
11
12
|
import { showToast } from "./6489.js";
|
|
12
|
-
import { workSpreadsheetChartSupportsGrouping, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleRows, normalizeSpreadsheetPrintTitleColumns, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, normalizeWorkSpreadsheetTrendline, spreadsheetPivotOutputContains, effectiveSpreadsheetCalculationSettings, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotIntersects, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, spreadsheetPivotCount, reconcileSpreadsheetPivots, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFields, spreadsheetPivotFilterItems, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
|
|
13
13
|
import { unsupportedSpreadsheetFormulaFunctions } from "./0~work-spreadsheet-formula-support.js";
|
|
14
14
|
import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~4595.js";
|
|
15
15
|
import { moveOfficeMenuFocus, stepOfficeZoom, Popover, useOfficeRemoteParticipants, button_Button, officePresenceColor, useOfficePublishPresenceLocation, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~6090.js";
|
|
@@ -440,18 +440,10 @@ function cellKey(row, column) {
|
|
|
440
440
|
return `${row}_${column}`;
|
|
441
441
|
}
|
|
442
442
|
function forEachCell(data, ranges, visit) {
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const endRow = Math.max(0, Math.min(maximumRow, range.row[1]));
|
|
448
|
-
const startColumn = Math.max(0, Math.min(maximumColumn, range.column[0]));
|
|
449
|
-
const endColumn = Math.max(0, Math.min(maximumColumn, range.column[1]));
|
|
450
|
-
for(let row = startRow; row <= endRow; row += 1)for(let column = startColumn; column <= endColumn; column += 1)visit({
|
|
451
|
-
row,
|
|
452
|
-
column
|
|
453
|
-
});
|
|
454
|
-
}
|
|
443
|
+
for (const [row, cells] of sparseArrayEntries(data))for (const [column] of sparseArrayEntries(cells))if (ranges.some((range)=>row >= range.row[0] && row <= range.row[1] && column >= range.column[0] && column <= range.column[1])) visit({
|
|
444
|
+
row,
|
|
445
|
+
column
|
|
446
|
+
});
|
|
455
447
|
}
|
|
456
448
|
function cellValue(data, row, column) {
|
|
457
449
|
return data[row]?.[column]?.v ?? null;
|
|
@@ -547,11 +539,12 @@ function spreadsheetSelectionSummary(sheet, selection) {
|
|
|
547
539
|
const rowEnd = Math.min(range.row[1] ?? rowStart, sheet.data.length - 1);
|
|
548
540
|
const columnStart = range.column[0] ?? 0;
|
|
549
541
|
const columnEnd = range.column[1] ?? columnStart;
|
|
550
|
-
for(
|
|
542
|
+
for (const rowIndex of sparseArrayIndexes(sheet.data)){
|
|
543
|
+
if (rowIndex < rowStart || rowIndex > rowEnd) continue;
|
|
551
544
|
const row = sheet.data[rowIndex];
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
|
|
545
|
+
if (row) {
|
|
546
|
+
for (const columnIndex of sparseArrayIndexes(row))if (!(columnIndex < columnStart) && !(columnIndex > columnEnd)) collect(row[columnIndex]);
|
|
547
|
+
}
|
|
555
548
|
}
|
|
556
549
|
} else {
|
|
557
550
|
const rowStart = range.row[0] ?? 0;
|
|
@@ -607,28 +600,66 @@ function spreadsheetSheetsWithFiniteSelections(sheets) {
|
|
|
607
600
|
}));
|
|
608
601
|
}
|
|
609
602
|
function spreadsheetSheetsForFortune(sheets) {
|
|
610
|
-
return
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
603
|
+
return sheets.map((sheet)=>{
|
|
604
|
+
const { celldata: sourceCellData, data, ...sourceMetadata } = sheet;
|
|
605
|
+
const projected = structuredClone(sourceMetadata);
|
|
606
|
+
const cells = new Map();
|
|
607
|
+
if (data) for (const rowIndex of sparseArrayIndexes(data)){
|
|
608
|
+
const row = data[rowIndex];
|
|
609
|
+
if (row) for (const columnIndex of sparseArrayIndexes(row)){
|
|
610
|
+
const cell = row[columnIndex];
|
|
611
|
+
if (null != cell) cells.set(`${rowIndex}_${columnIndex}`, {
|
|
612
|
+
r: rowIndex,
|
|
613
|
+
c: columnIndex,
|
|
614
|
+
v: structuredClone(cell)
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
else for (const entry of sourceCellData ?? [])cells.set(`${entry.r}_${entry.c}`, structuredClone(entry));
|
|
619
|
+
for (const merge of Object.values(projected.config?.merge ?? {}))for(let rowIndex = merge.r; rowIndex < merge.r + merge.rs; rowIndex += 1)for(let columnIndex = merge.c; columnIndex < merge.c + merge.cs; columnIndex += 1){
|
|
620
|
+
const key = `${rowIndex}_${columnIndex}`;
|
|
621
|
+
const current = cells.get(key);
|
|
622
|
+
cells.set(key, {
|
|
623
|
+
r: rowIndex,
|
|
624
|
+
c: columnIndex,
|
|
625
|
+
v: {
|
|
626
|
+
...current?.v ?? {},
|
|
627
|
+
mc: rowIndex === merge.r && columnIndex === merge.c ? {
|
|
628
|
+
...merge
|
|
629
|
+
} : {
|
|
630
|
+
r: merge.r,
|
|
631
|
+
c: merge.c
|
|
632
|
+
}
|
|
620
633
|
}
|
|
621
|
-
};
|
|
634
|
+
});
|
|
622
635
|
}
|
|
623
636
|
return {
|
|
624
|
-
...
|
|
625
|
-
celldata:
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
637
|
+
...projected,
|
|
638
|
+
celldata: Array.from(cells.values()).sort((left, right)=>left.r - right.r || left.c - right.c)
|
|
639
|
+
};
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
function spreadsheetSheetsFromFortune(sheets, sourceSheets) {
|
|
643
|
+
return sheets.map((sheet, index)=>{
|
|
644
|
+
const source = (sheet.id ? sourceSheets.find((candidate)=>candidate.id === sheet.id) : void 0) ?? sourceSheets[index];
|
|
645
|
+
const cells = spreadsheetPopulatedCellData(sheet);
|
|
646
|
+
const { celldata: _cellData, data: _data, ...metadata } = sheet;
|
|
647
|
+
const useMatrix = source ? void 0 !== source.data : void 0 !== sheet.data;
|
|
648
|
+
if (!useMatrix) return {
|
|
649
|
+
...metadata,
|
|
650
|
+
celldata: cells
|
|
651
|
+
};
|
|
652
|
+
const data = [];
|
|
653
|
+
data.length = Math.max(sheet.data?.length ?? 0, source?.data?.length ?? 0, positiveSpreadsheetDimension(sheet.row));
|
|
654
|
+
for (const { r: rowIndex, c: columnIndex, v: cell } of cells){
|
|
655
|
+
const row = data[rowIndex] ?? [];
|
|
656
|
+
data[rowIndex] = row;
|
|
657
|
+
row.length = Math.max(row.length, sheet.data?.[rowIndex]?.length ?? 0, source?.data?.[rowIndex]?.length ?? 0, positiveSpreadsheetDimension(sheet.column));
|
|
658
|
+
row[columnIndex] = cell;
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
...metadata,
|
|
662
|
+
data
|
|
632
663
|
};
|
|
633
664
|
});
|
|
634
665
|
}
|
|
@@ -644,7 +675,9 @@ function finiteSpreadsheetSelection(selection) {
|
|
|
644
675
|
};
|
|
645
676
|
}
|
|
646
677
|
function sameSpreadsheetWorkbookState(changed, rendered) {
|
|
647
|
-
|
|
678
|
+
const left = changed.map(spreadsheetSheetWithoutTransientSelection);
|
|
679
|
+
const right = rendered.map(spreadsheetSheetWithoutTransientSelection);
|
|
680
|
+
return sameSpreadsheetHistoryValue(left, right);
|
|
648
681
|
}
|
|
649
682
|
function sameSpreadsheetHistoryContent(left, right) {
|
|
650
683
|
return sameSpreadsheetHistoryValue({
|
|
@@ -737,8 +770,33 @@ function finiteSpreadsheetIndex(value, fallback) {
|
|
|
737
770
|
return 'number' == typeof value && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : fallback;
|
|
738
771
|
}
|
|
739
772
|
function spreadsheetSheetWithoutTransientSelection(sheet) {
|
|
740
|
-
const { celldata: _cellData, luckysheet_select_save: _selection, luckysheet_selection_range: _range, ...content } = sheet;
|
|
741
|
-
return
|
|
773
|
+
const { celldata: _cellData, calcChain: _calculationChain, data: _data, dynamicArray_compute: _dynamicArrayComputation, luckysheet_select_save: _selection, luckysheet_selection_range: _range, zoomRatio, ...content } = sheet;
|
|
774
|
+
return {
|
|
775
|
+
...content,
|
|
776
|
+
...void 0 === zoomRatio || 1 === zoomRatio ? {} : {
|
|
777
|
+
zoomRatio
|
|
778
|
+
},
|
|
779
|
+
celldata: spreadsheetPopulatedCellData(sheet)
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function spreadsheetPopulatedCellData(sheet) {
|
|
783
|
+
const cells = [];
|
|
784
|
+
if (void 0 !== sheet.data) for (const rowIndex of sparseArrayIndexes(sheet.data)){
|
|
785
|
+
const row = sheet.data[rowIndex];
|
|
786
|
+
if (row) for (const columnIndex of sparseArrayIndexes(row)){
|
|
787
|
+
const cell = row[columnIndex];
|
|
788
|
+
if (null != cell) cells.push({
|
|
789
|
+
r: rowIndex,
|
|
790
|
+
c: columnIndex,
|
|
791
|
+
v: cell
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
else for (const cell of sheet.celldata ?? [])if (null != cell.v) cells.push(cell);
|
|
796
|
+
return cells.sort((left, right)=>left.r - right.r || left.c - right.c);
|
|
797
|
+
}
|
|
798
|
+
function positiveSpreadsheetDimension(value) {
|
|
799
|
+
return 'number' == typeof value && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
742
800
|
}
|
|
743
801
|
function sameSpreadsheetHistoryValue(left, right) {
|
|
744
802
|
if (left === right) return true;
|
|
@@ -748,7 +806,9 @@ function sameSpreadsheetHistoryValue(left, right) {
|
|
|
748
806
|
if (leftFormulaCell || rightFormulaCell) return Boolean(leftFormulaCell && rightFormulaCell && sameSpreadsheetFormulaHistoryCell(leftFormulaCell, rightFormulaCell));
|
|
749
807
|
if (Array.isArray(left) || Array.isArray(right)) {
|
|
750
808
|
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
|
|
751
|
-
|
|
809
|
+
const leftKeys = Object.keys(left).filter((key)=>void 0 !== left[Number(key)]);
|
|
810
|
+
const rightKeys = Object.keys(right).filter((key)=>void 0 !== right[Number(key)]);
|
|
811
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key)=>Object.hasOwn(right, key) && sameSpreadsheetHistoryValue(left[Number(key)], right[Number(key)]));
|
|
752
812
|
}
|
|
753
813
|
if ('object' != typeof left || 'object' != typeof right) return false;
|
|
754
814
|
const leftRecord = left;
|
|
@@ -1471,13 +1531,13 @@ function spreadsheetSelectionContainsFocus(selection, focus) {
|
|
|
1471
1531
|
}
|
|
1472
1532
|
function spreadsheetSheetBounds(sheet) {
|
|
1473
1533
|
const dataRows = sheet.data?.length ?? 0;
|
|
1474
|
-
const dataColumns =
|
|
1534
|
+
const dataColumns = sparseMatrixColumnCount(sheet.data);
|
|
1475
1535
|
return {
|
|
1476
|
-
lastRow:
|
|
1477
|
-
lastColumn:
|
|
1536
|
+
lastRow: spreadsheet_keyboard_navigation_positiveSpreadsheetDimension(sheet.row, dataRows, spreadsheetDefaultRows) - 1,
|
|
1537
|
+
lastColumn: spreadsheet_keyboard_navigation_positiveSpreadsheetDimension(sheet.column, dataColumns, spreadsheetDefaultColumns) - 1
|
|
1478
1538
|
};
|
|
1479
1539
|
}
|
|
1480
|
-
function
|
|
1540
|
+
function spreadsheet_keyboard_navigation_positiveSpreadsheetDimension(configured, dataDimension, fallback) {
|
|
1481
1541
|
const value = Number(configured);
|
|
1482
1542
|
if (Number.isFinite(value) && value > 0) return Math.max(1, Math.trunc(value));
|
|
1483
1543
|
if (dataDimension > 0) return dataDimension;
|
|
@@ -1817,11 +1877,10 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1817
1877
|
return Boolean(sheet && (context.editable || context.view && 1 !== sheet.hide));
|
|
1818
1878
|
},
|
|
1819
1879
|
execute: (context, sheetId)=>{
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
}
|
|
1880
|
+
const sheet = context.content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
1881
|
+
if (!sheet) return false;
|
|
1882
|
+
if (context.view && 1 !== sheet.hide) return context.view?.activateSheet(sheetId) ?? false;
|
|
1883
|
+
if (!context.editable) return false;
|
|
1825
1884
|
return applySpreadsheetSheetChange(context, activateSpreadsheetSheet(context.content, sheetId));
|
|
1826
1885
|
}
|
|
1827
1886
|
},
|
|
@@ -2134,7 +2193,7 @@ function spreadsheetStructureExtent(context, axis) {
|
|
|
2134
2193
|
const range = spreadsheetStructureRange(liveRange(context), axis);
|
|
2135
2194
|
if (!sheet) return range[1] + 1;
|
|
2136
2195
|
if ('row' === axis) return Math.max(sheet.row ?? 0, sheet.data?.length ?? 0, range[1] + 1);
|
|
2137
|
-
const dataWidth =
|
|
2196
|
+
const dataWidth = sparseMatrixColumnCount(sheet.data);
|
|
2138
2197
|
return Math.max(sheet.column ?? 0, dataWidth, range[1] + 1);
|
|
2139
2198
|
}
|
|
2140
2199
|
function clearSelectedCells(context, mode = 'contents') {
|
|
@@ -2757,7 +2816,7 @@ function scanSpreadsheetFormulas(content) {
|
|
|
2757
2816
|
for (const sheet of content.sheets){
|
|
2758
2817
|
summary.normalizedSharedFormulaGroups += sheet.formulaMetadata?.normalizedSharedFormulaGroups ?? 0;
|
|
2759
2818
|
summary.normalizedSharedFormulaCells += sheet.formulaMetadata?.normalizedSharedFormulaCells ?? 0;
|
|
2760
|
-
for (const [row, cells] of (sheet.data
|
|
2819
|
+
for (const [row, cells] of sparseArrayEntries(sheet.data))for (const [column, cell] of sparseArrayEntries(cells)){
|
|
2761
2820
|
if (!cell?.f) continue;
|
|
2762
2821
|
const address = spreadsheetCellAddress(row, column);
|
|
2763
2822
|
const location = `${sheet.name}!${address}`;
|
|
@@ -5459,17 +5518,11 @@ function spreadsheetFindMatches(sheet, query) {
|
|
|
5459
5518
|
}
|
|
5460
5519
|
function indexedSpreadsheetCells(sheet) {
|
|
5461
5520
|
const indexed = new Map();
|
|
5462
|
-
for(
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
row,
|
|
5468
|
-
column,
|
|
5469
|
-
cell
|
|
5470
|
-
});
|
|
5471
|
-
}
|
|
5472
|
-
}
|
|
5521
|
+
for (const [row, cells] of sparseArrayEntries(sheet.data))for (const [column, cell] of sparseArrayEntries(cells))if (cell) indexed.set(`${row}:${column}`, {
|
|
5522
|
+
row,
|
|
5523
|
+
column,
|
|
5524
|
+
cell
|
|
5525
|
+
});
|
|
5473
5526
|
for (const entry of sheet.celldata ?? []){
|
|
5474
5527
|
if (!Number.isSafeInteger(entry.r) || !Number.isSafeInteger(entry.c) || entry.r < 0 || entry.c < 0 || !entry.v) continue;
|
|
5475
5528
|
const key = `${entry.r}:${entry.c}`;
|
|
@@ -9643,7 +9696,7 @@ function SpreadsheetProtectionPanel({ content, onChange }) {
|
|
|
9643
9696
|
if (ranges.some((range, index)=>index !== selectedIndex && range.name.trim().toLowerCase() === name.toLowerCase())) return void setError('当前工作表中已经存在这个区域名称。');
|
|
9644
9697
|
if (editableRangeCellCount(parsed) > MAX_EDITABLE_RANGE_CELLS) return void setError('一次最多可设置 100,000 个可编辑单元格。');
|
|
9645
9698
|
const maximumRow = Math.max(1, sheet.row ?? sheet.data?.length ?? 1) - 1;
|
|
9646
|
-
const maximumColumn = Math.max(1, sheet.column ??
|
|
9699
|
+
const maximumColumn = Math.max(1, sheet.column ?? sparseMatrixColumnCount(sheet.data)) - 1;
|
|
9647
9700
|
if (parsed.some((range)=>range.row[1] > maximumRow || range.column[1] > maximumColumn)) return void setError(`范围必须位于当前工作表的 ${maximumRow + 1} 行 × ${maximumColumn + 1} 列以内。`);
|
|
9648
9701
|
const index = selectedIndex ?? ranges.length;
|
|
9649
9702
|
updateSheet(withEditableRange(sheet, selectedIndex, {
|
|
@@ -10682,12 +10735,9 @@ function sparseSpreadsheetCells(sheet, maximumCells) {
|
|
|
10682
10735
|
};
|
|
10683
10736
|
if (sheet.data) {
|
|
10684
10737
|
if (sheet.data.length > OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) return null;
|
|
10685
|
-
for(
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
if (values.length > 16384) return null;
|
|
10689
|
-
for(let column = 0; column < values.length; column += 1)if (!appendCell(values[column], row, column)) return null;
|
|
10690
|
-
}
|
|
10738
|
+
for (const [row, values] of sparseArrayEntries(sheet.data)){
|
|
10739
|
+
if (values.length > 16384) return null;
|
|
10740
|
+
for (const [column, cell] of sparseArrayEntries(values))if (!appendCell(cell, row, column)) return null;
|
|
10691
10741
|
}
|
|
10692
10742
|
} else for (const entry of sheet.celldata ?? [])if (!appendCell(entry.v, entry.r, entry.c)) return null;
|
|
10693
10743
|
return cells.sort((left, right)=>left.row - right.row || left.column - right.column);
|
|
@@ -11316,9 +11366,7 @@ function spreadsheetCellReader(sheet) {
|
|
|
11316
11366
|
}
|
|
11317
11367
|
function spreadsheetUsedBounds(sheet) {
|
|
11318
11368
|
let lastRow = Math.max((sheet.data?.length ?? 1) - 1, 0);
|
|
11319
|
-
let lastColumn = Math.max(
|
|
11320
|
-
0
|
|
11321
|
-
]);
|
|
11369
|
+
let lastColumn = Math.max(sparseMatrixColumnCount(sheet.data) - 1, 0);
|
|
11322
11370
|
for (const cell of sheet.celldata ?? []){
|
|
11323
11371
|
lastRow = Math.max(lastRow, cell.r);
|
|
11324
11372
|
lastColumn = Math.max(lastColumn, cell.c);
|
|
@@ -11940,9 +11988,7 @@ function spreadsheetFormatPainterSheetBounds(sheet, target, pattern) {
|
|
|
11940
11988
|
const requestedColumnCount = Math.max(target.column[0], target.column[1]) + pattern.columnCount;
|
|
11941
11989
|
return {
|
|
11942
11990
|
rowCount: positiveInteger(sheet.row) ?? Math.max(sheet.data?.length ?? 0, requestedRowCount),
|
|
11943
|
-
columnCount: positiveInteger(sheet.column) ?? Math.max(
|
|
11944
|
-
0
|
|
11945
|
-
], requestedColumnCount)
|
|
11991
|
+
columnCount: positiveInteger(sheet.column) ?? Math.max(sparseMatrixColumnCount(sheet.data), requestedColumnCount)
|
|
11946
11992
|
};
|
|
11947
11993
|
}
|
|
11948
11994
|
function positiveInteger(value) {
|
|
@@ -12035,6 +12081,7 @@ function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
|
12035
12081
|
const sessionRef = useRef(session);
|
|
12036
12082
|
if (sessionRef.current !== session) throw new Error('SpreadsheetEditor collaboration sessions cannot be replaced while mounted. Remount the editor for another shared workbook.');
|
|
12037
12083
|
const viewStateRef = useRef(spreadsheetCollaborationViewState(initialContent));
|
|
12084
|
+
const [derivedOrigin] = useState(()=>session.createOrigin('system', 'spreadsheet-calculation'));
|
|
12038
12085
|
const [content, setContent] = useState(()=>spreadsheetContentWithCollaborationViewState(readWorkOfficeSpreadsheetCollaboration(session), viewStateRef.current));
|
|
12039
12086
|
const contentRef = useRef(content);
|
|
12040
12087
|
const bindingRef = useRef(void 0);
|
|
@@ -12042,15 +12089,15 @@ function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
|
12042
12089
|
const onChangeRef = useRef(onChange);
|
|
12043
12090
|
onChangeRef.current = onChange;
|
|
12044
12091
|
contentRef.current = content;
|
|
12092
|
+
const project = useCallback((sharedContent)=>{
|
|
12093
|
+
const projected = spreadsheetContentWithCollaborationViewState(sharedContent, viewStateRef.current);
|
|
12094
|
+
contentRef.current = projected;
|
|
12095
|
+
setContent(projected);
|
|
12096
|
+
return projected;
|
|
12097
|
+
}, []);
|
|
12045
12098
|
useEffect(()=>{
|
|
12046
12099
|
const binding = createWorkOfficeSpreadsheetCollaborationBinding(session);
|
|
12047
12100
|
bindingRef.current = binding;
|
|
12048
|
-
const project = (sharedContent)=>{
|
|
12049
|
-
const projected = spreadsheetContentWithCollaborationViewState(sharedContent, viewStateRef.current);
|
|
12050
|
-
contentRef.current = projected;
|
|
12051
|
-
setContent(projected);
|
|
12052
|
-
return projected;
|
|
12053
|
-
};
|
|
12054
12101
|
const unsubscribeContent = binding.subscribe(({ content: next })=>{
|
|
12055
12102
|
onChangeRef.current(project(next));
|
|
12056
12103
|
});
|
|
@@ -12069,11 +12116,12 @@ function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
|
12069
12116
|
binding.destroy();
|
|
12070
12117
|
};
|
|
12071
12118
|
}, [
|
|
12119
|
+
project,
|
|
12072
12120
|
session
|
|
12073
12121
|
]);
|
|
12074
12122
|
const commit = useCallback((next)=>{
|
|
12075
|
-
updateSpreadsheetCollaborationViewState(viewStateRef.current, next);
|
|
12076
12123
|
const previous = contentRef.current;
|
|
12124
|
+
updateSpreadsheetCollaborationViewStateForContentChange(viewStateRef.current, previous, next);
|
|
12077
12125
|
const binding = bindingRef.current;
|
|
12078
12126
|
if (binding?.replace(previous, next)) {
|
|
12079
12127
|
contentRef.current = spreadsheetContentWithCollaborationViewState(binding.content(), viewStateRef.current);
|
|
@@ -12083,17 +12131,42 @@ function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
|
12083
12131
|
contentRef.current = projected;
|
|
12084
12132
|
setContent(projected);
|
|
12085
12133
|
}, []);
|
|
12134
|
+
const commitDerived = useCallback((next)=>{
|
|
12135
|
+
const previous = contentRef.current;
|
|
12136
|
+
const binding = bindingRef.current;
|
|
12137
|
+
if (binding && replaceWorkOfficeSpreadsheetCollaboration(session, previous, next, derivedOrigin)) {
|
|
12138
|
+
contentRef.current = spreadsheetContentWithCollaborationViewState(binding.content(), viewStateRef.current);
|
|
12139
|
+
return;
|
|
12140
|
+
}
|
|
12141
|
+
project(binding?.content() ?? previous);
|
|
12142
|
+
}, [
|
|
12143
|
+
derivedOrigin,
|
|
12144
|
+
project,
|
|
12145
|
+
session
|
|
12146
|
+
]);
|
|
12086
12147
|
const view = useMemo(()=>({
|
|
12087
12148
|
activateSheet: (sheetId)=>{
|
|
12149
|
+
const sharedContent = bindingRef.current?.content() ?? contentRef.current;
|
|
12150
|
+
const sheet = sharedContent.sheets.find((candidate)=>candidate.id === sheetId && 1 !== candidate.hide);
|
|
12151
|
+
if (!sheet) return false;
|
|
12152
|
+
if (viewStateRef.current.activeSheetId === sheetId) return true;
|
|
12088
12153
|
viewStateRef.current.activeSheetId = sheetId;
|
|
12154
|
+
project(sharedContent);
|
|
12155
|
+
return true;
|
|
12089
12156
|
},
|
|
12090
12157
|
select: (sheetId, selection)=>{
|
|
12091
12158
|
viewStateRef.current.selections.set(sheetId, finiteSpreadsheetSelection(selection));
|
|
12092
12159
|
},
|
|
12093
12160
|
setZoom: (sheetId, zoomRatio)=>{
|
|
12161
|
+
const sharedContent = bindingRef.current?.content() ?? contentRef.current;
|
|
12162
|
+
if (!sharedContent.sheets.some((sheet)=>sheet.id === sheetId)) return;
|
|
12163
|
+
if (viewStateRef.current.zoomBySheet.get(sheetId) === zoomRatio) return;
|
|
12094
12164
|
viewStateRef.current.zoomBySheet.set(sheetId, zoomRatio);
|
|
12165
|
+
project(sharedContent);
|
|
12095
12166
|
}
|
|
12096
|
-
}), [
|
|
12167
|
+
}), [
|
|
12168
|
+
project
|
|
12169
|
+
]);
|
|
12097
12170
|
const history = useMemo(()=>({
|
|
12098
12171
|
canRedo: bindingRef.current?.canRedo() ?? false,
|
|
12099
12172
|
canUndo: bindingRef.current?.canUndo() ?? false,
|
|
@@ -12106,6 +12179,7 @@ function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
|
12106
12179
|
content,
|
|
12107
12180
|
history,
|
|
12108
12181
|
onChange: commit,
|
|
12182
|
+
onDerivedChange: commitDerived,
|
|
12109
12183
|
readOnly: 'edit' !== session.mode,
|
|
12110
12184
|
view
|
|
12111
12185
|
};
|
|
@@ -12125,16 +12199,21 @@ function spreadsheetCollaborationViewState(content) {
|
|
|
12125
12199
|
zoomBySheet
|
|
12126
12200
|
};
|
|
12127
12201
|
}
|
|
12128
|
-
function
|
|
12129
|
-
pruneSpreadsheetCollaborationViewState(view,
|
|
12130
|
-
|
|
12202
|
+
function updateSpreadsheetCollaborationViewStateForContentChange(view, previous, next) {
|
|
12203
|
+
pruneSpreadsheetCollaborationViewState(view, next);
|
|
12204
|
+
if (!spreadsheetSheetVisibilityChanged(previous, next)) return;
|
|
12205
|
+
const active = next.sheets.find((sheet)=>1 === sheet.status && 1 !== sheet.hide);
|
|
12131
12206
|
if (active?.id) view.activeSheetId = active.id;
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12207
|
+
}
|
|
12208
|
+
function spreadsheetSheetVisibilityChanged(previous, next) {
|
|
12209
|
+
if (previous.sheets.length !== next.sheets.length) return true;
|
|
12210
|
+
const previousById = new Map(previous.sheets.flatMap((sheet)=>sheet.id ? [
|
|
12211
|
+
[
|
|
12212
|
+
sheet.id,
|
|
12213
|
+
sheet.hide
|
|
12214
|
+
]
|
|
12215
|
+
] : []));
|
|
12216
|
+
return next.sheets.some((sheet)=>!sheet.id || !previousById.has(sheet.id) || previousById.get(sheet.id) !== sheet.hide);
|
|
12138
12217
|
}
|
|
12139
12218
|
function spreadsheetContentWithCollaborationViewState(content, view) {
|
|
12140
12219
|
pruneSpreadsheetCollaborationViewState(view, content);
|
|
@@ -12194,10 +12273,11 @@ function CollaborativeSpreadsheetEditor(props) {
|
|
|
12194
12273
|
collaborationHistory: shared.history,
|
|
12195
12274
|
collaborationView: shared.view,
|
|
12196
12275
|
onChange: shared.onChange,
|
|
12276
|
+
onDerivedChange: shared.onDerivedChange,
|
|
12197
12277
|
preview: props.preview || shared.readOnly
|
|
12198
12278
|
});
|
|
12199
12279
|
}
|
|
12200
|
-
function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHistory, collaborationView, kernelWasmUrl, preview, saveStatus = '已自动保存', fileActions, onChange, onAgentRequest }) {
|
|
12280
|
+
function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHistory, collaborationView, kernelWasmUrl, preview, saveStatus = '已自动保存', fileActions, onChange, onDerivedChange, onAgentRequest }) {
|
|
12201
12281
|
const materializedContent = useMemo(()=>refreshSpreadsheetPivotTables(content), [
|
|
12202
12282
|
content
|
|
12203
12283
|
]);
|
|
@@ -12396,19 +12476,24 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
12396
12476
|
const workbookSheetsRef = useRef(workbookSheets);
|
|
12397
12477
|
workbookSheetsRef.current = displayedWorkbookSheets;
|
|
12398
12478
|
const handleWorkbookChange = useCallback((sheets)=>{
|
|
12399
|
-
|
|
12479
|
+
const controlledSheets = spreadsheetSheetsFromFortune(sheets, contentRef.current.sheets);
|
|
12480
|
+
const matchesRenderedWorkbook = sameSpreadsheetWorkbookState(controlledSheets, workbookSheetsRef.current);
|
|
12481
|
+
if (ignoreChangeDuringExternalSync(matchesRenderedWorkbook)) return void takeWorkbookOperations();
|
|
12400
12482
|
const operations = takeWorkbookOperations();
|
|
12401
|
-
|
|
12402
|
-
|
|
12483
|
+
const hasPendingResultPatches = calculation.hasPendingResultPatches();
|
|
12484
|
+
if (previewRef.current || matchesRenderedWorkbook && !hasPendingResultPatches) return;
|
|
12485
|
+
const withCharts = reconcileSpreadsheetChartPreviews(contentRef.current, controlledSheets);
|
|
12403
12486
|
const next = reconcileSpreadsheetPivots(contentRef.current, withCharts.sheets);
|
|
12404
12487
|
contentRef.current = next;
|
|
12405
12488
|
acceptWorkbookContent(next);
|
|
12406
12489
|
calculation.synchronizeWorkbook(next, operations);
|
|
12407
|
-
|
|
12490
|
+
if (matchesRenderedWorkbook && onDerivedChange) onDerivedChange(next);
|
|
12491
|
+
else spreadsheetCommandsRef.current?.setSpreadsheetContent(next);
|
|
12408
12492
|
}, [
|
|
12409
12493
|
acceptWorkbookContent,
|
|
12410
12494
|
calculation,
|
|
12411
12495
|
ignoreChangeDuringExternalSync,
|
|
12496
|
+
onDerivedChange,
|
|
12412
12497
|
takeWorkbookOperations
|
|
12413
12498
|
]);
|
|
12414
12499
|
const handleWorkbookOperations = useCallback((operations)=>{
|
|
@@ -12514,14 +12599,14 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
12514
12599
|
pasteSpreadsheetSelection(browserSpreadsheetClipboard, commands.pasteCells);
|
|
12515
12600
|
return true;
|
|
12516
12601
|
};
|
|
12517
|
-
const
|
|
12518
|
-
if (!previewRef.current) return false;
|
|
12602
|
+
const activateLocalSpreadsheetSheet = useCallback((sheetId)=>{
|
|
12603
|
+
if (!previewRef.current && !collaborationView) return false;
|
|
12519
12604
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetId && 1 !== candidate.hide);
|
|
12520
12605
|
if (!sheet) return false;
|
|
12521
12606
|
activeSheetIdRef.current = sheetId;
|
|
12522
|
-
collaborationView
|
|
12607
|
+
if (collaborationView && !collaborationView.activateSheet(sheetId)) return false;
|
|
12523
12608
|
setSelectionState(null);
|
|
12524
|
-
setPreviewActiveSheetId(sheetId);
|
|
12609
|
+
if (previewRef.current) setPreviewActiveSheetId(sheetId);
|
|
12525
12610
|
try {
|
|
12526
12611
|
workbookRef.current?.activateSheet({
|
|
12527
12612
|
id: sheetId
|
|
@@ -12564,8 +12649,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
12564
12649
|
selection: selectionState,
|
|
12565
12650
|
targetSheetId: toolbarSheetId,
|
|
12566
12651
|
toolbarCell,
|
|
12567
|
-
view: preview ? {
|
|
12568
|
-
activateSheet:
|
|
12652
|
+
view: preview || collaborationView ? {
|
|
12653
|
+
activateSheet: activateLocalSpreadsheetSheet
|
|
12569
12654
|
} : null,
|
|
12570
12655
|
workbook: workbookInstance
|
|
12571
12656
|
}, spreadsheetExtensions);
|
|
@@ -2777,8 +2777,8 @@ function work_docx_table_sizing_import_textNodes(root) {
|
|
|
2777
2777
|
}
|
|
2778
2778
|
const work_docx_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
2779
2779
|
const work_docx_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
|
2780
|
-
async function prepareDocxImport(buffer) {
|
|
2781
|
-
const archive = await OoxmlPackage.load(buffer);
|
|
2780
|
+
async function prepareDocxImport(buffer, sourcePackage) {
|
|
2781
|
+
const archive = sourcePackage ?? await OoxmlPackage.load(buffer);
|
|
2782
2782
|
const bibliography = (await readDocxBibliography(archive)).bibliography;
|
|
2783
2783
|
const fallback = documentInitialSectionLayout({
|
|
2784
2784
|
type: 'document',
|
|
@@ -1626,14 +1626,15 @@ async function diagnoseXlsxPivots(archive) {
|
|
|
1626
1626
|
});
|
|
1627
1627
|
return issues;
|
|
1628
1628
|
}
|
|
1629
|
-
async function analyzeDocxCompatibility(file, messages) {
|
|
1629
|
+
async function analyzeDocxCompatibility(file, messages, sourcePackage) {
|
|
1630
1630
|
const issues = [
|
|
1631
1631
|
work_office_diagnostics_issue('docx.page-layout', 'Page layout', 'Per-section paper size, orientation, exact native page margins, one-to-six equal or custom-width columns, section breaks, and explicit page breaks are preserved; exact pagination and line wrapping may normalize.'),
|
|
1632
1632
|
work_office_diagnostics_issue('docx.package-state', 'OOXML package state', 'Source-backed export retains safe source-only parts byte-for-byte and reconnects their content types and relationships. Passive relationship-free extensions in settings XML, uniquely matched style or numbering identities, stable picture drawings, unchanged native-identity paragraphs, stable table, row, or cell scopes, and uniquely matched footnote, endnote, comment, or comment-thread records are preserved against the final package graph. Text-stable direct, supported-hyperlink-wrapped, and eligible static-content-control note and comment runs retain paragraph, table, wrapper, run, and run-property metadata; native note tables and DrawingML pictures remain editable, note image relationships and media targets are repaired and validated, bounded structured OMML equations remain atomically updateable in supported Word stories, uniquely matched table-bearing rich-text controls are reconstructed, safe web, mail, and internal note/comment links are rebound to collision-free final relationship IDs, and content-control ID collisions are rewritten. Native note, comment, and note-picture identities survive reorderings, comment durable IDs are rebound to regenerated paragraph IDs, and eligible source font-table metadata is retained. Generated Word semantics remain authoritative; source-only, changed-text or table structure, malformed, duplicate or cross-kind, active, unsupported wrappers, mixed-semantic, unsafe relationship-bound, legacy VML, non-picture drawings, or unsupported rich content may normalize.', 'info')
|
|
1633
1633
|
];
|
|
1634
1634
|
for (const message of messages)issues.push(work_office_diagnostics_issue(`docx.converter.${message.type}`, 'Document conversion', message.message, 'error' === message.type ? 'error' : 'warning'));
|
|
1635
1635
|
try {
|
|
1636
|
-
const archive = await OoxmlPackage.load(await file.arrayBuffer());
|
|
1636
|
+
const archive = void 0 === sourcePackage ? await OoxmlPackage.load(await file.arrayBuffer()) : sourcePackage;
|
|
1637
|
+
if (!archive) throw new Error('The DOCX package could not be loaded.');
|
|
1637
1638
|
const packagePaths = archive.paths('');
|
|
1638
1639
|
const normalizedPackagePaths = packagePaths.map((path)=>path.toLowerCase());
|
|
1639
1640
|
const document = archive.has('word/document.xml') ? await archive.xml('word/document.xml') : null;
|
|
@@ -1723,7 +1724,7 @@ async function analyzeDocxCompatibility(file, messages) {
|
|
|
1723
1724
|
}
|
|
1724
1725
|
return report(file, 'DOCX', issues);
|
|
1725
1726
|
}
|
|
1726
|
-
async function analyzeSpreadsheetCompatibility(file, extension, workbook) {
|
|
1727
|
+
async function analyzeSpreadsheetCompatibility(file, extension, workbook, sourcePackage) {
|
|
1727
1728
|
if ('csv' === extension) return null;
|
|
1728
1729
|
const sourceFormat = extension.toUpperCase();
|
|
1729
1730
|
const issues = [];
|
|
@@ -1748,7 +1749,8 @@ async function analyzeSpreadsheetCompatibility(file, extension, workbook) {
|
|
|
1748
1749
|
if ((workbook.Workbook?.Sheets?.[index]?.Hidden ?? 0) > 0) issues.push(work_office_diagnostics_issue('sheet.hidden', 'Hidden worksheets', 'Hidden worksheet state is preserved but can be changed by the editor.', 'info', name));
|
|
1749
1750
|
}
|
|
1750
1751
|
if ('xlsx' === extension) try {
|
|
1751
|
-
const archive = await OoxmlPackage.load(await file.arrayBuffer());
|
|
1752
|
+
const archive = void 0 === sourcePackage ? await OoxmlPackage.load(await file.arrayBuffer()) : sourcePackage;
|
|
1753
|
+
if (!archive) throw new Error('The XLSX package could not be loaded.');
|
|
1752
1754
|
await inspectXlsxPackage(archive, issues);
|
|
1753
1755
|
} catch {
|
|
1754
1756
|
issues.push(work_office_diagnostics_issue('xlsx.inspect', 'Package inspection', 'Some XLSX features could not be inspected before conversion.'));
|
|
@@ -478,8 +478,8 @@ const EMU_PER_INCH = 914400;
|
|
|
478
478
|
const DEFAULT_SLIDE_WIDTH = 13.333;
|
|
479
479
|
const DEFAULT_SLIDE_HEIGHT = 7.5;
|
|
480
480
|
const MAX_EMBEDDED_IMAGE_BYTES = 11534336;
|
|
481
|
-
async function importPptxPresentation(file) {
|
|
482
|
-
const archive = await OoxmlPackage.load(await file.arrayBuffer());
|
|
481
|
+
async function importPptxPresentation(file, sourceBytes) {
|
|
482
|
+
const archive = await OoxmlPackage.load(sourceBytes ?? await file.arrayBuffer());
|
|
483
483
|
if (!archive.has('ppt/presentation.xml')) throw new Error('The selected file is not a valid PPTX presentation.');
|
|
484
484
|
const presentation = await archive.xml('ppt/presentation.xml');
|
|
485
485
|
const presentationRelationships = await archive.relationships('ppt/presentation.xml');
|