@@ -260,6 +260,7 @@ export class ElementNode<T> extends BaseNode<T> {
260260 node : CollectionNode < T > | null ;
261261 isMutated = true ;
262262 private _index : number = 0 ;
263+ private _attributesByNameMap = new Map < string , string > ( ) ;
263264 isHidden = false ;
264265
265266 constructor ( type : string , ownerDocument : Document < T , any > ) {
@@ -333,7 +334,7 @@ export class ElementNode<T> extends BaseNode<T> {
333334 let node ;
334335 let { value, textValue, id, ...props } = obj ;
335336 if ( this . node == null ) {
336- node = new CollectionNodeClass ( id ?? `react-aria- ${ ++ this . ownerDocument . nodeId } ` ) ;
337+ node = new CollectionNodeClass ( id ?? makeId ( this ) ) ;
337338 this . node = node ;
338339 } else {
339340 node = this . getMutableNode ( ) ;
@@ -398,9 +399,20 @@ export class ElementNode<T> extends BaseNode<T> {
398399 }
399400
400401 hasAttribute ( ) : void { }
401- setAttribute ( ) : void { }
402+
403+ setAttribute ( qualifiedName : string , value : string ) : void {
404+ this . _attributesByNameMap . set ( qualifiedName , '' + value ) ;
405+ }
406+
407+ getAttribute ( qualifiedName : string ) : string | null {
408+ return this . _attributesByNameMap . get ( qualifiedName ) ?? null ;
409+ }
410+
402411 setAttributeNS ( ) : void { }
403- removeAttribute ( ) : void { }
412+
413+ removeAttribute ( qualifiedName : string ) : void {
414+ this . _attributesByNameMap . delete ( qualifiedName ) ;
415+ }
404416}
405417
406418/**
@@ -567,3 +579,17 @@ export class Document<T, C extends BaseCollection<T> = BaseCollection<T>> extend
567579 }
568580 }
569581}
582+
583+ function makeId ( node : ElementNode < unknown > ) {
584+ const identifierPrefix = 'react-aria' ;
585+ if ( node . parentNode instanceof ElementNode ) {
586+ // We only use this for id generation on the client
587+ const parentKey = node . parentNode . getAttribute ( 'data-key' ) ;
588+ if ( parentKey != null ) {
589+ // If parentNode specifies a key, generate a stable id based on parentKey
590+ // so that useDroppableCollection can keep track of each child even if it is recreated
591+ return identifierPrefix + '-' + parentKey + '-' + node . index . toString ( 32 ) ;
592+ }
593+ }
594+ return identifierPrefix + '-' + ( ++ node . ownerDocument . nodeId ) . toString ( 32 ) ;
595+ }
0 commit comments