UNPKG

react-ally

Version:

Accessible react components

1,082 lines (923 loc) 30.6 kB
'use strict'; 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;