{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"contact-01","type":"registry:component","title":"Contact 01","description":"A comprehensive contact component with split-layout design featuring contact information sidebar and detailed form. Features contact information with icons and multiline support, response time indicator card, comprehensive form with flexible field configuration, and professional styling. Perfect for business websites, service providers, and professional organizations requiring detailed contact capabilities with user-friendly form submission.","dependencies":["lucide-react","react-hook-form","@hookform/resolvers","zod"],"registryDependencies":["badge","button","card","input","textarea","form"],"files":[{"path":"src/registry/blocks/marketing/landing-pages/contact/contact-01.tsx","content":"\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Clock, type LucideIcon, Mail, MapPin, Phone } from \"lucide-react\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { cn } from \"@/registry/lib/utils\";\nimport { Badge } from \"@/registry/ui/badge\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/ui/card\";\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from \"@/registry/ui/form\";\nimport { Input } from \"@/registry/ui/input\";\nimport { Textarea } from \"@/registry/ui/textarea\";\n\ninterface ContactInfo {\n  id: string;\n  icon: LucideIcon;\n  label: string;\n  value: string | string[];\n  multiline?: boolean;\n}\n\ninterface FormFieldData {\n  id: string;\n  label: string;\n  type: \"text\" | \"email\" | \"tel\" | \"textarea\";\n  placeholder: string;\n  required?: boolean;\n  gridSpan?: \"full\" | \"half\";\n}\n\nconst formSchema = z.object({\n  firstName: z.string().min(2, \"First name must be at least 2 characters\"),\n  lastName: z.string().min(2, \"Last name must be at least 2 characters\"),\n  email: z.string().email(\"Please enter a valid email address\"),\n  phone: z.string().optional(),\n  subject: z.string().min(3, \"Subject must be at least 3 characters\"),\n  message: z.string().min(10, \"Message must be at least 10 characters\"),\n});\n\ntype FormValues = z.infer<typeof formSchema>;\n\nexport interface Contact01Props {\n  className?: string;\n}\n\nconst content: {\n  header: {\n    badge: {\n      text: string;\n      variant: \"outline\";\n      className: string;\n    };\n    title: string;\n    description: string;\n  };\n  maxWidth: string;\n  sectionPadding: string;\n  contactInfo: ContactInfo[];\n  responseTime: {\n    value: string;\n    label: string;\n  };\n  form: {\n    title: string;\n    description: string;\n    buttonText: string;\n    disclaimer: string;\n    fields: FormFieldData[];\n  };\n} = {\n  header: {\n    badge: {\n      text: \"Get in Touch\",\n      variant: \"outline\",\n      className: \"bg-primary/5 text-primary border-primary/20\",\n    },\n    title: \"Contact Us\",\n    description:\n      \"Have a question or want to work together? We'd love to hear from you. Send us a message and we'll respond as soon as possible.\",\n  },\n  maxWidth: \"max-w-6xl\",\n  sectionPadding: \"py-16 px-4\",\n  contactInfo: [\n    {\n      id: \"email\",\n      icon: Mail,\n      label: \"Email\",\n      value: \"hello@company.com\",\n    },\n    {\n      id: \"phone\",\n      icon: Phone,\n      label: \"Phone\",\n      value: \"+1 (555) 123-4567\",\n    },\n    {\n      id: \"address\",\n      icon: MapPin,\n      label: \"Address\",\n      value: [\"123 Business Street\", \"Suite 100\", \"San Francisco, CA 94105\"],\n      multiline: true,\n    },\n    {\n      id: \"hours\",\n      icon: Clock,\n      label: \"Business Hours\",\n      value: [\n        \"Monday - Friday: 9:00 AM - 6:00 PM\",\n        \"Saturday: 10:00 AM - 4:00 PM\",\n        \"Sunday: Closed\",\n      ],\n      multiline: true,\n    },\n  ],\n  responseTime: {\n    value: \"<24h\",\n    label: \"Average response time\",\n  },\n  form: {\n    title: \"Send us a Message\",\n    description: \"Fill out the form below and we'll get back to you shortly.\",\n    buttonText: \"Send Message\",\n    disclaimer: \"By submitting this form, you agree to our Privacy Policy.\",\n    fields: [\n      {\n        id: \"firstName\",\n        label: \"First Name *\",\n        type: \"text\",\n        placeholder: \"John\",\n        required: true,\n        gridSpan: \"half\",\n      },\n      {\n        id: \"lastName\",\n        label: \"Last Name *\",\n        type: \"text\",\n        placeholder: \"Doe\",\n        required: true,\n        gridSpan: \"half\",\n      },\n      {\n        id: \"email\",\n        label: \"Email Address *\",\n        type: \"email\",\n        placeholder: \"john@example.com\",\n        required: true,\n        gridSpan: \"full\",\n      },\n      {\n        id: \"phone\",\n        label: \"Phone Number\",\n        type: \"tel\",\n        placeholder: \"+1 (555) 123-4567\",\n        required: false,\n        gridSpan: \"full\",\n      },\n      {\n        id: \"subject\",\n        label: \"Subject *\",\n        type: \"text\",\n        placeholder: \"How can we help you?\",\n        required: true,\n        gridSpan: \"full\",\n      },\n      {\n        id: \"message\",\n        label: \"Message *\",\n        type: \"textarea\",\n        placeholder: \"Tell us more about your project or inquiry...\",\n        required: true,\n        gridSpan: \"full\",\n      },\n    ],\n  },\n};\n\nexport function Contact01({ className }: Contact01Props) {\n  const form = useForm<FormValues>({\n    resolver: zodResolver(formSchema),\n    defaultValues: {\n      firstName: \"\",\n      lastName: \"\",\n      email: \"\",\n      phone: \"\",\n      subject: \"\",\n      message: \"\",\n    },\n  });\n\n  const onSubmit = (values: FormValues) => {\n    console.log(\"Form submitted:\", values);\n    // Handle form submission here\n    form.reset();\n  };\n\n  return (\n    <section\n      className={cn(content.sectionPadding, className)}\n      data-testid=\"contact-01\"\n    >\n      <div className={cn(content.maxWidth, \"mx-auto\")}>\n        <div\n          className=\"text-center space-y-4 mb-12 md:mb-16\"\n          data-testid=\"header-section\"\n        >\n          <Badge\n            variant={content.header.badge.variant}\n            className={content.header.badge.className}\n            data-testid=\"header-badge\"\n          >\n            {content.header.badge.text}\n          </Badge>\n          <h2\n            className=\"text-3xl md:text-4xl font-bold\"\n            data-testid=\"header-title\"\n          >\n            {content.header.title}\n          </h2>\n          <p\n            className=\"text-lg text-muted-foreground max-w-2xl mx-auto\"\n            data-testid=\"header-description\"\n          >\n            {content.header.description}\n          </p>\n        </div>\n\n        <div\n          className=\"grid lg:grid-cols-3 gap-8 md:gap-16\"\n          data-testid=\"contact-grid\"\n        >\n          {/* Contact Information */}\n          <div className=\"space-y-6\" data-testid=\"contact-info-section\">\n            <div>\n              <h3\n                className=\"text-xl font-semibold mb-4\"\n                data-testid=\"contact-info-title\"\n              >\n                Contact Information\n              </h3>\n              <div className=\"space-y-4\" data-testid=\"contact-info-list\">\n                {content.contactInfo.map((info) => {\n                  const IconComponent = info.icon;\n                  return (\n                    <div\n                      key={info.id}\n                      className=\"flex items-start gap-3\"\n                      data-testid={`contact-info-${info.id}`}\n                    >\n                      <div\n                        className=\"w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0\"\n                        data-testid={`contact-icon-${info.id}`}\n                      >\n                        <IconComponent className=\"h-5 w-5 text-primary\" />\n                      </div>\n                      <div>\n                        <p\n                          className=\"font-medium\"\n                          data-testid={`contact-label-${info.id}`}\n                        >\n                          {info.label}\n                        </p>\n                        {info.multiline && Array.isArray(info.value) ? (\n                          <div\n                            className=\"text-muted-foreground\"\n                            data-testid={`contact-value-${info.id}`}\n                          >\n                            {info.value.map((line, lineIndex) => (\n                              <p key={lineIndex}>{line}</p>\n                            ))}\n                          </div>\n                        ) : (\n                          <p\n                            className=\"text-muted-foreground\"\n                            data-testid={`contact-value-${info.id}`}\n                          >\n                            {Array.isArray(info.value)\n                              ? info.value[0]\n                              : info.value}\n                          </p>\n                        )}\n                      </div>\n                    </div>\n                  );\n                })}\n              </div>\n            </div>\n\n            {/* Response Time */}\n            <Card\n              className=\"bg-muted/30 border-border\"\n              data-testid=\"response-time-card\"\n            >\n              <CardContent>\n                <div className=\"text-center space-y-2\">\n                  <div\n                    className=\"text-2xl font-bold text-primary\"\n                    data-testid=\"response-time-value\"\n                  >\n                    {content.responseTime.value}\n                  </div>\n                  <p\n                    className=\"text-sm text-muted-foreground\"\n                    data-testid=\"response-time-label\"\n                  >\n                    {content.responseTime.label}\n                  </p>\n                </div>\n              </CardContent>\n            </Card>\n          </div>\n\n          {/* Contact Form */}\n          <div className=\"lg:col-span-2\" data-testid=\"contact-form-section\">\n            <Card\n              className=\"bg-card border-border shadow-lg gap-10\"\n              data-testid=\"contact-form-card\"\n            >\n              <CardHeader>\n                <CardTitle className=\"text-2xl\" data-testid=\"form-title\">\n                  {content.form.title}\n                </CardTitle>\n                <CardDescription data-testid=\"form-description\">\n                  {content.form.description}\n                </CardDescription>\n              </CardHeader>\n              <CardContent>\n                <Form {...form}>\n                  <form\n                    onSubmit={form.handleSubmit(onSubmit)}\n                    className=\"space-y-6\"\n                    data-testid=\"contact-form\"\n                  >\n                    {/* Grid fields (side by side) */}\n                    <div\n                      className=\"grid md:grid-cols-2 gap-4\"\n                      data-testid=\"form-grid-fields\"\n                    >\n                      <FormField\n                        control={form.control}\n                        name=\"firstName\"\n                        render={({ field }) => (\n                          <FormItem data-testid=\"form-field-firstName\">\n                            <FormLabel data-testid=\"label-firstName\">\n                              First Name *\n                            </FormLabel>\n                            <FormControl>\n                              <Input\n                                placeholder=\"John\"\n                                className=\"bg-background border-border\"\n                                data-testid=\"input-firstName\"\n                                {...field}\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                      <FormField\n                        control={form.control}\n                        name=\"lastName\"\n                        render={({ field }) => (\n                          <FormItem data-testid=\"form-field-lastName\">\n                            <FormLabel data-testid=\"label-lastName\">\n                              Last Name *\n                            </FormLabel>\n                            <FormControl>\n                              <Input\n                                placeholder=\"Doe\"\n                                className=\"bg-background border-border\"\n                                data-testid=\"input-lastName\"\n                                {...field}\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n                    </div>\n\n                    {/* Full width fields */}\n                    <FormField\n                      control={form.control}\n                      name=\"email\"\n                      render={({ field }) => (\n                        <FormItem data-testid=\"form-field-email\">\n                          <FormLabel data-testid=\"label-email\">\n                            Email Address *\n                          </FormLabel>\n                          <FormControl>\n                            <Input\n                              type=\"email\"\n                              placeholder=\"john@example.com\"\n                              className=\"bg-background border-border\"\n                              data-testid=\"input-email\"\n                              {...field}\n                            />\n                          </FormControl>\n                          <FormMessage />\n                        </FormItem>\n                      )}\n                    />\n\n                    <FormField\n                      control={form.control}\n                      name=\"phone\"\n                      render={({ field }) => (\n                        <FormItem data-testid=\"form-field-phone\">\n                          <FormLabel data-testid=\"label-phone\">\n                            Phone Number\n                          </FormLabel>\n                          <FormControl>\n                            <Input\n                              type=\"tel\"\n                              placeholder=\"+1 (555) 123-4567\"\n                              className=\"bg-background border-border\"\n                              data-testid=\"input-phone\"\n                              {...field}\n                            />\n                          </FormControl>\n                          <FormMessage />\n                        </FormItem>\n                      )}\n                    />\n\n                    <FormField\n                      control={form.control}\n                      name=\"subject\"\n                      render={({ field }) => (\n                        <FormItem data-testid=\"form-field-subject\">\n                          <FormLabel data-testid=\"label-subject\">\n                            Subject *\n                          </FormLabel>\n                          <FormControl>\n                            <Input\n                              placeholder=\"How can we help you?\"\n                              className=\"bg-background border-border\"\n                              data-testid=\"input-subject\"\n                              {...field}\n                            />\n                          </FormControl>\n                          <FormMessage />\n                        </FormItem>\n                      )}\n                    />\n\n                    <FormField\n                      control={form.control}\n                      name=\"message\"\n                      render={({ field }) => (\n                        <FormItem data-testid=\"form-field-message\">\n                          <FormLabel data-testid=\"label-message\">\n                            Message *\n                          </FormLabel>\n                          <FormControl>\n                            <Textarea\n                              placeholder=\"Tell us more about your project or inquiry...\"\n                              className=\"bg-background border-border min-h-[120px]\"\n                              data-testid=\"textarea-message\"\n                              {...field}\n                            />\n                          </FormControl>\n                          <FormMessage />\n                        </FormItem>\n                      )}\n                    />\n\n                    <Button\n                      type=\"submit\"\n                      className=\"w-full\"\n                      size=\"lg\"\n                      disabled={form.formState.isSubmitting}\n                      data-testid=\"form-submit-button\"\n                    >\n                      {form.formState.isSubmitting\n                        ? \"Submitting...\"\n                        : content.form.buttonText}\n                    </Button>\n\n                    <p\n                      className=\"text-xs text-muted-foreground text-center\"\n                      data-testid=\"form-disclaimer\"\n                    >\n                      {content.form.disclaimer.includes(\"Privacy Policy\") ? (\n                        <>\n                          {content.form.disclaimer.split(\"Privacy Policy\")[0]}\n                          <a\n                            href=\"#\"\n                            className=\"text-primary hover:underline\"\n                            data-testid=\"privacy-policy-link\"\n                          >\n                            Privacy Policy\n                          </a>\n                          {content.form.disclaimer.split(\"Privacy Policy\")[1]}\n                        </>\n                      ) : (\n                        content.form.disclaimer\n                      )}\n                    </p>\n                  </form>\n                </Form>\n              </CardContent>\n            </Card>\n          </div>\n        </div>\n      </div>\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"}]}