@xpayeg/react 1.0.0 → 2.0.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 +45 -0
- package/README.md +3 -54
- package/dist/index.cjs +2 -69
- package/dist/index.d.cts +4 -39
- package/dist/index.d.mts +4 -39
- package/dist/index.mjs +3 -69
- package/package.json +18 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# @xpayeg/react
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
### Major Changes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- [#331](https://github.com/xpayeg/xpay/pull/331) [`bdc6a48`](https://github.com/xpayeg/xpay/commit/bdc6a4865f8c0326a4c0eb3dd20808e1207d682a) Thanks [@Elmosh](https://github.com/Elmosh)! - **Breaking:** `returnUrl` is removed from `confirmPayment()` options. The return destination is always the checkout session's `afterCompletion.redirect.url`, set server-side at session creation.
|
|
9
|
+
|
|
10
|
+
The URL is sent to the bank during authentication, before the browser leaves your page, so a value passed at confirm time could only ever conflict with what the bank already received. Delete `returnUrl` from `confirmPayment()` and set `afterCompletion.redirect.url` on `createSession`. `redirect: "always"` now follows that destination.
|
|
11
|
+
|
|
12
|
+
**Breaking:** `afterCompletion` is now required for `uiMode: "embedded"` and `uiMode: "custom"`, and must be `type: "redirect"`. That URL is where the bank returns when authentication takes over the full page, which happens in in-app browsers where an embedded challenge cannot run. `hosted_confirmation` is rejected for these modes since those integrations run on your own site and there is no XPay page to return to.
|
|
13
|
+
|
|
14
|
+
Also fixed: the 3DS challenge now renders at the size declared to the issuer (previously cropped or oversized), the overlay waits for the issuer's page to paint instead of showing an empty frame, and a challenge that cannot run in an iframe takes over the full tab instead of failing silently.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
- [#333](https://github.com/xpayeg/xpay/pull/333) [`3dcea81`](https://github.com/xpayeg/xpay/commit/3dcea81b3e3f67267624105560c38f2615c35d96) Thanks [@Elmosh](https://github.com/Elmosh)! - Documentation: the `redirect: "always"` tables and examples now state that the destination is the checkout session's `afterCompletion.redirect.url`, set server-side at session creation.
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`3dcea81`](https://github.com/xpayeg/xpay/commit/3dcea81b3e3f67267624105560c38f2615c35d96), [`bdc6a48`](https://github.com/xpayeg/xpay/commit/bdc6a4865f8c0326a4c0eb3dd20808e1207d682a)]:
|
|
23
|
+
- @xpayeg/sdk@2.0.0
|
|
24
|
+
|
|
25
|
+
## 1.0.1
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
- [#103](https://github.com/xpayeg/xpay/pull/103) [`7402e27`](https://github.com/xpayeg/xpay/commit/7402e27cde482148f126b2073694ef38386ea87a) Thanks [@Elmosh](https://github.com/Elmosh)! - Remove `CardElement` from both SDKs — `PaymentElement` is the only supported element going forward. It handles every payment method (Card, ValU, Fawry, etc.) through one unified UI and renders the appropriate fields based on the customer's choice.
|
|
31
|
+
|
|
32
|
+
This release also republishes both packages through the proper `pnpm publish` flow, which fixes the `workspace:*` protocol leak in 1.0.0's `devDependencies` and `peerDependencies`. `npm install @xpayeg/sdk` and `npm install @xpayeg/react` now work cleanly.
|
|
33
|
+
|
|
34
|
+
**Migration:** replace `elements.create("card")` with `elements.create("payment")`. If you previously rendered `<CardElement>` only when the user selected "Card" from your own picker, switch to `<PaymentElement>` which provides both the picker and the card form together.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// Before
|
|
38
|
+
const cardElement = elements.create("card");
|
|
39
|
+
cardElement.mount("#card");
|
|
40
|
+
|
|
41
|
+
// After
|
|
42
|
+
const paymentElement = elements.create("payment");
|
|
43
|
+
paymentElement.mount("#payment");
|
|
44
|
+
```
|
|
45
|
+
- Updated dependencies [[`7402e27`](https://github.com/xpayeg/xpay/commit/7402e27cde482148f126b2073694ef38386ea87a)]:
|
|
46
|
+
- @xpayeg/sdk@1.0.1
|
|
47
|
+
|
|
3
48
|
## 1.0.0
|
|
4
49
|
### Major Changes
|
|
5
50
|
|
package/README.md
CHANGED
|
@@ -633,14 +633,6 @@ Renders the payment method selector and card form.
|
|
|
633
633
|
| `className` | `string` | CSS class for the container div |
|
|
634
634
|
| `id` | `string` | ID for the container div |
|
|
635
635
|
|
|
636
|
-
### `<CardElement>`
|
|
637
|
-
|
|
638
|
-
Card form only (no payment method selector).
|
|
639
|
-
|
|
640
|
-
```tsx
|
|
641
|
-
<CardElement onChange={(e) => console.log(e.complete, e.value.brand)} />
|
|
642
|
-
```
|
|
643
|
-
|
|
644
636
|
### `<CheckoutButton>`
|
|
645
637
|
|
|
646
638
|
Opens the drop-in checkout modal on click.
|
|
@@ -680,44 +672,6 @@ A button that opens the full checkout in a modal overlay. No form needed.
|
|
|
680
672
|
</XPayProvider>
|
|
681
673
|
```
|
|
682
674
|
|
|
683
|
-
### Card Element with Custom Payment Method Selector
|
|
684
|
-
|
|
685
|
-
Build your own selector. Mount card form only when "Card" is selected.
|
|
686
|
-
|
|
687
|
-
```tsx
|
|
688
|
-
function CustomCheckout() {
|
|
689
|
-
const checkoutState = useCheckout();
|
|
690
|
-
const [method, setMethod] = useState("card");
|
|
691
|
-
|
|
692
|
-
if (checkoutState.type !== "success") return <div>Loading...</div>;
|
|
693
|
-
|
|
694
|
-
const { checkout } = checkoutState;
|
|
695
|
-
|
|
696
|
-
return (
|
|
697
|
-
<div>
|
|
698
|
-
<div className="flex gap-2">
|
|
699
|
-
{checkout.paymentMethods.map((pm) => (
|
|
700
|
-
<button
|
|
701
|
-
key={pm.type}
|
|
702
|
-
onClick={() => setMethod(pm.type)}
|
|
703
|
-
className={method === pm.type ? "border-blue-500 border-2" : "border-gray-200 border"}
|
|
704
|
-
>
|
|
705
|
-
{pm.displayName}
|
|
706
|
-
</button>
|
|
707
|
-
))}
|
|
708
|
-
</div>
|
|
709
|
-
|
|
710
|
-
{method === "card" && <CardElement />}
|
|
711
|
-
{method !== "card" && <p>You will complete payment in a secure form.</p>}
|
|
712
|
-
|
|
713
|
-
<button onClick={() => checkout.confirm({ paymentMethod: method })}>
|
|
714
|
-
{method === "card" ? "Pay" : `Continue with ${method}`}
|
|
715
|
-
</button>
|
|
716
|
-
</div>
|
|
717
|
-
);
|
|
718
|
-
}
|
|
719
|
-
```
|
|
720
|
-
|
|
721
675
|
### Dark Mode Toggle
|
|
722
676
|
|
|
723
677
|
Sync XPay appearance with your site's theme at runtime using `changeAppearance()`.
|
|
@@ -754,21 +708,16 @@ await checkout.confirm({
|
|
|
754
708
|
redirect: "always",
|
|
755
709
|
});
|
|
756
710
|
// ^ If successful, the page navigates away. Code below only runs on error.
|
|
757
|
-
|
|
758
|
-
// Override the redirect URL from the client:
|
|
759
|
-
await checkout.confirm({
|
|
760
|
-
customerDetails: { email, name },
|
|
761
|
-
redirect: "always",
|
|
762
|
-
returnUrl: "https://mysite.com/custom-success",
|
|
763
|
-
});
|
|
764
711
|
```
|
|
765
712
|
|
|
766
713
|
| `redirect` | Behavior |
|
|
767
714
|
|---|---|
|
|
768
715
|
| Not set (default) | `"if_required"` — returns result to your code |
|
|
769
|
-
| `"always"` | Redirects to
|
|
716
|
+
| `"always"` | Redirects to the session's `afterCompletion.redirect.url` |
|
|
770
717
|
| `"if_required"` | Returns result to your code — no redirect |
|
|
771
718
|
|
|
719
|
+
Your server sets that URL when it creates the session. XPay navigates there unchanged, appending nothing.
|
|
720
|
+
|
|
772
721
|
---
|
|
773
722
|
|
|
774
723
|
## Appearance
|
package/dist/index.cjs
CHANGED
|
@@ -388,7 +388,7 @@ function isEqual(a, b) {
|
|
|
388
388
|
const isServer = typeof window === "undefined";
|
|
389
389
|
//#endregion
|
|
390
390
|
//#region src/PaymentElement.tsx
|
|
391
|
-
const IMMUTABLE_OPTS
|
|
391
|
+
const IMMUTABLE_OPTS = [];
|
|
392
392
|
const PaymentElementClient = ({ options, onReady, onChange, onLoaderStart, onLoadError, className, id }) => {
|
|
393
393
|
const elements = useElements();
|
|
394
394
|
const containerRef = (0, react.useRef)(null);
|
|
@@ -415,7 +415,7 @@ const PaymentElementClient = ({ options, onReady, onChange, onLoaderStart, onLoa
|
|
|
415
415
|
}, []);
|
|
416
416
|
(0, react.useEffect)(() => {
|
|
417
417
|
if (!element || !options) return;
|
|
418
|
-
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS
|
|
418
|
+
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS);
|
|
419
419
|
if (updates && "update" in element) element.update(updates);
|
|
420
420
|
}, [
|
|
421
421
|
options,
|
|
@@ -457,72 +457,6 @@ const PaymentElementServer = ({ className, id }) => {
|
|
|
457
457
|
*/
|
|
458
458
|
const PaymentElement = isServer ? PaymentElementServer : PaymentElementClient;
|
|
459
459
|
//#endregion
|
|
460
|
-
//#region src/CardElement.tsx
|
|
461
|
-
const IMMUTABLE_OPTS = [];
|
|
462
|
-
const CardElementClient = ({ options, onReady, onChange, onLoaderStart, onLoadError, className, id }) => {
|
|
463
|
-
const elements = useElements();
|
|
464
|
-
const containerRef = (0, react.useRef)(null);
|
|
465
|
-
const elementRef = (0, react.useRef)(null);
|
|
466
|
-
const [element, setElement] = (0, react.useState)(null);
|
|
467
|
-
const prevOptions = usePrevious(options);
|
|
468
|
-
(0, react.useLayoutEffect)(() => {
|
|
469
|
-
if (elementRef.current !== null || !elements || !containerRef.current) return;
|
|
470
|
-
const el = elements.create("card", options);
|
|
471
|
-
elementRef.current = el;
|
|
472
|
-
setElement(el);
|
|
473
|
-
el.mount(containerRef.current);
|
|
474
|
-
}, [elements]);
|
|
475
|
-
(0, react.useLayoutEffect)(() => {
|
|
476
|
-
return () => {
|
|
477
|
-
if (elementRef.current) {
|
|
478
|
-
try {
|
|
479
|
-
elementRef.current.destroy();
|
|
480
|
-
} catch {}
|
|
481
|
-
elementRef.current = null;
|
|
482
|
-
}
|
|
483
|
-
setElement(null);
|
|
484
|
-
};
|
|
485
|
-
}, []);
|
|
486
|
-
(0, react.useEffect)(() => {
|
|
487
|
-
if (!element || !options) return;
|
|
488
|
-
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS);
|
|
489
|
-
if (updates && "update" in element) element.update(updates);
|
|
490
|
-
}, [
|
|
491
|
-
options,
|
|
492
|
-
prevOptions,
|
|
493
|
-
element
|
|
494
|
-
]);
|
|
495
|
-
useAttachEvent(element, "ready", onReady);
|
|
496
|
-
useAttachEvent(element, "change", onChange);
|
|
497
|
-
useAttachEvent(element, "loaderstart", onLoaderStart);
|
|
498
|
-
useAttachEvent(element, "loaderror", onLoadError);
|
|
499
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
500
|
-
ref: containerRef,
|
|
501
|
-
className,
|
|
502
|
-
id
|
|
503
|
-
});
|
|
504
|
-
};
|
|
505
|
-
const CardElementServer = ({ className, id }) => {
|
|
506
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
507
|
-
className,
|
|
508
|
-
id
|
|
509
|
-
});
|
|
510
|
-
};
|
|
511
|
-
/**
|
|
512
|
-
* Renders the XPay Card Element — a card-only form (number, expiry, CVV).
|
|
513
|
-
*
|
|
514
|
-
* Use this when you handle payment method selection yourself.
|
|
515
|
-
* Must be used inside `<XPayProvider>` with an `options` prop containing `clientSecret`.
|
|
516
|
-
*
|
|
517
|
-
* @example
|
|
518
|
-
* ```tsx
|
|
519
|
-
* <CardElement
|
|
520
|
-
* onChange={(e) => setCardReady(e.complete)}
|
|
521
|
-
* />
|
|
522
|
-
* ```
|
|
523
|
-
*/
|
|
524
|
-
const CardElement = isServer ? CardElementServer : CardElementClient;
|
|
525
|
-
//#endregion
|
|
526
460
|
//#region src/CheckoutButton.tsx
|
|
527
461
|
/**
|
|
528
462
|
* Button that opens the drop-in checkout modal on click.
|
|
@@ -566,7 +500,6 @@ const CheckoutButton = ({ clientSecret, children = "Pay", checkoutOptions, class
|
|
|
566
500
|
});
|
|
567
501
|
};
|
|
568
502
|
//#endregion
|
|
569
|
-
exports.CardElement = CardElement;
|
|
570
503
|
exports.CheckoutButton = CheckoutButton;
|
|
571
504
|
exports.PaymentElement = PaymentElement;
|
|
572
505
|
exports.XPayProvider = XPayProvider;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, FC } from 'react';
|
|
3
3
|
import * as _xpayeg_sdk from '@xpayeg/sdk';
|
|
4
|
-
import { CheckoutSession, CheckoutActions, XPayInstance, ElementsOptions, Elements, PaymentElementOptions, PaymentElementChangeEvent,
|
|
5
|
-
export { ActionResult, Appearance,
|
|
4
|
+
import { CheckoutSession, CheckoutActions, XPayInstance, ElementsOptions, Elements, PaymentElementOptions, PaymentElementChangeEvent, CheckoutOptions } from '@xpayeg/sdk';
|
|
5
|
+
export { ActionResult, Appearance, CheckoutActions, CheckoutSession, ConfirmPaymentOptions, ElementsOptions, PaymentElementChangeEvent, PaymentMethodInfo, XPayError } from '@xpayeg/sdk';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The checkout object returned by `useCheckout()` on success.
|
|
@@ -168,41 +168,6 @@ interface PaymentElementProps {
|
|
|
168
168
|
*/
|
|
169
169
|
declare const PaymentElement: FC<PaymentElementProps>;
|
|
170
170
|
|
|
171
|
-
interface CardElementProps {
|
|
172
|
-
/** Element configuration options */
|
|
173
|
-
options?: CardElementOptions;
|
|
174
|
-
/** Fired when the element is mounted and the iframe content is ready */
|
|
175
|
-
onReady?: () => void;
|
|
176
|
-
/** Fired on every card field change — use `event.complete` to enable/disable your pay button */
|
|
177
|
-
onChange?: (event: CardElementChangeEvent) => void;
|
|
178
|
-
/** Fired when the element's iframe starts loading */
|
|
179
|
-
onLoaderStart?: () => void;
|
|
180
|
-
/** Fired when the element fails to load */
|
|
181
|
-
onLoadError?: (event: {
|
|
182
|
-
type: string;
|
|
183
|
-
message: string;
|
|
184
|
-
code?: string;
|
|
185
|
-
}) => void;
|
|
186
|
-
/** CSS class name for the container `<div>` */
|
|
187
|
-
className?: string;
|
|
188
|
-
/** HTML id for the container `<div>` */
|
|
189
|
-
id?: string;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Renders the XPay Card Element — a card-only form (number, expiry, CVV).
|
|
193
|
-
*
|
|
194
|
-
* Use this when you handle payment method selection yourself.
|
|
195
|
-
* Must be used inside `<XPayProvider>` with an `options` prop containing `clientSecret`.
|
|
196
|
-
*
|
|
197
|
-
* @example
|
|
198
|
-
* ```tsx
|
|
199
|
-
* <CardElement
|
|
200
|
-
* onChange={(e) => setCardReady(e.complete)}
|
|
201
|
-
* />
|
|
202
|
-
* ```
|
|
203
|
-
*/
|
|
204
|
-
declare const CardElement: FC<CardElementProps>;
|
|
205
|
-
|
|
206
171
|
interface CheckoutButtonProps {
|
|
207
172
|
/** Checkout session client secret */
|
|
208
173
|
clientSecret: string;
|
|
@@ -235,5 +200,5 @@ interface CheckoutButtonProps {
|
|
|
235
200
|
*/
|
|
236
201
|
declare const CheckoutButton: FC<CheckoutButtonProps>;
|
|
237
202
|
|
|
238
|
-
export {
|
|
239
|
-
export type {
|
|
203
|
+
export { CheckoutButton, PaymentElement, XPayProvider, useCheckout, useConfirmPayment, useElements, useXPay };
|
|
204
|
+
export type { Checkout, CheckoutButtonProps, PaymentElementProps, UseCheckoutResult };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, FC } from 'react';
|
|
3
3
|
import * as _xpayeg_sdk from '@xpayeg/sdk';
|
|
4
|
-
import { CheckoutSession, CheckoutActions, XPayInstance, ElementsOptions, Elements, PaymentElementOptions, PaymentElementChangeEvent,
|
|
5
|
-
export { ActionResult, Appearance,
|
|
4
|
+
import { CheckoutSession, CheckoutActions, XPayInstance, ElementsOptions, Elements, PaymentElementOptions, PaymentElementChangeEvent, CheckoutOptions } from '@xpayeg/sdk';
|
|
5
|
+
export { ActionResult, Appearance, CheckoutActions, CheckoutSession, ConfirmPaymentOptions, ElementsOptions, PaymentElementChangeEvent, PaymentMethodInfo, XPayError } from '@xpayeg/sdk';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The checkout object returned by `useCheckout()` on success.
|
|
@@ -168,41 +168,6 @@ interface PaymentElementProps {
|
|
|
168
168
|
*/
|
|
169
169
|
declare const PaymentElement: FC<PaymentElementProps>;
|
|
170
170
|
|
|
171
|
-
interface CardElementProps {
|
|
172
|
-
/** Element configuration options */
|
|
173
|
-
options?: CardElementOptions;
|
|
174
|
-
/** Fired when the element is mounted and the iframe content is ready */
|
|
175
|
-
onReady?: () => void;
|
|
176
|
-
/** Fired on every card field change — use `event.complete` to enable/disable your pay button */
|
|
177
|
-
onChange?: (event: CardElementChangeEvent) => void;
|
|
178
|
-
/** Fired when the element's iframe starts loading */
|
|
179
|
-
onLoaderStart?: () => void;
|
|
180
|
-
/** Fired when the element fails to load */
|
|
181
|
-
onLoadError?: (event: {
|
|
182
|
-
type: string;
|
|
183
|
-
message: string;
|
|
184
|
-
code?: string;
|
|
185
|
-
}) => void;
|
|
186
|
-
/** CSS class name for the container `<div>` */
|
|
187
|
-
className?: string;
|
|
188
|
-
/** HTML id for the container `<div>` */
|
|
189
|
-
id?: string;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Renders the XPay Card Element — a card-only form (number, expiry, CVV).
|
|
193
|
-
*
|
|
194
|
-
* Use this when you handle payment method selection yourself.
|
|
195
|
-
* Must be used inside `<XPayProvider>` with an `options` prop containing `clientSecret`.
|
|
196
|
-
*
|
|
197
|
-
* @example
|
|
198
|
-
* ```tsx
|
|
199
|
-
* <CardElement
|
|
200
|
-
* onChange={(e) => setCardReady(e.complete)}
|
|
201
|
-
* />
|
|
202
|
-
* ```
|
|
203
|
-
*/
|
|
204
|
-
declare const CardElement: FC<CardElementProps>;
|
|
205
|
-
|
|
206
171
|
interface CheckoutButtonProps {
|
|
207
172
|
/** Checkout session client secret */
|
|
208
173
|
clientSecret: string;
|
|
@@ -235,5 +200,5 @@ interface CheckoutButtonProps {
|
|
|
235
200
|
*/
|
|
236
201
|
declare const CheckoutButton: FC<CheckoutButtonProps>;
|
|
237
202
|
|
|
238
|
-
export {
|
|
239
|
-
export type {
|
|
203
|
+
export { CheckoutButton, PaymentElement, XPayProvider, useCheckout, useConfirmPayment, useElements, useXPay };
|
|
204
|
+
export type { Checkout, CheckoutButtonProps, PaymentElementProps, UseCheckoutResult };
|
package/dist/index.mjs
CHANGED
|
@@ -387,7 +387,7 @@ function isEqual(a, b) {
|
|
|
387
387
|
const isServer = typeof window === "undefined";
|
|
388
388
|
//#endregion
|
|
389
389
|
//#region src/PaymentElement.tsx
|
|
390
|
-
const IMMUTABLE_OPTS
|
|
390
|
+
const IMMUTABLE_OPTS = [];
|
|
391
391
|
const PaymentElementClient = ({ options, onReady, onChange, onLoaderStart, onLoadError, className, id }) => {
|
|
392
392
|
const elements = useElements();
|
|
393
393
|
const containerRef = useRef(null);
|
|
@@ -414,7 +414,7 @@ const PaymentElementClient = ({ options, onReady, onChange, onLoaderStart, onLoa
|
|
|
414
414
|
}, []);
|
|
415
415
|
useEffect(() => {
|
|
416
416
|
if (!element || !options) return;
|
|
417
|
-
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS
|
|
417
|
+
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS);
|
|
418
418
|
if (updates && "update" in element) element.update(updates);
|
|
419
419
|
}, [
|
|
420
420
|
options,
|
|
@@ -456,72 +456,6 @@ const PaymentElementServer = ({ className, id }) => {
|
|
|
456
456
|
*/
|
|
457
457
|
const PaymentElement = isServer ? PaymentElementServer : PaymentElementClient;
|
|
458
458
|
//#endregion
|
|
459
|
-
//#region src/CardElement.tsx
|
|
460
|
-
const IMMUTABLE_OPTS = [];
|
|
461
|
-
const CardElementClient = ({ options, onReady, onChange, onLoaderStart, onLoadError, className, id }) => {
|
|
462
|
-
const elements = useElements();
|
|
463
|
-
const containerRef = useRef(null);
|
|
464
|
-
const elementRef = useRef(null);
|
|
465
|
-
const [element, setElement] = useState(null);
|
|
466
|
-
const prevOptions = usePrevious(options);
|
|
467
|
-
useLayoutEffect(() => {
|
|
468
|
-
if (elementRef.current !== null || !elements || !containerRef.current) return;
|
|
469
|
-
const el = elements.create("card", options);
|
|
470
|
-
elementRef.current = el;
|
|
471
|
-
setElement(el);
|
|
472
|
-
el.mount(containerRef.current);
|
|
473
|
-
}, [elements]);
|
|
474
|
-
useLayoutEffect(() => {
|
|
475
|
-
return () => {
|
|
476
|
-
if (elementRef.current) {
|
|
477
|
-
try {
|
|
478
|
-
elementRef.current.destroy();
|
|
479
|
-
} catch {}
|
|
480
|
-
elementRef.current = null;
|
|
481
|
-
}
|
|
482
|
-
setElement(null);
|
|
483
|
-
};
|
|
484
|
-
}, []);
|
|
485
|
-
useEffect(() => {
|
|
486
|
-
if (!element || !options) return;
|
|
487
|
-
const updates = extractAllowedOptionsUpdates(options, prevOptions, IMMUTABLE_OPTS);
|
|
488
|
-
if (updates && "update" in element) element.update(updates);
|
|
489
|
-
}, [
|
|
490
|
-
options,
|
|
491
|
-
prevOptions,
|
|
492
|
-
element
|
|
493
|
-
]);
|
|
494
|
-
useAttachEvent(element, "ready", onReady);
|
|
495
|
-
useAttachEvent(element, "change", onChange);
|
|
496
|
-
useAttachEvent(element, "loaderstart", onLoaderStart);
|
|
497
|
-
useAttachEvent(element, "loaderror", onLoadError);
|
|
498
|
-
return /* @__PURE__ */ jsx("div", {
|
|
499
|
-
ref: containerRef,
|
|
500
|
-
className,
|
|
501
|
-
id
|
|
502
|
-
});
|
|
503
|
-
};
|
|
504
|
-
const CardElementServer = ({ className, id }) => {
|
|
505
|
-
return /* @__PURE__ */ jsx("div", {
|
|
506
|
-
className,
|
|
507
|
-
id
|
|
508
|
-
});
|
|
509
|
-
};
|
|
510
|
-
/**
|
|
511
|
-
* Renders the XPay Card Element — a card-only form (number, expiry, CVV).
|
|
512
|
-
*
|
|
513
|
-
* Use this when you handle payment method selection yourself.
|
|
514
|
-
* Must be used inside `<XPayProvider>` with an `options` prop containing `clientSecret`.
|
|
515
|
-
*
|
|
516
|
-
* @example
|
|
517
|
-
* ```tsx
|
|
518
|
-
* <CardElement
|
|
519
|
-
* onChange={(e) => setCardReady(e.complete)}
|
|
520
|
-
* />
|
|
521
|
-
* ```
|
|
522
|
-
*/
|
|
523
|
-
const CardElement = isServer ? CardElementServer : CardElementClient;
|
|
524
|
-
//#endregion
|
|
525
459
|
//#region src/CheckoutButton.tsx
|
|
526
460
|
/**
|
|
527
461
|
* Button that opens the drop-in checkout modal on click.
|
|
@@ -565,4 +499,4 @@ const CheckoutButton = ({ clientSecret, children = "Pay", checkoutOptions, class
|
|
|
565
499
|
});
|
|
566
500
|
};
|
|
567
501
|
//#endregion
|
|
568
|
-
export {
|
|
502
|
+
export { CheckoutButton, PaymentElement, XPayProvider, useCheckout, useConfirmPayment, useElements, useXPay };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xpayeg/react",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "XPay React components — PaymentElement,
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "XPay React components — PaymentElement, CheckoutButton, and hooks",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -32,30 +32,25 @@
|
|
|
32
32
|
"CHANGELOG.md",
|
|
33
33
|
"LICENSE"
|
|
34
34
|
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"build": "tsdown && rollup -c rollup.dts.config.mjs",
|
|
37
|
-
"lint:pkg": "publint && attw --pack .",
|
|
38
|
-
"typecheck": "tsc --noEmit"
|
|
39
|
-
},
|
|
40
35
|
"peerDependencies": {
|
|
41
|
-
"@xpayeg/sdk": "workspace:*",
|
|
42
36
|
"react": "^18 || ^19",
|
|
43
|
-
"react-dom": "^18 || ^19"
|
|
37
|
+
"react-dom": "^18 || ^19",
|
|
38
|
+
"@xpayeg/sdk": "2.0.0"
|
|
44
39
|
},
|
|
45
40
|
"devDependencies": {
|
|
46
41
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
47
42
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
48
|
-
"@types/react": "
|
|
49
|
-
"@types/react-dom": "
|
|
50
|
-
"@xpay/tsconfig": "workspace:*",
|
|
51
|
-
"@xpayeg/sdk": "workspace:*",
|
|
43
|
+
"@types/react": "19.2.7",
|
|
44
|
+
"@types/react-dom": "19.2.3",
|
|
52
45
|
"publint": "^0.3.21",
|
|
53
|
-
"react": "
|
|
54
|
-
"react-dom": "
|
|
46
|
+
"react": "^19.2.6",
|
|
47
|
+
"react-dom": "^19.2.6",
|
|
55
48
|
"rollup": "^4.60.4",
|
|
56
49
|
"rollup-plugin-dts": "^6.4.1",
|
|
57
50
|
"tsdown": "^0.22.0",
|
|
58
|
-
"typescript": "
|
|
51
|
+
"typescript": "5.9.3",
|
|
52
|
+
"@xpay/tsconfig": "0.0.0",
|
|
53
|
+
"@xpayeg/sdk": "2.0.0"
|
|
59
54
|
},
|
|
60
55
|
"repository": {
|
|
61
56
|
"type": "git",
|
|
@@ -72,5 +67,10 @@
|
|
|
72
67
|
"egypt",
|
|
73
68
|
"checkout",
|
|
74
69
|
"sdk"
|
|
75
|
-
]
|
|
76
|
-
|
|
70
|
+
],
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "tsdown && rollup -c rollup.dts.config.mjs",
|
|
73
|
+
"lint:pkg": "publint && attw --pack .",
|
|
74
|
+
"typecheck": "tsc --noEmit"
|
|
75
|
+
}
|
|
76
|
+
}
|