@stripe/react-stripe-js
Version:
React components for Stripe.js and Stripe Elements
912 lines (894 loc) • 35.5 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: true,
configurable: true,
writable: true
}) : e[r] = t, e;
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = true,
o = false;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = true, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _objectWithoutProperties(e, t) {
if (null == e) return {};
var o,
r,
i = _objectWithoutPropertiesLoose(e, t);
if (Object.getOwnPropertySymbols) {
var n = Object.getOwnPropertySymbols(e);
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
}
return i;
}
function _objectWithoutPropertiesLoose(r, e) {
if (null == r) return {};
var t = {};
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
if (-1 !== e.indexOf(n)) continue;
t[n] = r[n];
}
return t;
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var isUnknownObject = function isUnknownObject(raw) {
return raw !== null && _typeof(raw) === 'object';
};
var isPromise = function isPromise(raw) {
return isUnknownObject(raw) && typeof raw.then === 'function';
};
// We are using types to enforce the `stripe` prop in this lib,
// but in an untyped integration `stripe` could be anything, so we need
// to do some sanity validation to prevent type errors.
var isStripe = function isStripe(raw) {
return isUnknownObject(raw) && typeof raw.elements === 'function' && typeof raw.createToken === 'function' && typeof raw.createPaymentMethod === 'function' && typeof raw.confirmCardPayment === 'function';
};
var INVALID_STRIPE_ERROR$2 = 'Invalid prop `stripe` supplied to `Elements`. We recommend using the `loadStripe` utility from `@stripe/stripe-js`. See https://stripe.com/docs/stripe-js/react#elements-props-stripe for details.';
// We are using types to enforce the `stripe` prop in this lib, but in a real
// integration `stripe` could be anything, so we need to do some sanity
// validation to prevent type errors.
var validateStripe = function validateStripe(maybeStripe) {
var errorMsg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : INVALID_STRIPE_ERROR$2;
if (maybeStripe === null || isStripe(maybeStripe)) {
return maybeStripe;
}
throw new Error(errorMsg);
};
var parseStripeProp = function parseStripeProp(raw) {
var errorMsg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : INVALID_STRIPE_ERROR$2;
if (isPromise(raw)) {
return {
tag: 'async',
stripePromise: Promise.resolve(raw).then(function (result) {
return validateStripe(result, errorMsg);
})
};
}
var stripe = validateStripe(raw, errorMsg);
if (stripe === null) {
return {
tag: 'empty'
};
}
return {
tag: 'sync',
stripe: stripe
};
};
var usePrevious = function usePrevious(value) {
var ref = React.useRef(value);
React.useEffect(function () {
ref.current = value;
}, [value]);
return ref.current;
};
var PLAIN_OBJECT_STR = '[object Object]';
var isEqual = function isEqual(left, right) {
if (!isUnknownObject(left) || !isUnknownObject(right)) {
return left === right;
}
var leftArray = Array.isArray(left);
var rightArray = Array.isArray(right);
if (leftArray !== rightArray) return false;
var leftPlainObject = Object.prototype.toString.call(left) === PLAIN_OBJECT_STR;
var rightPlainObject = Object.prototype.toString.call(right) === PLAIN_OBJECT_STR;
if (leftPlainObject !== rightPlainObject) return false;
// not sure what sort of special object this is (regexp is one option), so
// fallback to reference check.
if (!leftPlainObject && !leftArray) return left === right;
var leftKeys = Object.keys(left);
var rightKeys = Object.keys(right);
if (leftKeys.length !== rightKeys.length) return false;
var keySet = {};
for (var i = 0; i < leftKeys.length; i += 1) {
keySet[leftKeys[i]] = true;
}
for (var _i = 0; _i < rightKeys.length; _i += 1) {
keySet[rightKeys[_i]] = true;
}
var allKeys = Object.keys(keySet);
if (allKeys.length !== leftKeys.length) {
return false;
}
var l = left;
var r = right;
var pred = function pred(key) {
return isEqual(l[key], r[key]);
};
return allKeys.every(pred);
};
var registerWithStripeJs = function registerWithStripeJs(stripe) {
if (!stripe || !stripe._registerWrapper || !stripe.registerAppInfo) {
return;
}
stripe._registerWrapper({
name: 'react-stripe-js',
version: "6.8.0"
});
stripe.registerAppInfo({
name: 'react-stripe-js',
version: "6.8.0",
url: 'https://stripe.com/docs/stripe-js/react'
});
};
var extractAllowedOptionsUpdates = function extractAllowedOptionsUpdates(options, prevOptions, immutableKeys) {
if (!isUnknownObject(options)) {
return null;
}
return Object.keys(options).reduce(function (newOptions, key) {
var isUpdated = !isUnknownObject(prevOptions) || !isEqual(options[key], prevOptions[key]);
if (immutableKeys.includes(key)) {
if (isUpdated) {
console.warn("Unsupported prop change: options.".concat(key, " is not a mutable property."));
}
return newOptions;
}
if (!isUpdated) {
return newOptions;
}
return _objectSpread2(_objectSpread2({}, newOptions || {}), {}, _defineProperty({}, key, options[key]));
}, null);
};
var ElementsContext = /*#__PURE__*/React.createContext(null);
ElementsContext.displayName = 'ElementsContext';
var parseElementsContext = function parseElementsContext(ctx, useCase) {
if (!ctx) {
throw new Error("Could not find Elements context; You need to wrap the part of your app that ".concat(useCase, " in an <Elements> provider."));
}
return ctx;
};
({
stripe: PropTypes.any,
options: PropTypes.object
});
({
children: PropTypes.func.isRequired
});
var _excluded$2 = ["on", "loadActions"],
_excluded2$1 = ["getSession"];
var CheckoutContext = /*#__PURE__*/React.createContext(null);
CheckoutContext.displayName = 'CheckoutContext';
var validateCheckoutContext = function validateCheckoutContext(ctx, useCase) {
if (!ctx) {
throw new Error("Could not find checkout context; You need to wrap the part of your app that ".concat(useCase, " in a <CheckoutElementsProvider> or <CheckoutFormProvider> provider."));
}
return ctx;
};
var useElementsOrCheckoutContextWithUseCase = function useElementsOrCheckoutContextWithUseCase(useCaseString) {
var checkout = React.useContext(CheckoutContext);
var elements = React.useContext(ElementsContext);
if (checkout) {
if (elements) {
throw new Error("You cannot wrap the part of your app that ".concat(useCaseString, " in both a checkout provider and <Elements> provider."));
} else {
return checkout;
}
} else {
return parseElementsContext(elements, useCaseString);
}
};
// One runtime shape, two possible static types depending on the calling hook.
// The spread destructure runs uniformly against either SDK kind because both
// StripeCheckoutElementsSdk and StripeCheckoutFormSdk expose `on` and
// `loadActions`; the final cast selects the surface that the caller expects.
var mapStateToCheckoutResult = function mapStateToCheckoutResult(checkoutState) {
if (checkoutState.type === 'success') {
var sdk = checkoutState.sdk,
session = checkoutState.session,
checkoutActions = checkoutState.checkoutActions;
sdk.on;
sdk.loadActions;
var sdkMethods = _objectWithoutProperties(sdk, _excluded$2);
checkoutActions.getSession;
var otherCheckoutActions = _objectWithoutProperties(checkoutActions, _excluded2$1);
return {
type: 'success',
checkout: _objectSpread2(_objectSpread2(_objectSpread2({}, session), sdkMethods), otherCheckoutActions)
};
} else if (checkoutState.type === 'loading') {
return {
type: 'loading'
};
} else {
return {
type: 'error',
error: checkoutState.error
};
}
};
/**
* @deprecated Since v6.3.0. Will be removed in v7.0.0. Prefer the
* provider-specific hooks:
* - Inside `<CheckoutElementsProvider>`, use `useCheckoutElements()`.
* - Inside `<CheckoutFormProvider>`, use `useCheckoutForm()`.
*
* The provider-specific hooks return the exact action surface exposed by
* their SDK.
*
* `useCheckout()` will keep working under both providers and returns the
* Elements-shaped result for backward compatibility.
*/
var useCheckout = function useCheckout() {
var ctx = React.useContext(CheckoutContext);
var _validateCheckoutCont = validateCheckoutContext(ctx, 'calls useCheckout()'),
checkoutState = _validateCheckoutCont.checkoutState;
return mapStateToCheckoutResult(checkoutState);
};
var useCheckoutElements = function useCheckoutElements() {
var ctx = React.useContext(CheckoutContext);
var _validateCheckoutCont2 = validateCheckoutContext(ctx, 'calls useCheckoutElements()'),
checkoutState = _validateCheckoutCont2.checkoutState;
if (checkoutState.type === 'success' && checkoutState.sdkKind !== 'elements') {
throw new Error('useCheckoutElements() must be used inside <CheckoutElementsProvider>. Inside <CheckoutFormProvider>, use useCheckoutForm() instead.');
}
return mapStateToCheckoutResult(checkoutState);
};
var useCheckoutForm = function useCheckoutForm() {
var ctx = React.useContext(CheckoutContext);
var _validateCheckoutCont3 = validateCheckoutContext(ctx, 'calls useCheckoutForm()'),
checkoutState = _validateCheckoutCont3.checkoutState;
if (checkoutState.type === 'success' && checkoutState.sdkKind !== 'form') {
throw new Error('useCheckoutForm() must be used inside <CheckoutFormProvider>. Inside <CheckoutElementsProvider>, use useCheckoutElements() instead.');
}
return mapStateToCheckoutResult(checkoutState);
};
var INVALID_STRIPE_ERROR$1 = 'Invalid prop `stripe` supplied to `CheckoutElementsProvider`. We recommend using the `loadStripe` utility from `@stripe/stripe-js`. See https://stripe.com/docs/stripe-js/react#elements-props-stripe for details.';
var maybeSdk = function maybeSdk(state) {
if (state.type === 'success' || state.type === 'loading') {
return state.sdk;
} else {
return null;
}
};
var CheckoutElementsProvider = function CheckoutElementsProvider(_ref) {
var rawStripeProp = _ref.stripe,
options = _ref.options,
children = _ref.children;
var parsed = React.useMemo(function () {
return parseStripeProp(rawStripeProp, INVALID_STRIPE_ERROR$1);
}, [rawStripeProp]);
var _React$useState = React.useState({
type: 'loading',
sdk: null
}),
_React$useState2 = _slicedToArray(_React$useState, 2),
state = _React$useState2[0],
setState = _React$useState2[1];
var _React$useState3 = React.useState(null),
_React$useState4 = _slicedToArray(_React$useState3, 2),
stripe = _React$useState4[0],
setStripe = _React$useState4[1];
// Ref used to avoid calling initCheckoutElementsSdk multiple times when options changes
var initCalledRef = React.useRef(false);
React.useEffect(function () {
var isMounted = true;
var init = function init(_ref2) {
var stripe = _ref2.stripe;
if (stripe && isMounted && !initCalledRef.current) {
// Only update context if the component is still mounted
// and stripe is not null. We allow stripe to be null to make
// handling SSR easier.
initCalledRef.current = true;
var _sdk = stripe.initCheckoutElementsSdk(options);
setState({
type: 'loading',
sdk: _sdk
});
_sdk.loadActions().then(function (result) {
if (result.type === 'success') {
var actions = result.actions;
setState({
type: 'success',
sdkKind: 'elements',
sdk: _sdk,
checkoutActions: actions,
session: actions.getSession()
});
_sdk.on('change', function (session) {
setState(function (prevState) {
if (prevState.type === 'success' && prevState.sdkKind === 'elements') {
return {
type: 'success',
sdkKind: 'elements',
sdk: prevState.sdk,
checkoutActions: prevState.checkoutActions,
session: session
};
} else {
return prevState;
}
});
});
} else {
setState({
type: 'error',
error: result.error
});
}
})["catch"](function (error) {
setState({
type: 'error',
error: error
});
});
}
};
if (parsed.tag === 'async') {
parsed.stripePromise.then(function (stripe) {
setStripe(stripe);
if (stripe) {
init({
stripe: stripe
});
}
});
} else if (parsed.tag === 'sync') {
setStripe(parsed.stripe);
init({
stripe: parsed.stripe
});
}
return function () {
isMounted = false;
};
}, [parsed, options, setState]);
// Warn on changes to stripe prop
var prevStripe = usePrevious(rawStripeProp);
React.useEffect(function () {
if (prevStripe !== null && prevStripe !== rawStripeProp) {
console.warn('Unsupported prop change on CheckoutElementsProvider: You cannot change the `stripe` prop after setting it.');
}
}, [prevStripe, rawStripeProp]);
// Apply updates to elements when options prop has relevant changes
var sdk = maybeSdk(state);
var prevOptions = usePrevious(options);
React.useEffect(function () {
var _prevOptions$elements, _options$elementsOpti, _prevOptions$elements2, _options$elementsOpti2;
// Ignore changes while checkout sdk is not initialized.
if (!sdk) {
return;
}
// Handle appearance changes
var previousAppearance = prevOptions === null || prevOptions === void 0 ? void 0 : (_prevOptions$elements = prevOptions.elementsOptions) === null || _prevOptions$elements === void 0 ? void 0 : _prevOptions$elements.appearance;
var currentAppearance = options === null || options === void 0 ? void 0 : (_options$elementsOpti = options.elementsOptions) === null || _options$elementsOpti === void 0 ? void 0 : _options$elementsOpti.appearance;
var hasAppearanceChanged = !isEqual(currentAppearance, previousAppearance);
if (currentAppearance && hasAppearanceChanged) {
sdk.changeAppearance(currentAppearance);
}
// Handle fonts changes
var previousFonts = prevOptions === null || prevOptions === void 0 ? void 0 : (_prevOptions$elements2 = prevOptions.elementsOptions) === null || _prevOptions$elements2 === void 0 ? void 0 : _prevOptions$elements2.fonts;
var currentFonts = options === null || options === void 0 ? void 0 : (_options$elementsOpti2 = options.elementsOptions) === null || _options$elementsOpti2 === void 0 ? void 0 : _options$elementsOpti2.fonts;
var hasFontsChanged = !isEqual(previousFonts, currentFonts);
if (currentFonts && hasFontsChanged) {
sdk.loadFonts(currentFonts);
}
}, [options, prevOptions, sdk]);
// Attach react-stripe-js version to stripe.js instance
React.useEffect(function () {
registerWithStripeJs(stripe);
}, [stripe]);
// Use useMemo to prevent unnecessary re-renders of child components
// when the context value object reference changes but the actual values haven't
var contextValue = React.useMemo(function () {
return {
stripe: stripe,
checkoutState: state
};
}, [stripe, state]);
return /*#__PURE__*/React.createElement(CheckoutContext.Provider, {
value: contextValue
}, children);
};
CheckoutElementsProvider.propTypes = {
stripe: PropTypes.any,
options: PropTypes.shape({
clientSecret: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Promise)]).isRequired,
elementsOptions: PropTypes.object
}).isRequired
};
var INVALID_STRIPE_ERROR = 'Invalid prop `stripe` supplied to `CheckoutFormProvider`. We recommend using the `loadStripe` utility from `@stripe/stripe-js`. See https://stripe.com/docs/stripe-js/react#elements-props-stripe for details.';
var CheckoutFormProvider = function CheckoutFormProvider(_ref) {
var rawStripeProp = _ref.stripe,
options = _ref.options,
children = _ref.children;
var parsed = React.useMemo(function () {
return parseStripeProp(rawStripeProp, INVALID_STRIPE_ERROR);
}, [rawStripeProp]);
var _React$useState = React.useState({
type: 'loading',
sdk: null
}),
_React$useState2 = _slicedToArray(_React$useState, 2),
state = _React$useState2[0],
setState = _React$useState2[1];
var _React$useState3 = React.useState(null),
_React$useState4 = _slicedToArray(_React$useState3, 2),
stripe = _React$useState4[0],
setStripe = _React$useState4[1];
// Ref used to avoid calling initCheckoutFormSdk multiple times when options changes
var initCalledRef = React.useRef(false);
React.useEffect(function () {
var isMounted = true;
var init = function init(_ref2) {
var stripe = _ref2.stripe;
if (stripe && isMounted && !initCalledRef.current) {
// Only update context if the component is still mounted
// and stripe is not null. We allow stripe to be null to make
// handling SSR easier.
initCalledRef.current = true;
var _sdk = stripe.initCheckoutFormSdk(options);
setState({
type: 'loading',
sdk: _sdk
});
_sdk.loadActions().then(function (result) {
if (result.type === 'success') {
var actions = result.actions;
setState({
type: 'success',
sdkKind: 'form',
sdk: _sdk,
checkoutActions: actions,
session: actions.getSession()
});
_sdk.on('change', function (session) {
setState(function (prevState) {
if (prevState.type === 'success' && prevState.sdkKind === 'form') {
return {
type: 'success',
sdkKind: 'form',
sdk: prevState.sdk,
checkoutActions: prevState.checkoutActions,
session: session
};
} else {
return prevState;
}
});
});
} else {
setState({
type: 'error',
error: result.error
});
}
})["catch"](function (error) {
setState({
type: 'error',
error: error
});
});
}
};
if (parsed.tag === 'async') {
parsed.stripePromise.then(function (stripe) {
setStripe(stripe);
if (stripe) {
init({
stripe: stripe
});
}
});
} else if (parsed.tag === 'sync') {
setStripe(parsed.stripe);
init({
stripe: parsed.stripe
});
}
return function () {
isMounted = false;
};
}, [parsed, options, setState]);
// Warn on changes to stripe prop
var prevStripe = usePrevious(rawStripeProp);
React.useEffect(function () {
if (prevStripe !== null && prevStripe !== rawStripeProp) {
console.warn('Unsupported prop change on CheckoutFormProvider: You cannot change the `stripe` prop after setting it.');
}
}, [prevStripe, rawStripeProp]);
// Apply updates when options prop has relevant changes.
// Unlike CheckoutElementsProvider, appearance/fonts are top-level options.
var sdk = state.type === 'success' || state.type === 'loading' ? state.sdk : null;
var prevOptions = usePrevious(options);
React.useEffect(function () {
// Ignore changes while checkout sdk is not initialized.
if (!sdk) {
return;
}
// Handle appearance changes
var previousAppearance = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.appearance;
var currentAppearance = options === null || options === void 0 ? void 0 : options.appearance;
var hasAppearanceChanged = !isEqual(currentAppearance, previousAppearance);
if (currentAppearance && hasAppearanceChanged) {
sdk.changeAppearance(currentAppearance);
}
// Handle fonts changes
var previousFonts = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.fonts;
var currentFonts = options === null || options === void 0 ? void 0 : options.fonts;
var hasFontsChanged = !isEqual(previousFonts, currentFonts);
if (currentFonts && hasFontsChanged) {
sdk.loadFonts(currentFonts);
}
}, [options, prevOptions, sdk]);
// Attach react-stripe-js version to stripe.js instance
React.useEffect(function () {
registerWithStripeJs(stripe);
}, [stripe]);
// Use useMemo to prevent unnecessary re-renders of child components
// when the context value object reference changes but the actual values haven't
var contextValue = React.useMemo(function () {
return {
stripe: stripe,
checkoutState: state
};
}, [stripe, state]);
return /*#__PURE__*/React.createElement(CheckoutContext.Provider, {
value: contextValue
}, children);
};
CheckoutFormProvider.propTypes = {
stripe: PropTypes.any,
options: PropTypes.shape({
clientSecret: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Promise)]).isRequired,
appearance: PropTypes.object,
loader: PropTypes.string,
fonts: PropTypes.array,
savedPaymentMethod: PropTypes.object,
defaultValues: PropTypes.object
}).isRequired
};
var useAttachEvent = function useAttachEvent(element, event, cb) {
var cbDefined = !!cb;
var cbRef = React.useRef(cb);
// In many integrations the callback prop changes on each render.
// Using a ref saves us from calling element.on/.off every render.
React.useEffect(function () {
cbRef.current = cb;
}, [cb]);
React.useEffect(function () {
if (!cbDefined || !element) {
return function () {};
}
var decoratedCb = function decoratedCb() {
if (cbRef.current) {
return cbRef.current.apply(cbRef, arguments);
}
return undefined;
};
element.on(event, decoratedCb);
return function () {
element.off(event, decoratedCb);
};
}, [cbDefined, event, element, cbRef]);
};
var _excluded$1 = ["mode"];
var capitalized = function capitalized(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
var createElementComponent = function createElementComponent(type, isServer, customDisplayName) {
var displayName = customDisplayName || "".concat(capitalized(type), "Element");
var ClientElement = function ClientElement(_ref) {
var id = _ref.id,
className = _ref.className,
_ref$options = _ref.options,
options = _ref$options === void 0 ? {} : _ref$options,
onBlur = _ref.onBlur,
onFocus = _ref.onFocus,
onReady = _ref.onReady,
onChange = _ref.onChange,
onEscape = _ref.onEscape,
onClick = _ref.onClick,
onLoadError = _ref.onLoadError,
onLoaderStart = _ref.onLoaderStart,
onNetworksChange = _ref.onNetworksChange,
onConfirm = _ref.onConfirm,
onCancel = _ref.onCancel,
onShippingAddressChange = _ref.onShippingAddressChange,
onShippingRateChange = _ref.onShippingRateChange,
onSavedPaymentMethodRemove = _ref.onSavedPaymentMethodRemove,
onSavedPaymentMethodUpdate = _ref.onSavedPaymentMethodUpdate,
onAvailablePaymentMethodsChange = _ref.onAvailablePaymentMethodsChange;
var ctx = useElementsOrCheckoutContextWithUseCase("mounts <".concat(displayName, ">"));
var elements = 'elements' in ctx ? ctx.elements : null;
var checkoutState = 'checkoutState' in ctx ? ctx.checkoutState : null;
var checkoutSdk = (checkoutState === null || checkoutState === void 0 ? void 0 : checkoutState.type) === 'success' || (checkoutState === null || checkoutState === void 0 ? void 0 : checkoutState.type) === 'loading' ? checkoutState.sdk : null;
var _React$useState = React.useState(null),
_React$useState2 = _slicedToArray(_React$useState, 2),
element = _React$useState2[0],
setElement = _React$useState2[1];
var elementRef = React.useRef(null);
var domNode = React.useRef(null);
// For every event where the merchant provides a callback, call element.on
// with that callback. If the merchant ever changes the callback, removes
// the old callback with element.off and then call element.on with the new one.
useAttachEvent(element, 'blur', onBlur);
useAttachEvent(element, 'focus', onFocus);
useAttachEvent(element, 'escape', onEscape);
useAttachEvent(element, 'click', onClick);
useAttachEvent(element, 'loaderror', onLoadError);
useAttachEvent(element, 'loaderstart', onLoaderStart);
useAttachEvent(element, 'networkschange', onNetworksChange);
useAttachEvent(element, 'confirm', onConfirm);
useAttachEvent(element, 'cancel', onCancel);
useAttachEvent(element, 'shippingaddresschange', onShippingAddressChange);
useAttachEvent(element, 'shippingratechange', onShippingRateChange);
useAttachEvent(element, 'savedpaymentmethodremove', onSavedPaymentMethodRemove);
useAttachEvent(element, 'savedpaymentmethodupdate', onSavedPaymentMethodUpdate);
useAttachEvent(element, 'availablepaymentmethodschange', onAvailablePaymentMethodsChange);
useAttachEvent(element, 'change', onChange);
var readyCallback;
if (onReady) {
if (type === 'expressCheckout') {
// Passes through the event, which includes visible PM types
readyCallback = onReady;
} else {
// For other Elements, pass through the Element itself.
readyCallback = function readyCallback() {
onReady(element);
};
}
}
useAttachEvent(element, 'ready', readyCallback);
React.useLayoutEffect(function () {
if (elementRef.current === null && domNode.current !== null && (elements || checkoutSdk)) {
var newElement = null;
if (checkoutSdk) {
var elementsSdk = checkoutSdk;
var formSdk = checkoutSdk;
switch (type) {
case 'paymentForm':
newElement = formSdk.createForm(options);
break;
case 'payment':
newElement = elementsSdk.createPaymentElement(options);
break;
case 'address':
if ('mode' in options) {
var mode = options.mode,
restOptions = _objectWithoutProperties(options, _excluded$1);
if (mode === 'shipping') {
newElement = elementsSdk.createShippingAddressElement(restOptions);
} else if (mode === 'billing') {
newElement = elementsSdk.createBillingAddressElement(restOptions);
} else {
throw new Error("Invalid options.mode. mode must be 'billing' or 'shipping'.");
}
} else {
throw new Error("You must supply options.mode. mode must be 'billing' or 'shipping'.");
}
break;
case 'expressCheckout':
newElement = elementsSdk.createExpressCheckoutElement(options);
break;
case 'currencySelector':
newElement = checkoutSdk.createCurrencySelectorElement();
break;
case 'taxId':
newElement = elementsSdk.createTaxIdElement(options);
break;
case 'contactDetails':
newElement = elementsSdk.createContactDetailsElement();
break;
case 'terms':
newElement = elementsSdk.createTermsElement(options);
break;
default:
throw new Error("<".concat(displayName, "> is not supported inside a checkout provider. Use an <Elements> provider instead."));
}
} else if (elements) {
newElement = elements.create(type, options);
}
// Store element in a ref to ensure it's _immediately_ available in cleanup hooks in StrictMode
elementRef.current = newElement;
// Store element in state to facilitate event listener attachment
setElement(newElement);
if (newElement) {
newElement.mount(domNode.current);
}
}
}, [elements, checkoutSdk, options]);
var prevOptions = usePrevious(options);
React.useEffect(function () {
if (!elementRef.current) {
return;
}
var updates = extractAllowedOptionsUpdates(options, prevOptions, ['paymentRequest']);
if (updates && 'update' in elementRef.current) {
elementRef.current.update(updates);
}
}, [options, prevOptions]);
React.useLayoutEffect(function () {
return function () {
if (elementRef.current && typeof elementRef.current.destroy === 'function') {
try {
elementRef.current.destroy();
elementRef.current = null;
} catch (error) {
// Do nothing
}
}
};
}, []);
return /*#__PURE__*/React.createElement("div", {
id: id,
className: className,
ref: domNode
});
};
// Only render the Element wrapper in a server environment.
var ServerElement = function ServerElement(props) {
useElementsOrCheckoutContextWithUseCase("mounts <".concat(displayName, ">"));
var id = props.id,
className = props.className;
return /*#__PURE__*/React.createElement("div", {
id: id,
className: className
});
};
var Element = isServer ? ServerElement : ClientElement;
Element.propTypes = {
id: PropTypes.string,
className: PropTypes.string,
onChange: PropTypes.func,
onBlur: PropTypes.func,
onFocus: PropTypes.func,
onReady: PropTypes.func,
onEscape: PropTypes.func,
onClick: PropTypes.func,
onLoadError: PropTypes.func,
onLoaderStart: PropTypes.func,
onNetworksChange: PropTypes.func,
onConfirm: PropTypes.func,
onCancel: PropTypes.func,
onShippingAddressChange: PropTypes.func,
onShippingRateChange: PropTypes.func,
onSavedPaymentMethodRemove: PropTypes.func,
onSavedPaymentMethodUpdate: PropTypes.func,
onAvailablePaymentMethodsChange: PropTypes.func,
options: PropTypes.object
};
Element.displayName = displayName;
Element.__elementType = type;
return Element;
};
var isServer = typeof window === 'undefined';
var _excluded = ["options"],
_excluded2 = ["options"];
var CurrencySelectorElement = createElementComponent('currencySelector', isServer);
var PaymentElement = createElementComponent('payment', isServer);
var CheckoutForm = createElementComponent('paymentForm', isServer, 'CheckoutForm');
var ExpressCheckoutElement = createElementComponent('expressCheckout', isServer);
var TaxIdElement = createElementComponent('taxId', isServer);
var ContactDetailsElement = createElementComponent('contactDetails', isServer);
var AddressElementBase = createElementComponent('address', isServer);
var BillingAddressElement = function BillingAddressElement(props) {
var options = props.options,
rest = _objectWithoutProperties(props, _excluded);
var merged = _objectSpread2(_objectSpread2({}, options), {}, {
mode: 'billing'
});
return /*#__PURE__*/React.createElement(AddressElementBase, _objectSpread2(_objectSpread2({}, rest), {}, {
options: merged
}));
};
var ShippingAddressElement = function ShippingAddressElement(props) {
var options = props.options,
rest = _objectWithoutProperties(props, _excluded2);
var merged = _objectSpread2(_objectSpread2({}, options), {}, {
mode: 'shipping'
});
return /*#__PURE__*/React.createElement(AddressElementBase, _objectSpread2(_objectSpread2({}, rest), {}, {
options: merged
}));
};
/**
* Requires beta access:
* Contact [Stripe support](https://support.stripe.com/) for more information.
*/
var TermsElement = createElementComponent('terms', isServer);
export { BillingAddressElement, CheckoutElementsProvider, CheckoutForm, CheckoutFormProvider, ContactDetailsElement, CurrencySelectorElement, ExpressCheckoutElement, PaymentElement, ShippingAddressElement, TaxIdElement, TermsElement, useCheckout, useCheckoutElements, useCheckoutForm };