{"version":3,"sources":["../../src/components/SnackbarList.tsx","../../src/components/icons/Close.tsx","../../src/components/SnackbarContext.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { Alert, IconButton, Portal } from '@mui/material';\nimport { styled, useThemeProps, type CSSObject } from '@mui/material/styles';\n\nimport { Close } from './icons';\n\nimport { type AnchorOrigin, useSnackbarNotification } from './SnackbarContext';\n\nexport interface SnackbarListProps extends HTMLAttributes<HTMLDivElement> {\n    anchorOrigin: AnchorOrigin;\n    ariaLabel?: string;\n}\n\ninterface SnackbarListOwnerState {\n    anchorOrigin: AnchorOrigin;\n}\n\nconst positionStyles: Record<AnchorOrigin, CSSObject> = {\n    topLeft: { top: 16, left: 16 },\n    topCenter: { top: 16, left: '50%', transform: 'translateX(-50%)' },\n    topRight: { top: 16, right: 16 },\n    bottomLeft: { bottom: 16, left: 16 },\n    bottomCenter: { bottom: 16, left: '50%', transform: 'translateX(-50%)' },\n    bottomRight: { bottom: 16, right: 16 },\n};\n\nconst severityMap = {\n    default: undefined,\n    success: 'success' as const,\n    error: 'error' as const,\n    warning: 'warning' as const,\n    info: 'info' as const,\n};\n\nconst SnackbarListRoot = styled('div', {\n    name: 'MuiSnackbarList',\n    slot: 'Root',\n})<{ ownerState: SnackbarListOwnerState }>(({ theme, ownerState }) => ({\n    position: 'fixed',\n    display: 'flex',\n    flexDirection: 'column-reverse',\n    gap: theme.spacing(1),\n    zIndex: theme.zIndex.snackbar,\n    ...positionStyles[ownerState.anchorOrigin],\n}));\n\nexport const SnackbarList = forwardRef<HTMLDivElement, SnackbarListProps>(\n    function SnackbarList(inProps, ref) {\n        const props = useThemeProps({ props: inProps, name: 'MuiSnackbarList' });\n        const { anchorOrigin, ariaLabel, className, ...other } = props;\n        const { notifications, removeNotification } = useSnackbarNotification();\n        const items = notifications[anchorOrigin];\n\n        if (items.length === 0) {\n            return null;\n        }\n\n        const ownerState: SnackbarListOwnerState = { anchorOrigin };\n\n        return (\n            <Portal>\n                <SnackbarListRoot\n                    ref={ref}\n                    ownerState={ownerState}\n                    role=\"region\"\n                    aria-label={ariaLabel ?? 'Notifications'}\n                    className={className}\n                    {...other}>\n                    {items.map((notification) => {\n                        const severity = severityMap[notification.variant ?? 'default'];\n                        return (\n                            <Alert\n                                key={notification.id}\n                                severity={severity}\n                                variant=\"filled\"\n                                action={\n                                    <>\n                                        {notification.action}\n                                        <IconButton\n                                            size=\"small\"\n                                            aria-label=\"close\"\n                                            color=\"inherit\"\n                                            sx={{ fontSize: '1.125rem' }}\n                                            onClick={() => {\n                                                removeNotification(anchorOrigin, notification.id);\n                                            }}>\n                                            <Close fontSize=\"inherit\" />\n                                        </IconButton>\n                                    </>\n                                }>\n                                {notification.message}\n                            </Alert>\n                        );\n                    })}\n                </SnackbarListRoot>\n            </Portal>\n        );\n    }\n);\n","import { createSvgIcon } from '@mui/material/utils';\n\nconst Close = createSvgIcon(\n    <svg viewBox=\"0 -960 960 960\">\n        <path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\n    </svg>,\n    'Close'\n);\n\nexport { Close };\n","'use client';\n\nimport { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react';\n\nexport type AnchorOrigin =\n    | 'topLeft'\n    | 'topCenter'\n    | 'topRight'\n    | 'bottomLeft'\n    | 'bottomCenter'\n    | 'bottomRight';\n\nexport interface SnackbarNotification {\n    id: string;\n    message: string;\n    variant?: 'default' | 'success' | 'error' | 'warning' | 'info';\n    autoHideDuration?: number;\n    action?: ReactNode;\n}\n\nexport interface SnackbarNotificationContextValue {\n    notifications: Record<AnchorOrigin, SnackbarNotification[]>;\n    addNotification: (anchor: AnchorOrigin, notification: Omit<SnackbarNotification, 'id'>) => void;\n    removeNotification: (anchor: AnchorOrigin, id: string) => void;\n    clearAll: (anchor: AnchorOrigin) => void;\n}\n\nfunction createEmptyNotifications(): Record<AnchorOrigin, SnackbarNotification[]> {\n    return {\n        topLeft: [],\n        topCenter: [],\n        topRight: [],\n        bottomLeft: [],\n        bottomCenter: [],\n        bottomRight: [],\n    };\n}\n\nconst SnackbarNotificationContext = createContext<SnackbarNotificationContextValue | null>(null);\n\ninterface SnackbarNotificationProviderProps {\n    maxStack?: number;\n    children: ReactNode;\n}\n\nexport function SnackbarNotificationProvider({\n    maxStack = 4,\n    children,\n}: SnackbarNotificationProviderProps) {\n    const [notifications, setNotifications] =\n        useState<Record<AnchorOrigin, SnackbarNotification[]>>(createEmptyNotifications);\n\n    const removeNotification = useCallback((anchor: AnchorOrigin, id: string) => {\n        setNotifications((prev) => ({\n            ...prev,\n            [anchor]: prev[anchor].filter((n) => n.id !== id),\n        }));\n    }, []);\n\n    const addNotification = useCallback(\n        (anchor: AnchorOrigin, notification: Omit<SnackbarNotification, 'id'>) => {\n            const id = crypto.randomUUID();\n            const entry: SnackbarNotification = { ...notification, id };\n\n            setNotifications((prev) => {\n                let list = [...prev[anchor], entry];\n                if (list.length > maxStack) {\n                    list = list.slice(list.length - maxStack);\n                }\n                return { ...prev, [anchor]: list };\n            });\n\n            if (notification.autoHideDuration) {\n                setTimeout(() => {\n                    removeNotification(anchor, id);\n                }, notification.autoHideDuration);\n            }\n        },\n        [maxStack, removeNotification]\n    );\n\n    const clearAll = useCallback((anchor: AnchorOrigin) => {\n        setNotifications((prev) => ({ ...prev, [anchor]: [] }));\n    }, []);\n\n    const value = useMemo<SnackbarNotificationContextValue>(\n        () => ({ notifications, addNotification, removeNotification, clearAll }),\n        [notifications, addNotification, removeNotification, clearAll]\n    );\n\n    return (\n        <SnackbarNotificationContext.Provider value={value}>\n            {children}\n        </SnackbarNotificationContext.Provider>\n    );\n}\n\nexport function useSnackbarNotification(): SnackbarNotificationContextValue {\n    const ctx = useContext(SnackbarNotificationContext);\n    if (!ctx) {\n        throw new Error(\n            'useSnackbarNotification must be used within a SnackbarNotificationProvider'\n        );\n    }\n    return ctx;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAAA,gBAAgD;AAChD,sBAA0C;AAC1C,oBAAsD;;;ACJtD,mBAA8B;AAItB;AAFR,IAAM,YAAQ;AAAA,EACV,4CAAC,SAAI,SAAQ,kBACT,sDAAC,UAAK,GAAE,qGAAoG,GAChH;AAAA,EACA;AACJ;;;ACLA,mBAA0F;AAyFlF,IAAAC,sBAAA;AArDR,IAAM,kCAA8B,4BAAuD,IAAI;AA2DxF,SAAS,0BAA4D;AACxE,QAAM,UAAM,yBAAW,2BAA2B;AAClD,MAAI,CAAC,KAAK;AACN,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ;AACA,SAAO;AACX;;;AF3BoC,IAAAC,sBAAA;AA3DpC,IAAM,iBAAkD;AAAA,EACpD,SAAS,EAAE,KAAK,IAAI,MAAM,GAAG;AAAA,EAC7B,WAAW,EAAE,KAAK,IAAI,MAAM,OAAO,WAAW,mBAAmB;AAAA,EACjE,UAAU,EAAE,KAAK,IAAI,OAAO,GAAG;AAAA,EAC/B,YAAY,EAAE,QAAQ,IAAI,MAAM,GAAG;AAAA,EACnC,cAAc,EAAE,QAAQ,IAAI,MAAM,OAAO,WAAW,mBAAmB;AAAA,EACvE,aAAa,EAAE,QAAQ,IAAI,OAAO,GAAG;AACzC;AAEA,IAAM,cAAc;AAAA,EAChB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AACV;AAEA,IAAM,uBAAmB,sBAAO,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AACV,CAAC,EAA0C,CAAC,EAAE,OAAO,WAAW,OAAO;AAAA,EACnE,UAAU;AAAA,EACV,SAAS;AAAA,EACT,eAAe;AAAA,EACf,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpB,QAAQ,MAAM,OAAO;AAAA,EACrB,GAAG,eAAe,WAAW,YAAY;AAC7C,EAAE;AAEK,IAAM,mBAAe;AAAA,EACxB,SAASC,cAAa,SAAS,KAAK;AAChC,UAAM,YAAQ,6BAAc,EAAE,OAAO,SAAS,MAAM,kBAAkB,CAAC;AACvE,UAAM,EAAE,cAAc,WAAW,WAAW,GAAG,MAAM,IAAI;AACzD,UAAM,EAAE,eAAe,mBAAmB,IAAI,wBAAwB;AACtE,UAAM,QAAQ,cAAc,YAAY;AAExC,QAAI,MAAM,WAAW,GAAG;AACpB,aAAO;AAAA,IACX;AAEA,UAAM,aAAqC,EAAE,aAAa;AAE1D,WACI,6CAAC,0BACG;AAAA,MAAC;AAAA;AAAA,QACG;AAAA,QACA;AAAA,QACA,MAAK;AAAA,QACL,cAAY,aAAa;AAAA,QACzB;AAAA,QACC,GAAG;AAAA,QACH,gBAAM,IAAI,CAAC,iBAAiB;AACzB,gBAAM,WAAW,YAAY,aAAa,WAAW,SAAS;AAC9D,iBACI;AAAA,YAAC;AAAA;AAAA,cAEG;AAAA,cACA,SAAQ;AAAA,cACR,QACI,8EACK;AAAA,6BAAa;AAAA,gBACd;AAAA,kBAAC;AAAA;AAAA,oBACG,MAAK;AAAA,oBACL,cAAW;AAAA,oBACX,OAAM;AAAA,oBACN,IAAI,EAAE,UAAU,WAAW;AAAA,oBAC3B,SAAS,MAAM;AACX,yCAAmB,cAAc,aAAa,EAAE;AAAA,oBACpD;AAAA,oBACA,uDAAC,SAAM,UAAS,WAAU;AAAA;AAAA,gBAC9B;AAAA,iBACJ;AAAA,cAEH,uBAAa;AAAA;AAAA,YAlBT,aAAa;AAAA,UAmBtB;AAAA,QAER,CAAC;AAAA;AAAA,IACL,GACJ;AAAA,EAER;AACJ;","names":["import_react","import_jsx_runtime","import_jsx_runtime","SnackbarList"]}