UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

848 lines (813 loc) 29.3 kB
/** * MSKCC 2021, 2024 */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var iconsReact = require('@carbon/icons-react'); var layout = require('@carbon/layout'); var cx = require('classnames'); var debounce = require('lodash.debounce'); var PropTypes = require('prop-types'); var React = require('react'); var reactIs = require('react-is'); require('../Tooltip/DefinitionTooltip.js'); var Tooltip = require('../Tooltip/Tooltip.js'); var useControllableState = require('../../internal/useControllableState.js'); var useEffectOnce = require('../../internal/useEffectOnce.js'); var useId = require('../../internal/useId.js'); var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js'); var useMergedRefs = require('../../internal/useMergedRefs.js'); var useNoInteractiveChildren = require('../../internal/useNoInteractiveChildren.js'); var usePrefix = require('../../internal/usePrefix.js'); var usePressable = require('./usePressable.js'); var deprecate = require('../../prop-types/deprecate.js'); var useEvent = require('../../internal/useEvent.js'); var useMatchMedia = require('../../internal/useMatchMedia.js'); var match = require('../../internal/keyboard/match.js'); var keys = require('../../internal/keyboard/keys.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx); var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce); var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var _ChevronLeft, _ChevronRight, _Close; // Used to manage the overall state of the Tabs const TabsContext = /*#__PURE__*/React__default["default"].createContext({ baseId: '', activeIndex: 0, defaultSelectedIndex: 0, dismissable: false, onTabCloseRequest() {}, setActiveIndex() {}, selectedIndex: 0, setSelectedIndex() {} }); // Used to keep track of position in a tablist const TabContext = /*#__PURE__*/React__default["default"].createContext({ index: 0, hasSecondaryLabel: false }); const lgMediaQuery = `(min-width: ${layout.breakpoints.lg.width})`; // Used to keep track of position in a list of tab panels const TabPanelContext = /*#__PURE__*/React__default["default"].createContext(0); /** * Tabs */ function Tabs(_ref) { let { children, defaultSelectedIndex = 0, onChange, selectedIndex: controlledSelectedIndex, dismissable, onTabCloseRequest } = _ref; const baseId = useId.useId('ccs'); // The active index is used to track the element which has focus in our tablist const [activeIndex, setActiveIndex] = React.useState(defaultSelectedIndex); // The selected index is used for the tab/panel pairing which is "visible" const [selectedIndex, setSelectedIndex] = useControllableState.useControllableState({ value: controlledSelectedIndex, defaultValue: defaultSelectedIndex, onChange: value => onChange?.({ selectedIndex: value }) }); const value = { baseId, activeIndex, defaultSelectedIndex, dismissable, onTabCloseRequest, setActiveIndex, selectedIndex, setSelectedIndex }; return /*#__PURE__*/React__default["default"].createElement(TabsContext.Provider, { value: value }, children); } Tabs.propTypes = { /** * Provide child elements to be rendered inside the `Tabs`. * These elements should render either `TabsList` or `TabsPanels` */ children: PropTypes__default["default"].node, /** * Specify which content tab should be initially selected when the component * is first rendered */ defaultSelectedIndex: PropTypes__default["default"].number, /** * Whether the render Tab children should be dismissable. */ dismissable: PropTypes__default["default"].bool, /** * Provide an optional function which is called whenever the state of the * `Tabs` changes */ onChange: PropTypes__default["default"].func, /** * If specifying the `onTabCloseRequest` prop, provide a callback function * responsible for removing the tab when close button is pressed on one of the Tab elements */ onTabCloseRequest: props => { if (props.dismissable && !props.onTabCloseRequest) { return new Error('dismissable property specified without also providing an onTabCloseRequest property.'); } return undefined; }, /** * Control which content panel is currently selected. This puts the component * in a controlled mode and should be used along with `onChange` */ selectedIndex: PropTypes__default["default"].number }; /** * Get the next index for a given keyboard event * given a count of the total items and the current index */ function getNextIndex(event, total, index) { switch (true) { case match.match(event, keys.ArrowRight): return (index + 1) % total; case match.match(event, keys.ArrowLeft): return (total + index - 1) % total; case match.match(event, keys.Home): return 0; case match.match(event, keys.End): return total - 1; default: return index; } } /** * TabList */ function TabList(_ref2) { let { activation = 'automatic', 'aria-label': label, children, className: customClassName, contained = false, fullWidth = false, iconSize, leftOverflowButtonProps, light, rightOverflowButtonProps, scrollDebounceWait = 200, scrollIntoView, ...rest } = _ref2; const { activeIndex, selectedIndex, setSelectedIndex, setActiveIndex, dismissable } = React__default["default"].useContext(TabsContext); const prefix = usePrefix.usePrefix(); const ref = React.useRef(null); const previousButton = React.useRef(null); const nextButton = React.useRef(null); const [isScrollable, setIsScrollable] = React.useState(false); const [scrollLeft, setScrollLeft] = React.useState(0); let hasSecondaryLabelTabs = false; if (contained) { hasSecondaryLabelTabs = React__default["default"].Children.toArray(children).some(child => { return reactIs.isElement(child) && !!child.props.secondaryLabel; }); } const isLg = useMatchMedia.useMatchMedia(lgMediaQuery); const distributeWidth = fullWidth && contained && isLg && React__default["default"].Children.toArray(children).length < 9; const className = cx__default["default"](`${prefix}--tabs`, { [`${prefix}--tabs--contained`]: contained, [`${prefix}--tabs--light`]: light, [`${prefix}--tabs__icon--default`]: iconSize === 'default', [`${prefix}--tabs__icon--lg`]: iconSize === 'lg', // TODO: V12 - Remove this class [`${prefix}--layout--size-lg`]: iconSize === 'lg', [`${prefix}--tabs--tall`]: hasSecondaryLabelTabs, [`${prefix}--tabs--full-width`]: distributeWidth }, customClassName); // Previous Button // VISIBLE IF: // SCROLLABLE // AND SCROLL_LEFT > 0 const buttonWidth = 44; // Next Button // VISIBLE IF: // SCROLLABLE // AND SCROLL_LEFT + CLIENT_WIDTH < SCROLL_WIDTH const [isNextButtonVisible, setIsNextButtonVisible] = React.useState(ref.current ? scrollLeft + buttonWidth + ref.current.clientWidth < ref.current.scrollWidth : false); const isPreviousButtonVisible = ref.current ? isScrollable && scrollLeft > 0 : false; const previousButtonClasses = cx__default["default"](`${prefix}--tab--overflow-nav-button`, `${prefix}--tab--overflow-nav-button--previous`, { [`${prefix}--tab--overflow-nav-button--hidden`]: !isPreviousButtonVisible }); const nextButtonClasses = cx__default["default"](`${prefix}--tab--overflow-nav-button`, `${prefix}--tab--overflow-nav-button--next`, { [`${prefix}--tab--overflow-nav-button--hidden`]: !isNextButtonVisible }); const tabs = React.useRef([]); const debouncedOnScroll = React.useCallback(() => { return debounce__default["default"](event => { setScrollLeft(event.target.scrollLeft); }, scrollDebounceWait); }, [scrollDebounceWait]); function onKeyDown(event) { if (match.matches(event, [keys.ArrowRight, keys.ArrowLeft, keys.Home, keys.End])) { event.preventDefault(); const activeTabs = tabs.current.filter(tab => !tab.disabled); const currentIndex = activeTabs.indexOf(tabs.current[activation === 'automatic' ? selectedIndex : activeIndex]); const nextIndex = tabs.current.indexOf(activeTabs[getNextIndex(event, activeTabs.length, currentIndex)]); if (activation === 'automatic') { setSelectedIndex(nextIndex); } else if (activation === 'manual') { setActiveIndex(nextIndex); } tabs.current[nextIndex]?.focus(); } } useEffectOnce.useEffectOnce(() => { const tab = tabs.current[selectedIndex]; if (scrollIntoView && tab) { tab.scrollIntoView({ block: 'nearest', inline: 'nearest' }); } }); React.useEffect(() => { setIsNextButtonVisible(ref.current ? scrollLeft + buttonWidth + ref.current.clientWidth < ref.current.scrollWidth : false); if (dismissable) { if (ref.current) { setIsScrollable(ref.current.scrollWidth > ref.current.clientWidth); } } }, [scrollLeft, children, dismissable]); useEffectOnce.useEffectOnce(() => { if (tabs.current[selectedIndex].disabled) { const activeTabs = tabs.current.filter(tab => { return !tab.disabled; }); if (activeTabs.length > 0) { const tab = activeTabs[0]; setSelectedIndex(tabs.current.indexOf(tab)); } } }); useIsomorphicEffect["default"](() => { if (ref.current) { setIsScrollable(ref.current.scrollWidth > ref.current.clientWidth); } function handler() { if (ref.current) { setIsScrollable(ref.current.scrollWidth > ref.current.clientWidth); } } const debouncedHandler = debounce__default["default"](handler, 200); window.addEventListener('resize', debouncedHandler); return () => { debouncedHandler.cancel(); window.removeEventListener('resize', debouncedHandler); }; }, []); // updates scroll location for all scroll behavior. useIsomorphicEffect["default"](() => { if (scrollLeft !== null && ref.current) { ref.current.scrollLeft = scrollLeft; } }, [scrollLeft]); useIsomorphicEffect["default"](() => { if (!isScrollable || !ref.current) { return; } const tab = activation === 'manual' ? tabs.current[activeIndex] : tabs.current[selectedIndex]; if (tab) { // The width of the "scroll buttons" // The start and end position of the selected tab const { width: tabWidth } = tab.getBoundingClientRect(); const start = tab.offsetLeft; const end = tab.offsetLeft + tabWidth; // The start and end of the visible area for the tabs const visibleStart = ref.current.scrollLeft + buttonWidth; const visibleEnd = ref.current.scrollLeft + ref.current.clientWidth - buttonWidth; // The beginning of the tab is clipped and not visible if (start < visibleStart) { setScrollLeft(start - buttonWidth); } // The end of the tab is clipped and not visible if (end > visibleEnd) { setScrollLeft(end + buttonWidth - ref.current.clientWidth); } } }, [activation, activeIndex, selectedIndex, isScrollable, children]); usePressable.usePressable(previousButton, { onPress(_ref3) { let { longPress } = _ref3; if (!longPress && ref.current) { setScrollLeft(Math.max(scrollLeft - ref.current.scrollWidth / tabs.current.length * 1.5, 0)); } }, onLongPress() { return createLongPressBehavior(ref, 'backward', setScrollLeft); } }); usePressable.usePressable(nextButton, { onPress(_ref4) { let { longPress } = _ref4; if (!longPress && ref.current) { setScrollLeft(Math.min(scrollLeft + ref.current.scrollWidth / tabs.current.length * 1.5, ref.current.scrollWidth - ref.current.clientWidth)); } }, onLongPress() { return createLongPressBehavior(ref, 'forward', setScrollLeft); } }); return /*#__PURE__*/React__default["default"].createElement("div", { className: className }, /*#__PURE__*/React__default["default"].createElement("button", _rollupPluginBabelHelpers["extends"]({ "aria-hidden": "true", tabIndex: -1, "aria-label": "Scroll left", ref: previousButton, className: previousButtonClasses, type: "button" }, leftOverflowButtonProps), _ChevronLeft || (_ChevronLeft = /*#__PURE__*/React__default["default"].createElement(iconsReact.ChevronLeft, null))), /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({}, rest, { "aria-label": label, ref: ref, role: "tablist", className: `${prefix}--tab--list`, onScroll: debouncedOnScroll, onKeyDown: onKeyDown }), React__default["default"].Children.map(children, (child, index) => { return !reactIs.isElement(child) ? null : /*#__PURE__*/React__default["default"].createElement(TabContext.Provider, { value: { index, hasSecondaryLabel: hasSecondaryLabelTabs, contained } }, /*#__PURE__*/React__default["default"].cloneElement(child, { ref: node => { tabs.current[index] = node; } })); })), /*#__PURE__*/React__default["default"].createElement("button", _rollupPluginBabelHelpers["extends"]({ "aria-hidden": "true", tabIndex: -1, "aria-label": "Scroll right", ref: nextButton, className: nextButtonClasses, type: "button" }, rightOverflowButtonProps), _ChevronRight || (_ChevronRight = /*#__PURE__*/React__default["default"].createElement(iconsReact.ChevronRight, null)))); } TabList.propTypes = { /** * Specify whether the content tab should be activated automatically or * manually */ activation: PropTypes__default["default"].oneOf(['automatic', 'manual']), /** * Provide an accessible label to be read when a user interacts with this * component */ 'aria-label': PropTypes__default["default"].string.isRequired, /** * Provide child elements to be rendered inside `ContentTabs`. * These elements should render a `ContentTab` */ children: PropTypes__default["default"].node, /** * Specify an optional className to be added to the container node */ className: PropTypes__default["default"].string, /** * Specify whether component is contained type */ contained: PropTypes__default["default"].bool, /** * Used for tabs within a grid, this makes it so tabs span the full container width and have the same width. Only available on contained tabs with <9 children */ fullWidth: PropTypes__default["default"].bool, /** * If using `IconTab`, specify the size of the icon being used. */ iconSize: PropTypes__default["default"].oneOf(['default', 'lg']), /** * Provide the props that describe the left overflow button */ leftOverflowButtonProps: PropTypes__default["default"].object, /** * Specify whether to use the light component variant */ light: deprecate["default"](PropTypes__default["default"].bool, 'The `light` prop for `TabList` has ' + 'been deprecated in favor of the new `Layer` component. It will be removed in the next major release.'), /** * Provide the props that describe the right overflow button */ rightOverflowButtonProps: PropTypes__default["default"].object, /** * Optionally provide a delay (in milliseconds) passed to the lodash * debounce of the onScroll handler. This will impact the responsiveness * of scroll arrow buttons rendering when scrolling to the first or last tab. */ scrollDebounceWait: PropTypes__default["default"].number, /** * Choose whether to automatically scroll * to newly selected tabs on component rerender */ scrollIntoView: PropTypes__default["default"].bool }; /** * Helper function to set up the behavior when a button is "long pressed". * This function will take a ref to the tablist, a direction, and a setter * for scrollLeft and will update the scroll position within a requestAnimationFrame. * * It returns a cleanup function to be run * when the long press is deactivated */ function createLongPressBehavior(ref, direction, setScrollLeft) { const node = ref.current; if (!node) { return () => {}; } // We manually override the scroll behavior to be "auto". // If it is set as smooth, this animation does not update correctly const defaultScrollBehavior = node?.style['scroll-behavior']; node.style['scroll-behavior'] = 'auto'; const scrollDelta = direction === 'forward' ? 5 : -5; let frameId = null; function tick() { if (!node) { return; } node.scrollLeft = node.scrollLeft + scrollDelta; frameId = requestAnimationFrame(tick); } frameId = requestAnimationFrame(tick); return () => { // Restore the previous scroll behavior node.style['scroll-behavior'] = defaultScrollBehavior; // Make sure that our `scrollLeft` value is in sync with the existing // `ref` after our requestAnimationFrame loop above setScrollLeft(node.scrollLeft); if (frameId) { cancelAnimationFrame(frameId); } }; } /** * Tab */ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) { let { as = 'button', children, className: customClassName, disabled, onClick, onKeyDown, secondaryLabel, renderIcon: Icon, labelOnly, ...rest } = _ref5; const prefix = usePrefix.usePrefix(); const { selectedIndex, setSelectedIndex, baseId, dismissable, onTabCloseRequest } = React__default["default"].useContext(TabsContext); const { index, hasSecondaryLabel, contained } = React__default["default"].useContext(TabContext); const dismissIconRef = React.useRef(null); const tabRef = React.useRef(null); const ref = useMergedRefs.useMergedRefs([forwardRef, tabRef]); const [ignoreHover, setIgnoreHover] = React.useState(false); const id = `${baseId}-tab-${index}`; const panelId = `${baseId}-tabpanel-${index}`; const className = cx__default["default"](`${prefix}--tabs__nav-item`, `${prefix}--tabs__nav-link`, { [`${prefix}--tabs__nav-item--selected`]: selectedIndex === index, [`${prefix}--tabs__nav-item--disabled`]: disabled, [`${prefix}--tabs__nav-item--hover-off`]: ignoreHover, 'msk-tabs--tab-label-only': labelOnly }, customClassName); const BaseComponent = as; const onDismissIconMouseEnter = evt => { if (contained && tabRef.current) { evt.stopPropagation(); setIgnoreHover(true); tabRef.current.classList.add(`${prefix}--tabs__nav-item--hover-off`); } }; const onDismissIconMouseLeave = () => { if (contained && tabRef.current) { tabRef.current.classList.remove(`${prefix}--tabs__nav-item--hover-off`); setIgnoreHover(false); } }; useEvent.useEvent(dismissIconRef, 'mouseover', onDismissIconMouseEnter); useEvent.useEvent(dismissIconRef, 'mouseleave', onDismissIconMouseLeave); const handleClose = evt => { evt.stopPropagation(); onTabCloseRequest?.(index); }; const handleKeyDown = event => { if (dismissable && match.match(event, keys.Delete)) { handleClose(event); } onKeyDown?.(event); }; const DismissIcon = /*#__PURE__*/ // eslint-disable-next-line jsx-a11y/click-events-have-key-events React__default["default"].createElement("div", { role: "button", tabIndex: -1, "aria-hidden": true, className: cx__default["default"](`${prefix}--tabs__nav-item--close-icon`, { [`${prefix}--visually-hidden`]: !dismissable }), onClick: handleClose, "aria-label": "Close tab", title: "Close tab", ref: dismissIconRef }, _Close || (_Close = /*#__PURE__*/React__default["default"].createElement(iconsReact.Close, null))); const hasIcon = Icon ?? dismissable; if (labelOnly) { return /*#__PURE__*/React__default["default"].createElement("button", { type: "button" // eslint-disable-next-line jsx-a11y/no-interactive-element-to-noninteractive-role , role: "alert", className: className, title: secondaryLabel, tabIndex: -1 }, /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--tabs__nav-item-label-wrapper` }, /*#__PURE__*/React__default["default"].createElement("span", { className: `${prefix}--tabs__nav-item-label` }, children), /*#__PURE__*/React__default["default"].createElement("div", { className: cx__default["default"](`${prefix}--tabs__nav-item--icon`, { [`${prefix}--visually-hidden`]: !hasIcon }) }, !dismissable && Icon && /*#__PURE__*/React__default["default"].createElement(Icon, { size: 16 })))); } return /*#__PURE__*/React__default["default"].createElement(BaseComponent, _rollupPluginBabelHelpers["extends"]({}, rest, { "aria-controls": panelId, "aria-disabled": disabled, "aria-selected": selectedIndex === index, ref: ref, id: id, role: "tab", className: className, disabled: disabled, onClick: evt => { if (disabled) { return; } setSelectedIndex(index); onClick?.(evt); }, onKeyDown: handleKeyDown, tabIndex: selectedIndex === index ? '0' : '-1', type: "button" }), /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--tabs__nav-item-label-wrapper` }, dismissable && Icon && /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--tabs__nav-item--icon-left` }, /*#__PURE__*/React__default["default"].createElement(Icon, { size: 16 })), /*#__PURE__*/React__default["default"].createElement("span", { className: `${prefix}--tabs__nav-item-label`, title: children }, children), /*#__PURE__*/React__default["default"].createElement("div", { className: cx__default["default"](`${prefix}--tabs__nav-item--icon`, { [`${prefix}--visually-hidden`]: !hasIcon }) }, DismissIcon, !dismissable && Icon && /*#__PURE__*/React__default["default"].createElement(Icon, { size: 16 }))), hasSecondaryLabel && /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--tabs__nav-item-secondary-label`, title: secondaryLabel }, secondaryLabel)); }); Tab.propTypes = { /** * Provide a custom element to render instead of the default button */ // @ts-expect-error: Invalid prop type derivation as: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].elementType]), /** * Provide child elements to be rendered inside `Tab`. */ children: PropTypes__default["default"].node, /** * Specify an optional className to be added to your Tab */ className: PropTypes__default["default"].string, /** * Whether your Tab is disabled. */ disabled: PropTypes__default["default"].bool, /** * Whether your Tab is only a label. */ labelOnly: PropTypes__default["default"].bool, /** * Provide a handler that is invoked when a user clicks on the control */ onClick: PropTypes__default["default"].func, /** * Provide a handler that is invoked on the key down event for the control */ onKeyDown: PropTypes__default["default"].func, /* * An optional parameter to allow overriding the anchor rendering. * Useful for using Tab along with react-router or other client * side router libraries. **/ renderButton: PropTypes__default["default"].func, /** * Optional prop to render an icon next to the label. * Can be a React component class */ // @ts-expect-error: Invalid prop type derivation renderIcon: PropTypes__default["default"].oneOfType([PropTypes__default["default"].func, PropTypes__default["default"].object]), /* * An optional label to render under the primary tab label. /* This prop is only useful for conained tabs **/ secondaryLabel: PropTypes__default["default"].string }; /** * IconTab */ const IconTab = /*#__PURE__*/React__default["default"].forwardRef(function IconTab(_ref6, ref) { let { children, className: customClassName, defaultOpen = false, enterDelayMs, leaveDelayMs, label, ...rest } = _ref6; const prefix = usePrefix.usePrefix(); const classNames = cx__default["default"](`${prefix}--tabs__nav-item--icon-only`, customClassName); return /*#__PURE__*/React__default["default"].createElement(Tooltip.Tooltip, { align: "bottom", defaultOpen: defaultOpen, className: `${prefix}--icon-tooltip`, enterDelayMs: enterDelayMs, label: label, leaveDelayMs: leaveDelayMs }, /*#__PURE__*/React__default["default"].createElement(Tab, _rollupPluginBabelHelpers["extends"]({ className: classNames, ref: ref }, rest), children)); }); IconTab.propTypes = { /** * Provide an icon to be rendered inside `IconTab` as the visual label for Tab. */ children: PropTypes__default["default"].node, /** * Specify an optional className to be added to your Tab */ className: PropTypes__default["default"].string, /** * Specify whether the tooltip for the icon should be open when it first renders */ defaultOpen: PropTypes__default["default"].bool, /** * Specify the duration in milliseconds to delay before displaying the tooltip for the icon. */ enterDelayMs: PropTypes__default["default"].number, /** * Provide the label to be rendered inside the Tooltip. The label will use * `aria-labelledby` and will fully describe the child node that is provided. * This means that if you have text in the child node it will not be * announced to the screen reader. */ label: PropTypes__default["default"].node.isRequired, /** * Specify the duration in milliseconds to delay before hiding the tooltip */ leaveDelayMs: PropTypes__default["default"].number }; /** * TabPanel */ const TabPanel = /*#__PURE__*/React__default["default"].forwardRef(function TabPanel(_ref7, forwardRef) { let { children, className: customClassName, ...rest } = _ref7; const prefix = usePrefix.usePrefix(); const panel = React.useRef(null); const ref = useMergedRefs.useMergedRefs([forwardRef, panel]); const [tabIndex, setTabIndex] = React.useState(0); const [interactiveContent, setInteractiveContent] = React.useState(false); const { selectedIndex, baseId } = React__default["default"].useContext(TabsContext); const index = React__default["default"].useContext(TabPanelContext); const id = `${baseId}-tabpanel-${index}`; const tabId = `${baseId}-tab-${index}`; const className = cx__default["default"](`${prefix}--tab-content`, customClassName, { [`${prefix}--tab-content--interactive`]: interactiveContent }); useEffectOnce.useEffectOnce(() => { if (!panel.current) { return; } const content = useNoInteractiveChildren.getInteractiveContent(panel.current); if (content) { setInteractiveContent(true); setTabIndex(-1); } }); // tabindex should only be 0 if no interactive content in children React.useEffect(() => { const node = panel.current; if (!node) { return; } function callback() { const content = useNoInteractiveChildren.getInteractiveContent(node); if (content) { setInteractiveContent(true); setTabIndex(-1); } else { setInteractiveContent(false); setTabIndex(0); } } const observer = new MutationObserver(callback); observer.observe(node, { childList: true, subtree: true }); return () => observer.disconnect(); }, []); return /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({}, rest, { "aria-labelledby": tabId, id: id, className: className, ref: ref, role: "tabpanel", tabIndex: tabIndex, hidden: selectedIndex !== index }), children); }); TabPanel.propTypes = { /** * Provide child elements to be rendered inside `TabPanel`. */ children: PropTypes__default["default"].node, /** * Specify an optional className to be added to TabPanel. */ className: PropTypes__default["default"].string }; /** * TabPanels */ function TabPanels(_ref8) { let { children } = _ref8; return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, React__default["default"].Children.map(children, (child, index) => { return /*#__PURE__*/React__default["default"].createElement(TabPanelContext.Provider, { value: index }, child); })); } TabPanels.propTypes = { /** * Provide child elements to be rendered inside `TabPanels`. */ children: PropTypes__default["default"].node }; exports.IconTab = IconTab; exports.Tab = Tab; exports.TabList = TabList; exports.TabPanel = TabPanel; exports.TabPanels = TabPanels; exports.Tabs = Tabs;