baseui
Version:
A React Component library implementing the Base design language
135 lines (132 loc) • 5.38 kB
JavaScript
;
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
}))));
}