@carbon/react
Version:
React components for the Carbon Design System
162 lines (154 loc) • 5.93 kB
JavaScript
/**
* 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.
*/
;
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;