UNPKG

4.55 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import * as React from 'react';
3import { unstable_useEventCallback as useEventCallback } from '@mui/utils';
4import extractEventHandlers from '../utils/extractEventHandlers';
5
6/**
7 * The basic building block for creating custom snackbar.
8 *
9 * Demos:
10 *
11 * - [Snackbar](https://mui.com/base/react-snackbar/#hook)
12 *
13 * API:
14 *
15 * - [useSnackbar API](https://mui.com/base/react-snackbar/hooks-api/#use-snackbar)
16 */
17export default function useSnackbar(parameters) {
18 const {
19 autoHideDuration = null,
20 disableWindowBlurListener = false,
21 onClose,
22 open,
23 resumeHideDuration
24 } = parameters;
25 const timerAutoHide = React.useRef();
26 React.useEffect(() => {
27 if (!open) {
28 return undefined;
29 }
30
31 /**
32 * @param {KeyboardEvent} nativeEvent
33 */
34 function handleKeyDown(nativeEvent) {
35 if (!nativeEvent.defaultPrevented) {
36 // IE11, Edge (prior to using Blink?) use 'Esc'
37 if (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc') {
38 // not calling `preventDefault` since we don't know if people may ignore this event e.g. a permanently open snackbar
39 onClose?.(nativeEvent, 'escapeKeyDown');
40 }
41 }
42 }
43 document.addEventListener('keydown', handleKeyDown);
44 return () => {
45 document.removeEventListener('keydown', handleKeyDown);
46 };
47 }, [open, onClose]);
48 const handleClose = useEventCallback((event, reason) => {
49 onClose?.(event, reason);
50 });
51 const setAutoHideTimer = useEventCallback(autoHideDurationParam => {
52 if (!onClose || autoHideDurationParam == null) {
53 return;
54 }
55 clearTimeout(timerAutoHide.current);
56 timerAutoHide.current = setTimeout(() => {
57 handleClose(null, 'timeout');
58 }, autoHideDurationParam);
59 });
60 React.useEffect(() => {
61 if (open) {
62 setAutoHideTimer(autoHideDuration);
63 }
64 return () => {
65 clearTimeout(timerAutoHide.current);
66 };
67 }, [open, autoHideDuration, setAutoHideTimer]);
68 const handleClickAway = event => {
69 onClose?.(event, 'clickaway');
70 };
71
72 // Pause the timer when the user is interacting with the Snackbar
73 // or when the user hide the window.
74 const handlePause = () => {
75 clearTimeout(timerAutoHide.current);
76 };
77
78 // Restart the timer when the user is no longer interacting with the Snackbar
79 // or when the window is shown back.
80 const handleResume = React.useCallback(() => {
81 if (autoHideDuration != null) {
82 setAutoHideTimer(resumeHideDuration != null ? resumeHideDuration : autoHideDuration * 0.5);
83 }
84 }, [autoHideDuration, resumeHideDuration, setAutoHideTimer]);
85 const createHandleBlur = otherHandlers => event => {
86 const onBlurCallback = otherHandlers.onBlur;
87 onBlurCallback?.(event);
88 handleResume();
89 };
90 const createHandleFocus = otherHandlers => event => {
91 const onFocusCallback = otherHandlers.onFocus;
92 onFocusCallback?.(event);
93 handlePause();
94 };
95 const createMouseEnter = otherHandlers => event => {
96 const onMouseEnterCallback = otherHandlers.onMouseEnter;
97 onMouseEnterCallback?.(event);
98 handlePause();
99 };
100 const createMouseLeave = otherHandlers => event => {
101 const onMouseLeaveCallback = otherHandlers.onMouseLeave;
102 onMouseLeaveCallback?.(event);
103 handleResume();
104 };
105 React.useEffect(() => {
106 // TODO: window global should be refactored here
107 if (!disableWindowBlurListener && open) {
108 window.addEventListener('focus', handleResume);
109 window.addEventListener('blur', handlePause);
110 return () => {
111 window.removeEventListener('focus', handleResume);
112 window.removeEventListener('blur', handlePause);
113 };
114 }
115 return undefined;
116 }, [disableWindowBlurListener, handleResume, open]);
117 const getRootProps = (otherHandlers = {}) => {
118 const propsEventHandlers = extractEventHandlers(parameters);
119 const externalEventHandlers = _extends({}, propsEventHandlers, otherHandlers);
120 return _extends({
121 // ClickAwayListener adds an `onClick` prop which results in the alert not being announced.
122 // See https://github.com/mui/material-ui/issues/29080
123 role: 'presentation'
124 }, externalEventHandlers, {
125 onBlur: createHandleBlur(externalEventHandlers),
126 onFocus: createHandleFocus(externalEventHandlers),
127 onMouseEnter: createMouseEnter(externalEventHandlers),
128 onMouseLeave: createMouseLeave(externalEventHandlers)
129 });
130 };
131 return {
132 getRootProps,
133 onClickAway: handleClickAway
134 };
135}
\No newline at end of file