UNPKG

@carbon/react

Version:

React components for the Carbon Design System

162 lines (154 loc) 5.93 kB
/** * Copyright IBM Corp. 2016, 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var PropTypes = require('prop-types'); var React = require('react'); var cx = require('classnames'); var deprecate = require('../../prop-types/deprecate.js'); var index = require('../Layout/index.js'); var events = require('../../tools/events.js'); var keys = require('../../internal/keyboard/keys.js'); var match = require('../../internal/keyboard/match.js'); var navigation = require('../../internal/keyboard/navigation.js'); var usePrefix = require('../../internal/usePrefix.js'); var noopFn = require('../../internal/noopFn.js'); require('../Switch/Switch.js'); var IconSwitch = require('../Switch/IconSwitch.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx); const ContentSwitcher = ({ children, className, light, lowContrast, selectedIndex: selectedIndexProp = 0, selectionMode = 'automatic', size, onChange = noopFn.noopFn, ...other }) => { const prefix = React.useContext(usePrefix.PrefixContext); const [selectedIndex, setSelectedIndex] = React.useState(selectedIndexProp); const prevSelectedIndexRef = React.useRef(selectedIndexProp); const switchRefs = React.useRef([]); const childrenArray = React.Children.toArray(children); React.useEffect(() => { if (prevSelectedIndexRef.current !== selectedIndexProp) { setSelectedIndex(selectedIndexProp); prevSelectedIndexRef.current = selectedIndexProp; } }, [selectedIndexProp]); const handleItemRef = index => ref => { if (ref) { switchRefs.current[index] = ref; } }; const focusSwitch = index => { const ref = switchRefs.current[index]; if (ref) { ref.focus(); } }; const isKeyboardEvent = event => event && typeof event === 'object' && 'key' in event; const handleChildChange = event => { if (typeof event.index === 'undefined') return; const { index } = event; if (isKeyboardEvent(event) && match.matches(event, [keys.ArrowRight, keys.ArrowLeft])) { const nextIndex = navigation.getNextIndex(event.key, index, childrenArray.length); if (typeof nextIndex !== 'number') return; focusSwitch(nextIndex); if (selectionMode !== 'manual') { const child = childrenArray[nextIndex]; setSelectedIndex(nextIndex); if (/*#__PURE__*/React.isValidElement(child)) { onChange({ ...event, index: nextIndex, name: child.props.name, text: child.props.text }); } } } else if (selectedIndex !== index) { setSelectedIndex(index); focusSwitch(index); onChange(event); } }; const isIconOnly = React.Children.map(children, child => { return /*#__PURE__*/React.isValidElement(child) ? child.type === IconSwitch["default"] : null; })?.every(val => val === true); const classes = cx__default["default"](`${prefix}--content-switcher`, className, { [`${prefix}--content-switcher--light`]: light, [`${prefix}--content-switcher--${size}`]: size, // TODO: V12 - Remove this class [`${prefix}--layout--size-${size}`]: size, [`${prefix}--content-switcher--icon-only`]: isIconOnly, [`${prefix}--content-switcher--low-contrast`]: lowContrast }); return /*#__PURE__*/React__default["default"].createElement(index.LayoutConstraint, _rollupPluginBabelHelpers["extends"]({ size: { default: 'md', min: 'sm', max: 'lg' } }, other, { className: classes, role: "tablist", onChange: undefined }), children && React.Children.map(children, (child, index) => /*#__PURE__*/React.cloneElement(child, { index, onClick: events.composeEventHandlers([handleChildChange, child.props.onClick]), onKeyDown: events.composeEventHandlers([handleChildChange, child.props.onKeyDown]), selected: index === selectedIndex, ref: handleItemRef(index), size }))); }; ContentSwitcher.displayName = 'ContentSwitcher'; ContentSwitcher.propTypes = { /** * Pass in Switch components to be rendered in the ContentSwitcher */ children: PropTypes__default["default"].node, /** * Specify an optional className to be added to the container node */ className: PropTypes__default["default"].string, /** * `true` to use the light variant. */ light: deprecate["default"](PropTypes__default["default"].bool, 'The `light` prop for `ContentSwitcher` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'), /** * `true` to use the low contrast version. */ lowContrast: PropTypes__default["default"].bool, /** * Specify an `onChange` handler that is called whenever the ContentSwitcher * changes which item is selected */ onChange: PropTypes__default["default"].func.isRequired, /** * Specify a selected index for the initially selected content */ selectedIndex: PropTypes__default["default"].number, /** * Choose whether or not to automatically change selection on focus when left/right arrow pressed. Defaults to 'automatic' */ selectionMode: PropTypes__default["default"].oneOf(['automatic', 'manual']), /** * Specify the size of the Content Switcher. Currently supports either `sm`, `md` (default) or `lg` as an option. */ size: PropTypes__default["default"].oneOf(['sm', 'md', 'lg']) }; exports.ContentSwitcher = ContentSwitcher;