import * as React from 'react'; import { AdditionalData, AriaLabel, Callbacks, ChargebeeInstance, Classes, Fonts, PaymentIntent, Placeholder, Styles } from "@chargebee/chargebee-js-types"; import {genUUID, isEqual} from '../utils/'; interface ComponentContext { cbComponent: any; } const ComponentDefaultContext: ComponentContext = { cbComponent: null } export const ComponentContext = React.createContext(ComponentDefaultContext); export function getPropOptions(props: FieldContainerProps) { const { fonts, classes, icon, styles: style, showTestCards, locale, placeholder, currency, ariaLabel } = props; return { fonts, classes, locale, style, showTestCards, placeholder, ariaLabel, icon, currency, } } export interface FieldContainerProps { children?: React.ReactNode; type?: string; fonts?: Fonts; classes?: Classes; icon?: boolean; styles?: Styles; showTestCards?: boolean; locale?: string; placeholder?: Placeholder; currency?: string; ariaLabel?: AriaLabel; className?: string; onBlur?: React.MouseEventHandler; onChange?: React.ChangeEventHandler; onFocus?: React.FocusEventHandler; onReady?: React.EventHandler; onKeyPress?: Function; cbInstance?: any; } interface FieldContainerState { cbComponent: any; cbInstance: ChargebeeInstance; id: string; ready: boolean; } export default class FieldContainer extends React.Component { private id: string; private containerRef = React.createRef(); constructor(props: FieldContainerProps) { super(props); this.id = `${this.props.type}-field-${genUUID()}`; this.state = { cbComponent: null, cbInstance: this.props.cbInstance, id: this.id, ready: false } } createCardComponent() { const {type, onBlur, onChange, onFocus, onReady, onKeyPress} = this.props; const options = getPropOptions(this.props); let cbComponent = this.props.cbInstance.createComponent(type, options) // Attach listeners if specified (only applicable for combined field) if(onReady) cbComponent.on('ready', onReady); if(onBlur) cbComponent.on('blur', onBlur); if(onFocus) cbComponent.on('focus', onFocus); if(onChange) cbComponent.on('change', onChange); if(onKeyPress) cbComponent.on('keyPress', onKeyPress); return cbComponent; } componentWillUnmount() { if (this.state.cbComponent) { this.state.cbComponent.destroy(); } } componentDidUpdate(prevProps: FieldContainerProps) { const cbComponent = this.state.cbComponent; const prevOptions = getPropOptions(prevProps); const currentOptions = getPropOptions(this.props); if (!isEqual(prevOptions, currentOptions) && cbComponent) { cbComponent.update(currentOptions); } } componentDidMount() { const cbComponent = this.createCardComponent(); this.setState({ cbComponent, ready: true }, () => { if (this.state.cbComponent && this.state.cbComponent.status === 0) { if (this.containerRef.current) { this.state.cbComponent.mount(this.containerRef.current); } } }); } tokenize(additionalData: AdditionalData) { const { cbComponent } = this.state; return cbComponent.tokenize(additionalData) } authorizeWith3ds(paymentIntent: PaymentIntent, additionalData: AdditionalData, callbacks: Callbacks) { const { cbComponent } = this.state; return cbComponent.authorizeWith3ds(paymentIntent, additionalData, callbacks) } focus() { const { cbComponent } = this.state; cbComponent.focus(); } blur() { const { cbComponent } = this.state; cbComponent.blur(); } clear() { const { cbComponent } = this.state; cbComponent.clear(); } render() { const { ready } = this.state; // Destructure ready state return (
{ready && this.props.children || []}
); } }