import Leaf from './leaf' import Mark from '../models/mark' import OffsetKey from '../utils/offset-key' import React from 'react' import ReactDOM from 'react-dom' import keycode from 'keycode' import { IS_FIREFOX } from '../utils/environment' /** * Void. * * @type {Component} */ class Void extends React.Component { /** * Property types. */ static propTypes = { children: React.PropTypes.any.isRequired, className: React.PropTypes.string, editor: React.PropTypes.object.isRequired, node: React.PropTypes.object.isRequired, state: React.PropTypes.object.isRequired, style: React.PropTypes.object }; /** * Default properties. */ static defaultProps = { style: {} } /** * Should the component update? * * @param {Object} props * @param {Object} state * @return {Boolean} */ shouldComponentUpdate = (props, state) => { return ( props.node != this.props.node || (props.state.isFocused && props.state.selection.hasEdgeIn(props.node)) ) } /** * When one of the wrapper elements it clicked, select the void node. * * @param {Event} e */ onClick = (e) => { e.preventDefault() const { state, node, editor } = this.props const next = state .transform() .moveToRangeOf(node) .focus() .apply() editor.onChange(next) } /** * Render. * * @return {Element} */ render = () => { const { children, node, className, style } = this.props const Tag = node.kind == 'block' ? 'div' : 'span' // Make the outer wrapper relative, so the spacer can overlay it. const styles = { ...style, position: 'relative' } return ( {this.renderSpacer()} {children} ) } /** * Render a fake spacer leaf, which will catch the cursor when it the void * node is navigated to with the arrow keys. Having this spacer there means * the browser continues to manage the selection natively, so it keeps track * of the right offset when moving across the block. * * @return {Element} */ renderSpacer = () => { // COMPAT: In Firefox, if the is positioned absolutely, it won't // receive the cursor properly when navigating via arrow keys. const style = IS_FIREFOX ? { pointerEvents: 'none', width: '0px', height: '0px', lineHeight: '0px', visibility: 'hidden' } : { position: 'absolute', top: '0px', left: '-9999px', textIndent: '-9999px' } return ( {this.renderLeaf()} ) } /** * Render a fake leaf. * * @return {Element} */ renderLeaf = () => { const { node, state } = this.props const child = node.getTexts().first() const ranges = child.getRanges() const text = '' const marks = Mark.createSet() const index = 0 const offsetKey = OffsetKey.stringify({ key: child.key, index }) return ( ) } /** * Render a fake leaf mark. * * @return {Object} */ renderLeafMark = (mark) => { return {} } } /** * Export. */ export default Void