Files
supabase/studio/components/ui/SqlEditor.tsx
2022-07-08 12:46:46 +08:00

127 lines
3.0 KiB
TypeScript

import Editor, { OnChange, useMonaco } from '@monaco-editor/react'
import { FC, useEffect, useRef } from 'react'
import { Typography } from '@supabase/ui'
import { useStore } from 'hooks'
interface Props {
contextmenu?: boolean
defaultValue?: string
language?: string
onInputChange?: OnChange
queryId?: string
readOnly?: boolean
}
const SqlEditor: FC<Props> = ({
queryId,
language = 'pgsql',
defaultValue = '',
readOnly = false,
contextmenu = true,
onInputChange = () => {},
}) => {
const monaco = useMonaco()
const { meta } = useStore()
const editorRef = useRef<any>()
useEffect(() => {
if (monaco) {
// Supabase theming (Can't seem to get it to work for now)
monaco.editor.defineTheme('supabase', {
base: 'vs-dark',
inherit: true,
colors: {},
rules: [
{ token: '', background: '4a5568' },
{ token: 'string.sql', foreground: '24b47e' },
{ token: 'comment', foreground: '666666' },
{ token: 'predefined.sql', foreground: 'D4D4D4' },
],
})
// Enable pgsql format
const formatprovider = monaco.languages.registerDocumentFormattingEditProvider('pgsql', {
async provideDocumentFormattingEdits(model: any) {
const value = model.getValue()
const formatted = await formatPgsql(value)
return [
{
range: model.getFullModelRange(),
text: formatted,
},
]
},
})
return () => {
formatprovider.dispose()
}
}
}, [monaco])
useEffect(() => {
if (editorRef.current) {
// add margin above first line
editorRef.current?.changeViewZones((accessor: any) => {
accessor.addZone({
afterLineNumber: 0,
heightInPx: 4,
domNode: document.createElement('div'),
})
})
}
}, [queryId])
async function formatPgsql(value: any) {
try {
const formatted = await meta.formatQuery(value)
if (formatted.error) throw formatted.error
return formatted
} catch (error) {
console.error('formatPgsql error:', error)
return value
}
}
const onMount = (editor: any, monaco: any) => {
editorRef.current = editor
// Add margin above first line
editor.changeViewZones((accessor: any) => {
accessor.addZone({
afterLineNumber: 0,
heightInPx: 4,
domNode: document.createElement('div'),
})
})
}
const Loading = () => <Typography.Title level={4}>Loading</Typography.Title>
return (
<Editor
className="monaco-editor"
theme="vs-dark"
defaultLanguage={language}
defaultValue={defaultValue}
path={queryId}
loading={<Loading />}
options={{
readOnly,
tabSize: 2,
fontSize: 13,
minimap: {
enabled: false,
},
wordWrap: 'on',
fixedOverflowWidgets: true,
contextmenu: contextmenu,
}}
onMount={onMount}
onChange={onInputChange}
/>
)
}
export default SqlEditor