@paypal/react-paypal-js
Advanced tools
Comparing version 3.0.3 to 4.0.0-beta.1
@@ -23,441 +23,30 @@ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } | ||
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
import React, { useContext, useReducer, useEffect, createContext, useRef, useState } from 'react'; | ||
import React, { createContext, useContext, useReducer, useEffect, useRef, useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
/*! | ||
* paypal-js v1.0.3 (2020-10-14T17:44:15.504Z) | ||
* Copyright 2020-present, PayPal, Inc. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
import { loadScript } from '@paypal/paypal-js'; | ||
var SCRIPT_LOADING_STATE; | ||
/** | ||
* @this {Promise} | ||
*/ | ||
(function (SCRIPT_LOADING_STATE) { | ||
SCRIPT_LOADING_STATE["PENDING"] = "pending"; | ||
SCRIPT_LOADING_STATE["REJECTED"] = "rejected"; | ||
SCRIPT_LOADING_STATE["RESOLVED"] = "resolved"; | ||
})(SCRIPT_LOADING_STATE || (SCRIPT_LOADING_STATE = {})); | ||
function finallyConstructor(callback) { | ||
var constructor = this.constructor; | ||
return this.then(function (value) { | ||
// @ts-ignore | ||
return constructor.resolve(callback()).then(function () { | ||
return value; | ||
}); | ||
}, function (reason) { | ||
// @ts-ignore | ||
return constructor.resolve(callback()).then(function () { | ||
// @ts-ignore | ||
return constructor.reject(reason); | ||
}); | ||
}); | ||
} // Store setTimeout reference so promise-polyfill will be unaffected by | ||
// other code modifying setTimeout (like sinon.useFakeTimers()) | ||
var ScriptContext = createContext(null); | ||
var ScriptDispatchContext = createContext(null); | ||
var setTimeoutFunc = setTimeout; | ||
function isArray(x) { | ||
return Boolean(x && typeof x.length !== 'undefined'); | ||
} | ||
function noop() {} // Polyfill for Function.prototype.bind | ||
function bind(fn, thisArg) { | ||
return function () { | ||
fn.apply(thisArg, arguments); | ||
}; | ||
} | ||
/** | ||
* @constructor | ||
* @param {Function} fn | ||
*/ | ||
function Promise(fn) { | ||
if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); | ||
if (typeof fn !== 'function') throw new TypeError('not a function'); | ||
/** @type {!number} */ | ||
this._state = 0; | ||
/** @type {!boolean} */ | ||
this._handled = false; | ||
/** @type {Promise|undefined} */ | ||
this._value = undefined; | ||
/** @type {!Array<!Function>} */ | ||
this._deferreds = []; | ||
doResolve(fn, this); | ||
} | ||
function handle(self, deferred) { | ||
while (self._state === 3) { | ||
self = self._value; | ||
} | ||
if (self._state === 0) { | ||
self._deferreds.push(deferred); | ||
return; | ||
} | ||
self._handled = true; | ||
Promise._immediateFn(function () { | ||
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; | ||
if (cb === null) { | ||
(self._state === 1 ? resolve : reject)(deferred.promise, self._value); | ||
return; | ||
} | ||
var ret; | ||
try { | ||
ret = cb(self._value); | ||
} catch (e) { | ||
reject(deferred.promise, e); | ||
return; | ||
} | ||
resolve(deferred.promise, ret); | ||
}); | ||
} | ||
function resolve(self, newValue) { | ||
try { | ||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure | ||
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); | ||
if (newValue && (_typeof(newValue) === 'object' || typeof newValue === 'function')) { | ||
var then = newValue.then; | ||
if (newValue instanceof Promise) { | ||
self._state = 3; | ||
self._value = newValue; | ||
finale(self); | ||
return; | ||
} else if (typeof then === 'function') { | ||
doResolve(bind(then, newValue), self); | ||
return; | ||
} | ||
} | ||
self._state = 1; | ||
self._value = newValue; | ||
finale(self); | ||
} catch (e) { | ||
reject(self, e); | ||
} | ||
} | ||
function reject(self, newValue) { | ||
self._state = 2; | ||
self._value = newValue; | ||
finale(self); | ||
} | ||
function finale(self) { | ||
if (self._state === 2 && self._deferreds.length === 0) { | ||
Promise._immediateFn(function () { | ||
if (!self._handled) { | ||
Promise._unhandledRejectionFn(self._value); | ||
} | ||
}); | ||
} | ||
for (var i = 0, len = self._deferreds.length; i < len; i++) { | ||
handle(self, self._deferreds[i]); | ||
} | ||
self._deferreds = null; | ||
} | ||
/** | ||
* @constructor | ||
*/ | ||
function Handler(onFulfilled, onRejected, promise) { | ||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; | ||
this.onRejected = typeof onRejected === 'function' ? onRejected : null; | ||
this.promise = promise; | ||
} | ||
/** | ||
* Take a potentially misbehaving resolver function and make sure | ||
* onFulfilled and onRejected are only called once. | ||
* | ||
* Makes no guarantees about asynchrony. | ||
*/ | ||
function doResolve(fn, self) { | ||
var done = false; | ||
try { | ||
fn(function (value) { | ||
if (done) return; | ||
done = true; | ||
resolve(self, value); | ||
}, function (reason) { | ||
if (done) return; | ||
done = true; | ||
reject(self, reason); | ||
}); | ||
} catch (ex) { | ||
if (done) return; | ||
done = true; | ||
reject(self, ex); | ||
} | ||
} | ||
Promise.prototype['catch'] = function (onRejected) { | ||
return this.then(null, onRejected); | ||
}; | ||
Promise.prototype.then = function (onFulfilled, onRejected) { | ||
// @ts-ignore | ||
var prom = new this.constructor(noop); | ||
handle(this, new Handler(onFulfilled, onRejected, prom)); | ||
return prom; | ||
}; | ||
Promise.prototype['finally'] = finallyConstructor; | ||
Promise.all = function (arr) { | ||
return new Promise(function (resolve, reject) { | ||
if (!isArray(arr)) { | ||
return reject(new TypeError('Promise.all accepts an array')); | ||
} | ||
var args = Array.prototype.slice.call(arr); | ||
if (args.length === 0) return resolve([]); | ||
var remaining = args.length; | ||
function res(i, val) { | ||
try { | ||
if (val && (_typeof(val) === 'object' || typeof val === 'function')) { | ||
var then = val.then; | ||
if (typeof then === 'function') { | ||
then.call(val, function (val) { | ||
res(i, val); | ||
}, reject); | ||
return; | ||
} | ||
} | ||
args[i] = val; | ||
if (--remaining === 0) { | ||
resolve(args); | ||
} | ||
} catch (ex) { | ||
reject(ex); | ||
} | ||
} | ||
for (var i = 0; i < args.length; i++) { | ||
res(i, args[i]); | ||
} | ||
}); | ||
}; | ||
Promise.resolve = function (value) { | ||
if (value && _typeof(value) === 'object' && value.constructor === Promise) { | ||
return value; | ||
} | ||
return new Promise(function (resolve) { | ||
resolve(value); | ||
}); | ||
}; | ||
Promise.reject = function (value) { | ||
return new Promise(function (resolve, reject) { | ||
reject(value); | ||
}); | ||
}; | ||
Promise.race = function (arr) { | ||
return new Promise(function (resolve, reject) { | ||
if (!isArray(arr)) { | ||
return reject(new TypeError('Promise.race accepts an array')); | ||
} | ||
for (var i = 0, len = arr.length; i < len; i++) { | ||
Promise.resolve(arr[i]).then(resolve, reject); | ||
} | ||
}); | ||
}; // Use polyfill for setImmediate for performance gains | ||
Promise._immediateFn = // @ts-ignore | ||
typeof setImmediate === 'function' && function (fn) { | ||
// @ts-ignore | ||
setImmediate(fn); | ||
} || function (fn) { | ||
setTimeoutFunc(fn, 0); | ||
}; | ||
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { | ||
if (typeof console !== 'undefined' && console) { | ||
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console | ||
} | ||
}; | ||
function findScript(url, dataAttributes) { | ||
var currentScript = document.querySelector("script[src=\"".concat(url, "\"]")); | ||
if (!currentScript) return null; | ||
var nextScript = createScriptElement(url, dataAttributes); // check if the new script has the same number of data attributes | ||
if (objectSize(currentScript.dataset) !== objectSize(nextScript.dataset)) { | ||
return null; | ||
} | ||
var isExactMatch = true; // check if the data attribute values are the same | ||
forEachObjectKey(currentScript.dataset, function (key) { | ||
if (currentScript.dataset[key] !== nextScript.dataset[key]) { | ||
isExactMatch = false; | ||
} | ||
}); | ||
return isExactMatch ? currentScript : null; | ||
} | ||
function insertScriptElement(_ref) { | ||
var url = _ref.url, | ||
dataAttributes = _ref.dataAttributes, | ||
onSuccess = _ref.onSuccess, | ||
onError = _ref.onError; | ||
var newScript = createScriptElement(url, dataAttributes); | ||
newScript.onerror = onError; | ||
newScript.onload = onSuccess; | ||
document.head.insertBefore(newScript, document.head.firstElementChild); | ||
} | ||
function processOptions() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var processedOptions = { | ||
queryParams: {}, | ||
dataAttributes: {} | ||
}; | ||
forEachObjectKey(options, function (key) { | ||
if (key.substring(0, 5) === 'data-') { | ||
processedOptions.dataAttributes[key] = options[key]; | ||
} else { | ||
processedOptions.queryParams[key] = options[key]; | ||
} | ||
}); | ||
var queryParams = processedOptions.queryParams, | ||
dataAttributes = processedOptions.dataAttributes; | ||
return { | ||
queryString: objectToQueryString(queryParams), | ||
dataAttributes: dataAttributes | ||
}; | ||
} | ||
function objectToQueryString(params) { | ||
var queryString = ''; | ||
forEachObjectKey(params, function (key) { | ||
if (queryString.length !== 0) queryString += '&'; | ||
queryString += key + '=' + params[key]; | ||
}); | ||
return queryString; | ||
} | ||
function createScriptElement(url) { | ||
var dataAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var newScript = document.createElement('script'); | ||
newScript.src = url; | ||
forEachObjectKey(dataAttributes, function (key) { | ||
newScript.setAttribute(key, dataAttributes[key]); | ||
}); | ||
return newScript; | ||
} // uses es3 to avoid requiring polyfills for Array.prototype.forEach and Object.keys | ||
function forEachObjectKey(obj, callback) { | ||
for (var key in obj) { | ||
if (Object.prototype.hasOwnProperty.call(obj, key)) { | ||
callback(key); | ||
} | ||
} | ||
} | ||
function objectSize(obj) { | ||
var size = 0; | ||
forEachObjectKey(obj, function () { | ||
return size++; | ||
}); | ||
return size; | ||
} | ||
var SDK_BASE_URL = 'https://www.paypal.com/sdk/js'; | ||
var loadingPromise; | ||
var isLoading = false; | ||
function loadScript(options) { | ||
// resolve with the existing promise when the script is loading | ||
if (isLoading) return loadingPromise; | ||
return loadingPromise = new Promise(function (resolve, reject) { | ||
// resolve with null when running in Node | ||
if (typeof window === 'undefined') return resolve(null); | ||
var _processOptions = processOptions(options), | ||
queryString = _processOptions.queryString, | ||
dataAttributes = _processOptions.dataAttributes; | ||
var url = "".concat(SDK_BASE_URL, "?").concat(queryString); // resolve with the existing global paypal object when a script with the same src already exists | ||
if (findScript(url, dataAttributes) && window.paypal) return resolve(window.paypal); | ||
isLoading = true; | ||
insertScriptElement({ | ||
url: url, | ||
dataAttributes: dataAttributes, | ||
onSuccess: function onSuccess() { | ||
isLoading = false; | ||
if (window.paypal) return resolve(window.paypal); | ||
return reject(new Error('The window.paypal global variable is not available.')); | ||
}, | ||
onError: function onError() { | ||
isLoading = false; | ||
return reject(new Error("The script \"".concat(url, "\" didn't load correctly."))); | ||
} | ||
}); | ||
}); | ||
} // replaced with the package.json version at build time | ||
var SCRIPT_LOADING_STATE = { | ||
PENDING: "pending", | ||
REJECTED: "rejected", | ||
RESOLVED: "resolved" | ||
}; | ||
var ScriptContext = /*#__PURE__*/createContext(); | ||
var ScriptDispatchContext = /*#__PURE__*/createContext(); | ||
function scriptReducer(state, action) { | ||
switch (action.type) { | ||
case "setLoadingStatus": | ||
var loadingStatus = action.value; | ||
return { | ||
options: _objectSpread({}, state.options), | ||
loadingStatus: action.value | ||
loadingStatus: loadingStatus | ||
}; | ||
case "resetOptions": | ||
var options = action.value; | ||
return { | ||
loadingStatus: SCRIPT_LOADING_STATE.PENDING, | ||
options: action.value | ||
options: options | ||
}; | ||
@@ -476,3 +65,3 @@ | ||
if (scriptContext === undefined || dispatchContext === undefined) { | ||
if (scriptContext === null || dispatchContext === null) { | ||
throw new Error("useScriptReducer must be used within a ScriptProvider"); | ||
@@ -493,5 +82,5 @@ } | ||
function PayPalScriptProvider(_ref2) { | ||
var options = _ref2.options, | ||
children = _ref2.children; | ||
function PayPalScriptProvider(_ref) { | ||
var options = _ref.options, | ||
children = _ref.children; | ||
var initialState = { | ||
@@ -529,5 +118,5 @@ options: options, | ||
}); | ||
return /*#__PURE__*/React.createElement(ScriptContext.Provider, { | ||
return React.createElement(ScriptContext.Provider, { | ||
value: state | ||
}, /*#__PURE__*/React.createElement(ScriptDispatchContext.Provider, { | ||
}, React.createElement(ScriptDispatchContext.Provider, { | ||
value: dispatch | ||
@@ -587,2 +176,3 @@ }, children)); | ||
if (buttons.current) { | ||
// @ts-expect-error - figure out types with useRef | ||
buttons.current.close(); | ||
@@ -598,10 +188,12 @@ } | ||
return cleanup; | ||
} | ||
} // @ts-expect-error - null checks | ||
buttons.current = window.paypal.Buttons(_objectSpread({}, props)); | ||
buttons.current = window.paypal.Buttons(_objectSpread({}, props)); // @ts-expect-error - null checks | ||
if (!buttons.current.isEligible()) { | ||
return cleanup; | ||
} | ||
} // @ts-expect-error - null checks | ||
buttons.current.render(buttonsContainerRef.current)["catch"](function (err) { | ||
@@ -612,11 +204,13 @@ console.error("Failed to render <PayPalButtons /> component. ".concat(err)); | ||
}, [isResolved, props.forceReRender, props.fundingSource]); | ||
return /*#__PURE__*/React.createElement("div", { | ||
return React.createElement("div", { | ||
ref: buttonsContainerRef | ||
}); | ||
} | ||
} // @ts-expect-error - figure out setErrorState | ||
function hasValidGlobalStateForButtons(_ref3, setErrorState) { | ||
var _ref3$components = _ref3.components, | ||
components = _ref3$components === void 0 ? "" : _ref3$components; | ||
function hasValidGlobalStateForButtons(_ref2, setErrorState) { | ||
var _ref2$components = _ref2.components, | ||
components = _ref2$components === void 0 ? "" : _ref2$components; | ||
// @ts-expect-error - needs null checks | ||
if (typeof window.paypal.Buttons !== "undefined") { | ||
@@ -759,10 +353,12 @@ return true; | ||
return; | ||
} | ||
} // @ts-expect-error - null checks | ||
mark.current = window.paypal.Marks(_objectSpread({}, props)); | ||
mark.current = window.paypal.Marks(_objectSpread({}, props)); // @ts-expect-error - null checks | ||
if (!mark.current.isEligible()) { | ||
return; | ||
} | ||
} // @ts-expect-error - null checks | ||
mark.current.render(markContainerRef.current)["catch"](function (err) { | ||
@@ -772,11 +368,13 @@ console.error("Failed to render <PayPalMarks /> component. ".concat(err)); | ||
}, [isResolved, props.fundingSource]); | ||
return /*#__PURE__*/React.createElement("div", { | ||
return React.createElement("div", { | ||
ref: markContainerRef | ||
}); | ||
} | ||
} // @ts-expect-error - figure out setErrorState | ||
function hasValidStateForMarks(_ref4, setErrorState) { | ||
var _ref4$components = _ref4.components, | ||
components = _ref4$components === void 0 ? "" : _ref4$components; | ||
function hasValidStateForMarks(_ref3, setErrorState) { | ||
var _ref3$components = _ref3.components, | ||
components = _ref3$components === void 0 ? "" : _ref3$components; | ||
// @ts-expect-error - needs null checks | ||
if (typeof window.paypal.Marks !== "undefined") { | ||
@@ -817,5 +415,7 @@ return true; | ||
return; | ||
} | ||
} // @ts-expect-error - null checks | ||
messages.current = window.paypal.Messages(_objectSpread({}, props)); | ||
messages.current = window.paypal.Messages(_objectSpread({}, props)); // @ts-expect-error - null checks | ||
messages.current.render(messagesContainerRef.current)["catch"](function (err) { | ||
@@ -825,3 +425,3 @@ console.error("Failed to render <PayPalMessages /> component. ".concat(err)); | ||
}, [isResolved, props.forceReRender]); | ||
return /*#__PURE__*/React.createElement("div", { | ||
return React.createElement("div", { | ||
ref: messagesContainerRef | ||
@@ -828,0 +428,0 @@ }); |
@@ -14,3 +14,3 @@ 'use strict'; | ||
/*! | ||
* paypal-js v1.0.3 (2020-10-14T17:44:15.504Z) | ||
* paypal-js v2.1.2 (2021-01-10T17:22:23.865Z) | ||
* Copyright 2020-present, PayPal, Inc. All rights reserved. | ||
@@ -30,280 +30,5 @@ * | ||
*/ | ||
/** | ||
* @this {Promise} | ||
*/ | ||
function finallyConstructor(callback) { | ||
var constructor = this.constructor; | ||
return this.then(function (value) { | ||
// @ts-ignore | ||
return constructor.resolve(callback()).then(function () { | ||
return value; | ||
}); | ||
}, function (reason) { | ||
// @ts-ignore | ||
return constructor.resolve(callback()).then(function () { | ||
// @ts-ignore | ||
return constructor.reject(reason); | ||
}); | ||
}); | ||
} // Store setTimeout reference so promise-polyfill will be unaffected by | ||
// other code modifying setTimeout (like sinon.useFakeTimers()) | ||
var setTimeoutFunc = setTimeout; | ||
function isArray(x) { | ||
return Boolean(x && typeof x.length !== 'undefined'); | ||
} | ||
function noop() {} // Polyfill for Function.prototype.bind | ||
function bind(fn, thisArg) { | ||
return function () { | ||
fn.apply(thisArg, arguments); | ||
}; | ||
} | ||
/** | ||
* @constructor | ||
* @param {Function} fn | ||
*/ | ||
function Promise(fn) { | ||
if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); | ||
if (typeof fn !== 'function') throw new TypeError('not a function'); | ||
/** @type {!number} */ | ||
this._state = 0; | ||
/** @type {!boolean} */ | ||
this._handled = false; | ||
/** @type {Promise|undefined} */ | ||
this._value = undefined; | ||
/** @type {!Array<!Function>} */ | ||
this._deferreds = []; | ||
doResolve(fn, this); | ||
} | ||
function handle(self, deferred) { | ||
while (self._state === 3) { | ||
self = self._value; | ||
} | ||
if (self._state === 0) { | ||
self._deferreds.push(deferred); | ||
return; | ||
} | ||
self._handled = true; | ||
Promise._immediateFn(function () { | ||
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; | ||
if (cb === null) { | ||
(self._state === 1 ? resolve : reject)(deferred.promise, self._value); | ||
return; | ||
} | ||
var ret; | ||
try { | ||
ret = cb(self._value); | ||
} catch (e) { | ||
reject(deferred.promise, e); | ||
return; | ||
} | ||
resolve(deferred.promise, ret); | ||
}); | ||
} | ||
function resolve(self, newValue) { | ||
try { | ||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure | ||
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); | ||
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { | ||
var then = newValue.then; | ||
if (newValue instanceof Promise) { | ||
self._state = 3; | ||
self._value = newValue; | ||
finale(self); | ||
return; | ||
} else if (typeof then === 'function') { | ||
doResolve(bind(then, newValue), self); | ||
return; | ||
} | ||
} | ||
self._state = 1; | ||
self._value = newValue; | ||
finale(self); | ||
} catch (e) { | ||
reject(self, e); | ||
} | ||
} | ||
function reject(self, newValue) { | ||
self._state = 2; | ||
self._value = newValue; | ||
finale(self); | ||
} | ||
function finale(self) { | ||
if (self._state === 2 && self._deferreds.length === 0) { | ||
Promise._immediateFn(function () { | ||
if (!self._handled) { | ||
Promise._unhandledRejectionFn(self._value); | ||
} | ||
}); | ||
} | ||
for (var i = 0, len = self._deferreds.length; i < len; i++) { | ||
handle(self, self._deferreds[i]); | ||
} | ||
self._deferreds = null; | ||
} | ||
/** | ||
* @constructor | ||
*/ | ||
function Handler(onFulfilled, onRejected, promise) { | ||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; | ||
this.onRejected = typeof onRejected === 'function' ? onRejected : null; | ||
this.promise = promise; | ||
} | ||
/** | ||
* Take a potentially misbehaving resolver function and make sure | ||
* onFulfilled and onRejected are only called once. | ||
* | ||
* Makes no guarantees about asynchrony. | ||
*/ | ||
function doResolve(fn, self) { | ||
var done = false; | ||
try { | ||
fn(function (value) { | ||
if (done) return; | ||
done = true; | ||
resolve(self, value); | ||
}, function (reason) { | ||
if (done) return; | ||
done = true; | ||
reject(self, reason); | ||
}); | ||
} catch (ex) { | ||
if (done) return; | ||
done = true; | ||
reject(self, ex); | ||
} | ||
} | ||
Promise.prototype['catch'] = function (onRejected) { | ||
return this.then(null, onRejected); | ||
}; | ||
Promise.prototype.then = function (onFulfilled, onRejected) { | ||
// @ts-ignore | ||
var prom = new this.constructor(noop); | ||
handle(this, new Handler(onFulfilled, onRejected, prom)); | ||
return prom; | ||
}; | ||
Promise.prototype['finally'] = finallyConstructor; | ||
Promise.all = function (arr) { | ||
return new Promise(function (resolve, reject) { | ||
if (!isArray(arr)) { | ||
return reject(new TypeError('Promise.all accepts an array')); | ||
} | ||
var args = Array.prototype.slice.call(arr); | ||
if (args.length === 0) return resolve([]); | ||
var remaining = args.length; | ||
function res(i, val) { | ||
try { | ||
if (val && (typeof val === 'object' || typeof val === 'function')) { | ||
var then = val.then; | ||
if (typeof then === 'function') { | ||
then.call(val, function (val) { | ||
res(i, val); | ||
}, reject); | ||
return; | ||
} | ||
} | ||
args[i] = val; | ||
if (--remaining === 0) { | ||
resolve(args); | ||
} | ||
} catch (ex) { | ||
reject(ex); | ||
} | ||
} | ||
for (var i = 0; i < args.length; i++) { | ||
res(i, args[i]); | ||
} | ||
}); | ||
}; | ||
Promise.resolve = function (value) { | ||
if (value && typeof value === 'object' && value.constructor === Promise) { | ||
return value; | ||
} | ||
return new Promise(function (resolve) { | ||
resolve(value); | ||
}); | ||
}; | ||
Promise.reject = function (value) { | ||
return new Promise(function (resolve, reject) { | ||
reject(value); | ||
}); | ||
}; | ||
Promise.race = function (arr) { | ||
return new Promise(function (resolve, reject) { | ||
if (!isArray(arr)) { | ||
return reject(new TypeError('Promise.race accepts an array')); | ||
} | ||
for (var i = 0, len = arr.length; i < len; i++) { | ||
Promise.resolve(arr[i]).then(resolve, reject); | ||
} | ||
}); | ||
}; // Use polyfill for setImmediate for performance gains | ||
Promise._immediateFn = // @ts-ignore | ||
typeof setImmediate === 'function' && function (fn) { | ||
// @ts-ignore | ||
setImmediate(fn); | ||
} || function (fn) { | ||
setTimeoutFunc(fn, 0); | ||
}; | ||
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { | ||
if (typeof console !== 'undefined' && console) { | ||
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console | ||
} | ||
}; | ||
function findScript(url, dataAttributes) { | ||
var currentScript = document.querySelector("script[src=\"".concat(url, "\"]")); | ||
if (!currentScript) return null; | ||
if (currentScript === null) return null; | ||
var nextScript = createScriptElement(url, dataAttributes); // check if the new script has the same number of data attributes | ||
@@ -336,4 +61,10 @@ | ||
function processOptions() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
function processOptions(options) { | ||
var sdkBaseURL = 'https://www.paypal.com/sdk/js'; | ||
if (options.sdkBaseURL) { | ||
sdkBaseURL = options.sdkBaseURL; | ||
delete options.sdkBaseURL; | ||
} | ||
var processedOptions = { | ||
@@ -344,7 +75,5 @@ queryParams: {}, | ||
forEachObjectKey(options, function (key) { | ||
if (key.substring(0, 5) === 'data-') { | ||
processedOptions.dataAttributes[key] = options[key]; | ||
} else { | ||
processedOptions.queryParams[key] = options[key]; | ||
} | ||
var keyType = key.substring(0, 5) === 'data-' ? 'dataAttributes' : 'queryParams'; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
processedOptions[keyType][key] = options[key].toString(); | ||
}); | ||
@@ -354,3 +83,3 @@ var queryParams = processedOptions.queryParams, | ||
return { | ||
queryString: objectToQueryString(queryParams), | ||
url: "".concat(sdkBaseURL, "?").concat(objectToQueryString(queryParams)), | ||
dataAttributes: dataAttributes | ||
@@ -375,2 +104,6 @@ }; | ||
newScript.setAttribute(key, dataAttributes[key]); | ||
if (key === 'data-csp-nonce') { | ||
newScript.setAttribute('nonce', dataAttributes['data-csp-nonce']); | ||
} | ||
}); | ||
@@ -397,10 +130,22 @@ return newScript; | ||
var SDK_BASE_URL = 'https://www.paypal.com/sdk/js'; | ||
var loadingPromise; | ||
var isLoading = false; | ||
function loadScript(options) { | ||
// resolve with the existing promise when the script is loading | ||
function loadScript(options, PromisePonyfill) { | ||
if (!(options instanceof Object)) { | ||
throw new Error('Invalid arguments. Expected an object to be passed into loadScript().'); | ||
} | ||
if (typeof PromisePonyfill === 'undefined') { | ||
// default to using window.Promise as the Promise implementation | ||
if (typeof Promise === 'undefined') { | ||
throw new Error('Failed to load the PayPal JS SDK script because Promise is undefined. To resolve the issue, use a Promise polyfill.'); | ||
} | ||
PromisePonyfill = Promise; | ||
} // resolve with the existing promise when the script is loading | ||
if (isLoading) return loadingPromise; | ||
return loadingPromise = new Promise(function (resolve, reject) { | ||
return loadingPromise = new PromisePonyfill(function (resolve, reject) { | ||
// resolve with null when running in Node | ||
@@ -410,6 +155,5 @@ if (typeof window === 'undefined') return resolve(null); | ||
var _processOptions = processOptions(options), | ||
queryString = _processOptions.queryString, | ||
dataAttributes = _processOptions.dataAttributes; | ||
url = _processOptions.url, | ||
dataAttributes = _processOptions.dataAttributes; // resolve with the existing global paypal object when a script with the same src already exists | ||
var url = "".concat(SDK_BASE_URL, "?").concat(queryString); // resolve with the existing global paypal object when a script with the same src already exists | ||
@@ -432,113 +176,103 @@ if (findScript(url, dataAttributes) && window.paypal) return resolve(window.paypal); | ||
}); | ||
} // replaced with the package.json version at build time | ||
} | ||
const SCRIPT_LOADING_STATE = { | ||
PENDING: "pending", | ||
REJECTED: "rejected", | ||
RESOLVED: "resolved" | ||
}; | ||
const ScriptContext = /*#__PURE__*/React.createContext(); | ||
const ScriptDispatchContext = /*#__PURE__*/React.createContext(); | ||
var SCRIPT_LOADING_STATE; | ||
(function (SCRIPT_LOADING_STATE) { | ||
SCRIPT_LOADING_STATE["PENDING"] = "pending"; | ||
SCRIPT_LOADING_STATE["REJECTED"] = "rejected"; | ||
SCRIPT_LOADING_STATE["RESOLVED"] = "resolved"; | ||
})(SCRIPT_LOADING_STATE || (SCRIPT_LOADING_STATE = {})); | ||
const ScriptContext = React.createContext(null); | ||
const ScriptDispatchContext = React.createContext(null); | ||
function scriptReducer(state, action) { | ||
switch (action.type) { | ||
case "setLoadingStatus": | ||
return { | ||
options: { ...state.options | ||
}, | ||
loadingStatus: action.value | ||
}; | ||
case "resetOptions": | ||
return { | ||
loadingStatus: SCRIPT_LOADING_STATE.PENDING, | ||
options: action.value | ||
}; | ||
default: | ||
{ | ||
throw new Error(`Unhandled action type: ${action.type}`); | ||
} | ||
} | ||
switch (action.type) { | ||
case "setLoadingStatus": | ||
const loadingStatus = action.value; | ||
return { | ||
options: { | ||
...state.options, | ||
}, | ||
loadingStatus | ||
}; | ||
case "resetOptions": | ||
const options = action.value; | ||
return { | ||
loadingStatus: SCRIPT_LOADING_STATE.PENDING, | ||
options | ||
}; | ||
default: { | ||
throw new Error(`Unhandled action type: ${action.type}`); | ||
} | ||
} | ||
} | ||
function usePayPalScriptReducer() { | ||
const scriptContext = React.useContext(ScriptContext); | ||
const dispatchContext = React.useContext(ScriptDispatchContext); | ||
if (scriptContext === undefined || dispatchContext === undefined) { | ||
throw new Error("useScriptReducer must be used within a ScriptProvider"); | ||
} | ||
const { | ||
loadingStatus, | ||
...restScriptContext | ||
} = scriptContext; | ||
const derivedStatusContext = { ...restScriptContext, | ||
isPending: loadingStatus === SCRIPT_LOADING_STATE.PENDING, | ||
isResolved: loadingStatus === SCRIPT_LOADING_STATE.RESOLVED, | ||
isRejected: loadingStatus === SCRIPT_LOADING_STATE.REJECTED | ||
}; | ||
return [derivedStatusContext, dispatchContext]; | ||
const scriptContext = React.useContext(ScriptContext); | ||
const dispatchContext = React.useContext(ScriptDispatchContext); | ||
if (scriptContext === null || dispatchContext === null) { | ||
throw new Error("useScriptReducer must be used within a ScriptProvider"); | ||
} | ||
const { loadingStatus, ...restScriptContext } = scriptContext; | ||
const derivedStatusContext = { | ||
...restScriptContext, | ||
isPending: loadingStatus === SCRIPT_LOADING_STATE.PENDING, | ||
isResolved: loadingStatus === SCRIPT_LOADING_STATE.RESOLVED, | ||
isRejected: loadingStatus === SCRIPT_LOADING_STATE.REJECTED, | ||
}; | ||
return [derivedStatusContext, dispatchContext]; | ||
} | ||
function PayPalScriptProvider({ | ||
options, | ||
children | ||
}) { | ||
const initialState = { | ||
options, | ||
loadingStatus: SCRIPT_LOADING_STATE.PENDING | ||
}; | ||
const [state, dispatch] = React.useReducer(scriptReducer, initialState); | ||
React.useEffect(() => { | ||
if (state.loadingStatus !== SCRIPT_LOADING_STATE.PENDING) return; | ||
let isSubscribed = true; | ||
loadScript(state.options).then(() => { | ||
if (isSubscribed) { | ||
dispatch({ | ||
type: "setLoadingStatus", | ||
value: SCRIPT_LOADING_STATE.RESOLVED | ||
function PayPalScriptProvider({ options, children }) { | ||
const initialState = { | ||
options, | ||
loadingStatus: SCRIPT_LOADING_STATE.PENDING, | ||
}; | ||
const [state, dispatch] = React.useReducer(scriptReducer, initialState); | ||
React.useEffect(() => { | ||
if (state.loadingStatus !== SCRIPT_LOADING_STATE.PENDING) | ||
return; | ||
let isSubscribed = true; | ||
loadScript(state.options) | ||
.then(() => { | ||
if (isSubscribed) { | ||
dispatch({ | ||
type: "setLoadingStatus", | ||
value: SCRIPT_LOADING_STATE.RESOLVED, | ||
}); | ||
} | ||
}) | ||
.catch(() => { | ||
if (isSubscribed) { | ||
dispatch({ | ||
type: "setLoadingStatus", | ||
value: SCRIPT_LOADING_STATE.REJECTED, | ||
}); | ||
} | ||
}); | ||
} | ||
}).catch(() => { | ||
if (isSubscribed) { | ||
dispatch({ | ||
type: "setLoadingStatus", | ||
value: SCRIPT_LOADING_STATE.REJECTED | ||
}); | ||
} | ||
return () => { | ||
isSubscribed = false; | ||
}; | ||
}); | ||
return () => { | ||
isSubscribed = false; | ||
}; | ||
}); | ||
return /*#__PURE__*/React__default['default'].createElement(ScriptContext.Provider, { | ||
value: state | ||
}, /*#__PURE__*/React__default['default'].createElement(ScriptDispatchContext.Provider, { | ||
value: dispatch | ||
}, children)); | ||
return (React__default['default'].createElement(ScriptContext.Provider, { value: state }, | ||
React__default['default'].createElement(ScriptDispatchContext.Provider, { value: dispatch }, children))); | ||
} | ||
PayPalScriptProvider.propTypes = { | ||
children: PropTypes__default['default'].node.isRequired, | ||
options: PropTypes__default['default'].exact({ | ||
"buyer-country": PropTypes__default['default'].string, | ||
"client-id": PropTypes__default['default'].string.isRequired, | ||
commit: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]), | ||
components: PropTypes__default['default'].string, | ||
currency: PropTypes__default['default'].string, | ||
"data-client-token": PropTypes__default['default'].string, | ||
"data-csp-nonce": PropTypes__default['default'].string, | ||
"data-order-id": PropTypes__default['default'].string, | ||
"data-page-type": PropTypes__default['default'].string, | ||
"data-partner-attribution-id": PropTypes__default['default'].string, | ||
debug: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]), | ||
"disable-funding": PropTypes__default['default'].string, | ||
"integration-date": PropTypes__default['default'].string, | ||
intent: PropTypes__default['default'].string, | ||
locale: PropTypes__default['default'].string, | ||
"merchant-id": PropTypes__default['default'].string, | ||
vault: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]) | ||
}) | ||
children: PropTypes__default['default'].node.isRequired, | ||
options: PropTypes__default['default'].exact({ | ||
"buyer-country": PropTypes__default['default'].string, | ||
"client-id": PropTypes__default['default'].string.isRequired, | ||
commit: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]), | ||
components: PropTypes__default['default'].string, | ||
currency: PropTypes__default['default'].string, | ||
"data-client-token": PropTypes__default['default'].string, | ||
"data-csp-nonce": PropTypes__default['default'].string, | ||
"data-order-id": PropTypes__default['default'].string, | ||
"data-page-type": PropTypes__default['default'].string, | ||
"data-partner-attribution-id": PropTypes__default['default'].string, | ||
debug: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]), | ||
"disable-funding": PropTypes__default['default'].string, | ||
"integration-date": PropTypes__default['default'].string, | ||
intent: PropTypes__default['default'].string, | ||
locale: PropTypes__default['default'].string, | ||
"merchant-id": PropTypes__default['default'].string, | ||
vault: PropTypes__default['default'].oneOfType([PropTypes__default['default'].bool, PropTypes__default['default'].string]), | ||
}), | ||
}; | ||
@@ -556,138 +290,117 @@ | ||
*/ | ||
function PayPalButtons(props) { | ||
const [{ | ||
isResolved, | ||
options | ||
}] = usePayPalScriptReducer(); | ||
const buttonsContainerRef = React.useRef(null); | ||
const buttons = React.useRef(null); | ||
const [, setErrorState] = React.useState(null); | ||
React.useEffect(() => { | ||
const cleanup = () => { | ||
if (buttons.current) { | ||
buttons.current.close(); | ||
} | ||
}; | ||
if (!isResolved) { | ||
return cleanup; | ||
const [{ isResolved, options }] = usePayPalScriptReducer(); | ||
const buttonsContainerRef = React.useRef(null); | ||
const buttons = React.useRef(null); | ||
const [, setErrorState] = React.useState(null); | ||
React.useEffect(() => { | ||
const cleanup = () => { | ||
if (buttons.current) { | ||
// @ts-expect-error - figure out types with useRef | ||
buttons.current.close(); | ||
} | ||
}; | ||
if (!isResolved) { | ||
return cleanup; | ||
} | ||
if (!hasValidGlobalStateForButtons(options, setErrorState)) { | ||
return cleanup; | ||
} | ||
// @ts-expect-error - null checks | ||
buttons.current = window.paypal.Buttons({ ...props }); | ||
// @ts-expect-error - null checks | ||
if (!buttons.current.isEligible()) { | ||
return cleanup; | ||
} | ||
// @ts-expect-error - null checks | ||
buttons.current.render(buttonsContainerRef.current).catch((err) => { | ||
console.error(`Failed to render <PayPalButtons /> component. ${err}`); | ||
}); | ||
return cleanup; | ||
}, [isResolved, props.forceReRender, props.fundingSource]); | ||
return React__default['default'].createElement("div", { ref: buttonsContainerRef }); | ||
} | ||
// @ts-expect-error - figure out setErrorState | ||
function hasValidGlobalStateForButtons({ components = "" }, setErrorState) { | ||
// @ts-expect-error - needs null checks | ||
if (typeof window.paypal.Buttons !== "undefined") { | ||
return true; | ||
} | ||
if (!hasValidGlobalStateForButtons(options, setErrorState)) { | ||
return cleanup; | ||
let errorMessage = "Unable to render <PayPalButtons /> because window.paypal.Buttons is undefined."; | ||
// the JS SDK includes the Buttons component by default when no 'components' are specified. | ||
// The 'buttons' component must be included in the 'components' list when using it with other components. | ||
if (components.length && !components.includes("buttons")) { | ||
const expectedComponents = `${components},buttons`; | ||
errorMessage += | ||
"\nTo fix the issue, add 'buttons' to the list of components passed to the parent PayPalScriptProvider:" + | ||
`\n\`<PayPalScriptProvider options={{ components: '${expectedComponents}'}}>\`.`; | ||
} | ||
buttons.current = window.paypal.Buttons({ ...props | ||
setErrorState(() => { | ||
throw new Error(errorMessage); | ||
}); | ||
if (!buttons.current.isEligible()) { | ||
return cleanup; | ||
} | ||
buttons.current.render(buttonsContainerRef.current).catch(err => { | ||
console.error(`Failed to render <PayPalButtons /> component. ${err}`); | ||
}); | ||
return cleanup; | ||
}, [isResolved, props.forceReRender, props.fundingSource]); | ||
return /*#__PURE__*/React__default['default'].createElement("div", { | ||
ref: buttonsContainerRef | ||
}); | ||
return false; | ||
} | ||
function hasValidGlobalStateForButtons({ | ||
components = "" | ||
}, setErrorState) { | ||
if (typeof window.paypal.Buttons !== "undefined") { | ||
return true; | ||
} | ||
let errorMessage = "Unable to render <PayPalButtons /> because window.paypal.Buttons is undefined."; // the JS SDK includes the Buttons component by default when no 'components' are specified. | ||
// The 'buttons' component must be included in the 'components' list when using it with other components. | ||
if (components.length && !components.includes("buttons")) { | ||
const expectedComponents = `${components},buttons`; | ||
errorMessage += "\nTo fix the issue, add 'buttons' to the list of components passed to the parent PayPalScriptProvider:" + `\n\`<PayPalScriptProvider options={{ components: '${expectedComponents}'}}>\`.`; | ||
} | ||
setErrorState(() => { | ||
throw new Error(errorMessage); | ||
}); | ||
return false; | ||
} | ||
PayPalButtons.propTypes = { | ||
/** | ||
* Sets up the transaction. Called when the buyer clicks the PayPal button. | ||
*/ | ||
createOrder: PropTypes__default['default'].func, | ||
/** | ||
* Deprecated, replaced by `createSubscription`. | ||
*/ | ||
createBillingAgreement: PropTypes__default['default'].func, | ||
/** | ||
* Sets up a subscription. Called when the buyer clicks the PayPal button. | ||
*/ | ||
createSubscription: PropTypes__default['default'].func, | ||
/** | ||
* The individual button to render. Use the `FUNDING` constant exported by this library to set this value. | ||
* View the [list of available funding sources](https://developer.paypal.com/docs/business/checkout/configure-payments/standalone-buttons/#funding-sources) for more info. | ||
*/ | ||
fundingSource: PropTypes__default['default'].string, | ||
/** | ||
* [Styling options](https://developer.paypal.com/docs/business/checkout/reference/style-guide/#customize-the-payment-buttons) for customizing layout, color, shape, and labels. | ||
*/ | ||
style: PropTypes__default['default'].exact({ | ||
color: PropTypes__default['default'].string, | ||
height: PropTypes__default['default'].number, | ||
label: PropTypes__default['default'].string, | ||
layout: PropTypes__default['default'].string, | ||
shape: PropTypes__default['default'].string, | ||
tagline: PropTypes__default['default'].bool | ||
}), | ||
/** | ||
* Finalizes the transaction. Often used to show the buyer a [confirmation page](https://developer.paypal.com/docs/checkout/integration-features/confirmation-page/). | ||
*/ | ||
onApprove: PropTypes__default['default'].func, | ||
/** | ||
* Called when the buyer cancels the transaction. | ||
* Often used to show the buyer a [cancellation page](https://developer.paypal.com/docs/business/checkout/add-capabilities/buyer-experience/#show-a-cancellation-page). | ||
*/ | ||
onCancel: PropTypes__default['default'].func, | ||
/** | ||
* Called when the button is clicked. Often used for [validation](https://developer.paypal.com/docs/checkout/integration-features/validation/). | ||
*/ | ||
onClick: PropTypes__default['default'].func, | ||
/** | ||
* Catch all for errors preventing buyer checkout. | ||
* Often used to show the buyer an [error page](https://developer.paypal.com/docs/checkout/integration-features/handle-errors/). | ||
*/ | ||
onError: PropTypes__default['default'].func, | ||
/** | ||
* Called when the button first renders. | ||
*/ | ||
onInit: PropTypes__default['default'].func, | ||
/** | ||
* Called when the buyer changes their shipping address on PayPal. | ||
*/ | ||
onShippingChange: PropTypes__default['default'].func, | ||
/** | ||
* Used to re-render the component. Changes to this prop will destroy | ||
* the existing Buttons and render them again using the current props. | ||
*/ | ||
forceReRender: PropTypes__default['default'].any | ||
/** | ||
* Sets up the transaction. Called when the buyer clicks the PayPal button. | ||
*/ | ||
createOrder: PropTypes__default['default'].func, | ||
/** | ||
* Deprecated, replaced by `createSubscription`. | ||
*/ | ||
createBillingAgreement: PropTypes__default['default'].func, | ||
/** | ||
* Sets up a subscription. Called when the buyer clicks the PayPal button. | ||
*/ | ||
createSubscription: PropTypes__default['default'].func, | ||
/** | ||
* The individual button to render. Use the `FUNDING` constant exported by this library to set this value. | ||
* View the [list of available funding sources](https://developer.paypal.com/docs/business/checkout/configure-payments/standalone-buttons/#funding-sources) for more info. | ||
*/ | ||
fundingSource: PropTypes__default['default'].string, | ||
/** | ||
* [Styling options](https://developer.paypal.com/docs/business/checkout/reference/style-guide/#customize-the-payment-buttons) for customizing layout, color, shape, and labels. | ||
*/ | ||
style: PropTypes__default['default'].exact({ | ||
color: PropTypes__default['default'].string, | ||
height: PropTypes__default['default'].number, | ||
label: PropTypes__default['default'].string, | ||
layout: PropTypes__default['default'].string, | ||
shape: PropTypes__default['default'].string, | ||
tagline: PropTypes__default['default'].bool, | ||
}), | ||
/** | ||
* Finalizes the transaction. Often used to show the buyer a [confirmation page](https://developer.paypal.com/docs/checkout/integration-features/confirmation-page/). | ||
*/ | ||
onApprove: PropTypes__default['default'].func, | ||
/** | ||
* Called when the buyer cancels the transaction. | ||
* Often used to show the buyer a [cancellation page](https://developer.paypal.com/docs/business/checkout/add-capabilities/buyer-experience/#show-a-cancellation-page). | ||
*/ | ||
onCancel: PropTypes__default['default'].func, | ||
/** | ||
* Called when the button is clicked. Often used for [validation](https://developer.paypal.com/docs/checkout/integration-features/validation/). | ||
*/ | ||
onClick: PropTypes__default['default'].func, | ||
/** | ||
* Catch all for errors preventing buyer checkout. | ||
* Often used to show the buyer an [error page](https://developer.paypal.com/docs/checkout/integration-features/handle-errors/). | ||
*/ | ||
onError: PropTypes__default['default'].func, | ||
/** | ||
* Called when the button first renders. | ||
*/ | ||
onInit: PropTypes__default['default'].func, | ||
/** | ||
* Called when the buyer changes their shipping address on PayPal. | ||
*/ | ||
onShippingChange: PropTypes__default['default'].func, | ||
/** | ||
* Used to re-render the component. Changes to this prop will destroy | ||
* the existing Buttons and render them again using the current props. | ||
*/ | ||
forceReRender: PropTypes__default['default'].any, | ||
}; | ||
PayPalButtons.defaultProps = { | ||
style: {} | ||
style: {}, | ||
}; | ||
@@ -717,84 +430,71 @@ | ||
*/ | ||
function PayPalMarks(props) { | ||
const [{ | ||
isResolved, | ||
options | ||
}] = usePayPalScriptReducer(); | ||
const markContainerRef = React.useRef(null); | ||
const mark = React.useRef(null); | ||
const [, setErrorState] = React.useState(null); | ||
React.useEffect(() => { | ||
if (!isResolved || mark.current) { | ||
return; | ||
const [{ isResolved, options }] = usePayPalScriptReducer(); | ||
const markContainerRef = React.useRef(null); | ||
const mark = React.useRef(null); | ||
const [, setErrorState] = React.useState(null); | ||
React.useEffect(() => { | ||
if (!isResolved || mark.current) { | ||
return; | ||
} | ||
if (!hasValidStateForMarks(options, setErrorState)) { | ||
return; | ||
} | ||
// @ts-expect-error - null checks | ||
mark.current = window.paypal.Marks({ ...props }); | ||
// @ts-expect-error - null checks | ||
if (!mark.current.isEligible()) { | ||
return; | ||
} | ||
// @ts-expect-error - null checks | ||
mark.current.render(markContainerRef.current).catch((err) => { | ||
console.error(`Failed to render <PayPalMarks /> component. ${err}`); | ||
}); | ||
}, [isResolved, props.fundingSource]); | ||
return React__default['default'].createElement("div", { ref: markContainerRef }); | ||
} | ||
// @ts-expect-error - figure out setErrorState | ||
function hasValidStateForMarks({ components = "" }, setErrorState) { | ||
// @ts-expect-error - needs null checks | ||
if (typeof window.paypal.Marks !== "undefined") { | ||
return true; | ||
} | ||
if (!hasValidStateForMarks(options, setErrorState)) { | ||
return; | ||
let errorMessage = "Unable to render <PayPalMarks /> because window.paypal.Marks is undefined."; | ||
// the JS SDK does not load the Marks component by default. It must be passed into the "components" query parameter. | ||
if (!components.includes("marks")) { | ||
const expectedComponents = components ? `${components},marks` : "marks"; | ||
errorMessage += | ||
"\nTo fix the issue, add 'marks' to the list of components passed to the parent PayPalScriptProvider:" + | ||
`\n\`<PayPalScriptProvider options={{ components: '${expectedComponents}'}}>\`.`; | ||
} | ||
mark.current = window.paypal.Marks({ ...props | ||
setErrorState(() => { | ||
throw new Error(errorMessage); | ||
}); | ||
if (!mark.current.isEligible()) { | ||
return; | ||
} | ||
mark.current.render(markContainerRef.current).catch(err => { | ||
console.error(`Failed to render <PayPalMarks /> component. ${err}`); | ||
}); | ||
}, [isResolved, props.fundingSource]); | ||
return /*#__PURE__*/React__default['default'].createElement("div", { | ||
ref: markContainerRef | ||
}); | ||
return false; | ||
} | ||
function hasValidStateForMarks({ | ||
components = "" | ||
}, setErrorState) { | ||
if (typeof window.paypal.Marks !== "undefined") { | ||
return true; | ||
} | ||
let errorMessage = "Unable to render <PayPalMarks /> because window.paypal.Marks is undefined."; // the JS SDK does not load the Marks component by default. It must be passed into the "components" query parameter. | ||
if (!components.includes("marks")) { | ||
const expectedComponents = components ? `${components},marks` : "marks"; | ||
errorMessage += "\nTo fix the issue, add 'marks' to the list of components passed to the parent PayPalScriptProvider:" + `\n\`<PayPalScriptProvider options={{ components: '${expectedComponents}'}}>\`.`; | ||
} | ||
setErrorState(() => { | ||
throw new Error(errorMessage); | ||
}); | ||
return false; | ||
} | ||
PayPalMarks.propTypes = { | ||
/** | ||
* The individual mark to render. Use the `FUNDING` constant exported by this library to set this value. | ||
* View the [list of available funding sources](https://developer.paypal.com/docs/business/checkout/configure-payments/standalone-buttons/#funding-sources) for more info. | ||
*/ | ||
fundingSource: PropTypes__default['default'].string | ||
/** | ||
* The individual mark to render. Use the `FUNDING` constant exported by this library to set this value. | ||
* View the [list of available funding sources](https://developer.paypal.com/docs/business/checkout/configure-payments/standalone-buttons/#funding-sources) for more info. | ||
*/ | ||
fundingSource: PropTypes__default['default'].string, | ||
}; | ||
function PayPalMessages(props) { | ||
const [{ | ||
isResolved | ||
}] = usePayPalScriptReducer(); | ||
const messagesContainerRef = React.useRef(null); | ||
const messages = React.useRef(null); | ||
React.useEffect(() => { | ||
if (!isResolved) { | ||
return; | ||
} | ||
messages.current = window.paypal.Messages({ ...props | ||
}); | ||
messages.current.render(messagesContainerRef.current).catch(err => { | ||
console.error(`Failed to render <PayPalMessages /> component. ${err}`); | ||
}); // eslint-disable-next-line react/prop-types | ||
}, [isResolved, props.forceReRender]); | ||
return /*#__PURE__*/React__default['default'].createElement("div", { | ||
ref: messagesContainerRef | ||
}); | ||
const [{ isResolved }] = usePayPalScriptReducer(); | ||
const messagesContainerRef = React.useRef(null); | ||
const messages = React.useRef(null); | ||
React.useEffect(() => { | ||
if (!isResolved) { | ||
return; | ||
} | ||
// @ts-expect-error - null checks | ||
messages.current = window.paypal.Messages({ ...props }); | ||
// @ts-expect-error - null checks | ||
messages.current.render(messagesContainerRef.current).catch((err) => { | ||
console.error(`Failed to render <PayPalMessages /> component. ${err}`); | ||
}); | ||
// eslint-disable-next-line react/prop-types | ||
}, [isResolved, props.forceReRender]); | ||
return React__default['default'].createElement("div", { ref: messagesContainerRef }); | ||
} | ||
@@ -801,0 +501,0 @@ |
{ | ||
"name": "@paypal/react-paypal-js", | ||
"version": "3.0.3", | ||
"version": "4.0.0-beta.1", | ||
"description": "React components for the PayPal JS SDK", | ||
@@ -16,2 +16,3 @@ "keywords": [ | ||
"module": "dist/react-paypal.esm.js", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
@@ -29,3 +30,4 @@ "build": "rollup --config", | ||
"release:minor": "node ./scripts/publish minor", | ||
"release:major": "node ./scripts/publish major" | ||
"release:major": "node ./scripts/publish major", | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
@@ -41,3 +43,3 @@ "files": [ | ||
"dependencies": { | ||
"@paypal/paypal-js": "^1.0.4", | ||
"@paypal/paypal-js": "^2.1.2", | ||
"@paypal/sdk-constants": "^1.0.77", | ||
@@ -50,5 +52,7 @@ "prop-types": "^15.7.2" | ||
"@babel/preset-react": "^7.12.5", | ||
"@babel/preset-typescript": "^7.12.7", | ||
"@rollup/plugin-babel": "^5.2.1", | ||
"@rollup/plugin-node-resolve": "^10.0.0", | ||
"@rollup/plugin-replace": "^2.3.4", | ||
"@rollup/plugin-typescript": "^8.1.0", | ||
"@storybook/addon-actions": "^6.0.28", | ||
@@ -60,2 +64,3 @@ "@storybook/addon-essentials": "^6.0.28", | ||
"@testing-library/react": "^11.1.2", | ||
"@types/react": "^17.0.0", | ||
"babel-jest": "^26.6.3", | ||
@@ -75,3 +80,4 @@ "babel-loader": "^8.2.1", | ||
"rollup": "^2.33.1", | ||
"shelljs": "^0.8.4" | ||
"shelljs": "^0.8.4", | ||
"typescript": "^4.1.3" | ||
}, | ||
@@ -78,0 +84,0 @@ "peerDependencies": { |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
10
67411
31
1036
2
+ Added@paypal/paypal-js@2.1.9(transitive)
- Removed@paypal/paypal-js@1.0.5(transitive)
Updated@paypal/paypal-js@^2.1.2