refactor: upgrade tiptap dependencies and enhance toolbar functionality
- Updated Tiptap dependencies to version 3.x, including core, extensions, and starter kit. - Added Link extension to the editor for hyperlink support. - Refactored ToolBar component to utilize useEditorState for better state management. - Enhanced toolbar with additional heading options (H5, H6) and improved button states for formatting actions. - Added a button to clear all marks in the editor.
This commit is contained in:
parent
0ea14d0650
commit
7a50ba4147
5 changed files with 423 additions and 4866 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
NEW IDEA TODOS:
|
NEW IDEA TODOS:
|
||||||
//TODO predere privacy policy sito vecchio e adattarla
|
|
||||||
|
|
||||||
- trigger pag sucecss event from ordini tab and gen payment button in order detail
|
- trigger pag sucecss event from ordini tab and gen payment button in order detail
|
||||||
|
|
||||||
|
|
|
||||||
5167
apps/infoalloggi/package-lock.json
generated
5167
apps/infoalloggi/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -32,10 +32,12 @@
|
||||||
"@tanstack/react-query": "^5.74.4",
|
"@tanstack/react-query": "^5.74.4",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"@tanstack/react-virtual": "^3.13.12",
|
"@tanstack/react-virtual": "^3.13.12",
|
||||||
"@tiptap/extension-underline": "^2.23.0",
|
"@tiptap/core": "^3.0.9",
|
||||||
"@tiptap/pm": "^2.25.0",
|
"@tiptap/extension-link": "^3.0.9",
|
||||||
"@tiptap/react": "^2.23.0",
|
"@tiptap/extension-underline": "^3.0.9",
|
||||||
"@tiptap/starter-kit": "^2.25.0",
|
"@tiptap/pm": "^3.0.9",
|
||||||
|
"@tiptap/react": "^3.0.9",
|
||||||
|
"@tiptap/starter-kit": "^3.0.9",
|
||||||
"@trpc/client": "^11.1.0",
|
"@trpc/client": "^11.1.0",
|
||||||
"@trpc/next": "^11.4.3",
|
"@trpc/next": "^11.4.3",
|
||||||
"@trpc/react-query": "^11.1.0",
|
"@trpc/react-query": "^11.1.0",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { useEditor, EditorContent } from "@tiptap/react";
|
import { useEditor, EditorContent } from "@tiptap/react";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import Underline from "@tiptap/extension-underline";
|
import Underline from "@tiptap/extension-underline";
|
||||||
|
import Link from "@tiptap/extension-link";
|
||||||
import ToolBar from "~/components/tip-tap/toolbar";
|
import ToolBar from "~/components/tip-tap/toolbar";
|
||||||
function Tiptap({
|
function Tiptap({
|
||||||
value,
|
value,
|
||||||
|
|
@ -13,7 +14,13 @@ function Tiptap({
|
||||||
id: string;
|
id: string;
|
||||||
}) {
|
}) {
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
extensions: [StarterKit, Underline],
|
extensions: [
|
||||||
|
StarterKit,
|
||||||
|
Underline,
|
||||||
|
Link.configure({
|
||||||
|
defaultProtocol: "https",
|
||||||
|
}),
|
||||||
|
],
|
||||||
content: value,
|
content: value,
|
||||||
editorProps: {
|
editorProps: {
|
||||||
attributes: {
|
attributes: {
|
||||||
|
|
@ -27,6 +34,10 @@ function Tiptap({
|
||||||
immediatelyRender: false,
|
immediatelyRender: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!editor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex h-full min-h-[250px] w-full flex-col justify-stretch"
|
className="flex h-full min-h-[250px] w-full flex-col justify-stretch"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { type Editor } from "@tiptap/react";
|
import { useEditorState, type Editor } from "@tiptap/react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Bold,
|
Bold,
|
||||||
|
BrushCleaning,
|
||||||
Heading1,
|
Heading1,
|
||||||
Heading2,
|
Heading2,
|
||||||
Heading3,
|
Heading3,
|
||||||
Heading4,
|
Heading4,
|
||||||
|
Heading5,
|
||||||
|
Heading6,
|
||||||
Italic,
|
Italic,
|
||||||
List,
|
List,
|
||||||
ListOrdered,
|
ListOrdered,
|
||||||
|
|
@ -21,26 +24,47 @@ import {
|
||||||
import { Toggle } from "~/components/ui/toggle";
|
import { Toggle } from "~/components/ui/toggle";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
||||||
type Props = {
|
function ToolBar({ editor }: { editor: Editor }) {
|
||||||
editor: Editor | null;
|
const editorState = useEditorState({
|
||||||
|
editor,
|
||||||
|
selector: (ctx) => {
|
||||||
|
return {
|
||||||
|
isBold: ctx.editor.isActive("bold") ?? false,
|
||||||
|
canBold: ctx.editor.can().chain().toggleBold().run() ?? false,
|
||||||
|
isItalic: ctx.editor.isActive("italic") ?? false,
|
||||||
|
canItalic: ctx.editor.can().chain().toggleItalic().run() ?? false,
|
||||||
|
isUnderline: ctx.editor.isActive("underline") ?? false,
|
||||||
|
canUnderline: ctx.editor.can().chain().toggleUnderline().run() ?? false,
|
||||||
|
isStrike: ctx.editor.isActive("strike") ?? false,
|
||||||
|
canStrike: ctx.editor.can().chain().toggleStrike().run() ?? false,
|
||||||
|
canClearMarks: ctx.editor.can().chain().unsetAllMarks().run() ?? false,
|
||||||
|
isParagraph: ctx.editor.isActive("paragraph") ?? false,
|
||||||
|
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,
|
||||||
|
isBulletList: ctx.editor.isActive("bulletList") ?? false,
|
||||||
|
isOrderedList: ctx.editor.isActive("orderedList") ?? false,
|
||||||
|
isBlockquote: ctx.editor.isActive("blockquote") ?? false,
|
||||||
|
canUndo: ctx.editor.can().chain().undo().run() ?? false,
|
||||||
|
canRedo: ctx.editor.can().chain().redo().run() ?? false,
|
||||||
};
|
};
|
||||||
|
},
|
||||||
function ToolBar({ editor }: Props) {
|
});
|
||||||
if (!editor) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-input my-2 flex flex-wrap gap-3 rounded-lg border p-1">
|
<div className="border-input my-2 flex flex-wrap gap-3 rounded-lg border p-1">
|
||||||
<Toggle
|
<Toggle
|
||||||
onPressedChange={() => editor.chain().focus().setParagraph().run()}
|
onPressedChange={() => editor.chain().focus().setParagraph().run()}
|
||||||
pressed={editor.isActive("paragraph")}
|
pressed={editorState.isParagraph}
|
||||||
>
|
>
|
||||||
<Text className="size-4" />
|
<Text className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("heading", { level: 1 })}
|
pressed={editorState.isHeading1}
|
||||||
onPressedChange={() =>
|
onPressedChange={() =>
|
||||||
editor.chain().focus().toggleHeading({ level: 1 }).run()
|
editor.chain().focus().toggleHeading({ level: 1 }).run()
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +73,7 @@ function ToolBar({ editor }: Props) {
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("heading", { level: 2 })}
|
pressed={editorState.isHeading2}
|
||||||
onPressedChange={() =>
|
onPressedChange={() =>
|
||||||
editor.chain().focus().toggleHeading({ level: 2 }).run()
|
editor.chain().focus().toggleHeading({ level: 2 }).run()
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +82,7 @@ function ToolBar({ editor }: Props) {
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("heading", { level: 3 })}
|
pressed={editorState.isHeading3}
|
||||||
onPressedChange={() =>
|
onPressedChange={() =>
|
||||||
editor.chain().focus().toggleHeading({ level: 3 }).run()
|
editor.chain().focus().toggleHeading({ level: 3 }).run()
|
||||||
}
|
}
|
||||||
|
|
@ -67,59 +91,81 @@ function ToolBar({ editor }: Props) {
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("heading", { level: 4 })}
|
pressed={editorState.isHeading4}
|
||||||
onPressedChange={() =>
|
onPressedChange={() =>
|
||||||
editor.chain().focus().toggleHeading({ level: 4 }).run()
|
editor.chain().focus().toggleHeading({ level: 4 }).run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Heading4 className="size-4" />
|
<Heading4 className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
|
<Toggle
|
||||||
|
size="sm"
|
||||||
|
pressed={editorState.isHeading5}
|
||||||
|
onPressedChange={() =>
|
||||||
|
editor.chain().focus().toggleHeading({ level: 5 }).run()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Heading5 className="size-4" />
|
||||||
|
</Toggle>
|
||||||
|
<Toggle
|
||||||
|
size="sm"
|
||||||
|
pressed={editorState.isHeading6}
|
||||||
|
onPressedChange={() =>
|
||||||
|
editor.chain().focus().toggleHeading({ level: 6 }).run()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Heading6 className="size-4" />
|
||||||
|
</Toggle>
|
||||||
|
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("bold")}
|
pressed={editorState.isBold}
|
||||||
|
disabled={!editorState.canBold}
|
||||||
onPressedChange={() => editor.chain().focus().toggleBold().run()}
|
onPressedChange={() => editor.chain().focus().toggleBold().run()}
|
||||||
>
|
>
|
||||||
<Bold className="size-4" />
|
<Bold className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("italic")}
|
pressed={editorState.isItalic}
|
||||||
|
disabled={!editorState.canItalic}
|
||||||
onPressedChange={() => editor.chain().focus().toggleItalic().run()}
|
onPressedChange={() => editor.chain().focus().toggleItalic().run()}
|
||||||
>
|
>
|
||||||
<Italic className="size-4" />
|
<Italic className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("underline")}
|
pressed={editorState.isUnderline}
|
||||||
|
disabled={!editorState.canUnderline}
|
||||||
onPressedChange={() => editor.chain().focus().toggleUnderline().run()}
|
onPressedChange={() => editor.chain().focus().toggleUnderline().run()}
|
||||||
>
|
>
|
||||||
<Underline className="size-4" />
|
<Underline className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("strike")}
|
pressed={editorState.isStrike}
|
||||||
|
disabled={!editorState.canStrike}
|
||||||
onPressedChange={() => editor.chain().focus().toggleStrike().run()}
|
onPressedChange={() => editor.chain().focus().toggleStrike().run()}
|
||||||
>
|
>
|
||||||
<StrikethroughIcon className="size-4" />
|
<StrikethroughIcon className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("bulletList")}
|
pressed={editorState.isBulletList}
|
||||||
onPressedChange={() => editor.chain().focus().toggleBulletList().run()}
|
onPressedChange={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
>
|
>
|
||||||
<List className="size-4" />
|
<List className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("orderedList")}
|
pressed={editorState.isOrderedList}
|
||||||
onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}
|
onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
>
|
>
|
||||||
<ListOrdered className="size-4" />
|
<ListOrdered className="size-4" />
|
||||||
</Toggle>
|
</Toggle>
|
||||||
<Toggle
|
<Toggle
|
||||||
size="sm"
|
size="sm"
|
||||||
pressed={editor.isActive("blockquote")}
|
pressed={editorState.isBlockquote}
|
||||||
onPressedChange={() => editor.chain().focus().toggleBlockquote().run()}
|
onPressedChange={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
>
|
>
|
||||||
<Quote className="size-4" />
|
<Quote className="size-4" />
|
||||||
|
|
@ -138,10 +184,19 @@ function ToolBar({ editor }: Props) {
|
||||||
>
|
>
|
||||||
Hard break
|
Hard break
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
type="button"
|
||||||
|
disabled={!editorState.canClearMarks}
|
||||||
|
onClick={() => editor.chain().focus().unsetAllMarks().run()}
|
||||||
|
>
|
||||||
|
<BrushCleaning className="size-4" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
type="button"
|
type="button"
|
||||||
|
disabled={!editorState.canUndo}
|
||||||
onClick={() => editor.chain().focus().undo().run()}
|
onClick={() => editor.chain().focus().undo().run()}
|
||||||
>
|
>
|
||||||
<Undo className="size-4" />
|
<Undo className="size-4" />
|
||||||
|
|
@ -149,6 +204,7 @@ function ToolBar({ editor }: Props) {
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
type="button"
|
type="button"
|
||||||
|
disabled={!editorState.canRedo}
|
||||||
onClick={() => editor.chain().focus().redo().run()}
|
onClick={() => editor.chain().focus().redo().run()}
|
||||||
>
|
>
|
||||||
<Redo className="size-4" />
|
<Redo className="size-4" />
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue