fix(lit-components): fix rendering and interaction issues in force-graph, html-table, and draggable-dom
Build and Deploy / build-and-deploy (push) Has been cancelled
Build and Deploy / build-and-deploy (push) Has been cancelled
- lit-force-graph: Refactored for instance reuse, better lifecycle management, and added dynamic imports for AR/VR modes. - lit-html-table: Improved visual design, readability of headers, and fixed reactivity in editable mode. - lit-draggable-dom: Fixed clipping issues by switching to relative/absolute positioning and resolved a panning speed bug caused by CSS variable inheritance.
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
import { LitElement } from "lit";
|
||||
import * as monaco from "monaco-editor";
|
||||
export declare class CodeEditor extends LitElement {
|
||||
private container;
|
||||
editor?: monaco.editor.IStandaloneCodeEditor;
|
||||
readOnly?: boolean;
|
||||
theme?: string;
|
||||
language?: string;
|
||||
code?: string;
|
||||
static styles: import("lit").CSSResultGroup;
|
||||
render(): import("lit").TemplateResult<1>;
|
||||
private getFile;
|
||||
private getCode;
|
||||
private getLang;
|
||||
private getTheme;
|
||||
private isDark;
|
||||
setValue(value: string): void;
|
||||
getValue(): string;
|
||||
setReadOnly(value: boolean): void;
|
||||
setOptions(value: monaco.editor.IStandaloneEditorConstructionOptions): void;
|
||||
firstUpdated(): void;
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"code-editor": CodeEditor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import "./code-editor";
|
||||
|
||||
describe("Lit Code Editor Component", () => {
|
||||
test("registers code-editor custom element successfully", () => {
|
||||
expect(customElements.get("code-editor")).toBeDefined();
|
||||
});
|
||||
|
||||
test("mounts code-editor successfully", async () => {
|
||||
document.body.innerHTML = '<code-editor code="console.log(1);"></code-editor>';
|
||||
await window.happyDOM.whenAsyncComplete();
|
||||
|
||||
const element = document.body.querySelector("code-editor");
|
||||
expect(element).toBeDefined();
|
||||
expect(element?.getAttribute("code")).toBe("console.log(1);");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { createRef, Ref, ref } from "lit/directives/ref.js";
|
||||
|
||||
// -- Monaco Editor Imports --
|
||||
import * as monaco from "monaco-editor";
|
||||
import styles from "monaco-editor/min/vs/editor/editor.main.css";
|
||||
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";
|
||||
|
||||
// @ts-ignore
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_: any, label: string) {
|
||||
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();
|
||||
},
|
||||
};
|
||||
|
||||
@customElement("code-editor")
|
||||
export class CodeEditor extends LitElement {
|
||||
private container: Ref<HTMLElement> = createRef();
|
||||
editor?: monaco.editor.IStandaloneCodeEditor;
|
||||
@property({ type: Boolean, attribute: "readonly" }) readOnly?: boolean;
|
||||
@property() theme?: string;
|
||||
@property() language?: string;
|
||||
@property() code?: string;
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--editor-width: 100%;
|
||||
--editor-height: 100vh;
|
||||
}
|
||||
main {
|
||||
width: var(--editor-width);
|
||||
height: var(--editor-height);
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<style>
|
||||
${styles}
|
||||
</style>
|
||||
<main ${ref(this.container)}></main>
|
||||
`;
|
||||
}
|
||||
|
||||
private getFile() {
|
||||
if (this.children.length > 0) return this.children[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
private getCode() {
|
||||
if (this.code) return this.code;
|
||||
const file = this.getFile();
|
||||
if (!file) return;
|
||||
return file.innerHTML.trim();
|
||||
}
|
||||
|
||||
private getLang() {
|
||||
if (this.language) return this.language;
|
||||
const file = this.getFile();
|
||||
if (!file) return;
|
||||
const type = file.getAttribute("type")!;
|
||||
return type.split("/").pop()!;
|
||||
}
|
||||
|
||||
private getTheme() {
|
||||
if (this.theme) return this.theme;
|
||||
if (this.isDark()) return "vs-dark";
|
||||
return "vs-light";
|
||||
}
|
||||
|
||||
private isDark() {
|
||||
return (
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
);
|
||||
}
|
||||
|
||||
setValue(value: string) {
|
||||
this.editor!.setValue(value);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
const value = this.editor!.getValue();
|
||||
return value;
|
||||
}
|
||||
|
||||
setReadOnly(value: boolean) {
|
||||
this.readOnly = value;
|
||||
this.setOptions({ readOnly: value });
|
||||
}
|
||||
|
||||
setOptions(value: monaco.editor.IStandaloneEditorConstructionOptions) {
|
||||
this.editor!.updateOptions(value);
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.editor = monaco.editor.create(this.container.value!, {
|
||||
value: this.getCode(),
|
||||
language: this.getLang(),
|
||||
theme: this.getTheme(),
|
||||
automaticLayout: true,
|
||||
readOnly: this.readOnly ?? false,
|
||||
});
|
||||
this.editor.getModel()!.onDidChangeContent(() => {
|
||||
this.dispatchEvent(new CustomEvent("change", { detail: {} }));
|
||||
});
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
.addEventListener("change", () => {
|
||||
monaco.editor.setTheme(this.getTheme());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"code-editor": CodeEditor;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user