UNPKG

@carbon/react

Version:

React components for the Carbon Design System

209 lines (207 loc) 7.22 kB
/** * 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_keys = require("../../internal/keyboard/keys.js"); const require_match = require("../../internal/keyboard/match.js"); const require_useId = require("../../internal/useId.js"); const require_useEvent = require("../../internal/useEvent.js"); const require_index = require("../Popover/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"); //#region src/components/Toggletip/index.tsx /** * 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. */ /** * Used to render the label for a Toggletip */ function ToggletipLabel({ as: BaseComponent = "span", children, className: customClassName, ...rest }) { return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BaseComponent, { className: (0, classnames.default)(`${require_usePrefix.usePrefix()}--toggletip-label`, customClassName), ...rest, children }); } ToggletipLabel.propTypes = { as: prop_types.default.elementType, children: prop_types.default.node, className: prop_types.default.string }; const ToggletipContext = react.default.createContext(void 0); function useToggletip() { return (0, 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 = (0, react.useRef)(null); const [open, setOpen] = (0, react.useState)(defaultOpen); const prefix = require_usePrefix.usePrefix(); const id = require_useId.useId(); const className = (0, classnames.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 : void 0, onClick: actions.toggle }, contentProps: { id }, onClick: { onClick: actions.toggle } }; const onKeyDown = (event) => { if (open && require_match.match(event, require_keys.Escape)) { event.stopPropagation(); actions.close(); const button = ref.current?.children[0]; if (button instanceof HTMLButtonElement) button.focus(); } }; const handleBlur = (event) => { if (open && event.relatedTarget === null) return; if (!event.currentTarget.contains(event.relatedTarget)) actions.close(); }; require_useEvent.useWindowEvent("blur", () => { if (open) actions.close(); }); (0, react.useEffect)(() => { if (!open || !ref.current) return; const targetDocument = ref.current.ownerDocument || document; const eventType = "PointerEvent" in window ? "pointerdown" : "mousedown"; const handleOutsideClick = (event) => { const { current } = ref; if (!current) return; const isInsideCurrent = (target) => target instanceof Node && current.contains(target); if (!(isInsideCurrent(event.target) || typeof event.composedPath === "function" && event.composedPath().some(isInsideCurrent))) setOpen(false); }; const options = { capture: true }; targetDocument.addEventListener(eventType, handleOutsideClick, options); return () => { targetDocument.removeEventListener(eventType, handleOutsideClick, options); }; }, [open]); return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggletipContext.Provider, { value, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index.Popover, { align, as, caret: true, className, dropShadow: false, highContrast: true, open, onKeyDown, onBlur: handleBlur, ref, autoAlign, ...rest, children }) }); } const { open, ...popoverNonOpenPropTypes } = require_index.Popover.propTypes ?? {}; Toggletip.propTypes = { ...popoverNonOpenPropTypes, defaultOpen: prop_types.default.bool }; /** * `ToggletipButton` controls the visibility of the Toggletip through mouse * clicks and keyboard interactions. */ const ToggletipButton = (0, react.forwardRef)(function ToggletipButton({ children, className: customClassName, label = "Show information", as: BaseComponent, ...rest }, ref) { const toggletip = useToggletip(); const className = (0, classnames.default)(`${require_usePrefix.usePrefix()}--toggletip-button`, customClassName); const ComponentToggle = BaseComponent ?? "button"; if (ComponentToggle !== "button") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentToggle, { ...toggletip?.onClick, className, ...rest, children }); return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { ...toggletip?.buttonProps, "aria-label": label, type: "button", className, ref, ...rest, children }); }); ToggletipButton.propTypes = { children: prop_types.default.node, className: prop_types.default.string, label: prop_types.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 = (0, react.forwardRef)((props, ref) => { const { children, className: customClassName } = props; const toggletip = useToggletip(); const prefix = require_usePrefix.usePrefix(); return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index.PopoverContent, { className: customClassName, ...toggletip?.contentProps, ref, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: `${prefix}--toggletip-content`, children }) }); }); ToggletipContent.propTypes = { children: prop_types.default.node, className: prop_types.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 }) { return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0, classnames.default)(`${require_usePrefix.usePrefix()}--toggletip-actions`, customClassName), children }); } ToggletipActions.propTypes = { children: prop_types.default.node, className: prop_types.default.string }; //#endregion exports.ToggletipActions = ToggletipActions; exports.ToggletipButton = ToggletipButton; exports.ToggletipContent = ToggletipContent; exports.ToggletipLabel = ToggletipLabel; exports.default = Toggletip;