Skip to content

Commit

Permalink
feat(native): selectField with search
Browse files Browse the repository at this point in the history
  • Loading branch information
defless committed Feb 2, 2021
1 parent c8bccb9 commit b102975
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 13 deletions.
88 changes: 75 additions & 13 deletions packages/junipero-native/lib/SelectField/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import React, {
} from 'react';
import PropTypes from 'prop-types';
import { mockState } from '@poool/junipero-utils';
import { useTimeout } from '@poool/junipero-hooks';
import { TouchableWithoutFeedback, Text, View } from 'react-native';
import TextField from '../TextField';

import { applyStyles } from '../theme';
import styles from './index.styles.js';
Expand All @@ -15,6 +17,7 @@ const SelectField = forwardRef(({
autoFocus = false,
testID = 'SelectField',
label,
noItems = 'No items found :(',
noSearchResults = 'No result found :(',
placeholder,
disabled = false,
Expand All @@ -23,20 +26,30 @@ const SelectField = forwardRef(({
options = [],
parseTitle = val => val?.toString?.(),
parseValue,
search,
searchPlaceholder = 'Search...',
searchMinCharacters = 2,
searchThreshold = 400,
customStyle = {},
...rest }, ref) => {

const innerRef = useRef();
const [state, dispatch] = useReducer(mockState, {
active: autoFocus,
selectedOption: defaultOption,
searchValue: '',
searching: false,
});

useImperativeHandle(ref, () => ({
active: state.active,
selectedOption: state.selectedOption,
}));

useTimeout(() => {
search_();
}, searchThreshold, [state.searchValue]);

const onPress_ = () => {
if (disabled) {
return;
Expand All @@ -55,6 +68,23 @@ const SelectField = forwardRef(({
onChange(value);
};

const onSearch_ = field =>
dispatch({ searchValue: field.value, searching: true });

const search_ = async () => {
console.log('pipi');
if (!state.searchValue) {
dispatch({ searching: false, searchResults: null });
}

if (state.searchValue?.length < searchMinCharacters) {
return;
}

const results = await search(state.searchValue);
dispatch({ searchResults: results, searching: false });
};

return (
<View
pointerEvents={disabled ? 'none' : 'auto'}
Expand Down Expand Up @@ -147,20 +177,47 @@ const SelectField = forwardRef(({
</TouchableWithoutFeedback>
{ state.active &&
<View style={styles.dropdownMenu} testID="SelectField/Dropdown">
{ options.length
? options.map(option =>
<Text
key={parseTitle(option)}
testID={parseTitle(option)}
style={styles.dropdownItem}
onPress={onOptionPress_.bind(null, option)}>
{parseTitle(option)}
{
search &&
<View style={styles.search}>
<TextField
placeholder={searchPlaceholder}
onChange={onSearch_}
/>
</View>
}
{ state.searchResults
? state.searchResults.length
? state.searchResults.map(result =>
<Text
key={parseTitle(result)}
testID={parseTitle(result)}
style={styles.dropdownItem}
onPress={onOptionPress_.bind(null, result)}>
{parseTitle(result)}
</Text>
)
: <Text style={styles.noResults} testID="SelectField/NoResults" >
{noSearchResults}
</Text>
: options.length
? options.map(option =>
<Text
key={parseTitle(option)}
testID={parseTitle(option)}
style={[
styles.dropdownItem,
applyStyles(state.searching, [
styles.dropdownItem__searching,
]),
]}
onPress={onOptionPress_.bind(null, option)}>
{parseTitle(option)}
</Text>
)
: <Text style={styles.noResults} testID="SelectField/NoResults" >
{noItems}
</Text>
)
: <Text style={styles.noResults} testID="SelectField/NoResults" >
{noSearchResults}
</Text>

}
</View>
}
Expand All @@ -172,6 +229,7 @@ SelectField.propTypes = {
autoFocus: PropTypes.bool,
customStyle: PropTypes.object,
placeholder: PropTypes.string,
noItems: PropTypes.string,
noSearchResults: PropTypes.string,
label: PropTypes.string,
disabled: PropTypes.bool,
Expand All @@ -180,6 +238,10 @@ SelectField.propTypes = {
onChange: PropTypes.func,
parseTitle: PropTypes.func,
parseValue: PropTypes.func,
search: PropTypes.func,
searchPlaceholder: PropTypes.string,
searchMinCharacters: PropTypes.number,
searchThreshold: PropTypes.number,
testID: PropTypes.string,
};

Expand Down
9 changes: 9 additions & 0 deletions packages/junipero-native/lib/SelectField/index.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export default { title: 'junipero-native/SelectField' };

const options = ['One', 'Two', 'Three'];

const search = ['Four', 'Five', 'Six'];

const objectOptions = [
{ title: 'One', value: 1 },
{ title: 'Two', value: 2 },
Expand Down Expand Up @@ -85,3 +87,10 @@ export const autoFocused = () => (
/>
</React.Fragment>
);

export const withSearch = () => (
<SelectField
options={options}
search={val => search.filter(o => (new RegExp(val, 'ig')).test(o))}
onChange={action('change')} />
);
8 changes: 8 additions & 0 deletions packages/junipero-native/lib/SelectField/index.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,19 @@ export default StyleSheet.create({
...commons.defaultFont,
paddingVertical: 5,
paddingHorizontal: 20,
opacity: 1,
},
dropdownItem__searching: {
opacity: 0.5,
},
noResults: {
...commons.defaultFont,
color: colors.shuttleGray,
padding: 10,
textAlign: 'center',
},
search: {
paddingHorizontal: 10,
paddingBottom: 10,
},
});

0 comments on commit b102975

Please sign in to comment.