UNPKG

codogo-react-widgets

Version:

Provides a unified way to access the styling of commonly used widgets across different apps

201 lines (169 loc) 4.43 kB
import selectionManipulator from "selection-range"; import autobind from "autobind-decorator"; import hljs from "highlight.js"; import styled from "styled-components"; import { keyCodesToForwardOnChange, } from "./constants"; const MarkdownStyler = styled.div` div { display: inline-block; margin: 0; outline: 0px solid transparent; pointer-events: all; tabSize: 4; white-space: pre-wrap; width: 100%; &:empty { display: block; } &:empty::before { content: "${R.prop("placeholder")}"; opacity: 0.33; } } a, a:hover, a:visited, a:active, a:link { color: ${R.path(["theme", "colors", "primary",])}; max-width: 100%; cursor: pointer; text-decoration: underline; word-wrap: break-word; } .hljs-emphasis { color: ${R.path(["theme", "colors", "red",])}; } .hljs-strong { color: ${R.path(["theme", "colors", "yellow",])}; } .hljs-string { color: ${R.path(["theme", "colors", "green",])}; } .hljs-link { color: ${R.path(["theme", "colors", "blue",])}; } .hljs-code { color: ${R.path(["theme", "colors", "orange",])}; } `; const selectionEq = (lhs = {}, rhs = {}) => lhs.start === rhs.start && lhs.end === rhs.end; const isFirefox = typeof InstallTrigger !== "undefined"; //const isOpera = (!!window.opr && !!window.opr.addons) || !!window.opera || navigator.userAgent.indexOf(" OPR/") >= 0; //const isSafari = /constructor/i.test(window.HTMLElement) || (function(p) { return p.toString() === "[object SafariRemoteNotification]"; })( !window["safari"] || (typeof safari !== "undefined" && safari.pushNotification),); //const isIE = [>@cc_on!@<] false || !!document.documentMode; //const isEdge = !isIE && !!window.StyleMedia; //const isChrome = !!window.chrome && !!window.chrome.webstore; //const isBlink = (isChrome || isOpera) && !!window.CSS; export default class Markdown extends React.Component { 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(); } const oldValue = domElement.textContent; if (oldValue !== this.props.value) { domElement.textContent = this.props.value; domElement.innerHTML = hljs.highlight( "markdown", this.props.value, ).value; } const oldSelection = selectionManipulator(domElement); if ( !selectionEq(oldSelection, this.props.selection) && this.props.value.length ) { selectionManipulator(domElement, this.props.selection || {}); } } else { domElement.textContent = this.props.value; domElement.blur(); } } @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> ); } }