dishui 0.0.84 → 0.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/components/Input/index.js +52 -62
  2. package/dist/components/Input/index.js.map +1 -1
  3. package/dist/components/LayoutSuite/index.d.ts +10 -0
  4. package/dist/components/LayoutSuite/index.js +27 -18
  5. package/dist/components/LayoutSuite/index.js.map +1 -1
  6. package/dist/components/Markdown/markdownComponents.js +1 -0
  7. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  8. package/dist/components/Markdown/useMarkdownSource.js +46 -31
  9. package/dist/components/Markdown/useMarkdownSource.js.map +1 -1
  10. package/dist/components/Markdown/useMarkmapRenderer.js +44 -31
  11. package/dist/components/Markdown/useMarkmapRenderer.js.map +1 -1
  12. package/dist/components/Markdown/useMermaidRenderer.js +49 -31
  13. package/dist/components/Markdown/useMermaidRenderer.js.map +1 -1
  14. package/dist/components/ProtectedRoute/index.d.ts +2 -1
  15. package/dist/components/ProtectedRoute/index.js +16 -6
  16. package/dist/components/ProtectedRoute/index.js.map +1 -1
  17. package/dist/components/Select/index.d.ts +6 -0
  18. package/dist/components/Select/index.js +166 -136
  19. package/dist/components/Select/index.js.map +1 -1
  20. package/dist/components/Table/index.d.ts +23 -2
  21. package/dist/components/Table/index.js +153 -101
  22. package/dist/components/Table/index.js.map +1 -1
  23. package/dist/components/Tabs/index.d.ts +12 -1
  24. package/dist/components/Tabs/index.js +42 -17
  25. package/dist/components/Tabs/index.js.map +1 -1
  26. package/dist/components/pro/ArticleContextMenu/index.js +7 -7
  27. package/dist/components/pro/CodeEditor/editors/CodeEditor.js +200 -189
  28. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  29. package/dist/components/pro/CodeEditor/types.d.ts +3 -0
  30. package/dist/components/pro/DataTable/DataTable.d.ts +1 -1
  31. package/dist/components/pro/DataTable/DataTable.js +124 -247
  32. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  33. package/dist/components/pro/DataTable/components/TableBody.d.ts +3 -1
  34. package/dist/components/pro/DataTable/components/TableBody.js +41 -41
  35. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  36. package/dist/components/pro/DataTable/components/TablePagination.d.ts +3 -9
  37. package/dist/components/pro/DataTable/components/TablePagination.js +29 -25
  38. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  39. package/dist/components/pro/DataTable/components/TableToolbar.d.ts +2 -1
  40. package/dist/components/pro/DataTable/components/TableToolbar.js +25 -19
  41. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  42. package/dist/components/pro/DataTable/index.d.ts +1 -1
  43. package/dist/components/pro/DataTable/rowDetailExtension.js +1 -1
  44. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  45. package/dist/components/pro/DataTable/tanstack-table.d.ts +2 -2
  46. package/dist/components/pro/DataTable/tanstack-table.js +29 -21
  47. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  48. package/dist/components/pro/DataTable/treeDataUtils.d.ts +2 -0
  49. package/dist/components/pro/DataTable/treeDataUtils.js +18 -19
  50. package/dist/components/pro/DataTable/treeDataUtils.js.map +1 -1
  51. package/dist/components/pro/DataTable/types.d.ts +43 -0
  52. package/dist/components/pro/DataTable/useDataTableModel.d.ts +16 -0
  53. package/dist/components/pro/DataTable/useDataTableModel.js +148 -0
  54. package/dist/components/pro/DataTable/useDataTableModel.js.map +1 -0
  55. package/dist/components/pro/FileExplorer/Breadcrumb.js +12 -12
  56. package/dist/components/pro/Flow/nodes/DataNodeView.js +87 -82
  57. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  58. package/dist/components/pro/Flow/nodes/MediaContent.js +1 -1
  59. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  60. package/dist/components/pro/Flow/nodes/MediaOverlay.js +1 -1
  61. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  62. package/dist/components/pro/Flow/nodes/Model3DView.js +69 -63
  63. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  64. package/dist/components/pro/Flow/nodes/chartGeometryBudget.d.ts +14 -0
  65. package/dist/components/pro/Flow/nodes/chartGeometryBudget.js +76 -0
  66. package/dist/components/pro/Flow/nodes/chartGeometryBudget.js.map +1 -0
  67. package/dist/components/pro/Flow/nodes/demandRender.d.ts +11 -0
  68. package/dist/components/pro/Flow/nodes/demandRender.js +26 -0
  69. package/dist/components/pro/Flow/nodes/demandRender.js.map +1 -0
  70. package/dist/components/pro/RichTextEditor/SlashMenu.js +68 -58
  71. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  72. package/dist/contexts/AppContext.d.ts +1 -0
  73. package/dist/contexts/AppContext.js +144 -145
  74. package/dist/contexts/AppContext.js.map +1 -1
  75. package/dist/contexts/authentication.d.ts +7 -0
  76. package/dist/contexts/authentication.js +22 -0
  77. package/dist/contexts/authentication.js.map +1 -0
  78. package/dist/data-table.js.map +1 -1
  79. package/dist/dishui.css +1 -1
  80. package/dist/hooks/useControllableState.d.ts +6 -14
  81. package/dist/hooks/useControllableState.js +21 -15
  82. package/dist/hooks/useControllableState.js.map +1 -1
  83. package/dist/hooks/useTableColumns.d.ts +3 -3
  84. package/dist/hooks/useTableColumns.js +2 -2
  85. package/dist/hooks/useTableColumns.js.map +1 -1
  86. package/dist/hooks/useTableData.d.ts +11 -4
  87. package/dist/hooks/useTableData.js +44 -26
  88. package/dist/hooks/useTableData.js.map +1 -1
  89. package/dist/index-nostyled.d.ts +2 -2
  90. package/dist/index.d.ts +4 -4
  91. package/dist/index.js +97 -97
  92. package/dist/lite.d.ts +2 -0
  93. package/dist/lite.js +22 -21
  94. package/dist/utils/i18n.js +1 -1
  95. package/dist/utils/i18n.js.map +1 -1
  96. package/dist/utils/routerBuilder.d.ts +7 -5
  97. package/dist/utils/routerBuilder.js +11 -15
  98. package/dist/utils/routerBuilder.js.map +1 -1
  99. package/dist/utils/safeStorage.d.ts +8 -0
  100. package/dist/utils/safeStorage.js +45 -0
  101. package/dist/utils/safeStorage.js.map +1 -0
  102. package/package.json +22 -5
@@ -1,290 +1,301 @@
1
1
  import { bracketMatchingStyle as e, jumpTargetHighlight as t, jumpToDefinition as n, lineHighlightStyle as r, smartAutocompletion as i } from "../extensions/index.js";
2
2
  import { createHighlightExtension as a, createThemeExtension as o } from "../themes.js";
3
3
  import { collectVariables as s, generateOutline as c } from "../utils.js";
4
- import { defaultContextMenu as l } from "../extensions/contextMenu.js";
5
- import { forwardRef as u, useCallback as d, useEffect as f, useImperativeHandle as p, useRef as m, useState as h } from "react";
6
- import { jsx as g, jsxs as ee } from "react/jsx-runtime";
7
- import { EditorView as _, drawSelection as te, highlightActiveLine as ne, highlightActiveLineGutter as re, keymap as ie, lineNumbers as ae } from "@codemirror/view";
8
- import { Compartment as v, EditorState as y } from "@codemirror/state";
9
- import { defaultKeymap as oe, history as se, historyKeymap as ce, indentWithTab as le } from "@codemirror/commands";
10
- import { bracketMatching as ue, defaultHighlightStyle as de, foldGutter as fe, indentOnInput as pe, syntaxHighlighting as me } from "@codemirror/language";
11
- import { closeBrackets as he, closeBracketsKeymap as ge, completionKeymap as _e } from "@codemirror/autocomplete";
12
- import { lintKeymap as ve } from "@codemirror/lint";
13
- import { searchKeymap as ye } from "@codemirror/search";
14
- import { javascript as b } from "@codemirror/lang-javascript";
15
- import { python as x } from "@codemirror/lang-python";
16
- import { html as S } from "@codemirror/lang-html";
17
- import { css as C } from "@codemirror/lang-css";
18
- import { json as w } from "@codemirror/lang-json";
19
- import { markdown as T } from "@codemirror/lang-markdown";
4
+ import { defaultContextMenu as ee } from "../extensions/contextMenu.js";
5
+ import { forwardRef as l, useCallback as u, useEffect as d, useImperativeHandle as te, useLayoutEffect as ne, useRef as f, useState as p } from "react";
6
+ import { jsx as m, jsxs as re } from "react/jsx-runtime";
7
+ import { EditorView as h, drawSelection as ie, highlightActiveLine as ae, highlightActiveLineGutter as oe, keymap as se, lineNumbers as ce } from "@codemirror/view";
8
+ import { Compartment as g, EditorState as _ } from "@codemirror/state";
9
+ import { defaultKeymap as le, history as ue, historyKeymap as de, indentWithTab as fe } from "@codemirror/commands";
10
+ import { bracketMatching as pe, defaultHighlightStyle as me, foldGutter as he, indentOnInput as ge, syntaxHighlighting as _e } from "@codemirror/language";
11
+ import { closeBrackets as ve, closeBracketsKeymap as ye, completionKeymap as be } from "@codemirror/autocomplete";
12
+ import { lintKeymap as xe } from "@codemirror/lint";
13
+ import { searchKeymap as Se } from "@codemirror/search";
14
+ import { javascript as v } from "@codemirror/lang-javascript";
15
+ import { python as y } from "@codemirror/lang-python";
16
+ import { html as b } from "@codemirror/lang-html";
17
+ import { css as x } from "@codemirror/lang-css";
18
+ import { json as Ce } from "@codemirror/lang-json";
19
+ import { markdown as we } from "@codemirror/lang-markdown";
20
20
  //#region src/components/pro/CodeEditor/editors/CodeEditor.tsx
21
- var E = (e) => ({
22
- javascript: () => b({ jsx: !1 }),
23
- jsx: () => b({ jsx: !0 }),
24
- typescript: () => b({
21
+ var Te = (e) => ({
22
+ javascript: () => v({ jsx: !1 }),
23
+ jsx: () => v({ jsx: !0 }),
24
+ typescript: () => v({
25
25
  jsx: !1,
26
26
  typescript: !0
27
27
  }),
28
- tsx: () => b({
28
+ tsx: () => v({
29
29
  jsx: !0,
30
30
  typescript: !0
31
31
  }),
32
- python: x,
33
- html: S,
34
- css: C,
35
- json: w,
36
- markdown: T
37
- })[e]?.() || b(), D = u(({ value: u = "", onChange: b, language: x = "javascript", theme: S = "light", readOnly: C = !1, lineNumbers: w = !0, highlightActiveLine: T = !0, autocompletion: D = !0, jumpToDefinition: O = !0, contextMenu: be, onVariablesCollected: k, onOutlineGenerated: A, enableHistory: j = !1, historyLimit: M = 50, historySaveInterval: N = 3, onHistoryChange: P, className: xe = "", height: Se = "400px", minHeight: Ce, maxHeight: we, placeholder: F, extensions: Te = [] }, Ee) => {
38
- let I = m(null), L = m(null), [R, De] = h({
32
+ python: y,
33
+ html: b,
34
+ css: x,
35
+ json: Ce,
36
+ markdown: we
37
+ })[e]?.() || v(), S = l(({ value: l = "", onChange: v, language: y = "javascript", theme: b = "light", readOnly: x = !1, lineNumbers: Ce = !0, highlightActiveLine: we = !0, autocompletion: S = !0, jumpToDefinition: C = !0, contextMenu: Ee, onVariablesCollected: w, onOutlineGenerated: T, enableHistory: E = !1, historyLimit: D = 50, historySaveInterval: O = 3, onHistoryChange: k, className: De = "", height: Oe = "400px", minHeight: ke, maxHeight: Ae, placeholder: je, extensions: Me = [] }, Ne) => {
38
+ let A = f(null), j = f(null), [M, N] = p({
39
39
  visible: !1,
40
40
  x: 0,
41
41
  y: 0
42
- }), [z, B] = h([]), [V, H] = h(-1), U = m(0), W = m(!1), G = m(!1), K = m(""), q = m(!1), J = m(""), Oe = m(new v()), ke = m(new v()), Ae = m(new v()), je = m(new v()), Y = m(x);
43
- f(() => {
44
- Y.current = x;
45
- }, [x]);
46
- let X = d((e) => {
47
- if (L.current) try {
48
- let t = L.current.state.doc.line(e);
49
- L.current.dispatch({
42
+ }), [P, F] = p([]), [I, L] = p(-1), R = f(0), z = f(!1), B = f(!1), V = f(""), H = f(!1), U = f(""), Pe = f(new g()), Fe = f(new g()), Ie = f(new g()), Le = f(new g()), W = f(y), G = f(l), K = f(null), q = f(0), J = f({
43
+ onChange: v,
44
+ onVariablesCollected: w,
45
+ onOutlineGenerated: T
46
+ }), Re = !!w, ze = !!T, Y = u(() => {
47
+ q.current += 1, K.current !== null && (clearTimeout(K.current), K.current = null);
48
+ }, []), X = u((e, t = 150) => {
49
+ Y();
50
+ let n = j.current;
51
+ if (!n || !J.current.onVariablesCollected && !J.current.onOutlineGenerated) return;
52
+ let r = q.current, i = n.state.doc, a = W.current, o = () => r === q.current && j.current === n && n.state.doc === i && W.current === a;
53
+ K.current = setTimeout(() => {
54
+ if (K.current = null, !o()) return;
55
+ let t = J.current.onVariablesCollected ? s(e, a) : void 0, n = J.current.onOutlineGenerated ? c(e, a) : void 0;
56
+ t && o() && J.current.onVariablesCollected?.(t), n && o() && J.current.onOutlineGenerated?.(n);
57
+ }, t);
58
+ }, [Y]), Z = u((e) => {
59
+ if (j.current) try {
60
+ let t = j.current.state.doc.line(e);
61
+ j.current.dispatch({
50
62
  selection: {
51
63
  anchor: t.from,
52
64
  head: t.to
53
65
  },
54
66
  scrollIntoView: !0
55
- }), L.current.focus();
67
+ }), j.current.focus();
56
68
  } catch (e) {
57
69
  console.error("Failed to jump to line:", e);
58
70
  }
59
- }, []), Z = d((e, t) => {
60
- if (!j || W.current || G.current) return;
61
- let n = Date.now(), r = N * 1e4;
62
- if (!(n - U.current >= r)) {
63
- q.current = !0, K.current = e;
71
+ }, []), Q = u((e, t) => {
72
+ if (!E || z.current || B.current) return;
73
+ let n = Date.now(), r = O * 1e4;
74
+ if (!(n - R.current >= r)) {
75
+ H.current = !0, V.current = e;
64
76
  return;
65
77
  }
66
- if (e === J.current && !t) {
67
- q.current = !1;
78
+ if (e === U.current && !t) {
79
+ H.current = !1;
68
80
  return;
69
81
  }
70
- U.current = n, q.current = !1, J.current = e, B((r) => {
71
- let i = V >= 0 ? r.slice(0, V + 1) : r, a = {
82
+ R.current = n, H.current = !1, U.current = e, F((r) => {
83
+ let i = I >= 0 ? r.slice(0, I + 1) : r, a = {
72
84
  id: `${n}-${Math.random()}`,
73
85
  timestamp: new Date(n),
74
86
  content: e,
75
87
  description: t
76
88
  }, o = [...i, a];
77
- o.length > M && o.shift();
89
+ o.length > D && o.shift();
78
90
  let s = o.length - 1;
79
- return H(s), setTimeout(() => {
80
- P && P(o, s);
91
+ return L(s), setTimeout(() => {
92
+ k && k(o, s);
81
93
  }, 0), o;
82
94
  });
83
95
  }, [
84
- j,
85
- M,
86
- N,
87
- V,
88
- P
89
- ]), Q = d((e) => {
90
- if (e < 0 || e >= z.length) return;
91
- W.current = !0;
92
- let t = z[e];
93
- L.current && L.current.dispatch({ changes: {
96
+ E,
97
+ D,
98
+ O,
99
+ I,
100
+ k
101
+ ]), Be = f(Q);
102
+ ne(() => {
103
+ W.current = y, J.current = {
104
+ onChange: v,
105
+ onVariablesCollected: w,
106
+ onOutlineGenerated: T
107
+ }, Be.current = Q;
108
+ });
109
+ let Ve = u((e) => {
110
+ if (e < 0 || e >= P.length) return;
111
+ z.current = !0;
112
+ let t = P[e];
113
+ j.current && j.current.dispatch({ changes: {
94
114
  from: 0,
95
- to: L.current.state.doc.length,
115
+ to: j.current.state.doc.length,
96
116
  insert: t.content
97
117
  } });
98
- let n = z.slice(0, e + 1);
99
- B(n);
118
+ let n = P.slice(0, e + 1);
119
+ F(n);
100
120
  let r = n.length - 1;
101
- H(r), setTimeout(() => {
102
- P && P(n, r);
103
- }, 0), b && b(t.content), setTimeout(() => {
104
- W.current = !1;
121
+ L(r), setTimeout(() => {
122
+ k && k(n, r);
123
+ }, 0), v && v(t.content), setTimeout(() => {
124
+ z.current = !1;
105
125
  }, 100);
106
126
  }, [
107
- z,
108
- b,
109
- P
127
+ P,
128
+ v,
129
+ k
110
130
  ]);
111
- p(Ee, () => ({
112
- jumpToLine: X,
113
- getView: () => L.current,
114
- getValue: () => L.current?.state.doc.toString() || "",
131
+ te(Ne, () => ({
132
+ jumpToLine: Z,
133
+ getView: () => j.current,
134
+ getValue: () => j.current?.state.doc.toString() || "",
115
135
  setValue: (e) => {
116
- L.current && L.current.dispatch({ changes: {
136
+ j.current && j.current.dispatch({ changes: {
117
137
  from: 0,
118
- to: L.current.state.doc.length,
138
+ to: j.current.state.doc.length,
119
139
  insert: e
120
140
  } });
121
141
  },
122
- focus: () => L.current?.focus(),
123
- getHistory: () => z,
124
- restoreHistory: Q,
142
+ focus: () => j.current?.focus(),
143
+ getHistory: () => P,
144
+ restoreHistory: Ve,
125
145
  clearHistory: () => {
126
- B([]), H(-1), U.current = 0, q.current = !1, K.current = "", J.current = "", setTimeout(() => {
127
- P && P([], -1);
146
+ F([]), L(-1), R.current = 0, H.current = !1, V.current = "", U.current = "", setTimeout(() => {
147
+ k && k([], -1);
128
148
  }, 0);
129
149
  }
130
150
  }), [
131
- X,
132
- z,
133
- Q,
134
- P
135
- ]), f(() => {
136
- if (!j) return;
137
- let e = N * 1e4, t = setInterval(() => {
138
- q.current && K.current && Z(K.current);
151
+ Z,
152
+ P,
153
+ Ve,
154
+ k
155
+ ]), d(() => {
156
+ if (!E) return;
157
+ let e = O * 1e4, t = setInterval(() => {
158
+ H.current && V.current && Q(V.current);
139
159
  }, e);
140
160
  return () => clearInterval(t);
141
161
  }, [
142
- j,
143
- N,
144
- Z
145
- ]), f(() => {
146
- if (!I.current) return;
147
- let l = _.updateListener.of((e) => {
148
- if (e.docChanged && b) {
149
- let t = e.state.doc.toString();
150
- b(t), j && !G.current && Z(t), G.current &&= !1;
151
- }
152
- if (e.docChanged && k) {
153
- let t = e.state.doc.toString();
154
- k(s(t, Y.current));
155
- }
156
- if (e.docChanged && A) {
157
- let t = e.state.doc.toString();
158
- A(c(t, Y.current));
162
+ E,
163
+ O,
164
+ Q
165
+ ]), d(() => {
166
+ if (!A.current) return;
167
+ let s = h.updateListener.of((e) => {
168
+ if (!e.docChanged) return;
169
+ let t = e.state.doc.toString();
170
+ G.current = t, X(t);
171
+ try {
172
+ B.current || Be.current(t);
173
+ } finally {
174
+ B.current = !1;
159
175
  }
160
- }), d = [
161
- se(),
162
- te(),
176
+ J.current.onChange?.(t);
177
+ }), c = [
163
178
  ue(),
164
- he(),
179
+ ie(),
165
180
  pe(),
166
- me(de, { fallback: !0 }),
167
- Oe.current.of(E(x)),
168
- ke.current.of(o(S)),
169
- Ae.current.of(a(S)),
170
- je.current.of(y.readOnly.of(C)),
171
- l,
172
- ie.of([
173
- ...ge,
174
- ...oe,
181
+ ve(),
182
+ ge(),
183
+ _e(me, { fallback: !0 }),
184
+ Pe.current.of(Te(y)),
185
+ Fe.current.of(o(b)),
186
+ Ie.current.of(a(b)),
187
+ Le.current.of(_.readOnly.of(x)),
188
+ s,
189
+ se.of([
175
190
  ...ye,
176
- ...ce,
177
- ..._e,
178
- ...ve,
179
- le
191
+ ...le,
192
+ ...Se,
193
+ ...de,
194
+ ...be,
195
+ ...xe,
196
+ fe
180
197
  ]),
181
198
  e,
182
199
  r,
183
200
  t
184
201
  ];
185
- if (w && d.push(ae(), fe(), re()), T && d.push(ne()), D) {
186
- let e = typeof D == "object" ? D : {};
187
- d.push(i(x, e));
202
+ if (Ce && c.push(ce(), he(), oe()), we && c.push(ae()), S) {
203
+ let e = typeof S == "object" ? S : {};
204
+ c.push(i(y, e));
188
205
  }
189
- if (O) {
190
- let e = typeof O == "object" ? O : {};
191
- d.push(n(X, e));
206
+ if (C) {
207
+ let e = typeof C == "object" ? C : {};
208
+ c.push(n(Z, e));
192
209
  }
193
- F && d.push(_.contentAttributes.of({ "data-placeholder": F })), Te.length > 0 && d.push(...Te);
194
- let f = y.create({
195
- doc: u,
196
- extensions: d
197
- }), p = new _({
198
- state: f,
199
- parent: I.current
210
+ je && c.push(h.contentAttributes.of({ "data-placeholder": je })), Me.length > 0 && c.push(...Me);
211
+ let ee = _.create({
212
+ doc: l,
213
+ extensions: c
214
+ }), u = new h({
215
+ state: ee,
216
+ parent: A.current
200
217
  });
201
- return L.current = p, setTimeout(() => {
202
- k && k(s(u, x)), A && A(c(u, x));
203
- }, 0), j && u && Z(u, "Initial content"), () => {
204
- p.destroy();
218
+ return j.current = u, G.current = u.state.doc.toString(), E && l && Q(l, "Initial content"), () => {
219
+ Y(), j.current = null, u.destroy();
205
220
  };
206
- }, []), f(() => {
207
- L.current && u !== L.current.state.doc.toString() && (G.current = !0, L.current.dispatch({ changes: {
221
+ }, []), d(() => {
222
+ j.current && l !== G.current && (B.current = !0, j.current.dispatch({ changes: {
208
223
  from: 0,
209
- to: L.current.state.doc.length,
210
- insert: u
224
+ to: j.current.state.doc.length,
225
+ insert: l
211
226
  } }));
212
- }, [u]), f(() => {
213
- if (L.current) {
214
- L.current.dispatch({ effects: Oe.current.reconfigure(E(x)) });
215
- let e = L.current.state.doc.toString();
216
- setTimeout(() => {
217
- k && k(s(e, x)), A && A(c(e, x));
218
- }, 0);
219
- }
220
- }, [
221
- x,
222
- k,
223
- A
224
- ]), f(() => {
225
- L.current && L.current.dispatch({ effects: [ke.current.reconfigure(o(S)), Ae.current.reconfigure(a(S))] });
226
- }, [S]), f(() => {
227
- L.current && L.current.dispatch({ effects: je.current.reconfigure(y.readOnly.of(C)) });
228
- }, [C]);
229
- let Me = d((e) => {
230
- e.preventDefault(), De({
227
+ }, [l]), d(() => {
228
+ j.current && j.current.dispatch({ effects: Pe.current.reconfigure(Te(y)) });
229
+ }, [y]), d(() => (X(G.current, 0), Y), [
230
+ y,
231
+ Re,
232
+ ze,
233
+ X,
234
+ Y
235
+ ]), d(() => {
236
+ j.current && j.current.dispatch({ effects: [Fe.current.reconfigure(o(b)), Ie.current.reconfigure(a(b))] });
237
+ }, [b]), d(() => {
238
+ j.current && j.current.dispatch({ effects: Le.current.reconfigure(_.readOnly.of(x)) });
239
+ }, [x]);
240
+ let He = u((e) => {
241
+ e.preventDefault(), N({
231
242
  visible: !0,
232
243
  x: e.clientX,
233
244
  y: e.clientY
234
245
  });
235
- }, []), $ = d(() => {
236
- De({
246
+ }, []), $ = u(() => {
247
+ N({
237
248
  visible: !1,
238
249
  x: 0,
239
250
  y: 0
240
251
  });
241
- }, []), Ne = d((e) => {
242
- L.current && !e.disabled && e.action(L.current), $();
252
+ }, []), Ue = u((e) => {
253
+ j.current && !e.disabled && e.action(j.current), $();
243
254
  }, [$]);
244
- f(() => {
245
- if (R.visible) {
255
+ d(() => {
256
+ if (M.visible) {
246
257
  let e = () => $();
247
258
  return document.addEventListener("click", e), () => document.removeEventListener("click", e);
248
259
  }
249
- }, [R.visible, $]);
250
- let Pe = {
251
- height: Se,
252
- minHeight: Ce,
253
- maxHeight: we,
260
+ }, [M.visible, $]);
261
+ let We = {
262
+ height: Oe,
263
+ minHeight: ke,
264
+ maxHeight: Ae,
254
265
  overflow: "auto"
255
- }, Fe = be || l;
256
- return /* @__PURE__ */ ee("div", {
257
- className: `code-editor-wrapper ${xe}`,
266
+ }, Ge = Ee || ee;
267
+ return /* @__PURE__ */ re("div", {
268
+ className: `code-editor-wrapper ${De}`,
258
269
  children: [
259
- /* @__PURE__ */ g("div", {
260
- ref: I,
261
- onContextMenu: Me,
262
- style: Pe,
270
+ /* @__PURE__ */ m("div", {
271
+ ref: A,
272
+ onContextMenu: He,
273
+ style: We,
263
274
  className: "code-editor"
264
275
  }),
265
- R.visible && /* @__PURE__ */ g("div", {
276
+ M.visible && /* @__PURE__ */ m("div", {
266
277
  className: "context-menu",
267
278
  style: {
268
279
  position: "fixed",
269
- top: R.y,
270
- left: R.x,
280
+ top: M.y,
281
+ left: M.x,
271
282
  zIndex: 1e3
272
283
  },
273
- children: /* @__PURE__ */ g("ul", {
284
+ children: /* @__PURE__ */ m("ul", {
274
285
  className: "menu bg-base-200 rounded-box shadow-lg",
275
- children: Fe.map((e, t) => e.separator ? /* @__PURE__ */ g("li", { className: "menu-separator" }, t) : /* @__PURE__ */ g("li", { children: /* @__PURE__ */ g("a", {
276
- onClick: () => Ne(e),
286
+ children: Ge.map((e, t) => e.separator ? /* @__PURE__ */ m("li", { className: "menu-separator" }, t) : /* @__PURE__ */ m("li", { children: /* @__PURE__ */ m("a", {
287
+ onClick: () => Ue(e),
277
288
  className: e.disabled ? "disabled" : "",
278
289
  children: e.label
279
290
  }) }, t))
280
291
  })
281
292
  }),
282
- /* @__PURE__ */ g("style", { children: "\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 " })
293
+ /* @__PURE__ */ m("style", { children: "\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 " })
283
294
  ]
284
295
  });
285
296
  });
286
- D.displayName = "CodeEditor";
297
+ S.displayName = "CodeEditor";
287
298
  //#endregion
288
- export { D as default };
299
+ export { S as default };
289
300
 
290
301
  //# sourceMappingURL=CodeEditor.js.map
@@ -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, useLayoutEffect, 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 const languageRef = useRef(language);\n const documentText = useRef(value);\n const analysisTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const analysisRevision = useRef(0);\n const callbacksRef = useRef({ onChange, onVariablesCollected, onOutlineGenerated });\n const hasVariableListener = Boolean(onVariablesCollected);\n const hasOutlineListener = Boolean(onOutlineGenerated);\n\n const cancelAnalysis = useCallback(() => {\n analysisRevision.current += 1;\n if (analysisTimer.current !== null) {\n clearTimeout(analysisTimer.current);\n analysisTimer.current = null;\n }\n }, []);\n\n const scheduleAnalysis = useCallback((code: string, delay = 150) => {\n cancelAnalysis();\n const view = viewRef.current;\n if (!view || (!callbacksRef.current.onVariablesCollected && !callbacksRef.current.onOutlineGenerated)) return;\n\n const revision = analysisRevision.current;\n const doc = view.state.doc;\n const analysisLanguage = languageRef.current;\n const isCurrent = () => revision === analysisRevision.current\n && viewRef.current === view && view.state.doc === doc\n && languageRef.current === analysisLanguage;\n\n analysisTimer.current = setTimeout(() => {\n analysisTimer.current = null;\n if (!isCurrent()) return;\n const variables = callbacksRef.current.onVariablesCollected\n ? collectVariables(code, analysisLanguage) : undefined;\n const outline = callbacksRef.current.onOutlineGenerated\n ? generateOutline(code, analysisLanguage) : undefined;\n\n // A callback may synchronously change the document/language or unmount us.\n if (variables && isCurrent()) callbacksRef.current.onVariablesCollected?.(variables);\n if (outline && isCurrent()) callbacksRef.current.onOutlineGenerated?.(outline);\n }, delay);\n }, [cancelAnalysis]);\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 const historyWriterRef = useRef(addToHistory);\n useLayoutEffect(() => {\n languageRef.current = language;\n callbacksRef.current = { onChange, onVariablesCollected, onOutlineGenerated };\n historyWriterRef.current = addToHistory;\n });\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) return;\n const newContent = update.state.doc.toString();\n documentText.current = newContent;\n // Schedule before notifying consumers so reentrant updates always win.\n scheduleAnalysis(newContent);\n try {\n if (!isExternalUpdate.current) historyWriterRef.current(newContent);\n } finally {\n isExternalUpdate.current = false;\n }\n callbacksRef.current.onChange?.(newContent);\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 documentText.current = view.state.doc.toString();\n\n // 添加初始内容到历史记录\n if (enableHistory && value) {\n addToHistory(value, 'Initial content');\n }\n\n return () => {\n cancelAnalysis();\n viewRef.current = null;\n view.destroy();\n };\n }, []); // 只在挂载时初始化\n\n // 更新值\n useEffect(() => {\n if (viewRef.current && value !== documentText.current) {\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 }, [language]);\n\n // Callback identity changes only update refs: inline callbacks must not restart\n // pending input analysis or create a callback -> render -> analysis loop.\n useEffect(() => {\n scheduleAnalysis(documentText.current, 0);\n return cancelAnalysis;\n }, [language, hasVariableListener, hasOutlineListener, scheduleAnalysis, cancelAnalysis]);\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":";;;;;;;;;;;;;;;;;;;;AAsCA,IAAM,MAAwB,OAarB;CAXL,kBAAkB,EAAW,EAAE,KAAK,GAAM,CAAC;CAC3C,WAAW,EAAW,EAAE,KAAK,GAAK,CAAC;CACnC,kBAAkB,EAAW;EAAE,KAAK;EAAO,YAAY;CAAK,CAAC;CAC7D,WAAW,EAAW;EAAE,KAAK;EAAM,YAAY;CAAK,CAAC;CACrD;CACA;CACA;CACA;CACA;AAGK,EAAA,CAAQ,EAAS,GAAG,KAAK,EAAW,GAKvC,IAAa,GAA+C,EAChE,WAAQ,IACR,aACA,cAAW,cACX,WAAQ,SACR,cAAW,IACX,aAAa,KAAkB,IAC/B,qBAAqB,KAA4B,IACjD,oBAAiB,IACjB,kBAAkB,IAAyB,IAC3C,iBACA,yBACA,uBACA,mBAAgB,IAChB,kBAAe,IACf,yBAAsB,GACtB,oBACA,gBAAY,IACZ,aAAS,SACT,eACA,eACA,iBACA,YAAY,KAAmB,CAAC,KAC/B,OAAQ;CACT,IAAM,IAAY,EAAuB,IAAI,GACvC,IAAU,EAA0B,IAAI,GACxC,CAAC,GAAkB,KAAuB,EAI7C;EAAE,SAAS;EAAO,GAAG;EAAG,GAAG;CAAE,CAAC,GAG3B,CAAC,GAAa,KAAkB,EAAyB,CAAC,CAAC,GAC3D,CAAC,GAAqB,KAA0B,EAAiB,EAAE,GACnE,IAAe,EAAe,CAAC,GAC/B,IAAqB,EAAgB,EAAK,GAC1C,IAAmB,EAAgB,EAAK,GACxC,IAAiB,EAAe,EAAE,GAClC,IAAa,EAAgB,EAAK,GAClC,IAAmB,EAAe,EAAE,GAGpC,KAAsB,EAAO,IAAI,EAAY,CAAC,GAC9C,KAAmB,EAAO,IAAI,EAAY,CAAC,GAC3C,KAAuB,EAAO,IAAI,EAAY,CAAC,GAC/C,KAAsB,EAAO,IAAI,EAAY,CAAC,GAE9C,IAAc,EAAO,CAAQ,GAC7B,IAAe,EAAO,CAAK,GAC3B,IAAgB,EAA6C,IAAI,GACjE,IAAmB,EAAO,CAAC,GAC3B,IAAe,EAAO;EAAE;EAAU;EAAsB;CAAmB,CAAC,GAC5E,KAAsB,EAAQ,GAC9B,KAAqB,EAAQ,GAE7B,IAAiB,QAAkB;EAEvC,AADA,EAAiB,WAAW,GACxB,EAAc,YAAY,SAC5B,aAAa,EAAc,OAAO,GAClC,EAAc,UAAU;CAE5B,GAAG,CAAC,CAAC,GAEC,IAAmB,GAAa,GAAc,IAAQ,QAAQ;EAClE,EAAe;EACf,IAAM,IAAO,EAAQ;EACrB,IAAI,CAAC,KAAS,CAAC,EAAa,QAAQ,wBAAwB,CAAC,EAAa,QAAQ,oBAAqB;EAEvG,IAAM,IAAW,EAAiB,SAC5B,IAAM,EAAK,MAAM,KACjB,IAAmB,EAAY,SAC/B,UAAkB,MAAa,EAAiB,WACjD,EAAQ,YAAY,KAAQ,EAAK,MAAM,QAAQ,KAC/C,EAAY,YAAY;EAE7B,EAAc,UAAU,iBAAiB;GAEvC,IADA,EAAc,UAAU,MACpB,CAAC,EAAU,GAAG;GAClB,IAAM,IAAY,EAAa,QAAQ,uBACnC,EAAiB,GAAM,CAAgB,IAAI,KAAA,GACzC,IAAU,EAAa,QAAQ,qBACjC,EAAgB,GAAM,CAAgB,IAAI,KAAA;GAI9C,AADI,KAAa,EAAU,KAAG,EAAa,QAAQ,uBAAuB,CAAS,GAC/E,KAAW,EAAU,KAAG,EAAa,QAAQ,qBAAqB,CAAO;EAC/E,GAAG,CAAK;CACV,GAAG,CAAC,CAAc,CAAC,GAGb,IAAa,GAAa,MAAiB;EAC/C,IAAI,EAAQ,SACV,IAAI;GACF,IAAM,IAAW,EAAQ,QAAQ,MAAM,IAAI,KAAK,CAAI;GAKpD,AAJA,EAAQ,QAAQ,SAAS;IACvB,WAAW;KAAE,QAAQ,EAAS;KAAM,MAAM,EAAS;IAAG;IACtD,gBAAgB;GAClB,CAAC,GACD,EAAQ,QAAQ,MAAM;EACxB,SAAS,GAAO;GACd,QAAQ,MAAM,2BAA2B,CAAK;EAChD;CAEJ,GAAG,CAAC,CAAC,GAGC,IAAe,GAAa,GAAiB,MAAyB;EAE1E,IAAI,CAAC,KAAiB,EAAmB,WAAW,EAAiB,SACnE;EAGF,IAAM,IAAM,KAAK,IAAI,GACf,IAAa,IAAsB;EAKzC,IAAI,EAJsB,IAAM,EAAa,WACA,IAGvB;GAGpB,AADA,EAAW,UAAU,IACrB,EAAe,UAAU;GACzB;EACF;EAGA,IAAI,MAAY,EAAiB,WAAW,CAAC,GAAa;GAExD,EAAW,UAAU;GACrB;EACF;EAOA,AAJA,EAAa,UAAU,GACvB,EAAW,UAAU,IACrB,EAAiB,UAAU,GAE3B,GAAgB,MAAgB;GAE9B,IAAM,IAAa,KAAuB,IACtC,EAAY,MAAM,GAAG,IAAsB,CAAC,IAC5C,GAEE,IAAyB;IAC7B,IAAI,GAAG,EAAI,GAAG,KAAK,OAAO;IAC1B,WAAW,IAAI,KAAK,CAAG;IACvB;IACA;GACF,GAEM,IAAiB,CAAC,GAAG,GAAY,CAAQ;GAG/C,AAAI,EAAe,SAAS,KAC1B,EAAe,MAAM;GAGvB,IAAM,IAAW,EAAe,SAAS;GAUzC,OATA,EAAuB,CAAQ,GAG/B,iBAAiB;IACf,AAAI,KACF,EAAgB,GAAgB,CAAQ;GAE5C,GAAG,CAAC,GAEG;EACT,CAAC;CACH,GAAG;EAAC;EAAe;EAAc;EAAqB;EAAqB;CAAe,CAAC,GAErF,KAAmB,EAAO,CAAY;CAC5C,SAAsB;EAGpB,AAFA,EAAY,UAAU,GACtB,EAAa,UAAU;GAAE;GAAU;GAAsB;EAAmB,GAC5E,GAAiB,UAAU;CAC7B,CAAC;CAGD,IAAM,KAAiB,GAAa,MAAkB;EACpD,IAAI,IAAQ,KAAK,KAAS,EAAY,QAAQ;EAE9C,EAAmB,UAAU;EAC7B,IAAM,IAAQ,EAAY;EAE1B,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS;GACP,MAAM;GACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;GAC9B,QAAQ,EAAM;EAChB,EACF,CAAC;EAIH,IAAM,IAAa,EAAY,MAAM,GAAG,IAAQ,CAAC;EACjD,EAAe,CAAU;EAGzB,IAAM,IAAW,EAAW,SAAS;EAgBrC,AAfA,EAAuB,CAAQ,GAG/B,iBAAiB;GACf,AAAI,KACF,EAAgB,GAAY,CAAQ;EAExC,GAAG,CAAC,GAGA,KACF,EAAS,EAAM,OAAO,GAIxB,iBAAiB;GACf,EAAmB,UAAU;EAC/B,GAAG,GAAG;CACR,GAAG;EAAC;EAAa;EAAU;CAAe,CAAC;CAyM3C,AAtMA,GAAoB,WAAY;EAC9B;EACA,eAAe,EAAQ;EACvB,gBAAgB,EAAQ,SAAS,MAAM,IAAI,SAAS,KAAK;EACzD,WAAW,MAAqB;GAC9B,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS;IACP,MAAM;IACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;IAC9B,QAAQ;GACV,EACF,CAAC;EAEL;EACA,aAAa,EAAQ,SAAS,MAAM;EACpC,kBAAkB;EAClB;EACA,oBAAoB;GASlB,AARA,EAAe,CAAC,CAAC,GACjB,EAAuB,EAAE,GAEzB,EAAa,UAAU,GACvB,EAAW,UAAU,IACrB,EAAe,UAAU,IACzB,EAAiB,UAAU,IAE3B,iBAAiB;IACf,AAAI,KACF,EAAgB,CAAC,GAAG,EAAE;GAE1B,GAAG,CAAC;EACN;CACF,IAAW;EAAC;EAAY;EAAa;EAAgB;CAAe,CAAC,GAGrE,QAAgB;EACd,IAAI,CAAC,GAAe;EAEpB,IAAM,IAAa,IAAsB,KAEnC,IAAW,kBAAkB;GACjC,AAAI,EAAW,WAAW,EAAe,WACvC,EAAa,EAAe,OAAO;EAEvC,GAAG,CAAU;EAEb,aAAa,cAAc,CAAQ;CACrC,GAAG;EAAC;EAAe;EAAqB;CAAY,CAAC,GAGrD,QAAgB;EACd,IAAI,CAAC,EAAU,SAAS;EAExB,IAAM,IAAiB,EAAW,eAAe,IAAI,MAAW;GAC9D,IAAI,CAAC,EAAO,YAAY;GACxB,IAAM,IAAa,EAAO,MAAM,IAAI,SAAS;GAG7C,AAFA,EAAa,UAAU,GAEvB,EAAiB,CAAU;GAC3B,IAAI;IACF,AAAK,EAAiB,WAAS,GAAiB,QAAQ,CAAU;GACpE,UAAU;IACR,EAAiB,UAAU;GAC7B;GACA,EAAa,QAAQ,WAAW,CAAU;EAC5C,CAAC,GAEK,IAA8B;GAClC,GAAQ;GACR,GAAc;GACd,GAAgB;GAChB,GAAc;GACd,GAAc;GACd,GAAmB,IAAuB,EAAE,UAAU,GAAK,CAAC;GAC5D,GAAoB,QAAQ,GAAG,GAAqB,CAAQ,CAAC;GAC7D,GAAiB,QAAQ,GAAG,EAAqB,CAAK,CAAC;GACvD,GAAqB,QAAQ,GAAG,EAAyB,CAAK,CAAC;GAC/D,GAAoB,QAAQ,GAAG,EAAY,SAAS,GAAG,CAAQ,CAAC;GAChE;GACA,GAAO,GAAG;IACR,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH;GACF,CAAC;GACD;GACA;GACA;EACF;EAYA,IATI,MACF,EAAe,KAAK,GAAY,GAAG,GAAW,GAAG,GAA0B,CAAC,GAG1E,MACF,EAAe,KAAK,GAAoB,CAAC,GAIvC,GAAgB;GAClB,IAAM,IAA+B,OAAO,KAAmB,WAAW,IAAiB,CAAC;GAC5F,EAAe,KAAK,EAAoB,GAAU,CAAM,CAAC;EAC3D;EAGA,IAAI,GAAwB;GAC1B,IAAM,IAAiC,OAAO,KAA2B,WACrE,IACA,CAAC;GACL,EAAe,KAAK,EAAiB,GAAY,CAAM,CAAC;EAC1D;EAUA,AAPI,MACF,EAAe,KACb,EAAW,kBAAkB,GAAG,EAAE,oBAAoB,GAAY,CAAC,CACrE,GAIE,GAAiB,SAAS,KAC5B,EAAe,KAAK,GAAG,EAAgB;EAGzC,IAAM,KAAa,EAAY,OAAO;GACpC,KAAK;GACL,YAAY;EACd,CAAC,GAEK,IAAO,IAAI,EAAW;GAC1B,OAAO;GACP,QAAQ,EAAU;EACpB,CAAC;EAUD,OARA,EAAQ,UAAU,GAClB,EAAa,UAAU,EAAK,MAAM,IAAI,SAAS,GAG3C,KAAiB,KACnB,EAAa,GAAO,iBAAiB,SAG1B;GAGX,AAFA,EAAe,GACf,EAAQ,UAAU,MAClB,EAAK,QAAQ;EACf;CACF,GAAG,CAAC,CAAC,GAGL,QAAgB;EACd,AAAI,EAAQ,WAAW,MAAU,EAAa,YAC5C,EAAiB,UAAU,IAC3B,EAAQ,QAAQ,SAAS,EACvB,SAAS;GACP,MAAM;GACN,IAAI,EAAQ,QAAQ,MAAM,IAAI;GAC9B,QAAQ;EACV,EACF,CAAC;CAGL,GAAG,CAAC,CAAK,CAAC,GAGV,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,GAAoB,QAAQ,YAAY,GAAqB,CAAQ,CAAC,EACjF,CAAC;CAEL,GAAG,CAAC,CAAQ,CAAC,GAIb,SACE,EAAiB,EAAa,SAAS,CAAC,GACjC,IACN;EAAC;EAAU;EAAqB;EAAoB;EAAkB;CAAc,CAAC,GAGxF,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,CACP,GAAiB,QAAQ,YAAY,EAAqB,CAAK,CAAC,GAChE,GAAqB,QAAQ,YAAY,EAAyB,CAAK,CAAC,CAC1E,EACF,CAAC;CAEL,GAAG,CAAC,CAAK,CAAC,GAGV,QAAgB;EACd,AAAI,EAAQ,WACV,EAAQ,QAAQ,SAAS,EACvB,SAAS,GAAoB,QAAQ,YAAY,EAAY,SAAS,GAAG,CAAQ,CAAC,EACpF,CAAC;CAEL,GAAG,CAAC,CAAQ,CAAC;CAGb,IAAM,KAAoB,GAAa,MAAwB;EAE7D,AADA,EAAE,eAAe,GACjB,EAAoB;GAClB,SAAS;GACT,GAAG,EAAE;GACL,GAAG,EAAE;EACP,CAAC;CACH,GAAG,CAAC,CAAC,GAEC,IAAmB,QAAkB;EACzC,EAAoB;GAAE,SAAS;GAAO,GAAG;GAAG,GAAG;EAAE,CAAC;CACpD,GAAG,CAAC,CAAC,GAEC,KAAsB,GACzB,MAAc;EAIb,AAHI,EAAQ,WAAW,CAAC,EAAK,YAC3B,EAAK,OAAO,EAAQ,OAAO,GAE7B,EAAiB;CACnB,GACA,CAAC,CAAgB,CACnB;CAGA,QAAgB;EACd,IAAI,EAAiB,SAAS;GAC5B,IAAM,UAAoB,EAAiB;GAE3C,OADA,SAAS,iBAAiB,SAAS,CAAW,SACjC,SAAS,oBAAoB,SAAS,CAAW;EAChE;CACF,GAAG,CAAC,EAAiB,SAAS,CAAgB,CAAC;CAE/C,IAAM,KAAoC;EACxC;EACA;EACA;EACA,UAAU;CACZ,GAEM,KAAY,MAAe;CAEjC,OACE,mBAAC,OAAD;EAAK,WAAW,uBAAuB;EAAvC,UAAA;GACE,kBAAC,OAAD;IACE,KAAK;IACL,eAAe;IACf,OAAO;IACP,WAAU;GACX,CAAA;GAGA,EAAiB,WAChB,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KACL,UAAU;KACV,KAAK,EAAiB;KACtB,MAAM,EAAiB;KACvB,QAAQ;IACV;IAEA,UAAA,kBAAC,MAAD;KAAI,WAAU;KACX,UAAA,GAAU,KAAK,GAAM,MAChB,EAAK,YACA,kBAAC,MAAD,EAAgB,WAAU,iBAAkB,GAAnC,CAAmC,IAGnD,kBAAC,MAAD,EAAA,UACE,kBAAC,KAAD;MACE,eAAe,GAAoB,CAAI;MACvC,WAAW,EAAK,WAAW,aAAa;MAEvC,UAAA,EAAK;KACL,CAAA,EACD,GAPK,CAOL,CAEP;IACC,CAAA;GACD,CAAA;GAGP,kBAAC,SAAD,EAAA,UAAQ,mkCAwCC,CAAA;EACN;;AAET,CAAC;AAED,EAAW,cAAc"}