@mantine/notifications
Version:
Mantine notifications system
207 lines (206 loc) • 7.91 kB
JavaScript
"use client";
const require_get_auto_close = require("./get-auto-close/get-auto-close.cjs");
let _mantine_hooks = require("@mantine/hooks");
let react = require("react");
let _mantine_core = require("@mantine/core");
let react_jsx_runtime = require("react/jsx-runtime");
//#region packages/@mantine/notifications/src/NotificationContainer.tsx
const SCROLL_DISMISS_RESET_TIMEOUT = 120;
function NotificationContainer({ data, onHide, autoClose, transitionDuration, allowDragDismiss, allowScrollDismiss, paused, onHoverStart, onHoverEnd, ref, style, ...others }) {
const [offset, setOffset] = (0, react.useState)(0);
const [dismissed, setDismissed] = (0, react.useState)(false);
const [dismissDirection, setDismissDirection] = (0, react.useState)(1);
const [scrollDismissActive, setScrollDismissActive] = (0, react.useState)(false);
const theme = (0, _mantine_core.useMantineTheme)();
const { autoClose: _autoClose, message, allowClose, position: _position, style: dataStyle, withCloseButton, onOpen: _onOpen, ...notificationProps } = data;
const autoCloseDuration = require_get_auto_close.getAutoClose(autoClose, data.autoClose);
const autoCloseTimeout = (0, react.useRef)(-1);
const hideTimeout = (0, react.useRef)(-1);
const scrollDismissTimeout = (0, react.useRef)(-1);
const notificationRef = (0, react.useRef)(null);
const hoveredRef = (0, react.useRef)(false);
const offsetRef = (0, react.useRef)(0);
const isCloseDisabled = allowClose === false;
const cancelAutoClose = () => window.clearTimeout(autoCloseTimeout.current);
const cancelHide = () => window.clearTimeout(hideTimeout.current);
const cancelScrollDismissReset = () => window.clearTimeout(scrollDismissTimeout.current);
const setSwipeOffset = (value) => {
offsetRef.current = value;
setOffset(value);
};
const handleHide = () => {
onHide(data.id);
cancelAutoClose();
cancelHide();
cancelScrollDismissReset();
};
const handleAutoClose = () => {
if (dismissed || active || paused || hoveredRef.current || typeof autoCloseDuration !== "number") return;
autoCloseTimeout.current = window.setTimeout(handleHide, autoCloseDuration);
};
const getExitOffset = (direction) => {
return direction * ((notificationRef.current?.offsetWidth ?? 440) + 40);
};
const shouldDismiss = (movement, velocity) => {
const width = notificationRef.current?.offsetWidth ?? 440;
return Math.abs(movement) > width * .35 || velocity > .5;
};
const resetSwipe = () => {
cancelScrollDismissReset();
setScrollDismissActive(false);
setSwipeOffset(0);
};
const dismissNotification = (direction) => {
setDismissDirection(direction);
setDismissed(true);
setScrollDismissActive(false);
setSwipeOffset(getExitOffset(direction));
cancelAutoClose();
cancelHide();
cancelScrollDismissReset();
hideTimeout.current = window.setTimeout(handleHide, transitionDuration);
};
const scheduleScrollDismissReset = () => {
cancelScrollDismissReset();
scrollDismissTimeout.current = window.setTimeout(() => {
setScrollDismissActive(false);
setSwipeOffset(0);
handleAutoClose();
}, SCROLL_DISMISS_RESET_TIMEOUT);
};
const { ref: dragRef, active } = (0, _mantine_hooks.useDrag)((state) => {
if (dismissed) return;
if (state.first) cancelAutoClose();
if (state.last) {
if (state.tap || state.canceled) {
setSwipeOffset(0);
handleAutoClose();
return;
}
const movement = state.movement[0];
const direction = movement === 0 ? state.direction[0] === -1 ? -1 : 1 : movement > 0 ? 1 : -1;
if (shouldDismiss(movement, state.velocity[0])) dismissNotification(direction);
else {
setSwipeOffset(0);
handleAutoClose();
}
} else setSwipeOffset(state.movement[0]);
}, {
axis: "x",
threshold: 5,
filterTaps: true,
enabled: allowDragDismiss && !isCloseDisabled && !dismissed
});
const mergedRef = (0, _mantine_hooks.useMergedRef)(ref, notificationRef, dragRef);
const resolvedStyle = (0, _mantine_core.getStyleObject)(style, theme);
const resolvedDataStyle = (0, _mantine_core.getStyleObject)(dataStyle, theme);
const baseStyle = {
...resolvedStyle,
...resolvedDataStyle
};
const baseOpacity = typeof baseStyle.opacity === "number" ? baseStyle.opacity : 1;
const swipeOpacity = dismissed ? 0 : 1 - Math.min(Math.abs(offset) / 200, 1) * .6;
const resolvedTransitionDuration = baseStyle.transitionDuration ?? `${transitionDuration}ms, ${transitionDuration}ms, ${transitionDuration}ms`;
const notificationStyle = {
...baseStyle,
["--notifications-state-transform"]: typeof baseStyle.transform === "string" ? baseStyle.transform : "translateX(0)",
["--notifications-state-opacity"]: String(baseOpacity),
["--notifications-swipe-offset"]: `${offset}px`,
["--notifications-swipe-opacity"]: String(swipeOpacity),
transform: "var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)",
opacity: "calc(var(--notifications-state-opacity) * var(--notifications-swipe-opacity))",
transitionDuration: active || scrollDismissActive ? "0ms, 0ms, 0ms" : resolvedTransitionDuration,
cursor: "default",
touchAction: "pan-y"
};
const handleMouseEnter = () => {
hoveredRef.current = true;
cancelAutoClose();
onHoverStart?.();
};
const handleMouseLeave = () => {
hoveredRef.current = false;
if (!scrollDismissActive) {
resetSwipe();
handleAutoClose();
}
onHoverEnd?.();
};
const handleWheel = (0, react.useEffectEvent)((event) => {
if (dismissed || active) return;
const isDocumentEvent = event.currentTarget === document;
if (!isDocumentEvent && !hoveredRef.current) return;
const { deltaX, deltaY } = event;
if (Math.abs(deltaX) <= Math.abs(deltaY) || deltaX === 0) return;
if (!allowScrollDismiss || isCloseDisabled) return;
if (!isDocumentEvent) {
event.preventDefault();
event.stopPropagation();
}
cancelAutoClose();
setScrollDismissActive(true);
const nextOffset = offsetRef.current - deltaX;
const direction = nextOffset > 0 ? 1 : -1;
if (shouldDismiss(nextOffset, 0)) {
dismissNotification(direction);
return;
}
setSwipeOffset(nextOffset);
scheduleScrollDismissReset();
});
(0, react.useEffect)(() => {
if (!scrollDismissActive) return;
document.addEventListener("wheel", handleWheel, { passive: false });
return () => document.removeEventListener("wheel", handleWheel, { passive: false });
}, [scrollDismissActive]);
(0, react.useEffect)(() => {
const handleResize = () => {
if (dismissed) setSwipeOffset(getExitOffset(dismissDirection));
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [dismissDirection, dismissed]);
(0, react.useEffect)(() => {
const node = notificationRef.current;
if (!node) return;
node.addEventListener("wheel", handleWheel, { passive: false });
return () => node.removeEventListener("wheel", handleWheel, { passive: false });
}, []);
(0, react.useEffect)(() => {
return () => {
cancelHide();
cancelScrollDismissReset();
};
}, []);
(0, react.useEffect)(() => {
data.onOpen?.(data);
}, []);
(0, react.useEffect)(() => {
handleAutoClose();
return cancelAutoClose;
}, [
autoCloseDuration,
active,
dismissed
]);
(0, react.useEffect)(() => {
if (paused) cancelAutoClose();
else handleAutoClose();
return cancelAutoClose;
}, [paused]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Notification, {
ref: mergedRef,
...others,
style: notificationStyle,
...notificationProps,
withCloseButton: isCloseDisabled ? false : withCloseButton,
onClose: handleHide,
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
children: message
});
}
NotificationContainer.displayName = "@mantine/notifications/NotificationContainer";
//#endregion
exports.NotificationContainer = NotificationContainer;
//# sourceMappingURL=NotificationContainer.cjs.map