File
Blob: src/client/components/editor/controllers/callout.ts
| 1 | import type { Editor, JSONContent, Range } from "@tiptap/core"; |
| 2 | import { DEFAULT_CALLOUT_KIND, normalizeCalloutKind, type CalloutKind } from "../extensions/callout/kinds"; |
| 3 | |
| 4 | export interface CalloutBlockAttrs { |
| 5 | kind?: CalloutKind; |
| 6 | } |
| 7 | |
| 8 | export function createCalloutNode(attrs: CalloutBlockAttrs = {}): JSONContent { |
| 9 | const kind = attrs.kind ? normalizeCalloutKind(attrs.kind) : DEFAULT_CALLOUT_KIND; |
| 10 | return { |
| 11 | type: "callout", |
| 12 | attrs: { kind }, |
| 13 | content: [{ type: "paragraph" }], |
| 14 | }; |
| 15 | } |
| 16 | |
| 17 | export function insertCalloutBlock(editor: Editor, range: Range, attrs: CalloutBlockAttrs = {}): boolean { |
| 18 | // After deleteRange + insertContent(callout > paragraph), positioning the |
| 19 | // caret at range.from + 2 lands inside the first empty paragraph (one |
| 20 | // step past the callout opening, one past the paragraph opening). |
| 21 | const caret = range.from + 2; |
| 22 | return editor |
| 23 | .chain() |
| 24 | .focus(null, { scrollIntoView: false }) |
| 25 | .deleteRange(range) |
| 26 | .insertContent(createCalloutNode(attrs)) |
| 27 | .setTextSelection(caret) |
| 28 | .run(); |
| 29 | } |