infoalloggi-monorepo/apps/infoalloggi/src/components/tip-tap/toolbar.tsx

217 lines
5.8 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
"use client";
2025-08-28 18:27:07 +02:00
import { type Editor, useEditorState } from "@tiptap/react";
2025-08-04 17:45:44 +02:00
import {
2025-08-28 18:27:07 +02:00
Bold,
BrushCleaning,
Heading1,
Heading2,
Heading3,
Heading4,
Heading5,
Heading6,
Italic,
List,
ListOrdered,
Quote,
Redo,
SeparatorHorizontal,
StrikethroughIcon,
Text,
Underline,
Undo,
2025-08-04 17:45:44 +02:00
} from "lucide-react";
import { Button } from "~/components/ui/button";
2025-08-28 18:27:07 +02:00
import { Toggle } from "~/components/ui/toggle";
2025-08-04 17:45:44 +02:00
function ToolBar({ editor }: { editor: Editor }) {
2025-08-28 18:27:07 +02:00
const editorState = useEditorState({
editor,
selector: (ctx) => {
return {
canBold: ctx.editor.can().chain().toggleBold().run() ?? false,
2025-08-29 16:18:32 +02:00
canClearMarks: ctx.editor.can().chain().unsetAllMarks().run() ?? false,
2025-08-28 18:27:07 +02:00
canItalic: ctx.editor.can().chain().toggleItalic().run() ?? false,
2025-08-29 16:18:32 +02:00
canRedo: ctx.editor.can().chain().redo().run() ?? false,
2025-08-28 18:27:07 +02:00
canStrike: ctx.editor.can().chain().toggleStrike().run() ?? false,
2025-08-29 16:18:32 +02:00
canUnderline: ctx.editor.can().chain().toggleUnderline().run() ?? false,
canUndo: ctx.editor.can().chain().undo().run() ?? false,
isBlockquote: ctx.editor.isActive("blockquote") ?? false,
isBold: ctx.editor.isActive("bold") ?? false,
isBulletList: ctx.editor.isActive("bulletList") ?? false,
2025-08-28 18:27:07 +02:00
isHeading1: ctx.editor.isActive("heading", { level: 1 }) ?? false,
isHeading2: ctx.editor.isActive("heading", { level: 2 }) ?? false,
isHeading3: ctx.editor.isActive("heading", { level: 3 }) ?? false,
isHeading4: ctx.editor.isActive("heading", { level: 4 }) ?? false,
isHeading5: ctx.editor.isActive("heading", { level: 5 }) ?? false,
isHeading6: ctx.editor.isActive("heading", { level: 6 }) ?? false,
2025-08-29 16:18:32 +02:00
isItalic: ctx.editor.isActive("italic") ?? false,
2025-08-28 18:27:07 +02:00
isOrderedList: ctx.editor.isActive("orderedList") ?? false,
2025-08-29 16:18:32 +02:00
isParagraph: ctx.editor.isActive("paragraph") ?? false,
isStrike: ctx.editor.isActive("strike") ?? false,
isUnderline: ctx.editor.isActive("underline") ?? false,
2025-08-28 18:27:07 +02:00
};
},
});
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
return (
2025-10-10 16:18:43 +02:00
<div className="my-2 flex flex-wrap gap-3 rounded-lg border border-input p-1">
2025-08-28 18:27:07 +02:00
<Toggle
onPressedChange={() => editor.chain().focus().setParagraph().run()}
pressed={editorState.isParagraph}
>
<Text className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 1 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading1}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading1 className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 2 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading2}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading2 className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 3 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading3}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading3 className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 4 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading4}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading4 className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 5 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading5}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading5 className="size-4" />
</Toggle>
<Toggle
onPressedChange={() =>
editor.chain().focus().toggleHeading({ level: 6 }).run()
}
2025-08-29 16:18:32 +02:00
pressed={editorState.isHeading6}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Heading6 className="size-4" />
</Toggle>
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
<Toggle
disabled={!editorState.canBold}
onPressedChange={() => editor.chain().focus().toggleBold().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isBold}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Bold className="size-4" />
</Toggle>
<Toggle
disabled={!editorState.canItalic}
onPressedChange={() => editor.chain().focus().toggleItalic().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isItalic}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Italic className="size-4" />
</Toggle>
<Toggle
disabled={!editorState.canUnderline}
onPressedChange={() => editor.chain().focus().toggleUnderline().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isUnderline}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Underline className="size-4" />
</Toggle>
<Toggle
disabled={!editorState.canStrike}
onPressedChange={() => editor.chain().focus().toggleStrike().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isStrike}
size="sm"
2025-08-28 18:27:07 +02:00
>
<StrikethroughIcon className="size-4" />
</Toggle>
<Toggle
onPressedChange={() => editor.chain().focus().toggleBulletList().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isBulletList}
size="sm"
2025-08-28 18:27:07 +02:00
>
<List className="size-4" />
</Toggle>
<Toggle
onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isOrderedList}
size="sm"
2025-08-28 18:27:07 +02:00
>
<ListOrdered className="size-4" />
</Toggle>
<Toggle
onPressedChange={() => editor.chain().focus().toggleBlockquote().run()}
2025-08-29 16:18:32 +02:00
pressed={editorState.isBlockquote}
size="sm"
2025-08-28 18:27:07 +02:00
>
<Quote className="size-4" />
</Toggle>
<Button
onClick={() => editor.chain().focus().setHorizontalRule().run()}
2025-08-29 16:18:32 +02:00
type="button"
variant="ghost"
2025-08-28 18:27:07 +02:00
>
<SeparatorHorizontal className="size-4" />
</Button>
<Button
onClick={() => editor.chain().focus().setHardBreak().run()}
2025-08-29 16:18:32 +02:00
type="button"
variant="ghost"
2025-08-28 18:27:07 +02:00
>
Hard break
</Button>
<Button
disabled={!editorState.canClearMarks}
onClick={() => editor.chain().focus().unsetAllMarks().run()}
2025-08-29 16:18:32 +02:00
type="button"
variant="ghost"
2025-08-28 18:27:07 +02:00
>
<BrushCleaning className="size-4" />
</Button>
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
<Button
disabled={!editorState.canUndo}
onClick={() => editor.chain().focus().undo().run()}
2025-08-29 16:18:32 +02:00
type="button"
variant="ghost"
2025-08-28 18:27:07 +02:00
>
<Undo className="size-4" />
</Button>
<Button
disabled={!editorState.canRedo}
onClick={() => editor.chain().focus().redo().run()}
2025-08-29 16:18:32 +02:00
type="button"
variant="ghost"
2025-08-28 18:27:07 +02:00
>
<Redo className="size-4" />
</Button>
</div>
);
2025-08-04 17:45:44 +02:00
}
export default ToolBar;