'use client'; import type { SnackbarItem, SnackbarPlacement } from '../types'; import { addSnackbarToState, closeAllSnackbarsInState, closeOverflowedSnackbarsInState, closeSnackbarInState, removeSnackbarFromState, type SnackbarState, updateSnackbarPropsInState, } from './snackbarStateHelpers'; export type SnackbarStore = { getState: () => SnackbarState; getSnackbarsByPlacement: (placement: SnackbarPlacement, limit: number) => SnackbarItem[]; subscribe: (listener: () => void) => () => void; showedSnackbars: Set; addSnackbar: (snackbar: SnackbarItem) => void; removeSnackbar: (id: string) => void; updateSnackbar: (id: string, config: Partial) => void; closeSnackbar: (id: string) => void; closeAll: (showedSnackbars: Set) => void; closeOverflowedSnackbars: (placementSnackbars: SnackbarItem[]) => void; }; export const createSnackbarStore = (): SnackbarStore => { let state: SnackbarState = { snackbars: [], snackbarsToClose: new Set(), }; const listeners = new Set<() => void>(); const showedSnackbars = new Set(); const notify = () => { listeners.forEach((listener) => listener()); }; const setState = (updater: (oldState: SnackbarState) => SnackbarState) => { state = updater(state); notify(); }; return { getState: () => state, getSnackbarsByPlacement: (placement, limit) => { const result: SnackbarItem[] = []; let openedCount = 0; for (const snackbar of state.snackbars) { if (snackbar.snackbarProps.placement !== placement) { continue; } const isClosing = state.snackbarsToClose.has(snackbar.id); if (openedCount >= limit && !isClosing) { break; } result.push(snackbar); if (!isClosing) { openedCount++; } } return result; }, subscribe: (listener) => { listeners.add(listener); return () => listeners.delete(listener); }, showedSnackbars, addSnackbar: (snackbar) => { setState((oldState) => addSnackbarToState(oldState, snackbar)); }, removeSnackbar: (id) => { setState((oldState) => removeSnackbarFromState(oldState, id)); showedSnackbars.delete(id); }, updateSnackbar: (id, config) => { setState((oldState) => updateSnackbarPropsInState(oldState, id, config)); }, closeSnackbar: (id) => { setState((oldState) => closeSnackbarInState(oldState, id)); }, closeAll: (showed) => { setState((oldState) => closeAllSnackbarsInState(oldState, showed)); }, closeOverflowedSnackbars: (placementSnackbars) => { setState((oldState) => closeOverflowedSnackbarsInState(oldState, placementSnackbars)); }, }; };