fix: expanded editor shortcut (#47374)

## TL;DR 
fixes `Cmd/Ctrl+Enter` in the expanded editor by wiring the save
shortcut directly to monaco...

## ref:
- closes https://github.com/supabase/supabase/issues/47368

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a Ctrl/Cmd+Enter shortcut in both the JSON and text editors to
trigger validation and save actions.
* **Bug Fixes**
* Improved editor reliability by standardizing how editor actions are
wired and executed after mounting.
* **Performance**
* Reduced unnecessary re-renders by memoizing the shared save/validation
handlers used by the editor and the action bar.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Vaibhav authored and GitHub committed 2026-06-29 07:18:05 -06:00
1 parent 2aa1b52234
commit 27ca9ee64d
2 files changed
+53 -15

No files matched your search

@@ -1,3 +1,4 @@
import type { OnMount } from '@monaco-editor/react'
import { MAX_CHARACTERS } from '@supabase/pg-meta/src/query/table-row-query'
import { useParams } from 'common'
import { AlignLeft } from 'lucide-react'
@@ -60,16 +61,33 @@ export const JsonEditor = ({
const { mutate: getCellValue, isPending, isSuccess, reset } = useGetCellValueMutation()
const validateJSON = async (resolve: () => void) => {
try {
const newJsonStr = removeJSONTrailingComma(jsonStr)
const minifiedJSON = minifyJSON(newJsonStr)
if (onSaveJSON) onSaveJSON(minifiedJSON, resolve)
} catch (error: any) {
resolve()
toast.error('JSON seems to have an invalid structure.')
}
}
const validateJSON = useCallback(
async (nextValue: string, resolve: () => void) => {
try {
const newJsonStr = removeJSONTrailingComma(nextValue)
const minifiedJSON = minifyJSON(newJsonStr)
if (onSaveJSON) onSaveJSON(minifiedJSON, resolve)
} catch (error: any) {
resolve()
toast.error('JSON seems to have an invalid structure.')
}
},
[onSaveJSON]
)
const handleEditorMount: OnMount = useCallback(
(editor, monaco) => {
if (readOnly) return
editor.addAction({
id: 'save-value',
label: 'Save value',
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.Enter],
run: () => validateJSON(editor.getValue(), () => undefined),
})
},
[readOnly, validateJSON]
)
const prettify = () => {
const res = prettifyJSON(jsonStr)
@@ -166,7 +184,7 @@ export const JsonEditor = ({
closePanel={onClose}
backButtonLabel={backButtonLabel}
applyButtonLabel={applyButtonLabel}
applyFunction={readOnly ? undefined : validateJSON}
applyFunction={readOnly ? undefined : (resolve) => validateJSON(jsonStr, resolve)}
/>
}
>
@@ -179,6 +197,7 @@ export const JsonEditor = ({
language="json"
value={(jsonStr ?? '').toString()}
onInputChange={(val) => setJsonStr(val ?? '')}
onMount={handleEditorMount}
/>
</div>
) : (
@@ -1,3 +1,4 @@
import type { OnMount } from '@monaco-editor/react'
import { MAX_CHARACTERS } from '@supabase/pg-meta/src/query/table-row-query'
import { useParams } from 'common'
import { useCallback, useEffect, useState } from 'react'
@@ -77,9 +78,26 @@ export const TextEditor = ({
)
}
const saveValue = (resolve: () => void) => {
if (onSaveField) onSaveField(strValue, resolve)
}
const saveValue = useCallback(
(nextValue: string, resolve: () => void) => {
if (onSaveField) onSaveField(nextValue, resolve)
},
[onSaveField]
)
const handleEditorMount: OnMount = useCallback(
(editor, monaco) => {
if (readOnly) return
editor.addAction({
id: 'save-value',
label: 'Save value',
keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.Enter],
run: () => saveValue(editor.getValue(), () => undefined),
})
},
[readOnly, saveValue]
)
useEffect(() => {
if (visible) {
@@ -121,7 +139,7 @@ export const TextEditor = ({
closePanel={onClose}
backButtonLabel="Cancel"
applyButtonLabel="Save value"
applyFunction={readOnly ? undefined : saveValue}
applyFunction={readOnly ? undefined : (resolve) => saveValue(strValue, resolve)}
/>
}
>
@@ -134,6 +152,7 @@ export const TextEditor = ({
language="markdown"
value={strValue ?? ''}
onInputChange={(val) => setStrValue(val ?? '')}
onMount={handleEditorMount}
/>
</div>
) : (