@uiw/react-codemirror
Version:
CodeMirror component for React.
180 lines (179 loc) • 6.49 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useCodeMirror = useCodeMirror;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = require("react");
var _state = require("@codemirror/state");
var _view = require("@codemirror/view");
var _getDefaultExtensions = require("./getDefaultExtensions");
var _utils = require("./utils");
var External = _state.Annotation.define();
var emptyExtensions = [];
function useCodeMirror(props) {
var value = props.value,
selection = props.selection,
onChange = props.onChange,
onStatistics = props.onStatistics,
onCreateEditor = props.onCreateEditor,
onUpdate = props.onUpdate,
_props$extensions = props.extensions,
extensions = _props$extensions === void 0 ? emptyExtensions : _props$extensions,
autoFocus = props.autoFocus,
_props$theme = props.theme,
theme = _props$theme === void 0 ? 'light' : _props$theme,
_props$height = props.height,
height = _props$height === void 0 ? null : _props$height,
_props$minHeight = props.minHeight,
minHeight = _props$minHeight === void 0 ? null : _props$minHeight,
_props$maxHeight = props.maxHeight,
maxHeight = _props$maxHeight === void 0 ? null : _props$maxHeight,
_props$width = props.width,
width = _props$width === void 0 ? null : _props$width,
_props$minWidth = props.minWidth,
minWidth = _props$minWidth === void 0 ? null : _props$minWidth,
_props$maxWidth = props.maxWidth,
maxWidth = _props$maxWidth === void 0 ? null : _props$maxWidth,
_props$placeholder = props.placeholder,
placeholderStr = _props$placeholder === void 0 ? '' : _props$placeholder,
_props$editable = props.editable,
editable = _props$editable === void 0 ? true : _props$editable,
_props$readOnly = props.readOnly,
readOnly = _props$readOnly === void 0 ? false : _props$readOnly,
_props$indentWithTab = props.indentWithTab,
defaultIndentWithTab = _props$indentWithTab === void 0 ? true : _props$indentWithTab,
_props$basicSetup = props.basicSetup,
defaultBasicSetup = _props$basicSetup === void 0 ? true : _props$basicSetup,
root = props.root,
initialState = props.initialState;
var _useState = (0, _react.useState)(),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
container = _useState2[0],
setContainer = _useState2[1];
var _useState3 = (0, _react.useState)(),
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
view = _useState4[0],
setView = _useState4[1];
var _useState5 = (0, _react.useState)(),
_useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
state = _useState6[0],
setState = _useState6[1];
var defaultThemeOption = _view.EditorView.theme({
'&': {
height: height,
minHeight: minHeight,
maxHeight: maxHeight,
width: width,
minWidth: minWidth,
maxWidth: maxWidth
},
'& .cm-scroller': {
height: '100% !important'
}
});
var updateListener = _view.EditorView.updateListener.of(function (vu) {
if (vu.docChanged && typeof onChange === 'function' &&
// Fix echoing of the remote changes:
// If transaction is market as remote we don't have to call `onChange` handler again
!vu.transactions.some(function (tr) {
return tr.annotation(External);
})) {
var doc = vu.state.doc;
var _value = doc.toString();
onChange(_value, vu);
}
onStatistics && onStatistics((0, _utils.getStatistics)(vu));
});
var defaultExtensions = (0, _getDefaultExtensions.getDefaultExtensions)({
theme: theme,
editable: editable,
readOnly: readOnly,
placeholder: placeholderStr,
indentWithTab: defaultIndentWithTab,
basicSetup: defaultBasicSetup
});
var getExtensions = [updateListener, defaultThemeOption].concat((0, _toConsumableArray2["default"])(defaultExtensions));
if (onUpdate && typeof onUpdate === 'function') {
getExtensions.push(_view.EditorView.updateListener.of(onUpdate));
}
getExtensions = getExtensions.concat(extensions);
(0, _react.useLayoutEffect)(function () {
if (container && !state) {
var config = {
doc: value,
selection: selection,
extensions: getExtensions
};
var stateCurrent = initialState ? _state.EditorState.fromJSON(initialState.json, config, initialState.fields) : _state.EditorState.create(config);
setState(stateCurrent);
if (!view) {
var viewCurrent = new _view.EditorView({
state: stateCurrent,
parent: container,
root: root
});
setView(viewCurrent);
onCreateEditor && onCreateEditor(viewCurrent, stateCurrent);
}
}
return function () {
if (view) {
setState(undefined);
setView(undefined);
}
};
}, [container, state]);
(0, _react.useEffect)(function () {
if (props.container) {
setContainer(props.container);
}
}, [props.container]);
(0, _react.useEffect)(function () {
return function () {
if (view) {
view.destroy();
setView(undefined);
}
};
}, [view]);
(0, _react.useEffect)(function () {
if (autoFocus && view) {
view.focus();
}
}, [autoFocus, view]);
(0, _react.useEffect)(function () {
if (view) {
view.dispatch({
effects: _state.StateEffect.reconfigure.of(getExtensions)
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [theme, extensions, height, minHeight, maxHeight, width, minWidth, maxWidth, placeholderStr, editable, readOnly, defaultIndentWithTab, defaultBasicSetup, onChange, onUpdate]);
(0, _react.useEffect)(function () {
if (value === undefined) {
return;
}
var currentValue = view ? view.state.doc.toString() : '';
if (view && value !== currentValue) {
view.dispatch({
changes: {
from: 0,
to: currentValue.length,
insert: value || ''
},
annotations: [External.of(true)]
});
}
}, [value, view]);
return {
state: state,
setState: setState,
view: view,
setView: setView,
container: container,
setContainer: setContainer
};
}