@carbon/react
Version:
React components for the Carbon Design System
230 lines (228 loc) • 9.17 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 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_usePrefix = require("../../internal/usePrefix.js");
const require_useId = require("../../internal/useId.js");
const require_deprecate = require("../../prop-types/deprecate.js");
const require_deprecateValuesWithin = require("../../prop-types/deprecateValuesWithin.js");
const require_mapPopoverAlign = require("../../tools/mapPopoverAlign.js");
const require_index = require("../Button/index.js");
const require_useResizeObserver = require("../../internal/useResizeObserver.js");
const require_index$1 = require("../Copy/index.js");
const require_index$2 = require("../CopyButton/index.js");
let classnames = require("classnames");
classnames = require_runtime.__toESM(classnames);
let react = require("react");
react = require_runtime.__toESM(react);
let prop_types = require("prop-types");
prop_types = require_runtime.__toESM(prop_types);
let react_jsx_runtime = require("react/jsx-runtime");
let _carbon_icons_react = require("@carbon/icons-react");
let copy_to_clipboard = require("copy-to-clipboard");
copy_to_clipboard = require_runtime.__toESM(copy_to_clipboard);
//#region src/components/CodeSnippet/CodeSnippet.tsx
/**
* Copyright IBM Corp. 2016, 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.
*/
const rowHeightInPixels = 16;
const defaultMaxCollapsedNumberOfRows = 15;
const defaultMaxExpandedNumberOfRows = 0;
const defaultMinCollapsedNumberOfRows = 3;
const defaultMinExpandedNumberOfRows = 16;
function CodeSnippet({ align = "bottom", autoAlign = false, className, type = "single", children, disabled, feedback, feedbackTimeout, onClick, ["aria-label"]: ariaLabel = "Copy to clipboard", ariaLabel: deprecatedAriaLabel, copyText, copyButtonDescription, light, showMoreText = "Show more", showLessText = "Show less", hideCopyButton, wrapText = false, maxCollapsedNumberOfRows = defaultMaxCollapsedNumberOfRows, maxExpandedNumberOfRows = defaultMaxExpandedNumberOfRows, minCollapsedNumberOfRows = defaultMinCollapsedNumberOfRows, minExpandedNumberOfRows = defaultMinExpandedNumberOfRows, ...rest }) {
const [expandedCode, setExpandedCode] = (0, react.useState)(false);
const [shouldShowMoreLessBtn, setShouldShowMoreLessBtn] = (0, react.useState)(false);
const { current: uid } = (0, react.useRef)(require_useId.useId());
const codeContentRef = (0, react.useRef)(null);
const codeContainerRef = (0, react.useRef)(null);
const innerCodeRef = (0, react.useRef)(null);
const getCodeRef = (0, react.useCallback)(() => {
if (type === "single") return codeContainerRef;
if (type === "multi") return codeContentRef;
else return innerCodeRef;
}, [type]);
const prefix = require_usePrefix.usePrefix();
require_useResizeObserver.useResizeObserver({
ref: getCodeRef(),
onResize: () => {
if (innerCodeRef?.current && type === "multi") {
const { height } = innerCodeRef.current.getBoundingClientRect();
if (maxCollapsedNumberOfRows > 0 && (maxExpandedNumberOfRows <= 0 || maxExpandedNumberOfRows > maxCollapsedNumberOfRows) && height > maxCollapsedNumberOfRows * rowHeightInPixels) setShouldShowMoreLessBtn(true);
else setShouldShowMoreLessBtn(false);
if (expandedCode && minExpandedNumberOfRows > 0 && height <= minExpandedNumberOfRows * rowHeightInPixels) setExpandedCode(false);
}
}
});
const handleCopyClick = (evt) => {
if (copyText || innerCodeRef?.current) (0, copy_to_clipboard.default)(copyText ?? innerCodeRef?.current?.innerText ?? "");
if (onClick) onClick(evt);
};
const codeSnippetClasses = (0, classnames.default)(className, `${prefix}--snippet`, {
[`${prefix}--snippet--${type}`]: type,
[`${prefix}--snippet--disabled`]: type !== "inline" && disabled,
[`${prefix}--snippet--expand`]: expandedCode,
[`${prefix}--snippet--light`]: light,
[`${prefix}--snippet--no-copy`]: hideCopyButton,
[`${prefix}--snippet--wraptext`]: wrapText
});
const expandCodeBtnText = expandedCode ? showLessText : showMoreText;
if (type === "inline") {
if (hideCopyButton) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: codeSnippetClasses,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
id: uid,
ref: innerCodeRef,
children
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$1.default, {
...rest,
align,
autoAlign,
onClick: handleCopyClick,
"aria-label": deprecatedAriaLabel || ariaLabel,
"aria-describedby": uid,
className: codeSnippetClasses,
disabled,
feedback,
feedbackTimeout,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
id: uid,
ref: innerCodeRef,
children
})
});
}
const containerStyle = {};
if (type === "multi") {
const styles = {};
if (expandedCode) {
if (maxExpandedNumberOfRows > 0) styles.maxHeight = maxExpandedNumberOfRows * rowHeightInPixels;
if (minExpandedNumberOfRows > 0) styles.minHeight = minExpandedNumberOfRows * rowHeightInPixels;
} else {
if (maxCollapsedNumberOfRows > 0) styles.maxHeight = maxCollapsedNumberOfRows * rowHeightInPixels;
if (minCollapsedNumberOfRows > 0) styles.minHeight = minCollapsedNumberOfRows * rowHeightInPixels;
}
if (Object.keys(styles).length) containerStyle.style = styles;
}
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
...rest,
className: codeSnippetClasses,
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
ref: codeContainerRef,
role: type === "single" || type === "multi" ? "textbox" : void 0,
tabIndex: (type === "single" || type === "multi") && !disabled ? 0 : void 0,
className: `${prefix}--snippet-container`,
"aria-label": deprecatedAriaLabel || ariaLabel || "code-snippet",
"aria-readonly": type === "single" || type === "multi" ? true : void 0,
"aria-multiline": type === "multi" ? true : void 0,
...containerStyle,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
ref: codeContentRef,
...containerStyle,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
ref: innerCodeRef,
children
})
})
}),
!hideCopyButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$2.default, {
align,
autoAlign,
size: type === "multi" ? "sm" : "md",
disabled,
onClick: handleCopyClick,
feedback,
feedbackTimeout,
iconDescription: copyButtonDescription
}),
shouldShowMoreLessBtn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_index.default, {
kind: "ghost",
size: "sm",
className: `${prefix}--snippet-btn--expand`,
disabled,
onClick: () => setExpandedCode(!expandedCode),
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: `${prefix}--snippet-btn--text`,
children: expandCodeBtnText
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_carbon_icons_react.ChevronDown, {
className: `${prefix}--icon-chevron--down ${prefix}--snippet__icon`,
name: "chevron--down",
role: "img"
})]
})
]
});
}
CodeSnippet.propTypes = {
align: require_deprecateValuesWithin.deprecateValuesWithin(prop_types.default.oneOf([
"top",
"top-left",
"top-right",
"bottom",
"bottom-left",
"bottom-right",
"left",
"left-bottom",
"left-top",
"right",
"right-bottom",
"right-top",
"top-start",
"top-end",
"bottom-start",
"bottom-end",
"left-end",
"left-start",
"right-end",
"right-start"
]), [
"top",
"top-start",
"top-end",
"bottom",
"bottom-start",
"bottom-end",
"left",
"left-start",
"left-end",
"right",
"right-start",
"right-end"
], require_mapPopoverAlign.mapPopoverAlign),
["aria-label"]: prop_types.default.string,
ariaLabel: require_deprecate.deprecate(prop_types.default.string, "This prop syntax has been deprecated. Please use the new `aria-label`."),
autoAlign: prop_types.default.bool,
children: prop_types.default.node,
className: prop_types.default.string,
copyButtonDescription: prop_types.default.string,
copyText: prop_types.default.string,
disabled: prop_types.default.bool,
feedback: prop_types.default.string,
feedbackTimeout: prop_types.default.number,
hideCopyButton: prop_types.default.bool,
light: require_deprecate.deprecate(prop_types.default.bool, "The `light` prop for `CodeSnippet` has been deprecated in favor of the new `Layer` component. It will be removed in the next major release."),
maxCollapsedNumberOfRows: prop_types.default.number,
maxExpandedNumberOfRows: prop_types.default.number,
minCollapsedNumberOfRows: prop_types.default.number,
minExpandedNumberOfRows: prop_types.default.number,
onClick: prop_types.default.func,
showLessText: prop_types.default.string,
showMoreText: prop_types.default.string,
type: prop_types.default.oneOf([
"single",
"inline",
"multi"
]),
wrapText: prop_types.default.bool
};
//#endregion
exports.default = CodeSnippet;