@schnsrw/casual-sheets 0.2.0 → 0.3.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/dist/sheets.js ADDED
@@ -0,0 +1,89 @@
1
+ // src/sheets/CasualSheets.tsx
2
+ import { useEffect, useRef } from "react";
3
+ import {
4
+ LocaleType,
5
+ LogLevel,
6
+ Univer,
7
+ UniverInstanceType
8
+ } from "@univerjs/core";
9
+ import { FUniver } from "@univerjs/core/facade";
10
+ import { defaultTheme } from "@univerjs/themes";
11
+ import { UniverRenderEnginePlugin } from "@univerjs/engine-render";
12
+ import { UniverFormulaEnginePlugin } from "@univerjs/engine-formula";
13
+ import { UniverUIPlugin } from "@univerjs/ui";
14
+ import { UniverDocsPlugin } from "@univerjs/docs";
15
+ import { UniverDocsUIPlugin } from "@univerjs/docs-ui";
16
+ import { UniverSheetsPlugin } from "@univerjs/sheets";
17
+ import { UniverSheetsUIPlugin } from "@univerjs/sheets-ui";
18
+ import { UniverSheetsFormulaPlugin } from "@univerjs/sheets-formula";
19
+ import { UniverSheetsFormulaUIPlugin } from "@univerjs/sheets-formula-ui";
20
+ import { UniverSheetsNumfmtPlugin } from "@univerjs/sheets-numfmt";
21
+ import { UniverSheetsNumfmtUIPlugin } from "@univerjs/sheets-numfmt-ui";
22
+ import { jsx } from "react/jsx-runtime";
23
+ var DEFAULT_STYLE = {
24
+ width: "100%",
25
+ height: "100%",
26
+ position: "relative"
27
+ };
28
+ var DEFAULT_UI = {
29
+ header: false,
30
+ toolbar: false,
31
+ footer: false,
32
+ contextMenu: true
33
+ };
34
+ function CasualSheets({
35
+ initialData,
36
+ onReady,
37
+ locale = LocaleType.EN_US,
38
+ locales,
39
+ logLevel = LogLevel.WARN,
40
+ ui,
41
+ theme = defaultTheme,
42
+ style,
43
+ className,
44
+ testId = "casual-sheets"
45
+ }) {
46
+ const hostRef = useRef(null);
47
+ useEffect(() => {
48
+ const container = hostRef.current;
49
+ if (!container) return;
50
+ const univer = new Univer({
51
+ theme,
52
+ locale,
53
+ locales,
54
+ logLevel
55
+ });
56
+ const uiOpts = { ...DEFAULT_UI, ...ui, container };
57
+ univer.registerPlugin(UniverRenderEnginePlugin);
58
+ univer.registerPlugin(UniverFormulaEnginePlugin);
59
+ univer.registerPlugin(UniverUIPlugin, uiOpts);
60
+ univer.registerPlugin(UniverDocsPlugin);
61
+ univer.registerPlugin(UniverDocsUIPlugin);
62
+ univer.registerPlugin(UniverSheetsPlugin);
63
+ univer.registerPlugin(UniverSheetsUIPlugin);
64
+ univer.registerPlugin(UniverSheetsFormulaPlugin);
65
+ univer.registerPlugin(UniverSheetsFormulaUIPlugin);
66
+ univer.registerPlugin(UniverSheetsNumfmtPlugin);
67
+ univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
68
+ univer.createUnit(UniverInstanceType.UNIVER_SHEET, initialData);
69
+ const api = FUniver.newAPI(univer);
70
+ onReady?.(api, univer);
71
+ return () => {
72
+ const toDispose = univer;
73
+ queueMicrotask(() => toDispose.dispose());
74
+ };
75
+ }, []);
76
+ return /* @__PURE__ */ jsx(
77
+ "div",
78
+ {
79
+ ref: hostRef,
80
+ style: { ...DEFAULT_STYLE, ...style },
81
+ className,
82
+ "data-testid": testId
83
+ }
84
+ );
85
+ }
86
+ export {
87
+ CasualSheets
88
+ };
89
+ //# sourceMappingURL=sheets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sheets/CasualSheets.tsx"],"sourcesContent":["/**\n * CasualSheets — minimal React wrapper around Univer Sheets.\n *\n * Boots Univer with the eager plugin set (render + formula engine +\n * UI + docs + sheets + sheets-ui + sheets-formula + numfmt), mounts a\n * single workbook unit from `initialData`, and surfaces the\n * `FUniver` API to the host via `onReady`.\n *\n * Intentionally NOT included (host can layer on top via FUniver):\n * - Lazy plugin loading (conditional formatting, drawings, sort,\n * filter, hyperlinks, tables, comments, find/replace, …). Host\n * calls `univer.registerPlugin(...)` after `onReady`.\n * - Formula compute via Web Worker — `notExecuteFormula: false`\n * is the default; the formula engine runs on the main thread.\n * Host wires `UniverRPCMainThreadPlugin` + a worker URL itself\n * if it wants the off-main path.\n * - Snapshot swap (this component mounts a snapshot once; change\n * the React `key` to remount with a fresh snapshot).\n * - Paste-merge hooks, dev helpers, zoom-shortcut overrides,\n * facade extensions — all app concerns.\n *\n * Styles: host must import `@schnsrw/casual-sheets/styles.css`\n * (or the per-plugin CSS) once at app boot. Tree-shaking strips the\n * styles from this entry if the host doesn't reach the styles export.\n */\n\nimport { useEffect, useRef, type CSSProperties } from 'react';\nimport {\n LocaleType,\n LogLevel,\n Univer,\n UniverInstanceType,\n type IWorkbookData,\n type ILocales,\n} from '@univerjs/core';\nimport { FUniver } from '@univerjs/core/facade';\nimport { defaultTheme } from '@univerjs/themes';\n\nimport { UniverRenderEnginePlugin } from '@univerjs/engine-render';\nimport { UniverFormulaEnginePlugin } from '@univerjs/engine-formula';\nimport { UniverUIPlugin } from '@univerjs/ui';\nimport { UniverDocsPlugin } from '@univerjs/docs';\nimport { UniverDocsUIPlugin } from '@univerjs/docs-ui';\nimport { UniverSheetsPlugin } from '@univerjs/sheets';\nimport { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';\nimport { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';\nimport { UniverSheetsFormulaUIPlugin } from '@univerjs/sheets-formula-ui';\nimport { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';\nimport { UniverSheetsNumfmtUIPlugin } from '@univerjs/sheets-numfmt-ui';\n\nexport interface CasualSheetsProps {\n /** Workbook snapshot to mount. Read once on initial mount; change\n * the React `key` on this component to remount with a new\n * workbook. */\n initialData: IWorkbookData;\n /** Called after the workbook unit is created. The FUniver API is\n * how the host drives the sheet (read cells, mutate, listen for\n * events, register additional plugins). */\n onReady?: (api: FUniver, univer: Univer) => void;\n /** Locale identifier. Defaults to `LocaleType.EN_US`. */\n locale?: LocaleType;\n /** Locale string bundle. Optional — Univer's default English\n * strings load if omitted. */\n locales?: ILocales;\n /** Univer log level. Defaults to `LogLevel.WARN`. */\n logLevel?: LogLevel;\n /** Univer chrome toggles. Defaults: header / toolbar / footer off,\n * context menu on — matches Casual Sheets' embedded shape. */\n ui?: {\n header?: boolean;\n toolbar?: boolean;\n footer?: boolean;\n contextMenu?: boolean;\n };\n /** Override the theme. Defaults to Univer's `defaultTheme`. */\n theme?: typeof defaultTheme;\n /** Container style. Default fills the parent. */\n style?: CSSProperties;\n /** Container className for additional styling hooks. */\n className?: string;\n /** Optional test id for the host container. */\n testId?: string;\n}\n\nconst DEFAULT_STYLE: CSSProperties = {\n width: '100%',\n height: '100%',\n position: 'relative',\n};\n\nconst DEFAULT_UI = {\n header: false,\n toolbar: false,\n footer: false,\n contextMenu: true,\n};\n\nexport function CasualSheets({\n initialData,\n onReady,\n locale = LocaleType.EN_US,\n locales,\n logLevel = LogLevel.WARN,\n ui,\n theme = defaultTheme,\n style,\n className,\n testId = 'casual-sheets',\n}: CasualSheetsProps) {\n const hostRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const container = hostRef.current;\n if (!container) return;\n\n const univer = new Univer({\n theme,\n locale,\n locales,\n logLevel,\n });\n\n const uiOpts = { ...DEFAULT_UI, ...ui, container };\n\n univer.registerPlugin(UniverRenderEnginePlugin);\n univer.registerPlugin(UniverFormulaEnginePlugin);\n univer.registerPlugin(UniverUIPlugin, uiOpts);\n univer.registerPlugin(UniverDocsPlugin);\n univer.registerPlugin(UniverDocsUIPlugin);\n univer.registerPlugin(UniverSheetsPlugin);\n univer.registerPlugin(UniverSheetsUIPlugin);\n univer.registerPlugin(UniverSheetsFormulaPlugin);\n univer.registerPlugin(UniverSheetsFormulaUIPlugin);\n univer.registerPlugin(UniverSheetsNumfmtPlugin);\n univer.registerPlugin(UniverSheetsNumfmtUIPlugin);\n\n univer.createUnit(UniverInstanceType.UNIVER_SHEET, initialData);\n\n const api = FUniver.newAPI(univer);\n onReady?.(api, univer);\n\n return () => {\n // Defer disposal off the React render phase — Univer owns its\n // own React root, and a synchronous unmount mid-render warns\n // and leaves the canvas detached.\n const toDispose = univer;\n queueMicrotask(() => toDispose.dispose());\n };\n // initialData is intentionally NOT in the dep array — the wrapper\n // mounts the snapshot once. Hosts that need to swap workbooks\n // change the React `key` to force a remount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div\n ref={hostRef}\n style={{ ...DEFAULT_STYLE, ...style }}\n className={className}\n data-testid={testId}\n />\n );\n}\n"],"mappings":";AA0BA,SAAS,WAAW,cAAkC;AACtD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAE7B,SAAS,gCAAgC;AACzC,SAAS,iCAAiC;AAC1C,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAC1C,SAAS,mCAAmC;AAC5C,SAAS,gCAAgC;AACzC,SAAS,kCAAkC;AA2GvC;AAvEJ,IAAM,gBAA+B;AAAA,EACnC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AACZ;AAEA,IAAM,aAAa;AAAA,EACjB,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AACf;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,SAAS,WAAW;AAAA,EACpB;AAAA,EACA,WAAW,SAAS;AAAA,EACpB;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAsB;AACpB,QAAM,UAAU,OAAuB,IAAI;AAE3C,YAAU,MAAM;AACd,UAAM,YAAY,QAAQ;AAC1B,QAAI,CAAC,UAAW;AAEhB,UAAM,SAAS,IAAI,OAAO;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,SAAS,EAAE,GAAG,YAAY,GAAG,IAAI,UAAU;AAEjD,WAAO,eAAe,wBAAwB;AAC9C,WAAO,eAAe,yBAAyB;AAC/C,WAAO,eAAe,gBAAgB,MAAM;AAC5C,WAAO,eAAe,gBAAgB;AACtC,WAAO,eAAe,kBAAkB;AACxC,WAAO,eAAe,kBAAkB;AACxC,WAAO,eAAe,oBAAoB;AAC1C,WAAO,eAAe,yBAAyB;AAC/C,WAAO,eAAe,2BAA2B;AACjD,WAAO,eAAe,wBAAwB;AAC9C,WAAO,eAAe,0BAA0B;AAEhD,WAAO,WAAW,mBAAmB,cAAc,WAAW;AAE9D,UAAM,MAAM,QAAQ,OAAO,MAAM;AACjC,cAAU,KAAK,MAAM;AAErB,WAAO,MAAM;AAIX,YAAM,YAAY;AAClB,qBAAe,MAAM,UAAU,QAAQ,CAAC;AAAA,IAC1C;AAAA,EAKF,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,OAAO,EAAE,GAAG,eAAe,GAAG,MAAM;AAAA,MACpC;AAAA,MACA,eAAa;AAAA;AAAA,EACf;AAEJ;","names":[]}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ // src/styles.ts
4
+ var import_lib = require("@univerjs/design/lib/index.css");
5
+ var import_lib2 = require("@univerjs/ui/lib/index.css");
6
+ var import_lib3 = require("@univerjs/docs-ui/lib/index.css");
7
+ var import_lib4 = require("@univerjs/sheets-ui/lib/index.css");
8
+ var import_lib5 = require("@univerjs/sheets-formula-ui/lib/index.css");
9
+ var import_lib6 = require("@univerjs/sheets-numfmt-ui/lib/index.css");
10
+ //# sourceMappingURL=styles.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles.ts"],"sourcesContent":["/**\n * Univer plugin CSS — side-effect-only imports for the eager plugin\n * set CasualSheets boots. Hosts import this once at app boot:\n *\n * import '@schnsrw/casual-sheets/styles';\n *\n * If the host adds lazy plugins (sort, filter, drawing, comments,\n * conditional formatting, …) it imports the corresponding CSS\n * separately — those plugins ship their own /lib/index.css.\n */\nimport '@univerjs/design/lib/index.css';\nimport '@univerjs/ui/lib/index.css';\nimport '@univerjs/docs-ui/lib/index.css';\nimport '@univerjs/sheets-ui/lib/index.css';\nimport '@univerjs/sheets-formula-ui/lib/index.css';\nimport '@univerjs/sheets-numfmt-ui/lib/index.css';\n"],"mappings":";;;AAUA,iBAAO;AACP,IAAAA,cAAO;AACP,IAAAA,cAAO;AACP,IAAAA,cAAO;AACP,IAAAA,cAAO;AACP,IAAAA,cAAO;","names":["import_lib"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/styles.js ADDED
@@ -0,0 +1,8 @@
1
+ // src/styles.ts
2
+ import "@univerjs/design/lib/index.css";
3
+ import "@univerjs/ui/lib/index.css";
4
+ import "@univerjs/docs-ui/lib/index.css";
5
+ import "@univerjs/sheets-ui/lib/index.css";
6
+ import "@univerjs/sheets-formula-ui/lib/index.css";
7
+ import "@univerjs/sheets-numfmt-ui/lib/index.css";
8
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles.ts"],"sourcesContent":["/**\n * Univer plugin CSS — side-effect-only imports for the eager plugin\n * set CasualSheets boots. Hosts import this once at app boot:\n *\n * import '@schnsrw/casual-sheets/styles';\n *\n * If the host adds lazy plugins (sort, filter, drawing, comments,\n * conditional formatting, …) it imports the corresponding CSS\n * separately — those plugins ship their own /lib/index.css.\n */\nimport '@univerjs/design/lib/index.css';\nimport '@univerjs/ui/lib/index.css';\nimport '@univerjs/docs-ui/lib/index.css';\nimport '@univerjs/sheets-ui/lib/index.css';\nimport '@univerjs/sheets-formula-ui/lib/index.css';\nimport '@univerjs/sheets-numfmt-ui/lib/index.css';\n"],"mappings":";AAUA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@schnsrw/casual-sheets",
3
- "version": "0.2.0",
4
- "description": "Casual Sheets SDK — signing pipeline + iframe postMessage protocol. Univer wrapper (CasualSheets component) to follow.",
3
+ "version": "0.3.0",
4
+ "description": "Casual Sheets SDK — signing pipeline, iframe postMessage protocol, and CasualSheets React wrapper around Univer.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -28,6 +28,15 @@
28
28
  "types": "./dist/embed.d.ts",
29
29
  "import": "./dist/embed.js",
30
30
  "require": "./dist/embed.cjs"
31
+ },
32
+ "./sheets": {
33
+ "types": "./dist/sheets.d.ts",
34
+ "import": "./dist/sheets.js",
35
+ "require": "./dist/sheets.cjs"
36
+ },
37
+ "./styles": {
38
+ "import": "./dist/styles.js",
39
+ "require": "./dist/styles.cjs"
31
40
  }
32
41
  },
33
42
  "files": [
@@ -37,7 +46,21 @@
37
46
  ],
38
47
  "peerDependencies": {
39
48
  "react": "^18.0.0 || ^19.0.0",
40
- "react-dom": "^18.0.0 || ^19.0.0"
49
+ "react-dom": "^18.0.0 || ^19.0.0",
50
+ "@univerjs/core": "^0.24.0",
51
+ "@univerjs/design": "^0.24.0",
52
+ "@univerjs/docs": "^0.24.0",
53
+ "@univerjs/docs-ui": "^0.24.0",
54
+ "@univerjs/engine-formula": "^0.24.0",
55
+ "@univerjs/engine-render": "^0.24.0",
56
+ "@univerjs/sheets": "^0.24.0",
57
+ "@univerjs/sheets-formula": "^0.24.0",
58
+ "@univerjs/sheets-formula-ui": "^0.24.0",
59
+ "@univerjs/sheets-numfmt": "^0.24.0",
60
+ "@univerjs/sheets-numfmt-ui": "^0.24.0",
61
+ "@univerjs/sheets-ui": "^0.24.0",
62
+ "@univerjs/themes": "^0.24.0",
63
+ "@univerjs/ui": "^0.24.0"
41
64
  },
42
65
  "peerDependenciesMeta": {
43
66
  "react": {
@@ -45,6 +68,48 @@
45
68
  },
46
69
  "react-dom": {
47
70
  "optional": true
71
+ },
72
+ "@univerjs/core": {
73
+ "optional": true
74
+ },
75
+ "@univerjs/design": {
76
+ "optional": true
77
+ },
78
+ "@univerjs/docs": {
79
+ "optional": true
80
+ },
81
+ "@univerjs/docs-ui": {
82
+ "optional": true
83
+ },
84
+ "@univerjs/engine-formula": {
85
+ "optional": true
86
+ },
87
+ "@univerjs/engine-render": {
88
+ "optional": true
89
+ },
90
+ "@univerjs/sheets": {
91
+ "optional": true
92
+ },
93
+ "@univerjs/sheets-formula": {
94
+ "optional": true
95
+ },
96
+ "@univerjs/sheets-formula-ui": {
97
+ "optional": true
98
+ },
99
+ "@univerjs/sheets-numfmt": {
100
+ "optional": true
101
+ },
102
+ "@univerjs/sheets-numfmt-ui": {
103
+ "optional": true
104
+ },
105
+ "@univerjs/sheets-ui": {
106
+ "optional": true
107
+ },
108
+ "@univerjs/themes": {
109
+ "optional": true
110
+ },
111
+ "@univerjs/ui": {
112
+ "optional": true
48
113
  }
49
114
  },
50
115
  "devDependencies": {
@@ -55,7 +120,21 @@
55
120
  "react-dom": "^19.0.0",
56
121
  "tsup": "^8.0.0",
57
122
  "tsx": "^4.0.0",
58
- "typescript": "^5.4.0"
123
+ "typescript": "^5.4.0",
124
+ "@univerjs/core": "0.24.0",
125
+ "@univerjs/design": "0.24.0",
126
+ "@univerjs/docs": "0.24.0",
127
+ "@univerjs/docs-ui": "0.24.0",
128
+ "@univerjs/engine-formula": "0.24.0",
129
+ "@univerjs/engine-render": "0.24.0",
130
+ "@univerjs/sheets": "0.24.0",
131
+ "@univerjs/sheets-formula": "0.24.0",
132
+ "@univerjs/sheets-formula-ui": "0.24.0",
133
+ "@univerjs/sheets-numfmt": "0.24.0",
134
+ "@univerjs/sheets-numfmt-ui": "0.24.0",
135
+ "@univerjs/sheets-ui": "0.24.0",
136
+ "@univerjs/themes": "0.24.0",
137
+ "@univerjs/ui": "0.24.0"
59
138
  },
60
139
  "publishConfig": {
61
140
  "access": "public"
package/src/index.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  /**
2
2
  * @schnsrw/casual-sheets — Casual Sheets SDK
3
3
  *
4
- * Two surfaces shipped in v0.1.0:
5
- * - `./signing` — anchored cell signatures (drawn / typed / uploaded)
6
- * - `./embed` — iframe postMessage protocol for host integrations
4
+ * Three surfaces:
5
+ * - `./signing` — anchored cell signatures (drawn / typed / uploaded).
6
+ * - `./embed` — iframe postMessage protocol for host integrations.
7
+ * - `./sheets` — `CasualSheets` React wrapper around Univer Sheets.
7
8
  *
8
- * A `CasualSheets` React component that wraps the Univer-Sheets bootstrap
9
- * is planned for a follow-up release.
9
+ * The `./styles` side-effect entry brings in the eager plugin CSS:
10
+ *
11
+ * import '@schnsrw/casual-sheets/styles';
10
12
  */
11
13
 
12
14
  export * from './signing';
13
15
  export * from './embed';
16
+ export * from './sheets';
@@ -0,0 +1,163 @@
1
+ /**
2
+ * CasualSheets — minimal React wrapper around Univer Sheets.
3
+ *
4
+ * Boots Univer with the eager plugin set (render + formula engine +
5
+ * UI + docs + sheets + sheets-ui + sheets-formula + numfmt), mounts a
6
+ * single workbook unit from `initialData`, and surfaces the
7
+ * `FUniver` API to the host via `onReady`.
8
+ *
9
+ * Intentionally NOT included (host can layer on top via FUniver):
10
+ * - Lazy plugin loading (conditional formatting, drawings, sort,
11
+ * filter, hyperlinks, tables, comments, find/replace, …). Host
12
+ * calls `univer.registerPlugin(...)` after `onReady`.
13
+ * - Formula compute via Web Worker — `notExecuteFormula: false`
14
+ * is the default; the formula engine runs on the main thread.
15
+ * Host wires `UniverRPCMainThreadPlugin` + a worker URL itself
16
+ * if it wants the off-main path.
17
+ * - Snapshot swap (this component mounts a snapshot once; change
18
+ * the React `key` to remount with a fresh snapshot).
19
+ * - Paste-merge hooks, dev helpers, zoom-shortcut overrides,
20
+ * facade extensions — all app concerns.
21
+ *
22
+ * Styles: host must import `@schnsrw/casual-sheets/styles.css`
23
+ * (or the per-plugin CSS) once at app boot. Tree-shaking strips the
24
+ * styles from this entry if the host doesn't reach the styles export.
25
+ */
26
+
27
+ import { useEffect, useRef, type CSSProperties } from 'react';
28
+ import {
29
+ LocaleType,
30
+ LogLevel,
31
+ Univer,
32
+ UniverInstanceType,
33
+ type IWorkbookData,
34
+ type ILocales,
35
+ } from '@univerjs/core';
36
+ import { FUniver } from '@univerjs/core/facade';
37
+ import { defaultTheme } from '@univerjs/themes';
38
+
39
+ import { UniverRenderEnginePlugin } from '@univerjs/engine-render';
40
+ import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula';
41
+ import { UniverUIPlugin } from '@univerjs/ui';
42
+ import { UniverDocsPlugin } from '@univerjs/docs';
43
+ import { UniverDocsUIPlugin } from '@univerjs/docs-ui';
44
+ import { UniverSheetsPlugin } from '@univerjs/sheets';
45
+ import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
46
+ import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
47
+ import { UniverSheetsFormulaUIPlugin } from '@univerjs/sheets-formula-ui';
48
+ import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
49
+ import { UniverSheetsNumfmtUIPlugin } from '@univerjs/sheets-numfmt-ui';
50
+
51
+ export interface CasualSheetsProps {
52
+ /** Workbook snapshot to mount. Read once on initial mount; change
53
+ * the React `key` on this component to remount with a new
54
+ * workbook. */
55
+ initialData: IWorkbookData;
56
+ /** Called after the workbook unit is created. The FUniver API is
57
+ * how the host drives the sheet (read cells, mutate, listen for
58
+ * events, register additional plugins). */
59
+ onReady?: (api: FUniver, univer: Univer) => void;
60
+ /** Locale identifier. Defaults to `LocaleType.EN_US`. */
61
+ locale?: LocaleType;
62
+ /** Locale string bundle. Optional — Univer's default English
63
+ * strings load if omitted. */
64
+ locales?: ILocales;
65
+ /** Univer log level. Defaults to `LogLevel.WARN`. */
66
+ logLevel?: LogLevel;
67
+ /** Univer chrome toggles. Defaults: header / toolbar / footer off,
68
+ * context menu on — matches Casual Sheets' embedded shape. */
69
+ ui?: {
70
+ header?: boolean;
71
+ toolbar?: boolean;
72
+ footer?: boolean;
73
+ contextMenu?: boolean;
74
+ };
75
+ /** Override the theme. Defaults to Univer's `defaultTheme`. */
76
+ theme?: typeof defaultTheme;
77
+ /** Container style. Default fills the parent. */
78
+ style?: CSSProperties;
79
+ /** Container className for additional styling hooks. */
80
+ className?: string;
81
+ /** Optional test id for the host container. */
82
+ testId?: string;
83
+ }
84
+
85
+ const DEFAULT_STYLE: CSSProperties = {
86
+ width: '100%',
87
+ height: '100%',
88
+ position: 'relative',
89
+ };
90
+
91
+ const DEFAULT_UI = {
92
+ header: false,
93
+ toolbar: false,
94
+ footer: false,
95
+ contextMenu: true,
96
+ };
97
+
98
+ export function CasualSheets({
99
+ initialData,
100
+ onReady,
101
+ locale = LocaleType.EN_US,
102
+ locales,
103
+ logLevel = LogLevel.WARN,
104
+ ui,
105
+ theme = defaultTheme,
106
+ style,
107
+ className,
108
+ testId = 'casual-sheets',
109
+ }: CasualSheetsProps) {
110
+ const hostRef = useRef<HTMLDivElement>(null);
111
+
112
+ useEffect(() => {
113
+ const container = hostRef.current;
114
+ if (!container) return;
115
+
116
+ const univer = new Univer({
117
+ theme,
118
+ locale,
119
+ locales,
120
+ logLevel,
121
+ });
122
+
123
+ const uiOpts = { ...DEFAULT_UI, ...ui, container };
124
+
125
+ univer.registerPlugin(UniverRenderEnginePlugin);
126
+ univer.registerPlugin(UniverFormulaEnginePlugin);
127
+ univer.registerPlugin(UniverUIPlugin, uiOpts);
128
+ univer.registerPlugin(UniverDocsPlugin);
129
+ univer.registerPlugin(UniverDocsUIPlugin);
130
+ univer.registerPlugin(UniverSheetsPlugin);
131
+ univer.registerPlugin(UniverSheetsUIPlugin);
132
+ univer.registerPlugin(UniverSheetsFormulaPlugin);
133
+ univer.registerPlugin(UniverSheetsFormulaUIPlugin);
134
+ univer.registerPlugin(UniverSheetsNumfmtPlugin);
135
+ univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
136
+
137
+ univer.createUnit(UniverInstanceType.UNIVER_SHEET, initialData);
138
+
139
+ const api = FUniver.newAPI(univer);
140
+ onReady?.(api, univer);
141
+
142
+ return () => {
143
+ // Defer disposal off the React render phase — Univer owns its
144
+ // own React root, and a synchronous unmount mid-render warns
145
+ // and leaves the canvas detached.
146
+ const toDispose = univer;
147
+ queueMicrotask(() => toDispose.dispose());
148
+ };
149
+ // initialData is intentionally NOT in the dep array — the wrapper
150
+ // mounts the snapshot once. Hosts that need to swap workbooks
151
+ // change the React `key` to force a remount.
152
+ // eslint-disable-next-line react-hooks/exhaustive-deps
153
+ }, []);
154
+
155
+ return (
156
+ <div
157
+ ref={hostRef}
158
+ style={{ ...DEFAULT_STYLE, ...style }}
159
+ className={className}
160
+ data-testid={testId}
161
+ />
162
+ );
163
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Sheets surface — React wrapper around Univer Sheets.
3
+ */
4
+ export { CasualSheets, type CasualSheetsProps } from './CasualSheets';
package/src/styles.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Univer plugin CSS — side-effect-only imports for the eager plugin
3
+ * set CasualSheets boots. Hosts import this once at app boot:
4
+ *
5
+ * import '@schnsrw/casual-sheets/styles';
6
+ *
7
+ * If the host adds lazy plugins (sort, filter, drawing, comments,
8
+ * conditional formatting, …) it imports the corresponding CSS
9
+ * separately — those plugins ship their own /lib/index.css.
10
+ */
11
+ import '@univerjs/design/lib/index.css';
12
+ import '@univerjs/ui/lib/index.css';
13
+ import '@univerjs/docs-ui/lib/index.css';
14
+ import '@univerjs/sheets-ui/lib/index.css';
15
+ import '@univerjs/sheets-formula-ui/lib/index.css';
16
+ import '@univerjs/sheets-numfmt-ui/lib/index.css';