b9e42c3ef4
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.
131 lines
3.1 KiB
TypeScript
131 lines
3.1 KiB
TypeScript
import { html, css, LitElement } from "lit";
|
|
import { customElement, property } from "lit/decorators.js";
|
|
import { live } from "../utils/live";
|
|
|
|
import "./rich-toolbar";
|
|
import "./rich-viewer";
|
|
|
|
@customElement("rich-text")
|
|
export class RichText extends LitElement {
|
|
static styles = css`
|
|
:host {
|
|
--rich-color: black;
|
|
--rich-background: white;
|
|
--rich-action-active-color: red;
|
|
--icon-size: 24px;
|
|
--rich-padding: 8px;
|
|
}
|
|
main {
|
|
height: 100%;
|
|
width: 100%;
|
|
display: grid;
|
|
grid-template-rows: 1fr auto;
|
|
grid-template-columns: 1fr;
|
|
grid-template-areas:
|
|
"viewer"
|
|
"toolbar";
|
|
}
|
|
|
|
rich-toolbar {
|
|
grid-area: toolbar;
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
background-color: var(--rich-background);
|
|
color: var(--rich-color);
|
|
border-top: 1px solid var(--rich-color);
|
|
}
|
|
|
|
rich-viewer {
|
|
grid-area: viewer;
|
|
flex: 1;
|
|
width: 100%;
|
|
overflow-y: auto;
|
|
background-color: var(--rich-background);
|
|
color: var(--rich-color);
|
|
}
|
|
|
|
/* @media (hover: hover) and (pointer: fine) {
|
|
main {
|
|
grid-template-rows: auto 1fr;
|
|
grid-template-areas:
|
|
"toolbar"
|
|
"viewer";
|
|
}
|
|
rich-toolbar {
|
|
border-top: none;
|
|
border-bottom: 1px solid var(--rich-color);
|
|
}
|
|
} */
|
|
main {
|
|
grid-template-rows: auto 1fr;
|
|
grid-template-areas:
|
|
"toolbar"
|
|
"viewer";
|
|
}
|
|
rich-toolbar {
|
|
border-top: none;
|
|
border-bottom: 1px solid var(--rich-color);
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:host {
|
|
--rich-background: black;
|
|
--rich-color: white;
|
|
}
|
|
}
|
|
`;
|
|
|
|
@live selection: Selection | null = null;
|
|
@property({ type: Boolean }) readonly = false;
|
|
@property({ type: Object, hasChanged: () => true }) node: Element =
|
|
document.createElement("div");
|
|
|
|
render() {
|
|
const { selection, readonly, node } = this;
|
|
return html`<main>
|
|
<rich-toolbar
|
|
.selection=${selection}
|
|
.node=${node}
|
|
@set-content=${(e: Event) => {
|
|
const event = e as CustomEvent<string>;
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(event.detail, "text/html");
|
|
const root = doc.querySelector("body");
|
|
this.node.innerHTML = root?.innerHTML ?? "";
|
|
this.requestUpdate();
|
|
}}
|
|
></rich-toolbar>
|
|
<rich-viewer
|
|
?readonly=${readonly}
|
|
@selection=${(e: Event) => {
|
|
const event = e as CustomEvent;
|
|
this.selection = event.detail;
|
|
}}
|
|
.node=${node}
|
|
>
|
|
</rich-viewer>
|
|
</main>`;
|
|
}
|
|
|
|
firstUpdated() {
|
|
const children = this.children;
|
|
if (children.length > 0) {
|
|
// Check if <template> is the first child
|
|
const template = children[0];
|
|
if (template.tagName === "TEMPLATE") {
|
|
const content = template.innerHTML.trim();
|
|
if (content.length > 0) {
|
|
this.node.innerHTML = content;
|
|
this.requestUpdate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"rich-text": RichText;
|
|
}
|
|
}
|