diff --git a/README.md b/README.md
index 342dc34..8a60841 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,16 @@ export default function App() {
| onCategoryChangeFailed | function | warn(info) | no | Callback on category change failed (info: {index, highestMeasuredFrameIndex, averageItemLength}) |
| translation | CategoryTranslation | en | no | Translation object *see translation section* |
| disabledCategory | CategoryTypes[] | [] | no | Hide categories by passing their slugs |
+## 🖼 Usage as static
+
+```js
+import { EmojiKeyboard } from 'rn-emoji-keyboard';
+
+// ...
+
+
+```
+Example about serving as static keyboard [you can find here](/example/src/Dark/Dark.tsx).
## 🇺🇸 Internationalization
### Pre-defined
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)
### [DisabledCategories](/example/src/DisabledCategories/DisabledCategories.tsx)
![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)
## 📈 Future plans
* Skin tone palette selector.
* Search bar.
-* Hide forbidden emojis.
+* Write native module to display forbidden emojis on android.
## ⚖️ License
**[MIT](/LICENSE)**
diff --git a/example/assets/static-modal-preview.jpg b/example/assets/static-modal-preview.jpg
new file mode 100644
index 0000000..cdf165f
Binary files /dev/null and b/example/assets/static-modal-preview.jpg differ
diff --git a/example/assets/static-preview.jpg b/example/assets/static-preview.jpg
index cdf165f..4189492 100644
Binary files a/example/assets/static-preview.jpg and b/example/assets/static-preview.jpg differ
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 74b8418..67c9a24 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -7,6 +7,7 @@ import Basic from './Basic/Basic';
import Dark from './Dark/Dark';
import Translated from './Translated/Translated';
import DisabledCategories from './DisabledCategories/DisabledCategories';
+import StaticModal from './StaticModal/StaticModal';
import Static from './Static/Static';
const Stack = createStackNavigator();
@@ -22,6 +23,7 @@ export default () => {
name="DisabledCategories"
component={DisabledCategories}
/>
+
diff --git a/example/src/Basic/Basic.tsx b/example/src/Basic/Basic.tsx
index 198f860..3bfb3a6 100644
--- a/example/src/Basic/Basic.tsx
+++ b/example/src/Basic/Basic.tsx
@@ -14,7 +14,7 @@ const Basic = () => {
setIsModalOpen((prev) => !prev);
};
return (
-
+
Result: {result}
setIsModalOpen(true)}>
Open
diff --git a/example/src/DisabledCategories/DisabledCategories.tsx b/example/src/DisabledCategories/DisabledCategories.tsx
index 21a7294..3d6f72d 100644
--- a/example/src/DisabledCategories/DisabledCategories.tsx
+++ b/example/src/DisabledCategories/DisabledCategories.tsx
@@ -14,7 +14,7 @@ const DisabledCategories = () => {
setIsModalOpen((prev) => !prev);
};
return (
-
+
Result: {result}
setIsModalOpen(true)}>
Open
diff --git a/example/src/Examples/Examples.tsx b/example/src/Examples/Examples.tsx
index d8c992c..64a11b2 100644
--- a/example/src/Examples/Examples.tsx
+++ b/example/src/Examples/Examples.tsx
@@ -9,6 +9,7 @@ type RootStackParamList = {
Dark: undefined;
Translated: undefined;
DisabledCategories: undefined;
+ StaticModal: undefined;
Static: undefined;
};
@@ -28,6 +29,10 @@ const Examples = ({ navigation }: Props) => {
title="DisabledCategories"
onPress={() => navigation.navigate('DisabledCategories')}
/>
+
diff --git a/example/src/Static/Static.tsx b/example/src/Static/Static.tsx
index 31df522..a3e18e0 100644
--- a/example/src/Static/Static.tsx
+++ b/example/src/Static/Static.tsx
@@ -1,32 +1,26 @@
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 EmojiPicker from 'rn-emoji-keyboard';
+import { EmojiKeyboard } from 'rn-emoji-keyboard';
import type { EmojiType } from 'src/types';
const Static = () => {
const [result, setResult] = React.useState();
- const [isModalOpen, setIsModalOpen] = React.useState(false);
const handlePick = (emoji: EmojiType) => {
- console.log(emoji);
setResult(emoji.emoji);
- setIsModalOpen((prev) => !prev);
};
return (
-
- Result: {result}
- setIsModalOpen(true)}>
- Open
-
-
- setIsModalOpen(false)}
- expandable={false}
- defaultHeight="65%"
- />
+
+
+ Result: {result}
+
+
+
+
);
};
@@ -40,6 +34,9 @@ const styles = StyleSheet.create({
margin: 64,
fontSize: 18,
},
+ keyboardContainer: {
+ borderRadius: 0,
+ },
});
export default Static;
diff --git a/example/src/StaticModal/StaticModal.tsx b/example/src/StaticModal/StaticModal.tsx
new file mode 100644
index 0000000..e1d3476
--- /dev/null
+++ b/example/src/StaticModal/StaticModal.tsx
@@ -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();
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
+
+ const handlePick = (emoji: EmojiType) => {
+ console.log(emoji);
+ setResult(emoji.emoji);
+ setIsModalOpen((prev) => !prev);
+ };
+ return (
+
+ Result: {result}
+ setIsModalOpen(true)}>
+ Open
+
+
+ setIsModalOpen(false)}
+ expandable={false}
+ defaultHeight="65%"
+ />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ text: {
+ textAlign: 'center',
+ margin: 64,
+ fontSize: 18,
+ },
+});
+
+export default StaticModal;
diff --git a/example/src/Translated/Translated.tsx b/example/src/Translated/Translated.tsx
index 1863b99..4f7dd4a 100644
--- a/example/src/Translated/Translated.tsx
+++ b/example/src/Translated/Translated.tsx
@@ -14,7 +14,7 @@ const Translated = () => {
setIsModalOpen((prev) => !prev);
};
return (
-
+
Emotka: {result}
setIsModalOpen(true)}>
Otwórz
diff --git a/src/EmojiKeyboard.tsx b/src/EmojiKeyboard.tsx
index f287928..2faedb7 100644
--- a/src/EmojiKeyboard.tsx
+++ b/src/EmojiKeyboard.tsx
@@ -1,90 +1,19 @@
import * as React from 'react';
+import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
+import { KeyboardProvider } from './contexts/KeyboardProvider';
+import type {
+ KeyboardProps,
+ OnEmojiSelected,
+} from './contexts/KeyboardContext';
-import {
- StyleSheet,
- View,
- 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(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) => ,
- []
- );
- React.useEffect(() => {
- Animated.spring(scrollNav, {
- toValue: activeCategoryIndex * (28 + 9),
- useNativeDriver: true,
- }).start();
- }, [activeCategoryIndex, scrollNav]);
+type EmojiKeyboardProps = {
+ onEmojiSelected: OnEmojiSelected;
+} & Partial;
+export const EmojiKeyboard = (props: EmojiKeyboardProps) => {
return (
-
- {
- 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}
- />
-
-
+
+
+
);
};
-
-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,
- },
-});
diff --git a/src/EmojiPicker.tsx b/src/EmojiPicker.tsx
index 1e2453d..ebe5e99 100644
--- a/src/EmojiPicker.tsx
+++ b/src/EmojiPicker.tsx
@@ -1,9 +1,12 @@
import * as React from 'react';
import { Animated, useWindowDimensions } from 'react-native';
-import { EmojiKeyboard } from './EmojiKeyboard';
+import { EmojiStaticKeyboard } from './components/EmojiStaticKeyboard';
import { Knob } from './components/Knob';
-import { defaultKeyboardContext, KeyboardProvider } from './KeyboardProvider';
-import type { KeyboardProps } from './KeyboardContext';
+import {
+ defaultKeyboardContext,
+ KeyboardProvider,
+} from './contexts/KeyboardProvider';
+import type { KeyboardProps } from './contexts/KeyboardContext';
import type { EmojiType } from './types';
import { ModalWithBackdrop } from './components/ModalWithBackdrop';
import { getHeight } from './utils';
@@ -61,7 +64,7 @@ export const EmojiPicker = ({
},
]}
>
-
+
>
diff --git a/src/components/Categories.tsx b/src/components/Categories.tsx
index 2572f5e..dc3856e 100644
--- a/src/components/Categories.tsx
+++ b/src/components/Categories.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { View, Animated, StyleSheet, FlatList } from 'react-native';
-import { KeyboardContext } from '../KeyboardContext';
+import { KeyboardContext } from '../contexts/KeyboardContext';
import {
CATEGORIES,
CATEGORIES_NAVIGATION,
diff --git a/src/components/CategoryItem.tsx b/src/components/CategoryItem.tsx
index e9e8c4d..8f1c39a 100644
--- a/src/components/CategoryItem.tsx
+++ b/src/components/CategoryItem.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { View, StyleSheet, TouchableOpacity } from 'react-native';
-import { KeyboardContext } from '../KeyboardContext';
+import { KeyboardContext } from '../contexts/KeyboardContext';
import type { CategoryNavigationItem, CategoryTypes } from '../types';
import { Icon } from './Icon';
diff --git a/src/components/EmojiCategory.tsx b/src/components/EmojiCategory.tsx
index 55ea4f7..fcf3971 100644
--- a/src/components/EmojiCategory.tsx
+++ b/src/components/EmojiCategory.tsx
@@ -3,7 +3,7 @@ import * as React from 'react';
import { StyleSheet, View, Text, FlatList } from 'react-native';
import type { EmojisByCategory, EmojiType, JsonEmoji } from '../types';
import { SingleEmoji } from './SingleEmoji';
-import { KeyboardContext } from '../KeyboardContext';
+import { KeyboardContext } from '../contexts/KeyboardContext';
const emptyEmoji = {
emoji: '',
diff --git a/src/components/EmojiStaticKeyboard.tsx b/src/components/EmojiStaticKeyboard.tsx
new file mode 100644
index 0000000..e5634bc
--- /dev/null
+++ b/src/components/EmojiStaticKeyboard.tsx
@@ -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(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) => ,
+ []
+ );
+ React.useEffect(() => {
+ Animated.spring(scrollNav, {
+ toValue: activeCategoryIndex * (28 + 9),
+ useNativeDriver: true,
+ }).start();
+ }, [activeCategoryIndex, scrollNav]);
+
+ return (
+
+ {
+ 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}
+ />
+
+
+ );
+};
+
+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,
+ },
+});
diff --git a/src/components/Knob.tsx b/src/components/Knob.tsx
index 3cecc2f..b0a87d7 100644
--- a/src/components/Knob.tsx
+++ b/src/components/Knob.tsx
@@ -7,7 +7,7 @@ import {
PanResponder,
} from 'react-native';
import { getHeight } from '../utils';
-import { KeyboardContext } from '../KeyboardContext';
+import { KeyboardContext } from '../contexts/KeyboardContext';
type KnobProps = {
offsetY: Animated.Value;
diff --git a/src/components/ModalWithBackdrop.tsx b/src/components/ModalWithBackdrop.tsx
index a21180e..9f45d42 100644
--- a/src/components/ModalWithBackdrop.tsx
+++ b/src/components/ModalWithBackdrop.tsx
@@ -8,7 +8,7 @@ import {
TouchableOpacity,
View,
} from 'react-native';
-import { KeyboardContext } from '../KeyboardContext';
+import { KeyboardContext } from '../contexts/KeyboardContext';
type ModalWithBackdropProps = {
isOpen: boolean;
diff --git a/src/KeyboardContext.tsx b/src/contexts/KeyboardContext.tsx
similarity index 91%
rename from src/KeyboardContext.tsx
rename to src/contexts/KeyboardContext.tsx
index a22349a..3cc7d56 100644
--- a/src/KeyboardContext.tsx
+++ b/src/contexts/KeyboardContext.tsx
@@ -4,12 +4,14 @@ import {
defaultKeyboardContext,
defaultKeyboardValues,
} 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 = {
open: boolean;
onClose: () => void;
- onEmojiSelected: (emoji: EmojiType) => void;
+ onEmojiSelected: OnEmojiSelected;
emojiSize?: number;
containerStyles?: ViewStyle;
knobStyles?: ViewStyle;
diff --git a/src/KeyboardProvider.tsx b/src/contexts/KeyboardProvider.tsx
similarity index 91%
rename from src/KeyboardProvider.tsx
rename to src/contexts/KeyboardProvider.tsx
index 5b7286b..22505f4 100644
--- a/src/KeyboardProvider.tsx
+++ b/src/contexts/KeyboardProvider.tsx
@@ -4,12 +4,14 @@ import {
KeyboardProps,
ContextValues,
KeyboardContext,
+ OnEmojiSelected,
} from './KeyboardContext';
-import en from './translation/en';
-import type { EmojiType } from './types';
+import en from '../translation/en';
+import type { EmojiType } from '../types';
-type ProviderProps = KeyboardProps & {
+type ProviderProps = Partial & {
children: React.ReactNode;
+ onEmojiSelected: OnEmojiSelected;
};
export const defaultKeyboardContext: Required = {
diff --git a/src/index.tsx b/src/index.tsx
index 52717ae..0802c3f 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,10 +1,9 @@
-import { EmojiKeyboard } from './EmojiKeyboard';
import { EmojiPicker } from './EmojiPicker';
-import { KeyboardProvider } from './KeyboardProvider';
+import { EmojiKeyboard } from './EmojiKeyboard';
import en from './translation/en';
import pl from './translation/pl';
-export { EmojiKeyboard, KeyboardProvider };
+export { EmojiKeyboard };
export { en, pl };
export default EmojiPicker;