UNPKG

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