text: /*
  Copyright (c) Uber Technologies, Inc.
  
  This source code is licensed under the MIT license found in the
  LICENSE file in the root directory of this source tree.
  */
  
  /* global document cancelIdleCallback requestIdleCallback */
  import * as React from 'react';
  import axe from 'axe-core';
  import { Layer, TetherBehavior, TETHER_PLACEMENT } from '../layer/index.js';
  import { Paragraph3, Caption1 } from '../typography/index.js';
  import { styled } from '../styles/index.js';
  import { ThemeContext } from '../styles/theme-provider.js';
  
  function validateNode(node) {
    return new Promise((resolve, reject) => {
      axe.run(node, {
        reporter: 'v2'
      }, (error, results) => {
        if (error) reject(error);
        resolve(results.violations);
      });
    });
  }
  
  function segmentViolationsByNode(violations) {
    const nodes = violations.reduce((map, violation) => {
      violation.nodes.forEach(node => {
        if (!map[node.target]) {
          map[node.target] = [violation];
        } else {
          map[node.target] = map[node.target].push(violation);
        }
      });
      return map;
    }, {});
    return Object.entries(nodes);
  }
  
  const ViolationContainer = styled('div', ({
    $theme,
    $top,
    $left
  }) => {
    return {
      backgroundColor: $theme.colors.mono100,
      boxShadow: $theme.lighting.shadow600,
      position: 'absolute',
      padding: $theme.sizing.scale400,
      top: $top,
      left: $left
    };
  });
  ViolationContainer.displayName = "ViolationContainer";
  
  function Violation(props) {
    const [offset, setOffset] = React.useState({
      top: 0,
      left: 0
    });
    const [anchor, setAnchor] = React.useState(null);
    const [popper, setPopper] = React.useState(null);
    const [isHovered, setIsHovered] = React.useState(false);
    const theme = React.useContext(ThemeContext);
  
    const handleMouseEnter = () => setIsHovered(true);
  
    const handleMouseLeave = () => setIsHovered(false);
  
    React.useEffect(() => {
      const node = document.querySelector(props.target);
  
      if (node) {
        setAnchor(node);
        node.setAttribute('style', `border: solid 1px ${theme.colors.negative300};`);
        node.addEventListener('mouseenter', handleMouseEnter);
        node.addEventListener('mouseleave', handleMouseLeave);
      }
  
      return () => {
        if (node) {
          node.removeEventListener('mouseenter', handleMouseEnter);
          node.removeEventListener('mouseleave', handleMouseLeave);
        }
      };
    }, [props.target]);
    if (!isHovered) return null;
    return /*#__PURE__*/React.createElement(Layer, null, /*#__PURE__*/React.createElement(TetherBehavior, {
      anchorRef: anchor,
      popperRef: popper,
      onPopperUpdate: update => setOffset(update.popper),
      placement: TETHER_PLACEMENT.bottom
    }, /*#__PURE__*/React.createElement(ViolationContainer, {
      ref: setPopper,
      $top: `${offset.top}px` || '0px',
      $left: `${offset.left}px` || '0px'
    }, /*#__PURE__*/React.createElement(Caption1, null, props.target), props.violations.map((violation, index) => /*#__PURE__*/React.createElement(Paragraph3, {
      key: index
    }, violation.description)))));
  }
  
  export default function A11y(props) {
    const [violations, setViolations] = React.useState([]);
    const [idleID, setIdleID] = React.useState(null);
    const child = React.useRef(null);
    React.useEffect(() => {
      if (child.current) {
        if (idleID) {
          cancelIdleCallback(idleID);
          setIdleID(null);
        }
  
        const id = requestIdleCallback(() => {
          validateNode(child.current).then(setViolations);
        });
        setIdleID(id);
      }
    }, [props.children]);
    const violationsByNode = segmentViolationsByNode(violations);
    return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
      ref: child
    }, props.children), /*#__PURE__*/React.createElement("div", null, violationsByNode.map(([node, violations], index) =>
    /*#__PURE__*/
    // eslint-disable-next-line flowtype/no-weak-types
    React.createElement(Violation, {
      target: node,
      violations: violations,
      key: index
    }))));
  }