UNPKG

@wordpress/components

Version:
202 lines (194 loc) 7.52 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.TabPanel = void 0; var Ariakit = _interopRequireWildcard(require("@ariakit/react")); var _clsx = _interopRequireDefault(require("clsx")); var _element = require("@wordpress/element"); var _compose = require("@wordpress/compose"); var _i18n = require("@wordpress/i18n"); var _button = _interopRequireDefault(require("../button")); var _jsxRuntime = require("react/jsx-runtime"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ // Separate the actual tab name from the instance ID. This is // necessary because Ariakit internally uses the element ID when // a new tab is selected, but our implementation looks specifically // for the tab name to be passed to the `onSelect` callback. const extractTabName = id => { if (typeof id === 'undefined' || id === null) { return; } return id.match(/^tab-panel-[0-9]*-(.*)/)?.[1]; }; /** * TabPanel is an ARIA-compliant tabpanel. * * TabPanels organize content across different screens, data sets, and interactions. * It has two sections: a list of tabs, and the view to show when tabs are chosen. * * ```jsx * import { TabPanel } from '@wordpress/components'; * * const onSelect = ( tabName ) => { * console.log( 'Selecting tab', tabName ); * }; * * const MyTabPanel = () => ( * <TabPanel * className="my-tab-panel" * activeClass="active-tab" * onSelect={ onSelect } * tabs={ [ * { * name: 'tab1', * title: 'Tab 1', * className: 'tab-one', * }, * { * name: 'tab2', * title: 'Tab 2', * className: 'tab-two', * }, * ] } * > * { ( tab ) => <p>{ tab.title }</p> } * </TabPanel> * ); * ``` */ const UnforwardedTabPanel = ({ className, children, tabs, selectOnMove = true, initialTabName, orientation = 'horizontal', activeClass = 'is-active', onSelect }, ref) => { const instanceId = (0, _compose.useInstanceId)(TabPanel, 'tab-panel'); const prependInstanceId = (0, _element.useCallback)(tabName => { if (typeof tabName === 'undefined') { return; } return `${instanceId}-${tabName}`; }, [instanceId]); const tabStore = Ariakit.useTabStore({ setSelectedId: newTabValue => { if (typeof newTabValue === 'undefined' || newTabValue === null) { return; } const newTab = tabs.find(t => prependInstanceId(t.name) === newTabValue); if (newTab?.disabled || newTab === selectedTab) { return; } const simplifiedTabName = extractTabName(newTabValue); if (typeof simplifiedTabName === 'undefined') { return; } onSelect?.(simplifiedTabName); }, orientation, selectOnMove, defaultSelectedId: prependInstanceId(initialTabName), rtl: (0, _i18n.isRTL)() }); const selectedTabName = extractTabName(Ariakit.useStoreState(tabStore, 'selectedId')); const setTabStoreSelectedId = (0, _element.useCallback)(tabName => { tabStore.setState('selectedId', prependInstanceId(tabName)); }, [prependInstanceId, tabStore]); const selectedTab = tabs.find(({ name }) => name === selectedTabName); const previousSelectedTabName = (0, _compose.usePrevious)(selectedTabName); // Ensure `onSelect` is called when the initial tab is selected. (0, _element.useEffect)(() => { if (previousSelectedTabName !== selectedTabName && selectedTabName === initialTabName && !!selectedTabName) { onSelect?.(selectedTabName); } }, [selectedTabName, initialTabName, onSelect, previousSelectedTabName]); // Handle selecting the initial tab. (0, _element.useLayoutEffect)(() => { // If there's a selected tab, don't override it. if (selectedTab) { return; } const initialTab = tabs.find(tab => tab.name === initialTabName); // Wait for the denoted initial tab to be declared before making a // selection. This ensures that if a tab is declared lazily it can // still receive initial selection. if (initialTabName && !initialTab) { return; } if (initialTab && !initialTab.disabled) { // Select the initial tab if it's not disabled. setTabStoreSelectedId(initialTab.name); } else { // Fallback to the first enabled tab when the initial tab is // disabled or it can't be found. const firstEnabledTab = tabs.find(tab => !tab.disabled); if (firstEnabledTab) { setTabStoreSelectedId(firstEnabledTab.name); } } }, [tabs, selectedTab, initialTabName, instanceId, setTabStoreSelectedId]); // Handle the currently selected tab becoming disabled. (0, _element.useEffect)(() => { // This effect only runs when the selected tab is defined and becomes disabled. if (!selectedTab?.disabled) { return; } const firstEnabledTab = tabs.find(tab => !tab.disabled); // If the currently selected tab becomes disabled, select the first enabled tab. // (if there is one). if (firstEnabledTab) { setTabStoreSelectedId(firstEnabledTab.name); } }, [tabs, selectedTab?.disabled, setTabStoreSelectedId, instanceId]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { className: className, ref: ref, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Ariakit.TabList, { store: tabStore, className: "components-tab-panel__tabs", children: tabs.map(tab => { return /*#__PURE__*/(0, _jsxRuntime.jsx)(Ariakit.Tab, { id: prependInstanceId(tab.name), className: (0, _clsx.default)('components-tab-panel__tabs-item', tab.className, { [activeClass]: tab.name === selectedTabName }), disabled: tab.disabled, "aria-controls": `${prependInstanceId(tab.name)}-view`, render: /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, { __next40pxDefaultSize: true, icon: tab.icon, label: tab.icon && tab.title, showTooltip: !!tab.icon }), children: !tab.icon && tab.title }, tab.name); }) }), selectedTab && /*#__PURE__*/(0, _jsxRuntime.jsx)(Ariakit.TabPanel, { id: `${prependInstanceId(selectedTab.name)}-view`, store: tabStore, tabId: prependInstanceId(selectedTab.name), className: "components-tab-panel__tab-content", children: children(selectedTab) })] }); }; const TabPanel = exports.TabPanel = (0, _element.forwardRef)(UnforwardedTabPanel); var _default = exports.default = TabPanel; //# sourceMappingURL=index.js.map