{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"testimonials-05","type":"registry:component","title":"Testimonials 05","description":"Auto-scrolling testimonials with infinite horizontal scroll, customizable scroll speed, and bottom statistics section. Features smooth infinite scrolling animation, gradient edge overlays, and responsive testimonial cards. Perfect for showcasing large volumes of customer feedback with engaging visual presentation and supporting metrics.","dependencies":["lucide-react"],"registryDependencies":["card","avatar","badge"],"files":[{"path":"src/registry/blocks/marketing/social-proof/testimonials/testimonials-05.tsx","content":"\"use client\";\n\nimport { type LucideIcon, Quote, Star } from \"lucide-react\";\nimport Image from \"next/image\";\nimport { useEffect, useRef } from \"react\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/registry/ui/avatar\";\nimport { Badge } from \"@/registry/ui/badge\";\nimport { Card, CardContent } from \"@/registry/ui/card\";\n\nexport interface ScrollingTestimonial {\n  id: number;\n  name: string;\n  role: string;\n  company: string;\n  avatar?: string;\n  rating: number;\n  content: string;\n  companyLogo?: string;\n}\n\nexport interface StatItem {\n  value: string;\n  label: string;\n}\n\nexport interface Testimonials05Props {\n  title?: string;\n  subtitle?: string;\n  badgeText?: string;\n  badgeIcon?: LucideIcon;\n  testimonials?: ScrollingTestimonial[];\n  stats?: StatItem[];\n  scrollSpeed?: number;\n  backgroundColor?: string;\n  className?: string;\n}\n\nconst defaultTestimonials: ScrollingTestimonial[] = [\n  {\n    id: 1,\n    name: \"Sarah Johnson\",\n    role: \"CEO\",\n    company: \"TechStart Inc.\",\n    avatar: \"https://randomuser.me/api/portraits/women/40.jpg\",\n    rating: 5,\n    content:\n      \"This platform has completely transformed how we manage our projects. The intuitive interface and powerful features have increased our team's productivity by 40%.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 2,\n    name: \"Michael Chen\",\n    role: \"Product Manager\",\n    company: \"InnovateCorp\",\n    avatar: \"https://randomuser.me/api/portraits/men/41.jpg\",\n    rating: 5,\n    content:\n      \"The customer support is exceptional, and the features are exactly what we needed. Our development cycle has become much more efficient.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 3,\n    name: \"Emily Rodriguez\",\n    role: \"Marketing Director\",\n    company: \"GrowthLab\",\n    avatar: \"https://randomuser.me/api/portraits/women/42.jpg\",\n    rating: 5,\n    content:\n      \"Amazing results! We've seen a 60% increase in our campaign effectiveness. The analytics dashboard provides insights we never had before.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 4,\n    name: \"David Park\",\n    role: \"CTO\",\n    company: \"DevSolutions\",\n    avatar: \"https://randomuser.me/api/portraits/men/43.jpg\",\n    rating: 5,\n    content:\n      \"Seamless integration with our existing tools and excellent API documentation. The technical support team is knowledgeable and responsive.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 5,\n    name: \"Lisa Thompson\",\n    role: \"Operations Manager\",\n    company: \"StreamlineOps\",\n    avatar: \"https://randomuser.me/api/portraits/women/44.jpg\",\n    rating: 5,\n    content:\n      \"The automation features have saved us countless hours every week. What used to take our team days now happens automatically.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 6,\n    name: \"James Wilson\",\n    role: \"Founder\",\n    company: \"StartupHub\",\n    avatar: \"https://randomuser.me/api/portraits/men/45.jpg\",\n    rating: 5,\n    content:\n      \"As a startup, we needed something reliable and scalable. This platform grows with us and the pricing is fair.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 7,\n    name: \"Rachel Green\",\n    role: \"VP of Marketing\",\n    company: \"GrowthCorp\",\n    avatar: \"https://randomuser.me/api/portraits/women/46.jpg\",\n    rating: 5,\n    content:\n      \"The ROI has been incredible. We've increased our conversion rate by 180% in just 3 months using this platform.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n  {\n    id: 8,\n    name: \"Thomas Anderson\",\n    role: \"CTO\",\n    company: \"TechInnovate\",\n    avatar: \"https://randomuser.me/api/portraits/men/47.jpg\",\n    rating: 5,\n    content:\n      \"We reduced deployment time by 75% and improved system reliability. The platform exceeded all our expectations.\",\n    companyLogo: \"/placeholder.svg?height=32&width=120\",\n  },\n];\n\nconst defaultStats: StatItem[] = [\n  { value: \"25,000+\", label: \"Happy Customers\" },\n  { value: \"4.9★\", label: \"Average Rating\" },\n  { value: \"150+\", label: \"Countries\" },\n  { value: \"99%\", label: \"Satisfaction\" },\n];\n\nexport function Testimonials05({\n  title = \"What our customers are saying\",\n  subtitle = \"Join thousands of satisfied customers who have transformed their business with our platform.\",\n  badgeText = \"Customer Reviews\",\n  badgeIcon: BadgeIcon = Quote,\n  testimonials = defaultTestimonials,\n  stats = defaultStats,\n  scrollSpeed = 30,\n  backgroundColor = \"bg-gradient-to-r from-muted/30 via-background to-muted/30\",\n  className = \"\",\n}: Testimonials05Props) {\n  const scrollRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const scrollContainer = scrollRef.current;\n    if (!scrollContainer) return;\n\n    const scrollWidth = scrollContainer.scrollWidth;\n    const clientWidth = scrollContainer.clientWidth;\n    let scrollPosition = 0;\n\n    const scroll = () => {\n      scrollPosition += 1;\n      if (scrollPosition >= scrollWidth - clientWidth) {\n        scrollPosition = 0;\n      }\n      scrollContainer.scrollLeft = scrollPosition;\n    };\n\n    const intervalId = setInterval(scroll, scrollSpeed);\n\n    return () => clearInterval(intervalId);\n  }, [scrollSpeed]);\n\n  const renderStars = (rating: number) => {\n    return Array.from({ length: 5 }, (_, i) => (\n      <Star\n        key={i}\n        className={`h-4 w-4 ${\n          i < rating\n            ? \"fill-yellow-400 text-yellow-400\"\n            : \"text-muted-foreground\"\n        }`}\n      />\n    ));\n  };\n\n  const getInitials = (name: string) => {\n    return name\n      .split(\" \")\n      .map((n) => n[0])\n      .join(\"\")\n      .toUpperCase();\n  };\n\n  // Duplicate testimonials for infinite scroll effect\n  const duplicatedTestimonials = [...testimonials, ...testimonials];\n\n  return (\n    <section\n      className={`py-12 sm:py-16 lg:py-20 ${backgroundColor} overflow-hidden ${className}`}\n    >\n      <div className=\"container px-4 sm:px-6 lg:px-8 mb-12\">\n        {/* Header */}\n        <div className=\"text-center\">\n          {badgeText && (\n            <Badge variant=\"secondary\" className=\"mb-4\">\n              <BadgeIcon className=\"h-4 w-4 mr-1\" />\n              {badgeText}\n            </Badge>\n          )}\n          <h2 className=\"text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight mb-4\">\n            {title}\n          </h2>\n          <p className=\"text-lg sm:text-xl text-muted-foreground max-w-2xl mx-auto\">\n            {subtitle}\n          </p>\n        </div>\n      </div>\n\n      {/* Full-width scrolling testimonials */}\n      <div className=\"relative\">\n        {/* Gradient overlays */}\n        <div className=\"absolute left-0 top-0 bottom-0 w-32 bg-gradient-to-r from-background to-transparent z-10 pointer-events-none\" />\n        <div className=\"absolute right-0 top-0 bottom-0 w-32 bg-gradient-to-l from-background to-transparent z-10 pointer-events-none\" />\n\n        <div\n          ref={scrollRef}\n          className=\"flex space-x-6 overflow-hidden\"\n          style={{\n            width: \"100vw\",\n            marginLeft: \"calc(-50vw + 50%)\",\n          }}\n        >\n          {duplicatedTestimonials.map((testimonial, index) => (\n            <Card\n              key={`${testimonial.id}-${index}`}\n              className=\"flex-shrink-0 w-80 sm:w-96 bg-background/80 backdrop-blur-sm border-border hover:shadow-lg transition-shadow\"\n            >\n              <CardContent className=\"p-6\">\n                {/* Quote Icon */}\n                <div className=\"mb-4\">\n                  <Quote className=\"h-6 w-6 text-primary/30\" />\n                </div>\n\n                {/* Rating */}\n                <div className=\"flex items-center space-x-1 mb-4\">\n                  {renderStars(testimonial.rating)}\n                </div>\n\n                {/* Content */}\n                <blockquote className=\"text-sm sm:text-base text-foreground mb-6 leading-relaxed line-clamp-4\">\n                  \"{testimonial.content}\"\n                </blockquote>\n\n                {/* Author Info */}\n                <div className=\"flex items-center space-x-3 mb-4\">\n                  <Avatar className=\"h-10 w-10\">\n                    <AvatarImage\n                      src={testimonial.avatar || \"/placeholder.svg\"}\n                      alt={testimonial.name}\n                    />\n                    <AvatarFallback>\n                      {getInitials(testimonial.name)}\n                    </AvatarFallback>\n                  </Avatar>\n                  <div className=\"flex-1 min-w-0\">\n                    <p className=\"text-sm font-semibold text-foreground truncate\">\n                      {testimonial.name}\n                    </p>\n                    <p className=\"text-xs text-muted-foreground truncate\">\n                      {testimonial.role} at {testimonial.company}\n                    </p>\n                  </div>\n                </div>\n\n                {/* Company Logo */}\n                {testimonial.companyLogo && (\n                  <div className=\"flex justify-center pt-4 border-t border-border\">\n                    <Image\n                      src={testimonial.companyLogo}\n                      alt={`${testimonial.company} logo`}\n                      width={120}\n                      height={20}\n                      className=\"h-5 opacity-60 hover:opacity-100 transition-opacity\"\n                    />\n                  </div>\n                )}\n              </CardContent>\n            </Card>\n          ))}\n        </div>\n      </div>\n\n      {/* Bottom stats */}\n      {stats.length > 0 && (\n        <div className=\"container px-4 sm:px-6 lg:px-8 mt-12\">\n          <div\n            className={`grid gap-6 lg:gap-8 max-w-4xl mx-auto ${\n              stats.length === 2\n                ? \"grid-cols-2\"\n                : stats.length === 3\n                  ? \"grid-cols-1 sm:grid-cols-3\"\n                  : stats.length === 4\n                    ? \"grid-cols-2 md:grid-cols-4\"\n                    : \"grid-cols-2 md:grid-cols-3 lg:grid-cols-5\"\n            }`}\n          >\n            {stats.map((stat, index) => (\n              <div key={index} className=\"text-center\">\n                <div className=\"text-2xl sm:text-3xl font-bold text-primary mb-1\">\n                  {stat.value}\n                </div>\n                <p className=\"text-sm text-muted-foreground\">{stat.label}</p>\n              </div>\n            ))}\n          </div>\n        </div>\n      )}\n    </section>\n  );\n}\n","type":"registry:component"},{"path":"src/registry/lib/utils.ts","content":"import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n","type":"registry:lib"}]}