0889ee9117
feat(hooks): add useLiveStream generic WebSocket hook - supports websocket/sse/polling transports - exponential backoff reconnect with jitter - circular buffer with configurable size - typed filter callback per use case - manual disconnect + reconnect + error state feat(hooks): add useLiveMetrics derived hook - sliding time-window cut - moving average (configurable window) - current / avg / min / max / ratePerSecond - zero allocations per tick (memoized) feat(charts): add LiveMetricChart molecule (Recharts) - line + area variants, grid + tooltip - moving-average overlay (dashed) - ConnectionStatus atom in header - status bar + compact mode - 100% responsive, GPU via SVG ViewBox feat(atoms): add ConnectionStatus indicator - 5 states: disconnected/connecting/connected/reconnecting/error - animated pulse, JetBrains Mono, pill style - exported helpers: formatLatency / formatBytes docs(pkg): bump v0.1.0 → v0.2.0, add recharts peerDep
1 line
8.6 KiB
Plaintext
Executable File
1 line
8.6 KiB
Plaintext
Executable File
{"version":3,"sources":["../../src/components/index.tsx"],"sourcesContent":["/**\n * Componentes atômicos — Receptor de className sempre no topo,\n * spread de props SEMPRE por último.\n */\n\nimport { cn } from '../utils';\n\n// =========================================================\n// 🅱 Button\n// =========================================================\ntype ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'success';\ntype ButtonSize = 'sm' | 'md' | 'lg';\n\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n loading?: boolean;\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary: 'bg-indigo-600 text-white hover:bg-indigo-700 active:bg-indigo-800 disabled:bg-indigo-300',\n secondary: 'border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 active:bg-gray-100',\n ghost: 'text-gray-600 hover:bg-gray-100 active:bg-gray-200',\n danger: 'bg-red-600 text-white hover:bg-red-700 active:bg-red-800',\n success: 'bg-emerald-600 text-white hover:bg-emerald-700 active:bg-emerald-800',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: 'px-2.5 py-1 text-xs rounded',\n md: 'px-4 py-2 text-sm rounded-md',\n lg: 'px-6 py-3 text-base rounded-lg',\n};\n\nexport function Button({\n className, variant = 'primary', size = 'md',\n loading, leftIcon, rightIcon,\n children, disabled, ...rest\n}: ButtonProps) {\n return (\n <button\n className={cn(\n 'inline-flex items-center justify-center gap-2 font-medium transition-colors',\n 'focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n variantStyles[variant], sizeStyles[size], className\n )}\n disabled={disabled || loading}\n {...rest}\n >\n {loading ? <Spinner size={16} /> : (leftIcon ?? null)}\n {children}\n {!loading && rightIcon}\n </button>\n );\n}\n\n// =========================================================\n// 🅸 Input\n// =========================================================\ninterface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n hint?: string;\n}\n\nexport function Input({ className, label, error, hint, id, ...rest }: InputProps) {\n const inputId = id ?? label?.toLowerCase().replace(/\\s+/g, '-');\n return (\n <div className=\"flex flex-col gap-1\">\n {label && <label htmlFor={inputId} className=\"text-sm font-medium text-gray-700\">{label}</label>}\n <input\n id={inputId}\n className={cn(\n 'w-full rounded-md border border-gray-300 px-3 py-2 text-sm',\n 'placeholder:text-gray-400',\n 'focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500',\n 'disabled:bg-gray-100 disabled:cursor-not-allowed',\n error && 'border-red-500 focus:ring-red-500 focus:border-red-500',\n className\n )}\n {...rest}\n />\n {error && <span className=\"text-xs text-red-500\">{error}</span>}\n {hint && !error && <span className=\"text-xs text-gray-400\">{hint}</span>}\n </div>\n );\n}\n\n// =========================================================\n// 🔔 Toast / Alert\n// =========================================================\ntype AlertVariant = 'info' | 'success' | 'warning' | 'error';\n\ninterface AlertProps {\n variant?: AlertVariant;\n title?: string;\n children: React.ReactNode;\n onClose?: () => void;\n}\n\nconst alertStyles: Record<AlertVariant, { container: string; icon: string }> = {\n info: { container: 'bg-blue-50 border-blue-200 text-blue-800', icon: 'ℹ️' },\n success: { container: 'bg-emerald-50 border-emerald-200 text-emerald-800', icon: '✅' },\n warning: { container: 'bg-amber-50 border-amber-200 text-amber-800', icon: '⚠️' },\n error: { container: 'bg-red-50 border-red-200 text-red-800', icon: '❌' },\n};\n\nexport function Alert({ variant = 'info', title, children, onClose }: AlertProps) {\n const s = alertStyles[variant];\n return (\n <div className={cn('flex items-start gap-2 rounded-lg border px-4 py-3', s.container)}>\n <span className=\"text-base leading-none\">{s.icon}</span>\n <div className=\"flex-1\">\n {title && <p className=\"font-semibold text-sm\">{title}</p>}\n <p className=\"text-sm\">{children}</p>\n </div>\n {onClose && <button onClick={onClose} className=\"ml-auto text-lg leading-none opacity-50 hover:opacity-100\">×</button>}\n </div>\n );\n}\n\n// =========================================================\n// 🃏 Card\n// =========================================================\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> { children: React.ReactNode; }\nexport const Card: React.FC<CardProps> = ({ className, children, ...rest }) => (\n <div className={cn('rounded-xl border border-gray-200 bg-white shadow-sm', className)} {...rest}>{children}</div>\n);\nexport const CardHeader: React.FC<CardProps> = ({ className, children, ...rest }) => (\n <div className={cn('px-5 py-4 border-b border-gray-100', className)} {...rest}>{children}</div>\n);\nexport const CardTitle: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <h3 className=\"font-semibold text-gray-900 text-base\">{children}</h3>\n);\nexport const CardBody: React.FC<CardProps> = ({ className, children, ...rest }) => (\n <div className={cn('px-5 py-4', className)} {...rest}>{children}</div>\n);\n\n// ── Spinner (reutilizável) ─────────────────────────────────\nexport function Spinner({ size = 16, className = '' }: { size?: number; className?: string }) {\n return (\n <svg className={cn('animate-spin', className)} width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\" />\n </svg>\n );\n}\n\n// ── Cn helper re-export ────────────────────────────────────\nexport { cn } from '../utils';\n"],"mappings":"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","names":[]} |