UNPKG

lightning-auth-and-payment

Version:

Lightning Network authentication and payment processing library for modern web applications

216 lines 11.8 kB
"use strict"; 'use client'; Object.defineProperty(exports, "__esModule", { value: true }); exports.LightningInput = LightningInput; exports.LightningAddressInput = LightningAddressInput; exports.LightningPubkeyInput = LightningPubkeyInput; exports.LightningWalletInput = LightningWalletInput; exports.LightningPaymentInput = LightningPaymentInput; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const lucide_react_1 = require("lucide-react"); const input_1 = require("./ui/input"); const button_1 = require("./ui/button"); const formatting_1 = require("../utils/formatting"); const variantConfig = { default: { icon: lucide_react_1.Zap, className: 'border-slate-300 focus:border-slate-500', iconColor: 'text-slate-500', }, lightning: { icon: lucide_react_1.Zap, className: 'border-orange-300 focus:border-orange-500', iconColor: 'text-orange-500', }, wallet: { icon: lucide_react_1.Wallet, className: 'border-purple-300 focus:border-purple-500', iconColor: 'text-purple-500', }, user: { icon: lucide_react_1.User, className: 'border-blue-300 focus:border-blue-500', iconColor: 'text-blue-500', }, payment: { icon: lucide_react_1.Send, className: 'border-green-300 focus:border-green-500', iconColor: 'text-green-500', }, }; const sizeConfig = { sm: { className: 'h-8 px-3 text-sm', iconSize: 'w-4 h-4', }, md: { className: 'h-10 px-3 text-sm', iconSize: 'w-5 h-5', }, lg: { className: 'h-12 px-4 text-base', iconSize: 'w-6 h-6', }, }; // Lightning-specific validation functions const validateLightningAddress = (value) => { if (!value) return { isValid: false, message: 'Lightning address is required' }; // Check for LNURL if (value.startsWith('lnurl1')) { return { isValid: true, message: 'Valid LNURL' }; } // Check for BOLT11 invoice if (value.startsWith('lnbc')) { return { isValid: true, message: 'Valid BOLT11 invoice' }; } // Check for Lightning address format (user@domain.com) if (value.includes('@') && value.split('@').length === 2) { return { isValid: true, message: 'Valid Lightning address' }; } // Check for node pubkey (66 hex characters) if (/^[0-9a-fA-F]{66}$/.test(value)) { return { isValid: true, message: 'Valid node pubkey' }; } return { isValid: false, message: 'Invalid Lightning address format' }; }; const validateWalletAddress = (value) => { if (!value) return { isValid: false, message: 'Wallet address is required' }; // Basic wallet address validation (can be extended) if (value.length < 10) { return { isValid: false, message: 'Address too short' }; } return { isValid: true, message: 'Valid wallet address' }; }; const validateUserPubkey = (value) => { if (!value) return { isValid: false, message: 'Public key is required' }; // Check for 66 hex characters if (/^[0-9a-fA-F]{66}$/.test(value)) { return { isValid: true, message: 'Valid public key' }; } return { isValid: false, message: 'Invalid public key format' }; }; function LightningInput({ type = 'text', value, onChange, placeholder, label, description, error, success, disabled = false, required = false, className, variant = 'default', size = 'md', showCopy = false, showVisibilityToggle = false, showValidation = true, validate, autoFocus = false, readOnly = false, maxLength, minLength, pattern, icon, showIcon = true, iconPosition = 'left', }) { const [isVisible, setIsVisible] = (0, react_1.useState)(false); const [copied, setCopied] = (0, react_1.useState)(false); const [validationResult, setValidationResult] = (0, react_1.useState)(null); const inputRef = (0, react_1.useRef)(null); const config = variantConfig[variant]; const sizeInfo = sizeConfig[size]; const IconComponent = config.icon; // Get validation function based on variant const getValidationFunction = () => { if (validate) return validate; switch (variant) { case 'lightning': return validateLightningAddress; case 'wallet': return validateWalletAddress; case 'user': return validateUserPubkey; default: return undefined; } }; // Validate input const handleValidation = (inputValue) => { const validationFn = getValidationFunction(); if (validationFn && showValidation) { const result = validationFn(inputValue); setValidationResult(result); } }; // Handle input change const handleChange = (e) => { const newValue = e.target.value; onChange(newValue); handleValidation(newValue); }; // Handle copy const handleCopy = async () => { try { await navigator.clipboard.writeText(value); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (err) { console.error('Failed to copy:', err); } }; // Handle visibility toggle const toggleVisibility = () => { setIsVisible(!isVisible); }; // Get input type const getInputType = () => { if (type === 'password' && showVisibilityToggle) { return isVisible ? 'text' : 'password'; } return type; }; // Get status classes const getStatusClasses = () => { if (error) { return 'border-red-500 focus:border-red-500 focus:ring-red-500'; } if (success || validationResult?.isValid) { return 'border-green-500 focus:border-green-500 focus:ring-green-500'; } if (validationResult && !validationResult.isValid) { return 'border-red-500 focus:border-red-500 focus:ring-red-500'; } return config.className; }; // Render icon const renderIcon = () => { if (!showIcon) return null; if (icon) { return icon; } return (0, jsx_runtime_1.jsx)(IconComponent, { className: (0, formatting_1.cn)(sizeInfo.iconSize, config.iconColor) }); }; // Render status icon const renderStatusIcon = () => { if (error || (validationResult && !validationResult.isValid)) { return (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-4 h-4 text-red-500" }); } if (success || (validationResult && validationResult.isValid)) { return (0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle, { className: "w-4 h-4 text-green-500" }); } return null; }; // Render action buttons const renderActions = () => { const actions = []; if (showCopy && value) { actions.push((0, jsx_runtime_1.jsx)(button_1.Button, { variant: "ghost", size: "sm", onClick: handleCopy, className: "h-6 w-6 p-0", children: copied ? (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3 h-3" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "w-3 h-3" }) }, "copy")); } if (showVisibilityToggle && type === 'password') { actions.push((0, jsx_runtime_1.jsx)(button_1.Button, { variant: "ghost", size: "sm", onClick: toggleVisibility, className: "h-6 w-6 p-0", children: isVisible ? (0, jsx_runtime_1.jsx)(lucide_react_1.EyeOff, { className: "w-3 h-3" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { className: "w-3 h-3" }) }, "visibility")); } if (renderStatusIcon()) { actions.push((0, jsx_runtime_1.jsx)("div", { className: "flex items-center", children: renderStatusIcon() }, "status")); } return actions.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center space-x-1", children: actions })) : null; }; return ((0, jsx_runtime_1.jsxs)("div", { className: (0, formatting_1.cn)('space-y-2', className), children: [label && ((0, jsx_runtime_1.jsxs)("label", { className: "text-sm font-medium text-slate-700 dark:text-slate-300", children: [label, required && (0, jsx_runtime_1.jsx)("span", { className: "text-red-500 ml-1", children: "*" })] })), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [showIcon && iconPosition === 'left' && ((0, jsx_runtime_1.jsx)("div", { className: "absolute left-3 top-1/2 transform -translate-y-1/2", children: renderIcon() })), (0, jsx_runtime_1.jsx)(input_1.Input, { ref: inputRef, type: getInputType(), value: value, onChange: handleChange, placeholder: placeholder, disabled: disabled, required: required, autoFocus: autoFocus, readOnly: readOnly, maxLength: maxLength, minLength: minLength, pattern: pattern, className: (0, formatting_1.cn)(sizeInfo.className, getStatusClasses(), showIcon && iconPosition === 'left' && 'pl-10', showIcon && iconPosition === 'right' && 'pr-10', renderActions() && 'pr-20', 'transition-colors duration-200') }), showIcon && iconPosition === 'right' && ((0, jsx_runtime_1.jsx)("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2", children: renderIcon() })), renderActions() && ((0, jsx_runtime_1.jsx)("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2", children: renderActions() }))] }), description && ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: description })), error && ((0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-red-500 flex items-center space-x-1", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-3 h-3" }), (0, jsx_runtime_1.jsx)("span", { children: error })] })), success && ((0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-green-500 flex items-center space-x-1", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle, { className: "w-3 h-3" }), (0, jsx_runtime_1.jsx)("span", { children: success })] })), validationResult && !error && !success && ((0, jsx_runtime_1.jsxs)("p", { className: (0, formatting_1.cn)('text-xs flex items-center space-x-1', validationResult.isValid ? 'text-green-500' : 'text-red-500'), children: [validationResult.isValid ? ((0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle, { className: "w-3 h-3" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "w-3 h-3" })), (0, jsx_runtime_1.jsx)("span", { children: validationResult.message })] })), maxLength && ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs text-slate-500", children: [(0, jsx_runtime_1.jsxs)("span", { children: [value.length, " / ", maxLength, " characters"] }), value.length > maxLength * 0.9 && ((0, jsx_runtime_1.jsx)("span", { className: "text-orange-500", children: "Approaching limit" }))] }))] })); } // Convenience components for specific Lightning input types function LightningAddressInput(props) { return ((0, jsx_runtime_1.jsx)(LightningInput, { variant: "lightning", placeholder: "Enter Lightning address (user@domain.com, lnurl1..., lnbc...)", ...props })); } function LightningPubkeyInput(props) { return ((0, jsx_runtime_1.jsx)(LightningInput, { variant: "user", placeholder: "Enter public key (66 hex characters)", ...props })); } function LightningWalletInput(props) { return ((0, jsx_runtime_1.jsx)(LightningInput, { variant: "wallet", placeholder: "Enter wallet address", ...props })); } function LightningPaymentInput(props) { return ((0, jsx_runtime_1.jsx)(LightningInput, { variant: "payment", placeholder: "Enter payment amount or invoice", ...props })); } //# sourceMappingURL=LightningInput.js.map