@explita/editor
Version:
`@explita/editor` is a versatile, modern rich-text editor built on TipTap for seamless integration into React applications. It provides extensive customization options and advanced features to cater to diverse content creation needs.
58 lines (57 loc) • 6.23 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, } from "./ui/menubar";
import { FaFilePdf } from "react-icons/fa";
import { LuBold, LuGlobe, LuItalic, LuPrinter, LuRedo2, LuRemoveFormatting, LuSave, LuStrikethrough, LuText, LuTextCursor, LuUnderline, LuUndo2, LuX, } from "react-icons/lu";
import { TiExport } from "react-icons/ti";
import { BsFiletypeJson } from "react-icons/bs";
import { useEditorStore } from "../store/useEditorState";
import { FiEdit } from "react-icons/fi";
export function MenuBar({ onCreateNew, onSave, onClose }) {
const { editor } = useEditorStore();
function insertTable(selected) {
editor
?.chain()
.focus()
.insertTable({ rows: selected, cols: selected, withHeaderRow: false })
.run();
}
function onExport(blob, filename) {
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}
function onExportJSON() {
if (!editor)
return;
const json = editor?.getJSON();
const blob = new Blob([JSON.stringify(json)], { type: "application/json" });
onExport(blob, "document.json");
}
function onExportHTML() {
if (!editor)
return;
const html = editor?.getHTML();
const blob = new Blob([html], { type: "text/html" });
onExport(blob, "document.html");
}
function onExportText() {
if (!editor)
return;
const text = editor?.getText();
const blob = new Blob([text], { type: "text/plain" });
onExport(blob, "document.txt");
}
return (_jsx("div", { className: "px-4", children: _jsxs(Menubar, { className: "border-none bg-transparent shadow-none h-auto p-0", children: [_jsxs(MenubarMenu, { children: [_jsx(MenubarTrigger, { className: "menu-trigger", children: "File" }), _jsxs(MenubarContent, { className: "print:hidden", children: [_jsxs(MenubarItem, { className: "gap-2", onClick: onCreateNew, children: [_jsx(FiEdit, { size: 16 }), "New Document"] }), _jsxs(MenubarSub, { children: [_jsxs(MenubarSubTrigger, { className: "gap-2", children: [_jsx(TiExport, { size: 16 }), "Export as"] }), _jsxs(MenubarSubContent, { children: [_jsxs(MenubarItem, { className: "gap-2", onClick: () => {
if (confirm(`To export the document as a PDF, click the 'Print' button below, on the menubar or toolbar. Then, in the print dialog box that appears, select 'Save as PDF' and click 'Save' button to save the document.`))
window.print();
}, children: [_jsx(FaFilePdf, { size: 16 }), "PDF"] }), _jsxs(MenubarItem, { className: "gap-2", onClick: onExportHTML, children: [_jsx(LuGlobe, { size: 16 }), "HTML"] }), _jsxs(MenubarItem, { className: "gap-2", onClick: onExportJSON, children: [_jsx(BsFiletypeJson, { size: 16 }), "JSON"] }), _jsxs(MenubarItem, { className: "gap-2", onClick: onExportText, children: [_jsx(LuTextCursor, { size: 16 }), "Text"] })] })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => window.print(), children: [_jsx(LuPrinter, { size: 16 }), "Print Document"] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => onSave?.(editor?.getHTML() || ""), children: [_jsx(LuSave, { size: 16 }), "Save"] }), _jsx(MenubarSeparator, {}), _jsxs(MenubarItem, { className: "gap-2", onClick: onClose, children: [_jsx(LuX, { size: 16 }), "Close"] })] })] }), _jsxs(MenubarMenu, { children: [_jsx(MenubarTrigger, { className: "menu-trigger", children: "Edit" }), _jsxs(MenubarContent, { children: [_jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().undo().run(), children: [_jsx(LuUndo2, { size: 16 }), "Undo", _jsx(MenubarShortcut, { children: "Ctrl+Z" })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().redo().run(), children: [_jsx(LuRedo2, { size: 16 }), "Redo", _jsx(MenubarShortcut, { children: "Ctrl+Y" })] })] })] }), _jsxs(MenubarMenu, { children: [_jsx(MenubarTrigger, { className: "menu-trigger", children: "Insert" }), _jsx(MenubarContent, { children: _jsxs(MenubarSub, { children: [_jsx(MenubarSubTrigger, { children: "Table" }), _jsx(MenubarSubContent, { children: Array.from({ length: 5 }, (_, i) => i + 1).map((n) => (_jsx(MenubarItem, { onClick: () => insertTable(n), children: `${n} x ${n}` }, n))) })] }) })] }), _jsxs(MenubarMenu, { children: [_jsx(MenubarTrigger, { className: "menu-trigger", children: "Format" }), _jsxs(MenubarContent, { children: [_jsxs(MenubarSub, { children: [_jsxs(MenubarSubTrigger, { className: "gap-2", children: [_jsx(LuText, { size: 16 }), "Text"] }), _jsxs(MenubarSubContent, { children: [_jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().toggleBold().run(), children: [_jsx(LuBold, { size: 16 }), "Bold", _jsx(MenubarShortcut, { children: "Ctrl+B" })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().toggleItalic().run(), children: [_jsx(LuItalic, { size: 16 }), "Italic", _jsx(MenubarShortcut, { children: "Ctrl+I" })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().toggleUnderline().run(), children: [_jsx(LuUnderline, { size: 16 }), "Underline", _jsx(MenubarShortcut, { children: "Ctrl+U" })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().toggleStrike().run(), children: [_jsx(LuStrikethrough, { size: 16 }), "Strikethrough \u00A0 \u00A0", _jsx(MenubarShortcut, { children: "Ctrl+K" })] })] })] }), _jsxs(MenubarItem, { className: "gap-2", onClick: () => editor?.chain().focus().unsetAllMarks().run(), children: [_jsx(LuRemoveFormatting, { size: 16 }), "Clear Formatting"] })] })] })] }) }));
}
MenuBar.defaultProps = {
onCreateNew: () => { },
onSave: () => { },
onClose: () => { },
};