diff --git a/package-lock.json b/package-lock.json index cf8b9c2a..6b83fae3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@ai-sdk/openai": "^0.0.51", "@dnd-kit/sortable": "^8.0.0", + "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-alert-dialog": "^1.1.1", "@radix-ui/react-avatar": "^1.1.0", @@ -44,10 +45,10 @@ "html-to-image": "^1.11.11", "i18next": "^23.14.0", "lucide-react": "^0.441.0", + "monaco-editor": "^0.52.0", "nanoid": "^5.0.7", "node-sql-parser": "^5.3.2", "react": "^18.3.1", - "react-code-blocks": "^0.1.6", "react-dom": "^18.3.1", "react-hotkeys-hook": "^4.5.0", "react-i18next": "^15.0.1", @@ -946,27 +947,6 @@ "react": ">=16.8.0" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "license": "MIT" - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -1650,6 +1630,32 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "license": "MIT", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3264,15 +3270,6 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, - "node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2" - } - }, "node_modules/@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -3323,18 +3320,6 @@ "@types/react": "*" } }, - "node_modules/@types/stylis": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", - "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", - "license": "MIT" - }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -4314,15 +4299,6 @@ "node": ">= 6" } }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001667", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", @@ -4359,36 +4335,6 @@ "node": ">=4" } }, - "node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -4967,16 +4913,6 @@ "dev": true, "license": "MIT" }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -5023,15 +4959,6 @@ "node": ">= 8" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, "node_modules/css-in-js-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", @@ -5047,17 +4974,6 @@ "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==", "license": "BSD" }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "license": "MIT", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "node_modules/css-tree": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", @@ -6318,19 +6234,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fault": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", - "license": "MIT", - "dependencies": { - "format": "^0.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6421,14 +6324,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -6798,42 +6693,6 @@ "node": ">= 0.4" } }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -6989,30 +6848,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -7165,16 +7000,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -7250,16 +7075,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -7765,20 +7580,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", - "license": "MIT", - "dependencies": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7902,6 +7703,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/monaco-editor": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz", + "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8230,24 +8037,6 @@ "node": ">=6" } }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "license": "MIT", - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8602,15 +8391,6 @@ "node": ">=6.0.0" } }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -8622,19 +8402,6 @@ "react-is": "^16.13.1" } }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8677,24 +8444,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-code-blocks": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/react-code-blocks/-/react-code-blocks-0.1.6.tgz", - "integrity": "sha512-ENNuxG07yO+OuX1ChRje3ieefPRz6yrIpHmebQlaFQgzcAHbUfVeTINpOpoI9bSRSObeYo/OdHsporeToZ7fcg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.4", - "react-syntax-highlighter": "^15.5.0", - "styled-components": "^6.1.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16" - } - }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -8892,22 +8641,6 @@ } } }, - "node_modules/react-syntax-highlighter": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", - "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "lowlight": "^1.17.0", - "prismjs": "^1.27.0", - "refractor": "^3.6.0" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -8992,30 +8725,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", - "license": "MIT", - "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -9343,12 +9052,6 @@ "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==", "license": "MIT" }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "license": "MIT" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9429,16 +9132,6 @@ "node": ">=0.10.0" } }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/sswr": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sswr/-/sswr-2.1.0.tgz", @@ -9496,6 +9189,12 @@ "stacktrace-gps": "^3.0.4" } }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -9713,92 +9412,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/styled-components": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz", - "integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==", - "license": "MIT", - "dependencies": { - "@emotion/is-prop-valid": "1.2.2", - "@emotion/unitless": "0.8.1", - "@types/stylis": "4.2.5", - "css-to-react-native": "3.2.0", - "csstype": "3.1.3", - "postcss": "8.4.38", - "shallowequal": "1.1.0", - "stylis": "4.3.2", - "tslib": "2.6.2" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0" - } - }, - "node_modules/styled-components/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/styled-components/node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/styled-components/node_modules/stylis": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", - "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", - "license": "MIT" - }, - "node_modules/styled-components/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "license": "0BSD" - }, "node_modules/stylis": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", @@ -10807,15 +10420,6 @@ "dev": true, "license": "ISC" }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 8bfb91ff..7400760f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "@ai-sdk/openai": "^0.0.51", "@dnd-kit/sortable": "^8.0.0", + "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-alert-dialog": "^1.1.1", "@radix-ui/react-avatar": "^1.1.0", @@ -48,10 +49,10 @@ "html-to-image": "^1.11.11", "i18next": "^23.14.0", "lucide-react": "^0.441.0", + "monaco-editor": "^0.52.0", "nanoid": "^5.0.7", "node-sql-parser": "^5.3.2", "react": "^18.3.1", - "react-code-blocks": "^0.1.6", "react-dom": "^18.3.1", "react-hotkeys-hook": "^4.5.0", "react-i18next": "^15.0.1", diff --git a/src/components/code-snippet/code-editor.ts b/src/components/code-snippet/code-editor.ts new file mode 100644 index 00000000..8c5b1570 --- /dev/null +++ b/src/components/code-snippet/code-editor.ts @@ -0,0 +1,2 @@ +import './config.ts'; +export { Editor } from '@monaco-editor/react'; diff --git a/src/components/code-snippet/code-snippet.tsx b/src/components/code-snippet/code-snippet.tsx index 75376f0b..db737653 100644 --- a/src/components/code-snippet/code-snippet.tsx +++ b/src/components/code-snippet/code-snippet.tsx @@ -1,46 +1,127 @@ import { cn } from '@/lib/utils'; -import React, { Suspense } from 'react'; -import type { CopyBlockProps } from 'react-code-blocks/dist/components/CopyBlock'; +import React, { lazy, Suspense, useCallback, useEffect } from 'react'; import { Spinner } from '../spinner/spinner'; +import { useTheme } from '@/hooks/use-theme'; +import { useMonaco } from '@monaco-editor/react'; +import { Button } from '../button/button'; +import { Copy, CopyCheck } from 'lucide-react'; +import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip/tooltip'; +import { useTranslation } from 'react-i18next'; +import { DarkTheme } from './themes/dark'; +import { LightTheme } from './themes/light'; export interface CodeSnippetProps { className?: string; - codeProps?: CopyBlockProps; code: string; - language?: 'sql' | 'bash'; + language?: 'sql' | 'shell'; loading?: boolean; } -const CopyBlock = React.lazy(() => - import('react-code-blocks').then((module) => ({ - default: (props: CopyBlockProps) => ( - - ), +export const Editor = lazy(() => + import('./code-editor').then((module) => ({ + default: module.Editor, })) ); export const CodeSnippet: React.FC = 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[]) {