dishui 0.0.64 → 0.0.65
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/components/Badge/index.js +12 -9
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Button/index.js +43 -40
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +11 -0
- package/dist/components/Card/index.js +62 -37
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Chart/Chart.js.map +1 -1
- package/dist/components/Checkbox/index.js +32 -30
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/EmptyState/index.d.ts +4 -1
- package/dist/components/EmptyState/index.js +3 -3
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/FileUploader/DropZone.js.map +1 -1
- package/dist/components/FileUploader/FileItem.js.map +1 -1
- package/dist/components/FileUploader/FileUploader.js.map +1 -1
- package/dist/components/FileUploader/UploadQueue.js.map +1 -1
- package/dist/components/Input/index.js +30 -30
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js +41 -40
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/List/index.js +47 -32
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Markdown/Markdown.js +61 -57
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/markdownComponents.js +49 -49
- package/dist/components/Markdown/markdownComponents.js.map +1 -1
- package/dist/components/Modal/index.d.ts +7 -3
- package/dist/components/Modal/index.js +77 -65
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/index.d.ts +58 -0
- package/dist/components/Page/index.js +74 -0
- package/dist/components/Page/index.js.map +1 -0
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/Select/index.js +0 -3
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/StatCard/index.d.ts +3 -1
- package/dist/components/StatCard/index.js +39 -11
- package/dist/components/StatCard/index.js.map +1 -1
- package/dist/components/Table/index.js +103 -85
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +19 -5
- package/dist/components/Tabs/index.js +32 -13
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
- package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js +59 -59
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/DataTable/DataTable.js +49 -48
- package/dist/components/pro/DataTable/DataTable.js.map +1 -1
- package/dist/components/pro/DataTable/Filters.js +42 -42
- package/dist/components/pro/DataTable/Filters.js.map +1 -1
- package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
- package/dist/components/pro/DataTable/PivotView.js +35 -32
- package/dist/components/pro/DataTable/PivotView.js.map +1 -1
- package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
- package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
- package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
- package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
- package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/DataTable/tanstack-table.js +37 -37
- package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
- package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
- package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
- package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
- package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +496 -494
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +916 -917
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
- package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
- package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +1 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
- package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
- package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
- package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
- package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/hooks/useTableColumns.js +7 -8
- package/dist/hooks/useTableColumns.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -221
- package/dist/layouts/MainLayout.js +22 -22
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Navbar.js.map +1 -1
- package/dist/layouts/Sidebar.js +94 -73
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
- package/dist/utils/i18n.js +10 -10
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/dist/utils/routerBuilder.js +17 -15
- package/dist/utils/routerBuilder.js.map +1 -1
- package/dist/utils/themes.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { bracketMatchingStyle as vt, jumpTargetHighlight as wt, jumpToDefinition as yt, lineHighlightStyle as kt, smartAutocompletion as jt } from "../extensions/index.js";
|
|
2
|
-
import { createHighlightExtension as
|
|
3
|
-
import { collectVariables as
|
|
2
|
+
import { createHighlightExtension as nt, createThemeExtension as ct } from "../themes.js";
|
|
3
|
+
import { collectVariables as W, generateOutline as X } from "../utils.js";
|
|
4
4
|
import { defaultContextMenu as St } from "../extensions/contextMenu.js";
|
|
5
|
-
import { forwardRef as Mt, useCallback as
|
|
6
|
-
import { jsx as
|
|
7
|
-
import { EditorView as
|
|
8
|
-
import { Compartment as
|
|
5
|
+
import { forwardRef as Mt, useCallback as g, useEffect as f, useImperativeHandle as Et, useRef as c, useState as Y } from "react";
|
|
6
|
+
import { jsx as p, jsxs as Tt } from "react/jsx-runtime";
|
|
7
|
+
import { EditorView as q, drawSelection as It, highlightActiveLine as Nt, highlightActiveLineGutter as Lt, keymap as Ct, lineNumbers as Rt } from "@codemirror/view";
|
|
8
|
+
import { Compartment as N, EditorState as J } from "@codemirror/state";
|
|
9
9
|
import { defaultKeymap as Kt, history as At, historyKeymap as Ht, indentWithTab as Dt } from "@codemirror/commands";
|
|
10
10
|
import { bracketMatching as $t, defaultHighlightStyle as zt, foldGutter as Bt, indentOnInput as Ft, syntaxHighlighting as Ut } from "@codemirror/language";
|
|
11
11
|
import { closeBrackets as Wt, closeBracketsKeymap as Xt, completionKeymap as Yt } from "@codemirror/autocomplete";
|
|
12
12
|
import { lintKeymap as qt } from "@codemirror/lint";
|
|
13
13
|
import { searchKeymap as Jt } from "@codemirror/search";
|
|
14
|
-
import { javascript as
|
|
14
|
+
import { javascript as S } from "@codemirror/lang-javascript";
|
|
15
15
|
import { python as Pt } from "@codemirror/lang-python";
|
|
16
16
|
import { html as Qt } from "@codemirror/lang-html";
|
|
17
17
|
import { css as Vt } from "@codemirror/lang-css";
|
|
18
18
|
import { json as Zt } from "@codemirror/lang-json";
|
|
19
19
|
import { markdown as _t } from "@codemirror/lang-markdown";
|
|
20
|
-
var
|
|
21
|
-
javascript: () =>
|
|
22
|
-
jsx: () =>
|
|
23
|
-
typescript: () =>
|
|
20
|
+
var ot = (i) => ({
|
|
21
|
+
javascript: () => S({ jsx: !1 }),
|
|
22
|
+
jsx: () => S({ jsx: !0 }),
|
|
23
|
+
typescript: () => S({
|
|
24
24
|
jsx: !1,
|
|
25
25
|
typescript: !0
|
|
26
26
|
}),
|
|
27
|
-
tsx: () =>
|
|
27
|
+
tsx: () => S({
|
|
28
28
|
jsx: !0,
|
|
29
29
|
typescript: !0
|
|
30
30
|
}),
|
|
@@ -33,16 +33,16 @@ var ct = (s) => ({
|
|
|
33
33
|
css: Vt,
|
|
34
34
|
json: Zt,
|
|
35
35
|
markdown: _t
|
|
36
|
-
})[
|
|
37
|
-
const
|
|
36
|
+
})[i]?.() || S(), Ot = Mt(({ value: i = "", onChange: b, language: o = "javascript", theme: v = "light", readOnly: L = !1, lineNumbers: it = !0, highlightActiveLine: st = !0, autocompletion: C = !0, jumpToDefinition: R = !0, contextMenu: ut, onVariablesCollected: l, onOutlineGenerated: d, enableHistory: h = !1, historyLimit: P = 50, historySaveInterval: M = 3, onHistoryChange: u, className: at = "", height: ft = "400px", minHeight: lt, maxHeight: dt, placeholder: Q, extensions: V = [] }, mt) => {
|
|
37
|
+
const K = c(null), e = c(null), [w, Z] = Y({
|
|
38
38
|
visible: !1,
|
|
39
39
|
x: 0,
|
|
40
40
|
y: 0
|
|
41
|
-
}), [
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
}), [x, A] = Y([]), [H, D] = Y(-1), $ = c(0), z = c(!1), y = c(!1), E = c(""), k = c(!1), B = c(""), _ = c(new N()), O = c(new N()), G = c(new N()), tt = c(new N()), F = c(o);
|
|
42
|
+
f(() => {
|
|
43
|
+
F.current = o;
|
|
44
44
|
}, [o]);
|
|
45
|
-
const
|
|
45
|
+
const U = g((t) => {
|
|
46
46
|
if (e.current) try {
|
|
47
47
|
const r = e.current.state.doc.line(t);
|
|
48
48
|
e.current.dispatch({
|
|
@@ -55,60 +55,60 @@ var ct = (s) => ({
|
|
|
55
55
|
} catch (r) {
|
|
56
56
|
console.error("Failed to jump to line:", r);
|
|
57
57
|
}
|
|
58
|
-
}, []),
|
|
59
|
-
if (!
|
|
60
|
-
const
|
|
61
|
-
if (!(
|
|
62
|
-
|
|
58
|
+
}, []), T = g((t, r) => {
|
|
59
|
+
if (!h || z.current || y.current) return;
|
|
60
|
+
const s = Date.now(), m = M * 1e4;
|
|
61
|
+
if (!(s - $.current >= m)) {
|
|
62
|
+
k.current = !0, E.current = t;
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
if (t ===
|
|
66
|
-
|
|
65
|
+
if (t === B.current && !r) {
|
|
66
|
+
k.current = !1;
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
id: `${
|
|
72
|
-
timestamp: new Date(
|
|
69
|
+
$.current = s, k.current = !1, B.current = t, A((n) => {
|
|
70
|
+
const a = H >= 0 ? n.slice(0, H + 1) : n, bt = {
|
|
71
|
+
id: `${s}-${Math.random()}`,
|
|
72
|
+
timestamp: new Date(s),
|
|
73
73
|
content: t,
|
|
74
74
|
description: r
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
return
|
|
79
|
-
u && u(
|
|
80
|
-
}, 0),
|
|
75
|
+
}, j = [...a, bt];
|
|
76
|
+
j.length > P && j.shift();
|
|
77
|
+
const rt = j.length - 1;
|
|
78
|
+
return D(rt), setTimeout(() => {
|
|
79
|
+
u && u(j, rt);
|
|
80
|
+
}, 0), j;
|
|
81
81
|
});
|
|
82
82
|
}, [
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
h,
|
|
84
|
+
P,
|
|
85
|
+
M,
|
|
86
|
+
H,
|
|
87
87
|
u
|
|
88
|
-
]),
|
|
89
|
-
if (t < 0 || t >=
|
|
90
|
-
|
|
91
|
-
const r =
|
|
88
|
+
]), et = g((t) => {
|
|
89
|
+
if (t < 0 || t >= x.length) return;
|
|
90
|
+
z.current = !0;
|
|
91
|
+
const r = x[t];
|
|
92
92
|
e.current && e.current.dispatch({ changes: {
|
|
93
93
|
from: 0,
|
|
94
94
|
to: e.current.state.doc.length,
|
|
95
95
|
insert: r.content
|
|
96
96
|
} });
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
u && u(
|
|
102
|
-
}, 0),
|
|
103
|
-
|
|
97
|
+
const s = x.slice(0, t + 1);
|
|
98
|
+
A(s);
|
|
99
|
+
const m = s.length - 1;
|
|
100
|
+
D(m), setTimeout(() => {
|
|
101
|
+
u && u(s, m);
|
|
102
|
+
}, 0), b && b(r.content), setTimeout(() => {
|
|
103
|
+
z.current = !1;
|
|
104
104
|
}, 100);
|
|
105
105
|
}, [
|
|
106
|
-
p,
|
|
107
106
|
x,
|
|
107
|
+
b,
|
|
108
108
|
u
|
|
109
109
|
]);
|
|
110
|
-
Et(
|
|
111
|
-
jumpToLine:
|
|
110
|
+
Et(mt, () => ({
|
|
111
|
+
jumpToLine: U,
|
|
112
112
|
getView: () => e.current,
|
|
113
113
|
getValue: () => e.current?.state.doc.toString() || "",
|
|
114
114
|
setValue: (t) => {
|
|
@@ -119,36 +119,43 @@ var ct = (s) => ({
|
|
|
119
119
|
} });
|
|
120
120
|
},
|
|
121
121
|
focus: () => e.current?.focus(),
|
|
122
|
-
getHistory: () =>
|
|
123
|
-
restoreHistory:
|
|
122
|
+
getHistory: () => x,
|
|
123
|
+
restoreHistory: et,
|
|
124
124
|
clearHistory: () => {
|
|
125
|
-
|
|
125
|
+
A([]), D(-1), $.current = 0, k.current = !1, E.current = "", B.current = "", setTimeout(() => {
|
|
126
126
|
u && u([], -1);
|
|
127
127
|
}, 0);
|
|
128
128
|
}
|
|
129
129
|
}), [
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
U,
|
|
131
|
+
x,
|
|
132
|
+
et,
|
|
133
133
|
u
|
|
134
|
-
]),
|
|
135
|
-
if (!
|
|
136
|
-
const t =
|
|
137
|
-
|
|
134
|
+
]), f(() => {
|
|
135
|
+
if (!h) return;
|
|
136
|
+
const t = M * 1e4, r = setInterval(() => {
|
|
137
|
+
k.current && E.current && T(E.current);
|
|
138
138
|
}, t);
|
|
139
139
|
return () => clearInterval(r);
|
|
140
140
|
}, [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
]),
|
|
145
|
-
if (!
|
|
146
|
-
const t =
|
|
147
|
-
if (n.docChanged &&
|
|
148
|
-
const
|
|
149
|
-
|
|
141
|
+
h,
|
|
142
|
+
M,
|
|
143
|
+
T
|
|
144
|
+
]), f(() => {
|
|
145
|
+
if (!K.current) return;
|
|
146
|
+
const t = q.updateListener.of((n) => {
|
|
147
|
+
if (n.docChanged && b) {
|
|
148
|
+
const a = n.state.doc.toString();
|
|
149
|
+
b(a), h && !y.current && T(a), y.current && (y.current = !1);
|
|
150
|
+
}
|
|
151
|
+
if (n.docChanged && l) {
|
|
152
|
+
const a = n.state.doc.toString();
|
|
153
|
+
l(W(a, F.current));
|
|
154
|
+
}
|
|
155
|
+
if (n.docChanged && d) {
|
|
156
|
+
const a = n.state.doc.toString();
|
|
157
|
+
d(X(a, F.current));
|
|
150
158
|
}
|
|
151
|
-
n.docChanged && f && f(U(n.state.doc.toString(), B.current)), n.docChanged && l && l(W(n.state.doc.toString(), B.current));
|
|
152
159
|
}), r = [
|
|
153
160
|
At(),
|
|
154
161
|
It(),
|
|
@@ -156,10 +163,10 @@ var ct = (s) => ({
|
|
|
156
163
|
Wt(),
|
|
157
164
|
Ft(),
|
|
158
165
|
Ut(zt, { fallback: !0 }),
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
_.current.of(ot(o)),
|
|
167
|
+
O.current.of(ct(v)),
|
|
168
|
+
G.current.of(nt(v)),
|
|
169
|
+
tt.current.of(J.readOnly.of(L)),
|
|
163
170
|
t,
|
|
164
171
|
Ct.of([
|
|
165
172
|
...Xt,
|
|
@@ -174,104 +181,104 @@ var ct = (s) => ({
|
|
|
174
181
|
kt,
|
|
175
182
|
wt
|
|
176
183
|
];
|
|
177
|
-
if (
|
|
178
|
-
const n = typeof
|
|
184
|
+
if (it && r.push(Rt(), Bt(), Lt()), st && r.push(Nt()), C) {
|
|
185
|
+
const n = typeof C == "object" ? C : {};
|
|
179
186
|
r.push(jt(o, n));
|
|
180
187
|
}
|
|
181
|
-
if (
|
|
182
|
-
const n = typeof
|
|
183
|
-
r.push(yt(
|
|
188
|
+
if (R) {
|
|
189
|
+
const n = typeof R == "object" ? R : {};
|
|
190
|
+
r.push(yt(U, n));
|
|
184
191
|
}
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
parent:
|
|
192
|
+
Q && r.push(q.contentAttributes.of({ "data-placeholder": Q })), V.length > 0 && r.push(...V);
|
|
193
|
+
const s = J.create({
|
|
194
|
+
doc: i,
|
|
195
|
+
extensions: r
|
|
196
|
+
}), m = new q({
|
|
197
|
+
state: s,
|
|
198
|
+
parent: K.current
|
|
192
199
|
});
|
|
193
|
-
return e.current =
|
|
194
|
-
|
|
195
|
-
}, 0),
|
|
196
|
-
|
|
200
|
+
return e.current = m, setTimeout(() => {
|
|
201
|
+
l && l(W(i, o)), d && d(X(i, o));
|
|
202
|
+
}, 0), h && i && T(i, "Initial content"), () => {
|
|
203
|
+
m.destroy();
|
|
197
204
|
};
|
|
198
|
-
}, []),
|
|
199
|
-
e.current &&
|
|
205
|
+
}, []), f(() => {
|
|
206
|
+
e.current && i !== e.current.state.doc.toString() && (y.current = !0, e.current.dispatch({ changes: {
|
|
200
207
|
from: 0,
|
|
201
208
|
to: e.current.state.doc.length,
|
|
202
|
-
insert:
|
|
209
|
+
insert: i
|
|
203
210
|
} }));
|
|
204
|
-
}, [
|
|
211
|
+
}, [i]), f(() => {
|
|
205
212
|
if (e.current) {
|
|
206
|
-
e.current.dispatch({ effects:
|
|
213
|
+
e.current.dispatch({ effects: _.current.reconfigure(ot(o)) });
|
|
207
214
|
const t = e.current.state.doc.toString();
|
|
208
215
|
setTimeout(() => {
|
|
209
|
-
|
|
216
|
+
l && l(W(t, o)), d && d(X(t, o));
|
|
210
217
|
}, 0);
|
|
211
218
|
}
|
|
212
219
|
}, [
|
|
213
220
|
o,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
]),
|
|
217
|
-
e.current && e.current.dispatch({ effects: [
|
|
218
|
-
}, [
|
|
219
|
-
e.current && e.current.dispatch({ effects:
|
|
220
|
-
}, [
|
|
221
|
-
const
|
|
222
|
-
t.preventDefault(),
|
|
221
|
+
l,
|
|
222
|
+
d
|
|
223
|
+
]), f(() => {
|
|
224
|
+
e.current && e.current.dispatch({ effects: [O.current.reconfigure(ct(v)), G.current.reconfigure(nt(v))] });
|
|
225
|
+
}, [v]), f(() => {
|
|
226
|
+
e.current && e.current.dispatch({ effects: tt.current.reconfigure(J.readOnly.of(L)) });
|
|
227
|
+
}, [L]);
|
|
228
|
+
const pt = g((t) => {
|
|
229
|
+
t.preventDefault(), Z({
|
|
223
230
|
visible: !0,
|
|
224
231
|
x: t.clientX,
|
|
225
232
|
y: t.clientY
|
|
226
233
|
});
|
|
227
|
-
}, []),
|
|
228
|
-
|
|
234
|
+
}, []), I = g(() => {
|
|
235
|
+
Z({
|
|
229
236
|
visible: !1,
|
|
230
237
|
x: 0,
|
|
231
238
|
y: 0
|
|
232
239
|
});
|
|
233
|
-
}, []),
|
|
234
|
-
e.current && !t.disabled && t.action(e.current),
|
|
235
|
-
}, [
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
const t = () =>
|
|
240
|
+
}, []), ht = g((t) => {
|
|
241
|
+
e.current && !t.disabled && t.action(e.current), I();
|
|
242
|
+
}, [I]);
|
|
243
|
+
f(() => {
|
|
244
|
+
if (w.visible) {
|
|
245
|
+
const t = () => I();
|
|
239
246
|
return document.addEventListener("click", t), () => document.removeEventListener("click", t);
|
|
240
247
|
}
|
|
241
|
-
}, [
|
|
242
|
-
const
|
|
243
|
-
height:
|
|
244
|
-
minHeight:
|
|
245
|
-
maxHeight:
|
|
248
|
+
}, [w.visible, I]);
|
|
249
|
+
const xt = {
|
|
250
|
+
height: ft,
|
|
251
|
+
minHeight: lt,
|
|
252
|
+
maxHeight: dt,
|
|
246
253
|
overflow: "auto"
|
|
247
|
-
},
|
|
254
|
+
}, gt = ut || St;
|
|
248
255
|
return /* @__PURE__ */ Tt("div", {
|
|
249
|
-
className: `code-editor-wrapper ${
|
|
256
|
+
className: `code-editor-wrapper ${at}`,
|
|
250
257
|
children: [
|
|
251
|
-
/* @__PURE__ */
|
|
252
|
-
ref:
|
|
253
|
-
onContextMenu:
|
|
254
|
-
style:
|
|
258
|
+
/* @__PURE__ */ p("div", {
|
|
259
|
+
ref: K,
|
|
260
|
+
onContextMenu: pt,
|
|
261
|
+
style: xt,
|
|
255
262
|
className: "code-editor"
|
|
256
263
|
}),
|
|
257
|
-
|
|
264
|
+
w.visible && /* @__PURE__ */ p("div", {
|
|
258
265
|
className: "context-menu",
|
|
259
266
|
style: {
|
|
260
267
|
position: "fixed",
|
|
261
|
-
top:
|
|
262
|
-
left:
|
|
268
|
+
top: w.y,
|
|
269
|
+
left: w.x,
|
|
263
270
|
zIndex: 1e3
|
|
264
271
|
},
|
|
265
|
-
children: /* @__PURE__ */
|
|
272
|
+
children: /* @__PURE__ */ p("ul", {
|
|
266
273
|
className: "menu bg-base-200 rounded-box shadow-lg",
|
|
267
|
-
children:
|
|
268
|
-
onClick: () =>
|
|
274
|
+
children: gt.map((t, r) => t.separator ? /* @__PURE__ */ p("li", { className: "menu-separator" }, r) : /* @__PURE__ */ p("li", { children: /* @__PURE__ */ p("a", {
|
|
275
|
+
onClick: () => ht(t),
|
|
269
276
|
className: t.disabled ? "disabled" : "",
|
|
270
277
|
children: t.label
|
|
271
278
|
}) }, r))
|
|
272
279
|
})
|
|
273
280
|
}),
|
|
274
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ p("style", { children: `
|
|
275
282
|
.code-editor-wrapper {
|
|
276
283
|
position: relative;
|
|
277
284
|
border: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/CodeEditor.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection } from '@codemirror/view';\nimport { EditorState, Extension, Compartment } from '@codemirror/state';\nimport { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport { syntaxHighlighting, defaultHighlightStyle, foldGutter, indentOnInput, bracketMatching } from '@codemirror/language';\nimport { completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';\nimport { lintKeymap } from '@codemirror/lint';\nimport { searchKeymap } from '@codemirror/search';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\nimport { markdown } from '@codemirror/lang-markdown';\nimport { jumpToDefinition, smartAutocompletion, bracketMatchingStyle, lineHighlightStyle, jumpTargetHighlight } from '../extensions';\nimport { createThemeExtension, createHighlightExtension } from '../themes';\nimport { collectVariables, generateOutline } from '../utils';\nimport { defaultContextMenu } from '../extensions/contextMenu';\n\n// 导出类型\nexport type {\n CodeEditorProps,\n CodeEditorHandle,\n LanguageType,\n EditorTheme,\n ContextMenuItem,\n VariableInfo,\n OutlineItem,\n AutocompletionConfig,\n JumpToDefinitionConfig,\n CodeSnippet,\n HistoryEntry,\n} from '../types';\n\nimport type { CodeEditorProps, CodeEditorHandle, AutocompletionConfig, JumpToDefinitionConfig, HistoryEntry } from '../types';\n\n// ============= 语言扩展映射 =============\n\nconst getLanguageExtension = (language: string): Extension => {\n const langMap: Record<string, () => Extension> = {\n javascript: () => javascript({ jsx: false }),\n jsx: () => javascript({ jsx: true }),\n typescript: () => javascript({ jsx: false, typescript: true }),\n tsx: () => javascript({ jsx: true, typescript: true }),\n python,\n html,\n css,\n json,\n markdown,\n };\n\n return langMap[language]?.() || javascript();\n};\n\n// ============= CodeEditor 组件 =============\n\nconst CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({\n value = '',\n onChange,\n language = 'javascript',\n theme = 'light',\n readOnly = false,\n lineNumbers: showLineNumbers = true,\n highlightActiveLine: shouldHighlightActiveLine = true,\n autocompletion = true,\n jumpToDefinition: jumpToDefinitionConfig = true,\n contextMenu,\n onVariablesCollected,\n onOutlineGenerated,\n enableHistory = false,\n historyLimit = 50,\n historySaveInterval = 3, // 默认 3 * 10s = 30s\n onHistoryChange,\n className = '',\n height = '400px',\n minHeight,\n maxHeight,\n placeholder,\n extensions: customExtensions = [],\n}, ref) => {\n const editorRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [contextMenuState, setContextMenuState] = useState<{\n visible: boolean;\n x: number;\n y: number;\n }>({ visible: false, x: 0, y: 0 });\n\n // 历史记录状态\n const [codeHistory, setCodeHistory] = useState<HistoryEntry[]>([]);\n const [currentHistoryIndex, setCurrentHistoryIndex] = useState<number>(-1);\n const lastSaveTime = useRef<number>(0);\n const isRestoringHistory = useRef<boolean>(false);\n const isExternalUpdate = useRef<boolean>(false); // 标记是否是外部更新\n const pendingContent = useRef<string>('');\n const hasChanges = useRef<boolean>(false);\n const lastSavedContent = useRef<string>(''); // 记录上次保存的内容\n\n // 配置隔间,用于动态更新\n const languageCompartment = useRef(new Compartment());\n const themeCompartment = useRef(new Compartment());\n const highlightCompartment = useRef(new Compartment());\n const readOnlyCompartment = useRef(new Compartment());\n\n // 使用 ref 存储 language,确保 updateListener 能访问到最新值\n const languageRef = useRef(language);\n\n // 更新 languageRef\n useEffect(() => {\n languageRef.current = language;\n }, [language]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n if (viewRef.current) {\n try {\n const lineInfo = viewRef.current.state.doc.line(line);\n viewRef.current.dispatch({\n selection: { anchor: lineInfo.from, head: lineInfo.to },\n scrollIntoView: true,\n });\n viewRef.current.focus();\n } catch (error) {\n console.error('Failed to jump to line:', error);\n }\n }\n }, []);\n\n // 添加历史记录\n const addToHistory = useCallback((content: string, description?: string) => {\n // 如果是外部更新或正在恢复历史,不添加记录\n if (!enableHistory || isRestoringHistory.current || isExternalUpdate.current) {\n return;\n }\n\n const now = Date.now();\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n const timeSinceLastSave = now - lastSaveTime.current;\n const timeCheckPassed = timeSinceLastSave >= intervalMs;\n\n // 按配置的间隔记录\n if (!timeCheckPassed) {\n // 时间未到,标记有变更,但不立即保存\n hasChanges.current = true;\n pendingContent.current = content;\n return;\n }\n\n // 时间检查已通过,现在检查内容是否真的发生变化\n if (content === lastSavedContent.current && !description) {\n // 内容没有变化,不保存\n hasChanges.current = false;\n return;\n }\n\n // 时间检查通过 + 内容有变化 → 保存!\n lastSaveTime.current = now;\n hasChanges.current = false;\n lastSavedContent.current = content; // 记录本次保存的内容\n\n setCodeHistory((prevHistory) => {\n // 如果当前不在最新位置,删除后面的历史\n const newHistory = currentHistoryIndex >= 0\n ? prevHistory.slice(0, currentHistoryIndex + 1)\n : prevHistory;\n\n const newEntry: HistoryEntry = {\n id: `${now}-${Math.random()}`,\n timestamp: new Date(now),\n content,\n description,\n };\n\n const updatedHistory = [...newHistory, newEntry];\n\n // 限制历史记录数量\n if (updatedHistory.length > historyLimit) {\n updatedHistory.shift();\n }\n\n const newIndex = updatedHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(updatedHistory, newIndex);\n }\n }, 0);\n\n return updatedHistory;\n });\n }, [enableHistory, historyLimit, historySaveInterval, currentHistoryIndex, onHistoryChange]);\n\n // 恢复历史记录\n const restoreHistory = useCallback((index: number) => {\n if (index < 0 || index >= codeHistory.length) return;\n\n isRestoringHistory.current = true;\n const entry = codeHistory[index];\n\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: entry.content,\n },\n });\n }\n\n // 清除当前版本之后的所有版本\n const newHistory = codeHistory.slice(0, index + 1);\n setCodeHistory(newHistory);\n\n // 回滚的版本成为最新版本\n const newIndex = newHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(newHistory, newIndex);\n }\n }, 0);\n\n // 触发 onChange\n if (onChange) {\n onChange(entry.content);\n }\n\n // 延迟重置标志,确保不会立即添加到历史\n setTimeout(() => {\n isRestoringHistory.current = false;\n }, 100);\n }, [codeHistory, onChange, onHistoryChange]);\n\n // 暴露历史记录相关方法\n useImperativeHandle(ref, () => ({\n jumpToLine,\n getView: () => viewRef.current,\n getValue: () => viewRef.current?.state.doc.toString() || '',\n setValue: (newValue: string) => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: newValue,\n },\n });\n }\n },\n focus: () => viewRef.current?.focus(),\n getHistory: () => codeHistory,\n restoreHistory,\n clearHistory: () => {\n setCodeHistory([]);\n setCurrentHistoryIndex(-1);\n // 重置所有历史记录相关的内部状态\n lastSaveTime.current = 0;\n hasChanges.current = false;\n pendingContent.current = '';\n lastSavedContent.current = '';\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange([], -1);\n }\n }, 0);\n },\n } as any), [jumpToLine, codeHistory, restoreHistory, onHistoryChange]);\n\n // 定时保存待处理的历史记录\n useEffect(() => {\n if (!enableHistory) return;\n\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n\n const interval = setInterval(() => {\n if (hasChanges.current && pendingContent.current) {\n addToHistory(pendingContent.current);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n }, [enableHistory, historySaveInterval, addToHistory]);\n\n // 初始化编辑器\n useEffect(() => {\n if (!editorRef.current) return;\n\n const updateListener = EditorView.updateListener.of((update) => {\n if (update.docChanged && onChange) {\n const newContent = update.state.doc.toString();\n onChange(newContent);\n\n // 添加到历史记录\n // 注意:只有在用户实际输入时才添加,外部更新不添加\n if (enableHistory && !isExternalUpdate.current) {\n addToHistory(newContent);\n }\n\n // 如果是外部更新触发的变更,重置标志\n if (isExternalUpdate.current) {\n isExternalUpdate.current = false;\n }\n }\n\n if (update.docChanged && onVariablesCollected) {\n const code = update.state.doc.toString();\n // 使用 languageRef.current 获取最新的 language 值\n const variables = collectVariables(code, languageRef.current);\n onVariablesCollected(variables);\n }\n\n if (update.docChanged && onOutlineGenerated) {\n const code = update.state.doc.toString();\n // 使用 languageRef.current 获取最新的 language 值\n const outline = generateOutline(code, languageRef.current);\n onOutlineGenerated(outline);\n }\n });\n\n const baseExtensions: Extension[] = [\n history(),\n drawSelection(),\n bracketMatching(),\n closeBrackets(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n languageCompartment.current.of(getLanguageExtension(language)),\n themeCompartment.current.of(createThemeExtension(theme)),\n highlightCompartment.current.of(createHighlightExtension(theme)),\n readOnlyCompartment.current.of(EditorState.readOnly.of(readOnly)),\n updateListener,\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n bracketMatchingStyle,\n lineHighlightStyle,\n jumpTargetHighlight,\n ];\n\n // 可选扩展\n if (showLineNumbers) {\n baseExtensions.push(lineNumbers(), foldGutter(), highlightActiveLineGutter());\n }\n\n if (shouldHighlightActiveLine) {\n baseExtensions.push(highlightActiveLine());\n }\n\n // 自动补全\n if (autocompletion) {\n const config: AutocompletionConfig = typeof autocompletion === 'object' ? autocompletion : {};\n baseExtensions.push(smartAutocompletion(language, config));\n }\n\n // 跳转到定义\n if (jumpToDefinitionConfig) {\n const config: JumpToDefinitionConfig = typeof jumpToDefinitionConfig === 'object'\n ? jumpToDefinitionConfig\n : {};\n baseExtensions.push(jumpToDefinition(jumpToLine, config));\n }\n\n // 占位符\n if (placeholder) {\n baseExtensions.push(\n EditorView.contentAttributes.of({ 'data-placeholder': placeholder })\n );\n }\n\n // 自定义扩展\n if (customExtensions.length > 0) {\n baseExtensions.push(...customExtensions);\n }\n\n const startState = EditorState.create({\n doc: value,\n extensions: baseExtensions,\n });\n\n const view = new EditorView({\n state: startState,\n parent: editorRef.current,\n });\n\n viewRef.current = view;\n\n // 延迟初始收集变量和大纲(避免在渲染期间更新父组件)\n setTimeout(() => {\n if (onVariablesCollected) {\n const variables = collectVariables(value, language);\n onVariablesCollected(variables);\n }\n\n if (onOutlineGenerated) {\n const outline = generateOutline(value, language);\n onOutlineGenerated(outline);\n }\n }, 0);\n\n // 添加初始内容到历史记录\n if (enableHistory && value) {\n addToHistory(value, 'Initial content');\n }\n\n return () => {\n view.destroy();\n };\n }, []); // 只在挂载时初始化\n\n // 更新值\n useEffect(() => {\n if (viewRef.current && value !== viewRef.current.state.doc.toString()) {\n isExternalUpdate.current = true; // 标记为外部更新\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: value,\n },\n });\n // 注意:标志会在 updateListener 中被立即重置,不需要 setTimeout\n }\n }, [value]);\n\n // 更新语言\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: languageCompartment.current.reconfigure(getLanguageExtension(language)),\n });\n\n const code = viewRef.current.state.doc.toString();\n\n // 延迟执行回调,避免在渲染期间更新父组件\n setTimeout(() => {\n if (onVariablesCollected) {\n const variables = collectVariables(code, language);\n onVariablesCollected(variables);\n }\n if (onOutlineGenerated) {\n const outline = generateOutline(code, language);\n onOutlineGenerated(outline);\n }\n }, 0);\n }\n }, [language, onVariablesCollected, onOutlineGenerated]);\n\n // 更新主题\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: [\n themeCompartment.current.reconfigure(createThemeExtension(theme)),\n highlightCompartment.current.reconfigure(createHighlightExtension(theme)),\n ],\n });\n }\n }, [theme]);\n\n // 更新只读状态\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: readOnlyCompartment.current.reconfigure(EditorState.readOnly.of(readOnly)),\n });\n }\n }, [readOnly]);\n\n // 处理右键菜单\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setContextMenuState({\n visible: true,\n x: e.clientX,\n y: e.clientY,\n });\n }, []);\n\n const closeContextMenu = useCallback(() => {\n setContextMenuState({ visible: false, x: 0, y: 0 });\n }, []);\n\n const handleMenuItemClick = useCallback(\n (item: any) => {\n if (viewRef.current && !item.disabled) {\n item.action(viewRef.current);\n }\n closeContextMenu();\n },\n [closeContextMenu]\n );\n\n // 点击其他地方关闭菜单\n useEffect(() => {\n if (contextMenuState.visible) {\n const handleClick = () => closeContextMenu();\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }\n }, [contextMenuState.visible, closeContextMenu]);\n\n const editorStyles: React.CSSProperties = {\n height,\n minHeight,\n maxHeight,\n overflow: 'auto',\n };\n\n const menuItems = contextMenu || defaultContextMenu;\n\n return (\n <div className={`code-editor-wrapper ${className}`}>\n <div\n ref={editorRef}\n onContextMenu={handleContextMenu}\n style={editorStyles}\n className=\"code-editor\"\n />\n\n {/* 上下文菜单 */}\n {contextMenuState.visible && (\n <div\n className=\"context-menu\"\n style={{\n position: 'fixed',\n top: contextMenuState.y,\n left: contextMenuState.x,\n zIndex: 1000,\n }}\n >\n <ul className=\"menu bg-base-200 rounded-box shadow-lg\">\n {menuItems.map((item, index) => {\n if (item.separator) {\n return <li key={index} className=\"menu-separator\" />;\n }\n return (\n <li key={index}>\n <a\n onClick={() => handleMenuItemClick(item)}\n className={item.disabled ? 'disabled' : ''}\n >\n {item.label}\n </a>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n <style>{`\n .code-editor-wrapper {\n position: relative;\n border: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2));\n border-radius: 0.5rem;\n overflow: hidden;\n }\n\n .code-editor .cm-editor {\n height: 100%;\n }\n\n .code-editor .cm-scroller {\n overflow: auto;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .code-editor .cm-content[data-placeholder]::before {\n content: attr(data-placeholder);\n color: var(--fallback-bc, oklch(var(--bc) / 0.4));\n position: absolute;\n pointer-events: none;\n }\n\n .context-menu {\n min-width: 150px;\n }\n\n .context-menu .menu-separator {\n height: 1px;\n background: var(--fallback-bc, oklch(var(--bc) / 0.2));\n margin: 0.25rem 0;\n }\n\n .context-menu .disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n `}</style>\n </div>\n );\n});\n\nCodeEditor.displayName = 'CodeEditor';\n\nexport default CodeEditor;\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeEditor.js","names":[],"sources":["../../../../../src/components/pro/CodeEditor/editors/CodeEditor.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react';\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection } from '@codemirror/view';\nimport { EditorState, Extension, Compartment } from '@codemirror/state';\nimport { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport { syntaxHighlighting, defaultHighlightStyle, foldGutter, indentOnInput, bracketMatching } from '@codemirror/language';\nimport { completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';\nimport { lintKeymap } from '@codemirror/lint';\nimport { searchKeymap } from '@codemirror/search';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { html } from '@codemirror/lang-html';\nimport { css } from '@codemirror/lang-css';\nimport { json } from '@codemirror/lang-json';\nimport { markdown } from '@codemirror/lang-markdown';\nimport { jumpToDefinition, smartAutocompletion, bracketMatchingStyle, lineHighlightStyle, jumpTargetHighlight } from '../extensions';\nimport { createThemeExtension, createHighlightExtension } from '../themes';\nimport { collectVariables, generateOutline } from '../utils';\nimport { defaultContextMenu } from '../extensions/contextMenu';\n\n// 导出类型\nexport type {\n CodeEditorProps,\n CodeEditorHandle,\n LanguageType,\n EditorTheme,\n ContextMenuItem,\n VariableInfo,\n OutlineItem,\n AutocompletionConfig,\n JumpToDefinitionConfig,\n CodeSnippet,\n HistoryEntry,\n} from '../types';\n\nimport type { CodeEditorProps, CodeEditorHandle, AutocompletionConfig, JumpToDefinitionConfig, HistoryEntry } from '../types';\n\n// ============= 语言扩展映射 =============\n\nconst getLanguageExtension = (language: string): Extension => {\n const langMap: Record<string, () => Extension> = {\n javascript: () => javascript({ jsx: false }),\n jsx: () => javascript({ jsx: true }),\n typescript: () => javascript({ jsx: false, typescript: true }),\n tsx: () => javascript({ jsx: true, typescript: true }),\n python,\n html,\n css,\n json,\n markdown,\n };\n\n return langMap[language]?.() || javascript();\n};\n\n// ============= CodeEditor 组件 =============\n\nconst CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({\n value = '',\n onChange,\n language = 'javascript',\n theme = 'light',\n readOnly = false,\n lineNumbers: showLineNumbers = true,\n highlightActiveLine: shouldHighlightActiveLine = true,\n autocompletion = true,\n jumpToDefinition: jumpToDefinitionConfig = true,\n contextMenu,\n onVariablesCollected,\n onOutlineGenerated,\n enableHistory = false,\n historyLimit = 50,\n historySaveInterval = 3, // 默认 3 * 10s = 30s\n onHistoryChange,\n className = '',\n height = '400px',\n minHeight,\n maxHeight,\n placeholder,\n extensions: customExtensions = [],\n}, ref) => {\n const editorRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [contextMenuState, setContextMenuState] = useState<{\n visible: boolean;\n x: number;\n y: number;\n }>({ visible: false, x: 0, y: 0 });\n\n // 历史记录状态\n const [codeHistory, setCodeHistory] = useState<HistoryEntry[]>([]);\n const [currentHistoryIndex, setCurrentHistoryIndex] = useState<number>(-1);\n const lastSaveTime = useRef<number>(0);\n const isRestoringHistory = useRef<boolean>(false);\n const isExternalUpdate = useRef<boolean>(false); // 标记是否是外部更新\n const pendingContent = useRef<string>('');\n const hasChanges = useRef<boolean>(false);\n const lastSavedContent = useRef<string>(''); // 记录上次保存的内容\n\n // 配置隔间,用于动态更新\n const languageCompartment = useRef(new Compartment());\n const themeCompartment = useRef(new Compartment());\n const highlightCompartment = useRef(new Compartment());\n const readOnlyCompartment = useRef(new Compartment());\n\n // 使用 ref 存储 language,确保 updateListener 能访问到最新值\n const languageRef = useRef(language);\n\n // 更新 languageRef\n useEffect(() => {\n languageRef.current = language;\n }, [language]);\n\n // 跳转到指定行\n const jumpToLine = useCallback((line: number) => {\n if (viewRef.current) {\n try {\n const lineInfo = viewRef.current.state.doc.line(line);\n viewRef.current.dispatch({\n selection: { anchor: lineInfo.from, head: lineInfo.to },\n scrollIntoView: true,\n });\n viewRef.current.focus();\n } catch (error) {\n console.error('Failed to jump to line:', error);\n }\n }\n }, []);\n\n // 添加历史记录\n const addToHistory = useCallback((content: string, description?: string) => {\n // 如果是外部更新或正在恢复历史,不添加记录\n if (!enableHistory || isRestoringHistory.current || isExternalUpdate.current) {\n return;\n }\n\n const now = Date.now();\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n const timeSinceLastSave = now - lastSaveTime.current;\n const timeCheckPassed = timeSinceLastSave >= intervalMs;\n\n // 按配置的间隔记录\n if (!timeCheckPassed) {\n // 时间未到,标记有变更,但不立即保存\n hasChanges.current = true;\n pendingContent.current = content;\n return;\n }\n\n // 时间检查已通过,现在检查内容是否真的发生变化\n if (content === lastSavedContent.current && !description) {\n // 内容没有变化,不保存\n hasChanges.current = false;\n return;\n }\n\n // 时间检查通过 + 内容有变化 → 保存!\n lastSaveTime.current = now;\n hasChanges.current = false;\n lastSavedContent.current = content; // 记录本次保存的内容\n\n setCodeHistory((prevHistory) => {\n // 如果当前不在最新位置,删除后面的历史\n const newHistory = currentHistoryIndex >= 0\n ? prevHistory.slice(0, currentHistoryIndex + 1)\n : prevHistory;\n\n const newEntry: HistoryEntry = {\n id: `${now}-${Math.random()}`,\n timestamp: new Date(now),\n content,\n description,\n };\n\n const updatedHistory = [...newHistory, newEntry];\n\n // 限制历史记录数量\n if (updatedHistory.length > historyLimit) {\n updatedHistory.shift();\n }\n\n const newIndex = updatedHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(updatedHistory, newIndex);\n }\n }, 0);\n\n return updatedHistory;\n });\n }, [enableHistory, historyLimit, historySaveInterval, currentHistoryIndex, onHistoryChange]);\n\n // 恢复历史记录\n const restoreHistory = useCallback((index: number) => {\n if (index < 0 || index >= codeHistory.length) return;\n\n isRestoringHistory.current = true;\n const entry = codeHistory[index];\n\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: entry.content,\n },\n });\n }\n\n // 清除当前版本之后的所有版本\n const newHistory = codeHistory.slice(0, index + 1);\n setCodeHistory(newHistory);\n\n // 回滚的版本成为最新版本\n const newIndex = newHistory.length - 1;\n setCurrentHistoryIndex(newIndex);\n\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange(newHistory, newIndex);\n }\n }, 0);\n\n // 触发 onChange\n if (onChange) {\n onChange(entry.content);\n }\n\n // 延迟重置标志,确保不会立即添加到历史\n setTimeout(() => {\n isRestoringHistory.current = false;\n }, 100);\n }, [codeHistory, onChange, onHistoryChange]);\n\n // 暴露历史记录相关方法\n useImperativeHandle(ref, () => ({\n jumpToLine,\n getView: () => viewRef.current,\n getValue: () => viewRef.current?.state.doc.toString() || '',\n setValue: (newValue: string) => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: newValue,\n },\n });\n }\n },\n focus: () => viewRef.current?.focus(),\n getHistory: () => codeHistory,\n restoreHistory,\n clearHistory: () => {\n setCodeHistory([]);\n setCurrentHistoryIndex(-1);\n // 重置所有历史记录相关的内部状态\n lastSaveTime.current = 0;\n hasChanges.current = false;\n pendingContent.current = '';\n lastSavedContent.current = '';\n // 延迟调用 onHistoryChange 避免在渲染期间更新父组件\n setTimeout(() => {\n if (onHistoryChange) {\n onHistoryChange([], -1);\n }\n }, 0);\n },\n } as any), [jumpToLine, codeHistory, restoreHistory, onHistoryChange]);\n\n // 定时保存待处理的历史记录\n useEffect(() => {\n if (!enableHistory) return;\n\n const intervalMs = historySaveInterval * 10000; // 转换为毫秒\n\n const interval = setInterval(() => {\n if (hasChanges.current && pendingContent.current) {\n addToHistory(pendingContent.current);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n }, [enableHistory, historySaveInterval, addToHistory]);\n\n // 初始化编辑器\n useEffect(() => {\n if (!editorRef.current) return;\n\n const updateListener = EditorView.updateListener.of((update) => {\n if (update.docChanged && onChange) {\n const newContent = update.state.doc.toString();\n onChange(newContent);\n\n // 添加到历史记录\n // 注意:只有在用户实际输入时才添加,外部更新不添加\n if (enableHistory && !isExternalUpdate.current) {\n addToHistory(newContent);\n }\n\n // 如果是外部更新触发的变更,重置标志\n if (isExternalUpdate.current) {\n isExternalUpdate.current = false;\n }\n }\n\n if (update.docChanged && onVariablesCollected) {\n const code = update.state.doc.toString();\n // 使用 languageRef.current 获取最新的 language 值\n const variables = collectVariables(code, languageRef.current);\n onVariablesCollected(variables);\n }\n\n if (update.docChanged && onOutlineGenerated) {\n const code = update.state.doc.toString();\n // 使用 languageRef.current 获取最新的 language 值\n const outline = generateOutline(code, languageRef.current);\n onOutlineGenerated(outline);\n }\n });\n\n const baseExtensions: Extension[] = [\n history(),\n drawSelection(),\n bracketMatching(),\n closeBrackets(),\n indentOnInput(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n languageCompartment.current.of(getLanguageExtension(language)),\n themeCompartment.current.of(createThemeExtension(theme)),\n highlightCompartment.current.of(createHighlightExtension(theme)),\n readOnlyCompartment.current.of(EditorState.readOnly.of(readOnly)),\n updateListener,\n keymap.of([\n ...closeBracketsKeymap,\n ...defaultKeymap,\n ...searchKeymap,\n ...historyKeymap,\n ...completionKeymap,\n ...lintKeymap,\n indentWithTab,\n ]),\n bracketMatchingStyle,\n lineHighlightStyle,\n jumpTargetHighlight,\n ];\n\n // 可选扩展\n if (showLineNumbers) {\n baseExtensions.push(lineNumbers(), foldGutter(), highlightActiveLineGutter());\n }\n\n if (shouldHighlightActiveLine) {\n baseExtensions.push(highlightActiveLine());\n }\n\n // 自动补全\n if (autocompletion) {\n const config: AutocompletionConfig = typeof autocompletion === 'object' ? autocompletion : {};\n baseExtensions.push(smartAutocompletion(language, config));\n }\n\n // 跳转到定义\n if (jumpToDefinitionConfig) {\n const config: JumpToDefinitionConfig = typeof jumpToDefinitionConfig === 'object'\n ? jumpToDefinitionConfig\n : {};\n baseExtensions.push(jumpToDefinition(jumpToLine, config));\n }\n\n // 占位符\n if (placeholder) {\n baseExtensions.push(\n EditorView.contentAttributes.of({ 'data-placeholder': placeholder })\n );\n }\n\n // 自定义扩展\n if (customExtensions.length > 0) {\n baseExtensions.push(...customExtensions);\n }\n\n const startState = EditorState.create({\n doc: value,\n extensions: baseExtensions,\n });\n\n const view = new EditorView({\n state: startState,\n parent: editorRef.current,\n });\n\n viewRef.current = view;\n\n // 延迟初始收集变量和大纲(避免在渲染期间更新父组件)\n setTimeout(() => {\n if (onVariablesCollected) {\n const variables = collectVariables(value, language);\n onVariablesCollected(variables);\n }\n\n if (onOutlineGenerated) {\n const outline = generateOutline(value, language);\n onOutlineGenerated(outline);\n }\n }, 0);\n\n // 添加初始内容到历史记录\n if (enableHistory && value) {\n addToHistory(value, 'Initial content');\n }\n\n return () => {\n view.destroy();\n };\n }, []); // 只在挂载时初始化\n\n // 更新值\n useEffect(() => {\n if (viewRef.current && value !== viewRef.current.state.doc.toString()) {\n isExternalUpdate.current = true; // 标记为外部更新\n viewRef.current.dispatch({\n changes: {\n from: 0,\n to: viewRef.current.state.doc.length,\n insert: value,\n },\n });\n // 注意:标志会在 updateListener 中被立即重置,不需要 setTimeout\n }\n }, [value]);\n\n // 更新语言\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: languageCompartment.current.reconfigure(getLanguageExtension(language)),\n });\n\n const code = viewRef.current.state.doc.toString();\n\n // 延迟执行回调,避免在渲染期间更新父组件\n setTimeout(() => {\n if (onVariablesCollected) {\n const variables = collectVariables(code, language);\n onVariablesCollected(variables);\n }\n if (onOutlineGenerated) {\n const outline = generateOutline(code, language);\n onOutlineGenerated(outline);\n }\n }, 0);\n }\n }, [language, onVariablesCollected, onOutlineGenerated]);\n\n // 更新主题\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: [\n themeCompartment.current.reconfigure(createThemeExtension(theme)),\n highlightCompartment.current.reconfigure(createHighlightExtension(theme)),\n ],\n });\n }\n }, [theme]);\n\n // 更新只读状态\n useEffect(() => {\n if (viewRef.current) {\n viewRef.current.dispatch({\n effects: readOnlyCompartment.current.reconfigure(EditorState.readOnly.of(readOnly)),\n });\n }\n }, [readOnly]);\n\n // 处理右键菜单\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setContextMenuState({\n visible: true,\n x: e.clientX,\n y: e.clientY,\n });\n }, []);\n\n const closeContextMenu = useCallback(() => {\n setContextMenuState({ visible: false, x: 0, y: 0 });\n }, []);\n\n const handleMenuItemClick = useCallback(\n (item: any) => {\n if (viewRef.current && !item.disabled) {\n item.action(viewRef.current);\n }\n closeContextMenu();\n },\n [closeContextMenu]\n );\n\n // 点击其他地方关闭菜单\n useEffect(() => {\n if (contextMenuState.visible) {\n const handleClick = () => closeContextMenu();\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }\n }, [contextMenuState.visible, closeContextMenu]);\n\n const editorStyles: React.CSSProperties = {\n height,\n minHeight,\n maxHeight,\n overflow: 'auto',\n };\n\n const menuItems = contextMenu || defaultContextMenu;\n\n return (\n <div className={`code-editor-wrapper ${className}`}>\n <div\n ref={editorRef}\n onContextMenu={handleContextMenu}\n style={editorStyles}\n className=\"code-editor\"\n />\n\n {/* 上下文菜单 */}\n {contextMenuState.visible && (\n <div\n className=\"context-menu\"\n style={{\n position: 'fixed',\n top: contextMenuState.y,\n left: contextMenuState.x,\n zIndex: 1000,\n }}\n >\n <ul className=\"menu bg-base-200 rounded-box shadow-lg\">\n {menuItems.map((item, index) => {\n if (item.separator) {\n return <li key={index} className=\"menu-separator\" />;\n }\n return (\n <li key={index}>\n <a\n onClick={() => handleMenuItemClick(item)}\n className={item.disabled ? 'disabled' : ''}\n >\n {item.label}\n </a>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n <style>{`\n .code-editor-wrapper {\n position: relative;\n border: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2));\n border-radius: 0.5rem;\n overflow: hidden;\n }\n\n .code-editor .cm-editor {\n height: 100%;\n }\n\n .code-editor .cm-scroller {\n overflow: auto;\n font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .code-editor .cm-content[data-placeholder]::before {\n content: attr(data-placeholder);\n color: var(--fallback-bc, oklch(var(--bc) / 0.4));\n position: absolute;\n pointer-events: none;\n }\n\n .context-menu {\n min-width: 150px;\n }\n\n .context-menu .menu-separator {\n height: 1px;\n background: var(--fallback-bc, oklch(var(--bc) / 0.2));\n margin: 0.25rem 0;\n }\n\n .context-menu .disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n `}</style>\n </div>\n );\n});\n\nCodeEditor.displayName = 'CodeEditor';\n\nexport default CodeEditor;\n\n"],"mappings":"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"}
|