JSFiddle - React, Tailwind, and code Playground
by Jason Miller
HTML
<script src="https://unpkg.com/preact"></script>
CSS
div[contentEditable] {
min-height: 50px;
padding: 10px;
background: white;
border: 1px solid #CCC;
border-radius: 3px;
}
Babel + JSX
const { h, Component, render } = preact; /** @jsx h */
class Demo extends Component {
state = { content: '' };
// when pressing enter, insert an HR
onChange = ({ value, keyCode }) => {
let content = value;
if (keyCode===13) {
content = this.state.content + '<hr>';
}
this.setState({ content });
};
render({}, { content }) {
return (
<Editor
value={content}
onChange={this.onChange}
/>
);
}
}
/** It's ideal to wrap in a sCU */
class Editor extends Component {
shouldComponentUpdate(nextProps) {
return nextProps.value!==this.props.value && nextProps.value!==this.currentValue;
}
handleKeyDown = e => {
let value = this.base.innerHTML;
this.currentValue = value;
let evt = { value, keyCode: e.keyCode };
if (this.props.onChange(evt)===false) {
return e.preventDefault(), false;
}
};
moveSelectionToEnd = () => {
let sel = getSelection();
sel.removeAllRanges();
let range = document.createRange();
range.setStartAfter(this.base.lastChild);
sel.addRange(range);
};
componentDidUpdate(prevProps) {
let { value } = this.props;
if (value.length > prevProps.value.length) {
this.moveSelectionToEnd();
}
}
render({ value }) {
return (
<div
contentEditable
onKeyDown={this.handleKeyDown}
dangerouslySetInnerHTML={{
__html: value
}}
/>
);
}
}
render(<Demo />, document.body);