Create standalone browser port of LTX Athena with authenticated native API transport

This commit is contained in:
Mikei386 committed 2026-09-29 17:59:23 +02:00
commit 1333b0c36b
202 files changed
+63054

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
destructive: 'bg-red-500 text-white shadow-sm hover:bg-red-600',
outline: 'border border-border bg-transparent shadow-sm hover:bg-secondary',
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
ghost: 'hover:bg-secondary hover:text-secondary-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-9 px-4 py-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
icon: 'h-9 w-9',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = 'Button'
export { Button, buttonVariants }
+40
View File
@@ -0,0 +1,40 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {
value?: number
max?: number
showLabel?: boolean
}
const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
({ className, value = 0, max = 100, showLabel = false, ...props }, ref) => {
const percentage = Math.min(100, Math.max(0, (value / max) * 100))
return (
<div className="w-full">
<div
ref={ref}
className={cn(
'relative h-2 w-full overflow-hidden rounded-full bg-secondary',
className
)}
{...props}
>
<div
className="h-full bg-primary transition-all duration-300 ease-in-out"
style={{ width: `${percentage}%` }}
/>
</div>
{showLabel && (
<span className="text-xs text-muted-foreground mt-1 block text-right">
{Math.round(percentage)}%
</span>
)}
</div>
)
}
)
Progress.displayName = 'Progress'
export { Progress }
+47
View File
@@ -0,0 +1,47 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
import { ChevronDown } from 'lucide-react'
interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
label?: string
badge?: string
}
const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
({ className, label, badge, children, ...props }, ref) => {
return (
<div className="relative">
{label && (
<label className="flex items-center gap-2 text-[12px] font-semibold text-zinc-500 mb-2 uppercase leading-4 h-4">
{label}
{badge && (
<span className="px-1.5 py-0.5 text-[10px] bg-zinc-700 text-zinc-300 rounded border border-zinc-600 font-semibold leading-none">
{badge}
</span>
)}
</label>
)}
<div className="relative">
<select
className={cn(
'flex h-10 w-full appearance-none rounded-lg border border-zinc-700 bg-zinc-800 px-3 py-2 text-sm text-white',
'focus:outline-none focus:ring-1 focus:ring-zinc-500 focus:border-zinc-500',
'disabled:cursor-not-allowed disabled:opacity-50',
'pr-8 cursor-pointer',
'[&>option]:bg-zinc-800 [&>option]:text-white [&>option:disabled]:text-zinc-500',
className
)}
ref={ref}
{...props}
>
{children}
</select>
<ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400 pointer-events-none" />
</div>
</div>
)
}
)
Select.displayName = 'Select'
export { Select }
+48
View File
@@ -0,0 +1,48 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
label?: string
helperText?: string
charCount?: number
maxChars?: number
}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, label, helperText, charCount, maxChars, ...props }, ref) => {
return (
<div className="w-full">
{label && (
<label className="block text-[12px] font-semibold text-zinc-500 mb-2 uppercase leading-4">
{label}
</label>
)}
<textarea
className={cn(
'flex min-h-[120px] w-full rounded-lg border border-zinc-700 bg-zinc-800 px-3 py-3 text-sm text-white',
'placeholder:text-zinc-500',
'focus:outline-none focus:ring-1 focus:ring-zinc-500 focus:border-zinc-500',
'disabled:cursor-not-allowed disabled:opacity-50',
'resize-y',
className
)}
ref={ref}
{...props}
/>
<div className="flex justify-between mt-2">
{helperText && (
<span className="text-xs text-zinc-500">{helperText}</span>
)}
{maxChars !== undefined && (
<span className="text-xs text-zinc-500 ml-auto">
{charCount ?? 0}/{maxChars}
</span>
)}
</div>
</div>
)
}
)
Textarea.displayName = 'Textarea'
export { Textarea }
+75
View File
@@ -0,0 +1,75 @@
import React, { useState, useRef, useCallback, useEffect } from 'react'
import ReactDOM from 'react-dom'
import { cn } from '@/lib/utils'
interface TooltipProps {
content: React.ReactNode
children: React.ReactNode
/** Which side of the trigger the tooltip appears on. Default: 'top' */
side?: 'top' | 'bottom' | 'left' | 'right'
className?: string
}
const DELAY_MS = 500
const GAP_PX = 6
/**
* Styled tooltip with 250ms show delay and instant hide.
* Renders via a portal into document.body so it is never clipped
* by overflow-hidden ancestors.
*/
export function Tooltip({ content, children, side = 'top', className }: TooltipProps) {
const [visible, setVisible] = useState(false)
const [style, setStyle] = useState<React.CSSProperties>({})
const wrapperRef = useRef<HTMLDivElement>(null)
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const computeStyle = useCallback(() => {
const rect = wrapperRef.current?.getBoundingClientRect()
if (!rect) return {}
switch (side) {
case 'top':
return { left: rect.left + rect.width / 2, top: rect.top - GAP_PX, transform: 'translate(-50%, -100%)' }
case 'bottom':
return { left: rect.left + rect.width / 2, top: rect.bottom + GAP_PX, transform: 'translate(-50%, 0)' }
case 'left':
return { left: rect.left - GAP_PX, top: rect.top + rect.height / 2, transform: 'translate(-100%, -50%)' }
case 'right':
return { left: rect.right + GAP_PX, top: rect.top + rect.height / 2, transform: 'translate(0, -50%)' }
}
}, [side])
const handleMouseEnter = useCallback(() => {
timerRef.current = setTimeout(() => {
setStyle(computeStyle() ?? {})
setVisible(true)
}, DELAY_MS)
}, [computeStyle])
const handleMouseLeave = useCallback(() => {
if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null }
setVisible(false)
}, [])
useEffect(() => () => { if (timerRef.current) clearTimeout(timerRef.current) }, [])
return (
<div
ref={wrapperRef}
className={cn('inline-flex', className)}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{children}
{visible && ReactDOM.createPortal(
<div
className="fixed z-[99999] px-2.5 py-1.5 bg-white text-zinc-800 text-xs font-medium rounded-md shadow-md whitespace-nowrap pointer-events-none select-none"
style={style}
>
{content}
</div>,
document.body,
)}
</div>
)
}