@@ -2,6 +2,7 @@ import React from 'react';
22import { createContextScope } from '@radix-ui/react-context' ;
33import { useComposedRefs } from '@radix-ui/react-compose-refs' ;
44import { createSlot , type Slot } from '@radix-ui/react-slot' ;
5+ import { OrderedDict } from './ordered-dictionary' ;
56
67type SlotProps = React . ComponentPropsWithoutRef < typeof Slot > ;
78type CollectionElement = HTMLElement ;
@@ -11,7 +12,7 @@ interface CollectionProps extends SlotProps {
1112
1213// We have resorted to returning slots directly rather than exposing primitives that can then
1314// be slotted like `<CollectionItem as={Slot}>…</CollectionItem>`.
14- // This is because we encountered issues with generic types that cannot be statically analysed
15+ // This is because we encountered issues with generic types that cannot be statically analyzed
1516// due to creating them dynamically via createCollection.
1617
1718function createCollection < ItemElement extends HTMLElement , ItemData = { } > ( name : string ) {
@@ -22,23 +23,25 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
2223 const PROVIDER_NAME = name + 'CollectionProvider' ;
2324 const [ createCollectionContext , createCollectionScope ] = createContextScope ( PROVIDER_NAME ) ;
2425
26+ type ItemMap = OrderedDict <
27+ React . RefObject < ItemElement | null > ,
28+ { ref : React . RefObject < ItemElement | null > } & ItemData
29+ > ;
30+
2531 type ContextValue = {
2632 collectionRef : React . RefObject < CollectionElement | null > ;
27- itemMap : Map <
28- React . RefObject < ItemElement | null > ,
29- { ref : React . RefObject < ItemElement | null > } & ItemData
30- > ;
33+ itemMap : React . RefObject < ItemMap > ;
3134 } ;
3235
3336 const [ CollectionProviderImpl , useCollectionContext ] = createCollectionContext < ContextValue > (
3437 PROVIDER_NAME ,
35- { collectionRef : { current : null } , itemMap : new Map ( ) } ,
38+ { collectionRef : { current : null } , itemMap : { current : new OrderedDict ( ) } } ,
3639 ) ;
3740
3841 const CollectionProvider : React . FC < { children ?: React . ReactNode ; scope : any } > = ( props ) => {
3942 const { scope, children } = props ;
4043 const ref = React . useRef < CollectionElement > ( null ) ;
41- const itemMap = React . useRef < ContextValue [ 'itemMap' ] > ( new Map ( ) ) . current ;
44+ const itemMap = React . useRef < ItemMap > ( new OrderedDict ( ) ) ;
4245 return (
4346 < CollectionProviderImpl scope = { scope } itemMap = { itemMap } collectionRef = { ref } >
4447 { children }
@@ -87,8 +90,8 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
8790 const context = useCollectionContext ( ITEM_SLOT_NAME , scope ) ;
8891
8992 React . useEffect ( ( ) => {
90- context . itemMap . set ( ref , { ref, ...( itemData as unknown as ItemData ) } ) ;
91- return ( ) => void context . itemMap . delete ( ref ) ;
93+ context . itemMap . current . set ( ref , { ref, ...( itemData as unknown as ItemData ) } ) ;
94+ return ( ) => void context . itemMap . current . delete ( ref ) ;
9295 } ) ;
9396
9497 return (
@@ -112,11 +115,10 @@ function createCollection<ItemElement extends HTMLElement, ItemData = {}>(name:
112115 const collectionNode = context . collectionRef . current ;
113116 if ( ! collectionNode ) return [ ] ;
114117 const orderedNodes = Array . from ( collectionNode . querySelectorAll ( `[${ ITEM_DATA_ATTR } ]` ) ) ;
115- const items = Array . from ( context . itemMap . values ( ) ) ;
116- const orderedItems = items . sort (
117- ( a , b ) => orderedNodes . indexOf ( a . ref . current ! ) - orderedNodes . indexOf ( b . ref . current ! ) ,
118+ const items = context . itemMap . current . toSorted (
119+ ( a , b ) => orderedNodes . indexOf ( a [ 0 ] . current ! ) - orderedNodes . indexOf ( b [ 0 ] . current ! ) ,
118120 ) ;
119- return orderedItems ;
121+ return Array . from ( items . values ( ) ) ;
120122 } , [ context . collectionRef , context . itemMap ] ) ;
121123
122124 return getItems ;
0 commit comments