diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx
index 6b33be84e2c..babff3766a2 100644
--- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx
@@ -185,7 +185,10 @@ const RLSCodeEditor = ({
{placeholder !== undefined && (
div>p]:text-foreground-lighter [&>div>p]:!m-0'
+ )}
style={{ display: 'none' }}
>
diff --git a/apps/studio/components/interfaces/Database/Functions/CreateFunction/FunctionEditor.tsx b/apps/studio/components/interfaces/Database/Functions/CreateFunction/FunctionEditor.tsx
index 8742807280e..37db03c783e 100644
--- a/apps/studio/components/interfaces/Database/Functions/CreateFunction/FunctionEditor.tsx
+++ b/apps/studio/components/interfaces/Database/Functions/CreateFunction/FunctionEditor.tsx
@@ -9,26 +9,31 @@ import {
Tooltip_Shadcn_,
cn,
} from 'ui'
+import CodeEditor from 'components/ui/CodeEditor/CodeEditor'
export const FunctionEditor = ({
field,
+ language,
focused,
setFocused,
}: {
field: any
+ language: string
focused: boolean
setFocused: (b: boolean) => void
}) => {
return (
- {
- field.onChange(value)
- }}
- contextmenu={false}
- />
+ {language !== undefined && (
+
+ )}
setFocused(!focused)}
icon={focused ?
:
}
- >
+ />
{focused ? 'Minimize editor' : 'Maximize editor'}
diff --git a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx
index c8db848536d..e0950b10feb 100644
--- a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx
+++ b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx
@@ -39,7 +39,6 @@ import {
SheetSection,
Toggle,
cn,
- useWatch_Shadcn_,
} from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
@@ -82,6 +81,7 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => {
const form = useForm>({
resolver: zodResolver(FormSchema),
})
+ const language = form.watch('language')
const { mutate: createDatabaseFunction, isLoading: isCreating } =
useDatabaseFunctionCreateMutation()
@@ -256,11 +256,7 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => {
- The language below should be written in{' '}
-
-
-
- .
+ The language below should be written in {language}.
{!isEditing && Change the language in the Advanced Settings below.
}
@@ -273,6 +269,7 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => {
>
@@ -647,9 +644,3 @@ const FormFieldLanguage = () => {
/>
)
}
-
-const FormLanguage = () => {
- const language = useWatch_Shadcn_({ name: 'language' })
-
- return language
-}
diff --git a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx
index f955a339e97..24eeb0d677d 100644
--- a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx
+++ b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx
@@ -1,10 +1,11 @@
-import Editor, { EditorProps, OnMount } from '@monaco-editor/react'
+import Editor, { EditorProps, Monaco, OnChange, OnMount } from '@monaco-editor/react'
import { merge, noop } from 'lodash'
import { editor } from 'monaco-editor'
-import { useRef } from 'react'
-import { cn } from 'ui'
+import { useEffect, useRef, useState } from 'react'
+import { Markdown } from 'components/interfaces/Markdown'
import { timeout } from 'lib/helpers'
+import { cn } from 'ui'
import { Loading } from '../Loading'
import { alignEditor } from './CodeEditor.utils'
@@ -21,6 +22,8 @@ interface CodeEditorProps {
loading?: boolean
options?: EditorProps['options']
value?: string
+ placeholder?: string
+ disableTabToUsePlaceholder?: boolean
}
const CodeEditor = ({
@@ -36,13 +39,47 @@ const CodeEditor = ({
loading,
options,
value,
+ placeholder,
+ disableTabToUsePlaceholder = false,
}: CodeEditorProps) => {
+ const hasValue = useRef()
+
const editorRef = useRef()
+ const monacoRef = useRef()
+
+ const showPlaceholderDefault = placeholder !== undefined && (value ?? '').trim().length === 0
+ const [showPlaceholder, setShowPlaceholder] = useState(showPlaceholderDefault)
const onMount: OnMount = async (editor, monaco) => {
editorRef.current = editor
+ monacoRef.current = monaco
alignEditor(editor)
+ hasValue.current = editor.createContextKey('hasValue', false)
+ hasValue.current.set(value !== undefined && value.trim().length > 0)
+ setShowPlaceholder(showPlaceholderDefault)
+
+ if (!disableTabToUsePlaceholder) {
+ editor.addCommand(
+ monaco.KeyCode.Tab,
+ () => {
+ editor.executeEdits('source', [
+ {
+ // @ts-ignore
+ identifier: 'add-placeholder',
+ range: new monaco.Range(1, 1, 1, 1),
+ text: (placeholder ?? '')
+ .split('\n\n')
+ .join('\n')
+ .replaceAll('*', '')
+ .replaceAll(' ', ''),
+ },
+ ])
+ },
+ '!hasValue'
+ )
+ }
+
editor.addAction({
id: 'supabase',
label: 'Run Query',
@@ -57,10 +94,22 @@ const CodeEditor = ({
},
})
+ const model = editor.getModel()
+ if (model) {
+ const position = model.getPositionAt((value ?? '').length)
+ editor.setPosition(position)
+ }
+
await timeout(500)
if (autofocus) editor?.focus()
}
+ const onChangeContent: OnChange = (value) => {
+ hasValue.current.set((value ?? '').length > 0)
+ setShowPlaceholder(!value)
+ onInputChange(value)
+ }
+
const optionsMerged = merge(
{
tabSize: 2,
@@ -72,27 +121,73 @@ const CodeEditor = ({
contextmenu: true,
lineNumbers: hideLineNumbers ? 'off' : undefined,
glyphMargin: hideLineNumbers ? false : undefined,
- lineNumbersMinChars: hideLineNumbers ? 0 : undefined,
+ lineNumbersMinChars: hideLineNumbers ? 0 : 4,
folding: hideLineNumbers ? false : undefined,
+ scrollBeyondLastLine: false,
},
options
)
- merge({ cpp: '12' }, { java: '23' }, { python: '35' })
+ useEffect(() => {
+ setShowPlaceholder(showPlaceholderDefault)
+ }, [showPlaceholderDefault])
+
+ useEffect(() => {
+ if (
+ !disableTabToUsePlaceholder &&
+ editorRef.current !== undefined &&
+ monacoRef.current !== undefined
+ ) {
+ const editor = editorRef.current
+ const monaco = monacoRef.current
+
+ editor.addCommand(
+ monaco.KeyCode.Tab,
+ () => {
+ editor.executeEdits('source', [
+ {
+ // @ts-ignore
+ identifier: 'add-placeholder',
+ range: new monaco.Range(1, 1, 1, 1),
+ text: (placeholder ?? ' ')
+ .split('\n\n')
+ .join('\n')
+ .replaceAll('*', '')
+ .replaceAll(' ', ''),
+ },
+ ])
+ },
+ '!hasValue'
+ )
+ }
+ }, [placeholder, disableTabToUsePlaceholder])
return (
- }
- options={optionsMerged}
- onMount={onMount}
- onChange={onInputChange}
- />
+ <>
+ }
+ options={optionsMerged}
+ onMount={onMount}
+ onChange={onChangeContent}
+ />
+ {placeholder !== undefined && (
+ div>p]:text-foreground-lighter [&>div>p]:!m-0 tracking-tighter',
+ showPlaceholder ? 'block' : 'hidden'
+ )}
+ >
+
+
+ )}
+ >
)
}
diff --git a/apps/studio/components/ui/SqlEditor.tsx b/apps/studio/components/ui/SqlEditor.tsx
index 15ab2f73845..ad982e4ebbc 100644
--- a/apps/studio/components/ui/SqlEditor.tsx
+++ b/apps/studio/components/ui/SqlEditor.tsx
@@ -16,6 +16,9 @@ interface SqlEditorProps {
readOnly?: boolean
}
+/**
+ * @deprecated Use CodeEditor instead
+ */
const SqlEditor = ({
queryId,
language = 'pgsql',