@xpayeg/react 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/index.cjs +26 -2
- package/dist/index.d.cts +7 -1
- package/dist/index.d.mts +7 -1
- package/dist/index.mjs +26 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @xpayeg/react
|
|
2
2
|
|
|
3
|
+
## 2.2.0
|
|
4
|
+
### Minor Changes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- [#462](https://github.com/xpayeg/xpay/pull/462) [`f083704`](https://github.com/xpayeg/xpay/commit/f08370434ff93c52450cfaee17f249c11b5cd46c) Thanks [@Elmosh](https://github.com/Elmosh)! - Deferred-mount Payment Element: `xpay.elements({ mode: "payment", amount, currency })` renders the payment form with no checkout session — your server creates the session with the final total when the customer clicks Pay, and its clientSecret is passed to `confirmPayment({ elements, clientSecret })` (a plain string). The session's total must equal the amount the element displays, or the confirmation fails with `amount_reconfirmation_required` and nothing is charged. Adds `elements.update({ amount, currency })` for deferred display updates. `XPayProvider` accepts the new options form; deferred amount/currency prop changes flow through `elements.update()` without recreating the instance. The existing `{ clientSecret }` path is unchanged.
|
|
9
|
+
|
|
10
|
+
Also in this release: the overlay scroll lock (3DS/action overlay and drop-in modal, now one shared implementation) pins the page at its measured geometry and preserves the scrollbar gutter, so centered boxed themes no longer shift when an overlay opens; `elements.fetchUpdates()` now genuinely re-fetches the session from the server (it previously answered from the iframe's local state; failures now resolve the error arm instead of returning stale data), and `CheckoutSession` gains optional `presentmentDetails` — the customer-facing amounts, present only when the merchant prices in a currency other than the processing currency. Read amounts presentment-first.
|
|
11
|
+
|
|
3
12
|
## 2.1.0
|
|
4
13
|
### Minor Changes
|
|
5
14
|
|
package/dist/index.cjs
CHANGED
|
@@ -64,10 +64,34 @@ function XPayProvider({ xpay: xpayProp, options, children }) {
|
|
|
64
64
|
cancelled = true;
|
|
65
65
|
};
|
|
66
66
|
}, [xpayProp]);
|
|
67
|
+
const clientSecretOpt = options && "clientSecret" in options ? options.clientSecret : void 0;
|
|
68
|
+
const modeOpt = options && "mode" in options ? options.mode : void 0;
|
|
67
69
|
const elements = (0, react.useMemo)(() => {
|
|
68
|
-
if (!resolvedXPay || !options
|
|
70
|
+
if (!resolvedXPay || !options) return null;
|
|
71
|
+
if (!clientSecretOpt && !modeOpt) return null;
|
|
69
72
|
return resolvedXPay.elements(options);
|
|
70
|
-
}, [
|
|
73
|
+
}, [
|
|
74
|
+
resolvedXPay,
|
|
75
|
+
clientSecretOpt,
|
|
76
|
+
modeOpt
|
|
77
|
+
]);
|
|
78
|
+
const lastDeferredRef = (0, react.useRef)(null);
|
|
79
|
+
(0, react.useEffect)(() => {
|
|
80
|
+
if (!elements || !options || !("mode" in options) || !options.mode) {
|
|
81
|
+
lastDeferredRef.current = null;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const prev = lastDeferredRef.current;
|
|
85
|
+
lastDeferredRef.current = {
|
|
86
|
+
amount: options.amount,
|
|
87
|
+
currency: options.currency
|
|
88
|
+
};
|
|
89
|
+
if (!prev) return;
|
|
90
|
+
const updates = {};
|
|
91
|
+
if (options.amount !== prev.amount) updates.amount = options.amount;
|
|
92
|
+
if (options.currency !== prev.currency) updates.currency = options.currency;
|
|
93
|
+
if (updates.amount !== void 0 || updates.currency !== void 0) elements.update(updates);
|
|
94
|
+
}, [elements, options]);
|
|
71
95
|
const [session, setSession] = (0, react.useState)(null);
|
|
72
96
|
const [sessionError, setSessionError] = (0, react.useState)(null);
|
|
73
97
|
(0, react.useEffect)(() => {
|
package/dist/index.d.cts
CHANGED
|
@@ -36,7 +36,13 @@ interface XPayProviderProps {
|
|
|
36
36
|
* Use `loadXPay()` from `@xpayeg/sdk` — call it at module level, not inside a component.
|
|
37
37
|
*/
|
|
38
38
|
xpay: XPayInstance | Promise<XPayInstance | null> | null;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Elements options — either `{ clientSecret }` (session-first) or
|
|
41
|
+
* `{ mode: "payment", amount, currency }` (deferred — the session is created
|
|
42
|
+
* by your server at confirm time). In deferred mode use `useElements()` +
|
|
43
|
+
* `<PaymentElement>`; `useCheckout()` session data reflects the display
|
|
44
|
+
* amount until a session is bound at confirm.
|
|
45
|
+
*/
|
|
40
46
|
options?: ElementsOptions;
|
|
41
47
|
children: ReactNode;
|
|
42
48
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -36,7 +36,13 @@ interface XPayProviderProps {
|
|
|
36
36
|
* Use `loadXPay()` from `@xpayeg/sdk` — call it at module level, not inside a component.
|
|
37
37
|
*/
|
|
38
38
|
xpay: XPayInstance | Promise<XPayInstance | null> | null;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Elements options — either `{ clientSecret }` (session-first) or
|
|
41
|
+
* `{ mode: "payment", amount, currency }` (deferred — the session is created
|
|
42
|
+
* by your server at confirm time). In deferred mode use `useElements()` +
|
|
43
|
+
* `<PaymentElement>`; `useCheckout()` session data reflects the display
|
|
44
|
+
* amount until a session is bound at confirm.
|
|
45
|
+
*/
|
|
40
46
|
options?: ElementsOptions;
|
|
41
47
|
children: ReactNode;
|
|
42
48
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -63,10 +63,34 @@ function XPayProvider({ xpay: xpayProp, options, children }) {
|
|
|
63
63
|
cancelled = true;
|
|
64
64
|
};
|
|
65
65
|
}, [xpayProp]);
|
|
66
|
+
const clientSecretOpt = options && "clientSecret" in options ? options.clientSecret : void 0;
|
|
67
|
+
const modeOpt = options && "mode" in options ? options.mode : void 0;
|
|
66
68
|
const elements = useMemo(() => {
|
|
67
|
-
if (!resolvedXPay || !options
|
|
69
|
+
if (!resolvedXPay || !options) return null;
|
|
70
|
+
if (!clientSecretOpt && !modeOpt) return null;
|
|
68
71
|
return resolvedXPay.elements(options);
|
|
69
|
-
}, [
|
|
72
|
+
}, [
|
|
73
|
+
resolvedXPay,
|
|
74
|
+
clientSecretOpt,
|
|
75
|
+
modeOpt
|
|
76
|
+
]);
|
|
77
|
+
const lastDeferredRef = useRef(null);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!elements || !options || !("mode" in options) || !options.mode) {
|
|
80
|
+
lastDeferredRef.current = null;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const prev = lastDeferredRef.current;
|
|
84
|
+
lastDeferredRef.current = {
|
|
85
|
+
amount: options.amount,
|
|
86
|
+
currency: options.currency
|
|
87
|
+
};
|
|
88
|
+
if (!prev) return;
|
|
89
|
+
const updates = {};
|
|
90
|
+
if (options.amount !== prev.amount) updates.amount = options.amount;
|
|
91
|
+
if (options.currency !== prev.currency) updates.currency = options.currency;
|
|
92
|
+
if (updates.amount !== void 0 || updates.currency !== void 0) elements.update(updates);
|
|
93
|
+
}, [elements, options]);
|
|
70
94
|
const [session, setSession] = useState(null);
|
|
71
95
|
const [sessionError, setSessionError] = useState(null);
|
|
72
96
|
useEffect(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xpayeg/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "XPay React components — PaymentElement, CheckoutButton, and hooks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"tsdown": "^0.22.0",
|
|
51
51
|
"typescript": "5.9.3",
|
|
52
52
|
"@xpay/tsconfig": "0.0.0",
|
|
53
|
-
"@xpayeg/sdk": "2.
|
|
53
|
+
"@xpayeg/sdk": "2.2.0"
|
|
54
54
|
},
|
|
55
55
|
"repository": {
|
|
56
56
|
"type": "git",
|