UNPKG

10.3 kBJavaScriptView Raw
1'use client';
2
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import composeClasses from '@mui/utils/composeClasses';
6import useSlotProps from '@mui/utils/useSlotProps';
7import useSnackbar from "./useSnackbar.js";
8import ClickAwayListener from "../ClickAwayListener/index.js";
9import { styled, useTheme } from "../zero-styled/index.js";
10import memoTheme from "../utils/memoTheme.js";
11import { useDefaultProps } from "../DefaultPropsProvider/index.js";
12import capitalize from "../utils/capitalize.js";
13import Grow from "../Grow/index.js";
14import SnackbarContent from "../SnackbarContent/index.js";
15import { getSnackbarUtilityClass } from "./snackbarClasses.js";
16import { jsx as _jsx } from "react/jsx-runtime";
17const useUtilityClasses = ownerState => {
18 const {
19 classes,
20 anchorOrigin
21 } = ownerState;
22 const slots = {
23 root: ['root', `anchorOrigin${capitalize(anchorOrigin.vertical)}${capitalize(anchorOrigin.horizontal)}`]
24 };
25 return composeClasses(slots, getSnackbarUtilityClass, classes);
26};
27const SnackbarRoot = styled('div', {
28 name: 'MuiSnackbar',
29 slot: 'Root',
30 overridesResolver: (props, styles) => {
31 const {
32 ownerState
33 } = props;
34 return [styles.root, styles[`anchorOrigin${capitalize(ownerState.anchorOrigin.vertical)}${capitalize(ownerState.anchorOrigin.horizontal)}`]];
35 }
36})(memoTheme(({
37 theme
38}) => ({
39 zIndex: (theme.vars || theme).zIndex.snackbar,
40 position: 'fixed',
41 display: 'flex',
42 left: 8,
43 right: 8,
44 justifyContent: 'center',
45 alignItems: 'center',
46 variants: [{
47 props: ({
48 ownerState
49 }) => ownerState.anchorOrigin.vertical === 'top',
50 style: {
51 top: 8,
52 [theme.breakpoints.up('sm')]: {
53 top: 24
54 }
55 }
56 }, {
57 props: ({
58 ownerState
59 }) => ownerState.anchorOrigin.vertical !== 'top',
60 style: {
61 bottom: 8,
62 [theme.breakpoints.up('sm')]: {
63 bottom: 24
64 }
65 }
66 }, {
67 props: ({
68 ownerState
69 }) => ownerState.anchorOrigin.horizontal === 'left',
70 style: {
71 justifyContent: 'flex-start',
72 [theme.breakpoints.up('sm')]: {
73 left: 24,
74 right: 'auto'
75 }
76 }
77 }, {
78 props: ({
79 ownerState
80 }) => ownerState.anchorOrigin.horizontal === 'right',
81 style: {
82 justifyContent: 'flex-end',
83 [theme.breakpoints.up('sm')]: {
84 right: 24,
85 left: 'auto'
86 }
87 }
88 }, {
89 props: ({
90 ownerState
91 }) => ownerState.anchorOrigin.horizontal === 'center',
92 style: {
93 [theme.breakpoints.up('sm')]: {
94 left: '50%',
95 right: 'auto',
96 transform: 'translateX(-50%)'
97 }
98 }
99 }]
100})));
101const Snackbar = /*#__PURE__*/React.forwardRef(function Snackbar(inProps, ref) {
102 const props = useDefaultProps({
103 props: inProps,
104 name: 'MuiSnackbar'
105 });
106 const theme = useTheme();
107 const defaultTransitionDuration = {
108 enter: theme.transitions.duration.enteringScreen,
109 exit: theme.transitions.duration.leavingScreen
110 };
111 const {
112 action,
113 anchorOrigin: {
114 vertical,
115 horizontal
116 } = {
117 vertical: 'bottom',
118 horizontal: 'left'
119 },
120 autoHideDuration = null,
121 children,
122 className,
123 ClickAwayListenerProps,
124 ContentProps,
125 disableWindowBlurListener = false,
126 message,
127 onBlur,
128 onClose,
129 onFocus,
130 onMouseEnter,
131 onMouseLeave,
132 open,
133 resumeHideDuration,
134 TransitionComponent = Grow,
135 transitionDuration = defaultTransitionDuration,
136 TransitionProps: {
137 onEnter,
138 onExited,
139 ...TransitionProps
140 } = {},
141 ...other
142 } = props;
143 const ownerState = {
144 ...props,
145 anchorOrigin: {
146 vertical,
147 horizontal
148 },
149 autoHideDuration,
150 disableWindowBlurListener,
151 TransitionComponent,
152 transitionDuration
153 };
154 const classes = useUtilityClasses(ownerState);
155 const {
156 getRootProps,
157 onClickAway
158 } = useSnackbar({
159 ...ownerState
160 });
161 const [exited, setExited] = React.useState(true);
162 const rootProps = useSlotProps({
163 elementType: SnackbarRoot,
164 getSlotProps: getRootProps,
165 externalForwardedProps: other,
166 ownerState,
167 additionalProps: {
168 ref
169 },
170 className: [classes.root, className]
171 });
172 const handleExited = node => {
173 setExited(true);
174 if (onExited) {
175 onExited(node);
176 }
177 };
178 const handleEnter = (node, isAppearing) => {
179 setExited(false);
180 if (onEnter) {
181 onEnter(node, isAppearing);
182 }
183 };
184
185 // So we only render active snackbars.
186 if (!open && exited) {
187 return null;
188 }
189 return /*#__PURE__*/_jsx(ClickAwayListener, {
190 onClickAway: onClickAway,
191 ...ClickAwayListenerProps,
192 children: /*#__PURE__*/_jsx(SnackbarRoot, {
193 ...rootProps,
194 children: /*#__PURE__*/_jsx(TransitionComponent, {
195 appear: true,
196 in: open,
197 timeout: transitionDuration,
198 direction: vertical === 'top' ? 'down' : 'up',
199 onEnter: handleEnter,
200 onExited: handleExited,
201 ...TransitionProps,
202 children: children || /*#__PURE__*/_jsx(SnackbarContent, {
203 message: message,
204 action: action,
205 ...ContentProps
206 })
207 })
208 })
209 });
210});
211process.env.NODE_ENV !== "production" ? Snackbar.propTypes /* remove-proptypes */ = {
212 // ┌────────────────────────────── Warning ──────────────────────────────┐
213 // │ These PropTypes are generated from the TypeScript type definitions. │
214 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
215 // └─────────────────────────────────────────────────────────────────────┘
216 /**
217 * The action to display. It renders after the message, at the end of the snackbar.
218 */
219 action: PropTypes.node,
220 /**
221 * The anchor of the `Snackbar`.
222 * On smaller screens, the component grows to occupy all the available width,
223 * the horizontal alignment is ignored.
224 * @default { vertical: 'bottom', horizontal: 'left' }
225 */
226 anchorOrigin: PropTypes.shape({
227 horizontal: PropTypes.oneOf(['center', 'left', 'right']).isRequired,
228 vertical: PropTypes.oneOf(['bottom', 'top']).isRequired
229 }),
230 /**
231 * The number of milliseconds to wait before automatically calling the
232 * `onClose` function. `onClose` should then set the state of the `open`
233 * prop to hide the Snackbar. This behavior is disabled by default with
234 * the `null` value.
235 * @default null
236 */
237 autoHideDuration: PropTypes.number,
238 /**
239 * Replace the `SnackbarContent` component.
240 */
241 children: PropTypes.element,
242 /**
243 * Override or extend the styles applied to the component.
244 */
245 classes: PropTypes.object,
246 /**
247 * @ignore
248 */
249 className: PropTypes.string,
250 /**
251 * Props applied to the `ClickAwayListener` element.
252 */
253 ClickAwayListenerProps: PropTypes.object,
254 /**
255 * Props applied to the [`SnackbarContent`](https://mui.com/material-ui/api/snackbar-content/) element.
256 */
257 ContentProps: PropTypes.object,
258 /**
259 * If `true`, the `autoHideDuration` timer will expire even if the window is not focused.
260 * @default false
261 */
262 disableWindowBlurListener: PropTypes.bool,
263 /**
264 * When displaying multiple consecutive snackbars using a single parent-rendered
265 * `<Snackbar/>`, add the `key` prop to ensure independent treatment of each message.
266 * For instance, use `<Snackbar key={message} />`. Otherwise, messages might update
267 * in place, and features like `autoHideDuration` could be affected.
268 */
269 key: () => null,
270 /**
271 * The message to display.
272 */
273 message: PropTypes.node,
274 /**
275 * @ignore
276 */
277 onBlur: PropTypes.func,
278 /**
279 * Callback fired when the component requests to be closed.
280 * Typically `onClose` is used to set state in the parent component,
281 * which is used to control the `Snackbar` `open` prop.
282 * The `reason` parameter can optionally be used to control the response to `onClose`,
283 * for example ignoring `clickaway`.
284 *
285 * @param {React.SyntheticEvent<any> | Event} event The event source of the callback.
286 * @param {string} reason Can be: `"timeout"` (`autoHideDuration` expired), `"clickaway"`, or `"escapeKeyDown"`.
287 */
288 onClose: PropTypes.func,
289 /**
290 * @ignore
291 */
292 onFocus: PropTypes.func,
293 /**
294 * @ignore
295 */
296 onMouseEnter: PropTypes.func,
297 /**
298 * @ignore
299 */
300 onMouseLeave: PropTypes.func,
301 /**
302 * If `true`, the component is shown.
303 */
304 open: PropTypes.bool,
305 /**
306 * The number of milliseconds to wait before dismissing after user interaction.
307 * If `autoHideDuration` prop isn't specified, it does nothing.
308 * If `autoHideDuration` prop is specified but `resumeHideDuration` isn't,
309 * we default to `autoHideDuration / 2` ms.
310 */
311 resumeHideDuration: PropTypes.number,
312 /**
313 * The system prop that allows defining system overrides as well as additional CSS styles.
314 */
315 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
316 /**
317 * The component used for the transition.
318 * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.
319 * @default Grow
320 */
321 TransitionComponent: PropTypes.elementType,
322 /**
323 * The duration for the transition, in milliseconds.
324 * You may specify a single timeout for all transitions, or individually with an object.
325 * @default {
326 * enter: theme.transitions.duration.enteringScreen,
327 * exit: theme.transitions.duration.leavingScreen,
328 * }
329 */
330 transitionDuration: PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
331 appear: PropTypes.number,
332 enter: PropTypes.number,
333 exit: PropTypes.number
334 })]),
335 /**
336 * Props applied to the transition element.
337 * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component.
338 * @default {}
339 */
340 TransitionProps: PropTypes.object
341} : void 0;
342export default Snackbar;
\No newline at end of file