All files index.ts

100% Statements 31/31
100% Branches 15/15
100% Functions 3/3
100% Lines 30/30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 731x 1x   1x 1x   1x 1x   3x 2x                                 2x   2x   2x 20x 20x   20x         2x   2x 2x 6x     6x 6x   1x     5x 2x     5x 5x 5x   5x 3x         20x       1x  
import * as React from 'react';
import * as ReactDOM from 'react-dom';
 
const HIGHLIGHT_CLASS = 'react-update-highlight';
const MATCHES_HIGHLIGHT_CLASS = /\s*\breact-update-highlight\b\s*/gi;
 
const STYLE = document.createElement('style');
STYLE.type = 'text/css';
 
export const highlightUpdates = (color: string = 'rgba(255, 0, 0, 0.5)') => {
  STYLE.innerHTML =
`.react-update-highlight {
  animation-name: react-update-highlight;
  animation-duration: 2s;
  animation-iteration-count: 1;
}
 
@keyframes react-update-highlight {
  from {
    background-color: ${color};
  }
 
  to {
    background-color: transparent;
  }
}`;
 
  document.head.appendChild(STYLE);
 
  const originalCreateElement = React.createElement;
 
  (React as any).createElement = function () {
    const args = Array.prototype.slice.call(arguments);
    const component = args[0];
 
    if (
      typeof component === 'function' &&
      component.prototype instanceof React.Component &&
      !component.prototype.hasReactUpdateHighlight
    ) {
      const originalComponentDidUpdate = (component as any).prototype.componentDidUpdate;
 
      component.prototype.hasReactUpdateHighlight = true;
      (component as any).prototype.componentDidUpdate = function () {
        const updateArgs = Array.prototype.slice.call(arguments);
        let node: Element;
 
        try {
          node = ReactDOM.findDOMNode(this);
        } catch (error) {
          return;
        }
 
        if (MATCHES_HIGHLIGHT_CLASS.test(node.className)) {
          node.className = node.className.replace(MATCHES_HIGHLIGHT_CLASS, '');
        }
 
        void (node as any).offsetWidth; // tslint:disable-line:no-unused-expression
        const needsSpace = node.className || node.className.lastIndexOf(' ') !== node.className.length - 1;
        node.className = `${node.className}${needsSpace ? ' ' + HIGHLIGHT_CLASS : HIGHLIGHT_CLASS}`;
 
        if (typeof originalComponentDidUpdate === 'function') {
          originalComponentDidUpdate.apply(this, updateArgs);
        }
      };
    }
 
    return originalCreateElement.apply(this, args);
  };
};
 
export default highlightUpdates;