diff --git a/examples/06-custom-schema/05-equation/.bnexample.json b/examples/06-custom-schema/05-equation/.bnexample.json new file mode 100644 index 000000000..896230e29 --- /dev/null +++ b/examples/06-custom-schema/05-equation/.bnexample.json @@ -0,0 +1,11 @@ +{ + "playground": true, + "docs": false, + "author": "jkcs", + "tags": ["Equation", "Inline Equation", "Custom Schemas", "Latex", "Katex"], + "dependencies": { + "katex": "^0.16.11", + "@types/katex": "^0.16.7", + "react-icons": "^5.2.1" + } +} diff --git a/examples/06-custom-schema/05-equation/App.tsx b/examples/06-custom-schema/05-equation/App.tsx new file mode 100644 index 000000000..f5c7c4215 --- /dev/null +++ b/examples/06-custom-schema/05-equation/App.tsx @@ -0,0 +1,90 @@ +import { + BlockNoteSchema, + defaultInlineContentSpecs, + filterSuggestionItems, +} from "@blocknote/core"; +import "@blocknote/core/fonts/inter.css"; +import { BlockNoteView } from "@blocknote/mantine"; +import "@blocknote/mantine/style.css"; +import { + SuggestionMenuController, + getDefaultReactSlashMenuItems, + useCreateBlockNote, +} from "@blocknote/react"; +import { RiFormula } from "react-icons/ri"; + +import { InlineEquation } from "./Equation"; + +// Our schema with block specs, which contain the configs and implementations for blocks +// that we want our editor to use. +const schema = BlockNoteSchema.create({ + inlineContentSpecs: { + ...defaultInlineContentSpecs, + inlineEquation: InlineEquation, + }, +}); + +const insertInlineEquation = (editor: typeof schema.BlockNoteEditor) => ({ + icon: , + title: "Inline Equation", + key: "inlineEquation", + subtext: "Insert mathematical symbols in text.", + aliases: ["equation", "latex", "katex"], + group: "Other", + onItemClick: () => { + editor.insertInlineContent([ + { + type: "inlineEquation", + }, + " ", // add a space after the mention + ]); + }, +}); + +export default function App() { + const editor = useCreateBlockNote({ + schema, + initialContent: [ + { + type: "paragraph", + content: [ + "This is an example inline equation ", + { + type: "inlineEquation", + props: { + content: "c = \\pm\\sqrt{a^2 + b^2}", + }, + }, + ], + }, + { + type: "paragraph", + content: "Press the '/' key to open the Slash Menu and add another", + }, + { + type: "paragraph", + }, + { + type: "paragraph", + }, + ], + }); + + // Renders the editor instance. + return ( + + + filterSuggestionItems( + [ + ...getDefaultReactSlashMenuItems(editor), + insertInlineEquation(editor), + ], + query + ) + } + /> + + ); +} diff --git a/examples/06-custom-schema/05-equation/Equation.tsx b/examples/06-custom-schema/05-equation/Equation.tsx new file mode 100644 index 000000000..512efa369 --- /dev/null +++ b/examples/06-custom-schema/05-equation/Equation.tsx @@ -0,0 +1,250 @@ +import { InlineContentFromConfig } from "@blocknote/core"; +import { + createReactInlineContentSpec, + useBlockNoteEditor, + useComponentsContext, +} from "@blocknote/react"; +import { Node as TipTapNode } from "@tiptap/pm/model"; +import { NodeViewWrapper } from "@tiptap/react"; +import katex from "katex"; +import "katex/dist/katex.min.css"; +import { + ChangeEvent, + MouseEvent as ReactMouseEvent, + TextareaHTMLAttributes, + forwardRef, + useCallback, + useEffect, + useMemo, + useRef, +} from "react"; +import { AiOutlineEnter } from "react-icons/ai"; +import "./styles.css"; + +const TextareaView = forwardRef< + HTMLTextAreaElement, + { + autofocus?: boolean; + } & TextareaHTMLAttributes +>((props, ref) => { + const { autofocus, ...rest } = props; + useEffect(() => { + if (autofocus && ref && typeof ref !== "function" && ref.current) { + ref.current.setSelectionRange(0, ref.current.value.length); + ref.current.focus(); + } + }, [autofocus, ref]); + + return ( +