@carbon/ibm-products
Version:
Carbon for IBM Products
223 lines (214 loc) • 8.41 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2025
*
* 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';
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var react = require('@carbon/react');
var icons = require('@carbon/react/icons');
var React = require('react');
var index$1 = require('../../node_modules/@carbon/colors/es/index.js');
var Carousel = require('../Carousel/Carousel.js');
require('../Carousel/CarouselItem.js');
var index = require('../../_virtual/index.js');
var cx = require('classnames');
var devtools = require('../../global/js/utils/devtools.js');
var settings = require('../../settings.js');
var uuidv4 = require('../../global/js/utils/uuidv4.js');
var _CaretLeft, _CaretRight, _Close;
// The block part of our conventional BEM class names (blockClass__E--M).
const blockClass = `${settings.pkg.prefix}--guidebanner`;
const componentName = 'Guidebanner';
const defaults = {
collapsible: false,
withLeftGutter: false,
// Labels
closeIconDescription: 'Close',
collapseButtonLabel: 'Read less',
expandButtonLabel: 'Read more',
nextIconDescription: 'Next',
previousIconDescription: 'Back'
};
/**
* The guide banner sits at the top of a page, or page-level tab,
* to introduce foundational concepts related to the page's content.
*/
exports.Guidebanner = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
children,
className,
collapsible = defaults.collapsible,
onClose,
withLeftGutter = defaults.withLeftGutter,
// Labels
closeIconDescription = defaults.closeIconDescription,
collapseButtonLabel = defaults.collapseButtonLabel,
expandButtonLabel = defaults.expandButtonLabel,
nextIconDescription = defaults.nextIconDescription,
previousIconDescription = defaults.previousIconDescription,
title,
...rest
} = _ref;
const scrollRef = React.useRef(null);
const toggleRef = React.useRef(null);
const [scrollPosition, setScrollPosition] = React.useState(0);
const [showNavigation, setShowNavigation] = React.useState(false);
const [isCollapsed, setIsCollapsed] = React.useState(collapsible ? true : false);
const handleClickToggle = () => {
setIsCollapsed(prevState => !prevState);
};
const carouselContentId = `${uuidv4.default()}--carousel-content-id`;
return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({}, rest, {
"aria-owns": !isCollapsed ? carouselContentId : undefined,
className: cx(blockClass, className, collapsible && `${blockClass}__collapsible`, isCollapsed && `${blockClass}__collapsible-collapsed`, withLeftGutter && `${blockClass}__with-left-gutter`),
ref: ref
}, devtools.getDevtoolsProps(componentName)), /*#__PURE__*/React.createElement(icons.Idea, {
size: 20,
className: `${blockClass}__icon-idea`
}), /*#__PURE__*/React.createElement("div", {
className: `${blockClass}__title`
}, title), /*#__PURE__*/React.createElement(Carousel.Carousel, {
id: carouselContentId,
className: `${blockClass}__carousel`
// These colors are to match the Carousel's faded edges
// against the Guidebanner's gradient background.
,
fadedEdgeColor: {
left: index$1.blue90,
right: index$1.purple70
},
ref: scrollRef,
onChangeIsScrollable: value => {
setShowNavigation(value);
},
onScroll: scrollPercent => {
setScrollPosition(scrollPercent);
},
isScrollMode: true
}, children), /*#__PURE__*/React.createElement("div", {
className: cx([collapsible || showNavigation ? `${blockClass}__navigation` : null])
}, collapsible && /*#__PURE__*/React.createElement(react.Button, {
kind: "ghost",
size: "md",
className: `${blockClass}__toggle-button`,
onClick: handleClickToggle,
ref: toggleRef,
"aria-controls": !isCollapsed ? carouselContentId : undefined,
"aria-expanded": !isCollapsed
}, isCollapsed ? expandButtonLabel : collapseButtonLabel), showNavigation && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
className: cx(`${blockClass}__back-button`, [scrollPosition === 0 ? `${blockClass}__back-button--disabled` : null])
}, /*#__PURE__*/React.createElement(react.IconButton, {
align: "top",
disabled: scrollPosition === 0,
kind: "ghost",
label: previousIconDescription,
onClick: () => {
scrollRef.current.scrollPrev();
},
size: "md"
}, _CaretLeft || (_CaretLeft = /*#__PURE__*/React.createElement(icons.CaretLeft, {
size: 16
})))), /*#__PURE__*/React.createElement("span", {
className: cx(`${blockClass}__next-button`, [scrollPosition === 1 ? `${blockClass}__next-button--disabled` : null])
}, /*#__PURE__*/React.createElement(react.IconButton, {
align: "top-right",
disabled: scrollPosition === 1,
kind: "ghost",
label: nextIconDescription,
onClick: () => {
scrollRef.current.scrollNext();
},
size: "md"
}, _CaretRight || (_CaretRight = /*#__PURE__*/React.createElement(icons.CaretRight, {
size: 16
})))))), onClose && /*#__PURE__*/React.createElement("span", {
className: `${blockClass}__close-button`
}, /*#__PURE__*/React.createElement(react.IconButton, {
align: "bottom-end",
kind: "ghost",
label: closeIconDescription,
onClick: onClose,
size: "md"
}, _Close || (_Close = /*#__PURE__*/React.createElement(icons.Close, {
size: 16
})))));
});
// Return a placeholder if not released and not enabled by feature flag
exports.Guidebanner = settings.pkg.checkComponentEnabled(exports.Guidebanner, componentName);
// The display name of the component, used by React. Note that displayName
// is used in preference to relying on function.name.
exports.Guidebanner.displayName = componentName;
// The types and DocGen commentary for the component props,
// in alphabetical order (for consistency).
// See https://www.npmjs.com/package/prop-types#usage.
exports.Guidebanner.propTypes = {
/**
* Provide the contents of the Guidebanner.
* One or more GuidebannerElement components are required.
*/
children: (props, propName) => {
let error;
const prop = props[propName];
if (!prop) {
error = new Error('`Guidebanner` requires one or more children of type `GuidebannerElement`.');
}
React.Children.forEach(prop, child => {
if (child.type.displayName !== 'GuidebannerElement') {
// If child element is not `GuidebannerElement`, then show:
// Carbon Products component's `displayName` (child.type.displayName) or
// React component's `name` (child.type.name) or
// HTML element's tag name (child.type).
error = new Error(`\`Guidebanner\` only accepts children of type \`GuidebannerElement\`, found \`${child.type?.displayName || child.type?.name || child.type}\` instead.`);
}
});
return error;
},
/**
* Provide an optional class to be applied to the containing node.
*/
className: index.default.string,
/**
* Tooltip text and aria label for the Close button icon.
*/
closeIconDescription: index.default.string,
/**
* Text label for the Collapse button.
*/
collapseButtonLabel: index.default.string,
/**
* When true, the Guidebanner will initialize in a collapsed state,
* showing the title and the Expand button.
*
* When expanded, it will show the GuidebannerElement child components and the Collapse button.
*/
collapsible: index.default.bool,
/**
* Text label for the Expand button.
*/
expandButtonLabel: index.default.string,
/**
* Tooltip text and aria label for the Next button icon.
*/
nextIconDescription: index.default.string,
/**
* If defined, a Close button will render in the top-right corner and a
* callback function will be triggered when button is clicked.
*/
onClose: index.default.func,
/**
* Tooltip text and aria label for the Back button icon.
*/
previousIconDescription: index.default.string,
/**
* Title text.
*/
title: index.default.string.isRequired,
/**
* If true, insert 1 rem of "space" on the left of the component.
* This will allow the component's content to line up with other
* content on the page under special circumstances.
*/
withLeftGutter: index.default.bool
};