UNPKG

@carbon/ibm-products

Version:
695 lines (693 loc) 28 kB
/** * 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_pconsole = require("../../global/js/utils/pconsole.js"); const require_settings = require("../../settings.js"); const require_usePreviousValue = require("../../global/js/hooks/usePreviousValue.js"); const require_useFocus = require("../../global/js/hooks/useFocus.js"); const require_usePresence = require("../../global/js/hooks/usePresence.js"); const require_usePrefersReducedMotion = require("../../global/js/hooks/usePrefersReducedMotion.js"); const require_devtools = require("../../global/js/utils/devtools.js"); const require_props_helper = require("../../global/js/utils/props-helper.js"); const require_index$1 = require("../FeatureFlags/index.js"); const require_ActionSet = require("../ActionSet/ActionSet.js"); const require_constants = require("./constants.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"); let _carbon_react_icons = require("@carbon/react/icons"); let _carbon_labs_react_resizer = require("@carbon-labs/react-resizer"); let _carbon_motion = require("@carbon/motion"); //#region src/components/SidePanel/SidePanel.tsx /** * 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. */ var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default); const blockClass = `${require_settings.pkg.prefix}--side-panel`; const componentName = "SidePanel"; const defaults = { animateTitle: true, closeIconDescription: "Close", closeIconTooltipAlignment: "left", currentStep: 0, hideCloseButton: false, navigationBackIconDescription: "Back", placement: "right", size: "md" }; /** * Side panels keep users in-context of a page while performing tasks like navigating, editing, viewing details, or configuring something new. */ const SidePanel = react.default.forwardRef((props, ref) => { const { actionToolbarButtons, actions, aiLabel, animateTitle = defaults.animateTitle, children, className, closeIconDescription = defaults.closeIconDescription, closeIconTooltipAlignment = defaults.closeIconTooltipAlignment, condensedActions, currentStep = defaults.currentStep, decorator, hideCloseButton = defaults.hideCloseButton, id = blockClass, includeOverlay, labelText, navigationBackIconDescription = defaults.navigationBackIconDescription, onNavigationBack, onRequestClose, onUnmount, open, placement = defaults.placement, preventCloseOnClickOutside, selectorPageContent, selectorPrimaryFocus, size = defaults.size, slideIn, slug, subtitle, title, launcherButtonRef, ...rest } = props; const [animationComplete, setAnimationComplete] = (0, react.useState)(false); const localRef = (0, react.useRef)(null); const sidePanelRef = ref || localRef; const overlayRef = (0, react.useRef)(null); const innerContentRef = (0, react.useRef)(null); const closeRef = (0, react.useRef)(null); const animatedScrollRef = (0, react.useRef)(null); const headerRef = (0, react.useRef)(null); const titleRef = (0, react.useRef)(null); const labelTextRef = (0, react.useRef)(null); const subtitleRef = (0, react.useRef)(null); const previousState = require_usePreviousValue.usePreviousValue({ size, open, currentStep }); const [scrollAnimationDistance, setScrollAnimationDistance] = (0, react.useState)(-1); const [doAnimateTitle, setDoAnimateTitle] = (0, react.useState)(true); const { firstElement, keyDownListener } = require_useFocus.useFocus(sidePanelRef); const panelRefValue = sidePanelRef.current; const previousOpen = require_usePreviousValue.usePreviousValue(open); const enableResizer = require_index$1.useFeatureFlag("enableSidepanelResizer"); const sidePanelWidth = (0, react.useRef)(void 0); const accumulatedDeltaRef = (0, react.useRef)(0); const shouldReduceMotion = require_usePrefersReducedMotion.usePrefersReducedMotion(); const { shouldRender } = require_usePresence.usePresence(open, sidePanelRef, shouldReduceMotion ? "side-panel-exit-reduced" : placement === "right" ? "side-panel-exit-right" : "side-panel-exit-left"); const [labelTextHeight, setLabelTextHeight] = (0, react.useState)(0); const handleEscapeKey = (0, react.useCallback)((event) => { if (event.key === "Escape" && open) onRequestClose?.(); }, [onRequestClose, open]); (0, react.useEffect)(() => { if (open && !slideIn) { window.addEventListener("keydown", handleEscapeKey); return () => { window.removeEventListener("keydown", handleEscapeKey); }; } }, [ handleEscapeKey, open, slideIn ]); (0, react.useEffect)(() => { if (!enableResizer) return; const parentEl = sidePanelRef.current?.parentElement; if (parentEl) parentEl.style.removeProperty("--c4p-side-panel-modified-size"); }, [ size, enableResizer, sidePanelRef ]); (0, react.useEffect)(() => { if (!enableResizer) return; sidePanelWidth.current = sidePanelRef?.current?.clientWidth; }, [ sidePanelRef, sidePanelRef?.current?.clientWidth, enableResizer ]); (0, react.useEffect)(() => { if (open && !titleRef?.current) setDoAnimateTitle(false); else setDoAnimateTitle(animateTitle); }, [animateTitle, open]); const onResize = (0, react.useCallback)((event, delta) => { event.preventDefault(); event.stopPropagation(); const setWidth = (width) => { const parentEl = sidePanelRef.current?.parentElement; if (parentEl) parentEl.style.setProperty("--c4p-side-panel-modified-size", typeof width === "number" ? `${width}px` : width); }; if (event.type === "keydown") { switch (event.key) { case "Home": setWidth("75vw"); break; case "End": setWidth(require_constants.SIDE_PANEL_SIZES["xs"]); break; case "ArrowLeft": case "ArrowRight": accumulatedDeltaRef.current += delta; setWidth((sidePanelWidth.current ?? 0) - (placement === "right" ? accumulatedDeltaRef.current : -accumulatedDeltaRef.current)); break; } return; } if (sidePanelRef.current?.style) sidePanelRef.current.style.transition = "none"; setWidth((sidePanelWidth.current ?? 0) - (placement === "right" ? delta : -delta)); }, [ placement, sidePanelRef, sidePanelWidth ]); const getPanelWidthPercent = (0, react.useCallback)((customWidth) => { if (customWidth) { const remInPixels = parseFloat(customWidth) * parseFloat(getComputedStyle(document.documentElement).fontSize); return Math.round(remInPixels / window.innerWidth * 100); } return Math.round((sidePanelRef.current?.clientWidth || 0) / window.innerWidth * 100); }, [sidePanelRef]); const onResizeEnd = (0, react.useCallback)((_, ref) => { accumulatedDeltaRef.current = 0; sidePanelRef.current?.style?.removeProperty("transition"); ref.current.setAttribute("aria-label", `side panel is covering ${getPanelWidthPercent()}% of screen`); ref.current.setAttribute("aria-valuenow", getPanelWidthPercent()); sidePanelWidth.current = sidePanelRef.current?.clientWidth; }, [sidePanelRef, getPanelWidthPercent]); const onDoubleClick = (0, react.useCallback)(() => { sidePanelWidth.current = Math.min(parseFloat(require_constants.SIDE_PANEL_SIZES[size]) * 16, window.innerWidth * .75); const parentEl = sidePanelRef.current?.parentElement; if (parentEl) parentEl.style.removeProperty("--c4p-side-panel-modified-size"); }, [sidePanelRef, size]); const titleItemsStyles = (0, react.useCallback)((progress) => { if (subtitleRef?.current) { const subtitleEl = subtitleRef?.current; const calculatedMargin = subtitleEl?.clientHeight * progress; subtitleEl?.style?.setProperty("margin-top", `${-calculatedMargin}px`); } if (labelTextRef?.current) { const calculatedMargin = labelTextHeight * progress; labelTextRef?.current?.style?.setProperty("margin-top", `${-calculatedMargin}px`); } }, [labelTextHeight]); (0, react.useEffect)(() => { if (open && animateTitle && labelTextRef?.current) setLabelTextHeight(Number(labelTextRef?.current?.clientHeight || null)); }, [ animateTitle, labelTextRef, open ]); const handleScroll = (0, react.useCallback)(() => { if (doAnimateTitle && innerContentRef?.current) { const scrollTop = innerContentRef?.current?.scrollTop; const animationProgress = Math.min(Number(scrollTop), scrollAnimationDistance) / scrollAnimationDistance; panelRefValue?.style.setProperty(`--${blockClass}--scroll-animation-progress`, animationProgress.toString()); titleItemsStyles(animationProgress); } }, [ doAnimateTitle, panelRefValue?.style, scrollAnimationDistance, titleItemsStyles ]); (0, react.useEffect)(() => { if (sidePanelRef && panelRefValue) { const scrollableSection = animatedScrollRef.current ?? innerContentRef.current; if (previousState && previousState["currentStep"] !== currentStep && scrollableSection) scrollableSection.scrollTop = 0; if (previousState && previousState["size"] !== size && scrollableSection) scrollableSection.scrollTop = 0; } }, [ currentStep, sidePanelRef, size, previousState, id, panelRefValue ]); (0, react.useEffect)(() => { if (!title && labelText) console.warn(`${componentName}: The prop \`labelText\` was provided without a \`title\`. It is required to have a \`title\` when using the \`labelText\` prop.`); }, [labelText, title]); (0, react.useEffect)(() => { if (previousOpen && !open && launcherButtonRef) setTimeout(() => { launcherButtonRef?.current?.focus(); }, 0); }, [ launcherButtonRef, open, previousOpen ]); const checkSetDoAnimateTitle = () => { let canDoAnimateTitle = false; if (panelRefValue && open && animateTitle && animationComplete && titleRef?.current && title && title.length && !shouldReduceMotion) { const titleEl = titleRef.current; const labelHeight = labelTextRef?.current?.offsetHeight ?? 0; const subtitleHeight = subtitleRef?.current?.offsetHeight ?? 0; const titleVerticalBorder = actionToolbarButtons ? titleEl.offsetHeight - titleEl.clientHeight : 0; const scrollAnimationDistance = labelHeight + subtitleHeight + titleVerticalBorder; setScrollAnimationDistance(scrollAnimationDistance); panelRefValue?.style.setProperty(`--${blockClass}--scroll-animation-distance`, scrollAnimationDistance.toString()); const scrollEl = innerContentRef.current; if (scrollEl) { const innerComputed = window?.getComputedStyle(innerContentRef.current); const innerPaddingHeight = innerComputed ? parseFloat(innerComputed?.paddingTop) + parseFloat(innerComputed?.paddingBottom) : 0; canDoAnimateTitle = (!!labelText || !!actionToolbarButtons || !!subtitle) && scrollEl.scrollHeight - scrollEl.clientHeight >= scrollAnimationDistance + innerPaddingHeight; } } if (doAnimateTitle !== canDoAnimateTitle) setDoAnimateTitle(canDoAnimateTitle); }; (0, react.useEffect)(() => { if (!doAnimateTitle && sidePanelRef.current) panelRefValue?.style.setProperty(`--${blockClass}--scroll-animation-progress`, "0"); }, [ doAnimateTitle, handleScroll, sidePanelRef, innerContentRef, open, panelRefValue?.style ]); (0, react.useEffect)(() => { if (panelRefValue && open && animateTitle && animationComplete && titleRef?.current && title && title.length && !shouldReduceMotion) checkSetDoAnimateTitle(); }, [ open, doAnimateTitle, animationComplete, handleScroll, title, size, shouldReduceMotion, id ]); (0, react.useEffect)(() => { const handleOutsideClick = (event) => { if (panelRefValue && overlayRef.current && overlayRef.current.contains(event.target) && onRequestClose) onRequestClose(); }; const bodyElement = document.body; if (includeOverlay && open) bodyElement.style.overflow = "hidden"; else if (includeOverlay && !open) bodyElement.style.overflow = ""; if (includeOverlay && !preventCloseOnClickOutside) document.addEventListener("click", handleOutsideClick); return () => { const bodyElement = document.body; bodyElement.style.overflow = ""; document.removeEventListener("click", handleOutsideClick); }; }, [ includeOverlay, onRequestClose, open, preventCloseOnClickOutside, onUnmount, sidePanelRef, panelRefValue ]); const onAnimationEnd = () => { if (!open) onUnmount?.(); setAnimationComplete(!animationComplete); }; (0, react.useEffect)(() => { if (shouldReduceMotion) setAnimationComplete(true); }, [shouldReduceMotion]); const onAnimationStart = () => { setAnimationComplete(false); }; (0, react.useEffect)(() => { if (!open && slideIn) { const pageContentElement = selectorPageContent ? document.querySelector(selectorPageContent) : null; if (placement && placement === "right" && pageContentElement) pageContentElement.style.marginInlineEnd = "0"; else if (pageContentElement) pageContentElement.style.marginInlineStart = "0"; } }, [ open, placement, selectorPageContent, slideIn ]); (0, react.useEffect)(() => { if (!open && previousState && previousState["open"] && shouldReduceMotion) onUnmount?.(); }, [ open, onUnmount, shouldReduceMotion, previousState ]); (0, react.useEffect)(() => { if (open && slideIn) { const pageContentElement = selectorPageContent ? document.querySelector(selectorPageContent) : null; if (pageContentElement) pageContentElement.style.inlineSize = "auto"; else require_pconsole.default.warn("SidePanel prop `selectorPageContent` was not provided a selector that matches any element on your page. If an element is not found, the panel will render as a slide over."); if (placement && placement === "right" && pageContentElement) { pageContentElement.style.marginInlineEnd = "0"; pageContentElement.style.transition = !shouldReduceMotion ? `margin-inline-end ${_carbon_motion.moderate02}` : ""; pageContentElement.style.marginInlineEnd = require_constants.SIDE_PANEL_SIZES[size]; } else if (pageContentElement) { pageContentElement.style.marginInlineStart = "0"; pageContentElement.style.transition = !shouldReduceMotion ? `margin-inline-start ${_carbon_motion.moderate02}` : ""; pageContentElement.style.marginInlineStart = require_constants.SIDE_PANEL_SIZES[size]; } } }, [ slideIn, selectorPageContent, placement, size, shouldReduceMotion, open ]); (0, react.useEffect)(() => { if (open && animationComplete) { if (selectorPrimaryFocus && require_useFocus.getSpecificElement(sidePanelRef?.current, selectorPrimaryFocus)) { const primeFocusEl = require_useFocus.getSpecificElement(sidePanelRef?.current, selectorPrimaryFocus); if (primeFocusEl && window?.getComputedStyle(primeFocusEl)?.display !== "none") setTimeout(() => primeFocusEl?.focus(), 0); } else if (!slideIn) setTimeout(() => firstElement?.focus(), 0); } }, [ animationComplete, firstElement, open, selectorPrimaryFocus, sidePanelRef, slideIn ]); const primaryActionContainerClassNames = (0, import_classnames.default)([`${blockClass}__actions-container`, { [`${blockClass}__actions-container--condensed`]: condensedActions }]); const mainPanelClassNames = (0, import_classnames.default)([ blockClass, className, `${blockClass}`, `${blockClass}--${size}`, { [`${blockClass}--right-placement`]: placement === "right", [`${blockClass}--left-placement`]: placement === "left", [`${blockClass}--slide-in`]: slideIn, [`${blockClass}--enable-sidepanel-resizer`]: enableResizer && window.innerWidth > 768, [`${blockClass}--has-decorator`]: decorator, [`${blockClass}--has-slug`]: slug, [`${blockClass}--has-ai-label`]: aiLabel, [`${blockClass}--condensed-actions`]: condensedActions, [`${blockClass}--has-overlay`]: includeOverlay, [`${blockClass}--open`]: open, [`${blockClass}--closing`]: !open, [`${blockClass}--reduced-motion`]: shouldReduceMotion } ]); const renderTitle = () => /* @__PURE__ */ react.default.createElement("div", { className: (0, import_classnames.default)(`${blockClass}__title`, { [`${blockClass}__title--no-label`]: !labelTextRef.current }), ref: titleRef }, /* @__PURE__ */ react.default.createElement(_carbon_react.Heading, { className: `${blockClass}__title-text`, "aria-hidden": false }, title), doAnimateTitle && !shouldReduceMotion && /* @__PURE__ */ react.default.createElement(_carbon_react.Heading, { className: `${blockClass}__collapsed-title-text`, "aria-hidden": true }, title)); const renderHeader = () => { const closeSize = actions && actions.length && /l/.test(size) ? "md" : "sm"; let normalizedDecorator; /** * slug is deprecated * can remove this condition in future release */ if (slug && slug["type"]?.displayName === "AILabel") normalizedDecorator = react.default.cloneElement(slug, { size: "xs" }); if (aiLabel && aiLabel["type"]?.displayName === "AILabel") normalizedDecorator = react.default.cloneElement(aiLabel, { size: "xs" }); if (decorator?.["type"]?.displayName === "AILabel") normalizedDecorator = react.default.cloneElement(decorator, { size: "xs" }); return /* @__PURE__ */ react.default.createElement("div", { className: (0, import_classnames.default)(`${blockClass}__header`, { [`${blockClass}__header--on-detail-step`]: currentStep > 0, [`${blockClass}__header--no-title-animation`]: !animateTitle, [`${blockClass}__header--reduced-motion`]: shouldReduceMotion, [`${blockClass}__header--has-title`]: title }), ref: headerRef }, currentStep > 0 && /* @__PURE__ */ react.default.createElement(_carbon_react.IconButton, { kind: "ghost", size: closeSize, align: "bottom", label: navigationBackIconDescription, className: `${blockClass}__navigation-back-button`, onClick: onNavigationBack }, /* @__PURE__ */ react.default.createElement(_carbon_react_icons.ArrowLeft, null)), title && title.length && labelText && labelText.length && /* @__PURE__ */ react.default.createElement("p", { className: `${blockClass}__label-text`, ref: labelTextRef }, labelText), title && title.length && renderTitle(), (normalizedDecorator || !hideCloseButton) && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__decorator-and-close` }, normalizedDecorator, !hideCloseButton && /* @__PURE__ */ react.default.createElement(_carbon_react.IconButton, { className: `${blockClass}__close-button`, label: closeIconDescription, onClick: onRequestClose, onKeyDown: slideIn ? void 0 : handleEscapeKey, ref: closeRef, align: closeIconTooltipAlignment }, /* @__PURE__ */ react.default.createElement(_carbon_react_icons.Close, { size: 16, "aria-hidden": "true", tabIndex: "-1", className: `${blockClass}--btn__icon` }))), subtitle && /* @__PURE__ */ react.default.createElement("p", { className: (0, import_classnames.default)(`${blockClass}__subtitle-text`, { [`${blockClass}__subtitle-text-no-animation-no-action-toolbar`]: !doAnimateTitle && (!actionToolbarButtons || !actionToolbarButtons.length) }), ref: subtitleRef }, subtitle), actionToolbarButtons && actionToolbarButtons.length && /* @__PURE__ */ react.default.createElement("div", { className: `${blockClass}__action-toolbar` }, actionToolbarButtons.map(({ label, kind, hasIconOnly = false, icon, renderIcon, tooltipPosition, tooltipAlignment, leading, disabled, className, onClick, ...rest }) => /* @__PURE__ */ react.default.createElement(_carbon_react.Button, { ...rest, key: label, kind: kind || "ghost", size: "sm", renderIcon: renderIcon || icon, iconDescription: label, ...hasIconOnly && { tooltipPosition: tooltipPosition || "bottom", tooltipAlignment: tooltipAlignment || "start" }, hasIconOnly, disabled, className: (0, import_classnames.default)([ `${blockClass}__action-toolbar-button`, className, { [`${blockClass}__action-toolbar-leading-button`]: leading } ]), onClick }, leading && label)))); }; const renderMain = () => { return /* @__PURE__ */ react.default.createElement("div", { ref: innerContentRef, onScroll: handleScroll, className: (0, import_classnames.default)(`${blockClass}__inner-content`, `${blockClass}--scrolls`, `${!doAnimateTitle && !animateTitle ? `${blockClass}__inner-content--no-animated-title` : ""}`) }, /* @__PURE__ */ react.default.createElement(_carbon_react.Layer, null, children)); }; const handleKeyDown = (event) => { if (!slideIn) { handleEscapeKey(event); keyDownListener(event); } }; return shouldRender ? /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement(_carbon_react.Section, { ...require_devtools.getDevtoolsProps(componentName), ...rest, id, className: mainPanelClassNames, ref: sidePanelRef, as: "aside", "aria-label": title || rest["aria-label"], onAnimationEnd, onAnimationStart, onKeyDown: handleKeyDown }, !slideIn && enableResizer && window.innerWidth > 768 && /* @__PURE__ */ react.default.createElement(_carbon_labs_react_resizer.Resizer, { className: `${blockClass}__resizer`, orientation: "vertical", "aria-valuemin": getPanelWidthPercent(require_constants.SIDE_PANEL_SIZES["xs"]), "aria-valuemax": 75, "aria-valuenow": getPanelWidthPercent(), onResize, onResizeEnd, onDoubleClick }), renderHeader(), renderMain(), /* @__PURE__ */ react.default.createElement(require_ActionSet.ActionSet, { actions: actions ?? [], className: primaryActionContainerClassNames, size: size === "xs" ? "sm" : size })), includeOverlay && /* @__PURE__ */ react.default.createElement("div", { ref: overlayRef, className: (0, import_classnames.default)(`${blockClass}__overlay`, { [`${blockClass}__overlay--closing`]: !open }) })) : null; }); const deprecatedProps = { /** * **deprecated** * **Experimental:** Provide a `Slug` component to be rendered inside the `SidePanel` component */ slug: prop_types.default.node, /** * **deprecated** * Please use the `decorator` instead * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. */ aiLabel: prop_types.default.node }; SidePanel.propTypes = { /** * Sets the action toolbar buttons */ /**@ts-ignore */ actionToolbarButtons: prop_types.default.arrayOf(prop_types.default.shape({ label: prop_types.default.string, leading: prop_types.default.bool, icon: prop_types.default.oneOfType([prop_types.default.object, prop_types.default.func]), onClick: prop_types.default.func, kind: prop_types.default.oneOf([ "ghost", "tertiary", "secondary", "primary" ]), tooltipAlignment: prop_types.default.oneOf([ "top", "right", "bottom", "left" ]), tooltipPosition: prop_types.default.oneOf([ "start", "center", "end" ]) })), /** * The primary actions to be shown in the side panel. Each action is * specified as an object with optional fields: 'label' to supply the button * label, 'kind' to select the button kind (must be 'primary', 'secondary' or * 'ghost'), 'tooltipPosition' to select where the tooltip is placed around * the button (must be 'top', 'right', 'bottom', or 'left'), 'tooltipAlignment' * to select how the tooltip is aligned with the button (must be 'start', * 'center', or 'end', 'loading' to display a loading indicator, and 'onClick' to * receive notifications when the button is clicked. Additional fields in the * object will be passed to the Button component, and these can include * 'disabled', 'ref', 'className', and any other Button props. Any other * fields in the object will be passed through to the button element as HTML * attributes. * * See https://react.carbondesignsystem.com/?path=/docs/components-button--default#component-api */ actions: require_props_helper.allPropTypes([prop_types.default.arrayOf(prop_types.default.shape({ ..._carbon_react.Button.propTypes, kind: prop_types.default.oneOf([ "ghost", "danger--ghost", "secondary", "danger", "primary" ]), tooltipPosition: prop_types.default.oneOf([ "top", "right", "bottom", "left" ]), tooltipAlignment: prop_types.default.oneOf([ "start", "center", "end" ]), label: prop_types.default.string, loading: prop_types.default.bool, /**@ts-ignore */ onClick: _carbon_react.Button.propTypes.onClick }))]), /** * Determines if the title will animate on scroll */ animateTitle: prop_types.default.bool, /** * Sets the body content of the side panel */ children: prop_types.default.oneOfType([prop_types.default.arrayOf(prop_types.default.node), prop_types.default.node]).isRequired, /** * Sets an optional className to be added to the side panel outermost element */ className: prop_types.default.string, /** * Sets the close button icon description */ closeIconDescription: prop_types.default.string, /** * Sets the close button tooltip alignment */ closeIconTooltipAlignment: prop_types.default.string, /** * Determines whether the side panel should render the condensed version (affects action buttons primarily) */ condensedActions: prop_types.default.bool, /** * Sets the current step of the side panel */ currentStep: prop_types.default.number, /** * Show/hide the "X" close button. */ hideCloseButton: prop_types.default.bool, /** * Unique identifier */ id: prop_types.default.string, /** * Determines whether the side panel should render with an overlay */ includeOverlay: prop_types.default.bool, /** * Sets the label text which will display above the title text */ labelText: prop_types.default.string, /** * Provide a ref to return focus to once the modal is closed. */ /**@ts-ignore */ launcherButtonRef: prop_types.default.any, /** * Sets the icon description for the navigation back icon button */ navigationBackIconDescription: prop_types.default.string, /** * Changes the current side panel page to the previous page */ onNavigationBack: prop_types.default.func, /** * Specify a handler for closing the side panel. * This handler closes the modal, e.g. changing `open` prop. */ onRequestClose: prop_types.default.func, /** * Optional function called when the side panel exit animation is complete. * This handler can be used for any state cleanup needed before the panel is removed from the DOM. */ onUnmount: prop_types.default.func, /** * Determines whether the side panel should render or not */ open: prop_types.default.bool.isRequired, /** * Determines if the side panel is on the right or left */ placement: prop_types.default.oneOf(["left", "right"]), /** * Prevent closing on click outside of the panel */ preventCloseOnClickOutside: prop_types.default.bool, /** * This is the selector to the element that contains all of the page content that will shrink if the panel is a slide in. * This prop is required when using the `slideIn` variant of the side panel. */ /**@ts-ignore*/ selectorPageContent: prop_types.default.string, /** * Specify a CSS selector that matches the DOM element that should * be focused when the side panel opens */ /**@ts-ignore*/ selectorPrimaryFocus: prop_types.default.string, /** * Sets the size of the side panel */ /**@ts-ignore*/ size: prop_types.default.oneOf([ "xs", "sm", "md", "lg", "xl", "2xl" ]), /** * Determines if this panel slides in */ /**@ts-ignore*/ slideIn: prop_types.default.bool, /** * Sets the subtitle text */ subtitle: prop_types.default.node, /** * Sets the title text */ /**@ts-ignore*/ title: prop_types.default.string, ...deprecatedProps }; SidePanel.displayName = componentName; //#endregion exports.SidePanel = SidePanel;