├── example ├── .watchmanconfig ├── .ruby-version ├── .bundle │ └── config ├── app.json ├── src │ ├── component │ │ ├── index.ts │ │ └── Card │ │ │ ├── index.ts │ │ │ ├── types.ts │ │ │ ├── styles.ts │ │ │ ├── Card.tsx │ │ │ └── CustomCard.tsx │ ├── AppStyles.ts │ ├── theme │ │ ├── index.ts │ │ ├── Colors.ts │ │ └── Metrics.ts │ ├── constants │ │ ├── index.ts │ │ ├── Strings.ts │ │ └── emojiDataLists.ts │ └── App.tsx ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── drawable │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── jni │ │ │ │ │ ├── MainApplicationModuleProvider.h │ │ │ │ │ ├── OnLoad.cpp │ │ │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ │ │ ├── MainComponentsRegistry.h │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ │ │ ├── Android.mk │ │ │ │ │ └── MainComponentsRegistry.cpp │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── reactions_example │ │ │ │ │ ├── newarchitecture │ │ │ │ │ ├── components │ │ │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ │ ├── modules │ │ │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ │ │ └── MainApplicationReactNativeHost.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── reactions_example │ │ │ │ └── ReactNativeFlipper.java │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ ├── build_defs.bzl │ │ ├── _BUCK │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── gradle.properties │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── ios │ ├── reactions_example │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── AppDelegate.mm │ ├── reactions_example.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── .xcode.env │ ├── reactions_exampleTests │ │ ├── Info.plist │ │ └── reactions_exampleTests.m │ ├── Podfile │ ├── reactions_example.xcodeproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── reactions_example.xcscheme │ └── Podfile.lock ├── .buckconfig ├── babel.config.js ├── .prettierrc.js ├── Gemfile ├── index.js ├── tsconfig.json ├── .eslintrc.js ├── .gitignore ├── metro.config.js └── package.json ├── .eslintignore ├── .husky ├── pre-commit ├── pre-push └── commit-msg ├── src ├── utils │ ├── index.ts │ └── Validation.ts ├── constants │ ├── index.ts │ └── GlobalConstants.ts ├── components │ ├── EmojiItem │ │ ├── hooks │ │ │ ├── index.ts │ │ │ └── useEmojiItem.ts │ │ ├── styles.ts │ │ ├── types.ts │ │ └── index.tsx │ ├── EmojiView │ │ ├── hooks │ │ │ ├── index.ts │ │ │ └── useEmojiView.ts │ │ ├── styles.ts │ │ ├── types.ts │ │ └── index.tsx │ ├── ReactionView │ │ ├── hooks │ │ │ ├── index.ts │ │ │ └── useReaction.ts │ │ ├── index.ts │ │ ├── styles.ts │ │ ├── __tests__ │ │ │ ├── ReactionView.test.tsx │ │ │ └── __snapshots__ │ │ │ │ └── ReactionView.test.tsx.snap │ │ ├── RootReaction.tsx │ │ ├── types.ts │ │ ├── ReactionViewModal.tsx │ │ └── ReactionView.tsx │ ├── ReactionProvider │ │ ├── types.ts │ │ └── index.tsx │ ├── EmojiImage │ │ ├── styles.ts │ │ ├── types.ts │ │ └── index.tsx │ └── ReactionModal │ │ ├── types.ts │ │ └── index.tsx ├── index.ts └── theme │ ├── index.ts │ ├── Colors.ts │ └── Metrics.ts ├── assets ├── custom.gif ├── default.gif ├── Reaction.png └── ReactionBanner.png ├── .buckconfig ├── babel.config.js ├── .npmignore ├── .prettierrc.js ├── jest-setup.js ├── .eslintrc ├── .github └── workflows │ └── publish.yml ├── CONTRIBUTING.md ├── tsconfig.json ├── LICENSE ├── .gitignore ├── package.json └── README.md /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.5 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | example/ 3 | lib/ 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn build 5 | yarn test -------------------------------------------------------------------------------- /example/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { isValidUrl } from './Validation'; 2 | 3 | export { isValidUrl }; 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactions_example", 3 | "displayName": "reactions_example" 4 | } -------------------------------------------------------------------------------- /example/src/component/index.ts: -------------------------------------------------------------------------------- 1 | import { Card, CustomCard } from "./Card"; 2 | 3 | export { Card, CustomCard } -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | import GlobalConstants from './GlobalConstants'; 2 | 3 | export { GlobalConstants }; 4 | -------------------------------------------------------------------------------- /assets/custom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/assets/custom.gif -------------------------------------------------------------------------------- /assets/default.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/assets/default.gif -------------------------------------------------------------------------------- /assets/Reaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/assets/Reaction.png -------------------------------------------------------------------------------- /src/components/EmojiItem/hooks/index.ts: -------------------------------------------------------------------------------- 1 | import useEmojiItem from './useEmojiItem'; 2 | 3 | export { useEmojiItem }; 4 | -------------------------------------------------------------------------------- /src/components/EmojiView/hooks/index.ts: -------------------------------------------------------------------------------- 1 | import useEmojiView from './useEmojiView'; 2 | 3 | export { useEmojiView }; 4 | -------------------------------------------------------------------------------- /src/components/ReactionView/hooks/index.ts: -------------------------------------------------------------------------------- 1 | import useReaction from './useReaction'; 2 | 3 | export { useReaction }; 4 | -------------------------------------------------------------------------------- /src/components/ReactionProvider/types.ts: -------------------------------------------------------------------------------- 1 | export interface reactionProviderProps { 2 | children: React.ReactElement; 3 | } 4 | -------------------------------------------------------------------------------- /assets/ReactionBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/assets/ReactionBanner.png -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { ReactionProvider } from './components/ReactionProvider'; 2 | 3 | export * from './components/ReactionView'; 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | reactions_example 3 | 4 | -------------------------------------------------------------------------------- /example/src/component/Card/index.ts: -------------------------------------------------------------------------------- 1 | import Card from "./Card"; 2 | import CustomCard from "./CustomCard"; 3 | 4 | export { CustomCard, Card } -------------------------------------------------------------------------------- /example/ios/reactions_example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: [ 4 | 'react-native-reanimated/plugin', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | .husky/ 3 | example/ 4 | assets/ 5 | .eslintignore 6 | .eslintrc 7 | CONTRIBUTING.md 8 | babel.config.js 9 | .buckconfig 10 | jest-setup.js 11 | -------------------------------------------------------------------------------- /example/src/AppStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const styles = StyleSheet.create({ 4 | mainStyle: { 5 | flex: 1, 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: true, 5 | singleQuote: true, 6 | trailingComma: 'es5' 7 | }; 8 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset',], 3 | plugins: [ 4 | 'react-native-reanimated/plugin', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: true, 5 | singleQuote: true, 6 | trailingComma: 'es5', 7 | }; 8 | -------------------------------------------------------------------------------- /example/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import Colors from './Colors'; 2 | import { scale, moderateScale, verticalScale } from './Metrics'; 3 | 4 | export { Colors, scale, moderateScale, verticalScale }; 5 | -------------------------------------------------------------------------------- /src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { scale, moderateScale, verticalScale } from './Metrics'; 2 | 3 | export { default as Colors } from './Colors'; 4 | export { scale, moderateScale, verticalScale }; 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby '2.7.5' 5 | 6 | gem 'cocoapods', '~> 1.11', '>= 1.11.2' 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-reactions/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | import { CardEmojiList, PostItemList, CardEmojiUrlList } from './emojiDataLists' 2 | import Strings from './Strings' 3 | 4 | export { CardEmojiList, Strings, PostItemList, CardEmojiUrlList } -------------------------------------------------------------------------------- /src/theme/Colors.ts: -------------------------------------------------------------------------------- 1 | const colors = { 2 | red: '#FF0000', 3 | blue: '#0000FF', 4 | white: '#FFFFFF', 5 | black: '#000000', 6 | blackTransparent: 'rgba(0,0,0,0.24)', 7 | grey: '#101010', 8 | }; 9 | 10 | export default colors; 11 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import { AppRegistry } from 'react-native'; 6 | 7 | import { name as appName } from './app.json'; 8 | import App from './src/App'; 9 | 10 | AppRegistry.registerComponent(appName, () => App); 11 | -------------------------------------------------------------------------------- /src/components/ReactionView/index.ts: -------------------------------------------------------------------------------- 1 | import RootReaction from './RootReaction'; 2 | import { getCoordinatesRef } from './ReactionViewModal'; 3 | 4 | export { RootReaction as Reaction, getCoordinatesRef }; 5 | export type { ReactionViewProps } from './types'; 6 | -------------------------------------------------------------------------------- /src/constants/GlobalConstants.ts: -------------------------------------------------------------------------------- 1 | const GlobalConstants = { 2 | min: 15, 3 | max: 30, 4 | default: 'default', 5 | modal: 'modal', 6 | onPress: 'onPress', 7 | onLongPress: 'onLongPress', 8 | }; 9 | 10 | export default GlobalConstants; 11 | -------------------------------------------------------------------------------- /example/ios/reactions_example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/ios/reactions_example/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /example/src/theme/Colors.ts: -------------------------------------------------------------------------------- 1 | const Colors = { 2 | red: '#FF0000', 3 | blue: '#0000FF', 4 | white: '#FFFFFF', 5 | black: '#000000', 6 | blackTransparent: 'rgba(0,0,0,0.24)', 7 | grey: '#101010', 8 | linkWater:'#c9cdd0', 9 | }; 10 | 11 | export default Colors; 12 | -------------------------------------------------------------------------------- /example/ios/reactions_example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/reactions_example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/components/EmojiImage/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { moderateScale } from '../../theme'; 3 | 4 | const styles = StyleSheet.create({ 5 | img: { 6 | width: moderateScale(25), 7 | height: moderateScale(20), 8 | resizeMode: 'contain', 9 | }, 10 | }); 11 | 12 | export default styles; 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/constants/Strings.ts: -------------------------------------------------------------------------------- 1 | const Strings = { 2 | title: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.', 3 | comment: 'Comment', 4 | like: 'Like', 5 | share: 'Share', 6 | dot:'.....', 7 | postLike:'1.4k', 8 | postComments:'150 comments', 9 | postShare:'25 shared', 10 | } 11 | 12 | export default Strings; -------------------------------------------------------------------------------- /src/components/ReactionProvider/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactionModal from '../ReactionModal'; 3 | import type { reactionProviderProps } from './types'; 4 | 5 | export const ReactionProvider = ({ children }: reactionProviderProps) => { 6 | return ( 7 | <> 8 | 9 | {children} 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /src/components/EmojiImage/types.ts: -------------------------------------------------------------------------------- 1 | import type { ImageSourcePropType, ImageStyle, StyleProp } from 'react-native'; 2 | export type ImageProps = { 3 | source: ImageSourcePropType; 4 | emojiImageStyle?: StyleProp; 5 | }; 6 | export interface EmojiImageType extends ImageProps { 7 | emojiElementStyle: StyleProp; 8 | emojiSize?: number; 9 | } 10 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "esModuleInterop": true, 5 | "jsx": "react-native", 6 | "lib": ["ESNext"], 7 | "module": "CommonJS", 8 | "noEmit": true, 9 | "paths": { 10 | "react-native-reactions": ["../src"] 11 | }, 12 | "skipLibCheck": true, 13 | "strict": true, 14 | "target": "ESNext" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/components/ReactionView/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { verticalScale } from '../../theme'; 3 | 4 | const styles = StyleSheet.create({ 5 | subContainer: { 6 | position: 'absolute', 7 | zIndex: 10, 8 | height: verticalScale(80), 9 | }, 10 | textWrapperStyle: { 11 | justifyContent: 'center', 12 | alignItems: 'center', 13 | }, 14 | }); 15 | 16 | export default styles; 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | std::shared_ptr MainApplicationModuleProvider( 12 | const std::string moduleName, 13 | const JavaTurboModule::InitParams ¶ms); 14 | 15 | } // namespace react 16 | } // namespace facebook 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/OnLoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MainApplicationTurboModuleManagerDelegate.h" 3 | #include "MainComponentsRegistry.h" 4 | 5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 6 | return facebook::jni::initialize(vm, [] { 7 | facebook::react::MainApplicationTurboModuleManagerDelegate:: 8 | registerNatives(); 9 | facebook::react::MainComponentsRegistry::registerNatives(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /src/components/ReactionModal/types.ts: -------------------------------------------------------------------------------- 1 | export interface ModalProps { 2 | x?: number; 3 | y?: number; 4 | contentHeight?: number; 5 | width?: number; 6 | emojiSize?: number; 7 | directTouchRelease?: boolean; 8 | directTouchLoad?: boolean; 9 | position?: number; 10 | panResponder?: any; 11 | } 12 | 13 | export interface RefProps { 14 | show: (props: ModalProps) => void; 15 | hide: () => void; 16 | sendUpdatedValues: (props: Partial) => void; 17 | } 18 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /src/components/ReactionView/__tests__/ReactionView.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react-native'; 3 | import ReactionView from '../ReactionView'; 4 | import { Text } from 'react-native'; 5 | 6 | jest.useFakeTimers(); 7 | 8 | describe('ReactionView component', () => { 9 | it('Match Snapshot', () => { 10 | const { toJSON } = render( 11 | 12 | Emoji Text 13 | 14 | ); 15 | expect(toJSON()).toMatchSnapshot(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/components/ReactionView/RootReaction.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactionView from './ReactionView'; 3 | import ReactionViewModal from './ReactionViewModal'; 4 | import type { ReactionViewProps } from './types'; 5 | import { GlobalConstants } from '../../constants'; 6 | 7 | const RootReaction = (props: ReactionViewProps) => { 8 | const { type } = props; 9 | return type === GlobalConstants.modal ? ( 10 | 11 | ) : ( 12 | 13 | ); 14 | }; 15 | 16 | export default RootReaction; 17 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@react-native-community", "prettier"], 3 | "rules": { 4 | "prettier/prettier": [ 5 | "error", 6 | { 7 | "quoteProps": "preserve", 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "es5", 11 | "useTabs": false 12 | } 13 | ], 14 | "no-bitwise": 0, 15 | "prefer-const": "warn", 16 | "no-console": ["error", { "allow": ["warn", "error"] }] 17 | }, 18 | "globals": { 19 | "JSX": "readonly" 20 | }, 21 | "plugins": ["prettier"] 22 | } 23 | -------------------------------------------------------------------------------- /jest-setup.js: -------------------------------------------------------------------------------- 1 | const mockGestureHandler = jest.requireMock('react-native-gesture-handler'); 2 | const mock = jest.requireMock('react-native-reanimated'); 3 | 4 | jest.mock('react-native-gesture-handler', () => { 5 | const View = require('react-native/Libraries/Components/View/View'); 6 | return { 7 | ...mockGestureHandler, 8 | PanGestureHandler: View, 9 | }; 10 | }); 11 | 12 | jest.mock('react-native-reanimated', () => { 13 | return { 14 | ...mock, 15 | useSharedValue: jest.fn, 16 | useValue: jest.fn, 17 | event: jest.fn(), 18 | }; 19 | }); 20 | -------------------------------------------------------------------------------- /src/components/EmojiView/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Colors, moderateScale, verticalScale } from '../../theme'; 3 | 4 | export const styles = StyleSheet.create({ 5 | emojiBox: { 6 | flexDirection: 'row', 7 | padding: moderateScale(9), 8 | backgroundColor: Colors.white, 9 | borderRadius: 30, 10 | shadowColor: Colors.black, 11 | shadowOffset: { 12 | width: moderateScale(3), 13 | height: verticalScale(2), 14 | }, 15 | shadowOpacity: 0.5, 16 | shadowRadius: 1, 17 | elevation: 5, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /src/utils/Validation.ts: -------------------------------------------------------------------------------- 1 | export const isValidUrl = (urlString: string) => { 2 | const urlPattern = new RegExp( 3 | '^(https?:\\/\\/)?' + // validate protocol 4 | '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // validate domain name 5 | '((\\d{1,3}\\.){3}\\d{1,3}))' + // validate OR ip (v4) address 6 | '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // validate port and path 7 | '(\\?[;&a-z\\d%_.~+=-]*)?' + // validate query string 8 | '(\\#[-a-z\\d_]*)?$', 9 | 'i' 10 | ); // validate fragment locator 11 | return !!urlPattern.test(urlString); 12 | }; 13 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/src/component/Card/types.ts: -------------------------------------------------------------------------------- 1 | export interface EmojiItemProp { 2 | // EmojiItemProp object is indexed with a Key it will return a value of any type. 3 | [key: string]: any; 4 | id: number; 5 | emoji: React.ReactNode | string | number; 6 | title: string; 7 | } 8 | 9 | interface PostItemListProps { 10 | id: string; 11 | title: string; 12 | image: string; 13 | } 14 | export interface CardProps { 15 | index: number; 16 | selectedEmoji?:EmojiItemProp 17 | setSelectedEmoji?:(e:EmojiItemProp | undefined)=>void 18 | onShowDismissCard?: (e?:boolean)=> void; 19 | isScrollDisable?: boolean; 20 | item?:PostItemListProps 21 | } -------------------------------------------------------------------------------- /src/components/EmojiImage/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Image, StyleSheet } from 'react-native'; 3 | import { moderateScale } from '../../theme'; 4 | import styles from './styles'; 5 | import type { EmojiImageType } from './types'; 6 | 7 | const EmojiImage = ({ 8 | emojiElementStyle, 9 | emojiSize = 0, 10 | ...rest 11 | }: EmojiImageType) => { 12 | const imageStyle = StyleSheet.flatten([ 13 | styles.img, 14 | emojiElementStyle, 15 | { width: moderateScale(emojiSize), height: moderateScale(emojiSize) }, 16 | ]); 17 | return ; 18 | }; 19 | 20 | export default EmojiImage; 21 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'reactions_example' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/react-native-gradle-plugin') 5 | 6 | if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { 7 | include(":ReactAndroid") 8 | project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') 9 | include(":ReactAndroid:hermes-engine") 10 | project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine') 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@react-native-community", "prettier"], 3 | "root": true, 4 | "rules": { 5 | "prettier/prettier": [ 6 | "error", 7 | { 8 | "quoteProps": "preserve", 9 | "singleQuote": true, 10 | "tabWidth": 2, 11 | "trailingComma": "es5", 12 | "useTabs": false 13 | } 14 | ], 15 | "no-shadow": "off", 16 | "@typescript-eslint/no-shadow": ["error"], 17 | "no-bitwise": 0, 18 | "prefer-const": "warn", 19 | "no-console": ["error", { "allow": ["warn", "error"] }] 20 | }, 21 | "globals": { 22 | "JSX": "readonly" 23 | }, 24 | "env": { 25 | "jest": true 26 | }, 27 | "plugins": ["prettier"] 28 | } 29 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 Publish" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release: 10 | name: 🚀 Publish 11 | runs-on: macos-11 12 | steps: 13 | - name: 📚 checkout 14 | uses: actions/checkout@v2.4.2 15 | - name: 🟢 node 16 | uses: actions/setup-node@v3.3.0 17 | with: 18 | node-version: 16 19 | registry-url: https://registry.npmjs.org 20 | - name: 🚀 Build & Publish 21 | run: yarn install && yarn build && yarn publish --access public 22 | env: 23 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We welcome code changes that improve this library or fix a problem, and please make sure to follow all best practices and test all the changes/fixes before committing and creating a pull request. 🚀 🚀 4 | 5 | ### Committing and Pushing Changes 6 | 7 | Commit messages should be formatted as: 8 | 9 | ``` 10 | [optional scope]: 11 | 12 | [optional body] 13 | 14 | [optional footer] 15 | ``` 16 | 17 | Where type can be one of the following: 18 | 19 | - feat 20 | - fix 21 | - docs 22 | - chore 23 | - style 24 | - refactor 25 | - test 26 | 27 | and an optional scope can be a component 28 | 29 | ``` 30 | docs: update contributing guide 31 | ``` 32 | 33 | ``` 34 | fix(TicketId/Component): layout flicker issue 35 | ``` 36 | -------------------------------------------------------------------------------- /example/ios/reactions_exampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationModuleProvider.h" 2 | 3 | #include 4 | 5 | namespace facebook { 6 | namespace react { 7 | 8 | std::shared_ptr MainApplicationModuleProvider( 9 | const std::string moduleName, 10 | const JavaTurboModule::InitParams ¶ms) { 11 | // Here you can provide your own module provider for TurboModules coming from 12 | // either your application or from external libraries. The approach to follow 13 | // is similar to the following (for a library called `samplelibrary`: 14 | // 15 | // auto module = samplelibrary_ModuleProvider(moduleName, params); 16 | // if (module != nullptr) { 17 | // return module; 18 | // } 19 | // return rncore_ModuleProvider(moduleName, params); 20 | return rncore_ModuleProvider(moduleName, params); 21 | } 22 | 23 | } // namespace react 24 | } // namespace facebook 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "allowUnreachableCode": false, 7 | "allowUnusedLabels": false, 8 | "jsx": "react", 9 | "lib": ["ESNext"], 10 | "module": "ESNext", 11 | "importsNotUsedAsValues": "error", 12 | "forceConsistentCasingInFileNames": true, 13 | "moduleResolution": "Node", 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitReturns": true, 16 | "noImplicitUseStrict": false, 17 | "noStrictGenericChecks": false, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "resolveJsonModule": true, 21 | "noEmitOnError": true, 22 | "outDir": "./lib", 23 | "skipLibCheck": true, 24 | "sourceMap": true, 25 | "strict": true, 26 | "target": "ES2018" 27 | }, 28 | "exclude": ["example/node_modules/**", "node_modules/**", "**/__tests__/*"], 29 | "include": ["src"] 30 | } 31 | -------------------------------------------------------------------------------- /src/components/EmojiItem/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Colors, moderateScale, scale, verticalScale } from '../../theme'; 3 | 4 | const styles = StyleSheet.create({ 5 | root: { 6 | alignItems: 'center', 7 | justifyContent: 'center', 8 | marginVertical: scale(3), 9 | margin: scale(5), 10 | }, 11 | titleBox: { 12 | position: 'absolute', 13 | backgroundColor: Colors.red, 14 | paddingVertical: verticalScale(4), 15 | borderRadius: 16, 16 | paddingHorizontal: scale(5), 17 | }, 18 | title: { 19 | textTransform: 'capitalize', 20 | color: Colors.white, 21 | fontWeight: '600', 22 | fontSize: moderateScale(12), 23 | }, 24 | img: { 25 | width: moderateScale(25), 26 | height: moderateScale(20), 27 | resizeMode: 'contain', 28 | }, 29 | emojiText: { 30 | textTransform: 'capitalize', 31 | color: Colors.white, 32 | textAlign: 'center', 33 | }, 34 | }); 35 | 36 | export default styles; 37 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainComponentsRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | class MainComponentsRegistry 12 | : public facebook::jni::HybridClass { 13 | public: 14 | // Adapt it to the package you used for your Java class. 15 | constexpr static auto kJavaDescriptor = 16 | "Lcom/reactions_example/newarchitecture/components/MainComponentsRegistry;"; 17 | 18 | static void registerNatives(); 19 | 20 | MainComponentsRegistry(ComponentFactory *delegate); 21 | 22 | private: 23 | static std::shared_ptr 24 | sharedProviderRegistry(); 25 | 26 | static jni::local_ref initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate); 29 | }; 30 | 31 | } // namespace react 32 | } // namespace facebook 33 | -------------------------------------------------------------------------------- /src/components/EmojiView/types.ts: -------------------------------------------------------------------------------- 1 | import type { GestureResponderEvent, LayoutRectangle } from 'react-native'; 2 | import type { ModalProps } from '../ReactionModal/types'; 3 | import type { ReactionViewProps } from '../ReactionView'; 4 | 5 | // here don't require children in EmojiModalProps 6 | type ReactionProps = Omit; 7 | 8 | export interface EmojiModalProps 9 | extends ReactionProps, 10 | ModalProps, 11 | EmojiAnimationProps { 12 | onStartShouldSetResponder?: 13 | | ((event: GestureResponderEvent) => boolean) 14 | | undefined; 15 | isModal?: boolean; 16 | setShowPopUpCard?: (showPopUpCardType: boolean) => void; 17 | showPopUpCard?: boolean; 18 | onEmojiCloseModal?: () => void; 19 | onShowDismissCard?: (onShowDismissCardType?: boolean) => void; 20 | isShowCardInCenter?: boolean; 21 | directTouchRelease?: boolean; 22 | directTouchLoad?: boolean; 23 | position?: number; 24 | getEmojiViewCoordinates?: (args: LayoutRectangle) => void; 25 | } 26 | 27 | export interface EmojiAnimationProps { 28 | opacityRange?: number[]; 29 | cardDuration?: number; 30 | } 31 | -------------------------------------------------------------------------------- /example/src/component/Card/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native' 2 | import { moderateScale, scale, verticalScale, Colors } from '../../theme' 3 | 4 | export const styles = StyleSheet.create({ 5 | cardContainer: { 6 | marginVertical: verticalScale(5), 7 | backgroundColor: Colors.white, 8 | paddingVertical: verticalScale(10) 9 | }, 10 | postImageContainer: { 11 | alignItems: 'center', 12 | zIndex: -1 13 | }, 14 | postImage: { 15 | width: '100%', 16 | height: verticalScale(200), 17 | zIndex: -1, 18 | resizeMode:'center' 19 | }, 20 | line: { 21 | borderWidth: 0.3, 22 | borderColor: Colors.linkWater, 23 | }, 24 | bottomContainer: { 25 | flexDirection: 'row', 26 | justifyContent: 'space-between', 27 | margin: moderateScale(10), 28 | marginHorizontal: scale(20) 29 | }, 30 | emojiImage:{ 31 | width: scale(18), 32 | height: verticalScale(18), 33 | resizeMode: "contain" 34 | }, 35 | text: { 36 | color: Colors.black 37 | } 38 | }) 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Simform Solutions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/reactions_example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | yarn.lock 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # Ruby / CocoaPods 60 | /ios/Pods/ 61 | /vendor/bundle/ 62 | 63 | # generated 64 | lib 65 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { FlatList, SafeAreaView } from 'react-native'; 3 | import { ReactionProvider } from 'react-native-reactions'; 4 | import { Card } from './component'; 5 | import { styles } from './AppStyles'; 6 | import { Colors } from './theme'; 7 | import { PostItemList } from './constants'; 8 | 9 | const App = () => { 10 | const [isScrollDisable, setIsScrollDisable] = useState(true); 11 | 12 | return ( 13 | 14 | 15 | ( 20 | setIsScrollDisable(!e)} 24 | isScrollDisable 25 | /> 26 | )} 27 | keyExtractor={item => item.id} 28 | /> 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default App; 35 | -------------------------------------------------------------------------------- /src/components/EmojiItem/types.ts: -------------------------------------------------------------------------------- 1 | import type { StyleProp, TextStyle, ViewStyle } from 'react-native'; 2 | import type { EmojiItemProp } from '../ReactionView/types'; 3 | 4 | export interface EmojiItemProps extends emojiProps { 5 | data: EmojiItemProp; 6 | onEmojiPress: () => void; 7 | currentPosition: number; 8 | showTopEmojiCard?: boolean; 9 | emojiKey?: string; 10 | isModal?: boolean; 11 | isTouchRelease?: boolean; 12 | setShowPopUpCard?: (e: boolean) => void; 13 | onTap?: (e: EmojiItemProp | undefined) => void; 14 | loaded?: boolean; 15 | index: number; 16 | showPopUpCard?: boolean; 17 | onEmojiCloseModal?: () => void; 18 | setTouchRelease?: (e: boolean) => void; 19 | emojiSize?: number; 20 | } 21 | 22 | export interface emojiData extends emojiProps { 23 | emojiData: EmojiItemProp; 24 | emojiKey?: string; 25 | emojiSize?: number; 26 | } 27 | export interface emojiProps { 28 | iconSize?: number; 29 | titleStyle?: StyleProp; 30 | titleBoxStyle?: StyleProp; 31 | emojiContainerStyle?: StyleProp; 32 | emojiDuration?: number; 33 | scaleDuration?: number; 34 | emojiStyle?: StyleProp; 35 | } 36 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | 34 | # node.js 35 | # 36 | node_modules/ 37 | npm-debug.log 38 | yarn-error.log 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | !debug.keystore 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/ 52 | 53 | **/fastlane/report.xml 54 | **/fastlane/Preview.html 55 | **/fastlane/screenshots 56 | **/fastlane/test_output 57 | 58 | # Bundle artifact 59 | *.jsbundle 60 | 61 | 62 | # Ruby / CocoaPods 63 | /ios/Pods/ 64 | /vendor/bundle/ 65 | Gemfile.lock 66 | yarn.lock 67 | -------------------------------------------------------------------------------- /src/components/ReactionView/types.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | LayoutRectangle, 3 | PressableProps, 4 | StyleProp, 5 | ViewStyle, 6 | } from 'react-native'; 7 | import type { emojiProps } from '../EmojiItem/types'; 8 | import type { EmojiAnimationProps } from '../EmojiView/types'; 9 | 10 | export interface ReactionViewProps extends emojiProps, EmojiAnimationProps { 11 | type?: 'default' | 'modal'; 12 | children: JSX.Element; 13 | items?: EmojiItemProp[]; 14 | onTap?: (e: EmojiItemProp | undefined) => void; 15 | cardStyle?: StyleProp; 16 | touchableProps?: PressableProps; 17 | itemIndex?: number; 18 | onShowDismissCard?: (onShowDismissCardType?: boolean) => void; 19 | isShowCardInCenter?: boolean; 20 | showPopupType?: 'default' | 'onPress'; 21 | onPress?: () => void; 22 | disabled?: boolean; 23 | onLongPress?: () => void; 24 | panResponder?: any; 25 | } 26 | 27 | export interface EmojiItemProp { 28 | // emojiData object is indexed with a Key it will return a value of any type. 29 | [key: string]: any; 30 | id: number; 31 | emoji: React.ReactNode | string | number; 32 | title: string; 33 | } 34 | 35 | export interface GetCoordinateRef { 36 | sendCoordinates: (coordinates: LayoutRectangle) => void; 37 | } 38 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace facebook { 8 | namespace react { 9 | 10 | class MainApplicationTurboModuleManagerDelegate 11 | : public jni::HybridClass< 12 | MainApplicationTurboModuleManagerDelegate, 13 | TurboModuleManagerDelegate> { 14 | public: 15 | // Adapt it to the package you used for your Java class. 16 | static constexpr auto kJavaDescriptor = 17 | "Lcom/reactions_example/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; 18 | 19 | static jni::local_ref initHybrid(jni::alias_ref); 20 | 21 | static void registerNatives(); 22 | 23 | std::shared_ptr getTurboModule( 24 | const std::string name, 25 | const std::shared_ptr jsInvoker) override; 26 | std::shared_ptr getTurboModule( 27 | const std::string name, 28 | const JavaTurboModule::InitParams ¶ms) override; 29 | 30 | /** 31 | * Test-only method. Allows user to verify whether a TurboModule can be 32 | * created by instances of this class. 33 | */ 34 | bool canCreateTurboModule(std::string name); 35 | }; 36 | 37 | } // namespace react 38 | } // namespace facebook 39 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/reactions_example/newarchitecture/components/MainComponentsRegistry.java: -------------------------------------------------------------------------------- 1 | package com.reactions_example.newarchitecture.components; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.proguard.annotations.DoNotStrip; 5 | import com.facebook.react.fabric.ComponentFactory; 6 | import com.facebook.soloader.SoLoader; 7 | 8 | /** 9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a 10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 11 | * folder for you). 12 | * 13 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 14 | * `newArchEnabled` property). Is ignored otherwise. 15 | */ 16 | @DoNotStrip 17 | public class MainComponentsRegistry { 18 | static { 19 | SoLoader.loadLibrary("fabricjni"); 20 | } 21 | 22 | @DoNotStrip private final HybridData mHybridData; 23 | 24 | @DoNotStrip 25 | private native HybridData initHybrid(ComponentFactory componentFactory); 26 | 27 | @DoNotStrip 28 | private MainComponentsRegistry(ComponentFactory componentFactory) { 29 | mHybridData = initHybrid(componentFactory); 30 | } 31 | 32 | @DoNotStrip 33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) { 34 | return new MainComponentsRegistry(componentFactory); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | const path = require('path'); 8 | const rootPackage = require('../package.json'); 9 | const blacklist = require('metro-config/src/defaults/exclusionList'); 10 | const rootModules = Object.keys({ 11 | ...rootPackage.peerDependencies, 12 | }); 13 | const moduleRoot = path.resolve(__dirname, '..'); 14 | /** 15 | * Only load one version for peerDependencies and alias them to the versions in example's node_modules" 16 | */ 17 | module.exports = { 18 | watchFolders: [moduleRoot], 19 | resolver: { 20 | blacklistRE: blacklist([ 21 | ...rootModules.map( 22 | m => 23 | new RegExp( 24 | `^${escape(path.join(moduleRoot, 'node_modules', m))}\\/.*$` 25 | ) 26 | ), 27 | /^((?!example).)+[\/\\]node_modules[/\\]react[/\\].*/, 28 | /^((?!example).)+[\/\\]node_modules[/\\]react-native[/\\].*/, 29 | ]), 30 | extraNodeModules: { 31 | ...rootModules.reduce((acc, name) => { 32 | acc[name] = path.join(__dirname, 'node_modules', name); 33 | return acc; 34 | }, {}), 35 | }, 36 | }, 37 | transformer: { 38 | getTransformOptions: async () => ({ 39 | transform: { 40 | experimentalImportSupport: false, 41 | inlineRequires: true, 42 | }, 43 | }), 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '12.4' 5 | install! 'cocoapods', :deterministic_uuids => false 6 | 7 | production = ENV["PRODUCTION"] == "1" 8 | 9 | target 'reactions_example' do 10 | config = use_native_modules! 11 | 12 | # Flags change depending on the env values. 13 | flags = get_default_flags() 14 | 15 | use_react_native!( 16 | :path => config[:reactNativePath], 17 | # to enable hermes on iOS, change `false` to `true` and then install pods 18 | :production => production, 19 | # :hermes_enabled => flags[:hermes_enabled], 20 | # :fabric_enabled => flags[:fabric_enabled], 21 | # :flipper_configuration => FlipperConfiguration.enabled, 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | target 'reactions_exampleTests' do 27 | inherit! :complete 28 | # Pods for testing 29 | end 30 | 31 | post_install do |installer| 32 | react_native_post_install(installer) 33 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 34 | installer.pods_project.targets.each do |target| 35 | target.build_configurations.each do |config| 36 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.4' 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /example/android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.reactions_example", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.reactions_example", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactions_example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx" 11 | }, 12 | "dependencies": { 13 | "lodash": "^4.17.21", 14 | "react": "18.0.0", 15 | "react-native": "0.69.5", 16 | "react-native-gesture-handler": "2.16.2", 17 | "react-native-reanimated": "3.8.1" 18 | }, 19 | "devDependencies": { 20 | "@babel/core": "^7.12.9", 21 | "@babel/runtime": "^7.12.5", 22 | "@react-native-community/eslint-config": "^3.0.1", 23 | "@tsconfig/react-native": "^2.0.2", 24 | "@types/jest": "^27.4.0", 25 | "@types/lodash": "^4.14.186", 26 | "@types/react-native": "^0.69.5", 27 | "@types/react-test-renderer": "^18.0.0", 28 | "@typescript-eslint/eslint-plugin": "^5.29.0", 29 | "@typescript-eslint/parser": "^5.29.0", 30 | "babel-jest": "^27.4.6", 31 | "eslint": "^7.32.0", 32 | "eslint-plugin-simple-import-sort": "^7.0.0", 33 | "jest": "^27.4.7", 34 | "metro-react-native-babel-preset": "^0.70.3", 35 | "react-test-renderer": "18.0.0", 36 | "typescript": "^4.6.4" 37 | }, 38 | "resolutions": { 39 | "@types/react": "*", 40 | "react-native-reanimated": "3.8.1" 41 | }, 42 | "jest": { 43 | "preset": "react-native", 44 | "moduleFileExtensions": [ 45 | "ts", 46 | "tsx", 47 | "js", 48 | "jsx", 49 | "json", 50 | "node" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationTurboModuleManagerDelegate.h" 2 | #include "MainApplicationModuleProvider.h" 3 | 4 | namespace facebook { 5 | namespace react { 6 | 7 | jni::local_ref 8 | MainApplicationTurboModuleManagerDelegate::initHybrid( 9 | jni::alias_ref) { 10 | return makeCxxInstance(); 11 | } 12 | 13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() { 14 | registerHybrid({ 15 | makeNativeMethod( 16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), 17 | makeNativeMethod( 18 | "canCreateTurboModule", 19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), 20 | }); 21 | } 22 | 23 | std::shared_ptr 24 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 25 | const std::string name, 26 | const std::shared_ptr jsInvoker) { 27 | // Not implemented yet: provide pure-C++ NativeModules here. 28 | return nullptr; 29 | } 30 | 31 | std::shared_ptr 32 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 33 | const std::string name, 34 | const JavaTurboModule::InitParams ¶ms) { 35 | return MainApplicationModuleProvider(name, params); 36 | } 37 | 38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( 39 | std::string name) { 40 | return getTurboModule(name, nullptr) != nullptr || 41 | getTurboModule(name, {.moduleName = name}) != nullptr; 42 | } 43 | 44 | } // namespace react 45 | } // namespace facebook 46 | -------------------------------------------------------------------------------- /example/src/component/Card/Card.tsx: -------------------------------------------------------------------------------- 1 | import { Image, Text, View } from 'react-native'; 2 | import React, { memo, useState } from 'react'; 3 | import { styles } from './styles'; 4 | import { Reaction } from 'react-native-reactions'; 5 | import { CardEmojiList, Strings } from '../../constants'; 6 | import { CardProps, EmojiItemProp } from './types'; 7 | import _ from 'lodash'; 8 | 9 | const Footer = ({ 10 | index, 11 | selectedEmoji, 12 | setSelectedEmoji, 13 | onShowDismissCard, 14 | }: CardProps) => ( 15 | 16 | 22 | {selectedEmoji ? selectedEmoji?.emoji : Strings?.like} 23 | 24 | {Strings?.share} 25 | 26 | ); 27 | 28 | const Card = ({ index, onShowDismissCard, item }: CardProps) => { 29 | const [selectedEmoji, setSelectedEmoji] = useState(); 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 |