From 5cab329d571307bdb87dffc512641f86da96fd22 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 8 Jul 2021 15:10:57 +0200 Subject: [PATCH] build: create many optional props and general improve --- README.md | 68 +++++++++++++++++++++++----- example/src/App.tsx | 2 +- src/EmojiKeyboard.tsx | 13 +++++- src/EmojiPicker.tsx | 48 ++++++++------------ src/KeyboardContext.tsx | 12 ++++- src/KeyboardProvider.tsx | 16 +++++-- src/components/EmojiCategory.tsx | 4 +- src/components/Knob.tsx | 10 ++-- src/components/ModalWithBackdrop.tsx | 10 +++- src/types.ts | 4 +- 10 files changed, 129 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 5f9ebff..f96e86d 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,70 @@ . -## Installation - -```sh -npm install react-native-emoji-keyboard -``` - ## Usage ```js -import EmojiKeyboard from "react-native-emoji-keyboard"; +import EmojiPicker from '{package-name}'; -// ... +export default function App() { + const [isOpen, setIsOpen] = React.useState(false); -const result = await EmojiKeyboard.multiply(3, 7); + const handlePick = (emojiObject: EmojiType) => { + console.log(emojiObject); + /* example emojiObject = { { + "emoji": "❤️", + "name": "red heart", + "slug": "red_heart", + "skin_tone_support": false, + "unicode_version": "0.6", + "emoji_version": "0.6" + }, + */ + }; + + return ( + setIsOpen(false)} /> + ) +} ``` -## Contributing +## Installation +```sh +yarn add {package-name} +``` -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. +or +```sh +npm install {package-name} +``` +## Full Example +```js +TODO +``` +## Accepted props (current implemented) +| Name | Type | Default Value | Required | Description | +|---|---|---|---|---| +| onEmojiSelected | function | undefined | yes | Callback on emoji selected | +| open | boolean | false | yes | Opens modal picker | +| onClose | function | undefined | yes | Request close modal *runs when onEmojiSelected or backdrop pressed* | +| emojiSize | number | 28 | no | Custom emoji size | +| headerStyles | TextStyle | {} | no | Override category name styles | +| knobStyles | ViewStyle | {} | no | Override knob styles | +| containerStyles | ViewStyle | {} | no | Override container styles | +| hideHeader | boolean | false | no | Hide category names | +| expandable | boolean | true | no | Show knob and enable expand on swipe up | +| defaultHeight | number | 0.4 | no | Specify collapsed container height (1 is full screen height) | +| expandedHeight | number | 0.8 | no | Specify expanded container height (1 is full screen height) *only if expandable is true* | +| backdropColor | string | "#00000055" | no | Change backdrop color and alpha | ## License + **MIT** -MIT +


+## TODO +categories => Specify displayed categories + +language => Use translation \ No newline at end of file diff --git a/example/src/App.tsx b/example/src/App.tsx index a1b6fe4..103ae05 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -21,7 +21,7 @@ export default function App() { setIsModalOpen(false)} /> diff --git a/src/EmojiKeyboard.tsx b/src/EmojiKeyboard.tsx index 141d24f..d55e21b 100644 --- a/src/EmojiKeyboard.tsx +++ b/src/EmojiKeyboard.tsx @@ -62,7 +62,9 @@ export const EmojiKeyboard = () => { }, [ctx, scrollNav]); return ( - + item} @@ -88,5 +90,14 @@ 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 da22093..04e95c8 100644 --- a/src/EmojiPicker.tsx +++ b/src/EmojiPicker.tsx @@ -1,35 +1,34 @@ import * as React from 'react'; -import { Animated, useWindowDimensions, StyleSheet } from 'react-native'; +import { Animated, useWindowDimensions } from 'react-native'; import { EmojiKeyboard } from './EmojiKeyboard'; import { Knob } from './components/Knob'; -import { KeyboardProvider } from './KeyboardProvider'; +import { defaultKeyboardContext, KeyboardProvider } from './KeyboardProvider'; import type { KeyboardProps } from './KeyboardContext'; import type { EmojiType } from './types'; import { ModalWithBackdrop } from './components/ModalWithBackdrop'; -type EmojiPickerProps = { - isOpen: boolean; - onClose: () => void; -}; - export const EmojiPicker = ({ onEmojiSelected, - isOpen, + open, onClose, + expandable = defaultKeyboardContext.expandable, + defaultHeight = defaultKeyboardContext.defaultHeight, ...props -}: EmojiPickerProps & KeyboardProps) => { +}: KeyboardProps) => { const { height: screenHeight } = useWindowDimensions(); const offsetY = React.useRef(new Animated.Value(0)).current; - const height = React.useRef(new Animated.Value(screenHeight * 0.4)).current; + const height = React.useRef( + new Animated.Value(screenHeight * defaultHeight) + ).current; const translateY = React.useRef(new Animated.Value(0)).current; React.useEffect(() => { Animated.timing(translateY, { - toValue: isOpen ? 0 : screenHeight, + toValue: open ? 0 : screenHeight, useNativeDriver: true, duration: 500, }).start(); - }, [isOpen, screenHeight, translateY]); + }, [open, screenHeight, translateY]); const close = () => { height.setValue(screenHeight * 0.4); @@ -43,18 +42,22 @@ export const EmojiPicker = ({ onEmojiSelected(emoji); close(); }} - isOpen={isOpen} + open={open} + onClose={close} + expandable={expandable} + defaultHeight={defaultHeight} {...props} > - + <> - + {expandable && ( + + )} @@ -64,16 +67,3 @@ export const EmojiPicker = ({ ); }; - -const styles = StyleSheet.create({ - modalContainer: { flex: 1, justifyContent: 'flex-end' }, - container: { - backgroundColor: '#fff', - borderRadius: 16, - shadowColor: 'black', - shadowOpacity: 0.15, - shadowOffset: { width: 0, height: 0 }, - shadowRadius: 5, - }, - backdrop: { backgroundColor: '#00000055' }, -}); diff --git a/src/KeyboardContext.tsx b/src/KeyboardContext.tsx index b17f264..79aed4f 100644 --- a/src/KeyboardContext.tsx +++ b/src/KeyboardContext.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import type { ViewStyle } from 'react-native'; +import type { TextStyle, ViewStyle } from 'react-native'; import { defaultKeyboardContext, defaultKeyboardValues, @@ -7,10 +7,18 @@ import { import type { EmojiType } from './types'; export type KeyboardProps = { + open: boolean; + onClose: () => void; onEmojiSelected: (emoji: EmojiType) => void; emojiSize?: number; containerStyles?: ViewStyle; - isOpen?: boolean; + knobStyles?: ViewStyle; + headerStyles?: TextStyle; + expandable?: boolean; + hideHeader?: boolean; + defaultHeight?: number; + expandedHeight?: number; + backdropColor?: string; }; export type ContextValues = { activeCategoryIndex: number; diff --git a/src/KeyboardProvider.tsx b/src/KeyboardProvider.tsx index 3fbaf30..e345cbe 100644 --- a/src/KeyboardProvider.tsx +++ b/src/KeyboardProvider.tsx @@ -11,10 +11,18 @@ type ProviderProps = KeyboardProps & { }; export const defaultKeyboardContext: Required = { + open: false, + onClose: () => {}, onEmojiSelected: (_emoji: EmojiType) => {}, - emojiSize: 24, + emojiSize: 28, containerStyles: {}, - isOpen: false, + knobStyles: {}, + headerStyles: {}, + expandable: true, + hideHeader: false, + defaultHeight: 0.4, + expandedHeight: 0.8, + backdropColor: '#00000055', }; export const defaultKeyboardValues: ContextValues = { @@ -27,8 +35,8 @@ export const KeyboardProvider: React.FC = React.memo((props) => { const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0); React.useEffect(() => { - if (props.isOpen) setActiveCategoryIndex(0); - }, [props.isOpen]); + if (props.open) setActiveCategoryIndex(0); + }, [props.open]); const value: Required & ContextValues = { ...defaultKeyboardContext, diff --git a/src/components/EmojiCategory.tsx b/src/components/EmojiCategory.tsx index 0d5e681..f8030e2 100644 --- a/src/components/EmojiCategory.tsx +++ b/src/components/EmojiCategory.tsx @@ -42,7 +42,9 @@ export const EmojiCategory = ({ item }: { item: CategoryTypes }) => { return ( - {item} + {!ctx.hideHeader && ( + {item} + )} emoji.name} diff --git a/src/components/Knob.tsx b/src/components/Knob.tsx index 6d492f5..30c51d3 100644 --- a/src/components/Knob.tsx +++ b/src/components/Knob.tsx @@ -5,6 +5,7 @@ import { PanGestureHandlerGestureEvent, State, } from 'react-native-gesture-handler'; +import { KeyboardContext } from '../KeyboardContext'; type KnobProps = { offsetY: Animated.Value; @@ -14,6 +15,7 @@ type KnobProps = { export const Knob = ({ offsetY, height, onClose }: KnobProps) => { const { height: screenHeight } = useWindowDimensions(); + const ctx = React.useContext(KeyboardContext); const handleGesture = ({ nativeEvent: { translationY, state }, @@ -31,16 +33,16 @@ export const Knob = ({ offsetY, height, onClose }: KnobProps) => { if (translationY < -30) { Animated.spring(height, { useNativeDriver: false, - toValue: screenHeight * 0.8, + toValue: screenHeight * ctx.expandedHeight, }).start(); } else if (translationY > 150) { - height.setValue(screenHeight * 0.4); + height.setValue(screenHeight * ctx.defaultHeight); offsetY.setValue(0); onClose(); } else { Animated.spring(height, { useNativeDriver: false, - toValue: screenHeight * 0.4, + toValue: screenHeight * ctx.defaultHeight, }).start(); } } @@ -51,7 +53,7 @@ export const Knob = ({ offsetY, height, onClose }: KnobProps) => { onGestureEvent={handleGesture} onHandlerStateChange={handleGesture} > - + ); }; diff --git a/src/components/ModalWithBackdrop.tsx b/src/components/ModalWithBackdrop.tsx index d77fdc2..ceea955 100644 --- a/src/components/ModalWithBackdrop.tsx +++ b/src/components/ModalWithBackdrop.tsx @@ -8,6 +8,7 @@ import { TouchableOpacity, View, } from 'react-native'; +import { KeyboardContext } from '../KeyboardContext'; type ModalWithBackdropProps = { isOpen: boolean; @@ -22,6 +23,7 @@ export const ModalWithBackdrop = ({ }: ModalWithBackdropProps) => { const { height: screenHeight } = useWindowDimensions(); const translateY = React.useRef(new Animated.Value(0)).current; + const ctx = React.useContext(KeyboardContext); React.useEffect(() => { Animated.timing(translateY, { @@ -38,7 +40,12 @@ export const ModalWithBackdrop = ({ activeOpacity={1} onPress={backdropPress} > - +