{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comparator-grid",
  "title": "Comparator Grid",
  "description": "Plan-column comparison Payload block: pricing columns in a bordered card over a feature matrix.",
  "registryDependencies": [
    "badge",
    "card"
  ],
  "files": [
    {
      "path": "payload-components/source/blocks/shared/comparatorFields.ts",
      "content": "import type { Field } from 'payload'\n\n/**\n * Shared field core for the Comparator component family.\n *\n * Every comparator variant (comparator-table, comparator-grid, comparator-stack)\n * spreads this optional section header first and then appends its own plan/feature\n * shape — the feature matrix for the table and grid layouts, or the per-plan\n * checklists for the stacked layout. Editing the shared title/description here\n * updates every installed comparator block at once, so the family never drifts\n * field-by-field across a repo.\n *\n * Installed once per repo at `src/blocks/shared/comparatorFields.ts`; re-running\n * `payload-components add comparator-*` never overwrites a copy you have already edited.\n */\nexport const comparatorFields: Field[] = [\n  {\n    name: 'title',\n    type: 'text',\n  },\n  {\n    name: 'description',\n    type: 'textarea',\n  },\n]\n",
      "type": "registry:file",
      "target": "~/src/blocks/shared/comparatorFields.ts"
    },
    {
      "path": "payload-components/source/blocks/ComparatorGrid/config.ts",
      "content": "import type { Block } from 'payload'\n\nimport { comparatorFields } from '@/blocks/shared/comparatorFields'\nimport { linkGroup } from '@/fields/linkGroup'\n\nexport const ComparatorGrid: Block = {\n  slug: 'comparatorGrid',\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_com_gri',\n  interfaceName: 'ComparatorGridBlock',\n  fields: [\n    // Shared comparator header (title, description). Variant-specific fields\n    // follow; edit the shared shape in @/blocks/shared/comparatorFields.\n    ...comparatorFields,\n    {\n      name: 'plans',\n      type: 'array',\n      required: true,\n      minRows: 2,\n      maxRows: 4,\n      admin: {\n        initCollapsed: true,\n      },\n      fields: [\n        {\n          name: 'name',\n          type: 'text',\n          required: true,\n        },\n        {\n          name: 'price',\n          type: 'text',\n        },\n        {\n          name: 'period',\n          type: 'text',\n          admin: {\n            description: 'Shown next to the price, e.g. \"/month\".',\n          },\n        },\n        {\n          name: 'badge',\n          type: 'text',\n          admin: {\n            description: 'Optional pill above the plan name, e.g. \"Most popular\".',\n          },\n        },\n        {\n          name: 'highlighted',\n          type: 'checkbox',\n          admin: {\n            description: 'Tints this column to draw the eye to the recommended plan.',\n          },\n        },\n        linkGroup({\n          overrides: {\n            maxRows: 1,\n          },\n        }),\n      ],\n    },\n    {\n      name: 'features',\n      type: 'array',\n      required: true,\n      minRows: 1,\n      admin: {\n        initCollapsed: true,\n      },\n      fields: [\n        {\n          name: 'feature',\n          type: 'text',\n          required: true,\n        },\n        {\n          name: 'values',\n          type: 'array',\n          admin: {\n            description: 'One cell per plan, in the same order as Plans. Tick \"included\" for a checkmark, or set a label for a text value.',\n          },\n          fields: [\n            {\n              name: 'included',\n              type: 'checkbox',\n            },\n            {\n              name: 'label',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    },\n  ],\n  labels: {\n    plural: 'Comparator Grid Blocks',\n    singular: 'Comparator Grid',\n  },\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/ComparatorGrid/config.ts"
    },
    {
      "path": "payload-components/source/blocks/ComparatorGrid/Component.tsx",
      "content": "import React from 'react'\n\nimport { Check, Minus } from 'lucide-react'\n\nimport type { ComparatorGridBlock as ComparatorGridBlockData } from '@/payload-types'\n\nimport { CMSLink } from '@/components/Link'\nimport { Badge } from '@/components/ui/badge'\nimport { Card } from '@/components/ui/card'\nimport { cn } from '@/utilities/ui'\n\n// Layout adapted from tailark/blocks (MIT) — re-implemented as a Payload block.\n\ntype Props = ComparatorGridBlockData & {\n  id?: string\n  className?: string\n  disableInnerContainer?: boolean\n}\n\nexport const ComparatorGridBlock: React.FC<Props> = ({\n  className,\n  description,\n  disableInnerContainer,\n  features,\n  id,\n  plans,\n  title,\n}) => {\n  const columns = `minmax(8rem, 1.4fr) repeat(${plans?.length ?? 0}, minmax(0, 1fr))`\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-10', {\n            'mx-auto max-w-4xl': !disableInnerContainer,\n          })}\n        >\n          {title || description ? (\n            <div className=\"flex flex-col items-center gap-4 text-center\">\n              {title ? (\n                <h2 className=\"text-4xl font-medium tracking-display text-balance sm:text-5xl\">{title}</h2>\n              ) : null}\n\n              {description ? (\n                <p className=\"max-w-xl text-base leading-7 text-muted-foreground sm:text-lg\">{description}</p>\n              ) : null}\n            </div>\n          ) : null}\n\n          {plans && plans.length > 0 ? (\n            <Card className=\"overflow-x-auto border-border/70 bg-background/60 p-0 shadow-none\">\n              <div className=\"min-w-[36rem]\">\n                <div\n                  className=\"grid items-end border-b border-border/70\"\n                  style={{ gridTemplateColumns: columns }}\n                >\n                  <div className=\"p-4\" />\n\n                  {plans.map((plan, planIndex) => (\n                    <div\n                      key={plan.id ?? planIndex}\n                      className={cn('flex flex-col gap-2 p-4 text-center', {\n                        'bg-primary/5': plan.highlighted,\n                      })}\n                    >\n                      {plan.badge ? (\n                        <Badge\n                          variant=\"outline\"\n                          className=\"mx-auto rounded-full px-2 py-0.5 text-xs uppercase tracking-eyebrow\"\n                        >\n                          {plan.badge}\n                        </Badge>\n                      ) : null}\n\n                      <span className=\"text-base font-medium text-foreground\">{plan.name}</span>\n\n                      <span className=\"flex items-baseline justify-center gap-1\">\n                        <span className=\"text-2xl font-medium tracking-title text-foreground\">{plan.price}</span>\n                        {plan.period ? <span className=\"text-sm text-muted-foreground\">{plan.period}</span> : null}\n                      </span>\n                    </div>\n                  ))}\n                </div>\n\n                {features?.map((row, rowIndex) => (\n                  <div\n                    key={row.id ?? rowIndex}\n                    className=\"grid items-center border-b border-border/70 last:border-b-0\"\n                    style={{ gridTemplateColumns: columns }}\n                  >\n                    <div className=\"p-4 text-sm text-muted-foreground\">{row.feature}</div>\n\n                    {plans.map((plan, planIndex) => {\n                      const cell = row.values?.[planIndex]\n\n                      return (\n                        <div\n                          key={plan.id ?? planIndex}\n                          className={cn('flex items-center justify-center p-4 text-sm text-foreground', {\n                            'bg-primary/5': plan.highlighted,\n                          })}\n                        >\n                          {cell?.included ? (\n                            <Check aria-label=\"Included\" className=\"size-4 text-primary\" role=\"img\" />\n                          ) : cell?.label ? (\n                            <span>{cell.label}</span>\n                          ) : (\n                            <Minus aria-label=\"Not included\" className=\"size-4 text-muted-foreground\" role=\"img\" />\n                          )}\n                        </div>\n                      )\n                    })}\n                  </div>\n                ))}\n\n                <div className=\"grid border-t border-border/70\" style={{ gridTemplateColumns: columns }}>\n                  <div className=\"p-4\" />\n\n                  {plans.map((plan, planIndex) => (\n                    <div\n                      key={plan.id ?? planIndex}\n                      className={cn('p-4', {\n                        'bg-primary/5': plan.highlighted,\n                      })}\n                    >\n                      {plan.links && plan.links.length > 0 ? (\n                        <div className=\"flex flex-col gap-2\">\n                          {plan.links.map(({ link }, linkIndex) => (\n                            <CMSLink\n                              key={linkIndex}\n                              appearance={link.appearance === 'outline' ? 'outline' : 'default'}\n                              {...link}\n                            />\n                          ))}\n                        </div>\n                      ) : null}\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </Card>\n          ) : null}\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/ComparatorGrid/Component.tsx"
    }
  ],
  "meta": {
    "payloadComponent": {
      "installCommand": "payload-components add comparator-grid",
      "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 comparator-grid\n```\n\nDirect shadcn install URL:\n\n```bash\npnpm dlx shadcn@latest add https://www.payload-components.xyz/r/comparator-grid.json\n```\n\nDirect shadcn installs only copy the block source files and shadcn UI dependencies. Use `payload-components add comparator-grid` when you also want Payload layout registration, `RenderBlocks` wiring, `generate:types`, and `generate:importmap` handled for you.",
  "type": "registry:block"
}