Skip to content

Commit bdb22bc

Browse files
Merge pull request #193 from Sibsankar-de/issue-190
Text editor updated and tools added.
2 parents 2f96e88 + 32e61c2 commit bdb22bc

7 files changed

Lines changed: 1428 additions & 235 deletions

File tree

savebook/app/globals.css

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
@import "tailwindcss";
22

3+
@plugin "@tailwindcss/typography";
4+
35
body {
4-
background-color: #101828;
6+
background-color: #101828;
57
}
68

79
input::-ms-reveal,

savebook/components/notes/AddNote.js

Lines changed: 78 additions & 144 deletions
Large diffs are not rendered by default.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
"use client"
2+
import React from 'react';
3+
import {
4+
Bold,
5+
Italic,
6+
Strikethrough,
7+
Code,
8+
List,
9+
ListOrdered,
10+
ListChecks,
11+
Quote,
12+
Heading1,
13+
Heading2,
14+
Heading3,
15+
Undo,
16+
Redo,
17+
Minus,
18+
Link as LinkIcon,
19+
Unlink
20+
} from 'lucide-react';
21+
import { clsx } from 'clsx';
22+
import { twMerge } from 'tailwind-merge';
23+
24+
const ToolbarButton = ({ onClick, isActive, disabled, children, title }) => {
25+
return (
26+
<button
27+
onClick={(e) => {
28+
e.preventDefault();
29+
onClick();
30+
}}
31+
disabled={disabled}
32+
title={title}
33+
className={twMerge(
34+
"p-1.5 rounded-md transition-colors duration-200 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed",
35+
isActive && "bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"
36+
)}
37+
>
38+
{children}
39+
</button>
40+
);
41+
};
42+
43+
const Divider = () => <div className="w-px h-5 bg-gray-200 dark:bg-gray-700 mx-1" />;
44+
45+
export default function EditorToolbar({ editor }) {
46+
if (!editor) {
47+
return null;
48+
}
49+
50+
const setLink = () => {
51+
const previousUrl = editor.getAttributes('link').href
52+
const url = window.prompt('URL', previousUrl)
53+
54+
// cancelled
55+
if (url === null) {
56+
return
57+
}
58+
59+
// empty
60+
if (url === '') {
61+
editor.chain().focus().extendMarkRange('link').unsetLink().run()
62+
return
63+
}
64+
65+
// update link
66+
editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run()
67+
}
68+
69+
return (
70+
<div className="flex flex-wrap items-center gap-1 p-2 border-b border-gray-600 bg-gray-900 rounded-t-lg">
71+
<ToolbarButton
72+
onClick={() => editor.chain().focus().toggleBold().run()}
73+
isActive={editor.isActive("bold")}
74+
title="Bold"
75+
>
76+
<Bold className="w-4 h-4" />
77+
</ToolbarButton>
78+
<ToolbarButton
79+
onClick={() => editor.chain().focus().toggleItalic().run()}
80+
isActive={editor.isActive("italic")}
81+
title="Italic"
82+
>
83+
<Italic className="w-4 h-4" />
84+
</ToolbarButton>
85+
<ToolbarButton
86+
onClick={() => editor.chain().focus().toggleStrike().run()}
87+
isActive={editor.isActive("strike")}
88+
title="Strikethrough"
89+
>
90+
<Strikethrough className="w-4 h-4" />
91+
</ToolbarButton>
92+
93+
<Divider />
94+
95+
<ToolbarButton
96+
onClick={setLink}
97+
isActive={editor.isActive('link')}
98+
title="Add Link"
99+
>
100+
<LinkIcon className="w-4 h-4" />
101+
</ToolbarButton>
102+
<ToolbarButton
103+
onClick={() => editor.chain().focus().unsetLink().run()}
104+
disabled={!editor.isActive('link')}
105+
title="Remove Link"
106+
>
107+
<Unlink className="w-4 h-4" />
108+
</ToolbarButton>
109+
110+
<Divider />
111+
112+
<ToolbarButton
113+
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
114+
isActive={editor.isActive("heading", { level: 1 })}
115+
title="Heading 1"
116+
>
117+
<Heading1 className="w-4 h-4" />
118+
</ToolbarButton>
119+
<ToolbarButton
120+
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
121+
isActive={editor.isActive("heading", { level: 2 })}
122+
title="Heading 2"
123+
>
124+
<Heading2 className="w-4 h-4" />
125+
</ToolbarButton>
126+
<ToolbarButton
127+
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
128+
isActive={editor.isActive("heading", { level: 3 })}
129+
title="Heading 3"
130+
>
131+
<Heading3 className="w-4 h-4" />
132+
</ToolbarButton>
133+
134+
<Divider />
135+
136+
<ToolbarButton
137+
onClick={() => editor.chain().focus().toggleBulletList().run()}
138+
isActive={editor.isActive("bulletList")}
139+
title="Bullet List"
140+
>
141+
<List className="w-4 h-4" />
142+
</ToolbarButton>
143+
<ToolbarButton
144+
onClick={() => editor.chain().focus().toggleOrderedList().run()}
145+
isActive={editor.isActive("orderedList")}
146+
title="Ordered List"
147+
>
148+
<ListOrdered className="w-4 h-4" />
149+
</ToolbarButton>
150+
<ToolbarButton
151+
onClick={() => editor.chain().focus().toggleTaskList().run()}
152+
isActive={editor.isActive("taskList")}
153+
title="Checklist"
154+
>
155+
<ListChecks className="w-4 h-4" />
156+
</ToolbarButton>
157+
158+
<Divider />
159+
160+
<ToolbarButton
161+
onClick={() => editor.chain().focus().toggleBlockquote().run()}
162+
isActive={editor.isActive("blockquote")}
163+
title="Blockquote"
164+
>
165+
<Quote className="w-4 h-4" />
166+
</ToolbarButton>
167+
<ToolbarButton
168+
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
169+
isActive={editor.isActive("codeBlock")}
170+
title="Code Block"
171+
>
172+
<Code className="w-4 h-4" />
173+
</ToolbarButton>
174+
<ToolbarButton
175+
onClick={() => editor.chain().focus().setHorizontalRule().run()}
176+
title="Horizontal Rule"
177+
>
178+
<Minus className="w-4 h-4" />
179+
</ToolbarButton>
180+
181+
<Divider />
182+
183+
<ToolbarButton
184+
onClick={() => editor.chain().focus().undo().run()}
185+
disabled={!editor.can().undo()}
186+
title="Undo"
187+
>
188+
<Undo className="w-4 h-4" />
189+
</ToolbarButton>
190+
<ToolbarButton
191+
onClick={() => editor.chain().focus().redo().run()}
192+
disabled={!editor.can().redo()}
193+
title="Redo"
194+
>
195+
<Redo className="w-4 h-4" />
196+
</ToolbarButton>
197+
</div>
198+
);
199+
}

0 commit comments

Comments
 (0)