react-ally
Version:
Accessible react components
1,082 lines (923 loc) • 30.6 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var ReactDOM = _interopDefault(require('react-dom'));
var bodyScrollLock = require('body-scroll-lock');
var React = require('react');
var React__default = _interopDefault(React);
var propTypes = require('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 = React.useState(),
_useState2 = _slicedToArray(_useState, 2),
focusIndex = _useState2[0],
setFocusIndex = _useState2[1];
var onKeyDown = function onKeyDown(_ref2, index) {
var keyCode = _ref2.keyCode;
var count = React__default.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__default.createElement(React__default.Fragment, null, React__default.Children.map(children, function (child, index) {
return React__default.cloneElement(child, {
focused: index === focusIndex,
setFocusOnKeyDown: function setFocusOnKeyDown(e) {
return onKeyDown(e, index);
}
});
}));
};
var Level = React.createContext(1);
var Heading = React.forwardRef(function (props, ref) {
var level = React.useContext(Level);
var Tag = "h".concat(level);
return React__default.createElement(Tag, _extends({
ref: ref
}, props));
});
var Section = function Section(_ref) {
var children = _ref.children,
levelOverride = _ref.levelOverride;
var level = React.useContext(Level);
return React__default.createElement(Level.Provider, {
value: Math.min(levelOverride || level + 1, 6)
}, React__default.createElement(React__default.Fragment, null, children));
};
Section.propTypes = {
levelOverride: propTypes.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 React.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 = React.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__default.createElement(Section, {
levelOverride: headingLevel
}, React__default.createElement("div", props, React__default.createElement(ArrowTrap, null, React__default.Children.map(children, function (child, index) {
return React__default.cloneElement(child, {
accordionId: "".concat(props.id, "-").concat(index, "th"),
isOpen: !!openIndexes[index],
multi: multi,
onClickHeader: function onClickHeader() {
return open(index);
}
});
}))));
};
Group.propTypes = {
headingLevel: propTypes.number,
id: propTypes.string.isRequired,
initialOpen: propTypes.oneOf(['none', 'first', 'all']),
multi: propTypes.bool
};
var Accordion = function Accordion(_ref) {
var children = _ref.children,
props = _objectWithoutProperties(_ref, ["children"]);
return React__default.createElement(React__default.Fragment, null, React__default.Children.map(children, function (child) {
return React__default.cloneElement(child, _objectSpread({}, props));
}));
};
var buttonId = function buttonId(id) {
return "".concat(id, "-button");
};
var contentId = function contentId(id) {
return "".concat(id, "-content");
};
var Header = React.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 = React.useRef(null);
React.useEffect(function () {
if (focused) {
buttonRef.current.focus();
}
}, [focused]);
return React__default.createElement(Heading, _extends({
ref: ref
}, props), React__default.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: propTypes.object
};
var Panel = React.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__default.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__default.Children.count(children);
return React__default.createElement("nav", _extends({}, props, {
"aria-label": "Breadcrumb"
}), React__default.createElement("ol", listProps, React__default.Children.map(children, function (child, index) {
if (count - 1 === index) {
return React__default.cloneElement(child, {
'aria-current': 'page'
});
}
return child;
})));
};
Breadcrumb.propTypes = {
listProps: propTypes.object
};
var BreadcrumbLink = function BreadcrumbLink(_ref2) {
var _ref2$listItemProps = _ref2.listItemProps,
listItemProps = _ref2$listItemProps === void 0 ? {} : _ref2$listItemProps,
props = _objectWithoutProperties(_ref2, ["listItemProps"]);
return React__default.createElement("li", listItemProps, React__default.createElement("a", props));
};
BreadcrumbLink.propTypes = {
href: propTypes.string.isRequired,
listItemProps: propTypes.object
};
BreadcrumbLink.displayName = 'BreadcrumbLink';
var Overlay = function Overlay(_ref) {
var backgroundColor = _ref.backgroundColor,
props = _objectWithoutProperties(_ref, ["backgroundColor"]);
return React__default.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);
};
React.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);
};
};
React.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);
};
}
};
React.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);
};
};
React.useEffect(onWrapperClick, []);
return React__default.createElement(React__default.Fragment, null, children && React__default.cloneElement(children, {
tabIndex: -1
}));
};
FocusTrap.propTypes = {
children: propTypes.element.isRequired,
firstTabbableElementRef: propTypes.object.isRequired,
initialFocusElementRef: propTypes.object,
lastTabbableElementRef: propTypes.object,
wrapperRef: propTypes.object.isRequired
};
var DialogContext = React.createContext({});
var Dialog = React.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');
}
React.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 = React.useRef(document.createElement('div'));
var _useState = React.useState(''),
_useState2 = _slicedToArray(_useState, 2),
labelledby = _useState2[0],
setLabelledby = _useState2[1];
var _useState3 = React.useState(''),
_useState4 = _slicedToArray(_useState3, 2),
describedby = _useState4[0],
setDescribedby = _useState4[1];
React.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() {
bodyScrollLock.disableBodyScroll(ref.current);
return function () {
bodyScrollLock.enableBodyScroll(ref.current);
};
};
React.useEffect(lockBody, [isOpen]);
React.useEffect(function () {
if (isOpen) {
return function () {
if (dialogRoot.current.parentNode) {
dialogRoot.current.parentNode.removeChild(dialogRoot.current);
}
};
}
}, [isOpen]);
React.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__default.createElement(Overlay, _extends({
backgroundColor: overlayBackgroundColor
}, overlayProps, {
onClick: function onClick(e) {
if (closeOnOverlayClick) {
close(e);
}
}
}), React__default.createElement(DialogContext.Provider, {
value: {
contentId: props.id,
setDescribedby: setDescribedby,
setLabelledby: setLabelledby
}
}, React__default.createElement(FocusTrap, {
firstTabbableElementRef: firstTabbableElementRef,
initialFocusElementRef: initialFocusElementRef,
lastTabbableElementRef: lastTabbableElementRef,
wrapperRef: ref
}, React__default.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: propTypes.func.isRequired,
closeOnOverlayClick: propTypes.bool,
firstTabbableElementRef: propTypes.object.isRequired,
id: propTypes.string.isRequired,
isOpen: propTypes.bool.isRequired,
initialFocusElementRef: propTypes.object,
lastTabbableElementRef: propTypes.object,
onClick: propTypes.func,
onKeyDown: propTypes.func,
overlayBackgroundColor: propTypes.string,
overlayProps: propTypes.object,
returnFocus: propTypes.object
};
var Description = function Description(props) {
var mounted = React.useRef(false);
React.useEffect(function () {
mounted.current = true;
}, []);
var _useContext = React.useContext(DialogContext),
setDescribedby = _useContext.setDescribedby,
contentId = _useContext.contentId;
var id = "".concat(contentId, "-description");
if (!mounted.current) {
setDescribedby(id);
}
return React__default.createElement("div", _extends({}, props, {
id: id
}));
};
var Label = function Label(props) {
var mounted = React.useRef(false);
React.useEffect(function () {
mounted.current = true;
}, []);
var _useContext = React.useContext(DialogContext),
setLabelledby = _useContext.setLabelledby,
contentId = _useContext.contentId;
var id = "".concat(contentId, "-label");
if (!mounted.current) {
setLabelledby(id);
}
return React__default.createElement("h2", _extends({}, props, {
id: id
}));
};
var Helpers = function Helpers() {
var initializeOpen = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var firstTabbableElementRef = React.useRef(null);
var lastTabbableElementRef = React.useRef(null);
var wrapperRef = React.useRef(null);
var _useState = React.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 = React.createContext({});
var SpinButton = React__default.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__default.createElement(SpinButtonContext.Provider, {
value: {
current: current,
maxValue: maxValue,
minValue: minValue,
onChange: onChange
}
}, React__default.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': propTypes.number.isRequired,
'aria-valuemin': propTypes.number.isRequired,
'aria-valuenow': propTypes.number.isRequired,
'aria-valuetext': propTypes.string,
bigStep: propTypes.number,
onChange: propTypes.func.isRequired
};
var Button = function Button(props) {
return React__default.createElement("button", _extends({}, props, {
"aria-hidden": true,
onMouseDown: function onMouseDown(e) {
e.preventDefault();
},
tabIndex: -1
}));
};
var UpButton = function UpButton(props) {
var _useContext = React.useContext(SpinButtonContext),
current = _useContext.current,
onChange = _useContext.onChange,
maxValue = _useContext.maxValue;
return React__default.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 = React.useContext(SpinButtonContext),
current = _useContext.current,
onChange = _useContext.onChange,
minValue = _useContext.minValue;
return React__default.createElement(Button, _extends({}, props, {
disabled: current === minValue,
onClick: function onClick() {
onChange(function (prevValue) {
return Math.max(prevValue - 1, minValue);
});
}
}));
};
var TabsContext = React.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 = React.useState(initialActiveIndex),
_useState2 = _slicedToArray(_useState, 2),
activeIndex = _useState2[0],
setActiveIndex = _useState2[1];
return React__default.createElement(TabsContext.Provider, {
value: {
activeIndex: activeIndex,
tabsId: id,
setActiveIndex: setActiveIndex
}
}, React__default.createElement("div", _extends({
id: id
}, props)));
};
Tabs.propTypes = {
id: propTypes.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 = React.useState(-1),
_useState4 = _slicedToArray(_useState3, 2),
focusIndex = _useState4[0],
setFocusIndex = _useState4[1];
return React__default.createElement("div", _extends({}, props, {
role: "tablist"
}), React__default.Children.map(props.children, function (child, index) {
return React__default.cloneElement(child, {
count: props.children.length,
focusIndex: focusIndex,
index: index,
manual: manual,
setFocusIndex: setFocusIndex
});
}));
};
TabList.propTypes = {
manual: propTypes.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 = React.useRef(null);
var mounted = React.useRef(false);
var _useContext = React.useContext(TabsContext),
activeIndex = _useContext.activeIndex,
setActiveIndex = _useContext.setActiveIndex,
tabsId = _useContext.tabsId;
var active = index === activeIndex;
var focused = focusIndex > -1 ? index === focusIndex : index === activeIndex;
React.useEffect(function () {
if (mounted.current && focused) {
ref.current.focus();
}
}, [activeIndex, focusIndex]);
React.useEffect(function () {
mounted.current = true;
}, []);
return React__default.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 = manual ? setFocusIndex : setActiveIndex;
var next = function next() {
return func((index + 1) % count);
};
var prev = function prev() {
return func((index - 1 + count) % count);
};
switch (e.keyCode) {
case 35:
func(count - 1);
break;
case 36:
func(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__default.createElement(React.Fragment, null, React__default.Children.map(children, function (child, index) {
return React__default.cloneElement(child, {
index: index
});
}));
};
var TabPanel = function TabPanel(_ref5) {
var index = _ref5.index,
props = _objectWithoutProperties(_ref5, ["index"]);
var _useContext2 = React.useContext(TabsContext),
activeIndex = _useContext2.activeIndex,
tabsId = _useContext2.tabsId;
var active = index === activeIndex;
return React__default.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
}));
};
exports.AccordionGroup = Group;
exports.Accordion = Accordion;
exports.AccordionHeader = Header;
exports.AccordionPanel = Panel;
exports.Breadcrumb = Breadcrumb;
exports.BreadcrumbLink = BreadcrumbLink;
exports.ArrowTrap = ArrowTrap;
exports.Dialog = Dialog;
exports.DialogLabel = Label;
exports.DialogDescription = Description;
exports.DialogHelpers = Helpers;
exports.FocusTrap = FocusTrap;
exports.Heading = Heading;
exports.Section = Section;
exports.SpinButton = SpinButton;
exports.UpButton = UpButton;
exports.DownButton = DownButton;
exports.Tabs = Tabs;
exports.TabList = TabList;
exports.Tab = Tab;
exports.TabPanels = TabPanels;
exports.TabPanel = TabPanel;