UNPKG

baseui

Version:

A React Component library implementing the Base design language

135 lines (132 loc) • 5.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = A11y; var React = _interopRequireWildcard(require("react")); var _axeCore = _interopRequireDefault(require("axe-core")); var _layer = require("../layer"); var _typography = require("../typography"); var _styles = require("../styles"); var _themeProvider = require("../styles/theme-provider"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /* 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 */ function validateNode(node) { return new Promise((resolve, reject) => { _axeCore.default.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 => { // @ts-expect-error todo(flow-ts) node.target is an Array if (!map[node.target]) { // @ts-expect-error todo(flow-ts) node.target is an Array map[node.target] = [violation]; } else { // todo(flow->ts) node.target is an Array // @ts-expect-error todo(flow-ts) result of Array.push is not Array map[node.target] = map[node.target].push(violation); } }); return map; }, {}); return Object.entries(nodes); } const ViolationContainer = (0, _styles.styled)('div', ({ $theme, $top, $left }) => { return { backgroundColor: $theme.colors.backgroundPrimary, 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(_themeProvider.ThemeContext); const handleMouseEnter = () => setIsHovered(true); const handleMouseLeave = () => setIsHovered(false); React.useEffect(() => { const node = document.querySelector(props.target); if (node) { // @ts-ignore setAnchor(node); node.setAttribute('style', `border: solid 1px ${theme.colors.borderNegative};`); 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.Layer, null, /*#__PURE__*/React.createElement(_layer.TetherBehavior, { anchorRef: anchor, popperRef: popper, onPopperUpdate: update => setOffset(update.popper), placement: _layer.TETHER_PLACEMENT.bottom }, /*#__PURE__*/React.createElement(ViolationContainer // @ts-ignore , { ref: setPopper, $top: `${offset.top}px` || '0px', $left: `${offset.left}px` || '0px' }, /*#__PURE__*/React.createElement(_typography.ParagraphXSmall, null, props.target), props.violations.map((violation, index) => /*#__PURE__*/React.createElement(_typography.ParagraphSmall, { key: index }, violation.description))))); } 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(() => { // @ts-ignore validateNode(child.current).then(setViolations); }); // @ts-ignore 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__*/React.createElement(Violation, { target: node, violations: violations, key: index })))); }