UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

399 lines (396 loc) 14.2 kB
import { ImageDialog } from "./chunk-LVDGCRQI.mjs"; import { MathNode } from "./chunk-NVNYYFHH.mjs"; import { FormulaDialog, processLatexInHtml } from "./chunk-FTQMDLZ5.mjs"; import "./chunk-IPVIZIHN.mjs"; import "./chunk-GKY77WVA.mjs"; import { normalizeLineBreaksInHtml } from "./chunk-QV5SUP4T.mjs"; import "./chunk-LI2FS7M2.mjs"; import "./chunk-WI3GQX74.mjs"; import "./chunk-EXVVHZOO.mjs"; import "./chunk-TNLGS7SB.mjs"; import "./chunk-Z2G5TBXF.mjs"; import { Button_default } from "./chunk-LAYB7IKW.mjs"; import { Text_default } from "./chunk-IMCIR6TJ.mjs"; import "./chunk-53ICLDGS.mjs"; import "./chunk-YG7W6JE3.mjs"; import "./chunk-AYI25BJ2.mjs"; import "./chunk-DG76FRXG.mjs"; import "./chunk-G7IP4VLI.mjs"; import "./chunk-RB5U4DHU.mjs"; // src/components/RichEditor/RichEditorCore.tsx import { EditorContent, useEditor } from "@tiptap/react"; // src/components/RichEditor/components/extensions.ts import StarterKit from "@tiptap/starter-kit"; import Underline from "@tiptap/extension-underline"; import TextAlign from "@tiptap/extension-text-align"; import { Color } from "@tiptap/extension-color"; import { TextStyle } from "@tiptap/extension-text-style"; import Highlight from "@tiptap/extension-highlight"; import Subscript from "@tiptap/extension-subscript"; import Superscript from "@tiptap/extension-superscript"; import Link from "@tiptap/extension-link"; import Placeholder from "@tiptap/extension-placeholder"; import Image from "@tiptap/extension-image"; function createRichEditorExtensions(placeholder) { return [ StarterKit, Underline, TextStyle, Color, Highlight.configure({ multicolor: true }), Subscript, Superscript, TextAlign.configure({ types: ["heading", "paragraph"] }), Link.configure({ openOnClick: false }), Placeholder.configure({ placeholder }), Image.configure({ inline: false, allowBase64: false }), MathNode ]; } // src/components/RichEditor/RichEditorCore.tsx import "katex/dist/katex.min.css"; import { TextBolderIcon } from "@phosphor-icons/react/dist/csr/TextB"; import { TextItalicIcon } from "@phosphor-icons/react/dist/csr/TextItalic"; import { TextUnderlineIcon } from "@phosphor-icons/react/dist/csr/TextUnderline"; import { TextStrikethroughIcon } from "@phosphor-icons/react/dist/csr/TextStrikethrough"; import { TextAlignLeftIcon } from "@phosphor-icons/react/dist/csr/TextAlignLeft"; import { TextAlignCenterIcon } from "@phosphor-icons/react/dist/csr/TextAlignCenter"; import { TextAlignRightIcon } from "@phosphor-icons/react/dist/csr/TextAlignRight"; import { TextAlignJustifyIcon } from "@phosphor-icons/react/dist/csr/TextAlignJustify"; import { LinkIcon } from "@phosphor-icons/react/dist/csr/Link"; import { ListBulletsIcon } from "@phosphor-icons/react/dist/csr/ListBullets"; import { ListNumbersIcon } from "@phosphor-icons/react/dist/csr/ListNumbers"; import { QuotesIcon } from "@phosphor-icons/react/dist/csr/Quotes"; import { MinusIcon } from "@phosphor-icons/react/dist/csr/Minus"; import { CodeIcon } from "@phosphor-icons/react/dist/csr/Code"; import { TextHOneIcon } from "@phosphor-icons/react/dist/csr/TextHOne"; import { TextHTwoIcon } from "@phosphor-icons/react/dist/csr/TextHTwo"; import { TextHThreeIcon } from "@phosphor-icons/react/dist/csr/TextHThree"; import { MathOperationsIcon } from "@phosphor-icons/react/dist/csr/MathOperations"; import { ImageIcon } from "@phosphor-icons/react/dist/csr/Image"; import { useState, useRef, useEffect } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; var ToolbarBtn = ({ onClick, active, title, children }) => /* @__PURE__ */ jsx( Button_default, { type: "button", onClick, title, size: "small", className: `bg-transparent border-transparent h-7 w-7 p-0 flex items-center justify-center rounded hover:bg-background-100 ${active ? "bg-background-200 text-primary-700" : "text-text-700"}`, children } ); var Divider = () => /* @__PURE__ */ jsx("div", { className: "w-px h-5 bg-border-200 mx-0.5" }); var prepareContent = (content) => processLatexInHtml(normalizeLineBreaksInHtml(content || "")); function RichEditor({ content, onChange, placeholder = "Digite aqui...", onGenerateLatexWithAI, onUploadImage }) { const [formulaOpen, setFormulaOpen] = useState(false); const [imageOpen, setImageOpen] = useState(false); const lastContentRef = useRef(content); const editor = useEditor({ extensions: createRichEditorExtensions(placeholder), content: prepareContent(content), // External updates do not reach this callback: the sync effect below calls // setContent with `emitUpdate: false`. onUpdate: ({ editor: editor2 }) => { const html = editor2.getHTML(); lastContentRef.current = html; onChange?.({ json: editor2.getJSON(), html }); }, editorProps: { attributes: { class: "min-h-[120px] outline-none prose prose-sm max-w-none px-4 py-3 focus:outline-none" } } }); useEffect(() => { if (editor && content !== void 0 && content !== lastContentRef.current) { editor.commands.setContent(prepareContent(content), { emitUpdate: false }); lastContentRef.current = content; } }, [content, editor]); const insertFormula = (latex) => { if (!latex || !editor) return; editor.chain().focus().insertContent({ type: "mathInline", attrs: { latex } }).run(); setFormulaOpen(false); }; const insertImage = (src, alt) => { if (!src || !editor) return; editor.chain().focus().setImage({ src, alt }).run(); setImageOpen(false); }; const setLink = () => { const url = globalThis.window.prompt("URL do link:"); if (url === null || !editor) return; if (url === "") { editor.chain().focus().extendMarkRange("link").unsetLink().run(); return; } editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run(); }; if (!editor) return null; return /* @__PURE__ */ jsxs("div", { className: "border border-border-200 rounded-xl overflow-hidden bg-background-0", children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 border-b border-border-200 bg-background-50 px-2 py-1.5 flex-wrap", children: [ /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(), active: editor.isActive("heading", { level: 1 }), title: "T\xEDtulo 1", children: /* @__PURE__ */ jsx(TextHOneIcon, { size: 16, weight: "bold" }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(), active: editor.isActive("heading", { level: 2 }), title: "T\xEDtulo 2", children: /* @__PURE__ */ jsx(TextHTwoIcon, { size: 16, weight: "bold" }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(), active: editor.isActive("heading", { level: 3 }), title: "T\xEDtulo 3", children: /* @__PURE__ */ jsx(TextHThreeIcon, { size: 16, weight: "bold" }) } ), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: "Negrito (Ctrl+B)", children: /* @__PURE__ */ jsx(TextBolderIcon, { size: 16, weight: "bold" }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: "It\xE1lico (Ctrl+I)", children: /* @__PURE__ */ jsx(TextItalicIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleUnderline().run(), active: editor.isActive("underline"), title: "Sublinhado (Ctrl+U)", children: /* @__PURE__ */ jsx(TextUnderlineIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: "Tachado", children: /* @__PURE__ */ jsx(TextStrikethroughIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleSubscript().run(), active: editor.isActive("subscript"), title: "Subscrito", children: /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [ "X", /* @__PURE__ */ jsx("sub", { className: "text-[8px]", children: "2" }) ] }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleSuperscript().run(), active: editor.isActive("superscript"), title: "Sobrescrito", children: /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium", children: [ "X", /* @__PURE__ */ jsx("sup", { className: "text-[8px]", children: "2" }) ] }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: "C\xF3digo inline", children: /* @__PURE__ */ jsx(CodeIcon, { size: 16 }) } ), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().setTextAlign("left").run(), active: editor.isActive({ textAlign: "left" }), title: "Alinhar \xE0 esquerda", children: /* @__PURE__ */ jsx(TextAlignLeftIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().setTextAlign("center").run(), active: editor.isActive({ textAlign: "center" }), title: "Centralizar", children: /* @__PURE__ */ jsx(TextAlignCenterIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().setTextAlign("right").run(), active: editor.isActive({ textAlign: "right" }), title: "Alinhar \xE0 direita", children: /* @__PURE__ */ jsx(TextAlignRightIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().setTextAlign("justify").run(), active: editor.isActive({ textAlign: "justify" }), title: "Justificar", children: /* @__PURE__ */ jsx(TextAlignJustifyIcon, { size: 16 }) } ), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleBulletList().run(), active: editor.isActive("bulletList"), title: "Lista com marcadores", children: /* @__PURE__ */ jsx(ListBulletsIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleOrderedList().run(), active: editor.isActive("orderedList"), title: "Lista numerada", children: /* @__PURE__ */ jsx(ListNumbersIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().toggleBlockquote().run(), active: editor.isActive("blockquote"), title: "Cita\xE7\xE3o", children: /* @__PURE__ */ jsx(QuotesIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => editor.chain().focus().setHorizontalRule().run(), active: false, title: "Linha horizontal", children: /* @__PURE__ */ jsx(MinusIcon, { size: 16 }) } ), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: setLink, active: editor.isActive("link"), title: "Inserir link", children: /* @__PURE__ */ jsx(LinkIcon, { size: 16 }) } ), /* @__PURE__ */ jsx( ToolbarBtn, { onClick: () => setImageOpen(true), active: editor.isActive("image"), title: "Inserir imagem", children: /* @__PURE__ */ jsx(ImageIcon, { size: 16 }) } ), /* @__PURE__ */ jsxs( Button_default, { type: "button", onClick: () => setFormulaOpen(true), title: "Inserir f\xF3rmula LaTeX", size: "extra-small", variant: "link", children: [ /* @__PURE__ */ jsx(MathOperationsIcon, { size: 16 }), "LaTeX" ] } ) ] }), /* @__PURE__ */ jsx(EditorContent, { editor }), /* @__PURE__ */ jsx("div", { className: "border-t border-border-200 px-4 py-2 bg-background-50", children: /* @__PURE__ */ jsxs(Text_default, { size: "xs", color: "text-text-400", children: [ "Dica: use", " ", /* @__PURE__ */ jsx("code", { className: "bg-background-200 px-1 rounded", children: "$f\xF3rmula$" }), " para inserir LaTeX inline diretamente." ] }) }), /* @__PURE__ */ jsx( FormulaDialog, { open: formulaOpen, onClose: () => setFormulaOpen(false), onInsert: insertFormula, onGenerateWithAI: onGenerateLatexWithAI } ), /* @__PURE__ */ jsx( ImageDialog, { open: imageOpen, onClose: () => setImageOpen(false), onInsert: insertImage, onUploadImage } ) ] }); } export { RichEditor }; //# sourceMappingURL=RichEditorCore-ZGHPGZXZ.mjs.map