From a539ad6d19c02763d2ff276f50c603d8a41395a3 Mon Sep 17 00:00:00 2001 From: _Kerman Date: Tue, 14 Nov 2023 14:03:17 +0800 Subject: [PATCH] feat: add monaco-editor --- packages/monaco-editor/package.json | 28 ++++++++++ packages/monaco-editor/src/component.r.ts | 68 +++++++++++++++++++++++ packages/monaco-editor/src/index.ts | 7 +++ packages/monaco-editor/src/plugin.ts | 4 ++ packages/monaco-editor/tsconfig.json | 7 +++ packages/northstar/package.json | 2 + packages/northstar/src/app.r.ts | 8 +-- packages/northstar/vite.config.ts | 4 ++ pnpm-lock.yaml | 36 ++++++++++++ 9 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 packages/monaco-editor/package.json create mode 100644 packages/monaco-editor/src/component.r.ts create mode 100644 packages/monaco-editor/src/index.ts create mode 100644 packages/monaco-editor/src/plugin.ts create mode 100644 packages/monaco-editor/tsconfig.json diff --git a/packages/monaco-editor/package.json b/packages/monaco-editor/package.json new file mode 100644 index 0000000..d423aa4 --- /dev/null +++ b/packages/monaco-editor/package.json @@ -0,0 +1,28 @@ +{ + "name": "@quasi-dev/monaco-editor", + "version": "0.0.1", + "type": "module", + "license": "MIT", + "description": "Monaco Editor for Quasi", + "repository": "https://github.com/Quasi-Studio/quasi", + "scripts": { + "check": "tsc --noEmit" + }, + "devDependencies": { + "@refina/tsconfig": "link:..\\..\\..\\refina\\packages\\tsconfig", + "typescript": "^5.0.2", + "vite": "^4.4.8" + }, + "main": "./src/index.ts", + "types": "./src/index.ts", + "files": [ + "src" + ], + "exports": { + ".": "./src/index.ts" + }, + "dependencies": { + "monaco-editor": "^0.44.0", + "refina": "link:..\\..\\..\\refina\\packages\\core" + } +} diff --git a/packages/monaco-editor/src/component.r.ts b/packages/monaco-editor/src/component.r.ts new file mode 100644 index 0000000..e6fe1fe --- /dev/null +++ b/packages/monaco-editor/src/component.r.ts @@ -0,0 +1,68 @@ +import * as monaco from "monaco-editor"; +import { ComponentContext, D, HTMLElementComponent, TriggerComponent, getD, ref } from "refina"; +import Monaco from "./plugin"; + +@Monaco.triggerComponent("monacoEditor") +export class MonacoEditor extends TriggerComponent { + containerRef = ref>(); + // overflowRef = ref>(); + editor: monaco.editor.IStandaloneCodeEditor | null = null; + main( + _: ComponentContext, + initialValue: string, + language: string, + options: Omit< + monaco.editor.IStandaloneEditorConstructionOptions, + "value" | "language" | "overflowWidgetsDomNode" + > = {}, + ): void { + _.$css`height:100%`; + _.$ref(this.containerRef) && _._div(); + + // _.portal(_ => { + // _.$ref(this.overflowRef) && _._div(); + // }); + + if (_.$updating) { + _.$app.pushHook("afterModifyDOM", () => { + setTimeout(() => { + if (!this.editor) { + const node = this.containerRef.current!.node; + + this.editor = monaco.editor.create(node, { + ...options, + value: initialValue, + language, + // overflowWidgetsDomNode: this.overflowRef.current!.node, + }); + + this.editor.getModel()?.onDidChangeContent(ev => { + const newValue = this.editor!.getValue(); + this.$fire(newValue); + }); + + const parent = node.parentElement!; + + window.addEventListener("resize", () => { + // make editor as small as possible + this.editor!.layout({ width: 0, height: 0 }); + + // wait for next frame to ensure last layout finished + window.requestAnimationFrame(() => { + // get the parent dimensions and re-layout the editor + const rect = parent.getBoundingClientRect(); + this.editor!.layout({ width: rect.width, height: rect.height }); + }); + }); + } + }); + }); + } + } +} + +declare module "refina" { + interface TriggerComponents { + monacoEditor: MonacoEditor; + } +} diff --git a/packages/monaco-editor/src/index.ts b/packages/monaco-editor/src/index.ts new file mode 100644 index 0000000..2a2649d --- /dev/null +++ b/packages/monaco-editor/src/index.ts @@ -0,0 +1,7 @@ +import * as monaco from "monaco-editor"; +export { monaco }; + +import Monaco from "./plugin"; +export default Monaco; + +export * from "./component.r"; diff --git a/packages/monaco-editor/src/plugin.ts b/packages/monaco-editor/src/plugin.ts new file mode 100644 index 0000000..c20a89c --- /dev/null +++ b/packages/monaco-editor/src/plugin.ts @@ -0,0 +1,4 @@ +import { Plugin } from "refina"; + +const Monaco = new Plugin("monaco-editor"); +export default Monaco; diff --git a/packages/monaco-editor/tsconfig.json b/packages/monaco-editor/tsconfig.json new file mode 100644 index 0000000..55a854a --- /dev/null +++ b/packages/monaco-editor/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@refina/tsconfig", + "include": ["src"], + "compilerOptions": { + "lib": ["ESNext", "DOM"] + } +} diff --git a/packages/northstar/package.json b/packages/northstar/package.json index d8e8624..1d1f4d9 100644 --- a/packages/northstar/package.json +++ b/packages/northstar/package.json @@ -19,6 +19,7 @@ "tailwindcss": "^3.3.3", "typescript": "^5.1.6", "vite": "^4.4.8", + "vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-refina": "link:..\\..\\..\\refina\\packages\\vite-plugin", "vite-plugin-static-copy": "^0.17.0" }, @@ -26,6 +27,7 @@ "@quasi-dev/block-data": "workspace:^", "@quasi-dev/browser-tailwind": "workspace:^", "@quasi-dev/compiler": "workspace:^", + "@quasi-dev/monaco-editor": "workspace:^", "@quasi-dev/runtime": "workspace:^", "@quasi-dev/visual-flow": "workspace:^", "@refina/basic-components": "link:..\\..\\..\\refina\\packages\\basic-components", diff --git a/packages/northstar/src/app.r.ts b/packages/northstar/src/app.r.ts index e2b7b22..0841acb 100644 --- a/packages/northstar/src/app.r.ts +++ b/packages/northstar/src/app.r.ts @@ -1,18 +1,18 @@ +import Monaco from "@quasi-dev/monaco-editor"; import Vf from "@quasi-dev/visual-flow"; import Basics from "@refina/basic-components"; import FluentUI from "@refina/fluentui"; import { app } from "refina"; import { currentGraph } from "./store"; +import { duplicateBlocks, hasBlocksToDuplicate, hasBlocksToRemove, removeBlocks } from "./utils"; import blocksView from "./views/blocks.r"; +import previewView from "./views/preview.r"; import propertiesView from "./views/properties.r"; import toolbarView, { graphElRef, previewMode } from "./views/toolbar.r"; -import { isComponentBlock } from "./blocks/component/block"; -import { duplicateBlocks, hasBlocksToDuplicate, hasBlocksToRemove, removeBlocks } from "./utils"; -import previewView from "./views/preview.r"; document.body.spellcheck = false; -app.use(FluentUI).use(Vf).use(Basics)(_ => { +app.use(FluentUI).use(Vf).use(Basics).use(Monaco)(_ => { _.$rootCls`fixed top-0 left-0 right-0 bottom-0`; _.documentTitle("Quasi Studio"); diff --git a/packages/northstar/vite.config.ts b/packages/northstar/vite.config.ts index 557d532..df323eb 100644 --- a/packages/northstar/vite.config.ts +++ b/packages/northstar/vite.config.ts @@ -7,6 +7,9 @@ import { } from "vite"; import Refina from "vite-plugin-refina"; import { viteStaticCopy } from "vite-plugin-static-copy"; +import MonacoEditorPluginObj from "vite-plugin-monaco-editor"; +const MonacoEditorPlugin = (MonacoEditorPluginObj as any) + .default as typeof MonacoEditorPluginObj; // Base on https://github.com/vitejs/vite/issues/6757#issuecomment-1584823965 function TsBundleUrlPlugin(): PluginOption { @@ -70,6 +73,7 @@ function TsBundleUrlPlugin(): PluginOption { export default defineConfig({ plugins: [ Refina(), + MonacoEditorPlugin({}), TsBundleUrlPlugin(), viteStaticCopy({ targets: [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f8200c..36fae19 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,6 +69,25 @@ importers: specifier: ^5.1.6 version: 5.2.2 + packages/monaco-editor: + dependencies: + monaco-editor: + specifier: ^0.44.0 + version: 0.44.0 + refina: + specifier: link:..\..\..\refina\packages\core + version: link:../../../refina/packages/core + devDependencies: + '@refina/tsconfig': + specifier: link:..\..\..\refina\packages\tsconfig + version: link:../../../refina/packages/tsconfig + typescript: + specifier: ^5.0.2 + version: 5.2.2 + vite: + specifier: ^4.4.8 + version: 4.4.11 + packages/northstar: dependencies: '@quasi-dev/block-data': @@ -80,6 +99,9 @@ importers: '@quasi-dev/compiler': specifier: workspace:^ version: link:../compiler + '@quasi-dev/monaco-editor': + specifier: workspace:^ + version: link:../monaco-editor '@quasi-dev/runtime': specifier: workspace:^ version: link:../runtime @@ -129,6 +151,9 @@ importers: vite: specifier: ^4.4.8 version: 4.4.11 + vite-plugin-monaco-editor: + specifier: ^1.1.0 + version: 1.1.0(monaco-editor@0.44.0) vite-plugin-refina: specifier: link:..\..\..\refina\packages\vite-plugin version: link:../../../refina/packages/vite-plugin @@ -1294,6 +1319,9 @@ packages: resolution: {integrity: sha512-uxxD4PdbIitXFlcNbO6kpRuxssfN+rJDfr8Pk2/eOx1dFz+LcaYDfbfeq7UxKuhsOVeN1tj996wEY3yJYwhnaQ==} dev: false + /monaco-editor@0.44.0: + resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==} + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -1739,6 +1767,14 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /vite-plugin-monaco-editor@1.1.0(monaco-editor@0.44.0): + resolution: {integrity: sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==} + peerDependencies: + monaco-editor: '>=0.33.0' + dependencies: + monaco-editor: 0.44.0 + dev: true + /vite-plugin-static-copy@0.17.0(vite@4.4.11): resolution: {integrity: sha512-2HpNbHfDt8SDy393AGXh9llHkc8FJMQkI8s3T5WsH3SWLMO+f5cFIyPErl4yGKU9Uh3Vaqsd4lHZYTf042fQ2A==} engines: {node: ^14.18.0 || >=16.0.0}