@fc-components/monaco-editor 0.3.1 → 0.3.2

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.2",
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,32 @@ 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: 0.6;
102
+ transition: opacity 0.15s;
103
+
104
+ &:hover {
105
+ opacity: 1;
106
+ background: var(--format-btn-hover-bg, rgba(128, 128, 128, 0.15));
107
+ }
108
+ `;
109
+
110
+ const SqlEditor = forwardRef<SqlEditorHandle, SqlEditorProps>((props, ref) => {
77
111
  const id = uuidv4();
78
112
  const {
79
113
  className,
@@ -83,6 +117,7 @@ export default function SqlEditor(props: SqlEditorProps) {
83
117
  theme = 'light',
84
118
  value = '',
85
119
  placeholder,
120
+ enableFormat = false,
86
121
  enableAutocomplete = true,
87
122
  readOnly = false,
88
123
  disabled = false,
@@ -91,6 +126,7 @@ export default function SqlEditor(props: SqlEditorProps) {
91
126
  onBlur,
92
127
  onFocus,
93
128
  editorDidMount,
129
+ renderFormatButton,
94
130
  } = props;
95
131
 
96
132
  const containerRef = useRef<HTMLDivElement>(null);
@@ -223,6 +259,18 @@ export default function SqlEditor(props: SqlEditorProps) {
223
259
  editorDidMount?.(editor);
224
260
  };
225
261
 
262
+ const handleFormat = useCallback(() => {
263
+ const editor = editorRef.current;
264
+ if (!editor) return;
265
+ const currentValue = editor.getValue();
266
+ const formatted = formatSql(currentValue);
267
+ editor.setValue(formatted);
268
+ }, []);
269
+
270
+ useImperativeHandle(ref, () => ({
271
+ format: handleFormat,
272
+ }));
273
+
226
274
  const themeValue = themeMap[theme];
227
275
 
228
276
  return (
@@ -238,6 +286,7 @@ export default function SqlEditor(props: SqlEditorProps) {
238
286
  display: 'block',
239
287
  resize: 'vertical',
240
288
  overflow: 'auto',
289
+ position: 'relative',
241
290
  minHeight: SIZE_MAP[size].minHeight,
242
291
  maxHeight,
243
292
  }}
@@ -285,6 +334,45 @@ export default function SqlEditor(props: SqlEditorProps) {
285
334
  }}
286
335
  />
287
336
  </div>
337
+ {enableFormat &&
338
+ (renderFormatButton ? (
339
+ renderFormatButton(handleFormat)
340
+ ) : (
341
+ <button
342
+ onClick={handleFormat}
343
+ className={formatBtnClassName}
344
+ title='Format SQL'
345
+ style={
346
+ {
347
+ '--format-btn-hover-bg':
348
+ theme === 'dark' ? 'rgba(255,255,255,0.2)' : 'rgba(128,128,128,0.15)',
349
+ } as React.CSSProperties
350
+ }
351
+ >
352
+ <svg
353
+ xmlns='http://www.w3.org/2000/svg'
354
+ width='16'
355
+ height='16'
356
+ viewBox='0 0 24 24'
357
+ fill='none'
358
+ stroke='currentColor'
359
+ strokeWidth='2'
360
+ strokeLinecap='round'
361
+ strokeLinejoin='round'
362
+ >
363
+ <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' />
364
+ <path d='m14 7 3 3' />
365
+ <path d='M5 6v4' />
366
+ <path d='M19 14v4' />
367
+ <path d='M10 2v2' />
368
+ <path d='M7 8H3' />
369
+ <path d='M21 16h-4' />
370
+ <path d='M11 3H9' />
371
+ </svg>
372
+ </button>
373
+ ))}
288
374
  </div>
289
375
  );
290
- }
376
+ });
377
+
378
+ export default SqlEditor;