text: import { render, unmountComponentAtNode } from 'react-dom';
  import * as React from 'react';
  import toArray from "rc-util/es/Children/toArray"; // We only handle element & text node.
  
  var ELEMENT_NODE = 1;
  var TEXT_NODE = 3;
  var COMMENT_NODE = 8;
  var ellipsisContainer;
  var wrapperStyle = {
    padding: 0,
    margin: 0,
    display: 'inline',
    lineHeight: 'inherit'
  };
  
  function styleToString(style) {
    // There are some different behavior between Firefox & Chrome.
    // We have to handle this ourself.
    var styleNames = Array.prototype.slice.apply(style);
    return styleNames.map(function (name) {
      return "".concat(name, ": ").concat(style.getPropertyValue(name), ";");
    }).join('');
  }
  
  function mergeChildren(children) {
    var childList = [];
    children.forEach(function (child) {
      var prevChild = childList[childList.length - 1];
  
      if (typeof child === 'string' && typeof prevChild === 'string') {
        childList[childList.length - 1] += child;
      } else {
        childList.push(child);
      }
    });
    return childList;
  }
  
  function resetDomStyles(target, origin) {
    target.setAttribute('aria-hidden', 'true');
    var originStyle = window.getComputedStyle(origin);
    var originCSS = styleToString(originStyle); // Set shadow
  
    target.setAttribute('style', originCSS);
    target.style.position = 'fixed';
    target.style.left = '0';
    target.style.height = 'auto';
    target.style.minHeight = 'auto';
    target.style.maxHeight = 'auto';
    target.style.paddingTop = '0';
    target.style.paddingBottom = '0';
    target.style.borderTopWidth = '0';
    target.style.borderBottomWidth = '0';
    target.style.top = '-999999px';
    target.style.zIndex = '-1000'; // clean up css overflow
  
    target.style.textOverflow = 'clip';
    target.style.whiteSpace = 'normal';
    target.style.webkitLineClamp = 'none';
  }
  
  function getRealLineHeight(originElement) {
    var heightContainer = document.createElement('div');
    resetDomStyles(heightContainer, originElement);
    heightContainer.appendChild(document.createTextNode('text'));
    document.body.appendChild(heightContainer); // The element real height is always less than multiple of line-height
    // Use getBoundingClientRect to get actual single row height of the element
  
    var realHeight = heightContainer.getBoundingClientRect().height;
    document.body.removeChild(heightContainer);
    return realHeight;
  }
  
  export default (function (originElement, option, content, fixedContent, ellipsisStr) {
    if (!ellipsisContainer) {
      ellipsisContainer = document.createElement('div');
      ellipsisContainer.setAttribute('aria-hidden', 'true');
    } // HMR will remove this from body which should patch back
  
  
    if (!ellipsisContainer.parentNode) {
      document.body.appendChild(ellipsisContainer);
    }
  
    var rows = option.rows,
        _option$suffix = option.suffix,
        suffix = _option$suffix === void 0 ? '' : _option$suffix;
    var lineHeight = getRealLineHeight(originElement);
    var maxHeight = Math.round(lineHeight * rows * 100) / 100;
    resetDomStyles(ellipsisContainer, originElement); // Render in the fake container
  
    var contentList = mergeChildren(toArray(content));
    render( /*#__PURE__*/React.createElement("div", {
      style: wrapperStyle
    }, /*#__PURE__*/React.createElement("span", {
      style: wrapperStyle
    }, contentList, suffix), /*#__PURE__*/React.createElement("span", {
      style: wrapperStyle
    }, fixedContent)), ellipsisContainer); // wrap in an div for old version react
    // Check if ellipsis in measure div is height enough for content
  
    function inRange() {
      var currentHeight = Math.round(ellipsisContainer.getBoundingClientRect().height * 100) / 100;
      return currentHeight - .1 <= maxHeight; // -.1 for firefox
    } // Skip ellipsis if already match
  
  
    if (inRange()) {
      unmountComponentAtNode(ellipsisContainer);
      return {
        content: content,
        text: ellipsisContainer.innerHTML,
        ellipsis: false
      };
    } // We should clone the childNode since they're controlled by React and we can't reuse it without warning
  
  
    var childNodes = Array.prototype.slice.apply(ellipsisContainer.childNodes[0].childNodes[0].cloneNode(true).childNodes).filter(function (_ref) {
      var nodeType = _ref.nodeType;
      return nodeType !== COMMENT_NODE;
    });
    var fixedNodes = Array.prototype.slice.apply(ellipsisContainer.childNodes[0].childNodes[1].cloneNode(true).childNodes);
    unmountComponentAtNode(ellipsisContainer); // ========================= Find match ellipsis content =========================
  
    var ellipsisChildren = [];
    ellipsisContainer.innerHTML = ''; // Create origin content holder
  
    var ellipsisContentHolder = document.createElement('span');
    ellipsisContainer.appendChild(ellipsisContentHolder);
    var ellipsisTextNode = document.createTextNode(ellipsisStr + suffix);
    ellipsisContentHolder.appendChild(ellipsisTextNode);
    fixedNodes.forEach(function (childNode) {
      ellipsisContainer.appendChild(childNode);
    }); // Append before fixed nodes
  
    function appendChildNode(node) {
      ellipsisContentHolder.insertBefore(node, ellipsisTextNode);
    } // Get maximum text
  
  
    function measureText(textNode, fullText) {
      var startLoc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
      var endLoc = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : fullText.length;
      var lastSuccessLoc = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
      var midLoc = Math.floor((startLoc + endLoc) / 2);
      var currentText = fullText.slice(0, midLoc);
      textNode.textContent = currentText;
  
      if (startLoc >= endLoc - 1) {
        // Loop when step is small
        for (var step = endLoc; step >= startLoc; step -= 1) {
          var currentStepText = fullText.slice(0, step);
          textNode.textContent = currentStepText;
  
          if (inRange() || !currentStepText) {
            return step === fullText.length ? {
              finished: false,
              reactNode: fullText
            } : {
              finished: true,
              reactNode: currentStepText
            };
          }
        }
      }
  
      if (inRange()) {
        return measureText(textNode, fullText, midLoc, endLoc, midLoc);
      }
  
      return measureText(textNode, fullText, startLoc, midLoc, lastSuccessLoc);
    }
  
    function measureNode(childNode, index) {
      var type = childNode.nodeType;
  
      if (type === ELEMENT_NODE) {
        // We don't split element, it will keep if whole element can be displayed.
        appendChildNode(childNode);
  
        if (inRange()) {
          return {
            finished: false,
            reactNode: contentList[index]
          };
        } // Clean up if can not pull in
  
  
        ellipsisContentHolder.removeChild(childNode);
        return {
          finished: true,
          reactNode: null
        };
      }
  
      if (type === TEXT_NODE) {
        var fullText = childNode.textContent || '';
        var textNode = document.createTextNode(fullText);
        appendChildNode(textNode);
        return measureText(textNode, fullText);
      } // Not handle other type of content
      // PS: This code should not be attached after react 16
  
      /* istanbul ignore next */
  
  
      return {
        finished: false,
        reactNode: null
      };
    }
  
    childNodes.some(function (childNode, index) {
      var _measureNode = measureNode(childNode, index),
          finished = _measureNode.finished,
          reactNode = _measureNode.reactNode;
  
      if (reactNode) {
        ellipsisChildren.push(reactNode);
      }
  
      return finished;
    });
    return {
      content: ellipsisChildren,
      text: ellipsisContainer.innerHTML,
      ellipsis: true
    };
  });