12
12
13
13
import { action } from '@storybook/addon-actions' ;
14
14
import { Autocomplete , Button , Cell , Collection , Column , DialogTrigger , GridList , Header , Input , Keyboard , Label , ListBox , ListBoxSection , ListLayout , Menu , MenuItem , MenuSection , MenuTrigger , OverlayArrow , Popover , Row , SearchField , Select , SelectValue , Separator , SubmenuTrigger , Table , TableBody , TableHeader , TableLayout , TagGroup , TagList , Text , TextField , Tooltip , TooltipTrigger , Virtualizer } from 'react-aria-components' ;
15
+ import { LoadingSpinner , MyListBoxItem , MyMenuItem } from './utils' ;
15
16
import { Meta , StoryObj } from '@storybook/react' ;
16
17
import { MyCheckbox } from './Table.stories' ;
17
- import { MyListBoxItem , MyMenuItem } from './utils ' ;
18
- import { MyListBoxLoaderIndicator , renderEmptyState } from './ListBox.stories' ;
18
+ import { MyGridListItem } from './GridList.stories ' ;
19
+ import { MyListBoxLoaderIndicator } from './ListBox.stories' ;
19
20
import { MyTag } from './TagGroup.stories' ;
20
- import React from 'react' ;
21
+ import React , { useState } from 'react' ;
21
22
import styles from '../example/index.css' ;
22
23
import { useAsyncList , useListData , useTreeData } from 'react-stately' ;
23
24
import { useFilter } from 'react-aria' ;
24
25
import './styles.css' ;
25
- import { MyGridListItem } from './GridList.stories' ;
26
26
27
27
export default {
28
28
title : 'React Aria Components/Autocomplete' ,
@@ -868,8 +868,23 @@ interface Character {
868
868
birth_year : number
869
869
}
870
870
871
+ let renderEmptyState = ( list , cursor ) => {
872
+ let emptyStateContent ;
873
+ if ( list . loadingState === 'loading' ) {
874
+ emptyStateContent = < LoadingSpinner style = { { height : 20 , width : 20 , transform : 'translate(-50%, -50%)' } } /> ;
875
+ } else if ( list . loadingState === 'idle' && ! cursor ) {
876
+ emptyStateContent = 'No results' ;
877
+ }
878
+ return (
879
+ < div style = { { height : 30 , width : '100%' } } >
880
+ { emptyStateContent }
881
+ </ div >
882
+ ) ;
883
+ } ;
884
+
871
885
872
886
export const AutocompleteWithAsyncListBox = ( args ) => {
887
+ let [ cursor , setCursor ] = useState ( null ) ;
873
888
let list = useAsyncList < Character > ( {
874
889
async load ( { signal, cursor, filterText} ) {
875
890
if ( cursor ) {
@@ -879,6 +894,7 @@ export const AutocompleteWithAsyncListBox = (args) => {
879
894
await new Promise ( resolve => setTimeout ( resolve , args . delay ) ) ;
880
895
let res = await fetch ( cursor || `https://swapi.py4e.com/api/people/?search=${ filterText } ` , { signal} ) ;
881
896
let json = await res . json ( ) ;
897
+ setCursor ( json . next ) ;
882
898
return {
883
899
items : json . results ,
884
900
cursor : json . next
@@ -913,7 +929,7 @@ export const AutocompleteWithAsyncListBox = (args) => {
913
929
display : 'flex'
914
930
} }
915
931
aria-label = "async virtualized listbox"
916
- renderEmptyState = { ( ) => renderEmptyState ( { isLoading : list . isLoading } ) } >
932
+ renderEmptyState = { ( ) => renderEmptyState ( list , cursor ) } >
917
933
< Collection items = { list . items } >
918
934
{ ( item : Character ) => (
919
935
< MyListBoxItem
@@ -1075,10 +1091,10 @@ export const AutocompleteWithTagGroup = () => {
1075
1091
) ;
1076
1092
} ;
1077
1093
1078
- function AutocompletePreserveFirstSection ( args ) {
1094
+ function AutocompleteNodeFiltering ( args ) {
1079
1095
let { contains} = useFilter ( { sensitivity : 'base' } ) ;
1080
1096
let filter = ( textValue , inputValue , node ) => {
1081
- if ( node . parentKey === 'Section 1' ) {
1097
+ if ( ( node . parentKey === 'Section 1' && textValue === 'Open View' ) || ( node . parentKey === 'Section 2' && textValue === 'Appearance' ) ) {
1082
1098
return true ;
1083
1099
}
1084
1100
return contains ( textValue , inputValue ) ;
@@ -1101,6 +1117,11 @@ function AutocompletePreserveFirstSection(args) {
1101
1117
}
1102
1118
1103
1119
export const AutocompletePreserveFirstSectionStory : AutocompleteStory = {
1104
- render : ( args ) => < AutocompletePreserveFirstSection { ...args } /> ,
1105
- name : 'Autocomplete, never filter first section'
1120
+ render : ( args ) => < AutocompleteNodeFiltering { ...args } /> ,
1121
+ name : 'Autocomplete, per node filtering' ,
1122
+ parameters : {
1123
+ description : {
1124
+ data : 'It should never filter out Open View or Appearance'
1125
+ }
1126
+ }
1106
1127
} ;
0 commit comments