UNPKG

quill

Version:

Your powerful, rich text editor

114 lines 4.09 kB
import { merge } from 'lodash-es'; import Emitter from '../core/emitter.js'; import BaseTheme, { BaseTooltip } from './base.js'; import { Range } from '../core/selection.js'; import icons from '../ui/icons.js'; import Quill from '../core/quill.js'; const TOOLBAR_CONFIG = [['bold', 'italic', 'link'], [{ header: 1 }, { header: 2 }, 'blockquote']]; class BubbleTooltip extends BaseTooltip { static TEMPLATE = ['<span class="ql-tooltip-arrow"></span>', '<div class="ql-tooltip-editor">', '<input type="text" data-formula="e=mc^2" data-link="https://quilljs.com" data-video="Embed URL">', '<a class="ql-close"></a>', '</div>'].join(''); constructor(quill, bounds) { super(quill, bounds); this.quill.on(Emitter.events.EDITOR_CHANGE, (type, range, oldRange, source) => { if (type !== Emitter.events.SELECTION_CHANGE) return; if (range != null && range.length > 0 && source === Emitter.sources.USER) { this.show(); // Lock our width so we will expand beyond our offsetParent boundaries this.root.style.left = '0px'; this.root.style.width = ''; this.root.style.width = `${this.root.offsetWidth}px`; const lines = this.quill.getLines(range.index, range.length); if (lines.length === 1) { const bounds = this.quill.getBounds(range); if (bounds != null) { this.position(bounds); } } else { const lastLine = lines[lines.length - 1]; const index = this.quill.getIndex(lastLine); const length = Math.min(lastLine.length() - 1, range.index + range.length - index); const indexBounds = this.quill.getBounds(new Range(index, length)); if (indexBounds != null) { this.position(indexBounds); } } } else if (document.activeElement !== this.textbox && this.quill.hasFocus()) { this.hide(); } }); } listen() { super.listen(); // @ts-expect-error Fix me later this.root.querySelector('.ql-close').addEventListener('click', () => { this.root.classList.remove('ql-editing'); }); this.quill.on(Emitter.events.SCROLL_OPTIMIZE, () => { // Let selection be restored by toolbar handlers before repositioning setTimeout(() => { if (this.root.classList.contains('ql-hidden')) return; const range = this.quill.getSelection(); if (range != null) { const bounds = this.quill.getBounds(range); if (bounds != null) { this.position(bounds); } } }, 1); }); } cancel() { this.show(); } position(reference) { const shift = super.position(reference); const arrow = this.root.querySelector('.ql-tooltip-arrow'); // @ts-expect-error arrow.style.marginLeft = ''; if (shift !== 0) { // @ts-expect-error arrow.style.marginLeft = `${-1 * shift - arrow.offsetWidth / 2}px`; } return shift; } } class BubbleTheme extends BaseTheme { constructor(quill, options) { if (options.modules.toolbar != null && options.modules.toolbar.container == null) { options.modules.toolbar.container = TOOLBAR_CONFIG; } super(quill, options); this.quill.container.classList.add('ql-bubble'); } extendToolbar(toolbar) { // @ts-expect-error this.tooltip = new BubbleTooltip(this.quill, this.options.bounds); if (toolbar.container != null) { this.tooltip.root.appendChild(toolbar.container); this.buildButtons(toolbar.container.querySelectorAll('button'), icons); this.buildPickers(toolbar.container.querySelectorAll('select'), icons); } } } BubbleTheme.DEFAULTS = merge({}, BaseTheme.DEFAULTS, { modules: { toolbar: { handlers: { link(value) { if (!value) { this.quill.format('link', false, Quill.sources.USER); } else { // @ts-expect-error this.quill.theme.tooltip.edit(); } } } } } }); export { BubbleTooltip, BubbleTheme as default }; //# sourceMappingURL=bubble.js.map