diff --git a/frontends/ol-components/src/components/TiptapEditor/extensions/node/LearningResource/LearningResourceNode.tsx b/frontends/ol-components/src/components/TiptapEditor/extensions/node/LearningResource/LearningResourceNode.tsx index 2496d75320..8991cb43bc 100644 --- a/frontends/ol-components/src/components/TiptapEditor/extensions/node/LearningResource/LearningResourceNode.tsx +++ b/frontends/ol-components/src/components/TiptapEditor/extensions/node/LearningResource/LearningResourceNode.tsx @@ -1,7 +1,7 @@ import React from "react" import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react" import type { ReactNodeViewProps } from "@tiptap/react" -import { Node, mergeAttributes, type CommandProps } from "@tiptap/core" +import { Node, mergeAttributes } from "@tiptap/core" import { LearningResourceListCard, styled } from "ol-components" import { useLearningResourcesDetail } from "api/hooks/learningResources" @@ -76,11 +76,39 @@ export const LearningResourceNode = Node.create({ return { insertLearningResource: (resourceId: number, href?: string) => - ({ commands }: CommandProps) => { - return commands.insertContent({ - type: this.name, - attrs: { resourceId, href }, - }) + ({ state, tr, dispatch }) => { + const { $from } = state.selection + + const nodeType = state.schema.nodes.learningResource + const paragraphType = state.schema.nodes.paragraph + if (!nodeType) return false + + // 🛑 Guard: top-level selection + if ($from.depth === 0) { + tr.insert( + state.selection.from, + nodeType.create({ resourceId, href }), + ) + + dispatch?.(tr.scrollIntoView()) + return true + } + + // ✅ Replace the current block + const from = $from.before($from.depth) + const to = $from.after($from.depth) + + tr.replaceWith( + from, + to, + [ + nodeType.create({ resourceId, href }), + paragraphType?.create(), + ].filter(Boolean), + ) + + dispatch?.(tr.scrollIntoView()) + return true }, } }, diff --git a/frontends/ol-components/src/components/TiptapEditor/extensions/node/MediaEmbed/MediaEmbedNode.ts b/frontends/ol-components/src/components/TiptapEditor/extensions/node/MediaEmbed/MediaEmbedNode.ts index 17653b62d0..e3a0b8538a 100644 --- a/frontends/ol-components/src/components/TiptapEditor/extensions/node/MediaEmbed/MediaEmbedNode.ts +++ b/frontends/ol-components/src/components/TiptapEditor/extensions/node/MediaEmbed/MediaEmbedNode.ts @@ -50,11 +50,19 @@ export const MediaEmbedNode = Node.create({ return { insertMedia: (src: string) => - ({ commands }: CommandProps) => { - return commands.insertContent({ - type: this.name, - attrs: { src }, - }) + ({ state, chain }: CommandProps) => { + const { from } = state.selection + + return ( + chain() + .insertContentAt(from, { + type: this.name, + attrs: { src }, + }) + // 👇 Move cursor AFTER the inserted node + .setTextSelection(from + 2) + .run() + ) }, } },