@mantine/notifications 9.5.2 → 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/NotificationContainer.cjs +142 -11
- package/cjs/NotificationContainer.cjs.map +1 -1
- package/cjs/Notifications.cjs +208 -41
- package/cjs/Notifications.cjs.map +1 -1
- package/cjs/Notifications.module.cjs.map +1 -1
- package/cjs/notifications.store.cjs.map +1 -1
- package/esm/NotificationContainer.mjs +143 -12
- package/esm/NotificationContainer.mjs.map +1 -1
- package/esm/Notifications.mjs +208 -41
- package/esm/Notifications.mjs.map +1 -1
- package/esm/Notifications.module.mjs.map +1 -1
- package/esm/notifications.store.mjs.map +1 -1
- package/lib/NotificationContainer.d.ts +10 -1
- package/lib/Notifications.d.ts +5 -1
- package/lib/notifications.store.d.ts +5 -0
- package/package.json +6 -6
- package/styles.css +8 -0
- package/styles.layer.css +8 -0
|
@@ -6,21 +6,73 @@ let _mantine_core = require("@mantine/core");
|
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
//#region packages/@mantine/notifications/src/NotificationContainer.tsx
|
|
8
8
|
const SCROLL_DISMISS_RESET_TIMEOUT = 120;
|
|
9
|
-
|
|
9
|
+
const MAX_VISIBLE_STACK_DEPTH = 4;
|
|
10
|
+
/**
|
|
11
|
+
* Props that belong to the default `Notification` rendering or to the Styles API and must
|
|
12
|
+
* not reach the plain `div` used for custom rendering. Everything else is a valid div prop
|
|
13
|
+
* and is forwarded – an allow list would silently drop supported props like `onClick`,
|
|
14
|
+
* `dir`, `lang` or `hidden`.
|
|
15
|
+
*/
|
|
16
|
+
const NON_DOM_PROPS = /* @__PURE__ */ new Set([
|
|
17
|
+
"classNames",
|
|
18
|
+
"styles",
|
|
19
|
+
"unstyled",
|
|
20
|
+
"vars",
|
|
21
|
+
"attributes",
|
|
22
|
+
"variant",
|
|
23
|
+
"color",
|
|
24
|
+
"radius",
|
|
25
|
+
"icon",
|
|
26
|
+
"title",
|
|
27
|
+
"loading",
|
|
28
|
+
"withBorder",
|
|
29
|
+
"withCloseButton",
|
|
30
|
+
"closeButtonProps",
|
|
31
|
+
"className",
|
|
32
|
+
"style",
|
|
33
|
+
"role",
|
|
34
|
+
"ref",
|
|
35
|
+
"children",
|
|
36
|
+
"mod"
|
|
37
|
+
]);
|
|
38
|
+
function pickDomProps(props) {
|
|
39
|
+
const { rest } = (0, _mantine_core.extractStyleProps)(props);
|
|
40
|
+
return Object.fromEntries(Object.entries(rest).filter(([key, value]) => !NON_DOM_PROPS.has(key) && value !== void 0));
|
|
41
|
+
}
|
|
42
|
+
function NotificationContainer({ data, onHide, autoClose, transitionDuration, allowDragDismiss, allowScrollDismiss, paused, onHoverStart, onHoverEnd, onExpandRequest, ref, style, renderNotification, layout, stackIndex, stackSize, stackPosition, stackExpanded, stackExpandedOffset, transitionState, ...others }) {
|
|
10
43
|
const [offset, setOffset] = (0, react.useState)(0);
|
|
11
44
|
const [dismissed, setDismissed] = (0, react.useState)(false);
|
|
12
45
|
const [dismissDirection, setDismissDirection] = (0, react.useState)(1);
|
|
13
46
|
const [scrollDismissActive, setScrollDismissActive] = (0, react.useState)(false);
|
|
14
47
|
const theme = (0, _mantine_core.useMantineTheme)();
|
|
15
|
-
const { autoClose: _autoClose, message, allowClose, position: _position, style: dataStyle, withCloseButton, onOpen: _onOpen, priority: _priority, __sequence: _sequence, ...notificationProps } = data;
|
|
48
|
+
const { autoClose: _autoClose, message, allowClose, position: _position, style: dataStyle, withCloseButton, renderNotification: _renderNotification, onOpen: _onOpen, priority: _priority, __sequence: _sequence, ...notificationProps } = data;
|
|
16
49
|
const autoCloseDuration = require_get_auto_close.getAutoClose(autoClose, data.autoClose);
|
|
17
50
|
const autoCloseTimeout = (0, react.useRef)(-1);
|
|
18
51
|
const hideTimeout = (0, react.useRef)(-1);
|
|
19
52
|
const scrollDismissTimeout = (0, react.useRef)(-1);
|
|
20
53
|
const notificationRef = (0, react.useRef)(null);
|
|
21
54
|
const hoveredRef = (0, react.useRef)(false);
|
|
55
|
+
const focusedRef = (0, react.useRef)(false);
|
|
56
|
+
const contributedActiveRef = (0, react.useRef)(false);
|
|
22
57
|
const offsetRef = (0, react.useRef)(0);
|
|
23
58
|
const isCloseDisabled = allowClose === false;
|
|
59
|
+
const syncActive = () => {
|
|
60
|
+
const shouldContribute = hoveredRef.current || focusedRef.current;
|
|
61
|
+
if (shouldContribute && !contributedActiveRef.current) {
|
|
62
|
+
contributedActiveRef.current = true;
|
|
63
|
+
onHoverStart?.();
|
|
64
|
+
} else if (!shouldContribute && contributedActiveRef.current) {
|
|
65
|
+
contributedActiveRef.current = false;
|
|
66
|
+
onHoverEnd?.();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const releaseActive = (0, react.useEffectEvent)(() => {
|
|
70
|
+
if (contributedActiveRef.current) {
|
|
71
|
+
contributedActiveRef.current = false;
|
|
72
|
+
onHoverEnd?.();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
(0, react.useEffect)(() => () => releaseActive(), []);
|
|
24
76
|
const cancelAutoClose = () => window.clearTimeout(autoCloseTimeout.current);
|
|
25
77
|
const cancelHide = () => window.clearTimeout(hideTimeout.current);
|
|
26
78
|
const cancelScrollDismissReset = () => window.clearTimeout(scrollDismissTimeout.current);
|
|
@@ -34,8 +86,12 @@ function NotificationContainer({ data, onHide, autoClose, transitionDuration, al
|
|
|
34
86
|
cancelHide();
|
|
35
87
|
cancelScrollDismissReset();
|
|
36
88
|
};
|
|
89
|
+
const pausedRef = (0, react.useRef)(paused);
|
|
90
|
+
(0, react.useEffect)(() => {
|
|
91
|
+
pausedRef.current = paused;
|
|
92
|
+
});
|
|
37
93
|
const handleAutoClose = () => {
|
|
38
|
-
if (dismissed || active ||
|
|
94
|
+
if (dismissed || active || hoveredRef.current || focusedRef.current || pausedRef.current || typeof autoCloseDuration !== "number") return;
|
|
39
95
|
cancelAutoClose();
|
|
40
96
|
autoCloseTimeout.current = window.setTimeout(handleHide, autoCloseDuration);
|
|
41
97
|
};
|
|
@@ -102,22 +158,47 @@ function NotificationContainer({ data, onHide, autoClose, transitionDuration, al
|
|
|
102
158
|
const baseOpacity = typeof baseStyle.opacity === "number" ? baseStyle.opacity : 1;
|
|
103
159
|
const swipeOpacity = dismissed ? 0 : 1 - Math.min(Math.abs(offset) / 200, 1) * .6;
|
|
104
160
|
const resolvedTransitionDuration = baseStyle.transitionDuration ?? `${transitionDuration}ms, ${transitionDuration}ms, ${transitionDuration}ms`;
|
|
161
|
+
const isStackedLayout = layout === "stacked";
|
|
162
|
+
const isStacked = isStackedLayout && stackIndex !== void 0 && stackIndex > 0;
|
|
163
|
+
const isCollapsed = isStacked && !stackExpanded;
|
|
164
|
+
const isExiting = transitionState === "exiting" || transitionState === "exited";
|
|
165
|
+
const stackDirection = stackPosition?.startsWith("top") ? 1 : -1;
|
|
166
|
+
const stackDepth = Math.min(stackIndex ?? 0, MAX_VISIBLE_STACK_DEPTH);
|
|
167
|
+
const collapsedOffset = isCollapsed ? stackDepth * 10 * stackDirection : 0;
|
|
168
|
+
const staggerDelay = isStackedLayout ? (stackIndex || 0) * 30 : 0;
|
|
169
|
+
const isDragging = active || scrollDismissActive;
|
|
170
|
+
const getStackedTransform = () => {
|
|
171
|
+
if (!isStackedLayout) return "var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)";
|
|
172
|
+
if (isExiting) return `translateY(${stackExpanded ? stackExpandedOffset || 0 : collapsedOffset}px) var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)`;
|
|
173
|
+
if (stackExpanded) return `translateY(${stackExpandedOffset || 0}px) translate3d(var(--notifications-swipe-offset), 0, 0)`;
|
|
174
|
+
if (isStacked) return `scale(${1 - stackDepth * .03}) translateY(${collapsedOffset}px)`;
|
|
175
|
+
return "var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)";
|
|
176
|
+
};
|
|
105
177
|
const notificationStyle = {
|
|
106
178
|
...baseStyle,
|
|
179
|
+
...isStackedLayout ? { maxHeight: void 0 } : {},
|
|
107
180
|
["--notifications-state-transform"]: typeof baseStyle.transform === "string" ? baseStyle.transform : "translateX(0)",
|
|
108
181
|
["--notifications-state-opacity"]: String(baseOpacity),
|
|
109
182
|
["--notifications-swipe-offset"]: `${offset}px`,
|
|
110
183
|
["--notifications-swipe-opacity"]: String(swipeOpacity),
|
|
111
|
-
transform:
|
|
184
|
+
transform: getStackedTransform(),
|
|
112
185
|
opacity: "calc(var(--notifications-state-opacity) * var(--notifications-swipe-opacity))",
|
|
113
|
-
transitionDuration:
|
|
186
|
+
transitionDuration: isDragging ? "0ms, 0ms, 0ms" : resolvedTransitionDuration,
|
|
114
187
|
cursor: "default",
|
|
115
|
-
touchAction: "pan-y"
|
|
188
|
+
touchAction: "pan-y",
|
|
189
|
+
...isStackedLayout ? {
|
|
190
|
+
gridArea: "1 / 1",
|
|
191
|
+
zIndex: (stackSize || 5) - (stackIndex ?? 0),
|
|
192
|
+
pointerEvents: isCollapsed ? "none" : void 0,
|
|
193
|
+
alignSelf: stackDirection === 1 ? "start" : "end",
|
|
194
|
+
transition: isDragging ? "none" : `transform ${transitionDuration}ms cubic-bezier(.51,.3,0,1.21), opacity ${transitionDuration}ms ease`,
|
|
195
|
+
transitionDelay: isDragging || isExiting ? "0ms" : `${staggerDelay}ms`
|
|
196
|
+
} : {}
|
|
116
197
|
};
|
|
117
198
|
const handleMouseEnter = () => {
|
|
118
199
|
hoveredRef.current = true;
|
|
119
200
|
cancelAutoClose();
|
|
120
|
-
|
|
201
|
+
syncActive();
|
|
121
202
|
};
|
|
122
203
|
const handleMouseLeave = () => {
|
|
123
204
|
hoveredRef.current = false;
|
|
@@ -125,7 +206,20 @@ function NotificationContainer({ data, onHide, autoClose, transitionDuration, al
|
|
|
125
206
|
resetSwipe();
|
|
126
207
|
handleAutoClose();
|
|
127
208
|
}
|
|
128
|
-
|
|
209
|
+
syncActive();
|
|
210
|
+
};
|
|
211
|
+
const handleFocusCapture = isStackedLayout ? () => {
|
|
212
|
+
focusedRef.current = true;
|
|
213
|
+
cancelAutoClose();
|
|
214
|
+
syncActive();
|
|
215
|
+
} : void 0;
|
|
216
|
+
const handleBlurCapture = isStackedLayout ? () => {
|
|
217
|
+
focusedRef.current = false;
|
|
218
|
+
if (!scrollDismissActive) handleAutoClose();
|
|
219
|
+
syncActive();
|
|
220
|
+
} : void 0;
|
|
221
|
+
const handlePointerDownCapture = (event) => {
|
|
222
|
+
if (isStackedLayout && (event.pointerType === "touch" || event.pointerType === "pen")) onExpandRequest?.();
|
|
129
223
|
};
|
|
130
224
|
const handleWheel = (0, react.useEffectEvent)((event) => {
|
|
131
225
|
if (dismissed || active) return;
|
|
@@ -189,15 +283,52 @@ function NotificationContainer({ data, onHide, autoClose, transitionDuration, al
|
|
|
189
283
|
else handleAutoClose();
|
|
190
284
|
return cancelAutoClose;
|
|
191
285
|
}, [paused]);
|
|
286
|
+
const consumerProps = {
|
|
287
|
+
...others,
|
|
288
|
+
...notificationProps
|
|
289
|
+
};
|
|
290
|
+
const interactionProps = {
|
|
291
|
+
style: notificationStyle,
|
|
292
|
+
inert: isCollapsed,
|
|
293
|
+
onMouseEnter: (event) => {
|
|
294
|
+
consumerProps.onMouseEnter?.(event);
|
|
295
|
+
handleMouseEnter();
|
|
296
|
+
},
|
|
297
|
+
onMouseLeave: (event) => {
|
|
298
|
+
consumerProps.onMouseLeave?.(event);
|
|
299
|
+
handleMouseLeave();
|
|
300
|
+
},
|
|
301
|
+
onFocusCapture: (event) => {
|
|
302
|
+
consumerProps.onFocusCapture?.(event);
|
|
303
|
+
handleFocusCapture?.();
|
|
304
|
+
},
|
|
305
|
+
onBlurCapture: (event) => {
|
|
306
|
+
consumerProps.onBlurCapture?.(event);
|
|
307
|
+
handleBlurCapture?.();
|
|
308
|
+
},
|
|
309
|
+
onPointerDownCapture: (event) => {
|
|
310
|
+
consumerProps.onPointerDownCapture?.(event);
|
|
311
|
+
handlePointerDownCapture(event);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
if (renderNotification) {
|
|
315
|
+
const classNames = [others.className, notificationProps.className].filter(Boolean).join(" ");
|
|
316
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
317
|
+
ref: mergedRef,
|
|
318
|
+
role: notificationProps.role || others.role || "alert",
|
|
319
|
+
...pickDomProps(consumerProps),
|
|
320
|
+
className: classNames || void 0,
|
|
321
|
+
...interactionProps,
|
|
322
|
+
children: renderNotification(data)
|
|
323
|
+
});
|
|
324
|
+
}
|
|
192
325
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Notification, {
|
|
193
326
|
ref: mergedRef,
|
|
194
327
|
...others,
|
|
195
|
-
style: notificationStyle,
|
|
196
328
|
...notificationProps,
|
|
329
|
+
...interactionProps,
|
|
197
330
|
withCloseButton: isCloseDisabled ? false : withCloseButton,
|
|
198
331
|
onClose: handleHide,
|
|
199
|
-
onMouseEnter: handleMouseEnter,
|
|
200
|
-
onMouseLeave: handleMouseLeave,
|
|
201
332
|
children: message
|
|
202
333
|
});
|
|
203
334
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationContainer.cjs","names":["getAutoClose","Notification"],"sources":["../src/NotificationContainer.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport { getStyleObject, Notification, NotificationProps, useMantineTheme } from '@mantine/core';\nimport { useDrag, useMergedRef } from '@mantine/hooks';\nimport { getAutoClose } from './get-auto-close/get-auto-close';\nimport { NotificationData } from './notifications.store';\n\nconst SCROLL_DISMISS_RESET_TIMEOUT = 120;\n\ninterface NotificationContainerProps extends NotificationProps {\n data: NotificationData;\n onHide: (id: string) => void;\n autoClose: number | false;\n transitionDuration: number;\n allowDragDismiss: boolean;\n allowScrollDismiss: boolean;\n paused: boolean;\n onHoverStart?: () => void;\n onHoverEnd?: () => void;\n ref?: React.Ref<HTMLDivElement>;\n}\n\nexport function NotificationContainer({\n data,\n onHide,\n autoClose,\n transitionDuration,\n allowDragDismiss,\n allowScrollDismiss,\n paused,\n onHoverStart,\n onHoverEnd,\n ref,\n style,\n ...others\n}: NotificationContainerProps) {\n const [offset, setOffset] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n const [dismissDirection, setDismissDirection] = useState<-1 | 1>(1);\n const [scrollDismissActive, setScrollDismissActive] = useState(false);\n const theme = useMantineTheme();\n const {\n autoClose: _autoClose,\n message,\n allowClose,\n position: _position,\n style: dataStyle,\n withCloseButton,\n onOpen: _onOpen,\n priority: _priority,\n __sequence: _sequence,\n ...notificationProps\n } = data as NotificationData & { __sequence?: number };\n const autoCloseDuration = getAutoClose(autoClose, data.autoClose);\n const autoCloseTimeout = useRef<number>(-1);\n const hideTimeout = useRef<number>(-1);\n const scrollDismissTimeout = useRef<number>(-1);\n const notificationRef = useRef<HTMLDivElement>(null);\n const hoveredRef = useRef(false);\n const offsetRef = useRef(0);\n const isCloseDisabled = allowClose === false;\n\n const cancelAutoClose = () => window.clearTimeout(autoCloseTimeout.current);\n const cancelHide = () => window.clearTimeout(hideTimeout.current);\n const cancelScrollDismissReset = () => window.clearTimeout(scrollDismissTimeout.current);\n\n const setSwipeOffset = (value: number) => {\n offsetRef.current = value;\n setOffset(value);\n };\n\n const handleHide = () => {\n onHide(data.id!);\n cancelAutoClose();\n cancelHide();\n cancelScrollDismissReset();\n };\n\n const handleAutoClose = () => {\n if (\n dismissed ||\n active ||\n paused ||\n hoveredRef.current ||\n typeof autoCloseDuration !== 'number'\n ) {\n return;\n }\n\n cancelAutoClose();\n autoCloseTimeout.current = window.setTimeout(handleHide, autoCloseDuration);\n };\n\n const getExitOffset = (direction: -1 | 1) => {\n const width = notificationRef.current?.offsetWidth ?? 440;\n return direction * (width + 40);\n };\n\n const shouldDismiss = (movement: number, velocity: number) => {\n const width = notificationRef.current?.offsetWidth ?? 440;\n return Math.abs(movement) > width * 0.35 || velocity > 0.5;\n };\n\n const resetSwipe = () => {\n cancelScrollDismissReset();\n setScrollDismissActive(false);\n setSwipeOffset(0);\n };\n\n const dismissNotification = (direction: -1 | 1) => {\n setDismissDirection(direction);\n setDismissed(true);\n setScrollDismissActive(false);\n setSwipeOffset(getExitOffset(direction));\n cancelAutoClose();\n cancelHide();\n cancelScrollDismissReset();\n hideTimeout.current = window.setTimeout(handleHide, transitionDuration);\n };\n\n const scheduleScrollDismissReset = () => {\n cancelScrollDismissReset();\n scrollDismissTimeout.current = window.setTimeout(() => {\n setScrollDismissActive(false);\n setSwipeOffset(0);\n handleAutoClose();\n }, SCROLL_DISMISS_RESET_TIMEOUT);\n };\n\n const { ref: dragRef, active } = useDrag<HTMLDivElement>(\n (state) => {\n if (dismissed) {\n return;\n }\n\n if (state.first) {\n cancelAutoClose();\n }\n\n if (state.last) {\n if (state.tap || state.canceled) {\n setSwipeOffset(0);\n handleAutoClose();\n return;\n }\n\n const movement = state.movement[0];\n const direction =\n movement === 0 ? (state.direction[0] === -1 ? -1 : 1) : movement > 0 ? 1 : -1;\n\n if (shouldDismiss(movement, state.velocity[0])) {\n dismissNotification(direction);\n } else {\n setSwipeOffset(0);\n handleAutoClose();\n }\n } else {\n setSwipeOffset(state.movement[0]);\n }\n },\n {\n axis: 'x',\n threshold: 5,\n filterTaps: true,\n enabled: allowDragDismiss && !isCloseDisabled && !dismissed,\n }\n );\n\n const mergedRef = useMergedRef(ref, notificationRef, dragRef);\n const resolvedStyle = getStyleObject(style, theme);\n const resolvedDataStyle = getStyleObject(dataStyle, theme);\n const baseStyle = { ...resolvedStyle, ...resolvedDataStyle };\n const baseOpacity = typeof baseStyle.opacity === 'number' ? baseStyle.opacity : 1;\n const swipeOpacity = dismissed ? 0 : 1 - Math.min(Math.abs(offset) / 200, 1) * 0.6;\n const resolvedTransitionDuration =\n baseStyle.transitionDuration ??\n `${transitionDuration}ms, ${transitionDuration}ms, ${transitionDuration}ms`;\n const notificationStyle = {\n ...baseStyle,\n ['--notifications-state-transform' as string]:\n typeof baseStyle.transform === 'string' ? baseStyle.transform : 'translateX(0)',\n ['--notifications-state-opacity' as string]: String(baseOpacity),\n ['--notifications-swipe-offset' as string]: `${offset}px`,\n ['--notifications-swipe-opacity' as string]: String(swipeOpacity),\n transform:\n 'var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)',\n opacity: 'calc(var(--notifications-state-opacity) * var(--notifications-swipe-opacity))',\n transitionDuration:\n active || scrollDismissActive ? '0ms, 0ms, 0ms' : resolvedTransitionDuration,\n cursor: 'default',\n touchAction: 'pan-y',\n } as React.CSSProperties;\n\n const handleMouseEnter = () => {\n hoveredRef.current = true;\n cancelAutoClose();\n onHoverStart?.();\n };\n\n const handleMouseLeave = () => {\n hoveredRef.current = false;\n if (!scrollDismissActive) {\n resetSwipe();\n handleAutoClose();\n }\n onHoverEnd?.();\n };\n\n const handleWheel = useEffectEvent((event: WheelEvent) => {\n if (dismissed || active) {\n return;\n }\n\n const isDocumentEvent = event.currentTarget === document;\n if (!isDocumentEvent && !hoveredRef.current) {\n return;\n }\n\n const { deltaX, deltaY } = event;\n if (Math.abs(deltaX) <= Math.abs(deltaY) || deltaX === 0) {\n return;\n }\n\n if (!allowScrollDismiss || isCloseDisabled) {\n return;\n }\n\n if (!isDocumentEvent) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n cancelAutoClose();\n setScrollDismissActive(true);\n\n const nextOffset = offsetRef.current - deltaX;\n const direction = nextOffset > 0 ? 1 : -1;\n\n if (shouldDismiss(nextOffset, 0)) {\n dismissNotification(direction);\n return;\n }\n\n setSwipeOffset(nextOffset);\n scheduleScrollDismissReset();\n });\n\n useEffect(() => {\n if (!scrollDismissActive) {\n return undefined;\n }\n\n document.addEventListener('wheel', handleWheel, { passive: false });\n return () => document.removeEventListener('wheel', handleWheel, { passive: false } as any);\n }, [scrollDismissActive]);\n\n useEffect(() => {\n const handleResize = () => {\n if (dismissed) {\n setSwipeOffset(getExitOffset(dismissDirection));\n }\n };\n\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [dismissDirection, dismissed]);\n\n useEffect(() => {\n const node = notificationRef.current;\n if (!node) {\n return undefined;\n }\n\n node.addEventListener('wheel', handleWheel, { passive: false });\n return () => node.removeEventListener('wheel', handleWheel, { passive: false } as any);\n }, []);\n\n useEffect(() => {\n return () => {\n cancelHide();\n cancelScrollDismissReset();\n };\n }, []);\n\n useEffect(() => {\n data.onOpen?.(data);\n }, []);\n\n useEffect(() => {\n handleAutoClose();\n return cancelAutoClose;\n }, [autoCloseDuration, active, dismissed]);\n\n useEffect(() => {\n if (paused) {\n cancelAutoClose();\n } else {\n handleAutoClose();\n }\n\n return cancelAutoClose;\n }, [paused]);\n\n return (\n <Notification\n ref={mergedRef}\n {...others}\n style={notificationStyle}\n {...notificationProps}\n withCloseButton={isCloseDisabled ? false : withCloseButton}\n onClose={handleHide}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {message}\n </Notification>\n );\n}\n\nNotificationContainer.displayName = '@mantine/notifications/NotificationContainer';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NotificationContainer.cjs","names":["extractStyleProps","useState","useMantineTheme","getAutoClose","useRef","useEffectEvent","useDrag","useMergedRef","getStyleObject","Notification"],"sources":["../src/NotificationContainer.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport {\n extractStyleProps,\n getStyleObject,\n Notification,\n NotificationProps,\n useMantineTheme,\n} from '@mantine/core';\nimport { useDrag, useMergedRef } from '@mantine/hooks';\nimport { getAutoClose } from './get-auto-close/get-auto-close';\nimport { NotificationData } from './notifications.store';\n\nconst SCROLL_DISMISS_RESET_TIMEOUT = 120;\n\ninterface NotificationContainerProps extends NotificationProps {\n data: NotificationData;\n onHide: (id: string) => void;\n autoClose: number | false;\n transitionDuration: number;\n allowDragDismiss: boolean;\n allowScrollDismiss: boolean;\n paused: boolean;\n onHoverStart?: () => void;\n onHoverEnd?: () => void;\n onExpandRequest?: () => void;\n ref?: React.Ref<HTMLDivElement>;\n renderNotification?: ((notification: NotificationData) => React.ReactNode) | null;\n layout?: 'default' | 'stacked';\n stackIndex?: number;\n stackSize?: number;\n stackPosition?: string;\n stackExpanded?: boolean;\n stackExpandedOffset?: number;\n transitionState?: string;\n}\n\nconst MAX_VISIBLE_STACK_DEPTH = 4;\n\n/**\n * Props that belong to the default `Notification` rendering or to the Styles API and must\n * not reach the plain `div` used for custom rendering. Everything else is a valid div prop\n * and is forwarded – an allow list would silently drop supported props like `onClick`,\n * `dir`, `lang` or `hidden`.\n */\nconst NON_DOM_PROPS = new Set([\n 'classNames',\n 'styles',\n 'unstyled',\n 'vars',\n 'attributes',\n 'variant',\n 'color',\n 'radius',\n 'icon',\n 'title',\n 'loading',\n 'withBorder',\n 'withCloseButton',\n 'closeButtonProps',\n 'className',\n 'style',\n 'role',\n 'ref',\n 'children',\n 'mod',\n]);\n\nfunction pickDomProps(props: Record<string, any>) {\n // Mantine style props (`mt`, `bg`, `w`, …) are valid `NotificationProps` but are not DOM\n // attributes, so they are separated out rather than leaked onto the element.\n const { rest } = extractStyleProps(props);\n\n return Object.fromEntries(\n Object.entries(rest).filter(([key, value]) => !NON_DOM_PROPS.has(key) && value !== undefined)\n );\n}\n\nexport function NotificationContainer({\n data,\n onHide,\n autoClose,\n transitionDuration,\n allowDragDismiss,\n allowScrollDismiss,\n paused,\n onHoverStart,\n onHoverEnd,\n onExpandRequest,\n ref,\n style,\n renderNotification,\n layout,\n stackIndex,\n stackSize,\n stackPosition,\n stackExpanded,\n stackExpandedOffset,\n transitionState,\n ...others\n}: NotificationContainerProps) {\n const [offset, setOffset] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n const [dismissDirection, setDismissDirection] = useState<-1 | 1>(1);\n const [scrollDismissActive, setScrollDismissActive] = useState(false);\n const theme = useMantineTheme();\n const {\n autoClose: _autoClose,\n message,\n allowClose,\n position: _position,\n style: dataStyle,\n withCloseButton,\n renderNotification: _renderNotification,\n onOpen: _onOpen,\n priority: _priority,\n __sequence: _sequence,\n ...notificationProps\n } = data as NotificationData & { __sequence?: number };\n const autoCloseDuration = getAutoClose(autoClose, data.autoClose);\n const autoCloseTimeout = useRef<number>(-1);\n const hideTimeout = useRef<number>(-1);\n const scrollDismissTimeout = useRef<number>(-1);\n const notificationRef = useRef<HTMLDivElement>(null);\n const hoveredRef = useRef(false);\n const focusedRef = useRef(false);\n\n // Hover and focus both keep the notification \"active\". The contribution to the parent\n // counter is tracked so it can be released on unmount – a notification dismissed while\n // hovered or focused never fires `mouseleave` or `blur`, which would otherwise leave the\n // stack expanded and auto close paused forever.\n const contributedActiveRef = useRef(false);\n const offsetRef = useRef(0);\n const isCloseDisabled = allowClose === false;\n\n const syncActive = () => {\n const shouldContribute = hoveredRef.current || focusedRef.current;\n\n if (shouldContribute && !contributedActiveRef.current) {\n contributedActiveRef.current = true;\n onHoverStart?.();\n } else if (!shouldContribute && contributedActiveRef.current) {\n contributedActiveRef.current = false;\n onHoverEnd?.();\n }\n };\n\n const releaseActive = useEffectEvent(() => {\n if (contributedActiveRef.current) {\n contributedActiveRef.current = false;\n onHoverEnd?.();\n }\n });\n\n useEffect(() => () => releaseActive(), []);\n\n const cancelAutoClose = () => window.clearTimeout(autoCloseTimeout.current);\n const cancelHide = () => window.clearTimeout(hideTimeout.current);\n const cancelScrollDismissReset = () => window.clearTimeout(scrollDismissTimeout.current);\n\n const setSwipeOffset = (value: number) => {\n offsetRef.current = value;\n setOffset(value);\n };\n\n const handleHide = () => {\n onHide(data.id!);\n cancelAutoClose();\n cancelHide();\n cancelScrollDismissReset();\n };\n\n // `handleAutoClose` is also called from timeouts scheduled in earlier renders, so the\n // latest `paused` is read through a ref. Written in an effect rather than during render –\n // this effect is declared before every effect that calls `handleAutoClose`, so it is\n // always up to date by the time they run.\n const pausedRef = useRef(paused);\n\n useEffect(() => {\n pausedRef.current = paused;\n });\n\n const handleAutoClose = () => {\n if (\n dismissed ||\n active ||\n hoveredRef.current ||\n focusedRef.current ||\n pausedRef.current ||\n typeof autoCloseDuration !== 'number'\n ) {\n return;\n }\n\n cancelAutoClose();\n autoCloseTimeout.current = window.setTimeout(handleHide, autoCloseDuration);\n };\n\n const getExitOffset = (direction: -1 | 1) => {\n const width = notificationRef.current?.offsetWidth ?? 440;\n return direction * (width + 40);\n };\n\n const shouldDismiss = (movement: number, velocity: number) => {\n const width = notificationRef.current?.offsetWidth ?? 440;\n return Math.abs(movement) > width * 0.35 || velocity > 0.5;\n };\n\n const resetSwipe = () => {\n cancelScrollDismissReset();\n setScrollDismissActive(false);\n setSwipeOffset(0);\n };\n\n const dismissNotification = (direction: -1 | 1) => {\n setDismissDirection(direction);\n setDismissed(true);\n setScrollDismissActive(false);\n setSwipeOffset(getExitOffset(direction));\n cancelAutoClose();\n cancelHide();\n cancelScrollDismissReset();\n hideTimeout.current = window.setTimeout(handleHide, transitionDuration);\n };\n\n const scheduleScrollDismissReset = () => {\n cancelScrollDismissReset();\n scrollDismissTimeout.current = window.setTimeout(() => {\n setScrollDismissActive(false);\n setSwipeOffset(0);\n handleAutoClose();\n }, SCROLL_DISMISS_RESET_TIMEOUT);\n };\n\n const { ref: dragRef, active } = useDrag<HTMLDivElement>(\n (state) => {\n if (dismissed) {\n return;\n }\n\n if (state.first) {\n cancelAutoClose();\n }\n\n if (state.last) {\n if (state.tap || state.canceled) {\n setSwipeOffset(0);\n handleAutoClose();\n return;\n }\n\n const movement = state.movement[0];\n const direction =\n movement === 0 ? (state.direction[0] === -1 ? -1 : 1) : movement > 0 ? 1 : -1;\n\n if (shouldDismiss(movement, state.velocity[0])) {\n dismissNotification(direction);\n } else {\n setSwipeOffset(0);\n handleAutoClose();\n }\n } else {\n setSwipeOffset(state.movement[0]);\n }\n },\n {\n axis: 'x',\n threshold: 5,\n filterTaps: true,\n enabled: allowDragDismiss && !isCloseDisabled && !dismissed,\n }\n );\n\n const mergedRef = useMergedRef(ref, notificationRef, dragRef);\n const resolvedStyle = getStyleObject(style, theme);\n const resolvedDataStyle = getStyleObject(dataStyle, theme);\n const baseStyle = { ...resolvedStyle, ...resolvedDataStyle };\n const baseOpacity = typeof baseStyle.opacity === 'number' ? baseStyle.opacity : 1;\n const swipeOpacity = dismissed ? 0 : 1 - Math.min(Math.abs(offset) / 200, 1) * 0.6;\n const resolvedTransitionDuration =\n baseStyle.transitionDuration ??\n `${transitionDuration}ms, ${transitionDuration}ms, ${transitionDuration}ms`;\n\n const isStackedLayout = layout === 'stacked';\n const isStacked = isStackedLayout && stackIndex !== undefined && stackIndex > 0;\n const isCollapsed = isStacked && !stackExpanded;\n const isExiting = transitionState === 'exiting' || transitionState === 'exited';\n const stackDirection = stackPosition?.startsWith('top') ? 1 : -1;\n\n // Only a few layers are visible behind the front notification – without a cap the scale\n // below reaches 0 at 34 stacked notifications and inverts beyond that, which `limit` can\n // easily exceed.\n const stackDepth = Math.min(stackIndex ?? 0, MAX_VISIBLE_STACK_DEPTH);\n const collapsedOffset = isCollapsed ? stackDepth * 10 * stackDirection : 0;\n const staggerDelay = isStackedLayout ? (stackIndex || 0) * 30 : 0;\n const isDragging = active || scrollDismissActive;\n\n const getStackedTransform = () => {\n if (!isStackedLayout) {\n return 'var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)';\n }\n\n if (isExiting) {\n const exitOffset = stackExpanded ? stackExpandedOffset || 0 : collapsedOffset;\n return `translateY(${exitOffset}px) var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)`;\n }\n\n if (stackExpanded) {\n return `translateY(${stackExpandedOffset || 0}px) translate3d(var(--notifications-swipe-offset), 0, 0)`;\n }\n\n if (isStacked) {\n return `scale(${1 - stackDepth * 0.03}) translateY(${collapsedOffset}px)`;\n }\n\n return 'var(--notifications-state-transform) translate3d(var(--notifications-swipe-offset), 0, 0)';\n };\n\n const notificationStyle = {\n ...baseStyle,\n ...(isStackedLayout ? { maxHeight: undefined } : {}),\n ['--notifications-state-transform' as string]:\n typeof baseStyle.transform === 'string' ? baseStyle.transform : 'translateX(0)',\n ['--notifications-state-opacity' as string]: String(baseOpacity),\n ['--notifications-swipe-offset' as string]: `${offset}px`,\n ['--notifications-swipe-opacity' as string]: String(swipeOpacity),\n transform: getStackedTransform(),\n opacity: 'calc(var(--notifications-state-opacity) * var(--notifications-swipe-opacity))',\n transitionDuration: isDragging ? '0ms, 0ms, 0ms' : resolvedTransitionDuration,\n cursor: 'default',\n touchAction: 'pan-y',\n ...(isStackedLayout\n ? {\n gridArea: '1 / 1' as const,\n // `z-index` is not animatable, so it must not depend on `stackExpanded` – flipping\n // the stack to a single layer on hover repaints every notification in front of the\n // first one a frame before the reveal transform has moved anything.\n zIndex: (stackSize || 5) - (stackIndex ?? 0),\n pointerEvents: isCollapsed ? ('none' as const) : undefined,\n alignSelf: stackDirection === 1 ? ('start' as const) : ('end' as const),\n transition: isDragging\n ? 'none'\n : `transform ${transitionDuration}ms cubic-bezier(.51,.3,0,1.21), opacity ${transitionDuration}ms ease`,\n transitionDelay: isDragging || isExiting ? '0ms' : `${staggerDelay}ms`,\n }\n : {}),\n } as React.CSSProperties;\n\n const handleMouseEnter = () => {\n hoveredRef.current = true;\n cancelAutoClose();\n syncActive();\n };\n\n const handleMouseLeave = () => {\n hoveredRef.current = false;\n if (!scrollDismissActive) {\n resetSwipe();\n handleAutoClose();\n }\n syncActive();\n };\n\n // Keyboard users never trigger the hover handlers, and touch devices have no hover at\n // all – both need a way to expand a collapsed stack. Scoped to the stacked layout: its\n // only purpose is keeping the stack expanded, and applying it everywhere would silently\n // change the default layout, where a notification that merely contains the focused\n // element (an action button the user just clicked) would stop auto closing.\n const handleFocusCapture = isStackedLayout\n ? () => {\n focusedRef.current = true;\n cancelAutoClose();\n syncActive();\n }\n : undefined;\n\n const handleBlurCapture = isStackedLayout\n ? () => {\n focusedRef.current = false;\n if (!scrollDismissActive) {\n handleAutoClose();\n }\n syncActive();\n }\n : undefined;\n\n const handlePointerDownCapture = (event: React.PointerEvent) => {\n // Explicitly opt in for touch and pen: hover already covers the mouse, and an unknown\n // pointer type should not pin the stack open.\n if (isStackedLayout && (event.pointerType === 'touch' || event.pointerType === 'pen')) {\n onExpandRequest?.();\n }\n };\n\n const handleWheel = useEffectEvent((event: WheelEvent) => {\n if (dismissed || active) {\n return;\n }\n\n const isDocumentEvent = event.currentTarget === document;\n if (!isDocumentEvent && !hoveredRef.current) {\n return;\n }\n\n const { deltaX, deltaY } = event;\n if (Math.abs(deltaX) <= Math.abs(deltaY) || deltaX === 0) {\n return;\n }\n\n if (!allowScrollDismiss || isCloseDisabled) {\n return;\n }\n\n if (!isDocumentEvent) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n cancelAutoClose();\n setScrollDismissActive(true);\n\n const nextOffset = offsetRef.current - deltaX;\n const direction = nextOffset > 0 ? 1 : -1;\n\n if (shouldDismiss(nextOffset, 0)) {\n dismissNotification(direction);\n return;\n }\n\n setSwipeOffset(nextOffset);\n scheduleScrollDismissReset();\n });\n\n useEffect(() => {\n if (!scrollDismissActive) {\n return undefined;\n }\n\n document.addEventListener('wheel', handleWheel, { passive: false });\n return () => document.removeEventListener('wheel', handleWheel, { passive: false } as any);\n }, [scrollDismissActive]);\n\n useEffect(() => {\n const handleResize = () => {\n if (dismissed) {\n setSwipeOffset(getExitOffset(dismissDirection));\n }\n };\n\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [dismissDirection, dismissed]);\n\n useEffect(() => {\n const node = notificationRef.current;\n if (!node) {\n return undefined;\n }\n\n node.addEventListener('wheel', handleWheel, { passive: false });\n return () => node.removeEventListener('wheel', handleWheel, { passive: false } as any);\n }, []);\n\n useEffect(() => {\n return () => {\n cancelHide();\n cancelScrollDismissReset();\n };\n }, []);\n\n useEffect(() => {\n data.onOpen?.(data);\n }, []);\n\n useEffect(() => {\n handleAutoClose();\n return cancelAutoClose;\n }, [autoCloseDuration, active, dismissed]);\n\n useEffect(() => {\n if (paused) {\n cancelAutoClose();\n } else {\n handleAutoClose();\n }\n\n return cancelAutoClose;\n }, [paused]);\n\n const consumerProps: Record<string, any> = { ...others, ...notificationProps };\n\n // The interaction handlers below are internal, but the same events are part of the public\n // props of both `Notifications` and every notification – they are composed with whatever\n // the consumer passed instead of replacing it.\n const interactionProps = {\n style: notificationStyle,\n // A collapsed notification is hidden behind the one in front of it – `pointer-events`\n // alone does not take its controls out of the tab order or hide them from a screen\n // reader, so it is fully inert until the stack is expanded.\n inert: isCollapsed,\n onMouseEnter: (event: React.MouseEvent<HTMLDivElement>) => {\n consumerProps.onMouseEnter?.(event);\n handleMouseEnter();\n },\n onMouseLeave: (event: React.MouseEvent<HTMLDivElement>) => {\n consumerProps.onMouseLeave?.(event);\n handleMouseLeave();\n },\n onFocusCapture: (event: React.FocusEvent<HTMLDivElement>) => {\n consumerProps.onFocusCapture?.(event);\n handleFocusCapture?.();\n },\n onBlurCapture: (event: React.FocusEvent<HTMLDivElement>) => {\n consumerProps.onBlurCapture?.(event);\n handleBlurCapture?.();\n },\n onPointerDownCapture: (event: React.PointerEvent<HTMLDivElement>) => {\n consumerProps.onPointerDownCapture?.(event);\n handlePointerDownCapture(event);\n },\n };\n\n if (renderNotification) {\n const classNames = [others.className, notificationProps.className].filter(Boolean).join(' ');\n\n return (\n <div\n ref={mergedRef}\n role={notificationProps.role || others.role || 'alert'}\n {...pickDomProps(consumerProps)}\n className={classNames || undefined}\n {...interactionProps}\n >\n {renderNotification(data)}\n </div>\n );\n }\n\n return (\n <Notification\n ref={mergedRef}\n {...others}\n {...notificationProps}\n {...interactionProps}\n withCloseButton={isCloseDisabled ? false : withCloseButton}\n onClose={handleHide}\n >\n {message}\n </Notification>\n );\n}\n\nNotificationContainer.displayName = '@mantine/notifications/NotificationContainer';\n"],"mappings":"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"}
|
package/cjs/Notifications.cjs
CHANGED
|
@@ -11,6 +11,10 @@ let _mantine_core = require("@mantine/core");
|
|
|
11
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
12
|
//#region packages/@mantine/notifications/src/Notifications.tsx
|
|
13
13
|
const Transition = react_transition_group.Transition;
|
|
14
|
+
/** Vertical gap between notifications of an expanded stack, in px */
|
|
15
|
+
const STACK_EXPANDED_GAP = 16;
|
|
16
|
+
/** Offset step used for a notification that has not been measured yet, in px */
|
|
17
|
+
const FALLBACK_NOTIFICATION_HEIGHT = 80;
|
|
14
18
|
const defaultProps = {
|
|
15
19
|
position: "bottom-right",
|
|
16
20
|
autoClose: 4e3,
|
|
@@ -23,7 +27,8 @@ const defaultProps = {
|
|
|
23
27
|
zIndex: (0, _mantine_core.getDefaultZIndex)("overlay"),
|
|
24
28
|
store: require_notifications_store.notificationsStore,
|
|
25
29
|
withinPortal: true,
|
|
26
|
-
pauseResetOnHover: "all"
|
|
30
|
+
pauseResetOnHover: "all",
|
|
31
|
+
layout: "default"
|
|
27
32
|
};
|
|
28
33
|
const varsResolver = (0, _mantine_core.createVarsResolver)((_, { zIndex, containerWidth }) => ({ root: {
|
|
29
34
|
"--notifications-z-index": zIndex?.toString(),
|
|
@@ -31,16 +36,134 @@ const varsResolver = (0, _mantine_core.createVarsResolver)((_, { zIndex, contain
|
|
|
31
36
|
} }));
|
|
32
37
|
const Notifications = (0, _mantine_core.factory)((_props) => {
|
|
33
38
|
const props = (0, _mantine_core.useProps)("Notifications", defaultProps, _props);
|
|
34
|
-
const { classNames, className, style, styles, unstyled, vars, attributes, position, autoClose, transitionDuration, allowDragDismiss, allowScrollDismiss, containerWidth, notificationMaxHeight, limit, zIndex, store, portalProps, withinPortal, pauseResetOnHover, ...others } = props;
|
|
39
|
+
const { classNames, className, style, styles, unstyled, vars, attributes, position, autoClose, transitionDuration, allowDragDismiss, allowScrollDismiss, containerWidth, notificationMaxHeight, limit, zIndex, store, portalProps, withinPortal, pauseResetOnHover, renderNotification, layout, ...others } = props;
|
|
35
40
|
const theme = (0, _mantine_core.useMantineTheme)();
|
|
36
41
|
const data = require_notifications_store.useNotifications(store);
|
|
37
42
|
const forceUpdate = (0, _mantine_hooks.useForceUpdate)();
|
|
38
43
|
const shouldReduceMotion = (0, _mantine_hooks.useReducedMotion)();
|
|
39
44
|
const refs = (0, react.useRef)({});
|
|
40
45
|
const previousLength = (0, react.useRef)(0);
|
|
41
|
-
const [
|
|
42
|
-
const
|
|
43
|
-
const
|
|
46
|
+
const [hoveredCounts, setHoveredCounts] = (0, react.useState)({});
|
|
47
|
+
const [expandedPositions, setExpandedPositions] = (0, react.useState)({});
|
|
48
|
+
const [hoveredGroups, setHoveredGroups] = (0, react.useState)({});
|
|
49
|
+
const [pinnedPosition, setPinnedPosition] = (0, react.useState)(null);
|
|
50
|
+
const collapseTimeouts = (0, react.useRef)({});
|
|
51
|
+
const hoveredCount = Object.values(hoveredCounts).reduce((acc, count) => acc + (count ?? 0), 0) + Object.values(hoveredGroups).filter(Boolean).length;
|
|
52
|
+
const handleHoverStart = (0, react.useCallback)((pos) => setHoveredCounts((current) => ({
|
|
53
|
+
...current,
|
|
54
|
+
[pos]: (current[pos] ?? 0) + 1
|
|
55
|
+
})), []);
|
|
56
|
+
const handleHoverEnd = (0, react.useCallback)((pos) => setHoveredCounts((current) => ({
|
|
57
|
+
...current,
|
|
58
|
+
[pos]: Math.max(0, (current[pos] ?? 0) - 1)
|
|
59
|
+
})), []);
|
|
60
|
+
const getGroupHoverProps = (0, react.useCallback)((pos) => layout === "stacked" ? {
|
|
61
|
+
onMouseEnter: () => setHoveredGroups((current) => ({
|
|
62
|
+
...current,
|
|
63
|
+
[pos]: true
|
|
64
|
+
})),
|
|
65
|
+
onMouseLeave: () => setHoveredGroups((current) => ({
|
|
66
|
+
...current,
|
|
67
|
+
[pos]: false
|
|
68
|
+
}))
|
|
69
|
+
} : {}, [layout]);
|
|
70
|
+
const handleExpandRequest = (0, react.useCallback)((pos) => setPinnedPosition(pos), []);
|
|
71
|
+
(0, react.useEffect)(() => {
|
|
72
|
+
if (layout !== "stacked") return;
|
|
73
|
+
const timeouts = collapseTimeouts.current;
|
|
74
|
+
require_get_grouped_notifications.positions.forEach((pos) => {
|
|
75
|
+
if ((hoveredCounts[pos] ?? 0) > 0 || hoveredGroups[pos] || pinnedPosition === pos) {
|
|
76
|
+
window.clearTimeout(timeouts[pos]);
|
|
77
|
+
setExpandedPositions((current) => current[pos] ? current : {
|
|
78
|
+
...current,
|
|
79
|
+
[pos]: true
|
|
80
|
+
});
|
|
81
|
+
} else timeouts[pos] = window.setTimeout(() => {
|
|
82
|
+
setExpandedPositions((current) => current[pos] ? {
|
|
83
|
+
...current,
|
|
84
|
+
[pos]: false
|
|
85
|
+
} : current);
|
|
86
|
+
}, 200);
|
|
87
|
+
});
|
|
88
|
+
return () => require_get_grouped_notifications.positions.forEach((pos) => window.clearTimeout(timeouts[pos]));
|
|
89
|
+
}, [
|
|
90
|
+
hoveredCounts,
|
|
91
|
+
hoveredGroups,
|
|
92
|
+
pinnedPosition,
|
|
93
|
+
layout
|
|
94
|
+
]);
|
|
95
|
+
(0, react.useEffect)(() => {
|
|
96
|
+
if (!pinnedPosition) return;
|
|
97
|
+
const handlePointerDown = (event) => {
|
|
98
|
+
const target = event.target;
|
|
99
|
+
if (!(target !== null && Object.values(refs.current).some((element) => element?.contains(target)))) setPinnedPosition(null);
|
|
100
|
+
};
|
|
101
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
102
|
+
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
103
|
+
}, [pinnedPosition]);
|
|
104
|
+
const grouped = require_get_grouped_notifications.getGroupedNotifications(data.notifications, position);
|
|
105
|
+
const pinnedCount = pinnedPosition ? grouped[pinnedPosition].length : 0;
|
|
106
|
+
(0, react.useEffect)(() => {
|
|
107
|
+
if (layout !== "stacked" || pinnedPosition !== null && pinnedCount === 0) setPinnedPosition(null);
|
|
108
|
+
}, [
|
|
109
|
+
pinnedCount,
|
|
110
|
+
pinnedPosition,
|
|
111
|
+
layout
|
|
112
|
+
]);
|
|
113
|
+
(0, react.useEffect)(() => {
|
|
114
|
+
if (layout !== "stacked") setHoveredGroups((current) => Object.values(current).some(Boolean) ? {} : current);
|
|
115
|
+
}, [layout]);
|
|
116
|
+
const resizeObserver = (0, react.useRef)(null);
|
|
117
|
+
const measuredHeights = (0, react.useRef)({});
|
|
118
|
+
const observedIds = (0, react.useRef)(/* @__PURE__ */ new WeakMap());
|
|
119
|
+
const measureNotification = (0, react.useCallback)((id, element) => {
|
|
120
|
+
const height = element.offsetHeight;
|
|
121
|
+
if (measuredHeights.current[id] === height) return false;
|
|
122
|
+
measuredHeights.current[id] = height;
|
|
123
|
+
return true;
|
|
124
|
+
}, []);
|
|
125
|
+
(0, react.useEffect)(() => {
|
|
126
|
+
if (layout !== "stacked" || typeof ResizeObserver === "undefined") return;
|
|
127
|
+
const observer = new ResizeObserver((entries) => {
|
|
128
|
+
let changed = false;
|
|
129
|
+
entries.forEach((entry) => {
|
|
130
|
+
const id = observedIds.current.get(entry.target);
|
|
131
|
+
if (id && measureNotification(id, entry.target)) changed = true;
|
|
132
|
+
});
|
|
133
|
+
if (changed) forceUpdate();
|
|
134
|
+
});
|
|
135
|
+
resizeObserver.current = observer;
|
|
136
|
+
Object.values(refs.current).forEach((element) => element && observer.observe(element));
|
|
137
|
+
return () => {
|
|
138
|
+
observer.disconnect();
|
|
139
|
+
resizeObserver.current = null;
|
|
140
|
+
};
|
|
141
|
+
}, [
|
|
142
|
+
layout,
|
|
143
|
+
forceUpdate,
|
|
144
|
+
measureNotification
|
|
145
|
+
]);
|
|
146
|
+
const refCallbacks = (0, react.useRef)({});
|
|
147
|
+
const getNotificationRef = (0, react.useCallback)((id) => {
|
|
148
|
+
if (!refCallbacks.current[id]) refCallbacks.current[id] = (node) => {
|
|
149
|
+
const previous = refs.current[id];
|
|
150
|
+
if (previous && previous !== node) {
|
|
151
|
+
resizeObserver.current?.unobserve(previous);
|
|
152
|
+
observedIds.current.delete(previous);
|
|
153
|
+
}
|
|
154
|
+
if (node) {
|
|
155
|
+
refs.current[id] = node;
|
|
156
|
+
observedIds.current.set(node, id);
|
|
157
|
+
measureNotification(id, node);
|
|
158
|
+
resizeObserver.current?.observe(node);
|
|
159
|
+
} else {
|
|
160
|
+
delete refs.current[id];
|
|
161
|
+
delete refCallbacks.current[id];
|
|
162
|
+
delete measuredHeights.current[id];
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
return refCallbacks.current[id];
|
|
166
|
+
}, [measureNotification]);
|
|
44
167
|
const duration = (theme.respectReducedMotion ? shouldReduceMotion : false) ? 1 : transitionDuration;
|
|
45
168
|
const getStyles = (0, _mantine_core.useStyles)({
|
|
46
169
|
name: "Notifications",
|
|
@@ -66,37 +189,57 @@ const Notifications = (0, _mantine_core.factory)((_props) => {
|
|
|
66
189
|
if (data.notifications.length > previousLength.current) setTimeout(() => forceUpdate(), 0);
|
|
67
190
|
previousLength.current = data.notifications.length;
|
|
68
191
|
}, [data.notifications]);
|
|
69
|
-
const grouped = require_get_grouped_notifications.getGroupedNotifications(data.notifications, position);
|
|
70
192
|
const groupedComponents = require_get_grouped_notifications.positions.reduce((acc, pos) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
193
|
+
const groupLength = grouped[pos].length;
|
|
194
|
+
const expandedOffsets = new Array(groupLength).fill(0);
|
|
195
|
+
const stackExpanded = layout === "stacked" && !!expandedPositions[pos];
|
|
196
|
+
const stackOrder = layout === "stacked" ? [...grouped[pos]].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || (b.__sequence ?? 0) - (a.__sequence ?? 0)) : grouped[pos];
|
|
197
|
+
if (stackExpanded && groupLength > 0) {
|
|
198
|
+
const direction = pos.startsWith("top") ? 1 : -1;
|
|
199
|
+
let cumOffset = 0;
|
|
200
|
+
for (let i = 0; i < groupLength; i += 1) {
|
|
201
|
+
expandedOffsets[i] = cumOffset * direction;
|
|
202
|
+
cumOffset += (measuredHeights.current[stackOrder[i].id] || FALLBACK_NOTIFICATION_HEIGHT) + STACK_EXPANDED_GAP;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
acc[pos] = stackOrder.map((item, stackIndex) => {
|
|
206
|
+
const { style: notificationStyle, ...notification } = item;
|
|
207
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Transition, {
|
|
208
|
+
timeout: duration,
|
|
209
|
+
onEnter: () => refs.current[notification.id].offsetHeight,
|
|
210
|
+
nodeRef: { current: refs.current[notification.id] },
|
|
211
|
+
children: (state) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_NotificationContainer.NotificationContainer, {
|
|
212
|
+
ref: getNotificationRef(notification.id),
|
|
213
|
+
data: notification,
|
|
214
|
+
onHide: (id) => require_notifications_store.hideNotification(id, store),
|
|
215
|
+
autoClose,
|
|
216
|
+
transitionDuration: duration,
|
|
217
|
+
allowDragDismiss,
|
|
218
|
+
allowScrollDismiss,
|
|
219
|
+
paused: (pauseResetOnHover === "all" ? hoveredCount > 0 : false) || layout === "stacked" && !stackExpanded && stackIndex > 0,
|
|
220
|
+
onHoverStart: () => handleHoverStart(pos),
|
|
221
|
+
onHoverEnd: () => handleHoverEnd(pos),
|
|
222
|
+
onExpandRequest: () => handleExpandRequest(pos),
|
|
223
|
+
renderNotification: "renderNotification" in notification ? notification.renderNotification : renderNotification,
|
|
224
|
+
layout,
|
|
225
|
+
stackIndex,
|
|
226
|
+
stackSize: groupLength,
|
|
227
|
+
stackPosition: pos,
|
|
228
|
+
stackExpanded,
|
|
229
|
+
stackExpandedOffset: expandedOffsets[stackIndex],
|
|
230
|
+
transitionState: state,
|
|
231
|
+
...getStyles("notification", { style: {
|
|
232
|
+
...require_get_notification_state_styles.getNotificationStateStyles({
|
|
233
|
+
state,
|
|
234
|
+
position: pos,
|
|
235
|
+
transitionDuration: duration,
|
|
236
|
+
maxHeight: notificationMaxHeight
|
|
237
|
+
}),
|
|
238
|
+
...notificationStyle
|
|
239
|
+
} })
|
|
240
|
+
})
|
|
241
|
+
}, notification.id);
|
|
242
|
+
});
|
|
100
243
|
return acc;
|
|
101
244
|
}, {});
|
|
102
245
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_mantine_core.OptionalPortal, {
|
|
@@ -106,38 +249,62 @@ const Notifications = (0, _mantine_core.factory)((_props) => {
|
|
|
106
249
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
107
250
|
...getStyles("root"),
|
|
108
251
|
"data-position": "top-center",
|
|
252
|
+
"data-layout": layout,
|
|
109
253
|
...others,
|
|
110
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
254
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
255
|
+
...getGroupHoverProps("top-center"),
|
|
256
|
+
children: groupedComponents["top-center"]
|
|
257
|
+
})
|
|
111
258
|
}),
|
|
112
259
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
113
260
|
...getStyles("root"),
|
|
114
261
|
"data-position": "top-left",
|
|
262
|
+
"data-layout": layout,
|
|
115
263
|
...others,
|
|
116
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
264
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
265
|
+
...getGroupHoverProps("top-left"),
|
|
266
|
+
children: groupedComponents["top-left"]
|
|
267
|
+
})
|
|
117
268
|
}),
|
|
118
269
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
119
270
|
...getStyles("root", { className: _mantine_core.RemoveScroll.classNames.fullWidth }),
|
|
120
271
|
"data-position": "top-right",
|
|
272
|
+
"data-layout": layout,
|
|
121
273
|
...others,
|
|
122
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
274
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
275
|
+
...getGroupHoverProps("top-right"),
|
|
276
|
+
children: groupedComponents["top-right"]
|
|
277
|
+
})
|
|
123
278
|
}),
|
|
124
279
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
125
280
|
...getStyles("root", { className: _mantine_core.RemoveScroll.classNames.fullWidth }),
|
|
126
281
|
"data-position": "bottom-right",
|
|
282
|
+
"data-layout": layout,
|
|
127
283
|
...others,
|
|
128
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
284
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
285
|
+
...getGroupHoverProps("bottom-right"),
|
|
286
|
+
children: groupedComponents["bottom-right"]
|
|
287
|
+
})
|
|
129
288
|
}),
|
|
130
289
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
131
290
|
...getStyles("root"),
|
|
132
291
|
"data-position": "bottom-left",
|
|
292
|
+
"data-layout": layout,
|
|
133
293
|
...others,
|
|
134
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
294
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
295
|
+
...getGroupHoverProps("bottom-left"),
|
|
296
|
+
children: groupedComponents["bottom-left"]
|
|
297
|
+
})
|
|
135
298
|
}),
|
|
136
299
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Box, {
|
|
137
300
|
...getStyles("root"),
|
|
138
301
|
"data-position": "bottom-center",
|
|
302
|
+
"data-layout": layout,
|
|
139
303
|
...others,
|
|
140
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
304
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.TransitionGroup, {
|
|
305
|
+
...getGroupHoverProps("bottom-center"),
|
|
306
|
+
children: groupedComponents["bottom-center"]
|
|
307
|
+
})
|
|
141
308
|
})
|
|
142
309
|
]
|
|
143
310
|
});
|