22import React , {
33 Component ,
44 ComponentType ,
5+ createRef ,
56 PropsWithChildren ,
67 PureComponent ,
78 ReactElement ,
89 ReactNode ,
10+ Ref ,
11+ RefCallback ,
12+ RefObject ,
913} from 'react' ;
14+ import mergeRefs from 'react-merge-refs' ;
1015import {
1116 Align ,
1217 FixedSizeList ,
@@ -95,35 +100,53 @@ export type OpennessState<
95100 Record < string , OpennessStateUpdateRules < TData , TNodePublicState > | boolean >
96101> ;
97102
98- export type TreeProps <
103+ export type TreeComputerProps < TData extends NodeData > = Readonly < {
104+ async ?: boolean ;
105+ buildingTaskTimeout ?: number ;
106+ placeholder ?: ReactNode ;
107+ treeWalker : TreeWalker < TData > ;
108+ } > ;
109+
110+ export type TreeComputerState <
99111 TData extends NodeData ,
100112 TNodePublicState extends NodePublicState < TData >
113+ > = Readonly < {
114+ order ?: string [ ] ;
115+ records : ReadonlyMap < string | symbol , NodeRecord < TNodePublicState > > ;
116+ setState : Component <
117+ any ,
118+ TreeComputerState < TData , TNodePublicState >
119+ > [ 'setState' ] ;
120+ // A simple hack to get over the PureComponent shallow comparison
121+ updateRequest : object ;
122+ } > ;
123+
124+ export type TreeProps <
125+ TData extends NodeData ,
126+ TNodePublicState extends NodePublicState < TData > ,
127+ TListComponent extends FixedSizeList | VariableSizeList
101128> = Readonly < Omit < ListProps , 'children' | 'itemCount' | 'itemKey' > > &
129+ TreeComputerProps < TData > &
102130 Readonly < {
103- buildingTaskTimeout ?: number ;
104131 children : ComponentType < NodeComponentProps < TData , TNodePublicState > > ;
105- placeholder ?: ReactNode ;
106- async ?: boolean ;
132+ listRef ?: Ref < TListComponent > ;
107133 rowComponent ?: ComponentType < ListChildComponentProps > ;
108- treeWalker : TreeWalker < TData > ;
109134 } > ;
110135
111136export type TreeState <
112137 TData extends NodeData ,
113- TNodePublicState extends NodePublicState < TData >
114- > = Readonly < {
115- order ?: string [ ] ;
116- computeTree : TreeComputer < any , any , any , any > ;
117- records : ReadonlyMap < string | symbol , NodeRecord < TNodePublicState > > ;
118- recomputeTree : (
119- options : OpennessState < TData , TNodePublicState > ,
120- ) => Promise < void > ;
121- setState : Component < any , TreeState < TData , TNodePublicState > > [ 'setState' ] ;
122- treeWalker : TreeWalker < TData > ;
123-
124- // A simple hack to get over the PureComponent shallow comparison
125- updateRequest : object ;
126- } > ;
138+ TNodePublicState extends NodePublicState < TData > ,
139+ TListComponent extends FixedSizeList | VariableSizeList
140+ > = TreeComputerState < TData , TNodePublicState > &
141+ Readonly < {
142+ attachRefs : RefCallback < TListComponent > ;
143+ computeTree : TreeComputer < any , any , any , any > ;
144+ list : RefObject < TListComponent > ;
145+ recomputeTree : (
146+ options : OpennessState < TData , TNodePublicState > ,
147+ ) => Promise < void > ;
148+ treeWalker : TreeWalker < TData > ;
149+ } > ;
127150
128151export type TypedListChildComponentData <
129152 TData extends NodeData ,
@@ -183,7 +206,7 @@ export const Row = <
183206export type TreeCreatorOptions <
184207 TData extends NodeData ,
185208 TNodePublicState extends NodePublicState < TData > ,
186- TState extends TreeState < TData , TNodePublicState >
209+ TState extends TreeComputerState < TData , TNodePublicState >
187210> = Readonly < {
188211 createRecord : (
189212 data : TData ,
@@ -204,8 +227,8 @@ export type TreeComputerOptions<
204227export type TreeComputer <
205228 TData extends NodeData ,
206229 TNodePublicState extends NodePublicState < TData > ,
207- TProps extends TreeProps < TData , TNodePublicState > ,
208- TState extends TreeState < TData , TNodePublicState >
230+ TProps extends TreeComputerProps < TData > ,
231+ TState extends TreeComputerState < TData , TNodePublicState >
209232> = (
210233 props : TProps ,
211234 state : TState ,
@@ -219,8 +242,8 @@ export type TreeComputer<
219242const generateNewTree = <
220243 TData extends NodeData ,
221244 TNodePublicState extends NodePublicState < TData > ,
222- TProps extends TreeProps < TData , TNodePublicState > ,
223- TState extends TreeState < TData , TNodePublicState >
245+ TProps extends TreeComputerProps < TData > ,
246+ TState extends TreeComputerState < TData , TNodePublicState >
224247> (
225248 { createRecord} : TreeCreatorOptions < TData , TNodePublicState , TState > ,
226249 { buildingTaskTimeout, placeholder, async = false , treeWalker} : TProps ,
@@ -379,8 +402,8 @@ const MAX_FUNCTION_ARGUMENTS = 32768;
379402const updateExistingTree = <
380403 TData extends NodeData ,
381404 TNodePublicState extends NodePublicState < TData > ,
382- TProps extends TreeProps < TData , TNodePublicState > ,
383- TState extends TreeState < TData , TNodePublicState >
405+ TProps extends TreeComputerProps < TData > ,
406+ TState extends TreeComputerState < TData , TNodePublicState >
384407> (
385408 { order, records} : TState ,
386409 { opennessState} : TreeComputerOptions < TData , TNodePublicState > ,
@@ -564,8 +587,8 @@ const updateExistingTree = <
564587export const createTreeComputer = <
565588 TData extends NodeData ,
566589 TNodePublicState extends NodePublicState < TData > ,
567- TProps extends TreeProps < TData , TNodePublicState > ,
568- TState extends TreeState < TData , TNodePublicState >
590+ TProps extends TreeComputerProps < TData > ,
591+ TState extends TreeComputerState < TData , TNodePublicState >
569592> (
570593 creatorOptions : TreeCreatorOptions < TData , TNodePublicState , TState > ,
571594) : TreeComputer < TData , TNodePublicState , TProps , TState > => (
@@ -580,8 +603,8 @@ export const createTreeComputer = <
580603class Tree <
581604 TData extends NodeData ,
582605 TNodePublicState extends NodePublicState < TData > ,
583- TProps extends TreeProps < TData , TNodePublicState > ,
584- TState extends TreeState < TData , TNodePublicState > ,
606+ TProps extends TreeProps < TData , TNodePublicState , TListComponent > ,
607+ TState extends TreeState < TData , TNodePublicState , TListComponent > ,
585608 TListComponent extends FixedSizeList | VariableSizeList
586609> extends PureComponent < TProps , TState > {
587610 public static defaultProps : Partial < DefaultTreeProps > = {
@@ -592,26 +615,26 @@ class Tree<
592615 props : DefaultTreeProps ,
593616 state : DefaultTreeState ,
594617 ) : Partial < DefaultTreeState > | null {
595- const { treeWalker} = props ;
596- const { computeTree, order, treeWalker : oldTreeWalker } = state ;
618+ const { listRef = null , treeWalker} = props ;
619+ const { computeTree, list , order, treeWalker : oldTreeWalker } = state ;
597620
598621 return {
622+ attachRefs : mergeRefs ( [ list , listRef ] ) ,
599623 ...( treeWalker !== oldTreeWalker || ! order
600624 ? computeTree ( props , state , { refresh : true } )
601625 : null ) ,
602626 treeWalker,
603627 } ;
604628 }
605629
606- protected readonly list : React . RefObject < TListComponent > = React . createRef ( ) ;
607-
608630 public constructor ( props : TProps , context : any ) {
609631 super ( props , context ) ;
610632
611633 this . getRecordData = this . getRecordData . bind ( this ) ;
612634
613635 /* eslint-disable react/no-unused-state,@typescript-eslint/consistent-type-assertions */
614636 this . state = {
637+ list : createRef ( ) ,
615638 recomputeTree : this . recomputeTree . bind ( this ) ,
616639 setState : this . setState . bind ( this ) ,
617640 } as TState ;
@@ -653,12 +676,13 @@ class Tree<
653676 }
654677
655678 public scrollTo ( scrollOffset : number ) : void {
656- this . list . current ?. scrollTo ( scrollOffset ) ;
679+ // eslint-disable-next-line react/destructuring-assignment
680+ this . state . list . current ?. scrollTo ( scrollOffset ) ;
657681 }
658682
659683 public scrollToItem ( id : string , align ?: Align ) : void {
660684 // eslint-disable-next-line react/destructuring-assignment
661- this . list . current ?. scrollToItem ( this . state . order ! . indexOf ( id ) , align ) ;
685+ this . state . list . current ?. scrollToItem ( this . state . order ! . indexOf ( id ) , align ) ;
662686 }
663687}
664688
0 commit comments