diff --git a/src/components/Widgets/MarkdownControl.js b/src/components/Widgets/MarkdownControl.js index 13e02dca..15daa406 100644 --- a/src/components/Widgets/MarkdownControl.js +++ b/src/components/Widgets/MarkdownControl.js @@ -4,6 +4,7 @@ import Portal from 'react-portal'; import position from 'selection-position'; import Markdown from 'slate-markdown-serializer'; import { DEFAULT_NODE, NODES, MARKS } from './MarkdownControlElements/localRenderers'; +import AddBlock from './MarkdownControlElements/AddBlock'; import { Icon } from '../UI'; import styles from './MarkdownControl.css'; @@ -17,17 +18,22 @@ class MarkdownControl extends React.Component { super(props); this.blockEdit = false; this.state = { - state: props.value ? markdown.deserialize(props.value) : Plain.deserialize('') + state: props.value ? markdown.deserialize(props.value) : Plain.deserialize(''), + addBlockButton:{ + show: false + } }; this.hasMark = this.hasMark.bind(this); this.hasBlock = this.hasBlock.bind(this); this.handleChange = this.handleChange.bind(this); this.handleDocumentChange = this.handleDocumentChange.bind(this); + this.maybeShowBlockAddButton = this.maybeShowBlockAddButton.bind(this); this.onClickMark = this.onClickMark.bind(this); this.onClickBlock = this.onClickBlock.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.renderMenu = this.renderMenu.bind(this); + this.renderAddBlock = this.renderAddBlock.bind(this); this.renderMarkButton = this.renderMarkButton.bind(this); this.renderBlockButton = this.renderBlockButton.bind(this); this.renderNode = this.renderNode.bind(this); @@ -69,7 +75,8 @@ class MarkdownControl extends React.Component { if (this.blockEdit) { this.blockEdit = false; } else { - this.setState({ state }); + + this.setState({ state }, this.maybeShowBlockAddButton); } } @@ -77,6 +84,22 @@ class MarkdownControl extends React.Component { this.props.onChange(markdown.serialize(state)); } + maybeShowBlockAddButton() { + if (this.state.state.blocks.get(0).isEmpty) { + const rect = document.querySelectorAll(`[data-key='${this.state.state.selection.focusKey}']`)[0].getBoundingClientRect(); + this.setState({ addBlockButton: { + show: true, + top: rect.top + window.scrollY + 2, + left: rect.left + window.scrollX - 28 + } }); + + } else { + this.setState({ addBlockButton: { + show: false + } }); + } + } + /** * Toggle marks / blocks when button is clicked */ @@ -179,6 +202,12 @@ class MarkdownControl extends React.Component { ); } + renderAddBlock() { + return ( + this.state.addBlockButton.show ? <AddBlock top={this.state.addBlockButton.top} left={this.state.addBlockButton.left} /> : null + ); + } + renderMarkButton(type, icon) { const isActive = this.hasMark(type); const onMouseDown = e => this.onClickMark(e, type); @@ -233,6 +262,7 @@ class MarkdownControl extends React.Component { return ( <div> {this.renderMenu()} + {this.renderAddBlock()} <Editor placeholder={'Enter some rich text...'} state={this.state.state} diff --git a/src/components/Widgets/MarkdownControlElements/AddBlock.css b/src/components/Widgets/MarkdownControlElements/AddBlock.css new file mode 100644 index 00000000..f2f43ba7 --- /dev/null +++ b/src/components/Widgets/MarkdownControlElements/AddBlock.css @@ -0,0 +1,10 @@ +.root { + position: absolute; + color: #ddd; + transition: color 0.5s ease; + cursor: pointer; +} + +.root:hover { + color: #aaa; +} diff --git a/src/components/Widgets/MarkdownControlElements/AddBlock.js b/src/components/Widgets/MarkdownControlElements/AddBlock.js new file mode 100644 index 00000000..c54310dd --- /dev/null +++ b/src/components/Widgets/MarkdownControlElements/AddBlock.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Icon } from '../../UI'; +import styles from './AddBlock.css'; + +export default function AddBlock({top, left}) { + const style = { + top, + left + } + return ( + <Icon type="plus-squared" className={styles.root} style={style} /> + ); +}