Replace CodeEditor with MonacoEditor (#2013)

Co-authored-by: Boy132 <mail@boy132.de>
This commit is contained in:
Charles
2025-12-19 18:31:55 -05:00
committed by GitHub
parent 5a47948a93
commit 2ab4c81e2a
10 changed files with 712 additions and 40 deletions

View File

@@ -0,0 +1,5 @@
.-rotate-180,.-translate-x-5,.-translate-y-12,.fme-placeholder,.rotate-180,.scale-100,.scale-95,.transform,.translate-x-0,.translate-x-12,.translate-x-5,.translate-x-full,.translate-y-12{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fme-full-screen-btn-icon,.fme-placeholder,.group\/button:hover .group-hover\/button\:text-gray-500{color:rgba(var(--gray-500),var(--tw-text-opacity));--tw-text-opacity:1}.fme-full-screen-btn:focus,input:checked+.\[input\:checked\+\&\]\:ring-0{--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.fme-wrapper{display:flex;width:100%;flex-direction:column}.fme-full-screen{position:fixed;top:64px;left:300px;z-index:1;width:100vw;height:100vw;overflow:hidden;border-top-width:.5px;border-color:#65656d;--tw-bg-opacity:1;background-color:rgb(24 24 27 / var(--tw-bg-opacity))}.fme-control-section{display:flex;justify-content:space-between;padding:.5rem}.fme-full-screen-btn{border-radius:.25rem;padding:.25rem .5rem}.fme-full-screen-btn:focus{--tw-bg-opacity:1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}.fme-full-screen-btn-icon{height:1rem;width:1rem}.fme-container{flex-direction:column;justify-content:flex-start;--tw-bg-opacity:1}.fme-container,.fme-loader{display:flex;height:100%;width:100%}.fme-element-wrapper{position:relative;z-index:10;height:100%;width:100%;border-radius:.25rem}.fme-element{height:100%;width:100%;font-size:1.125rem;line-height:1.75rem}.fme-placeholder{position:absolute;left:0;top:0;z-index:50;margin-left:3.5rem;margin-top:.125rem;width:100%;--tw-translate-x:-0.125rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875rem;line-height:1.25rem}.grow{flex-grow:1}.truncate,.whitespace-nowrap{white-space:nowrap}.\!bg-gray-50,.\!bg-gray-700{--tw-bg-opacity:1!important}.pb-6,.py-6{padding-bottom:1.5rem}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus-visible\:ring-1:focus-visible,.focus-visible\:ring-2:focus-visible{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::-moz-placeholder,.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::placeholder{-webkit-text-fill-color:rgba(var(--gray-400),1)}.group\/item:focus-visible .group-focus-visible\/item\:underline,.group\/link:focus-visible .group-focus-visible\/link\:underline{text-decoration-line:underline}.dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled:is(
.dark *
)::-moz-placeholder,.dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled:is(
.dark *
)::placeholder{-webkit-text-fill-color:rgba(var(--gray-500),1)}.group:focus-visible .dark\:group-focus-visible\:text-gray-200:is(.dark *),.group:hover .dark\:group-hover\:text-gray-200:is(.dark *){--tw-text-opacity:1;color:rgba(var(--gray-200),var(--tw-text-opacity))}:checked+*>.\[\:checked\+\*\>\&\]\:text-white,input:checked+.\[input\:checked\+\&\]\:text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity))}input:checked+.\[input\:checked\+\&\]\:bg-custom-600{--tw-bg-opacity:1;background-color:rgba(var(--c-600),var(--tw-bg-opacity))}input:checked+.\[input\:checked\+\&\]\:hover\:bg-custom-500:hover,input:checked+.dark\:\[input\:checked\+\&\]\:bg-custom-500:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--c-500),var(--tw-bg-opacity))}input:checked+.dark\:\[input\:checked\+\&\]\:hover\:bg-custom-400:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgba(var(--c-400),var(--tw-bg-opacity))}input:checked:focus-visible+.\[input\:checked\:focus-visible\+\&\]\:ring-custom-500\/50{--tw-ring-color:rgba(var(--c-500), 0.5)}input:checked:focus-visible+.dark\:\[input\:checked\:focus-visible\+\&\]\:ring-custom-400\/50:is(.dark *){--tw-ring-color:rgba(var(--c-400), 0.5)}input:focus-visible+.\[input\:focus-visible\+\&\]\:z-10{z-index:10}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px+var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-gray-950\/10{--tw-ring-color:rgba(var(--gray-950), 0.1)}input:focus-visible+.dark\:\[input\:focus-visible\+\&\]\:ring-white\/20:is(.dark *){--tw-ring-color:#fff3}

View File

@@ -0,0 +1,144 @@
@script
<script>
$wire.on('setContent', ({ content }) => {
document.getElementById('{{ $getId() }}').editor.getModel().setValue(content);
});
$wire.on('setLanguage', ({ lang }) => {
monaco.editor.setModelLanguage(document.getElementById('{{ $getId() }}').editor.getModel(), lang);
});
</script>
@endscript
@vite(['resources/css/monaco-editor.css'])
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field" class="overflow-hidden">
<div x-data="{
monacoContent: $wire.$entangle('{{ $getStatePath() }}'),
fullScreenModeEnabled: false,
monacoLanguage: '{{ $getLanguage() }}',
monacoLoader: {{ (int) $getShowLoader() }},
monacoFontSize: '{{ $getFontSize() }}',
lineNumbersMinChars: {{ $getLineNumbersMinChars() }},
automaticLayout: {{ (int) $getAutomaticLayout() }},
monacoId: '{{ $getId() }}',
toggleFullScreenMode() {
this.fullScreenModeEnabled = !this.fullScreenModeEnabled;
this.fullScreenModeEnabled ? document.body.classList.add('overflow-hidden')
: document.body.classList.remove('overflow-hidden');
$el.style.width = this.fullScreenModeEnabled ? '100vw'
: $el.parentElement.clientWidth + 'px';
},
monacoEditor(editor){
editor.onDidChangeModelContent((e) => {
this.monacoContent = editor.getValue();
});
},
monacoEditorFocus(){
document.getElementById(this.monacoId).dispatchEvent(
new CustomEvent('monaco-editor-focused', { monacoId: this.monacoId })
);
},
monacoEditorAddLoaderScriptToHead() {
script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/loader.min.js';
document.head.appendChild(script);
},
}" x-init="
$el.style.height = '650px';
$watch('fullScreenModeEnabled', value => {
if (value) {
$el.style.height = '100vh';
} else {
$el.style.height = '650px';
}
});
if(typeof _amdLoaderGlobal == 'undefined'){
monacoEditorAddLoaderScriptToHead();
}
monacoLoaderInterval = setInterval(() => {
if(typeof _amdLoaderGlobal !== 'undefined'){
// Based on https://jsfiddle.net/developit/bwgkr6uq/ which works without needing service worker. Provided by loader.min.js.
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs' }});
let proxy = URL.createObjectURL(new Blob([` self.MonacoEnvironment = { baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min' }; importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.49.0/min/vs/base/worker/workerMain.min.js');`], { type: 'text/javascript' }));
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
require(['vs/editor/editor.main'], () => {
monaco.editor.defineTheme('custom', {{ $editorTheme() }});
document.getElementById(monacoId).editor = monaco.editor.create($refs.monacoEditorElement, {
value: monacoContent,
theme: localStorage.getItem('theme') === 'light' ? 'iPlastic' : 'custom',
fontSize: monacoFontSize,
lineNumbersMinChars: lineNumbersMinChars,
automaticLayout: automaticLayout,
language: monacoLanguage,
scrollbar: {
horizontal: 'auto',
horizontalScrollbarSize: 15,
vertical: 'auto',
verticalScrollbarSize: 15
},
wordWrap: 'on',
wrappingIndent: 'same',
});
$el.style.zIndex = '1';
monacoEditor(document.getElementById(monacoId).editor);
});
clearInterval(monacoLoaderInterval);
monacoLoader = false;
}
}, 5); " :id="monacoId"
class="fme-wrapper"
:class="{ 'fme-full-screen': fullScreenModeEnabled }" x-cloak>
{{-- <div class="fme-control-section">--}}
{{-- <div class="flex items-center ml-auto">--}}
{{-- @if($getShowFullScreenToggle())--}}
{{-- <button type="button" aria-label="{{ __("full_screen_btn_label") }}" class="fme-full-screen-btn"--}}
{{-- @click="toggleFullScreenMode()">--}}
{{-- <svg class="fme-full-screen-btn-icon" x-show="!fullScreenModeEnabled"--}}
{{-- xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"--}}
{{-- stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">--}}
{{-- <path stroke="none" d="M0 0h24v24H0z" fill="none" />--}}
{{-- <path d="M16 4l4 0l0 4" />--}}
{{-- <path d="M14 10l6 -6" />--}}
{{-- <path d="M8 20l-4 0l0 -4" />--}}
{{-- <path d="M4 20l6 -6" />--}}
{{-- <path d="M16 20l4 0l0 -4" />--}}
{{-- <path d="M14 14l6 6" />--}}
{{-- <path d="M8 4l-4 0l0 4" />--}}
{{-- <path d="M4 4l6 6" />--}}
{{-- </svg>--}}
{{-- <svg class="fme-full-screen-btn-icon" x-show="fullScreenModeEnabled"--}}
{{-- xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"--}}
{{-- stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">--}}
{{-- <path stroke="none" d="M0 0h24v24H0z" fill="none" />--}}
{{-- <path d="M5 9l4 0l0 -4" />--}}
{{-- <path d="M3 3l6 6" />--}}
{{-- <path d="M5 15l4 0l0 4" />--}}
{{-- <path d="M3 21l6 -6" />--}}
{{-- <path d="M19 9l-4 0l0 -4" />--}}
{{-- <path d="M15 9l6 -6" />--}}
{{-- <path d="M19 15l-4 0l0 4" />--}}
{{-- <path d="M15 15l6 6" />--}}
{{-- </svg>--}}
{{-- </button>--}}
{{-- @endif--}}
{{-- </div>--}}
{{-- </div>--}}
<div class="fme-container">
<div x-show="!monacoLoader" class="fme-element-wrapper">
<div x-ref="monacoEditorElement" class="fme-element" wire:ignore style="height: 100%"></div>
</div>
</div>
</div>
</x-dynamic-component>