2
2
import React , {
3
3
Component ,
4
4
ComponentType ,
5
+ createRef ,
5
6
PropsWithChildren ,
6
7
PureComponent ,
7
8
ReactElement ,
8
9
ReactNode ,
10
+ Ref ,
11
+ RefCallback ,
12
+ RefObject ,
9
13
} from 'react' ;
14
+ import mergeRefs from 'react-merge-refs' ;
10
15
import {
11
16
Align ,
12
17
FixedSizeList ,
@@ -95,35 +100,53 @@ export type OpennessState<
95
100
Record < string , OpennessStateUpdateRules < TData , TNodePublicState > | boolean >
96
101
> ;
97
102
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 <
99
111
TData extends NodeData ,
100
112
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
101
128
> = Readonly < Omit < ListProps , 'children' | 'itemCount' | 'itemKey' > > &
129
+ TreeComputerProps < TData > &
102
130
Readonly < {
103
- buildingTaskTimeout ?: number ;
104
131
children : ComponentType < NodeComponentProps < TData , TNodePublicState > > ;
105
- placeholder ?: ReactNode ;
106
- async ?: boolean ;
132
+ listRef ?: Ref < TListComponent > ;
107
133
rowComponent ?: ComponentType < ListChildComponentProps > ;
108
- treeWalker : TreeWalker < TData > ;
109
134
} > ;
110
135
111
136
export type TreeState <
112
137
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
+ } > ;
127
150
128
151
export type TypedListChildComponentData <
129
152
TData extends NodeData ,
@@ -183,7 +206,7 @@ export const Row = <
183
206
export type TreeCreatorOptions <
184
207
TData extends NodeData ,
185
208
TNodePublicState extends NodePublicState < TData > ,
186
- TState extends TreeState < TData , TNodePublicState >
209
+ TState extends TreeComputerState < TData , TNodePublicState >
187
210
> = Readonly < {
188
211
createRecord : (
189
212
data : TData ,
@@ -204,8 +227,8 @@ export type TreeComputerOptions<
204
227
export type TreeComputer <
205
228
TData extends NodeData ,
206
229
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 >
209
232
> = (
210
233
props : TProps ,
211
234
state : TState ,
@@ -219,8 +242,8 @@ export type TreeComputer<
219
242
const generateNewTree = <
220
243
TData extends NodeData ,
221
244
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 >
224
247
> (
225
248
{ createRecord} : TreeCreatorOptions < TData , TNodePublicState , TState > ,
226
249
{ buildingTaskTimeout, placeholder, async = false , treeWalker} : TProps ,
@@ -379,8 +402,8 @@ const MAX_FUNCTION_ARGUMENTS = 32768;
379
402
const updateExistingTree = <
380
403
TData extends NodeData ,
381
404
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 >
384
407
> (
385
408
{ order, records} : TState ,
386
409
{ opennessState} : TreeComputerOptions < TData , TNodePublicState > ,
@@ -564,8 +587,8 @@ const updateExistingTree = <
564
587
export const createTreeComputer = <
565
588
TData extends NodeData ,
566
589
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 >
569
592
> (
570
593
creatorOptions : TreeCreatorOptions < TData , TNodePublicState , TState > ,
571
594
) : TreeComputer < TData , TNodePublicState , TProps , TState > => (
@@ -580,8 +603,8 @@ export const createTreeComputer = <
580
603
class Tree <
581
604
TData extends NodeData ,
582
605
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 > ,
585
608
TListComponent extends FixedSizeList | VariableSizeList
586
609
> extends PureComponent < TProps , TState > {
587
610
public static defaultProps : Partial < DefaultTreeProps > = {
@@ -592,26 +615,26 @@ class Tree<
592
615
props : DefaultTreeProps ,
593
616
state : DefaultTreeState ,
594
617
) : 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 ;
597
620
598
621
return {
622
+ attachRefs : mergeRefs ( [ list , listRef ] ) ,
599
623
...( treeWalker !== oldTreeWalker || ! order
600
624
? computeTree ( props , state , { refresh : true } )
601
625
: null ) ,
602
626
treeWalker,
603
627
} ;
604
628
}
605
629
606
- protected readonly list : React . RefObject < TListComponent > = React . createRef ( ) ;
607
-
608
630
public constructor ( props : TProps , context : any ) {
609
631
super ( props , context ) ;
610
632
611
633
this . getRecordData = this . getRecordData . bind ( this ) ;
612
634
613
635
/* eslint-disable react/no-unused-state,@typescript-eslint/consistent-type-assertions */
614
636
this . state = {
637
+ list : createRef ( ) ,
615
638
recomputeTree : this . recomputeTree . bind ( this ) ,
616
639
setState : this . setState . bind ( this ) ,
617
640
} as TState ;
@@ -653,12 +676,13 @@ class Tree<
653
676
}
654
677
655
678
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 ) ;
657
681
}
658
682
659
683
public scrollToItem ( id : string , align ?: Align ) : void {
660
684
// 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 ) ;
662
686
}
663
687
}
664
688
0 commit comments