├── .editorconfig
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── enzyme-setup.js
├── examples
├── advanced
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── index.html
│ │ ├── logo.png
│ │ └── manifest.json
│ ├── src
│ │ ├── button.tsx
│ │ ├── config.tsx
│ │ ├── global.d.ts
│ │ ├── index.tsx
│ │ ├── reducers.ts
│ │ ├── styles.ts
│ │ └── wrapper.tsx
│ ├── tsconfig.json
│ ├── tsconfig.prod.json
│ └── tslint.json
├── basic
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── index.html
│ │ ├── logo.png
│ │ └── manifest.json
│ ├── src
│ │ ├── button.tsx
│ │ ├── config.ts
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── tsconfig.json
│ ├── tsconfig.prod.json
│ └── tslint.json
└── redux
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── index.html
│ ├── logo.png
│ └── manifest.json
│ ├── src
│ ├── button.tsx
│ ├── config.tsx
│ ├── global.d.ts
│ ├── index.tsx
│ ├── reducers.ts
│ ├── styles.ts
│ └── wrapper.tsx
│ ├── tsconfig.json
│ ├── tsconfig.prod.json
│ └── tslint.json
├── jest.json
├── logo.png
├── package.json
├── rollup.config.js
├── src
├── index.ts
├── paymentRequest.fixture.ts
├── paymentRequest.test.tsx
├── paymentRequest.tsx
└── types.ts
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | dist
4 | lib
5 | .DS_Store
6 | .rpt2_cache
7 | coverage
8 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | examples
3 | logo.png
4 | .rpt2_cache
5 | coverage
6 | src
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - '8'
5 |
6 | install:
7 | - npm install
8 |
9 | script:
10 | - npm run test
11 | - npm run build
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-present, Marco Lanaro
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React high order component to drive payment request widget on react applications 💳.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | ## Browser support
25 |
26 | [Payment request api](https://developers.google.com/web/fundamentals/getting-started/primers/payment-request/) is supported on Chrome for desktop v. ^61.0, Chrome for Android and Android Webview v. ^56.0, Microsoft Edge v. ^15.0.
27 |
28 | ## Demo
29 |
30 | You can find a working demo [here](https://lanaro.net/react-payment-request-api/). Be sure to use a supported browser.
31 |
32 | ## NPM Install
33 |
34 | ```bash
35 | npm install react-payment-request-api --save
36 | ```
37 |
38 | ## Usage
39 |
40 | Consume the UI component in the hight order component `button.js`:
41 |
42 | ```js
43 | import React from "react";
44 | import paymentRequest from 'react-payment-request-api';
45 |
46 | const Button = ({ show, isSupported }) => isSupported
47 | ? Pay now!
48 | : Payment request not supported ;
49 |
50 | export default paymentRequest()(Button);
51 | ```
52 |
53 | Pass the configuration to the high order component `smartComponent.js`:
54 |
55 | ```js
56 | import React from "react";
57 |
58 | import Button from "./button";
59 |
60 | const SmartComponent = (config) =>
61 | ;
62 |
63 | export default SmartComponent;
64 | ```
65 |
66 | ## FAQ
67 |
68 | #### How does it work?
69 |
70 | It takes a configuration prop that define how the native widget should behave and any other property you want to pass to the UI component. It spread all the properties a part from the configuration to the enhanced UI component. The UI component will also receive other props that will help improving the experience allowing complete control on the renderer and on the action handler.
71 |
72 | #### Does it support Redux or any other flux implementation?
73 |
74 | Yes, with version 1.0 we have changed the interface allowing the user to inject the configuration from the parent component. In this way it does not matter which flux implementation you are using. At the same time, we are preserving the high order component pattern so you have complete control on the renderer and on the action handler.
75 |
76 | #### Does it support Typescript?
77 |
78 | Yes, you don't need to install any typescript dependecies because types come with the library. It export `PaymentRequestParams` (injected configuration) and `PaymentRequestInterface` (UI component extended props) typescript interfaces. All the [examples](https://github.com/marcolanaro/react-payment-request-api/tree/master/examples) are written in typescript.
79 |
80 | ## API
81 |
82 | Your wrapped component will be decorated with this injected props:
83 |
84 | Parameter | Type | Description
85 | ----------- | ------------------------------ | -----------
86 | isSupported | boolean | True if the payment request api is supported by the browser.
87 | show | function: () => PaymentRequest | It will begin the process when the merchant site want to create a new [PaymentRequest](https://www.w3.org/TR/payment-request/#paymentrequest-interface).
88 | abort | function: () => void | You can intentionally [abort a PaymentRequest](https://www.w3.org/TR/payment-request/#abort) by calling the abort method after show has been called.
89 |
90 | Configuration of the high order component:
91 |
92 | Parameter | Type | Description
93 | ----------------------- | -------------------------------------------------- | -----------
94 | methodData | object | Required [payment method data](https://www.w3.org/TR/payment-request/#idl-def-paymentmethoddata).
95 | details | object | Required information about [transaction](https://www.w3.org/TR/payment-request/#dom-paymentdetails).
96 | options | object | [Optional parameter](https://www.w3.org/TR/payment-request/#dom-paymentoptions) for things like shipping, etc.
97 | onShowSuccess | Promise based callback: (result, resolve, reject) | The handler will be executed after the filling of the form is [successfull](https://www.w3.org/TR/payment-request/#dfn-complete). You should post your payment request and then resolve or reject the promise.
98 | onShowFail | Promise based callback: (error) | The handler will be executed if the filling of the form is [not successfull](https://www.w3.org/TR/payment-request/#dom-paymentcomplete-fail) (like when the user dismiss the form).
99 | onShippingAddressChange | Promise based callback: (request, resolve, reject) | The handler will be executed if the [shipping address has change](https://www.w3.org/TR/payment-request/#idl-def-paymentrequestupdateevent). You can change the request and then resolve the promise.
100 | onShippingOptionChange | Promise based callback: (request, resolve, reject) | The handler will be executed if the [shipping option has change](https://www.w3.org/TR/payment-request/#idl-def-paymentrequestupdateevent). You can change the request and then resolve the promise.
101 | onMerchantValidation | Promise based callback: (event) | Thde handler is used by Apple pay to [validate the merchant](https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/providing_merchant_validation).
102 |
103 | ## License
104 |
105 | See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT).
106 |
--------------------------------------------------------------------------------
/enzyme-setup.js:
--------------------------------------------------------------------------------
1 | var enzyme = require('enzyme');
2 | var Adapter = require('enzyme-adapter-react-16');
3 |
4 | enzyme.configure({ adapter: new Adapter() });
5 |
--------------------------------------------------------------------------------
/examples/advanced/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | .DS_Store
4 | npm-debug.log*
5 |
--------------------------------------------------------------------------------
/examples/advanced/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React high order component to drive payment request widget on react applications 💳.
7 |
8 |
9 |
10 | ## Andorid Pay Demo
11 |
12 | This component differ from the [redux](../redux) example because it add Android Pay as supported method.
13 |
14 | ## Run the demo
15 |
16 | Install:
17 |
18 | ```bash
19 | npm install
20 | ```
21 |
22 | Run
23 |
24 | ```bash
25 | npm start
26 | ```
27 |
28 | Open your browser at [http://localhost:8080/](http://localhost:8080/).
29 |
30 |
31 | ## License
32 |
33 | See the [LICENSE](../../LICENSE.md) file for license rights and limitations (MIT).
34 |
--------------------------------------------------------------------------------
/examples/advanced/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-payment-request-api-example-android-pay",
3 | "homepage": "https://lanaro.net/react-payment-request-api",
4 | "version": "0.1.0",
5 | "private": true,
6 | "dependencies": {
7 | "@types/jest": "^21.1.4",
8 | "@types/node": "^8.0.46",
9 | "@types/react": "^16.4.14",
10 | "@types/react-dom": "^16.0.7",
11 | "react": "^16.5.2",
12 | "react-dom": "^16.5.2",
13 | "react-payment-request-api": "^3.1.0",
14 | "react-redux": "^5.0.6",
15 | "redux": "^3.7.2",
16 | "redux-thunk": "^2.2.0"
17 | },
18 | "devDependencies": {
19 | "@types/react-redux": "^4.4.43",
20 | "@types/redux": "^3.6.0",
21 | "@types/redux-actions": "^1.2.6",
22 | "gh-pages": "^1.0.0",
23 | "react-scripts-ts": "2.17.0",
24 | "typescript": "^3.0.3"
25 | },
26 | "scripts": {
27 | "start": "react-scripts-ts start",
28 | "build": "react-scripts-ts build",
29 | "eject": "react-scripts-ts eject",
30 | "predeploy": "npm run build",
31 | "deploy": "gh-pages -d build"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/advanced/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | React - Payment request API
10 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/advanced/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/4b7c14feb9ac5b79bdd17aa38a89dce503ceac01/examples/advanced/public/logo.png
--------------------------------------------------------------------------------
/examples/advanced/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Payment Request",
3 | "name": "React Payment Request API",
4 | "icons": [
5 | {
6 | "src": "logo.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/advanced/src/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import paymentRequest, { PaymentRequestInterface } from 'react-payment-request-api';
3 | import { connect } from 'react-redux';
4 |
5 | import styles from './styles';
6 |
7 | export interface OwnProps {
8 | style: React.CSSProperties;
9 | }
10 |
11 | export interface StateProps {
12 | payed: boolean;
13 | }
14 |
15 | const Button: React.StatelessComponent = ({
16 | show, isSupported, style, payed,
17 | }) => isSupported
18 | ? (
19 |
20 | {payed ? 'Payed' : 'Pay now'}
21 |
22 | )
23 | : Payment request not supported ;
24 |
25 | const ConnectedButton = connect((state) => ({
26 | payed: state.payed,
27 | }))(Button);
28 |
29 | export default paymentRequest()(ConnectedButton);
30 |
--------------------------------------------------------------------------------
/examples/advanced/src/config.tsx:
--------------------------------------------------------------------------------
1 | import { PaymentRequestParams } from 'react-payment-request-api';
2 |
3 | const details: PaymentDetailsInit = {
4 | displayItems: [{
5 | label: 'Original donation amount',
6 | amount: { currency: 'USD', value: '65.00' },
7 | }, {
8 | label: 'Friends and family discount',
9 | amount: { currency: 'USD', value: '-10.00' },
10 | }, {
11 | label: 'Delivery tax',
12 | pending: true,
13 | amount: { currency: 'USD', value: '10.00' },
14 | }],
15 | total: {
16 | label: 'Total due',
17 | amount: { currency: 'USD', value : '55.00' },
18 | },
19 | };
20 |
21 | const getConfig = (supportedPaymentCards: string[], onShowSuccess: () => void) => ({
22 | methodData: [
23 | {
24 | supportedMethods: ['basic-card'],
25 | data: {
26 | supportedNetworks: ['visa', 'mastercard', 'diners'],
27 | },
28 | },
29 | {
30 | supportedMethods: ['https://android.com/pay'],
31 | data: {
32 | merchantId: 'fake',
33 | environment: 'TEST',
34 | allowedCardNetwork: ['AMEX', 'MASTERCARD', 'VISA', 'DISCOVER'],
35 | paymentMethodTokenizationParameters: {
36 | tokenizationType: 'GATEWAY_TOKEN',
37 | parameters: {
38 | 'gateway': 'stripe',
39 | 'stripe:publishableKey': 'fake',
40 | 'stripe:version': '2016-07-06'
41 | },
42 | },
43 | },
44 | },
45 | {
46 | supportedMethods: 'https://apple.com/apple-pay',
47 | data: {
48 | version: 3,
49 | merchantIdentifier: 'merchant.com.example',
50 | merchantCapabilities: ['supportsDebit'],
51 | supportedNetworks: ['masterCard', 'visa'],
52 | countryCode: 'US',
53 | },
54 | },
55 | ],
56 | details: details,
57 | options: {
58 | requestShipping: true,
59 | requestPayerEmail: true,
60 | requestPayerPhone: true,
61 | },
62 | onShowSuccess: (result, resolve, reject): void => {
63 | /* tslint:disable-next-line:no-console */
64 | console.log('Result:', result);
65 | // make the payment
66 | setTimeout(() => { onShowSuccess(); resolve(); }, 2000);
67 | },
68 | /* tslint:disable-next-line:no-console */
69 | onShowFail: (error) => console.log('Error', error),
70 | onShippingAddressChange: (request, resolve, reject): void => {
71 | /* tslint:disable-next-line:no-console */
72 | console.log('ShippingAddress:', request.shippingAddress);
73 | // recalculate details
74 | details.shippingOptions = [{
75 | id: 'all',
76 | label: 'Wherever you want for free',
77 | amount: { currency: 'USD', value: '0.00' },
78 | selected: true
79 | }];
80 | details.displayItems![2] = {
81 | label: 'Tax',
82 | pending: false,
83 | amount: { currency: 'USD', value: '8.00' },
84 | };
85 | resolve(details);
86 | },
87 | onShippingOptionChange: (request, resolve, reject): void => {
88 | resolve(details);
89 | },
90 | // tslint:disable-next-line:no-any
91 | onMerchantValidation: (event: any): void => {
92 | event.complete(Promise.resolve(event.validationURL));
93 | },
94 | }) as PaymentRequestParams;
95 |
96 | export default getConfig;
97 |
--------------------------------------------------------------------------------
/examples/advanced/src/global.d.ts:
--------------------------------------------------------------------------------
1 | interface Window {
2 | __REDUX_DEVTOOLS_EXTENSION__?(): any; // tslint:disable-line:no-any
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { createStore, applyMiddleware } from 'redux';
5 | import thunk from 'redux-thunk';
6 |
7 | import reducers from './reducers';
8 | import Wrapper from './wrapper';
9 | import styles from './styles';
10 |
11 | const store = createStore(
12 | reducers,
13 | window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
14 | applyMiddleware(thunk)
15 | );
16 |
17 | const App = () => (
18 |
19 |
20 |
21 |
React Payment Request API
22 |
23 | High order component to drive
24 | Payment Request
25 | widget on react applications 💳
26 |
27 |
28 | This component generate the configuration from a smart component connected to redux.
29 |
30 | It will also dispatch a redux action on success.
31 |
32 |
33 |
34 |
35 |
36 |
37 | );
38 |
39 | ReactDOM.render( , document.getElementById('app'));
40 |
--------------------------------------------------------------------------------
/examples/advanced/src/reducers.ts:
--------------------------------------------------------------------------------
1 | import { Action } from 'redux-actions';
2 |
3 | export interface State {
4 | supportedPaymentCards: string[];
5 | }
6 |
7 | const initialState = {
8 | supportedPaymentCards: ['visa'],
9 | payed: false,
10 | };
11 |
12 | const reducers = (previousState: State = initialState, action: Action) => { // tslint:disable-line:no-any
13 | switch (action.type) {
14 | case 'PROCESSING_PAYMENT':
15 | return ({ ...previousState, payed: true });
16 | default:
17 | return ({ ...previousState });
18 | }
19 | };
20 |
21 | export default reducers;
22 |
--------------------------------------------------------------------------------
/examples/advanced/src/styles.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default {
4 | container: {
5 | display: 'flex',
6 | flexDirection: 'column',
7 | padding: '1rem',
8 | alignItems: 'center',
9 | } as React.CSSProperties,
10 | a: {
11 | color: '#48b5f2',
12 | },
13 | h1: {
14 | fontSize: '1.7rem',
15 | },
16 | h2: {
17 | color: '#0f4b6d',
18 | fontSize: '1.2rem',
19 | },
20 | logo: {
21 | backgroundImage: 'url(https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/master/logo.png)',
22 | backgroundSize: 'cover',
23 | backgroundPosition: 'center',
24 | width: '10rem',
25 | height: '10rem',
26 | minWidth: '10rem',
27 | minHeight: '10rem',
28 | borderRadius: '0.1875rem',
29 | },
30 | content: {
31 | display: 'flex',
32 | flexGrow: 1,
33 | flexDirection: 'column',
34 | justifyContent: 'center',
35 | } as React.CSSProperties,
36 | button: {
37 | boxShadow: '0 0 1px #fff inset',
38 | borderRadius: '1rem',
39 | padding: '1rem 2rem',
40 | font: '3rem Calibri, Arial, sans-serif',
41 | textShadow: '1px 1px 0 rgba(255,255,255,0.4)',
42 | },
43 | toPay: {
44 | backgroundColor: '#48b5f2',
45 | border: '1px solid #84acc3',
46 | color: '#0f4b6d',
47 | },
48 | payed: {
49 | backgroundColor: '#48f28c',
50 | border: '1px solid #84c38c',
51 | color: '#0f6d1c',
52 | },
53 | };
54 |
--------------------------------------------------------------------------------
/examples/advanced/src/wrapper.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { connect } from 'react-redux';
3 | import { Dispatch } from 'redux';
4 |
5 | import Button from './button';
6 | import getConfig from './config';
7 | import { State } from './reducers';
8 |
9 | interface StateProps {
10 | supportedPaymentCards: string[];
11 | }
12 |
13 | interface DispatchProps {
14 | onShowSuccess: () => void;
15 | }
16 |
17 | interface OwnProps {
18 | style: React.CSSProperties;
19 | }
20 |
21 | const Wrapper: React.StatelessComponent = ({
22 | style, supportedPaymentCards, onShowSuccess,
23 | }) => (
24 |
28 | );
29 |
30 | const mapState2Props = (state: State): StateProps => ({
31 | supportedPaymentCards: state.supportedPaymentCards,
32 | });
33 |
34 | const mapDispatch2Props = (dispatch: Dispatch): DispatchProps => ({
35 | onShowSuccess: () => dispatch({ type: 'PROCESSING_PAYMENT' }),
36 | });
37 |
38 | export default connect(mapState2Props, mapDispatch2Props)(Wrapper);
39 |
--------------------------------------------------------------------------------
/examples/advanced/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "build/dist",
4 | "module": "commonjs",
5 | "target": "es5",
6 | "lib": ["es6", "dom"],
7 | "sourceMap": true,
8 | "allowJs": true,
9 | "jsx": "react",
10 | "moduleResolution": "node",
11 | "rootDir": "src",
12 | "forceConsistentCasingInFileNames": true,
13 | "noImplicitReturns": true,
14 | "noImplicitThis": true,
15 | "noImplicitAny": true,
16 | "skipLibCheck": true,
17 | "strictNullChecks": true,
18 | "suppressImplicitAnyIndexErrors": true,
19 | "noUnusedLocals": true
20 | },
21 | "exclude": [
22 | "node_modules",
23 | "build",
24 | "scripts",
25 | "acceptance-tests",
26 | "webpack",
27 | "jest",
28 | "src/setupTests.ts"
29 | ],
30 | "types": [
31 | "typePatches"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/examples/advanced/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | }
--------------------------------------------------------------------------------
/examples/advanced/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint-react"],
3 | "rules": {
4 | "align": [
5 | true,
6 | "parameters",
7 | "arguments",
8 | "statements"
9 | ],
10 | "ban": false,
11 | "class-name": true,
12 | "comment-format": [
13 | true,
14 | "check-space"
15 | ],
16 | "curly": true,
17 | "eofline": false,
18 | "forin": true,
19 | "indent": [ true, "spaces" ],
20 | "interface-name": [true, "never-prefix"],
21 | "jsdoc-format": true,
22 | "jsx-no-lambda": false,
23 | "jsx-no-multiline-js": false,
24 | "label-position": true,
25 | "max-line-length": [ true, 120 ],
26 | "member-ordering": [
27 | true,
28 | "public-before-private",
29 | "static-before-instance",
30 | "variables-before-functions"
31 | ],
32 | "no-any": true,
33 | "no-arg": true,
34 | "no-bitwise": true,
35 | "no-console": [
36 | true,
37 | "log",
38 | "error",
39 | "debug",
40 | "info",
41 | "time",
42 | "timeEnd",
43 | "trace"
44 | ],
45 | "no-consecutive-blank-lines": true,
46 | "no-construct": true,
47 | "no-debugger": true,
48 | "no-duplicate-variable": true,
49 | "no-empty": true,
50 | "no-eval": true,
51 | "no-shadowed-variable": true,
52 | "no-string-literal": true,
53 | "no-switch-case-fall-through": true,
54 | "no-trailing-whitespace": false,
55 | "no-unused-expression": true,
56 | "no-use-before-declare": true,
57 | "one-line": [
58 | true,
59 | "check-catch",
60 | "check-else",
61 | "check-open-brace",
62 | "check-whitespace"
63 | ],
64 | "quotemark": [true, "single", "jsx-double"],
65 | "radix": true,
66 | "semicolon": [true, "always"],
67 | "switch-default": true,
68 |
69 | "trailing-comma": false,
70 |
71 | "triple-equals": [ true, "allow-null-check" ],
72 | "typedef": [
73 | true,
74 | "parameter",
75 | "property-declaration"
76 | ],
77 | "typedef-whitespace": [
78 | true,
79 | {
80 | "call-signature": "nospace",
81 | "index-signature": "nospace",
82 | "parameter": "nospace",
83 | "property-declaration": "nospace",
84 | "variable-declaration": "nospace"
85 | }
86 | ],
87 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
88 | "whitespace": [
89 | true,
90 | "check-branch",
91 | "check-decl",
92 | "check-module",
93 | "check-operator",
94 | "check-separator",
95 | "check-type",
96 | "check-typecast"
97 | ]
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/examples/basic/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | .DS_Store
4 | npm-debug.log*
5 |
--------------------------------------------------------------------------------
/examples/basic/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React high order component to drive payment request widget on react applications 💳.
7 |
8 |
9 |
10 | ## Standalone Demo
11 |
12 | This component accept a standalone configuration and will log the result on the console.
13 |
14 | ## Run the demo
15 |
16 | Install:
17 |
18 | ```bash
19 | npm install
20 | ```
21 |
22 | Run
23 |
24 | ```bash
25 | npm start
26 | ```
27 |
28 | Open your browser at [http://localhost:8080/](http://localhost:8080/).
29 |
30 |
31 | ## License
32 |
33 | See the [LICENSE](../../LICENSE.md) file for license rights and limitations (MIT).
34 |
--------------------------------------------------------------------------------
/examples/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-payment-request-api-example-basic",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@types/jest": "^21.1.4",
7 | "@types/node": "^8.0.46",
8 | "@types/react": "^16.4.14",
9 | "@types/react-dom": "^16.0.7",
10 | "react": "^16.5.2",
11 | "react-dom": "^16.5.2",
12 | "react-payment-request-api": "^3.0.0"
13 | },
14 | "devDependencies": {
15 | "react-scripts-ts": "2.17.0",
16 | "typescript": "^3.0.3"
17 | },
18 | "scripts": {
19 | "start": "react-scripts-ts start",
20 | "build": "react-scripts-ts build",
21 | "eject": "react-scripts-ts eject"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/examples/basic/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | React - Payment request API
10 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/basic/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/4b7c14feb9ac5b79bdd17aa38a89dce503ceac01/examples/basic/public/logo.png
--------------------------------------------------------------------------------
/examples/basic/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Payment Request",
3 | "name": "React Payment Request API",
4 | "icons": [
5 | {
6 | "src": "logo.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/basic/src/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import paymentRequest, { PaymentRequestInterface } from 'react-payment-request-api';
3 |
4 | export interface OwnProps {
5 | style: object;
6 | }
7 |
8 | const Button: React.StatelessComponent = ({
9 | show, isSupported, style,
10 | }) => isSupported
11 | ? Pay now!
12 | : Payment request not supported ;
13 |
14 | export default paymentRequest()(Button);
15 |
--------------------------------------------------------------------------------
/examples/basic/src/config.ts:
--------------------------------------------------------------------------------
1 | import { PaymentRequestParams } from 'react-payment-request-api';
2 |
3 | const details: PaymentDetailsInit = {
4 | displayItems: [{
5 | label: 'Original donation amount',
6 | amount: { currency: 'USD', value: '65.00' },
7 | }, {
8 | label: 'Friends and family discount',
9 | amount: { currency: 'USD', value: '-10.00' },
10 | }, {
11 | label: 'Delivery tax',
12 | pending: true,
13 | amount: { currency: 'USD', value: '10.00' },
14 | }],
15 | total: {
16 | label: 'Total due',
17 | amount: { currency: 'USD', value : '55.00' },
18 | },
19 | };
20 |
21 | const getConfig = () => ({
22 | methodData: [{
23 | supportedMethods: ['basic-card'],
24 | data: {
25 | supportedNetworks: ['visa', 'mastercard', 'diners'],
26 | },
27 | }],
28 | details: details,
29 | options: {
30 | requestShipping: true,
31 | requestPayerEmail: true,
32 | requestPayerPhone: true,
33 | },
34 | onShowSuccess: (result, resolve, reject): void => {
35 | /* tslint:disable-next-line:no-console */
36 | console.log('Result:', result);
37 | // make the payment
38 | setTimeout(resolve, 2000);
39 | },
40 | /* tslint:disable-next-line:no-console */
41 | onShowFail: (error) => console.log('Error', error),
42 | onShippingAddressChange: (request, resolve, reject): void => {
43 | /* tslint:disable-next-line:no-console */
44 | console.log('ShippingAddress:', request.shippingAddress);
45 | // recalculate details
46 | details.shippingOptions = [{
47 | id: 'all',
48 | label: 'Wherever you want for free',
49 | amount: { currency: 'USD', value: '0.00' },
50 | selected: true
51 | }];
52 | details.displayItems![2] = {
53 | label: 'Tax',
54 | pending: false,
55 | amount: { currency: 'USD', value: '8.00' },
56 | };
57 | resolve(details);
58 | },
59 | onShippingOptionChange: (request, resolve, reject): void => {
60 | resolve(details);
61 | },
62 | }) as PaymentRequestParams;
63 |
64 | export default getConfig;
65 |
--------------------------------------------------------------------------------
/examples/basic/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 |
4 | import Button from './button';
5 | import getConfig from './config';
6 | import styles from './styles';
7 |
8 | const App = () => (
9 |
10 |
11 |
React Payment Request API
12 |
13 | High order component to drive
14 | Payment Request
15 | widget on react applications 💳
16 |
17 |
This component accept a standalone configuration and will log the result on the console.
18 |
19 |
20 |
21 |
22 | );
23 |
24 | ReactDOM.render( , document.getElementById('app'));
25 |
--------------------------------------------------------------------------------
/examples/basic/src/styles.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default {
4 | container: {
5 | display: 'flex',
6 | flexDirection: 'column',
7 | padding: '1rem',
8 | alignItems: 'center',
9 | } as React.CSSProperties,
10 | a: {
11 | color: '#48b5f2',
12 | },
13 | h1: {
14 | fontSize: '1.7rem',
15 | },
16 | h2: {
17 | color: '#0f4b6d',
18 | fontSize: '1.2rem',
19 | },
20 | logo: {
21 | backgroundImage: 'url(https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/master/logo.png)',
22 | backgroundSize: 'cover',
23 | backgroundPosition: 'center',
24 | width: '10rem',
25 | height: '10rem',
26 | minWidth: '10rem',
27 | minHeight: '10rem',
28 | borderRadius: '0.1875rem',
29 | },
30 | content: {
31 | display: 'flex',
32 | flexGrow: 1,
33 | flexDirection: 'column',
34 | justifyContent: 'center',
35 | } as React.CSSProperties,
36 | button: {
37 | backgroundColor: '#48b5f2',
38 | border: '1px solid #84acc3',
39 | color: '#0f4b6d',
40 | boxShadow: '0 0 1px #fff inset',
41 | borderRadius: '1rem',
42 | padding: '1rem 2rem',
43 | font: '3rem Calibri, Arial, sans-serif',
44 | textShadow: '1px 1px 0 rgba(255,255,255,0.4)',
45 | },
46 | };
47 |
--------------------------------------------------------------------------------
/examples/basic/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "build/dist",
4 | "module": "commonjs",
5 | "target": "es5",
6 | "lib": ["es6", "dom"],
7 | "sourceMap": true,
8 | "allowJs": true,
9 | "jsx": "react",
10 | "moduleResolution": "node",
11 | "rootDir": "src",
12 | "forceConsistentCasingInFileNames": true,
13 | "noImplicitReturns": true,
14 | "noImplicitThis": true,
15 | "noImplicitAny": true,
16 | "skipLibCheck": true,
17 | "strictNullChecks": true,
18 | "suppressImplicitAnyIndexErrors": true,
19 | "noUnusedLocals": true
20 | },
21 | "exclude": [
22 | "node_modules",
23 | "build",
24 | "scripts",
25 | "acceptance-tests",
26 | "webpack",
27 | "jest",
28 | "src/setupTests.ts"
29 | ],
30 | "types": [
31 | "typePatches"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/examples/basic/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | }
--------------------------------------------------------------------------------
/examples/basic/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint-react"],
3 | "rules": {
4 | "align": [
5 | true,
6 | "parameters",
7 | "arguments",
8 | "statements"
9 | ],
10 | "ban": false,
11 | "class-name": true,
12 | "comment-format": [
13 | true,
14 | "check-space"
15 | ],
16 | "curly": true,
17 | "eofline": false,
18 | "forin": true,
19 | "indent": [ true, "spaces" ],
20 | "interface-name": [true, "never-prefix"],
21 | "jsdoc-format": true,
22 | "jsx-no-lambda": false,
23 | "jsx-no-multiline-js": false,
24 | "label-position": true,
25 | "max-line-length": [ true, 120 ],
26 | "member-ordering": [
27 | true,
28 | "public-before-private",
29 | "static-before-instance",
30 | "variables-before-functions"
31 | ],
32 | "no-any": true,
33 | "no-arg": true,
34 | "no-bitwise": true,
35 | "no-console": [
36 | true,
37 | "log",
38 | "error",
39 | "debug",
40 | "info",
41 | "time",
42 | "timeEnd",
43 | "trace"
44 | ],
45 | "no-consecutive-blank-lines": true,
46 | "no-construct": true,
47 | "no-debugger": true,
48 | "no-duplicate-variable": true,
49 | "no-empty": true,
50 | "no-eval": true,
51 | "no-shadowed-variable": true,
52 | "no-string-literal": true,
53 | "no-switch-case-fall-through": true,
54 | "no-trailing-whitespace": false,
55 | "no-unused-expression": true,
56 | "no-use-before-declare": true,
57 | "one-line": [
58 | true,
59 | "check-catch",
60 | "check-else",
61 | "check-open-brace",
62 | "check-whitespace"
63 | ],
64 | "quotemark": [true, "single", "jsx-double"],
65 | "radix": true,
66 | "semicolon": [true, "always"],
67 | "switch-default": true,
68 |
69 | "trailing-comma": false,
70 |
71 | "triple-equals": [ true, "allow-null-check" ],
72 | "typedef": [
73 | true,
74 | "parameter",
75 | "property-declaration"
76 | ],
77 | "typedef-whitespace": [
78 | true,
79 | {
80 | "call-signature": "nospace",
81 | "index-signature": "nospace",
82 | "parameter": "nospace",
83 | "property-declaration": "nospace",
84 | "variable-declaration": "nospace"
85 | }
86 | ],
87 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
88 | "whitespace": [
89 | true,
90 | "check-branch",
91 | "check-decl",
92 | "check-module",
93 | "check-operator",
94 | "check-separator",
95 | "check-type",
96 | "check-typecast"
97 | ]
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/examples/redux/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | .DS_Store
4 | npm-debug.log*
5 |
--------------------------------------------------------------------------------
/examples/redux/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React high order component to drive payment request widget on react applications 💳.
7 |
8 |
9 |
10 | ## Redux Demo
11 |
12 | This component generate the configuration from a smart component connected to redux.
13 |
14 | It will also dispatch a redux action on success.
15 |
16 | ## Run the demo
17 |
18 | Install:
19 |
20 | ```bash
21 | npm install
22 | ```
23 |
24 | Run
25 |
26 | ```bash
27 | npm start
28 | ```
29 |
30 | Open your browser at [http://localhost:8080/](http://localhost:8080/).
31 |
32 |
33 | ## License
34 |
35 | See the [LICENSE](../../LICENSE.md) file for license rights and limitations (MIT).
36 |
--------------------------------------------------------------------------------
/examples/redux/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-payment-request-api-example-redux",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@types/jest": "^21.1.4",
7 | "@types/node": "^8.0.46",
8 | "@types/react": "^16.4.14",
9 | "@types/react-dom": "^16.0.7",
10 | "react": "^16.5.2",
11 | "react-dom": "^16.5.2",
12 | "react-payment-request-api": "^3.0.0",
13 | "react-redux": "^5.0.6",
14 | "redux": "^3.7.2",
15 | "redux-thunk": "^2.2.0"
16 | },
17 | "devDependencies": {
18 | "@types/react-redux": "^4.4.43",
19 | "@types/redux": "^3.6.0",
20 | "@types/redux-actions": "^1.2.6",
21 | "react-scripts-ts": "2.17.0",
22 | "typescript": "^3.0.3"
23 | },
24 | "scripts": {
25 | "start": "react-scripts-ts start",
26 | "build": "react-scripts-ts build",
27 | "eject": "react-scripts-ts eject"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/redux/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | React - Payment request API
10 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/redux/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/4b7c14feb9ac5b79bdd17aa38a89dce503ceac01/examples/redux/public/logo.png
--------------------------------------------------------------------------------
/examples/redux/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Payment Request",
3 | "name": "React Payment Request API",
4 | "icons": [
5 | {
6 | "src": "logo.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/redux/src/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import paymentRequest, { PaymentRequestInterface } from 'react-payment-request-api';
3 | import { connect } from 'react-redux';
4 |
5 | import styles from './styles';
6 |
7 | export interface OwnProps {
8 | style: React.CSSProperties;
9 | }
10 |
11 | export interface StateProps {
12 | payed: boolean;
13 | }
14 |
15 | const Button: React.StatelessComponent = ({
16 | show, isSupported, style, payed,
17 | }) => isSupported
18 | ? (
19 |
20 | {payed ? 'Payed' : 'Pay now'}
21 |
22 | )
23 | : Payment request not supported ;
24 |
25 | const ConnectedButton = connect((state) => ({
26 | payed: state.payed,
27 | }))(Button);
28 |
29 | export default paymentRequest()(ConnectedButton);
30 |
--------------------------------------------------------------------------------
/examples/redux/src/config.tsx:
--------------------------------------------------------------------------------
1 | import { PaymentRequestParams } from 'react-payment-request-api';
2 |
3 | const details: PaymentDetailsInit = {
4 | displayItems: [{
5 | label: 'Original donation amount',
6 | amount: { currency: 'USD', value: '65.00' },
7 | }, {
8 | label: 'Friends and family discount',
9 | amount: { currency: 'USD', value: '-10.00' },
10 | }, {
11 | label: 'Delivery tax',
12 | pending: true,
13 | amount: { currency: 'USD', value: '10.00' },
14 | }],
15 | total: {
16 | label: 'Total due',
17 | amount: { currency: 'USD', value : '55.00' },
18 | },
19 | };
20 |
21 | const getConfig = (supportedPaymentCards: string[], onShowSuccess: () => void) => ({
22 | methodData: [{
23 | supportedMethods: ['basic-card'],
24 | data: {
25 | supportedNetworks: supportedPaymentCards,
26 | },
27 | }],
28 | details: details,
29 | options: {
30 | requestShipping: true,
31 | requestPayerEmail: true,
32 | requestPayerPhone: true,
33 | },
34 | onShowSuccess: (result, resolve, reject): void => {
35 | /* tslint:disable-next-line:no-console */
36 | console.log('Result:', result);
37 | // make the payment
38 | setTimeout(() => { onShowSuccess(); resolve(); }, 2000);
39 | },
40 | /* tslint:disable-next-line:no-console */
41 | onShowFail: (error) => console.log('Error', error),
42 | onShippingAddressChange: (request, resolve, reject): void => {
43 | /* tslint:disable-next-line:no-console */
44 | console.log('ShippingAddress:', request.shippingAddress);
45 | // recalculate details
46 | details.shippingOptions = [{
47 | id: 'all',
48 | label: 'Wherever you want for free',
49 | amount: { currency: 'USD', value: '0.00' },
50 | selected: true
51 | }];
52 | details.displayItems![2] = {
53 | label: 'Tax',
54 | pending: false,
55 | amount: { currency: 'USD', value: '8.00' },
56 | };
57 | resolve(details);
58 | },
59 | onShippingOptionChange: (request, resolve, reject): void => {
60 | resolve(details);
61 | },
62 | }) as PaymentRequestParams;
63 |
64 | export default getConfig;
65 |
--------------------------------------------------------------------------------
/examples/redux/src/global.d.ts:
--------------------------------------------------------------------------------
1 | interface Window {
2 | __REDUX_DEVTOOLS_EXTENSION__?(): any; // tslint:disable-line:no-any
3 | }
4 |
--------------------------------------------------------------------------------
/examples/redux/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { createStore, applyMiddleware } from 'redux';
5 | import thunk from 'redux-thunk';
6 |
7 | import reducers from './reducers';
8 | import Wrapper from './wrapper';
9 | import styles from './styles';
10 |
11 | const store = createStore(
12 | reducers,
13 | window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
14 | applyMiddleware(thunk)
15 | );
16 |
17 | const App = () => (
18 |
19 |
20 |
21 |
React Payment Request API
22 |
23 | High order component to drive
24 | Payment Request
25 | widget on react applications 💳
26 |
27 |
28 | This component generate the configuration from a smart component connected to redux.
29 |
30 | It will also dispatch a redux action on success.
31 |
32 |
33 |
34 |
35 |
36 |
37 | );
38 |
39 | ReactDOM.render( , document.getElementById('app'));
40 |
--------------------------------------------------------------------------------
/examples/redux/src/reducers.ts:
--------------------------------------------------------------------------------
1 | import { Action } from 'redux-actions';
2 |
3 | export interface State {
4 | supportedPaymentCards: string[];
5 | }
6 |
7 | const initialState = {
8 | supportedPaymentCards: ['visa'],
9 | payed: false,
10 | };
11 |
12 | const reducers = (previousState: State = initialState, action: Action) => { // tslint:disable-line:no-any
13 | switch (action.type) {
14 | case 'PROCESSING_PAYMENT':
15 | return ({ ...previousState, payed: true });
16 | default:
17 | return ({ ...previousState });
18 | }
19 | };
20 |
21 | export default reducers;
22 |
--------------------------------------------------------------------------------
/examples/redux/src/styles.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default {
4 | container: {
5 | display: 'flex',
6 | flexDirection: 'column',
7 | padding: '1rem',
8 | alignItems: 'center',
9 | } as React.CSSProperties,
10 | a: {
11 | color: '#48b5f2',
12 | },
13 | h1: {
14 | fontSize: '1.7rem',
15 | },
16 | h2: {
17 | color: '#0f4b6d',
18 | fontSize: '1.2rem',
19 | },
20 | logo: {
21 | backgroundImage: 'url(https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/master/logo.png)',
22 | backgroundSize: 'cover',
23 | backgroundPosition: 'center',
24 | width: '10rem',
25 | height: '10rem',
26 | minWidth: '10rem',
27 | minHeight: '10rem',
28 | borderRadius: '0.1875rem',
29 | },
30 | content: {
31 | display: 'flex',
32 | flexGrow: 1,
33 | flexDirection: 'column',
34 | justifyContent: 'center',
35 | } as React.CSSProperties,
36 | button: {
37 | boxShadow: '0 0 1px #fff inset',
38 | borderRadius: '1rem',
39 | padding: '1rem 2rem',
40 | font: '3rem Calibri, Arial, sans-serif',
41 | textShadow: '1px 1px 0 rgba(255,255,255,0.4)',
42 | },
43 | toPay: {
44 | backgroundColor: '#48b5f2',
45 | border: '1px solid #84acc3',
46 | color: '#0f4b6d',
47 | },
48 | payed: {
49 | backgroundColor: '#48f28c',
50 | border: '1px solid #84c38c',
51 | color: '#0f6d1c',
52 | },
53 | };
54 |
--------------------------------------------------------------------------------
/examples/redux/src/wrapper.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { connect } from 'react-redux';
3 | import { Dispatch } from 'redux';
4 |
5 | import Button from './button';
6 | import getConfig from './config';
7 | import { State } from './reducers';
8 |
9 | interface StateProps {
10 | supportedPaymentCards: string[];
11 | }
12 |
13 | interface DispatchProps {
14 | onShowSuccess: () => void;
15 | }
16 |
17 | interface OwnProps {
18 | style: React.CSSProperties;
19 | }
20 |
21 | const Wrapper: React.StatelessComponent = ({
22 | style, supportedPaymentCards, onShowSuccess,
23 | }) => (
24 |
28 | );
29 |
30 | const mapState2Props = (state: State): StateProps => ({
31 | supportedPaymentCards: state.supportedPaymentCards,
32 | });
33 |
34 | const mapDispatch2Props = (dispatch: Dispatch): DispatchProps => ({
35 | onShowSuccess: () => dispatch({ type: 'PROCESSING_PAYMENT' }),
36 | });
37 |
38 | export default connect(mapState2Props, mapDispatch2Props)(Wrapper);
39 |
--------------------------------------------------------------------------------
/examples/redux/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "build/dist",
4 | "module": "commonjs",
5 | "target": "es5",
6 | "lib": ["es6", "dom"],
7 | "sourceMap": true,
8 | "allowJs": true,
9 | "jsx": "react",
10 | "moduleResolution": "node",
11 | "rootDir": "src",
12 | "forceConsistentCasingInFileNames": true,
13 | "noImplicitReturns": true,
14 | "noImplicitThis": true,
15 | "noImplicitAny": true,
16 | "skipLibCheck": true,
17 | "strictNullChecks": true,
18 | "suppressImplicitAnyIndexErrors": true,
19 | "noUnusedLocals": true
20 | },
21 | "exclude": [
22 | "node_modules",
23 | "build",
24 | "scripts",
25 | "acceptance-tests",
26 | "webpack",
27 | "jest",
28 | "src/setupTests.ts"
29 | ],
30 | "types": [
31 | "typePatches"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/examples/redux/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | }
--------------------------------------------------------------------------------
/examples/redux/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint-react"],
3 | "rules": {
4 | "align": [
5 | true,
6 | "parameters",
7 | "arguments",
8 | "statements"
9 | ],
10 | "ban": false,
11 | "class-name": true,
12 | "comment-format": [
13 | true,
14 | "check-space"
15 | ],
16 | "curly": true,
17 | "eofline": false,
18 | "forin": true,
19 | "indent": [ true, "spaces" ],
20 | "interface-name": [true, "never-prefix"],
21 | "jsdoc-format": true,
22 | "jsx-no-lambda": false,
23 | "jsx-no-multiline-js": false,
24 | "label-position": true,
25 | "max-line-length": [ true, 120 ],
26 | "member-ordering": [
27 | true,
28 | "public-before-private",
29 | "static-before-instance",
30 | "variables-before-functions"
31 | ],
32 | "no-any": true,
33 | "no-arg": true,
34 | "no-bitwise": true,
35 | "no-console": [
36 | true,
37 | "log",
38 | "error",
39 | "debug",
40 | "info",
41 | "time",
42 | "timeEnd",
43 | "trace"
44 | ],
45 | "no-consecutive-blank-lines": true,
46 | "no-construct": true,
47 | "no-debugger": true,
48 | "no-duplicate-variable": true,
49 | "no-empty": true,
50 | "no-eval": true,
51 | "no-shadowed-variable": true,
52 | "no-string-literal": true,
53 | "no-switch-case-fall-through": true,
54 | "no-trailing-whitespace": false,
55 | "no-unused-expression": true,
56 | "no-use-before-declare": true,
57 | "one-line": [
58 | true,
59 | "check-catch",
60 | "check-else",
61 | "check-open-brace",
62 | "check-whitespace"
63 | ],
64 | "quotemark": [true, "single", "jsx-double"],
65 | "radix": true,
66 | "semicolon": [true, "always"],
67 | "switch-default": true,
68 |
69 | "trailing-comma": false,
70 |
71 | "triple-equals": [ true, "allow-null-check" ],
72 | "typedef": [
73 | true,
74 | "parameter",
75 | "property-declaration"
76 | ],
77 | "typedef-whitespace": [
78 | true,
79 | {
80 | "call-signature": "nospace",
81 | "index-signature": "nospace",
82 | "parameter": "nospace",
83 | "property-declaration": "nospace",
84 | "variable-declaration": "nospace"
85 | }
86 | ],
87 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
88 | "whitespace": [
89 | true,
90 | "check-branch",
91 | "check-decl",
92 | "check-module",
93 | "check-operator",
94 | "check-separator",
95 | "check-type",
96 | "check-typecast"
97 | ]
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/jest.json:
--------------------------------------------------------------------------------
1 | {
2 | "transform": {
3 | ".(ts|tsx)": "ts-jest/preprocessor.js"
4 | },
5 | "moduleFileExtensions": [
6 | "ts",
7 | "tsx",
8 | "js"
9 | ],
10 | "testRegex": "./src/.*\\.test\\.(ts|tsx|js)$",
11 | "collectCoverage": true,
12 | "collectCoverageFrom": ["src/paymentRequest.tsx", "src/normalizeInstrumentations.ts"],
13 | "setupTestFrameworkScriptFile": "./enzyme-setup.js"
14 | }
15 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcolanaro/react-payment-request-api/4b7c14feb9ac5b79bdd17aa38a89dce503ceac01/logo.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-payment-request-api",
3 | "version": "3.1.0",
4 | "description": "React high order component that expose the payment request api",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "scripts": {
8 | "clean": "rm -rf ./lib && rm -rf ./dist",
9 | "build:lib": "tsc",
10 | "build:dist": "rollup -c",
11 | "build": "npm run build:lib && npm run build:dist",
12 | "lint": "tslint -c ./tslint.json './src/**/*.{ts,tsx}'",
13 | "test": "jest --config jest.json",
14 | "test:watch": "jest --config jest.json --watch",
15 | "prepublish": "npm run clean && npm run lint && npm run test && npm run build"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/marcolanaro/react-payment-request-api.git"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/marcolanaro/react-payment-request-api/issues"
23 | },
24 | "homepage": "https://github.com/marcolanaro/react-payment-request-api",
25 | "keywords": [
26 | "react",
27 | "component",
28 | "payment-request",
29 | "android-pay",
30 | "high-order",
31 | "typescript"
32 | ],
33 | "author": "Marco Lanaro (https://github.com/marcolanaro)",
34 | "license": "MIT",
35 | "devDependencies": {
36 | "@types/enzyme": "^3.1.14",
37 | "@types/jest": "^23.3.2",
38 | "@types/react": "^16.4.14",
39 | "@types/react-dom": "^16.0.7",
40 | "enzyme": "^3.6.0",
41 | "enzyme-adapter-react-16": "^1.5.0",
42 | "jest": "^23.6.0",
43 | "pre-commit": "^1.2.2",
44 | "react-test-renderer": "^16.5.2",
45 | "rollup": "^0.50.0",
46 | "rollup-plugin-typescript2": "^0.7.0",
47 | "rollup-plugin-uglify": "^2.0.1",
48 | "source-map-loader": "^0.2.4",
49 | "ts-jest": "^23.10.1",
50 | "ts-loader": "^5.2.1",
51 | "tslint": "^5.11.0",
52 | "tslint-eslint-rules": "^5.4.0",
53 | "tslint-microsoft-contrib": "^5.2.1",
54 | "tslint-react": "^3.6.0",
55 | "typescript": "^3.0.3"
56 | },
57 | "dependencies": {
58 | "react": "^16.5.2",
59 | "react-dom": "^16.5.2"
60 | },
61 | "pre-commit": [
62 | "lint",
63 | "build"
64 | ]
65 | }
66 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from 'rollup-plugin-typescript2';
2 | import uglify from 'rollup-plugin-uglify';
3 |
4 | export default {
5 | input: './src/index.ts',
6 | name: 'react-payment-request-api',
7 | output: [{ file: 'dist/react-payment-request-api.min.js', format: 'umd' }],
8 | plugins: [
9 | typescript(),
10 | uglify()
11 | ],
12 | exports: 'named',
13 | external: ['react', 'react-dom'],
14 | globals: {
15 | react: 'React',
16 | 'react-dom': 'ReactDOM',
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import paymentRequest from './paymentRequest';
2 |
3 | export { PaymentRequestParams, PaymentRequestInterface } from './types';
4 | export default paymentRequest;
5 |
--------------------------------------------------------------------------------
/src/paymentRequest.fixture.ts:
--------------------------------------------------------------------------------
1 | import { PaymentRequestParams } from './index';
2 |
3 | const details: PaymentDetailsInit = {
4 | total: {
5 | label: 'Total due',
6 | amount: { currency: 'USD', value : '22.15' },
7 | },
8 | };
9 |
10 | const getConfig = (onShowFail?: jest.Mock<{}>, removeOptions?: boolean) => ({
11 | methodData: [{
12 | supportedMethods: ['basic-card'],
13 | data: {
14 | supportedNetworks: ['visa'],
15 | },
16 | }],
17 | details: details,
18 | options: removeOptions ? undefined : {
19 | requestShipping: true,
20 | },
21 | onShowSuccess: (result, resolve, reject): void => {
22 | resolve();
23 | },
24 | onShowFail,
25 | onShippingAddressChange: (request, resolve, reject): void => {
26 | resolve(details);
27 | },
28 | onShippingOptionChange: (request, resolve, reject): void => {
29 | resolve(details);
30 | },
31 | // tslint:disable-next-line:no-any
32 | onMerchantValidation: (event: any): void => {
33 | event.complete(Promise.resolve(event.validationURL));
34 | },
35 | }) as PaymentRequestParams;
36 |
37 | export default getConfig;
38 |
--------------------------------------------------------------------------------
/src/paymentRequest.test.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { shallow } from 'enzyme';
3 |
4 | import paymentRequest, { PaymentRequestParams, PaymentRequestInterface } from './index';
5 | import getConfig from './paymentRequest.fixture';
6 |
7 | declare var global: any; // tslint:disable-line:no-any
8 |
9 | const generator = (removeOptions: boolean = false, showMethod: string = 'resolve') => {
10 | const complete = jest.fn();
11 | const showResponse = showMethod === 'resolve' ? { complete } : 'error';
12 | const show = jest.fn().mockImplementation(() => Promise[showMethod](showResponse));
13 | const abort = jest.fn();
14 | const addEventListener = jest.fn().mockImplementation((event: string) => {}); // tslint:disable-line:no-empty
15 | const onShowFail = jest.fn();
16 | const PaymentRequest = jest.fn().mockImplementation(() => ({ // tslint:disable-line:no-any
17 | show,
18 | abort,
19 | addEventListener,
20 | }));
21 |
22 | global.window.PaymentRequest = PaymentRequest;
23 |
24 | const UIComponent: React.StatelessComponent = () =>
;
25 | const PaymentComponent = paymentRequest<{}>()(UIComponent);
26 | const wrapper = shallow( );
27 | return {
28 | complete,
29 | show,
30 | abort,
31 | addEventListener,
32 | onShowFail,
33 | PaymentRequest,
34 | UIComponent,
35 | PaymentComponent,
36 | wrapper,
37 | };
38 | };
39 |
40 | describe('PaymentRequest', () => {
41 | describe('given an environment with no support for the API', () => {
42 | const UIComponent = () =>
;
43 | const PaymentComponent = paymentRequest<{}>()(UIComponent);
44 | const config = {} as PaymentRequestParams;
45 | const wrapper = shallow( );
46 |
47 | it('should render the UI component', () => {
48 | expect(wrapper.find(UIComponent).length).toBe(1);
49 | });
50 |
51 | it('should pass to the UI component the custom props', () => {
52 | expect(wrapper.find(UIComponent).prop('data-test')).toBe(true);
53 | });
54 |
55 | it('should not pass to the UI component the config prop', () => {
56 | expect(wrapper.find(UIComponent).prop('config')).toBe(undefined);
57 | });
58 |
59 | it('should decorate the UI component with "isSupported" = false', () => {
60 | expect(wrapper.find(UIComponent).prop('isSupported')).toBe(false);
61 | });
62 |
63 | it('should not decorate the UI component with "show" prop', () => {
64 | expect(wrapper.find(UIComponent).prop('show')).toBe(undefined);
65 | });
66 |
67 | it('should not decorate the UI component with "abort" prop', () => {
68 | expect(wrapper.find(UIComponent).prop('abort')).toBe(undefined);
69 | });
70 | });
71 |
72 | describe('given an environment with support for the API', () => {
73 | it('should render the UI component', () => {
74 | const { wrapper, UIComponent } = generator();
75 | expect(wrapper.find(UIComponent).length).toBe(1);
76 | });
77 |
78 | it('should pass to the UI component the custom props', () => {
79 | const { wrapper, UIComponent } = generator();
80 | expect(wrapper.find(UIComponent).prop('data-test')).toBe(true);
81 | });
82 |
83 | it('should not pass to the UI component the config prop', () => {
84 | const { wrapper, UIComponent } = generator();
85 | expect(wrapper.find(UIComponent).prop('config')).toBe(undefined);
86 | });
87 |
88 | it('should decorate the UI component with "isSupported" = true', () => {
89 | const { wrapper, UIComponent } = generator();
90 | expect(wrapper.find(UIComponent).prop('isSupported')).toBe(true);
91 | });
92 |
93 | describe('when "show" prop is executed', () => {
94 | describe('PaymentRequest API', () => {
95 | it('should be executed once', () => {
96 | const { wrapper, UIComponent } = generator();
97 | wrapper.find(UIComponent).prop('show')();
98 | expect(PaymentRequest).toHaveBeenCalledTimes(1);
99 | });
100 |
101 | it('should be executed with config.methodData, config.details, config.options', () => {
102 | const { wrapper, UIComponent } = generator();
103 | wrapper.find(UIComponent).prop('show')();
104 | expect(PaymentRequest).toHaveBeenCalledWith(getConfig().methodData, getConfig().details, getConfig().options);
105 | });
106 |
107 | it('should force empty options if not provided', () => {
108 | const { wrapper, UIComponent } = generator(true);
109 | wrapper.find(UIComponent).prop('show')();
110 | expect(PaymentRequest).toHaveBeenCalledWith(getConfig().methodData, getConfig().details, {});
111 | });
112 | });
113 |
114 | describe('PaymentRequest.addEventListener API', () => {
115 | it('should be executed twice', () => {
116 | const { wrapper, UIComponent, addEventListener } = generator();
117 | wrapper.find(UIComponent).prop('show')();
118 | expect(addEventListener).toHaveBeenCalledTimes(3);
119 | });
120 |
121 | it('should add an event on shippingaddresschange', () => {
122 | const { wrapper, UIComponent, addEventListener } = generator();
123 | wrapper.find(UIComponent).prop('show')();
124 | expect(addEventListener).toHaveBeenCalledWith('shippingaddresschange', expect.any(Function));
125 | });
126 |
127 | it('should add an event on shippingoptionchange', () => {
128 | const { wrapper, UIComponent, addEventListener } = generator();
129 | wrapper.find(UIComponent).prop('show')();
130 | expect(addEventListener).toHaveBeenCalledWith('shippingoptionchange', expect.any(Function));
131 | });
132 |
133 | it('should add an event on onmerchantvalidation', () => {
134 | const { wrapper, UIComponent, addEventListener } = generator();
135 | wrapper.find(UIComponent).prop('show')();
136 | expect(addEventListener).toHaveBeenCalledWith('onmerchantvalidation', expect.any(Function));
137 | });
138 | });
139 |
140 | describe('PaymentRequest.show API', () => {
141 | it('should be executed once', () => {
142 | const { wrapper, UIComponent, show } = generator();
143 | wrapper.find(UIComponent).prop('show')();
144 | expect(show).toHaveBeenCalledTimes(1);
145 | });
146 |
147 | it('should be executed without params', () => {
148 | const { wrapper, UIComponent, show } = generator();
149 | wrapper.find(UIComponent).prop('show')();
150 | expect(show).toHaveBeenCalledWith();
151 | });
152 | });
153 | });
154 |
155 | describe('when PaymentRequest.show API is resolved', () => {
156 | describe('PaymentResponse.complete API', () => {
157 | it('should be executed once', () => {
158 | const { wrapper, UIComponent, complete } = generator();
159 | wrapper.find(UIComponent).prop('show')();
160 | return Promise.resolve().then(() =>
161 | Promise.resolve().then(() =>
162 | expect(complete).toHaveBeenCalledTimes(1)
163 | )
164 | );
165 | });
166 |
167 | it('should be executed with "success"', () => {
168 | const { wrapper, UIComponent, complete } = generator();
169 | wrapper.find(UIComponent).prop('show')();
170 | return Promise.resolve().then(() =>
171 | Promise.resolve().then(() =>
172 | expect(complete).toHaveBeenCalledWith('success')
173 | )
174 | );
175 | });
176 | });
177 |
178 | describe('config.onShowFail', () => {
179 | it('should not be executed', () => {
180 | const { wrapper, UIComponent, onShowFail } = generator();
181 | wrapper.find(UIComponent).prop('show')();
182 | return Promise.resolve().then(() =>
183 | Promise.resolve().then(() =>
184 | expect(onShowFail).toHaveBeenCalledTimes(0)
185 | )
186 | );
187 | });
188 | });
189 | });
190 |
191 | describe('when PaymentRequest.show API is rejected', () => {
192 | describe('PaymentResponse.complete API', () => {
193 | it('should not be executed', () => {
194 | const { wrapper, UIComponent, complete } = generator(false, 'reject');
195 | wrapper.find(UIComponent).prop('show')();
196 | return Promise.resolve().then(() =>
197 | Promise.resolve().then(() =>
198 | expect(complete).toHaveBeenCalledTimes(0)
199 | )
200 | );
201 | });
202 | });
203 |
204 | describe('config.onShowFail', () => {
205 | it('should be executed once', () => {
206 | const { wrapper, UIComponent, onShowFail } = generator(false, 'reject');
207 | wrapper.find(UIComponent).prop('show')();
208 | return Promise.resolve().then(() =>
209 | Promise.resolve().then(() =>
210 | expect(onShowFail).toHaveBeenCalledTimes(1)
211 | )
212 | );
213 | });
214 |
215 | it('should be executed with error', () => {
216 | const { wrapper, UIComponent, onShowFail } = generator(false, 'reject');
217 | wrapper.find(UIComponent).prop('show')();
218 | return Promise.resolve().then(() =>
219 | Promise.resolve().then(() =>
220 | expect(onShowFail).toHaveBeenCalledWith('error')
221 | )
222 | );
223 | });
224 | });
225 | });
226 |
227 | describe('when "abort" prop is executed after "show"', () => {
228 | describe('PaymentRequest.abort API', () => {
229 | it('should be executed once', () => {
230 | const { wrapper, UIComponent, abort } = generator();
231 | wrapper.find(UIComponent).prop('show')();
232 | wrapper.find(UIComponent).prop('abort')();
233 | expect(abort).toHaveBeenCalledTimes(1);
234 | });
235 |
236 | it('should be executed without params', () => {
237 | const { wrapper, UIComponent, abort } = generator();
238 | wrapper.find(UIComponent).prop('show')();
239 | wrapper.find(UIComponent).prop('abort')();
240 | expect(abort).toHaveBeenCalledWith();
241 | });
242 | });
243 | });
244 | });
245 | });
246 |
--------------------------------------------------------------------------------
/src/paymentRequest.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import {
4 | PaymentRequestParamsConfig,
5 | PaymentRequestInterface,
6 | PaymentRequestParams,
7 | Callback,
8 | Resolve,
9 | Reject,
10 | } from './types';
11 |
12 | let request: PaymentRequest;
13 |
14 | const hasSupport = () => !!(window as any).PaymentRequest; // tslint:disable-line:no-any
15 |
16 | const addEventListener = (requestListener: PaymentRequest, event: string, callback?: Callback) => {
17 | if (!!callback) {
18 | requestListener.addEventListener(
19 | event,
20 | (e: PaymentRequestUpdateEvent) => e.updateWith(
21 | new Promise((resolve: Resolve, reject: Reject) => callback(requestListener, resolve, reject))
22 | )
23 | );
24 | }
25 | };
26 |
27 | export const abort = () => request.abort();
28 |
29 | export const show = (params: PaymentRequestParams) => () => {
30 | request = new PaymentRequest(
31 | params.methodData,
32 | params.details,
33 | params.options || {}
34 | );
35 |
36 | addEventListener(request, 'shippingaddresschange', params.onShippingAddressChange);
37 | addEventListener(request, 'shippingoptionchange', params.onShippingOptionChange);
38 | addEventListener(request, 'onmerchantvalidation', params.onMerchantValidation);
39 |
40 | request.show()
41 | .then((paymentResponse) => {
42 | return new Promise((resolve: Resolve, reject: Reject) =>
43 | params.onShowSuccess(paymentResponse, resolve, reject))
44 | .then(() => paymentResponse.complete('success'))
45 | .catch(() => paymentResponse.complete('fail'));
46 | })
47 | .catch((err) => params.onShowFail(err));
48 | };
49 |
50 | const paymentRequest = () => (
51 | // tslint:disable-next-line:max-line-length no-any
52 | WrappedComponent: React.ClassType | React.SFC
53 | // tslint:disable-next-line:no-any
54 | ): React.ClassType => (
55 | class ExtendedComponent extends React.Component {
56 | render() {
57 | const { config, ...passedProps } = this.props as any; // tslint:disable-line:no-any
58 | const isSupported = hasSupport();
59 | const supportedProps = isSupported && config
60 | ? { isSupported, abort, show: show(config) }
61 | : { isSupported };
62 |
63 | return ;
64 | }
65 | }
66 | );
67 |
68 | export default paymentRequest;
69 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export type Resolve = (value?: {} | PromiseLike<{}>) => void;
2 | export type Reject = (reason?: any) => void; // tslint:disable-line:no-any
3 | export type Callback = (request: PaymentRequest, resolve: Resolve, reject: Reject) => void;
4 |
5 | export type PaymentRequestParams = {
6 | methodData: PaymentMethodData[];
7 | details: PaymentDetailsInit;
8 | options?: PaymentOptions;
9 | onShowSuccess: (paymentResponse: PaymentResponse, resolve: Resolve, reject: Reject) => void;
10 | onShowFail: (err: string) => void;
11 | onShippingAddressChange?: Callback;
12 | onShippingOptionChange?: Callback;
13 | onMerchantValidation?: Callback;
14 | };
15 |
16 | export interface PaymentRequestParamsConfig {
17 | config: PaymentRequestParams;
18 | }
19 |
20 | export interface PaymentRequestInterface {
21 | isSupported: boolean;
22 | show: () => void;
23 | abort: () => void;
24 | }
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "forceConsistentCasingInFileNames": true,
5 | "jsx": "react",
6 | "lib": ["es6", "dom"],
7 | "module": "commonjs",
8 | "moduleResolution": "node",
9 | "noImplicitReturns": true,
10 | "noImplicitThis": true,
11 | "noImplicitAny": true,
12 | "noUnusedLocals": true,
13 | "removeComments": true,
14 | "outDir": "./lib",
15 | "rootDir": "./src",
16 | "sourceMap": true,
17 | "strictNullChecks": true,
18 | "suppressImplicitAnyIndexErrors": true,
19 | "target": "es5",
20 | "types": ["jest"]
21 | },
22 | "exclude": [
23 | "examples",
24 | "node_modules",
25 | "lib",
26 | "dist",
27 | "**/*.test.*"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/tslint-microsoft-contrib",
4 | "node_modules/tslint-eslint-rules/dist/rules"
5 | ],
6 | "extends": ["tslint-react"],
7 | "rules": {
8 | "align": [
9 | true,
10 | "parameters",
11 | "statements"
12 | ],
13 | "ban": false,
14 | "class-name": true,
15 | "comment-format": [
16 | true,
17 | "check-space"
18 | ],
19 | "curly": true,
20 | "eofline": false,
21 | "forin": true,
22 | "indent": [ true, "spaces" ],
23 | "interface-name": [true, "never-prefix"],
24 | "jsdoc-format": true,
25 | "jsx-no-lambda": false,
26 | "jsx-no-multiline-js": false,
27 | "jsx-wrap-multiline": false,
28 | "label-position": true,
29 | "max-line-length": [ true, 120 ],
30 | "member-ordering": [
31 | true,
32 | "public-before-private",
33 | "static-before-instance",
34 | "variables-before-functions"
35 | ],
36 | "no-any": true,
37 | "no-arg": true,
38 | "no-bitwise": true,
39 | "no-console": [
40 | true,
41 | "log",
42 | "error",
43 | "debug",
44 | "info",
45 | "time",
46 | "timeEnd",
47 | "trace"
48 | ],
49 | "no-consecutive-blank-lines": [true, 1],
50 | "no-construct": true,
51 | "no-debugger": true,
52 | "no-duplicate-variable": true,
53 | "no-empty": true,
54 | "no-eval": true,
55 | "no-shadowed-variable": true,
56 | "no-string-literal": true,
57 | "no-switch-case-fall-through": false,
58 | "no-trailing-whitespace": false,
59 | "no-unused-expression": true,
60 |
61 | "no-use-before-declare": true,
62 | "one-line": [
63 | true,
64 | "check-catch",
65 | "check-else",
66 | "check-open-brace",
67 | "check-whitespace"
68 | ],
69 | "quotemark": [true, "single", "jsx-double"],
70 | "radix": true,
71 | "semicolon": [true, "always"],
72 | "switch-default": true,
73 |
74 | "triple-equals": [ true, "allow-null-check" ],
75 | "typedef": [
76 | true,
77 | "parameter",
78 | "property-declaration"
79 | ],
80 | "typedef-whitespace": [
81 | true,
82 | {
83 | "call-signature": "nospace",
84 | "index-signature": "nospace",
85 | "parameter": "nospace",
86 | "property-declaration": "nospace",
87 | "variable-declaration": "nospace"
88 | }
89 | ],
90 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
91 | "whitespace": [
92 | true,
93 | "check-branch",
94 | "check-decl",
95 | "check-module",
96 | "check-operator",
97 | "check-separator",
98 | "check-type",
99 | "check-typecast"
100 | ]
101 | }
102 | }
--------------------------------------------------------------------------------