diff --git a/examples/01-basic/01-minimal/App.tsx b/examples/01-basic/01-minimal/App.tsx index a3b92bafd2..aa5f884ad5 100644 --- a/examples/01-basic/01-minimal/App.tsx +++ b/examples/01-basic/01-minimal/App.tsx @@ -1,12 +1,125 @@ +import { + BlockNoteSchema, + defaultInlineContentSpecs, + filterSuggestionItems, +} from "@blocknote/core"; import "@blocknote/core/fonts/inter.css"; import { BlockNoteView } from "@blocknote/mantine"; import "@blocknote/mantine/style.css"; -import { useCreateBlockNote } from "@blocknote/react"; +import { + DefaultReactSuggestionItem, + SuggestionMenuController, + useCreateBlockNote, +} from "@blocknote/react"; +import { Reference } from "./Reference"; export default function App() { - // Creates a new editor instance. - const editor = useCreateBlockNote(); + const schema = BlockNoteSchema.create({ + inlineContentSpecs: { + ...defaultInlineContentSpecs, + reference: Reference, + }, + }); + + const getReferenceMenuItems = ( + editor: typeof schema.BlockNoteEditor, + ): DefaultReactSuggestionItem[] => { + const citations = [ + { + key: 1, + doi: "10.1093/ajae/aaq063", + author: "Steve Smith", + title: "Understanding BlockNote", + journal: "BlockNote Journal", + year: 2023, + }, + { + key: 2, + doi: "10.1234/example.doi", + author: "Jane Doe", + title: "Exploring BlockNote Features", + journal: "BlockNote Features Journal", + year: 2022, + }, + { + key: 3, + doi: "10.5678/another.example", + author: "John Doe", + title: "Advanced BlockNote Techniques", + journal: "BlockNote Techniques Journal", + year: 2021, + }, + ]; + + return citations.map((citation) => ({ + title: citation.title, + onItemClick: () => { + editor.insertInlineContent([ + { + type: "reference", + props: { + ...citation, + }, + }, + " ", + ]); + }, + })); + }; + + + const editor = useCreateBlockNote({ + schema, + initialContent: [ + { + type: "paragraph", + content: "Welcome to this demo!", + }, + { + type: "paragraph", + content: [ + { + type: "text", + text: "Woah, you can add a reference like this: ", + styles: {}, + }, + { + type: "reference", + props: { + key: 1, + doi: "10.1093/ajae/aaq063", + author: "Steve Smith", + title: "Understanding BlockNote", + journal: "BlockNote Journal", + year: 2023, + }, + }, + { + type: "text", + text: " <- This is an example reference", + styles: {}, + }, + ], + }, + { + type: "paragraph", + content: "Press the '@' key to open the references menu and add another", + }, + { + type: "paragraph", + }, + ], + }); // Renders the editor instance using a React component. - return ; + return ( + + + filterSuggestionItems(getReferenceMenuItems(editor), query) + } + /> + + ); } diff --git a/examples/01-basic/01-minimal/Reference.tsx b/examples/01-basic/01-minimal/Reference.tsx new file mode 100644 index 0000000000..6ab9421415 --- /dev/null +++ b/examples/01-basic/01-minimal/Reference.tsx @@ -0,0 +1,71 @@ +import { createReactInlineContentSpec } from "@blocknote/react"; +import { useFloating, useHover, useInteractions } from "@floating-ui/react"; +import { useState } from "react"; +import "./styles.css"; + +export const Reference = createReactInlineContentSpec( + { + type: "reference", + propSchema: { + key: { + type: "number", + default: 1, + description: "The key for the reference.", + }, + doi: { + default: "Unknown", + }, + author: { + type: "string", + default: "Unknown Author", + }, + title: { + type: "string", + default: "Unknown Title", + }, + journal: { + type: "string", + default: "Unknown Journal", + }, + year: { + type: "number", + default: 2023, + }, + }, + content: "none", + }, + { + render: (props) => { + const [isOpen, setIsOpen] = useState(false); + + const { refs, floatingStyles, context } = useFloating({ + open: isOpen, + onOpenChange: setIsOpen, + }); + + const hover = useHover(context); + + const { getReferenceProps, getFloatingProps } = useInteractions([hover]); + + const citation = props.inlineContent.props; + + return ( + + + [{citation.key}] + + {isOpen && ( +
+ {citation.author}, {citation.title}, {citation.year} +
+ )} +
+ ); + }, + }, +); diff --git a/examples/01-basic/01-minimal/package.json b/examples/01-basic/01-minimal/package.json index 5179e10576..1f7cc8ecdf 100644 --- a/examples/01-basic/01-minimal/package.json +++ b/examples/01-basic/01-minimal/package.json @@ -15,6 +15,7 @@ "@blocknote/ariakit": "latest", "@blocknote/mantine": "latest", "@blocknote/shadcn": "latest", + "@floating-ui/react": "0.27.11", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -24,4 +25,4 @@ "@vitejs/plugin-react": "^4.3.1", "vite": "^5.3.4" } -} \ No newline at end of file +} diff --git a/examples/01-basic/01-minimal/styles.css b/examples/01-basic/01-minimal/styles.css new file mode 100644 index 0000000000..f2457adea0 --- /dev/null +++ b/examples/01-basic/01-minimal/styles.css @@ -0,0 +1,5 @@ +.floating { + background-color: black; + padding: 5px 10px; + border-radius: 5px; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38fa085186..4a18294878 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -234,6 +234,9 @@ importers: '@blocknote/shadcn': specifier: latest version: link:../../../packages/shadcn + '@floating-ui/react': + specifier: 0.27.11 + version: 0.27.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -6106,12 +6109,24 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' + '@floating-ui/react-dom@2.1.3': + resolution: {integrity: sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + '@floating-ui/react@0.26.28': resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' + '@floating-ui/react@0.27.11': + resolution: {integrity: sha512-ZVtJxk4gQceaAOm1p5TlNeUcSxvzEwbAkKPgLYfV2b3aavC9Up9OZ5qPWQrMCASzmXUtNK1VuKdrqZkhAYhaeQ==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} @@ -16812,6 +16827,12 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + '@floating-ui/react-dom@2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/dom': 1.6.13 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@floating-ui/react@0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16820,6 +16841,14 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tabbable: 6.2.0 + '@floating-ui/react@0.27.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/utils': 0.2.9 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tabbable: 6.2.0 + '@floating-ui/utils@0.2.9': {} '@hapi/hoek@9.3.0': {}