UNPKG

@svelte-put/modal

Version:
109 lines (108 loc) 3.29 kB
/* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { createEventDispatcher } from 'svelte'; import { writable } from 'svelte/store'; /** * Create a svelte store for handling modal * @example * * ```typescript * import { createModalStore } from '@svelte-put/modal'; * const store = createModalStore(); * ``` * @returns {ModalStore} extended svelte {@link ModalStore} */ export function createModalStore() { const { subscribe, set } = writable([]); let modals = []; const resolveMap = {}; const resolveCallbacks = {}; const push = function (input) { let _resolve; let resolved = false; const promise = new Promise((resolve) => { _resolve = (value) => { resolved = true; resolve(value); }; }); let id = (crypto && crypto.randomUUID && crypto.randomUUID()) ?? `modal-indexed-${modals.length}`; let props; let component; if (typeof input === 'function') { component = input; props = {}; } else { id = input.id ?? id; props = input.props ?? {}; component = input.component; } const pushed = { id, props, component, resolve: () => promise, resolved, }; modals.push(pushed); resolveMap[pushed.id] = _resolve; set([...modals]); return pushed; }; const pop = function (pushed, resolved) { let popped; if (pushed?.id) { modals = modals.filter((modal) => { if (modal.id === pushed.id) { popped = modal; return false; } return true; }); set(modals); } else { popped = modals.pop(); set([...modals]); } if (popped) { const rResolved = { trigger: 'pop', ...(resolved ?? {}), }; resolveMap[popped.id]?.(rResolved); resolveMap[popped.id] = undefined; resolveCallbacks[popped.id]?.forEach((callback) => callback(rResolved)); resolveCallbacks[popped.id] = undefined; } return popped; }; const onPop = function (modalId, callback) { if (!resolveCallbacks[modalId]) { resolveCallbacks[modalId] = [callback]; } else if (!resolveCallbacks[modalId]?.includes(callback)) { resolveCallbacks[modalId]?.push(callback); } return () => { if (resolveCallbacks[modalId]) { resolveCallbacks[modalId] = resolveCallbacks[modalId]?.filter((cb) => cb !== callback); } }; }; return { subscribe, push, pop, onPop, }; } /** *Helper that wraps svelte `createEventDispatcher` for creating typesafe *event dispatcher from the `$$Events` type. See {@link ExtendedModalEvents} * @returns {ReturnType<typeof createEventDispatcher>} svelte event dispatcher */ export function createModalEventDispatcher() { return createEventDispatcher(); }