@ai-matrx/office 0.0.0 → 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.
@@ -0,0 +1,320 @@
1
+ import { ICommandInfo, ImageSourceType, ImageUploadStatusType, IDisposable } from '@univerjs/core';
2
+ import * as react from 'react';
3
+ import { SVGAttributes } from 'react';
4
+ import { FUniver } from '@univerjs/presets';
5
+
6
+ /**
7
+ * The host ports of the Univer glue.
8
+ *
9
+ * The glue belongs to the package, but four things belong to the app that mounts an editor: the
10
+ * toast path, the signed-in person, the file store and the painted theme. The host states them
11
+ * once at start-up with `configureUniverHost`; the glue reads them here. State sits on a
12
+ * `globalThis` slot so a dual-bundled copy of the package still sees one host (dual-bundle rule).
13
+ * An unconfigured port THROWS naming the port (nothing fails silently).
14
+ */
15
+ type UniverToastId = string | number;
16
+ type ToastShow = (title: string, options?: {
17
+ description?: string;
18
+ duration?: number;
19
+ }) => UniverToastId;
20
+ interface UniverHostPorts {
21
+ /** The app's toast path (one toaster per page). */
22
+ toast: {
23
+ success: ToastShow;
24
+ info: ToastShow;
25
+ warning: ToastShow;
26
+ error: ToastShow;
27
+ message: ToastShow;
28
+ dismiss(id: UniverToastId): void;
29
+ };
30
+ /** Who is typing, or null when signed out. `metadata` is the auth user's metadata bag. */
31
+ getSignedInUser(): Promise<{
32
+ id: string;
33
+ email?: string | null;
34
+ metadata?: Record<string, unknown> | null;
35
+ } | null>;
36
+ /** The file store behind pictures on a sheet or in a document. */
37
+ files: {
38
+ upload(file: File): Promise<{
39
+ fileId: string;
40
+ }>;
41
+ getBlob(fileId: string): Promise<Blob>;
42
+ };
43
+ /** Tell the person a picture did not upload. */
44
+ notifyUploadError(error: unknown): void;
45
+ /** The painted colour mode, as a React hook (re-renders on a switch). */
46
+ useThemeMode(): "light" | "dark";
47
+ }
48
+ declare function configureUniverHost(ports: UniverHostPorts): void;
49
+ declare function getUniverHost(): UniverHostPorts;
50
+
51
+ /**
52
+ * A document's or a workbook's snapshot history as a canvas tab — the keys and toggle inputs the
53
+ * editors use, and the reader the two history views use. One tab per document (`document-history`,
54
+ * keyed by the document id) and per workbook (`workbook-history`, keyed by the workbook id).
55
+ *
56
+ * Pure: no React, no canvas package, no Univer. The two `defineCanvasKind` registrations stay with
57
+ * the host app (matrx-frontend `features/canvas/host`) and lazy-load the views, so this module never
58
+ * imports a view (the cycle the old `lib/univer/historyKinds.ts` closed).
59
+ */
60
+ declare const DOCUMENT_HISTORY_KIND = "document-history";
61
+ declare const WORKBOOK_HISTORY_KIND = "workbook-history";
62
+ interface HistoryTabData {
63
+ id: string;
64
+ editable: boolean;
65
+ }
66
+ /** Structurally the host's `ToolToggleInput` (the canvas toggle the editor's History button presses). */
67
+ interface HistoryToggleInput {
68
+ kind: string;
69
+ key: string;
70
+ title: string;
71
+ data: {
72
+ id: string;
73
+ editable: boolean;
74
+ };
75
+ followTitle: true;
76
+ }
77
+ /** A tab's data as a history subject, or null when it names no subject. */
78
+ declare function readHistoryTab(data: unknown): HistoryTabData | null;
79
+ declare function documentHistoryToggleInput(documentId: string, editable: boolean, documentName?: string | null): HistoryToggleInput;
80
+ declare function workbookHistoryToggleInput(workbookId: string, editable: boolean, workbookName?: string | null): HistoryToggleInput;
81
+
82
+ /** Univer owns React roots; synchronous dispose during React commit causes races. */
83
+ declare function disposeUniverInstance(instance: {
84
+ dispose(): void;
85
+ } | null | undefined): void;
86
+
87
+ type InjectorLike$2 = {
88
+ get(id: unknown): unknown;
89
+ };
90
+ /**
91
+ * Tell Univer who is typing, so a comment thread is attributed to the
92
+ * signed-in person instead of Univer's placeholder owner.
93
+ *
94
+ * The userID MUST keep the `Owner_` prefix: Univer's built-in local
95
+ * permission service grants unit roles by user-id prefix (`isDevRole`), so a
96
+ * bare uuid gets no role and every edit is refused as "range is protected".
97
+ * Our own access (canActOn) decides editability; Univer must always see an
98
+ * owner. Guarded by identify-univer-user-keeps-owner-role.test.ts.
99
+ */
100
+ declare function identifyUniverUser(injector: InjectorLike$2): Promise<void>;
101
+ /** Univer's local permission service reads the role from this prefix. */
102
+ declare function univerOwnerId(userId: string): string;
103
+
104
+ /**
105
+ * isSnapshotMutation — the autosave dirty-filter for the Univer editors.
106
+ *
107
+ * D97: `onCommandExecuted` fires for EVERY command — including viewport
108
+ * scrolls and selection moves — so an unfiltered listener marked the doc
109
+ * dirty on mere scrolling and wrote a new snapshot row (version history +
110
+ * collab broadcast) 2.5s later. Only CommandType.MUTATION changes the data
111
+ * that a snapshot persists (Univer's own docs: OPERATION = "not saved to
112
+ * snapshot, such as modifying scroll position"). We therefore accept ONLY
113
+ * mutations, and additionally deny-list any mutation whose id marks it as
114
+ * scroll / selection / viewport bookkeeping, belt-and-braces.
115
+ */
116
+
117
+ declare function isSnapshotMutation(command: ICommandInfo): boolean;
118
+ declare function isWorkbookSnapshotMutation(command: ICommandInfo): boolean;
119
+
120
+ /**
121
+ * univerImageStore — images on a sheet or in a document live in OUR file
122
+ * store; the Univer snapshot holds only a reference (`matrx-file:<fileId>`).
123
+ *
124
+ * Why: Univer's stock image service inlines every picture as base64 into the
125
+ * snapshot, so one 2 MB photo made every autosave, history row and collab
126
+ * mutation ~2 MB. Here `saveImage` uploads the file and hands Univer a URL-type
127
+ * source; Univer's URL-image downloader turns the reference back into bytes
128
+ * (`getBlob` → object URL) when it paints. Images already inline (BASE64
129
+ * sources) are untouched and keep rendering.
130
+ */
131
+
132
+ declare const MATRX_IMAGE_PREFIX = "matrx-file:";
133
+ declare const isMatrxImageSource: (source: string) => boolean;
134
+ declare const matrxImageFileId: (source: string) => string;
135
+ type ImageStorePorts = {
136
+ upload(file: File): Promise<{
137
+ fileId: string;
138
+ }>;
139
+ getBlob(fileId: string): Promise<Blob>;
140
+ /** Called when an upload fails, so the person is told (never silent). */
141
+ onUploadError(error: unknown): void;
142
+ };
143
+ type InjectorLike$1 = {
144
+ get(id: unknown): unknown;
145
+ };
146
+ /** Pure core: the two replacements, given ports. */
147
+ declare function createMatrxImageStore(ports: ImageStorePorts): {
148
+ /** Revoke every object URL this store made (the editor is going away). */
149
+ dispose(): void;
150
+ saveImage(file: File): Promise<{
151
+ imageId: string;
152
+ imageSourceType: ImageSourceType;
153
+ source: string;
154
+ base64Cache: string;
155
+ status: ImageUploadStatusType;
156
+ }>;
157
+ download(url: string): Promise<string>;
158
+ };
159
+ /** Release the object URLs of the store wired into this Univer instance (call as the instance is disposed). */
160
+ declare function releaseMatrxImageStore(injector: object | null | undefined): void;
161
+ /** Wire the store into one Univer instance's image services. */
162
+ declare function registerMatrxImageStore(injector: InjectorLike$1, ports: ImageStorePorts): void;
163
+
164
+ /** The real file-store ports (the host's): upload, read back as a blob, tell the person on failure. */
165
+ declare const matrxImagePorts: ImageStorePorts;
166
+ /** Export: a snapshot picture source (`matrx-file:<id>` or a URL) as bytes + type, or null if unreadable. */
167
+ declare function resolveExportImage(source: string): Promise<{
168
+ bytes: Uint8Array;
169
+ extension: "png" | "jpeg" | "gif";
170
+ } | null>;
171
+ /** Import: store a picture from a file, return its file id. */
172
+ declare function uploadImportedImage(bytes: Uint8Array, extension: string): Promise<string>;
173
+
174
+ /**
175
+ * THE ONE way to replace the whole content of an open Univer editor
176
+ * (workbook or document) with a snapshot that is already SAVED: a history
177
+ * restore, "Update from Google" / "Use Google's", and a collaborator's
178
+ * replacement all arrive here.
179
+ *
180
+ * Callers save first, then call `showSavedSnapshot`. The open editor for that
181
+ * record (registered below) swaps its content in place, drops its pending
182
+ * autosave (it would write the old content back over the new one), and — in
183
+ * a collab room — tells every peer to reload the same snapshot. A caller
184
+ * never touches Univer units itself: disposing the current unit by hand left
185
+ * Univer's selection observers pointing at nothing (`getUnitId` of null).
186
+ *
187
+ * Pure registry (no Univer import), so it is testable without booting Univer.
188
+ */
189
+ type EditorRecordKind = "workbook" | "document";
190
+ /** A snapshot row as stored: its id and the Univer body. */
191
+ type SavedEditorSnapshot = {
192
+ id: string;
193
+ snapshot: unknown;
194
+ };
195
+ type EditorContentReplacer = (row: SavedEditorSnapshot) => void | Promise<void>;
196
+ /**
197
+ * The open editor of a record lends its replacer while it is mounted. The
198
+ * newest registration wins; the returned release only removes its own.
199
+ */
200
+ declare function registerOpenEditorContent(kind: EditorRecordKind, recordId: string, replace: EditorContentReplacer): () => void;
201
+ /**
202
+ * Show a saved snapshot in the record's open editor (and its collab peers).
203
+ * Returns false when no editor of the record is open in this tab — the saved
204
+ * row then simply is the content the next open loads.
205
+ */
206
+ declare function showSavedSnapshot(kind: EditorRecordKind, recordId: string, row: SavedEditorSnapshot): Promise<boolean>;
207
+ /**
208
+ * THE CONTENT-SWAP GUARD. A swap is dispose-then-create; if the create throws, the unit is gone and
209
+ * the grid would stay blank. `swap(snapshot)` is the editor's own dispose+create (it disposes
210
+ * whatever unit is open, if any). On a throw this puts the content that was open before straight
211
+ * back (synchronously — never a blank grid) and says so; the editor then reloads the latest SAVED
212
+ * version and still raises the original error, so the person is told.
213
+ */
214
+ declare function swapContentGuarded(args: {
215
+ swap: (snapshot: unknown) => void;
216
+ next: unknown;
217
+ /** What was open before (`workbook.save()` taken before the swap), or null when nothing was. */
218
+ previous: unknown | null;
219
+ }): {
220
+ ok: true;
221
+ } | {
222
+ ok: false;
223
+ error: unknown;
224
+ previousRestored: boolean;
225
+ };
226
+
227
+ interface IIconProps extends SVGAttributes<SVGSVGElement> {
228
+ /** Preserve scalable stroke widths relative to a 16×16 baseline. */
229
+ preserveStrokeWidth?: boolean;
230
+ extend?: IExtendProps;
231
+ }
232
+ interface IExtendProps {
233
+ colorChannel1?: string;
234
+ }
235
+
236
+ type InjectorLike = {
237
+ get(id: unknown): unknown;
238
+ };
239
+ /** Icons Univer's own plugins reference but do not register. */
240
+ declare const MISSING_UNIVER_ICONS: {
241
+ readonly AddImageIcon: react.ForwardRefExoticComponent<IIconProps & react.RefAttributes<SVGElement>>;
242
+ };
243
+ declare function registerMissingUniverIcons(injector: InjectorLike): void;
244
+
245
+ type UniverDependency = new (...args: never[]) => unknown;
246
+ type UniverInjector = {
247
+ has(dependency: UniverDependency): boolean;
248
+ add(dependency: [UniverDependency]): void;
249
+ };
250
+ /**
251
+ * Register services required by process-global Univer Facade observers.
252
+ *
253
+ * Facade modules can outlive the editor type that first imported them, so a
254
+ * later Univer instance may receive their lifecycle callbacks without loading
255
+ * that type's plugins. Registration is intentionally narrow: callers name only
256
+ * the observer dependencies that are safe for their instance.
257
+ */
258
+ declare function registerUniverFacadeDependencies(injector: UniverInjector, dependencies: readonly UniverDependency[]): void;
259
+
260
+ /**
261
+ * Univer's notifications go through the APP's toast path — one toaster per page.
262
+ *
263
+ * Univer's own `DesktopNotificationService` mounts a second sonner `<Toaster>`
264
+ * into its workbench the moment it is created. sonner's toast store is global,
265
+ * so with the app's Toaster also mounted every toast (ours and Univer's) showed
266
+ * twice on a workbook or document page. Replacing the service before anything
267
+ * resolves it means Univer never mounts that Toaster, and what Univer has to
268
+ * say (clipboard permission, paste limits) reaches the person through
269
+ * the host's toast port like every other message (tracked, Error Inspector, Alchemy).
270
+ *
271
+ * Call right after `createUniver`, before the first unit is created.
272
+ */
273
+
274
+ type UniverNotification = {
275
+ title: unknown;
276
+ content?: string;
277
+ type?: "success" | "info" | "warning" | "error" | "message" | "loading";
278
+ duration?: number;
279
+ };
280
+ interface NotificationReplaceableInjector {
281
+ replace?: (dependency: [unknown, unknown]) => void;
282
+ }
283
+ /** Show one Univer notification as an app toast; dismissing the disposable removes it. */
284
+ declare function showUniverNotification(params: UniverNotification): IDisposable;
285
+ declare function routeUniverNotificationsToApp(injector: NotificationReplaceableInjector | null | undefined): {
286
+ applied: boolean;
287
+ reason?: string;
288
+ };
289
+
290
+ /**
291
+ * Resolve a colour Univer hands its canvas — WITHOUT the dark-mode inversion.
292
+ *
293
+ * Univer 1.0 writes many of its own fills as THEME TOKENS, not colours: the
294
+ * page is `"gray.0"`, the desk `"gray.100"`, the page outline `"gray.200"`,
295
+ * default ink `"gray.900"` (engine-render 1.0.2 `DocBackground`, docs-ui
296
+ * `resolveDocRenderBackground`). Its `CanvasColorService` turns a token into a
297
+ * colour before anything reaches `ctx.fillStyle`; its `DumbCanvasColorService`
298
+ * does NOT — it returns `"gray.0"` as-is. A canvas IGNORES a `fillStyle` it
299
+ * cannot parse and keeps the previous one, which starts as `#000000`, so with
300
+ * the dumb service every page came out solid black and the canvas element's
301
+ * CSS background (`style.backgroundColor = "gray.100"`, also ignored) stayed
302
+ * transparent — in every browser, headed or headless, light or dark.
303
+ *
304
+ * Pure (no Univer import) so the jest test and `check:univer-doc-theme` drive
305
+ * the same function the editor installs.
306
+ */
307
+ /**
308
+ * @param color What Univer is about to paint: a theme token or a real colour.
309
+ * @param lookup The live theme (`ThemeService.getColorFromTheme`).
310
+ * @returns the token's colour from the current theme; anything else unchanged.
311
+ */
312
+ declare function resolveUniverCanvasColor(color: string, lookup: (token: string) => unknown): string;
313
+
314
+ /**
315
+ * @param apiRef Ref holding the Univer Facade API (set once the instance boots).
316
+ * @param ready True once the instance is booted and the API is usable.
317
+ */
318
+ declare function useUniverDarkModeSync(apiRef: React.RefObject<FUniver | null>, ready: boolean): void;
319
+
320
+ export { DOCUMENT_HISTORY_KIND, type EditorContentReplacer, type EditorRecordKind, type HistoryTabData, type HistoryToggleInput, type ImageStorePorts, MATRX_IMAGE_PREFIX, MISSING_UNIVER_ICONS, type NotificationReplaceableInjector, type SavedEditorSnapshot, type UniverHostPorts, type UniverToastId, WORKBOOK_HISTORY_KIND, configureUniverHost, createMatrxImageStore, disposeUniverInstance, documentHistoryToggleInput, getUniverHost, identifyUniverUser, isMatrxImageSource, isSnapshotMutation, isWorkbookSnapshotMutation, matrxImageFileId, matrxImagePorts, readHistoryTab, registerMatrxImageStore, registerMissingUniverIcons, registerOpenEditorContent, registerUniverFacadeDependencies, releaseMatrxImageStore, resolveExportImage, resolveUniverCanvasColor, routeUniverNotificationsToApp, showSavedSnapshot, showUniverNotification, swapContentGuarded, univerOwnerId, uploadImportedImage, useUniverDarkModeSync, workbookHistoryToggleInput };
@@ -0,0 +1,320 @@
1
+ import { ICommandInfo, ImageSourceType, ImageUploadStatusType, IDisposable } from '@univerjs/core';
2
+ import * as react from 'react';
3
+ import { SVGAttributes } from 'react';
4
+ import { FUniver } from '@univerjs/presets';
5
+
6
+ /**
7
+ * The host ports of the Univer glue.
8
+ *
9
+ * The glue belongs to the package, but four things belong to the app that mounts an editor: the
10
+ * toast path, the signed-in person, the file store and the painted theme. The host states them
11
+ * once at start-up with `configureUniverHost`; the glue reads them here. State sits on a
12
+ * `globalThis` slot so a dual-bundled copy of the package still sees one host (dual-bundle rule).
13
+ * An unconfigured port THROWS naming the port (nothing fails silently).
14
+ */
15
+ type UniverToastId = string | number;
16
+ type ToastShow = (title: string, options?: {
17
+ description?: string;
18
+ duration?: number;
19
+ }) => UniverToastId;
20
+ interface UniverHostPorts {
21
+ /** The app's toast path (one toaster per page). */
22
+ toast: {
23
+ success: ToastShow;
24
+ info: ToastShow;
25
+ warning: ToastShow;
26
+ error: ToastShow;
27
+ message: ToastShow;
28
+ dismiss(id: UniverToastId): void;
29
+ };
30
+ /** Who is typing, or null when signed out. `metadata` is the auth user's metadata bag. */
31
+ getSignedInUser(): Promise<{
32
+ id: string;
33
+ email?: string | null;
34
+ metadata?: Record<string, unknown> | null;
35
+ } | null>;
36
+ /** The file store behind pictures on a sheet or in a document. */
37
+ files: {
38
+ upload(file: File): Promise<{
39
+ fileId: string;
40
+ }>;
41
+ getBlob(fileId: string): Promise<Blob>;
42
+ };
43
+ /** Tell the person a picture did not upload. */
44
+ notifyUploadError(error: unknown): void;
45
+ /** The painted colour mode, as a React hook (re-renders on a switch). */
46
+ useThemeMode(): "light" | "dark";
47
+ }
48
+ declare function configureUniverHost(ports: UniverHostPorts): void;
49
+ declare function getUniverHost(): UniverHostPorts;
50
+
51
+ /**
52
+ * A document's or a workbook's snapshot history as a canvas tab — the keys and toggle inputs the
53
+ * editors use, and the reader the two history views use. One tab per document (`document-history`,
54
+ * keyed by the document id) and per workbook (`workbook-history`, keyed by the workbook id).
55
+ *
56
+ * Pure: no React, no canvas package, no Univer. The two `defineCanvasKind` registrations stay with
57
+ * the host app (matrx-frontend `features/canvas/host`) and lazy-load the views, so this module never
58
+ * imports a view (the cycle the old `lib/univer/historyKinds.ts` closed).
59
+ */
60
+ declare const DOCUMENT_HISTORY_KIND = "document-history";
61
+ declare const WORKBOOK_HISTORY_KIND = "workbook-history";
62
+ interface HistoryTabData {
63
+ id: string;
64
+ editable: boolean;
65
+ }
66
+ /** Structurally the host's `ToolToggleInput` (the canvas toggle the editor's History button presses). */
67
+ interface HistoryToggleInput {
68
+ kind: string;
69
+ key: string;
70
+ title: string;
71
+ data: {
72
+ id: string;
73
+ editable: boolean;
74
+ };
75
+ followTitle: true;
76
+ }
77
+ /** A tab's data as a history subject, or null when it names no subject. */
78
+ declare function readHistoryTab(data: unknown): HistoryTabData | null;
79
+ declare function documentHistoryToggleInput(documentId: string, editable: boolean, documentName?: string | null): HistoryToggleInput;
80
+ declare function workbookHistoryToggleInput(workbookId: string, editable: boolean, workbookName?: string | null): HistoryToggleInput;
81
+
82
+ /** Univer owns React roots; synchronous dispose during React commit causes races. */
83
+ declare function disposeUniverInstance(instance: {
84
+ dispose(): void;
85
+ } | null | undefined): void;
86
+
87
+ type InjectorLike$2 = {
88
+ get(id: unknown): unknown;
89
+ };
90
+ /**
91
+ * Tell Univer who is typing, so a comment thread is attributed to the
92
+ * signed-in person instead of Univer's placeholder owner.
93
+ *
94
+ * The userID MUST keep the `Owner_` prefix: Univer's built-in local
95
+ * permission service grants unit roles by user-id prefix (`isDevRole`), so a
96
+ * bare uuid gets no role and every edit is refused as "range is protected".
97
+ * Our own access (canActOn) decides editability; Univer must always see an
98
+ * owner. Guarded by identify-univer-user-keeps-owner-role.test.ts.
99
+ */
100
+ declare function identifyUniverUser(injector: InjectorLike$2): Promise<void>;
101
+ /** Univer's local permission service reads the role from this prefix. */
102
+ declare function univerOwnerId(userId: string): string;
103
+
104
+ /**
105
+ * isSnapshotMutation — the autosave dirty-filter for the Univer editors.
106
+ *
107
+ * D97: `onCommandExecuted` fires for EVERY command — including viewport
108
+ * scrolls and selection moves — so an unfiltered listener marked the doc
109
+ * dirty on mere scrolling and wrote a new snapshot row (version history +
110
+ * collab broadcast) 2.5s later. Only CommandType.MUTATION changes the data
111
+ * that a snapshot persists (Univer's own docs: OPERATION = "not saved to
112
+ * snapshot, such as modifying scroll position"). We therefore accept ONLY
113
+ * mutations, and additionally deny-list any mutation whose id marks it as
114
+ * scroll / selection / viewport bookkeeping, belt-and-braces.
115
+ */
116
+
117
+ declare function isSnapshotMutation(command: ICommandInfo): boolean;
118
+ declare function isWorkbookSnapshotMutation(command: ICommandInfo): boolean;
119
+
120
+ /**
121
+ * univerImageStore — images on a sheet or in a document live in OUR file
122
+ * store; the Univer snapshot holds only a reference (`matrx-file:<fileId>`).
123
+ *
124
+ * Why: Univer's stock image service inlines every picture as base64 into the
125
+ * snapshot, so one 2 MB photo made every autosave, history row and collab
126
+ * mutation ~2 MB. Here `saveImage` uploads the file and hands Univer a URL-type
127
+ * source; Univer's URL-image downloader turns the reference back into bytes
128
+ * (`getBlob` → object URL) when it paints. Images already inline (BASE64
129
+ * sources) are untouched and keep rendering.
130
+ */
131
+
132
+ declare const MATRX_IMAGE_PREFIX = "matrx-file:";
133
+ declare const isMatrxImageSource: (source: string) => boolean;
134
+ declare const matrxImageFileId: (source: string) => string;
135
+ type ImageStorePorts = {
136
+ upload(file: File): Promise<{
137
+ fileId: string;
138
+ }>;
139
+ getBlob(fileId: string): Promise<Blob>;
140
+ /** Called when an upload fails, so the person is told (never silent). */
141
+ onUploadError(error: unknown): void;
142
+ };
143
+ type InjectorLike$1 = {
144
+ get(id: unknown): unknown;
145
+ };
146
+ /** Pure core: the two replacements, given ports. */
147
+ declare function createMatrxImageStore(ports: ImageStorePorts): {
148
+ /** Revoke every object URL this store made (the editor is going away). */
149
+ dispose(): void;
150
+ saveImage(file: File): Promise<{
151
+ imageId: string;
152
+ imageSourceType: ImageSourceType;
153
+ source: string;
154
+ base64Cache: string;
155
+ status: ImageUploadStatusType;
156
+ }>;
157
+ download(url: string): Promise<string>;
158
+ };
159
+ /** Release the object URLs of the store wired into this Univer instance (call as the instance is disposed). */
160
+ declare function releaseMatrxImageStore(injector: object | null | undefined): void;
161
+ /** Wire the store into one Univer instance's image services. */
162
+ declare function registerMatrxImageStore(injector: InjectorLike$1, ports: ImageStorePorts): void;
163
+
164
+ /** The real file-store ports (the host's): upload, read back as a blob, tell the person on failure. */
165
+ declare const matrxImagePorts: ImageStorePorts;
166
+ /** Export: a snapshot picture source (`matrx-file:<id>` or a URL) as bytes + type, or null if unreadable. */
167
+ declare function resolveExportImage(source: string): Promise<{
168
+ bytes: Uint8Array;
169
+ extension: "png" | "jpeg" | "gif";
170
+ } | null>;
171
+ /** Import: store a picture from a file, return its file id. */
172
+ declare function uploadImportedImage(bytes: Uint8Array, extension: string): Promise<string>;
173
+
174
+ /**
175
+ * THE ONE way to replace the whole content of an open Univer editor
176
+ * (workbook or document) with a snapshot that is already SAVED: a history
177
+ * restore, "Update from Google" / "Use Google's", and a collaborator's
178
+ * replacement all arrive here.
179
+ *
180
+ * Callers save first, then call `showSavedSnapshot`. The open editor for that
181
+ * record (registered below) swaps its content in place, drops its pending
182
+ * autosave (it would write the old content back over the new one), and — in
183
+ * a collab room — tells every peer to reload the same snapshot. A caller
184
+ * never touches Univer units itself: disposing the current unit by hand left
185
+ * Univer's selection observers pointing at nothing (`getUnitId` of null).
186
+ *
187
+ * Pure registry (no Univer import), so it is testable without booting Univer.
188
+ */
189
+ type EditorRecordKind = "workbook" | "document";
190
+ /** A snapshot row as stored: its id and the Univer body. */
191
+ type SavedEditorSnapshot = {
192
+ id: string;
193
+ snapshot: unknown;
194
+ };
195
+ type EditorContentReplacer = (row: SavedEditorSnapshot) => void | Promise<void>;
196
+ /**
197
+ * The open editor of a record lends its replacer while it is mounted. The
198
+ * newest registration wins; the returned release only removes its own.
199
+ */
200
+ declare function registerOpenEditorContent(kind: EditorRecordKind, recordId: string, replace: EditorContentReplacer): () => void;
201
+ /**
202
+ * Show a saved snapshot in the record's open editor (and its collab peers).
203
+ * Returns false when no editor of the record is open in this tab — the saved
204
+ * row then simply is the content the next open loads.
205
+ */
206
+ declare function showSavedSnapshot(kind: EditorRecordKind, recordId: string, row: SavedEditorSnapshot): Promise<boolean>;
207
+ /**
208
+ * THE CONTENT-SWAP GUARD. A swap is dispose-then-create; if the create throws, the unit is gone and
209
+ * the grid would stay blank. `swap(snapshot)` is the editor's own dispose+create (it disposes
210
+ * whatever unit is open, if any). On a throw this puts the content that was open before straight
211
+ * back (synchronously — never a blank grid) and says so; the editor then reloads the latest SAVED
212
+ * version and still raises the original error, so the person is told.
213
+ */
214
+ declare function swapContentGuarded(args: {
215
+ swap: (snapshot: unknown) => void;
216
+ next: unknown;
217
+ /** What was open before (`workbook.save()` taken before the swap), or null when nothing was. */
218
+ previous: unknown | null;
219
+ }): {
220
+ ok: true;
221
+ } | {
222
+ ok: false;
223
+ error: unknown;
224
+ previousRestored: boolean;
225
+ };
226
+
227
+ interface IIconProps extends SVGAttributes<SVGSVGElement> {
228
+ /** Preserve scalable stroke widths relative to a 16×16 baseline. */
229
+ preserveStrokeWidth?: boolean;
230
+ extend?: IExtendProps;
231
+ }
232
+ interface IExtendProps {
233
+ colorChannel1?: string;
234
+ }
235
+
236
+ type InjectorLike = {
237
+ get(id: unknown): unknown;
238
+ };
239
+ /** Icons Univer's own plugins reference but do not register. */
240
+ declare const MISSING_UNIVER_ICONS: {
241
+ readonly AddImageIcon: react.ForwardRefExoticComponent<IIconProps & react.RefAttributes<SVGElement>>;
242
+ };
243
+ declare function registerMissingUniverIcons(injector: InjectorLike): void;
244
+
245
+ type UniverDependency = new (...args: never[]) => unknown;
246
+ type UniverInjector = {
247
+ has(dependency: UniverDependency): boolean;
248
+ add(dependency: [UniverDependency]): void;
249
+ };
250
+ /**
251
+ * Register services required by process-global Univer Facade observers.
252
+ *
253
+ * Facade modules can outlive the editor type that first imported them, so a
254
+ * later Univer instance may receive their lifecycle callbacks without loading
255
+ * that type's plugins. Registration is intentionally narrow: callers name only
256
+ * the observer dependencies that are safe for their instance.
257
+ */
258
+ declare function registerUniverFacadeDependencies(injector: UniverInjector, dependencies: readonly UniverDependency[]): void;
259
+
260
+ /**
261
+ * Univer's notifications go through the APP's toast path — one toaster per page.
262
+ *
263
+ * Univer's own `DesktopNotificationService` mounts a second sonner `<Toaster>`
264
+ * into its workbench the moment it is created. sonner's toast store is global,
265
+ * so with the app's Toaster also mounted every toast (ours and Univer's) showed
266
+ * twice on a workbook or document page. Replacing the service before anything
267
+ * resolves it means Univer never mounts that Toaster, and what Univer has to
268
+ * say (clipboard permission, paste limits) reaches the person through
269
+ * the host's toast port like every other message (tracked, Error Inspector, Alchemy).
270
+ *
271
+ * Call right after `createUniver`, before the first unit is created.
272
+ */
273
+
274
+ type UniverNotification = {
275
+ title: unknown;
276
+ content?: string;
277
+ type?: "success" | "info" | "warning" | "error" | "message" | "loading";
278
+ duration?: number;
279
+ };
280
+ interface NotificationReplaceableInjector {
281
+ replace?: (dependency: [unknown, unknown]) => void;
282
+ }
283
+ /** Show one Univer notification as an app toast; dismissing the disposable removes it. */
284
+ declare function showUniverNotification(params: UniverNotification): IDisposable;
285
+ declare function routeUniverNotificationsToApp(injector: NotificationReplaceableInjector | null | undefined): {
286
+ applied: boolean;
287
+ reason?: string;
288
+ };
289
+
290
+ /**
291
+ * Resolve a colour Univer hands its canvas — WITHOUT the dark-mode inversion.
292
+ *
293
+ * Univer 1.0 writes many of its own fills as THEME TOKENS, not colours: the
294
+ * page is `"gray.0"`, the desk `"gray.100"`, the page outline `"gray.200"`,
295
+ * default ink `"gray.900"` (engine-render 1.0.2 `DocBackground`, docs-ui
296
+ * `resolveDocRenderBackground`). Its `CanvasColorService` turns a token into a
297
+ * colour before anything reaches `ctx.fillStyle`; its `DumbCanvasColorService`
298
+ * does NOT — it returns `"gray.0"` as-is. A canvas IGNORES a `fillStyle` it
299
+ * cannot parse and keeps the previous one, which starts as `#000000`, so with
300
+ * the dumb service every page came out solid black and the canvas element's
301
+ * CSS background (`style.backgroundColor = "gray.100"`, also ignored) stayed
302
+ * transparent — in every browser, headed or headless, light or dark.
303
+ *
304
+ * Pure (no Univer import) so the jest test and `check:univer-doc-theme` drive
305
+ * the same function the editor installs.
306
+ */
307
+ /**
308
+ * @param color What Univer is about to paint: a theme token or a real colour.
309
+ * @param lookup The live theme (`ThemeService.getColorFromTheme`).
310
+ * @returns the token's colour from the current theme; anything else unchanged.
311
+ */
312
+ declare function resolveUniverCanvasColor(color: string, lookup: (token: string) => unknown): string;
313
+
314
+ /**
315
+ * @param apiRef Ref holding the Univer Facade API (set once the instance boots).
316
+ * @param ready True once the instance is booted and the API is usable.
317
+ */
318
+ declare function useUniverDarkModeSync(apiRef: React.RefObject<FUniver | null>, ready: boolean): void;
319
+
320
+ export { DOCUMENT_HISTORY_KIND, type EditorContentReplacer, type EditorRecordKind, type HistoryTabData, type HistoryToggleInput, type ImageStorePorts, MATRX_IMAGE_PREFIX, MISSING_UNIVER_ICONS, type NotificationReplaceableInjector, type SavedEditorSnapshot, type UniverHostPorts, type UniverToastId, WORKBOOK_HISTORY_KIND, configureUniverHost, createMatrxImageStore, disposeUniverInstance, documentHistoryToggleInput, getUniverHost, identifyUniverUser, isMatrxImageSource, isSnapshotMutation, isWorkbookSnapshotMutation, matrxImageFileId, matrxImagePorts, readHistoryTab, registerMatrxImageStore, registerMissingUniverIcons, registerOpenEditorContent, registerUniverFacadeDependencies, releaseMatrxImageStore, resolveExportImage, resolveUniverCanvasColor, routeUniverNotificationsToApp, showSavedSnapshot, showUniverNotification, swapContentGuarded, univerOwnerId, uploadImportedImage, useUniverDarkModeSync, workbookHistoryToggleInput };