"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.serialization = exports.reactAttributes = exports.parseStyleString = exports.moveFocusToBeginningOfTable = exports["default"] = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _react = _interopRequireDefault(require("react"));

var _slate = require("slate");

var _debug = _interopRequireDefault(require("debug"));

var _GridOn = _interopRequireDefault(require("@material-ui/icons/GridOn"));

var _tableToolbar = _interopRequireDefault(require("./table-toolbar"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _slatePropTypes = _interopRequireDefault(require("slate-prop-types"));

var _styles = require("@material-ui/core/styles");

var _reactAttrConverter = _interopRequireDefault(require("react-attr-converter"));

var _toStyle = require("to-style");

var _CustomTablePlugin = _interopRequireDefault(require("./CustomTablePlugin"));

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

var log = (0, _debug["default"])('@pie-lib:editable-html:plugins:table');
var Table = (0, _styles.withStyles)(function () {
  return {
    table: {}
  };
})(function (props) {
  var nodeAttributes = dataToAttributes(props.node.data);
  return /*#__PURE__*/_react["default"].createElement("table", (0, _extends2["default"])({
    className: props.classes.table
  }, props.attributes, nodeAttributes, {
    onFocus: props.onFocus,
    onBlur: props.onBlur
  }), /*#__PURE__*/_react["default"].createElement("tbody", null, props.children));
});
Table.propTypes = {
  attributes: _propTypes["default"].object,
  onFocus: _propTypes["default"].func,
  onBlur: _propTypes["default"].func,
  node: _slatePropTypes["default"].node,
  children: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].node), _propTypes["default"].node]).isRequired
};

var TableRow = function TableRow(props) {
  return /*#__PURE__*/_react["default"].createElement("tr", props.attributes, props.children);
};

TableRow.propTypes = {
  attributes: _propTypes["default"].object,
  onFocus: _propTypes["default"].func,
  onBlur: _propTypes["default"].func,
  children: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].node), _propTypes["default"].node]).isRequired
};
var TableCell = (0, _styles.withStyles)(function () {
  return {
    td: {
      minWidth: '25px'
    }
  };
})(function (props) {
  var Tag = props.node.data.get('header') ? 'th' : 'td';
  var nodeAttributes = dataToAttributes(props.node.data);
  delete nodeAttributes.header;
  return /*#__PURE__*/_react["default"].createElement(Tag, (0, _extends2["default"])({}, props.attributes, nodeAttributes, {
    colSpan: props.node.data.get('colspan'),
    className: props.classes[Tag],
    onFocus: props.onFocus,
    onBlur: props.onBlur
  }), props.children);
});
TableCell.propTypes = {
  attributes: _propTypes["default"].object,
  onFocus: _propTypes["default"].func,
  onBlur: _propTypes["default"].func,
  children: _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].node), _propTypes["default"].node]).isRequired
};

var moveFocusToBeginningOfTable = function moveFocusToBeginningOfTable(change) {
  var addedTable = change.value.document.findDescendant(function (d) {
    return !!d.data && !!d.data.get('newTable');
  });

  if (!addedTable) {
    return;
  }

  change.collapseToStartOf(addedTable);
  var update = addedTable.data.remove('newTable');
  change.setNodeByKey(addedTable.key, {
    data: update
  });
};

exports.moveFocusToBeginningOfTable = moveFocusToBeginningOfTable;

var _default = function _default(opts, toolbarPlugins
/* :  {toolbar: {}}[] */
) {
  var core = (0, _CustomTablePlugin["default"])(opts); // fix outdated schema

  if (core.schema && core.schema.blocks) {
    Object.keys(core.schema.blocks).forEach(function (key) {
      var block = core.schema.blocks[key];

      if (block.parent) {
        if (block.nodes[0].types) {
          block.nodes[0] = {
            type: block.nodes[0].types[0]
          };
        }

        if (block.nodes[0].objects) {
          block.nodes[0] = {
            object: block.nodes[0].objects[0]
          };
        }

        block.parent = {
          type: block.parent.types[0]
        };
      } else {
        block.nodes[0] = {
          type: block.nodes[0].types[0]
        };
      }
    });
  }

  core.utils.getTableBlock = function (containerNode, key) {
    var node = containerNode.getDescendant(key);
    var ancestors = containerNode.getAncestors(key).push(node);
    return ancestors.findLast(function (p) {
      return p.type === 'table';
    });
  };

  core.utils.createTableWithOptions = function (row, columns, extra) {
    var createdTable = core.utils.createTable(row, columns);

    var newTable = _slate.Block.create(_objectSpread(_objectSpread({}, createdTable.toJSON()), extra));

    return newTable;
  };

  core.toolbar = {
    type: 'table',
    icon: /*#__PURE__*/_react["default"].createElement(_GridOn["default"], null),
    ariaLabel: 'Insert Table',
    onClick: function onClick(value, onChange) {
      log('insert table');
      var change = value.change();
      var newTable = core.utils.createTableWithOptions(2, 2, {
        data: {
          border: '1',
          newTable: true
        }
      });
      change.insertBlock(newTable);
      moveFocusToBeginningOfTable(change);
      onChange(change);
    },
    supports: function supports(node, value) {
      return node && node.object === 'block' && core.utils.isSelectionInTable(value);
    },

    /**
     * Note - the node may not be a table node - it may be a node inside a table.
     */
    customToolbar: function customToolbar(node, value, onToolbarDone, getFocusedValue) {
      log('[customToolbar] node.data: ', node.data);
      var tableBlock = core.utils.getTableBlock(value.document, node === null || node === void 0 ? void 0 : node.key);
      log('[customToolbar] tableBlock: ', tableBlock);

      var hasBorder = function hasBorder() {
        return tableBlock.data.get('border') && tableBlock.data.get('border') !== '0';
      };

      var addRow = function addRow() {
        var change = core.changes.insertRow(value.change());
        onToolbarDone(change, false);
      };

      var addColumn = function addColumn() {
        var change = core.changes.insertColumn(value.change());
        onToolbarDone(change, false);
      };

      var removeRow = function removeRow() {
        var change = core.changes.removeRow(value.change());
        onToolbarDone(change, false);
      };

      var removeColumn = function removeColumn() {
        var change = core.changes.removeColumn(value.change());
        onToolbarDone(change, false);
      };

      var removeTable = function removeTable() {
        var change = core.changes.removeTable(value.change());
        onToolbarDone(change, false);
      };

      var toggleBorder = function toggleBorder() {
        var data = tableBlock.data;
        var update = data.set('border', hasBorder() ? '0' : '1');
        log('[toggleBorder] update: ', update);
        var change = value.change().setNodeByKey(tableBlock.key, {
          data: update
        });
        onToolbarDone(change, false);
      };

      var onDone = function onDone() {
        log('[onDone] call onToolbarDone...');
        onToolbarDone(null, true);
      };

      var Tb = function Tb() {
        return /*#__PURE__*/_react["default"].createElement(_tableToolbar["default"], {
          getFocusedValue: getFocusedValue,
          plugins: toolbarPlugins,
          onChange: function onChange(c) {
            return onToolbarDone(c, false);
          },
          value: value,
          onAddRow: addRow,
          onRemoveRow: removeRow,
          onAddColumn: addColumn,
          onRemoveColumn: removeColumn,
          onRemoveTable: removeTable,
          hasBorder: hasBorder(),
          onToggleBorder: toggleBorder,
          onDone: onDone
        });
      };

      return Tb;
    }
  };

  var Node = function Node(props) {
    switch (props.node.type) {
      case 'table':
        return /*#__PURE__*/_react["default"].createElement(Table, (0, _extends2["default"])({}, props, {
          onFocus: opts.onFocus,
          onBlur: opts.onBlur
        }));

      case 'table_row':
        return /*#__PURE__*/_react["default"].createElement(TableRow, props);

      case 'table_cell':
        return /*#__PURE__*/_react["default"].createElement(TableCell, (0, _extends2["default"])({}, props, {
          onFocus: opts.onFocus,
          onBlur: opts.onBlur
        }));

      default:
        return null;
    }
  };

  Node.propTypes = {
    node: _propTypes["default"].object
  };

  core.normalizeNode = function (node) {
    var addNodeBeforeArray = [];
    if (node.object !== 'document') return;
    node.findDescendant(function (d) {
      if (d.type === 'table') {
        var tablePath = node.getPath(d.key);
        var prevNode = node.getPreviousNode(tablePath);
        var nextNode = node.getNextNode(tablePath);

        if (!prevNode || !nextNode) {
          addNodeBeforeArray.push({
            node: d,
            prevNode: prevNode,
            nextNode: nextNode
          });
        }
      }
    });

    if (!addNodeBeforeArray.length) {
      return;
    }

    return function (change) {
      var newBlock = {
        object: 'block',
        type: 'div'
      };
      addNodeBeforeArray.forEach(function (n) {
        var tablePath = change.value.document.getPath(n.node.key).toJSON(); // removing tableIndex

        var indexToAdd = tablePath.splice(-1)[0];

        if (!n.prevNode) {
          // inserting block key before table
          change.insertNodeByPath(tablePath, indexToAdd, newBlock); // this will trigger another normalization, which will figure out if there's not
          // a block after the table and add it, so we exit for now

          return;
        }

        if (!n.nextNode) {
          // inserting block key after table
          change.insertNodeByPath(tablePath, indexToAdd + 1, newBlock);
        }
      });
    };
  };

  core.renderNode = Node;
  core.name = 'table';
  return core;
};

exports["default"] = _default;

var parseStyleString = function parseStyleString(s) {
  var regex = /([\w-]*)\s*:\s*([^;]*)/g;
  var match;
  var result = {};

  while (match = regex.exec(s)) {
    result[match[1]] = match[2].trim();
  }

  return result;
};

exports.parseStyleString = parseStyleString;

var reactAttributes = function reactAttributes(o) {
  return (0, _toStyle.object)(o, {
    camelize: true,
    addUnits: false
  });
};

exports.reactAttributes = reactAttributes;

var attributesToMap = function attributesToMap(el) {
  return function (acc, attribute) {
    var value = el.getAttribute(attribute);

    if (value) {
      if (attribute === 'style') {
        var styleString = el.getAttribute(attribute);
        var reactStyleObject = reactAttributes(parseStyleString(styleString));
        acc['style'] = reactStyleObject;
      } else {
        acc[attribute] = el.getAttribute(attribute);
      }
    }

    return acc;
  };
};

var dataToAttributes = function dataToAttributes(data) {
  if (!data || !data.get) {
    return {};
  }

  return data.reduce(function (acc, v, name) {
    if (v) {
      acc[(0, _reactAttrConverter["default"])(name)] = v;
    }

    return acc;
  }, {});
};

var attributes = ['border', 'cellpadding', 'cellspacing', 'class', 'style'];
var cellAttributes = ['colspan', 'rowspan', 'class', 'style'];
var serialization = {
  deserialize: function deserialize(el, next) {
    var tag = el.tagName.toLowerCase();

    switch (tag) {
      case 'table':
        {
          var children = el.children.length === 1 && el.children[0].tagName.toLowerCase() === 'tbody' ? el.children[0].children : el.children;
          var c = Array.from(children);
          return {
            object: 'block',
            type: 'table',
            nodes: next(c),
            data: attributes.reduce(attributesToMap(el), {})
          };
        }

      case 'th':
        {
          return {
            object: 'block',
            type: 'table_cell',
            nodes: next(el.childNodes),
            data: cellAttributes.reduce(attributesToMap(el), {
              header: true
            })
          };
        }

      case 'tr':
        {
          return {
            object: 'block',
            type: 'table_row',
            nodes: next(Array.from(el.children))
          };
        }

      case 'td':
        {
          return {
            object: 'block',
            type: 'table_cell',
            nodes: next(Array.from(el.childNodes)),
            data: cellAttributes.reduce(attributesToMap(el), {
              header: false
            })
          };
        }
    }
  },
  serialize: function serialize(object, children) {
    if (object.object !== 'block') {
      return;
    }

    switch (object.type) {
      case 'table':
        {
          var _attributes = dataToAttributes(object.data);

          return /*#__PURE__*/_react["default"].createElement("table", _attributes, /*#__PURE__*/_react["default"].createElement("tbody", null, children));
        }

      case 'table_row':
        {
          return /*#__PURE__*/_react["default"].createElement("tr", null, children);
        }

      case 'table_cell':
        {
          var _attributes2 = dataToAttributes(object.data);

          delete _attributes2.header;

          if (object.data.get('header')) {
            return /*#__PURE__*/_react["default"].createElement("th", _attributes2, children);
          } else {
            return /*#__PURE__*/_react["default"].createElement("td", _attributes2, children);
          }
        }
    }
  }
};
exports.serialization = serialization;
//# sourceMappingURL=index.js.map