Floating button to add different block types
This commit is contained in:
parent
d7c7ba4cdc
commit
62d6ece758
@ -4,6 +4,7 @@ import Portal from 'react-portal';
|
|||||||
import position from 'selection-position';
|
import position from 'selection-position';
|
||||||
import Markdown from 'slate-markdown-serializer';
|
import Markdown from 'slate-markdown-serializer';
|
||||||
import { DEFAULT_NODE, NODES, MARKS } from './MarkdownControlElements/localRenderers';
|
import { DEFAULT_NODE, NODES, MARKS } from './MarkdownControlElements/localRenderers';
|
||||||
|
import AddBlock from './MarkdownControlElements/AddBlock';
|
||||||
import { Icon } from '../UI';
|
import { Icon } from '../UI';
|
||||||
import styles from './MarkdownControl.css';
|
import styles from './MarkdownControl.css';
|
||||||
|
|
||||||
@ -17,17 +18,22 @@ class MarkdownControl extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.blockEdit = false;
|
this.blockEdit = false;
|
||||||
this.state = {
|
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.hasMark = this.hasMark.bind(this);
|
||||||
this.hasBlock = this.hasBlock.bind(this);
|
this.hasBlock = this.hasBlock.bind(this);
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
this.handleDocumentChange = this.handleDocumentChange.bind(this);
|
this.handleDocumentChange = this.handleDocumentChange.bind(this);
|
||||||
|
this.maybeShowBlockAddButton = this.maybeShowBlockAddButton.bind(this);
|
||||||
this.onClickMark = this.onClickMark.bind(this);
|
this.onClickMark = this.onClickMark.bind(this);
|
||||||
this.onClickBlock = this.onClickBlock.bind(this);
|
this.onClickBlock = this.onClickBlock.bind(this);
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.renderMenu = this.renderMenu.bind(this);
|
this.renderMenu = this.renderMenu.bind(this);
|
||||||
|
this.renderAddBlock = this.renderAddBlock.bind(this);
|
||||||
this.renderMarkButton = this.renderMarkButton.bind(this);
|
this.renderMarkButton = this.renderMarkButton.bind(this);
|
||||||
this.renderBlockButton = this.renderBlockButton.bind(this);
|
this.renderBlockButton = this.renderBlockButton.bind(this);
|
||||||
this.renderNode = this.renderNode.bind(this);
|
this.renderNode = this.renderNode.bind(this);
|
||||||
@ -69,7 +75,8 @@ class MarkdownControl extends React.Component {
|
|||||||
if (this.blockEdit) {
|
if (this.blockEdit) {
|
||||||
this.blockEdit = false;
|
this.blockEdit = false;
|
||||||
} else {
|
} else {
|
||||||
this.setState({ state });
|
|
||||||
|
this.setState({ state }, this.maybeShowBlockAddButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +84,22 @@ class MarkdownControl extends React.Component {
|
|||||||
this.props.onChange(markdown.serialize(state));
|
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
|
* 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) {
|
renderMarkButton(type, icon) {
|
||||||
const isActive = this.hasMark(type);
|
const isActive = this.hasMark(type);
|
||||||
const onMouseDown = e => this.onClickMark(e, type);
|
const onMouseDown = e => this.onClickMark(e, type);
|
||||||
@ -233,6 +262,7 @@ class MarkdownControl extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.renderMenu()}
|
{this.renderMenu()}
|
||||||
|
{this.renderAddBlock()}
|
||||||
<Editor
|
<Editor
|
||||||
placeholder={'Enter some rich text...'}
|
placeholder={'Enter some rich text...'}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
|
10
src/components/Widgets/MarkdownControlElements/AddBlock.css
Normal file
10
src/components/Widgets/MarkdownControlElements/AddBlock.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.root {
|
||||||
|
position: absolute;
|
||||||
|
color: #ddd;
|
||||||
|
transition: color 0.5s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root:hover {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
13
src/components/Widgets/MarkdownControlElements/AddBlock.js
Normal file
13
src/components/Widgets/MarkdownControlElements/AddBlock.js
Normal file
@ -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} />
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user