feat: create search bar
This commit is contained in:
parent
c0cbef73c2
commit
bc68650c6a
|
@ -0,0 +1,11 @@
|
|||
import * as React from 'react';
|
||||
import Svg, { FillProps, Path } from 'react-native-svg';
|
||||
|
||||
export default ({ fill }: FillProps) => (
|
||||
<Svg width="23" height="23" viewBox="0 0 24 24" fill="none">
|
||||
<Path
|
||||
d="M20.71 19.29l-3.4-3.39A7.92 7.92 0 0 0 19 11a8 8 0 1 0-8 8 7.92 7.92 0 0 0 4.9-1.69l3.39 3.4a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.42zM5 11a6 6 0 1 1 6 6 6 6 0 0 1-6-6z"
|
||||
fill={fill}
|
||||
/>
|
||||
</Svg>
|
||||
);
|
|
@ -23,6 +23,7 @@ export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
|||
disabledCategory,
|
||||
activeCategoryContainerColor,
|
||||
categoryPosition,
|
||||
searchPhrase,
|
||||
} = React.useContext(KeyboardContext);
|
||||
|
||||
const handleScrollToCategory = React.useCallback(
|
||||
|
@ -94,9 +95,11 @@ export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
|
|||
<View style={[categoryPosition === 'floating' && styles.floating]}>
|
||||
<View style={getStylesBasedOnPosition()}>
|
||||
<FlatList
|
||||
data={CATEGORIES_NAVIGATION.filter(
|
||||
({ category }) => !disabledCategory.includes(category)
|
||||
)}
|
||||
data={CATEGORIES_NAVIGATION.filter(({ category }) => {
|
||||
console.log(searchPhrase, 'search');
|
||||
if (searchPhrase === '' && category === 'search') return false;
|
||||
return !disabledCategory.includes(category);
|
||||
})}
|
||||
keyExtractor={(item) => item.category}
|
||||
renderItem={rendarItem}
|
||||
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { EmojiCategory } from './EmojiCategory';
|
|||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
import { Categories } from './Categories';
|
||||
import emojisByGroup from '../assets/emojis.json';
|
||||
import { SearchBar } from './SearchBar';
|
||||
|
||||
export const EmojiStaticKeyboard = () => {
|
||||
const { width } = useWindowDimensions();
|
||||
|
@ -21,6 +22,9 @@ export const EmojiStaticKeyboard = () => {
|
|||
onCategoryChangeFailed,
|
||||
disabledCategory,
|
||||
categoryPosition,
|
||||
enableSearchBar,
|
||||
searchPhrase,
|
||||
setActiveCategoryIndex,
|
||||
} = React.useContext(KeyboardContext);
|
||||
|
||||
const flatListRef = React.useRef<FlatList>(null);
|
||||
|
@ -47,6 +51,29 @@ export const EmojiStaticKeyboard = () => {
|
|||
}).start();
|
||||
}, [activeCategoryIndex, scrollNav]);
|
||||
|
||||
const getData = React.useCallback(() => {
|
||||
const enabledCategories = emojisByGroup.filter((category) => {
|
||||
const title = category.title as CategoryTypes;
|
||||
return !disabledCategory.includes(title);
|
||||
});
|
||||
enabledCategories.push({
|
||||
title: 'search',
|
||||
data: emojisByGroup
|
||||
.map((group) => group.data)
|
||||
.flat()
|
||||
.filter((emoji) => {
|
||||
return emoji.name.toLowerCase().includes(searchPhrase.toLowerCase());
|
||||
}),
|
||||
});
|
||||
return enabledCategories;
|
||||
}, [disabledCategory, searchPhrase]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (searchPhrase !== '') {
|
||||
flatListRef.current?.scrollToEnd();
|
||||
setActiveCategoryIndex(getData().length - 1);
|
||||
}
|
||||
}, [getData, searchPhrase, setActiveCategoryIndex]);
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
|
@ -56,11 +83,10 @@ export const EmojiStaticKeyboard = () => {
|
|||
containerStyles,
|
||||
]}
|
||||
>
|
||||
{enableSearchBar && <SearchBar />}
|
||||
<Animated.FlatList
|
||||
data={emojisByGroup.filter((category) => {
|
||||
const title = category.title as CategoryTypes;
|
||||
return !disabledCategory.includes(title);
|
||||
})}
|
||||
data={getData()}
|
||||
extraData={searchPhrase}
|
||||
keyExtractor={(item: EmojisByCategory) => item.title}
|
||||
renderItem={renderItem}
|
||||
removeClippedSubviews={true}
|
||||
|
|
|
@ -8,6 +8,7 @@ import Smile from '../assets/Smile';
|
|||
import Trees from '../assets/Trees';
|
||||
import Ban from '../assets/Ban';
|
||||
import Users from '../assets/Users';
|
||||
import Search from '../assets/Search';
|
||||
|
||||
export const Icon = ({
|
||||
iconName,
|
||||
|
@ -40,6 +41,8 @@ export const Icon = ({
|
|||
return <Ban fill={color()} />;
|
||||
case 'Users':
|
||||
return <Users fill={color()} />;
|
||||
case 'Search':
|
||||
return <Search fill={color()} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import * as React from 'react';
|
||||
import { View, StyleSheet, TextInput } from 'react-native';
|
||||
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||
|
||||
export const SearchBar = () => {
|
||||
const [search, setSearch] = React.useState('');
|
||||
const { setSearchPhrase, translation } = React.useContext(KeyboardContext);
|
||||
React.useEffect(() => {
|
||||
console.log(search);
|
||||
}, [search]);
|
||||
|
||||
const handleSearch = (text: string) => {
|
||||
setSearch(text);
|
||||
setSearchPhrase(text);
|
||||
};
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={search}
|
||||
onChangeText={handleSearch}
|
||||
placeholder={translation.search}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginTop: 16,
|
||||
},
|
||||
input: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 12,
|
||||
marginHorizontal: 16,
|
||||
borderRadius: 100,
|
||||
borderWidth: 1,
|
||||
borderColor: '#00000011',
|
||||
},
|
||||
});
|
|
@ -38,12 +38,15 @@ export type KeyboardProps = {
|
|||
translation?: CategoryTranslation;
|
||||
disabledCategory?: CategoryTypes[];
|
||||
categoryPosition?: CategoryPosition;
|
||||
enableSearchBar?: boolean;
|
||||
};
|
||||
export type ContextValues = {
|
||||
activeCategoryIndex: number;
|
||||
setActiveCategoryIndex: (index: number) => void;
|
||||
numberOfColumns: number;
|
||||
width: number;
|
||||
searchPhrase: string;
|
||||
setSearchPhrase: (phrase: string) => void;
|
||||
};
|
||||
|
||||
export const KeyboardContext = React.createContext<
|
||||
|
|
|
@ -37,6 +37,7 @@ export const defaultKeyboardContext: Required<KeyboardProps> = {
|
|||
translation: en,
|
||||
disabledCategory: [],
|
||||
categoryPosition: 'floating',
|
||||
enableSearchBar: false,
|
||||
};
|
||||
|
||||
export const defaultKeyboardValues: ContextValues = {
|
||||
|
@ -44,11 +45,14 @@ export const defaultKeyboardValues: ContextValues = {
|
|||
setActiveCategoryIndex: () => {},
|
||||
numberOfColumns: 5,
|
||||
width: 0,
|
||||
searchPhrase: '',
|
||||
setSearchPhrase: (_phrase: string) => {},
|
||||
};
|
||||
|
||||
export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
|
||||
const { width } = useWindowDimensions();
|
||||
const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0);
|
||||
const [searchPhrase, setSearchPhrase] = React.useState('');
|
||||
const numberOfColumns = React.useRef<number>(
|
||||
Math.floor(
|
||||
width /
|
||||
|
@ -60,6 +64,7 @@ export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
|
|||
);
|
||||
React.useEffect(() => {
|
||||
if (props.open) setActiveCategoryIndex(0);
|
||||
setSearchPhrase('');
|
||||
}, [props.open]);
|
||||
|
||||
const value: Required<KeyboardProps> & ContextValues = {
|
||||
|
@ -70,6 +75,8 @@ export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
|
|||
setActiveCategoryIndex,
|
||||
numberOfColumns: numberOfColumns.current,
|
||||
width,
|
||||
searchPhrase,
|
||||
setSearchPhrase,
|
||||
};
|
||||
return (
|
||||
<KeyboardContext.Provider value={value}>
|
||||
|
|
|
@ -10,5 +10,6 @@ export const en: CategoryTranslation = {
|
|||
objects: 'Objects',
|
||||
symbols: 'Symbols',
|
||||
flags: 'Flags',
|
||||
search: 'Search',
|
||||
};
|
||||
export default en;
|
||||
|
|
|
@ -10,5 +10,6 @@ const pl: CategoryTranslation = {
|
|||
objects: 'Przedmioty',
|
||||
symbols: 'Symbole',
|
||||
flags: 'Flagi',
|
||||
search: 'Szukaj',
|
||||
};
|
||||
export default pl;
|
||||
|
|
|
@ -19,7 +19,8 @@ export type CategoryTypes =
|
|||
| 'activities'
|
||||
| 'objects'
|
||||
| 'symbols'
|
||||
| 'flags';
|
||||
| 'flags'
|
||||
| 'search';
|
||||
|
||||
export type CategoryPosition = 'floating' | 'top' | 'bottom';
|
||||
|
||||
|
@ -33,6 +34,7 @@ export const CATEGORIES: CategoryTypes[] = [
|
|||
'objects',
|
||||
'symbols',
|
||||
'flags',
|
||||
'search',
|
||||
];
|
||||
|
||||
export type CategoryNavigationItem = {
|
||||
|
@ -54,6 +56,7 @@ export const CATEGORIES_NAVIGATION: CategoryNavigationItem[] = [
|
|||
{ icon: 'Lightbulb', category: 'objects' },
|
||||
{ icon: 'Ban', category: 'symbols' },
|
||||
{ icon: 'Flag', category: 'flags' },
|
||||
{ icon: 'Search', category: 'search' },
|
||||
];
|
||||
|
||||
export type EmojisByCategory = {
|
||||
|
|
Loading…
Reference in New Issue