diff --git a/src/components/Widgets/MarkdownControl.js b/src/components/Widgets/MarkdownControl.js index 8631ce99..4f41f969 100644 --- a/src/components/Widgets/MarkdownControl.js +++ b/src/components/Widgets/MarkdownControl.js @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react'; +import _ from 'lodash'; import { Editor, Plain } from 'slate'; import position from 'selection-position'; import Markdown from 'slate-markdown-serializer'; @@ -41,7 +42,8 @@ class MarkdownControl extends React.Component { this.handleInlineClick = this.handleInlineClick.bind(this); this.handleBlockTypeClick = this.handleBlockTypeClick.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); - this.calculateMenuPositions = this.calculateMenuPositions.bind(this); + this.calculateHoverMenuPosition = _.throttle(this.calculateHoverMenuPosition.bind(this), 100); + this.calculateBlockMenuPosition = _.throttle(this.calculateBlockMenuPosition.bind(this), 100); this.renderBlockTypesMenu = this.renderBlockTypesMenu.bind(this); this.renderNode = this.renderNode.bind(this); this.renderMark = this.renderMark.bind(this); @@ -57,7 +59,8 @@ class MarkdownControl extends React.Component { if (this.blockEdit) { this.blockEdit = false; } else { - this.setState({ state }, this.calculateMenuPositions); + this.calculateHoverMenuPosition(); + this.setState({ state }, this.calculateBlockMenuPosition); } } @@ -65,29 +68,30 @@ class MarkdownControl extends React.Component { this.props.onChange(markdown.serialize(state)); } - /** - * All menu positions are calculated accessing dom elements - * That's why calculateMenuPositions is called on handleChange's setState callback - */ - calculateMenuPositions() { - const rect1 = position(); + calculateHoverMenuPosition() { + const rect = position(); this.menuPositions.stylesMenu = { - top: rect1.top + window.scrollY, - left: rect1.left + window.scrollX, - width: rect1.width, - height: rect1.height + top: rect.top + window.scrollY, + left: rect.left + window.scrollX, + width: rect.width, + height: rect.height }; + } - const blockElement = document.querySelectorAll(`[data-key='${this.state.state.selection.focusKey}']`); - if (blockElement.length > 0) { - const rect2 = blockElement[0].getBoundingClientRect(); - this.menuPositions.blockTypesMenu = { - top: rect2.top + window.scrollY, - left: rect2.left + window.scrollX - }; - this.forceUpdate(); + calculateBlockMenuPosition() { + // Don't bother calculating position if block is not empty + if (this.state.state.blocks.get(0).isEmpty) { + const blockElement = document.querySelectorAll(`[data-key='${this.state.state.selection.focusKey}']`); + if (blockElement.length > 0) { + const rect = blockElement[0].getBoundingClientRect(); + this.menuPositions.blockTypesMenu = { + top: rect.top + window.scrollY, + left: rect.left + window.scrollX + }; + // Force re-render so the menu is positioned on these new coordinates + this.forceUpdate(); + } } - } /** @@ -191,7 +195,10 @@ class MarkdownControl extends React.Component { state = state .transform() - .insertBlock(type) + .insertBlock({ + type: type, + isVoid: true + }) .apply(); this.setState({ state }, () => { @@ -235,7 +242,7 @@ class MarkdownControl extends React.Component { renderBlockTypesMenu() { const currentBlock = this.state.state.blocks.get(0); - const isOpen = (currentBlock.isEmpty && currentBlock.type !== 'list-item' && currentBlock.type !== 'horizontal-rule'); + const isOpen = (currentBlock.isEmpty && currentBlock.type !== 'horizontal-rule'); return ( {children} - ); -} - -BlockStatic.propTypes = { - children: PropTypes.node.isRequired, - type: PropTypes.oneOf(AVAILABLE_TYPES).isRequired -}; - -export default BlockStatic; diff --git a/src/components/Widgets/MarkdownControlElements/localRenderers.css b/src/components/Widgets/MarkdownControlElements/localRenderers.css new file mode 100644 index 00000000..4ceb194b --- /dev/null +++ b/src/components/Widgets/MarkdownControlElements/localRenderers.css @@ -0,0 +1,3 @@ +.active { + box-shadow: 0 0 0 2px blue; +} diff --git a/src/components/Widgets/MarkdownControlElements/localRenderers.js b/src/components/Widgets/MarkdownControlElements/localRenderers.js index 32974536..d6a133af 100644 --- a/src/components/Widgets/MarkdownControlElements/localRenderers.js +++ b/src/components/Widgets/MarkdownControlElements/localRenderers.js @@ -1,6 +1,6 @@ import React from 'react'; import Block from './Block'; -import BlockStatic from './BlockStatic'; +import styles from './localRenderers.css' /* eslint react/prop-types: 0, react/no-multi-comp: 0 */ @@ -19,7 +19,14 @@ export const NODES = { 'heading6': props => {props.children}, 'list-item': props =>
  • {props.children}
  • , 'paragraph': props => {props.children}, - 'horizontal-rule': props => {props.children}, + 'horizontal-rule': props => { + const { node, state } = props; + const isFocused = state.selection.hasEdgeIn(node); + const className = isFocused ? styles.active : null; + return ( +
    + ); + }, 'link': (props) => { const { data } = props.node; const href = data.get('href');