Make sure editors are scrollable in fullscreen mode

This commit is contained in:
Martin Kleinschrodt 2022-07-18 10:02:08 +02:00
parent b64ae60886
commit 26b72d7d4f
2 changed files with 175 additions and 149 deletions

View File

@ -11,6 +11,7 @@ import { $l } from "@padloc/locale/src/translate";
import "./textarea"; import "./textarea";
import { Textarea } from "./textarea"; import { Textarea } from "./textarea";
import "./select"; import "./select";
import { customScrollbar } from "../styles/mixins";
@customElement("pl-rich-input") @customElement("pl-rich-input")
export class RichInput extends LitElement { export class RichInput extends LitElement {
@ -19,6 +20,10 @@ export class RichInput extends LitElement {
} }
set value(md: string) { set value(md: string) {
// Disallow updating the value while we're editing
if (this._editor.isFocused || this._markdownInput?.focused) {
return;
}
const html = markdownToHtml(md).replace(/\n/g, ""); const html = markdownToHtml(md).replace(/\n/g, "");
console.log(md, html); console.log(md, html);
this._editor.commands.clearContent(); this._editor.commands.clearContent();
@ -59,7 +64,15 @@ export class RichInput extends LitElement {
} }
focus() { focus() {
this._editor.commands.focus(); if (this.mode === "wysiwyg") {
if (!this._editor.isFocused) {
this._editor.commands.focus();
}
} else {
if (!this._markdownInput.focused) {
this._markdownInput.focus();
}
}
} }
private async _toggleMarkdown() { private async _toggleMarkdown() {
@ -83,191 +96,202 @@ export class RichInput extends LitElement {
content, content,
css` css`
:host { :host {
display: block;
position: relative; position: relative;
cursor: text; cursor: text;
border: solid 1px var(--color-shade-1); border: solid 1px var(--color-shade-1);
border-radius: 0.5em; border-radius: 0.5em;
display: flex;
flex-direction: column;
} }
:host(.focused) { :host(.focused) {
border-color: var(--color-highlight); border-color: var(--color-highlight);
} }
.container {
min-height: 0;
overflow-y: auto;
}
${customScrollbar(".container")}
pl-textarea { pl-textarea {
border: none; border: none;
--input-padding: calc(2 * var(--spacing)); --input-padding: calc(2 * var(--spacing));
font-family: var(--font-family-mono); font-family: var(--font-family-mono);
font-size: 0.9em; font-size: 0.9em;
line-height: 1.3em; line-height: 1.3em;
min-height: 0;
} }
`, `,
]; ];
render() { render() {
return html` return html`
<div class="small padded double-spacing horizontal layout border-bottom"> <div class="vertical layout fit-vertically">
<div class="half-spacing wrapping horizontal layout stretch" ?disabled=${this.mode !== "wysiwyg"}> <div class="small padded double-spacing horizontal layout border-bottom">
<pl-button class="transparent slim" title="${$l("Text Mode")}"> <div class="half-spacing wrapping horizontal layout stretch" ?disabled=${this.mode !== "wysiwyg"}>
${this._editor?.isActive("heading", { level: 1 }) <pl-button class="transparent slim" title="${$l("Text Mode")}">
? html` <pl-icon icon="heading-1"></pl-icon> ` ${this._editor?.isActive("heading", { level: 1 })
: this._editor?.isActive("heading", { level: 2 }) ? html` <pl-icon icon="heading-1"></pl-icon> `
? html` <pl-icon icon="heading-2"></pl-icon> ` : this._editor?.isActive("heading", { level: 2 })
: this._editor?.isActive("heading", { level: 3 }) ? html` <pl-icon icon="heading-2"></pl-icon> `
? html` <pl-icon icon="heading-3"></pl-icon> ` : this._editor?.isActive("heading", { level: 3 })
: html` <pl-icon icon="text"></pl-icon> `} ? html` <pl-icon icon="heading-3"></pl-icon> `
: html` <pl-icon icon="text"></pl-icon> `}
<pl-icon class="small" icon="dropdown"></pl-icon> <pl-icon class="small" icon="dropdown"></pl-icon>
</pl-button> </pl-button>
<pl-popover hide-on-click> <pl-popover hide-on-click>
<pl-list> <pl-list>
<div <div
class="small double-padded centering horizontal layout list-item hover click" class="small double-padded centering horizontal layout list-item hover click"
@click=${() => this._editor.chain().focus().setHeading({ level: 1 }).run()} @click=${() => this._editor.chain().focus().setHeading({ level: 1 }).run()}
> >
<pl-icon icon="heading-1"></pl-icon> <pl-icon icon="heading-1"></pl-icon>
</div> </div>
<div <div
class="small double-padded centering horizontal layout list-item hover click" class="small double-padded centering horizontal layout list-item hover click"
@click=${() => this._editor.chain().focus().setHeading({ level: 2 }).run()} @click=${() => this._editor.chain().focus().setHeading({ level: 2 }).run()}
> >
<pl-icon icon="heading-2"></pl-icon> <pl-icon icon="heading-2"></pl-icon>
</div> </div>
<div <div
class="small double-padded centering horizontal layout list-item hover click" class="small double-padded centering horizontal layout list-item hover click"
@click=${() => this._editor.chain().focus().setHeading({ level: 3 }).run()} @click=${() => this._editor.chain().focus().setHeading({ level: 3 }).run()}
> >
<pl-icon icon="heading-3"></pl-icon> <pl-icon icon="heading-3"></pl-icon>
</div> </div>
<div <div
class="small double-padded centering horizontal layout list-item hover click" class="small double-padded centering horizontal layout list-item hover click"
@click=${() => this._editor.chain().focus().setParagraph().run()} @click=${() => this._editor.chain().focus().setParagraph().run()}
> >
<pl-icon icon="text"></pl-icon> <pl-icon icon="text"></pl-icon>
</div> </div>
</pl-list> </pl-list>
</pl-popover> </pl-popover>
<div class="border-left"></div> <div class="border-left"></div>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("bold")} .toggled=${this._editor?.isActive("bold")}
@click=${() => this._editor.chain().focus().toggleBold().run()} @click=${() => this._editor.chain().focus().toggleBold().run()}
title="${$l("Bold")}" title="${$l("Bold")}"
> >
<pl-icon icon="bold"></pl-icon> <pl-icon icon="bold"></pl-icon>
</pl-button> </pl-button>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("italic")} .toggled=${this._editor?.isActive("italic")}
@click=${() => this._editor.chain().focus().toggleItalic().run()} @click=${() => this._editor.chain().focus().toggleItalic().run()}
title="${$l("Italic")}" title="${$l("Italic")}"
> >
<pl-icon icon="italic"></pl-icon> <pl-icon icon="italic"></pl-icon>
</pl-button> </pl-button>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("strike")} .toggled=${this._editor?.isActive("strike")}
@click=${() => this._editor.chain().focus().toggleStrike().run()} @click=${() => this._editor.chain().focus().toggleStrike().run()}
title="${$l("Strikethrough")}" title="${$l("Strikethrough")}"
> >
<pl-icon icon="strikethrough"></pl-icon> <pl-icon icon="strikethrough"></pl-icon>
</pl-button> </pl-button>
<div class="border-left"></div> <div class="border-left"></div>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("bulletList")} .toggled=${this._editor?.isActive("bulletList")}
@click=${() => this._editor.chain().focus().toggleBulletList().run()} @click=${() => this._editor.chain().focus().toggleBulletList().run()}
title="${$l("Unordered List")}" title="${$l("Unordered List")}"
> >
<pl-icon icon="list"></pl-icon> <pl-icon icon="list"></pl-icon>
</pl-button> </pl-button>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("orderedList")} .toggled=${this._editor?.isActive("orderedList")}
@click=${() => this._editor.chain().focus().toggleOrderedList().run()} @click=${() => this._editor.chain().focus().toggleOrderedList().run()}
title="${$l("Ordered List")}" title="${$l("Ordered List")}"
> >
<pl-icon icon="list-ol"></pl-icon> <pl-icon icon="list-ol"></pl-icon>
</pl-button> </pl-button>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("blockquote")} .toggled=${this._editor?.isActive("blockquote")}
@click=${() => this._editor.chain().focus().toggleBlockquote().run()} @click=${() => this._editor.chain().focus().toggleBlockquote().run()}
title="${$l("Blockquote")}" title="${$l("Blockquote")}"
> >
<pl-icon icon="blockquote"></pl-icon> <pl-icon icon="blockquote"></pl-icon>
</pl-button> </pl-button>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
.toggled=${this._editor?.isActive("codeBlock")} .toggled=${this._editor?.isActive("codeBlock")}
@click=${() => this._editor.chain().focus().toggleCodeBlock().run()} @click=${() => this._editor.chain().focus().toggleCodeBlock().run()}
title="${$l("Code Block")}" title="${$l("Code Block")}"
> >
<pl-icon icon="code"></pl-icon> <pl-icon icon="code"></pl-icon>
</pl-button> </pl-button>
<div class="border-left"></div> <div class="border-left"></div>
<pl-button <pl-button
class="transparent slim" class="transparent slim"
@click=${() => this._editor.chain().focus().setHorizontalRule().run()} @click=${() => this._editor.chain().focus().setHorizontalRule().run()}
title="${$l("Insert Horizontal Line")}" title="${$l("Insert Horizontal Line")}"
> >
<pl-icon icon="line"></pl-icon> <pl-icon icon="line"></pl-icon>
</pl-button> </pl-button>
</div>
<div class="half-spacing left-padded horizontal layout border-left">
<pl-select
class="slim"
.value=${this.mode as any}
.options=${[
{
label: "WYSIWYG",
value: "wysiwyg",
},
{
label: "Markdown",
value: "markdown",
},
]}
hidden
></pl-select>
<pl-button
class="transparent slim"
style="line-height: 1.2em"
@click=${() => this._toggleMarkdown()}
.toggled=${this.mode === "markdown"}
>
<div>M</div>
<pl-icon icon="markdown"></pl-icon>
</pl-button>
<pl-button
class="transparent slim"
@click=${() => this.dispatchEvent(new CustomEvent("toggle-fullscreen"))}
>
<pl-icon icon="${this.isFullscreen ? "cancel" : "expand"}"></pl-icon>
</pl-button>
</div>
</div> </div>
<div class="half-spacing left-padded horizontal layout border-left"> <div
<pl-select class="double-padded container scroller stretch"
class="slim" @click=${(e: Event) => e.stopPropagation()}
.value=${this.mode as any} ?hidden=${this.mode !== "wysiwyg"}
.options=${[ ></div>
{ <div class="scrolling stretch">
label: "WYSIWYG", <pl-textarea autosize ?hidden=${this.mode !== "markdown"} class="fill-vertically"></pl-textarea>
value: "wysiwyg",
},
{
label: "Markdown",
value: "markdown",
},
]}
hidden
></pl-select>
<pl-button
class="transparent slim"
style="line-height: 1.2em"
@click=${() => this._toggleMarkdown()}
.toggled=${this.mode === "markdown"}
>
<div>M</div>
<pl-icon icon="markdown"></pl-icon>
</pl-button>
<pl-button
class="transparent slim"
@click=${() => this.dispatchEvent(new CustomEvent("toggle-fullscreen"))}
>
<pl-icon icon="${this.isFullscreen ? "cancel" : "expand"}"></pl-icon>
</pl-button>
</div> </div>
</div> </div>
<div
class="double-padded container scroller stretch"
@click=${(e: Event) => e.stopPropagation()}
?hidden=${this.mode !== "wysiwyg"}
></div>
<pl-textarea autosize class="stretch" ?hidden=${this.mode !== "markdown"}></pl-textarea>
`; `;
} }
} }

View File

@ -109,12 +109,13 @@ export const content = css`
blockquote { blockquote {
border-left: solid 2px var(--color-shade-3); border-left: solid 2px var(--color-shade-3);
padding-left: 0.5em; padding: 0.25em 0 0.25em 0.5em;
} }
hr { hr {
border: none; border: none;
border-top: solid 1px var(--color-shade-3); border-top: solid 1px var(--color-shade-3);
margin: 0.5em 0;
} }
pre > code { pre > code {
@ -125,5 +126,6 @@ export const content = css`
border-radius: 0.5em; border-radius: 0.5em;
font-size: 0.9em; font-size: 0.9em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
overflow-x: auto;
} }
`; `;