react-ally
Version:
Accessible react components
1,054 lines (898 loc) • 29 kB
JavaScript
import ReactDOM from 'react-dom';
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
import React, { useState, createContext, forwardRef, useContext, useEffect, useRef, Fragment } from 'react';
import { number, bool, oneOf, string, object, element, func } from 'prop-types';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function (key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
var TAB = 9;
var ESC = 27;
var PAGEUP = 33;
var PAGEDOWN = 34;
var END = 35;
var HOME = 36;
var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;
var ArrowTrap = function ArrowTrap(_ref) {
var children = _ref.children,
_ref$toolbarItem = _ref.toolbarItem,
toolbarItem = _ref$toolbarItem === void 0 ? false : _ref$toolbarItem;
var _useState = useState(),
_useState2 = _slicedToArray(_useState, 2),
focusIndex = _useState2[0],
setFocusIndex = _useState2[1];
var onKeyDown = function onKeyDown(_ref2, index) {
var keyCode = _ref2.keyCode;
var count = React.Children.count(children);
var next = function next() {
return setFocusIndex((index + 1) % count);
};
var prev = function prev() {
return setFocusIndex((index + count - 1) % count);
};
switch (keyCode) {
case HOME:
if (!toolbarItem) {
setFocusIndex(0);
}
break;
case END:
if (!toolbarItem) {
setFocusIndex(count - 1);
}
break;
case LEFT:
if (!toolbarItem || index > 0) {
prev();
}
break;
case RIGHT:
if (!toolbarItem || index + 1 === count) {
next();
}
break;
case UP:
prev();
break;
case DOWN:
next();
break;
}
};
return React.createElement(React.Fragment, null, React.Children.map(children, function (child, index) {
return React.cloneElement(child, {
focused: index === focusIndex,
setFocusOnKeyDown: function setFocusOnKeyDown(e) {
return onKeyDown(e, index);
}
});
}));
};
var Level = createContext(1);
var Heading = forwardRef(function (props, ref) {
var level = useContext(Level);
var Tag = "h".concat(level);
return React.createElement(Tag, _extends({
ref: ref
}, props));
});
var Section = function Section(_ref) {
var children = _ref.children,
levelOverride = _ref.levelOverride;
var level = useContext(Level);
return React.createElement(Level.Provider, {
value: Math.min(levelOverride || level + 1, 6)
}, React.createElement(React.Fragment, null, children));
};
Section.propTypes = {
levelOverride: number
};
var logAndThrow = function logAndThrow(message) {
if (typeof console !== 'undefined' && typeof console.error === 'function') {
console.error(message);
}
try {
throw new Error(message);
} catch (_) {}
};
var logError = function logError() {
var condition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var message = arguments.length > 1 ? arguments[1] : undefined;
return useEffect(function () {
if (condition) {
logAndThrow(message);
}
}, []);
};
var initialState = function initialState(initialOpen, children) {
switch (initialOpen) {
case 'none':
return {
0: false
};
case 'first':
return {
0: true
};
case 'all':
var result = {};
var count = children.length;
for (var i = 0; i < count; i++) {
result[i] = true;
}
return result;
default:
throw new Error();
}
};
var Group = function Group(_ref) {
var children = _ref.children,
_ref$multi = _ref.multi,
multi = _ref$multi === void 0 ? true : _ref$multi,
headingLevel = _ref.headingLevel,
_ref$initialOpen = _ref.initialOpen,
initialOpen = _ref$initialOpen === void 0 ? 'first' : _ref$initialOpen,
props = _objectWithoutProperties(_ref, ["children", "multi", "headingLevel", "initialOpen"]);
var _useState = useState(initialState(initialOpen, children)),
_useState2 = _slicedToArray(_useState, 2),
openIndexes = _useState2[0],
setOpen = _useState2[1];
var open = multi ? function (index) {
return setOpen(function (prevState) {
return Object.assign({}, prevState, _defineProperty({}, index, !openIndexes[index]));
});
} : function (index) {
return setOpen(_defineProperty({}, index, true));
};
logError(!multi && initialOpen === 'all', "Cannot use multi={false} with initialOpen=\"all\"");
return React.createElement(Section, {
levelOverride: headingLevel
}, React.createElement("div", props, React.createElement(ArrowTrap, null, React.Children.map(children, function (child, index) {
return React.cloneElement(child, {
accordionId: "".concat(props.id, "-").concat(index, "th"),
isOpen: !!openIndexes[index],
multi: multi,
onClickHeader: function onClickHeader() {
return open(index);
}
});
}))));
};
Group.propTypes = {
headingLevel: number,
id: string.isRequired,
initialOpen: oneOf(['none', 'first', 'all']),
multi: bool
};
var Accordion = function Accordion(_ref) {
var children = _ref.children,
props = _objectWithoutProperties(_ref, ["children"]);
return React.createElement(React.Fragment, null, React.Children.map(children, function (child) {
return React.cloneElement(child, _objectSpread({}, props));
}));
};
var buttonId = function buttonId(id) {
return "".concat(id, "-button");
};
var contentId = function contentId(id) {
return "".concat(id, "-content");
};
var Header = forwardRef(function (_ref, ref) {
var accordionId = _ref.accordionId,
buttonProps = _ref.buttonProps,
multi = _ref.multi,
focused = _ref.focused,
isOpen = _ref.isOpen,
onClickHeader = _ref.onClickHeader,
setFocusOnKeyDown = _ref.setFocusOnKeyDown,
props = _objectWithoutProperties(_ref, ["accordionId", "buttonProps", "multi", "focused", "isOpen", "onClickHeader", "setFocusOnKeyDown"]);
var buttonRef = useRef(null);
useEffect(function () {
if (focused) {
buttonRef.current.focus();
}
}, [focused]);
return React.createElement(Heading, _extends({
ref: ref
}, props), React.createElement("button", _extends({}, buttonProps, {
ref: buttonRef,
"aria-disabled": isOpen && !multi,
"aria-expanded": isOpen,
"aria-controls": contentId(accordionId),
id: buttonId(accordionId),
onClick: onClickHeader,
onKeyDown: setFocusOnKeyDown
}), props.children));
}); // Add custom prop validation for level to be between 1 and 6
Header.propTypes = {
buttonProps: object
};
var Panel = forwardRef(function (_ref, ref) {
var accordionId = _ref.accordionId,
ignoredMulti = _ref.multi,
ignoredFocused = _ref.focused,
isOpen = _ref.isOpen,
ignoredOnClick = _ref.onClickHeader,
ignoredSetFocus = _ref.setFocusOnKeyDown,
props = _objectWithoutProperties(_ref, ["accordionId", "multi", "focused", "isOpen", "onClickHeader", "setFocusOnKeyDown"]);
return React.createElement("div", _extends({
ref: ref
}, props, {
"aria-hidden": !isOpen,
"aria-labelledby": buttonId(accordionId),
id: contentId(accordionId)
}), isOpen && props.children);
});
Group.displayName = 'AccordionGroup';
Accordion.displayName = 'Accordion';
Header.displayName = 'AccordionHeader';
Panel.displayName = 'AccordionPanel';
var Breadcrumb = function Breadcrumb(_ref) {
var _ref$listProps = _ref.listProps,
listProps = _ref$listProps === void 0 ? {} : _ref$listProps,
children = _ref.children,
props = _objectWithoutProperties(_ref, ["listProps", "children"]);
var count = React.Children.count(children);
return React.createElement("nav", _extends({}, props, {
"aria-label": "Breadcrumb"
}), React.createElement("ol", listProps, React.Children.map(children, function (child, index) {
if (count - 1 === index) {
return React.cloneElement(child, {
'aria-current': 'page'
});
}
return child;
})));
};
Breadcrumb.propTypes = {
listProps: object
};
var BreadcrumbLink = function BreadcrumbLink(_ref2) {
var _ref2$listItemProps = _ref2.listItemProps,
listItemProps = _ref2$listItemProps === void 0 ? {} : _ref2$listItemProps,
props = _objectWithoutProperties(_ref2, ["listItemProps"]);
return React.createElement("li", listItemProps, React.createElement("a", props));
};
BreadcrumbLink.propTypes = {
href: string.isRequired,
listItemProps: object
};
BreadcrumbLink.displayName = 'BreadcrumbLink';
var Overlay = function Overlay(_ref) {
var backgroundColor = _ref.backgroundColor,
props = _objectWithoutProperties(_ref, ["backgroundColor"]);
return React.createElement("div", _extends({
style: {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: backgroundColor
}
}, props));
};
var FocusTrap = function FocusTrap(_ref) {
var children = _ref.children,
firstTabbableElementRef = _ref.firstTabbableElementRef,
initialFocusElementRef = _ref.initialFocusElementRef,
lastTabbableElementRef = _ref.lastTabbableElementRef,
wrapperRef = _ref.wrapperRef;
var setInitialFocus = function setInitialFocus() {
setTimeout(function () {
(initialFocusElementRef || firstTabbableElementRef).current.focus();
}, 0);
};
useEffect(setInitialFocus, []);
var onFirstTabbableKeyDown = function onFirstTabbableKeyDown() {
var onTab = function onTab(e) {
if (e.keyCode === TAB) {
if (!lastTabbableElementRef) {
// Keep focus on self
e.preventDefault();
} else if (e.shiftKey) {
e.preventDefault();
lastTabbableElementRef.current.focus();
}
}
};
firstTabbableElementRef.current.addEventListener('keydown', onTab);
return function () {
firstTabbableElementRef.current.removeEventListener('keydown', onTab);
};
};
useEffect(onFirstTabbableKeyDown, []);
var onLastTabbableKeyDown = function onLastTabbableKeyDown() {
var onTab = function onTab(e) {
if (!e.shiftKey && e.keyCode === TAB) {
e.preventDefault();
firstTabbableElementRef.current.focus();
}
};
if (lastTabbableElementRef) {
lastTabbableElementRef.current.addEventListener('keydown', onTab);
return function () {
lastTabbableElementRef.current.removeEventListener('keydown', onTab);
};
}
};
useEffect(onLastTabbableKeyDown, []);
var onWrapperClick = function onWrapperClick() {
var onTab = function onTab(e) {
if (e.keyCode === TAB && e.shiftKey) {
if (wrapperRef.current === document.activeElement) {
e.preventDefault();
if (lastTabbableElementRef.current) {
lastTabbableElementRef.current.focus();
} else {
firstTabbableElementRef.current.focus();
}
}
}
};
wrapperRef.current.addEventListener('keydown', onTab);
return function () {
wrapperRef.current.removeEventListener('keydown', onTab);
};
};
useEffect(onWrapperClick, []);
return React.createElement(React.Fragment, null, children && React.cloneElement(children, {
tabIndex: -1
}));
};
FocusTrap.propTypes = {
children: element.isRequired,
firstTabbableElementRef: object.isRequired,
initialFocusElementRef: object,
lastTabbableElementRef: object,
wrapperRef: object.isRequired
};
var DialogContext = createContext({});
var Dialog = forwardRef(function (_ref, ref) {
var _ref$close = _ref.close,
close = _ref$close === void 0 ? function () {} : _ref$close,
_ref$closeOnOverlayCl = _ref.closeOnOverlayClick,
closeOnOverlayClick = _ref$closeOnOverlayCl === void 0 ? true : _ref$closeOnOverlayCl,
firstTabbableElementRef = _ref.firstTabbableElementRef,
_ref$isOpen = _ref.isOpen,
isOpen = _ref$isOpen === void 0 ? false : _ref$isOpen,
initialFocusElementRef = _ref.initialFocusElementRef,
lastTabbableElementRef = _ref.lastTabbableElementRef,
_ref$onClick = _ref.onClick,
_onClick = _ref$onClick === void 0 ? function () {} : _ref$onClick,
_ref$onKeyDown = _ref.onKeyDown,
_onKeyDown = _ref$onKeyDown === void 0 ? function () {} : _ref$onKeyDown,
_ref$overlayBackgroun = _ref.overlayBackgroundColor,
overlayBackgroundColor = _ref$overlayBackgroun === void 0 ? 'rgba(255,255,255,0.75)' : _ref$overlayBackgroun,
_ref$overlayProps = _ref.overlayProps,
overlayProps = _ref$overlayProps === void 0 ? {} : _ref$overlayProps,
_ref$returnFocus = _ref.returnFocus,
returnFocus = _ref$returnFocus === void 0 ? {
current: document.activeElement
} : _ref$returnFocus,
props = _objectWithoutProperties(_ref, ["close", "closeOnOverlayClick", "firstTabbableElementRef", "isOpen", "initialFocusElementRef", "lastTabbableElementRef", "onClick", "onKeyDown", "overlayBackgroundColor", "overlayProps", "returnFocus"]);
if (!ref) {
throw new Error('Dialog requires a ref');
}
useEffect(function () {
if (isOpen && returnFocus.current === document.body) {
throw new Error("Dialog did not receive a valid element to send focus after closing. This usually occurs because the dialog initialized open, but wasn't passed a returnFocus ref.");
}
}, [isOpen]);
var dialogRoot = useRef(document.createElement('div'));
var _useState = useState(''),
_useState2 = _slicedToArray(_useState, 2),
labelledby = _useState2[0],
setLabelledby = _useState2[1];
var _useState3 = useState(''),
_useState4 = _slicedToArray(_useState3, 2),
describedby = _useState4[0],
setDescribedby = _useState4[1];
useEffect(function () {
if (isOpen) {
var root = returnFocus.current;
while (root.parentElement !== root.ownerDocument.body && root !== root.ownerDocument.body) {
root = root.parentElement;
}
root.setAttribute('aria-hidden', true);
return function () {
root.setAttribute('aria-hidden', false);
};
}
});
var lockBody = function lockBody() {
disableBodyScroll(ref.current);
return function () {
enableBodyScroll(ref.current);
};
};
useEffect(lockBody, [isOpen]);
useEffect(function () {
if (isOpen) {
return function () {
if (dialogRoot.current.parentNode) {
dialogRoot.current.parentNode.removeChild(dialogRoot.current);
}
};
}
}, [isOpen]);
useEffect(function () {
if (isOpen) {
// TODO: figure out why react-testing-library needs this
var current = returnFocus.current;
return function () {
current.focus();
};
}
}, [isOpen]);
var portal = React.createElement(Overlay, _extends({
backgroundColor: overlayBackgroundColor
}, overlayProps, {
onClick: function onClick(e) {
if (closeOnOverlayClick) {
close(e);
}
}
}), React.createElement(DialogContext.Provider, {
value: {
contentId: props.id,
setDescribedby: setDescribedby,
setLabelledby: setLabelledby
}
}, React.createElement(FocusTrap, {
firstTabbableElementRef: firstTabbableElementRef,
initialFocusElementRef: initialFocusElementRef,
lastTabbableElementRef: lastTabbableElementRef,
wrapperRef: ref
}, React.createElement("div", _extends({
ref: ref,
"aria-describedby": describedby,
"aria-labelledby": labelledby,
"aria-modal": true,
id: "test-dialog",
role: "dialog"
}, props, {
onClick: function onClick(e) {
e.stopPropagation();
_onClick(e);
},
onKeyDown: function onKeyDown(e) {
if (e.keyCode === ESC) {
close(e);
}
_onKeyDown(e);
}
})))));
if (isOpen) {
document.body.appendChild(dialogRoot.current);
return ReactDOM.createPortal(portal, dialogRoot.current);
}
return null;
});
Dialog.displayName = 'Dialog';
Dialog.propTypes = {
close: func.isRequired,
closeOnOverlayClick: bool,
firstTabbableElementRef: object.isRequired,
id: string.isRequired,
isOpen: bool.isRequired,
initialFocusElementRef: object,
lastTabbableElementRef: object,
onClick: func,
onKeyDown: func,
overlayBackgroundColor: string,
overlayProps: object,
returnFocus: object
};
var Description = function Description(props) {
var mounted = useRef(false);
useEffect(function () {
mounted.current = true;
}, []);
var _useContext = useContext(DialogContext),
setDescribedby = _useContext.setDescribedby,
contentId = _useContext.contentId;
var id = "".concat(contentId, "-description");
if (!mounted.current) {
setDescribedby(id);
}
return React.createElement("div", _extends({}, props, {
id: id
}));
};
var Label = function Label(props) {
var mounted = useRef(false);
useEffect(function () {
mounted.current = true;
}, []);
var _useContext = useContext(DialogContext),
setLabelledby = _useContext.setLabelledby,
contentId = _useContext.contentId;
var id = "".concat(contentId, "-label");
if (!mounted.current) {
setLabelledby(id);
}
return React.createElement("h2", _extends({}, props, {
id: id
}));
};
var Helpers = function Helpers() {
var initializeOpen = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var firstTabbableElementRef = useRef(null);
var lastTabbableElementRef = useRef(null);
var wrapperRef = useRef(null);
var _useState = useState(initializeOpen),
_useState2 = _slicedToArray(_useState, 2),
isOpen = _useState2[0],
setIsOpen = _useState2[1];
return {
close: function close() {
return setIsOpen(false);
},
firstTabbableElementRef: firstTabbableElementRef,
isOpen: isOpen,
lastTabbableElementRef: lastTabbableElementRef,
open: function open() {
return setIsOpen(true);
},
ref: wrapperRef
};
};
var SpinButtonContext = createContext({});
var SpinButton = React.forwardRef(function (_ref, ref) {
var _ref$bigStep = _ref.bigStep,
bigStep = _ref$bigStep === void 0 ? 1 : _ref$bigStep,
onChange = _ref.onChange,
_ref$onKeyDown = _ref.onKeyDown,
onKeyDown = _ref$onKeyDown === void 0 ? function () {} : _ref$onKeyDown,
_ref$onMouseDown = _ref.onMouseDown,
_onMouseDown = _ref$onMouseDown === void 0 ? function () {} : _ref$onMouseDown,
_ref$tabIndex = _ref.tabIndex,
tabIndex = _ref$tabIndex === void 0 ? 0 : _ref$tabIndex,
props = _objectWithoutProperties(_ref, ["bigStep", "onChange", "onKeyDown", "onMouseDown", "tabIndex"]);
var current = props['aria-valuenow'],
maxValue = props['aria-valuemax'],
minValue = props['aria-valuemin'];
var handleKeyDown = function handleKeyDown(e) {
switch (e.keyCode) {
case PAGEUP:
onChange(function (prevValue) {
return Math.min(prevValue + bigStep, maxValue);
});
break;
case PAGEDOWN:
onChange(function (prevValue) {
return Math.max(prevValue - bigStep, minValue);
});
break;
case END:
onChange(maxValue);
break;
case HOME:
onChange(minValue);
break;
case UP:
onChange(function (prevValue) {
return Math.min(prevValue + 1, maxValue);
});
break;
case DOWN:
onChange(function (prevValue) {
return Math.max(prevValue - 1, minValue);
});
break;
default:
break;
}
onKeyDown(e);
};
return React.createElement(SpinButtonContext.Provider, {
value: {
current: current,
maxValue: maxValue,
minValue: minValue,
onChange: onChange
}
}, React.createElement("div", _extends({}, props, {
ref: ref,
role: "spinbutton",
onKeyDown: handleKeyDown,
onMouseDown: function onMouseDown(e) {
ref.current.focus();
_onMouseDown(e);
},
tabIndex: tabIndex
})));
});
SpinButton.displayName = 'SpinButton';
SpinButton.propTypes = {
'aria-valuemax': number.isRequired,
'aria-valuemin': number.isRequired,
'aria-valuenow': number.isRequired,
'aria-valuetext': string,
bigStep: number,
onChange: func.isRequired
};
var Button = function Button(props) {
return React.createElement("button", _extends({}, props, {
"aria-hidden": true,
onMouseDown: function onMouseDown(e) {
e.preventDefault();
},
tabIndex: -1
}));
};
var UpButton = function UpButton(props) {
var _useContext = useContext(SpinButtonContext),
current = _useContext.current,
onChange = _useContext.onChange,
maxValue = _useContext.maxValue;
return React.createElement(Button, _extends({}, props, {
disabled: current === maxValue,
onClick: function onClick() {
onChange(function (prevValue) {
return Math.min(prevValue + 1, maxValue);
});
}
}));
};
var DownButton = function DownButton(props) {
var _useContext = useContext(SpinButtonContext),
current = _useContext.current,
onChange = _useContext.onChange,
minValue = _useContext.minValue;
return React.createElement(Button, _extends({}, props, {
disabled: current === minValue,
onClick: function onClick() {
onChange(function (prevValue) {
return Math.max(prevValue - 1, minValue);
});
}
}));
};
var TabsContext = createContext({});
var Tabs = function Tabs(_ref) {
var _ref$initialActiveInd = _ref.initialActiveIndex,
initialActiveIndex = _ref$initialActiveInd === void 0 ? 0 : _ref$initialActiveInd,
id = _ref.id,
props = _objectWithoutProperties(_ref, ["initialActiveIndex", "id"]);
var _useState = useState(initialActiveIndex),
_useState2 = _slicedToArray(_useState, 2),
activeIndex = _useState2[0],
setActiveIndex = _useState2[1];
return React.createElement(TabsContext.Provider, {
value: {
activeIndex: activeIndex,
tabsId: id,
setActiveIndex: setActiveIndex
}
}, React.createElement("div", _extends({
id: id
}, props)));
};
Tabs.propTypes = {
id: string.isRequired
};
var TabList = function TabList(_ref2) {
var _ref2$manual = _ref2.manual,
manual = _ref2$manual === void 0 ? false : _ref2$manual,
props = _objectWithoutProperties(_ref2, ["manual"]);
var _useState3 = useState(-1),
_useState4 = _slicedToArray(_useState3, 2),
focusIndex = _useState4[0],
setFocusIndex = _useState4[1];
return React.createElement("div", _extends({}, props, {
role: "tablist"
}), React.Children.map(props.children, function (child, index) {
return React.cloneElement(child, {
count: props.children.length,
focusIndex: focusIndex,
index: index,
manual: manual,
setFocusIndex: setFocusIndex
});
}));
};
TabList.propTypes = {
manual: bool
};
var tabId = function tabId(tabsId, index) {
return "".concat(tabsId, "-").concat(index, "th-tab");
};
var panelId = function panelId(tabsId, index) {
return "".concat(tabsId, "-").concat(index, "th-panel");
};
var Tab = function Tab(_ref3) {
var count = _ref3.count,
focusIndex = _ref3.focusIndex,
index = _ref3.index,
manual = _ref3.manual,
setFocusIndex = _ref3.setFocusIndex,
props = _objectWithoutProperties(_ref3, ["count", "focusIndex", "index", "manual", "setFocusIndex"]);
var ref = useRef(null);
var mounted = useRef(false);
var _useContext = useContext(TabsContext),
activeIndex = _useContext.activeIndex,
setActiveIndex = _useContext.setActiveIndex,
tabsId = _useContext.tabsId;
var active = index === activeIndex;
var focused = focusIndex > -1 ? index === focusIndex : index === activeIndex;
useEffect(function () {
if (mounted.current && focused) {
ref.current.focus();
}
}, [activeIndex, focusIndex]);
useEffect(function () {
mounted.current = true;
}, []);
return React.createElement("button", _extends({
ref: ref,
id: tabId(tabsId, index)
}, props, {
"aria-controls": panelId(tabsId, index),
"aria-selected": active,
onClick: function onClick() {
return setActiveIndex(index);
},
onKeyDown: function onKeyDown(e) {
var func$$1 = manual ? setFocusIndex : setActiveIndex;
var next = function next() {
return func$$1((index + 1) % count);
};
var prev = function prev() {
return func$$1((index - 1 + count) % count);
};
switch (e.keyCode) {
case 35:
func$$1(count - 1);
break;
case 36:
func$$1(0);
break;
case 37:
prev();
break;
case 38:
prev();
break;
case 39:
next();
break;
case 40:
next();
break;
default:
break;
}
},
role: "tab",
tabIndex: active - 1
}));
};
var TabPanels = function TabPanels(_ref4) {
var children = _ref4.children;
return React.createElement(Fragment, null, React.Children.map(children, function (child, index) {
return React.cloneElement(child, {
index: index
});
}));
};
var TabPanel = function TabPanel(_ref5) {
var index = _ref5.index,
props = _objectWithoutProperties(_ref5, ["index"]);
var _useContext2 = useContext(TabsContext),
activeIndex = _useContext2.activeIndex,
tabsId = _useContext2.tabsId;
var active = index === activeIndex;
return React.createElement("div", _extends({
id: panelId(tabsId, index)
}, props, {
"aria-labelledby": tabId(tabsId, index),
"aria-selected": active,
role: "tabpanel",
style: {
display: active ? 'inherit' : 'none'
},
tabIndex: 0
}));
};
export { Group as AccordionGroup, Accordion, Header as AccordionHeader, Panel as AccordionPanel, Breadcrumb, BreadcrumbLink, ArrowTrap, Dialog, Label as DialogLabel, Description as DialogDescription, Helpers as DialogHelpers, FocusTrap, Heading, Section, SpinButton, UpButton, DownButton, Tabs, TabList, Tab, TabPanels, TabPanel };