lightning-auth-and-payment
Version:
Lightning Network authentication and payment processing library for modern web applications
216 lines • 11.8 kB
JavaScript
;
'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