UNPKG

@nexcomponent/lib

Version:
1,833 lines (1,825 loc) 370 kB
import React, { useState, useRef, useEffect, useCallback, useContext, createContext, useMemo } from 'react'; import { useReducedMotion, AnimatePresence, motion } from 'framer-motion'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import classNames from 'classnames'; import { ChevronDown, Sun, Moon, LogIn, User, Fingerprint, Zap, Settings, Activity, Shield, Globe, Crown, LogOut, Menu, X, CheckCircle, AlertCircle, Mail, MessageCircle, Send } from 'lucide-react'; // Enterprise Animation System - Comprehensive Configuration const ANIMATION_CONFIG = { // Core timing presets with cubic-bezier easing timing: { instant: { duration: 0.05, ease: [0.4, 0, 0.2, 1] }, fast: { duration: 0.12, ease: [0.4, 0, 0.2, 1] }, medium: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, slow: { duration: 0.35, ease: [0.4, 0, 0.2, 1] }, slower: { duration: 0.5, ease: [0.4, 0, 0.2, 1] }, slowest: { duration: 0.7, ease: [0.4, 0, 0.2, 1] } }, // Advanced spring configurations spring: { // Responsive spring for interactive elements responsive: { type: "spring", stiffness: 450, damping: 28, mass: 0.8, restDelta: 0.001 }, // Fast spring for immediate feedback fast: { type: "spring", stiffness: 600, damping: 25, mass: 0.6, restDelta: 0.001 }, // Smooth spring for elegant animations smooth: { type: "spring", stiffness: 300, damping: 35, mass: 1.0, restDelta: 0.001 }, // Heavy spring for substantial elements heavy: { type: "spring", stiffness: 200, damping: 40, mass: 1.4, restDelta: 0.001 } }, // Enterprise stagger configurations stagger: { // Main container stagger container: { animate: { transition: { delayChildren: 0.08, staggerChildren: 0.04, staggerDirection: 1 } } }, // Fast stagger for immediate feedback fast: { animate: { transition: { delayChildren: 0.02, staggerChildren: 0.02, staggerDirection: 1 } } }, // Slow stagger for dramatic reveals slow: { animate: { transition: { delayChildren: 0.15, staggerChildren: 0.08, staggerDirection: 1 } } }, // Dropdown stagger for menu items dropdown: { animate: { transition: { delayChildren: 0.04, staggerChildren: 0.03, staggerDirection: 1 } } }, // Grid stagger for card layouts grid: { animate: { transition: { delayChildren: 0.06, staggerChildren: 0.05, staggerDirection: 1 } } } } }; // Enterprise Animation Variants const ANIMATION_VARIANTS = { // Core fade animations fade: { in: { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 } }, inUp: { initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -20 } }, inDown: { initial: { opacity: 0, y: -20 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 20 } }, inLeft: { initial: { opacity: 0, x: 20 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -20 } }, inRight: { initial: { opacity: 0, x: -20 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 20 } } }, // Scale animations scale: { in: { initial: { scale: 0.8, opacity: 0 }, animate: { scale: 1, opacity: 1 }, exit: { scale: 0.8, opacity: 0 } }, inUp: { initial: { scale: 0.8, y: 20, opacity: 0 }, animate: { scale: 1, y: 0, opacity: 1 }, exit: { scale: 0.8, y: -20, opacity: 0 } }, inDown: { initial: { scale: 0.8, y: -20, opacity: 0 }, animate: { scale: 1, y: 0, opacity: 1 }, exit: { scale: 0.8, y: 20, opacity: 0 } } }, // Mobile Navigation System mobileNav: { // Main container animation container: { initial: { y: '-100%', opacity: 0, backdropFilter: 'blur(0px) saturate(100%)' }, animate: { y: 0, opacity: 1, backdropFilter: 'blur(24px) saturate(180%)', transition: { type: "spring", stiffness: 300, damping: 35, mass: 1.0 } }, exit: { y: '-100%', opacity: 0, backdropFilter: 'blur(0px) saturate(100%)', transition: { type: "spring", stiffness: 400, damping: 30, mass: 0.8 } } }, // Header section header: { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 400, damping: 30 } }, exit: { opacity: 0, y: -10 } }, // Navigation items navItem: { initial: { opacity: 0, y: -8, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1, transition: { type: "spring", stiffness: 450, damping: 28 } }, exit: { opacity: 0, y: -8, scale: 0.95 } }, // Section titles sectionTitle: { initial: { opacity: 0, x: -10 }, animate: { opacity: 1, x: 0, transition: { type: "spring", stiffness: 400, damping: 30 } }, exit: { opacity: 0, x: -10 } }, // Dropdown containers dropdownContainer: { initial: { opacity: 0, height: 0, scale: 0.95 }, animate: { opacity: 1, height: 'auto', scale: 1, transition: { height: { duration: 0.25, ease: [0.4, 0, 0.2, 1] }, opacity: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, scale: { duration: 0.2, ease: [0.4, 0, 0.2, 1] } } }, exit: { opacity: 0, height: 0, scale: 0.95, transition: { height: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] }, scale: { duration: 0.15, ease: [0.4, 0, 0.2, 1] } } } }, // Dropdown items dropdownItem: { initial: { opacity: 0, y: -6, scale: 0.95, x: -5 }, animate: { opacity: 1, y: 0, scale: 1, x: 0, transition: { type: "spring", stiffness: 500, damping: 25 } }, exit: { opacity: 0, y: -6, scale: 0.95, x: -5 } }, // User avatar avatar: { initial: { opacity: 0, scale: 0.8, rotate: -10 }, animate: { opacity: 1, scale: 1, rotate: 0, transition: { type: "spring", stiffness: 400, damping: 30 } }, exit: { opacity: 0, scale: 0.8, rotate: -10 } }, // Badge animations badge: { initial: { opacity: 0, scale: 0.5 }, animate: { opacity: 1, scale: 1, transition: { type: "spring", stiffness: 600, damping: 25 } }, exit: { opacity: 0, scale: 0.5 } }, // Icon rotations iconRotate: { closed: { rotate: 0 }, open: { rotate: 180 } } }, // Interactive elements interactive: { // Button states button: { idle: { scale: 1, backgroundColor: "rgba(255, 255, 255, 0.08)", borderColor: "rgba(255, 255, 255, 0.1)", boxShadow: "0 2px 8px rgba(0, 0, 0, 0.08)" }, hover: { scale: 1.02, backgroundColor: "rgba(255, 255, 255, 0.12)", borderColor: "rgba(255, 255, 255, 0.18)", boxShadow: "0 4px 16px rgba(0, 0, 0, 0.12)" }, tap: { scale: 0.98, backgroundColor: "rgba(255, 24, 1, 0.15)", borderColor: "rgba(255, 24, 1, 0.25)", boxShadow: "0 2px 8px rgba(255, 24, 1, 0.2)" }, focus: { outline: "2px solid var(--nex-signature)", outlineOffset: "2px", boxShadow: "0 0 0 4px rgba(255, 24, 1, 0.1)" } }, // Nav item states (removed translateX for mobile nav) navItem: { idle: { backgroundColor: "rgba(255, 255, 255, 0)" }, hover: { backgroundColor: "rgba(255, 255, 255, 0.06)" }, active: { backgroundColor: "rgba(255, 255, 255, 0.1)" } }, // Enterprise hamburger button animations hamburger: { // Container rotation container: { closed: { rotate: 0, scale: 1, transition: { type: "spring", stiffness: 400, damping: 30 } }, open: { rotate: 180, scale: 1.05, transition: { type: "spring", stiffness: 400, damping: 30 } } }, // Menu icon (hamburger lines) menuIcon: { closed: { opacity: 1, scale: 1, rotate: 0, transition: { type: "spring", stiffness: 500, damping: 25 } }, open: { opacity: 0, scale: 0.8, rotate: -45, transition: { type: "spring", stiffness: 500, damping: 25 } } }, // Close icon (X) closeIcon: { closed: { opacity: 0, scale: 0.8, rotate: 45, transition: { type: "spring", stiffness: 500, damping: 25 } }, open: { opacity: 1, scale: 1, rotate: 0, transition: { type: "spring", stiffness: 500, damping: 25 } } } } }, // Background transitions background: { transparent: { background: 'rgba(255,255,255,0)', backdropFilter: 'blur(0px) saturate(100%)', WebkitBackdropFilter: 'blur(0px) saturate(100%)', borderBottom: 'none', boxShadow: 'none' }, light: { background: 'rgba(255,255,255,0.7)', backdropFilter: 'blur(24px) saturate(180%)', WebkitBackdropFilter: 'blur(24px) saturate(180%)', borderBottom: '1.5px solid rgba(255,255,255,0.22)', boxShadow: '0 8px 32px -8px rgba(0,0,0,0.12), 0 0 0 1.5px rgba(255,255,255,0.13) inset' }, medium: { background: 'rgba(255,255,255,0.85)', backdropFilter: 'blur(32px) saturate(200%)', WebkitBackdropFilter: 'blur(32px) saturate(200%)', borderBottom: '1.5px solid rgba(255,255,255,0.3)', boxShadow: '0 12px 40px -12px rgba(0,0,0,0.15), 0 0 0 1.5px rgba(255,255,255,0.2) inset' }, dark: { background: 'rgba(255,255,255,0.95)', backdropFilter: 'blur(40px) saturate(220%)', WebkitBackdropFilter: 'blur(40px) saturate(220%)', borderBottom: '1.5px solid rgba(255,255,255,0.4)', boxShadow: '0 16px 48px -16px rgba(0,0,0,0.18), 0 0 0 1.5px rgba(255,255,255,0.25) inset' } } }; // Performance optimization system const PERFORMANCE_CONFIG = { // Hardware acceleration presets hardwareAcceleration: { transform: 'translateZ(0)', backfaceVisibility: 'hidden', perspective: '1000px', willChange: 'transform, opacity' }, // Will-change hints for different animation types willChange: { transform: 'transform', opacity: 'opacity', background: 'background-color', backdrop: 'backdrop-filter', all: 'transform, opacity, background-color, border-color, box-shadow, backdrop-filter' }, // Animation performance modes performance: { high: { willChange: 'transform, opacity, backdrop-filter', transform: 'translateZ(0)', backfaceVisibility: 'hidden' }, medium: { willChange: 'transform, opacity', transform: 'translateZ(0)' }, low: { willChange: 'opacity' } } }; // Enterprise color schemes const COLOR_SCHEMES = { // Mobile navigation system mobileNav: { background: { primary: 'linear-gradient(120deg, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.4) 100%), linear-gradient(90deg, rgba(255,24,1,0.08) 0%, rgba(0,184,255,0.08) 100%)', secondary: 'linear-gradient(120deg, rgba(255,255,255,0.6) 0%, rgba(255,255,255,0.3) 100%)', dark: 'linear-gradient(120deg, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.6) 100%)' }, backdrop: { light: 'blur(24px) saturate(180%)', medium: 'blur(32px) saturate(200%)', heavy: 'blur(40px) saturate(220%)' }, border: { light: '1.5px solid rgba(255, 255, 255, 0.22)', medium: '1.5px solid rgba(255, 255, 255, 0.3)', heavy: '1.5px solid rgba(255, 255, 255, 0.4)' }, shadow: { light: '0 8px 32px -8px rgba(0,0,0,0.12), 0 0 0 1.5px rgba(255,255,255,0.13) inset', medium: '0 12px 40px -12px rgba(0,0,0,0.15), 0 0 0 1.5px rgba(255,255,255,0.2) inset', heavy: '0 16px 48px -16px rgba(0,0,0,0.18), 0 0 0 1.5px rgba(255,255,255,0.25) inset' } }, // Interactive elements interactive: { navItem: { idle: 'rgba(255, 255, 255, 0.02)', hover: 'rgba(255, 255, 255, 0.06)', active: 'rgba(255, 255, 255, 0.1)', selected: 'rgba(255, 24, 1, 0.08)' }, button: { primary: { idle: 'rgba(255, 255, 255, 0.08)', hover: 'rgba(255, 255, 255, 0.12)', active: 'rgba(255, 24, 1, 0.15)' }, secondary: { idle: 'rgba(255, 255, 255, 0.06)', hover: 'rgba(255, 255, 255, 0.1)', active: 'rgba(255, 24, 1, 0.12)' } } } }; // Enterprise hook with comprehensive configuration const useAnimationConfig = () => { const shouldReduceMotion = useReducedMotion(); // Reduced motion overrides const reducedMotionConfig = { timing: { instant: { duration: 0.02, ease: [0.4, 0, 0.2, 1] }, fast: { duration: 0.08, ease: [0.4, 0, 0.2, 1] }, medium: { duration: 0.12, ease: [0.4, 0, 0.2, 1] }, slow: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, slower: { duration: 0.25, ease: [0.4, 0, 0.2, 1] }, slowest: { duration: 0.3, ease: [0.4, 0, 0.2, 1] } }, stagger: { container: { animate: { transition: { delayChildren: 0.02, staggerChildren: 0.01, staggerDirection: 1 } } }, fast: { animate: { transition: { delayChildren: 0.01, staggerChildren: 0.005, staggerDirection: 1 } } }, slow: { animate: { transition: { delayChildren: 0.05, staggerChildren: 0.02, staggerDirection: 1 } } }, dropdown: { animate: { transition: { delayChildren: 0.01, staggerChildren: 0.01, staggerDirection: 1 } } }, grid: { animate: { transition: { delayChildren: 0.02, staggerChildren: 0.01, staggerDirection: 1 } } } } }; return { ...ANIMATION_CONFIG, ...(shouldReduceMotion && reducedMotionConfig), shouldReduceMotion, performance: PERFORMANCE_CONFIG, variants: ANIMATION_VARIANTS, colors: COLOR_SCHEMES }; }; // Legacy exports for backward compatibility ANIMATION_CONFIG.timing.fast; ANIMATION_CONFIG.timing.medium; ANIMATION_CONFIG.timing.slow; ANIMATION_CONFIG.timing.slower; ANIMATION_CONFIG.spring.responsive; ANIMATION_CONFIG.stagger.container; var styles$4 = {"nexAlert":"NexAlert-module_nexAlert__yf-EP","sizeSm":"NexAlert-module_sizeSm__75-5q","sizeMd":"NexAlert-module_sizeMd__3DIR2","sizeLg":"NexAlert-module_sizeLg__hKaSj","variantDefault":"NexAlert-module_variantDefault__nZGu8","variantGlass":"NexAlert-module_variantGlass__dG2Z9","variantPremium":"NexAlert-module_variantPremium__X9zau","variantMinimal":"NexAlert-module_variantMinimal__cyJ-s","typeError":"NexAlert-module_typeError__4JJvQ","typeSuccess":"NexAlert-module_typeSuccess__jkKPO","typeInfo":"NexAlert-module_typeInfo__4PVwl","typeWarning":"NexAlert-module_typeWarning__T5AJW","typeNeutral":"NexAlert-module_typeNeutral__YGSMH","content":"NexAlert-module_content__h-f2D","header":"NexAlert-module_header__-CLlQ","icon":"NexAlert-module_icon__ulim5","title":"NexAlert-module_title__tumVb","message":"NexAlert-module_message__32Mxx","description":"NexAlert-module_description__O5dZ1","actions":"NexAlert-module_actions__piUxm","actionButton":"NexAlert-module_actionButton__k3hTG","primary":"NexAlert-module_primary__yzE-Y","dismissButton":"NexAlert-module_dismissButton__y40Wl","progressBar":"NexAlert-module_progressBar__NGydb","swipeIndicator":"NexAlert-module_swipeIndicator__AvrcA","alertGroup":"NexAlert-module_alertGroup__MQxmj","positionTop":"NexAlert-module_positionTop__a-2GR","positionBottom":"NexAlert-module_positionBottom__kmCww","positionTopRight":"NexAlert-module_positionTopRight__TAV3L","positionBottomRight":"NexAlert-module_positionBottomRight__OWvBz","positionCenter":"NexAlert-module_positionCenter__XTdSk","progress-shrink":"NexAlert-module_progress-shrink__dKJFx"}; const defaultIcons = { error: /*#__PURE__*/jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("circle", { cx: "12", cy: "12", r: "10" }), /*#__PURE__*/jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), /*#__PURE__*/jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })] }), success: /*#__PURE__*/jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }), /*#__PURE__*/jsx("polyline", { points: "22,4 12,14.01 9,11.01" })] }), info: /*#__PURE__*/jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("circle", { cx: "12", cy: "12", r: "10" }), /*#__PURE__*/jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }), /*#__PURE__*/jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })] }), warning: /*#__PURE__*/jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), /*#__PURE__*/jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), /*#__PURE__*/jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }), neutral: /*#__PURE__*/jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("circle", { cx: "12", cy: "12", r: "10" }), /*#__PURE__*/jsx("line", { x1: "8", y1: "12", x2: "16", y2: "12" })] }) }; /** * NexAlert - Premium Enterprise Alert Component * * A sophisticated, animated alert component with Apple-like design principles. * Features rich content support, multiple variants, progress indicators, and * comprehensive accessibility support. * * @example * ```tsx * <NexAlert * id="alert-1" * type="success" * title="Success!" * message="Your changes have been saved" * variant="glass" * timeout={5000} * onDismiss={() => console.log('Alert dismissed')} * /> * ``` */ const NexAlert = ({ id, type = 'info', variant = 'default', size = 'md', title, message, description, icon, timeout = 0, dismissible = true, pauseOnHover = false, persistent = false, actions = [], onUndo, onDismiss, onShow, className, style, // Legacy support handleDismiss }) => { const { shouldReduceMotion } = useAnimationConfig(); const [isVisible, setIsVisible] = useState(false); const [isPaused, setIsPaused] = useState(false); const [progress, setProgress] = useState(100); const timeoutRef = useRef(null); const progressRef = useRef(null); const startTimeRef = useRef(Date.now()); const totalDurationRef = useRef(timeout); // Legacy support const finalOnDismiss = onDismiss || handleDismiss; // Auto-dismiss logic with pause on hover useEffect(() => { if (timeout > 0 && !persistent && finalOnDismiss) { const startTimer = () => { startTimeRef.current = Date.now(); totalDurationRef.current = timeout; // Progress bar animation if (!shouldReduceMotion) { progressRef.current = setInterval(() => { const elapsed = Date.now() - startTimeRef.current; const remaining = Math.max(0, 100 - elapsed / timeout * 100); setProgress(remaining); }, 16); // ~60fps } // Dismiss timer timeoutRef.current = setTimeout(() => { if (!isPaused) { finalOnDismiss(); } }, timeout); }; if (!isPaused) { startTimer(); } return () => { if (timeoutRef.current) clearTimeout(timeoutRef.current); if (progressRef.current) clearInterval(progressRef.current); }; } }, [timeout, persistent, finalOnDismiss, isPaused, shouldReduceMotion]); // Pause/resume on hover const handleMouseEnter = useCallback(() => { if (pauseOnHover && timeout > 0 && !persistent) { setIsPaused(true); if (timeoutRef.current) clearTimeout(timeoutRef.current); if (progressRef.current) clearInterval(progressRef.current); } }, [pauseOnHover, timeout, persistent]); const handleMouseLeave = useCallback(() => { if (pauseOnHover && timeout > 0 && !persistent) { setIsPaused(false); // Restart timer with remaining time const elapsed = Date.now() - startTimeRef.current; const remaining = Math.max(0, timeout - elapsed); if (remaining > 0) { timeoutRef.current = setTimeout(() => { finalOnDismiss(); }, remaining); } } }, [pauseOnHover, timeout, persistent, finalOnDismiss]); // Show animation useEffect(() => { const timer = setTimeout(() => { setIsVisible(true); onShow?.(); }, 50); return () => clearTimeout(timer); }, [onShow]); // Dismiss handler const dismissAlert = useCallback(() => { setIsVisible(false); if (finalOnDismiss) { setTimeout(() => { finalOnDismiss(); }, 300); // Match animation duration } }, [finalOnDismiss]); // Action handler const handleAction = useCallback(action => { if (!action.disabled) { action.onClick(); if (action.variant === 'primary') { dismissAlert(); } } }, [dismissAlert]); // Build class names const alertClasses = [styles$4['nexAlert'], styles$4[`type${type.charAt(0).toUpperCase() + type.slice(1)}`], styles$4[`variant${variant.charAt(0).toUpperCase() + variant.slice(1)}`], styles$4[`size${size.charAt(0).toUpperCase() + size.slice(1)}`], className].filter(Boolean).join(' '); // Animation variants const alertVariants = { initial: { opacity: 0, y: -20, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1, transition: { duration: shouldReduceMotion ? 0.2 : 0.3, ease: [0.4, 0, 0.2, 1] } }, exit: { opacity: 0, y: -20, scale: 0.95, transition: { duration: shouldReduceMotion ? 0.1 : 0.2, ease: [0.4, 0, 0.2, 1] } } }; // Get the appropriate icon const alertIcon = icon || defaultIcons[type]; return /*#__PURE__*/jsx(AnimatePresence, { children: isVisible && /*#__PURE__*/jsxs(motion.div, { className: alertClasses, style: style, variants: alertVariants, initial: "initial", animate: "animate", exit: "exit", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, role: "alert", "aria-live": "polite", "aria-atomic": "true", children: [/*#__PURE__*/jsx("div", { className: `${styles$4.icon} ${styles$4[`size${size.charAt(0).toUpperCase() + size.slice(1)}`]}`, children: alertIcon }), /*#__PURE__*/jsxs("div", { className: styles$4.content, children: [(title || message) && /*#__PURE__*/jsxs("div", { className: styles$4.header, children: [title && /*#__PURE__*/jsx("h4", { className: `${styles$4.title} ${styles$4[`size${size.charAt(0).toUpperCase() + size.slice(1)}`]}`, children: title }), message && !title && /*#__PURE__*/jsx("p", { className: `${styles$4.message} ${styles$4[`size${size.charAt(0).toUpperCase() + size.slice(1)}`]}`, children: message })] }), message && title && /*#__PURE__*/jsx("p", { className: `${styles$4.message} ${styles$4[`size${size.charAt(0).toUpperCase() + size.slice(1)}`]}`, children: message }), description && /*#__PURE__*/jsx("p", { className: styles$4.description, children: description }), (actions.length > 0 || onUndo) && /*#__PURE__*/jsxs("div", { className: styles$4.actions, children: [actions.map((action, index) => /*#__PURE__*/jsx("button", { className: `${styles$4.actionButton} ${action.variant === 'primary' ? styles$4.primary : ''}`, onClick: () => handleAction(action), disabled: action.disabled, children: action.label }, index)), onUndo && /*#__PURE__*/jsx("button", { className: styles$4.actionButton, onClick: onUndo, children: "Undo" })] })] }), dismissible && /*#__PURE__*/jsx("button", { className: styles$4.dismissButton, onClick: handleDismiss, "aria-label": "Dismiss alert", children: /*#__PURE__*/jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [/*#__PURE__*/jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), /*#__PURE__*/jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }), timeout > 0 && !persistent && !shouldReduceMotion && /*#__PURE__*/jsx("div", { className: styles$4.progressBar, style: { width: `${progress}%`, animationDuration: `${timeout}ms` } })] }) }); }; const NEX_ALERT_PRESETS = { toast: { type: 'info', variant: 'glass', size: 'sm', timeout: 4000, dismissible: true, pauseOnHover: true }, notification: { type: 'info', variant: 'default', size: 'md', timeout: 0, dismissible: true, pauseOnHover: false }, banner: { type: 'warning', variant: 'premium', size: 'lg', timeout: 0, dismissible: false, pauseOnHover: false }, error: { type: 'error', variant: 'default', size: 'md', timeout: 0, dismissible: true, pauseOnHover: false }, success: { type: 'success', variant: 'default', size: 'md', timeout: 3000, dismissible: true, pauseOnHover: true } }; const NexAlertsContext = /*#__PURE__*/createContext(undefined); /** * NexAlertsProvider - Premium Alert Management System * * Provides a comprehensive alert management system with global state, * keyboard shortcuts, and advanced positioning options. */ const NexAlertsProvider = ({ children, maxAlerts = 4, defaultPosition = 'top', defaultTimeout = 4000, defaultVariant = 'default', defaultSize = 'md', enableKeyboardShortcuts = true, enableClickOutside = true, enableSwipeToDismiss = true }) => { const { shouldReduceMotion } = useAnimationConfig(); const [alerts, setAlerts] = useState([]); const containerRef = useRef(null); // Add alert with smart management const addAlert = useCallback(alert => { const id = Math.random().toString(36).slice(2, 9) + new Date().getTime().toString(36); // Apply defaults const newAlert = { id, type: alert.type || 'info', variant: alert.variant || defaultVariant, size: alert.size || defaultSize, timeout: alert.timeout ?? defaultTimeout, dismissible: alert.dismissible ?? true, pauseOnHover: alert.pauseOnHover ?? true, ...alert }; setAlerts(prev => { const newAlerts = [newAlert, ...prev]; // Limit number of alerts if (newAlerts.length > maxAlerts) { return newAlerts.slice(0, maxAlerts); } return newAlerts; }); return id; }, [maxAlerts, defaultVariant, defaultSize, defaultTimeout]); // Dismiss specific alert const dismissAlert = useCallback(id => { setAlerts(prev => prev.filter(alert => alert.id !== id)); }, []); // Dismiss all alerts const dismissAll = useCallback(() => { setAlerts([]); }, []); // Update specific alert const updateAlert = useCallback((id, updates) => { setAlerts(prev => prev.map(alert => alert.id === id ? { ...alert, ...updates } : alert)); }, []); // Clear all alerts const clearAlerts = useCallback(() => { setAlerts([]); }, []); // Keyboard shortcuts useEffect(() => { if (!enableKeyboardShortcuts) return; const handleKeyDown = event => { if (event.key === 'Escape') { dismissAll(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [enableKeyboardShortcuts, dismissAll]); // Click outside to dismiss useEffect(() => { if (!enableClickOutside) return; const handleClickOutside = event => { if (containerRef.current && !containerRef.current.contains(event.target)) { // Only dismiss non-persistent alerts setAlerts(prev => prev.filter(alert => alert.persistent)); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [enableClickOutside]); // Context value const contextValue = { alerts, addAlert, dismissAlert, dismissAll, updateAlert, clearAlerts }; // Animation variants for container const containerVariants = { initial: { opacity: 0 }, animate: { opacity: 1, transition: { duration: shouldReduceMotion ? 0.1 : 0.2, staggerChildren: shouldReduceMotion ? 0 : 0.1 } }, exit: { opacity: 0, transition: { duration: shouldReduceMotion ? 0.1 : 0.2 } } }; return /*#__PURE__*/jsxs(NexAlertsContext.Provider, { value: contextValue, children: [/*#__PURE__*/jsx(AnimatePresence, { children: alerts.length > 0 && /*#__PURE__*/jsx(motion.div, { ref: containerRef, className: `${styles$4['alertGroup']} ${styles$4[`position${defaultPosition.charAt(0).toUpperCase() + defaultPosition.slice(1)}`]}`, variants: containerVariants, initial: "initial", animate: "animate", exit: "exit", children: alerts.map(alert => /*#__PURE__*/jsx(NexAlert, { ...alert, onDismiss: () => dismissAlert(alert.id) }, alert.id)) }) }), children] }); }; /** * useAlerts - Hook for managing alerts * * Provides a convenient interface for adding and managing alerts * with preset configurations and advanced features. */ const useAlerts = () => { const context = useContext(NexAlertsContext); if (!context) { throw new Error('useAlerts must be used within a NexAlertsProvider'); } const { addAlert, dismissAlert, dismissAll, updateAlert, clearAlerts } = context; // Preset-based alert creators const createToast = useCallback((message, options) => { const preset = NEX_ALERT_PRESETS['toast']; return addAlert({ ...preset, message, ...options }); }, [addAlert]); const createNotification = useCallback((message, options) => { const preset = NEX_ALERT_PRESETS['notification']; return addAlert({ ...preset, message, ...options }); }, [addAlert]); const createBanner = useCallback((message, options) => { const preset = NEX_ALERT_PRESETS['banner']; return addAlert({ ...preset, message, ...options }); }, [addAlert]); const createError = useCallback((message, options) => { const preset = NEX_ALERT_PRESETS['error']; return addAlert({ ...preset, message, ...options }); }, [addAlert]); const createSuccess = useCallback((message, options) => { const preset = NEX_ALERT_PRESETS['success']; return addAlert({ ...preset, message, ...options }); }, [addAlert]); return { // Core functions addAlert, dismissAlert, dismissAll, updateAlert, clearAlerts, // Preset creators createToast, createNotification, createBanner, createError, createSuccess, // Quick actions showSuccess: createSuccess, showError: createError, showInfo: (message, options) => addAlert({ type: 'info', message, ...options }), showWarning: (message, options) => addAlert({ type: 'warning', message, ...options }) }; }; const NexButton = ({ onClick, className, size = 'normal', inverted, type, text, disabled = false, loading = false, icon, iconPosition = 'left', ...rest }) => { const { timing, spring, shouldReduceMotion } = useAnimationConfig(); const getTypeClass = type => { if (!type) return ''; const colorNames = ['primary', 'secondary', 'tertiary', 'quaternary', 'success', 'info', 'warning', 'danger', 'glass', 'enterprise']; return colorNames.includes(type) ? `nex-button--${type}` : ''; }; const getSizeClass = size => { return size ? `nex-button--${size}` : ''; }; const buttonClasses = `nex-button ${className || ''} ${getSizeClass(size)} ${getTypeClass(type)} ${inverted ? 'inverted' : ''} ${!type && inverted ? 'inverted-default' : ''} ${disabled ? 'disabled' : ''} ${loading ? 'loading' : ''}`; const handleClick = e => { if (disabled || loading) return; onClick?.(e); }; const handleKeyDown = e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (!disabled && !loading) { onClick?.(e); } } }; // Animation variants - no scale animations const buttonVariants = { initial: { opacity: 0, y: 10 }, animate: { opacity: 1, y: 0, transition: { duration: shouldReduceMotion ? 0.2 : 0.3, ease: [0.4, 0, 0.2, 1] } }, hover: { y: shouldReduceMotion ? 0 : -2, transition: timing.fast }, tap: { y: shouldReduceMotion ? 0 : 1, transition: timing.fast } }; const iconVariants = { initial: { opacity: 0, x: iconPosition === 'left' ? -10 : 10 }, animate: { opacity: 1, x: 0, transition: { duration: shouldReduceMotion ? 0.1 : 0.2, ease: [0.4, 0, 0.2, 1] } } }; const loadingVariants = { initial: { opacity: 0 }, animate: { opacity: 1, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] } } }; // Animated dots for loading const LoadingDots = () => /*#__PURE__*/jsxs(motion.div, { className: "nex-button-loading-dots", variants: loadingVariants, initial: "initial", animate: "animate", children: [/*#__PURE__*/jsx(motion.span, { animate: { opacity: [0.3, 1, 0.3] }, transition: { duration: 1.4, repeat: Infinity, ease: "easeInOut" }, children: "." }), /*#__PURE__*/jsx(motion.span, { animate: { opacity: [0.3, 1, 0.3] }, transition: { duration: 1.4, repeat: Infinity, ease: "easeInOut", delay: 0.2 }, children: "." }), /*#__PURE__*/jsx(motion.span, { animate: { opacity: [0.3, 1, 0.3] }, transition: { duration: 1.4, repeat: Infinity, ease: "easeInOut", delay: 0.4 }, children: "." })] }); return /*#__PURE__*/jsxs(motion.button, { className: buttonClasses, onClick: handleClick, onKeyDown: handleKeyDown, disabled: disabled || loading, role: "button", tabIndex: disabled ? -1 : 0, "aria-disabled": disabled || loading, "aria-label": text, variants: buttonVariants, initial: "initial", animate: "animate", whileHover: disabled || loading ? {} : "hover", whileTap: disabled || loading ? {} : "tap", whileFocus: { outline: "2px solid var(--nex-signature)", outlineOffset: "2px", transition: timing.fast }, ...rest, children: [loading && /*#__PURE__*/jsx(LoadingDots, {}), /*#__PURE__*/jsxs("div", { className: "nex-button-content", children: [icon && !loading && /*#__PURE__*/jsx(motion.div, { className: `nex-button-icon nex-button-icon--${iconPosition}`, variants: iconVariants, initial: "initial", animate: "animate", children: icon }), text && !loading && /*#__PURE__*/jsx(motion.span, { className: "nex-button-text", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { delay: shouldReduceMotion ? 0 : 0.1 }, children: text })] }), /*#__PURE__*/jsx(motion.div, { className: "nex-button-ripple", initial: { scale: 0, opacity: 0 }, whileTap: { scale: 2, opacity: [0, 0.3, 0], transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] } } })] }); }; var styles$3 = {"nexCard":"NexCard-module_nexCard__R-GNN","sizeSm":"NexCard-module_sizeSm__an0N3","sizeMd":"NexCard-module_sizeMd__65SfJ","sizeLg":"NexCard-module_sizeLg__mQIDI","sizeXl":"NexCard-module_sizeXl__F3pvi","layoutHorizontal":"NexCard-module_layoutHorizontal__mnQhY","content":"NexCard-module_content__de7gS","media":"NexCard-module_media__a-rqN","layoutAuto":"NexCard-module_layoutAuto__aXZfA","elevationFlat":"NexCard-module_elevationFlat__pP-hg","elevationRaised":"NexCard-module_elevationRaised__xuRdM","elevationHoverable":"NexCard-module_elevationHoverable__x609F","elevationInteractive":"NexCard-module_elevationInteractive__px3gA","variantDefault":"NexCard-module_variantDefault__pWbL-","variantGlass":"NexCard-module_variantGlass__8koFA","variantPremium":"NexCard-module_variantPremium__APZ-X","variantMinimal":"NexCard-module_variantMinimal__Yu9Kn","loading":"NexCard-module_loading__Eq9Kd","disabled":"NexCard-module_disabled__GZQBb","header":"NexCard-module_header__k1x2-","headerContent":"NexCard-module_headerContent__jeAey","icon":"NexCard-module_icon__OO6F0","title":"NexCard-module_title__2X8yw","subtitle":"NexCard-module_subtitle__1y0RW","description":"NexCard-module_description__gJYN4","body":"NexCard-module_body__CPZSu","footer":"NexCard-module_footer__rtvgr","actions":"NexCard-module_actions__QrzMI","image":"NexCard-module_image__-K2tb","aspectRatioSquare":"NexCard-module_aspectRatioSquare__E8FCT","aspectRatioVideo":"NexCard-module_aspectRatioVideo__ZSboW","aspectRatioWide":"NexCard-module_aspectRatioWide__BpNP4","aspectRatioAuto":"NexCard-module_aspectRatioAuto__RBIUQ","imageOverlay":"NexCard-module_imageOverlay__6BFUK","ripple":"NexCard-module_ripple__zYUIj","skeleton":"NexCard-module_skeleton__Gz-m6","skeleton-loading":"NexCard-module_skeleton-loading__Pw--n","skeletonTitle":"NexCard-module_skeletonTitle__VgOtV","skeletonDescription":"NexCard-module_skeletonDescription__xi-8Y"}; const NexCardContext = /*#__PURE__*/createContext(null); /** * NexCard - Premium Enterprise Card Component * * A sophisticated, animated card component with Apple-like design principles. * Features smooth animations, multiple elevation levels, responsive layouts, * and comprehensive accessibility support. * * @example * ```tsx * <NexCard * title="Premium Feature" * subtitle="Enterprise Grade" * description="Advanced functionality for professional users" * elevation="interactive" * onClick={() => console.log('Card clicked')} * /> * ``` */ const NexCard = ({ // Content title, subtitle, description, children, // Media image, icon, // Layout & Styling variant = 'default', elevation = 'flat', layout = 'vertical', size = 'md', // Interactive Features interactive = false, clickable = false, href, as, onClick, // States loading = false, disabled = false, // Custom Slots header, footer, actions, // Accessibility 'aria-label': ariaLabel, 'aria-describedby': ariaDescribedBy, // Styling className, style, // Animation animate = true, delay = 0, // Legacy support content, imageUrl, badge, type, elevated, ...rest }) => { const { shouldReduceMotion } = useAnimationConfig(); const [isPressed, setIsPressed] = useState(false); const [rippleKey, setRippleKey] = useState(0); const cardRef = useRef(null); // Legacy prop mapping const finalDescription = description || content; const finalImage = image || (imageUrl ? { src: imageUrl } : undefined); const finalVariant = variant || (type === 'glass' ? 'glass' : type === 'enterprise' ? 'premium' : 'default'); const finalElevation = elevation || (elevated ? 'raised' : 'flat'); const finalInteractive = interactive || clickable || !!onClick || !!href; // Determine the element type const Element = as || (href ? 'a' : finalInteractive ? 'button' : 'div'); // Context value const contextValue = useMemo(() => ({ variant: finalVariant, elevation: finalElevation, layout, size, interactive: finalInteractive, clickable: finalInteractive, loading, disabled }), [finalVariant, finalElevation, layout, size, finalInteractive, loading, disabled]); // Animation variants - Clean, elegant Apple-like animations const cardVariants = { initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0, transition: { duration: shouldReduceMotion ? 0.2 : 0.4, delay: shouldReduceMotion ? 0 : delay * 0.1, ease: [0.4, 0, 0.2, 1] } }, hover: finalInteractive && !loading && !disabled ? { y: shouldReduceMotion ? 0 : -2, transition: { duration: 0.3, ease: [0.4, 0, 0.2, 1] } } : {}, tap: finalInteractive && !loading && !disabled ? { y: shouldReduceMotion ? 0 : -1, transition: { duration: 0.1, ease: [0.4, 0, 0.2, 1] } } : {} }; // Ripple animation variants - Subtle, elegant effect const rippleVariants = { initial: { scale: 0, opacity: 0 }, animate: { scale: 1.5, opacity: [0, 0.2, 0], transition: { duration: 0.4, ease: [0.4, 0, 0.2, 1] } } }; // Event handlers const handleClick = event => { if (loading || disabled) return; if (finalInteractive) { // Create ripple effect setRippleKey(prev => prev + 1); // Call onClick if provided if (onClick) { onClick(event); } } }; const handleKeyDown = event => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); if (finalInteractive && !loading && !disabled) { handleClick(event); } } }; const handleMouseDown = () => { if (finalInteractive && !loading && !disabled) { setIsPressed(true); } }; const handleMouseUp = () => { setIsPressed(false); }; // Build class names const cardClasses = [styles$3.nexCard, styles$3[`size${size.charAt(0).toUpperCase() + size.slice(1)}`], styles$3[`layout${layout.charAt(0).toUpperCase() + layout.slice(1)}`], styles$3[`elevation${finalElevation.charAt(0).toUpperCase() + finalElevation.slice(1)}`], styles$3[`variant${finalVariant.charAt(0).toUpperCase() + finalVariant.slice(1)}`], loading && styles$3.loading, disabled && styles$3.disabled, className].filter(Boolean).join(' '); // Accessibility props const accessibilityProps = { role: Element === 'button' ? 'button' : Element === 'a' ? 'link' : undefined, tabIndex: finalInteractive ? 0 : undefined, 'aria-label': ariaLabel || (finalInteractive ? title : undefined), 'aria-describedby': ariaDescribedBy, 'aria-disabled': disabled || loading, 'aria-busy': loading }; // Element props const elementProps = { href: Element === 'a' ? href : undefined, type: Element === 'button' ? 'button' : undefined }; // Render skeleton loading state if (loading) { return /*#__PURE__*/jsx("div", { className: cardClasses, style: style, ...rest, children: /*#__PURE__*/jsxs("div", { className: styles$3.content, children: [/*#__PURE__*/jsxs("div", { className: styles$3.header, children: [/*#__PURE__*/jsxs("div", { className: styles$3.headerContent, children: [/*#__PURE__*/jsx("div", { className: `${styles$3.skeleton} ${styles$3.skeletonTitle}` }), subtitle && /*#__PURE__*/jsx("div", { className: `${styles$3.skeleton} ${styles$3.skeletonDescription}` })] }), icon && /*#__PURE__*/jsx("div", { className: styles$3.icon, children: icon })] }), /*#__PURE__*/jsxs("div", { className: styles$3.body, children: [/*#__PURE__*/jsx("div", { className: `${styles$3.skeleton} ${styles$3.skeletonDescription}` }), /*#__PURE__*/jsx("div", { className: `${styles$3.skeleton} ${styles$3.skeletonDescription}` }), /*#__PURE__*/jsx("div", { className: `${styles$3.skeleton} ${styles$3.skeletonDescription}` })] })] }) }); } return /*#__PURE__*/jsx(NexCardContext.Provider, { value: contextValue, children: /*#__PURE__*/jsxs(motion.div, { ref: cardRef, className: cardClasses, style: style, variants: animate ? cardVariants : undefined, initial: "initial", animate: "animate", whileHover: finalInteractive && !loading && !disabled ? "hover" : undefined, whileTap: finalInteractive && !loading && !disabled ? "tap" : undefined, onClick: handleClick, onKeyDown: handleKeyDown, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onMouseLeave: handleMouseUp, ...accessibilityProps, ...elementProps, ...rest, children: [finalImage && /*#__PURE__*/jsxs("div", { className: styles$3.media, children: [/*#__PURE__*/jsx("img", { src: finalImage.src, alt: finalImage.alt || title || 'Card image', className: `${styles$3.image} ${styles$3[`aspectRatio${finalImage.aspectRatio ? finalImage.aspectRatio.charAt(0).toUpperCase() + finalImage.aspectRatio.slice(1) : 'Auto'}`]}` }), /*#__PURE__*/jsx("div", { className: styles$3.imageOverlay })] }), /*#__PURE__*/jsxs("div", { className: styles$3.content, children: [(header || title || subtitle || icon) && /*#__PURE__*/jsxs("div", { className: styles$3.header, children: [/*#__PURE__*/jsx("div", { className: styles$3.headerContent, children: header || /*#__PURE__*/jsxs(Fragment, { children: [t