@casualoffice/sheets 0.9.0 → 0.10.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.
Files changed (67) hide show
  1. package/dist/api-BI2VLYQ6.d.cts +62 -0
  2. package/dist/api-BI2VLYQ6.d.ts +62 -0
  3. package/dist/chrome.cjs +2569 -0
  4. package/dist/chrome.cjs.map +1 -0
  5. package/dist/chrome.d.cts +96 -0
  6. package/dist/chrome.d.ts +96 -0
  7. package/dist/chrome.js +2556 -0
  8. package/dist/chrome.js.map +1 -0
  9. package/dist/collab.cjs +770 -0
  10. package/dist/collab.cjs.map +1 -0
  11. package/dist/collab.d.cts +248 -0
  12. package/dist/collab.d.ts +248 -0
  13. package/dist/collab.js +737 -0
  14. package/dist/collab.js.map +1 -0
  15. package/dist/embed/embed-runtime.js +128 -128
  16. package/dist/embed.cjs +166 -0
  17. package/dist/embed.cjs.map +1 -1
  18. package/dist/embed.d.cts +78 -3
  19. package/dist/embed.d.ts +78 -3
  20. package/dist/embed.js +166 -0
  21. package/dist/embed.js.map +1 -1
  22. package/dist/index.cjs +262 -165
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +4 -3
  25. package/dist/index.d.ts +4 -3
  26. package/dist/index.js +271 -168
  27. package/dist/index.js.map +1 -1
  28. package/dist/{protocol--KyBQUjU.d.cts → protocol-Cq4Cdoyi.d.cts} +19 -2
  29. package/dist/{protocol-cEzy7S0i.d.ts → protocol-DqDaG2yG.d.ts} +19 -2
  30. package/dist/sheets.cjs +102 -16
  31. package/dist/sheets.cjs.map +1 -1
  32. package/dist/sheets.d.cts +49 -63
  33. package/dist/sheets.d.ts +49 -63
  34. package/dist/sheets.js +111 -19
  35. package/dist/sheets.js.map +1 -1
  36. package/package.json +28 -3
  37. package/src/chrome/AutoSumPicker.tsx +176 -0
  38. package/src/chrome/BordersPicker.tsx +171 -0
  39. package/src/chrome/ChromeBottom.tsx +18 -0
  40. package/src/chrome/ChromeTop.tsx +21 -0
  41. package/src/chrome/ColorPicker.tsx +220 -0
  42. package/src/chrome/FindReplace.tsx +370 -0
  43. package/src/chrome/FormulaBar.tsx +378 -0
  44. package/src/chrome/Icon.tsx +43 -0
  45. package/src/chrome/MenuBar.tsx +336 -0
  46. package/src/chrome/NameBox.tsx +347 -0
  47. package/src/chrome/SheetTabs.tsx +346 -0
  48. package/src/chrome/StatusBar.tsx +232 -0
  49. package/src/chrome/Toolbar.tsx +401 -0
  50. package/src/chrome/fonts.ts +42 -0
  51. package/src/chrome/index.ts +24 -0
  52. package/src/collab/attachCollab.ts +151 -0
  53. package/src/collab/bridge-helpers.ts +97 -0
  54. package/src/collab/bridge.ts +885 -0
  55. package/src/collab/bridge.unit.test.ts +160 -0
  56. package/src/collab/index.ts +38 -0
  57. package/src/collab/replay-retry.ts +137 -0
  58. package/src/collab/replay-retry.unit.test.ts +223 -0
  59. package/src/collab/ws-url.ts +20 -0
  60. package/src/collab/ws-url.unit.test.ts +35 -0
  61. package/src/embed/EmbedHostTransport.ts +16 -1
  62. package/src/embed/EmbedTransport.ts +16 -0
  63. package/src/embed/EmbedTransport.unit.test.ts +88 -2
  64. package/src/embed/index.ts +7 -0
  65. package/src/embed/protocol.ts +34 -0
  66. package/src/embed-runtime/index.tsx +20 -0
  67. package/src/sheets/CasualSheets.tsx +204 -33
package/dist/sheets.d.cts CHANGED
@@ -1,69 +1,13 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
- import { IWorkbookData, IRange, LocaleType, ILocales, LogLevel } from '@univerjs/core';
3
+ import { IWorkbookData, Univer, LocaleType, ILocales, LogLevel } from '@univerjs/core';
4
4
  import { defaultTheme } from '@univerjs/themes';
5
- import { FUniver } from '@univerjs/core/facade';
6
- import { o as SelectionChangedData, p as SelectionFormatStateData, T as TelemetryEventData, b as CasualErrorData, c as CommandExecuteData } from './protocol--KyBQUjU.cjs';
5
+ import { C as CasualSheetsAPI } from './api-BI2VLYQ6.cjs';
6
+ export { R as RangeRef, c as createCasualSheetsAPI } from './api-BI2VLYQ6.cjs';
7
+ import { q as SelectionChangedData, r as SelectionFormatStateData, T as TelemetryEventData, b as CasualErrorData, c as CommandExecuteData } from './protocol-Cq4Cdoyi.cjs';
8
+ import '@univerjs/core/facade';
7
9
  import './types-s_O0u6Cg.cjs';
8
10
 
9
- /**
10
- * CasualSheetsAPI — the imperative ref handed to a host via `<CasualSheets onReady>`.
11
- *
12
- * This is the SDK's stable integration surface (Excalidraw's model: props +
13
- * imperative ref). Hosts drive the editor through these methods rather than
14
- * reaching into Univer directly; `api.univer` is the documented escape hatch and
15
- * is explicitly NOT covered by semver — everything else here is.
16
- *
17
- * Scope of THIS batch (SDK restructure, Phase 1 step 3):
18
- * getSnapshot / loadSnapshot / getSelection / executeCommand / univer
19
- *
20
- * Deferred to later, clearly-scoped batches (kept off the type until they work,
21
- * so the surface never advertises a method that throws):
22
- * - importXlsx / exportXlsx — the xlsx I/O batch. importXlsx must NOT be a
23
- * plain `import('../xlsx')` here: the main tsup config is `splitting:false`,
24
- * so a dynamic import gets inlined and balloons the editor entry from ~11KB
25
- * to ~200KB of parser code for hosts that never open a file. The xlsx-I/O
26
- * batch wires it as its own chunk (and lifts the export converter out of
27
- * apps/web — the SDK xlsx module is import-only today).
28
- * - attachCollab — belongs to the storage/collab adapter phase (Phase 2);
29
- * the editor ships collab-unaware until then.
30
- */
31
-
32
- /** The active selection, as a sheet-scoped range. */
33
- interface RangeRef {
34
- /** Workbook unit id the selection belongs to. */
35
- unitId: string;
36
- /** Worksheet (sub-unit) id the selection belongs to. */
37
- sheetId: string;
38
- /** `{ startRow, startColumn, endRow, endColumn }`. */
39
- range: IRange;
40
- }
41
- interface CasualSheetsAPI {
42
- /** Current workbook as an `IWorkbookData` snapshot. `null` before the unit
43
- * is created (shouldn't happen after `onReady`, but typed defensively). */
44
- getSnapshot(): IWorkbookData | null;
45
- /** Replace the workbook with a new snapshot. Disposes the current unit and
46
- * mounts `data` as a fresh one. */
47
- loadSnapshot(data: IWorkbookData): void;
48
- /** The active selection, or `null` when there is none. */
49
- getSelection(): RangeRef | null;
50
- /** Dispatch a Univer command by id. Resolves to the command's boolean
51
- * result. */
52
- executeCommand(id: string, params?: object): Promise<boolean>;
53
- /** Imperative light/dark switch — the API equivalent of the reactive
54
- * `appearance` prop. Flips Univer's `ThemeService.setDarkMode` (canvas
55
- * colours + the `univer-dark` class Univer applies to the document root). */
56
- setTheme(appearance: 'light' | 'dark'): void;
57
- /** The FUniver facade — documented escape hatch, NOT covered by semver. */
58
- univer: FUniver;
59
- }
60
- /**
61
- * Build the imperative API over a live FUniver facade. The wrapper holds no
62
- * state of its own — every call reads the current active workbook, so it stays
63
- * correct across `loadSnapshot` swaps without the host re-acquiring the ref.
64
- */
65
- declare function createCasualSheetsAPI(univerAPI: FUniver): CasualSheetsAPI;
66
-
67
11
  interface CasualSheetsProps {
68
12
  /** Workbook snapshot to mount. Read once on initial mount; change
69
13
  * the React `key` on this component to remount with a new
@@ -85,6 +29,13 @@ interface CasualSheetsProps {
85
29
  onChange?: (snapshot: IWorkbookData) => void;
86
30
  /** Debounce window for `onChange`, in ms. Default 400. */
87
31
  onChangeDebounceMs?: number;
32
+ /** Explicit save — fired when the user presses Ctrl/Cmd+S inside the editor
33
+ * (the browser's save dialog is suppressed). The host persists the snapshot.
34
+ * Part of the "host owns storage" contract: the SDK never writes a store. */
35
+ onSave?: (snapshot: IWorkbookData) => void;
36
+ /** Fired once when the editor unmounts, with the final snapshot — the host's
37
+ * last chance to persist before the workbook is disposed. */
38
+ onExit?: (snapshot: IWorkbookData) => void;
88
39
  /** Lazy-load the feature plugins (conditional formatting, data
89
40
  * validation, hyperlinks, notes, tables, comments, drawings, sort,
90
41
  * filter, find/replace). Default `true`: plugins whose data is in
@@ -93,6 +44,29 @@ interface CasualSheetsProps {
93
44
  * minimal editor (render + formula + numfmt only) — the embed-iframe
94
45
  * build does this to stay a single self-contained bundle. */
95
46
  lazyPlugins?: boolean;
47
+ /** Escape hatch fired after the SDK registers its built-in plugins but BEFORE
48
+ * the workbook unit is created — the host can `univer.registerPlugin(...)`
49
+ * additional plugins here (e.g. an off-main formula worker via
50
+ * `UniverRPCMainThreadPlugin`, crosshair-highlight, zen-editor). Anything
51
+ * registered after `createUnit` would miss the unit's plugin-init pass, so
52
+ * register-time extras must go through this hook. Power hosts (the reference
53
+ * app) use it to share the SDK editor core while keeping their extra plugins;
54
+ * most integrators never need it. NOT covered by semver — it hands you the
55
+ * raw `Univer` instance. */
56
+ onBeforeCreateUnit?: (univer: Univer) => void;
57
+ /** Off-main formula compute. By default the formula engine runs on the MAIN
58
+ * thread (fine for typical sheets, zero host setup). Provide a Web Worker (or
59
+ * its URL) to move compute off-thread so paste / sort / fill on large
60
+ * workbooks don't freeze the UI: the SDK then registers the formula plugins
61
+ * with `notExecuteFormula` and wires `UniverRPCMainThreadPlugin` to your
62
+ * worker. The host owns the worker (the SDK never bundles one — that's brittle
63
+ * across bundlers) and must have `@univerjs/rpc` installed. The worker script
64
+ * is the standard Univer formula worker (see the reference app's
65
+ * `apps/web/src/univer/formula-worker.ts`). */
66
+ formula?: {
67
+ /** A constructed `Worker`, or a URL/string the RPC plugin loads. */
68
+ worker?: Worker | string;
69
+ };
96
70
  /** Locale identifier. Defaults to `LocaleType.EN_US`. */
97
71
  locale?: LocaleType;
98
72
  /** Locale string bundle. Optional — Univer's default English
@@ -119,6 +93,18 @@ interface CasualSheetsProps {
119
93
  * Univer's design — a host that embeds the editor inside a light page
120
94
  * should scope the editor or accept the global dark CSS. */
121
95
  appearance?: 'light' | 'dark';
96
+ /** Office chrome rendered around the grid:
97
+ * - `'none'` (default): bare grid — the host supplies its own chrome.
98
+ * - `'minimal'` / `'full'`: the built-in Office shell — a menu bar
99
+ * (Edit/Insert/Format/Data/View), a formatting toolbar (font family/size,
100
+ * bold/italic/underline/strike, text & fill colour, borders, h/v align,
101
+ * wrap, merge, number formats, clear format, AutoSum), a formula bar with a
102
+ * name box + function autocomplete, a worksheet tab strip (switch/add/
103
+ * rename/delete), and a status bar (Average/Count/Numerical Count/Min/Max/
104
+ * Sum + zoom). All driven through the facade, themed via `--cs-chrome-*`
105
+ * (light/dark). `'minimal'` and `'full'` currently render the same shell;
106
+ * `'full'` is where richer panels (find/replace, charts, …) will land. */
107
+ chrome?: 'none' | 'minimal' | 'full';
122
108
  /** Container style. Default fills the parent. */
123
109
  style?: CSSProperties;
124
110
  /** Container className for additional styling hooks. */
@@ -126,7 +112,7 @@ interface CasualSheetsProps {
126
112
  /** Optional test id for the host container. */
127
113
  testId?: string;
128
114
  }
129
- declare function CasualSheets({ initialData, onReady, onChange, onChangeDebounceMs, lazyPlugins, locale, locales, logLevel, ui, theme, appearance, style, className, testId, }: CasualSheetsProps): react.JSX.Element;
115
+ declare function CasualSheets({ initialData, onReady, onChange, onChangeDebounceMs, onSave, onExit, lazyPlugins, onBeforeCreateUnit, formula, locale, locales, logLevel, ui, theme, appearance, chrome, style, className, testId, }: CasualSheetsProps): react.JSX.Element;
130
116
 
131
117
  /** What the host-side load/save handlers consume + return. The wrapper
132
118
  * binds these to the host's FileSource via simple adapters. */
@@ -174,4 +160,4 @@ interface CasualSheetsIframeProps {
174
160
  }
175
161
  declare const CasualSheetsIframe: react.ForwardRefExoticComponent<CasualSheetsIframeProps & react.RefAttributes<CasualSheetsIframeRef>>;
176
162
 
177
- export { CasualSheets, type CasualSheetsAPI, CasualSheetsIframe, type CasualSheetsIframeProps, type CasualSheetsIframeRef, type CasualSheetsProps, type HostFileBridge, type RangeRef, createCasualSheetsAPI };
163
+ export { CasualSheets, CasualSheetsAPI, CasualSheetsIframe, type CasualSheetsIframeProps, type CasualSheetsIframeRef, type CasualSheetsProps, type HostFileBridge };
package/dist/sheets.d.ts CHANGED
@@ -1,69 +1,13 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
- import { IWorkbookData, IRange, LocaleType, ILocales, LogLevel } from '@univerjs/core';
3
+ import { IWorkbookData, Univer, LocaleType, ILocales, LogLevel } from '@univerjs/core';
4
4
  import { defaultTheme } from '@univerjs/themes';
5
- import { FUniver } from '@univerjs/core/facade';
6
- import { o as SelectionChangedData, p as SelectionFormatStateData, T as TelemetryEventData, b as CasualErrorData, c as CommandExecuteData } from './protocol-cEzy7S0i.js';
5
+ import { C as CasualSheetsAPI } from './api-BI2VLYQ6.js';
6
+ export { R as RangeRef, c as createCasualSheetsAPI } from './api-BI2VLYQ6.js';
7
+ import { q as SelectionChangedData, r as SelectionFormatStateData, T as TelemetryEventData, b as CasualErrorData, c as CommandExecuteData } from './protocol-DqDaG2yG.js';
8
+ import '@univerjs/core/facade';
7
9
  import './types-s_O0u6Cg.js';
8
10
 
9
- /**
10
- * CasualSheetsAPI — the imperative ref handed to a host via `<CasualSheets onReady>`.
11
- *
12
- * This is the SDK's stable integration surface (Excalidraw's model: props +
13
- * imperative ref). Hosts drive the editor through these methods rather than
14
- * reaching into Univer directly; `api.univer` is the documented escape hatch and
15
- * is explicitly NOT covered by semver — everything else here is.
16
- *
17
- * Scope of THIS batch (SDK restructure, Phase 1 step 3):
18
- * getSnapshot / loadSnapshot / getSelection / executeCommand / univer
19
- *
20
- * Deferred to later, clearly-scoped batches (kept off the type until they work,
21
- * so the surface never advertises a method that throws):
22
- * - importXlsx / exportXlsx — the xlsx I/O batch. importXlsx must NOT be a
23
- * plain `import('../xlsx')` here: the main tsup config is `splitting:false`,
24
- * so a dynamic import gets inlined and balloons the editor entry from ~11KB
25
- * to ~200KB of parser code for hosts that never open a file. The xlsx-I/O
26
- * batch wires it as its own chunk (and lifts the export converter out of
27
- * apps/web — the SDK xlsx module is import-only today).
28
- * - attachCollab — belongs to the storage/collab adapter phase (Phase 2);
29
- * the editor ships collab-unaware until then.
30
- */
31
-
32
- /** The active selection, as a sheet-scoped range. */
33
- interface RangeRef {
34
- /** Workbook unit id the selection belongs to. */
35
- unitId: string;
36
- /** Worksheet (sub-unit) id the selection belongs to. */
37
- sheetId: string;
38
- /** `{ startRow, startColumn, endRow, endColumn }`. */
39
- range: IRange;
40
- }
41
- interface CasualSheetsAPI {
42
- /** Current workbook as an `IWorkbookData` snapshot. `null` before the unit
43
- * is created (shouldn't happen after `onReady`, but typed defensively). */
44
- getSnapshot(): IWorkbookData | null;
45
- /** Replace the workbook with a new snapshot. Disposes the current unit and
46
- * mounts `data` as a fresh one. */
47
- loadSnapshot(data: IWorkbookData): void;
48
- /** The active selection, or `null` when there is none. */
49
- getSelection(): RangeRef | null;
50
- /** Dispatch a Univer command by id. Resolves to the command's boolean
51
- * result. */
52
- executeCommand(id: string, params?: object): Promise<boolean>;
53
- /** Imperative light/dark switch — the API equivalent of the reactive
54
- * `appearance` prop. Flips Univer's `ThemeService.setDarkMode` (canvas
55
- * colours + the `univer-dark` class Univer applies to the document root). */
56
- setTheme(appearance: 'light' | 'dark'): void;
57
- /** The FUniver facade — documented escape hatch, NOT covered by semver. */
58
- univer: FUniver;
59
- }
60
- /**
61
- * Build the imperative API over a live FUniver facade. The wrapper holds no
62
- * state of its own — every call reads the current active workbook, so it stays
63
- * correct across `loadSnapshot` swaps without the host re-acquiring the ref.
64
- */
65
- declare function createCasualSheetsAPI(univerAPI: FUniver): CasualSheetsAPI;
66
-
67
11
  interface CasualSheetsProps {
68
12
  /** Workbook snapshot to mount. Read once on initial mount; change
69
13
  * the React `key` on this component to remount with a new
@@ -85,6 +29,13 @@ interface CasualSheetsProps {
85
29
  onChange?: (snapshot: IWorkbookData) => void;
86
30
  /** Debounce window for `onChange`, in ms. Default 400. */
87
31
  onChangeDebounceMs?: number;
32
+ /** Explicit save — fired when the user presses Ctrl/Cmd+S inside the editor
33
+ * (the browser's save dialog is suppressed). The host persists the snapshot.
34
+ * Part of the "host owns storage" contract: the SDK never writes a store. */
35
+ onSave?: (snapshot: IWorkbookData) => void;
36
+ /** Fired once when the editor unmounts, with the final snapshot — the host's
37
+ * last chance to persist before the workbook is disposed. */
38
+ onExit?: (snapshot: IWorkbookData) => void;
88
39
  /** Lazy-load the feature plugins (conditional formatting, data
89
40
  * validation, hyperlinks, notes, tables, comments, drawings, sort,
90
41
  * filter, find/replace). Default `true`: plugins whose data is in
@@ -93,6 +44,29 @@ interface CasualSheetsProps {
93
44
  * minimal editor (render + formula + numfmt only) — the embed-iframe
94
45
  * build does this to stay a single self-contained bundle. */
95
46
  lazyPlugins?: boolean;
47
+ /** Escape hatch fired after the SDK registers its built-in plugins but BEFORE
48
+ * the workbook unit is created — the host can `univer.registerPlugin(...)`
49
+ * additional plugins here (e.g. an off-main formula worker via
50
+ * `UniverRPCMainThreadPlugin`, crosshair-highlight, zen-editor). Anything
51
+ * registered after `createUnit` would miss the unit's plugin-init pass, so
52
+ * register-time extras must go through this hook. Power hosts (the reference
53
+ * app) use it to share the SDK editor core while keeping their extra plugins;
54
+ * most integrators never need it. NOT covered by semver — it hands you the
55
+ * raw `Univer` instance. */
56
+ onBeforeCreateUnit?: (univer: Univer) => void;
57
+ /** Off-main formula compute. By default the formula engine runs on the MAIN
58
+ * thread (fine for typical sheets, zero host setup). Provide a Web Worker (or
59
+ * its URL) to move compute off-thread so paste / sort / fill on large
60
+ * workbooks don't freeze the UI: the SDK then registers the formula plugins
61
+ * with `notExecuteFormula` and wires `UniverRPCMainThreadPlugin` to your
62
+ * worker. The host owns the worker (the SDK never bundles one — that's brittle
63
+ * across bundlers) and must have `@univerjs/rpc` installed. The worker script
64
+ * is the standard Univer formula worker (see the reference app's
65
+ * `apps/web/src/univer/formula-worker.ts`). */
66
+ formula?: {
67
+ /** A constructed `Worker`, or a URL/string the RPC plugin loads. */
68
+ worker?: Worker | string;
69
+ };
96
70
  /** Locale identifier. Defaults to `LocaleType.EN_US`. */
97
71
  locale?: LocaleType;
98
72
  /** Locale string bundle. Optional — Univer's default English
@@ -119,6 +93,18 @@ interface CasualSheetsProps {
119
93
  * Univer's design — a host that embeds the editor inside a light page
120
94
  * should scope the editor or accept the global dark CSS. */
121
95
  appearance?: 'light' | 'dark';
96
+ /** Office chrome rendered around the grid:
97
+ * - `'none'` (default): bare grid — the host supplies its own chrome.
98
+ * - `'minimal'` / `'full'`: the built-in Office shell — a menu bar
99
+ * (Edit/Insert/Format/Data/View), a formatting toolbar (font family/size,
100
+ * bold/italic/underline/strike, text & fill colour, borders, h/v align,
101
+ * wrap, merge, number formats, clear format, AutoSum), a formula bar with a
102
+ * name box + function autocomplete, a worksheet tab strip (switch/add/
103
+ * rename/delete), and a status bar (Average/Count/Numerical Count/Min/Max/
104
+ * Sum + zoom). All driven through the facade, themed via `--cs-chrome-*`
105
+ * (light/dark). `'minimal'` and `'full'` currently render the same shell;
106
+ * `'full'` is where richer panels (find/replace, charts, …) will land. */
107
+ chrome?: 'none' | 'minimal' | 'full';
122
108
  /** Container style. Default fills the parent. */
123
109
  style?: CSSProperties;
124
110
  /** Container className for additional styling hooks. */
@@ -126,7 +112,7 @@ interface CasualSheetsProps {
126
112
  /** Optional test id for the host container. */
127
113
  testId?: string;
128
114
  }
129
- declare function CasualSheets({ initialData, onReady, onChange, onChangeDebounceMs, lazyPlugins, locale, locales, logLevel, ui, theme, appearance, style, className, testId, }: CasualSheetsProps): react.JSX.Element;
115
+ declare function CasualSheets({ initialData, onReady, onChange, onChangeDebounceMs, onSave, onExit, lazyPlugins, onBeforeCreateUnit, formula, locale, locales, logLevel, ui, theme, appearance, chrome, style, className, testId, }: CasualSheetsProps): react.JSX.Element;
130
116
 
131
117
  /** What the host-side load/save handlers consume + return. The wrapper
132
118
  * binds these to the host's FileSource via simple adapters. */
@@ -174,4 +160,4 @@ interface CasualSheetsIframeProps {
174
160
  }
175
161
  declare const CasualSheetsIframe: react.ForwardRefExoticComponent<CasualSheetsIframeProps & react.RefAttributes<CasualSheetsIframeRef>>;
176
162
 
177
- export { CasualSheets, type CasualSheetsAPI, CasualSheetsIframe, type CasualSheetsIframeProps, type CasualSheetsIframeRef, type CasualSheetsProps, type HostFileBridge, type RangeRef, createCasualSheetsAPI };
163
+ export { CasualSheets, CasualSheetsAPI, CasualSheetsIframe, type CasualSheetsIframeProps, type CasualSheetsIframeRef, type CasualSheetsProps, type HostFileBridge };
package/dist/sheets.js CHANGED
@@ -3,7 +3,13 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
 
5
5
  // src/sheets/CasualSheets.tsx
6
- import { useEffect, useRef } from "react";
6
+ import {
7
+ lazy,
8
+ Suspense,
9
+ useEffect,
10
+ useRef,
11
+ useState
12
+ } from "react";
7
13
  import {
8
14
  ICommandService,
9
15
  LocaleType,
@@ -21,7 +27,7 @@ import { UniverDocsPlugin } from "@univerjs/docs";
21
27
  import { UniverDocsUIPlugin } from "@univerjs/docs-ui";
22
28
  import { UniverSheetsPlugin } from "@univerjs/sheets";
23
29
  import { UniverSheetsUIPlugin } from "@univerjs/sheets-ui";
24
- import { UniverSheetsFormulaPlugin } from "@univerjs/sheets-formula";
30
+ import { UniverSheetsFormulaPlugin, CalculationMode } from "@univerjs/sheets-formula";
25
31
  import { UniverSheetsFormulaUIPlugin } from "@univerjs/sheets-formula-ui";
26
32
  import { UniverSheetsNumfmtPlugin } from "@univerjs/sheets-numfmt";
27
33
  import { UniverSheetsNumfmtUIPlugin } from "@univerjs/sheets-numfmt-ui";
@@ -238,7 +244,13 @@ function snapshotHasHyperlinks(snapshot) {
238
244
  }
239
245
 
240
246
  // src/sheets/CasualSheets.tsx
241
- import { jsx } from "react/jsx-runtime";
247
+ import { jsx, jsxs } from "react/jsx-runtime";
248
+ var ChromeTop = lazy(
249
+ () => import("@casualoffice/sheets/chrome").then((m) => ({ default: m.ChromeTop }))
250
+ );
251
+ var ChromeBottom = lazy(
252
+ () => import("@casualoffice/sheets/chrome").then((m) => ({ default: m.ChromeBottom }))
253
+ );
242
254
  var DEFAULT_STYLE = {
243
255
  width: "100%",
244
256
  height: "100%",
@@ -255,13 +267,18 @@ function CasualSheets({
255
267
  onReady,
256
268
  onChange,
257
269
  onChangeDebounceMs = 400,
270
+ onSave,
271
+ onExit,
258
272
  lazyPlugins = true,
273
+ onBeforeCreateUnit,
274
+ formula,
259
275
  locale = LocaleType.EN_US,
260
276
  locales,
261
277
  logLevel = LogLevel.WARN,
262
278
  ui,
263
279
  theme = defaultTheme,
264
280
  appearance = "light",
281
+ chrome = "none",
265
282
  style,
266
283
  className,
267
284
  testId = "casual-sheets"
@@ -270,7 +287,12 @@ function CasualSheets({
270
287
  const onChangeRef = useRef(onChange);
271
288
  onChangeRef.current = onChange;
272
289
  const hasOnChange = useRef(!!onChange).current;
290
+ const onSaveRef = useRef(onSave);
291
+ onSaveRef.current = onSave;
292
+ const onExitRef = useRef(onExit);
293
+ onExitRef.current = onExit;
273
294
  const apiRef = useRef(null);
295
+ const [chromeApi, setChromeApi] = useState(null);
274
296
  useEffect(() => {
275
297
  const container = hostRef.current;
276
298
  if (!container) return;
@@ -281,22 +303,38 @@ function CasualSheets({
281
303
  logLevel
282
304
  });
283
305
  const uiOpts = { ...DEFAULT_UI, ...ui, container };
284
- univer.registerPlugin(UniverRenderEnginePlugin);
285
- univer.registerPlugin(UniverFormulaEnginePlugin);
286
- univer.registerPlugin(UniverUIPlugin, uiOpts);
287
- univer.registerPlugin(UniverDocsPlugin);
288
- univer.registerPlugin(UniverDocsUIPlugin);
289
- univer.registerPlugin(UniverSheetsPlugin);
290
- univer.registerPlugin(UniverSheetsUIPlugin);
291
- univer.registerPlugin(UniverSheetsFormulaPlugin);
292
- univer.registerPlugin(UniverSheetsFormulaUIPlugin);
293
- univer.registerPlugin(UniverSheetsNumfmtPlugin);
294
- univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
295
- if (lazyPlugins) setUniverForLazyLoad(univer);
306
+ const offMain = !!formula?.worker;
296
307
  let cancelled = false;
297
308
  let changeTimer = null;
298
309
  let changeSub;
299
310
  void (async () => {
311
+ let RPCMainThreadPlugin = null;
312
+ if (offMain && formula?.worker) {
313
+ RPCMainThreadPlugin = (await import("@univerjs/rpc")).UniverRPCMainThreadPlugin;
314
+ if (cancelled) return;
315
+ }
316
+ univer.registerPlugin(UniverRenderEnginePlugin);
317
+ univer.registerPlugin(
318
+ UniverFormulaEnginePlugin,
319
+ offMain ? { notExecuteFormula: true } : void 0
320
+ );
321
+ if (RPCMainThreadPlugin && formula?.worker) {
322
+ univer.registerPlugin(RPCMainThreadPlugin, { workerURL: formula.worker });
323
+ }
324
+ univer.registerPlugin(UniverUIPlugin, uiOpts);
325
+ univer.registerPlugin(UniverDocsPlugin);
326
+ univer.registerPlugin(UniverDocsUIPlugin);
327
+ univer.registerPlugin(UniverSheetsPlugin, offMain ? { notExecuteFormula: true } : void 0);
328
+ univer.registerPlugin(UniverSheetsUIPlugin);
329
+ univer.registerPlugin(
330
+ UniverSheetsFormulaPlugin,
331
+ offMain ? { notExecuteFormula: true, initialFormulaComputing: CalculationMode.NO_CALCULATION } : void 0
332
+ );
333
+ univer.registerPlugin(UniverSheetsFormulaUIPlugin);
334
+ univer.registerPlugin(UniverSheetsNumfmtPlugin);
335
+ univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
336
+ if (lazyPlugins) setUniverForLazyLoad(univer);
337
+ onBeforeCreateUnit?.(univer);
300
338
  if (lazyPlugins) {
301
339
  await eagerLoadForSnapshot(univer, initialData);
302
340
  if (cancelled) return;
@@ -304,6 +342,7 @@ function CasualSheets({
304
342
  univer.createUnit(UniverInstanceType.UNIVER_SHEET, initialData);
305
343
  const api = createCasualSheetsAPI(FUniver.newAPI(univer));
306
344
  apiRef.current = api;
345
+ if (!cancelled && chrome !== "none") setChromeApi(api);
307
346
  applyAppearance(api, container, appearance);
308
347
  onReady?.(api);
309
348
  if (hasOnChange) {
@@ -324,7 +363,12 @@ function CasualSheets({
324
363
  cancelled = true;
325
364
  if (changeTimer) clearTimeout(changeTimer);
326
365
  changeSub?.dispose();
366
+ if (onExitRef.current) {
367
+ const snap = apiRef.current?.getSnapshot();
368
+ if (snap) onExitRef.current(snap);
369
+ }
327
370
  apiRef.current = null;
371
+ setChromeApi(null);
328
372
  if (lazyPlugins) setUniverForLazyLoad(null);
329
373
  const toDispose = univer;
330
374
  queueMicrotask(() => toDispose.dispose());
@@ -336,13 +380,55 @@ function CasualSheets({
336
380
  if (!api || !container) return;
337
381
  applyAppearance(api, container, appearance);
338
382
  }, [appearance]);
339
- return /* @__PURE__ */ jsx(
383
+ const onKeyDownCapture = (e) => {
384
+ if ((e.metaKey || e.ctrlKey) && (e.key === "s" || e.key === "S")) {
385
+ e.preventDefault();
386
+ const snap = apiRef.current?.getSnapshot();
387
+ if (snap) onSaveRef.current?.(snap);
388
+ }
389
+ };
390
+ if (chrome === "none") {
391
+ return /* @__PURE__ */ jsx(
392
+ "div",
393
+ {
394
+ ref: hostRef,
395
+ onKeyDownCapture,
396
+ style: { ...DEFAULT_STYLE, ...style },
397
+ className,
398
+ "data-testid": testId
399
+ }
400
+ );
401
+ }
402
+ const dark = appearance === "dark";
403
+ const chromeVars = {
404
+ "--cs-chrome-bg": dark ? "#2a2e35" : "#eef1f5",
405
+ "--cs-chrome-fg": dark ? "#e6e6e6" : "#201f1e",
406
+ "--cs-chrome-muted": dark ? "#b0b3ba" : "#605e5c",
407
+ "--cs-chrome-border": dark ? "#32363d" : "#e6e9ee",
408
+ "--cs-chrome-input-bg": dark ? "#23262c" : "#ffffff",
409
+ "--cs-chrome-hover": dark ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)",
410
+ // accent (design-system #0e7490) for active toggle states.
411
+ "--cs-chrome-active": dark ? "rgba(21,151,186,0.22)" : "#e6f3f7",
412
+ "--cs-chrome-active-fg": dark ? "#7fd3e6" : "#0e7490"
413
+ };
414
+ return /* @__PURE__ */ jsxs(
340
415
  "div",
341
416
  {
342
- ref: hostRef,
343
- style: { ...DEFAULT_STYLE, ...style },
344
417
  className,
345
- "data-testid": testId
418
+ "data-testid": testId,
419
+ onKeyDownCapture,
420
+ style: {
421
+ ...DEFAULT_STYLE,
422
+ ...chromeVars,
423
+ ...style,
424
+ display: "flex",
425
+ flexDirection: "column"
426
+ },
427
+ children: [
428
+ /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ChromeTop, { api: chromeApi }) }),
429
+ /* @__PURE__ */ jsx("div", { ref: hostRef, style: { flex: "1 1 auto", minHeight: 0, position: "relative" } }),
430
+ /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ChromeBottom, { api: chromeApi }) })
431
+ ]
346
432
  }
347
433
  );
348
434
  }
@@ -477,6 +563,12 @@ var EmbedHostTransport = class {
477
563
  }
478
564
  return;
479
565
  }
566
+ case "casual.save.notify":
567
+ this.handlers.onSaveNotify?.(env.data);
568
+ return;
569
+ case "casual.exit":
570
+ this.handlers.onExit?.(env.data);
571
+ return;
480
572
  case "casual.selection.changed":
481
573
  this.handlers.onSelectionChanged?.(env.data);
482
574
  return;