wendang-react 0.6.3 → 0.6.5

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 (120) hide show
  1. package/NOTICE.md +1 -1
  2. package/README.md +133 -1
  3. package/dist/bindings/yjs.js +1 -5
  4. package/dist/chunks/AnchoredPanel-C7jMoPze.js +1 -0
  5. package/dist/chunks/DocumentExportMenu-CUMsgq3w.js +2 -0
  6. package/dist/chunks/Dropdown-D98tXfe0.js +3 -0
  7. package/dist/chunks/MindMapCanvas-C46Q5JBU.js +163 -0
  8. package/dist/chunks/MindMapViewer-C9zxZIW8.js +13 -0
  9. package/dist/chunks/SpreadsheetViewer-CoQ4VIgj.js +23 -0
  10. package/dist/chunks/code-highlight-BmaqTe1m.js +1 -30
  11. package/dist/chunks/code-highlight-engine-BFDzDPzy.js +1 -40
  12. package/dist/chunks/comment-hint-BhUxKjKK.js +14 -0
  13. package/dist/chunks/composition-state-Bl-U1R_2.js +1 -40
  14. package/dist/chunks/extensions-BefQ1tDm.js +14 -0
  15. package/dist/chunks/fuzzy-match-DYQR-4w2.js +1 -89
  16. package/dist/chunks/hooks-C53Dp0pr.js +1 -35
  17. package/dist/chunks/i18n-B0kCsIjc.js +2 -0
  18. package/dist/chunks/index-COeA2QcQ.js +15 -0
  19. package/dist/chunks/katex-WjrodtTU.js +1 -71
  20. package/dist/chunks/locale-DWpIJ_9X.js +1 -0
  21. package/dist/chunks/mind-map-controller-Ce76mETT.js +1 -0
  22. package/dist/chunks/mind-map-delete-CVsxdXfs.js +1 -31
  23. package/dist/chunks/mind-map-input-CEWRz_t6.js +1 -43
  24. package/dist/chunks/mind-topic-text-BHXkxexr.js +30 -0
  25. package/dist/chunks/popover-placement-D3xVYdkt.js +1 -47
  26. package/dist/chunks/worksheet-engine-c84sdD4N.js +1 -0
  27. package/dist/chunks/worksheet-preview-DsDVWxIM.js +1 -129
  28. package/dist/document/viewer.js +30 -289
  29. package/dist/document.js +120 -3811
  30. package/dist/export/json.js +1 -5
  31. package/dist/export/markdown.js +1 -2
  32. package/dist/export/mindmap.js +1 -2
  33. package/dist/export/pdf.js +1 -6
  34. package/dist/export/word.js +1 -2
  35. package/dist/export.js +1 -2
  36. package/dist/i18n.js +1 -0
  37. package/dist/index.js +1 -8
  38. package/dist/locales/en-US.js +1 -0
  39. package/dist/locales/es-ES.js +1 -0
  40. package/dist/locales/ja-JP.js +1 -0
  41. package/dist/locales/ko-KR.js +1 -0
  42. package/dist/locales/zh-CN.js +1 -0
  43. package/dist/locales/zh-TW.js +1 -0
  44. package/dist/mindmap/viewer.js +1 -6
  45. package/dist/mindmap.js +3 -123
  46. package/dist/shared.js +1 -52
  47. package/dist/spreadsheet/viewer.js +1 -5
  48. package/dist/spreadsheet/xlsx.js +1 -299
  49. package/dist/spreadsheet.js +2 -120
  50. package/dist/styles/callout.css +1 -34
  51. package/dist/styles/code-block.css +1 -58
  52. package/dist/styles/content-style.css +1 -619
  53. package/dist/styles/content-tokens.css +1 -29
  54. package/dist/styles/editor-interaction.css +1 -621
  55. package/dist/styles/file-video.css +1 -12
  56. package/dist/styles/image-preview.css +1 -103
  57. package/dist/styles/mind-map-block.css +1 -14
  58. package/dist/styles/mind-map-canvas.css +1 -80
  59. package/dist/styles/mind-map-comments.css +1 -93
  60. package/dist/styles/mind-map-details.css +1 -7
  61. package/dist/styles/mind-map-preview.css +1 -7
  62. package/dist/styles/mind-map-topic.css +1 -112
  63. package/dist/styles/page-picker.css +1 -47
  64. package/dist/styles/renderer.css +1 -45
  65. package/dist/styles/spreadsheet-editor.css +1 -3
  66. package/dist/styles/tokens.css +1 -142
  67. package/dist/styles/video-dialog.css +1 -41
  68. package/dist/styles/video-embed.css +1 -35
  69. package/dist/styles.css +1 -2655
  70. package/dist/types/editor/BlockAffordance.d.ts +5 -2
  71. package/dist/types/editor/CalloutView.d.ts +2 -1
  72. package/dist/types/editor/ImagePreview.d.ts +1 -1
  73. package/dist/types/editor/PagePicker.d.ts +1 -1
  74. package/dist/types/editor/extensions.d.ts +4 -1
  75. package/dist/types/engine/editor/block-commands.d.ts +1 -1
  76. package/dist/types/engine/editor/block-menu-hover.d.ts +16 -0
  77. package/dist/types/engine/editor/extensions/locale.d.ts +3 -0
  78. package/dist/types/engine/editor/nodes/image-nodeview.d.ts +1 -1
  79. package/dist/types/engine/editor/video-block-controls.d.ts +13 -0
  80. package/dist/types/engine/host.d.ts +60 -2
  81. package/dist/types/engine/renderer/attachments.d.ts +3 -3
  82. package/dist/types/engine/shared/video-feedback.d.ts +1 -1
  83. package/dist/types/engine/worksheets/worksheet-engine.d.ts +1 -0
  84. package/dist/types/engine/worksheets/worksheet-xlsx.d.ts +6 -1
  85. package/dist/types/host-types.d.ts +2 -60
  86. package/dist/types/host.d.ts +8 -1
  87. package/dist/types/i18n.d.ts +3 -0
  88. package/dist/types/index.d.ts +2 -0
  89. package/dist/types/locales/en-US.d.ts +1 -0
  90. package/dist/types/locales/es-ES.d.ts +1 -0
  91. package/dist/types/locales/ja-JP.d.ts +1 -0
  92. package/dist/types/locales/ko-KR.d.ts +1 -0
  93. package/dist/types/locales/zh-CN.d.ts +1 -0
  94. package/dist/types/locales/zh-TW.d.ts +1 -0
  95. package/dist/types/renderer/media.d.ts +2 -1
  96. package/dist/types/spreadsheet/xlsx.d.ts +1 -1
  97. package/dist/types/wui/Dropdown.d.ts +2 -1
  98. package/dist/types/wui/index.d.ts +2 -1
  99. package/integrity.json +3140 -0
  100. package/package.json +15 -5
  101. package/verify-integrity.mjs +138 -0
  102. package/dist/chunks/AnchoredPanel-Cv4RURwF.js +0 -68
  103. package/dist/chunks/DocumentExportMenu-BrGipZ59.js +0 -75
  104. package/dist/chunks/MindMapCanvas-tkFBBs4g.js +0 -2090
  105. package/dist/chunks/MindMapViewer-DJrryb2Y.js +0 -180
  106. package/dist/chunks/SpreadsheetViewer-DxCxIUx_.js +0 -163
  107. package/dist/chunks/comment-hint-B9qcrqvn.js +0 -296
  108. package/dist/chunks/extensions-ByORRoRa.js +0 -4210
  109. package/dist/chunks/host-C-V688Rq.js +0 -197
  110. package/dist/chunks/index-DdfMnva8.js +0 -726
  111. package/dist/chunks/mind-map-controller-B6SxK3GZ.js +0 -479
  112. package/dist/chunks/mind-topic-text-DSyb95vL.js +0 -446
  113. package/dist/chunks/nodes-iKqTGr_N.js +0 -291
  114. package/dist/chunks/worksheet-engine-TJ54m0KC.js +0 -125
  115. package/third-party-notices/wendang-export@0.6.0-NOTICE.md.txt +0 -51
  116. package/third-party-notices/wendang-export@0.6.1-LICENSE.txt +0 -21
  117. package/third-party-notices/wendang-export@0.6.2-LICENSE.txt +0 -21
  118. package/third-party-notices/wendang-export@0.6.2-NOTICE.md.txt +0 -70
  119. /package/third-party-notices/{wendang-export@0.6.0-LICENSE.txt → wendang-export@0.6.4-LICENSE.txt} +0 -0
  120. /package/third-party-notices/{wendang-export@0.6.1-NOTICE.md.txt → wendang-export@0.6.4-NOTICE.md.txt} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wendang-react",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Wendang 原生 React 文档、工作表和思维导图编辑与展示组件。",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -74,6 +74,14 @@
74
74
  "./export": {
75
75
  "types": "./dist/types/export.d.ts",
76
76
  "import": "./dist/export.js"
77
+ },
78
+ "./i18n": {
79
+ "types": "./dist/types/i18n.d.ts",
80
+ "import": "./dist/i18n.js"
81
+ },
82
+ "./locales/*": {
83
+ "types": "./dist/types/locales/*.d.ts",
84
+ "import": "./dist/locales/*.js"
77
85
  }
78
86
  },
79
87
  "files": [
@@ -81,6 +89,8 @@
81
89
  "README.md",
82
90
  "LICENSE",
83
91
  "NOTICE.md",
92
+ "integrity.json",
93
+ "verify-integrity.mjs",
84
94
  "third-party-notices"
85
95
  ],
86
96
  "sideEffects": [
@@ -120,8 +130,8 @@
120
130
  "lowlight": "3.3.0",
121
131
  "numfmt": "4.0.1",
122
132
  "tiny-pinyin": "1.3.2",
123
- "wendang": "0.6.1",
124
- "wendang-export": "0.6.2"
133
+ "wendang": "0.6.3",
134
+ "wendang-export": "0.6.4"
125
135
  },
126
136
  "devDependencies": {
127
137
  "react": "19.3.1",
@@ -144,7 +154,7 @@
144
154
  "scripts": {
145
155
  "sync:engine": "node ../../scripts/sync-react-engine.mjs",
146
156
  "typecheck": "pnpm sync:engine && tsc --noEmit",
147
- "build": "pnpm sync:engine && tsc --noEmit && vite build && tsc --emitDeclarationOnly && node ../../scripts/copy-react-styles.mjs",
148
- "dev": "pnpm sync:engine && vite build --watch"
157
+ "build": "pnpm sync:engine && tsc --noEmit && vite build && tsc --emitDeclarationOnly && node ../../scripts/copy-react-styles.mjs && node ../../scripts/minify-output.mjs react && node ../../scripts/generate-notices.mjs react && node ../../scripts/package-integrity.mjs generate react",
158
+ "dev": "node ../../scripts/watch-react.mjs"
149
159
  }
150
160
  }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Standalone package verifier, copied into the npm payload by the build.
3
+ * SHA-256 detects changes against a baseline; it is not a publisher signature.
4
+ */
5
+ import { createHash } from 'node:crypto';
6
+ import { lstatSync, readFileSync, readdirSync, realpathSync } from 'node:fs';
7
+ import path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ export const integrityName = 'integrity.json';
11
+ export const verifierName = 'verify-integrity.mjs';
12
+ export const payloadRoots = ['dist', 'README.md', 'LICENSE', 'NOTICE.md', 'third-party-notices', 'package.json', verifierName];
13
+ export const sha256 = bytes => createHash('sha256').update(bytes).digest('hex');
14
+ export function canonicalJson(value) {
15
+ if (Array.isArray(value)) return '[' + value.map(canonicalJson).join(',') + ']';
16
+ if (value && typeof value === 'object')
17
+ return '{' + Object.keys(value).sort().map(key => JSON.stringify(key) + ':' + canonicalJson(value[key])).join(',') + '}';
18
+ return JSON.stringify(value);
19
+ }
20
+ export function safePayloadPath(value) {
21
+ if (typeof value !== 'string' || !value || /[\x00-\x1f\x7f\\:]/.test(value) ||
22
+ path.posix.isAbsolute(value) || value.split('/').some(part => !part || part === '.' || part === '..'))
23
+ throw new Error(`Unsafe package path: ${JSON.stringify(value)}`);
24
+ if (!payloadRoots.some(root => value === root || value.startsWith(root + '/')))
25
+ throw new Error(`Unexpected package path: ${value}`);
26
+ return value;
27
+ }
28
+ export function packageMetadataBytes(bytes, workspaceVersions = {}, allowWorkspace = false) {
29
+ const metadata = JSON.parse(bytes.toString('utf8'));
30
+ for (const section of ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']) {
31
+ for (const [name, spec] of Object.entries(metadata[section] ?? {})) {
32
+ if (typeof spec !== 'string' || !spec.startsWith('workspace:')) continue;
33
+ if (!allowWorkspace) throw new Error(`Unresolved workspace dependency in package: ${name}`);
34
+ const version = workspaceVersions[name], range = spec.slice(10);
35
+ if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version ?? '') || !['*', '^', '~'].includes(range))
36
+ throw new Error(`Unsupported workspace dependency: ${name} ${spec}`);
37
+ metadata[section][name] = (range === '*' ? '' : range) + version;
38
+ }
39
+ }
40
+ // Registry/installer annotations do not change the executable package contract.
41
+ for (const key of ['gitHead', 'readme', 'readmeFilename', '_id', '_from', '_resolved', '_integrity', '_where']) delete metadata[key];
42
+ for (const hook of ['preinstall', 'install', 'postinstall', 'prepare'])
43
+ if (metadata.scripts?.[hook]) throw new Error(`Unexpected install lifecycle script: ${hook}`);
44
+ // pnpm removes publish lifecycle hooks from its packed manifest. Accept only
45
+ // our fixed, side-effect-free verifier hook, and normalize its known omission.
46
+ if (metadata.scripts?.prepack !== undefined) {
47
+ if (metadata.scripts.prepack !== 'node verify-integrity.mjs --workspace') throw new Error('Unexpected prepack script');
48
+ delete metadata.scripts.prepack;
49
+ }
50
+ for (const hook of ['postpack', 'prepublish', 'prepublishOnly', 'publish', 'postpublish'])
51
+ if (metadata.scripts?.[hook]) throw new Error(`Unexpected publish lifecycle script: ${hook}`);
52
+ if (metadata.scripts && !Object.keys(metadata.scripts).length) delete metadata.scripts;
53
+ return Buffer.from(canonicalJson(metadata));
54
+ }
55
+ function checkPublishFile(relative, bytes) {
56
+ if (/(?:^|\/)(?:src|__tests__|node_modules)(?:\/|$)|(?:^|\/)\.env(?:\.|$)|(?:^|\/)\.npmrc$|\.map$|\.spec\.|\.test\.|\.(?:vue|tsx)$/.test(relative) ||
57
+ relative.endsWith('.ts') && !relative.endsWith('.d.ts'))
58
+ throw new Error(`Source, test, map or private file in package: ${relative}`);
59
+ if (/\.(?:[cm]?js|css)$/.test(relative) && /[#@]\s*sourceMappingURL\s*=/.test(bytes.toString('utf8')))
60
+ throw new Error(`Source map reference in package: ${relative}`);
61
+ }
62
+ export function collectPayload(packageRoot, { workspaceVersions = {}, allowWorkspace = false, strict = true } = {}) {
63
+ const root = realpathSync(packageRoot), result = [];
64
+ function visit(relative) {
65
+ safePayloadPath(relative);
66
+ const file = path.join(root, relative), stat = lstatSync(file);
67
+ if (stat.isSymbolicLink()) throw new Error(`Symbolic link in package: ${relative}`);
68
+ if (stat.isDirectory()) {
69
+ for (const entry of readdirSync(file).sort()) visit(relative + '/' + entry);
70
+ } else if (stat.isFile()) {
71
+ const raw = readFileSync(file);
72
+ checkPublishFile(relative, raw);
73
+ const bytes = relative === 'package.json' ? packageMetadataBytes(raw, workspaceVersions, allowWorkspace) : raw;
74
+ result.push({ path: relative, bytes: bytes.length, sha256: sha256(bytes) });
75
+ } else throw new Error(`Unsupported file in package: ${relative}`);
76
+ }
77
+ const required = ['dist', 'README.md', 'LICENSE', 'NOTICE.md', 'third-party-notices', 'package.json', verifierName];
78
+ for (const relative of required) visit(relative);
79
+ if (strict) {
80
+ for (const entry of readdirSync(root)) {
81
+ if ([...payloadRoots, integrityName, 'node_modules'].includes(entry)) continue;
82
+ throw new Error(`Unexpected file in package: ${entry}`);
83
+ }
84
+ }
85
+ return result.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
86
+ }
87
+ export function integrityDigest(manifest) {
88
+ return sha256(canonicalJson({
89
+ formatVersion: manifest.formatVersion, algorithm: manifest.algorithm,
90
+ package: manifest.package, workspaceVersions: manifest.workspaceVersions, files: manifest.files,
91
+ }));
92
+ }
93
+ export function verifyPackage(packageRoot, { expectedDigest, allowWorkspace = false } = {}) {
94
+ const root = realpathSync(packageRoot), manifestFile = path.join(root, integrityName);
95
+ if (!lstatSync(manifestFile).isFile() || lstatSync(manifestFile).isSymbolicLink()) throw new Error('Invalid integrity manifest file');
96
+ const manifest = JSON.parse(readFileSync(manifestFile, 'utf8'));
97
+ if (manifest.formatVersion !== 1 || manifest.algorithm !== 'sha256' || !Array.isArray(manifest.files) ||
98
+ !manifest.files.length || !manifest.package?.name || !manifest.package?.version ||
99
+ !manifest.workspaceVersions || typeof manifest.workspaceVersions !== 'object')
100
+ throw new Error('Invalid integrity manifest');
101
+ const digest = integrityDigest(manifest);
102
+ if (manifest.digest !== digest) throw new Error('Integrity manifest digest mismatch');
103
+ if (expectedDigest !== undefined && (!/^[a-f0-9]{64}$/.test(expectedDigest) || expectedDigest !== digest))
104
+ throw new Error('Trusted package digest mismatch');
105
+ const paths = new Set();
106
+ for (const entry of manifest.files) {
107
+ safePayloadPath(entry.path);
108
+ if (paths.has(entry.path) || !/^[a-f0-9]{64}$/.test(entry.sha256) || !Number.isSafeInteger(entry.bytes) || entry.bytes < 0)
109
+ throw new Error(`Invalid or duplicate integrity entry: ${entry.path}`);
110
+ paths.add(entry.path);
111
+ }
112
+ const metadata = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8'));
113
+ if (metadata.name !== manifest.package.name || metadata.version !== manifest.package.version) throw new Error('Package identity mismatch');
114
+ const actual = collectPayload(root, { workspaceVersions: manifest.workspaceVersions, allowWorkspace, strict: !allowWorkspace });
115
+ const expected = new Map(manifest.files.map(entry => [entry.path, entry]));
116
+ const changed = actual.filter(entry => {
117
+ const baseline = expected.get(entry.path);
118
+ expected.delete(entry.path);
119
+ return !baseline || baseline.sha256 !== entry.sha256 || baseline.bytes !== entry.bytes;
120
+ }).map(entry => entry.path);
121
+ changed.push(...expected.keys());
122
+ if (changed.length) throw new Error(`Package integrity mismatch: ${changed.join(', ')}`);
123
+ return { name: manifest.package.name, version: manifest.package.version, files: actual.length, digest };
124
+ }
125
+
126
+ if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
127
+ try {
128
+ let directory = path.dirname(fileURLToPath(import.meta.url)), expectedDigest, allowWorkspace = false;
129
+ for (let i = 2; i < process.argv.length; i++) {
130
+ const arg = process.argv[i];
131
+ if (arg === '--workspace') allowWorkspace = true;
132
+ else if (arg === '--directory' && process.argv[i + 1]) directory = path.resolve(process.argv[++i]);
133
+ else if (arg === '--expected' && process.argv[i + 1]) expectedDigest = process.argv[++i];
134
+ else throw new Error(`Unknown or incomplete argument: ${arg}`);
135
+ }
136
+ console.log(JSON.stringify(verifyPackage(directory, { expectedDigest, allowWorkspace }), null, 2));
137
+ } catch (error) { console.error(error.message); process.exitCode = 1; }
138
+ }
@@ -1,68 +0,0 @@
1
- "use client";
2
- import { jsx } from "react/jsx-runtime";
3
- import { useRef, useState, useLayoutEffect } from "react";
4
- import { createPortal } from "react-dom";
5
- import { a as useContentContext } from "./host-C-V688Rq.js";
6
- import { p as placeAnchoredPopover } from "./popover-placement-D3xVYdkt.js";
7
- import { u as useLayer, L as LayerProvider, p as placePanel } from "./index-DdfMnva8.js";
8
- function AnchoredPanel({ anchor, onClose, align = "start", prefer = "below", gap = 8, label, role = "dialog", className = "", portal: portalOverride, children, onKeyDown }) {
9
- const context = useContentContext();
10
- const portal = typeof portalOverride === "function" ? portalOverride() : portalOverride !== void 0 ? portalOverride : context.portal;
11
- const panel = useRef(null);
12
- const trigger = useRef(anchor);
13
- trigger.current = anchor;
14
- const layer = useLayer(trigger, panel, true, onClose);
15
- const [position, setPosition] = useState(null);
16
- useLayoutEffect(() => {
17
- const measure = () => {
18
- var _a;
19
- const rect = anchor == null ? void 0 : anchor.getBoundingClientRect(), card = (_a = panel.current) == null ? void 0 : _a.getBoundingClientRect();
20
- if (!rect || !card) return;
21
- const placed = align === "end" ? placePanel({
22
- trigger: rect,
23
- panel: card,
24
- position: prefer === "above" ? "tr" : "br",
25
- gap,
26
- viewport: { width: innerWidth, height: innerHeight }
27
- }) : placeAnchoredPopover({
28
- align,
29
- prefer,
30
- anchor: { left: rect.left, top: rect.top, width: rect.width, height: rect.height },
31
- host: { left: 0, top: 0 },
32
- card: { width: card.width, height: card.height },
33
- bounds: { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight },
34
- gap
35
- });
36
- setPosition({ left: placed.left, top: placed.top });
37
- };
38
- measure();
39
- const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
40
- if (panel.current) observer == null ? void 0 : observer.observe(panel.current);
41
- window.addEventListener("resize", measure);
42
- window.addEventListener("scroll", measure, true);
43
- return () => {
44
- observer == null ? void 0 : observer.disconnect();
45
- window.removeEventListener("resize", measure);
46
- window.removeEventListener("scroll", measure, true);
47
- };
48
- }, [anchor, align, prefer, gap]);
49
- if (!portal) return null;
50
- return /* @__PURE__ */ jsx(LayerProvider, { layer, children: createPortal(/* @__PURE__ */ jsx(
51
- "div",
52
- {
53
- ref: panel,
54
- className: `w-popover w-popover--flush${className ? ` ${className}` : ""}`,
55
- role,
56
- "aria-label": label,
57
- onKeyDown,
58
- onPointerDown: (event) => event.stopPropagation(),
59
- onWheel: (event) => event.stopPropagation(),
60
- onContextMenu: (event) => event.stopPropagation(),
61
- style: { position: "fixed", left: (position == null ? void 0 : position.left) ?? -9999, top: (position == null ? void 0 : position.top) ?? -9999 },
62
- children
63
- }
64
- ), portal) });
65
- }
66
- export {
67
- AnchoredPanel as A
68
- };
@@ -1,75 +0,0 @@
1
- "use client";
2
- import { jsxs, jsx } from "react/jsx-runtime";
3
- import { useRef, useState, useEffect } from "react";
4
- import { b as useContentHost } from "./host-C-V688Rq.js";
5
- import { W as WSelect } from "./index-DdfMnva8.js";
6
- const options = [
7
- { value: "pdf", label: "PDF (.pdf)" },
8
- { value: "docx", label: "Word (.docx)" },
9
- { value: "markdown", label: "Markdown (.md)" },
10
- { value: "json", label: "JSON (.json)" }
11
- ];
12
- function DocumentExportMenu(props) {
13
- const host = useContentHost(), controller = useRef(void 0);
14
- const [busy, setBusy] = useState(false), [error, setError] = useState("");
15
- useEffect(() => {
16
- setBusy(false);
17
- setError("");
18
- return () => {
19
- var _a;
20
- (_a = controller.current) == null ? void 0 : _a.abort();
21
- controller.current = void 0;
22
- };
23
- }, [props.resourceId, props.allowExport, host.scope, host.exports]);
24
- async function execute(value) {
25
- var _a;
26
- if (controller.current || props.disabled || !props.allowExport || !host.exports) return;
27
- if (!options.some((option) => option.value === value)) return;
28
- const task = new AbortController();
29
- controller.current = task;
30
- setBusy(true);
31
- setError("");
32
- try {
33
- await host.exports.request({ kind: "document", format: value, resourceId: props.resourceId, signal: task.signal });
34
- } catch (cause) {
35
- if (!task.signal.aborted) {
36
- const failure = cause instanceof Error ? cause : new Error(String(cause));
37
- setError(failure.message);
38
- (_a = props.onError) == null ? void 0 : _a.call(props, failure);
39
- }
40
- } finally {
41
- if (controller.current === task) {
42
- controller.current = void 0;
43
- setBusy(false);
44
- }
45
- }
46
- }
47
- if (!props.allowExport || !host.exports) return null;
48
- return /* @__PURE__ */ jsxs(
49
- "div",
50
- {
51
- className: "document-export-menu",
52
- "aria-busy": busy || void 0,
53
- style: { display: "flex", alignItems: "center", flexWrap: "wrap", gap: 8, fontSize: 12 },
54
- children: [
55
- /* @__PURE__ */ jsx(
56
- WSelect,
57
- {
58
- value: "",
59
- label: busy ? "正在导出…" : "导出",
60
- ariaLabel: "导出文档",
61
- width: 112,
62
- options,
63
- disabled: props.disabled || busy,
64
- onChange: (value) => void execute(value)
65
- }
66
- ),
67
- busy && /* @__PURE__ */ jsx("span", { role: "status", style: { color: "var(--color-text-muted)" }, children: "正在生成文件…" }),
68
- error && /* @__PURE__ */ jsx("span", { role: "alert", style: { color: "var(--color-danger, #cf3d48)", overflowWrap: "anywhere" }, children: error })
69
- ]
70
- }
71
- );
72
- }
73
- export {
74
- DocumentExportMenu as D
75
- };