1
- import EditorJS from '@editorjs/editorjs' ;
2
- import React , { useEffect , useRef , useState } from 'react' ;
3
- import { graphql , useMutation } from 'react-relay' ;
4
- import Card from '../Card' ;
5
- import { EDITOR_JS_TOOLS } from './editorTools' ;
1
+ import EditorJS , { LogLevels , OutputData } from '@editorjs/editorjs'
2
+ import React , { useEffect , useRef , useState } from 'react'
3
+ import { graphql , useMutation } from 'react-relay'
4
+ import Button from '../Button'
5
+ import Card from '../Card'
6
+ import { EDITOR_JS_TOOLS } from './editorTools'
6
7
7
- const DEFAULT_INITIAL_DATA = ( ) => {
8
+ const DEFAULT_INITIAL_DATA = ( ) : OutputData => {
8
9
return {
9
- " time" : new Date ( ) . getTime ( ) ,
10
- " blocks" : [
10
+ time : new Date ( ) . getTime ( ) ,
11
+ blocks : [
11
12
{
12
- " type" : " header" ,
13
- " data" : {
14
- " text" : " This is my awesome editor!" ,
15
- " level" : 1
16
- }
13
+ type : ' header' ,
14
+ data : {
15
+ text : ' This is my awesome editor!' ,
16
+ level : 1 ,
17
+ } ,
17
18
} ,
18
- ]
19
+ ] ,
19
20
}
20
21
}
21
22
22
- const getAbstract = ( content ) => {
23
+ const getAbstract = ( content : OutputData ) => {
23
24
let abstract = ''
24
- for ( let i = 0 ; i < content . blocks . length ; i ++ ) {
25
- if ( content . blocks [ i ] . type == "header" || content . blocks [ i ] . type == "paragraph" ) {
25
+ for ( let i = 0 ; i < content . blocks . length ; i ++ ) {
26
+ if (
27
+ content . blocks [ i ] . type == 'header' ||
28
+ content . blocks [ i ] . type == 'paragraph'
29
+ ) {
26
30
abstract + = content . blocks [ i ] . data . text
27
31
}
28
- if ( abstract . length >= 200 ) break ;
32
+ if ( abstract . length >= 200 ) break
29
33
}
30
- return abstract ;
34
+ return abstract
31
35
}
32
-
33
- const EDITTOR_HOLDER_ID = 'editorjs' ;
34
36
35
- export default function Editor ( ) {
36
- const [ postTitle , setPostTitle ] = useState ( 'Your Title Goes Here' )
37
- const ejInstance = useRef ( ) ;
38
- const [ editorData , setEditorData ] = React . useState ( DEFAULT_INITIAL_DATA ) ;
39
-
40
- useEffect ( ( ) => {
41
- if ( ! ejInstance . current ) {
42
- initEditor ( ) ;
43
- }
44
- return ( ) => {
45
- ejInstance . current . destroy ( ) ;
46
- ejInstance . current = null ;
37
+ const EDITTOR_HOLDER_ID = 'editorjs'
38
+
39
+ export default function Editor ( ) {
40
+ const [ postTitle , setPostTitle ] = useState ( 'Your Title Goes Here' )
41
+ const ejInstance = useRef < EditorJS | null > ( )
42
+ const [ editorData , setEditorData ] = React . useState ( DEFAULT_INITIAL_DATA )
43
+
44
+ useEffect ( ( ) => {
45
+ if ( ! ejInstance . current ) {
46
+ initEditor ( )
47
+ }
48
+ return ( ) => {
49
+ ejInstance ?. current ?. destroy ( )
50
+ ejInstance . current = null
51
+ }
52
+ } , [ ] )
53
+
54
+ const initEditor = ( ) => {
55
+ const editor = new EditorJS ( {
56
+ holder : EDITTOR_HOLDER_ID ,
57
+ data : editorData ,
58
+ onReady : ( ) => {
59
+ ejInstance . current = editor
60
+ } ,
61
+ onChange : async ( ) => {
62
+ const content = await editor . saver . save ( )
63
+ setEditorData ( content )
64
+ } ,
65
+ autofocus : true ,
66
+ tools : EDITOR_JS_TOOLS ,
67
+ inlineToolbar : true ,
68
+ } )
69
+ }
70
+ const [ commitMutation , isMutationInFlight ] = useMutation (
71
+ graphql `
72
+ mutation StoryEditorCreateMutation($input: StoryInput!) {
73
+ createStory(story: $input) {
74
+ id
75
+ }
47
76
}
48
- } , [ ] ) ;
49
-
50
- const initEditor = ( ) => {
51
- const editor = new EditorJS ( {
52
- holder : EDITTOR_HOLDER_ID ,
53
- logLevel : "ERROR" ,
54
- data : editorData ,
55
- onReady : ( ) => {
56
- ejInstance . current = editor ;
77
+ `
78
+ )
79
+ const handleStorySubmit = ( ) => {
80
+ commitMutation ( {
81
+ variables : {
82
+ input : {
83
+ title : postTitle ,
84
+ contentJson : JSON . stringify ( editorData ) ,
85
+ abstractContent : getAbstract ( editorData ) ,
86
+ urlSuffix : postTitle . toLowerCase ( ) . replace ( ' ' , '-' ) . substring ( 0 , 32 ) ,
87
+ thumbnail : '' ,
57
88
} ,
58
- onChange : async ( ) => {
59
- let content = await editor . saver . save ( ) ;
60
- // Put your logic here to save this data to your DB
61
- setEditorData ( content ) ;
62
- } ,
63
- autofocus : true ,
64
- tools : EDITOR_JS_TOOLS ,
65
- inlineToolbar : true ,
66
- placehodler : 'water'
67
- } ) ;
68
- } ;
69
- const [ commitMutation , isMutationInFlight ] = useMutation (
70
- graphql `
71
- mutation StoryEditorCreateMutation($input: StoryInput!) {
72
- createStory(story:$input) {
73
- id
74
- }
89
+ } ,
90
+ } )
91
+ }
92
+ return (
93
+ < Card classes = "prose max-w-none" >
94
+ < div >
95
+ < div id = { EDITTOR_HOLDER_ID } > </ div >
96
+ </ div >
97
+ < style jsx >
98
+ { `
99
+ [contenteditable]:focus {
100
+ outline: 0px solid transparent;
101
+ border-bottom: 1px dashed #aaa;
75
102
}
76
- `
77
- ) ;
78
- const handleStorySubmit = ( ) => {
79
- commitMutation ( {
80
- variables : {
81
- input : {
82
- title : postTitle ,
83
- contentJson : JSON . stringify ( editorData ) ,
84
- abstractContent : getAbstract ( editorData ) ,
85
- urlSuffix : postTitle . toLowerCase ( ) . replace ( " " , "-" ) . substring ( 0 , 32 ) ,
86
- thumbnail : ''
87
- } ,
88
- } ,
89
- } )
90
- }
91
- return (
92
- < Card classes = "prose" >
93
- < h1 contentEditable onInput = { ( e ) => setPostTitle ( e . target . textContent ) } > { postTitle } </ h1 >
94
- < div >
95
- < div id = { EDITTOR_HOLDER_ID } > </ div >
96
- </ div >
97
- < style jsx >
98
- { `
99
- [contenteditable]:focus {
100
- outline: 0px solid transparent;
101
- border-bottom: 1px dashed #aaa;
102
- }
103
- ` }
104
- </ style >
105
- < button onClick = { ( ) => handleStorySubmit ( ) } > submit </ button >
106
- </ Card >
107
- )
108
-
109
- }
103
+ ` }
104
+ </ style >
105
+ < Button onClick = { ( ) => handleStorySubmit ( ) } > Submit </ Button >
106
+ </ Card >
107
+ )
108
+ }
0 commit comments