reactjs-tiptap-editor
Version:
A modern WYSIWYG rich text editor based on tiptap and shadcn ui for React
391 lines (390 loc) • 11.5 kB
JavaScript
import { h as $, m as X } from "./index-CXIIg9Sq.js";
import { w as Z, x as J, A as K, y as Y, z as Q, F as tt, B as et, G as rt, J as V, K as it, N as at } from "./RichTextEditor-iSPxjLdO.js";
import { N as st, R as nt } from "./dom-dataset-2RXYq9wp.js";
import { jsxs as C, jsx as o } from "react/jsx-runtime";
import { useState as g, useRef as ot, useCallback as y, useEffect as E, useMemo as k } from "react";
import { s as lt, i as ct } from "./shortId-WJVkrvml.js";
import { T as ht } from "./textarea-DpvZ1MKU.js";
import { I as q, h as dt, i as W } from "./index-D-DR0FPY.js";
const j = `graph TB
a-->b`, ut = ({ editor: r, upload: t }) => {
const [e, s] = g(j), [f, b] = g(""), [x, T] = g(!1), A = ot(null), [l, c] = g(null), N = y(
(n) => {
n && import("mermaid").then((p) => {
c(p.default);
});
},
[]
), _ = async (n) => {
try {
const { svg: p } = await l.render("mermaid-svg", n);
b(p);
} catch {
b("");
}
}, L = () => {
l.initialize({
darkMode: !1,
startOnLoad: !1,
// fontFamily:'',
fontSize: 12,
theme: "base"
}), _(e);
};
return E(() => {
l && x && L();
}, [l, x]), E(() => {
l && x && _(e);
}, [l && e]), /* @__PURE__ */ C(
Z,
{
onOpenChange: T,
open: x,
children: [
/* @__PURE__ */ o(J, { asChild: !0, children: /* @__PURE__ */ o(
K,
{
action: () => T(!0),
icon: "Mermaid",
tooltip: "Mermaid"
}
) }),
/* @__PURE__ */ C(Y, { className: "richtext-z-[99999] !richtext-max-w-[1300px]", children: [
/* @__PURE__ */ o(Q, { children: "Mermaid" }),
/* @__PURE__ */ o(
"div",
{
ref: N,
style: { height: "100%", border: "1px solid hsl(var(--border))" },
children: /* @__PURE__ */ C("div", { className: "richtext-flex richtext-gap-[10px] richtext-rounded-[10px] richtext-p-[10px]", children: [
/* @__PURE__ */ o(
ht,
{
autoFocus: !0,
className: "richtext-flex-1",
defaultValue: j,
onChange: (n) => s(n.target.value),
placeholder: "Text",
required: !0,
rows: 10,
value: e,
style: {
color: "hsl(var(--richtext-foreground))"
}
}
),
/* @__PURE__ */ o(
"div",
{
className: "richtext-flex richtext-flex-1 richtext-items-center richtext-justify-center richtext-rounded-[10px] richtext-p-[10px]",
dangerouslySetInnerHTML: { __html: f },
ref: A,
style: { height: "100%", borderWidth: 1, minHeight: 500, background: "#fff" }
}
)
] })
}
),
/* @__PURE__ */ o(tt, { children: /* @__PURE__ */ o(
et,
{
onClick: async () => {
if (e !== "") {
if (e) {
const n = A.current.querySelector("svg"), { width: p, height: H } = n.getBoundingClientRect(), I = `mermaid-${lt()}.svg`;
let w = ct(n.outerHTML);
if (t) {
console.log({
src: w
});
const R = rt(w, I);
w = await t(R);
}
r == null || r.chain().focus().setMermaid(
{
type: "mermaid",
src: w,
alt: encodeURIComponent(e),
width: p,
height: H
},
!!e
).run();
}
T(!1);
}
},
type: "button",
children: "Save changes"
}
) })
] })
]
}
);
}, O = {
TOP_LEFT: "tl",
TOP_RIGHT: "tr",
BOTTOM_LEFT: "bl",
BOTTOM_RIGHT: "br"
};
function mt({ editor: r, node: t, updateAttributes: e, getPos: s, selected: f }) {
const [b, x] = g({
width: q,
height: q
}), [T, A] = g({
width: 0,
height: 0
}), [l] = g([
O.TOP_LEFT,
O.TOP_RIGHT,
O.BOTTOM_LEFT,
O.BOTTOM_RIGHT
]), [c, N] = g(!1), [_, L] = g({
x: 0,
y: 0,
w: 0,
h: 0,
dir: ""
}), { align: F } = t == null ? void 0 : t.attrs, n = k(() => {
const { src: i, alt: d, width: u, height: M } = t == null ? void 0 : t.attrs, v = $(u) ? `${u}px` : u, a = $(M) ? `${M}px` : M;
return {
src: i || void 0,
alt: d || void 0,
style: {
width: v || void 0,
height: a || void 0
}
};
}, [t == null ? void 0 : t.attrs]), p = k(() => {
const {
style: { width: i }
} = n;
return { width: i === "100%" ? i : void 0 };
}, [n]);
function H(i) {
A({
width: i.target.width,
height: i.target.height
});
}
function I() {
r.commands.setNodeSelection(s());
}
const w = y(
V(() => {
const { width: i } = getComputedStyle(r.view.dom);
x((d) => ({
...d,
width: Number.parseInt(i, 10)
}));
}, W),
[r]
);
function R(i, d) {
i.preventDefault(), i.stopPropagation();
const u = T.width, M = T.height, v = u / M;
let a = Number(t.attrs.width), m = Number(t.attrs.height);
const h = b.width;
a && !m ? (a = a > h ? h : a, m = Math.round(a / v)) : m && !a ? (a = Math.round(m * v), a = a > h ? h : a) : !a && !m ? (a = u > h ? h : u, m = Math.round(a / v)) : a = a > h ? h : a, N(!0), L({
x: i.clientX,
y: i.clientY,
w: a,
h: m,
dir: d
});
}
const S = y(
V((i) => {
if (i.preventDefault(), i.stopPropagation(), !c)
return;
const { x: d, w: u, dir: M } = _, v = (i.clientX - d) * (/l/.test(M) ? -1 : 1), { width: a, height: m } = t == null ? void 0 : t.attrs, h = a / m, P = it(u + v, dt, b.width), U = Math.round(P / h);
e({
width: P,
height: U
});
}, W),
[c, _, b, e, t == null ? void 0 : t.attrs]
), z = y(
(i) => {
i.preventDefault(), i.stopPropagation(), c && (L({
x: 0,
y: 0,
w: 0,
h: 0,
dir: ""
}), N(!1), I());
},
[c, I]
), G = y(() => {
document == null || document.addEventListener("mousemove", S, !0), document == null || document.addEventListener("mouseup", z, !0);
}, [S, z]), B = y(() => {
document == null || document.removeEventListener("mousemove", S, !0), document == null || document.removeEventListener("mouseup", z, !0);
}, [S, z]);
E(() => (c ? G() : B(), () => {
B();
}), [c, G, B]);
const D = k(() => new ResizeObserver(() => w()), [w]);
return E(() => (D.observe(r.view.dom), () => {
D.disconnect();
}), [r.view.dom, D]), /* @__PURE__ */ o(
st,
{
className: "image-view",
style: { ...p, width: "100%", textAlign: F },
children: /* @__PURE__ */ C(
"div",
{
"data-drag-handle": !0,
draggable: "true",
style: { ...p, background: "#fff" },
className: `image-view__body ${f ? "image-view__body--focused" : ""} ${c ? "image-view__body--resizing" : ""}`,
children: [
/* @__PURE__ */ o(
"img",
{
alt: n.alt,
className: "image-view__body__image block",
height: "auto",
onClick: I,
onLoad: H,
src: n.src,
style: n.style
}
),
r.view.editable && (f || c) && /* @__PURE__ */ o("div", { className: "image-resizer", children: l == null ? void 0 : l.map((i) => /* @__PURE__ */ o(
"span",
{
className: `image-resizer__handler image-resizer__handler--${i}`,
onMouseDown: (d) => R(d, i)
},
`image-dir-${i}`
)) })
]
}
)
}
);
}
const Tt = /* @__PURE__ */ at.extend({
name: "mermaid",
addOptions() {
var r;
return {
...(r = this.parent) == null ? void 0 : r.call(this),
inline: !1,
content: "",
marks: "",
group: "block",
draggable: !1,
selectable: !0,
atom: !0,
HTMLAttributes: {
class: "mermaid"
},
button: ({ editor: t, t: e, extension: s }) => {
var f;
return {
component: ut,
componentProps: {
action: () => !0,
isActive: () => !1,
disabled: !1,
editor: t,
icon: "Mermaid",
tooltip: e("editor.mermaid.tooltip"),
upload: (f = s == null ? void 0 : s.options) == null ? void 0 : f.upload
}
};
}
};
},
addAttributes() {
var r;
return {
...(r = this.parent) == null ? void 0 : r.call(this),
width: {
default: null,
parseHTML: (t) => {
const e = t.querySelector("img"), s = e == null ? void 0 : e.getAttribute("width");
return s ? Number.parseInt(s, 10) : 320;
},
renderHTML: (t) => ({
width: t.width
})
},
height: {
default: null,
parseHTML: (t) => {
const e = t.querySelector("img"), s = e == null ? void 0 : e.getAttribute("height");
return s ? Number.parseInt(s, 10) : 212;
},
renderHTML: (t) => ({
height: t.height
})
},
align: {
default: "center",
parseHTML: (t) => t.getAttribute("align"),
renderHTML: (t) => ({
align: t.align
})
}
};
},
addNodeView() {
return nt(mt);
},
// @ts-ignore
addCommands() {
return {
setMermaid: (r, t) => ({ commands: e, editor: s }) => t ? e.insertContent({
type: this.name,
attrs: r
}) : e.insertContentAt(s.state.selection.anchor, {
type: this.name,
attrs: r
}),
setAlignImageMermaid: (r) => ({ commands: t }) => t.updateAttributes(this.name, { align: r })
};
},
renderHTML({ HTMLAttributes: r }) {
const { align: t } = r;
return [
"div",
// Parent element
{
style: t ? `text-align: ${t};` : "",
class: "imageMermaid"
},
[
"img",
X(
// @ts-ignore
this.options.HTMLAttributes,
r
)
]
];
},
parseHTML() {
return [
{
tag: "div[class=imageMermaid]",
getAttrs: (r) => {
const t = r.querySelector("img"), e = t == null ? void 0 : t.getAttribute("width"), s = t == null ? void 0 : t.getAttribute("height");
return {
src: t == null ? void 0 : t.getAttribute("src"),
alt: t == null ? void 0 : t.getAttribute("alt"),
width: e ? Number.parseInt(e, 10) : null,
height: s ? Number.parseInt(s, 10) : null,
align: (t == null ? void 0 : t.getAttribute("align")) || r.style.textAlign || null
};
}
}
];
}
});
export {
Tt as Mermaid
};