2023-11-15 17:18:45 +01:00
|
|
|
import { Editor } from '@tiptap/core';
|
2024-06-04 23:06:34 +02:00
|
|
|
import * as s from 'superstruct';
|
2023-11-15 17:18:45 +01:00
|
|
|
|
|
|
|
type EditorAction = {
|
|
|
|
run(): void;
|
|
|
|
isActive(): boolean;
|
|
|
|
isDisabled(): boolean;
|
|
|
|
};
|
|
|
|
|
|
|
|
export function getAction(
|
|
|
|
editor: Editor,
|
|
|
|
button: HTMLButtonElement
|
|
|
|
): EditorAction {
|
2024-06-04 23:06:34 +02:00
|
|
|
return s.create(button.dataset, tiptapActionSchema)(editor);
|
2023-11-15 17:18:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const EDITOR_ACTIONS: Record<string, (editor: Editor) => EditorAction> = {
|
|
|
|
title: (editor) => ({
|
|
|
|
run: () => editor.chain().focus(),
|
|
|
|
isActive: () => editor.isActive('title'),
|
|
|
|
isDisabled: () => !editor.isActive('title')
|
|
|
|
}),
|
|
|
|
heading2: (editor) => ({
|
2024-02-02 13:18:42 +01:00
|
|
|
run: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
2023-11-15 17:18:45 +01:00
|
|
|
isActive: () => editor.isActive('heading', { level: 2 }),
|
|
|
|
isDisabled: () =>
|
|
|
|
editor.isActive('title') ||
|
|
|
|
editor.isActive('header') ||
|
|
|
|
editor.isActive('footer')
|
|
|
|
}),
|
|
|
|
heading3: (editor) => ({
|
2024-02-02 13:18:42 +01:00
|
|
|
run: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
2023-11-15 17:18:45 +01:00
|
|
|
isActive: () => editor.isActive('heading', { level: 3 }),
|
|
|
|
isDisabled: () =>
|
|
|
|
editor.isActive('title') ||
|
|
|
|
editor.isActive('header') ||
|
|
|
|
editor.isActive('footer')
|
|
|
|
}),
|
|
|
|
bold: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleBold().run(),
|
|
|
|
isActive: () => editor.isActive('bold'),
|
|
|
|
isDisabled: () => editor.isActive('heading') || editor.isActive('title')
|
|
|
|
}),
|
|
|
|
italic: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleItalic().run(),
|
|
|
|
isActive: () => editor.isActive('italic'),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
underline: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleUnderline().run(),
|
|
|
|
isActive: () => editor.isActive('underline'),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
strike: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleStrike().run(),
|
|
|
|
isActive: () => editor.isActive('strike'),
|
|
|
|
isDisabled: () => editor.isActive('heading') || editor.isActive('title')
|
|
|
|
}),
|
|
|
|
highlight: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleHighlight().run(),
|
|
|
|
isActive: () => editor.isActive('highlight'),
|
|
|
|
isDisabled: () => editor.isActive('heading') || editor.isActive('title')
|
|
|
|
}),
|
|
|
|
bulletList: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleBulletList().run(),
|
|
|
|
isActive: () => editor.isActive('bulletList'),
|
|
|
|
isDisabled: () =>
|
|
|
|
editor.isActive('title') ||
|
|
|
|
editor.isActive('header') ||
|
|
|
|
editor.isActive('footer')
|
|
|
|
}),
|
|
|
|
orderedList: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().toggleOrderedList().run(),
|
|
|
|
isActive: () => editor.isActive('orderedList'),
|
|
|
|
isDisabled: () =>
|
|
|
|
editor.isActive('title') ||
|
|
|
|
editor.isActive('header') ||
|
|
|
|
editor.isActive('footer')
|
|
|
|
}),
|
|
|
|
left: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().setTextAlign('left').run(),
|
|
|
|
isActive: () => editor.isActive({ textAlign: 'left' }),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
center: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().setTextAlign('center').run(),
|
|
|
|
isActive: () => editor.isActive({ textAlign: 'center' }),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
right: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().setTextAlign('right').run(),
|
|
|
|
isActive: () => editor.isActive({ textAlign: 'right' }),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
justify: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().setTextAlign('justify').run(),
|
|
|
|
isActive: () => editor.isActive({ textAlign: 'justify' }),
|
|
|
|
isDisabled: () => false
|
|
|
|
}),
|
|
|
|
undo: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().undo().run(),
|
|
|
|
isActive: () => false,
|
|
|
|
isDisabled: () => !editor.can().chain().focus().undo().run()
|
|
|
|
}),
|
|
|
|
redo: (editor) => ({
|
|
|
|
run: () => editor.chain().focus().redo().run(),
|
|
|
|
isActive: () => false,
|
|
|
|
isDisabled: () => !editor.can().chain().focus().redo().run()
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2024-06-04 23:06:34 +02:00
|
|
|
const EditorActionFn = s.define<(editor: Editor) => EditorAction>(
|
|
|
|
'EditorActionFn',
|
|
|
|
(fn) => typeof fn == 'function'
|
|
|
|
);
|
|
|
|
|
|
|
|
const tiptapActionSchema = s.coerce(
|
|
|
|
EditorActionFn,
|
|
|
|
s.type({
|
|
|
|
tiptapAction: s.enums(Object.keys(EDITOR_ACTIONS) as [string, ...string[]])
|
|
|
|
}),
|
|
|
|
({ tiptapAction }) => EDITOR_ACTIONS[tiptapAction]
|
|
|
|
);
|