@@ -5,15 +5,26 @@ import Placeholder from '@tiptap/extension-placeholder'
5
5
import { Heading } from '@tiptap/extension-heading'
6
6
import { useLocalStorageValue } from "@react-hookz/web"
7
7
import { CREATE_CACHE } from "../constants"
8
+ import { BulletList } from "@tiptap/extension-bullet-list"
9
+ import { OrderedList } from "@tiptap/extension-ordered-list"
10
+ import { ListItem } from "@tiptap/extension-list-item"
11
+ import { Image } from "@tiptap/extension-image"
12
+ import { UploadImageDialog } from "./UploadImageDialog"
13
+ import { useState } from "react"
8
14
9
15
export const Tiptap = ( ) => {
16
+ const [ openImageDialog , setOpenImageDialog ] = useState ( false )
10
17
const [ , setCache ] = useLocalStorageValue < any > ( CREATE_CACHE )
11
18
const editor = useEditor ( {
12
19
onUpdate : ( { editor : e } ) => {
13
20
const json = e . getJSON ( )
14
21
setCache ( json )
15
22
} ,
16
23
extensions : [
24
+ BulletList ,
25
+ OrderedList ,
26
+ ListItem ,
27
+ Image ,
17
28
StarterKit ,
18
29
Paragraph . configure ( {
19
30
HTMLAttributes : {
@@ -30,7 +41,7 @@ export const Tiptap = () => {
30
41
} ,
31
42
} ) ,
32
43
Heading . configure ( {
33
- levels : [ 1 , 2 , 3 ] ,
44
+ levels : [ 1 , 2 ] ,
34
45
} ) ,
35
46
] ,
36
47
content : '' ,
@@ -42,19 +53,64 @@ export const Tiptap = () => {
42
53
} ,
43
54
} )
44
55
56
+ const handleImage = ( url ) => {
57
+ if ( url ) {
58
+ editor . chain ( ) . focus ( ) . setImage ( { src : url } ) . run ( )
59
+ }
60
+ setOpenImageDialog ( false )
61
+ }
62
+
45
63
return (
46
- < >
64
+ < div >
47
65
{ editor && < BubbleMenu editor = { editor } pluginKey = { 'menu' } >
48
66
< MenuUI editor = { editor } />
49
67
</ BubbleMenu > }
68
+ < UploadImageDialog open = { openImageDialog } close = { ( ) => setOpenImageDialog ( false ) } save = { handleImage } />
50
69
< EditorContent editor = { editor } />
51
- </ >
70
+ < div className = 'fixed bottom-6 inset-x-0' >
71
+ < div className = "flex justify-center" >
72
+ < FixedMenuUI editor = { editor } openImageDialog = { ( ) => setOpenImageDialog ( true ) } />
73
+ </ div >
74
+ </ div >
75
+ </ div >
76
+ )
77
+ }
78
+
79
+ const FixedMenuUI = ( { editor, openImageDialog } : { editor : Editor , openImageDialog : ( ) => void } ) => {
80
+ if ( ! editor ) return null
81
+ return (
82
+ < div className = " justify-center bg-gray-100 rounded flex px-2 divide-x w-80" >
83
+ < div className = "p-2 text-gray-800" >
84
+ < button
85
+ onClick = { ( e ) => { editor . chain ( ) . focus ( ) . toggleBulletList ( ) . run ( ) ; e . preventDefault ( ) } }
86
+ className = { editor . isActive ( 'bulletList' ) ? 'is-active' : '' }
87
+ >
88
+ Bullet list
89
+ </ button >
90
+ </ div >
91
+ < div className = "p-2 text-gray-800" >
92
+ < button
93
+ onClick = { ( e ) => { editor . chain ( ) . focus ( ) . toggleOrderedList ( ) . run ( ) ; e . preventDefault ( ) } }
94
+ className = { editor . isActive ( 'orderedList' ) ? 'is-active' : '' }
95
+ >
96
+ Order list
97
+ </ button >
98
+ </ div >
99
+ < div className = "p-2 text-gray-800" >
100
+ < button
101
+ onClick = { ( e ) => { e . preventDefault ( ) ; openImageDialog ( ) } }
102
+ >
103
+ Image
104
+ </ button >
105
+ </ div >
106
+ </ div >
52
107
)
53
108
}
54
109
55
110
const MenuUI = ( { editor } : { editor : Editor } ) => {
111
+ if ( ! editor ) return null
56
112
return (
57
- < div className = "shadow-md bg-white rounded flex px-2" >
113
+ < div className = "shadow-md bg-gray-100 rounded flex px-2 divide-x " >
58
114
< div className = "p-2 text-gray-800" >
59
115
< button
60
116
onClick = { ( ) => editor . chain ( ) . focus ( ) . toggleHeading ( { level : 1 } ) . run ( ) }
@@ -63,6 +119,14 @@ const MenuUI = ({ editor }: {editor: Editor}) => {
63
119
h1
64
120
</ button >
65
121
</ div >
122
+ < div className = "p-2 text-gray-800" >
123
+ < button
124
+ onClick = { ( ) => editor . chain ( ) . focus ( ) . toggleHeading ( { level : 2 } ) . run ( ) }
125
+ className = { editor . isActive ( 'h-1' ) ? 'is-active' : '' }
126
+ >
127
+ h2
128
+ </ button >
129
+ </ div >
66
130
< div className = "p-2 text-gray-800" >
67
131
< button
68
132
onClick = { ( ) => editor . chain ( ) . focus ( ) . toggleBold ( ) . run ( ) }
0 commit comments