re-quill
Version:
base on quill@1.3.7
128 lines (122 loc) • 3.13 kB
JavaScript
/*
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;