@tita-agent/dsh-data-table 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +172 -2
- package/cordis.patch.yml +7 -0
- package/lib/client.js +16766 -0
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/types/audit.d.ts +42 -0
- package/lib/types/audit.js +39 -0
- package/lib/types/client/ProjectImportMenu.d.ts +30 -0
- package/lib/types/client/ProjectImportMenu.js +70 -0
- package/lib/types/client/SheetPanel.d.ts +33 -0
- package/lib/types/client/SheetPanel.js +1766 -0
- package/lib/types/client/SheetToggle.d.ts +18 -0
- package/lib/types/client/SheetToggle.js +26 -0
- package/lib/types/client/index.d.ts +15 -0
- package/lib/types/client/index.js +110 -0
- package/lib/types/client/persistence/changes.d.ts +15 -0
- package/lib/types/client/persistence/changes.js +51 -0
- package/lib/types/client/persistence/ids.d.ts +34 -0
- package/lib/types/client/persistence/ids.js +48 -0
- package/lib/types/client/persistence/merge.d.ts +35 -0
- package/lib/types/client/persistence/merge.js +362 -0
- package/lib/types/client/store.d.ts +61 -0
- package/lib/types/client/store.js +152 -0
- package/lib/types/client/surface-context.d.ts +27 -0
- package/lib/types/client/surface-context.js +104 -0
- package/lib/types/client/surface-control.d.ts +2 -0
- package/lib/types/client/surface-control.js +12 -0
- package/lib/types/client/transport/workbookApi.d.ts +159 -0
- package/lib/types/client/transport/workbookApi.js +246 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.d.ts +5 -0
- package/lib/types/client/univer/StandaloneWorkbookPage.js +7 -0
- package/lib/types/client/univer/WorkbookCanvas.d.ts +40 -0
- package/lib/types/client/univer/WorkbookCanvas.js +87 -0
- package/lib/types/client/univer/WorkbookView.d.ts +3 -0
- package/lib/types/client/univer/WorkbookView.js +2 -0
- package/lib/types/client/univer/loader.d.ts +18 -0
- package/lib/types/client/univer/loader.js +81 -0
- package/lib/types/client/univer/standalone-entry.d.ts +1 -0
- package/lib/types/client/univer/standalone-entry.js +19 -0
- package/lib/types/client/versions/VersionChrome.d.ts +33 -0
- package/lib/types/client/versions/VersionChrome.js +21 -0
- package/lib/types/client/versions/inspect.d.ts +70 -0
- package/lib/types/client/versions/inspect.js +88 -0
- package/lib/types/client/versions/preview-decoration.d.ts +11 -0
- package/lib/types/client/versions/preview-decoration.js +54 -0
- package/lib/types/client/versions/records.d.ts +19 -0
- package/lib/types/client/versions/records.js +70 -0
- package/lib/types/client/workspace-host.d.ts +61 -0
- package/lib/types/client/workspace-host.js +124 -0
- package/lib/types/collaboration-hub.d.ts +31 -0
- package/lib/types/collaboration-hub.js +69 -0
- package/lib/types/contract/ids.d.ts +24 -0
- package/lib/types/contract/ids.js +46 -0
- package/lib/types/contract/mutations.d.ts +25 -0
- package/lib/types/contract/mutations.js +782 -0
- package/lib/types/contract/operations.d.ts +54 -0
- package/lib/types/contract/operations.js +203 -0
- package/lib/types/contract/snapshots.d.ts +176 -0
- package/lib/types/contract/snapshots.js +351 -0
- package/lib/types/contract/univer-api-catalog.d.ts +29 -0
- package/lib/types/contract/univer-api-catalog.js +264 -0
- package/lib/types/errors.d.ts +8 -0
- package/lib/types/errors.js +12 -0
- package/lib/types/http/assets-routes.d.ts +3 -0
- package/lib/types/http/assets-routes.js +169 -0
- package/lib/types/http/collaboration.d.ts +10 -0
- package/lib/types/http/collaboration.js +154 -0
- package/lib/types/http/history.d.ts +15 -0
- package/lib/types/http/history.js +134 -0
- package/lib/types/http/project-files.d.ts +79 -0
- package/lib/types/http/project-files.js +206 -0
- package/lib/types/http/project-scope.d.ts +50 -0
- package/lib/types/http/project-scope.js +52 -0
- package/lib/types/http/routes.d.ts +98 -0
- package/lib/types/http/routes.js +323 -0
- package/lib/types/http/standalone.d.ts +9 -0
- package/lib/types/http/standalone.js +31 -0
- package/lib/types/http/trunk.d.ts +10 -0
- package/lib/types/http/trunk.js +322 -0
- package/lib/types/http/worktree.d.ts +9 -0
- package/lib/types/http/worktree.js +145 -0
- package/lib/types/index.d.ts +18 -0
- package/lib/types/index.js +156 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/invariant.js +15 -0
- package/lib/types/request-params.d.ts +21 -0
- package/lib/types/request-params.js +76 -0
- package/lib/types/store/paths.d.ts +68 -0
- package/lib/types/store/paths.js +148 -0
- package/lib/types/store/project.d.ts +88 -0
- package/lib/types/store/project.js +120 -0
- package/lib/types/store/read.d.ts +110 -0
- package/lib/types/store/read.js +404 -0
- package/lib/types/store/retention.d.ts +27 -0
- package/lib/types/store/retention.js +111 -0
- package/lib/types/store/write.d.ts +22 -0
- package/lib/types/store/write.js +210 -0
- package/lib/types/tools/arguments.d.ts +40 -0
- package/lib/types/tools/arguments.js +130 -0
- package/lib/types/tools/cells.d.ts +50 -0
- package/lib/types/tools/cells.js +298 -0
- package/lib/types/tools/index.d.ts +2 -0
- package/lib/types/tools/index.js +250 -0
- package/lib/types/tools/render.d.ts +47 -0
- package/lib/types/tools/render.js +290 -0
- package/lib/types/tools/univer-api.d.ts +18 -0
- package/lib/types/tools/univer-api.js +198 -0
- package/lib/types/tools/workbook-catalog.d.ts +3 -0
- package/lib/types/tools/workbook-catalog.js +83 -0
- package/lib/types/tools/workbook-edit.d.ts +192 -0
- package/lib/types/tools/workbook-edit.js +912 -0
- package/lib/types/tools/workbook-find.d.ts +11 -0
- package/lib/types/tools/workbook-find.js +89 -0
- package/lib/types/tools/workbook-history.d.ts +2 -0
- package/lib/types/tools/workbook-history.js +59 -0
- package/lib/types/tools/workbook-read.d.ts +21 -0
- package/lib/types/tools/workbook-read.js +204 -0
- package/lib/types/types.d.ts +377 -0
- package/lib/types/types.js +34 -0
- package/lib/types/univer/apply-operation.d.ts +14 -0
- package/lib/types/univer/apply-operation.js +398 -0
- package/lib/types/univer/chunk.d.ts +68 -0
- package/lib/types/univer/chunk.js +16 -0
- package/lib/types/univer/decoration.d.ts +34 -0
- package/lib/types/univer/decoration.js +88 -0
- package/lib/types/univer/diagnostics.d.ts +31 -0
- package/lib/types/univer/diagnostics.js +141 -0
- package/lib/types/univer/engine.d.ts +33 -0
- package/lib/types/univer/engine.js +338 -0
- package/lib/types/univer/entry.d.ts +8 -0
- package/lib/types/univer/entry.js +11 -0
- package/lib/types/univer/facade.d.ts +107 -0
- package/lib/types/univer/facade.js +1 -0
- package/lib/types/univer/fonts.d.ts +202 -0
- package/lib/types/univer/fonts.js +140 -0
- package/lib/types/univer/plugins/collaboration.d.ts +23 -0
- package/lib/types/univer/plugins/collaboration.js +47 -0
- package/lib/types/univer/plugins/export.d.ts +39 -0
- package/lib/types/univer/plugins/export.js +246 -0
- package/lib/types/univer/plugins/history.d.ts +24 -0
- package/lib/types/univer/plugins/history.js +50 -0
- package/lib/types/univer/plugins/version.d.ts +13 -0
- package/lib/types/univer/plugins/version.js +13 -0
- package/lib/types/version/diff.d.ts +36 -0
- package/lib/types/version/diff.js +156 -0
- package/lib/types/version/grouping.d.ts +7 -0
- package/lib/types/version/grouping.js +94 -0
- package/lib/types/version/records.d.ts +17 -0
- package/lib/types/version/records.js +102 -0
- package/lib/types/version/session.d.ts +36 -0
- package/lib/types/version/session.js +89 -0
- package/lib/types/version/summary.d.ts +24 -0
- package/lib/types/version/summary.js +111 -0
- package/lib/types/workbook-manager.d.ts +191 -0
- package/lib/types/workbook-manager.js +935 -0
- package/lib/types/xlsx-export-worker.d.ts +5 -0
- package/lib/types/xlsx-export-worker.js +24 -0
- package/lib/types/xlsx-export.d.ts +21 -0
- package/lib/types/xlsx-export.js +371 -0
- package/lib/types/xlsx-import-worker.d.ts +1 -0
- package/lib/types/xlsx-import-worker.js +19 -0
- package/lib/univer-client.js +690 -0
- package/lib/workbook-page.js +23826 -0
- package/lib/xlsx-export-worker.js +104 -0
- package/lib/xlsx-import-worker.js +46 -0
- package/package.json +106 -3
- package/src/audit.ts +58 -0
- package/src/client/ProjectImportMenu.tsx +100 -0
- package/src/client/SheetPanel.module.css +1578 -0
- package/src/client/SheetPanel.tsx +1934 -0
- package/src/client/SheetToggle.module.css +73 -0
- package/src/client/SheetToggle.tsx +65 -0
- package/src/client/contract.d.ts +19 -0
- package/src/client/index.ts +131 -0
- package/src/client/persistence/changes.ts +58 -0
- package/src/client/persistence/ids.ts +60 -0
- package/src/client/persistence/merge.ts +392 -0
- package/src/client/store.ts +188 -0
- package/src/client/surface-context.ts +123 -0
- package/src/client/surface-control.ts +13 -0
- package/src/client/transport/workbookApi.ts +355 -0
- package/src/client/univer/SheetView.module.css +110 -0
- package/src/client/univer/StandaloneWorkbookPage.module.css +8 -0
- package/src/client/univer/StandaloneWorkbookPage.tsx +15 -0
- package/src/client/univer/WorkbookCanvas.tsx +128 -0
- package/src/client/univer/WorkbookView.module.css +30 -0
- package/src/client/univer/WorkbookView.tsx +3 -0
- package/src/client/univer/loader.ts +90 -0
- package/src/client/univer/react-dom-client.d.ts +10 -0
- package/src/client/univer/standalone-entry.tsx +19 -0
- package/src/client/univer/standalone.css +12 -0
- package/src/client/univer/univer-locales.d.ts +89 -0
- package/src/client/univer/univer-modules.d.ts +26 -0
- package/src/client/versions/VersionChrome.tsx +114 -0
- package/src/client/versions/inspect.ts +138 -0
- package/src/client/versions/preview-decoration.ts +54 -0
- package/src/client/versions/records.ts +78 -0
- package/src/client/workspace-host.ts +147 -0
- package/src/collaboration-hub.ts +83 -0
- package/src/contract/ids.ts +50 -0
- package/src/contract/mutations.ts +791 -0
- package/src/contract/operations.ts +221 -0
- package/src/contract/snapshots.ts +383 -0
- package/src/contract/univer-api-catalog.ts +289 -0
- package/src/css-modules.d.ts +6 -0
- package/src/errors.ts +25 -0
- package/src/http/assets-routes.ts +177 -0
- package/src/http/collaboration.ts +144 -0
- package/src/http/history.ts +151 -0
- package/src/http/project-files.ts +227 -0
- package/src/http/project-scope.ts +77 -0
- package/src/http/routes.ts +364 -0
- package/src/http/standalone.ts +32 -0
- package/src/http/trunk.ts +322 -0
- package/src/http/worktree.ts +119 -0
- package/src/index.ts +165 -0
- package/src/invariant.ts +17 -0
- package/src/request-params.ts +92 -0
- package/src/store/paths.ts +165 -0
- package/src/store/project.ts +137 -0
- package/src/store/read.ts +454 -0
- package/src/store/retention.ts +106 -0
- package/src/store/write.ts +230 -0
- package/src/tools/arguments.ts +128 -0
- package/src/tools/cells.ts +298 -0
- package/src/tools/index.ts +274 -0
- package/src/tools/render.ts +301 -0
- package/src/tools/univer-api.ts +243 -0
- package/src/tools/workbook-catalog.ts +94 -0
- package/src/tools/workbook-edit.ts +987 -0
- package/src/tools/workbook-find.ts +80 -0
- package/src/tools/workbook-history.ts +63 -0
- package/src/tools/workbook-read.ts +210 -0
- package/src/types.ts +432 -0
- package/src/univer/apply-operation.ts +369 -0
- package/src/univer/chunk.ts +77 -0
- package/src/univer/decoration.ts +111 -0
- package/src/univer/diagnostics.ts +136 -0
- package/src/univer/engine.ts +370 -0
- package/src/univer/entry.ts +14 -0
- package/src/univer/facade.ts +91 -0
- package/src/univer/fonts.ts +148 -0
- package/src/univer/overrides.css +33 -0
- package/src/univer/plugins/collaboration.ts +47 -0
- package/src/univer/plugins/export.ts +236 -0
- package/src/univer/plugins/history.ts +49 -0
- package/src/univer/plugins/version.ts +13 -0
- package/src/version/diff.ts +169 -0
- package/src/version/grouping.ts +96 -0
- package/src/version/records.ts +113 -0
- package/src/version/session.ts +90 -0
- package/src/version/summary.ts +117 -0
- package/src/workbook-manager.ts +1111 -0
- package/src/xlsx-export-worker.ts +34 -0
- package/src/xlsx-export.ts +373 -0
- package/src/xlsx-import-worker.ts +30 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live-canvas diagnostics and command mapping (docs/issue/0022 P4).
|
|
3
|
+
*
|
|
4
|
+
* Two jobs that both start from a Univer command: turning it into the small DSH
|
|
5
|
+
* change contract the Host persists, and leaving a probe behind so a live
|
|
6
|
+
* workbook can be inspected from the console (`__dshLastCellMutation`). They sit
|
|
7
|
+
* together because both are "what did Univer just do", and neither decides what
|
|
8
|
+
* to persist — `contract/operations.ts` decides that.
|
|
9
|
+
*/
|
|
10
|
+
import { normalizeCellFormula } from '../contract/snapshots.ts'
|
|
11
|
+
import type { WorkbookCellUpdate, WorkbookLocalChange, WorkbookPresencePayload } from '../types.ts'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Diagnostic seam for the incremental-save mapping (PRD v3.1 follow-up).
|
|
15
|
+
*
|
|
16
|
+
* Cell edits that cannot be expressed as a plain value fall back to a whole
|
|
17
|
+
* snapshot save, which is correct but ~230 KB per edit. This records why the
|
|
18
|
+
* last such mutation was not mapped, so the reason can be read from the
|
|
19
|
+
* browser console instead of guessed:
|
|
20
|
+
*
|
|
21
|
+
* __dshLastCellMutation // { commandId, mapped, reason?, keys? }
|
|
22
|
+
*/
|
|
23
|
+
let lastCellMutationNote: { reason?: string; keys?: string[] } | undefined
|
|
24
|
+
|
|
25
|
+
/** Why the current mutation could not become an incremental cell change. */
|
|
26
|
+
export function noteCellMutation(_commandId: string, mapped: boolean, detail: { reason?: string; keys?: string[] } = {}): void {
|
|
27
|
+
lastCellMutationNote = mapped ? undefined : detail
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Publish the outcome of one persisted mutation. This runs for *every*
|
|
32
|
+
* mutation the workbook persists, so a command id we do not map is still
|
|
33
|
+
* visible instead of leaving the probe undefined:
|
|
34
|
+
*
|
|
35
|
+
* __dshLastCellMutation // { commandId, mapped, reason?, keys? }
|
|
36
|
+
*/
|
|
37
|
+
export function publishMutationAttempt(commandId: string, mapped: boolean): void {
|
|
38
|
+
if (typeof window === 'undefined') return
|
|
39
|
+
;(window as unknown as { __dshLastCellMutation?: unknown }).__dshLastCellMutation = {
|
|
40
|
+
at: new Date().toISOString(),
|
|
41
|
+
commandId,
|
|
42
|
+
mapped,
|
|
43
|
+
...(mapped ? {} : (lastCellMutationNote ?? { reason: 'command-not-mapped' })),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function cellKeysOf(cellValue: unknown): string[] {
|
|
48
|
+
if (typeof cellValue !== 'object' || cellValue === null) return []
|
|
49
|
+
const firstRow = Object.values(cellValue as Record<string, unknown>)[0]
|
|
50
|
+
if (typeof firstRow !== 'object' || firstRow === null) return []
|
|
51
|
+
const firstCell = Object.values(firstRow as Record<string, unknown>)[0]
|
|
52
|
+
return typeof firstCell === 'object' && firstCell !== null ? Object.keys(firstCell) : []
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Convert Univer's sparse set-range-values mutation into the small DSH edit
|
|
57
|
+
* contract. Formatting, pasted rich objects, and structural commands return
|
|
58
|
+
* undefined so the browser deliberately falls back to a full snapshot save.
|
|
59
|
+
*/
|
|
60
|
+
export function toLocalCellChange(commandInfo: { id: string; params?: unknown }): WorkbookLocalChange | undefined {
|
|
61
|
+
if (commandInfo.id !== 'sheet.mutation.set-range-values') return undefined
|
|
62
|
+
if (typeof commandInfo.params !== 'object' || commandInfo.params === null) {
|
|
63
|
+
noteCellMutation(commandInfo.id, false, { reason: 'params-missing' })
|
|
64
|
+
return undefined
|
|
65
|
+
}
|
|
66
|
+
const params = commandInfo.params as Record<string, unknown>
|
|
67
|
+
if (typeof params.subUnitId !== 'string' || typeof params.cellValue !== 'object' || params.cellValue === null) {
|
|
68
|
+
noteCellMutation(commandInfo.id, false, { reason: 'cellValue-missing', keys: cellKeysOf(params.cellValue) })
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
const cells: WorkbookCellUpdate[] = []
|
|
72
|
+
const rows = params.cellValue as Record<string, unknown>
|
|
73
|
+
for (const [rowKey, rowValue] of Object.entries(rows)) {
|
|
74
|
+
const row = Number(rowKey)
|
|
75
|
+
if (!Number.isInteger(row) || typeof rowValue !== 'object' || rowValue === null) return undefined
|
|
76
|
+
for (const [columnKey, cellValue] of Object.entries(rowValue as Record<string, unknown>)) {
|
|
77
|
+
const column = Number(columnKey)
|
|
78
|
+
if (!Number.isInteger(column)) {
|
|
79
|
+
noteCellMutation(commandInfo.id, false, { reason: 'bad-column-key', keys: cellKeysOf(params.cellValue) })
|
|
80
|
+
return undefined
|
|
81
|
+
}
|
|
82
|
+
if (cellValue === null) {
|
|
83
|
+
cells.push({ row, column, value: null })
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
if (typeof cellValue !== 'object' || Array.isArray(cellValue)) {
|
|
87
|
+
noteCellMutation(commandInfo.id, false, { reason: 'cell-not-object', keys: cellKeysOf(params.cellValue) })
|
|
88
|
+
return undefined
|
|
89
|
+
}
|
|
90
|
+
const cell = cellValue as Record<string, unknown>
|
|
91
|
+
const unsupportedKeys = Object.keys(cell).filter(key => !['v', 'f', 't'].includes(key))
|
|
92
|
+
if (unsupportedKeys.length > 0) {
|
|
93
|
+
noteCellMutation(commandInfo.id, false, { reason: 'unsupported-cell-keys', keys: Object.keys(cell) })
|
|
94
|
+
return undefined
|
|
95
|
+
}
|
|
96
|
+
const value = cell.v
|
|
97
|
+
if (value !== undefined && value !== null && typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') return undefined
|
|
98
|
+
const formula = normalizeCellFormula(cell.f)
|
|
99
|
+
cells.push({ row, column, value: value === undefined ? null : value, ...(formula === undefined ? {} : { formula }) })
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (cells.length === 0) {
|
|
103
|
+
noteCellMutation(commandInfo.id, false, { reason: 'no-cells', keys: cellKeysOf(params.cellValue) })
|
|
104
|
+
return undefined
|
|
105
|
+
}
|
|
106
|
+
noteCellMutation(commandInfo.id, true)
|
|
107
|
+
return { type: 'update_cells', payload: { sheetId: params.subUnitId, cells } }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Convert selection/focus commands into a compact ephemeral presence event.
|
|
111
|
+
* Unknown commands are intentionally ignored so UI internals never become
|
|
112
|
+
* durable edits or high-volume network traffic. */
|
|
113
|
+
export function toPresence(commandInfo: { id: string; params?: unknown }): WorkbookPresencePayload | undefined {
|
|
114
|
+
const commandId = commandInfo.id.toLowerCase()
|
|
115
|
+
let kind: WorkbookPresencePayload['kind'] | undefined
|
|
116
|
+
if (commandId.includes('selection') || commandId.includes('set-selections')) kind = 'selection'
|
|
117
|
+
else if (commandId.includes('activate') || commandId.includes('active') || commandId.includes('focus') || commandId.includes('current-sheet')) kind = 'active-sheet'
|
|
118
|
+
else return undefined
|
|
119
|
+
const params = typeof commandInfo.params === 'object' && commandInfo.params !== null
|
|
120
|
+
? commandInfo.params as Record<string, unknown>
|
|
121
|
+
: {}
|
|
122
|
+
const payload: Record<string, unknown> = { commandId }
|
|
123
|
+
for (const key of ['subUnitId', 'unitId', 'sheetId']) {
|
|
124
|
+
if (typeof params[key] === 'string') payload[key] = params[key]
|
|
125
|
+
}
|
|
126
|
+
const range = params.range
|
|
127
|
+
if (typeof range === 'object' && range !== null && !Array.isArray(range)) {
|
|
128
|
+
const candidate = range as Record<string, unknown>
|
|
129
|
+
const safeRange: Record<string, number> = {}
|
|
130
|
+
for (const key of ['startRow', 'startColumn', 'endRow', 'endColumn']) {
|
|
131
|
+
if (typeof candidate[key] === 'number' && Number.isFinite(candidate[key])) safeRange[key] = candidate[key] as number
|
|
132
|
+
}
|
|
133
|
+
if (Object.keys(safeRange).length > 0) payload.range = safeRange
|
|
134
|
+
}
|
|
135
|
+
return { kind, payload }
|
|
136
|
+
}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heavy Univer engine for dsh-data-table: the sheets-core preset
|
|
3
|
+
* mount plus the free feature presets (filter/sort/find-replace/conditional
|
|
4
|
+
* formatting/data validation/drawing/hyper-link/note/thread-comment/table)
|
|
5
|
+
* and the Univer-native CSV/Excel export plugin. Bundled as a self-contained IIFE chunk
|
|
6
|
+
* (`lib/univer-client.js`) served on demand by the node half — the ~16MB
|
|
7
|
+
* Univer graph never enters the boot bundle.
|
|
8
|
+
* @module dsh-data-table/univer-engine
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createUniver,
|
|
13
|
+
defaultTheme,
|
|
14
|
+
LocaleType,
|
|
15
|
+
merge,
|
|
16
|
+
UniverInstanceType,
|
|
17
|
+
} from '@univerjs/presets'
|
|
18
|
+
// The es-path values carry runtime code; the honest types live in the types tree.
|
|
19
|
+
import { UniverSheetsCorePreset } from '@univerjs/presets/lib/es/preset-sheets-core/index.js'
|
|
20
|
+
import { UniverSheetsFilterPreset } from '@univerjs/presets/lib/es/preset-sheets-filter/index.js'
|
|
21
|
+
import { UniverSheetsSortPreset } from '@univerjs/presets/lib/es/preset-sheets-sort/index.js'
|
|
22
|
+
import { UniverSheetsFindReplacePreset } from '@univerjs/presets/lib/es/preset-sheets-find-replace/index.js'
|
|
23
|
+
import { UniverSheetsConditionalFormattingPreset } from '@univerjs/presets/lib/es/preset-sheets-conditional-formatting/index.js'
|
|
24
|
+
import { UniverSheetsDataValidationPreset } from '@univerjs/presets/lib/es/preset-sheets-data-validation/index.js'
|
|
25
|
+
import { UniverSheetsDrawingPreset } from '@univerjs/presets/lib/es/preset-sheets-drawing/index.js'
|
|
26
|
+
import { UniverSheetsHyperLinkPreset } from '@univerjs/presets/lib/es/preset-sheets-hyper-link/index.js'
|
|
27
|
+
import { UniverSheetsNotePreset } from '@univerjs/presets/lib/es/preset-sheets-note/index.js'
|
|
28
|
+
import { UniverSheetsThreadCommentPreset } from '@univerjs/presets/lib/es/preset-sheets-thread-comment/index.js'
|
|
29
|
+
import { UniverSheetsTablePreset } from '@univerjs/presets/lib/es/preset-sheets-table/index.js'
|
|
30
|
+
import { UniverSheetsCrosshairHighlightPlugin } from '@univerjs/sheets-crosshair-highlight'
|
|
31
|
+
import type {
|
|
32
|
+
WorkbookDecoration,
|
|
33
|
+
WorkbookMount,
|
|
34
|
+
WorkbookMountOptions,
|
|
35
|
+
} from './chunk.ts'
|
|
36
|
+
|
|
37
|
+
// Re-exported so `univer/entry.ts` and the loader keep one name for the mount
|
|
38
|
+
// contract, which lives in `univer/chunk.ts` beside the loader side.
|
|
39
|
+
export type { WorkbookDecoration, WorkbookDecorationCell, WorkbookDecorationTone, WorkbookMount, WorkbookMountOptions } from './chunk.ts'
|
|
40
|
+
import coreZhCN from '@univerjs/presets/lib/es/preset-sheets-core/locales/zh-CN.js'
|
|
41
|
+
import coreEnUS from '@univerjs/presets/lib/es/preset-sheets-core/locales/en-US.js'
|
|
42
|
+
import filterZhCN from '@univerjs/presets/lib/es/preset-sheets-filter/locales/zh-CN.js'
|
|
43
|
+
import filterEnUS from '@univerjs/presets/lib/es/preset-sheets-filter/locales/en-US.js'
|
|
44
|
+
import sortZhCN from '@univerjs/presets/lib/es/preset-sheets-sort/locales/zh-CN.js'
|
|
45
|
+
import sortEnUS from '@univerjs/presets/lib/es/preset-sheets-sort/locales/en-US.js'
|
|
46
|
+
import findReplaceZhCN from '@univerjs/presets/lib/es/preset-sheets-find-replace/locales/zh-CN.js'
|
|
47
|
+
import findReplaceEnUS from '@univerjs/presets/lib/es/preset-sheets-find-replace/locales/en-US.js'
|
|
48
|
+
import condFmtZhCN from '@univerjs/presets/lib/es/preset-sheets-conditional-formatting/locales/zh-CN.js'
|
|
49
|
+
import condFmtEnUS from '@univerjs/presets/lib/es/preset-sheets-conditional-formatting/locales/en-US.js'
|
|
50
|
+
import dataValZhCN from '@univerjs/presets/lib/es/preset-sheets-data-validation/locales/zh-CN.js'
|
|
51
|
+
import dataValEnUS from '@univerjs/presets/lib/es/preset-sheets-data-validation/locales/en-US.js'
|
|
52
|
+
import drawingZhCN from '@univerjs/presets/lib/es/preset-sheets-drawing/locales/zh-CN.js'
|
|
53
|
+
import drawingEnUS from '@univerjs/presets/lib/es/preset-sheets-drawing/locales/en-US.js'
|
|
54
|
+
import hyperLinkZhCN from '@univerjs/presets/lib/es/preset-sheets-hyper-link/locales/zh-CN.js'
|
|
55
|
+
import hyperLinkEnUS from '@univerjs/presets/lib/es/preset-sheets-hyper-link/locales/en-US.js'
|
|
56
|
+
import noteZhCN from '@univerjs/presets/lib/es/preset-sheets-note/locales/zh-CN.js'
|
|
57
|
+
import noteEnUS from '@univerjs/presets/lib/es/preset-sheets-note/locales/en-US.js'
|
|
58
|
+
import threadZhCN from '@univerjs/presets/lib/es/preset-sheets-thread-comment/locales/zh-CN.js'
|
|
59
|
+
import threadEnUS from '@univerjs/presets/lib/es/preset-sheets-thread-comment/locales/en-US.js'
|
|
60
|
+
import tableZhCN from '@univerjs/presets/lib/es/preset-sheets-table/locales/zh-CN.js'
|
|
61
|
+
import tableEnUS from '@univerjs/presets/lib/es/preset-sheets-table/locales/en-US.js'
|
|
62
|
+
import crosshairZhCN from '@univerjs/sheets-crosshair-highlight/locale/zh-CN'
|
|
63
|
+
import crosshairEnUS from '@univerjs/sheets-crosshair-highlight/locale/en-US'
|
|
64
|
+
// Univer ships its styles as separate artifacts; without them the workbench
|
|
65
|
+
// renders unstyled (toolbar stacked vertically). The client build turns these
|
|
66
|
+
// imports into inlined style injections.
|
|
67
|
+
import '@univerjs/presets/lib/styles/preset-sheets-core.css'
|
|
68
|
+
import '@univerjs/presets/lib/styles/preset-sheets-filter.css'
|
|
69
|
+
import '@univerjs/presets/lib/styles/preset-sheets-sort.css'
|
|
70
|
+
import '@univerjs/presets/lib/styles/preset-sheets-find-replace.css'
|
|
71
|
+
import '@univerjs/presets/lib/styles/preset-sheets-conditional-formatting.css'
|
|
72
|
+
import '@univerjs/presets/lib/styles/preset-sheets-data-validation.css'
|
|
73
|
+
import '@univerjs/presets/lib/styles/preset-sheets-drawing.css'
|
|
74
|
+
import '@univerjs/presets/lib/styles/preset-sheets-hyper-link.css'
|
|
75
|
+
import '@univerjs/presets/lib/styles/preset-sheets-note.css'
|
|
76
|
+
import '@univerjs/presets/lib/styles/preset-sheets-thread-comment.css'
|
|
77
|
+
import '@univerjs/presets/lib/styles/preset-sheets-table.css'
|
|
78
|
+
import '@univerjs/sheets-crosshair-highlight/lib/index.css'
|
|
79
|
+
import './overrides.css'
|
|
80
|
+
import type {
|
|
81
|
+
SheetColumn,
|
|
82
|
+
WorkbookCellStyle,
|
|
83
|
+
WorkbookCellUpdate,
|
|
84
|
+
WorkbookLocalChange,
|
|
85
|
+
WorkbookOperation,
|
|
86
|
+
WorkbookOperationPayload,
|
|
87
|
+
WorkbookFocusRange,
|
|
88
|
+
WorkbookRange,
|
|
89
|
+
WorkbookPresencePayload,
|
|
90
|
+
WorkbookSelectionRange,
|
|
91
|
+
} from '../types.ts'
|
|
92
|
+
import { DataSheetExportPlugin } from './plugins/export.ts'
|
|
93
|
+
import { DataSheetCollaborationPlugin } from './plugins/collaboration.ts'
|
|
94
|
+
import { DataSheetHistoryPlugin } from './plugins/history.ts'
|
|
95
|
+
import { getInstalledFontConfigs, withDefaultSheetFont } from './fonts.ts'
|
|
96
|
+
import { shouldPersistUniverMutation } from '../contract/operations.ts'
|
|
97
|
+
import { publishMutationAttempt, toLocalCellChange, toPresence } from './diagnostics.ts'
|
|
98
|
+
import { DEFAULT_SHEET_ROWS, DEFAULT_SHEET_COLUMNS } from '../contract/snapshots.ts'
|
|
99
|
+
import { createDecorationApplier } from './decoration.ts'
|
|
100
|
+
import { createOperationApplier } from './apply-operation.ts'
|
|
101
|
+
import type { SheetsApi, SheetResolver } from './facade.ts'
|
|
102
|
+
|
|
103
|
+
/** Default sheet extent (Univer's own default), so data lands on a full-size grid. */
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Load marker + default probe value.
|
|
107
|
+
*
|
|
108
|
+
* The engine chunk is a classic script the browser may still serve from cache,
|
|
109
|
+
* so "is my bundle current?" was impossible to answer from the console. These
|
|
110
|
+
* two globals are set as soon as the chunk evaluates:
|
|
111
|
+
*
|
|
112
|
+
* __dshDataSheetEngine // { version, loadedAt } — undefined means a stale chunk
|
|
113
|
+
* __dshLastCellMutation // { reason: 'no-persisted-mutation-yet' } until you edit
|
|
114
|
+
*/
|
|
115
|
+
if (typeof window !== 'undefined') {
|
|
116
|
+
const win = window as unknown as { __dshDataSheetEngine?: unknown; __dshLastCellMutation?: unknown }
|
|
117
|
+
win.__dshDataSheetEngine = { version: 'v3.2', loadedAt: new Date().toISOString() }
|
|
118
|
+
// One line, so "which engine build is this page running?" is answered by the
|
|
119
|
+
// console itself instead of a hand-typed global.
|
|
120
|
+
console.info('[data-sheet] Univer engine chunk v3.2 loaded · probe: __dshLastCellMutation')
|
|
121
|
+
win.__dshLastCellMutation = { reason: 'no-persisted-mutation-yet' }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Mount one resident Univer engine into a container; the container must be in
|
|
127
|
+
* the DOM and the chunk must already be loaded. The workbook data is an
|
|
128
|
+
* Univer snapshot (IWorkbookData-shaped) that the residency renders; `save()`
|
|
129
|
+
* returns the current snapshot for the client half to persist. The client
|
|
130
|
+
* batches ten durable user steps (or flushes on Ctrl/Cmd+S) into one Version.
|
|
131
|
+
*/
|
|
132
|
+
export function mountWorkbook(container: HTMLElement, workbookData: object, onDirty?: (change?: WorkbookLocalChange) => void, onPresence?: (presence: WorkbookPresencePayload) => void, options: WorkbookMountOptions = {}, onSelection?: (ranges: readonly WorkbookSelectionRange[]) => void): WorkbookMount {
|
|
133
|
+
const readOnly = options.readOnly === true
|
|
134
|
+
const decoration = options.decoration
|
|
135
|
+
const installedFontConfigs = getInstalledFontConfigs()
|
|
136
|
+
let openHistory: (() => void) | undefined
|
|
137
|
+
let refreshSelection = (): void => {}
|
|
138
|
+
const onUniverMutation = (commandInfo: { id: string; params?: unknown }, options?: { onlyLocal?: boolean; fromChangeset?: boolean; fromCollab?: boolean }): void => {
|
|
139
|
+
if (applier.isApplyingRemote() || options?.onlyLocal || options?.fromChangeset || options?.fromCollab) return
|
|
140
|
+
if (!shouldPersistUniverMutation(commandInfo.id)) {
|
|
141
|
+
const presence = toPresence(commandInfo)
|
|
142
|
+
// A preview is not somebody editing: it publishes no editing presence,
|
|
143
|
+
// so peers do not see a phantom collaborator.
|
|
144
|
+
if (presence !== undefined && !readOnly) onPresence?.(presence)
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
// Belt and braces with `setEditable(false)` below: even a command that
|
|
148
|
+
// slipped past the permission interceptor is never reported as a change,
|
|
149
|
+
// so a preview can never fork a Version.
|
|
150
|
+
if (readOnly) return
|
|
151
|
+
onPresence?.({ kind: 'editing', payload: { commandId: commandInfo.id } })
|
|
152
|
+
const change = toLocalCellChange(commandInfo)
|
|
153
|
+
publishMutationAttempt(commandInfo.id, change !== undefined)
|
|
154
|
+
onDirty?.(change)
|
|
155
|
+
refreshSelection()
|
|
156
|
+
}
|
|
157
|
+
const { univer, univerAPI } = createUniver({ // The sheets-core preset renders nothing (silently) without the locale
|
|
158
|
+
// packs and theme; keep both in sync with the official 0.25 usage.
|
|
159
|
+
locale: LocaleType.ZH_CN,
|
|
160
|
+
locales: {
|
|
161
|
+
zhCN: merge({}, coreZhCN, filterZhCN, sortZhCN, findReplaceZhCN, condFmtZhCN, dataValZhCN, drawingZhCN, hyperLinkZhCN, noteZhCN, threadZhCN, tableZhCN, crosshairZhCN),
|
|
162
|
+
enUS: merge({}, coreEnUS, filterEnUS, sortEnUS, findReplaceEnUS, condFmtEnUS, dataValEnUS, drawingEnUS, hyperLinkEnUS, noteEnUS, threadEnUS, tableEnUS, crosshairEnUS),
|
|
163
|
+
},
|
|
164
|
+
theme: defaultTheme,
|
|
165
|
+
plugins: [
|
|
166
|
+
DataSheetExportPlugin,
|
|
167
|
+
[DataSheetHistoryPlugin, { onOpenHistory: () => openHistory?.() }],
|
|
168
|
+
[DataSheetCollaborationPlugin, { onMutation: onUniverMutation }],
|
|
169
|
+
UniverSheetsCrosshairHighlightPlugin,
|
|
170
|
+
],
|
|
171
|
+
presets: [
|
|
172
|
+
UniverSheetsCorePreset({
|
|
173
|
+
container,
|
|
174
|
+
header: true,
|
|
175
|
+
// A preview shows history: the editing chrome would only invite edits
|
|
176
|
+
// that cannot be saved (PRD v3.3 §7.2). Read-only mode keeps the grid,
|
|
177
|
+
// the headers and the sheet tabs, and drops the rest.
|
|
178
|
+
toolbar: !readOnly,
|
|
179
|
+
formulaBar: !readOnly,
|
|
180
|
+
// (`disableEdit` is deliberately *not* passed here: this preset
|
|
181
|
+
// destructures a fixed key set and would drop it silently. It is not
|
|
182
|
+
// needed either — with the workbook permission off, the cell editor
|
|
183
|
+
// refuses to open, measured.)
|
|
184
|
+
statusBarStatistic: true,
|
|
185
|
+
// The footer carries the sheet tabs. A past Version still has several
|
|
186
|
+
// sheets, so switching between them is navigation and must stay
|
|
187
|
+
// available in a read-only view (GUI feedback 2026-09-19).
|
|
188
|
+
footer: true,
|
|
189
|
+
contextMenu: !readOnly,
|
|
190
|
+
// Register custom families during UI initialization so they are
|
|
191
|
+
// present in the font dropdown (addFonts alone is too late for the
|
|
192
|
+
// initial font-family component in this Univer version).
|
|
193
|
+
customFontFamily: {
|
|
194
|
+
list: installedFontConfigs,
|
|
195
|
+
override: true,
|
|
196
|
+
},
|
|
197
|
+
}),
|
|
198
|
+
// Free feature presets (mirrors the best_excel plugin set). Datasheet
|
|
199
|
+
// collaboration is provided by its own dependency-free adapter above;
|
|
200
|
+
// the commercial Univer collaboration preset is intentionally unused.
|
|
201
|
+
UniverSheetsFilterPreset(),
|
|
202
|
+
UniverSheetsSortPreset(),
|
|
203
|
+
UniverSheetsFindReplacePreset(),
|
|
204
|
+
UniverSheetsConditionalFormattingPreset(),
|
|
205
|
+
UniverSheetsDataValidationPreset(),
|
|
206
|
+
UniverSheetsDrawingPreset(),
|
|
207
|
+
UniverSheetsHyperLinkPreset(),
|
|
208
|
+
UniverSheetsNotePreset(),
|
|
209
|
+
UniverSheetsThreadCommentPreset(),
|
|
210
|
+
UniverSheetsTablePreset(),
|
|
211
|
+
],
|
|
212
|
+
})
|
|
213
|
+
// Univer does not download these fonts; the browser uses them when the
|
|
214
|
+
// corresponding family is installed on the user's machine.
|
|
215
|
+
univer.createUnit(UniverInstanceType.UNIVER_SHEET, withDefaultSheetFont(workbookData))
|
|
216
|
+
// Debug seam: mounted engines by container, for live workbook inspection.
|
|
217
|
+
{
|
|
218
|
+
const win = window as unknown as { __bestExcelDebugMounts?: Array<{ container: HTMLElement; api: unknown }> }
|
|
219
|
+
win.__bestExcelDebugMounts = win.__bestExcelDebugMounts ?? []
|
|
220
|
+
win.__bestExcelDebugMounts.push({ container, api: univerAPI })
|
|
221
|
+
}
|
|
222
|
+
// The sheets facade augments FUniver with the workbook API; the core type
|
|
223
|
+
// lacks it, so the engine views the facade structurally (see `facade.ts`).
|
|
224
|
+
const sheetsApi = univerAPI as unknown as SheetsApi
|
|
225
|
+
const getSheet: SheetResolver = (sheetRef) => {
|
|
226
|
+
const workbook = sheetsApi.getActiveWorkbook()
|
|
227
|
+
if (workbook === null) return null
|
|
228
|
+
if (sheetRef !== undefined) return workbook.getSheetBySheetId(sheetRef) ?? workbook.getSheetByName(sheetRef)
|
|
229
|
+
return workbook.getSheetBySheetId('sheet1') ?? null
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let selectionSubscription: { dispose(): void } | undefined
|
|
233
|
+
let currentSelectionRanges: Array<WorkbookRange & { sheetId?: string }> = []
|
|
234
|
+
const projectSelections = (ranges: readonly (WorkbookRange & { sheetId?: string })[]): WorkbookSelectionRange[] => {
|
|
235
|
+
const workbook = sheetsApi.getActiveWorkbook()
|
|
236
|
+
if (workbook === null) return []
|
|
237
|
+
const activeSheetId = workbook.getActiveSheet?.()?.getSheetId?.()
|
|
238
|
+
const projected: WorkbookSelectionRange[] = []
|
|
239
|
+
for (const range of ranges.slice(0, 40)) {
|
|
240
|
+
const sheetId = range.sheetId ?? activeSheetId
|
|
241
|
+
if (sheetId === undefined) continue
|
|
242
|
+
const sheet = workbook.getSheetBySheetId(sheetId)
|
|
243
|
+
if (sheet === null) continue
|
|
244
|
+
const startRow = Math.max(0, Math.floor(range.startRow))
|
|
245
|
+
const startColumn = Math.max(0, Math.floor(range.startColumn))
|
|
246
|
+
const endRow = Math.max(startRow, Math.floor(range.endRow))
|
|
247
|
+
const endColumn = Math.max(startColumn, Math.floor(range.endColumn))
|
|
248
|
+
const values = sheet.getRange(
|
|
249
|
+
startRow,
|
|
250
|
+
startColumn,
|
|
251
|
+
Math.min(endRow - startRow + 1, 10),
|
|
252
|
+
Math.min(endColumn - startColumn + 1, 20),
|
|
253
|
+
).getValues?.() ?? []
|
|
254
|
+
projected.push({
|
|
255
|
+
sheetId,
|
|
256
|
+
sheetName: sheet.getSheetName?.() ?? sheetId,
|
|
257
|
+
startRow,
|
|
258
|
+
startColumn,
|
|
259
|
+
endRow,
|
|
260
|
+
endColumn,
|
|
261
|
+
values,
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
return projected
|
|
265
|
+
}
|
|
266
|
+
const publishSelections = (ranges: readonly (WorkbookRange & { sheetId?: string })[]): void => {
|
|
267
|
+
currentSelectionRanges = [...ranges]
|
|
268
|
+
onSelection?.(projectSelections(currentSelectionRanges))
|
|
269
|
+
}
|
|
270
|
+
refreshSelection = (): void => {
|
|
271
|
+
if (currentSelectionRanges.length > 0) onSelection?.(projectSelections(currentSelectionRanges))
|
|
272
|
+
}
|
|
273
|
+
const bindSelectionWatcher = (): void => {
|
|
274
|
+
selectionSubscription?.dispose()
|
|
275
|
+
selectionSubscription = undefined
|
|
276
|
+
currentSelectionRanges = []
|
|
277
|
+
onSelection?.([])
|
|
278
|
+
const workbook = sheetsApi.getActiveWorkbook()
|
|
279
|
+
if (workbook?.onSelectionChange === undefined) return
|
|
280
|
+
selectionSubscription = workbook.onSelectionChange(ranges => {
|
|
281
|
+
if (sheetsApi.getActiveWorkbook()?.getId() !== workbook.getId()) return
|
|
282
|
+
publishSelections(ranges)
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
bindSelectionWatcher()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Show a different workbook **without rebuilding Univer** (PRD v3.5 §7.2).
|
|
290
|
+
*
|
|
291
|
+
* Switching the inspected Version used to change the canvas key, which
|
|
292
|
+
* unmounted the residency and called `createUniver` again — re-registering
|
|
293
|
+
* every plugin and rebuilding the whole DI graph for a change that is only
|
|
294
|
+
* "different cells". Swapping the *unit* on the same engine keeps the grid,
|
|
295
|
+
* the sheet tabs and the scroll position, and removes the re-init cost.
|
|
296
|
+
*
|
|
297
|
+
* A fresh unit also means the previous Version's diff tint disappears with
|
|
298
|
+
* it, so there is nothing to un-paint.
|
|
299
|
+
*/
|
|
300
|
+
const decoration_ = createDecorationApplier({ sheetsApi, getSheet, readOnly })
|
|
301
|
+
// Paint on the **mount** path too, not only in `swapWorkbook`. Entering inspect
|
|
302
|
+
// remounts the canvas (`preview === null` means there is no residency to swap),
|
|
303
|
+
// so the mount is the *first* preview a reader ever sees. Applying the plan
|
|
304
|
+
// only when swapping dropped both the diff tint and the read-only lock on that
|
|
305
|
+
// first look — the cells were counted in the bar but nothing was painted, and
|
|
306
|
+
// the unit stayed editable. Restores the pre-split behaviour, where the mount
|
|
307
|
+
// called the same thing (`if (readOnly || decoration !== undefined) apply…`).
|
|
308
|
+
if (readOnly || decoration !== undefined) decoration_.apply(decoration)
|
|
309
|
+
const applier = createOperationApplier({ sheetsApi, getSheet })
|
|
310
|
+
|
|
311
|
+
const swapWorkbook = (next: object, options: { decoration?: WorkbookDecoration } = {}): boolean => {
|
|
312
|
+
const previousId = sheetsApi.getActiveWorkbook()?.getId()
|
|
313
|
+
try {
|
|
314
|
+
univer.createUnit(UniverInstanceType.UNIVER_SHEET, withDefaultSheetFont(next))
|
|
315
|
+
} catch {
|
|
316
|
+
return false
|
|
317
|
+
}
|
|
318
|
+
bindSelectionWatcher()
|
|
319
|
+
decoration_.apply(options.decoration)
|
|
320
|
+
if (previousId !== undefined) {
|
|
321
|
+
try {
|
|
322
|
+
sheetsApi.disposeUnit?.(previousId)
|
|
323
|
+
} catch {
|
|
324
|
+
// A unit that refuses to dispose is a leak, not a broken canvas.
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return true
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
swapWorkbook,
|
|
332
|
+
save: () => {
|
|
333
|
+
const wb = sheetsApi.getActiveWorkbook()
|
|
334
|
+
if (wb === null) return workbookData
|
|
335
|
+
const snapshot = wb.getSnapshot()
|
|
336
|
+
if (typeof snapshot === 'object' && snapshot !== null && typeof (snapshot as { sheets?: unknown }).sheets === 'object') {
|
|
337
|
+
const sheets = (snapshot as { sheets: Record<string, Record<string, unknown>> }).sheets
|
|
338
|
+
for (const [sheetId, meta] of applier.liveSheetMetadata.entries()) {
|
|
339
|
+
const sheet = sheets[sheetId]
|
|
340
|
+
if (sheet !== undefined) sheet.dataSheetMeta = meta
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return snapshot
|
|
344
|
+
},
|
|
345
|
+
applyOperation: applier.apply,
|
|
346
|
+
focusRange: (target: WorkbookFocusRange): boolean => {
|
|
347
|
+
const workbook = sheetsApi.getActiveWorkbook()
|
|
348
|
+
const sheet = workbook?.getSheetBySheetId(target.sheetId)
|
|
349
|
+
if (workbook === null || workbook === undefined || sheet === null || sheet === undefined || workbook.setActiveRange === undefined) return false
|
|
350
|
+
workbook.setActiveSheet?.(sheet)
|
|
351
|
+
const range = sheet.getRange(
|
|
352
|
+
target.startRow,
|
|
353
|
+
target.startColumn,
|
|
354
|
+
target.endRow - target.startRow + 1,
|
|
355
|
+
target.endColumn - target.startColumn + 1,
|
|
356
|
+
)
|
|
357
|
+
workbook.setActiveRange(range)
|
|
358
|
+
return true
|
|
359
|
+
},
|
|
360
|
+
dispose: () => {
|
|
361
|
+
selectionSubscription?.dispose()
|
|
362
|
+
selectionSubscription = undefined
|
|
363
|
+
univer.dispose()
|
|
364
|
+
const win = window as unknown as { __bestExcelDebugMounts?: Array<{ container: HTMLElement; api: unknown }> }
|
|
365
|
+
if (win.__bestExcelDebugMounts !== undefined) {
|
|
366
|
+
win.__bestExcelDebugMounts = win.__bestExcelDebugMounts.filter(entry => entry.container !== container)
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
}
|
|
370
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk entry for dsh-data-table. Built as a self-contained IIFE
|
|
3
|
+
* (`lib/univer-client.js`, Univer fully inlined) and loaded as a classic
|
|
4
|
+
* script on first sheet render; it hands the engine surface to the client
|
|
5
|
+
* half through a global so the ~16MB graph never enters the boot bundle.
|
|
6
|
+
* @module dsh-data-table/univer/entry
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { UniverChunkApi } from './chunk.ts'
|
|
10
|
+
import { mountWorkbook } from './engine.ts'
|
|
11
|
+
|
|
12
|
+
// The interface and the `window` global live in ./chunk.ts so the loader
|
|
13
|
+
// in the client bundle cannot drift from the chunk it loads.
|
|
14
|
+
window.__bestExcelUniver = { mountWorkbook } satisfies UniverChunkApi
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Univer facade surface this adapter actually uses (docs/issue/0022 P4).
|
|
3
|
+
*
|
|
4
|
+
* The sheets facade augments `FUniver` with `getActiveWorkbook`/`getSnapshot`,
|
|
5
|
+
* which the core type does not declare, so the engine views it structurally. It
|
|
6
|
+
* is declared once here because three modules need the same view of it —
|
|
7
|
+
* decoration, the operation applier and the engine — and three copies would
|
|
8
|
+
* drift the moment one of them used a facade method the others did not declare.
|
|
9
|
+
*/
|
|
10
|
+
import type { WorkbookRange } from '../types.ts'
|
|
11
|
+
|
|
12
|
+
export interface UniverRange {
|
|
13
|
+
getValue?(): unknown
|
|
14
|
+
getValues?(): unknown[][]
|
|
15
|
+
setValue(value: unknown): unknown
|
|
16
|
+
clearContent(): unknown
|
|
17
|
+
setValues(value: unknown): unknown
|
|
18
|
+
getRange?(): WorkbookRange
|
|
19
|
+
/** Tint one cell; the diff overlay's only painting primitive. */
|
|
20
|
+
setBackgroundColor?(color: string): unknown | Promise<unknown>
|
|
21
|
+
setFontColor?(color: string): unknown
|
|
22
|
+
setFontFamily?(family: string): unknown
|
|
23
|
+
setFontSize?(size: number): unknown
|
|
24
|
+
setFontWeight?(weight: 'bold' | 'normal' | null): unknown
|
|
25
|
+
setFontStyle?(style: 'italic' | 'normal' | null): unknown
|
|
26
|
+
setFontLine?(line: 'underline' | 'line-through' | 'none' | null): unknown
|
|
27
|
+
setHorizontalAlignment?(alignment: 'left' | 'center' | 'normal'): unknown
|
|
28
|
+
setVerticalAlignment?(alignment: 'top' | 'middle' | 'bottom'): unknown
|
|
29
|
+
setTextRotation?(rotation: number): unknown
|
|
30
|
+
sort?(column: number | { column: number; ascending: boolean }): unknown
|
|
31
|
+
merge?(options?: { defaultMerge?: boolean; isForceMerge?: boolean }): unknown
|
|
32
|
+
breakApart?(): unknown
|
|
33
|
+
/** 0 = shift cells left, 1 = shift cells up (Univer facade enum). */
|
|
34
|
+
deleteCells?: (direction: 0 | 1) => unknown
|
|
35
|
+
setHyperLink?(url: string, label?: string): Promise<boolean>
|
|
36
|
+
cancelHyperLink?(): boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UniverSheet {
|
|
40
|
+
getSheetId?: () => string
|
|
41
|
+
getSheetName?: () => string
|
|
42
|
+
getRange(row: number, column: number, numRows?: number, numColumns?: number): UniverRange
|
|
43
|
+
deleteRows?: (rowPosition: number, howMany?: number) => unknown
|
|
44
|
+
insertRows?: (rowIndex: number, numRows?: number) => unknown
|
|
45
|
+
deleteColumns?: (columnPosition: number, howMany?: number) => unknown
|
|
46
|
+
insertColumns?: (columnIndex: number, numColumns?: number) => unknown
|
|
47
|
+
setName?: (name: string) => unknown
|
|
48
|
+
setColumnWidth?: (columnPosition: number, width: number) => unknown
|
|
49
|
+
setRowHeight?: (rowPosition: number, height: number) => unknown
|
|
50
|
+
setFreeze?: (freeze: { startRow: number; startColumn: number; xSplit: number; ySplit: number }) => unknown
|
|
51
|
+
cancelFreeze?: () => unknown
|
|
52
|
+
getLastRow?: () => number
|
|
53
|
+
getMaxColumns?: () => number
|
|
54
|
+
getMaxRows?: () => number
|
|
55
|
+
setColumnCount?: (count: number) => unknown
|
|
56
|
+
setRowCount?: (count: number) => unknown
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface UniverWorkbook {
|
|
60
|
+
getId(): string
|
|
61
|
+
getSnapshot(): unknown
|
|
62
|
+
getSheetBySheetId(sheetId: string): UniverSheet | null
|
|
63
|
+
getSheetByName(name: string): UniverSheet | null
|
|
64
|
+
getActiveSheet?(): UniverSheet | null
|
|
65
|
+
onSelectionChange?(listener: (ranges: readonly (WorkbookRange & { sheetId?: string })[]) => void): { dispose(): void }
|
|
66
|
+
create(name: string, rows: number, columns: number, options?: { sheet?: { id?: string } }): unknown
|
|
67
|
+
deleteSheet?(sheet: string | UniverSheet): unknown
|
|
68
|
+
/** Workbook-level edit permission (docs/issue/0002 PRD v3.2 §7.2). */
|
|
69
|
+
setEditable?(value: boolean): unknown
|
|
70
|
+
/**
|
|
71
|
+
* The permission facade behind that call, for *reading back* what was set.
|
|
72
|
+
* `canEdit()` is the only way to tell whether the lock actually landed — see
|
|
73
|
+
* `lockWorkbook` in `decoration.ts` for why that question is not rhetorical.
|
|
74
|
+
*/
|
|
75
|
+
getWorkbookPermission?(): { canEdit?(): boolean } | null
|
|
76
|
+
/** Select a range; the facade scrolls the active range into view. */
|
|
77
|
+
setActiveRange?(range: unknown): unknown
|
|
78
|
+
/** Activate a sheet before selecting a range on it. */
|
|
79
|
+
setActiveSheet?(sheet: unknown): unknown
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The facade's workbook-scoped API, as this adapter uses it. */
|
|
83
|
+
export interface SheetsApi {
|
|
84
|
+
/** Dispose a unit without tearing the engine down (used by `swapWorkbook`). */
|
|
85
|
+
disposeUnit?(unitId: string): boolean
|
|
86
|
+
getActiveWorkbook(): UniverWorkbook | null
|
|
87
|
+
executeCommand(id: string, params: unknown, options?: unknown): Promise<unknown>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Resolve a sheet by id, by name, or the default first sheet. */
|
|
91
|
+
export type SheetResolver = (sheetRef: string | undefined) => UniverSheet | null
|