@fc-components/monaco-editor 0.3.1 → 0.3.3

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.
@@ -0,0 +1 @@
1
+ export declare function formatSql(sql: string): string;
@@ -16,6 +16,13 @@ interface SqlEditorProps {
16
16
  onBlur?: (value: string) => void;
17
17
  onFocus?: (value: string) => void;
18
18
  editorDidMount?: (editor: monacoTypes.editor.IStandaloneCodeEditor) => void;
19
+ /** Whether to show the format button. Default: false */
20
+ enableFormat?: boolean;
21
+ /** Custom format button renderer */
22
+ renderFormatButton?: (handleFormat: () => void) => React.ReactNode;
19
23
  }
20
- export default function SqlEditor(props: SqlEditorProps): React.JSX.Element;
21
- export {};
24
+ export interface SqlEditorHandle {
25
+ format: () => void;
26
+ }
27
+ declare const SqlEditor: React.ForwardRefExoticComponent<SqlEditorProps & React.RefAttributes<SqlEditorHandle>>;
28
+ export default SqlEditor;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.3.1",
6
+ "version": "0.3.3",
7
7
  "license": "MIT",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/monaco-editor.esm.js",
@@ -58,6 +58,7 @@
58
58
  "monaco-promql": "^1.7.4",
59
59
  "pluralize": "^8.0.0",
60
60
  "react-monaco-editor": "^0.58.0",
61
+ "sql-formatter": "^15.8.0",
61
62
  "uuidv4": "^6.2.13"
62
63
  }
63
64
  }
@@ -0,0 +1,13 @@
1
+ import { format } from 'sql-formatter';
2
+
3
+ export function formatSql(sql: string): string {
4
+ try {
5
+ return format(sql, {
6
+ tabWidth: 2,
7
+ keywordCase: 'upper',
8
+ });
9
+ } catch {
10
+ // If formatting fails, return the original SQL
11
+ return sql;
12
+ }
13
+ }
package/src/sql/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react';
1
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
2
2
  import MonacoEditor from 'react-monaco-editor';
3
3
  import * as monaco from 'monaco-editor';
4
4
  import type * as monacoTypes from 'monaco-editor/esm/vs/editor/editor.api';
@@ -6,6 +6,7 @@ import { v4 as uuidv4 } from 'uuid';
6
6
  import { css } from '@emotion/css';
7
7
  import { language, languageConfiguration } from './sql';
8
8
  import { getSqlCompletionProvider } from './completion/getCompletionProvider';
9
+ import { formatSql } from './format';
9
10
 
10
11
  interface SqlEditorProps {
11
12
  className?: string;
@@ -23,6 +24,14 @@ interface SqlEditorProps {
23
24
  onBlur?: (value: string) => void;
24
25
  onFocus?: (value: string) => void;
25
26
  editorDidMount?: (editor: monacoTypes.editor.IStandaloneCodeEditor) => void;
27
+ /** Whether to show the format button. Default: false */
28
+ enableFormat?: boolean;
29
+ /** Custom format button renderer */
30
+ renderFormatButton?: (handleFormat: () => void) => React.ReactNode;
31
+ }
32
+
33
+ export interface SqlEditorHandle {
34
+ format: () => void;
26
35
  }
27
36
 
28
37
  const SQL_LANG_ID = 'sql';
@@ -73,7 +82,31 @@ const containerReadOnlyClassName = css`
73
82
  }
74
83
  `;
75
84
 
76
- export default function SqlEditor(props: SqlEditorProps) {
85
+ const formatBtnClassName = css`
86
+ position: absolute;
87
+ top: 4px;
88
+ right: 4px;
89
+ z-index: 10;
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ width: 24px;
94
+ height: 24px;
95
+ padding: 0;
96
+ border: none;
97
+ background: transparent;
98
+ border-radius: 4px;
99
+ cursor: pointer;
100
+ color: inherit;
101
+ opacity: 1;
102
+ transition: opacity 0.15s;
103
+
104
+ &:hover {
105
+ background: var(--format-btn-hover-bg, rgba(128, 128, 128, 0.15));
106
+ }
107
+ `;
108
+
109
+ const SqlEditor = forwardRef<SqlEditorHandle, SqlEditorProps>((props, ref) => {
77
110
  const id = uuidv4();
78
111
  const {
79
112
  className,
@@ -83,6 +116,7 @@ export default function SqlEditor(props: SqlEditorProps) {
83
116
  theme = 'light',
84
117
  value = '',
85
118
  placeholder,
119
+ enableFormat = false,
86
120
  enableAutocomplete = true,
87
121
  readOnly = false,
88
122
  disabled = false,
@@ -91,6 +125,7 @@ export default function SqlEditor(props: SqlEditorProps) {
91
125
  onBlur,
92
126
  onFocus,
93
127
  editorDidMount,
128
+ renderFormatButton,
94
129
  } = props;
95
130
 
96
131
  const containerRef = useRef<HTMLDivElement>(null);
@@ -223,6 +258,18 @@ export default function SqlEditor(props: SqlEditorProps) {
223
258
  editorDidMount?.(editor);
224
259
  };
225
260
 
261
+ const handleFormat = useCallback(() => {
262
+ const editor = editorRef.current;
263
+ if (!editor) return;
264
+ const currentValue = editor.getValue();
265
+ const formatted = formatSql(currentValue);
266
+ editor.setValue(formatted);
267
+ }, []);
268
+
269
+ useImperativeHandle(ref, () => ({
270
+ format: handleFormat,
271
+ }));
272
+
226
273
  const themeValue = themeMap[theme];
227
274
 
228
275
  return (
@@ -238,6 +285,7 @@ export default function SqlEditor(props: SqlEditorProps) {
238
285
  display: 'block',
239
286
  resize: 'vertical',
240
287
  overflow: 'auto',
288
+ position: 'relative',
241
289
  minHeight: SIZE_MAP[size].minHeight,
242
290
  maxHeight,
243
291
  }}
@@ -285,6 +333,44 @@ export default function SqlEditor(props: SqlEditorProps) {
285
333
  }}
286
334
  />
287
335
  </div>
336
+ {enableFormat &&
337
+ (renderFormatButton ? (
338
+ renderFormatButton(handleFormat)
339
+ ) : (
340
+ <button
341
+ onClick={handleFormat}
342
+ className={formatBtnClassName}
343
+ title='Format SQL'
344
+ style={
345
+ {
346
+ '--format-btn-hover-bg': theme === 'dark' ? 'rgba(255,255,255,0.2)' : 'rgba(128,128,128,0.15)',
347
+ } as React.CSSProperties
348
+ }
349
+ >
350
+ <svg
351
+ xmlns='http://www.w3.org/2000/svg'
352
+ width='12'
353
+ height='12'
354
+ viewBox='0 0 24 24'
355
+ fill='none'
356
+ stroke='currentColor'
357
+ strokeWidth='1'
358
+ strokeLinecap='round'
359
+ strokeLinejoin='round'
360
+ >
361
+ <path d='m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72' />
362
+ <path d='m14 7 3 3' />
363
+ <path d='M5 6v4' />
364
+ <path d='M19 14v4' />
365
+ <path d='M10 2v2' />
366
+ <path d='M7 8H3' />
367
+ <path d='M21 16h-4' />
368
+ <path d='M11 3H9' />
369
+ </svg>
370
+ </button>
371
+ ))}
288
372
  </div>
289
373
  );
290
- }
374
+ });
375
+
376
+ export default SqlEditor;