@carbon/ibm-products
Version:
Carbon for IBM Products
212 lines (210 loc) • 7.22 kB
JavaScript
/**
* 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_settings = require("../../settings.js");
const require_useIsomorphicEffect = require("../../global/js/hooks/useIsomorphicEffect.js");
const require_devtools = require("../../global/js/utils/devtools.js");
const require_uuidv4 = require("../../global/js/utils/uuidv4.js");
const require_enums = require("./utils/enums.js");
const require_context = require("./utils/context.js");
const require_CoachmarkDragbar = require("./CoachmarkDragbar.js");
const require_CoachmarkHeader = require("./CoachmarkHeader.js");
const require_constants = require("./utils/constants.js");
let react = require("react");
react = require_runtime.__toESM(react);
let prop_types = require("prop-types");
prop_types = require_runtime.__toESM(prop_types);
//#region src/components/Coachmark/CoachmarkOverlay.tsx
/**
* Copyright IBM Corp. 2023, 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}--coachmark-overlay`;
const componentName = "CoachmarkOverlay";
const defaults = {
kind: "floating",
theme: "light"
};
/**
* DO NOT USE. This component is for the exclusive use
* of other Onboarding components.
* @deprecated This component is deprecated.
*/
const CoachmarkOverlay = (0, react.forwardRef)((props, ref) => {
const { children, onClose, fixedIsVisible, className, kind = defaults.kind, theme = defaults.theme, ...rest } = props;
const { winHeight, winWidth } = useWindowDimensions();
const [a11yDragMode, setA11yDragMode] = (0, react.useState)(false);
const overlayRef = (0, react.useRef)(null);
const coachmark = require_context.useCoachmark();
const isBeacon = kind === "tooltip";
const isDraggable = kind === "floating";
const isVisible = className?.includes("is-visible");
const handleKeyPress = (event) => {
const { shiftKey, key } = event;
/* istanbul ignore next */
if (key === "Enter" || key === " ") setA11yDragMode((prevVal) => !prevVal);
else if (a11yDragMode) {
const distanceToMove = shiftKey ? 128 : 32;
switch (key) {
case "ArrowLeft":
handleDrag(distanceToMove * -1, 0);
break;
case "ArrowRight":
handleDrag(distanceToMove, 0);
break;
case "ArrowUp":
handleDrag(0, distanceToMove * -1);
break;
case "ArrowDown":
handleDrag(0, distanceToMove);
break;
default: break;
}
}
};
const styledTune = (0, react.useMemo)(() => {
const style = {};
if (isBeacon || isDraggable) {
if (coachmark?.targetRect) {
style.left = coachmark.targetRect.x + window.scrollX;
style.top = coachmark.targetRect.y + window.scrollY;
}
if (style.left && style.top) {
if (isBeacon) {
style.left = style.left + 16;
style.top = style.top + 16;
}
if (isDraggable) {
const offsetTune = require_constants.getOffsetTune(coachmark, kind);
style.left = style.left + offsetTune.left;
style.top = style.top + offsetTune.top;
}
}
}
return style;
}, [
isBeacon,
isDraggable,
coachmark,
kind
]);
/* istanbul ignore next */
function handleDragBounds(x, y) {
let xRes = x;
let yRes = y;
const xMax = winWidth - 288;
const yMax = winHeight - 150;
if (xRes < 0) xRes = 0;
else if (xRes > xMax) xRes = xMax;
if (yRes < 0) yRes = 0;
else if (yRes > yMax) yRes = yMax;
return {
targetX: xRes,
targetY: yRes
};
}
function handleDrag(movementX, movementY) {
const overlay = overlayRef.current;
if (!overlay) return;
const { x, y } = overlay.getBoundingClientRect();
const { targetX, targetY } = handleDragBounds(x + movementX, y + movementY);
overlay.style.transform = "none";
overlay.style.position = "fixed";
overlay.style.left = `${targetX}px`;
overlay.style.top = `${targetY}px`;
overlay.style.bottom = "auto";
}
const contentId = require_uuidv4.default();
require_useIsomorphicEffect.useIsomorphicEffect(() => {
if (overlayRef.current) {
const currentStyle = overlayRef.current?.style;
Object.keys(styledTune).forEach((key) => {
const value = styledTune[key];
currentStyle.setProperty(key, `${value}px`);
});
}
}, [styledTune, overlayRef]);
return /* @__PURE__ */ react.default.createElement("div", {
...rest,
className: (0, import_classnames.default)(blockClass, `${blockClass}--${kind}`, `${blockClass}__${theme}`, (isBeacon || isDraggable) && coachmark?.align && `${blockClass}--${coachmark.align}`, fixedIsVisible && `${blockClass}--is-visible`, a11yDragMode && `${blockClass}--is-dragmode`, className),
ref: overlayRef,
"aria-labelledby": contentId,
tabIndex: -1,
...require_devtools.getDevtoolsProps(componentName)
}, isDraggable ? /* @__PURE__ */ react.default.createElement(require_CoachmarkDragbar.CoachmarkDragbar, {
a11yKeyboardHandler: handleKeyPress,
onBlur: () => setA11yDragMode(false),
onDrag: handleDrag,
theme,
onClose
}) : /* @__PURE__ */ react.default.createElement(require_CoachmarkHeader.CoachmarkHeader, { onClose }), /* @__PURE__ */ react.default.createElement("div", {
className: `${blockClass}__body`,
ref,
id: contentId
}, react.default.Children.map(children, (child) => {
return react.default.cloneElement(child, { isVisible });
})));
});
function getWindowDimensions() {
const { innerWidth: winWidth, innerHeight: winHeight } = window;
return {
winWidth,
winHeight
};
}
const useWindowDimensions = () => {
const [windowDimensions, setWindowDimensions] = (0, react.useState)(getWindowDimensions());
(0, react.useEffect)(() => {
/* istanbul ignore next */
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowDimensions;
};
/**@ts-ignore*/
CoachmarkOverlay.deprecated = {
level: "warn",
details: `${componentName} is deprecated.`
};
CoachmarkOverlay.displayName = componentName;
CoachmarkOverlay.propTypes = {
/**
* The CoachmarkOverlayElements child components.
* Validation is handled in the parent Coachmark component.
*/
children: prop_types.default.node.isRequired,
/**
* Optional class name for this component.
*/
className: prop_types.default.string,
/**
* The visibility of CoachmarkOverlay is
* managed in the parent Coachmark component.
*/
fixedIsVisible: prop_types.default.bool.isRequired,
/**
* What kind or style of Coachmark to render.
*/
kind: prop_types.default.oneOf(Object.values(require_enums.COACHMARK_OVERLAY_KIND)),
/**
* Function to call when the Coachmark closes.
*/
onClose: prop_types.default.func.isRequired,
/**
* Determines the theme of the component.
*/
theme: prop_types.default.oneOf(["light", "dark"])
};
//#endregion
exports.CoachmarkOverlay = CoachmarkOverlay;