11import { isString , tryOnUnmounted } from '@vueuse/core'
22import { computed , inject , markRaw , reactive , useAttrs } from 'vue'
3+ import type { Component , Raw } from 'vue'
34import VueFinalModal from './components/VueFinalModal/VueFinalModal.vue'
45import type CoreModal from './components/CoreModal/CoreModal.vue'
56import { internalVfmSymbol , vfmSymbol } from './injectionSymbols'
6- import type { ComponentProps , IOverloadedUseModalFn , InternalVfm , UseModalOptions , UseModalOptionsPrivate , UseModalOptionsSlots , UseModalReturnType , Vfm } from './Modal'
7+
8+ import type { ComponentProps , IOverloadedUseModalFn , InternalVfm , ModalSlot , ModalSlotOptions , UseModalOptions , UseModalOptionsPrivate , UseModalReturnType , Vfm } from './Modal'
79
810/**
911 * Returns the vfm instance. Equivalent to using `$vfm` inside
@@ -20,12 +22,12 @@ export function useInternalVfm(): InternalVfm {
2022 return inject ( internalVfmSymbol ) !
2123}
2224
23- function withMarkRaw ( options : Partial < UseModalOptions > ) {
25+ function withMarkRaw ( options : Partial < UseModalOptions > , DefaultComponent : Component = VueFinalModal ) {
2426 const { component, slots : innerSlots , ...rest } = options
2527
2628 const slots = typeof innerSlots === 'undefined'
2729 ? { }
28- : Object . fromEntries < UseModalOptionsSlots [ 'slots' ] > ( Object . entries ( innerSlots ) . map ( ( [ name , maybeComponent ] ) => {
30+ : Object . fromEntries < ModalSlot > ( Object . entries ( innerSlots ) . map ( ( [ name , maybeComponent ] ) => {
2931 if ( isString ( maybeComponent ) )
3032 return [ name , maybeComponent ] as const
3133
@@ -41,7 +43,7 @@ function withMarkRaw(options: Partial<UseModalOptions>) {
4143
4244 return {
4345 ...rest ,
44- component : markRaw ( component || VueFinalModal ) ,
46+ component : markRaw ( component || DefaultComponent ) ,
4547 slots,
4648 }
4749}
@@ -83,13 +85,21 @@ export const useModal: IOverloadedUseModalFn = function (_options: UseModalOptio
8385 }
8486
8587 function patchOptions ( _options : Partial < UseModalOptions > ) {
86- const _patchOptions = withMarkRaw ( _options )
87- if ( _patchOptions ?. attrs )
88- Object . assign ( options . attrs || { } , _patchOptions . attrs )
89- if ( _patchOptions ?. component )
90- Object . assign ( options . component || { } , _patchOptions . component )
91- if ( _patchOptions ?. slots )
92- Object . assign ( options . slots || { } , _patchOptions . slots )
88+ const { slots, ...rest } = withMarkRaw ( _options , options . component )
89+
90+ // patch options.component and options.attrs
91+ patchComponentOptions ( options , rest )
92+
93+ // patch options.slots
94+ if ( slots ) {
95+ Object . entries ( slots ) . forEach ( ( [ name , slot ] ) => {
96+ const originSlot = options . slots ! [ name ]
97+ if ( isModalSlotOptions ( originSlot ) && isModalSlotOptions ( slot ) )
98+ patchComponentOptions ( originSlot , slot )
99+ else
100+ options . slots ! [ name ] = slot
101+ } )
102+ }
93103 }
94104
95105 function destroy ( ) : void {
@@ -115,6 +125,31 @@ export const useModal: IOverloadedUseModalFn = function (_options: UseModalOptio
115125 return modal
116126}
117127
128+ function patchAttrs < T extends Record < string , any > > ( attrs : T , newAttrs : Partial < T > ) : T {
129+ Object . entries ( newAttrs ) . forEach ( ( [ key , value ] ) => {
130+ attrs [ key as keyof T ] = value
131+ } )
132+
133+ return attrs
134+ }
135+
136+ type ComponentOptions = {
137+ component ?: Raw < Component >
138+ attrs ?: Record < string , any >
139+ }
140+
141+ function patchComponentOptions ( options : ComponentOptions , newOptions : ComponentOptions ) {
142+ if ( newOptions . component )
143+ options . component = newOptions . component
144+
145+ if ( newOptions . attrs )
146+ patchAttrs ( options . attrs ! , newOptions . attrs )
147+ }
148+
149+ function isModalSlotOptions ( value : any ) : value is ModalSlotOptions {
150+ return 'component' in value || 'attrs' in value
151+ }
152+
118153export function pickModalProps ( props : any , modalProps : any ) {
119154 return Object . keys ( modalProps ) . reduce ( ( acc , propName ) => {
120155 acc [ propName ] = props [ propName ]
0 commit comments