├── .editorconfig
├── .github
└── FUNDING.yml
├── .gitignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src
├── PeerDataContext.tsx
├── PeerDataProvider.tsx
├── index.test.tsx
├── index.ts
├── react-app-env.d.ts
├── usePeerData.tsx
├── useSignaling.tsx
└── withPeerData.tsx
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.test.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [vardius] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with a single custom sponsorship URL
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 | /.rpt2_cache
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": false,
3 | "printWidth": 80,
4 | "tabWidth": 2,
5 | "singleQuote": true,
6 | "trailingComma": "all",
7 | "bracketSpacing": false,
8 | "jsxBracketSameLine": true
9 | }
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "node"
4 | - 8
5 | - 9
6 | script:
7 | - yarn test && codecov
8 | before_install:
9 | - npm install -g yarn
10 | - npm i -g codecov
11 | after_success:
12 | - bash <(curl -s https://codecov.io/bash) -e TRAVIS_NODE_VERSION
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Rafał Lorenz
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | React WebRTC - PeerData
2 | ================
3 | [](https://travis-ci.org/vardius/react-peer-data)
4 | [](https://www.npmjs.com/package/react-peer-data)
5 | [](https://www.npmjs.com/package/react-peer-data)
6 | [](LICENSE)
7 | [](https://codecov.io/gh/vardius/react-peer-data)
8 |
9 |
10 | Table of Content
11 |
12 |
13 | - [About](#about)
14 | - [How to use](#how-to-use)
15 | - [Installation](#installation)
16 | - [Examples](#examples)
17 | - [Hook](#hook)
18 | - [HOC](#hoc)
19 | - [License](#license)
20 |
21 |
22 |
23 |
24 | ABOUT
25 | ==================================================
26 | React wrapper for PeerData library for files, media streaming/sharing using WebRTC.
27 |
28 | Contributors:
29 |
30 | * [Rafał Lorenz](http://rafallorenz.com)
31 |
32 | Want to contribute ? Feel free to send pull requests!
33 |
34 | Have problems, bugs, feature ideas?
35 | We are using the github [issue tracker](https://github.com/vardius/react-peer-data/issues) to manage them.
36 |
37 |
39 |
40 | HOW TO USE
41 | ==================================================
42 |
43 | 1. [Chat Example](https://github.com/vardius/react-webrtc-chat)
44 |
45 | ## Getting started
46 | ### Installation
47 | ```bash
48 | npm install react-peer-data
49 | ```
50 | ### Examples
51 | Use `PeerDataProvider` to instantiate and pass peerData object down the component tree
52 | ```javascript
53 | import React from 'react';
54 | import ReactDOM from 'react-dom';
55 | import { EventDispatcher } from "peer-data";
56 | import { PeerDataProvider } from 'react-peer-data';
57 |
58 | import App from './App';
59 |
60 | ReactDOM.render(
61 |
66 |
67 | ,
68 | document.getElementById("root")
69 | );
70 | ```
71 | You can access peerData context value in two ways:
72 | #### Hook
73 | ```javascript
74 | import React, { useEffect } from 'react';
75 | import { usePeerData } from 'react-peer-data';
76 |
77 | function App() {
78 | const peerData = usePeerData();
79 |
80 | useEffect(() => {
81 | const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
82 | const room = peerData.connect('my-room', stream);
83 | room
84 | .on("participant", participant => {
85 | participant
86 | .on("disconnected", () => { console.log('disconnected', participant.id); })
87 | .on("track", event => { console.log('stream', participant.id, event.streams[0]); })
88 | .on("message", payload => { console.log(participant.id, payload); })
89 | .on("error", event => {
90 | console.error('peer', participant.id, event);
91 | participant.renegotiate();
92 | });
93 | })
94 | .on("error", event => { console.error('room', name, event); });
95 |
96 | return () => room.disconnect()
97 | }, [peerData]);
98 |
99 | return null; // @TODO: render participants
100 | }
101 |
102 | export default App;
103 | ```
104 | #### HOC
105 | ```javascript
106 | import React from 'react';
107 | import { withPeerData } from 'react-peer-data';
108 |
109 | function App({ peerData }) {
110 | // follow example from above
111 |
112 | return null; // @TODO: render participants
113 | }
114 |
115 | export default withPeerData(App);
116 | ```
117 |
118 | License
119 | -------
120 |
121 | This package is released under the MIT license. See the complete license in the package:
122 |
123 | [LICENSE](LICENSE.md)
124 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-peer-data",
3 | "version": "1.1.4",
4 | "description": "React wrapper for PeerData library for files, media streaming/sharing using WebRTC",
5 | "author": {
6 | "name": "Rafał Lorenz",
7 | "email": "vardius@gmail.com"
8 | },
9 | "license": "MIT",
10 | "bugs": {
11 | "url": "https://github.com/vardius/react-peer-data/issues"
12 | },
13 | "homepage": "https://github.com/vardius/react-peer-data#readme",
14 | "main": "dist/index.js",
15 | "module": "dist/index.es.js",
16 | "jsnext:main": "dist/index.es.js",
17 | "types": "dist/index.d.ts",
18 | "peerDependencies": {
19 | "react": "^16.8.6",
20 | "react-dom": "^16.8.6"
21 | },
22 | "dependencies": {
23 | "peer-data": "^3.2.4"
24 | },
25 | "devDependencies": {
26 | "@types/jest": "^24.0.13",
27 | "@types/node": "^12.0.2",
28 | "@types/react": "^16.8.17",
29 | "@types/react-dom": "^16.8.4",
30 | "react": "^16.8.6",
31 | "react-dom": "^16.8.6",
32 | "react-scripts": "2.1.5",
33 | "rimraf": "^2.6.1",
34 | "rollup": "^1.11.3",
35 | "rollup-plugin-commonjs": "^9.3.4",
36 | "rollup-plugin-node-resolve": "^4.2.3",
37 | "rollup-plugin-sourcemaps": "^0.4.2",
38 | "rollup-plugin-typescript2": "^0.21.0",
39 | "typescript": "^3.4.5"
40 | },
41 | "scripts": {
42 | "test": "cp -f ./tsconfig.test.json ./tsconfig.json && react-scripts test --env=jsdom --coverage",
43 | "test:watch": "cp -f ./tsconfig.test.json ./tsconfig.json && CI=true react-scripts test --env=jsdom",
44 | "build": "cp -f ./tsconfig.prod.json ./tsconfig.json && rollup -c",
45 | "clean": "rimraf dist es lib coverage",
46 | "prepare": "yarn build",
47 | "prebuild": "yarn clean",
48 | "postbuild": "rimraf {lib,es}/**/__tests__",
49 | "preversion": "yarn test",
50 | "postversion": "git push && git push --tags"
51 | },
52 | "jest": {
53 | "collectCoverageFrom": [
54 | "src/**/*.{ts,tsx}",
55 | "!src/index.ts"
56 | ]
57 | },
58 | "files": [
59 | "dist"
60 | ],
61 | "keywords": [
62 | "react hook",
63 | "react-hook",
64 | "use",
65 | "webrtc",
66 | "web",
67 | "rtc",
68 | "peer",
69 | "peer2peer",
70 | "react",
71 | "usePeerData",
72 | "useWebRtc",
73 | "react-use-peer",
74 | "react-use-webrtc",
75 | "react-use-peerdata",
76 | "react-peer-hook",
77 | "react-peerdata-hook",
78 | "react-webrtc-hook",
79 | "use-peer",
80 | "peer data",
81 | "peerdata",
82 | "usepeerdata hook",
83 | "usewebrtc hook",
84 | "react-hooks-peer-data",
85 | "react-hooks-web-rtc",
86 | "react usepeerdata",
87 | "react usewebrtc",
88 | "react hooks tutorial",
89 | "react custom hooks",
90 | "react-usepeerdata",
91 | "react-usewebrtc",
92 | "use hooks",
93 | "react usepeerdata hook",
94 | "react usewebrtc hook",
95 | "react-hooks-peerdata",
96 | "react-hooks-webrtc",
97 | "react hooks usepeerdata",
98 | "react hooks webrtc",
99 | "use peer data hook",
100 | "react peer data hook",
101 | "react webrtc hook"
102 | ]
103 | }
104 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import sourcemaps from "rollup-plugin-sourcemaps";
2 | import resolve from "rollup-plugin-node-resolve";
3 | import commonjs from "rollup-plugin-commonjs";
4 | import typescript from "rollup-plugin-typescript2";
5 |
6 | const env = process.env.NODE_ENV;
7 | const pkg = require("./package");
8 | const external = [
9 | ...Object.keys(pkg.dependencies || {}),
10 | ...Object.keys(pkg.peerDependencies || {}),
11 | ];
12 | let override = { compilerOptions: { jsx: 'react' } };
13 |
14 | const plugins = [
15 | sourcemaps(),
16 | resolve({
17 | mainFields: ['module', 'main', 'browser', 'jsnext']
18 | }),
19 | typescript({
20 | clean: true,
21 | rollupCommonJSResolveHack: true,
22 | exclude: ['*.d.ts', '**/*.d.ts'],
23 | tsconfigOverride: override,
24 | }),
25 | commonjs(),
26 | ];
27 |
28 | const config = {
29 | input: "src/index.ts",
30 | external: external,
31 | plugins: plugins,
32 | output: [
33 | {
34 | name: pkg.name,
35 | exports: 'named',
36 | file: pkg.module,
37 | format: "es",
38 | sourcemap: true
39 | },
40 | {
41 | name: pkg.name,
42 | exports: 'named',
43 | file: pkg.main,
44 | format: "cjs",
45 | sourcemap: true
46 | },
47 | ]
48 | };
49 |
50 | export default config;
51 |
--------------------------------------------------------------------------------
/src/PeerDataContext.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PeerData from 'peer-data';
3 |
4 | const PeerDataContext = React.createContext(null);
5 |
6 | export default PeerDataContext;
7 |
--------------------------------------------------------------------------------
/src/PeerDataProvider.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 | import PeerData, { EventDispatcher } from 'peer-data';
3 | import PeerDataContext from './PeerDataContext';
4 | import useSignaling, {Options} from './useSignaling';
5 |
6 | export interface Props {
7 | children: ReactNode;
8 | servers?: RTCConfiguration,
9 | constraints?: RTCDataChannelInit,
10 | signaling?: Options,
11 | }
12 |
13 | function PeerDataProvider({ children, servers, constraints, signaling = {dispatcher: new EventDispatcher()} }: Props) {
14 | useSignaling(signaling);
15 |
16 | return (
17 |
18 | {React.Children.only(children)}
19 |
20 | );
21 | }
22 |
23 | export default PeerDataProvider;
24 |
--------------------------------------------------------------------------------
/src/index.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | it('renders without crashing', () => {
5 | const div = document.createElement('div');
6 | ReactDOM.render(, div);
7 | ReactDOM.unmountComponentAtNode(div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as PeerDataContext } from './PeerDataContext';
2 | export { default as PeerDataProvider } from './PeerDataProvider';
3 | export { default as usePeerData } from './usePeerData';
4 | export { default as useSignaling } from './useSignaling';
5 | export { default as withPeerData } from './withPeerData';
6 |
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/usePeerData.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import PeerData from 'peer-data';
3 | import PeerDataContext from './PeerDataContext';
4 |
5 | const usePeerData = (): PeerData | null => useContext(PeerDataContext);
6 |
7 | export default usePeerData;
8 |
--------------------------------------------------------------------------------
/src/useSignaling.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { SocketChannel, EventDispatcher } from "peer-data";
3 |
4 | export interface Options {
5 | dispatcher: EventDispatcher
6 | url?: string | null,
7 | customChannel?: Object | null,
8 | }
9 |
10 | const useSignaling = ({ dispatcher, url = null, customChannel = null }: Options) => useState(customChannel ? customChannel : new SocketChannel(dispatcher, url));
11 |
12 | export default useSignaling;
13 |
--------------------------------------------------------------------------------
/src/withPeerData.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentType, Ref } from 'react';
2 | import PeerData from 'peer-data';
3 | import usePeerData from './usePeerData';
4 |
5 | type Omit = Pick>;
6 | type Diff = Omit;
7 |
8 | interface InjectedProps {
9 | peerData: PeerData;
10 | }
11 |
12 | export default function withPeerData(WrappedComponent: ComponentType) {
13 | type HocProps = Diff & {
14 | forwardedRef?: Ref;
15 | };
16 |
17 | function Hoc(props: HocProps) {
18 | const peerData = usePeerData();
19 | const { forwardedRef, ...rest } = props;
20 |
21 | return ;
22 | }
23 |
24 | Hoc.displayName = `withPeerData(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
25 |
26 | return React.forwardRef((props: HocProps, ref) => {
27 | return ;
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "build",
4 | "target": "es5",
5 | "sourceMap": true,
6 | "declaration": true,
7 | "lib": [
8 | "dom",
9 | "dom.iterable",
10 | "esnext"
11 | ],
12 | "allowJs": false,
13 | "skipLibCheck": true,
14 | "esModuleInterop": true,
15 | "allowSyntheticDefaultImports": true,
16 | "strict": true,
17 | "forceConsistentCasingInFileNames": true,
18 | "module": "esnext",
19 | "moduleResolution": "node",
20 | "resolveJsonModule": true,
21 | "noEmit": true,
22 | "jsx": "preserve",
23 | "noImplicitReturns": true,
24 | "noImplicitThis": true,
25 | "noImplicitAny": true,
26 | "strictNullChecks": true,
27 | "suppressImplicitAnyIndexErrors": true,
28 | "noUnusedLocals": true,
29 | "noUnusedParameters": true,
30 | },
31 | "include": [
32 | "src"
33 | ],
34 | "exclude": [
35 | "node_modules",
36 | "build",
37 | "dist",
38 | "example",
39 | "rollup.config.js"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "build",
4 | "target": "es5",
5 | "sourceMap": true,
6 | "declaration": true,
7 | "lib": [
8 | "dom",
9 | "dom.iterable",
10 | "esnext"
11 | ],
12 | "allowJs": false,
13 | "skipLibCheck": true,
14 | "esModuleInterop": true,
15 | "allowSyntheticDefaultImports": true,
16 | "strict": true,
17 | "forceConsistentCasingInFileNames": true,
18 | "module": "esnext",
19 | "moduleResolution": "node",
20 | "resolveJsonModule": true,
21 | "noEmit": true,
22 | "jsx": "preserve",
23 | "noImplicitReturns": true,
24 | "noImplicitThis": true,
25 | "noImplicitAny": true,
26 | "strictNullChecks": true,
27 | "suppressImplicitAnyIndexErrors": true,
28 | "noUnusedLocals": true,
29 | "noUnusedParameters": true,
30 | },
31 | "include": [
32 | "src"
33 | ],
34 | "exclude": [
35 | "node_modules",
36 | "build",
37 | "dist",
38 | "example",
39 | "rollup.config.js"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.prod.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "jsx": "preserve",
6 | "declaration": false,
7 | "isolatedModules": true,
8 | }
9 | }
10 |
--------------------------------------------------------------------------------