UNPKG

re-quill

Version:
128 lines (122 loc) 3.13 kB
/* inspired by https://github.com/zenoamaro/react-quill */ import Quill from "quill"; import "quill/dist/quill.core.css"; import "quill/dist/quill.snow.css"; import React from "react"; function isDelta(value) { return value && value.ops; } function isequal(value1, value2) { return JSON.stringify(value1) == JSON.stringify(value2); } const ReactQuill = React.forwardRef((props, ref) => { const el = React.useRef(); const quill = React.useRef(); const lastValue = React.useRef(null); const onSelectionChange = React.useCallback( (range, source) => { if (range) { props.onFocus?.(quill.current, range, source); } else { props.onBlur?.(quill.current, range, source); } }, [props.onBlur, props.onFocus] ); const onChange = React.useCallback( (delta, source) => { let html = quill.current.root.innerHTML; if (html == lastValue.current) return; if (html === "<p><br></p>") html = ""; const nextValue = isDelta(lastValue.current) ? delta : html; if (!isequal(nextValue, lastValue.current)) { props.onChange?.(html, delta, source); } lastValue.current = nextValue; }, [props.onChange] ); React.useEffect(() => { const config = { bounds: props.bounds, formats: props.formats, modules: props.modules, placeholder: props.placeholder, tabIndex: props.tabIndex, theme: props.theme, readonly: props.readOnly, }; if (quill.current) { quill.current.blur(); quill.current = null; } quill.current = new Quill(el.current, config); quill.current.enable(false); quill.current.on("text-change", onChange); quill.current.on("selection-change", onSelectionChange); return () => { quill.current.off("text-change", onChange); quill.current.off("selection-change", onSelectionChange); quill.current = null; }; }, [ props.bounds, props.formats, props.modules, props.placeholder, props.theme, props.readOnly, ]); React.useEffect(() => { quill.current.enable(!Boolean(props.disabled)); }, [props.disabled]); React.useEffect(() => { if (isequal(props.value, lastValue.current)) return; if (props.value) { if (isDelta(props.value)) { quill.current.setContents(props.value); } else { const value = props.value || ""; quill.current.pasteHTML(value); } quill.current.blur(); } }, [props.value]); React.useImperativeHandle(ref, () => { return { blur: () => quill.current?.blur?.(), focus: () => quill.current?.focus?.(), quill: quill.current, getHTML: () => quill.current.root.innerHTML, getContents: () => quill.current.getContents(), }; }); return React.createElement( "div", { className: props.className }, React.createElement( "div", { className: "quill", id: props.id, onKeyPress: props.onKeyPress, onKeyDown: props.onKeyDown, onKeyUp: props.onKeyUp, }, React.createElement("div", { ref: el }) ), props.children ); }); ReactQuill.defaultProps = { theme: "snow", modules: {}, readOnly: false, disabled: false, className: "quill-container", value: "", }; ReactQuill.displayName = "ReactQuill"; export default ReactQuill;