@@ -8,9 +8,17 @@ import { injectSelf } from '@/util/injectSelf'
88import type { ComputedRef , InjectionKey , Ref , VNode } from 'vue'
99import type { MaybeRef } from '@/util'
1010
11+ export type SlotDefaults = {
12+ [ slotName : string ] : Record < string , unknown >
13+ }
14+
15+ export type ComponentDefaults = Record < string , unknown > & {
16+ [ slotKey : `#${string } `] : Record < string , unknown >
17+ }
18+
1119export type DefaultsInstance = undefined | {
12- [ key : string ] : undefined | Record < string , unknown >
13- global ?: Record < string , unknown >
20+ [ key : string ] : undefined | ComponentDefaults
21+ global ?: ComponentDefaults
1422}
1523
1624export type DefaultsOptions = Partial < DefaultsInstance >
@@ -89,6 +97,29 @@ function propIsDefined (vnode: VNode, prop: string) {
8997 typeof vnode . props [ toKebabCase ( prop ) ] !== 'undefined' )
9098}
9199
100+ function extractSlotDefaults ( componentDefaults : ComponentDefaults | undefined ) : {
101+ componentDefaults : Record < string , unknown >
102+ slotDefaults : SlotDefaults
103+ } {
104+ if ( ! componentDefaults ) {
105+ return { componentDefaults : { } , slotDefaults : { } }
106+ }
107+
108+ const slotDefaults : SlotDefaults = { }
109+ const filteredComponentDefaults : Record < string , unknown > = { }
110+
111+ for ( const [ key , value ] of Object . entries ( componentDefaults ) ) {
112+ if ( key . startsWith ( '#' ) ) {
113+ const slotName = key . slice ( 1 ) // Remove the '#' prefix
114+ slotDefaults [ slotName ] = value as Record < string , unknown >
115+ } else {
116+ filteredComponentDefaults [ key ] = value
117+ }
118+ }
119+
120+ return { componentDefaults : filteredComponentDefaults , slotDefaults }
121+ }
122+
92123export function internalUseDefaults (
93124 props : Record < string , any > = { } ,
94125 name ?: string ,
@@ -101,7 +132,12 @@ export function internalUseDefaults (
101132 throw new Error ( '[Vuetify] Could not determine component name' )
102133 }
103134
104- const componentDefaults = computed ( ( ) => defaults . value ?. [ props . _as ?? name ] )
135+ const rawComponentDefaults = computed ( ( ) => defaults . value ?. [ props . _as ?? name ] as ComponentDefaults | undefined )
136+ const extractedDefaults = computed ( ( ) =>
137+ extractSlotDefaults ( rawComponentDefaults . value )
138+ )
139+ const componentDefaults = computed ( ( ) => extractedDefaults . value . componentDefaults )
140+
105141 const _props = new Proxy ( props , {
106142 get ( target , prop : string ) {
107143 const propValue = Reflect . get ( target , prop )
@@ -118,14 +154,20 @@ export function internalUseDefaults (
118154 } )
119155
120156 const _subcomponentDefaults = shallowRef ( )
157+ const _slotDefaults = shallowRef < SlotDefaults > ( )
158+
121159 watchEffect ( ( ) => {
122- if ( componentDefaults . value ) {
123- const subComponents = Object . entries ( componentDefaults . value )
160+ const extracted = extractedDefaults . value
161+
162+ if ( extracted . componentDefaults ) {
163+ const subComponents = Object . entries ( extracted . componentDefaults )
124164 . filter ( ( [ key ] ) => key . startsWith ( key [ 0 ] . toUpperCase ( ) ) )
125165 _subcomponentDefaults . value = subComponents . length ? Object . fromEntries ( subComponents ) : undefined
126166 } else {
127167 _subcomponentDefaults . value = undefined
128168 }
169+
170+ _slotDefaults . value = extracted . slotDefaults
129171 } )
130172
131173 function provideSubDefaults ( ) {
@@ -138,16 +180,78 @@ export function internalUseDefaults (
138180 } ) )
139181 }
140182
141- return { props : _props , provideSubDefaults }
183+ function getSlotDefaults ( slotName : string ) : Record < string , unknown > | undefined {
184+ return _slotDefaults . value ?. [ slotName ]
185+ }
186+
187+ return { props : _props , provideSubDefaults, getSlotDefaults }
142188}
143189
144- export function useDefaults < T extends Record < string , any > > ( props : T , name ?: string ) : T
145- export function useDefaults ( props ?: undefined , name ?: string ) : Record < string , any >
190+ export function useDefaults < T extends Record < string , any > > ( props : T , name ?: string ) : T & { getSlotDefaults : ( slotName : string ) => Record < string , unknown > | undefined }
191+ export function useDefaults ( props ?: undefined , name ?: string ) : Record < string , any > & { getSlotDefaults : ( slotName : string ) => Record < string , unknown > | undefined }
146192export function useDefaults (
147193 props : Record < string , any > = { } ,
148194 name ?: string ,
149195) {
150- const { props : _props , provideSubDefaults } = internalUseDefaults ( props , name )
196+ const { props : _props , provideSubDefaults, getSlotDefaults } = internalUseDefaults ( props , name )
151197 provideSubDefaults ( )
152- return _props
198+
199+ // Create a new proxy that includes getSlotDefaults
200+ return new Proxy ( _props , {
201+ get ( target , prop ) {
202+ if ( prop === 'getSlotDefaults' ) {
203+ return getSlotDefaults
204+ }
205+ return Reflect . get ( target , prop )
206+ } ,
207+ has ( target , prop ) {
208+ if ( prop === 'getSlotDefaults' ) {
209+ return true
210+ }
211+ return Reflect . has ( target , prop )
212+ } ,
213+ ownKeys ( target ) {
214+ return [ ...Reflect . ownKeys ( target ) , 'getSlotDefaults' ]
215+ }
216+ } )
217+ }
218+
219+ export function createSlotDefaults ( slotDefaults : Record < string , unknown > | undefined ) {
220+ if ( ! slotDefaults ) return { }
221+
222+ const componentDefaults : Record < string , unknown > = { }
223+ const directProps : Record < string , unknown > = { }
224+
225+ for ( const [ key , value ] of Object . entries ( slotDefaults ) ) {
226+ if ( key [ 0 ] === key [ 0 ] . toUpperCase ( ) ) {
227+ // Component defaults (e.g., VBtn: { size: 'md' })
228+ componentDefaults [ key ] = value
229+ } else {
230+ // Direct props (e.g., class: 'pa-0')
231+ directProps [ key ] = value
232+ }
233+ }
234+
235+ return { componentDefaults, directProps }
236+ }
237+
238+ // Helper function to get slot defaults info without rendering
239+ export function useSlotDefaults ( ) {
240+ const defaults = injectDefaults ( )
241+ const vm = getCurrentInstance ( 'useSlotDefaults' )
242+
243+ function getSlotDefaultsInfo ( slotName : string ) {
244+ const componentName = vm ?. type . name ?? vm ?. type . __name
245+ if ( ! componentName ) return null
246+
247+ const componentDefaults = defaults . value ?. [ componentName ] as ComponentDefaults | undefined
248+ const { slotDefaults } = extractSlotDefaults ( componentDefaults )
249+ const slotDefaultsForSlot = slotDefaults [ slotName ]
250+
251+ if ( ! slotDefaultsForSlot ) return null
252+
253+ return createSlotDefaults ( slotDefaultsForSlot )
254+ }
255+
256+ return { getSlotDefaultsInfo }
153257}
0 commit comments