codogo-react-widgets
Version:
Provides a unified way to access the styling of commonly used widgets across different apps
163 lines (133 loc) • 3.23 kB
JavaScript
import PropTypes from "prop-types";
import selectionManipulator from "selection-range";
import autobind from "autobind-decorator";
import hljs from "highlight.js";
import { keyCodesToForwardOnChange, } from "./constants";
import { isFirefox, } from "./browsers";
import MarkdownStyler from "./MarkdownStyler";
const selectionEq = (lhs = {}, rhs = {}) =>
lhs.start === rhs.start && lhs.end === rhs.end;
class Markdown extends React.Component {
constructor(props) {
super(props);
this.oldProps = {};
}
componentDidMount() {
if (this.ref) {
this.ref.innerHTML = hljs.highlight(
"markdown",
this.props.value,
).value;
}
this.componentDidX();
}
componentDidUpdate() {
this.componentDidX();
}
componentDidX() {
const domElement = this.ref;
if (this.props.focus) {
if (document.activeElement !== domElement) {
domElement.focus();
}
if (this.oldProps.value !== this.props.value) {
domElement.innerHTML = hljs.highlight(
"markdown",
this.props.value,
).value;
}
if (
!selectionEq(this.oldProps.selection, this.props.selection) &&
this.props.value.length
) {
selectionManipulator(domElement, this.props.selection || {});
}
} else {
domElement.innerHTML = hljs.highlight(
"markdown",
this.props.value,
).value;
domElement.blur();
}
this.oldProps = this.props;
}
onRef(ref) {
if (ref) {
this.ref = ref;
}
}
onKeyDown() {}
onChange(event) {
const domElement = this.ref;
if (domElement) {
const selection = selectionManipulator(domElement);
const value = domElement.innerText;
if (isFirefox && event.keyCode === 13) {
selection.start = selection.start + 1;
selection.end = selection.end + 1;
}
const selectionChanged = !selectionEq(
selection,
this.props.selection,
);
const valueChanged = value !== this.props.value;
console.log("onChange", {
event,
value: valueChanged ? value : this.props.value,
selection: selectionChanged ? selection : this.props.selection,
});
this.props.onChange({
event,
value: valueChanged ? value : this.props.value,
selection: selectionChanged ? selection : this.props.selection,
});
}
}
onClick(event) {
this.onChange(event);
}
onKeyUp(event) {
//any key has been pressed,
//but this handler only deals with non-text-mutating actions
//so we'll need to weed those out
if (
this.lastCalled !== this.onInput &&
keyCodesToForwardOnChange.has(event.keyCode)
) {
this.onChange(event);
}
this.lastCalled = this.onKeyUp;
}
onInput(event) {
this.onChange(event);
this.lastCalled = this.onInput;
}
render() {
return (
<MarkdownStyler placeholder = { this.props.placeholder }>
<div
className = "markdown"
contentEditable
onKeyUp = { this.onKeyUp }
onInput = { this.onInput }
ref = { this.onRef }
/>
</MarkdownStyler>
);
}
}
Markdown.propTypes = {
value: PropTypes.string.isRequired,
selection: PropTypes.shape({
start: PropTypes.number.isRequired,
end: PropTypes.number.isRequired,
}).isRequired,
};
export default Markdown;