lightning-auth-and-payment
Version:
Lightning Network authentication and payment processing library for modern web applications
114 lines • 11.6 kB
JavaScript
;
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.LightningAuthModal = LightningAuthModal;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const lucide_react_1 = require("lucide-react");
const dialog_1 = require("./ui/dialog");
const button_1 = require("./ui/button");
const badge_1 = require("./ui/badge");
const QRCode_1 = require("./QRCode");
const formatting_1 = require("../utils/formatting");
const defaultWallets = [
{
name: 'Alby',
url: 'https://getalby.com/',
description: 'Browser extension for Lightning payments',
},
{
name: 'Zeus',
url: 'https://zeusln.app/',
description: 'Mobile Lightning wallet',
},
{
name: 'Phoenix',
url: 'https://phoenix.acinq.co/',
description: 'Non-custodial Lightning wallet',
},
{
name: 'Breez',
url: 'https://breez.technology/',
description: 'Lightning wallet with podcast support',
},
];
function LightningAuthModal({ isOpen, onClose, lnurl, error, isLoading, onRetry, qrCodeSize = 200, className, qrCodeComponent, title = 'Lightning Authentication', description = 'Authenticate using your Lightning wallet', showWalletRecommendations = true, wallets = defaultWallets, autoCloseOnSuccess = false, onSuccess, }) {
const [copied, setCopied] = (0, react_1.useState)(false);
const [showWallets, setShowWallets] = (0, react_1.useState)(false);
const modalRef = (0, react_1.useRef)(null);
// Handle ESC key press
(0, react_1.useEffect)(() => {
const handleEscKey = (event) => {
if (event.key === 'Escape') {
onClose();
}
};
if (isOpen) {
document.addEventListener('keydown', handleEscKey);
// Prevent body scroll when modal is open
document.body.style.overflow = 'hidden';
// Focus the modal for accessibility
setTimeout(() => {
modalRef.current?.focus();
}, 100);
}
return () => {
document.removeEventListener('keydown', handleEscKey);
document.body.style.overflow = 'unset';
};
}, [isOpen, onClose]);
// Auto-close on success
(0, react_1.useEffect)(() => {
if (autoCloseOnSuccess && !isLoading && !error && lnurl) {
const timer = setTimeout(() => {
onSuccess?.();
onClose();
}, 2000);
return () => clearTimeout(timer);
}
}, [autoCloseOnSuccess, isLoading, error, lnurl, onSuccess, onClose]);
const handleCopyLink = async () => {
if (lnurl) {
try {
await navigator.clipboard.writeText(lnurl);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
catch (err) {
console.error('Failed to copy link:', err);
}
}
};
const getStatusIcon = () => {
if (error) {
return (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-8 h-8 text-red-500" });
}
if (isLoading) {
return (0, jsx_runtime_1.jsx)(lucide_react_1.Clock, { className: "w-8 h-8 text-orange-500 animate-pulse" });
}
if (lnurl) {
return (0, jsx_runtime_1.jsx)(lucide_react_1.Zap, { className: "w-8 h-8 text-orange-500" });
}
return (0, jsx_runtime_1.jsx)(lucide_react_1.Wallet, { className: "w-8 h-8 text-slate-400" });
};
const getStatusMessage = () => {
if (error)
return error;
if (isLoading)
return 'Generating authentication link...';
if (lnurl)
return 'Scan QR code or copy the link below';
return 'Preparing authentication...';
};
const getStatusColor = () => {
if (error)
return 'text-red-500';
if (isLoading)
return 'text-orange-500';
if (lnurl)
return 'text-green-500';
return 'text-slate-400';
};
return ((0, jsx_runtime_1.jsx)(dialog_1.Dialog, { open: isOpen, onOpenChange: onClose, children: (0, jsx_runtime_1.jsxs)(dialog_1.DialogContent, { className: (0, formatting_1.cn)('max-w-md w-full max-h-[90vh] overflow-y-auto', 'bg-slate-900/95 backdrop-blur-md border-slate-700/50', className), ref: modalRef, tabIndex: -1, children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogHeader, { className: "space-y-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-2 bg-orange-500/20 rounded-lg", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Zap, { className: "w-6 h-6 text-orange-500" }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogTitle, { className: "text-xl font-bold text-white", children: title }), (0, jsx_runtime_1.jsx)(dialog_1.DialogDescription, { className: "text-slate-300", children: description })] })] }), (0, jsx_runtime_1.jsx)(badge_1.Badge, { variant: "secondary", className: "bg-slate-800 text-slate-300", children: "Lightning" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: getStatusIcon() }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("p", { className: (0, formatting_1.cn)('font-medium', getStatusColor()), children: getStatusMessage() }), lnurl && ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-slate-400", children: "Waiting for authentication..." }))] })] }), error && onRetry && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-red-500/10 border border-red-500/20 rounded-lg p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-2 text-red-400", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: "Authentication Failed" })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-red-300 text-sm mt-2", children: error })] }), (0, jsx_runtime_1.jsx)(button_1.Button, { onClick: onRetry, variant: "outline", className: "w-full border-red-500/20 text-red-400 hover:bg-red-500/10", children: "Try Again" })] })), lnurl && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-slate-800/50 rounded-lg p-4", children: [(0, jsx_runtime_1.jsxs)("h4", { className: "font-medium text-white mb-3 flex items-center space-x-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Wallet, { className: "w-4 h-4" }), (0, jsx_runtime_1.jsx)("span", { children: "How to authenticate:" })] }), (0, jsx_runtime_1.jsxs)("ol", { className: "text-sm text-slate-300 space-y-2", children: [(0, jsx_runtime_1.jsxs)("li", { className: "flex items-start space-x-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "bg-orange-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5", children: "1" }), (0, jsx_runtime_1.jsx)("span", { children: "Scan the QR code with your Lightning wallet" })] }), (0, jsx_runtime_1.jsxs)("li", { className: "flex items-start space-x-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "bg-orange-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5", children: "2" }), (0, jsx_runtime_1.jsx)("span", { children: "Or copy the login link below" })] }), (0, jsx_runtime_1.jsxs)("li", { className: "flex items-start space-x-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "bg-orange-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5", children: "3" }), (0, jsx_runtime_1.jsx)("span", { children: "Confirm the authentication in your wallet" })] }), (0, jsx_runtime_1.jsxs)("li", { className: "flex items-start space-x-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "bg-orange-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5", children: "4" }), (0, jsx_runtime_1.jsx)("span", { children: "You'll be logged in automatically" })] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "bg-white p-4 rounded-lg flex items-center justify-center", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [qrCodeComponent ? (qrCodeComponent({ lnurl, size: Math.min(qrCodeSize, 180) })) : ((0, jsx_runtime_1.jsx)(QRCode_1.QRCode, { value: lnurl, size: Math.min(qrCodeSize, 180), level: "M", className: "mx-auto" })), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-slate-500 mt-2", children: "Scan with Lightning wallet" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-slate-800/50 p-3 rounded-lg", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-slate-400 font-medium", children: "Login Link:" }), (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "ghost", size: "sm", onClick: handleCopyLink, className: "h-6 px-2 text-xs", children: copied ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3 h-3 mr-1" }), "Copied!"] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "w-3 h-3 mr-1" }), "Copy"] })) })] }), (0, jsx_runtime_1.jsx)("code", { className: "text-xs text-slate-300 break-all block hyphens-auto overflow-wrap-anywhere", children: lnurl })] }), showWalletRecommendations && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-white", children: "Don't have a Lightning wallet?" }), (0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "ghost", size: "sm", onClick: () => setShowWallets(!showWallets), className: "text-xs", children: [showWallets ? 'Hide' : 'Show', " Options"] })] }), showWallets && ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 gap-2", children: wallets.map((wallet, index) => ((0, jsx_runtime_1.jsx)("a", { href: wallet.url, target: "_blank", rel: "noopener noreferrer", className: "bg-slate-800/50 hover:bg-slate-700/50 p-3 rounded-lg transition-colors group", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-6 h-6 bg-orange-500/20 rounded flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Zap, { className: "w-3 h-3 text-orange-500" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs font-medium text-white truncate", children: wallet.name }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-slate-400 truncate", children: wallet.description })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "w-3 h-3 text-slate-400 group-hover:text-slate-300" })] }) }, index))) }))] }))] }))] })] }) }));
}
//# sourceMappingURL=LightningAuthModal.js.map