UNPKG

react-braintree-fields

Version:
375 lines (314 loc) 9.2 kB
import React from 'react'; import PropTypes from 'prop-types'; import Braintree$1 from 'braintree-web/client'; import HostedFields from 'braintree-web/hosted-fields'; import BraintreeDataCollector from 'braintree-web/data-collector'; import BraintreeThreeDSecure from 'braintree-web/three-d-secure'; function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function cap(string) { return string.charAt(0).toUpperCase() + string.slice(1); } class BraintreeClientApi { constructor(_ref) { var { authorization, styles, onAuthorizationSuccess } = _ref, callbacks = _objectWithoutPropertiesLoose(_ref, ["authorization", "styles", "onAuthorizationSuccess"]); this.fields = Object.create(null); this._nextFieldId = 0; this.fieldHandlers = Object.create(null); this.styles = styles || {}; this.wrapperHandlers = callbacks || {}; this.setAuthorization(authorization, onAuthorizationSuccess); } setAuthorization(authorization, onAuthorizationSuccess) { if (!authorization && this.authorization) { this.teardown(); } else if (authorization && authorization !== this.authorization) { // fields have not yet checked in, delay setting so they can register if (0 === Object.keys(this.fields).length && !this.pendingAuthTimer) { this.pendingAuthTimer = setTimeout(() => { this.pendingAuthTimer = null; this.setAuthorization(authorization, onAuthorizationSuccess); }, 5); return; } if (this.authorization) { this.teardown(); } this.authorization = authorization; Braintree$1.create({ authorization }, (err, clientInstance) => { if (err) { this.onError(err); } else { this.create(clientInstance, onAuthorizationSuccess); if (this.wrapperHandlers.onThreeDSecureReady) { BraintreeThreeDSecure.create({ client: clientInstance, version: 2 }, this.wrapperHandlers.onThreeDSecureReady); } if (this.wrapperHandlers.onDataCollectorInstanceReady) { BraintreeDataCollector.create({ client: clientInstance, kount: true }, this.wrapperHandlers.onDataCollectorInstanceReady); } } }); } } nextFieldId() { this._nextFieldId += 1; return this._nextFieldId; } onError(err) { if (!err) { return; } if (this.wrapperHandlers.onError) { this.wrapperHandlers.onError(err); } } create(client, onAuthorizationSuccess) { this.client = client; HostedFields.create({ client, styles: this.styles, fields: this.fields }, (err, hostedFields) => { if (err) { this.onError(err); return; } this.hostedFields = hostedFields; ['blur', 'focus', 'empty', 'notEmpty', 'cardTypeChange', 'validityChange'].forEach(eventName => { hostedFields.on(eventName, ev => this.onFieldEvent("on" + cap(eventName), ev)); }); this.onError(err); if (onAuthorizationSuccess) { onAuthorizationSuccess(); } }); } teardown() { if (this.hostedFields) { this.hostedFields.teardown(); } if (this.pendingAuthTimer) { clearTimeout(this.pendingAuthTimer); this.pendingAuthTimer = null; } } checkInField(_ref2) { var { formatInput, maxlength, minlength, placeholder, select, type, prefill, rejectUnsupportedCards, id = "braintree-field-wrapper-" + this.nextFieldId(), options = {} } = _ref2, handlers = _objectWithoutPropertiesLoose(_ref2, ["formatInput", "maxlength", "minlength", "placeholder", "select", "type", "prefill", "rejectUnsupportedCards", "id", "options"]); var onRenderComplete = () => { this.fieldHandlers[type] = handlers; this.fields[type] = _extends({ formatInput, maxlength, minlength, placeholder, select, prefill, selector: "#" + id }, options); if ('number' === type && rejectUnsupportedCards) { this.fields.number.rejectUnsupportedCards = true; } }; return [id, onRenderComplete]; } focusField(fieldType, cb) { this.hostedFields.focus(fieldType, cb); } clearField(fieldType, cb) { this.hostedFields.clear(fieldType, cb); } setAttribute(fieldType, name, value) { this.hostedFields.setAttribute({ field: fieldType, attribute: name, value }); } onFieldEvent(eventName, event) { var fieldHandlers = this.fieldHandlers[event.emittedBy]; if (fieldHandlers && fieldHandlers[eventName]) { fieldHandlers[eventName](event.fields[event.emittedBy], event); } if (this.wrapperHandlers[eventName]) { this.wrapperHandlers[eventName](event); } } tokenize(options) { if (options === void 0) { options = {}; } return new Promise((resolve, reject) => { // eslint-disable-line no-undef this.hostedFields.tokenize(options, (err, payload) => { if (err) { this.onError(err); reject(err); } else { resolve(payload); } }); }); } } var Context = /*#__PURE__*/React.createContext({ braintreeApi: null }); class Braintree extends React.Component { constructor(props) { super(props); this.api = new BraintreeClientApi(props); this.contextValue = { braintreeApi: this.api }; } componentDidMount() { this.api.setAuthorization(this.props.authorization, this.props.onAuthorizationSuccess); if (this.props.getTokenRef) { this.props.getTokenRef(this.api.tokenize.bind(this.api)); } } componentWillUnmount() { this.api.teardown(); } componentDidUpdate() { this.api.setAuthorization(this.props.authorization, this.props.onAuthorizationSuccess); } tokenize(options) { return this.api.tokenize(options); } render() { var { className: providedClass, tagName: Tag } = this.props; var className = 'braintree-hosted-fields-wrapper'; if (providedClass) { className += " " + providedClass; } return /*#__PURE__*/React.createElement(Context.Provider, { value: this.contextValue }, /*#__PURE__*/React.createElement(Tag, { className: className }, this.props.children)); } } Braintree.propTypes = { children: PropTypes.node.isRequired, onAuthorizationSuccess: PropTypes.func, authorization: PropTypes.string, getTokenRef: PropTypes.func, onValidityChange: PropTypes.func, onCardTypeChange: PropTypes.func, onError: PropTypes.func, styles: PropTypes.object, className: PropTypes.string, tagName: PropTypes.string }; Braintree.defaultProps = { tagName: 'div' }; class BraintreeHostedField extends React.Component { constructor() { super(...arguments); this.state = {}; } focus() { this.context.braintreeApi.focusField(this.props.type); } clear() { this.context.braintreeApi.clearField(this.props.type); } setPlaceholder(text) { this.context.braintreeApi.setAttribute(this.props.type, 'placeholder', text); } componentDidMount() { var [fieldId, onRenderComplete] = this.context.braintreeApi.checkInField(this.props); this.setState({ fieldId }, onRenderComplete); } get className() { var list = ['braintree-hosted-field']; if (this.props.className) { list.push(this.props.className); } return list.join(' '); } render() { var { fieldId } = this.state; if (!fieldId) { return null; } return /*#__PURE__*/React.createElement("div", { id: fieldId, className: this.className }); } } BraintreeHostedField.propTypes = { type: PropTypes.oneOf(['number', 'expirationDate', 'expirationMonth', 'expirationYear', 'cvv', 'postalCode', 'cardholderName']).isRequired, id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), placeholder: PropTypes.string, className: PropTypes.string, onCardTypeChange: PropTypes.func, onValidityChange: PropTypes.func, onNotEmpty: PropTypes.func, onFocus: PropTypes.func, onEmpty: PropTypes.func, onBlur: PropTypes.func, prefill: PropTypes.string }; BraintreeHostedField.contextType = Context; export { Braintree, BraintreeHostedField as HostedField }; //# sourceMappingURL=build.module.js.map