@vaadin/rich-text-editor 25.0.0-alpha8 → 25.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +15 -17
- package/src/styles/vaadin-rich-text-editor-base-icons.js +17 -15
- package/src/styles/vaadin-rich-text-editor-base-styles.js +280 -33
- package/src/styles/vaadin-rich-text-editor-popup-overlay-base-styles.js +1 -1
- package/src/vaadin-rich-text-editor-mixin.d.ts +2 -0
- package/src/vaadin-rich-text-editor-mixin.js +97 -69
- package/src/vaadin-rich-text-editor-popup.js +9 -24
- package/src/vaadin-rich-text-editor.d.ts +10 -8
- package/src/vaadin-rich-text-editor.js +40 -10
- package/vaadin-rich-text-editor.js +1 -1
- package/vendor/vaadin-quill.js +4 -3
- package/vendor/vaadin-quill.js.map +1 -1
- package/web-types.json +2 -2
- package/web-types.lit.json +2 -2
- package/src/styles/vaadin-rich-text-editor-core-styles.d.ts +0 -13
- package/src/styles/vaadin-rich-text-editor-core-styles.js +0 -329
- package/src/styles/vaadin-rich-text-editor-popup-overlay-core-styles.js +0 -13
- package/theme/lumo/vaadin-rich-text-editor-styles.d.ts +0 -4
- package/theme/lumo/vaadin-rich-text-editor-styles.js +0 -297
- package/theme/lumo/vaadin-rich-text-editor.d.ts +0 -6
- package/theme/lumo/vaadin-rich-text-editor.js +0 -6
|
@@ -9,40 +9,33 @@
|
|
|
9
9
|
* license.
|
|
10
10
|
*/
|
|
11
11
|
import '../vendor/vaadin-quill.js';
|
|
12
|
+
import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
12
13
|
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
13
14
|
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
14
15
|
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
15
16
|
|
|
16
17
|
const Quill = window.Quill;
|
|
17
18
|
|
|
18
|
-
//
|
|
19
|
-
// See https://github.com/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
this.remove();
|
|
37
|
-
|
|
38
|
-
return span; // eslint-disable-line no-constructor-return
|
|
19
|
+
// There are some issues e.g. `spellcheck="false"` not preserved
|
|
20
|
+
// See https://github.com/slab/quill/issues/4289
|
|
21
|
+
// Fix to add `spellcheck="false"` on the `<pre>` tag removed by Quill
|
|
22
|
+
const QuillCodeBlockContainer = Quill.import('formats/code-block-container');
|
|
23
|
+
|
|
24
|
+
class CodeBlockContainer extends QuillCodeBlockContainer {
|
|
25
|
+
html(index, length) {
|
|
26
|
+
const markup = super.html(index, length);
|
|
27
|
+
const tempDiv = document.createElement('div');
|
|
28
|
+
tempDiv.innerHTML = markup;
|
|
29
|
+
const preTag = tempDiv.querySelector('pre');
|
|
30
|
+
if (preTag) {
|
|
31
|
+
preTag.setAttribute('spellcheck', 'false');
|
|
32
|
+
return preTag.outerHTML;
|
|
33
|
+
}
|
|
34
|
+
return markup; // fallback
|
|
39
35
|
}
|
|
40
36
|
}
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
CustomColor.tagName = 'FONT';
|
|
44
|
-
|
|
45
|
-
Quill.register(CustomColor, true);
|
|
38
|
+
Quill.register('formats/code-block-container', CodeBlockContainer, true);
|
|
46
39
|
|
|
47
40
|
const HANDLERS = [
|
|
48
41
|
'bold',
|
|
@@ -69,8 +62,6 @@ const STATE = {
|
|
|
69
62
|
CLICKED: 2,
|
|
70
63
|
};
|
|
71
64
|
|
|
72
|
-
const TAB_KEY = 9;
|
|
73
|
-
|
|
74
65
|
const DEFAULT_I18N = {
|
|
75
66
|
undo: 'undo',
|
|
76
67
|
redo: 'redo',
|
|
@@ -87,6 +78,8 @@ const DEFAULT_I18N = {
|
|
|
87
78
|
superscript: 'superscript',
|
|
88
79
|
listOrdered: 'list ordered',
|
|
89
80
|
listBullet: 'list bullet',
|
|
81
|
+
outdent: 'outdent',
|
|
82
|
+
indent: 'indent',
|
|
90
83
|
alignLeft: 'align left',
|
|
91
84
|
alignCenter: 'align center',
|
|
92
85
|
alignRight: 'align right',
|
|
@@ -374,23 +367,21 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
374
367
|
}
|
|
375
368
|
});
|
|
376
369
|
|
|
377
|
-
const TAB_KEY = 9;
|
|
378
|
-
|
|
379
370
|
editorContent.addEventListener('keydown', (e) => {
|
|
380
371
|
if (e.key === 'Escape') {
|
|
381
372
|
if (!this.__tabBindings) {
|
|
382
|
-
this.__tabBindings = this._editor.keyboard.bindings
|
|
383
|
-
this._editor.keyboard.bindings
|
|
373
|
+
this.__tabBindings = this._editor.keyboard.bindings.Tab;
|
|
374
|
+
this._editor.keyboard.bindings.Tab = null;
|
|
384
375
|
}
|
|
385
376
|
} else if (this.__tabBindings) {
|
|
386
|
-
this._editor.keyboard.bindings
|
|
377
|
+
this._editor.keyboard.bindings.Tab = this.__tabBindings;
|
|
387
378
|
this.__tabBindings = null;
|
|
388
379
|
}
|
|
389
380
|
});
|
|
390
381
|
|
|
391
382
|
editorContent.addEventListener('blur', () => {
|
|
392
383
|
if (this.__tabBindings) {
|
|
393
|
-
this._editor.keyboard.bindings
|
|
384
|
+
this._editor.keyboard.bindings.Tab = this.__tabBindings;
|
|
394
385
|
this.__tabBindings = null;
|
|
395
386
|
}
|
|
396
387
|
});
|
|
@@ -422,9 +413,9 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
422
413
|
// Set up tooltip to show when hovering or focusing toolbar buttons
|
|
423
414
|
this._tooltip = document.createElement('vaadin-tooltip');
|
|
424
415
|
this._tooltip.slot = 'tooltip';
|
|
425
|
-
//
|
|
426
|
-
// tooltip being in the light DOM
|
|
427
|
-
this._tooltip.ariaTarget =
|
|
416
|
+
// Set ariaTarget to null, as toolbar buttons already have aria-label,
|
|
417
|
+
// and also cannot be linked with the tooltip being in the light DOM
|
|
418
|
+
this._tooltip.ariaTarget = null;
|
|
428
419
|
this.append(this._tooltip);
|
|
429
420
|
|
|
430
421
|
const buttons = this.shadowRoot.querySelectorAll('[part~="toolbar-button"]');
|
|
@@ -435,13 +426,16 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
435
426
|
}
|
|
436
427
|
|
|
437
428
|
/** @private */
|
|
438
|
-
__showTooltip(
|
|
439
|
-
|
|
429
|
+
__showTooltip({ type, target }) {
|
|
430
|
+
// Only show tooltip when focused with keyboard
|
|
431
|
+
if (type === 'focusin' && !isKeyboardActive()) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
440
434
|
this._tooltip.target = target;
|
|
441
435
|
this._tooltip.text = target.ariaLabel;
|
|
442
436
|
this._tooltip._stateController.open({
|
|
443
|
-
focus:
|
|
444
|
-
hover:
|
|
437
|
+
focus: type === 'focusin',
|
|
438
|
+
hover: type === 'mouseenter',
|
|
445
439
|
});
|
|
446
440
|
}
|
|
447
441
|
|
|
@@ -496,7 +490,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
496
490
|
buttons[index].focus();
|
|
497
491
|
}
|
|
498
492
|
// Esc and Tab focuses the content
|
|
499
|
-
if (e.keyCode === 27 || (e.
|
|
493
|
+
if (e.keyCode === 27 || (e.key === 'Tab' && !e.shiftKey)) {
|
|
500
494
|
e.preventDefault();
|
|
501
495
|
this._editor.focus();
|
|
502
496
|
}
|
|
@@ -539,7 +533,6 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
539
533
|
toolbar.controls.forEach((pair) => {
|
|
540
534
|
const input = pair[1];
|
|
541
535
|
const isActive = input.classList.contains('ql-active');
|
|
542
|
-
input.toggleAttribute('on', isActive);
|
|
543
536
|
input.part.toggle('toolbar-button-pressed', isActive);
|
|
544
537
|
});
|
|
545
538
|
};
|
|
@@ -552,19 +545,13 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
552
545
|
this._toolbar.querySelector('button:not([tabindex])').focus();
|
|
553
546
|
};
|
|
554
547
|
|
|
555
|
-
const keyboard = this._editor.
|
|
556
|
-
const bindings = keyboard.bindings[TAB_KEY];
|
|
557
|
-
|
|
558
|
-
// Exclude Quill shift-tab bindings, except for code block,
|
|
559
|
-
// as some of those are breaking when on a newline in the list
|
|
560
|
-
// https://github.com/vaadin/vaadin-rich-text-editor/issues/67
|
|
561
|
-
const originalBindings = bindings.filter((b) => !b.shiftKey || (b.format && b.format['code-block']));
|
|
562
|
-
const moveFocusBinding = { key: TAB_KEY, shiftKey: true, handler: focusToolbar };
|
|
548
|
+
const keyboard = this._editor.keyboard;
|
|
563
549
|
|
|
564
|
-
|
|
550
|
+
// Shift + Tab focuses a toolbar button unless we are in list / code block
|
|
551
|
+
keyboard.addBinding({ key: 'Tab', shiftKey: true, handler: focusToolbar });
|
|
565
552
|
|
|
566
553
|
// Alt-f10 focuses a toolbar button
|
|
567
|
-
keyboard.addBinding({ key:
|
|
554
|
+
keyboard.addBinding({ key: 'F10', altKey: true, handler: focusToolbar });
|
|
568
555
|
}
|
|
569
556
|
|
|
570
557
|
/** @private */
|
|
@@ -603,6 +590,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
603
590
|
_applyLink(link) {
|
|
604
591
|
if (link) {
|
|
605
592
|
this._markToolbarClicked();
|
|
593
|
+
this._editor.focus();
|
|
606
594
|
this._editor.format('link', link, SOURCE.USER);
|
|
607
595
|
this._editor.getModule('toolbar').update(this._editor.selection.savedRange);
|
|
608
596
|
}
|
|
@@ -678,6 +666,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
678
666
|
|
|
679
667
|
/** @private */
|
|
680
668
|
__onColorClick() {
|
|
669
|
+
this._tooltip.opened = false;
|
|
681
670
|
this._colorEditing = true;
|
|
682
671
|
}
|
|
683
672
|
|
|
@@ -686,6 +675,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
686
675
|
const color = event.detail.color;
|
|
687
676
|
this._colorValue = color === '#000000' ? null : color;
|
|
688
677
|
this._markToolbarClicked();
|
|
678
|
+
this._editor.focus();
|
|
689
679
|
this._editor.format('color', this._colorValue, SOURCE.USER);
|
|
690
680
|
this._toolbar.style.setProperty('--_color-value', this._colorValue);
|
|
691
681
|
this._colorEditing = false;
|
|
@@ -693,6 +683,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
693
683
|
|
|
694
684
|
/** @private */
|
|
695
685
|
__onBackgroundClick() {
|
|
686
|
+
this._tooltip.opened = false;
|
|
696
687
|
this._backgroundEditing = true;
|
|
697
688
|
}
|
|
698
689
|
|
|
@@ -701,6 +692,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
701
692
|
const color = event.detail.color;
|
|
702
693
|
this._backgroundValue = color === '#ffffff' ? null : color;
|
|
703
694
|
this._markToolbarClicked();
|
|
695
|
+
this._editor.focus();
|
|
704
696
|
this._editor.format('background', this._backgroundValue, SOURCE.USER);
|
|
705
697
|
this._toolbar.style.setProperty('--_background-value', this._backgroundValue);
|
|
706
698
|
this._backgroundEditing = false;
|
|
@@ -708,30 +700,66 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
708
700
|
|
|
709
701
|
/** @private */
|
|
710
702
|
__updateHtmlValue() {
|
|
711
|
-
|
|
712
|
-
let content =
|
|
713
|
-
|
|
714
|
-
// Remove Quill classes, e.g. ql-syntax, except for align
|
|
703
|
+
// We have to use this instead of `innerHTML` to get correct tags like `<pre>` etc.
|
|
704
|
+
let content = this._editor.getSemanticHTML();
|
|
705
|
+
// Remove Quill classes, e.g. ql-syntax, except for align and indent
|
|
715
706
|
content = content.replace(/class="([^"]*)"/gu, (_match, group1) => {
|
|
716
707
|
const classes = group1.split(' ').filter((className) => {
|
|
717
|
-
return !className.startsWith('ql-') || className.startsWith('ql-align');
|
|
708
|
+
return !className.startsWith('ql-') || className.startsWith('ql-align') || className.startsWith('ql-indent');
|
|
718
709
|
});
|
|
719
710
|
return `class="${classes.join(' ')}"`;
|
|
720
711
|
});
|
|
721
|
-
//
|
|
722
|
-
content =
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
712
|
+
// Process align and indent classes
|
|
713
|
+
content = this.__processQuillClasses(content);
|
|
714
|
+
this._setHtmlValue(content);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/** @private */
|
|
718
|
+
__processQuillClasses(content) {
|
|
719
|
+
const tempDiv = document.createElement('div');
|
|
720
|
+
tempDiv.innerHTML = content;
|
|
721
|
+
// Process only elements with align or indent classes
|
|
722
|
+
const elementsToProcess = tempDiv.querySelectorAll('[class*="ql-align"], [class*="ql-indent"]');
|
|
723
|
+
elementsToProcess.forEach((element) => {
|
|
724
|
+
this.__processAlignClasses(element);
|
|
725
|
+
this.__processIndentClasses(element);
|
|
726
|
+
element.removeAttribute('class');
|
|
730
727
|
});
|
|
728
|
+
return tempDiv.innerHTML;
|
|
729
|
+
}
|
|
731
730
|
|
|
732
|
-
|
|
731
|
+
/** @private */
|
|
732
|
+
__processAlignClasses(element) {
|
|
733
|
+
let styleText = element.getAttribute('style') || '';
|
|
734
|
+
const alignments = [this.__dir === 'rtl' ? 'left' : 'right', 'center', 'justify'];
|
|
735
|
+
alignments.forEach((align) => {
|
|
736
|
+
if (element.classList.contains(`ql-align-${align}`)) {
|
|
737
|
+
const newStyle = `text-align: ${align}`;
|
|
738
|
+
styleText = styleText ? `${styleText}; ${newStyle}` : newStyle;
|
|
739
|
+
element.setAttribute('style', styleText);
|
|
740
|
+
element.classList.remove(`ql-align-${align}`);
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
}
|
|
733
744
|
|
|
734
|
-
|
|
745
|
+
/** @private */
|
|
746
|
+
__processIndentClasses(element) {
|
|
747
|
+
const indentClass = Array.from(element.classList).find((className) => className.startsWith('ql-indent-'));
|
|
748
|
+
if (indentClass) {
|
|
749
|
+
const level = parseInt(indentClass.replace('ql-indent-', '').trim(), 10);
|
|
750
|
+
const tabs = '\t'.repeat(level);
|
|
751
|
+
// Add tabs to content
|
|
752
|
+
const firstChild = element.firstChild;
|
|
753
|
+
if (firstChild && firstChild.nodeType === Node.TEXT_NODE) {
|
|
754
|
+
firstChild.textContent = tabs + firstChild.textContent;
|
|
755
|
+
} else if (element.childNodes.length > 0) {
|
|
756
|
+
const tabNode = document.createTextNode(tabs);
|
|
757
|
+
element.insertBefore(tabNode, element.firstChild);
|
|
758
|
+
} else {
|
|
759
|
+
element.textContent = tabs;
|
|
760
|
+
}
|
|
761
|
+
element.classList.remove(indentClass);
|
|
762
|
+
}
|
|
735
763
|
}
|
|
736
764
|
|
|
737
765
|
/**
|
|
@@ -778,7 +806,7 @@ export const RichTextEditorMixin = (superClass) =>
|
|
|
778
806
|
htmlValue = htmlValue.replaceAll(/>[^<]*</gu, (match) => match.replaceAll(character, replacement)); // NOSONAR
|
|
779
807
|
});
|
|
780
808
|
|
|
781
|
-
const deltaFromHtml = this._editor.clipboard.convert(htmlValue);
|
|
809
|
+
const deltaFromHtml = this._editor.clipboard.convert({ html: htmlValue });
|
|
782
810
|
|
|
783
811
|
// Restore whitespace characters after the conversion
|
|
784
812
|
Object.entries(whitespaceCharacters).forEach(([character, replacement]) => {
|
|
@@ -16,7 +16,7 @@ import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
|
16
16
|
import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
|
|
17
17
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
18
18
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
19
|
-
import { richTextEditorPopupOverlayStyles } from './styles/vaadin-rich-text-editor-popup-overlay-
|
|
19
|
+
import { richTextEditorPopupOverlayStyles } from './styles/vaadin-rich-text-editor-popup-overlay-base-styles.js';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* An element used internally by `<vaadin-rich-text-editor>`. Not intended to be used separately.
|
|
@@ -32,15 +32,16 @@ class RichTextEditorPopup extends PolylitMixin(LitElement) {
|
|
|
32
32
|
|
|
33
33
|
static get styles() {
|
|
34
34
|
return css`
|
|
35
|
-
:host {
|
|
36
|
-
display: none !important;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
:host([opened]),
|
|
40
36
|
:host([opening]),
|
|
41
37
|
:host([closing]) {
|
|
42
38
|
display: contents !important;
|
|
43
39
|
}
|
|
40
|
+
|
|
41
|
+
:host,
|
|
42
|
+
:host([hidden]) {
|
|
43
|
+
display: none !important;
|
|
44
|
+
}
|
|
44
45
|
`;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -70,7 +71,7 @@ class RichTextEditorPopup extends PolylitMixin(LitElement) {
|
|
|
70
71
|
render() {
|
|
71
72
|
return html`
|
|
72
73
|
<vaadin-rich-text-editor-popup-overlay
|
|
73
|
-
|
|
74
|
+
id="overlay"
|
|
74
75
|
.owner="${this}"
|
|
75
76
|
.opened="${this.opened}"
|
|
76
77
|
.positionTarget="${this.target}"
|
|
@@ -163,22 +164,6 @@ class RichTextEditorPopupOverlay extends PositionMixin(
|
|
|
163
164
|
`;
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
/**
|
|
167
|
-
* @protected
|
|
168
|
-
* @override
|
|
169
|
-
*/
|
|
170
|
-
_attachOverlay() {
|
|
171
|
-
this.showPopover();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @protected
|
|
176
|
-
* @override
|
|
177
|
-
*/
|
|
178
|
-
_detachOverlay() {
|
|
179
|
-
this.hidePopover();
|
|
180
|
-
}
|
|
181
|
-
|
|
182
167
|
/**
|
|
183
168
|
* Override method from OverlayFocusMixin to use owner as content root
|
|
184
169
|
* @protected
|
|
@@ -189,11 +174,11 @@ class RichTextEditorPopupOverlay extends PositionMixin(
|
|
|
189
174
|
}
|
|
190
175
|
|
|
191
176
|
/**
|
|
192
|
-
* Override method from OverlayFocusMixin to use owner as
|
|
177
|
+
* Override method from OverlayFocusMixin to use owner as focus trap root
|
|
193
178
|
* @protected
|
|
194
179
|
* @override
|
|
195
180
|
*/
|
|
196
|
-
get
|
|
181
|
+
get _focusTrapRoot() {
|
|
197
182
|
return this.owner;
|
|
198
183
|
}
|
|
199
184
|
}
|
|
@@ -34,18 +34,17 @@ export interface RichTextEditorEventMap extends HTMLElementEventMap, RichTextEdi
|
|
|
34
34
|
* ```
|
|
35
35
|
*
|
|
36
36
|
* Vaadin Rich Text Editor focuses on the structure, not the styling of content.
|
|
37
|
-
* Therefore, the semantic HTML5 tags such as
|
|
37
|
+
* Therefore, the semantic HTML5 tags such as `<h1>`, `<strong>` and `<ul>` are used,
|
|
38
38
|
* and CSS usage is limited to most common cases, like horizontal text alignment.
|
|
39
39
|
*
|
|
40
40
|
* ### Styling
|
|
41
41
|
*
|
|
42
42
|
* The following state attributes are available for styling:
|
|
43
43
|
*
|
|
44
|
-
* Attribute | Description
|
|
45
|
-
*
|
|
46
|
-
* `disabled` | Set to a disabled text editor
|
|
47
|
-
* `readonly` | Set to a readonly text editor
|
|
48
|
-
* `on` | Set to a toolbar button applied to the selected text | toolbar-button
|
|
44
|
+
* Attribute | Description
|
|
45
|
+
* -------------|------------------------------
|
|
46
|
+
* `disabled` | Set to a disabled text editor
|
|
47
|
+
* `readonly` | Set to a readonly text editor
|
|
49
48
|
*
|
|
50
49
|
* The following shadow DOM parts are available for styling:
|
|
51
50
|
*
|
|
@@ -54,12 +53,13 @@ export interface RichTextEditorEventMap extends HTMLElementEventMap, RichTextEdi
|
|
|
54
53
|
* `content` | The content wrapper
|
|
55
54
|
* `toolbar` | The toolbar wrapper
|
|
56
55
|
* `toolbar-group` | The group for toolbar controls
|
|
57
|
-
* `toolbar-group-history` | The group for
|
|
56
|
+
* `toolbar-group-history` | The group for history controls
|
|
58
57
|
* `toolbar-group-emphasis` | The group for emphasis controls
|
|
59
58
|
* `toolbar-group-heading` | The group for heading controls
|
|
60
59
|
* `toolbar-group-style` | The group for style controls
|
|
61
60
|
* `toolbar-group-glyph-transformation` | The group for glyph transformation controls
|
|
62
|
-
* `toolbar-group-
|
|
61
|
+
* `toolbar-group-list` | The group for list controls
|
|
62
|
+
* `toolbar-group-indent` | The group for indentation controls
|
|
63
63
|
* `toolbar-group-alignment` | The group for alignment controls
|
|
64
64
|
* `toolbar-group-rich-text` | The group for rich text controls
|
|
65
65
|
* `toolbar-group-block` | The group for preformatted block controls
|
|
@@ -81,6 +81,8 @@ export interface RichTextEditorEventMap extends HTMLElementEventMap, RichTextEdi
|
|
|
81
81
|
* `toolbar-button-superscript` | The "superscript" button
|
|
82
82
|
* `toolbar-button-list-ordered` | The "ordered list" button
|
|
83
83
|
* `toolbar-button-list-bullet` | The "bullet list" button
|
|
84
|
+
* `toolbar-button-outdent` | The "decrease indentation" button
|
|
85
|
+
* `toolbar-button-indent` | The "increase indentation" button
|
|
84
86
|
* `toolbar-button-align-left` | The "left align" button
|
|
85
87
|
* `toolbar-button-align-center` | The "center align" button
|
|
86
88
|
* `toolbar-button-align-right` | The "right align" button
|
|
@@ -14,12 +14,13 @@ import '@vaadin/text-field/src/vaadin-text-field.js';
|
|
|
14
14
|
import '@vaadin/tooltip/src/vaadin-tooltip.js';
|
|
15
15
|
import './vaadin-rich-text-editor-popup.js';
|
|
16
16
|
import { html, LitElement, render } from 'lit';
|
|
17
|
+
import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
17
18
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
18
19
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
19
20
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
20
21
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
21
22
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
22
|
-
import { richTextEditorStyles } from './styles/vaadin-rich-text-editor-
|
|
23
|
+
import { richTextEditorStyles } from './styles/vaadin-rich-text-editor-base-styles.js';
|
|
23
24
|
import { RichTextEditorMixin } from './vaadin-rich-text-editor-mixin.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -32,18 +33,17 @@ import { RichTextEditorMixin } from './vaadin-rich-text-editor-mixin.js';
|
|
|
32
33
|
* ```
|
|
33
34
|
*
|
|
34
35
|
* Vaadin Rich Text Editor focuses on the structure, not the styling of content.
|
|
35
|
-
* Therefore, the semantic HTML5 tags such as
|
|
36
|
+
* Therefore, the semantic HTML5 tags such as `<h1>`, `<strong>` and `<ul>` are used,
|
|
36
37
|
* and CSS usage is limited to most common cases, like horizontal text alignment.
|
|
37
38
|
*
|
|
38
39
|
* ### Styling
|
|
39
40
|
*
|
|
40
41
|
* The following state attributes are available for styling:
|
|
41
42
|
*
|
|
42
|
-
* Attribute | Description
|
|
43
|
-
*
|
|
44
|
-
* `disabled` | Set to a disabled text editor
|
|
45
|
-
* `readonly` | Set to a readonly text editor
|
|
46
|
-
* `on` | Set to a toolbar button applied to the selected text | toolbar-button
|
|
43
|
+
* Attribute | Description
|
|
44
|
+
* -------------|------------------------------
|
|
45
|
+
* `disabled` | Set to a disabled text editor
|
|
46
|
+
* `readonly` | Set to a readonly text editor
|
|
47
47
|
*
|
|
48
48
|
* The following shadow DOM parts are available for styling:
|
|
49
49
|
*
|
|
@@ -52,12 +52,13 @@ import { RichTextEditorMixin } from './vaadin-rich-text-editor-mixin.js';
|
|
|
52
52
|
* `content` | The content wrapper
|
|
53
53
|
* `toolbar` | The toolbar wrapper
|
|
54
54
|
* `toolbar-group` | The group for toolbar controls
|
|
55
|
-
* `toolbar-group-history` | The group for
|
|
55
|
+
* `toolbar-group-history` | The group for history controls
|
|
56
56
|
* `toolbar-group-emphasis` | The group for emphasis controls
|
|
57
57
|
* `toolbar-group-heading` | The group for heading controls
|
|
58
58
|
* `toolbar-group-style` | The group for style controls
|
|
59
59
|
* `toolbar-group-glyph-transformation` | The group for glyph transformation controls
|
|
60
|
-
* `toolbar-group-
|
|
60
|
+
* `toolbar-group-list` | The group for list controls
|
|
61
|
+
* `toolbar-group-indent` | The group for indentation controls
|
|
61
62
|
* `toolbar-group-alignment` | The group for alignment controls
|
|
62
63
|
* `toolbar-group-rich-text` | The group for rich text controls
|
|
63
64
|
* `toolbar-group-block` | The group for preformatted block controls
|
|
@@ -79,6 +80,8 @@ import { RichTextEditorMixin } from './vaadin-rich-text-editor-mixin.js';
|
|
|
79
80
|
* `toolbar-button-superscript` | The "superscript" button
|
|
80
81
|
* `toolbar-button-list-ordered` | The "ordered list" button
|
|
81
82
|
* `toolbar-button-list-bullet` | The "bullet list" button
|
|
83
|
+
* `toolbar-button-outdent` | The "decrease indentation" button
|
|
84
|
+
* `toolbar-button-indent` | The "increase indentation" button
|
|
82
85
|
* `toolbar-button-align-left` | The "left align" button
|
|
83
86
|
* `toolbar-button-align-center` | The "center align" button
|
|
84
87
|
* `toolbar-button-align-right` | The "right align" button
|
|
@@ -115,6 +118,12 @@ class RichTextEditor extends RichTextEditorMixin(
|
|
|
115
118
|
return richTextEditorStyles;
|
|
116
119
|
}
|
|
117
120
|
|
|
121
|
+
static get lumoInjector() {
|
|
122
|
+
return {
|
|
123
|
+
includeBaseStyles: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
118
127
|
/** @protected */
|
|
119
128
|
render() {
|
|
120
129
|
return html`
|
|
@@ -259,6 +268,27 @@ class RichTextEditor extends RichTextEditorMixin(
|
|
|
259
268
|
></button>
|
|
260
269
|
</span>
|
|
261
270
|
|
|
271
|
+
<span part="toolbar-group toolbar-group-indent">
|
|
272
|
+
<!-- Decrease -->
|
|
273
|
+
<button
|
|
274
|
+
id="btn-outdent"
|
|
275
|
+
type="button"
|
|
276
|
+
class="ql-indent"
|
|
277
|
+
value="-1"
|
|
278
|
+
part="toolbar-button toolbar-button-outdent"
|
|
279
|
+
aria-label="${this.__effectiveI18n.outdent}"
|
|
280
|
+
></button>
|
|
281
|
+
<!-- Increase -->
|
|
282
|
+
<button
|
|
283
|
+
id="btn-indent"
|
|
284
|
+
type="button"
|
|
285
|
+
class="ql-indent"
|
|
286
|
+
value="+1"
|
|
287
|
+
part="toolbar-button toolbar-button-indent"
|
|
288
|
+
aria-label="${this.__effectiveI18n.indent}"
|
|
289
|
+
></button>
|
|
290
|
+
</span>
|
|
291
|
+
|
|
262
292
|
<span part="toolbar-group toolbar-group-alignment">
|
|
263
293
|
<!-- Align buttons -->
|
|
264
294
|
<button
|
|
@@ -438,7 +468,7 @@ class RichTextEditor extends RichTextEditorMixin(
|
|
|
438
468
|
confirmDialog.$.overlay.addEventListener(
|
|
439
469
|
'vaadin-overlay-open',
|
|
440
470
|
() => {
|
|
441
|
-
urlField.focus();
|
|
471
|
+
urlField.focus({ focusVisible: isKeyboardActive() });
|
|
442
472
|
},
|
|
443
473
|
{ once: true },
|
|
444
474
|
);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-rich-text-editor.js';
|
|
2
2
|
export * from './src/vaadin-rich-text-editor.js';
|