forked from FINAKON/HelpProject
421 lines
17 KiB
JavaScript
421 lines
17 KiB
JavaScript
|
"use strict";
|
||
|
/*
|
||
|
React-Quill
|
||
|
https://github.com/zenoamaro/react-quill
|
||
|
*/
|
||
|
var __extends = (this && this.__extends) || (function () {
|
||
|
var extendStatics = function (d, b) {
|
||
|
extendStatics = Object.setPrototypeOf ||
|
||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||
|
return extendStatics(d, b);
|
||
|
};
|
||
|
return function (d, b) {
|
||
|
extendStatics(d, b);
|
||
|
function __() { this.constructor = d; }
|
||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
|
};
|
||
|
})();
|
||
|
var __assign = (this && this.__assign) || function () {
|
||
|
__assign = Object.assign || function(t) {
|
||
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||
|
s = arguments[i];
|
||
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||
|
t[p] = s[p];
|
||
|
}
|
||
|
return t;
|
||
|
};
|
||
|
return __assign.apply(this, arguments);
|
||
|
};
|
||
|
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||
|
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||
|
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||
|
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||
|
r[k] = a[j];
|
||
|
return r;
|
||
|
};
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
var react_1 = __importDefault(require("react"));
|
||
|
var react_dom_1 = __importDefault(require("react-dom"));
|
||
|
var isEqual_1 = __importDefault(require("lodash/isEqual"));
|
||
|
var quill_1 = __importDefault(require("quill"));
|
||
|
var ReactQuill = /** @class */ (function (_super) {
|
||
|
__extends(ReactQuill, _super);
|
||
|
function ReactQuill(props) {
|
||
|
var _this = _super.call(this, props) || this;
|
||
|
/*
|
||
|
Changing one of these props should cause a full re-render and a
|
||
|
re-instantiation of the Quill editor.
|
||
|
*/
|
||
|
_this.dirtyProps = [
|
||
|
'modules',
|
||
|
'formats',
|
||
|
'bounds',
|
||
|
'theme',
|
||
|
'children',
|
||
|
];
|
||
|
/*
|
||
|
Changing one of these props should cause a regular update. These are mostly
|
||
|
props that act on the container, rather than the quillized editing area.
|
||
|
*/
|
||
|
_this.cleanProps = [
|
||
|
'id',
|
||
|
'className',
|
||
|
'style',
|
||
|
'placeholder',
|
||
|
'tabIndex',
|
||
|
'onChange',
|
||
|
'onChangeSelection',
|
||
|
'onFocus',
|
||
|
'onBlur',
|
||
|
'onKeyPress',
|
||
|
'onKeyDown',
|
||
|
'onKeyUp',
|
||
|
];
|
||
|
_this.state = {
|
||
|
generation: 0,
|
||
|
};
|
||
|
/*
|
||
|
Tracks the internal selection of the Quill editor
|
||
|
*/
|
||
|
_this.selection = null;
|
||
|
_this.onEditorChange = function (eventName, rangeOrDelta, oldRangeOrDelta, source) {
|
||
|
var _a, _b, _c, _d;
|
||
|
if (eventName === 'text-change') {
|
||
|
(_b = (_a = _this).onEditorChangeText) === null || _b === void 0 ? void 0 : _b.call(_a, _this.editor.root.innerHTML, rangeOrDelta, source, _this.unprivilegedEditor);
|
||
|
}
|
||
|
else if (eventName === 'selection-change') {
|
||
|
(_d = (_c = _this).onEditorChangeSelection) === null || _d === void 0 ? void 0 : _d.call(_c, rangeOrDelta, source, _this.unprivilegedEditor);
|
||
|
}
|
||
|
};
|
||
|
var value = _this.isControlled() ? props.value : props.defaultValue;
|
||
|
_this.value = (value !== null && value !== void 0 ? value : '');
|
||
|
return _this;
|
||
|
}
|
||
|
ReactQuill.prototype.validateProps = function (props) {
|
||
|
var _a;
|
||
|
if (react_1.default.Children.count(props.children) > 1)
|
||
|
throw new Error('The Quill editing area can only be composed of a single React element.');
|
||
|
if (react_1.default.Children.count(props.children)) {
|
||
|
var child = react_1.default.Children.only(props.children);
|
||
|
if (((_a = child) === null || _a === void 0 ? void 0 : _a.type) === 'textarea')
|
||
|
throw new Error('Quill does not support editing on a <textarea>. Use a <div> instead.');
|
||
|
}
|
||
|
if (this.lastDeltaChangeSet &&
|
||
|
props.value === this.lastDeltaChangeSet)
|
||
|
throw new Error('You are passing the `delta` object from the `onChange` event back ' +
|
||
|
'as `value`. You most probably want `editor.getContents()` instead. ' +
|
||
|
'See: https://github.com/zenoamaro/react-quill#using-deltas');
|
||
|
};
|
||
|
ReactQuill.prototype.shouldComponentUpdate = function (nextProps, nextState) {
|
||
|
var _this = this;
|
||
|
var _a;
|
||
|
this.validateProps(nextProps);
|
||
|
// If the editor hasn't been instantiated yet, or the component has been
|
||
|
// regenerated, we already know we should update.
|
||
|
if (!this.editor || this.state.generation !== nextState.generation) {
|
||
|
return true;
|
||
|
}
|
||
|
// Handle value changes in-place
|
||
|
if ('value' in nextProps) {
|
||
|
var prevContents = this.getEditorContents();
|
||
|
var nextContents = (_a = nextProps.value, (_a !== null && _a !== void 0 ? _a : ''));
|
||
|
// NOTE: Seeing that Quill is missing a way to prevent edits, we have to
|
||
|
// settle for a hybrid between controlled and uncontrolled mode. We
|
||
|
// can't prevent the change, but we'll still override content
|
||
|
// whenever `value` differs from current state.
|
||
|
// NOTE: Comparing an HTML string and a Quill Delta will always trigger a
|
||
|
// change, regardless of whether they represent the same document.
|
||
|
if (!this.isEqualValue(nextContents, prevContents)) {
|
||
|
this.setEditorContents(this.editor, nextContents);
|
||
|
}
|
||
|
}
|
||
|
// Handle read-only changes in-place
|
||
|
if (nextProps.readOnly !== this.props.readOnly) {
|
||
|
this.setEditorReadOnly(this.editor, nextProps.readOnly);
|
||
|
}
|
||
|
// Clean and Dirty props require a render
|
||
|
return __spreadArrays(this.cleanProps, this.dirtyProps).some(function (prop) {
|
||
|
return !isEqual_1.default(nextProps[prop], _this.props[prop]);
|
||
|
});
|
||
|
};
|
||
|
ReactQuill.prototype.shouldComponentRegenerate = function (nextProps) {
|
||
|
var _this = this;
|
||
|
// Whenever a `dirtyProp` changes, the editor needs reinstantiation.
|
||
|
return this.dirtyProps.some(function (prop) {
|
||
|
return !isEqual_1.default(nextProps[prop], _this.props[prop]);
|
||
|
});
|
||
|
};
|
||
|
ReactQuill.prototype.componentDidMount = function () {
|
||
|
this.instantiateEditor();
|
||
|
this.setEditorContents(this.editor, this.getEditorContents());
|
||
|
};
|
||
|
ReactQuill.prototype.componentWillUnmount = function () {
|
||
|
this.destroyEditor();
|
||
|
};
|
||
|
ReactQuill.prototype.componentDidUpdate = function (prevProps, prevState) {
|
||
|
var _this = this;
|
||
|
// If we're changing one of the `dirtyProps`, the entire Quill Editor needs
|
||
|
// to be re-instantiated. Regenerating the editor will cause the whole tree,
|
||
|
// including the container, to be cleaned up and re-rendered from scratch.
|
||
|
// Store the contents so they can be restored later.
|
||
|
if (this.editor && this.shouldComponentRegenerate(prevProps)) {
|
||
|
var delta = this.editor.getContents();
|
||
|
var selection = this.editor.getSelection();
|
||
|
this.regenerationSnapshot = { delta: delta, selection: selection };
|
||
|
this.setState({ generation: this.state.generation + 1 });
|
||
|
this.destroyEditor();
|
||
|
}
|
||
|
// The component has been regenerated, so it must be re-instantiated, and
|
||
|
// its content must be restored to the previous values from the snapshot.
|
||
|
if (this.state.generation !== prevState.generation) {
|
||
|
var _a = this.regenerationSnapshot, delta = _a.delta, selection_1 = _a.selection;
|
||
|
delete this.regenerationSnapshot;
|
||
|
this.instantiateEditor();
|
||
|
var editor_1 = this.editor;
|
||
|
editor_1.setContents(delta);
|
||
|
postpone(function () { return _this.setEditorSelection(editor_1, selection_1); });
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.instantiateEditor = function () {
|
||
|
if (this.editor) {
|
||
|
this.hookEditor(this.editor);
|
||
|
}
|
||
|
else {
|
||
|
this.editor = this.createEditor(this.getEditingArea(), this.getEditorConfig());
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.destroyEditor = function () {
|
||
|
if (!this.editor)
|
||
|
return;
|
||
|
this.unhookEditor(this.editor);
|
||
|
};
|
||
|
/*
|
||
|
We consider the component to be controlled if `value` is being sent in props.
|
||
|
*/
|
||
|
ReactQuill.prototype.isControlled = function () {
|
||
|
return 'value' in this.props;
|
||
|
};
|
||
|
ReactQuill.prototype.getEditorConfig = function () {
|
||
|
return {
|
||
|
bounds: this.props.bounds,
|
||
|
formats: this.props.formats,
|
||
|
modules: this.props.modules,
|
||
|
placeholder: this.props.placeholder,
|
||
|
readOnly: this.props.readOnly,
|
||
|
scrollingContainer: this.props.scrollingContainer,
|
||
|
tabIndex: this.props.tabIndex,
|
||
|
theme: this.props.theme,
|
||
|
};
|
||
|
};
|
||
|
ReactQuill.prototype.getEditor = function () {
|
||
|
if (!this.editor)
|
||
|
throw new Error('Accessing non-instantiated editor');
|
||
|
return this.editor;
|
||
|
};
|
||
|
/**
|
||
|
Creates an editor on the given element. The editor will be passed the
|
||
|
configuration, have its events bound,
|
||
|
*/
|
||
|
ReactQuill.prototype.createEditor = function (element, config) {
|
||
|
var editor = new quill_1.default(element, config);
|
||
|
if (config.tabIndex != null) {
|
||
|
this.setEditorTabIndex(editor, config.tabIndex);
|
||
|
}
|
||
|
this.hookEditor(editor);
|
||
|
return editor;
|
||
|
};
|
||
|
ReactQuill.prototype.hookEditor = function (editor) {
|
||
|
// Expose the editor on change events via a weaker, unprivileged proxy
|
||
|
// object that does not allow accidentally modifying editor state.
|
||
|
this.unprivilegedEditor = this.makeUnprivilegedEditor(editor);
|
||
|
// Using `editor-change` allows picking up silent updates, like selection
|
||
|
// changes on typing.
|
||
|
editor.on('editor-change', this.onEditorChange);
|
||
|
};
|
||
|
ReactQuill.prototype.unhookEditor = function (editor) {
|
||
|
editor.off('editor-change', this.onEditorChange);
|
||
|
};
|
||
|
ReactQuill.prototype.getEditorContents = function () {
|
||
|
return this.value;
|
||
|
};
|
||
|
ReactQuill.prototype.getEditorSelection = function () {
|
||
|
return this.selection;
|
||
|
};
|
||
|
/*
|
||
|
True if the value is a Delta instance or a Delta look-alike.
|
||
|
*/
|
||
|
ReactQuill.prototype.isDelta = function (value) {
|
||
|
return value && value.ops;
|
||
|
};
|
||
|
/*
|
||
|
Special comparison function that knows how to compare Deltas.
|
||
|
*/
|
||
|
ReactQuill.prototype.isEqualValue = function (value, nextValue) {
|
||
|
if (this.isDelta(value) && this.isDelta(nextValue)) {
|
||
|
return isEqual_1.default(value.ops, nextValue.ops);
|
||
|
}
|
||
|
else {
|
||
|
return isEqual_1.default(value, nextValue);
|
||
|
}
|
||
|
};
|
||
|
/*
|
||
|
Replace the contents of the editor, but keep the previous selection hanging
|
||
|
around so that the cursor won't move.
|
||
|
*/
|
||
|
ReactQuill.prototype.setEditorContents = function (editor, value) {
|
||
|
var _this = this;
|
||
|
this.value = value;
|
||
|
var sel = this.getEditorSelection();
|
||
|
if (typeof value === 'string') {
|
||
|
editor.setContents(editor.clipboard.convert(value));
|
||
|
}
|
||
|
else {
|
||
|
editor.setContents(value);
|
||
|
}
|
||
|
postpone(function () { return _this.setEditorSelection(editor, sel); });
|
||
|
};
|
||
|
ReactQuill.prototype.setEditorSelection = function (editor, range) {
|
||
|
this.selection = range;
|
||
|
if (range) {
|
||
|
// Validate bounds before applying.
|
||
|
var length_1 = editor.getLength();
|
||
|
range.index = Math.max(0, Math.min(range.index, length_1 - 1));
|
||
|
range.length = Math.max(0, Math.min(range.length, (length_1 - 1) - range.index));
|
||
|
editor.setSelection(range);
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.setEditorTabIndex = function (editor, tabIndex) {
|
||
|
var _a, _b;
|
||
|
if ((_b = (_a = editor) === null || _a === void 0 ? void 0 : _a.scroll) === null || _b === void 0 ? void 0 : _b.domNode) {
|
||
|
editor.scroll.domNode.tabIndex = tabIndex;
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.setEditorReadOnly = function (editor, value) {
|
||
|
if (value) {
|
||
|
editor.disable();
|
||
|
}
|
||
|
else {
|
||
|
editor.enable();
|
||
|
}
|
||
|
};
|
||
|
/*
|
||
|
Returns a weaker, unprivileged proxy object that only exposes read-only
|
||
|
accessors found on the editor instance, without any state-modifying methods.
|
||
|
*/
|
||
|
ReactQuill.prototype.makeUnprivilegedEditor = function (editor) {
|
||
|
var e = editor;
|
||
|
return {
|
||
|
getHTML: function () { return e.root.innerHTML; },
|
||
|
getLength: e.getLength.bind(e),
|
||
|
getText: e.getText.bind(e),
|
||
|
getContents: e.getContents.bind(e),
|
||
|
getSelection: e.getSelection.bind(e),
|
||
|
getBounds: e.getBounds.bind(e),
|
||
|
};
|
||
|
};
|
||
|
ReactQuill.prototype.getEditingArea = function () {
|
||
|
if (!this.editingArea) {
|
||
|
throw new Error('Instantiating on missing editing area');
|
||
|
}
|
||
|
var element = react_dom_1.default.findDOMNode(this.editingArea);
|
||
|
if (!element) {
|
||
|
throw new Error('Cannot find element for editing area');
|
||
|
}
|
||
|
if (element.nodeType === 3) {
|
||
|
throw new Error('Editing area cannot be a text node');
|
||
|
}
|
||
|
return element;
|
||
|
};
|
||
|
/*
|
||
|
Renders an editor area, unless it has been provided one to clone.
|
||
|
*/
|
||
|
ReactQuill.prototype.renderEditingArea = function () {
|
||
|
var _this = this;
|
||
|
var _a = this.props, children = _a.children, preserveWhitespace = _a.preserveWhitespace;
|
||
|
var generation = this.state.generation;
|
||
|
var properties = {
|
||
|
key: generation,
|
||
|
ref: function (instance) {
|
||
|
_this.editingArea = instance;
|
||
|
},
|
||
|
};
|
||
|
if (react_1.default.Children.count(children)) {
|
||
|
return react_1.default.cloneElement(react_1.default.Children.only(children), properties);
|
||
|
}
|
||
|
return preserveWhitespace ?
|
||
|
react_1.default.createElement("pre", __assign({}, properties)) :
|
||
|
react_1.default.createElement("div", __assign({}, properties));
|
||
|
};
|
||
|
ReactQuill.prototype.render = function () {
|
||
|
var _a;
|
||
|
return (react_1.default.createElement("div", { id: this.props.id, style: this.props.style, key: this.state.generation, className: "quill " + (_a = this.props.className, (_a !== null && _a !== void 0 ? _a : '')), onKeyPress: this.props.onKeyPress, onKeyDown: this.props.onKeyDown, onKeyUp: this.props.onKeyUp }, this.renderEditingArea()));
|
||
|
};
|
||
|
ReactQuill.prototype.onEditorChangeText = function (value, delta, source, editor) {
|
||
|
var _a, _b;
|
||
|
if (!this.editor)
|
||
|
return;
|
||
|
// We keep storing the same type of value as what the user gives us,
|
||
|
// so that value comparisons will be more stable and predictable.
|
||
|
var nextContents = this.isDelta(this.value)
|
||
|
? editor.getContents()
|
||
|
: editor.getHTML();
|
||
|
if (nextContents !== this.getEditorContents()) {
|
||
|
// Taint this `delta` object, so we can recognize whether the user
|
||
|
// is trying to send it back as `value`, preventing a likely loop.
|
||
|
this.lastDeltaChangeSet = delta;
|
||
|
this.value = nextContents;
|
||
|
(_b = (_a = this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, value, delta, source, editor);
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.onEditorChangeSelection = function (nextSelection, source, editor) {
|
||
|
var _a, _b, _c, _d, _e, _f;
|
||
|
if (!this.editor)
|
||
|
return;
|
||
|
var currentSelection = this.getEditorSelection();
|
||
|
var hasGainedFocus = !currentSelection && nextSelection;
|
||
|
var hasLostFocus = currentSelection && !nextSelection;
|
||
|
if (isEqual_1.default(nextSelection, currentSelection))
|
||
|
return;
|
||
|
this.selection = nextSelection;
|
||
|
(_b = (_a = this.props).onChangeSelection) === null || _b === void 0 ? void 0 : _b.call(_a, nextSelection, source, editor);
|
||
|
if (hasGainedFocus) {
|
||
|
(_d = (_c = this.props).onFocus) === null || _d === void 0 ? void 0 : _d.call(_c, nextSelection, source, editor);
|
||
|
}
|
||
|
else if (hasLostFocus) {
|
||
|
(_f = (_e = this.props).onBlur) === null || _f === void 0 ? void 0 : _f.call(_e, currentSelection, source, editor);
|
||
|
}
|
||
|
};
|
||
|
ReactQuill.prototype.focus = function () {
|
||
|
if (!this.editor)
|
||
|
return;
|
||
|
this.editor.focus();
|
||
|
};
|
||
|
ReactQuill.prototype.blur = function () {
|
||
|
if (!this.editor)
|
||
|
return;
|
||
|
this.selection = null;
|
||
|
this.editor.blur();
|
||
|
};
|
||
|
ReactQuill.displayName = 'React Quill';
|
||
|
/*
|
||
|
Export Quill to be able to call `register`
|
||
|
*/
|
||
|
ReactQuill.Quill = quill_1.default;
|
||
|
ReactQuill.defaultProps = {
|
||
|
theme: 'snow',
|
||
|
modules: {},
|
||
|
readOnly: false,
|
||
|
};
|
||
|
return ReactQuill;
|
||
|
}(react_1.default.Component));
|
||
|
/*
|
||
|
Small helper to execute a function in the next micro-tick.
|
||
|
*/
|
||
|
function postpone(fn) {
|
||
|
Promise.resolve().then(fn);
|
||
|
}
|
||
|
module.exports = ReactQuill;
|
||
|
//# sourceMappingURL=index.js.map
|