refactor: migrate frontend from shadcn/Tailwind to Mantine v9
Reescribe todos los componentes UI para usar Mantine v9 en lugar de shadcn/Tailwind. Elimina cn(), CVA, components.json, theme_provider custom y globals.css con Tailwind. Añade 25+ componentes nuevos (AppShell, AuthForm, DatePickerInput, Dropzone, etc.) y MantineProvider como wrapper estándar del sistema de temas. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,69 +1,57 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "../core/cn"
|
||||
import * as React from 'react'
|
||||
import { Avatar as MantineAvatar } from '@mantine/core'
|
||||
|
||||
const avatarVariants = cva(
|
||||
"relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted font-medium text-muted-foreground select-none",
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
xs: "size-6 text-xs",
|
||||
sm: "size-8 text-sm",
|
||||
md: "size-10 text-base",
|
||||
lg: "size-12 text-lg",
|
||||
xl: "size-16 text-xl",
|
||||
},
|
||||
},
|
||||
defaultVariants: { size: "md" },
|
||||
}
|
||||
)
|
||||
type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
|
||||
interface AvatarProps
|
||||
extends React.ComponentPropsWithoutRef<"span">,
|
||||
VariantProps<typeof avatarVariants> {
|
||||
const sizeMap: Record<AvatarSize, string> = {
|
||||
xs: 'sm',
|
||||
sm: 'sm',
|
||||
md: 'md',
|
||||
lg: 'lg',
|
||||
xl: 'xl',
|
||||
}
|
||||
|
||||
interface AvatarProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
src?: string
|
||||
alt?: string
|
||||
fallback?: string
|
||||
initials?: string
|
||||
size?: AvatarSize
|
||||
}
|
||||
|
||||
function getInitials(name?: string): string {
|
||||
if (!name) return "?"
|
||||
if (!name) return '?'
|
||||
const parts = name.trim().split(/\s+/)
|
||||
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase()
|
||||
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
||||
const first = parts[0] ?? ''
|
||||
const last = parts[parts.length - 1] ?? ''
|
||||
if (parts.length === 1) return first.slice(0, 2).toUpperCase()
|
||||
return ((first[0] ?? '') + (last[0] ?? '')).toUpperCase()
|
||||
}
|
||||
|
||||
const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
|
||||
({ className, size, src, alt, fallback, initials, ...props }, ref) => {
|
||||
const [imgError, setImgError] = React.useState(false)
|
||||
const showImage = src && !imgError
|
||||
/** Kept for backwards compatibility */
|
||||
const avatarVariants = sizeMap
|
||||
|
||||
const Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(
|
||||
({ className, size = 'md', src, alt, fallback, initials, ...props }, ref) => {
|
||||
const displayInitials = initials ?? getInitials(fallback ?? alt)
|
||||
|
||||
return (
|
||||
<span
|
||||
<MantineAvatar
|
||||
ref={ref}
|
||||
data-slot="avatar"
|
||||
className={cn(avatarVariants({ size }), className)}
|
||||
src={src}
|
||||
alt={alt ?? ''}
|
||||
size={sizeMap[size]}
|
||||
radius="xl"
|
||||
className={className}
|
||||
{...props}
|
||||
>
|
||||
{showImage ? (
|
||||
<img
|
||||
src={src}
|
||||
alt={alt ?? ""}
|
||||
className="aspect-square size-full object-cover"
|
||||
onError={() => setImgError(true)}
|
||||
/>
|
||||
) : (
|
||||
<span data-slot="avatar-fallback" aria-hidden="true">
|
||||
{displayInitials}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
{displayInitials}
|
||||
</MantineAvatar>
|
||||
)
|
||||
}
|
||||
)
|
||||
Avatar.displayName = "Avatar"
|
||||
Avatar.displayName = 'Avatar'
|
||||
|
||||
export { Avatar, avatarVariants }
|
||||
export type { AvatarProps }
|
||||
export type { AvatarProps, AvatarSize }
|
||||
|
||||
Reference in New Issue
Block a user