(undefined);
const [editor, setEditor] = useState<
editor.IStandaloneCodeEditor | undefined
>(undefined);
const [isEditorFocused, setIsEditorFocused] = useState(false);
+ const [autoHeightContentHeight, setAutoHeightContentHeight] = useState<
+ number | undefined
+ >(undefined);
const numericHeight = typeof height === 'number' ? height : 450;
const {
@@ -56,7 +76,28 @@ export const CodeEditor = ({
initialSize: numericHeight,
});
- const currentHeight = resizable ? resizableHeight : height;
+ const shouldAutoHeight = autoHeight && !resizable;
+ const codeEditorPadding =
+ typeof theme.spacingMultiplicator === 'number'
+ ? theme.spacingMultiplicator * 4
+ : undefined;
+ const currentHeight = shouldAutoHeight
+ ? (autoHeightContentHeight ?? height)
+ : resizable
+ ? resizableHeight
+ : height;
+ const contentPaddingOptions = {
+ ...(contentPadding === 'comfortable'
+ ? {
+ lineDecorationsWidth: codeEditorPadding,
+ }
+ : {}),
+ padding: {
+ bottom: codeEditorPadding,
+ top: codeEditorPadding,
+ },
+ };
+ const { padding: _callerPadding, ...editorOptions } = options ?? {};
const setModelMarkers = (
editor: editor.IStandaloneCodeEditor | undefined,
@@ -78,6 +119,43 @@ export const CodeEditor = ({
}
};
+ useEffect(() => {
+ if (!isDefined(monaco)) {
+ return;
+ }
+
+ setCodeEditorTheme(monaco, theme, colorScheme);
+ }, [colorScheme, monaco, theme]);
+
+ // Drive the container height from Monaco's content height; the editor's
+ // default automaticLayout then re-fits the canvas (no manual layout needed).
+ useEffect(() => {
+ if (!shouldAutoHeight || !isDefined(editor)) {
+ setAutoHeightContentHeight(undefined);
+ return;
+ }
+
+ const updateAutoHeight = () => {
+ const nextHeight = editor.getContentHeight();
+
+ if (!Number.isFinite(nextHeight) || nextHeight <= 0) {
+ return;
+ }
+
+ setAutoHeightContentHeight((currentHeight) =>
+ currentHeight === nextHeight ? currentHeight : nextHeight,
+ );
+ };
+
+ updateAutoHeight();
+
+ const disposable = editor.onDidContentSizeChange(updateAutoHeight);
+
+ return () => {
+ disposable.dispose();
+ };
+ }, [editor, shouldAutoHeight]);
+
return isLoading ? (
{
setIsEditorFocused(true);
@@ -143,6 +217,10 @@ export const CodeEditor = ({
options={{
formatOnPaste: true,
formatOnType: true,
+ fontFamily: theme.code.font.family,
+ bracketPairColorization: {
+ enabled: false,
+ },
overviewRulerLanes: 0,
scrollBeyondLastLine: false,
scrollbar: {
@@ -152,7 +230,8 @@ export const CodeEditor = ({
minimap: {
enabled: false,
},
- ...options,
+ ...editorOptions,
+ ...contentPaddingOptions,
}}
/>
diff --git a/packages/twenty-ui/src/input/code-editor/theme/utils/getBaseCodeEditorTheme.ts b/packages/twenty-ui/src/input/code-editor/theme/utils/getBaseCodeEditorTheme.ts
index 9a5134d865..433674776b 100644
--- a/packages/twenty-ui/src/input/code-editor/theme/utils/getBaseCodeEditorTheme.ts
+++ b/packages/twenty-ui/src/input/code-editor/theme/utils/getBaseCodeEditorTheme.ts
@@ -3,6 +3,10 @@ import { type editor } from 'monaco-editor';
import { isDefined } from '@ui/utilities/utils/isDefined';
const convertColorToHex = (color: string): string => {
+ if (color.trim() === 'transparent') {
+ return '#00000000';
+ }
+
const displayP3Match = color.match(
/color\(display-p3\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s+\/\s+([\d.]+))?\)/,
);
@@ -33,35 +37,81 @@ const convertColorToHex = (color: string): string => {
export const getBaseCodeEditorTheme = (
theme: ThemeType,
+ colorScheme: 'light' | 'dark',
): editor.IStandaloneThemeData => {
return {
- base: 'vs',
+ base: colorScheme === 'dark' ? 'vs-dark' : 'vs',
inherit: true,
rules: [
{
token: '',
- foreground: convertColorToHex(theme.code.text.gray),
- fontStyle: 'bold',
+ foreground: convertColorToHex(theme.font.color.secondary),
},
{
token: 'keyword',
- foreground: convertColorToHex(theme.code.text.sky),
+ foreground: convertColorToHex(theme.color.pink11),
},
{
- token: 'delimiter',
- foreground: convertColorToHex(theme.code.text.gray),
+ token: 'keyword.control',
+ foreground: convertColorToHex(theme.color.pink11),
+ },
+ {
+ token: 'keyword.json',
+ foreground: convertColorToHex(theme.color.orange11),
+ },
+ {
+ token: 'number',
+ foreground: convertColorToHex(theme.color.orange11),
+ },
+ {
+ token: 'number.json',
+ foreground: convertColorToHex(theme.color.orange11),
+ },
+ {
+ token: 'regexp',
+ foreground: convertColorToHex(theme.color.orange11),
+ },
+ {
+ token: 'type',
+ foreground: convertColorToHex(theme.color.green11),
+ },
+ {
+ token: 'attribute.name',
+ foreground: convertColorToHex(theme.color.blue11),
+ },
+ {
+ token: 'tag',
+ foreground: convertColorToHex(theme.color.pink11),
},
{
token: 'string',
- foreground: convertColorToHex(theme.code.text.pink),
+ foreground: convertColorToHex(theme.color.green11),
+ },
+ {
+ token: 'string.key.json',
+ foreground: convertColorToHex(theme.color.blue11),
+ },
+ {
+ token: 'delimiter',
+ foreground: convertColorToHex(theme.font.color.light),
+ },
+ {
+ token: 'delimiter.bracket.json',
+ foreground: convertColorToHex(theme.font.color.light),
+ },
+ {
+ token: 'string.value.json',
+ foreground: convertColorToHex(theme.color.green11),
},
{
token: 'comment',
- foreground: convertColorToHex(theme.code.text.orange),
+ foreground: convertColorToHex(theme.font.color.light),
+ fontStyle: 'italic',
},
],
colors: {
- 'editor.background': '#00000000',
+ 'editor.background': convertColorToHex('transparent'),
+ 'editor.foreground': convertColorToHex(theme.font.color.secondary),
'editorCursor.foreground': convertColorToHex(theme.font.color.primary),
'editorLineNumber.foreground': convertColorToHex(
theme.font.color.extraLight,
@@ -72,6 +122,22 @@ export const getBaseCodeEditorTheme = (
'editor.lineHighlightBackground': convertColorToHex(
theme.background.tertiary,
),
+ 'editor.selectionBackground': convertColorToHex(
+ theme.background.transparent.blue,
+ ),
+ 'editor.inactiveSelectionBackground': convertColorToHex(
+ theme.background.transparent.light,
+ ),
+ 'editorIndentGuide.background1': convertColorToHex(
+ theme.border.color.light,
+ ),
+ 'editorIndentGuide.activeBackground1': convertColorToHex(
+ theme.border.color.medium,
+ ),
+ 'editorBracketMatch.background': convertColorToHex(
+ theme.background.transparent.light,
+ ),
+ 'editorBracketMatch.border': convertColorToHex(theme.border.color.medium),
},
};
};