react-braintree-fields
Advanced tools
Comparing version 0.1.3 to 0.2.0
58
demo.jsx
@@ -11,4 +11,20 @@ import { render } from 'react-dom'; | ||
super(props); | ||
['onCardTypeChange'].forEach((prop) => | ||
this[prop] = this[prop].bind(this) | ||
[ | ||
'onError', | ||
'getToken', | ||
'onCardTypeChange', | ||
].forEach(prop => (this[prop] = this[prop].bind(this))); | ||
} | ||
state = {} | ||
onError(error) { | ||
this.setState({ error }); | ||
} | ||
getToken() { | ||
this.tokenize().then( | ||
token => this.setState({ token, error: null }), | ||
).catch( | ||
error => this.setState({ token: null, error }), | ||
); | ||
@@ -18,3 +34,3 @@ } | ||
onCardTypeChange({ cards }) { | ||
this.setState({ card: (cards.length == 1) ? cards[0].type : '' }); | ||
this.setState({ card: (1 === cards.length) ? cards[0].type : '' }); | ||
} | ||
@@ -26,2 +42,12 @@ | ||
renderResult(title, obj) { | ||
if (!obj) { return null; } | ||
return ( | ||
<div> | ||
<b>{title}:</b> | ||
<pre>{JSON.stringify(obj, null, 4)}</pre> | ||
</div> | ||
); | ||
} | ||
render() { | ||
@@ -31,14 +57,18 @@ return ( | ||
<h1>Braintree Hosted Fields Demo</h1> | ||
{this.renderResult('Error', this.state.error)} | ||
{this.renderResult('Token', this.state.token)} | ||
<Braintree | ||
authorization='sandbox_g42y39zw_348pk9cgf3bgyw2b' | ||
onError={console.log} | ||
onError={this.onError} | ||
getTokenRef={t => (this.tokenize = t)} | ||
onCardTypeChange={this.onCardTypeChange} | ||
styles={{ | ||
'input': { | ||
input: { | ||
'font-size': '14px', | ||
'font-family': 'helvetica, tahoma, calibri, sans-serif', | ||
'color': '#7d6b6b', | ||
color: '#7d6b6b', | ||
}, | ||
':focus': { | ||
'color': 'black', | ||
color: 'black', | ||
}, | ||
@@ -49,6 +79,7 @@ }} | ||
Number: | ||
<Field type="number" | ||
onBlur={() => this.setState({ numberFocused: false })} | ||
onFocus={() => this.setState({ numberFocused: true })} | ||
className={this.state.numberFocused ? 'focused' : ''} | ||
<Field | ||
type="number" | ||
onBlur={() => this.setState({ numberFocused: false })} | ||
onFocus={() => this.setState({ numberFocused: true })} | ||
className={this.state.numberFocused ? 'focused' : ''} | ||
/> | ||
@@ -68,4 +99,7 @@ <p>Card type: {this.state.card}</p> | ||
</Braintree> | ||
<div className="footer"> | ||
<button onClick={this.getToken}>Get token</button> | ||
</div> | ||
</div> | ||
) | ||
); | ||
} | ||
@@ -72,0 +106,0 @@ } |
@@ -101,5 +101,21 @@ (function (global, factory) { | ||
}, { | ||
key: 'tokenize', | ||
value: function tokenize() { | ||
var _this2 = this; | ||
return new Promise(function (resolve, reject) { | ||
_this2.hostedFields.tokenize(function (err, payload) { | ||
if (err) { | ||
_this2.onError(err); | ||
reject(err); | ||
} else { | ||
resolve(payload); | ||
} | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: '_attach', | ||
value: function _attach() { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -112,9 +128,9 @@ delete this.isAttachable; | ||
}, function (err, hostedFields) { | ||
_this2.hostedFields = hostedFields; | ||
_this3.hostedFields = hostedFields; | ||
['blur', 'focus', 'empty', 'notEmpty', 'cardTypeChange', 'validityChange'].forEach(function (eventName) { | ||
hostedFields.on(eventName, function (ev) { | ||
return _this2.onFieldEvent('on' + cap(eventName), ev); | ||
return _this3.onFieldEvent('on' + cap(eventName), ev); | ||
}); | ||
}); | ||
_this2.onError(err); | ||
_this3.onError(err); | ||
}); | ||
@@ -160,3 +176,8 @@ } | ||
value: function componentDidMount() { | ||
var _this2 = this; | ||
this.api.attach(); | ||
this.props.getTokenRef(function () { | ||
return _this2.api.tokenize(); | ||
}); | ||
} | ||
@@ -184,2 +205,3 @@ }, { | ||
authorization: PropTypes.string.isRequired, | ||
getTokenRef: PropTypes.func.isRequired, | ||
onValidityChange: PropTypes.func, | ||
@@ -186,0 +208,0 @@ onCardTypeChange: PropTypes.func, |
@@ -95,5 +95,21 @@ import React from 'react'; | ||
}, { | ||
key: 'tokenize', | ||
value: function tokenize() { | ||
var _this2 = this; | ||
return new Promise(function (resolve, reject) { | ||
_this2.hostedFields.tokenize(function (err, payload) { | ||
if (err) { | ||
_this2.onError(err); | ||
reject(err); | ||
} else { | ||
resolve(payload); | ||
} | ||
}); | ||
}); | ||
} | ||
}, { | ||
key: '_attach', | ||
value: function _attach() { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -106,9 +122,9 @@ delete this.isAttachable; | ||
}, function (err, hostedFields) { | ||
_this2.hostedFields = hostedFields; | ||
_this3.hostedFields = hostedFields; | ||
['blur', 'focus', 'empty', 'notEmpty', 'cardTypeChange', 'validityChange'].forEach(function (eventName) { | ||
hostedFields.on(eventName, function (ev) { | ||
return _this2.onFieldEvent('on' + cap(eventName), ev); | ||
return _this3.onFieldEvent('on' + cap(eventName), ev); | ||
}); | ||
}); | ||
_this2.onError(err); | ||
_this3.onError(err); | ||
}); | ||
@@ -154,3 +170,8 @@ } | ||
value: function componentDidMount() { | ||
var _this2 = this; | ||
this.api.attach(); | ||
this.props.getTokenRef(function () { | ||
return _this2.api.tokenize(); | ||
}); | ||
} | ||
@@ -178,2 +199,3 @@ }, { | ||
authorization: PropTypes.string.isRequired, | ||
getTokenRef: PropTypes.func.isRequired, | ||
onValidityChange: PropTypes.func, | ||
@@ -180,0 +202,0 @@ onCardTypeChange: PropTypes.func, |
{ | ||
"name": "react-braintree-fields", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "React component for braintree hosted fields", | ||
@@ -17,3 +17,3 @@ "main": "dist/build.full.js", | ||
"build": "rollup -c", | ||
"dev": "$(npm bin)/webpack-dev-server --hot --inline --port 2222", | ||
"dev": "", | ||
"prepublish": "npm run build && npm test" | ||
@@ -40,6 +40,8 @@ }, | ||
"enzyme": "^2.8.0", | ||
"eslint": "^3.19.0", | ||
"eslint-config-argosity": "^1.0.6", | ||
"jest": "^19.0.2", | ||
"react": "^15.0.0", | ||
"react-addons-test-utils": "^15.4.2", | ||
"react-dom": "^15.0.0", | ||
"react-addons-test-utils": "^15.4.2", | ||
"react-test-renderer": "^15.4.2", | ||
@@ -46,0 +48,0 @@ "rollup": "^0.41.6", |
@@ -13,7 +13,13 @@ # React components to integrate Braintree hosted fields | ||
let getToken; | ||
function onSubmit() { | ||
getToken().then((payload) => { | ||
console.log("nonce=" , payload.nonce) | ||
}) | ||
} | ||
<Braintree | ||
authorization='sandbox_g42y39zw_348pk9cgf3bgyw2b' | ||
onError={this.handleError} | ||
onCardTypeChange={this.onCardTypeChange} | ||
getTokenRef={ref => (getToken = ref)} | ||
styles={{ | ||
@@ -30,10 +36,14 @@ 'input': { | ||
> | ||
<div> | ||
<h3>child</h3> | ||
<div className="fields"> | ||
<Field type="number" onFocus={onFocus} /> | ||
<Field type="expirationDate" /> | ||
<Field type="cvv" /> | ||
</div> | ||
<button onClick={onSubmit}>Submit</button> | ||
</Braintree> | ||
``` | ||
See [demo site](https://nathanstitt.github.io/react-braintree-fields/) for a working example. It renders [demo.jsx](demo.jsx) | ||
@@ -46,4 +56,5 @@ ## Braintree Component | ||
* onError: Function that will be called if an Braintree error is encountered. | ||
* getTokenRef: A function that will be called once Braintree the API is initialized. It will be called with a function that can be used to initiate tokenization. | ||
* The tokenization function will return a Promise which will be either resolved or rejected. If resolved, the promise payload will contain an object with the `nonce` and other data from Braintree. | ||
## Field Component | ||
@@ -50,0 +61,0 @@ |
@@ -10,2 +10,4 @@ import React from 'react'; | ||
let getToken; | ||
const buildTree = (style = {}, props = {}) => ( | ||
@@ -15,2 +17,3 @@ <Braintree | ||
styles={style} | ||
getTokenRef={ref => (getToken = ref)} | ||
> | ||
@@ -53,2 +56,11 @@ <div> | ||
}); | ||
it('sets token ref', () => { | ||
const client = mount(buildTree()); | ||
const api = client.instance().api; | ||
expect(getToken).toBeTruthy(); | ||
api.tokenize = jest.fn(); | ||
getToken(); | ||
expect(api.tokenize).toHaveBeenCalled(); | ||
}); | ||
}); |
@@ -61,2 +61,15 @@ import Braintree from 'braintree-web/client'; | ||
tokenize() { | ||
return new Promise((resolve, reject) => { | ||
this.hostedFields.tokenize((err, payload) => { | ||
if (err) { | ||
this.onError(err); | ||
reject(err); | ||
} else { | ||
resolve(payload); | ||
} | ||
}); | ||
}); | ||
} | ||
_attach() { | ||
@@ -63,0 +76,0 @@ delete this.isAttachable; |
@@ -11,2 +11,3 @@ import React from 'react'; | ||
authorization: PropTypes.string.isRequired, | ||
getTokenRef: PropTypes.func.isRequired, | ||
onValidityChange: PropTypes.func, | ||
@@ -34,2 +35,3 @@ onCardTypeChange: PropTypes.func, | ||
this.api.attach(); | ||
this.props.getTokenRef(() => this.api.tokenize()); | ||
} | ||
@@ -36,0 +38,0 @@ |
@@ -6,13 +6,11 @@ const webpack = require('webpack'); | ||
entry: { | ||
lib: __dirname + '/src/index.js', | ||
demo: __dirname + '/demo.jsx', | ||
}, | ||
output: { | ||
path: __dirname, | ||
publicPath: '/', | ||
filename: '[name].js', | ||
path: __dirname + '/docs', | ||
publicPath: '/docs', | ||
filename: 'demo.js', | ||
}, | ||
module: { | ||
rules: [ | ||
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }, | ||
{ | ||
@@ -49,3 +47,3 @@ loader: 'babel-loader', | ||
inline: true, | ||
port: 8889, | ||
port: 2222, | ||
historyApiFallback: true, | ||
@@ -52,0 +50,0 @@ stats: { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2426970
31
24972
68
24
1