mirror of
https://github.com/hanzoai/shadcn.git
synced 2026-11-03 03:18:52 +00:00
- Updated build-registry.mts to include all component types (ui, ai, 3d, animation, code, etc.) - Fixed missing components issue by processing all components that start with 'components:' - Now properly handles components that only exist in one theme variant - Registry now contains 363 components (up from 117) - AI, 3D, animation, and code components are now accessible via the registry
14 lines
7.4 KiB
JSON
14 lines
7.4 KiB
JSON
{
|
|
"name": "3d-card",
|
|
"description": "Card with 3D tilt effect",
|
|
"dependencies": [
|
|
"motion"
|
|
],
|
|
"files": [
|
|
{
|
|
"name": "3d-card.tsx",
|
|
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ninterface Point {\n x: number\n y: number\n}\n\ninterface Card3DProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n maxTilt?: number\n perspective?: number\n scale?: number\n speed?: number\n glare?: boolean\n glareMaxOpacity?: number\n className?: string\n}\n\nconst Card3D = React.forwardRef<HTMLDivElement, Card3DProps>(\n (\n {\n children,\n maxTilt = 15,\n perspective = 1000,\n scale = 1.05,\n speed = 400,\n glare = true,\n glareMaxOpacity = 0.7,\n className,\n ...props\n },\n ref\n ) => {\n const cardRef = React.useRef<HTMLDivElement>(null)\n const glareRef = React.useRef<HTMLDivElement>(null)\n const [isHovered, setIsHovered] = React.useState(false)\n const [transforms, setTransforms] = React.useState({\n rotateX: 0,\n rotateY: 0,\n scale: 1,\n glareX: 50,\n glareY: 50,\n glareOpacity: 0,\n })\n\n const updateTransforms = React.useCallback(\n (point: Point | null, rect: DOMRect | null) => {\n if (!point || !rect) {\n setTransforms({\n rotateX: 0,\n rotateY: 0,\n scale: 1,\n glareX: 50,\n glareY: 50,\n glareOpacity: 0,\n })\n return\n }\n\n const centerX = rect.left + rect.width / 2\n const centerY = rect.top + rect.height / 2\n\n const deltaX = (point.x - centerX) / (rect.width / 2)\n const deltaY = (point.y - centerY) / (rect.height / 2)\n\n const rotateX = -deltaY * maxTilt\n const rotateY = deltaX * maxTilt\n\n const glareX = ((point.x - rect.left) / rect.width) * 100\n const glareY = ((point.y - rect.top) / rect.height) * 100\n\n setTransforms({\n rotateX,\n rotateY,\n scale,\n glareX,\n glareY,\n glareOpacity: glare ? glareMaxOpacity : 0,\n })\n },\n [maxTilt, scale, glare, glareMaxOpacity]\n )\n\n const handleMouseMove = React.useCallback(\n (e: React.MouseEvent) => {\n if (!cardRef.current) return\n\n const rect = cardRef.current.getBoundingClientRect()\n const point = { x: e.clientX, y: e.clientY }\n updateTransforms(point, rect)\n },\n [updateTransforms]\n )\n\n const handleTouchMove = React.useCallback(\n (e: React.TouchEvent) => {\n if (!cardRef.current || e.touches.length === 0) return\n\n e.preventDefault()\n const rect = cardRef.current.getBoundingClientRect()\n const touch = e.touches[0]\n const point = { x: touch.clientX, y: touch.clientY }\n updateTransforms(point, rect)\n },\n [updateTransforms]\n )\n\n const handleMouseEnter = React.useCallback(() => {\n setIsHovered(true)\n }, [])\n\n const handleMouseLeave = React.useCallback(() => {\n setIsHovered(false)\n updateTransforms(null, null)\n }, [updateTransforms])\n\n const handleTouchStart = React.useCallback(() => {\n setIsHovered(true)\n }, [])\n\n const handleTouchEnd = React.useCallback(() => {\n setIsHovered(false)\n updateTransforms(null, null)\n }, [updateTransforms])\n\n const cardStyle: React.CSSProperties = {\n transform: `perspective(${perspective}px) rotateX(${transforms.rotateX}deg) rotateY(${transforms.rotateY}deg) scale(${transforms.scale})`,\n transition: isHovered\n ? \"none\"\n : `transform ${speed}ms cubic-bezier(0.03, 0.98, 0.52, 0.99)`,\n transformStyle: \"preserve-3d\",\n }\n\n const glareStyle: React.CSSProperties = {\n background: `radial-gradient(circle at ${transforms.glareX}% ${transforms.glareY}%, rgba(255,255,255,${transforms.glareOpacity}) 0%, transparent 50%)`,\n transition: isHovered ? \"none\" : `opacity ${speed}ms ease-out`,\n }\n\n React.useImperativeHandle(ref, () => cardRef.current!)\n\n return (\n <div\n ref={cardRef}\n className={cn(\n \"relative rounded-lg border bg-card text-card-foreground shadow-lg cursor-pointer\",\n \"transform-gpu will-change-transform\",\n className\n )}\n style={cardStyle}\n onMouseMove={handleMouseMove}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n {...props}\n >\n {/* Content Layer */}\n <div className=\"relative z-10\">{children}</div>\n\n {/* Glare Effect */}\n {glare && (\n <div\n ref={glareRef}\n className=\"absolute inset-0 rounded-lg pointer-events-none z-20\"\n style={glareStyle}\n />\n )}\n </div>\n )\n }\n)\nCard3D.displayName = \"Card3D\"\n\n// Depth layer components that work with 3D transforms\nconst Card3DHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { depth?: number }\n>(({ className, depth = 20, style, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n style={{\n transform: `translateZ(${depth}px)`,\n ...style,\n }}\n {...props}\n />\n))\nCard3DHeader.displayName = \"Card3DHeader\"\n\nconst Card3DTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement> & { depth?: number }\n>(({ className, depth = 30, style, ...props }, ref) => (\n <h3\n ref={ref}\n className={cn(\n \"text-2xl font-semibold leading-none tracking-tight\",\n className\n )}\n style={{\n transform: `translateZ(${depth}px)`,\n ...style,\n }}\n {...props}\n />\n))\nCard3DTitle.displayName = \"Card3DTitle\"\n\nconst Card3DDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement> & { depth?: number }\n>(({ className, depth = 10, style, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n style={{\n transform: `translateZ(${depth}px)`,\n ...style,\n }}\n {...props}\n />\n))\nCard3DDescription.displayName = \"Card3DDescription\"\n\nconst Card3DContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { depth?: number }\n>(({ className, depth = 25, style, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"p-6 pt-0\", className)}\n style={{\n transform: `translateZ(${depth}px)`,\n ...style,\n }}\n {...props}\n />\n))\nCard3DContent.displayName = \"Card3DContent\"\n\nconst Card3DFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { depth?: number }\n>(({ className, depth = 15, style, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex items-center p-6 pt-0\", className)}\n style={{\n transform: `translateZ(${depth}px)`,\n ...style,\n }}\n {...props}\n />\n))\nCard3DFooter.displayName = \"Card3DFooter\"\n\nexport {\n Card3D,\n Card3DHeader,\n Card3DTitle,\n Card3DDescription,\n Card3DContent,\n Card3DFooter,\n}\n"
|
|
}
|
|
],
|
|
"type": "components:3d"
|
|
} |