diff --git a/packages/vue-final-modal/src/Modal.ts b/packages/vue-final-modal/src/Modal.ts index 8065fe7f..c503712a 100644 --- a/packages/vue-final-modal/src/Modal.ts +++ b/packages/vue-final-modal/src/Modal.ts @@ -1,71 +1,37 @@ -import type { App, CSSProperties, Component, ComponentOptions, ComponentPublicInstance, ComputedRef, ConcreteComponent, Raw, Ref, VNodeProps } from 'vue' -import type { VueFinalModal } from '.' +import type { App, CSSProperties, Component, ComponentPublicInstance, ComputedRef, Raw, Ref, VNodeProps } from 'vue' export type ComponentProps = ComponentPublicInstance['$props'] export type ModalId = number | string | symbol export type StyleValue = string | CSSProperties | (string | CSSProperties)[] -type RawProps = VNodeProps & { +export interface Constructor

{ + __isFragment?: never + __isTeleport?: never + __isSuspense?: never + new (...args: any[]): { $props: P } +} + +export type RawProps = VNodeProps & { // used to differ from a single VNode object as children __v_isVNode?: never // used to differ from Array children [Symbol.iterator]?: never } & Record -type VfmAttrs

= (RawProps & P) | ({} extends P ? InstanceType['$props'] : never) -interface UseModalOptionsConcreteComponent

{ component?: ConcreteComponent

; attrs?: VfmAttrs

} -interface UseModalOptionsComponentOptions

{ component?: ComponentOptions

; attrs?: VfmAttrs

} - -type SlotAttrs

= (RawProps & P) | ({} extends P ? null : never) -interface ModalSlotOptionsConcreteComponent

{ component: ConcreteComponent

; attrs?: SlotAttrs

} -interface ModalSlotOptionsComponentOptions

{ component: ComponentOptions

; attrs?: SlotAttrs

} - export interface ModalSlotOptions { component: Raw; attrs?: Record } export type ModalSlot = string | Component | ModalSlotOptions -export type UseModalOptionsSlots = { +export type UseModalOptions

= { + defaultModelValue?: boolean + context?: Vfm + component?: Constructor

+ attrs?: (RawProps & P) | ({} extends P ? null : never) slots?: { - default: ModalSlot [key: string]: ModalSlot } } -export type UseModalOptions = { - defaultModelValue?: boolean - context?: Vfm - component?: Raw - attrs?: Record -} & UseModalOptionsSlots - -export interface IOverloadedUseModalFn { -

(options: UseModalOptionsConcreteComponent

& UseModalOptionsSlots): UseModalReturnType -

(options: UseModalOptionsComponentOptions

& UseModalOptionsSlots): UseModalReturnType -

(options: - | UseModalOptionsConcreteComponent

& UseModalOptionsSlots - | UseModalOptionsComponentOptions

& UseModalOptionsSlots - | UseModalOptions - ): UseModalReturnType -} - -interface IOverloadedPatchOptionsFn { -

(options: UseModalOptionsConcreteComponent

& UseModalOptionsSlots): void -

(options: UseModalOptionsComponentOptions

& UseModalOptionsSlots): void -

(options: - | UseModalOptionsConcreteComponent

& UseModalOptionsSlots - | UseModalOptionsComponentOptions

& UseModalOptionsSlots - | Omit - ): void -} - -interface IOverloadedUseModalSlotFn { -

(options: ModalSlotOptionsConcreteComponent

): ModalSlot -

(options: ModalSlotOptionsComponentOptions

): ModalSlot -

(options: ModalSlotOptionsConcreteComponent

| ModalSlotOptionsComponentOptions

| ModalSlot): ModalSlot -} - -export const useModalSlot: IOverloadedUseModalSlotFn = (options: ModalSlot): ModalSlot => options - export type UseModalOptionsPrivate = { id: symbol modelValue: boolean @@ -73,11 +39,11 @@ export type UseModalOptionsPrivate = { resolveClosed: () => void } -export interface UseModalReturnType { - options: UseModalOptions & UseModalOptionsPrivate +export interface UseModalReturnType

{ + options: UseModalOptions

& UseModalOptionsPrivate open: () => Promise close: () => Promise - patchOptions: IOverloadedPatchOptionsFn + patchOptions: (options: Partial, 'defaultModelValue' | 'context'>>) => void destroy: () => void } @@ -85,7 +51,7 @@ export type Vfm = { install(app: App): void modals: ComputedRef[] openedModals: ComputedRef[] - dynamicModals: (UseModalOptions & UseModalOptionsPrivate)[] + dynamicModals: (UseModalOptions & UseModalOptionsPrivate)[] modalsContainers: Ref get: (modalId: ModalId) => undefined | ComputedRef toggle: (modalId: ModalId, show?: boolean) => undefined | Promise diff --git a/packages/vue-final-modal/src/components/ModalsContainer.vue b/packages/vue-final-modal/src/components/ModalsContainer.vue index 993435f5..49981228 100644 --- a/packages/vue-final-modal/src/components/ModalsContainer.vue +++ b/packages/vue-final-modal/src/components/ModalsContainer.vue @@ -11,7 +11,7 @@ const _vfm = useInternalVfm() const uid = Symbol('ModalsContainer') const shouldMount = computed(() => uid === vfm.modalsContainers.value?.[0]) -const openedDynamicModals: Ref<(UseModalOptions & UseModalOptionsPrivate)[]> = shallowRef([]) +const openedDynamicModals: Ref<(UseModalOptions & UseModalOptionsPrivate)[]> = shallowRef([]) function syncOpenDynamicModals() { openedDynamicModals.value = vfm.dynamicModals.filter(modal => modal.modelValue) diff --git a/packages/vue-final-modal/src/plugin.ts b/packages/vue-final-modal/src/plugin.ts index ce92e164..32a61a58 100644 --- a/packages/vue-final-modal/src/plugin.ts +++ b/packages/vue-final-modal/src/plugin.ts @@ -6,7 +6,7 @@ import type { InternalVfm, Modal, ModalId, UseModalOptions, UseModalOptionsPriva export function createVfm() { const modals: ComputedRef[] = shallowReactive([]) const openedModals: ComputedRef[] = shallowReactive([]) - const dynamicModals: (UseModalOptions & UseModalOptionsPrivate)[] = shallowReactive([]) + const dynamicModals: (UseModalOptions & UseModalOptionsPrivate)[] = shallowReactive([]) const modalsContainers = ref([]) const vfm: Vfm = markRaw({ diff --git a/packages/vue-final-modal/src/useApi.ts b/packages/vue-final-modal/src/useApi.ts index eb7f743f..db4660ed 100644 --- a/packages/vue-final-modal/src/useApi.ts +++ b/packages/vue-final-modal/src/useApi.ts @@ -1,11 +1,11 @@ import { isString, tryOnUnmounted } from '@vueuse/core' import { computed, getCurrentInstance, inject, markRaw, reactive, useAttrs } from 'vue' -import type { Component, Raw } from 'vue' +import type { Component } from 'vue' import VueFinalModal from './components/VueFinalModal/VueFinalModal.vue' import type CoreModal from './components/CoreModal/CoreModal.vue' import { internalVfmSymbol, vfmSymbol } from './injectionSymbols' -import type { ComponentProps, IOverloadedUseModalFn, InternalVfm, ModalSlot, ModalSlotOptions, UseModalOptions, UseModalOptionsPrivate, UseModalReturnType, Vfm } from './Modal' +import type { ComponentProps, Constructor, InternalVfm, ModalSlot, ModalSlotOptions, RawProps, UseModalOptions, UseModalOptionsPrivate, UseModalReturnType, Vfm } from './Modal' /** * Returns the vfm instance. Equivalent to using `$vfm` inside @@ -22,7 +22,7 @@ export function useInternalVfm(): InternalVfm { return inject(internalVfmSymbol)! } -function withMarkRaw(options: Partial, DefaultComponent: Component = VueFinalModal) { +function withMarkRaw

(options: Partial>, DefaultComponent: Component = VueFinalModal) { const { component, slots: innerSlots, ...rest } = options const slots = typeof innerSlots === 'undefined' @@ -43,7 +43,7 @@ function withMarkRaw(options: Partial, DefaultComponent: Compon return { ...rest, - component: markRaw(component || DefaultComponent), + component: markRaw(component || DefaultComponent) as Constructor

, slots, } } @@ -51,15 +51,15 @@ function withMarkRaw(options: Partial, DefaultComponent: Compon /** * Create a dynamic modal. */ -export const useModal: IOverloadedUseModalFn = function (_options: UseModalOptions): UseModalReturnType { +export function useModal

['$props']>(_options: UseModalOptions

): UseModalReturnType

{ const options = reactive({ id: Symbol('useModal'), modelValue: !!_options?.defaultModelValue, - resolveOpened: () => {}, - resolveClosed: () => {}, + resolveOpened: () => { }, + resolveClosed: () => { }, attrs: {}, - ...withMarkRaw(_options), - }) as UseModalOptions & UseModalOptionsPrivate + ...withMarkRaw

(_options), + }) as UseModalOptions

& UseModalOptionsPrivate if (!options.context) { const currentInstance = getCurrentInstance() @@ -89,7 +89,7 @@ export const useModal: IOverloadedUseModalFn = function (_options: UseModalOptio }) } - function patchOptions(_options: Partial) { + function patchOptions(_options: Partial, 'defaultModelValue' | 'context'>>) { const { slots, ...rest } = withMarkRaw(_options, options.component) // patch options.component and options.attrs @@ -132,6 +132,13 @@ export const useModal: IOverloadedUseModalFn = function (_options: UseModalOptio return modal } +export function useModalSlot

(options: { + component: Constructor

+ attrs?: (RawProps & P) | ({} extends P ? null : never) +}) { + return options +} + function patchAttrs>(attrs: T, newAttrs: Partial): T { Object.entries(newAttrs).forEach(([key, value]) => { attrs[key as keyof T] = value @@ -140,12 +147,10 @@ function patchAttrs>(attrs: T, newAttrs: Partial - attrs?: Record -} - -function patchComponentOptions(options: ComponentOptions | ModalSlotOptions, newOptions: ComponentOptions | ModalSlotOptions) { +function patchComponentOptions

( + options: Omit, 'defaultModelValue' | 'context'> | ModalSlotOptions, + newOptions: Partial, 'defaultModelValue' | 'context'>> | ModalSlotOptions, +) { if (newOptions.component) options.component = newOptions.component