@@ -23,28 +23,36 @@ import {
23
23
TreeItem ,
24
24
TreeItemContent ,
25
25
TreeItemContentProps ,
26
+ TreeLoadMoreItem ,
27
+ TreeLoadMoreItemProps ,
26
28
useContextProps ,
27
29
Virtualizer
28
30
} from 'react-aria-components' ;
29
31
import { centerBaseline } from './CenterBaseline' ;
30
32
import { Checkbox } from './Checkbox' ;
31
33
import Chevron from '../ui-icons/Chevron' ;
32
34
import { colorMix , focusRing , fontRelative , lightDark , style } from '../style' with { type : 'macro' } ;
33
- import { DOMRef , DOMRefValue , forwardRefType , GlobalDOMAttributes , Key } from '@react-types/shared' ;
35
+ import { DOMRef , forwardRefType , GlobalDOMAttributes , Key , LoadingState } from '@react-types/shared' ;
34
36
import { getAllowedOverrides , StylesPropWithHeight , UnsafeStyles } from './style-utils' with { type : 'macro' } ;
35
37
import { IconContext } from './Icon' ;
38
+ // @ts -ignore
39
+ import intlMessages from '../intl/*.json' ;
40
+ import { ProgressCircle } from './ProgressCircle' ;
36
41
import { raw } from '../style/style-macro' with { type : 'macro' } ;
37
42
import React , { createContext , forwardRef , JSXElementConstructor , ReactElement , ReactNode , useContext , useRef } from 'react' ;
38
43
import { TextContext } from './Content' ;
39
44
import { useDOMRef } from '@react-spectrum/utils' ;
40
- import { useLocale } from 'react-aria' ;
45
+ import { useLocale , useLocalizedStringFormatter } from 'react-aria' ;
41
46
import { useScale } from './utils' ;
42
47
43
48
interface S2TreeProps {
44
49
// Only detatched is supported right now with the current styles from Spectrum
50
+ // See https://github.com/adobe/react-spectrum/pull/7343 for what remaining combinations are left
51
+ /** Whether the tree should be displayed with a [detached style](https://spectrum.adobe.com/page/tree-view/#Detached). */
45
52
isDetached ?: boolean ,
53
+ /** Handler that is called when a user performs an action on a row. */
46
54
onAction ?: ( key : Key ) => void ,
47
- // not fully supported yet
55
+ /** Whether the tree should be displayed with a [emphasized style](https://spectrum.adobe.com/page/tree-view/#Emphasis). */
48
56
isEmphasized ?: boolean
49
57
}
50
58
@@ -58,6 +66,11 @@ export interface TreeViewItemProps extends Omit<RACTreeItemProps, 'className' |
58
66
hasChildItems ?: boolean
59
67
}
60
68
69
+ export interface TreeViewLoadMoreItemProps extends Pick < TreeLoadMoreItemProps , 'onLoadMore' > {
70
+ /** The current loading state of the TreeView or TreeView row. */
71
+ loadingState ?: LoadingState
72
+ }
73
+
61
74
interface TreeRendererContextValue {
62
75
renderer ?: ( item ) => ReactElement < any , string | JSXElementConstructor < any > >
63
76
}
@@ -91,7 +104,10 @@ const tree = style({
91
104
}
92
105
} , getAllowedOverrides ( { height : true } ) ) ;
93
106
94
- const TreeView = /*#__PURE__*/ ( forwardRef as forwardRefType ) ( function TreeView < T extends object > ( props : TreeViewProps < T > , ref : DOMRef < HTMLDivElement > ) {
107
+ /**
108
+ * A tree view provides users with a way to navigate nested hierarchical information.
109
+ */
110
+ export const TreeView = /*#__PURE__*/ ( forwardRef as forwardRefType ) ( function TreeView < T extends object > ( props : TreeViewProps < T > , ref : DOMRef < HTMLDivElement > ) {
95
111
let { children, isDetached, isEmphasized, UNSAFE_className, UNSAFE_style} = props ;
96
112
let scale = useScale ( ) ;
97
113
@@ -180,7 +196,6 @@ const treeRow = style({
180
196
}
181
197
} ) ;
182
198
183
-
184
199
const treeCellGrid = style ( {
185
200
display : 'grid' ,
186
201
width : 'full' ,
@@ -346,7 +361,6 @@ export const TreeViewItemContent = (props: TreeViewItemContentProps): ReactNode
346
361
gridArea : 'level-padding' ,
347
362
width : 'calc(calc(var(--tree-item-level, 0) - 1) * var(--indent))'
348
363
} ) } />
349
- { /* TODO: revisit when we do async loading, at the moment hasChildItems will only cause the chevron to be rendered, no aria/data attributes indicating the row's expandability are added */ }
350
364
< ExpandableRowChevron isDisabled = { isDisabled } isExpanded = { isExpanded } scale = { scale } isHidden = { ! ( hasChildItems ) } />
351
365
< Provider
352
366
values = { [
@@ -368,6 +382,33 @@ export const TreeViewItemContent = (props: TreeViewItemContentProps): ReactNode
368
382
) ;
369
383
} ;
370
384
385
+ const centeredWrapper = style ( {
386
+ display : 'flex' ,
387
+ alignItems : 'center' ,
388
+ justifyContent : 'center' ,
389
+ width : 'full' ,
390
+ height : 'full'
391
+ } ) ;
392
+
393
+ export const TreeViewLoadMoreItem = ( props : TreeViewLoadMoreItemProps ) : ReactNode => {
394
+ let { loadingState, onLoadMore} = props ;
395
+ let stringFormatter = useLocalizedStringFormatter ( intlMessages , '@react-spectrum/s2' ) ;
396
+ let isLoading = loadingState === 'loading' || loadingState === 'loadingMore' ;
397
+ return (
398
+ < TreeLoadMoreItem isLoading = { isLoading } onLoadMore = { onLoadMore } className = { style ( { width : 'full' , marginY : 4 } ) } >
399
+ { ( ) => {
400
+ return (
401
+ < div className = { centeredWrapper } >
402
+ < ProgressCircle
403
+ isIndeterminate
404
+ aria-label = { stringFormatter . format ( 'table.loadingMore' ) } />
405
+ </ div >
406
+ ) ;
407
+ } }
408
+ </ TreeLoadMoreItem >
409
+ ) ;
410
+ } ;
411
+
371
412
interface ExpandableRowChevronProps {
372
413
isExpanded ?: boolean ,
373
414
isDisabled ?: boolean ,
@@ -437,9 +478,3 @@ function ExpandableRowChevron(props: ExpandableRowChevronProps) {
437
478
</ Button >
438
479
) ;
439
480
}
440
-
441
- /**
442
- * A tree view provides users with a way to navigate nested hierarchical information.
443
- */
444
- const _TreeView : < T extends object > ( props : TreeViewProps < T > & React . RefAttributes < DOMRefValue < HTMLDivElement > > ) => ReactElement | null = TreeView ;
445
- export { _TreeView as TreeView } ;
0 commit comments