UNPKG

lightning-auth-and-payment

Version:

Lightning Network authentication and payment processing library for modern web applications

114 lines 11.6 kB
"use strict"; '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