UNPKG

@opentiny/fluent-editor

Version:

A rich text editor based on Quill 2.0, which extends rich modules and formats on the basis of Quill. It's powerful and out-of-the-box.

287 lines (286 loc) 9.47 kB
import { I18N_LOCALE_CHANGE } from "quill-i18n"; import { inputFile } from "../config/index.es.js"; import FluentEditor from "../core/fluent-editor.es.js"; import { CustomImageSpec } from "../modules/custom-image/specs/custom-image-spec.es.js"; import "../modules/link/index.es.js"; import { shortKey } from "../modules/shortcut-key/index.es.js"; import { ColorPicker, Picker } from "../modules/toolbar/better-picker.es.js"; import { FormatPainter } from "../tools/format-painter.es.js"; import { fullscreenHandler } from "../tools/fullscreen.es.js"; import { Screenshot } from "../tools/screenshot.es.js"; import { shouldInsertNbspOnSpace, isNullOrUndefined } from "../config/editor.utils.es.js"; import { LinkTooltip } from "../modules/link/modules/tooltip.es.js"; const OriginSnowTheme = FluentEditor.import("themes/snow"); const IconPicker = FluentEditor.import("ui/icon-picker"); OriginSnowTheme.DEFAULTS = { modules: { "i18n": true, "keyboard": { bindings: { ...shortKey, preserveWhiteSpace: { key: " ", collapsed: true, handler(range, context) { if (!shouldInsertNbspOnSpace(context.prefix)) { return true; } this.quill.insertText( range.index, " ", context.format, FluentEditor.sources.USER ); this.quill.setSelection(range.index + 1, FluentEditor.sources.SILENT); return false; } } } }, "toolbar": { handlers: { ...OriginSnowTheme.DEFAULTS.modules.toolbar.handlers, "formula": function() { if (!this.quill.isEnabled()) return; const mathlive = this.quill.getModule("mathlive"); if (!mathlive) { this.quill.theme.tooltip.edit("formula"); } else { mathlive.createDialog(); } }, "undo": function() { this.quill.history.undo(); }, "redo": function() { this.quill.history.redo(); }, "file": function() { const accept = this.quill.uploader.getAccept("file"); inputFile.call(this, "file", accept); }, "image": function() { const accept = this.quill.uploader.getAccept("image"); inputFile.call(this, "image", accept); }, "video": function() { const accept = this.quill.uploader.getAccept("video"); inputFile.call(this, "video", accept); }, "ai": function() { }, "emoji": function() { }, "fullscreen": fullscreenHandler, [FormatPainter.toolName]: FormatPainter, [Screenshot.toolName]: Screenshot, "line-height": function(value) { this.quill.format("line-height", value); }, "divider": function() { const range = this.quill.getSelection(true); this.quill.insertText(range.index, "\n", FluentEditor.sources.USER); this.quill.insertEmbed(range.index + 1, "divider", true, FluentEditor.sources.USER); this.quill.setSelection(range.index + 2, FluentEditor.sources.SILENT); } } }, "image": { specs: [CustomImageSpec], overlay: { style: { border: "1px dashed rgb(68, 68, 68)" } } }, "shortcut-key": false, "file": true } }; const ALIGNS = [false, "center", "right"]; const COLORS = [ "", "rgb(255, 255, 255)", "rgb(0, 0, 0)", "rgb(72, 83, 104)", "rgb(41, 114, 244)", "rgb(0, 163, 245)", "rgb(49, 155, 98)", "rgb(222, 60, 54)", "rgb(248, 136, 37)", "rgb(245, 196, 0)", "rgb(153, 56, 215)", "rgb(242, 242, 242)", "rgb(127, 127, 127)", "rgb(243, 245, 247)", "rgb(229, 239, 255)", "rgb(229, 246, 255)", "rgb(234, 250, 241)", "rgb(254, 233, 232)", "rgb(254, 243, 235)", "rgb(254, 249, 227)", "rgb(253, 235, 255)", "rgb(216, 216, 216)", "rgb(89, 89, 89)", "rgb(197, 202, 211)", "rgb(199, 220, 255)", "rgb(199, 236, 255)", "rgb(195, 234, 213)", "rgb(255, 201, 199)", "rgb(255, 220, 196)", "rgb(255, 238, 173)", "rgb(242, 199, 255)", "rgb(191, 191, 191)", "rgb(63, 63, 63)", "rgb(128, 139, 158)", "rgb(153, 190, 255)", "rgb(153, 221, 255)", "rgb(152, 215, 182)", "rgb(255, 156, 153)", "rgb(255, 186, 132)", "rgb(255, 226, 112)", "rgb(213, 142, 255)", "rgb(165, 165, 165)", "rgb(38, 38, 38)", "rgb(53, 59, 69)", "rgb(20, 80, 184)", "rgb(18, 116, 165)", "rgb(39, 124, 79)", "rgb(158, 30, 26)", "rgb(184, 96, 20)", "rgb(163, 130, 0)", "rgb(94, 34, 129)", "rgb(147, 147, 147)", "rgb(13, 13, 13)", "rgb(36, 39, 46)", "rgb(12, 48, 110)", "rgb(10, 65, 92)", "rgb(24, 78, 50)", "rgb(88, 17, 14)", "rgb(92, 48, 10)", "rgb(102, 82, 0)", "rgb(59, 21, 81)", "custom" ]; const FONTS = [false, "serif", "monospace"]; const HEADERS = ["1", "2", "3", false]; const SIZES = ["small", false, "large", "huge"]; const LINEHEIGHT = [false, "1.2", "1.5", "2"]; class SnowTheme extends OriginSnowTheme { constructor(quill, options) { super(quill, options); this.quill = quill; this.quill.on(I18N_LOCALE_CHANGE, () => { this.i18nTextToolbar(); }); } i18nTextToolbar() { const toolbar = this.quill.getModule("toolbar"); ColorPicker.clearText = this.quill.getLangText("clear-color"); ColorPicker.customText = this.quill.getLangText("custom-color"); if (!toolbar || !this.pickers) return; this.pickers.forEach((picker) => { if (picker instanceof ColorPicker) { const colorPicker = picker; colorPicker.options.remove(); Array.from(colorPicker.select.options).forEach((option) => { if (option.hasAttribute("custom")) { option.remove(); } }); colorPicker.buildOptions(); colorPicker.createUsedColor(); } if (picker.select && picker.select.classList.contains("ql-header")) { const getLabelKey = (v) => v ? `header-${v}` : "header-normal"; const labelValue = picker.label.getAttribute("data-value"); picker.label.setAttribute("data-label", this.quill.getLangText(getLabelKey(labelValue))); const select = picker.select; Array.from(select.options).forEach((option) => { const value = option.getAttribute("value"); option.textContent = this.quill.getLangText(getLabelKey(value)); }); picker.options.remove(); picker.buildOptions(); } }); } buildPickers(selects, icons) { this.pickers = Array.from(selects).map((select) => { if (select.classList.contains("ql-align")) { if (isNullOrUndefined(select.querySelector("option"))) { fillSelect(select, ALIGNS); } return new IconPicker(select, icons.align); } if (select.classList.contains("ql-background") || select.classList.contains("ql-color")) { const format = select.classList.contains("ql-background") ? "background" : "color"; if (isNullOrUndefined(select.querySelector("option"))) { fillColorSelect(select, COLORS, format, format === "background" ? "#ffffff" : "#000000"); } return new ColorPicker(select, icons[format], { expandIcon: '<i class="icon" />', closeAfterChange: false }); } if (isNullOrUndefined(select.querySelector("option"))) { if (select.classList.contains("ql-font")) { fillSelect(select, FONTS); } else if (select.classList.contains("ql-header")) { fillSelect(select, HEADERS); } else if (select.classList.contains("ql-size")) { fillSelect(select, SIZES); } else if (select.classList.contains("ql-line-height")) { fillSelect(select, LINEHEIGHT); } } return new Picker(select); }); const update = () => { this.pickers.forEach((picker) => { if (picker instanceof ColorPicker) return; picker.update(); }); }; this.quill.on(FluentEditor.events.EDITOR_CHANGE, update); } extendToolbar(toolbar) { const icons = FluentEditor.import("ui/icons"); toolbar.container.classList.add("ql-snow"); this.buildButtons(toolbar.container.querySelectorAll("button"), icons); this.buildPickers(toolbar.container.querySelectorAll("select"), icons); this.tooltip = new LinkTooltip(this.quill, this.options.bounds); } } function fillSelect(select, values, defaultValue = false) { values.forEach((value) => { const option = document.createElement("option"); if (value === defaultValue) { option.setAttribute("selected", "selected"); } else { option.setAttribute("value", value); } select.appendChild(option); }); } function fillColorSelect(select, values, format, defaultValue = false) { const colorGetter = document.createElement("span"); for (const value of values) { const option = document.createElement("option"); if (value === defaultValue) { option.setAttribute("selected", "selected"); } else { if (value !== "custom") { colorGetter.style[format] = String(value); option.setAttribute("value", colorGetter.style[format]); } else { option.setAttribute("value", value); } } select.appendChild(option); } } export { SnowTheme as default }; //# sourceMappingURL=snow.es.js.map