{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "faq-grouped",
  "title": "FAQ Grouped",
  "description": "Payload FAQ block: titled, icon-tagged category groups of accordions.",
  "registryDependencies": [
    "accordion",
    "badge"
  ],
  "files": [
    {
      "path": "payload-components/source/blocks/shared/faqFields.ts",
      "content": "import type { Field } from 'payload'\n\n/**\n * Shared field core for the FAQ component family.\n *\n * Every FAQ variant (faq-accordion, faq-split, faq-card, faq-icons,\n * faq-grouped, faq-grid) spreads these section-heading fields first and then\n * appends its own variant-specific shape — the question/answer items, which\n * differ per layout (flat list, icon-tagged, or grouped). Editing the shared\n * eyebrow/title/description here updates every installed FAQ block at once, so\n * the family never drifts field-by-field across a repo.\n *\n * Installed once per repo at `src/blocks/shared/faqFields.ts`; re-running\n * `payload-components add faq-*` never overwrites a copy you have already edited.\n */\nexport const faqFields: Field[] = [\n  {\n    name: 'eyebrow',\n    type: 'text',\n  },\n  {\n    name: 'title',\n    type: 'text',\n    required: true,\n  },\n  {\n    name: 'description',\n    type: 'textarea',\n  },\n]\n\n/**\n * Reusable question/answer array for the plain FAQ variants (faq-accordion,\n * faq-split, faq-card, faq-grid). The icon and grouped variants define their\n * own item shape, so they compose `faqFields` but not this field.\n */\nexport const faqItemsField: Field = {\n  name: 'items',\n  type: 'array',\n  required: true,\n  minRows: 1,\n  admin: {\n    initCollapsed: true,\n  },\n  fields: [\n    {\n      name: 'question',\n      type: 'text',\n      required: true,\n    },\n    {\n      name: 'answer',\n      type: 'textarea',\n      required: true,\n    },\n  ],\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/shared/faqFields.ts"
    },
    {
      "path": "payload-components/source/blocks/shared/faqIcons.ts",
      "content": "import type { Field } from 'payload'\nimport type { LucideIcon } from 'lucide-react'\n\nimport { Clock, CreditCard, Globe, HelpCircle, Package, Truck } from 'lucide-react'\n\n/**\n * Shared icon allowlist for the icon-bearing FAQ variants\n * (faq-icons, faq-grouped).\n *\n * Payload cannot store a React component, so each FAQ item (or group) picks an\n * icon by name from this fixed allowlist (`iconField`, a `select`) and the\n * frontend looks the name up in `faqIcons` at render. Keeping the options and\n * the component map in one file means the editor choices can never drift from\n * what actually renders — add an icon by adding it to both `faqIconOptions`\n * and `faqIcons` together.\n *\n * Installed once per repo at `src/blocks/shared/faqIcons.ts`; re-running\n * `payload-components add faq-*` never overwrites a copy you have already edited.\n */\nexport const faqIconOptions = ['clock', 'credit-card', 'truck', 'globe', 'package', 'help-circle'] as const\n\nexport type FaqIconName = (typeof faqIconOptions)[number]\n\nexport const iconField: Field = {\n  name: 'icon',\n  type: 'select',\n  options: [\n    { label: 'Clock', value: 'clock' },\n    { label: 'Credit card', value: 'credit-card' },\n    { label: 'Truck', value: 'truck' },\n    { label: 'Globe', value: 'globe' },\n    { label: 'Package', value: 'package' },\n    { label: 'Help circle', value: 'help-circle' },\n  ],\n}\n\nexport const faqIcons: Record<FaqIconName, LucideIcon> = {\n  clock: Clock,\n  'credit-card': CreditCard,\n  truck: Truck,\n  globe: Globe,\n  package: Package,\n  'help-circle': HelpCircle,\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/shared/faqIcons.ts"
    },
    {
      "path": "payload-components/source/blocks/FaqGrouped/config.ts",
      "content": "import type { Block } from 'payload'\n\nimport { faqFields } from '@/blocks/shared/faqFields'\nimport { iconField } from '@/blocks/shared/faqIcons'\n\nexport const FaqGrouped: Block = {\n  slug: 'faqGrouped',\n  // Existing apps must migrate stored data before adopting this identifier:\n  // https://www.payload-components.xyz/docs/registry#installed-source-and-migrations\n  dbName: 'pc_faq_gro',\n  interfaceName: 'FaqGroupedBlock',\n  fields: [\n    // Shared FAQ core (eyebrow, title, description). This variant buckets\n    // questions under titled, icon-tagged groups, so it defines a nested\n    // groups array rather than the shared faqItemsField.\n    ...faqFields,\n    {\n      name: 'groups',\n      type: 'array',\n      required: true,\n      minRows: 1,\n      admin: {\n        initCollapsed: true,\n      },\n      fields: [\n        iconField,\n        {\n          name: 'title',\n          type: 'text',\n          required: true,\n        },\n        {\n          name: 'items',\n          type: 'array',\n          required: true,\n          minRows: 1,\n          fields: [\n            {\n              name: 'question',\n              type: 'text',\n              required: true,\n            },\n            {\n              name: 'answer',\n              type: 'textarea',\n              required: true,\n            },\n          ],\n        },\n      ],\n    },\n  ],\n  labels: {\n    plural: 'FAQ Grouped Blocks',\n    singular: 'FAQ Grouped',\n  },\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/FaqGrouped/config.ts"
    },
    {
      "path": "payload-components/source/blocks/FaqGrouped/Component.tsx",
      "content": "import React from 'react'\n\nimport type { FaqGroupedBlock as FaqGroupedBlockData } from '@/payload-types'\n\nimport { faqIcons } from '@/blocks/shared/faqIcons'\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from '@/components/ui/accordion'\nimport { Badge } from '@/components/ui/badge'\nimport { cn } from '@/utilities/ui'\n\ntype Props = FaqGroupedBlockData & {\n  id?: string\n  className?: string\n  disableInnerContainer?: boolean\n}\n\nexport const FaqGroupedBlock: React.FC<Props> = ({\n  className,\n  description,\n  disableInnerContainer,\n  eyebrow,\n  groups,\n  id,\n  title,\n}) => {\n  return (\n    <section className={cn('container', className)} id={id ? `block-${id}` : undefined}>\n      <div className=\"overflow-hidden rounded-frame border border-border/70 bg-card/35 px-6 py-10 sm:px-8 lg:px-12 lg:py-14\">\n        <div\n          className={cn('flex flex-col gap-12', {\n            'mx-auto max-w-3xl': !disableInnerContainer,\n          })}\n        >\n          <div className=\"flex flex-col gap-4 text-center\">\n            {eyebrow ? (\n              <Badge variant=\"outline\" className=\"mx-auto w-fit rounded-full px-3 py-1 uppercase tracking-eyebrow\">\n                {eyebrow}\n              </Badge>\n            ) : null}\n\n            <h2 className=\"text-4xl font-medium tracking-display text-balance sm:text-5xl\">{title}</h2>\n\n            {description ? (\n              <p className=\"text-base leading-7 text-muted-foreground sm:text-lg\">{description}</p>\n            ) : null}\n          </div>\n\n          {groups && groups.length > 0 ? (\n            <div className=\"flex flex-col gap-10\">\n              {groups.map((group, groupIndex) => {\n                const Icon = group.icon ? faqIcons[group.icon] : null\n\n                return (\n                  <div className=\"flex flex-col gap-4\" key={group.id ?? `${group.title}-${groupIndex}`}>\n                    <div className=\"flex items-center gap-3\">\n                      {Icon ? <Icon className=\"size-5 text-muted-foreground\" /> : null}\n                      <h3 className=\"text-lg font-medium tracking-title\">{group.title}</h3>\n                    </div>\n\n                    <Accordion type=\"single\" collapsible className=\"w-full\">\n                      {group.items?.map((item, index) => (\n                        <AccordionItem\n                          key={item.id ?? `${item.question}-${index}`}\n                          value={item.id ?? `group-${groupIndex}-item-${index}`}\n                          className=\"border-border/70\"\n                        >\n                          <AccordionTrigger className=\"text-start text-base tracking-title hover:no-underline\">\n                            {item.question}\n                          </AccordionTrigger>\n                          <AccordionContent className=\"text-sm leading-7 text-muted-foreground\">\n                            {item.answer}\n                          </AccordionContent>\n                        </AccordionItem>\n                      ))}\n                    </Accordion>\n                  </div>\n                )\n              })}\n            </div>\n          ) : null}\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/FaqGrouped/Component.tsx"
    }
  ],
  "meta": {
    "payloadComponent": {
      "installCommand": "payload-components add faq-grouped",
      "postInstall": [
        "generate:types",
        "generate:importmap"
      ],
      "requiresPayloadComponentWrapper": true,
      "supportedTargets": [
        "payload-website-starter",
        "payload-blocks-app"
      ]
    }
  },
  "docs": "Payload Components installs this as a Payload CMS block for the Payload website starter shape.\n\nRecommended install:\n\n```bash\npnpm payload-components add faq-grouped\n```\n\nDirect shadcn install URL:\n\n```bash\npnpm dlx shadcn@latest add https://www.payload-components.xyz/r/faq-grouped.json\n```\n\nDirect shadcn installs only copy the block source files and shadcn UI dependencies. Use `payload-components add faq-grouped` when you also want Payload layout registration, `RenderBlocks` wiring, `generate:types`, and `generate:importmap` handled for you.",
  "type": "registry:block"
}