function _check_private_redeclaration(obj, privateCollection) {
    if (privateCollection.has(obj)) {
        throw new TypeError("Cannot initialize the same private elements twice on an object");
    }
}
function _class_apply_descriptor_get(receiver, descriptor) {
    if (descriptor.get) {
        return descriptor.get.call(receiver);
    }
    return descriptor.value;
}
function _class_apply_descriptor_set(receiver, descriptor, value) {
    if (descriptor.set) {
        descriptor.set.call(receiver, value);
    } else {
        if (!descriptor.writable) {
            throw new TypeError("attempted to set read only private field");
        }
        descriptor.value = value;
    }
}
function _class_extract_field_descriptor(receiver, privateMap, action) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to " + action + " private field on non-instance");
    }
    return privateMap.get(receiver);
}
function _class_private_field_get(receiver, privateMap) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
    return _class_apply_descriptor_get(receiver, descriptor);
}
function _class_private_field_init(obj, privateMap, value) {
    _check_private_redeclaration(obj, privateMap);
    privateMap.set(obj, value);
}
function _class_private_field_set(receiver, privateMap, value) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
    _class_apply_descriptor_set(receiver, descriptor, value);
    return value;
}
function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
import { nanoid } from "nanoid";
/**
 * @remarks \@since 6.0.0
 */ export const DEFAULT_TOAST_VISIBLE_TIME = 5000;
var _queue = /*#__PURE__*/ new WeakMap(), _timers = /*#__PURE__*/ new WeakMap(), _listeners = /*#__PURE__*/ new WeakMap(), _emit = /*#__PURE__*/ new WeakMap(), _getToastIndex = /*#__PURE__*/ new WeakMap(), _getToast = /*#__PURE__*/ new WeakMap(), /**
   * Starts the exit transition for the currently shown toast and adds the next
   * toast into the queue. This requires a manual call to `this.#emit()`
   * afterwards.
   */ _addToastImmediately = /*#__PURE__*/ new WeakMap(), /**
   * This calls `this.#emit()` if the toast was updated
   */ _updateToast = /*#__PURE__*/ new WeakMap();
/**
 * @see {@link ToastManagerProvider}
 *
 * @remarks \@since 6.0.0
 */ export class ToastManager {
    constructor(){
        _class_private_field_init(this, _queue, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _timers, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _listeners, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _emit, {
            writable: true,
            value: ()=>{
                // shallow clone to ensure react updates
                _class_private_field_set(this, _queue, [
                    ..._class_private_field_get(this, _queue)
                ]);
                _class_private_field_get(this, _listeners).forEach((callback)=>{
                    callback(_class_private_field_get(this, _queue));
                });
            }
        });
        _class_private_field_init(this, _getToastIndex, {
            writable: true,
            value: (toastId)=>{
                if (!toastId) {
                    return -1;
                }
                return _class_private_field_get(this, _queue).findIndex((toast)=>toast.toastId === toastId);
            }
        });
        _class_private_field_init(this, _getToast, {
            writable: true,
            value: (toastId)=>{
                return _class_private_field_get(this, _queue)[_class_private_field_get(this, _getToastIndex).call(this, toastId)];
            }
        });
        _class_private_field_init(this, _addToastImmediately, {
            writable: true,
            value: (nextToast)=>{
                const [current] = _class_private_field_get(this, _queue);
                this.clearTimer(current.toastId);
                _class_private_field_get(this, _queue)[0] = {
                    ...current,
                    visible: false
                };
                if (nextToast.priority === "immediate") {
                    _class_private_field_get(this, _queue).splice(1, 0, nextToast, current);
                } else {
                    _class_private_field_get(this, _queue).splice(1, 0, nextToast);
                }
            }
        });
        _class_private_field_init(this, _updateToast, {
            writable: true,
            value: (toastIdOrIndex, patch)=>{
                const index = typeof toastIdOrIndex === "number" ? toastIdOrIndex : _class_private_field_get(this, _getToastIndex).call(this, toastIdOrIndex);
                if (index === -1) {
                    return;
                }
                _class_private_field_get(this, _queue)[index] = {
                    ..._class_private_field_get(this, _queue)[index],
                    ...patch
                };
                _class_private_field_get(this, _emit).call(this);
            }
        });
        /**
   * This is just used to subscribe to changes in the {@link useToastQueue}.
   *
   * ```tsx
   * useSyncExternalStore(
   *   toastManager.subscribe,
   *   toastManager.getQueue,
   *   toastManager.getQueue,
   * );
   * ```
   *
   * @internal
   */ _define_property(this, "subscribe", (callback)=>{
            _class_private_field_get(this, _listeners).push(callback);
            return ()=>{
                _class_private_field_set(this, _listeners, _class_private_field_get(this, _listeners).filter((cb)=>cb !== callback));
            };
        });
        /**
   * @see {@link subscribe}
   * @internal
   */ _define_property(this, "getQueue", ()=>{
            return _class_private_field_get(this, _queue);
        });
        /**
   * Either adds the toast to the queue or updates an existing toast when using
   * an existing `toastId`.
   *
   * @example
   * Adding toasts
   * ```tsx
   * // create a toast when the user is offline that will not disappear
   * addToast({ toastId: "offline", visibleTime: null });
   *
   * // add a new toast that displays `"Toast"` to the queue
   * addToast({ children: "Toast!" });
   *
   * // add an online toast notification. since these three use the same toast
   * // id, the hide timer will be reset each time
   * addToast({ toastId: "online" });
   * addToast({ toastId: "online" });
   * addToast({ toastId: "online" });
   *
   * // add a server error toast to the queue where the second one will be
   * // ignored
   * addToast({
   *   toastId: "ServerError",
   *   theme: "error",
   *   duplicates: "prevent",
   * });
   * addToast({
   *   toastId: "ServerError",
   *   theme: "error",
   *   duplicates: "prevent",
   * });
   *
   * // add a toast to the queue that has an action button that says "Goodbye"
   * addToast({
   *   children: "Hello, world!",
   *   action: "Goodbye",
   * });
   *
   * // add a toast to the queue that has an action button that says "Goodbye"
   * // and a custom click handler
   * addToast({
   *   children: "Hello, world!",
   *   action: {
   *     onClick: () => {
   *       logout();
   *     },
   *     children: "Goodbye",
   *   },
   * });
   *
   * // add a toast to the queue that renders a react component in the content,
   * // a custom action button implementation (using `ToastActionButton`), and a
   * // close button
   * addToast({
   *   children: <SomeCustomComponent />,
   *   actionButton: <SomeCustomActionButton />,
   *   closeButton: true,
   * });
   * ```
   */ _define_property(this, "addToast", (toast)=>{
            const { toastId = nanoid(), visibleTime = DEFAULT_TOAST_VISIBLE_TIME, role = visibleTime === null ? "alert" : "status", priority = "normal", duplicates = "restart" } = toast;
            const existingIndex = _class_private_field_get(this, _getToastIndex).call(this, toast.toastId);
            if (existingIndex !== -1 && duplicates !== "allow") {
                const existingToast = _class_private_field_get(this, _queue)[existingIndex];
                // reorder/move the existing toast to be the next item in the queue by:
                // - removing the toast from the queue
                // - inserting it into the next position with the updates
                if (priority === "next" && existingIndex > 1) {
                    _class_private_field_get(this, _queue).splice(existingIndex, 1);
                    _class_private_field_get(this, _queue).splice(1, 0, {
                        ...existingToast,
                        ...toast
                    });
                    _class_private_field_get(this, _emit).call(this);
                    return;
                }
                // only need to reorder the queue if it is not being shown
                if ((priority === "replace" || priority === "immediate") && existingIndex !== 0) {
                    _class_private_field_get(this, _queue).splice(existingIndex, 1);
                    _class_private_field_get(this, _addToastImmediately).call(this, {
                        ...existingToast,
                        ...toast
                    });
                    _class_private_field_get(this, _emit).call(this);
                    return;
                }
                const timers = _class_private_field_get(this, _timers).get(toastId);
                if (existingToast.visible && duplicates === "restart" && timers) {
                    _class_private_field_get(this, _timers).set(toastId, {
                        ...timers,
                        elapsedTime: 0
                    });
                    this.startRemoveTimeout(toastId);
                }
                _class_private_field_get(this, _updateToast).call(this, existingIndex, toast);
                return;
            }
            const nextToast = {
                ...toast,
                role,
                paused: false,
                visible: true,
                toastId,
                priority,
                duplicates,
                visibleTime
            };
            const queueSize = _class_private_field_get(this, _queue).length;
            if (priority === "next" && queueSize > 1) {
                _class_private_field_get(this, _queue).splice(1, 0, nextToast);
            } else if ((priority === "replace" || priority === "immediate") && queueSize > 0) {
                _class_private_field_get(this, _addToastImmediately).call(this, nextToast);
            } else {
                _class_private_field_get(this, _queue).push(nextToast);
            }
            _class_private_field_get(this, _emit).call(this);
        });
        /**
   * Attempts to start the timeout for removing the toast when the `visibleTime`
   * is not null for a toast.
   *
   * @param toastId - The specific toastId to update
   */ _define_property(this, "startRemoveTimeout", (toastId)=>{
            const toast = _class_private_field_get(this, _getToast).call(this, toastId);
            if (!toast) {
                return;
            }
            const { visibleTime } = toast;
            if (visibleTime === null) {
                // Must manually be closed
                return;
            }
            const cached = _class_private_field_get(this, _timers).get(toastId);
            const timers = cached && {
                ...cached
            } || {
                inactive: false,
                startTime: Date.now(),
                elapsedTime: 0
            };
            window.clearTimeout(timers.exitTimeout);
            let duration = visibleTime;
            if (timers.elapsedTime) {
                duration -= timers.elapsedTime;
            }
            timers.inactive = false;
            timers.exitTimeout = window.setTimeout(()=>{
                this.removeToast(toastId, true);
            }, duration);
            _class_private_field_get(this, _timers).set(toastId, timers);
        });
        /**
   * Pauses the remove timeout for a specific toast normally with hover events
   * or the browser becoming inactive.
   *
   * @param toastId - The specific toastId to pause
   */ _define_property(this, "pauseRemoveTimeout", (toastId)=>{
            const toast = _class_private_field_get(this, _getToast).call(this, toastId);
            const cached = _class_private_field_get(this, _timers).get(toastId);
            if (!toast || !cached || cached.inactive) {
                return;
            }
            window.clearTimeout(cached.exitTimeout);
            const timers = {
                ...cached
            };
            timers.inactive = true;
            timers.elapsedTime = Date.now() - timers.startTime + timers.elapsedTime;
            _class_private_field_get(this, _timers).set(toastId, timers);
            _class_private_field_get(this, _updateToast).call(this, toastId, {
                paused: true
            });
        });
        /**
   * Resumes the current remove timeout if it was paused by
   * {@link pauseRemoveTimeout}.
   *
   * @param toastId - The specific toastId to resume
   */ _define_property(this, "resumeRemoveTimeout", (toastId)=>{
            const toastIndex = _class_private_field_get(this, _getToastIndex).call(this, toastId);
            const timers = _class_private_field_get(this, _timers).get(toastId);
            if (toastIndex === -1 || !timers?.startTime) {
                return;
            }
            _class_private_field_get(this, _updateToast).call(this, toastIndex, {
                paused: false
            });
            this.startRemoveTimeout(toastId);
        });
        /**
   * Removes a toast by id from the queue without any exit animation.
   *
   * @param toastId - The specific {@link QueuedToast.toastId}
   * @param transition - Set this to `true` to remove the toast by the exit
   * transition instead of immediately.
   */ _define_property(this, "removeToast", (toastId, transition)=>{
            const toastIndex = _class_private_field_get(this, _getToastIndex).call(this, toastId);
            if (toastIndex === -1) {
                return;
            }
            if (transition) {
                this.clearTimer(toastId);
                _class_private_field_get(this, _updateToast).call(this, toastIndex, {
                    visible: false
                });
                return;
            }
            _class_private_field_get(this, _queue).splice(toastIndex, 1);
            _class_private_field_get(this, _emit).call(this);
        });
        /**
   * Clears any pending timers for the provided toast id. This should generally
   * be used in the `useEffect` cleanup effect for any custom toast renderer
   * implementations.
   *
   * @example
   * ```tsx
   * const { toastId } = toast;
   * const toastManager = useToastManager();
   *
   * useEffect(() => {
   *   return () => {
   *     toastManager.clearTimer(toastId):
   *   }
   * }, [toastManager, toastId]);
   * ```
   */ _define_property(this, "clearTimer", (toastId)=>{
            const timer = _class_private_field_get(this, _timers).get(toastId);
            window.clearTimeout(timer?.exitTimeout);
            _class_private_field_get(this, _timers).delete(toastId);
        });
        /**
   * Removes first toast from the queue without any exit animation. You most
   * likely want to use {@link removeToast} instead.
   */ _define_property(this, "popToast", ()=>{
            _class_private_field_get(this, _queue).pop();
            _class_private_field_get(this, _emit).call(this);
        });
        /**
   * Removes all toasts from the queue. There will be no exit animation.
   *
   * @param disableEmit - Set this to `true` to disable emitting the empty queue.
   * Mostly used for tests.
   */ _define_property(this, "clearToasts", (disableEmit = false)=>{
            _class_private_field_set(this, _queue, []);
            _class_private_field_get(this, _timers).forEach((meta)=>{
                window.clearTimeout(meta.exitTimeout);
            });
            _class_private_field_get(this, _timers).clear();
            if (!disableEmit) {
                _class_private_field_get(this, _emit).call(this);
            }
        });
        _class_private_field_set(this, _queue, []);
        _class_private_field_set(this, _timers, new Map());
        _class_private_field_set(this, _listeners, []);
    // All of the class methods must be arrow functions to preserve the correct
    // `this` value. If they aren't arrow functions, I'd have to wrap each call
    // in an arrow function to work.
    //
    // i.e.
    // useSyncExternalStore(
    //   (cb) => manager.subscribe(cb),
    //   () => manager.getQueue(),
    //   () => manager.getQueue(),
    // );
    }
}
/**
 * The default toast manager for react-md apps that will allow toasts to be
 * added without setting up the {@link ToastManagerProvider}.
 *
 * @internal
 * @remarks \@since 6.0.0
 */ export const toastManager = new ToastManager();
/**
 * @see {@link ToastManager.addToast}
 * @remarks \@since 6.0.0
 */ export const addToast = (toast)=>toastManager.addToast(toast);
/**
 * @see {@link ToastManager.startRemoveTimeout}
 * @remarks \@since 6.0.0
 */ export const startRemoveToastTimeout = (toastId)=>toastManager.startRemoveTimeout(toastId);
/**
 * @see {@link ToastManager.popToast}
 * @remarks \@since 6.0.0
 */ export const popToast = ()=>toastManager.popToast();
/**
 * @see {@link ToastManager.removeToast}
 * @remarks \@since 6.0.0
 */ export const removeToast = (toastId, transition)=>toastManager.removeToast(toastId, transition);
/**
 * @see {@link ToastManager.clearToasts}
 * @remarks \@since 6.0.0
 */ export const clearToasts = ()=>toastManager.clearToasts();

//# sourceMappingURL=ToastManager.js.map