Last active
May 22, 2020 07:55
-
-
Save behnamazimi/7fb972af69dd3198799ee2043e8f5995 to your computer and use it in GitHub Desktop.
React component for Jodit HTML editor, module lazy loading support.
This file contains hidden or 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
/** | |
* React component for Jodit HTML editor | |
* + Jodit module lazy loading support. | |
* + Debounce for change event to improve performance | |
*/ | |
import React, {useEffect, useRef, forwardRef, useLayoutEffect, useMemo} from 'react' | |
import * as PropTypes from 'prop-types' | |
import 'jodit/build/jodit.min.css' | |
let CHANGE_DEBOUNCE_FLAG; | |
const HTMLEditor = forwardRef(({defaultValue, onChange, onBlur, tabIndex, name}, ref) => { | |
const textArea = useRef(null); | |
// jodit module loader on component mount | |
const JoditLoader = useMemo(() => { | |
return new Promise(resolve => { | |
import('jodit').then(res => resolve(res.default)) | |
}) | |
}, []) | |
// set the value of forwarded ref | |
useLayoutEffect(() => { | |
if (ref) { | |
if (typeof ref === 'function') { | |
ref(textArea.current) | |
} else { | |
ref.current = textArea.current | |
} | |
} | |
}, [textArea]); | |
// create instance of jodit | |
useEffect(() => { | |
const element = textArea.current; | |
(async () => { | |
const Jodit = await JoditLoader; | |
const config = { | |
buttons: "bold,strikethrough,underline,italic,eraser,|,superscript,subscript,|,ul,ol,|,outdent,indent,|,font,fontsize,brush,paragraph,|,table,link,image,|,align,,undo,redo,|,dots,strikethrough,underline,,selectall,cut,copy,paste,symbol,print,fullsize", | |
toolbarAdaptive: false, | |
} | |
textArea.current = Jodit.make(element, config); | |
textArea.current.value = defaultValue; | |
textArea.current.events.on('blur', () => blurHandler(textArea.current.value)); | |
textArea.current.events.on('change', () => changeHandler(textArea.current.value)); | |
textArea.current.workplace.tabIndex = tabIndex || -1; | |
})(); | |
return () => { | |
textArea.current.destruct(); | |
textArea.current = element; | |
} | |
}, []); | |
useEffect(() => { | |
if (textArea && textArea.current) { | |
textArea.current.value = defaultValue | |
} | |
}, [textArea, defaultValue]); | |
function blurHandler(newContent) { | |
if (onBlur && typeof onBlur === "function") { | |
onBlur(newContent) | |
} | |
} | |
function changeHandler(newContent) { | |
if (CHANGE_DEBOUNCE_FLAG) | |
clearTimeout(CHANGE_DEBOUNCE_FLAG); | |
CHANGE_DEBOUNCE_FLAG = setTimeout(() => { | |
if (onChange && typeof onChange === "function") { | |
onChange(newContent) | |
} | |
}, 300) | |
} | |
return <textarea ref={textArea} name={name}/> | |
}); | |
HTMLEditor.propTypes = { | |
defaultValue: PropTypes.string, | |
name: PropTypes.string, | |
tabIndex: PropTypes.number, | |
onChange: PropTypes.func, | |
onBlur: PropTypes.func | |
}; | |
export default HTMLEditor |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Would you happened to have a Typescript version of this wrapper?