wendang-react 0.6.3 → 0.6.4
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/NOTICE.md +1 -1
- package/README.md +105 -0
- package/dist/bindings/yjs.js +1 -5
- package/dist/chunks/AnchoredPanel-C7jMoPze.js +1 -0
- package/dist/chunks/DocumentExportMenu-CUMsgq3w.js +2 -0
- package/dist/chunks/Dropdown-D98tXfe0.js +3 -0
- package/dist/chunks/MindMapCanvas-CVXQXNOg.js +163 -0
- package/dist/chunks/MindMapViewer-BI8zbQM1.js +13 -0
- package/dist/chunks/SpreadsheetViewer-CoQ4VIgj.js +23 -0
- package/dist/chunks/code-highlight-BmaqTe1m.js +1 -30
- package/dist/chunks/code-highlight-engine-BFDzDPzy.js +1 -40
- package/dist/chunks/comment-hint-BhUxKjKK.js +14 -0
- package/dist/chunks/composition-state-Bl-U1R_2.js +1 -40
- package/dist/chunks/extensions-C1fCBnEs.js +14 -0
- package/dist/chunks/fuzzy-match-DYQR-4w2.js +1 -89
- package/dist/chunks/hooks-C53Dp0pr.js +1 -35
- package/dist/chunks/i18n-B0kCsIjc.js +2 -0
- package/dist/chunks/index-COeA2QcQ.js +15 -0
- package/dist/chunks/katex-WjrodtTU.js +1 -71
- package/dist/chunks/locale-DWpIJ_9X.js +1 -0
- package/dist/chunks/mind-map-controller-Ce76mETT.js +1 -0
- package/dist/chunks/mind-map-delete-CVsxdXfs.js +1 -31
- package/dist/chunks/mind-map-input-CEWRz_t6.js +1 -43
- package/dist/chunks/mind-topic-text-Bn1waxff.js +31 -0
- package/dist/chunks/popover-placement-D3xVYdkt.js +1 -47
- package/dist/chunks/worksheet-engine-c84sdD4N.js +1 -0
- package/dist/chunks/worksheet-preview-DsDVWxIM.js +1 -129
- package/dist/document/viewer.js +30 -289
- package/dist/document.js +120 -3811
- package/dist/export/json.js +1 -5
- package/dist/export/markdown.js +1 -2
- package/dist/export/mindmap.js +1 -2
- package/dist/export/pdf.js +1 -6
- package/dist/export/word.js +1 -2
- package/dist/export.js +1 -2
- package/dist/i18n.js +1 -0
- package/dist/index.js +1 -8
- package/dist/locales/en-US.js +1 -0
- package/dist/locales/es-ES.js +1 -0
- package/dist/locales/ja-JP.js +1 -0
- package/dist/locales/ko-KR.js +1 -0
- package/dist/locales/zh-CN.js +1 -0
- package/dist/locales/zh-TW.js +1 -0
- package/dist/mindmap/viewer.js +1 -6
- package/dist/mindmap.js +3 -123
- package/dist/shared.js +1 -52
- package/dist/spreadsheet/viewer.js +1 -5
- package/dist/spreadsheet/xlsx.js +1 -299
- package/dist/spreadsheet.js +2 -120
- package/dist/styles/callout.css +1 -34
- package/dist/styles/code-block.css +1 -58
- package/dist/styles/content-style.css +1 -619
- package/dist/styles/content-tokens.css +1 -29
- package/dist/styles/editor-interaction.css +1 -621
- package/dist/styles/file-video.css +1 -12
- package/dist/styles/image-preview.css +1 -103
- package/dist/styles/mind-map-block.css +1 -14
- package/dist/styles/mind-map-canvas.css +1 -80
- package/dist/styles/mind-map-comments.css +1 -93
- package/dist/styles/mind-map-details.css +1 -7
- package/dist/styles/mind-map-preview.css +1 -7
- package/dist/styles/mind-map-topic.css +1 -112
- package/dist/styles/page-picker.css +1 -47
- package/dist/styles/renderer.css +1 -45
- package/dist/styles/spreadsheet-editor.css +1 -3
- package/dist/styles/tokens.css +1 -142
- package/dist/styles/video-dialog.css +1 -41
- package/dist/styles/video-embed.css +1 -35
- package/dist/styles.css +1 -2655
- package/dist/types/editor/BlockAffordance.d.ts +5 -2
- package/dist/types/editor/CalloutView.d.ts +2 -1
- package/dist/types/editor/ImagePreview.d.ts +1 -1
- package/dist/types/editor/PagePicker.d.ts +1 -1
- package/dist/types/editor/extensions.d.ts +4 -1
- package/dist/types/engine/editor/block-commands.d.ts +1 -1
- package/dist/types/engine/editor/block-menu-hover.d.ts +16 -0
- package/dist/types/engine/editor/extensions/locale.d.ts +3 -0
- package/dist/types/engine/editor/nodes/image-nodeview.d.ts +1 -1
- package/dist/types/engine/host.d.ts +60 -2
- package/dist/types/engine/renderer/attachments.d.ts +3 -3
- package/dist/types/engine/shared/video-feedback.d.ts +1 -1
- package/dist/types/engine/worksheets/worksheet-engine.d.ts +1 -0
- package/dist/types/engine/worksheets/worksheet-xlsx.d.ts +6 -1
- package/dist/types/host-types.d.ts +2 -60
- package/dist/types/host.d.ts +8 -1
- package/dist/types/i18n.d.ts +3 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/locales/en-US.d.ts +1 -0
- package/dist/types/locales/es-ES.d.ts +1 -0
- package/dist/types/locales/ja-JP.d.ts +1 -0
- package/dist/types/locales/ko-KR.d.ts +1 -0
- package/dist/types/locales/zh-CN.d.ts +1 -0
- package/dist/types/locales/zh-TW.d.ts +1 -0
- package/dist/types/spreadsheet/xlsx.d.ts +1 -1
- package/dist/types/wui/Dropdown.d.ts +2 -1
- package/dist/types/wui/index.d.ts +2 -1
- package/integrity.json +3135 -0
- package/package.json +15 -5
- package/verify-integrity.mjs +138 -0
- package/dist/chunks/AnchoredPanel-Cv4RURwF.js +0 -68
- package/dist/chunks/DocumentExportMenu-BrGipZ59.js +0 -75
- package/dist/chunks/MindMapCanvas-tkFBBs4g.js +0 -2090
- package/dist/chunks/MindMapViewer-DJrryb2Y.js +0 -180
- package/dist/chunks/SpreadsheetViewer-DxCxIUx_.js +0 -163
- package/dist/chunks/comment-hint-B9qcrqvn.js +0 -296
- package/dist/chunks/extensions-ByORRoRa.js +0 -4210
- package/dist/chunks/host-C-V688Rq.js +0 -197
- package/dist/chunks/index-DdfMnva8.js +0 -726
- package/dist/chunks/mind-map-controller-B6SxK3GZ.js +0 -479
- package/dist/chunks/mind-topic-text-DSyb95vL.js +0 -446
- package/dist/chunks/nodes-iKqTGr_N.js +0 -291
- package/dist/chunks/worksheet-engine-TJ54m0KC.js +0 -125
- package/third-party-notices/wendang-export@0.6.0-NOTICE.md.txt +0 -51
- package/third-party-notices/wendang-export@0.6.1-LICENSE.txt +0 -21
- package/third-party-notices/wendang-export@0.6.2-LICENSE.txt +0 -21
- package/third-party-notices/wendang-export@0.6.2-NOTICE.md.txt +0 -70
- /package/third-party-notices/{wendang-export@0.6.0-LICENSE.txt → wendang-export@0.6.3-LICENSE.txt} +0 -0
- /package/third-party-notices/{wendang-export@0.6.1-NOTICE.md.txt → wendang-export@0.6.3-NOTICE.md.txt} +0 -0
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, Suspense, useRef, lazy } from "react";
|
|
4
|
-
import { readMindMap, mindMapOutline, MIND_MAP_PALETTE, layoutMindMap, mindRelationPaths } from "wendang/mindmap";
|
|
5
|
-
import { MIND_TOPIC_FONT, mindTopicLineHeight, readableTextColor } from "wendang/shared";
|
|
6
|
-
import { b as useContentHost } from "./host-C-V688Rq.js";
|
|
7
|
-
import { a as WButton } from "./index-DdfMnva8.js";
|
|
8
|
-
import { T as TopicLabel, A as AttachmentImage } from "./mind-topic-text-DSyb95vL.js";
|
|
9
|
-
const Canvas = lazy(() => import("./MindMapCanvas-tkFBBs4g.js").then((module) => ({ default: module.MindMapCanvas })));
|
|
10
|
-
function MindMapViewer({ value, modelValue, height, fetchAttachment }) {
|
|
11
|
-
var _a;
|
|
12
|
-
const model = value ?? modelValue;
|
|
13
|
-
const root = useRef(null), [width, setWidth] = useState(900);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
const node = root.current;
|
|
16
|
-
if (!node || typeof ResizeObserver === "undefined") return;
|
|
17
|
-
setWidth(node.clientWidth || 900);
|
|
18
|
-
const observer = new ResizeObserver((entries) => {
|
|
19
|
-
var _a2;
|
|
20
|
-
return setWidth(((_a2 = entries[0]) == null ? void 0 : _a2.contentRect.width) || 900);
|
|
21
|
-
});
|
|
22
|
-
observer.observe(node);
|
|
23
|
-
return () => observer.disconnect();
|
|
24
|
-
}, []);
|
|
25
|
-
if (!model) return /* @__PURE__ */ jsx("p", { role: "alert", children: "思维导图格式无效" });
|
|
26
|
-
const drawing = layoutMindMap(model), relations = mindRelationPaths(model, drawing);
|
|
27
|
-
const color = MIND_MAP_PALETTE[model.theme];
|
|
28
|
-
const previewHeight = height ?? model.height;
|
|
29
|
-
const scale = Math.min(1, (previewHeight - 30) / drawing.bounds.height, Math.max(100, width - 24) / drawing.bounds.width);
|
|
30
|
-
return /* @__PURE__ */ jsx(
|
|
31
|
-
"div",
|
|
32
|
-
{
|
|
33
|
-
ref: root,
|
|
34
|
-
className: "mind-preview-wrap",
|
|
35
|
-
style: { height: previewHeight },
|
|
36
|
-
role: "group",
|
|
37
|
-
"aria-label": ((_a = model.topics.find((topic) => topic.id === model.rootId)) == null ? void 0 : _a.text) || "思维导图",
|
|
38
|
-
children: /* @__PURE__ */ jsx("div", { className: "mind-preview-sized", style: { width: drawing.bounds.width * scale, height: drawing.bounds.height * scale }, children: /* @__PURE__ */ jsxs("div", { className: "mind-preview-scene", style: { width: drawing.bounds.width, height: drawing.bounds.height, transform: `scale(${scale})` }, children: [
|
|
39
|
-
/* @__PURE__ */ jsxs(
|
|
40
|
-
"svg",
|
|
41
|
-
{
|
|
42
|
-
className: "mind-preview-lines",
|
|
43
|
-
width: drawing.bounds.width,
|
|
44
|
-
height: drawing.bounds.height,
|
|
45
|
-
viewBox: `${drawing.bounds.x} ${drawing.bounds.y} ${drawing.bounds.width} ${drawing.bounds.height}`,
|
|
46
|
-
children: [
|
|
47
|
-
drawing.edges.map((edge) => /* @__PURE__ */ jsx("path", { d: edge.path, fill: "none", stroke: color, strokeWidth: 2 }, edge.id)),
|
|
48
|
-
relations.map((relation) => /* @__PURE__ */ jsxs("g", { children: [
|
|
49
|
-
/* @__PURE__ */ jsx("path", { d: relation.path, fill: "none", stroke: "#9a68d4", strokeWidth: 2, strokeDasharray: "6 4" }),
|
|
50
|
-
/* @__PURE__ */ jsx("text", { x: relation.x, y: relation.y, fontSize: 12, fill: "#9a68d4", children: relation.label || { related: "相关", depends: "依赖", reference: "参考" }[relation.kind] })
|
|
51
|
-
] }, relation.id))
|
|
52
|
-
]
|
|
53
|
-
}
|
|
54
|
-
),
|
|
55
|
-
drawing.nodes.map((topic) => /* @__PURE__ */ jsxs(
|
|
56
|
-
"div",
|
|
57
|
-
{
|
|
58
|
-
className: `mind-preview-topic ${topic.id === model.rootId ? "root" : ""} ${topic.shape === "text" ? "text" : ""}`,
|
|
59
|
-
style: {
|
|
60
|
-
left: topic.x - drawing.bounds.x,
|
|
61
|
-
top: topic.y - drawing.bounds.y,
|
|
62
|
-
width: topic.width,
|
|
63
|
-
minHeight: topic.height,
|
|
64
|
-
fontFamily: MIND_TOPIC_FONT,
|
|
65
|
-
borderRadius: topic.shape === "pill" ? 28 : void 0,
|
|
66
|
-
background: topic.shape === "text" ? "transparent" : topic.background || void 0,
|
|
67
|
-
color: topic.color || (topic.shape === "text" ? "var(--color-text)" : topic.background ? readableTextColor(topic.background) : void 0),
|
|
68
|
-
fontSize: topic.fontSize || 14,
|
|
69
|
-
textAlign: topic.align || "center",
|
|
70
|
-
"--mind-color": color
|
|
71
|
-
},
|
|
72
|
-
children: [
|
|
73
|
-
(topic.icon || topic.done) && /* @__PURE__ */ jsxs("span", { className: "mind-preview-icon", children: [
|
|
74
|
-
topic.done ? "☑ " : "",
|
|
75
|
-
topic.icon
|
|
76
|
-
] }),
|
|
77
|
-
/* @__PURE__ */ jsx("span", { className: "mind-preview-title", style: { minHeight: topic.lines.length * mindTopicLineHeight(topic.fontSize || 14), lineHeight: `${mindTopicLineHeight(topic.fontSize || 14)}px` }, children: /* @__PURE__ */ jsx(TopicLabel, { topic }) }),
|
|
78
|
-
topic.description && /* @__PURE__ */ jsx("span", { className: "mind-preview-description", children: topic.description }),
|
|
79
|
-
topic.note && /* @__PURE__ */ jsx("span", { className: "mind-preview-note", title: topic.note, children: "▤ 备注" }),
|
|
80
|
-
topic.attachmentId && /* @__PURE__ */ jsx("div", { className: "mind-preview-image", children: /* @__PURE__ */ jsx(AttachmentImage, { id: topic.attachmentId, alt: "主题图片", fetcher: fetchAttachment }) })
|
|
81
|
-
]
|
|
82
|
-
},
|
|
83
|
-
topic.id
|
|
84
|
-
))
|
|
85
|
-
] }) })
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
function MindMapBlock(props) {
|
|
90
|
-
const host = useContentHost(), c = props.controller;
|
|
91
|
-
const [open, setOpen] = useState(false), [outline, setOutline] = useState(false), [openComments, setOpenComments] = useState(false), [, update] = useState(0);
|
|
92
|
-
const node = props.node ?? props.value ?? props.modelValue;
|
|
93
|
-
const model = c ? c.snapshot() : node ? readMindMap(node) : null;
|
|
94
|
-
const editable = (c == null ? void 0 : c.editable()) ?? false;
|
|
95
|
-
const rows = model ? mindMapOutline(model) : [];
|
|
96
|
-
function show() {
|
|
97
|
-
if (model) {
|
|
98
|
-
setOpen(true);
|
|
99
|
-
if (c == null ? void 0 : c.context.viewState) c.context.viewState.openId = model.id;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function close() {
|
|
103
|
-
setOpen(false);
|
|
104
|
-
setOpenComments(false);
|
|
105
|
-
const state = c == null ? void 0 : c.context.viewState;
|
|
106
|
-
if (state && state.openId === (model == null ? void 0 : model.id)) state.openId = null;
|
|
107
|
-
}
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
const stop = c == null ? void 0 : c.subscribe(() => {
|
|
110
|
-
update((value) => value + 1);
|
|
111
|
-
if (!c.snapshot()) setOpen(false);
|
|
112
|
-
});
|
|
113
|
-
return () => {
|
|
114
|
-
stop == null ? void 0 : stop();
|
|
115
|
-
};
|
|
116
|
-
}, [c]);
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
var _a;
|
|
119
|
-
if (((_a = c == null ? void 0 : c.context.viewState) == null ? void 0 : _a.openId) === (model == null ? void 0 : model.id)) show();
|
|
120
|
-
if (!host.location || !model) return;
|
|
121
|
-
const linked = () => {
|
|
122
|
-
const params = new URLSearchParams(host.location.current().replace(/^#/, ""));
|
|
123
|
-
if (params.get("mind") === model.id && params.has("topic")) show();
|
|
124
|
-
};
|
|
125
|
-
linked();
|
|
126
|
-
return host.location.subscribe(linked);
|
|
127
|
-
}, [host.location, model == null ? void 0 : model.id, c]);
|
|
128
|
-
if (!model) return /* @__PURE__ */ jsx("p", { role: "alert", children: "思维导图格式无效" });
|
|
129
|
-
return /* @__PURE__ */ jsxs(
|
|
130
|
-
"section",
|
|
131
|
-
{
|
|
132
|
-
className: "mind-map-block",
|
|
133
|
-
"aria-label": "思维导图",
|
|
134
|
-
style: { "--mind-color": MIND_MAP_PALETTE[model.theme] },
|
|
135
|
-
onDoubleClick: (event) => {
|
|
136
|
-
event.stopPropagation();
|
|
137
|
-
show();
|
|
138
|
-
},
|
|
139
|
-
children: [
|
|
140
|
-
/* @__PURE__ */ jsxs("header", { className: "mind-map-block-header", children: [
|
|
141
|
-
/* @__PURE__ */ jsxs("span", { className: "mind-map-block-label", children: [
|
|
142
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "⌘" }),
|
|
143
|
-
" 思维导图 ",
|
|
144
|
-
/* @__PURE__ */ jsxs("span", { className: "mind-map-topic-count", children: [
|
|
145
|
-
model.topics.length,
|
|
146
|
-
" 个主题"
|
|
147
|
-
] })
|
|
148
|
-
] }),
|
|
149
|
-
/* @__PURE__ */ jsxs("div", { className: "mind-map-block-actions", children: [
|
|
150
|
-
host.comments && props.pageId && /* @__PURE__ */ jsx(WButton, { variant: "text", onClick: () => {
|
|
151
|
-
setOpenComments(true);
|
|
152
|
-
show();
|
|
153
|
-
}, children: editable ? "讨论" : "查看讨论" }),
|
|
154
|
-
/* @__PURE__ */ jsx(WButton, { variant: "text", onClick: () => setOutline(!outline), children: outline ? "查看导图" : "文字大纲" }),
|
|
155
|
-
/* @__PURE__ */ jsx(WButton, { variant: "text", onClick: show, children: editable ? "编辑导图" : "放大查看" })
|
|
156
|
-
] })
|
|
157
|
-
] }),
|
|
158
|
-
outline ? /* @__PURE__ */ jsx("div", { className: "mind-map-preview-outline", style: { maxHeight: model.height }, children: rows.map((row) => /* @__PURE__ */ jsx("div", { style: { paddingLeft: Math.min(row.depth, 20) * 18 }, children: row.text || "未命名主题" }, row.id)) }) : /* @__PURE__ */ jsx(MindMapViewer, { value: model, fetchAttachment: props.fetchAttachment ?? (c == null ? void 0 : c.context.fetchAttachment) }),
|
|
159
|
-
open && /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("p", { role: "status", children: "正在加载导图…" }), children: /* @__PURE__ */ jsx(
|
|
160
|
-
Canvas,
|
|
161
|
-
{
|
|
162
|
-
model,
|
|
163
|
-
controller: c,
|
|
164
|
-
pageId: props.pageId,
|
|
165
|
-
canComment: props.canComment,
|
|
166
|
-
allowExport: props.allowExport,
|
|
167
|
-
fetchAttachment: props.fetchAttachment,
|
|
168
|
-
openComments,
|
|
169
|
-
onCommentsChanged: props.onCommentsChanged,
|
|
170
|
-
onClose: close
|
|
171
|
-
}
|
|
172
|
-
) })
|
|
173
|
-
]
|
|
174
|
-
}
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
export {
|
|
178
|
-
MindMapBlock as M,
|
|
179
|
-
MindMapViewer as a
|
|
180
|
-
};
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useMemo } from "react";
|
|
4
|
-
import { validateWorkbook } from "wendang/spreadsheet";
|
|
5
|
-
import { p as previewAxes, a as previewMerges, c as columnName, b as cellStyleData, d as cellDisplay, s as safeColor } from "./worksheet-preview-DsDVWxIM.js";
|
|
6
|
-
import { a as WButton } from "./index-DdfMnva8.js";
|
|
7
|
-
import { b as useContentHost } from "./host-C-V688Rq.js";
|
|
8
|
-
function SpreadsheetViewer({ value, modelValue, allowExport = false, standalone = false, exportSnapshot, pageId }) {
|
|
9
|
-
const host = useContentHost();
|
|
10
|
-
const [sheetId, setSheetId] = useState(""), [row, setRow] = useState(0), [column, setColumn] = useState(0), [showAll, setShowAll] = useState(false), [error, setError] = useState("");
|
|
11
|
-
const [exporting, setExporting] = useState(false);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
setRow(0);
|
|
14
|
-
setColumn(0);
|
|
15
|
-
}, [value, modelValue, showAll, sheetId]);
|
|
16
|
-
const parsed = useMemo(() => {
|
|
17
|
-
try {
|
|
18
|
-
return { doc: validateWorkbook(value ?? modelValue), error: "" };
|
|
19
|
-
} catch (error2) {
|
|
20
|
-
return { doc: null, error: String(error2) };
|
|
21
|
-
}
|
|
22
|
-
}, [value, modelValue]);
|
|
23
|
-
if (!parsed.doc) return /* @__PURE__ */ jsx("p", { role: "alert", children: parsed.error });
|
|
24
|
-
const doc = parsed.doc, allIds = doc.workbook.sheetOrder, ids = allIds.filter((id) => {
|
|
25
|
-
var _a;
|
|
26
|
-
return showAll || !((_a = doc.workbook.sheets[id]) == null ? void 0 : _a.hidden);
|
|
27
|
-
});
|
|
28
|
-
const sheet = doc.workbook.sheets[ids.includes(sheetId) ? sheetId : ids[0]];
|
|
29
|
-
if (!sheet) return /* @__PURE__ */ jsx("section", { className: "worksheet-preview", "aria-label": "工作表只读预览", children: /* @__PURE__ */ jsxs("nav", { className: "sheet-tabs", "aria-label": "工作表页", children: [
|
|
30
|
-
/* @__PURE__ */ jsx("span", { className: "sheet-note", children: "没有可见工作表" }),
|
|
31
|
-
/* @__PURE__ */ jsx(WButton, { "aria-pressed": showAll, onClick: () => setShowAll(true), children: "查看全部行列表页" })
|
|
32
|
-
] }) });
|
|
33
|
-
const axes = previewAxes(doc, sheet, showAll);
|
|
34
|
-
const pageRows = 100, pageColumns = 50;
|
|
35
|
-
const rowStart = Math.min(row, Math.floor(Math.max(0, axes.rows.length - 1) / pageRows) * pageRows);
|
|
36
|
-
const colStart = Math.min(column, Math.floor(Math.max(0, axes.columns.length - 1) / pageColumns) * pageColumns);
|
|
37
|
-
const rows = axes.rows.slice(rowStart, rowStart + pageRows), columns = axes.columns.slice(colStart, colStart + pageColumns), merges = previewMerges(sheet, rows, columns);
|
|
38
|
-
const dimension = (raw, fallback, upper = 600) => {
|
|
39
|
-
const value2 = Number(raw);
|
|
40
|
-
return Number.isFinite(value2) && value2 > 0 ? Math.min(Math.max(value2, 12), upper) : fallback;
|
|
41
|
-
};
|
|
42
|
-
const cellStyle = (r, c) => {
|
|
43
|
-
var _a, _b;
|
|
44
|
-
const merge = merges.get(`${r}:${c}`), rr = (merge == null ? void 0 : merge.sourceRow) ?? r, cc = (merge == null ? void 0 : merge.sourceColumn) ?? c;
|
|
45
|
-
const style = cellStyleData(doc, sheet, rr, cc);
|
|
46
|
-
const border = (side) => {
|
|
47
|
-
var _a2;
|
|
48
|
-
const raw = (_a2 = style.bd) == null ? void 0 : _a2[side];
|
|
49
|
-
if (!(raw == null ? void 0 : raw.s)) return void 0;
|
|
50
|
-
const line = raw.s === 7 ? "double" : [3, 4, 5, 6, 9, 10, 11, 12].includes(raw.s) ? "dashed" : "solid";
|
|
51
|
-
return `${raw.s === 13 ? 3 : raw.s >= 7 ? 2 : 1}px ${line} ${safeColor(raw.cl) ?? "currentColor"}`;
|
|
52
|
-
};
|
|
53
|
-
return {
|
|
54
|
-
color: safeColor(style.cl),
|
|
55
|
-
backgroundColor: safeColor(style.bg),
|
|
56
|
-
fontWeight: style.bl === 1 ? "bold" : void 0,
|
|
57
|
-
fontStyle: style.it === 1 ? "italic" : void 0,
|
|
58
|
-
fontSize: typeof style.fs === "number" ? `${dimension(style.fs, 11, 72)}pt` : void 0,
|
|
59
|
-
textDecoration: [((_a = style.ul) == null ? void 0 : _a.s) === 1 ? "underline" : "", ((_b = style.st) == null ? void 0 : _b.s) === 1 ? "line-through" : ""].filter(Boolean).join(" ") || void 0,
|
|
60
|
-
textAlign: style.ht === 2 ? "center" : style.ht === 3 ? "right" : void 0,
|
|
61
|
-
verticalAlign: style.vt === 2 ? "middle" : style.vt === 3 ? "bottom" : "top",
|
|
62
|
-
whiteSpace: style.tb === 3 ? "pre-wrap" : "pre",
|
|
63
|
-
borderTop: border("t"),
|
|
64
|
-
borderBottom: border("b"),
|
|
65
|
-
borderLeft: border("l"),
|
|
66
|
-
borderRight: border("r")
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
async function exportFile() {
|
|
70
|
-
if (!allowExport || exporting) return;
|
|
71
|
-
setExporting(true);
|
|
72
|
-
setError("");
|
|
73
|
-
try {
|
|
74
|
-
if (host.exports) {
|
|
75
|
-
await host.exports.request({ kind: "spreadsheet", format: "xlsx", resourceId: pageId, blockId: doc.workbook.id });
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const snapshot = exportSnapshot ? await exportSnapshot() : { title: doc.workbook.name, doc };
|
|
79
|
-
const { exportXlsx } = await import("../spreadsheet/xlsx.js");
|
|
80
|
-
const bytes = await exportXlsx(snapshot.doc);
|
|
81
|
-
const url = URL.createObjectURL(new Blob([new Uint8Array(bytes)]));
|
|
82
|
-
const a = document.createElement("a");
|
|
83
|
-
a.href = url;
|
|
84
|
-
a.download = `${snapshot.title || "工作表"}.xlsx`;
|
|
85
|
-
a.click();
|
|
86
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
87
|
-
} catch (error2) {
|
|
88
|
-
setError(String(error2));
|
|
89
|
-
} finally {
|
|
90
|
-
setExporting(false);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return /* @__PURE__ */ jsxs("section", { className: `worksheet-preview${standalone ? " worksheet-preview-standalone" : ""}`, "aria-label": "工作表只读预览", children: [
|
|
94
|
-
/* @__PURE__ */ jsxs("nav", { className: "sheet-tabs", "aria-label": "工作表页", children: [
|
|
95
|
-
ids.map((id) => /* @__PURE__ */ jsxs(
|
|
96
|
-
WButton,
|
|
97
|
-
{
|
|
98
|
-
role: "tab",
|
|
99
|
-
variant: sheet.id === id ? "primary" : "text",
|
|
100
|
-
"aria-selected": sheet.id === id,
|
|
101
|
-
onClick: () => {
|
|
102
|
-
setSheetId(id);
|
|
103
|
-
setRow(0);
|
|
104
|
-
setColumn(0);
|
|
105
|
-
},
|
|
106
|
-
children: [
|
|
107
|
-
doc.workbook.sheets[id].name,
|
|
108
|
-
doc.workbook.sheets[id].hidden ? "(隐藏)" : ""
|
|
109
|
-
]
|
|
110
|
-
},
|
|
111
|
-
id
|
|
112
|
-
)),
|
|
113
|
-
/* @__PURE__ */ jsx("span", { className: "sheet-note", children: "只读预览" }),
|
|
114
|
-
/* @__PURE__ */ jsx(WButton, { "aria-pressed": showAll, onClick: () => setShowAll(!showAll), children: showAll ? "恢复保存视图" : "查看全部行列表页" }),
|
|
115
|
-
allowExport && /* @__PURE__ */ jsx(WButton, { loading: exporting, onClick: () => void exportFile(), children: "导出 XLSX" })
|
|
116
|
-
] }),
|
|
117
|
-
error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
|
|
118
|
-
(axes.hasFilter || axes.hasHidden) && /* @__PURE__ */ jsx("p", { className: "sheet-view-note", role: "status", children: showAll ? "正在查看全部内容;仅改变本次预览。" : `按保存的隐藏与筛选状态显示${axes.filtered ? `,筛除 ${axes.filtered} 行` : ""}。` }),
|
|
119
|
-
/* @__PURE__ */ jsx("div", { className: "sheet-table", tabIndex: 0, children: /* @__PURE__ */ jsxs("table", { children: [
|
|
120
|
-
/* @__PURE__ */ jsxs("colgroup", { children: [
|
|
121
|
-
/* @__PURE__ */ jsx("col", { style: { width: 40 } }),
|
|
122
|
-
columns.map((c) => {
|
|
123
|
-
var _a, _b;
|
|
124
|
-
return /* @__PURE__ */ jsx("col", { style: { width: dimension((_b = (_a = sheet.columnData) == null ? void 0 : _a[c]) == null ? void 0 : _b.w, dimension(sheet.defaultColumnWidth, 100, 600), 600) } }, c);
|
|
125
|
-
})
|
|
126
|
-
] }),
|
|
127
|
-
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
128
|
-
/* @__PURE__ */ jsx("th", { "aria-label": "行号" }),
|
|
129
|
-
columns.map((c) => /* @__PURE__ */ jsx("th", { children: columnName(c) }, c))
|
|
130
|
-
] }) }),
|
|
131
|
-
/* @__PURE__ */ jsx("tbody", { children: rows.map((r) => {
|
|
132
|
-
var _a, _b, _c, _d;
|
|
133
|
-
return /* @__PURE__ */ jsxs("tr", { style: { height: dimension(((_b = (_a = sheet.rowData) == null ? void 0 : _a[r]) == null ? void 0 : _b.h) ?? ((_d = (_c = sheet.rowData) == null ? void 0 : _c[r]) == null ? void 0 : _d.ah), dimension(sheet.defaultRowHeight, 30, 600), 600) }, children: [
|
|
134
|
-
/* @__PURE__ */ jsx("th", { children: r + 1 }),
|
|
135
|
-
columns.map((c) => {
|
|
136
|
-
var _a2, _b2;
|
|
137
|
-
const merge = merges.get(`${r}:${c}`);
|
|
138
|
-
if (merge == null ? void 0 : merge.hidden) return null;
|
|
139
|
-
const rr = (merge == null ? void 0 : merge.sourceRow) ?? r, cc = (merge == null ? void 0 : merge.sourceColumn) ?? c, style = cellStyleData(doc, sheet, rr, cc);
|
|
140
|
-
const display = cellDisplay((_b2 = (_a2 = sheet.cellData) == null ? void 0 : _a2[rr]) == null ? void 0 : _b2[cc], style);
|
|
141
|
-
return /* @__PURE__ */ jsx("td", { rowSpan: merge == null ? void 0 : merge.rowspan, colSpan: merge == null ? void 0 : merge.colspan, title: display.note, style: cellStyle(r, c), children: display.text }, c);
|
|
142
|
-
})
|
|
143
|
-
] }, r);
|
|
144
|
-
}) })
|
|
145
|
-
] }) }),
|
|
146
|
-
/* @__PURE__ */ jsxs("div", { className: "sheet-paging", children: [
|
|
147
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
148
|
-
"第 ",
|
|
149
|
-
rows.length ? `${rows[0] + 1}–${rows[rows.length - 1] + 1}` : "—",
|
|
150
|
-
" 行 · ",
|
|
151
|
-
columns.length ? `${columnName(columns[0])}–${columnName(columns[columns.length - 1])}` : "—",
|
|
152
|
-
" 列 · 公式显示最近保存结果"
|
|
153
|
-
] }),
|
|
154
|
-
/* @__PURE__ */ jsx(WButton, { disabled: rowStart === 0, onClick: () => setRow(Math.max(0, rowStart - pageRows)), children: "上一页行" }),
|
|
155
|
-
/* @__PURE__ */ jsx(WButton, { disabled: rowStart + pageRows >= axes.rows.length, onClick: () => setRow(rowStart + pageRows), children: "下一页行" }),
|
|
156
|
-
/* @__PURE__ */ jsx(WButton, { disabled: colStart === 0, onClick: () => setColumn(Math.max(0, colStart - pageColumns)), children: "上一页列" }),
|
|
157
|
-
/* @__PURE__ */ jsx(WButton, { disabled: colStart + pageColumns >= axes.columns.length, onClick: () => setColumn(colStart + pageColumns), children: "下一页列" })
|
|
158
|
-
] })
|
|
159
|
-
] });
|
|
160
|
-
}
|
|
161
|
-
export {
|
|
162
|
-
SpreadsheetViewer as S
|
|
163
|
-
};
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useRef, useEffect } from "react";
|
|
4
|
-
import { codeLanguageLabel, CODE_LANGUAGES, isKnownCodeLanguage } from "wendang/shared";
|
|
5
|
-
import { a as WButton, W as WSelect, b as WIcon } from "./index-DdfMnva8.js";
|
|
6
|
-
import { A as AnchoredPanel } from "./AnchoredPanel-Cv4RURwF.js";
|
|
7
|
-
import { b as useContentHost } from "./host-C-V688Rq.js";
|
|
8
|
-
import { CODE_THEMES, codeLineCount } from "wendang/internal/code-block";
|
|
9
|
-
function CodeToolbar({ text, language, editable, canCopy, display, onLanguage, onDisplay }) {
|
|
10
|
-
const host = useContentHost();
|
|
11
|
-
const [feedback, setFeedback] = useState(""), [copying, setCopying] = useState(false), [menu, setMenu] = useState(false);
|
|
12
|
-
const [foldTip, setFoldTip] = useState(false), foldTrigger = useRef(null), hoverTimer = useRef(void 0);
|
|
13
|
-
const trigger = useRef(null), menuRoot = useRef(null), timer = useRef(void 0);
|
|
14
|
-
const alive = useRef(true), running = useRef(false), latest = useRef({ display, onDisplay, canCopy, text });
|
|
15
|
-
latest.current = { display, onDisplay, canCopy, text };
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
alive.current = true;
|
|
18
|
-
return () => {
|
|
19
|
-
alive.current = false;
|
|
20
|
-
clearTimeout(timer.current);
|
|
21
|
-
clearTimeout(hoverTimer.current);
|
|
22
|
-
};
|
|
23
|
-
}, []);
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
var _a;
|
|
26
|
-
try {
|
|
27
|
-
const saved = (_a = host.preferences) == null ? void 0 : _a.get("code-theme");
|
|
28
|
-
if (CODE_THEMES.some((item) => item.value === saved) && saved !== latest.current.display.theme)
|
|
29
|
-
latest.current.onDisplay({ ...latest.current.display, theme: saved });
|
|
30
|
-
} catch {
|
|
31
|
-
}
|
|
32
|
-
}, [host.preferences]);
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (!foldTip) return;
|
|
35
|
-
const close = () => setFoldTip(false);
|
|
36
|
-
window.addEventListener("scroll", close, true);
|
|
37
|
-
return () => window.removeEventListener("scroll", close, true);
|
|
38
|
-
}, [foldTip]);
|
|
39
|
-
function showFoldTip() {
|
|
40
|
-
clearTimeout(hoverTimer.current);
|
|
41
|
-
hoverTimer.current = setTimeout(() => setFoldTip(true), 200);
|
|
42
|
-
}
|
|
43
|
-
function hideFoldTip() {
|
|
44
|
-
clearTimeout(hoverTimer.current);
|
|
45
|
-
setFoldTip(false);
|
|
46
|
-
}
|
|
47
|
-
function update(patch) {
|
|
48
|
-
onDisplay({ ...display, ...patch });
|
|
49
|
-
}
|
|
50
|
-
function settings(value) {
|
|
51
|
-
var _a;
|
|
52
|
-
if (value === "numbers") update({ lineNumbers: !display.lineNumbers });
|
|
53
|
-
else if (value === "height") update({ limited: !display.limited });
|
|
54
|
-
else if (CODE_THEMES.some((theme) => theme.value === value)) {
|
|
55
|
-
try {
|
|
56
|
-
(_a = host.preferences) == null ? void 0 : _a.set("code-theme", value);
|
|
57
|
-
} catch {
|
|
58
|
-
}
|
|
59
|
-
update({ theme: value });
|
|
60
|
-
}
|
|
61
|
-
setMenu(false);
|
|
62
|
-
}
|
|
63
|
-
const label = language === "plaintext" ? "纯文本" : codeLanguageLabel(language) || "自动识别";
|
|
64
|
-
const options = [
|
|
65
|
-
{ value: "", label: "自动识别" },
|
|
66
|
-
{ value: "plaintext", label: "纯文本" },
|
|
67
|
-
...CODE_LANGUAGES.filter((item) => item.value),
|
|
68
|
-
...!language || language === "plaintext" || isKnownCodeLanguage(language) ? [] : [{ value: language, label: language }]
|
|
69
|
-
];
|
|
70
|
-
async function copy() {
|
|
71
|
-
if (!latest.current.canCopy || running.current) return;
|
|
72
|
-
running.current = true;
|
|
73
|
-
setCopying(true);
|
|
74
|
-
try {
|
|
75
|
-
await navigator.clipboard.writeText(latest.current.text);
|
|
76
|
-
if (alive.current) setFeedback("已复制");
|
|
77
|
-
} catch {
|
|
78
|
-
if (alive.current) setFeedback("复制失败,请重试");
|
|
79
|
-
} finally {
|
|
80
|
-
running.current = false;
|
|
81
|
-
if (alive.current) setCopying(false);
|
|
82
|
-
}
|
|
83
|
-
if (!alive.current) return;
|
|
84
|
-
clearTimeout(timer.current);
|
|
85
|
-
timer.current = setTimeout(() => {
|
|
86
|
-
if (alive.current) setFeedback("");
|
|
87
|
-
}, 1800);
|
|
88
|
-
}
|
|
89
|
-
function menuKeydown(event) {
|
|
90
|
-
var _a, _b;
|
|
91
|
-
if (!menu || event.defaultPrevented || event.nativeEvent.isComposing || event.keyCode === 229) return;
|
|
92
|
-
if (event.key === "Escape") {
|
|
93
|
-
event.preventDefault();
|
|
94
|
-
setMenu(false);
|
|
95
|
-
(_a = trigger.current) == null ? void 0 : _a.focus();
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
99
|
-
const items = Array.from(((_b = menuRoot.current) == null ? void 0 : _b.querySelectorAll('[role="menuitem"],[role="menuitemradio"]')) ?? []);
|
|
100
|
-
if (!items.length) return;
|
|
101
|
-
event.preventDefault();
|
|
102
|
-
const index = items.indexOf(document.activeElement);
|
|
103
|
-
const next = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : (index + (event.key === "ArrowUp" ? -1 : 1) + items.length) % items.length;
|
|
104
|
-
items[next].focus();
|
|
105
|
-
}
|
|
106
|
-
return /* @__PURE__ */ jsxs(
|
|
107
|
-
"div",
|
|
108
|
-
{
|
|
109
|
-
className: "code-toolbar",
|
|
110
|
-
contentEditable: false,
|
|
111
|
-
"aria-label": "代码块工具栏",
|
|
112
|
-
onKeyDown: (event) => {
|
|
113
|
-
menuKeydown(event);
|
|
114
|
-
if (event.key === "Escape") hideFoldTip();
|
|
115
|
-
event.stopPropagation();
|
|
116
|
-
},
|
|
117
|
-
onPointerDown: (event) => event.stopPropagation(),
|
|
118
|
-
children: [
|
|
119
|
-
/* @__PURE__ */ jsx(
|
|
120
|
-
WButton,
|
|
121
|
-
{
|
|
122
|
-
ref: foldTrigger,
|
|
123
|
-
variant: "text",
|
|
124
|
-
size: "mini",
|
|
125
|
-
className: "code-fold-button",
|
|
126
|
-
"aria-label": display.collapsed ? "展开代码块" : "折叠代码块",
|
|
127
|
-
"aria-expanded": !display.collapsed,
|
|
128
|
-
onMouseEnter: showFoldTip,
|
|
129
|
-
onMouseLeave: hideFoldTip,
|
|
130
|
-
onFocus: showFoldTip,
|
|
131
|
-
onBlur: hideFoldTip,
|
|
132
|
-
onClick: () => update({ collapsed: !display.collapsed }),
|
|
133
|
-
children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", style: { transform: display.collapsed ? "rotate(-90deg)" : void 0 }, children: /* @__PURE__ */ jsx("path", { d: "m4 6 4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
134
|
-
}
|
|
135
|
-
),
|
|
136
|
-
foldTip && /* @__PURE__ */ jsx(AnchoredPanel, { anchor: foldTrigger.current, onClose: hideFoldTip, role: "tooltip", align: "center", prefer: "above", gap: 8, className: "code-tooltip-popup", children: /* @__PURE__ */ jsx("div", { className: "w-tooltip", children: display.collapsed ? "展开代码" : "折叠代码" }) }),
|
|
137
|
-
/* @__PURE__ */ jsxs("span", { className: "code-toolbar-summary", children: [
|
|
138
|
-
display.collapsed ? "已折叠 · " : "",
|
|
139
|
-
codeLineCount(text),
|
|
140
|
-
" 行"
|
|
141
|
-
] }),
|
|
142
|
-
/* @__PURE__ */ jsxs("div", { className: "code-toolbar-actions", children: [
|
|
143
|
-
editable ? /* @__PURE__ */ jsx(WSelect, { className: "code-language-select", ariaLabel: "代码语言", value: language, options, size: "small", searchable: true, onChange: onLanguage }) : /* @__PURE__ */ jsx("span", { className: "code-language-label", children: label }),
|
|
144
|
-
/* @__PURE__ */ jsx("span", { className: "code-toolbar-divider", "aria-hidden": "true" }),
|
|
145
|
-
/* @__PURE__ */ jsxs(
|
|
146
|
-
WButton,
|
|
147
|
-
{
|
|
148
|
-
variant: "text",
|
|
149
|
-
size: "mini",
|
|
150
|
-
className: "code-copy-button",
|
|
151
|
-
"aria-label": "复制代码",
|
|
152
|
-
disabled: !canCopy,
|
|
153
|
-
loading: copying,
|
|
154
|
-
title: canCopy ? "复制完整代码" : "当前空间未开放导出",
|
|
155
|
-
onClick: () => void copy(),
|
|
156
|
-
children: [
|
|
157
|
-
/* @__PURE__ */ jsx(WIcon, { name: "copy", size: 14 }),
|
|
158
|
-
/* @__PURE__ */ jsx("span", { children: feedback || "复制代码" })
|
|
159
|
-
]
|
|
160
|
-
}
|
|
161
|
-
),
|
|
162
|
-
feedback && /* @__PURE__ */ jsx("span", { className: "code-copy-announcement", role: "status", children: feedback }),
|
|
163
|
-
/* @__PURE__ */ jsx(
|
|
164
|
-
WButton,
|
|
165
|
-
{
|
|
166
|
-
ref: trigger,
|
|
167
|
-
variant: "text",
|
|
168
|
-
size: "mini",
|
|
169
|
-
className: "code-settings-button",
|
|
170
|
-
"aria-label": "代码块显示设置",
|
|
171
|
-
"aria-expanded": menu,
|
|
172
|
-
onClick: () => setMenu(!menu),
|
|
173
|
-
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "···" })
|
|
174
|
-
}
|
|
175
|
-
),
|
|
176
|
-
menu && /* @__PURE__ */ jsx(AnchoredPanel, { anchor: trigger.current, onClose: () => setMenu(false), role: "menu", label: "代码块显示设置", align: "end", gap: 6, className: "code-settings-popup", onKeyDown: menuKeydown, children: /* @__PURE__ */ jsxs("div", { ref: menuRoot, className: "w-dropdown", children: [
|
|
177
|
-
/* @__PURE__ */ jsxs("div", { className: "w-dropdown-group", role: "group", "aria-label": "配色主题", children: [
|
|
178
|
-
/* @__PURE__ */ jsx("div", { className: "w-dropdown-group__title", children: "配色主题" }),
|
|
179
|
-
CODE_THEMES.map((theme) => /* @__PURE__ */ jsxs(
|
|
180
|
-
"div",
|
|
181
|
-
{
|
|
182
|
-
className: "w-dropdown-option",
|
|
183
|
-
role: "menuitemradio",
|
|
184
|
-
tabIndex: -1,
|
|
185
|
-
"aria-checked": display.theme === theme.value,
|
|
186
|
-
onClick: () => settings(theme.value),
|
|
187
|
-
onKeyDown: (event) => {
|
|
188
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
189
|
-
event.preventDefault();
|
|
190
|
-
settings(theme.value);
|
|
191
|
-
}
|
|
192
|
-
},
|
|
193
|
-
children: [
|
|
194
|
-
/* @__PURE__ */ jsx("span", { className: "code-theme-swatch", "data-code-swatch": theme.value, "aria-hidden": "true" }),
|
|
195
|
-
theme.label,
|
|
196
|
-
display.theme === theme.value && /* @__PURE__ */ jsx("span", { className: "code-option-check", "aria-hidden": "true", children: "✓" })
|
|
197
|
-
]
|
|
198
|
-
},
|
|
199
|
-
theme.value
|
|
200
|
-
))
|
|
201
|
-
] }),
|
|
202
|
-
/* @__PURE__ */ jsx("div", { className: "w-dropdown-group", role: "group", children: [{ value: "numbers", label: display.lineNumbers ? "隐藏行号" : "显示行号" }, { value: "height", label: display.limited ? "取消高度限制" : "限制代码高度" }].map((option) => /* @__PURE__ */ jsx(
|
|
203
|
-
"div",
|
|
204
|
-
{
|
|
205
|
-
className: "w-dropdown-option",
|
|
206
|
-
role: "menuitem",
|
|
207
|
-
tabIndex: -1,
|
|
208
|
-
onClick: () => settings(option.value),
|
|
209
|
-
onKeyDown: (event) => {
|
|
210
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
211
|
-
event.preventDefault();
|
|
212
|
-
settings(option.value);
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
children: option.label
|
|
216
|
-
},
|
|
217
|
-
option.value
|
|
218
|
-
)) })
|
|
219
|
-
] }) })
|
|
220
|
-
] })
|
|
221
|
-
]
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
const HINT_GAP = 8;
|
|
226
|
-
const HINT_MIN_TOP_SPACE = 40;
|
|
227
|
-
function commentHintPosition(rect, hint2, viewport) {
|
|
228
|
-
const center = rect.left + rect.width / 2;
|
|
229
|
-
const half = Math.max(0, hint2.width / 2);
|
|
230
|
-
const minLeft = half + 8;
|
|
231
|
-
const maxLeft = Math.max(minLeft, viewport.width - half - 8);
|
|
232
|
-
const left = Math.min(Math.max(center, minLeft), maxLeft);
|
|
233
|
-
const above = rect.top >= HINT_MIN_TOP_SPACE;
|
|
234
|
-
return above ? { left, top: rect.top - HINT_GAP, placement: "top" } : { left, top: rect.top + rect.height + HINT_GAP, placement: "bottom" };
|
|
235
|
-
}
|
|
236
|
-
let hint = null;
|
|
237
|
-
let hideOnScroll = null;
|
|
238
|
-
function tokenOf(element, name, fallback) {
|
|
239
|
-
const value = getComputedStyle(element).getPropertyValue(name).trim();
|
|
240
|
-
return value || fallback;
|
|
241
|
-
}
|
|
242
|
-
function showCommentHint(anchor, text) {
|
|
243
|
-
if (typeof document === "undefined") return;
|
|
244
|
-
if (!(anchor instanceof HTMLElement)) return;
|
|
245
|
-
hideCommentHint();
|
|
246
|
-
const el = document.createElement("div");
|
|
247
|
-
el.className = "doc-comment-hint";
|
|
248
|
-
el.setAttribute("role", "tooltip");
|
|
249
|
-
el.textContent = text;
|
|
250
|
-
el.style.cssText = [
|
|
251
|
-
"position:fixed",
|
|
252
|
-
"z-index:1300",
|
|
253
|
-
"pointer-events:none",
|
|
254
|
-
"transform:translateX(-50%)",
|
|
255
|
-
"padding:5px 9px",
|
|
256
|
-
`border:1px solid ${tokenOf(anchor, "--color-border", "#dce2eb")}`,
|
|
257
|
-
`background:${tokenOf(anchor, "--color-surface", "#ffffff")}`,
|
|
258
|
-
`color:${tokenOf(anchor, "--color-text", "#1f2937")}`,
|
|
259
|
-
"font-size:12px",
|
|
260
|
-
"line-height:1.5",
|
|
261
|
-
"white-space:nowrap",
|
|
262
|
-
"box-shadow:0 6px 20px #1018282e",
|
|
263
|
-
"border-radius:0"
|
|
264
|
-
].join(";");
|
|
265
|
-
document.body.appendChild(el);
|
|
266
|
-
const rect = anchor.getBoundingClientRect();
|
|
267
|
-
const size = el.getBoundingClientRect();
|
|
268
|
-
const pos = commentHintPosition(
|
|
269
|
-
{ left: rect.left, top: rect.top, width: rect.width, height: rect.height },
|
|
270
|
-
{ width: size.width, height: size.height },
|
|
271
|
-
{ width: window.innerWidth }
|
|
272
|
-
);
|
|
273
|
-
el.style.left = `${pos.left}px`;
|
|
274
|
-
el.style.top = `${pos.top}px`;
|
|
275
|
-
if (pos.placement === "bottom") el.style.transform = "translateX(-50%)";
|
|
276
|
-
else el.style.transform = "translateX(-50%) translateY(-100%)";
|
|
277
|
-
hint = el;
|
|
278
|
-
hideOnScroll = () => hideCommentHint();
|
|
279
|
-
window.addEventListener("scroll", hideOnScroll, true);
|
|
280
|
-
window.addEventListener("resize", hideOnScroll);
|
|
281
|
-
}
|
|
282
|
-
function hideCommentHint() {
|
|
283
|
-
if (!hint) return;
|
|
284
|
-
hint.remove();
|
|
285
|
-
hint = null;
|
|
286
|
-
if (hideOnScroll) {
|
|
287
|
-
window.removeEventListener("scroll", hideOnScroll, true);
|
|
288
|
-
window.removeEventListener("resize", hideOnScroll);
|
|
289
|
-
hideOnScroll = null;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
export {
|
|
293
|
-
CodeToolbar as C,
|
|
294
|
-
hideCommentHint as h,
|
|
295
|
-
showCommentHint as s
|
|
296
|
-
};
|