= React.memo(
- ({ className, codeProps, code, loading, language = 'sql' }) => (
-
- {loading ? (
-
- ) : (
- }>
-
-
- )}
-
- )
+ ({ className, code, loading, language = 'sql' }) => {
+ const { t } = useTranslation();
+ const monaco = useMonaco();
+ const { effectiveTheme } = useTheme();
+ const [isCopied, setIsCopied] = React.useState(false);
+ const [tooltipOpen, setTooltipOpen] = React.useState(false);
+
+ useEffect(() => {
+ monaco?.editor?.defineTheme?.(
+ effectiveTheme,
+ effectiveTheme === 'dark' ? DarkTheme : LightTheme
+ );
+ monaco?.editor?.setTheme?.(effectiveTheme);
+ }, [monaco, effectiveTheme]);
+
+ useEffect(() => {
+ if (!isCopied) return;
+ setTimeout(() => {
+ setIsCopied(false);
+ }, 1500);
+ }, [isCopied]);
+
+ const copyToClipboard = useCallback(() => {
+ navigator.clipboard.writeText(code);
+ setIsCopied(true);
+ }, [code]);
+
+ return (
+
+ {loading ? (
+
+ ) : (
+ }>
+
+
+
+
+
+
+
+ {t(isCopied ? 'copied' : 'copy_to_clipboard')}
+
+
+
+ }
+ theme={effectiveTheme}
+ options={{
+ minimap: {
+ enabled: false,
+ },
+ readOnly: true,
+ automaticLayout: true,
+ scrollbar: {
+ vertical: 'hidden',
+ horizontal: 'hidden',
+ alwaysConsumeMouseWheel: false,
+ },
+ scrollBeyondLastLine: false,
+ renderValidationDecorations: 'off',
+ lineDecorationsWidth: 0,
+ overviewRulerBorder: false,
+ overviewRulerLanes: 0,
+ hideCursorInOverviewRuler: true,
+ guides: {
+ indentation: false,
+ },
+ contextmenu: false,
+ }}
+ />
+
+ )}
+
+ );
+ }
);
CodeSnippet.displayName = 'CodeSnippet';
diff --git a/src/components/code-snippet/config.ts b/src/components/code-snippet/config.ts
new file mode 100644
index 00000000..630078e9
--- /dev/null
+++ b/src/components/code-snippet/config.ts
@@ -0,0 +1,28 @@
+import { loader } from '@monaco-editor/react';
+
+import * as monaco from 'monaco-editor';
+import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
+import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
+import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
+import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
+import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
+
+self.MonacoEnvironment = {
+ getWorker(_, label) {
+ if (label === 'json') {
+ return new jsonWorker();
+ }
+ if (label === 'css' || label === 'scss' || label === 'less') {
+ return new cssWorker();
+ }
+ if (label === 'html' || label === 'handlebars' || label === 'razor') {
+ return new htmlWorker();
+ }
+ if (label === 'typescript' || label === 'javascript') {
+ return new tsWorker();
+ }
+ return new editorWorker();
+ },
+};
+
+loader.config({ monaco });
diff --git a/src/components/code-snippet/themes/dark.ts b/src/components/code-snippet/themes/dark.ts
new file mode 100644
index 00000000..ce832392
--- /dev/null
+++ b/src/components/code-snippet/themes/dark.ts
@@ -0,0 +1,12 @@
+import type { editor } from 'monaco-editor';
+
+export const DarkTheme: editor.IStandaloneThemeData = {
+ inherit: true,
+ base: 'vs-dark',
+ rules: [
+ { token: 'string.sql', foreground: 'CE9178' },
+ { token: 'predefined.sql', foreground: 'DCDCAB' },
+ ],
+ encodedTokensColors: [],
+ colors: {},
+};
diff --git a/src/components/code-snippet/themes/light.ts b/src/components/code-snippet/themes/light.ts
new file mode 100644
index 00000000..52a96ab4
--- /dev/null
+++ b/src/components/code-snippet/themes/light.ts
@@ -0,0 +1,9 @@
+import type { editor } from 'monaco-editor';
+
+export const LightTheme: editor.IStandaloneThemeData = {
+ inherit: true,
+ base: 'vs',
+ rules: [{ token: 'string.sql', foreground: 'A31515' }],
+ encodedTokensColors: [],
+ colors: {},
+};
diff --git a/src/context/storage-context/storage-provider.tsx b/src/context/storage-context/storage-provider.tsx
index 7d52563b..190a661b 100644
--- a/src/context/storage-context/storage-provider.tsx
+++ b/src/context/storage-context/storage-provider.tsx
@@ -411,7 +411,7 @@ export const StorageProvider: React.FC = ({
diagramId: string
): Promise => {
// Sort relationships alphabetically
- return await (
+ return (
await db.db_relationships
.where('diagramId')
.equals(diagramId)
diff --git a/src/dialogs/common/import-database/import-database.tsx b/src/dialogs/common/import-database/import-database.tsx
index 4fd45659..c42e8802 100644
--- a/src/dialogs/common/import-database/import-database.tsx
+++ b/src/dialogs/common/import-database/import-database.tsx
@@ -250,7 +250,7 @@ export const ImportDatabase: React.FC = ({
= ({
databaseClient,
}) ?? ''
}
- language={databaseClient ? 'bash' : 'sql'}
+ language={databaseClient ? 'shell' : 'sql'}
/>
) : (
)}
diff --git a/src/dialogs/create-diagram-dialog/create-diagram-dialog.tsx b/src/dialogs/create-diagram-dialog/create-diagram-dialog.tsx
index a45e7b08..2506937a 100644
--- a/src/dialogs/create-diagram-dialog/create-diagram-dialog.tsx
+++ b/src/dialogs/create-diagram-dialog/create-diagram-dialog.tsx
@@ -128,7 +128,7 @@ export const CreateDiagramDialog: React.FC = ({
}}
>
{step === CreateDiagramDialogStep.SELECT_DATABASE ? (
diff --git a/src/dialogs/export-sql-dialog/export-sql-dialog.tsx b/src/dialogs/export-sql-dialog/export-sql-dialog.tsx
index 8e2d87e6..01ad8598 100644
--- a/src/dialogs/export-sql-dialog/export-sql-dialog.tsx
+++ b/src/dialogs/export-sql-dialog/export-sql-dialog.tsx
@@ -132,7 +132,7 @@ export const ExportSQLDialog: React.FC = ({
}}
>
@@ -156,10 +156,7 @@ export const ExportSQLDialog: React.FC = ({
) : script.length === 0 ? (
renderError()
) : (
-
+
)}
diff --git a/src/dialogs/import-database-dialog/import-database-dialog.tsx b/src/dialogs/import-database-dialog/import-database-dialog.tsx
index b521b046..1a1bce72 100644
--- a/src/dialogs/import-database-dialog/import-database-dialog.tsx
+++ b/src/dialogs/import-database-dialog/import-database-dialog.tsx
@@ -323,7 +323,7 @@ export const ImportDatabaseDialog: React.FC = ({
}}
>
= ({
}}
>
diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts
index 06ea51b5..62c8e98f 100644
--- a/src/i18n/locales/de.ts
+++ b/src/i18n/locales/de.ts
@@ -94,6 +94,9 @@ export const de: LanguageTranslation = {
clear: 'Leeren',
show_more: 'Mehr anzeigen',
show_less: 'Weniger anzeigen',
+ // TODO: Translate
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'Schema:',
diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts
index d285ebd4..09e1c76a 100644
--- a/src/i18n/locales/en.ts
+++ b/src/i18n/locales/en.ts
@@ -93,6 +93,8 @@ export const en = {
clear: 'Clear',
show_more: 'Show More',
show_less: 'Show Less',
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'Schema:',
diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts
index e81cef38..d71877aa 100644
--- a/src/i18n/locales/es.ts
+++ b/src/i18n/locales/es.ts
@@ -85,6 +85,9 @@ export const es: LanguageTranslation = {
clear: 'Clear', // TODO: Translate
show_more: 'Show More', // TODO: Translate
show_less: 'Show Less', // TODO: Translate
+ // TODO: Translate
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'Schema:', // TODO: Translate
diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts
index 14f2dc7e..e3a3e427 100644
--- a/src/i18n/locales/fr.ts
+++ b/src/i18n/locales/fr.ts
@@ -85,6 +85,9 @@ export const fr: LanguageTranslation = {
clear: 'Effacer',
show_more: 'Afficher Plus',
show_less: 'Afficher Moins',
+ // TODO: Translate
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'Schéma:',
diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts
index 6faa04fc..aa4d611d 100644
--- a/src/i18n/locales/hi.ts
+++ b/src/i18n/locales/hi.ts
@@ -93,6 +93,9 @@ export const hi: LanguageTranslation = {
clear: 'साफ़ करें',
show_more: 'अधिक दिखाएँ',
show_less: 'कम दिखाएँ',
+ // TODO: Translate
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'स्कीमा:',
diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts
index c5019798..f59c9470 100644
--- a/src/i18n/locales/ja.ts
+++ b/src/i18n/locales/ja.ts
@@ -94,6 +94,9 @@ export const ja: LanguageTranslation = {
clear: 'クリア',
show_more: 'さらに表示',
show_less: '表示を減らす',
+ // TODO: Translate
+ copy_to_clipboard: 'Copy to Clipboard',
+ copied: 'Copied!',
side_panel: {
schema: 'スキーマ:',
diff --git a/src/index.css b/src/index.css
index 320629d1..cbbb43c8 100644
--- a/src/index.css
+++ b/src/index.css
@@ -12,6 +12,10 @@
@apply duration-100;
}
+ .monaco-editor .monaco-editor-overlaymessage {
+ @apply hidden !important;
+ }
+
.scrollable-flex > div {
@apply !flex;
}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index c340a6a5..5f317112 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,9 +1,8 @@
import { type ClassValue, clsx } from 'clsx';
import { customAlphabet } from 'nanoid';
-
+import { twMerge } from 'tailwind-merge';
const randomId = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 25);
-import { twMerge } from 'tailwind-merge';
const UUID_KEY = 'uuid';
export function cn(...inputs: ClassValue[]) {