reactjs-tiptap-editor
Version:
A modern WYSIWYG rich text editor based on tiptap and shadcn ui for React
252 lines (251 loc) • 8.83 kB
JavaScript
import { jsx as d, jsxs as b } from "react/jsx-runtime";
import { forwardRef as y, useState as w, useRef as v, useImperativeHandle as S, useEffect as B, Fragment as D } from "react";
import { E as N, z as L, L as T, c as V, I as z } from "./index-RcSPeQHn.js";
import "./theme.js";
import { H as A, u as G } from "./index-C07N8gA1.js";
import { y as $, V as q } from "./index-BG0kQamI.js";
function X({ t: i }) {
const a = [
{
name: "format",
title: i("editor.slash.format"),
commands: []
},
{
name: "insert",
title: i("editor.slash.insert"),
commands: []
}
];
return A.forEach((e) => {
a[0].commands.push({
name: `heading${e}`,
label: i(e === "Paragraph" ? "editor.paragraph.tooltip" : `editor.heading.h${e}.tooltip`),
aliases: [`h${e}`, "bt", `bt${e}`],
iconName: `Heading${e}`,
isActive: (t) => e === "Paragraph" ? !1 : t.isActive("heading", { level: e }) || !1,
action: ({ editor: t, range: l }) => {
const s = A.find((m) => t.isActive("heading", { level: m }));
if (e === "Paragraph") {
s !== void 0 && s !== "Paragraph" && t.commands.toggleHeading({ level: s }), t.chain().focus().deleteRange(l).run();
return;
}
if (e) {
t.chain().focus().deleteRange(l).setHeading({ level: e }).run();
return;
}
t.chain().focus().deleteRange(l).run();
}
});
}), a[0].commands.push({
name: "bulletList",
label: i("editor.bulletlist.tooltip"),
aliases: ["ul", "yxlb"],
iconName: "List",
isActive: (e) => e.isActive("bulletList"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).toggleBulletList().run();
}
}), a[0].commands.push({
name: "orderedlist",
label: i("editor.orderedlist.tooltip"),
aliases: ["ol", "yxlb"],
iconName: "ListOrdered",
isActive: (e) => e.isActive("orderedList"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).toggleOrderedList().run();
}
}), a[0].commands.push({
name: "taskList",
label: i("editor.tasklist.tooltip"),
iconName: "ListTodo",
description: "Task list with todo items",
aliases: ["todo"],
isActive: (e) => e.isActive("taskList"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).toggleTaskList().run();
}
}), a[0].commands.push({
name: "blockquote",
label: i("editor.blockquote.tooltip"),
description: "插入引入格式",
aliases: ["yr"],
iconName: "TextQuote",
isActive: (e) => e.isActive("blockquote"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).setBlockquote().run();
}
}), a[0].commands.push({
name: "codeBlock",
label: i("editor.codeblock.tooltip"),
iconName: "Code2",
description: "Code block with syntax highlighting",
shouldBeHidden: (e) => e.isActive("columns"),
isActive: (e) => e.isActive("codeBlock"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).setCodeBlock().run();
}
}), a[1].commands.push({
name: "image",
label: i("editor.image.tooltip"),
iconName: "ImageUp",
description: "Insert a image",
aliases: ["image", "tp", "tupian"],
shouldBeHidden: (e) => e.isActive("columns"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).run();
const l = N.UPLOAD_IMAGE(e.id);
L(l, !0);
}
}), a[1].commands.push({
name: "video",
label: i("editor.video.tooltip"),
iconName: "Video",
description: "Insert a video",
aliases: ["video", "sp", "shipin"],
shouldBeHidden: (e) => e.isActive("columns"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).run();
const l = N.UPLOAD_VIDEO(e.id);
L(l, !0);
}
}), a[1].commands.push({
name: "table",
label: i("editor.table.tooltip"),
iconName: "Table",
description: "Insert a table",
aliases: ["table", "bg", "biaoge", "biao"],
shouldBeHidden: (e) => e.isActive("columns"),
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).insertTable({ rows: 3, cols: 3, withHeaderRow: !1 }).run();
}
}), a[1].commands.push({
name: "horizontalRule",
label: i("editor.horizontalrule.tooltip"),
iconName: "Minus",
description: "Insert a horizontal divider",
aliases: ["hr", "fgx", "fg"],
action: ({ editor: e, range: t }) => {
e.chain().focus().deleteRange(t).setHorizontalRule().run();
}
}), a[1].commands.push({
name: "columns",
label: i("editor.columns.tooltip"),
iconName: "Columns2",
description: "Add two column content",
action: ({ editor: e }) => {
e.chain().focus().insertColumns({ cols: 2 }).run();
}
}), a;
}
function P(i, a) {
return i.map((l) => ({
...l,
commands: l.commands.filter((s) => {
const m = s.label.toLowerCase().trim(), u = a.toLowerCase().trim();
if (s.aliases) {
const p = s.aliases.map((h) => h.toLowerCase().trim()), r = m.match(u), f = p.some((h) => h.match(u));
return r || f;
}
return m.match(u);
})
})).filter((l) => l.commands.length > 0);
}
const U = $([]);
function O() {
const [i, a] = q(U);
return [i, a];
}
function F(i, a) {
const [e] = O(), [t, l] = w(0), [s, m] = w(0), u = v(null), { t: p } = G(), r = P(e, i.query), f = v([]);
S(a, () => ({
onKeyDown: h
})), B(() => {
if (!u.current)
return;
const o = s * 1e3 + t, n = f.current[o];
n && n.scrollIntoView({
behavior: "smooth",
block: "nearest"
});
}, [t, s]);
function h({ event: o }) {
return o.key === "ArrowUp" ? (C(), !0) : o.key === "ArrowDown" ? (I(), !0) : o.key === "Enter" ? (k(), !0) : !1;
}
function C() {
var c;
if (r.length === 0)
return !1;
let o = t - 1, n = s;
o < 0 && (n = s - 1, o = ((c = r[n]) == null ? void 0 : c.commands.length) - 1 || 0), n < 0 && (n = r.length - 1, o = r[n].commands.length - 1), l(o), m(n);
}
function I() {
if (r.length === 0)
return !1;
const o = r[s].commands;
let n = t + 1, c = s;
o.length - 1 < n && (n = 0, c = s + 1), r.length - 1 < c && (c = 0), l(n), m(c);
}
function k() {
if (r.length === 0 || s === -1 || t === -1)
return !1;
g(s, t);
}
function g(o, n) {
const c = r[o].commands[n];
i == null || i.command(c);
}
function R(o, n) {
g(o, n);
}
function H(o, n, c) {
f.current[o * 1e3 + n] = c;
}
return /* @__PURE__ */ d(
"div",
{
className: "richtext-max-h-[min(80vh,24rem)] richtext-flex-wrap richtext-overflow-y-auto richtext-overflow-x-hidden richtext-rounded-md !richtext-border !richtext-border-solid !richtext-border-border richtext-bg-popover richtext-p-1 richtext-text-popover-foreground richtext-shadow-md richtext-outline-none",
"data-richtext-portal": !0,
ref: u,
children: r != null && r.length ? /* @__PURE__ */ d("div", { className: "richtext-grid richtext-min-w-48 richtext-grid-cols-1 richtext-gap-0.5", children: r == null ? void 0 : r.map((o, n) => /* @__PURE__ */ b(D, { children: [
/* @__PURE__ */ d(T, { className: "richtext-mx-[4px] richtext-mb-[4px] richtext-mt-[8px] !richtext-text-[0.65rem] richtext-uppercase ", children: o.title }),
o.commands.map((c, x) => /* @__PURE__ */ b(
"button",
{
onClick: () => R(n, x),
ref: (E) => H(n, x, E),
className: V("richtext-flex richtext-items-center richtext-gap-3 richtext-px-2 richtext-py-1.5 richtext-text-sm richtext-text-foreground richtext-text-left richtext-w-full richtext-rounded-sm !richtext-outline-none !richtext-border-none richtext-transition-colors !richtext-bg-transparent hover:!richtext-bg-accent ", {
"bg-item-active": s === n && t === x
}),
children: [
c.iconUrl && /* @__PURE__ */ d(
"img",
{
alt: "",
className: "richtext-size-6",
src: c.iconUrl
}
),
c.iconName && /* @__PURE__ */ d(
z,
{
className: "!richtext-mr-1 !richtext-text-lg",
name: c.iconName
}
),
c.label
]
},
`command-${x}`
))
] }, `slash-${o.title}`)) }) : /* @__PURE__ */ d("div", { className: "richtext-p-3", children: /* @__PURE__ */ d("span", { className: "richtext-text-xs richtext-text-foreground", children: p("editor.slash.empty") }) })
}
);
}
const Y = y(F);
export {
Y as S,
P as a,
X as r,
O as u
};