UNPKG

@mantine/notifications

Version:

Mantine notifications system

1 lines 12.6 kB
{"version":3,"file":"Notifications.mjs","names":["Transition","_Transition","classes"],"sources":["../src/Notifications.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n Transition as _Transition,\n TransitionGroup,\n TransitionStatus,\n} from 'react-transition-group';\nimport {\n BasePortalProps,\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n factory,\n Factory,\n getDefaultZIndex,\n OptionalPortal,\n rem,\n RemoveScroll,\n StylesApiProps,\n useMantineTheme,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport { useDidUpdate, useForceUpdate, useReducedMotion } from '@mantine/hooks';\nimport {\n getGroupedNotifications,\n positions,\n} from './get-grouped-notifications/get-grouped-notifications';\nimport { getNotificationStateStyles } from './get-notification-state-styles';\nimport { NotificationContainer } from './NotificationContainer';\nimport {\n hideNotification,\n NotificationPosition,\n notifications,\n NotificationsStore,\n notificationsStore,\n useNotifications,\n} from './notifications.store';\nimport classes from './Notifications.module.css';\n\nconst Transition: any = _Transition;\n\nexport type NotificationsStylesNames = 'root' | 'notification';\nexport type NotificationsCssVariables = {\n root: '--notifications-z-index' | '--notifications-container-width';\n};\n\nexport interface NotificationsProps\n extends BoxProps, StylesApiProps<NotificationsFactory>, ElementProps<'div'> {\n /** Notifications default position @default 'bottom-right' */\n position?: NotificationPosition;\n\n /** Auto close timeout for all notifications in ms, `false` to disable auto close, can be overwritten for individual notifications in `notifications.show` function @default 4000 */\n autoClose?: number | false;\n\n /** Notification transition duration in ms @default 250 */\n transitionDuration?: number;\n\n /** Determines whether notifications can be dismissed by dragging left or right @default true */\n allowDragDismiss?: boolean;\n\n /** Determines whether notifications can be dismissed with horizontal scroll gesture while hovered @default true */\n allowScrollDismiss?: boolean;\n\n /** Notification width, cannot exceed 100% @default 440 */\n containerWidth?: number | string;\n\n /** Notification `max-height`, used for transitions @default 200 */\n notificationMaxHeight?: number | string;\n\n /** Maximum number of notifications displayed at a time, other new notifications will be added to queue @default 5 */\n limit?: number;\n\n /** Notifications container z-index @default 400 */\n zIndex?: string | number;\n\n /** Props passed down to the `Portal` component */\n portalProps?: BasePortalProps;\n\n /** Store for notifications state, can be used to create multiple instances of notifications system in your application */\n store?: NotificationsStore;\n\n /** Determines whether notifications container should be rendered inside `Portal` @default true */\n withinPortal?: boolean;\n\n /** Determines which notifications should pause auto close on hover, `'all'` – pauses auto close for all notifications when any notification is hovered, `'notification'` – pauses auto close only for the hovered notification @default 'all' */\n pauseResetOnHover?: 'all' | 'notification';\n}\n\nexport type NotificationsFactory = Factory<{\n props: NotificationsProps;\n ref: HTMLDivElement;\n stylesNames: NotificationsStylesNames;\n vars: NotificationsCssVariables;\n staticComponents: {\n show: typeof notifications.show;\n hide: typeof notifications.hide;\n update: typeof notifications.update;\n clean: typeof notifications.clean;\n cleanQueue: typeof notifications.cleanQueue;\n updateState: typeof notifications.updateState;\n };\n}>;\n\nconst defaultProps = {\n position: 'bottom-right',\n autoClose: 4000,\n transitionDuration: 250,\n allowDragDismiss: true,\n allowScrollDismiss: true,\n containerWidth: 440,\n notificationMaxHeight: 200,\n limit: 5,\n zIndex: getDefaultZIndex('overlay'),\n store: notificationsStore,\n withinPortal: true,\n pauseResetOnHover: 'all',\n} satisfies Partial<NotificationsProps>;\n\nconst varsResolver = createVarsResolver<NotificationsFactory>((_, { zIndex, containerWidth }) => ({\n root: {\n '--notifications-z-index': zIndex?.toString(),\n '--notifications-container-width': rem(containerWidth),\n },\n}));\n\nexport const Notifications = factory<NotificationsFactory>((_props) => {\n const props = useProps('Notifications', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n attributes,\n position,\n autoClose,\n transitionDuration,\n allowDragDismiss,\n allowScrollDismiss,\n containerWidth,\n notificationMaxHeight,\n limit,\n zIndex,\n store,\n portalProps,\n withinPortal,\n pauseResetOnHover,\n ...others\n } = props;\n\n const theme = useMantineTheme();\n const data = useNotifications(store);\n const forceUpdate = useForceUpdate();\n const shouldReduceMotion = useReducedMotion();\n const refs = useRef<Record<string, HTMLDivElement>>({});\n const previousLength = useRef<number>(0);\n const [hoveredCount, setHoveredCount] = useState(0);\n\n const handleHoverStart = useCallback(() => setHoveredCount((c) => c + 1), []);\n const handleHoverEnd = useCallback(() => setHoveredCount((c) => Math.max(0, c - 1)), []);\n\n const reduceMotion = theme.respectReducedMotion ? shouldReduceMotion : false;\n const duration = reduceMotion ? 1 : transitionDuration;\n\n const getStyles = useStyles<NotificationsFactory>({\n name: 'Notifications',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n useEffect(() => {\n store?.updateState((current) => ({\n ...current,\n limit: limit || 5,\n defaultPosition: position,\n }));\n }, [limit, position]);\n\n useDidUpdate(() => {\n if (data.notifications.length > previousLength.current) {\n setTimeout(() => forceUpdate(), 0);\n }\n previousLength.current = data.notifications.length;\n }, [data.notifications]);\n\n const grouped = getGroupedNotifications(data.notifications, position);\n const groupedComponents = positions.reduce(\n (acc, pos) => {\n acc[pos] = grouped[pos].map(({ style: notificationStyle, ...notification }) => (\n <Transition\n key={notification.id}\n timeout={duration}\n onEnter={() => refs.current[notification.id!].offsetHeight}\n nodeRef={{ current: refs.current[notification.id!] }}\n >\n {(state: TransitionStatus) => (\n <NotificationContainer\n ref={(node) => {\n if (node) {\n refs.current[notification.id!] = node;\n }\n }}\n data={notification}\n onHide={(id) => hideNotification(id, store)}\n autoClose={autoClose}\n transitionDuration={duration}\n allowDragDismiss={allowDragDismiss}\n allowScrollDismiss={allowScrollDismiss}\n paused={pauseResetOnHover === 'all' ? hoveredCount > 0 : false}\n onHoverStart={handleHoverStart}\n onHoverEnd={handleHoverEnd}\n {...getStyles('notification', {\n style: {\n ...getNotificationStateStyles({\n state,\n position: pos,\n transitionDuration: duration,\n maxHeight: notificationMaxHeight,\n }),\n ...notificationStyle,\n },\n })}\n />\n )}\n </Transition>\n ));\n\n return acc;\n },\n {} as Record<NotificationPosition, React.ReactNode>\n );\n\n return (\n <OptionalPortal withinPortal={withinPortal} {...portalProps}>\n <Box {...getStyles('root')} data-position=\"top-center\" {...others}>\n <TransitionGroup>{groupedComponents['top-center']}</TransitionGroup>\n </Box>\n\n <Box {...getStyles('root')} data-position=\"top-left\" {...others}>\n <TransitionGroup>{groupedComponents['top-left']}</TransitionGroup>\n </Box>\n\n <Box\n {...getStyles('root', { className: RemoveScroll.classNames.fullWidth })}\n data-position=\"top-right\"\n {...others}\n >\n <TransitionGroup>{groupedComponents['top-right']}</TransitionGroup>\n </Box>\n\n <Box\n {...getStyles('root', { className: RemoveScroll.classNames.fullWidth })}\n data-position=\"bottom-right\"\n {...others}\n >\n <TransitionGroup>{groupedComponents['bottom-right']}</TransitionGroup>\n </Box>\n\n <Box {...getStyles('root')} data-position=\"bottom-left\" {...others}>\n <TransitionGroup>{groupedComponents['bottom-left']}</TransitionGroup>\n </Box>\n\n <Box {...getStyles('root')} data-position=\"bottom-center\" {...others}>\n <TransitionGroup>{groupedComponents['bottom-center']}</TransitionGroup>\n </Box>\n </OptionalPortal>\n );\n});\n\nNotifications.classes = classes;\nNotifications.varsResolver = varsResolver;\nNotifications.displayName = '@mantine/notifications/Notifications';\nNotifications.show = notifications.show;\nNotifications.hide = notifications.hide;\nNotifications.update = notifications.update;\nNotifications.clean = notifications.clean;\nNotifications.cleanQueue = notifications.cleanQueue;\nNotifications.updateState = notifications.updateState;\n"],"mappings":";;;;;;;;;;;;AAwCA,MAAMA,eAAkBC;AAgExB,MAAM,eAAe;CACnB,UAAU;CACV,WAAW;CACX,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,gBAAgB;CAChB,uBAAuB;CACvB,OAAO;CACP,QAAQ,iBAAiB,SAAS;CAClC,OAAO;CACP,cAAc;CACd,mBAAmB;AACrB;AAEA,MAAM,eAAe,oBAA0C,GAAG,EAAE,QAAQ,sBAAsB,EAChG,MAAM;CACJ,2BAA2B,QAAQ,SAAS;CAC5C,mCAAmC,IAAI,cAAc;AACvD,EACF,EAAE;AAEF,MAAa,gBAAgB,SAA+B,WAAW;CACrE,MAAM,QAAQ,SAAS,iBAAiB,cAAc,MAAM;CAC5D,MAAM,EACJ,YACA,WACA,OACA,QACA,UACA,MACA,YACA,UACA,WACA,oBACA,kBACA,oBACA,gBACA,uBACA,OACA,QACA,OACA,aACA,cACA,mBACA,GAAG,WACD;CAEJ,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,OAAO,iBAAiB,KAAK;CACnC,MAAM,cAAc,eAAe;CACnC,MAAM,qBAAqB,iBAAiB;CAC5C,MAAM,OAAO,OAAuC,CAAC,CAAC;CACtD,MAAM,iBAAiB,OAAe,CAAC;CACvC,MAAM,CAAC,cAAc,mBAAmB,SAAS,CAAC;CAElD,MAAM,mBAAmB,kBAAkB,iBAAiB,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;CAC5E,MAAM,iBAAiB,kBAAkB,iBAAiB,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;CAGvF,MAAM,YADe,MAAM,uBAAuB,qBAAqB,SACvC,IAAI;CAEpC,MAAM,YAAY,UAAgC;EAChD,MAAM;EACN,SAAA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,gBAAgB;EACd,OAAO,aAAa,aAAa;GAC/B,GAAG;GACH,OAAO,SAAS;GAChB,iBAAiB;EACnB,EAAE;CACJ,GAAG,CAAC,OAAO,QAAQ,CAAC;CAEpB,mBAAmB;EACjB,IAAI,KAAK,cAAc,SAAS,eAAe,SAC7C,iBAAiB,YAAY,GAAG,CAAC;EAEnC,eAAe,UAAU,KAAK,cAAc;CAC9C,GAAG,CAAC,KAAK,aAAa,CAAC;CAEvB,MAAM,UAAU,wBAAwB,KAAK,eAAe,QAAQ;CACpE,MAAM,oBAAoB,UAAU,QACjC,KAAK,QAAQ;EACZ,IAAI,OAAO,QAAQ,KAAK,KAAK,EAAE,OAAO,mBAAmB,GAAG,mBAC1D,oBAACD,cAAD;GAEE,SAAS;GACT,eAAe,KAAK,QAAQ,aAAa,IAAK;GAC9C,SAAS,EAAE,SAAS,KAAK,QAAQ,aAAa,IAAK;cAEjD,UACA,oBAAC,uBAAD;IACE,MAAM,SAAS;KACb,IAAI,MACF,KAAK,QAAQ,aAAa,MAAO;IAErC;IACA,MAAM;IACN,SAAS,OAAO,iBAAiB,IAAI,KAAK;IAC/B;IACX,oBAAoB;IACF;IACE;IACpB,QAAQ,sBAAsB,QAAQ,eAAe,IAAI;IACzD,cAAc;IACd,YAAY;IACZ,GAAI,UAAU,gBAAgB,EAC5B,OAAO;KACL,GAAG,2BAA2B;MAC5B;MACA,UAAU;MACV,oBAAoB;MACpB,WAAW;KACb,CAAC;KACD,GAAG;IACL,EACF,CAAC;GACF,CAAA;EAEO,GAlCL,aAAa,EAkCR,CACb;EAED,OAAO;CACT,GACA,CAAC,CACH;CAEA,OACE,qBAAC,gBAAD;EAA8B;EAAc,GAAI;YAAhD;GACE,oBAAC,KAAD;IAAK,GAAI,UAAU,MAAM;IAAG,iBAAc;IAAa,GAAI;cACzD,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,cAA+B,CAAA;GAChE,CAAA;GAEL,oBAAC,KAAD;IAAK,GAAI,UAAU,MAAM;IAAG,iBAAc;IAAW,GAAI;cACvD,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,YAA6B,CAAA;GAC9D,CAAA;GAEL,oBAAC,KAAD;IACE,GAAI,UAAU,QAAQ,EAAE,WAAW,aAAa,WAAW,UAAU,CAAC;IACtE,iBAAc;IACd,GAAI;cAEJ,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,aAA8B,CAAA;GAC/D,CAAA;GAEL,oBAAC,KAAD;IACE,GAAI,UAAU,QAAQ,EAAE,WAAW,aAAa,WAAW,UAAU,CAAC;IACtE,iBAAc;IACd,GAAI;cAEJ,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,gBAAiC,CAAA;GAClE,CAAA;GAEL,oBAAC,KAAD;IAAK,GAAI,UAAU,MAAM;IAAG,iBAAc;IAAc,GAAI;cAC1D,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,eAAgC,CAAA;GACjE,CAAA;GAEL,oBAAC,KAAD;IAAK,GAAI,UAAU,MAAM;IAAG,iBAAc;IAAgB,GAAI;cAC5D,oBAAC,iBAAD,EAAA,UAAkB,kBAAkB,iBAAkC,CAAA;GACnE,CAAA;EACS;;AAEpB,CAAC;AAED,cAAc,UAAUE;AACxB,cAAc,eAAe;AAC7B,cAAc,cAAc;AAC5B,cAAc,OAAO,cAAc;AACnC,cAAc,OAAO,cAAc;AACnC,cAAc,SAAS,cAAc;AACrC,cAAc,QAAQ,cAAc;AACpC,cAAc,aAAa,cAAc;AACzC,cAAc,cAAc,cAAc"}