UNPKG

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
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(); } @autobind 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; } @autobind onRef(ref) { if (ref) { this.ref = ref; } } @autobind onKeyDown() {} @autobind 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, }); } } @autobind onClick(event) { this.onChange(event); } @autobind 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; } @autobind 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;