Feature/static keyboard (#2)
* fix: use container styles fix * refactor: rename static modal * refactor: let use EmojiStaticKeyboard outside modal * chore: add static keyboard to readme * fix: improve readme * refactor: easier use of static keyboard and refactor contexts * refactor: update readme example
This commit is contained in:
parent
bdb8799fe1
commit
cbe4243248
16
README.md
16
README.md
|
@ -61,6 +61,16 @@ export default function App() {
|
||||||
| onCategoryChangeFailed | function | warn(info) | no | Callback on category change failed (info: {index, highestMeasuredFrameIndex, averageItemLength}) |
|
| onCategoryChangeFailed | function | warn(info) | no | Callback on category change failed (info: {index, highestMeasuredFrameIndex, averageItemLength}) |
|
||||||
| translation | CategoryTranslation | en | no | Translation object *see translation section* |
|
| translation | CategoryTranslation | en | no | Translation object *see translation section* |
|
||||||
| disabledCategory | CategoryTypes[] | [] | no | Hide categories by passing their slugs |
|
| disabledCategory | CategoryTypes[] | [] | no | Hide categories by passing their slugs |
|
||||||
|
## 🖼 Usage as static
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { EmojiKeyboard } from 'rn-emoji-keyboard';
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
<EmojiKeyboard onEmojiSelected={handlePick} />
|
||||||
|
```
|
||||||
|
Example about serving as static keyboard [you can find here](/example/src/Dark/Dark.tsx).
|
||||||
## 🇺🇸 Internationalization
|
## 🇺🇸 Internationalization
|
||||||
### Pre-defined
|
### Pre-defined
|
||||||
Due to the limited translation possibilities, we only provide a few pre-defined translations into the following languages:
|
Due to the limited translation possibilities, we only provide a few pre-defined translations into the following languages:
|
||||||
|
@ -101,11 +111,13 @@ You can clone the repo and run `yarn example ios` or `yarn example android` to p
|
||||||
![Preview](/example/assets/translated-preview.jpg)
|
![Preview](/example/assets/translated-preview.jpg)
|
||||||
### [DisabledCategories](/example/src/DisabledCategories/DisabledCategories.tsx)
|
### [DisabledCategories](/example/src/DisabledCategories/DisabledCategories.tsx)
|
||||||
![Preview](/example/assets/categories-preview.jpg)
|
![Preview](/example/assets/categories-preview.jpg)
|
||||||
### [Static (without knob)](/example/src/Static/Static.tsx)
|
### [StaticModal (without knob)](/example/src/StaticModal/StaticModal.tsx)
|
||||||
|
![Preview](/example/assets/static-modal-preview.jpg)
|
||||||
|
### [Static](/example/src/Static/Static.tsx)
|
||||||
![Preview](/example/assets/static-preview.jpg)
|
![Preview](/example/assets/static-preview.jpg)
|
||||||
## 📈 Future plans
|
## 📈 Future plans
|
||||||
* Skin tone palette selector.
|
* Skin tone palette selector.
|
||||||
* Search bar.
|
* Search bar.
|
||||||
* Hide forbidden emojis.
|
* Write native module to display forbidden emojis on android.
|
||||||
## ⚖️ License
|
## ⚖️ License
|
||||||
**[MIT](/LICENSE)**
|
**[MIT](/LICENSE)**
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 46 KiB |
|
@ -7,6 +7,7 @@ import Basic from './Basic/Basic';
|
||||||
import Dark from './Dark/Dark';
|
import Dark from './Dark/Dark';
|
||||||
import Translated from './Translated/Translated';
|
import Translated from './Translated/Translated';
|
||||||
import DisabledCategories from './DisabledCategories/DisabledCategories';
|
import DisabledCategories from './DisabledCategories/DisabledCategories';
|
||||||
|
import StaticModal from './StaticModal/StaticModal';
|
||||||
import Static from './Static/Static';
|
import Static from './Static/Static';
|
||||||
|
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator();
|
||||||
|
@ -22,6 +23,7 @@ export default () => {
|
||||||
name="DisabledCategories"
|
name="DisabledCategories"
|
||||||
component={DisabledCategories}
|
component={DisabledCategories}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen name="StaticModal" component={StaticModal} />
|
||||||
<Stack.Screen name="Static" component={Static} />
|
<Stack.Screen name="Static" component={Static} />
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
|
|
|
@ -14,7 +14,7 @@ const Basic = () => {
|
||||||
setIsModalOpen((prev) => !prev);
|
setIsModalOpen((prev) => !prev);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView style={styles.container}>
|
||||||
<Text style={styles.text}>Result: {result}</Text>
|
<Text style={styles.text}>Result: {result}</Text>
|
||||||
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
||||||
<Text style={styles.text}>Open</Text>
|
<Text style={styles.text}>Open</Text>
|
||||||
|
|
|
@ -14,7 +14,7 @@ const DisabledCategories = () => {
|
||||||
setIsModalOpen((prev) => !prev);
|
setIsModalOpen((prev) => !prev);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView style={styles.container}>
|
||||||
<Text style={styles.text}>Result: {result}</Text>
|
<Text style={styles.text}>Result: {result}</Text>
|
||||||
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
||||||
<Text style={styles.text}>Open</Text>
|
<Text style={styles.text}>Open</Text>
|
||||||
|
|
|
@ -9,6 +9,7 @@ type RootStackParamList = {
|
||||||
Dark: undefined;
|
Dark: undefined;
|
||||||
Translated: undefined;
|
Translated: undefined;
|
||||||
DisabledCategories: undefined;
|
DisabledCategories: undefined;
|
||||||
|
StaticModal: undefined;
|
||||||
Static: undefined;
|
Static: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +29,10 @@ const Examples = ({ navigation }: Props) => {
|
||||||
title="DisabledCategories"
|
title="DisabledCategories"
|
||||||
onPress={() => navigation.navigate('DisabledCategories')}
|
onPress={() => navigation.navigate('DisabledCategories')}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
title="StaticModal"
|
||||||
|
onPress={() => navigation.navigate('StaticModal')}
|
||||||
|
/>
|
||||||
<Button title="Static" onPress={() => navigation.navigate('Static')} />
|
<Button title="Static" onPress={() => navigation.navigate('Static')} />
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
|
|
@ -1,32 +1,26 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
import EmojiPicker from 'rn-emoji-keyboard';
|
import { EmojiKeyboard } from 'rn-emoji-keyboard';
|
||||||
import type { EmojiType } from 'src/types';
|
import type { EmojiType } from 'src/types';
|
||||||
|
|
||||||
const Static = () => {
|
const Static = () => {
|
||||||
const [result, setResult] = React.useState<string>();
|
const [result, setResult] = React.useState<string>();
|
||||||
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
|
||||||
|
|
||||||
const handlePick = (emoji: EmojiType) => {
|
const handlePick = (emoji: EmojiType) => {
|
||||||
console.log(emoji);
|
|
||||||
setResult(emoji.emoji);
|
setResult(emoji.emoji);
|
||||||
setIsModalOpen((prev) => !prev);
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView style={styles.container}>
|
||||||
|
<View style={styles.container}>
|
||||||
<Text style={styles.text}>Result: {result}</Text>
|
<Text style={styles.text}>Result: {result}</Text>
|
||||||
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
</View>
|
||||||
<Text style={styles.text}>Open</Text>
|
<View style={styles.container}>
|
||||||
</TouchableOpacity>
|
<EmojiKeyboard
|
||||||
|
|
||||||
<EmojiPicker
|
|
||||||
onEmojiSelected={handlePick}
|
onEmojiSelected={handlePick}
|
||||||
open={isModalOpen}
|
containerStyles={styles.keyboardContainer}
|
||||||
onClose={() => setIsModalOpen(false)}
|
|
||||||
expandable={false}
|
|
||||||
defaultHeight="65%"
|
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -40,6 +34,9 @@ const styles = StyleSheet.create({
|
||||||
margin: 64,
|
margin: 64,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
},
|
},
|
||||||
|
keyboardContainer: {
|
||||||
|
borderRadius: 0,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Static;
|
export default Static;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
|
||||||
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import EmojiPicker from 'rn-emoji-keyboard';
|
||||||
|
import type { EmojiType } from 'src/types';
|
||||||
|
|
||||||
|
const StaticModal = () => {
|
||||||
|
const [result, setResult] = React.useState<string>();
|
||||||
|
const [isModalOpen, setIsModalOpen] = React.useState<boolean>(false);
|
||||||
|
|
||||||
|
const handlePick = (emoji: EmojiType) => {
|
||||||
|
console.log(emoji);
|
||||||
|
setResult(emoji.emoji);
|
||||||
|
setIsModalOpen((prev) => !prev);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<Text style={styles.text}>Result: {result}</Text>
|
||||||
|
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
||||||
|
<Text style={styles.text}>Open</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<EmojiPicker
|
||||||
|
onEmojiSelected={handlePick}
|
||||||
|
open={isModalOpen}
|
||||||
|
onClose={() => setIsModalOpen(false)}
|
||||||
|
expandable={false}
|
||||||
|
defaultHeight="65%"
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
textAlign: 'center',
|
||||||
|
margin: 64,
|
||||||
|
fontSize: 18,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default StaticModal;
|
|
@ -14,7 +14,7 @@ const Translated = () => {
|
||||||
setIsModalOpen((prev) => !prev);
|
setIsModalOpen((prev) => !prev);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView style={styles.container}>
|
||||||
<Text style={styles.text}>Emotka: {result}</Text>
|
<Text style={styles.text}>Emotka: {result}</Text>
|
||||||
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
<TouchableOpacity onPress={() => setIsModalOpen(true)}>
|
||||||
<Text style={styles.text}>Otwórz</Text>
|
<Text style={styles.text}>Otwórz</Text>
|
||||||
|
|
|
@ -1,90 +1,19 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
|
||||||
|
import { KeyboardProvider } from './contexts/KeyboardProvider';
|
||||||
|
import type {
|
||||||
|
KeyboardProps,
|
||||||
|
OnEmojiSelected,
|
||||||
|
} from './contexts/KeyboardContext';
|
||||||
|
|
||||||
import {
|
type EmojiKeyboardProps = {
|
||||||
StyleSheet,
|
onEmojiSelected: OnEmojiSelected;
|
||||||
View,
|
} & Partial<KeyboardProps>;
|
||||||
FlatList,
|
|
||||||
useWindowDimensions,
|
|
||||||
Animated,
|
|
||||||
} from 'react-native';
|
|
||||||
import type { CategoryTypes, EmojisByCategory } from './types';
|
|
||||||
import { EmojiCategory } from './components/EmojiCategory';
|
|
||||||
import { KeyboardContext } from './KeyboardContext';
|
|
||||||
import { Categories } from './components/Categories';
|
|
||||||
import emojisByGroup from './assets/emojis.json';
|
|
||||||
|
|
||||||
export const EmojiKeyboard = () => {
|
|
||||||
const { width } = useWindowDimensions();
|
|
||||||
const {
|
|
||||||
activeCategoryIndex,
|
|
||||||
containerStyles,
|
|
||||||
onCategoryChangeFailed,
|
|
||||||
disabledCategory,
|
|
||||||
} = React.useContext(KeyboardContext);
|
|
||||||
|
|
||||||
const flatListRef = React.useRef<FlatList>(null);
|
|
||||||
|
|
||||||
const scrollNav = React.useRef(new Animated.Value(0)).current;
|
|
||||||
|
|
||||||
const getItemLayout = (
|
|
||||||
_: CategoryTypes[] | null | undefined,
|
|
||||||
index: number
|
|
||||||
) => ({
|
|
||||||
length: width,
|
|
||||||
offset: width * index,
|
|
||||||
index,
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderItem = React.useCallback(
|
|
||||||
(props) => <EmojiCategory {...props} />,
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
React.useEffect(() => {
|
|
||||||
Animated.spring(scrollNav, {
|
|
||||||
toValue: activeCategoryIndex * (28 + 9),
|
|
||||||
useNativeDriver: true,
|
|
||||||
}).start();
|
|
||||||
}, [activeCategoryIndex, scrollNav]);
|
|
||||||
|
|
||||||
|
export const EmojiKeyboard = (props: EmojiKeyboardProps) => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, styles.containerShadow, containerStyles]}>
|
<KeyboardProvider {...props}>
|
||||||
<Animated.FlatList
|
<EmojiStaticKeyboard />
|
||||||
data={emojisByGroup.filter((category) => {
|
</KeyboardProvider>
|
||||||
const title = category.title as CategoryTypes;
|
|
||||||
return !disabledCategory.includes(title);
|
|
||||||
})}
|
|
||||||
keyExtractor={(item: EmojisByCategory) => item.title}
|
|
||||||
renderItem={renderItem}
|
|
||||||
removeClippedSubviews={true}
|
|
||||||
ref={flatListRef}
|
|
||||||
onScrollToIndexFailed={onCategoryChangeFailed}
|
|
||||||
horizontal
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
pagingEnabled
|
|
||||||
scrollEventThrottle={16}
|
|
||||||
getItemLayout={getItemLayout}
|
|
||||||
scrollEnabled={false}
|
|
||||||
initialNumToRender={1}
|
|
||||||
windowSize={2}
|
|
||||||
maxToRenderPerBatch={1}
|
|
||||||
/>
|
|
||||||
<Categories flatListRef={flatListRef} scrollNav={scrollNav} />
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
paddingTop: 16,
|
|
||||||
borderRadius: 16,
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
},
|
|
||||||
containerShadow: {
|
|
||||||
shadowColor: 'black',
|
|
||||||
shadowOpacity: 0.15,
|
|
||||||
shadowOffset: { width: 0, height: 0 },
|
|
||||||
shadowRadius: 5,
|
|
||||||
elevation: 10,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Animated, useWindowDimensions } from 'react-native';
|
import { Animated, useWindowDimensions } from 'react-native';
|
||||||
import { EmojiKeyboard } from './EmojiKeyboard';
|
import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
|
||||||
import { Knob } from './components/Knob';
|
import { Knob } from './components/Knob';
|
||||||
import { defaultKeyboardContext, KeyboardProvider } from './KeyboardProvider';
|
import {
|
||||||
import type { KeyboardProps } from './KeyboardContext';
|
defaultKeyboardContext,
|
||||||
|
KeyboardProvider,
|
||||||
|
} from './contexts/KeyboardProvider';
|
||||||
|
import type { KeyboardProps } from './contexts/KeyboardContext';
|
||||||
import type { EmojiType } from './types';
|
import type { EmojiType } from './types';
|
||||||
import { ModalWithBackdrop } from './components/ModalWithBackdrop';
|
import { ModalWithBackdrop } from './components/ModalWithBackdrop';
|
||||||
import { getHeight } from './utils';
|
import { getHeight } from './utils';
|
||||||
|
@ -61,7 +64,7 @@ export const EmojiPicker = ({
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<EmojiKeyboard />
|
<EmojiStaticKeyboard />
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</>
|
</>
|
||||||
</ModalWithBackdrop>
|
</ModalWithBackdrop>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, Animated, StyleSheet, FlatList } from 'react-native';
|
import { View, Animated, StyleSheet, FlatList } from 'react-native';
|
||||||
import { KeyboardContext } from '../KeyboardContext';
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
import {
|
import {
|
||||||
CATEGORIES,
|
CATEGORIES,
|
||||||
CATEGORIES_NAVIGATION,
|
CATEGORIES_NAVIGATION,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
import { KeyboardContext } from '../KeyboardContext';
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
import type { CategoryNavigationItem, CategoryTypes } from '../types';
|
import type { CategoryNavigationItem, CategoryTypes } from '../types';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as React from 'react';
|
||||||
import { StyleSheet, View, Text, FlatList } from 'react-native';
|
import { StyleSheet, View, Text, FlatList } from 'react-native';
|
||||||
import type { EmojisByCategory, EmojiType, JsonEmoji } from '../types';
|
import type { EmojisByCategory, EmojiType, JsonEmoji } from '../types';
|
||||||
import { SingleEmoji } from './SingleEmoji';
|
import { SingleEmoji } from './SingleEmoji';
|
||||||
import { KeyboardContext } from '../KeyboardContext';
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
|
|
||||||
const emptyEmoji = {
|
const emptyEmoji = {
|
||||||
emoji: '',
|
emoji: '',
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
FlatList,
|
||||||
|
useWindowDimensions,
|
||||||
|
Animated,
|
||||||
|
} from 'react-native';
|
||||||
|
import type { CategoryTypes, EmojisByCategory } from '../types';
|
||||||
|
import { EmojiCategory } from './EmojiCategory';
|
||||||
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
|
import { Categories } from './Categories';
|
||||||
|
import emojisByGroup from '../assets/emojis.json';
|
||||||
|
|
||||||
|
export const EmojiStaticKeyboard = () => {
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
|
const {
|
||||||
|
activeCategoryIndex,
|
||||||
|
containerStyles,
|
||||||
|
onCategoryChangeFailed,
|
||||||
|
disabledCategory,
|
||||||
|
} = React.useContext(KeyboardContext);
|
||||||
|
|
||||||
|
const flatListRef = React.useRef<FlatList>(null);
|
||||||
|
|
||||||
|
const scrollNav = React.useRef(new Animated.Value(0)).current;
|
||||||
|
|
||||||
|
const getItemLayout = (
|
||||||
|
_: CategoryTypes[] | null | undefined,
|
||||||
|
index: number
|
||||||
|
) => ({
|
||||||
|
length: width,
|
||||||
|
offset: width * index,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderItem = React.useCallback(
|
||||||
|
(props) => <EmojiCategory {...props} />,
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
React.useEffect(() => {
|
||||||
|
Animated.spring(scrollNav, {
|
||||||
|
toValue: activeCategoryIndex * (28 + 9),
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
}, [activeCategoryIndex, scrollNav]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, styles.containerShadow, containerStyles]}>
|
||||||
|
<Animated.FlatList
|
||||||
|
data={emojisByGroup.filter((category) => {
|
||||||
|
const title = category.title as CategoryTypes;
|
||||||
|
return !disabledCategory.includes(title);
|
||||||
|
})}
|
||||||
|
keyExtractor={(item: EmojisByCategory) => item.title}
|
||||||
|
renderItem={renderItem}
|
||||||
|
removeClippedSubviews={true}
|
||||||
|
ref={flatListRef}
|
||||||
|
onScrollToIndexFailed={onCategoryChangeFailed}
|
||||||
|
horizontal
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
pagingEnabled
|
||||||
|
scrollEventThrottle={16}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
|
scrollEnabled={false}
|
||||||
|
initialNumToRender={1}
|
||||||
|
windowSize={2}
|
||||||
|
maxToRenderPerBatch={1}
|
||||||
|
/>
|
||||||
|
<Categories flatListRef={flatListRef} scrollNav={scrollNav} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
paddingTop: 16,
|
||||||
|
borderRadius: 16,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
containerShadow: {
|
||||||
|
shadowColor: 'black',
|
||||||
|
shadowOpacity: 0.15,
|
||||||
|
shadowOffset: { width: 0, height: 0 },
|
||||||
|
shadowRadius: 5,
|
||||||
|
elevation: 10,
|
||||||
|
},
|
||||||
|
});
|
|
@ -7,7 +7,7 @@ import {
|
||||||
PanResponder,
|
PanResponder,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { getHeight } from '../utils';
|
import { getHeight } from '../utils';
|
||||||
import { KeyboardContext } from '../KeyboardContext';
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
|
|
||||||
type KnobProps = {
|
type KnobProps = {
|
||||||
offsetY: Animated.Value;
|
offsetY: Animated.Value;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { KeyboardContext } from '../KeyboardContext';
|
import { KeyboardContext } from '../contexts/KeyboardContext';
|
||||||
|
|
||||||
type ModalWithBackdropProps = {
|
type ModalWithBackdropProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
|
|
@ -4,12 +4,14 @@ import {
|
||||||
defaultKeyboardContext,
|
defaultKeyboardContext,
|
||||||
defaultKeyboardValues,
|
defaultKeyboardValues,
|
||||||
} from './KeyboardProvider';
|
} from './KeyboardProvider';
|
||||||
import type { CategoryTranslation, EmojiType, CategoryTypes } from './types';
|
import type { CategoryTranslation, EmojiType, CategoryTypes } from '../types';
|
||||||
|
|
||||||
|
export type OnEmojiSelected = (emoji: EmojiType) => void;
|
||||||
|
|
||||||
export type KeyboardProps = {
|
export type KeyboardProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onEmojiSelected: (emoji: EmojiType) => void;
|
onEmojiSelected: OnEmojiSelected;
|
||||||
emojiSize?: number;
|
emojiSize?: number;
|
||||||
containerStyles?: ViewStyle;
|
containerStyles?: ViewStyle;
|
||||||
knobStyles?: ViewStyle;
|
knobStyles?: ViewStyle;
|
|
@ -4,12 +4,14 @@ import {
|
||||||
KeyboardProps,
|
KeyboardProps,
|
||||||
ContextValues,
|
ContextValues,
|
||||||
KeyboardContext,
|
KeyboardContext,
|
||||||
|
OnEmojiSelected,
|
||||||
} from './KeyboardContext';
|
} from './KeyboardContext';
|
||||||
import en from './translation/en';
|
import en from '../translation/en';
|
||||||
import type { EmojiType } from './types';
|
import type { EmojiType } from '../types';
|
||||||
|
|
||||||
type ProviderProps = KeyboardProps & {
|
type ProviderProps = Partial<KeyboardProps> & {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
onEmojiSelected: OnEmojiSelected;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultKeyboardContext: Required<KeyboardProps> = {
|
export const defaultKeyboardContext: Required<KeyboardProps> = {
|
|
@ -1,10 +1,9 @@
|
||||||
import { EmojiKeyboard } from './EmojiKeyboard';
|
|
||||||
import { EmojiPicker } from './EmojiPicker';
|
import { EmojiPicker } from './EmojiPicker';
|
||||||
import { KeyboardProvider } from './KeyboardProvider';
|
import { EmojiKeyboard } from './EmojiKeyboard';
|
||||||
import en from './translation/en';
|
import en from './translation/en';
|
||||||
import pl from './translation/pl';
|
import pl from './translation/pl';
|
||||||
|
|
||||||
export { EmojiKeyboard, KeyboardProvider };
|
export { EmojiKeyboard };
|
||||||
export { en, pl };
|
export { en, pl };
|
||||||
|
|
||||||
export default EmojiPicker;
|
export default EmojiPicker;
|
||||||
|
|
Loading…
Reference in New Issue