diff --git a/frontend/packages/app/src/models/documents.ts b/frontend/packages/app/src/models/documents.tsx
similarity index 94%
rename from frontend/packages/app/src/models/documents.ts
rename to frontend/packages/app/src/models/documents.tsx
index b741f7b91d..de6c4e2ca9 100644
--- a/frontend/packages/app/src/models/documents.ts
+++ b/frontend/packages/app/src/models/documents.tsx
@@ -8,6 +8,8 @@ import {editorBlockToServerBlock} from '@mintter/app/src/client/editor-to-server
import {serverChildrenToEditorChildren} from '@mintter/app/src/client/server-to-editor'
import {useOpenUrl} from '@mintter/app/src/open-url'
import {toast} from '@mintter/app/src/toast'
+import {insertOrUpdateBlock} from '@mintter/editor'
+import {RiFile2Fill, RiImage2Fill, RiText, RiVideoAddFill} from 'react-icons/ri'
import {
Block,
BlockIdentifier,
@@ -786,18 +788,71 @@ export function useDraftEditor(
queryClient,
openUrl,
},
+
onEditorReady: (e) => {
readyThings.current[0] = e
handleMaybeReady()
},
blockSchema: hmBlockSchema,
- // slashCommands: [
- // ...defaultReactSlashMenuItems.slice(0, 2),
- // insertImage,
- // insertFile,
- // insertVideo,
- // ...defaultReactSlashMenuItems.slice(2),
- // ],
+ slashMenuItems: [
+ {
+ name: 'Paragraph',
+ aliases: ['p'],
+ icon: ,
+ execute: (editor) =>
+ insertOrUpdateBlock(editor, {
+ type: 'paragraph',
+ } as PartialBlock),
+ },
+ {
+ name: 'Heading',
+ aliases: ['h', 'heading1', 'subheading'],
+ execute: (editor) =>
+ insertOrUpdateBlock(editor, {
+ type: 'heading',
+ props: {level: '2'},
+ } as PartialBlock),
+ },
+ {
+ name: 'Image',
+ aliases: ['image', 'img', 'picture'],
+ icon: ,
+ hint: 'Insert a Image',
+ execute: (editor) =>
+ insertOrUpdateBlock(editor, {
+ type: 'image',
+ props: {
+ url: '',
+ },
+ } as PartialBlock),
+ },
+ {
+ name: 'Video',
+ aliases: ['video', 'vid', 'media'],
+ icon: ,
+ hint: 'Insert a video',
+ execute: (editor) =>
+ insertOrUpdateBlock(editor, {
+ type: 'video',
+ props: {
+ url: '',
+ },
+ } as PartialBlock),
+ },
+ {
+ name: 'File',
+ aliases: ['file', 'folder'],
+ icon: ,
+ hint: 'Insert a File',
+ execute: (editor) =>
+ insertOrUpdateBlock(editor, {
+ type: 'file',
+ props: {
+ url: '',
+ },
+ } as PartialBlock),
+ },
+ ],
_tiptapOptions: {
extensions: [
diff --git a/frontend/packages/app/src/pages/publication.tsx b/frontend/packages/app/src/pages/publication.tsx
index 409dbb4fde..296afe1d08 100644
--- a/frontend/packages/app/src/pages/publication.tsx
+++ b/frontend/packages/app/src/pages/publication.tsx
@@ -136,7 +136,6 @@ export function PublicationPageEditor() {
const docId = route?.documentId
const versionId = route?.versionId
- const blockId = route?.blockId
const accessory = route?.accessory
const accessoryKey = accessory?.key
const replace = useNavigate('replace')
@@ -146,11 +145,6 @@ export function PublicationPageEditor() {
)
const publication = usePublicationEditor(docId, versionId, route.pubContext)
- // this checks if there's a block in the url, so we can highlight and scroll into the selected block
- let [focusBlock] = useState(() => blockId)
-
- // useScrollToBlock(editor, scrollWrapperRef, focusBlock)
-
const {data: changes} = useDocChanges(
publication.status == 'success' ? docId : undefined,
)
@@ -287,29 +281,6 @@ type ResizablePanelMachineServices = {
}
}
-// eslint-disable-next-line
-// function useScrollToBlock(editor: SlateEditor, ref: any, blockId?: string) {
-// // TODO: find a way to scroll to the block when clicking on a mintter link
-// useEffect(() => {
-// setTimeout(() => {
-// if (blockId) {
-// if (ref?.current) {
-// let entry = getEditorBlock(editor, {id: blockId})
-
-// if (entry) {
-// let [block] = entry
-// let elm = ReactEditor.toDOMNode(editor, block)
-
-// let rect = elm.getBoundingClientRect()
-// let wrapper = ref.current.getBoundingClientRect()
-// ref.current.scrollTo({top: rect.top - wrapper.top - 24})
-// }
-// }
-// }
-// }, 1000)
-// }, [ref, blockId, editor])
-// }
-
function OutOfDateBanner({docId, version}: {docId: string; version: string}) {
const route = useNavRoute()
const context = route.key === 'publication' ? route.pubContext : undefined
diff --git a/frontend/packages/editor/src/block-utils.ts b/frontend/packages/editor/src/block-utils.ts
new file mode 100644
index 0000000000..ca3f04e8c6
--- /dev/null
+++ b/frontend/packages/editor/src/block-utils.ts
@@ -0,0 +1,34 @@
+import {Block as BlockNoteBlock, BlockNoteEditor} from './blocknote'
+import {HMBlockSchema} from './schema'
+import {useEffect, useState} from 'react'
+import {getBlockInfoFromPos} from './blocknote'
+
+export function useSelected(
+ block: BlockNoteBlock,
+ editor: BlockNoteEditor,
+) {
+ const [selected, setSelected] = useState(false)
+ const tiptapEditor = editor._tiptapEditor
+ const selection = tiptapEditor.state.selection
+
+ useEffect(() => {
+ if (editor) {
+ const selectedNode = getBlockInfoFromPos(
+ tiptapEditor.state.doc,
+ tiptapEditor.state.selection.from,
+ )
+ if (selectedNode && selectedNode.id) {
+ if (
+ selectedNode.id === block.id &&
+ selectedNode.startPos === selection.$anchor.pos
+ ) {
+ setSelected(true)
+ } else if (selectedNode.id !== block.id) {
+ setSelected(false)
+ }
+ }
+ }
+ }, [selection])
+
+ return selected
+}
diff --git a/frontend/packages/editor/src/blocknote/react/SlashMenu/components/SlashMenuPositioner.tsx b/frontend/packages/editor/src/blocknote/react/SlashMenu/components/SlashMenuPositioner.tsx
index 707885ad14..0b029a23f4 100644
--- a/frontend/packages/editor/src/blocknote/react/SlashMenu/components/SlashMenuPositioner.tsx
+++ b/frontend/packages/editor/src/blocknote/react/SlashMenu/components/SlashMenuPositioner.tsx
@@ -29,8 +29,14 @@ export const SlashMenuPositioner = <
useState[]>()
const [keyboardHoveredItemIndex, setKeyboardHoveredItemIndex] =
useState()
+ const scroller = useRef(null)
const referencePos = useRef()
+ useEffect(() => {
+ setTimeout(() => {
+ scroller.current = document.getElementById('scroll-page-wrapper')
+ }, 100)
+ }, [])
useEffect(() => {
return props.editor.slashMenu.onUpdate((slashMenuState) => {
@@ -76,7 +82,7 @@ export const SlashMenuPositioner = <
return (
- {/* */}
+
)
diff --git a/frontend/packages/editor/src/embed-block.tsx b/frontend/packages/editor/src/embed-block.tsx
index 76ecf23127..1fd4bdd2e1 100644
--- a/frontend/packages/editor/src/embed-block.tsx
+++ b/frontend/packages/editor/src/embed-block.tsx
@@ -32,6 +32,7 @@ import {
import {getBlockInfoFromPos} from './blocknote/core'
import {createReactBlockSpec} from './blocknote/react'
import {HMBlockSchema, hmBlockSchema} from './schema'
+import {useSelected} from './block-utils'
const EditorText = styled(Text, {
fontSize: '$5',
@@ -238,36 +239,6 @@ function StaticEmbedPresentation({block}: {block: EmbedBlockType}) {
)
}
-function useSelected(
- block: BlockNoteBlock,
- editor: BlockNoteEditor,
-) {
- const [selected, setSelected] = useState(false)
- const tiptapEditor = editor._tiptapEditor
- const selection = tiptapEditor.state.selection
-
- useEffect(() => {
- if (editor) {
- const selectedNode = getBlockInfoFromPos(
- tiptapEditor.state.doc,
- tiptapEditor.state.selection.from,
- )
- if (selectedNode && selectedNode.id) {
- if (
- selectedNode.id === block.id &&
- selectedNode.startPos === selection.$anchor.pos
- ) {
- setSelected(true)
- } else if (selectedNode.id !== block.id) {
- setSelected(false)
- }
- }
- }
- }, [selection])
-
- return selected
-}
-
export function StaticBlockNode({block}: {block: BlockNode}) {
const children =
block.children.length > 0 ? (
diff --git a/frontend/packages/editor/src/image.tsx b/frontend/packages/editor/src/image.tsx
index 85a91c0421..c08be95563 100644
--- a/frontend/packages/editor/src/image.tsx
+++ b/frontend/packages/editor/src/image.tsx
@@ -1,4 +1,5 @@
import {useAppContext} from '@mintter/app/src/app-context'
+import {toast} from '@mintter/app/src/toast'
import {BACKEND_FILE_UPLOAD_URL, BACKEND_FILE_URL} from '@mintter/shared'
import {
Button,
@@ -13,18 +14,16 @@ import {
useTheme,
} from '@mintter/ui'
import {ChangeEvent, useEffect, useState} from 'react'
-import {RiImage2Fill, RiImage2Line} from 'react-icons/ri'
+import {RiImage2Line} from 'react-icons/ri'
import {
Block,
BlockNoteEditor,
- DefaultBlockSchema,
createReactBlockSpec,
defaultProps,
getBlockInfoFromPos,
- insertOrUpdateBlock,
} from './blocknote'
-import {HMBlockSchema} from './schema'
import {InlineContent} from './blocknote/react'
+import {HMBlockSchema} from './schema'
export const ImageBlock = createReactBlockSpec({
type: 'image',
diff --git a/frontend/packages/ui/src/layout.tsx b/frontend/packages/ui/src/layout.tsx
index 88ba420574..6fa7d70042 100644
--- a/frontend/packages/ui/src/layout.tsx
+++ b/frontend/packages/ui/src/layout.tsx
@@ -19,7 +19,12 @@ export const MainWrapper = ({
noScroll?: boolean
}) => (
- {noScroll ? children : {children}}
+ {noScroll ? (
+ children
+ ) : (
+ // TODO: we cannot remove this ID here because the SlashMenu is referencing this!
+ {children}
+ )}
)