UNPKG

@carbon/react

Version:

React components for the Carbon Design System

110 lines (104 loc) 3.84 kB
/** * 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. */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var cx = require('classnames'); var PropTypes = require('prop-types'); var React = require('react'); var usePrefix = require('../../internal/usePrefix.js'); var keys = require('../../internal/keyboard/keys.js'); var match = require('../../internal/keyboard/match.js'); var useEvent = require('../../internal/useEvent.js'); var useMergedRefs = require('../../internal/useMergedRefs.js'); var Switcher = require('./Switcher.js'); var noopFn = require('../../internal/noopFn.js'); const HeaderPanel = /*#__PURE__*/React.forwardRef(({ children, className: customClassName, expanded, addFocusListeners = true, onHeaderPanelFocus = noopFn.noopFn, href, ...rest }, ref) => { const prefix = usePrefix.usePrefix(); const headerPanelReference = React.useRef(null); const headerPanelRef = useMergedRefs.useMergedRefs([headerPanelReference, ref]); const controlled = React.useRef(expanded !== undefined).current; const [expandedState, setExpandedState] = React.useState(expanded); const expandedProp = controlled ? expanded : expandedState; const [lastClickedElement, setLastClickedElement] = React.useState(null); const className = cx(`${prefix}--header-panel`, { [`${prefix}--header-panel--expanded`]: expandedProp, [customClassName]: !!customClassName }); const eventHandlers = {}; if (addFocusListeners) { eventHandlers.onBlur = event => { if (!event.currentTarget.contains(event.relatedTarget) && !lastClickedElement?.classList?.contains(`${prefix}--switcher__item-link`)) { setExpandedState(false); setLastClickedElement(null); if (expanded) { onHeaderPanelFocus(); } } }; eventHandlers.onKeyDown = event => { if (match.match(event, keys.Escape)) { setExpandedState(false); onHeaderPanelFocus(); if (href) { window.location.href = href; } } }; } useEvent.useWindowEvent('click', event => { const target = event.target; if (!(target instanceof HTMLElement)) return; setLastClickedElement(target); const isChildASwitcher = /*#__PURE__*/React.isValidElement(children) && typeof children.type !== 'string' && children.type === Switcher.default; if (isChildASwitcher && !target.closest(`.${prefix}--header-panel--expanded`) && !target.closest(`.${prefix}--header__action`) && !headerPanelReference?.current?.classList.contains(`${prefix}--switcher`) && expanded) { setExpandedState(false); onHeaderPanelFocus(); } }); return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({}, rest, { className: className, ref: headerPanelRef }, eventHandlers), children); }); HeaderPanel.propTypes = { /** * Specify whether focus and blur listeners are added. They are by default. */ addFocusListeners: PropTypes.bool, /** * The content that will render inside of the `HeaderPanel` */ children: PropTypes.node, /** * Optionally provide a custom class to apply to the underlying `<li>` node */ className: PropTypes.string, /** * Specify whether the panel is expanded */ expanded: PropTypes.bool, /** * Provide the `href` to the id of the element on your package that could * be target. */ href: PropTypes.string, /** * An optional listener that is called a callback to collapse the HeaderPanel */ onHeaderPanelFocus: PropTypes.func }; HeaderPanel.displayName = 'HeaderPanel'; exports.default = HeaderPanel;