Skip to content

Commit

Permalink
experiment: add LitElement based version of rich-text-editor (#6583)
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan authored Oct 5, 2023
1 parent 2372ed5 commit ecc3769
Show file tree
Hide file tree
Showing 13 changed files with 399 additions and 36 deletions.
2 changes: 2 additions & 0 deletions packages/rich-text-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
},
"files": [
"src",
"!src/vaadin-lit-rich-text-editor.d.ts",
"!src/vaadin-lit-rich-text-editor.js",
"theme",
"vaadin-*.d.ts",
"vaadin-*.js",
Expand Down
11 changes: 11 additions & 0 deletions packages/rich-text-editor/src/vaadin-lit-rich-text-editor.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @license
* Copyright (c) 2000 - 2023 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
export * from './vaadin-rich-text-editor.js';
284 changes: 284 additions & 0 deletions packages/rich-text-editor/src/vaadin-lit-rich-text-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/**
* @license
* Copyright (c) 2000 - 2023 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
*
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import '@vaadin/button/src/vaadin-lit-button.js';
import '@vaadin/confirm-dialog/src/vaadin-lit-confirm-dialog.js';
import '@vaadin/text-field/src/vaadin-lit-text-field.js';
import '@vaadin/tooltip/src/vaadin-lit-tooltip.js';
import { html, LitElement } from 'lit';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { RichTextEditorMixin } from './vaadin-rich-text-editor-mixin.js';
import { richTextEditorStyles } from './vaadin-rich-text-editor-styles.js';

/**
* LitElement based version of `<vaadin-rich-text-editor>` web component.
*
* ## Disclaimer
*
* This component is an experiment not intended for publishing to npm.
* There is no ETA regarding specific Vaadin version where it'll land.
*/
class RichTextEditor extends RichTextEditorMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
static get is() {
return 'vaadin-rich-text-editor';
}

static get cvdlName() {
return 'vaadin-rich-text-editor';
}

static get styles() {
return richTextEditorStyles;
}

/** @protected */
render() {
return html`
<div class="vaadin-rich-text-editor-container">
<!-- Create toolbar container -->
<div part="toolbar" role="toolbar">
<span part="toolbar-group toolbar-group-history">
<!-- Undo and Redo -->
<button
id="btn-undo"
type="button"
part="toolbar-button toolbar-button-undo"
@click="${this._undo}"
></button>
<vaadin-tooltip for="btn-undo" .text="${this.i18n.undo}"></vaadin-tooltip>
<button
id="btn-redo"
type="button"
part="toolbar-button toolbar-button-redo"
@click="${this._redo}"
></button>
<vaadin-tooltip for="btn-redo" .text="${this.i18n.redo}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-emphasis">
<!-- Bold -->
<button id="btn-bold" class="ql-bold" part="toolbar-button toolbar-button-bold"></button>
<vaadin-tooltip for="btn-bold" .text="${this.i18n.bold}"></vaadin-tooltip>
<!-- Italic -->
<button id="btn-italic" class="ql-italic" part="toolbar-button toolbar-button-italic"></button>
<vaadin-tooltip for="btn-italic" .text="${this.i18n.italic}"></vaadin-tooltip>
<!-- Underline -->
<button id="btn-underline" class="ql-underline" part="toolbar-button toolbar-button-underline"></button>
<vaadin-tooltip for="btn-underline" .text="${this.i18n.underline}"></vaadin-tooltip>
<!-- Strike -->
<button id="btn-strike" class="ql-strike" part="toolbar-button toolbar-button-strike"></button>
<vaadin-tooltip for="btn-strike" .text="${this.i18n.strike}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-heading">
<!-- Header buttons -->
<button
id="btn-h1"
type="button"
class="ql-header"
value="1"
part="toolbar-button toolbar-button-h1"
></button>
<vaadin-tooltip for="btn-h1" .text="${this.i18n.h1}"></vaadin-tooltip>
<button
id="btn-h2"
type="button"
class="ql-header"
value="2"
part="toolbar-button toolbar-button-h2"
></button>
<vaadin-tooltip for="btn-h2" .text="${this.i18n.h2}"></vaadin-tooltip>
<button
id="btn-h3"
type="button"
class="ql-header"
value="3"
part="toolbar-button toolbar-button-h3"
></button>
<vaadin-tooltip for="btn-h3" .text="${this.i18n.h3}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-glyph-transformation">
<!-- Subscript and superscript -->
<button
id="btn-subscript"
class="ql-script"
value="sub"
part="toolbar-button toolbar-button-subscript"
></button>
<vaadin-tooltip for="btn-subscript" .text="${this.i18n.subscript}"></vaadin-tooltip>
<button
id="btn-superscript"
class="ql-script"
value="super"
part="toolbar-button toolbar-button-superscript"
></button>
<vaadin-tooltip for="btn-superscript" text="${this.i18n.superscript}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-list">
<!-- List buttons -->
<button
id="btn-ol"
type="button"
class="ql-list"
value="ordered"
part="toolbar-button toolbar-button-list-ordered"
></button>
<vaadin-tooltip for="btn-ol" text="${this.i18n.listOrdered}"></vaadin-tooltip>
<button
id="btn-ul"
type="button"
class="ql-list"
value="bullet"
part="toolbar-button toolbar-button-list-bullet"
></button>
<vaadin-tooltip for="btn-ul" text="${this.i18n.listBullet}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-alignment">
<!-- Align buttons -->
<button
id="btn-left"
type="button"
class="ql-align"
value=""
part="toolbar-button toolbar-button-align-left"
></button>
<vaadin-tooltip for="btn-left" .text="${this.i18n.alignLeft}"></vaadin-tooltip>
<button
id="btn-center"
type="button"
class="ql-align"
value="center"
part="toolbar-button toolbar-button-align-center"
></button>
<vaadin-tooltip for="btn-center" .text="${this.i18n.alignCenter}"></vaadin-tooltip>
<button
id="btn-right"
type="button"
class="ql-align"
value="right"
part="toolbar-button toolbar-button-align-right"
></button>
<vaadin-tooltip for="btn-right" .text="${this.i18n.alignRight}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-rich-text">
<!-- Image -->
<button
id="btn-image"
type="button"
part="toolbar-button toolbar-button-image"
@touchend="${this._onImageTouchEnd}"
@click="${this._onImageClick}"
></button>
<vaadin-tooltip for="btn-image" .text="${this.i18n.image}"></vaadin-tooltip>
<!-- Link -->
<button
id="btn-link"
type="button"
part="toolbar-button toolbar-button-link"
@click="${this._onLinkClick}"
></button>
<vaadin-tooltip for="btn-link" .text="${this.i18n.link}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-block">
<!-- Blockquote -->
<button
id="btn-blockquote"
type="button"
class="ql-blockquote"
part="toolbar-button toolbar-button-blockquote"
></button>
<vaadin-tooltip for="btn-blockquote" .text="${this.i18n.blockquote}"></vaadin-tooltip>
<!-- Code block -->
<button
id="btn-code"
type="button"
class="ql-code-block"
part="toolbar-button toolbar-button-code-block"
></button>
<vaadin-tooltip for="btn-code" .text="${this.i18n.codeBlock}"></vaadin-tooltip>
</span>
<span part="toolbar-group toolbar-group-format">
<!-- Clean -->
<button id="btn-clean" type="button" class="ql-clean" part="toolbar-button toolbar-button-clean"></button>
<vaadin-tooltip for="btn-clean" .text="${this.i18n.clean}"></vaadin-tooltip>
</span>
<input
id="fileInput"
type="file"
accept="image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
@change="${this._uploadImage}"
/>
</div>
<div part="content"></div>
<div class="announcer" aria-live="polite"></div>
</div>
<vaadin-confirm-dialog
id="linkDialog"
.opened="${this._linkEditing}"
.header="${this.i18n.linkDialogTitle}"
@opened-changed="${this._onLinkEditingChanged}"
>
<vaadin-text-field
id="linkUrl"
.value="${this._linkUrl}"
style="width: 100%;"
@keydown="${this._onLinkKeydown}"
@value-changed="${this._onLinkUrlChanged}"
></vaadin-text-field>
<vaadin-button id="confirmLink" slot="confirm-button" theme="primary" @click="${this._onLinkEditConfirm}">
${this.i18n.ok}
</vaadin-button>
<vaadin-button
id="removeLink"
slot="reject-button"
theme="error"
@click="${this._onLinkEditRemove}"
?hidden="${!this._linkRange}"
>
${this.i18n.remove}
</vaadin-button>
<vaadin-button id="cancelLink" slot="cancel-button" @click="${this._onLinkEditCancel}">
${this.i18n.cancel}
</vaadin-button>
</vaadin-confirm-dialog>
`;
}

/** @private */
_onLinkEditingChanged(event) {
this._linkEditing = event.detail.value;
}

/** @private */
_onLinkUrlChanged(event) {
this._linkUrl = event.detail.value;
}
}

defineCustomElement(RichTextEditor);

export { RichTextEditor };
14 changes: 11 additions & 3 deletions packages/rich-text-editor/src/vaadin-rich-text-editor-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const RichTextEditorMixin = (superClass) =>
type: String,
notify: true,
value: '',
sync: true,
},

/**
Expand Down Expand Up @@ -188,6 +189,7 @@ export const RichTextEditorMixin = (superClass) =>
/** @private */
_linkEditing: {
type: Boolean,
value: false,
},

/** @private */
Expand Down Expand Up @@ -271,9 +273,13 @@ export const RichTextEditorMixin = (superClass) =>
}

/** @protected */
connectedCallback() {
async connectedCallback() {
super.connectedCallback();

if (!this.$ && this.updateComplete) {
await this.updateComplete;
}

const editor = this.shadowRoot.querySelector('[part="content"]');

this._editor = new Quill(editor, {
Expand Down Expand Up @@ -350,8 +356,10 @@ export const RichTextEditorMixin = (superClass) =>

this._addToolbarListeners();

this.$.linkDialog.$.dialog.$.overlay.addEventListener('vaadin-overlay-open', () => {
this.$.linkUrl.focus();
requestAnimationFrame(() => {
this.$.linkDialog.$.dialog.$.overlay.addEventListener('vaadin-overlay-open', () => {
this.$.linkUrl.focus();
});
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/rich-text-editor/test/a11y-lit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '../src/vaadin-lit-rich-text-editor.js';
import './a11y.common.js';
2 changes: 2 additions & 0 deletions packages/rich-text-editor/test/a11y-polymer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '../src/vaadin-rich-text-editor.js';
import './a11y.common.js';
Loading

0 comments on commit ecc3769

Please sign in to comment.