@tryfinch/react-connect 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "react-finch-connect-example",
3
+ "homepage": "https://.github.io/react-finch-connect",
4
+ "version": "0.0.0",
5
+ "license": "MIT",
6
+ "private": true,
7
+ "dependencies": {
8
+ "@types/react": "^17.0.37",
9
+ "prop-types": "^15.6.2",
10
+ "react": "file:../node_modules/react",
11
+ "react-dom": "^16.9.0",
12
+ "react-finch-connect": "file:.."
13
+ },
14
+ "scripts": {
15
+ "start": "react-scripts start",
16
+ "build": "react-scripts build",
17
+ "test": "react-scripts test --env=jsdom",
18
+ "eject": "react-scripts eject"
19
+ },
20
+ "eslintConfig": {
21
+ "extends": [
22
+ "react-app",
23
+ "react-app/jest"
24
+ ]
25
+ },
26
+ "browserslist": [
27
+ ">0.2%",
28
+ "not dead",
29
+ "not ie <= 11",
30
+ "not op_mini all"
31
+ ],
32
+ "devDependencies": {
33
+ "react-scripts": "^5.0.1"
34
+ }
35
+ }
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <meta name="theme-color" content="#000000">
7
+
8
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
9
+
10
+ <title>react-finch-connect</title>
11
+ </head>
12
+
13
+ <body>
14
+ <noscript>
15
+ You need to enable JavaScript to run this app.
16
+ </noscript>
17
+
18
+ <div id="root"></div>
19
+ </body>
20
+ </html>
@@ -0,0 +1,8 @@
1
+ {
2
+ "short_name": "react-finch-connect",
3
+ "name": "react-finch-connect",
4
+ "start_url": "./index.html",
5
+ "display": "standalone",
6
+ "theme_color": "#000000",
7
+ "background_color": "#ffffff"
8
+ }
@@ -0,0 +1,14 @@
1
+ .App {
2
+ text-align: center;
3
+ }
4
+
5
+ .App-header {
6
+ background-color: #282c34;
7
+ min-height: 100vh;
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: center;
11
+ justify-content: center;
12
+ font-size: calc(10px + 2vmin);
13
+ color: white;
14
+ }
@@ -0,0 +1,33 @@
1
+ import React, { useState } from 'react';
2
+ import { useFinchConnect, SuccessEvent, ErrorEvent } from 'react-finch-connect';
3
+ import './App.css';
4
+
5
+ const App = () => {
6
+ const [code, setCode] = useState<string>();
7
+
8
+ const onSuccess = ({ code }: SuccessEvent) => setCode(code);
9
+ const onError = ({ errorMessage }: ErrorEvent) => console.error(errorMessage);
10
+ const onClose = () => console.log('User exited Finch Connect');
11
+
12
+ const { open } = useFinchConnect({
13
+ clientId: '<your-client-id>',
14
+ products: ['company', 'directory', 'individual', 'employment'],
15
+ // sandbox: false,
16
+ // payrollProvider: '<payroll-provider-id>',
17
+ onSuccess,
18
+ onError,
19
+ onClose,
20
+ });
21
+
22
+ return (
23
+ <div className="App">
24
+ <header className="App-header">
25
+ <p>Code: {code}</p>
26
+ <button type="button" onClick={() => open()}>
27
+ Open Finch Connect
28
+ </button>
29
+ </header>
30
+ </div>
31
+ );
32
+ };
33
+ export default App;
@@ -0,0 +1,11 @@
1
+ body {
2
+ margin: 0;
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
4
+ 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
5
+ -webkit-font-smoothing: antialiased;
6
+ -moz-osx-font-smoothing: grayscale;
7
+ }
8
+
9
+ code {
10
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
11
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+
4
+ import './index.css';
5
+ import App from './App';
6
+
7
+ ReactDOM.render(<App />, document.getElementById('root'));
@@ -0,0 +1 @@
1
+ /// <reference types="react-scripts" />
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
9
+ "allowJs": true,
10
+ "skipLibCheck": true,
11
+ "esModuleInterop": true,
12
+ "allowSyntheticDefaultImports": true,
13
+ "strict": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "module": "esnext",
16
+ "moduleResolution": "node",
17
+ "resolveJsonModule": true,
18
+ "isolatedModules": true,
19
+ "noEmit": true,
20
+ "jsx": "react-jsx",
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": [
24
+ "src"
25
+ ]
26
+ }
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@tryfinch/react-connect",
3
+ "version": "2.8.0",
4
+ "description": "",
5
+ "author": "",
6
+ "license": "MIT",
7
+ "repository": "Finch-API/react-finch-connect",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "module": "dist/index.es.js",
11
+ "jsnext:main": "dist/index.es.js",
12
+ "engines": {
13
+ "node": ">=8",
14
+ "npm": ">=5"
15
+ },
16
+ "scripts": {
17
+ "test": "cross-env CI=1 react-scripts test --env=jsdom",
18
+ "test:watch": "react-scripts test --env=jsdom",
19
+ "build": "rollup -c",
20
+ "start": "rollup -c -w",
21
+ "prepare": "npm run build",
22
+ "predeploy": "cd example && npm install && npm run build"
23
+ },
24
+ "peerDependencies": {
25
+ "react": ">=16.9.0"
26
+ },
27
+ "devDependencies": {
28
+ "@babel/core": "^7.0.0",
29
+ "@babel/plugin-external-helpers": "^7.0.0",
30
+ "@babel/plugin-proposal-class-properties": "^7.0.0",
31
+ "@babel/plugin-proposal-decorators": "^7.0.0",
32
+ "@babel/plugin-proposal-do-expressions": "^7.0.0",
33
+ "@babel/plugin-proposal-export-default-from": "^7.0.0",
34
+ "@babel/plugin-proposal-export-namespace-from": "^7.0.0",
35
+ "@babel/plugin-proposal-function-bind": "^7.0.0",
36
+ "@babel/plugin-proposal-function-sent": "^7.0.0",
37
+ "@babel/plugin-proposal-json-strings": "^7.0.0",
38
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0",
39
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
40
+ "@babel/plugin-proposal-numeric-separator": "^7.0.0",
41
+ "@babel/plugin-proposal-optional-chaining": "^7.0.0",
42
+ "@babel/plugin-proposal-pipeline-operator": "^7.0.0",
43
+ "@babel/plugin-proposal-throw-expressions": "^7.0.0",
44
+ "@babel/plugin-syntax-dynamic-import": "^7.0.0",
45
+ "@babel/plugin-syntax-import-meta": "^7.0.0",
46
+ "@babel/preset-env": "^7.0.0",
47
+ "@babel/preset-react": "^7.0.0",
48
+ "@rollup/plugin-replace": "^4.0.0",
49
+ "@testing-library/react-hooks": "^3.2.1",
50
+ "babel-eslint": "^10.0.1",
51
+ "cross-env": "^5.2.0",
52
+ "eslint": "^7.32.0",
53
+ "eslint-config-airbnb": "^18.2.0",
54
+ "eslint-config-prettier": "^6.11.0",
55
+ "eslint-config-standard": "^11.0.0",
56
+ "eslint-config-standard-react": "^6.0.0",
57
+ "eslint-plugin-import": "^2.22.0",
58
+ "eslint-plugin-jsx-a11y": "^6.3.1",
59
+ "eslint-plugin-node": "^7.0.1",
60
+ "eslint-plugin-prettier": "^3.1.4",
61
+ "eslint-plugin-promise": "^4.0.0",
62
+ "eslint-plugin-react": "^7.20.3",
63
+ "eslint-plugin-react-hooks": "^4.0.8",
64
+ "eslint-plugin-standard": "^3.1.0",
65
+ "gh-pages": "^2.0.1",
66
+ "prettier": "^2.0.5",
67
+ "react": "^16.9.0",
68
+ "react-scripts": "^5.0.1",
69
+ "react-test-renderer": "^16.9.0",
70
+ "rollup": "^2.75.7",
71
+ "rollup-plugin-babel": "^4.3.2",
72
+ "rollup-plugin-commonjs": "^9.2.0",
73
+ "rollup-plugin-dts": "^4.0.1",
74
+ "rollup-plugin-node-resolve": "^4.0.0",
75
+ "rollup-plugin-peer-deps-external": "^2.2.0",
76
+ "rollup-plugin-url": "^2.1.0"
77
+ }
78
+ }
@@ -0,0 +1,49 @@
1
+ import babel from 'rollup-plugin-babel';
2
+ import commonjs from 'rollup-plugin-commonjs';
3
+ import dts from 'rollup-plugin-dts';
4
+ import external from 'rollup-plugin-peer-deps-external';
5
+ import resolve from 'rollup-plugin-node-resolve';
6
+ import url from 'rollup-plugin-url';
7
+ import replace from '@rollup/plugin-replace';
8
+
9
+ import pkg from './package.json';
10
+
11
+ export default [
12
+ {
13
+ input: 'src/index.js',
14
+ output: [
15
+ {
16
+ file: pkg.main,
17
+ format: 'cjs',
18
+ sourcemap: true,
19
+ },
20
+ {
21
+ file: pkg.module,
22
+ format: 'es',
23
+ sourcemap: true,
24
+ },
25
+ ],
26
+ plugins: [
27
+ external(),
28
+ url({ exclude: ['**/*.svg'] }),
29
+ babel({
30
+ exclude: 'node_modules/**',
31
+ }),
32
+ resolve(),
33
+ commonjs(),
34
+ replace({
35
+ SDK_VERSION: JSON.stringify(pkg.version), // has to be stringified somehow
36
+ }),
37
+ ],
38
+ },
39
+ {
40
+ input: 'src/index.d.ts',
41
+ output: [
42
+ {
43
+ file: pkg.types,
44
+ format: 'es',
45
+ },
46
+ ],
47
+ plugins: [dts()],
48
+ },
49
+ ];
package/src/index.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ declare module 'react-finch-connect' {
2
+ export type SuccessEvent = {
3
+ code: string;
4
+ };
5
+
6
+ export type ErrorEvent = {
7
+ errorMessage: string;
8
+ };
9
+
10
+ export type ConnectOptions = {
11
+ clientId: string;
12
+ products?: string[];
13
+ mode?: string;
14
+ manual?: boolean;
15
+ payrollProvider?: string;
16
+ sandbox?: boolean;
17
+ category?: string;
18
+ onSuccess?: (e: SuccessEvent) => void;
19
+ onError?: (e: ErrorEvent) => void;
20
+ onClose?: () => void;
21
+ zIndex?: bigint | string;
22
+ };
23
+
24
+ export function useFinchConnect(opts: ConnectOptions): { open: () => void };
25
+ }
package/src/index.js ADDED
@@ -0,0 +1,97 @@
1
+ import { useEffect } from 'react';
2
+
3
+ const BASE_FINCH_CONNECT_URI = 'https://connect.tryfinch.com';
4
+ const DEFAULT_FINCH_REDIRECT_URI = 'https://tryfinch.com';
5
+ const FINCH_CONNECT_IFRAME_ID = 'finch-connect-iframe';
6
+ const FINCH_AUTH_MESSAGE_NAME = 'finch-auth-message';
7
+
8
+ const noop = () => {};
9
+
10
+ // eslint-disable-next-line import/prefer-default-export
11
+ export const useFinchConnect = (options = {}) => {
12
+ const {
13
+ clientId,
14
+ products = [],
15
+ mode = 'employer',
16
+ category,
17
+ manual = false,
18
+ payrollProvider = null,
19
+ sandbox = false,
20
+ onSuccess = noop,
21
+ onError = noop,
22
+ onClose = noop,
23
+ zIndex = 999,
24
+ } = options;
25
+
26
+ const _constructAuthUrl = (clientId, products) => {
27
+ const authUrl = new URL(`${BASE_FINCH_CONNECT_URI}/authorize`);
28
+
29
+ if (clientId) authUrl.searchParams.append('client_id', clientId);
30
+ if (payrollProvider) authUrl.searchParams.append('payroll_provider', payrollProvider);
31
+ if (category) authUrl.searchParams.append('category', category);
32
+ authUrl.searchParams.append('products', products.join(' '));
33
+ authUrl.searchParams.append('app_type', 'spa');
34
+ authUrl.searchParams.append('redirect_uri', DEFAULT_FINCH_REDIRECT_URI);
35
+ authUrl.searchParams.append('mode', mode);
36
+ if (manual) authUrl.searchParams.append('manual', manual);
37
+ if (sandbox) authUrl.searchParams.append('sandbox', sandbox);
38
+ /* global SDK_VERSION */
39
+ if (SDK_VERSION) authUrl.searchParams.append('sdk_version', `react-${SDK_VERSION}`);
40
+
41
+ return authUrl.href;
42
+ };
43
+
44
+ const open = () => {
45
+ if (document.getElementById(FINCH_CONNECT_IFRAME_ID)) {
46
+ return null;
47
+ }
48
+
49
+ const iframe = document.createElement('iframe');
50
+ iframe.src = _constructAuthUrl(clientId, products);
51
+ iframe.frameBorder = '0';
52
+ iframe.id = FINCH_CONNECT_IFRAME_ID;
53
+ iframe.style.position = 'fixed';
54
+ iframe.style.zIndex = zIndex.toString();
55
+ iframe.style.height = '100%';
56
+ iframe.style.width = '100%';
57
+ iframe.style.top = '0';
58
+ iframe.style.backgroundColor = 'none transparent';
59
+ iframe.style.border = 'none';
60
+ document.body.prepend(iframe);
61
+ document.body.style.overflow = 'hidden';
62
+ };
63
+
64
+ const close = () => {
65
+ const frameToRemove = document.getElementById(FINCH_CONNECT_IFRAME_ID);
66
+ if (frameToRemove) {
67
+ frameToRemove.parentNode.removeChild(frameToRemove);
68
+ document.body.style.overflow = 'inherit';
69
+ }
70
+ };
71
+
72
+ useEffect(() => {
73
+ function handleFinchAuth(event) {
74
+ const handleFinchAuthSuccess = (code) => onSuccess({ code });
75
+ const handleFinchAuthError = (error) => onError({ errorMessage: error });
76
+ const handleFinchAuthClose = () => onClose();
77
+
78
+ if (!event.data) return;
79
+ if (event.data.name !== FINCH_AUTH_MESSAGE_NAME) return;
80
+ if (!event.origin.startsWith(BASE_FINCH_CONNECT_URI)) return;
81
+
82
+ const { code, error, closed } = event.data;
83
+
84
+ close();
85
+ if (code) handleFinchAuthSuccess(code);
86
+ else if (error) handleFinchAuthError(error);
87
+ else if (closed) handleFinchAuthClose();
88
+ }
89
+
90
+ window.addEventListener('message', handleFinchAuth);
91
+ return () => window.removeEventListener('message', handleFinchAuth);
92
+ }, [onClose, onError, onSuccess]);
93
+
94
+ return {
95
+ open,
96
+ };
97
+ };