Skip to content
This repository was archived by the owner on Mar 27, 2021. It is now read-only.

Commit 0cbd3e2

Browse files
authored
💳 react-stripe-elements (#1)
This is the v0.0.1 docs and API for react-stripe-elements.
1 parent 6e4b23d commit 0cbd3e2

20 files changed

+6161
-3
lines changed

‎.babelrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"presets": ["react", "es2015"],
3+
"plugins": ["transform-class-properties", "transform-object-rest-spread"]
4+
}

‎.eslintrc.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
extends:
3+
- stripe
4+
- plugin:flowtype/recommended
5+
parser: 'babel-eslint'
6+
plugins:
7+
- flowtype
8+
- jest
9+
env:
10+
jest/globals: true
11+
rules:
12+
react/jsx-filename-extension: 0
13+
no-duplicate-imports: 0 # doesn't support flow imports.
14+
no-console: 1 # disable this while undergoing lots of development.
15+
func-style: 2
16+
arrow-parens: 2
17+
consistent-return: 2
18+
prefer-arrow-callback:
19+
- 2
20+
- allowNamedFunctions: false
21+
allowUnboundThis: false
22+
flowtype/require-valid-file-annotation:
23+
- 2
24+
- 'always'
25+
- annotationStyle: 'line'
26+
no-unused-vars:
27+
- 2
28+
- ignoreRestSiblings: true

‎.flowconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[libs]
2+
src/decls/

‎README.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# react-stripe-elements
2+
3+
This project is a thin React wrapper around Stripe.js and Stripe Elements that allows you to
4+
use Elements in React without needing to manage Stripe state and the lifecycle of Elements.
5+
6+
The [Stripe.js / Stripe Elements API reference](https://stripe.com/docs/elements/reference)
7+
goes into more detail on the various customization options for Elements (e.g. styles, fonts).
8+
9+
## Project status
10+
11+
This project is currently in beta. The API presented below may undergo significant changes until
12+
we hit a stable release.
13+
14+
## Getting started
15+
16+
### Installation
17+
18+
First, install `react-stripe-elements`.
19+
20+
Using yarn:
21+
22+
yarn add react-stripe-elements
23+
24+
Using npm:
25+
26+
npm install --save react-stripe-elements
27+
28+
Then, load Stripe.js in your application:
29+
30+
```html
31+
<script src="https://js.stripe.com/v3/"></script>
32+
```
33+
34+
You’re good to go!
35+
36+
### The Stripe context (`StripeProvider`)
37+
38+
In order for your application to have access to [the Stripe object](https://stripe.com/docs/elements/reference#the-stripe-object),
39+
let's add `StripeProvider` to our root React App component:
40+
41+
```js
42+
// index.js
43+
import React from 'react';
44+
import {StripeProvider} from 'react-stripe-elements';
45+
46+
import MyStoreCheckout from './MyStoreCheckout';
47+
48+
const App = () => {
49+
return (
50+
<StripeProvider apiKey="pk_test_12345">
51+
<MyStoreCheckout />
52+
</StripeProvider>
53+
);
54+
};
55+
56+
ReactDOM.render(<App />, document.getElementById('root'));
57+
```
58+
59+
### Element groups (`Elements`)
60+
61+
Next, when you're building components for your checkout form, you'll want to wrap the `Elements` component around your `form`.
62+
This groups the set of Stripe Elements you're using together, so that we're able to pull data from groups of Elements when
63+
you're tokenizing.
64+
65+
```js
66+
// MyStoreCheckout.js
67+
import React from 'react';
68+
import {Elements} from 'react-stripe-elements';
69+
70+
import CheckoutForm from './CheckoutForm';
71+
72+
class MyStoreCheckout extends React.Component {
73+
render() {
74+
return (
75+
<Elements>
76+
<CheckoutForm />
77+
</Elements>
78+
);
79+
}
80+
}
81+
82+
export default MyStoreCheckout;
83+
```
84+
85+
### Setting up your payment form (`injectStripe`)
86+
87+
Use the `injectStripe` HOC to build your payment form components in the `Elements` tree. This HOC injects the `stripe`
88+
instance that manages your `Elements` groups. You can call `createToken` on the injected `stripe` instance to submit
89+
payment data to Stripe.
90+
91+
```js
92+
// CheckoutForm.js
93+
import React from 'react';
94+
import {injectStripe} from 'react-stripe-elements';
95+
96+
import AddressSection from './AddressSection';
97+
import CardSection from './CardSection';
98+
99+
class CheckoutForm extends React.Component {
100+
handleSubmit = (ev) => {
101+
// We don't want to let default form submission happen here, which would refresh the page.
102+
ev.preventDefault();
103+
104+
// Within the context of `Elements`, this call to createToken knows which Element to
105+
// tokenize, since there's only one in this group.
106+
this.props.stripe.createToken({owner: {name: 'Jenny Rosen'}}).then(({token}) => {
107+
console.log('Received Stripe token:', token);
108+
});
109+
110+
// However, this line of code will do the same thing:
111+
// this.props.stripe.createToken({type: 'card', owner: {name: 'Jenny Rosen'}});
112+
}
113+
114+
render() {
115+
return (
116+
<form onSubmit={this.handleSubmit}>
117+
<AddressSection />
118+
<CardSection />
119+
<button>Confirm order</button>
120+
</form>
121+
);
122+
}
123+
}
124+
125+
export default injectStripe(CheckoutForm);
126+
```
127+
128+
### Using individual `*Element`s
129+
130+
Now, you can use individual `*Element`s, such as `CardElement`, to build your form.
131+
132+
```js
133+
// CardSection.js
134+
import React from 'react';
135+
import {CardElement} from 'react-stripe-elements';
136+
137+
class CardSection extends React.Component {
138+
render() {
139+
return (
140+
<label>
141+
Card details
142+
<CardElement style={{base: {fontSize: '18px'}}} />
143+
</label>
144+
);
145+
}
146+
};
147+
148+
export default CardSection;
149+
```
150+
151+
## Component reference
152+
153+
### `<StripeProvider>`
154+
155+
All applications using react-stripe-elements must use the `<StripeProvider>` component, which sets up the Stripe context for a component tree.
156+
react-stripe-elements uses the provider pattern (which is also adopted by tools like react-redux and react-intl) to scope a Stripe context to a tree of components. This allows configuration like your API key to be provided at the root of a component tree. This context is then made available to the `<Elements>` component and individual `<*Element>` components that we provide.
157+
158+
An integration usually wraps the `<StripeProvider>` around the application’s root component. This way, your entire application has the configured Stripe context.
159+
160+
#### Props shape:
161+
162+
This component accepts all `options` that can be passed into `Stripe(apiKey, options)` as props.
163+
164+
```js
165+
type StripeProviderProps = {
166+
apiKey: string,
167+
};
168+
```
169+
170+
171+
### `<Elements>`
172+
173+
The `Elements` component wraps groups of Elements that belong together. In most cases, you want to wrap this around your checkout form.
174+
175+
#### Props shape:
176+
177+
This component accepts all `options` that can be passed into `stripe.elements(options)` as props.
178+
179+
```js
180+
type ElementsProps = {
181+
locale?: string,
182+
fonts?: Array<Object>,
183+
// The full specification for `elements()` options is here: https://stripe.com/docs/elements/reference#elements-options
184+
};
185+
```
186+
187+
### `<*Element>` components
188+
189+
These components display the UI for Elements, and must be used within `StripeProvider` and `Elements`.
190+
191+
#### Available components
192+
193+
(More to come!)
194+
195+
- `CardElement`
196+
- `CardNumberElement`
197+
- `CardExpiryElement`
198+
- `CardCVCElement`
199+
- `PostalCodeElement`
200+
201+
#### Props shape:
202+
203+
These components accept all `options` that can be passed into `elements.create(type, options)` as props.
204+
205+
```js
206+
type ElementProps = {
207+
elementRef?: (StripeElement) => void,
208+
209+
// For full documentation on the events and payloads below, see:
210+
// https://stripe.com/docs/elements/reference#element-on
211+
onChange?: (changeObject: Object) => void,
212+
onReady?: () => void,
213+
onFocus?: () => void,
214+
onBlur?: () => void,
215+
};
216+
```
217+
218+
### `injectStripe` HOC
219+
220+
Components that need to initiate Source or Token creations (e.g. a checkout form component) can access `stripe.createToken` via props of any component returned by the `injectStripe` HOC factory.
221+
222+
#### Example:
223+
224+
```js
225+
const StripeCheckoutForm = injectStripe(CheckoutForm);
226+
```
227+
228+
The following props will be available to this component:
229+
230+
```js
231+
type FactoryProps = {
232+
stripe: {
233+
createToken: (tokenParameters: {type?: string}) => Promise<{token?: Object, error?: Object}>,
234+
// and other functions available on the `stripe` object,
235+
// as officially documented here: https://stripe.com/docs/elements/reference#the-stripe-object
236+
},
237+
};
238+
```
239+
240+
241+
## Development
242+
243+
Run the demo:
244+
245+
yarn run demo
246+
247+
Run the tests:
248+
249+
yarn run test
250+
251+
Build:
252+
253+
yarn run build
254+
255+
Checks:
256+
257+
yarn run lint
258+
yarn run flow

‎demo/index.html

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<html>
2+
<head>
3+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.js"></script>
4+
<script src="https://js.stripe.com/v3/"></script>
5+
<style>
6+
body, html {
7+
background-color: #f6f9fc;
8+
font-size: 18px;
9+
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
10+
}
11+
12+
h1 {
13+
color: #32325d;
14+
font-weight: 400;
15+
line-height: 50px;
16+
font-size: 40px;
17+
margin: 20px 0;
18+
padding: 0;
19+
}
20+
21+
.Checkout {
22+
margin: 0 auto;
23+
max-width: 800px;
24+
box-sizing: border-box;
25+
padding: 0 5px;
26+
}
27+
28+
label {
29+
color: #6b7c93;
30+
font-weight: 300;
31+
letter-spacing: 0.025em;
32+
}
33+
34+
button {
35+
white-space: nowrap;
36+
border: 0;
37+
outline: 0;
38+
display: inline-block;
39+
height: 40px;
40+
line-height: 40px;
41+
padding: 0 14px;
42+
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
43+
color: #fff;
44+
border-radius: 4px;
45+
font-size: 15px;
46+
font-weight: 600;
47+
text-transform: uppercase;
48+
letter-spacing: 0.025em;
49+
background-color: #6772e5;
50+
text-decoration: none;
51+
-webkit-transition: all 150ms ease;
52+
transition: all 150ms ease;
53+
margin-top: 10px;
54+
}
55+
56+
form {
57+
margin-bottom: 40px;
58+
padding-bottom: 40px;
59+
border-bottom: 3px solid #e6ebf1;
60+
}
61+
62+
button:hover {
63+
color: #fff;
64+
cursor: pointer;
65+
background-color: #7795f8;
66+
transform: translateY(-1px);
67+
box-shadow: 0 7px 14px rgba(50, 50, 93, .10), 0 3px 6px rgba(0, 0, 0, .08);
68+
}
69+
70+
.StripeElement {
71+
display: block;
72+
margin: 10px 0 20px 0;
73+
max-width: 500px;
74+
padding: 10px 14px;
75+
box-shadow: rgba(50, 50, 93, 0.14902) 0px 1px 3px, rgba(0, 0, 0, 0.0196078) 0px 1px 0px;
76+
border-radius: 4px;
77+
background: white;
78+
}
79+
80+
.StripeElement--focus {
81+
box-shadow: rgba(50, 50, 93, 0.109804) 0px 4px 6px, rgba(0, 0, 0, 0.0784314) 0px 1px 3px;
82+
-webkit-transition: all 150ms ease;
83+
transition: all 150ms ease;
84+
}
85+
</style>
86+
</head>
87+
<body>
88+
<div class="App">
89+
</div>
90+
</body>
91+
</html>

0 commit comments

Comments
 (0)