Last active
January 6, 2024 07:17
-
-
Save madan712/75739927dfd5a7c3586757f692a41f1d to your computer and use it in GitHub Desktop.
React simple rich text editor using draft-js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from 'react'; | |
import { Editor, EditorState, RichUtils } from 'draft-js'; | |
import { | |
FaBold, | |
FaCode, | |
FaHeading, | |
FaItalic, | |
FaListOl, | |
FaListUl, | |
FaUnderline, | |
} from 'react-icons/fa'; | |
const InlineControls = [ | |
{ | |
icon: <FaBold title="bold" />, | |
name: 'BOLD', | |
}, | |
{ | |
icon: <FaItalic title="italic" />, | |
name: 'ITALIC', | |
}, | |
{ | |
icon: <FaUnderline title="underline" />, | |
name: 'UNDERLINE', | |
}, | |
{ | |
icon: <FaCode title="code" />, | |
name: 'CODE', | |
}, | |
]; | |
const BlockControls = [ | |
{ | |
icon: <FaHeading title="H1" />, | |
name: 'header-one', | |
}, | |
{ | |
icon: <FaListUl title="unordered list" />, | |
name: 'unordered-list-item', | |
}, | |
{ | |
icon: <FaListOl title="ordered list" />, | |
name: 'ordered-list-item', | |
}, | |
]; | |
const styles = { | |
box: { | |
border: '1px solid #c0c0c0', | |
marginTop: '10px', | |
}, | |
top: { | |
padding: '5px', | |
display: 'flex', | |
}, | |
content: { | |
borderTop: '1px solid #c0c0c0', | |
padding: '5px', | |
height: '300px', | |
}, | |
button: { | |
border: '1px solid #c0c0c0', | |
padding: '5px', | |
borderRadius: '5px', | |
cursor: 'pointer', | |
textAlign: 'center', | |
marginRight: '5px', | |
width: '50px', | |
'&:hover': { | |
backgroundColor: '#d3d3d3', | |
}, | |
}, | |
}; | |
const App = () => { | |
const [editorState, setEditorState] = useState(() => | |
EditorState.createEmpty() | |
); | |
const toggleBlockType = (blockType) => { | |
setEditorState(RichUtils.toggleBlockType(editorState, blockType)); | |
}; | |
const toggleInlineStyle = (inlineStyle) => { | |
setEditorState(RichUtils.toggleInlineStyle(editorState, inlineStyle)); | |
}; | |
const controlButton = (index, isSelected, toggle, icon) => ( | |
<div | |
key={index} | |
style={{ | |
...styles.button, | |
backgroundColor: isSelected ? '#d3d3d3' : '#ffffff', | |
}} | |
onClick={toggle} | |
> | |
{icon} | |
</div> | |
); | |
return ( | |
<div style={{ padding: '10px' }}> | |
<div style={styles.box}> | |
<div style={styles.top}> | |
{InlineControls.map((control, index) => { | |
const currentStyle = | |
editorState.getCurrentInlineStyle(); | |
return controlButton( | |
index, | |
currentStyle.has(control.name), | |
() => toggleInlineStyle(control.name), | |
control.icon | |
); | |
})} | |
{BlockControls.map((control, index) => { | |
const selection = editorState.getSelection(); | |
const blockType = editorState | |
.getCurrentContent() | |
.getBlockForKey(selection.getStartKey()) | |
.getType(); | |
return controlButton( | |
index, | |
control.name === blockType, | |
() => toggleBlockType(control.name), | |
control.icon | |
); | |
})} | |
</div> | |
<div style={styles.content}> | |
<Editor | |
editorState={editorState} | |
onChange={setEditorState} | |
/> | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment