Last active
July 29, 2021 12:34
-
-
Save loopmode/0fba6494c765235b51cad86103eabce1 to your computer and use it in GitHub Desktop.
SQL editor with formatting, based on monaco-editor, plus material UI wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import Editor from '@monaco-editor/react'; | |
import { format } from 'sql-formatter'; | |
export type InputEvent = { target: { name: string; value: string } }; | |
export default function MonacoSqlInput({ | |
value, | |
name = '', | |
height = 500, | |
onChange, | |
}: { | |
name?: string; | |
value?: string; | |
height?: number; | |
onChange?: (event: InputEvent) => void; | |
}) { | |
const handleChange = React.useCallback( | |
(value) => { | |
onChange?.({ | |
target: { name, value }, | |
}); | |
}, | |
[onChange, name] | |
); | |
const handleMount = React.useCallback( | |
(editor, monaco) => initSqlFormatter(monaco), | |
[] | |
); | |
return ( | |
<Editor | |
language="sql" | |
value={value || ''} | |
height={height} | |
onChange={handleChange} | |
onMount={handleMount} | |
/> | |
); | |
} | |
export function initSqlFormatter(monaco: typeof import('monaco-editor')) { | |
const m = monaco as any; | |
if (m.__sqlFormatterInitialized) return; | |
m.__sqlFormatterInitialized = true; | |
//-------------------------------------------------------------------------------- | |
// based on https://stackoverflow.com/a/66344338/368254 | |
//-------------------------------------------------------------------------------- | |
// define a document formatting provider | |
// then you contextmenu will add an "Format Document" action | |
const docFormatter = monaco.languages.registerDocumentFormattingEditProvider( | |
'sql', | |
{ | |
provideDocumentFormattingEdits(model, options) { | |
var formatted = format(model.getValue(), { | |
indent: ' '.repeat(options.tabSize), | |
}); | |
return [ | |
{ | |
range: model.getFullModelRange(), | |
text: formatted, | |
}, | |
]; | |
}, | |
} | |
); | |
// define a range formatting provider | |
// select some codes and right click those codes | |
// you contextmenu will have an "Format Selection" action | |
const rangeFormatter = | |
monaco.languages.registerDocumentRangeFormattingEditProvider('sql', { | |
provideDocumentRangeFormattingEdits(model, range, options) { | |
var formatted = format(model.getValueInRange(range), { | |
indent: ' '.repeat(options.tabSize), | |
}); | |
return [ | |
{ | |
range: range, | |
text: formatted, | |
}, | |
]; | |
}, | |
}); | |
return { | |
dispose: () => { | |
docFormatter.dispose(); | |
rangeFormatter.dispose(); | |
}, | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// material-ui wrapper | |
import React from 'react'; | |
import { Box, InputBaseComponentProps, TextField } from '@material-ui/core'; | |
const MonacoSqlInput = React.lazy(() => import('./MonacoSqlInput')); | |
type BaseProps = Omit< | |
React.ComponentProps<typeof TextField>, | |
'multiline' | 'rows' | |
>; | |
export const SqlTextField = React.memo(function SqlTextField({ | |
onChange, | |
InputProps, | |
height, | |
...props | |
}: BaseProps & { | |
height?: number; | |
}) { | |
return ( | |
<TextField | |
{...props} | |
multiline | |
InputProps={React.useMemo( | |
() => | |
Object.assign({}, InputProps, { | |
inputComponent: ( | |
inputComponentProps: React.PropsWithChildren<InputBaseComponentProps> | |
) => { | |
return ( | |
<Box mt={2} width={'100%'}> | |
<React.Suspense fallback={<div />}> | |
<MonacoSqlInput | |
{...inputComponentProps} | |
onChange={onChange as any} | |
height={height} | |
/> | |
</React.Suspense> | |
</Box> | |
); | |
}, | |
}), | |
[InputProps, onChange, height] | |
)} | |
/> | |
); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment