@exem-ui/react 0.3.4-next.20260701100258 → 0.3.4-next.20260702065311
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/README.en.md +4 -3
- package/README.md +18 -4
- package/dist/code-editor/index.d.mts +141 -0
- package/dist/code-editor/index.d.ts +141 -0
- package/dist/code-editor/index.js +987 -0
- package/dist/code-editor/index.js.map +1 -0
- package/dist/code-editor/index.mjs +965 -0
- package/dist/code-editor/index.mjs.map +1 -0
- package/package.json +21 -3
- package/styles.css +69 -0
|
@@ -0,0 +1,987 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var utils = require('@exem-ui/core/utils');
|
|
4
|
+
var React2 = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var react = require('@monaco-editor/react');
|
|
7
|
+
var sqlFormatter = require('sql-formatter');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
28
|
+
|
|
29
|
+
// src/codeEditor/CodeEditor.tsx
|
|
30
|
+
var CodeEditorSourceContext = React2__namespace.createContext(null);
|
|
31
|
+
var useCodeEditorSource = () => {
|
|
32
|
+
const context = React2__namespace.useContext(CodeEditorSourceContext);
|
|
33
|
+
if (!context) {
|
|
34
|
+
throw new Error("CodeEditor components must be used within CodeEditor");
|
|
35
|
+
}
|
|
36
|
+
return context;
|
|
37
|
+
};
|
|
38
|
+
var CodeEditorSourceProvider = ({
|
|
39
|
+
children,
|
|
40
|
+
onSourceValueChange,
|
|
41
|
+
readOnly,
|
|
42
|
+
sourceValue
|
|
43
|
+
}) => {
|
|
44
|
+
const contextValue = React2__namespace.useMemo(
|
|
45
|
+
() => ({
|
|
46
|
+
onSourceValueChange,
|
|
47
|
+
readOnly,
|
|
48
|
+
sourceValue
|
|
49
|
+
}),
|
|
50
|
+
[onSourceValueChange, readOnly, sourceValue]
|
|
51
|
+
);
|
|
52
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CodeEditorSourceContext.Provider, { value: contextValue, children });
|
|
53
|
+
};
|
|
54
|
+
var useControllableViewMode = ({
|
|
55
|
+
value,
|
|
56
|
+
defaultValue = "original",
|
|
57
|
+
onChange
|
|
58
|
+
}) => {
|
|
59
|
+
const [uncontrolledValue, setUncontrolledValue] = React2.useState(defaultValue);
|
|
60
|
+
const isControlled = value !== void 0;
|
|
61
|
+
const currentValue = isControlled ? value : uncontrolledValue;
|
|
62
|
+
const setValue = React2.useCallback(
|
|
63
|
+
(nextValue) => {
|
|
64
|
+
if (!isControlled) {
|
|
65
|
+
setUncontrolledValue(nextValue);
|
|
66
|
+
}
|
|
67
|
+
onChange?.(nextValue);
|
|
68
|
+
},
|
|
69
|
+
[isControlled, onChange]
|
|
70
|
+
);
|
|
71
|
+
return [currentValue, setValue];
|
|
72
|
+
};
|
|
73
|
+
var CodeEditorFormatContext = React2__namespace.createContext(null);
|
|
74
|
+
var useCodeEditorFormat = () => {
|
|
75
|
+
const context = React2__namespace.useContext(CodeEditorFormatContext);
|
|
76
|
+
if (!context) {
|
|
77
|
+
throw new Error("CodeEditor components must be used within CodeEditor");
|
|
78
|
+
}
|
|
79
|
+
return context;
|
|
80
|
+
};
|
|
81
|
+
var CodeEditorFormatProvider = ({
|
|
82
|
+
children,
|
|
83
|
+
defaultViewMode,
|
|
84
|
+
formatter,
|
|
85
|
+
onViewModeChange,
|
|
86
|
+
viewMode: viewModeProp
|
|
87
|
+
}) => {
|
|
88
|
+
const [viewMode, setViewMode] = useControllableViewMode({
|
|
89
|
+
value: viewModeProp,
|
|
90
|
+
defaultValue: defaultViewMode,
|
|
91
|
+
onChange: onViewModeChange
|
|
92
|
+
});
|
|
93
|
+
const [activeFormatterOverride, setActiveFormatterOverride] = React2__namespace.useState();
|
|
94
|
+
const activeFormatter = activeFormatterOverride === void 0 ? formatter : activeFormatterOverride;
|
|
95
|
+
const setActiveFormatter = React2__namespace.useCallback((nextFormatter) => {
|
|
96
|
+
setActiveFormatterOverride(() => nextFormatter);
|
|
97
|
+
}, []);
|
|
98
|
+
const contextValue = React2__namespace.useMemo(
|
|
99
|
+
() => ({
|
|
100
|
+
activeFormatter,
|
|
101
|
+
formatter,
|
|
102
|
+
setActiveFormatter,
|
|
103
|
+
setViewMode,
|
|
104
|
+
viewMode
|
|
105
|
+
}),
|
|
106
|
+
[activeFormatter, formatter, setActiveFormatter, setViewMode, viewMode]
|
|
107
|
+
);
|
|
108
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CodeEditorFormatContext.Provider, { value: contextValue, children });
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/codeEditor/format/getDisplayValue.ts
|
|
112
|
+
var getDisplayValue = (value, viewMode, formatter) => {
|
|
113
|
+
const currentValue = value ?? "";
|
|
114
|
+
if (viewMode !== "formatted" || !formatter) {
|
|
115
|
+
return currentValue;
|
|
116
|
+
}
|
|
117
|
+
return formatter(currentValue);
|
|
118
|
+
};
|
|
119
|
+
var useCopyState = (copiedDuration) => {
|
|
120
|
+
const [copied, setCopied] = React2__namespace.useState(false);
|
|
121
|
+
const timerRef = React2__namespace.useRef(null);
|
|
122
|
+
const markCopied = React2__namespace.useCallback(() => {
|
|
123
|
+
setCopied(true);
|
|
124
|
+
if (timerRef.current) {
|
|
125
|
+
clearTimeout(timerRef.current);
|
|
126
|
+
}
|
|
127
|
+
timerRef.current = setTimeout(() => {
|
|
128
|
+
setCopied(false);
|
|
129
|
+
timerRef.current = null;
|
|
130
|
+
}, copiedDuration);
|
|
131
|
+
}, [copiedDuration]);
|
|
132
|
+
React2__namespace.useEffect(() => {
|
|
133
|
+
return () => {
|
|
134
|
+
if (timerRef.current) {
|
|
135
|
+
clearTimeout(timerRef.current);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}, []);
|
|
139
|
+
return { copied, markCopied };
|
|
140
|
+
};
|
|
141
|
+
var CopyTrigger = ({
|
|
142
|
+
children,
|
|
143
|
+
copiedDuration = 1500,
|
|
144
|
+
formatter,
|
|
145
|
+
value
|
|
146
|
+
}) => {
|
|
147
|
+
const { activeFormatter, viewMode } = useCodeEditorFormat();
|
|
148
|
+
const { sourceValue } = useCodeEditorSource();
|
|
149
|
+
const copyFormatter = formatter === void 0 ? activeFormatter : formatter;
|
|
150
|
+
const displayValue = getDisplayValue(value ?? sourceValue, viewMode, copyFormatter);
|
|
151
|
+
const { copied, markCopied } = useCopyState(copiedDuration);
|
|
152
|
+
const copy = React2__namespace.useCallback(async () => {
|
|
153
|
+
try {
|
|
154
|
+
await navigator.clipboard.writeText(displayValue);
|
|
155
|
+
} catch {
|
|
156
|
+
throw new Error("CodeEditor.CopyTrigger: Clipboard copy failed.");
|
|
157
|
+
}
|
|
158
|
+
markCopied();
|
|
159
|
+
}, [displayValue, markCopied]);
|
|
160
|
+
const getCopyProps = React2__namespace.useCallback(
|
|
161
|
+
() => ({
|
|
162
|
+
onClick: copy,
|
|
163
|
+
type: "button"
|
|
164
|
+
}),
|
|
165
|
+
[copy]
|
|
166
|
+
);
|
|
167
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ copied, copy, getCopyProps }) });
|
|
168
|
+
};
|
|
169
|
+
CopyTrigger.displayName = "CodeEditor.CopyTrigger";
|
|
170
|
+
var FormatToggle = ({ children }) => {
|
|
171
|
+
const { viewMode, setViewMode } = useCodeEditorFormat();
|
|
172
|
+
const formatted = viewMode === "formatted";
|
|
173
|
+
const toggle = React2__namespace.useCallback(() => {
|
|
174
|
+
setViewMode(formatted ? "original" : "formatted");
|
|
175
|
+
}, [formatted, setViewMode]);
|
|
176
|
+
const getToggleProps = React2__namespace.useCallback(
|
|
177
|
+
() => ({
|
|
178
|
+
onClick: toggle,
|
|
179
|
+
"aria-pressed": formatted,
|
|
180
|
+
type: "button"
|
|
181
|
+
}),
|
|
182
|
+
[formatted, toggle]
|
|
183
|
+
);
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ formatted, toggle, getToggleProps }) });
|
|
185
|
+
};
|
|
186
|
+
FormatToggle.displayName = "CodeEditor.FormatToggle";
|
|
187
|
+
var FormatTrigger = ({ children }) => {
|
|
188
|
+
const { onSourceValueChange, readOnly, sourceValue } = useCodeEditorSource();
|
|
189
|
+
const { activeFormatter, setViewMode } = useCodeEditorFormat();
|
|
190
|
+
const disabled = readOnly || !activeFormatter || !onSourceValueChange;
|
|
191
|
+
const format2 = React2__namespace.useCallback(() => {
|
|
192
|
+
if (readOnly || !activeFormatter || !onSourceValueChange) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
onSourceValueChange(activeFormatter(sourceValue ?? ""));
|
|
196
|
+
setViewMode("original");
|
|
197
|
+
}, [activeFormatter, onSourceValueChange, readOnly, setViewMode, sourceValue]);
|
|
198
|
+
const getFormatProps = React2__namespace.useCallback(
|
|
199
|
+
() => ({
|
|
200
|
+
disabled,
|
|
201
|
+
onClick: format2,
|
|
202
|
+
type: "button"
|
|
203
|
+
}),
|
|
204
|
+
[disabled, format2]
|
|
205
|
+
);
|
|
206
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ format: format2, getFormatProps }) });
|
|
207
|
+
};
|
|
208
|
+
FormatTrigger.displayName = "CodeEditor.FormatTrigger";
|
|
209
|
+
var localMonacoLoaderPromise = null;
|
|
210
|
+
var configuredMonaco = null;
|
|
211
|
+
var codeEditorSemanticColorStyleId = "exem-code-editor-semantic-colors";
|
|
212
|
+
var codeEditorThemeName = "exem-code";
|
|
213
|
+
var defaultCodeEditorOptions = {
|
|
214
|
+
automaticLayout: true,
|
|
215
|
+
bracketPairColorization: { enabled: false },
|
|
216
|
+
domReadOnly: true,
|
|
217
|
+
folding: false,
|
|
218
|
+
fontFamily: "JetBrains Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
219
|
+
fontSize: 14,
|
|
220
|
+
glyphMargin: false,
|
|
221
|
+
guides: {
|
|
222
|
+
highlightActiveIndentation: false,
|
|
223
|
+
indentation: false
|
|
224
|
+
},
|
|
225
|
+
lineDecorationsWidth: 0,
|
|
226
|
+
lineHeight: 20,
|
|
227
|
+
lineNumbers: "on",
|
|
228
|
+
lineNumbersMinChars: 4,
|
|
229
|
+
minimap: { enabled: false },
|
|
230
|
+
overviewRulerLanes: 0,
|
|
231
|
+
padding: {
|
|
232
|
+
bottom: 8,
|
|
233
|
+
top: 8
|
|
234
|
+
},
|
|
235
|
+
readOnly: true,
|
|
236
|
+
renderLineHighlight: "none",
|
|
237
|
+
renderWhitespace: "none",
|
|
238
|
+
scrollbar: {
|
|
239
|
+
alwaysConsumeMouseWheel: false,
|
|
240
|
+
horizontal: "auto",
|
|
241
|
+
horizontalScrollbarSize: 10,
|
|
242
|
+
horizontalSliderSize: 6,
|
|
243
|
+
useShadows: false,
|
|
244
|
+
vertical: "hidden",
|
|
245
|
+
verticalScrollbarSize: 10,
|
|
246
|
+
verticalSliderSize: 6
|
|
247
|
+
},
|
|
248
|
+
scrollBeyondLastLine: false,
|
|
249
|
+
stickyScroll: {
|
|
250
|
+
enabled: false
|
|
251
|
+
},
|
|
252
|
+
wordWrap: "off"
|
|
253
|
+
};
|
|
254
|
+
var codeEditorSemanticColors = [
|
|
255
|
+
"--color-text-secondary",
|
|
256
|
+
"--color-tint-foreground-violet",
|
|
257
|
+
"--color-tint-foreground-teal",
|
|
258
|
+
"--color-tint-foreground-pink",
|
|
259
|
+
"--color-text-disabled",
|
|
260
|
+
"--color-text-tertiary",
|
|
261
|
+
"--color-tint-foreground-orange"
|
|
262
|
+
];
|
|
263
|
+
var codeEditorThemeRuleContributors = /* @__PURE__ */ new Set();
|
|
264
|
+
var registerCodeEditorThemeRules = (contributor) => {
|
|
265
|
+
codeEditorThemeRuleContributors.add(contributor);
|
|
266
|
+
if (configuredMonaco) {
|
|
267
|
+
configuredMonaco.editor.defineTheme(codeEditorThemeName, buildCodeEditorTheme());
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
var withoutHash = (color) => color.replace(/^#/, "");
|
|
271
|
+
var createCodeEditorTokenMarker = (index) => `#${String(index + 1).padStart(6, "0")}`;
|
|
272
|
+
var getCodeEditorSemanticColorMarker = (cssVariable) => createCodeEditorTokenMarker(codeEditorSemanticColors.indexOf(cssVariable));
|
|
273
|
+
var createCodeEditorThemeRules = (rules) => rules.map(({ token, cssVariable, fontStyle }) => {
|
|
274
|
+
const themeRule = {
|
|
275
|
+
token,
|
|
276
|
+
foreground: withoutHash(getCodeEditorSemanticColorMarker(cssVariable))
|
|
277
|
+
};
|
|
278
|
+
if (fontStyle) {
|
|
279
|
+
themeRule.fontStyle = fontStyle;
|
|
280
|
+
}
|
|
281
|
+
return themeRule;
|
|
282
|
+
});
|
|
283
|
+
var getCodeEditorSemanticColorStyleSheet = () => codeEditorSemanticColors.map(
|
|
284
|
+
(cssVariable, index) => `.exem-code-editor-monaco .mtk${index + 1} {
|
|
285
|
+
color: var(${cssVariable});
|
|
286
|
+
}`
|
|
287
|
+
).join("\n\n");
|
|
288
|
+
var ensureCodeEditorSemanticColorStyles = () => {
|
|
289
|
+
if (typeof document === "undefined" || document.getElementById(codeEditorSemanticColorStyleId)) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const styleElement = document.createElement("style");
|
|
293
|
+
styleElement.id = codeEditorSemanticColorStyleId;
|
|
294
|
+
styleElement.textContent = getCodeEditorSemanticColorStyleSheet();
|
|
295
|
+
document.head.append(styleElement);
|
|
296
|
+
};
|
|
297
|
+
var baseCodeEditorThemeRules = createCodeEditorThemeRules([
|
|
298
|
+
{ token: "", cssVariable: "--color-text-secondary" },
|
|
299
|
+
{ token: "attribute.name", cssVariable: "--color-tint-foreground-violet" },
|
|
300
|
+
{ token: "comment", cssVariable: "--color-text-disabled" },
|
|
301
|
+
{ token: "delimiter", cssVariable: "--color-text-secondary" },
|
|
302
|
+
{ token: "keyword", cssVariable: "--color-tint-foreground-violet" },
|
|
303
|
+
{ token: "number", cssVariable: "--color-tint-foreground-pink" },
|
|
304
|
+
{ token: "string", cssVariable: "--color-tint-foreground-teal" },
|
|
305
|
+
{ token: "string.key", cssVariable: "--color-tint-foreground-violet" },
|
|
306
|
+
{ token: "type", cssVariable: "--color-tint-foreground-violet" },
|
|
307
|
+
{ token: "variable", cssVariable: "--color-text-secondary" }
|
|
308
|
+
]);
|
|
309
|
+
var codeEditorEncodedTokenColors = codeEditorSemanticColors.map(
|
|
310
|
+
(_, index) => createCodeEditorTokenMarker(index)
|
|
311
|
+
);
|
|
312
|
+
var buildCodeEditorTheme = () => ({
|
|
313
|
+
base: "vs",
|
|
314
|
+
inherit: false,
|
|
315
|
+
encodedTokensColors: codeEditorEncodedTokenColors,
|
|
316
|
+
rules: [
|
|
317
|
+
...baseCodeEditorThemeRules,
|
|
318
|
+
...[...codeEditorThemeRuleContributors].flatMap((contributor) => contributor())
|
|
319
|
+
],
|
|
320
|
+
colors: {}
|
|
321
|
+
});
|
|
322
|
+
var hasCodeEditorLanguage = (monaco, languageId) => monaco.languages.getLanguages().some((language) => language.id === languageId);
|
|
323
|
+
var setupLocalMonacoLoader = () => {
|
|
324
|
+
localMonacoLoaderPromise ?? (localMonacoLoaderPromise = import('monaco-editor').then((monaco) => {
|
|
325
|
+
ensureCodeEditorSemanticColorStyles();
|
|
326
|
+
react.loader.config({ monaco });
|
|
327
|
+
configuredMonaco = monaco;
|
|
328
|
+
monaco.editor.defineTheme(codeEditorThemeName, buildCodeEditorTheme());
|
|
329
|
+
}));
|
|
330
|
+
return localMonacoLoaderPromise;
|
|
331
|
+
};
|
|
332
|
+
var useMonacoLoader = () => {
|
|
333
|
+
const [monacoLoaderError, setMonacoLoaderError] = React2.useState(null);
|
|
334
|
+
const [monacoLoaderReady, setMonacoLoaderReady] = React2.useState(false);
|
|
335
|
+
React2.useEffect(() => {
|
|
336
|
+
let canceled = false;
|
|
337
|
+
setupLocalMonacoLoader().then(() => {
|
|
338
|
+
if (!canceled) {
|
|
339
|
+
setMonacoLoaderReady(true);
|
|
340
|
+
}
|
|
341
|
+
}).catch((error) => {
|
|
342
|
+
if (!canceled) {
|
|
343
|
+
setMonacoLoaderError(error);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
return () => {
|
|
347
|
+
canceled = true;
|
|
348
|
+
};
|
|
349
|
+
}, []);
|
|
350
|
+
return { monacoLoaderError, monacoLoaderReady };
|
|
351
|
+
};
|
|
352
|
+
var getCodeEditorSurfaceReadOnly = ({
|
|
353
|
+
contextReadOnly,
|
|
354
|
+
readOnly,
|
|
355
|
+
viewMode
|
|
356
|
+
}) => {
|
|
357
|
+
if (viewMode === "formatted") {
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
return readOnly ?? contextReadOnly;
|
|
361
|
+
};
|
|
362
|
+
var CodeEditorSurface = React2__namespace.forwardRef(
|
|
363
|
+
({
|
|
364
|
+
className,
|
|
365
|
+
editorClassName,
|
|
366
|
+
height,
|
|
367
|
+
language = "plaintext",
|
|
368
|
+
value,
|
|
369
|
+
formatter,
|
|
370
|
+
onChange,
|
|
371
|
+
options,
|
|
372
|
+
readOnly,
|
|
373
|
+
beforeMount,
|
|
374
|
+
onMount
|
|
375
|
+
}, ref) => {
|
|
376
|
+
const { formatter: contextFormatter, viewMode } = useCodeEditorFormat();
|
|
377
|
+
const {
|
|
378
|
+
onSourceValueChange,
|
|
379
|
+
readOnly: contextReadOnly,
|
|
380
|
+
sourceValue: contextValue
|
|
381
|
+
} = useCodeEditorSource();
|
|
382
|
+
const { monacoLoaderError, monacoLoaderReady } = useMonacoLoader();
|
|
383
|
+
const surfaceFormatter = formatter === void 0 ? contextFormatter : formatter;
|
|
384
|
+
const displayValue = getDisplayValue(value ?? contextValue, viewMode, surfaceFormatter);
|
|
385
|
+
const surfaceReadOnly = getCodeEditorSurfaceReadOnly({
|
|
386
|
+
contextReadOnly,
|
|
387
|
+
readOnly,
|
|
388
|
+
viewMode
|
|
389
|
+
});
|
|
390
|
+
const handleChange = React2__namespace.useCallback(
|
|
391
|
+
(nextValue) => {
|
|
392
|
+
if (onChange) {
|
|
393
|
+
onChange(nextValue);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (surfaceReadOnly) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
onSourceValueChange?.(nextValue ?? "");
|
|
400
|
+
},
|
|
401
|
+
[onChange, onSourceValueChange, surfaceReadOnly]
|
|
402
|
+
);
|
|
403
|
+
if (monacoLoaderError) {
|
|
404
|
+
throw monacoLoaderError;
|
|
405
|
+
}
|
|
406
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
407
|
+
"div",
|
|
408
|
+
{
|
|
409
|
+
ref,
|
|
410
|
+
className: utils.cn(
|
|
411
|
+
"h-[400px] min-h-[160px] overflow-hidden rounded-medium border border-border-primary bg-background-primary",
|
|
412
|
+
className
|
|
413
|
+
),
|
|
414
|
+
style: height === void 0 ? void 0 : { height },
|
|
415
|
+
children: monacoLoaderReady ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
416
|
+
react.Editor,
|
|
417
|
+
{
|
|
418
|
+
beforeMount,
|
|
419
|
+
className: utils.cn("exem-code-editor-monaco size-full", editorClassName),
|
|
420
|
+
height: "100%",
|
|
421
|
+
language,
|
|
422
|
+
onChange: handleChange,
|
|
423
|
+
onMount,
|
|
424
|
+
options: {
|
|
425
|
+
...defaultCodeEditorOptions,
|
|
426
|
+
...options,
|
|
427
|
+
domReadOnly: surfaceReadOnly,
|
|
428
|
+
readOnly: surfaceReadOnly
|
|
429
|
+
},
|
|
430
|
+
theme: codeEditorThemeName,
|
|
431
|
+
value: displayValue
|
|
432
|
+
}
|
|
433
|
+
) : null
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
CodeEditorSurface.displayName = "CodeEditor.Surface";
|
|
439
|
+
var CodeEditor = React2__namespace.forwardRef(
|
|
440
|
+
({
|
|
441
|
+
value,
|
|
442
|
+
onValueChange,
|
|
443
|
+
readOnly = true,
|
|
444
|
+
defaultViewMode,
|
|
445
|
+
viewMode: viewModeProp,
|
|
446
|
+
onViewModeChange,
|
|
447
|
+
formatter,
|
|
448
|
+
className,
|
|
449
|
+
children
|
|
450
|
+
}, ref) => {
|
|
451
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
452
|
+
CodeEditorSourceProvider,
|
|
453
|
+
{
|
|
454
|
+
onSourceValueChange: onValueChange,
|
|
455
|
+
readOnly,
|
|
456
|
+
sourceValue: value,
|
|
457
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
458
|
+
CodeEditorFormatProvider,
|
|
459
|
+
{
|
|
460
|
+
defaultViewMode,
|
|
461
|
+
formatter,
|
|
462
|
+
onViewModeChange,
|
|
463
|
+
viewMode: viewModeProp,
|
|
464
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: utils.cn("flex min-w-0 flex-col gap-2", className), children })
|
|
465
|
+
}
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
);
|
|
471
|
+
CodeEditor.Surface = CodeEditorSurface;
|
|
472
|
+
CodeEditor.FormatToggle = FormatToggle;
|
|
473
|
+
CodeEditor.FormatTrigger = FormatTrigger;
|
|
474
|
+
CodeEditor.CopyTrigger = CopyTrigger;
|
|
475
|
+
CodeEditor.displayName = "CodeEditor";
|
|
476
|
+
var useActiveFormatter = (formatter) => {
|
|
477
|
+
const { setActiveFormatter } = useCodeEditorFormat();
|
|
478
|
+
React2__namespace.useEffect(() => {
|
|
479
|
+
setActiveFormatter(formatter);
|
|
480
|
+
return () => {
|
|
481
|
+
setActiveFormatter(void 0);
|
|
482
|
+
};
|
|
483
|
+
}, [formatter, setActiveFormatter]);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
// src/codeEditor/jsonEditor/formatJsonValue.ts
|
|
487
|
+
var formatJsonValue = (value) => {
|
|
488
|
+
try {
|
|
489
|
+
return JSON.stringify(JSON.parse(value), null, 2);
|
|
490
|
+
} catch {
|
|
491
|
+
return value;
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
// src/codeEditor/jsonEditor/monacoJsonEditor.ts
|
|
496
|
+
var jsonEditorLanguageId = "exem-json";
|
|
497
|
+
var isJsonEditorLanguageConfigured = false;
|
|
498
|
+
var defineJsonEditorLanguage = (monaco) => {
|
|
499
|
+
if (isJsonEditorLanguageConfigured) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (!hasCodeEditorLanguage(monaco, jsonEditorLanguageId)) {
|
|
503
|
+
monaco.languages.register({ id: jsonEditorLanguageId });
|
|
504
|
+
}
|
|
505
|
+
monaco.languages.setMonarchTokensProvider(jsonEditorLanguageId, {
|
|
506
|
+
tokenizer: {
|
|
507
|
+
root: [
|
|
508
|
+
[/\s+/, ""],
|
|
509
|
+
[/[{}]/, "delimiter.bracket.json"],
|
|
510
|
+
[/\[/, "delimiter.array.json"],
|
|
511
|
+
[/\]/, "delimiter.array.json"],
|
|
512
|
+
[/:/, "delimiter.colon.json"],
|
|
513
|
+
[/,/, "delimiter.comma.json"],
|
|
514
|
+
[/\b(?:true|false)\b/, "boolean.json"],
|
|
515
|
+
[/\bnull\b/, "keyword.json"],
|
|
516
|
+
[/-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/, "number.json"],
|
|
517
|
+
// 뒤에 콜론이 오면 key, 아니면 value 문자열로 구분한다.
|
|
518
|
+
[/"(?:\\.|[^"\\])*"(?=\s*:)/, "string.key.json"],
|
|
519
|
+
[/"(?:\\.|[^"\\])*"/, "string.value.json"]
|
|
520
|
+
]
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
isJsonEditorLanguageConfigured = true;
|
|
524
|
+
};
|
|
525
|
+
var getJsonEditorThemeRules = () => createCodeEditorThemeRules([
|
|
526
|
+
{ token: "boolean.json", cssVariable: "--color-text-secondary" },
|
|
527
|
+
{ token: "delimiter.array.json", cssVariable: "--color-text-secondary" },
|
|
528
|
+
{ token: "delimiter.bracket.json", cssVariable: "--color-text-secondary" },
|
|
529
|
+
{ token: "delimiter.colon.json", cssVariable: "--color-text-secondary" },
|
|
530
|
+
{ token: "delimiter.comma.json", cssVariable: "--color-text-secondary" },
|
|
531
|
+
{ token: "keyword.json", cssVariable: "--color-text-tertiary" },
|
|
532
|
+
{ token: "number.json", cssVariable: "--color-tint-foreground-violet" },
|
|
533
|
+
{ token: "string.key.json", cssVariable: "--color-tint-foreground-teal" },
|
|
534
|
+
{ token: "string.value.json", cssVariable: "--color-tint-foreground-orange" }
|
|
535
|
+
]);
|
|
536
|
+
registerCodeEditorThemeRules(getJsonEditorThemeRules);
|
|
537
|
+
var CodeEditorJSON = React2__namespace.forwardRef(
|
|
538
|
+
({ beforeMount, editorClassName, formatter, ...props }, ref) => {
|
|
539
|
+
const jsonFormatter = formatter === void 0 ? formatJsonValue : formatter;
|
|
540
|
+
useActiveFormatter(jsonFormatter);
|
|
541
|
+
const handleBeforeMount = React2__namespace.useCallback(
|
|
542
|
+
(monaco) => {
|
|
543
|
+
defineJsonEditorLanguage(monaco);
|
|
544
|
+
beforeMount?.(monaco);
|
|
545
|
+
},
|
|
546
|
+
[beforeMount]
|
|
547
|
+
);
|
|
548
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
549
|
+
CodeEditor.Surface,
|
|
550
|
+
{
|
|
551
|
+
ref,
|
|
552
|
+
...props,
|
|
553
|
+
beforeMount: handleBeforeMount,
|
|
554
|
+
editorClassName: utils.cn("exem-json-editor-monaco", editorClassName),
|
|
555
|
+
formatter: jsonFormatter,
|
|
556
|
+
language: jsonEditorLanguageId
|
|
557
|
+
}
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
);
|
|
561
|
+
CodeEditorJSON.displayName = "CodeEditor.JSON";
|
|
562
|
+
var resolveSqlFormatterLanguage = (dbType) => {
|
|
563
|
+
return dbType === "oracle" ? "plsql" : dbType;
|
|
564
|
+
};
|
|
565
|
+
var createSqlFormatter = (dbType = "sql") => {
|
|
566
|
+
let lastValue = null;
|
|
567
|
+
let lastResult = "";
|
|
568
|
+
return (value) => {
|
|
569
|
+
if (value === lastValue) {
|
|
570
|
+
return lastResult;
|
|
571
|
+
}
|
|
572
|
+
lastValue = value;
|
|
573
|
+
try {
|
|
574
|
+
lastResult = sqlFormatter.format(value, {
|
|
575
|
+
language: resolveSqlFormatterLanguage(dbType),
|
|
576
|
+
// :region 같은 바인드 변수를 파라미터로 인식시켜 포맷 중 깨지지 않게 한다.
|
|
577
|
+
paramTypes: { named: [":"] }
|
|
578
|
+
});
|
|
579
|
+
} catch {
|
|
580
|
+
lastResult = value;
|
|
581
|
+
}
|
|
582
|
+
return lastResult;
|
|
583
|
+
};
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// src/codeEditor/sqlEditor/monacoSqlEditor.ts
|
|
587
|
+
var sqlEditorLanguageId = "exem-sql";
|
|
588
|
+
var isSqlEditorLanguageConfigured = false;
|
|
589
|
+
var sqlEditorKeywords = [
|
|
590
|
+
"ADD",
|
|
591
|
+
"ALL",
|
|
592
|
+
"ALTER",
|
|
593
|
+
"AND",
|
|
594
|
+
"AS",
|
|
595
|
+
"ASC",
|
|
596
|
+
"BETWEEN",
|
|
597
|
+
"BY",
|
|
598
|
+
"CASE",
|
|
599
|
+
"COUNT",
|
|
600
|
+
"CREATE",
|
|
601
|
+
"DELETE",
|
|
602
|
+
"DESC",
|
|
603
|
+
"DISTINCT",
|
|
604
|
+
"DROP",
|
|
605
|
+
"ELSE",
|
|
606
|
+
"END",
|
|
607
|
+
"EXISTS",
|
|
608
|
+
"FROM",
|
|
609
|
+
"GROUP",
|
|
610
|
+
"HAVING",
|
|
611
|
+
"IN",
|
|
612
|
+
"INSERT",
|
|
613
|
+
"IS",
|
|
614
|
+
"JOIN",
|
|
615
|
+
"LEFT",
|
|
616
|
+
"LIKE",
|
|
617
|
+
"LIMIT",
|
|
618
|
+
"NOT",
|
|
619
|
+
"ON",
|
|
620
|
+
"OR",
|
|
621
|
+
"ORDER",
|
|
622
|
+
"RIGHT",
|
|
623
|
+
"SELECT",
|
|
624
|
+
"SET",
|
|
625
|
+
"SUM",
|
|
626
|
+
"THEN",
|
|
627
|
+
"UNION",
|
|
628
|
+
"UPDATE",
|
|
629
|
+
"VALUES",
|
|
630
|
+
"WHEN",
|
|
631
|
+
"WHERE"
|
|
632
|
+
];
|
|
633
|
+
var sqlEditorBooleans = ["FALSE", "TRUE"];
|
|
634
|
+
var sqlEditorConstants = ["NULL"];
|
|
635
|
+
var defineSqlEditorLanguage = (monaco) => {
|
|
636
|
+
if (isSqlEditorLanguageConfigured) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (!hasCodeEditorLanguage(monaco, sqlEditorLanguageId)) {
|
|
640
|
+
monaco.languages.register({ id: sqlEditorLanguageId });
|
|
641
|
+
}
|
|
642
|
+
monaco.languages.setMonarchTokensProvider(sqlEditorLanguageId, {
|
|
643
|
+
ignoreCase: true,
|
|
644
|
+
keywords: sqlEditorKeywords,
|
|
645
|
+
booleans: sqlEditorBooleans,
|
|
646
|
+
constants: sqlEditorConstants,
|
|
647
|
+
tokenizer: {
|
|
648
|
+
root: [
|
|
649
|
+
[/--.*$/, "comment.sql"],
|
|
650
|
+
[/\/\*/, { token: "comment.quote.sql", next: "@comment" }],
|
|
651
|
+
[/'(?:[^']|'')*'/, "string.sql"],
|
|
652
|
+
[/"(?:""|[^"])*"/, "identifier.quote.sql"],
|
|
653
|
+
[/\b\d+(?:\.\d+)?\b/, "number.sql"],
|
|
654
|
+
[/:[A-Za-z_][\w$#]*/, "variable.bind.sql"],
|
|
655
|
+
[/[(),;]/, "delimiter.sql"],
|
|
656
|
+
[/[<>!=]=?|[-+*/%]/, "operator.sql"],
|
|
657
|
+
[
|
|
658
|
+
/[A-Za-z_][\w$#]*/,
|
|
659
|
+
{
|
|
660
|
+
cases: {
|
|
661
|
+
"@booleans": "boolean.sql",
|
|
662
|
+
// 디자인 스펙상 NULL은 숫자와 같은 색이라 number 토큰으로 분류한다.
|
|
663
|
+
"@constants": "number.sql",
|
|
664
|
+
"@keywords": "keyword.sql",
|
|
665
|
+
"@default": "identifier.sql"
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
]
|
|
669
|
+
],
|
|
670
|
+
comment: [
|
|
671
|
+
[/[^*/]+/, "comment.quote.sql"],
|
|
672
|
+
[/\*\//, { token: "comment.quote.sql", next: "@pop" }],
|
|
673
|
+
[/[*/]/, "comment.quote.sql"]
|
|
674
|
+
]
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
isSqlEditorLanguageConfigured = true;
|
|
678
|
+
};
|
|
679
|
+
var getSqlEditorThemeRules = () => createCodeEditorThemeRules([
|
|
680
|
+
{ token: "identifier.sql", cssVariable: "--color-text-secondary" },
|
|
681
|
+
{ token: "identifier.quote.sql", cssVariable: "--color-text-secondary" },
|
|
682
|
+
{ token: "variable.bind.sql", cssVariable: "--color-tint-foreground-orange" },
|
|
683
|
+
{ token: "boolean.sql", cssVariable: "--color-text-tertiary" },
|
|
684
|
+
{ token: "keyword.sql", cssVariable: "--color-tint-foreground-violet" },
|
|
685
|
+
{ token: "operator.sql", cssVariable: "--color-text-secondary" },
|
|
686
|
+
{ token: "number.sql", cssVariable: "--color-tint-foreground-pink" },
|
|
687
|
+
{ token: "string.sql", cssVariable: "--color-tint-foreground-teal" },
|
|
688
|
+
{ token: "comment.sql", cssVariable: "--color-text-disabled", fontStyle: "italic" },
|
|
689
|
+
{ token: "comment.quote.sql", cssVariable: "--color-text-disabled", fontStyle: "italic" },
|
|
690
|
+
{ token: "delimiter.sql", cssVariable: "--color-text-secondary" }
|
|
691
|
+
]);
|
|
692
|
+
|
|
693
|
+
// src/codeEditor/sqlEditor/tokens.ts
|
|
694
|
+
var identifierBoundaryPattern = /[A-Za-z0-9_$#]/;
|
|
695
|
+
var escapeRegExp = (value) => {
|
|
696
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
697
|
+
};
|
|
698
|
+
var isProtectedOffset = (spans, start, end) => {
|
|
699
|
+
return spans.some((span) => start < span.end && end > span.start);
|
|
700
|
+
};
|
|
701
|
+
var getLineCommentEnd = (value, start) => {
|
|
702
|
+
const end = value.indexOf("\n", start + 2);
|
|
703
|
+
return end === -1 ? value.length : end;
|
|
704
|
+
};
|
|
705
|
+
var getBlockCommentEnd = (value, start) => {
|
|
706
|
+
const end = value.indexOf("*/", start + 2);
|
|
707
|
+
return end === -1 ? value.length : end + 2;
|
|
708
|
+
};
|
|
709
|
+
var getQuotedSpanEnd = (value, start) => {
|
|
710
|
+
const quote = value[start];
|
|
711
|
+
let index = start + 1;
|
|
712
|
+
while (index < value.length) {
|
|
713
|
+
if (value[index] === quote && value[index + 1] === quote) {
|
|
714
|
+
index += 2;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
if (value[index] === quote) {
|
|
718
|
+
return index + 1;
|
|
719
|
+
}
|
|
720
|
+
index += 1;
|
|
721
|
+
}
|
|
722
|
+
return index;
|
|
723
|
+
};
|
|
724
|
+
var getProtectedSpans = (value) => {
|
|
725
|
+
const spans = [];
|
|
726
|
+
let index = 0;
|
|
727
|
+
while (index < value.length) {
|
|
728
|
+
const char = value[index];
|
|
729
|
+
const next = value[index + 1];
|
|
730
|
+
if (char === "-" && next === "-") {
|
|
731
|
+
const start = index;
|
|
732
|
+
index = getLineCommentEnd(value, start);
|
|
733
|
+
spans.push({ start, end: index });
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
if (char === "/" && next === "*") {
|
|
737
|
+
const start = index;
|
|
738
|
+
index = getBlockCommentEnd(value, start);
|
|
739
|
+
spans.push({ start, end: index });
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
if (char === "'" || char === '"') {
|
|
743
|
+
const start = index;
|
|
744
|
+
index = getQuotedSpanEnd(value, start);
|
|
745
|
+
spans.push({ start, end: index });
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
index += 1;
|
|
749
|
+
}
|
|
750
|
+
return spans;
|
|
751
|
+
};
|
|
752
|
+
var getLineStarts = (value) => {
|
|
753
|
+
const lineStarts = [0];
|
|
754
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
755
|
+
if (value[index] === "\n") {
|
|
756
|
+
lineStarts.push(index + 1);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return lineStarts;
|
|
760
|
+
};
|
|
761
|
+
var offsetToPosition = (lineStarts, offset) => {
|
|
762
|
+
let low = 0;
|
|
763
|
+
let high = lineStarts.length - 1;
|
|
764
|
+
while (low <= high) {
|
|
765
|
+
const mid = Math.floor((low + high) / 2);
|
|
766
|
+
if ((lineStarts[mid] ?? 0) <= offset) {
|
|
767
|
+
low = mid + 1;
|
|
768
|
+
} else {
|
|
769
|
+
high = mid - 1;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
const lineIndex = Math.max(0, high);
|
|
773
|
+
const lineStart = lineStarts[lineIndex] ?? 0;
|
|
774
|
+
return {
|
|
775
|
+
lineNumber: lineIndex + 1,
|
|
776
|
+
column: offset - lineStart + 1
|
|
777
|
+
};
|
|
778
|
+
};
|
|
779
|
+
var getRangeFromOffsets = (lineStarts, startOffset, endOffset) => {
|
|
780
|
+
const start = offsetToPosition(lineStarts, startOffset);
|
|
781
|
+
const end = offsetToPosition(lineStarts, endOffset);
|
|
782
|
+
return {
|
|
783
|
+
startLineNumber: start.lineNumber,
|
|
784
|
+
startColumn: start.column,
|
|
785
|
+
endLineNumber: end.lineNumber,
|
|
786
|
+
endColumn: end.column
|
|
787
|
+
};
|
|
788
|
+
};
|
|
789
|
+
var hasIdentifierBoundary = (value, startOffset, endOffset) => {
|
|
790
|
+
const before = value[startOffset - 1];
|
|
791
|
+
const after = value[endOffset];
|
|
792
|
+
return !identifierBoundaryPattern.test(before ?? "") && !identifierBoundaryPattern.test(after ?? "");
|
|
793
|
+
};
|
|
794
|
+
var getSearchableTokens = (tokens) => {
|
|
795
|
+
const searchableTokens = /* @__PURE__ */ new Map();
|
|
796
|
+
for (const token of tokens) {
|
|
797
|
+
if (!token.match) {
|
|
798
|
+
continue;
|
|
799
|
+
}
|
|
800
|
+
const key = token.match.toLowerCase();
|
|
801
|
+
if (!searchableTokens.has(key)) {
|
|
802
|
+
searchableTokens.set(key, token);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
return [...searchableTokens.values()].sort((a, b) => b.match.length - a.match.length);
|
|
806
|
+
};
|
|
807
|
+
var getSqlEditorTokens = (value, tokens) => {
|
|
808
|
+
const searchableTokens = getSearchableTokens(tokens);
|
|
809
|
+
if (!searchableTokens.length) {
|
|
810
|
+
return [];
|
|
811
|
+
}
|
|
812
|
+
const tokenByMatch = new Map(searchableTokens.map((token) => [token.match.toLowerCase(), token]));
|
|
813
|
+
const pattern = new RegExp(
|
|
814
|
+
searchableTokens.map((token) => escapeRegExp(token.match)).join("|"),
|
|
815
|
+
"gi"
|
|
816
|
+
);
|
|
817
|
+
const protectedSpans = getProtectedSpans(value);
|
|
818
|
+
const lineStarts = getLineStarts(value);
|
|
819
|
+
const parsedTokens = [];
|
|
820
|
+
let match = pattern.exec(value);
|
|
821
|
+
while (match !== null) {
|
|
822
|
+
const text = match[0];
|
|
823
|
+
const startOffset = match.index;
|
|
824
|
+
const endOffset = startOffset + text.length;
|
|
825
|
+
const token = tokenByMatch.get(text.toLowerCase());
|
|
826
|
+
if (token && hasIdentifierBoundary(value, startOffset, endOffset) && !isProtectedOffset(protectedSpans, startOffset, endOffset)) {
|
|
827
|
+
parsedTokens.push({
|
|
828
|
+
token,
|
|
829
|
+
text,
|
|
830
|
+
range: getRangeFromOffsets(lineStarts, startOffset, endOffset),
|
|
831
|
+
startOffset,
|
|
832
|
+
endOffset,
|
|
833
|
+
className: token.className
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
match = pattern.exec(value);
|
|
837
|
+
}
|
|
838
|
+
return parsedTokens;
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
// src/codeEditor/sqlEditor/useSqlEditorTokenDecorations.ts
|
|
842
|
+
var isPositionInToken = (position, token) => {
|
|
843
|
+
const { range } = token;
|
|
844
|
+
if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
if (position.lineNumber === range.startLineNumber && position.column < range.startColumn) {
|
|
848
|
+
return false;
|
|
849
|
+
}
|
|
850
|
+
if (position.lineNumber === range.endLineNumber && position.column >= range.endColumn) {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
return true;
|
|
854
|
+
};
|
|
855
|
+
var useSqlEditorTokenDecorations = ({
|
|
856
|
+
displayValue,
|
|
857
|
+
tokens,
|
|
858
|
+
onTokenClick,
|
|
859
|
+
onMount
|
|
860
|
+
}) => {
|
|
861
|
+
const editorRef = React2.useRef(null);
|
|
862
|
+
const monacoRef = React2.useRef(null);
|
|
863
|
+
const decorationsRef = React2.useRef(null);
|
|
864
|
+
const clickHandlerRef = React2.useRef(null);
|
|
865
|
+
const applyTokenDecorations = React2.useCallback(() => {
|
|
866
|
+
const editor = editorRef.current;
|
|
867
|
+
const monaco = monacoRef.current;
|
|
868
|
+
if (!editor || !monaco) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const parsedTokens = getSqlEditorTokens(displayValue, tokens);
|
|
872
|
+
decorationsRef.current ?? (decorationsRef.current = editor.createDecorationsCollection());
|
|
873
|
+
decorationsRef.current.set(
|
|
874
|
+
parsedTokens.map((token) => ({
|
|
875
|
+
range: new monaco.Range(
|
|
876
|
+
token.range.startLineNumber,
|
|
877
|
+
token.range.startColumn,
|
|
878
|
+
token.range.endLineNumber,
|
|
879
|
+
token.range.endColumn
|
|
880
|
+
),
|
|
881
|
+
options: {
|
|
882
|
+
inlineClassName: token.className,
|
|
883
|
+
stickiness: monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
|
884
|
+
}
|
|
885
|
+
}))
|
|
886
|
+
);
|
|
887
|
+
if (clickHandlerRef.current) {
|
|
888
|
+
clickHandlerRef.current.dispose();
|
|
889
|
+
clickHandlerRef.current = null;
|
|
890
|
+
}
|
|
891
|
+
if (!onTokenClick) {
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
clickHandlerRef.current = editor.onMouseDown((mouseEvent) => {
|
|
895
|
+
const position = mouseEvent.target.position;
|
|
896
|
+
if (!position) {
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
const parsedToken = parsedTokens.find((token) => isPositionInToken(position, token));
|
|
900
|
+
if (!parsedToken) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
onTokenClick(parsedToken.token);
|
|
904
|
+
});
|
|
905
|
+
}, [displayValue, onTokenClick, tokens]);
|
|
906
|
+
const handleMount = React2.useCallback(
|
|
907
|
+
(editor, monaco) => {
|
|
908
|
+
editorRef.current = editor;
|
|
909
|
+
monacoRef.current = monaco;
|
|
910
|
+
applyTokenDecorations();
|
|
911
|
+
onMount?.(editor, monaco);
|
|
912
|
+
},
|
|
913
|
+
[applyTokenDecorations, onMount]
|
|
914
|
+
);
|
|
915
|
+
React2.useEffect(() => {
|
|
916
|
+
applyTokenDecorations();
|
|
917
|
+
}, [applyTokenDecorations]);
|
|
918
|
+
React2.useEffect(() => {
|
|
919
|
+
return () => {
|
|
920
|
+
if (clickHandlerRef.current) {
|
|
921
|
+
clickHandlerRef.current.dispose();
|
|
922
|
+
clickHandlerRef.current = null;
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
}, []);
|
|
926
|
+
return { handleMount };
|
|
927
|
+
};
|
|
928
|
+
registerCodeEditorThemeRules(getSqlEditorThemeRules);
|
|
929
|
+
var CodeEditorSQL = React2__namespace.forwardRef(
|
|
930
|
+
({
|
|
931
|
+
beforeMount,
|
|
932
|
+
dbType,
|
|
933
|
+
editorClassName,
|
|
934
|
+
formatter,
|
|
935
|
+
onMount,
|
|
936
|
+
onTokenClick,
|
|
937
|
+
tokens = [],
|
|
938
|
+
...props
|
|
939
|
+
}, ref) => {
|
|
940
|
+
const { viewMode } = useCodeEditorFormat();
|
|
941
|
+
const { sourceValue: contextValue } = useCodeEditorSource();
|
|
942
|
+
const sqlFormatter = React2__namespace.useMemo(
|
|
943
|
+
() => createSqlFormatter(dbType),
|
|
944
|
+
[dbType]
|
|
945
|
+
);
|
|
946
|
+
const surfaceFormatter = formatter === void 0 ? sqlFormatter : formatter;
|
|
947
|
+
const surfaceValue = props.value ?? contextValue ?? "";
|
|
948
|
+
const surfaceDisplayValue = getDisplayValue(surfaceValue, viewMode, surfaceFormatter);
|
|
949
|
+
useActiveFormatter(surfaceFormatter);
|
|
950
|
+
const { handleMount } = useSqlEditorTokenDecorations({
|
|
951
|
+
displayValue: surfaceDisplayValue,
|
|
952
|
+
tokens,
|
|
953
|
+
onTokenClick,
|
|
954
|
+
onMount
|
|
955
|
+
});
|
|
956
|
+
const handleBeforeMount = React2__namespace.useCallback(
|
|
957
|
+
(monaco) => {
|
|
958
|
+
defineSqlEditorLanguage(monaco);
|
|
959
|
+
beforeMount?.(monaco);
|
|
960
|
+
},
|
|
961
|
+
[beforeMount]
|
|
962
|
+
);
|
|
963
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
964
|
+
CodeEditor.Surface,
|
|
965
|
+
{
|
|
966
|
+
ref,
|
|
967
|
+
...props,
|
|
968
|
+
beforeMount: handleBeforeMount,
|
|
969
|
+
editorClassName: utils.cn("exem-sql-editor-monaco", editorClassName),
|
|
970
|
+
formatter: surfaceFormatter,
|
|
971
|
+
language: sqlEditorLanguageId,
|
|
972
|
+
onMount: handleMount
|
|
973
|
+
}
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
);
|
|
977
|
+
CodeEditorSQL.displayName = "CodeEditor.SQL";
|
|
978
|
+
|
|
979
|
+
// src/codeEditor/index.ts
|
|
980
|
+
var CodeEditor2 = CodeEditor;
|
|
981
|
+
CodeEditor2.JSON = CodeEditorJSON;
|
|
982
|
+
CodeEditor2.SQL = CodeEditorSQL;
|
|
983
|
+
|
|
984
|
+
exports.CodeEditor = CodeEditor2;
|
|
985
|
+
exports.getSqlEditorTokens = getSqlEditorTokens;
|
|
986
|
+
//# sourceMappingURL=index.js.map
|
|
987
|
+
//# sourceMappingURL=index.js.map
|