feat: enhance StripePaymentDialog with document handling and portal rendering
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* 后端当前返回 PaymentIntent clientSecret,因此这里直接用它完成前端确认。
|
||||
*/
|
||||
import { useState, type FormEvent } from "react";
|
||||
import { useEffect, useState, type FormEvent } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import {
|
||||
Elements,
|
||||
PaymentElement,
|
||||
@@ -35,8 +36,24 @@ export function StripePaymentDialog({
|
||||
onClose,
|
||||
onConfirmed,
|
||||
}: StripePaymentDialogProps) {
|
||||
if (!stripePromise) {
|
||||
return (
|
||||
useEffect(() => {
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
const prevOverflow = document.body.style.overflow;
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") onClose();
|
||||
};
|
||||
|
||||
document.body.style.overflow = "hidden";
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = prevOverflow;
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [onClose]);
|
||||
|
||||
const dialog = !stripePromise ? (
|
||||
<div className={styles.overlay} role="alertdialog" aria-modal="true">
|
||||
<div className={styles.dialog}>
|
||||
<div className={styles.header}>
|
||||
@@ -56,10 +73,7 @@ export function StripePaymentDialog({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
) : (
|
||||
<div
|
||||
className={styles.overlay}
|
||||
role="dialog"
|
||||
@@ -95,6 +109,10 @@ export function StripePaymentDialog({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (typeof document === "undefined") return null;
|
||||
|
||||
return createPortal(dialog, document.body);
|
||||
}
|
||||
|
||||
function StripePaymentForm({
|
||||
|
||||
Reference in New Issue
Block a user