@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.
151 lines (150 loc) • 5.68 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { isBoolean, isObject } from "../../../utils/is.es.js";
import { PREVIEW, COPY, DOWNLOAD, RIGHT_ALIGN, CENTER_ALIGN, LEFT_ALIGN } from "../options.es.js";
import "../preview/index.es.js";
import { getImagePreviewModal } from "../preview/preview-modal.es.js";
const ALIGN_ATTR = "data-align";
function setAlignStyle(el, display, float, margin) {
el.style.setProperty("display", display);
el.style.setProperty("float", float);
el.style.setProperty("margin", margin);
}
const alignmentHandler = {
left: (el, toolbarButtons) => {
setAlignStyle(el, "inline", "left", "0 1em 1em 0");
},
center: (el, toolbarButtons) => {
setAlignStyle(el, "block", null, "auto");
},
right: (el, toolbarButtons) => {
setAlignStyle(el, "inline", "right", "0 0 1em 1em");
},
download: (el, toolbarButtons) => {
const imageName = el.dataset.title || "image";
const url = el.src || "";
if (!url) return;
const a = document.createElement("a");
a.href = url;
a.target = "_blank";
a.download = imageName;
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.parentNode.removeChild(a);
},
copy: async (el, toolbarButtons) => {
if (!el.src) return;
const imageUrl = el.src;
try {
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error("Copy image failed");
}
const blob = await response.blob();
await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
} catch (e) {
throw new Error("Copy image failed");
}
}
};
const defaultButtons = {
[]: {
name: LEFT_ALIGN,
icon: `
<svg viewbox="0 0 18 18">
<line class="ql-stroke" x1="3" x2="15" y1="9" y2="9"></line>
<line class="ql-stroke" x1="3" x2="13" y1="14" y2="14"></line>
<line class="ql-stroke" x1="3" x2="9" y1="4" y2="4"></line>
</svg>
`,
isActive: (el) => el.getAttribute(ALIGN_ATTR) === "left",
apply: (el, toolbarButtons) => {
el.setAttribute(ALIGN_ATTR, "left");
alignmentHandler.left(el, toolbarButtons);
}
},
[]: {
name: CENTER_ALIGN,
icon: `
<svg viewbox="0 0 18 18">
<line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line>
<line class="ql-stroke" x1="14" x2="4" y1="14" y2="14"></line>
<line class="ql-stroke" x1="12" x2="6" y1="4" y2="4"></line>
</svg>
`,
isActive: (el) => el.getAttribute(ALIGN_ATTR) === "center",
apply: (el, toolbarButtons) => {
el.setAttribute(ALIGN_ATTR, "center");
alignmentHandler.center(el, toolbarButtons);
}
},
[]: {
name: RIGHT_ALIGN,
icon: `
<svg viewbox="0 0 18 18">
<line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line>
<line class="ql-stroke" x1="15" x2="5" y1="14" y2="14"></line>
<line class="ql-stroke" x1="15" x2="9" y1="4" y2="4"></line>
</svg>
`,
isActive: (el) => el.getAttribute(ALIGN_ATTR) === "right",
apply: (el, toolbarButtons) => {
el.setAttribute(ALIGN_ATTR, "right");
alignmentHandler.right(el, toolbarButtons);
}
},
[]: {
name: DOWNLOAD,
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path class="ql-fill" d="M26 24v4H6v-4H4v4a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2v-4zm0-10l-1.41-1.41L17 20.17V2h-2v18.17l-7.59-7.58L6 14l10 10z"/></svg>`,
apply: (el, toolbarButtons) => {
alignmentHandler.download(el, toolbarButtons);
}
},
[]: {
name: COPY,
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path class="ql-fill" d="M28 10v18H10V10zm0-2H10a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2"/><path class="ql-fill" d="M4 18H2V4a2 2 0 0 1 2-2h14v2H4Z"/></svg>`,
apply: (el, toolbarButtons) => {
alignmentHandler.copy(el, toolbarButtons);
}
},
[]: {
name: PREVIEW,
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path class="ql-fill" d="M16 7c-4.96 0-9.23 3.13-11 7.5 1.77 4.37 6.04 7.5 11 7.5s9.23-3.13 11-7.5c-1.77-4.37-6.04-7.5-11-7.5zm0 12c-2.49 0-4.5-2.01-4.5-4.5S13.51 10 16 10s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-7c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5z"/></svg>`,
apply: (el, toolbarButtons) => {
const imageSrc = el.getAttribute("src") || el.getAttribute("data-src");
if (imageSrc) {
const modal = getImagePreviewModal();
modal.show(imageSrc);
}
}
}
};
class ImageToolbarButtons {
constructor(options) {
__publicField(this, "buttons");
this.buttons = Object.entries(options.buttons).reduce((acc, [name, button]) => {
if (isBoolean(button) && button && defaultButtons[name]) {
acc[name] = defaultButtons[name];
} else if (isObject(button)) {
acc[button.name] = button;
}
return acc;
}, {});
}
getItems() {
return Object.keys(this.buttons).map((k) => this.buttons[k]);
}
clear(el) {
el.removeAttribute(ALIGN_ATTR);
setAlignStyle(el, null, null, null);
}
}
export {
ALIGN_ATTR,
ImageToolbarButtons,
alignmentHandler,
setAlignStyle
};
//# sourceMappingURL=image-toolbar-buttons.es.js.map