UNPKG

@carbon/react

Version:

React components for the Carbon Design System

321 lines (306 loc) 10.3 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 index = require('../Popover/index.js'); var keys = require('../../internal/keyboard/keys.js'); var match = require('../../internal/keyboard/match.js'); var useEvent = require('../../internal/useEvent.js'); var useId = require('../../internal/useId.js'); var usePrefix = require('../../internal/usePrefix.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx); var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); /** * Used to render the label for a Toggletip */ function ToggletipLabel({ as: BaseComponent = 'span', children, className: customClassName, ...rest }) { const prefix = usePrefix.usePrefix(); const className = cx__default["default"](`${prefix}--toggletip-label`, customClassName); const BaseComponentAsAny = BaseComponent; return /*#__PURE__*/React__default["default"].createElement(BaseComponentAsAny, _rollupPluginBabelHelpers["extends"]({ className: className }, rest), children); } ToggletipLabel.propTypes = { /** * Provide a custom element or component to render the top-level node for the * component. */ as: PropTypes__default["default"].elementType, /** * Custom children to be rendered as the content of the label */ children: PropTypes__default["default"].node, /** * Provide a custom class name to be added to the outermost node in the * component */ className: PropTypes__default["default"].string }; // Used to coordinate accessibility props between button and content along with // the actions to open and close the toggletip const ToggletipContext = /*#__PURE__*/React__default["default"].createContext(undefined); function useToggletip() { return React.useContext(ToggletipContext); } /** * Used as a container for the button and content of a toggletip. This component * is responsible for coordinating between interactions with the button and the * visibility of the content */ function Toggletip({ align, as, autoAlign, className: customClassName, children, defaultOpen = false, ...rest }) { const ref = React.useRef(null); const [open, setOpen] = React.useState(defaultOpen); const prefix = usePrefix.usePrefix(); const id = useId.useId(); const className = cx__default["default"](`${prefix}--toggletip`, customClassName, { [`${prefix}--toggletip--open`]: open, [`${prefix}--autoalign`]: autoAlign }); const actions = { toggle: () => { setOpen(!open); }, close: () => { setOpen(false); } }; const value = { buttonProps: { 'aria-expanded': open, 'aria-controls': id, 'aria-describedby': open ? id : undefined, onClick: actions.toggle }, contentProps: { id }, onClick: { onClick: actions.toggle } }; const onKeyDown = event => { if (open && match.match(event, keys.Escape)) { actions.close(); // If the menu is closed while focus is still inside the menu, it should return to the trigger button (#12922) const button = ref.current?.children[0]; if (button instanceof HTMLButtonElement) { button.focus(); } } }; const handleBlur = event => { // Do not close if the menu itself is clicked, should only close on focus out if (open && event.relatedTarget === null) { return; } if (!event.currentTarget.contains(event.relatedTarget)) { // The menu should be closed when focus leaves the `Toggletip` (#12922) actions.close(); } }; // If the `Toggletip` is the last focusable item in the tab order, it should also close when the browser window loses focus (#12922) useEvent.useWindowEvent('blur', () => { if (open) { actions.close(); } }); useEvent.useWindowEvent('click', ({ target }) => { if (open && target instanceof Node && !ref.current?.contains(target)) { actions.close(); } }); return /*#__PURE__*/React__default["default"].createElement(ToggletipContext.Provider, { value: value }, /*#__PURE__*/React__default["default"].createElement(index.Popover, _rollupPluginBabelHelpers["extends"]({ align: align, as: as, caret: true, className: className, dropShadow: false, highContrast: true, open: open, onKeyDown: onKeyDown, onBlur: handleBlur, ref: ref, autoAlign: autoAlign }, rest), children)); } Toggletip.propTypes = { /** * Specify how the toggletip should align with the button */ align: PropTypes__default["default"].oneOf(['top', 'top-left', // deprecated use top-start instead 'top-right', // deprecated use top-end instead 'bottom', 'bottom-left', // deprecated use bottom-start instead 'bottom-right', // deprecated use bottom-end instead 'left', 'left-bottom', // deprecated use left-end instead 'left-top', // deprecated use left-start instead 'right', 'right-bottom', // deprecated use right-end instead 'right-top', // deprecated use right-start instead // new values to match floating-ui 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']), /** * Provide an offset value for alignment axis. */ alignmentAxisOffset: PropTypes__default["default"].number, /** * Provide a custom element or component to render the top-level node for the * component. */ as: PropTypes__default["default"].elementType, /** * Will auto-align the popover on first render if it is not visible. This prop is currently experimental and is subject to future changes. */ autoAlign: PropTypes__default["default"].bool, /** * Custom children to be rendered as the content of the label */ children: PropTypes__default["default"].node, /** * Provide a custom class name to be added to the outermost node in the * component */ className: PropTypes__default["default"].string, /** * Specify if the toggletip should be open by default */ defaultOpen: PropTypes__default["default"].bool }; /** * `ToggletipButton` controls the visibility of the Toggletip through mouse * clicks and keyboard interactions. */ const ToggletipButton = /*#__PURE__*/React__default["default"].forwardRef(function ToggletipButton({ children, className: customClassName, label = 'Show information', as: BaseComponent, ...rest }, ref) { const toggletip = useToggletip(); const prefix = usePrefix.usePrefix(); const className = cx__default["default"](`${prefix}--toggletip-button`, customClassName); const ComponentToggle = BaseComponent ?? 'button'; if (ComponentToggle !== 'button') { return /*#__PURE__*/React__default["default"].createElement(ComponentToggle, _rollupPluginBabelHelpers["extends"]({}, toggletip?.onClick, { className: className }, rest), children); } return /*#__PURE__*/React__default["default"].createElement("button", _rollupPluginBabelHelpers["extends"]({}, toggletip?.buttonProps, { "aria-label": label, type: "button", className: className, ref: ref }, rest), children); }); ToggletipButton.propTypes = { /** * Custom children to be rendered as the content of the label */ children: PropTypes__default["default"].node, /** * Provide a custom class name to be added to the outermost node in the * component */ className: PropTypes__default["default"].string, /** * Provide an accessible label for this button */ label: PropTypes__default["default"].string }; ToggletipButton.displayName = 'ToggletipButton'; /** * `ToggletipContent` is a wrapper around `PopoverContent`. It places the * `children` passed in as a prop inside of `PopoverContent` so that they will * be rendered inside of the popover for this component. */ const ToggletipContent = /*#__PURE__*/React__default["default"].forwardRef(function ToggletipContent({ children, className: customClassName }, ref) { const toggletip = useToggletip(); const prefix = usePrefix.usePrefix(); return /*#__PURE__*/React__default["default"].createElement(index.PopoverContent, _rollupPluginBabelHelpers["extends"]({ className: customClassName }, toggletip?.contentProps, { ref: ref }), /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--toggletip-content` }, children)); }); ToggletipContent.propTypes = { /** * Custom children to be rendered as the content of the label */ children: PropTypes__default["default"].node, /** * Provide a custom class name to be added to the outermost node in the * component */ className: PropTypes__default["default"].string }; ToggletipContent.displayName = 'ToggletipContent'; /** * `ToggletipActions` is a container for one or two actions present at the base * of a toggletip. It is used for layout of these items. */ function ToggletipActions({ children, className: customClassName }) { const prefix = usePrefix.usePrefix(); const className = cx__default["default"](`${prefix}--toggletip-actions`, customClassName); return /*#__PURE__*/React__default["default"].createElement("div", { className: className }, children); } ToggletipActions.propTypes = { /** * Custom children to be rendered as the content of the label */ children: PropTypes__default["default"].node, /** * Provide a custom class name to be added to the outermost node in the * component */ className: PropTypes__default["default"].string }; exports.Toggletip = Toggletip; exports.ToggletipActions = ToggletipActions; exports.ToggletipButton = ToggletipButton; exports.ToggletipContent = ToggletipContent; exports.ToggletipLabel = ToggletipLabel;