@@ -23,28 +23,36 @@ import {
2323 TreeItem ,
2424 TreeItemContent ,
2525 TreeItemContentProps ,
26+ TreeLoadMoreItem ,
27+ TreeLoadMoreItemProps ,
2628 useContextProps ,
2729 Virtualizer
2830} from 'react-aria-components' ;
2931import { centerBaseline } from './CenterBaseline' ;
3032import { Checkbox } from './Checkbox' ;
3133import Chevron from '../ui-icons/Chevron' ;
3234import { 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' ;
3436import { getAllowedOverrides , StylesPropWithHeight , UnsafeStyles } from './style-utils' with { type : 'macro' } ;
3537import { IconContext } from './Icon' ;
38+ // @ts -ignore
39+ import intlMessages from '../intl/*.json' ;
40+ import { ProgressCircle } from './ProgressCircle' ;
3641import { raw } from '../style/style-macro' with { type : 'macro' } ;
3742import React , { createContext , forwardRef , JSXElementConstructor , ReactElement , ReactNode , useContext , useRef } from 'react' ;
3843import { TextContext } from './Content' ;
3944import { useDOMRef } from '@react-spectrum/utils' ;
40- import { useLocale } from 'react-aria' ;
45+ import { useLocale , useLocalizedStringFormatter } from 'react-aria' ;
4146import { useScale } from './utils' ;
4247
4348interface S2TreeProps {
4449 // 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). */
4552 isDetached ?: boolean ,
53+ /** Handler that is called when a user performs an action on a row. */
4654 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). */
4856 isEmphasized ?: boolean
4957}
5058
@@ -58,6 +66,11 @@ export interface TreeViewItemProps extends Omit<RACTreeItemProps, 'className' |
5866 hasChildItems ?: boolean
5967}
6068
69+ export interface TreeViewLoadMoreItemProps extends Pick < TreeLoadMoreItemProps , 'onLoadMore' > {
70+ /** The current loading state of the TreeView or TreeView row. */
71+ loadingState ?: LoadingState
72+ }
73+
6174interface TreeRendererContextValue {
6275 renderer ?: ( item ) => ReactElement < any , string | JSXElementConstructor < any > >
6376}
@@ -91,7 +104,10 @@ const tree = style({
91104 }
92105} , getAllowedOverrides ( { height : true } ) ) ;
93106
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 > ) {
95111 let { children, isDetached, isEmphasized, UNSAFE_className, UNSAFE_style} = props ;
96112 let scale = useScale ( ) ;
97113
@@ -180,7 +196,6 @@ const treeRow = style({
180196 }
181197} ) ;
182198
183-
184199const treeCellGrid = style ( {
185200 display : 'grid' ,
186201 width : 'full' ,
@@ -346,7 +361,6 @@ export const TreeViewItemContent = (props: TreeViewItemContentProps): ReactNode
346361 gridArea : 'level-padding' ,
347362 width : 'calc(calc(var(--tree-item-level, 0) - 1) * var(--indent))'
348363 } ) } />
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 */ }
350364 < ExpandableRowChevron isDisabled = { isDisabled } isExpanded = { isExpanded } scale = { scale } isHidden = { ! ( hasChildItems ) } />
351365 < Provider
352366 values = { [
@@ -368,6 +382,33 @@ export const TreeViewItemContent = (props: TreeViewItemContentProps): ReactNode
368382 ) ;
369383} ;
370384
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+
371412interface ExpandableRowChevronProps {
372413 isExpanded ?: boolean ,
373414 isDisabled ?: boolean ,
@@ -437,9 +478,3 @@ function ExpandableRowChevron(props: ExpandableRowChevronProps) {
437478 </ Button >
438479 ) ;
439480}
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