@@ -39,13 +39,15 @@ export function useSlots<Config extends SlotConfig>(
3939 config : Config ,
4040) : [ Partial < SlotElements < Config > > , React . ReactNode [ ] ] {
4141 // Object mapping slot names to their elements
42- const slots : Partial < SlotElements < Config > > = mapValues ( config , ( ) => undefined )
42+ const slots : Partial < SlotElements < Config > > = { } as Partial < SlotElements < Config > >
4343
4444 // Array of elements that are not slots
4545 const rest : React . ReactNode [ ] = [ ]
4646
4747 const keys = Object . keys ( config ) as Array < keyof Config >
4848 const values = Object . values ( config )
49+ const totalSlots = keys . length
50+ let slotsFound = 0
4951
5052 // eslint-disable-next-line github/array-foreach
5153 React . Children . forEach ( children , child => {
@@ -54,44 +56,50 @@ export function useSlots<Config extends SlotConfig>(
5456 return
5557 }
5658
57- const index = values . findIndex ( value => {
59+ // Short-circuit: if all slots are filled, remaining children go to rest
60+ if ( slotsFound === totalSlots ) {
61+ rest . push ( child )
62+ return
63+ }
64+
65+ let matchedIndex = - 1
66+ for ( let i = 0 ; i < totalSlots ; i ++ ) {
67+ // Skip already-filled slots
68+ if ( slots [ keys [ i ] ] !== undefined ) continue
69+
70+ const value = values [ i ]
5871 if ( Array . isArray ( value ) ) {
5972 const [ component , testFn ] = value
60- return ( child . type === component || isSlot ( child , component as SlotMarker ) ) && testFn ( child . props )
73+ if ( ( child . type === component || isSlot ( child , component as SlotMarker ) ) && testFn ( child . props ) ) {
74+ matchedIndex = i
75+ break
76+ }
6177 } else {
62- return child . type === value || isSlot ( child , value as SlotMarker )
78+ if ( child . type === value || isSlot ( child , value as SlotMarker ) ) {
79+ matchedIndex = i
80+ break
81+ }
6382 }
64- } )
83+ }
6584
6685 // If the child is not a slot, add it to the `rest` array
67- if ( index === - 1 ) {
86+ if ( matchedIndex === - 1 ) {
6887 rest . push ( child )
6988 return
7089 }
7190
72- const slotKey = keys [ index ]
91+ const slotKey = keys [ matchedIndex ]
7392
7493 // If slot is already filled, ignore duplicates
75- if ( slots [ slotKey ] ) {
94+ if ( slots [ slotKey ] !== undefined ) {
7695 warning ( true , `Found duplicate "${ String ( slotKey ) } " slot. Only the first will be rendered.` )
7796 return
7897 }
7998
8099 // If the child is a slot, add it to the `slots` object
81-
82100 slots [ slotKey ] = child as SlotValue < Config , keyof Config >
101+ slotsFound ++
83102 } )
84103
85104 return [ slots , rest ]
86105}
87-
88- /** Map the values of an object */
89- function mapValues < T extends Record < string , unknown > , V > ( obj : T , fn : ( value : T [ keyof T ] ) => V ) {
90- return Object . keys ( obj ) . reduce (
91- ( result , key : keyof T ) => {
92- result [ key ] = fn ( obj [ key ] )
93- return result
94- } ,
95- { } as Record < keyof T , V > ,
96- )
97- }
0 commit comments