@carbon/ibm-products
Version:
Carbon for IBM Products
158 lines (156 loc) • 6.7 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
const require_index = require("../../node_modules/classnames/index.js");
const require_settings = require("../../settings.js");
const require_props_helper = require("../../global/js/utils/props-helper.js");
const require_useResizeObserver = require("../../global/js/hooks/useResizeObserver.js");
let react = require("react");
react = require_runtime.__toESM(react);
let prop_types = require("prop-types");
prop_types = require_runtime.__toESM(prop_types);
let _carbon_react = require("@carbon/react");
//#region src/components/ButtonSetWithOverflow/ButtonSetWithOverflow.jsx
var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default);
const blockClass = `${require_settings.pkg.prefix}--button-set-with-overflow`;
const componentName = "ButtonSetWithOverflow";
const buttonSize = "md";
const ButtonSetWithOverflow = ({ buttons, className, onWidthChange, buttonSetOverflowLabel, menuOptionsClass, rightAlign }) => {
const carbonPrefix = (0, _carbon_react.usePrefix)();
const [showAsOverflow, setShowAsOverflow] = (0, react.useState)(false);
const spaceAvailableRef = (0, react.useRef)(null);
const sizingContainerRefSet = (0, react.useRef)(null);
const sizingContainerRefCombo = (0, react.useRef)(null);
const sizes = (0, react.useRef)({});
/**
* checkFullyVisibleItems determines display count based on space available and width of pageActions
*
* ButtonSetWithOverflow switches between a Carbon ButtonSet and use of the ButtonMenu component depending
* on the space available. While there is sufficient space to show all of the buttons side by side the
* ButtonSet is used, once this is no longer the case it switches to a ButtonMenu.
*
*/
const checkFullyVisibleItems = () => {
const spaceAvailable = spaceAvailableRef.current?.offsetWidth;
let newShowAsOverflow = true;
const sizingSet = sizingContainerRefSet.current?.querySelectorAll(`.${carbonPrefix}--btn`);
let sizingSetTotalSize = 0;
for (let item of sizingSet) sizingSetTotalSize += item.offsetWidth;
const sizingComboSize = sizingContainerRefCombo.current?.offsetWidth;
if (onWidthChange && (sizes.current.minWidth !== sizingComboSize || sizes.current.maxWidth !== sizingSetTotalSize)) {
sizes.current.minWidth = sizingComboSize;
sizes.current.maxWidth = sizingSetTotalSize;
onWidthChange({ ...sizes.current });
}
if (sizingSetTotalSize <= spaceAvailable) newShowAsOverflow = false;
setShowAsOverflow(newShowAsOverflow);
};
(0, react.useEffect)(() => {
checkFullyVisibleItems();
}, [buttons]);
const AButtonSet = react.default.forwardRef(({ isHidden = false, buttons, ...rest }, ref) => {
return /* @__PURE__ */ react.default.createElement(_carbon_react.ButtonSet, {
...rest,
ref
}, buttons.map(({ label, key, kind, id, ...other }) => {
const kindFix = kind === "default" ? "primary" : kind;
return /* @__PURE__ */ react.default.createElement(_carbon_react.Button, {
...other,
key: key && `button-set-${key}`,
size: buttonSize,
type: "button",
kind: kindFix,
id: id ? isHidden ? `${id}--hidden` : id : null
}, label);
}));
});
AButtonSet.propTypes = {
/**
* isHidden - Used to conditionally change id if one is passed to the `AButtonSet` component
* in order to avoid duplicate ids between the visible and hidden button set buttons
*/
isHidden: prop_types.default.bool };
const AButtonMenu = react.default.forwardRef(({ buttons, ...rest }, ref) => {
return /* @__PURE__ */ react.default.createElement(_carbon_react.MenuButton, {
...rest,
ref,
label: buttonSetOverflowLabel
}, buttons.map(({ key, kind, ...other }) => {
const kindFix = kind === "danger" ? "danger" : "default";
return /* @__PURE__ */ react.default.createElement(_carbon_react.MenuItem, {
...require_props_helper.prepareProps(other, ["iconDescription", "renderIcon"]),
key: key && `button-menu-${key}`,
kind: kindFix
});
}).reverse());
});
require_useResizeObserver.useResizeObserver(sizingContainerRefSet, checkFullyVisibleItems);
require_useResizeObserver.useResizeObserver(sizingContainerRefCombo, checkFullyVisibleItems);
require_useResizeObserver.useResizeObserver(spaceAvailableRef, checkFullyVisibleItems);
return /* @__PURE__ */ react.default.createElement("div", {
className: (0, import_classnames.default)([
blockClass,
className,
{ [`${blockClass}--right`]: rightAlign }
]),
ref: spaceAvailableRef
}, /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__button-container ${blockClass}__button-container--hidden` }, /* @__PURE__ */ react.default.createElement(AButtonSet, {
"aria-hidden": true,
ref: sizingContainerRefSet,
size: buttonSize,
buttons,
isHidden: true
})), /* @__PURE__ */ react.default.createElement("div", {
className: `${blockClass}__button-container ${blockClass}__button-container--hidden`,
"aria-hidden": true
}, /* @__PURE__ */ react.default.createElement(AButtonMenu, {
className: menuOptionsClass,
ref: sizingContainerRefCombo,
buttons,
size: buttonSize
})), /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__button-container ${blockClass}__button-container--visible` }, showAsOverflow ? /* @__PURE__ */ react.default.createElement(AButtonMenu, {
buttons,
size: buttonSize,
className: menuOptionsClass
}) : /* @__PURE__ */ react.default.createElement(AButtonSet, {
className: `${blockClass}__button-container`,
size: buttonSize,
buttons
})));
};
ButtonSetWithOverflow.propTypes = {
/**
* buttonSetOverflowLabel - used when button set is shown as combo button
*/
buttonSetOverflowLabel: prop_types.default.node.isRequired,
/**
* Specifies the buttons for the ButtonSetWithOverflow. Each item is specified as an object
* with the properties of a Carbon Button plus a label.
*
* Carbon Button API https://react.carbondesignsystem.com/?path=/docs/components-button--default#component-api
*/
buttons: prop_types.default.array.isRequired,
/**
* className
*/
className: prop_types.default.string,
/**
* class name applied to the overflow options
*/
menuOptionsClass: prop_types.default.string,
/**
* onResize reports maxSize on resize
*/
onWidthChange: prop_types.default.func,
/**
* align buttons to right of available space
*/
rightAlign: prop_types.default.bool
};
ButtonSetWithOverflow.displayName = componentName;
//#endregion
exports.ButtonSetWithOverflow = ButtonSetWithOverflow;