text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  
  var _debug = require('debug');
  
  var _debug2 = _interopRequireDefault(_debug);
  
  var _reactImmutableProptypes = require('react-immutable-proptypes');
  
  var _reactImmutableProptypes2 = _interopRequireDefault(_reactImmutableProptypes);
  
  var _react = require('react');
  
  var _react2 = _interopRequireDefault(_react);
  
  var _slatePropTypes = require('slate-prop-types');
  
  var _slatePropTypes2 = _interopRequireDefault(_slatePropTypes);
  
  var _slateDevLogger = require('slate-dev-logger');
  
  var _slateDevLogger2 = _interopRequireDefault(_slateDevLogger);
  
  var _propTypes = require('prop-types');
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _void = require('./void');
  
  var _void2 = _interopRequireDefault(_void);
  
  var _text = require('./text');
  
  var _text2 = _interopRequireDefault(_text);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  
  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  
  /**
   * Debug.
   *
   * @type {Function}
   */
  
  var debug = (0, _debug2.default)('slate:node');
  
  /**
   * Node.
   *
   * @type {Component}
   */
  
  var Node = function (_React$Component) {
    _inherits(Node, _React$Component);
  
    function Node() {
      var _ref;
  
      var _temp, _this, _ret;
  
      _classCallCheck(this, Node);
  
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
  
      return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Node.__proto__ || Object.getPrototypeOf(Node)).call.apply(_ref, [this].concat(args))), _this), _initialiseProps.call(_this), _temp), _possibleConstructorReturn(_this, _ret);
    }
  
    /**
     * Property types.
     *
     * @type {Object}
     */
  
    /**
     * Debug.
     *
     * @param {String} message
     * @param {Mixed} ...args
     */
  
    /**
     * Should the node update?
     *
     * @param {Object} nextProps
     * @param {Object} value
     * @return {Boolean}
     */
  
    _createClass(Node, [{
      key: 'render',
  
  
      /**
       * Render.
       *
       * @return {Element}
       */
  
      value: function render() {
        var _this2 = this;
  
        this.debug('render', this);
  
        var _props = this.props,
            editor = _props.editor,
            isSelected = _props.isSelected,
            node = _props.node,
            parent = _props.parent,
            readOnly = _props.readOnly;
        var value = editor.value;
        var selection = value.selection;
        var stack = editor.stack;
  
        var indexes = node.getSelectionIndexes(selection, isSelected);
        var children = node.nodes.toArray().map(function (child, i) {
          var isChildSelected = !!indexes && indexes.start <= i && i < indexes.end;
          return _this2.renderNode(child, isChildSelected);
        });
  
        // Attributes that the developer must to mix into the element in their
        // custom node renderer component.
        var attributes = { 'data-key': node.key };
  
        // If it's a block node with inline children, add the proper `dir` attribute
        // for text direction.
        if (node.kind == 'block' && node.nodes.first().kind != 'block') {
          var direction = node.getTextDirection();
          if (direction == 'rtl') attributes.dir = 'rtl';
        }
  
        var props = {
          key: node.key,
          editor: editor,
          isSelected: isSelected,
          node: node,
          parent: parent,
          readOnly: readOnly
        };
  
        var placeholder = stack.find('renderPlaceholder', props);
  
        if (placeholder) {
          placeholder = _react2.default.cloneElement(placeholder, { key: node.key + '-placeholder' });
          children = [placeholder].concat(_toConsumableArray(children));
        }
  
        var element = stack.find('renderNode', _extends({}, props, { attributes: attributes, children: children }));
  
        return node.isVoid ? _react2.default.createElement(
          _void2.default,
          this.props,
          element
        ) : element;
      }
  
      /**
       * Render a `child` node.
       *
       * @param {Node} child
       * @param {Boolean} isSelected
       * @return {Element}
       */
  
    }]);
  
    return Node;
  }(_react2.default.Component);
  
  /**
   * Export.
   *
   * @type {Component}
   */
  
  Node.propTypes = {
    block: _slatePropTypes2.default.block,
    decorations: _reactImmutableProptypes2.default.list.isRequired,
    editor: _propTypes2.default.object.isRequired,
    isSelected: _propTypes2.default.bool.isRequired,
    node: _slatePropTypes2.default.node.isRequired,
    parent: _slatePropTypes2.default.node.isRequired,
    readOnly: _propTypes2.default.bool.isRequired
  };
  
  var _initialiseProps = function _initialiseProps() {
    var _this3 = this;
  
    this.debug = function (message) {
      for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
        args[_key2 - 1] = arguments[_key2];
      }
  
      var node = _this3.props.node;
      var key = node.key,
          type = node.type;
  
      debug.apply(undefined, [message, key + ' (' + type + ')'].concat(args));
    };
  
    this.shouldComponentUpdate = function (nextProps) {
      var props = _this3.props;
      var stack = props.editor.stack;
  
      var shouldUpdate = stack.find('shouldNodeComponentUpdate', props, nextProps);
      var n = nextProps;
      var p = props;
  
      // If the `Component` has a custom logic to determine whether the component
      // needs to be updated or not, return true if it returns true. If it returns
      // false, we need to ignore it, because it shouldn't be allowed it.
      if (shouldUpdate != null) {
        if (shouldUpdate) {
          return true;
        }
  
        if (shouldUpdate === false) {
          _slateDevLogger2.default.warn('Returning false in `shouldNodeComponentUpdate` does not disable Slate\'s internal `shouldComponentUpdate` logic. If you want to prevent updates, use React\'s `shouldComponentUpdate` instead.');
        }
      }
  
      // If the `readOnly` status has changed, re-render in case there is any
      // user-land logic that depends on it, like nested editable contents.
      if (n.readOnly != p.readOnly) return true;
  
      // If the node has changed, update. PERF: There are cases where it will have
      // changed, but it's properties will be exactly the same (eg. copy-paste)
      // which this won't catch. But that's rare and not a drag on performance, so
      // for simplicity we just let them through.
      if (n.node != p.node) return true;
  
      // If the selection value of the node or of some of its children has changed,
      // re-render in case there is any user-land logic depends on it to render.
      // if the node is selected update it, even if it was already selected: the
      // selection value of some of its children could have been changed and they
      // need to be rendered again.
      if (n.isSelected || p.isSelected) return true;
  
      // If the decorations have changed, update.
      if (!n.decorations.equals(p.decorations)) return true;
  
      // Otherwise, don't update.
      return false;
    };
  
    this.renderNode = function (child, isSelected) {
      var _props2 = _this3.props,
          block = _props2.block,
          decorations = _props2.decorations,
          editor = _props2.editor,
          node = _props2.node,
          readOnly = _props2.readOnly;
      var stack = editor.stack;
  
      var Component = child.kind == 'text' ? _text2.default : Node;
      var decs = decorations.concat(node.getDecorations(stack));
      return _react2.default.createElement(Component, {
        block: node.kind == 'block' ? node : block,
        decorations: decs,
        editor: editor,
        isSelected: isSelected,
        key: child.key,
        node: child,
        parent: node,
        readOnly: readOnly
      });
    };
  };
  
  exports.default = Node;