UNPKG

@navinc/base-react-components

Version:
105 lines (97 loc) 3.25 kB
import React, { useEffect } from 'react' import styled from 'styled-components' import { loadScript, global } from '@navinc/utils' import noop from '@navinc/utils/noop.js' import Copy from './copy' import { Input, Label, FieldWrapper, Field, Errors, Err } from './form-elements/shared.js' import * as theme from './theme.js' export const stripeDefaults = { stripe: { fonts: [ { family: 'Averta', src: `local("Averta"), local("averta"), url('https://dxkdvuv3hanyu.cloudfront.net/webfonts/Averta-Regular.eot?#iefix') format('embedded-opentype'), url('https://dxkdvuv3hanyu.cloudfront.net/webfonts/Averta-Regular.woff2') format('woff2'), url('https://dxkdvuv3hanyu.cloudfront.net/webfonts/Averta-Regular.woff') format('woff'), url('https://dxkdvuv3hanyu.cloudfront.net/webfonts/Averta-Regular.ttf') format('truetype')`, weight: 400, style: 'normal', }, ], }, elements: { classes: { base: 'c-input__input-field c-input__input-field--stripe', empty: 'is-empty', focus: 'is-focused', complete: 'is-focused', invalid: 'is-focused', }, hideIcon: false, style: { base: { color: theme.neutral400, fontFamily: 'Averta', fontSize: '16px', lineHeight: '1.8', }, invalid: { color: theme.error, }, }, }, } export const CCInputWrapper = styled(Input).attrs(() => ({ as: 'div' }))`` const CC_INPUT_CLASS_NAME = 'js-stripe_card' export const CCInput = ({ className = '', label, hasSpaceForErrors, isInvalid, value, required, type, errors = [], lede = '', onChange = noop, onBlur = noop, onFocus = noop, createPaymentMethodRef = noop, createTokenRef = noop, ...props }) => { useEffect(() => { Promise.resolve(global.Stripe || loadScript('https://js.stripe.com/v3/').then(() => global.Stripe)) .then((stripe) => stripe(global?.process?.env?.CLIENT_BILLING_PUBLIC_KEY ?? '')) .then((stripe) => { const elements = stripe.elements(stripeDefaults.stripe) const cc = elements.create('card', stripeDefaults.elements) cc.mount(`.${CC_INPUT_CLASS_NAME}`) cc.addEventListener('change', (changeEvent) => { onChange(changeEvent) }) createTokenRef((billingInfo) => stripe.createToken(cc, billingInfo)) createPaymentMethodRef((billingInfo) => stripe.createPaymentMethod('card', cc, billingInfo)) return stripe }) .catch((err) => console.error('Stripe failed to initialize! ', err)) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return ( <FieldWrapper className={className}> {lede && <Copy bold>{lede}</Copy>} <Field value={value} isVisited isInvalid={isInvalid} required={required} type={type}> <CCInputWrapper className={`js-private ${CC_INPUT_CLASS_NAME}`} {...props} /> <Label required={required} value={value}> {label} </Label> </Field> <Errors hasSpaceForErrors={hasSpaceForErrors}> {!!errors.length && errors.map((err, i) => <Err key={`err-${i}`}>{err}</Err>)} </Errors> </FieldWrapper> ) } export default CCInput