import type { Component } from 'vue' import { reactive, markRaw, shallowReactive } from 'vue' import { createSharedComposable } from '@vueuse/core' import type { ComponentProps } from 'vue-component-type-helpers' export type OverlayOptions> = { defaultOpen?: boolean props?: OverlayAttrs destroyOnClose?: boolean } type ManagedOverlayOptionsPrivate = { component?: T id: symbol isMounted: boolean modelValue: boolean resolvePromise?: (value: unknown) => void } export type Overlay = OverlayOptions & ManagedOverlayOptionsPrivate interface OverlayInstance { open: (props?: ComponentProps) => Promise close: (value?: any) => void patch: (props: Partial>) => void } function _useOverlay() { const overlays = shallowReactive([]) const create = (component: T, _options?: OverlayOptions>): OverlayInstance => { const { props: props, defaultOpen, destroyOnClose } = _options || {} const options = reactive({ id: Symbol(import.meta.dev ? 'useOverlay' : ''), modelValue: !!defaultOpen, component: markRaw(component!), isMounted: !!defaultOpen, destroyOnClose: !!destroyOnClose, props: props || {} }) overlays.push(options) return { open: (props?: ComponentProps) => open(options.id, props), close: value => close(options.id, value), patch: (props: Partial>) => patch(options.id, props) } } const open = (id: symbol, props?: ComponentProps): Promise => { const overlay = getOverlay(id) // If props are provided, update the overlay's props if (props) { patch(overlay.id, props) } overlay.modelValue = true overlay.isMounted = true // Return a new promise that will be resolved when close is called return new Promise((resolve) => { overlay.resolvePromise = resolve }) } const close = (id: symbol, value?: any): void => { const overlay = getOverlay(id) overlay.modelValue = false // Resolve the promise if it exists if (overlay.resolvePromise) { overlay.resolvePromise(value) overlay.resolvePromise = undefined } } const unMount = (id: symbol): void => { const overlay = getOverlay(id) overlay.isMounted = false if (overlay.destroyOnClose) { const index = overlays.findIndex(overlay => overlay.id === id) overlays.splice(index, 1) } } const patch = (id: symbol, props: Partial>): void => { const overlay = getOverlay(id) Object.entries(props!).forEach(([key, value]) => { (overlay.props as any)[key] = value }) } const getOverlay = (id: symbol): Overlay => { const overlay = overlays.find(overlay => overlay.id === id) if (!overlay) { throw new Error('Overlay not found') } return overlay } return { overlays, open, close, create, patch, unMount } } export const useOverlay = /* @__PURE__ */ createSharedComposable(_useOverlay)