Repository: meinto/react-native-event-listeners Branch: master Commit: 5a73c7afc2d5 Files: 17 Total size: 20.6 KB Directory structure: gitextract_p8pemzyh/ ├── .babelrc ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .watchmanconfig ├── LICENSE ├── README.md ├── __tests__/ │ ├── __snapshots__/ │ │ └── index.test.js.snap │ └── index.test.js ├── app.json ├── index.d.ts ├── index.js ├── jsconfig.json └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": ["@babel/preset-env"], "plugins": [ "@babel/plugin-syntax-class-properties", "@babel/plugin-proposal-class-properties", ] } ================================================ FILE: .buckconfig ================================================ [android] target = Google Inc.:Google APIs:23 [maven_repositories] central = https://repo1.maven.org/maven2 ================================================ FILE: .eslintrc.js ================================================ module.exports = { "env": { "browser": true, "commonjs": true, "es6": true, "jest": true }, "extends": [ "eslint:recommended", "plugin:react/recommended" ], "parserOptions": { "ecmaFeatures": { "experimentalObjectRestSpread": true, "jsx": true }, "sourceType": "module" }, "plugins": [ "react", "react-native", "classes", ], "globals": { "dip" : true, "fdip" : true, "globalBackHandler": true, "jasmine": true, "idx": true, }, "parser": "babel-eslint", "rules": { "classes/space": 2, "classes/name": [2, "class", "method"], "classes/style": 2, "strict": 0, "prefer-const": "error", "react/prop-types": [ "error",{} ], "brace-style": "error", "new-cap": ["error", { "newIsCap": true } ], "block-spacing": "error", "keyword-spacing":"error", "no-irregular-whitespace": "error", "space-in-parens": ["error", "never"], "space-unary-ops": "error", "space-before-function-paren": ["error", "never"], "no-multi-spaces": "error", "comma-spacing": ["error", { "before": false, "after": true }], "computed-property-spacing": ["error", "never"], "key-spacing": ["error", { "beforeColon": false, "afterColon": true }], "no-lonely-if": "error", "no-mixed-spaces-and-tabs": "error", "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 1 }], "space-infix-ops": "error", "indent": [ "error", 2, { "SwitchCase": 1 } ], /*"linebreak-style": [ "error", "unix" ],*/ "quotes": [ "error", "single" ], "semi": [ "error", "never" ], "comma-dangle": [ "error", "always-multiline" ], "arrow-spacing": [ "error" ], "max-len": ["error", 130], "react/jsx-uses-react": "error", "react/jsx-uses-vars": "error", "react-native/no-unused-styles": 2, "react-native/split-platform-components": 0, "react-native/no-inline-styles": 2, "react-native/no-color-literals": 0, } }; ================================================ FILE: .flowconfig ================================================ [ignore] ; We fork some components by platform .*/*[.]android.js ; Ignore "BUCK" generated dirs /\.buckd/ ; Ignore unexpected extra "@providesModule" .*/node_modules/.*/node_modules/fbjs/.* ; Ignore duplicate module providers ; For RN Apps installed via npm, "Libraries" folder is inside ; "node_modules/react-native" but in the source repo it is in the root .*/Libraries/react-native/React.js .*/Libraries/react-native/ReactNative.js [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow flow/ [options] emoji=true module.system=haste experimental.strict_type_args=true munge_underscores=true module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FixMe suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-0]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-0]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError unsafe.enable_getters_and_setters=true [version] ^0.40.0 ================================================ FILE: .gitattributes ================================================ *.pbxproj -text ================================================ FILE: .gitignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate project.xcworkspace # Android/IntelliJ # build/ .idea .gradle local.properties *.iml # node.js # node_modules/ npm-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ *.keystore # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md fastlane/report.xml fastlane/Preview.html fastlane/screenshots coverage/ ================================================ FILE: .travis.yml ================================================ language: node_js node_js: - "stable" after_success: 'npm run coveralls' ================================================ FILE: .watchmanconfig ================================================ {} ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017-2018 Tobias Meinhardt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # React Native Event Listeners (This package isn't only restricted to react-native projects. The source is written in plain js with no dependencies to react-native.) [![Financial Contributors on Open Collective](https://opencollective.com/react-native-event-listeners/all/badge.svg?label=financial+contributors)](https://opencollective.com/react-native-event-listeners) [![npm version](https://badge.fury.io/js/react-native-event-listeners.svg)](https://badge.fury.io/js/react-native-event-listeners) [![dependencie status](https://david-dm.org/tobiasMeinhardt/react-native-event-listeners.svg)](https://david-dm.org/tobiasMeinhardt/react-native-event-listeners) [![dev-dependency status](https://david-dm.org/tobiasMeinhardt/react-native-event-listeners/dev-status.svg)](https://david-dm.org/tobiasMeinhardt/react-native-event-listeners?type=dev) [![npm](https://img.shields.io/npm/dm/react-native-event-listeners.svg)](https://www.npmjs.com/package/react-native-event-listeners) [![npm](https://img.shields.io/npm/dt/react-native-event-listeners.svg)](https://www.npmjs.com/package/react-native-event-listeners) [![travis build](https://travis-ci.org/meinto/react-native-event-listeners.svg?branch=master)](https://travis-ci.org/meinto/react-native-event-listeners) [![Coverage Status](https://coveralls.io/repos/github/meinto/react-native-event-listeners/badge.svg?branch=master)](https://coveralls.io/github/meinto/react-native-event-listeners?branch=master) ## Why In some very specific cases it can be charming to have a simple global event listener. While working with global event listeners **you don't have to pass touch events through the component tree** into other components or can **bypass easily the redux architecture** for example. ## Installation ``` npm install --save react-native-event-listeners ``` or ``` yarn add react-native-event-listeners ``` ## Usage Example *Hint: The event listeners also work across different files. You only have to import the ```EventRegister``` in every file you need to send or receive your events.* ```javascript import { EventRegister } from 'react-native-event-listeners' /* * RECEIVER COMPONENT */ class Receiver extends PureComponent { constructor(props) { super(props) this.state = { data: 'no data', } } componentWillMount() { this.listener = EventRegister.addEventListener('myCustomEvent', (data) => { this.setState({ data, }) }) } componentWillUnmount() { EventRegister.removeEventListener(this.listener) } render() { return {this.state.data} } } /* * SENDER COMPONENT */ const Sender = (props) => ( { EventRegister.emit('myCustomEvent', 'it works!!!') }) >Send Event ) ``` ## API ```javascript // import import { EventRegister } from 'react-native-event-listeners' ``` | static method | return value | description | | :------------------ | :---------------- | :------------------------------------------------------------- | | addEventListener | string \| boolean | return value is the id of the event listener or false on error | | removeEventListener | boolean | true on success otherwise false | | removeAllListeners | boolean | true on success otherwise false | | emitEvent | void | no return value | | on | string \| boolean | **shorthand** for addEventListener | | rm | boolean | **shorthand** for removeEventListener | | rmAll | boolean | **shorthand** for removeAllListeners | | emit | void | **shorthand** for emitEvent | ## Contributors ### Code Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ### Financial Contributors Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/react-native-event-listeners/contribute)] #### Individuals #### Organizations Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/react-native-event-listeners/contribute)] ================================================ FILE: __tests__/__snapshots__/index.test.js.snap ================================================ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EventRegister tests tests that eventlisteners are added properly 1`] = ` Object { "count": 3, "refs": Object { "l1": Object { "callback": [Function], "name": "test", }, "l2": Object { "callback": [Function], "name": "test", }, "l3": Object { "callback": [Function], "name": "test", }, }, } `; exports[`EventRegister tests tests that removeAllListeners works properly 1`] = ` Object { "count": 3, "refs": Object {}, } `; exports[`EventRegister tests tests that removeEventListener works properly 1`] = ` Object { "count": 3, "refs": Object { "l1": Object { "callback": [Function], "name": "test", }, "l3": Object { "callback": [Function], "name": "test", }, }, } `; ================================================ FILE: __tests__/index.test.js ================================================ import { EventRegister } from '../index' describe('EventRegister tests', () => { beforeEach(() => { EventRegister._Listeners = { count: 0, refs: {}, } }) const _addEventListener = (name = 'test', func = () => {}) => { return EventRegister.addEventListener(name, func) } it('tests that eventlisteners are added properly', () => { const id = _addEventListener() _addEventListener() _addEventListener() expect(id).toBe('l1') expect(EventRegister._Listeners).toMatchSnapshot() }) it('tests that removeEventListener works properly', () => { _addEventListener() const id = _addEventListener() _addEventListener() const removed = EventRegister.removeEventListener(id) expect(EventRegister._Listeners).toMatchSnapshot() expect(removed).toBe(true) const removed2 = EventRegister.removeEventListener('idNotAvailable') expect(removed2).toBe(true) const removed3 = EventRegister.removeEventListener(123) expect(removed3).toBe(false) }) it('tests that removeAllListeners works properly', () => { _addEventListener() _addEventListener() _addEventListener() const removed = EventRegister.removeAllListeners() expect(EventRegister._Listeners).toMatchSnapshot() expect(removed).toBe(true) }) it('tests that emitEvent works properly', () => { const mockFunc1 = jest.fn() const mockFunc2 = jest.fn() const mockFunc3 = jest.fn() _addEventListener('test1', mockFunc1) _addEventListener('test2', mockFunc2) _addEventListener('test3', mockFunc3) EventRegister.emitEvent('test1', { mockValue: 'mock 1' }) expect(mockFunc1).toHaveBeenCalledWith({ mockValue: 'mock 1' }) EventRegister.emitEvent('test3', { mockValue: 'mock 3' }) expect(mockFunc3).toHaveBeenCalledWith({ mockValue: 'mock 3' }) }) it('tests that removed callbacks are not called', () => { const mockFunc1 = jest.fn() const mockFunc2 = jest.fn() const mockFunc3 = jest.fn() const id = _addEventListener('test1', mockFunc1) _addEventListener('test2', mockFunc2) _addEventListener('test3', mockFunc3) EventRegister.removeEventListener(id) EventRegister.emitEvent('test1', { mockValue: 'mock 1' }) expect(mockFunc1).not.toHaveBeenCalled() EventRegister.emitEvent('test3', { mockValue: 'mock 3' }) expect(mockFunc3).toHaveBeenCalledWith({ mockValue: 'mock 3' }) _addEventListener('test1', mockFunc1) EventRegister.emitEvent('test1', { mockValue: 'mock 1' }) expect(mockFunc1).toHaveBeenCalledWith({ mockValue: 'mock 1' }) }) /* shorthands */ it('tests that addEventListener is called with shorthand "on"', () => { EventRegister.addEventListener = jest.fn() const func = jest.fn() EventRegister.on('name', func) expect(EventRegister.addEventListener).toHaveBeenCalledWith('name', func) }) it('tests that removeEventListener is called with shorthand "rm"', () => { EventRegister.removeEventListener = jest.fn(() => { return 'removed' }) const id = _addEventListener() const removed = EventRegister.rm(id) expect(EventRegister.removeEventListener).toHaveBeenCalledWith(id) expect(removed).toBe('removed') }) it('tests that removeAllListeners is called with shorthand "rmAll"', () => { EventRegister.removeAllListeners = jest.fn(() => { return 'removed' }) _addEventListener() _addEventListener() _addEventListener() const removed = EventRegister.rmAll() expect(EventRegister.removeAllListeners).toHaveBeenCalled() expect(removed).toBe('removed') }) it('tests that emitEvent is called with shorthand "emit"', () => { EventRegister.emitEvent = jest.fn() EventRegister.emit('test', { mockValue: 'val', }) expect(EventRegister.emitEvent).toHaveBeenCalledWith('test', { mockValue: 'val', }) }) }) ================================================ FILE: app.json ================================================ { "name": "reactNativeMirror", "displayName": "reactNativeMirror" } ================================================ FILE: index.d.ts ================================================ declare module 'react-native-event-listeners' { type Callback = (data: any) => void; class EventRegister { public static addEventListener(eventName: string, callback: Callback): string | boolean public static removeEventListener(id: string): boolean public static removeAllListeners(): boolean public static emitEvent(eventName: string, data?: any): void // shortener public static on(eventName: string, callback: Callback): string | boolean public static rm(id: string): boolean public static rmAll(): boolean public static emit(eventName: string, data?: any): void } export { EventRegister }; } ================================================ FILE: index.js ================================================ import type from 'type-detect' class EventRegister { static _Listeners = { count: 0, refs: {}, } static addEventListener(eventName, callback) { if ( type(eventName) === 'string' && type(callback) === 'function' ) { EventRegister._Listeners.count++ const eventId = 'l' + EventRegister._Listeners.count EventRegister._Listeners.refs[eventId] = { name: eventName, callback, } return eventId } return false } static removeEventListener(id) { if (type(id) === 'string') { return delete EventRegister._Listeners.refs[id] } return false } static removeAllListeners() { let removeError = false Object.keys(EventRegister._Listeners.refs).forEach(_id => { const removed = delete EventRegister._Listeners.refs[_id] removeError = (!removeError) ? !removed : removeError }) return !removeError } static emitEvent(eventName, data) { Object.keys(EventRegister._Listeners.refs).forEach(_id => { if ( EventRegister._Listeners.refs[_id] && eventName === EventRegister._Listeners.refs[_id].name ) EventRegister._Listeners.refs[_id].callback(data) }) } /* * shortener */ static on(eventName, callback) { return EventRegister.addEventListener(eventName, callback) } static rm(eventName) { return EventRegister.removeEventListener(eventName) } static rmAll() { return EventRegister.removeAllListeners() } static emit(eventName, data) { EventRegister.emitEvent(eventName, data) } } export { EventRegister } ================================================ FILE: jsconfig.json ================================================ { "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true }, "exclude": [ "node_modules" ] } ================================================ FILE: package.json ================================================ { "name": "react-native-event-listeners", "version": "1.0.7", "author": "Tobias Meinhardt ", "main": "index.js", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "test": "jest --no-cache", "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls" }, "repository": { "type": "git", "url": "https://github.com/tobiasMeinhardt/react-native-event-listeners" }, "bugs": { "url": "https://github.com/tobiasMeinhardt/react-native-event-listeners/issues" }, "keywords": [ "react", "react-native", "event listeners", "listeners", "events" ], "tags": [ "react", "react-native", "event listeners", "listeners", "events" ], "license": "MIT", "dependencies": { "type-detect": "^4.0.8" }, "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.7.0", "@babel/plugin-syntax-class-properties": "^7.2.0", "@babel/preset-env": "^7.7.1", "coveralls": "^3.0.7", "jest": "^24.9.0" }, "jest": { "collectCoverage": true, "collectCoverageFrom": [ "index.js" ] } }