{
  "name": "category-grid",
  "title": "CategoryGrid",
  "description": "Responsive grid of category cards.",
  "type": "component",
  "registryDependencies": [
    "cn"
  ],
  "files": [
    {
      "path": "category-grid.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport type { Category } from \"@cimplify/sdk\";\nimport { useCategories } from \"@cimplify/sdk/react\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface CategoryGridClassNames {\n  root?: string;\n  item?: string;\n  name?: string;\n  description?: string;\n  count?: string;\n  empty?: string;\n}\n\nexport interface CategoryGridProps {\n  /** Override categories (skips useCategories fetch). */\n  categories?: Category[];\n  /** Called when a category card is clicked. */\n  onSelect?: (category: Category) => void;\n  /** Custom card renderer. */\n  renderCard?: (category: Category) => React.ReactNode;\n  /** Responsive column counts. */\n  columns?: { sm?: number; md?: number; lg?: number };\n  /** Text shown when empty. */\n  emptyMessage?: string;\n  className?: string;\n  classNames?: CategoryGridClassNames;\n}\n\n/**\n * CategoryGrid — responsive grid of category cards.\n *\n * Fetches categories via `useCategories` unless overridden.\n * Uses `React.useId()` for hydration-safe responsive CSS.\n */\nexport function CategoryGrid({\n  categories: categoriesProp,\n  onSelect,\n  renderCard,\n  columns,\n  emptyMessage,\n  className,\n  classNames,\n}: CategoryGridProps): React.ReactElement {\n  const { categories: fetched, isLoading } = useCategories({\n    enabled: categoriesProp === undefined,\n  });\n  const categories = categoriesProp ?? fetched;\n\n  const rawId = React.useId();\n  const gridId = `cimplify-cat-grid-${rawId.replace(/:/g, \"\")}`;\n\n  const sm = columns?.sm ?? 2;\n  const md = columns?.md ?? 3;\n  const lg = columns?.lg ?? 4;\n\n  if (isLoading && categories.length === 0) {\n    return (\n      <div\n        data-cimplify-category-grid\n        aria-busy=\"true\"\n        className={cn(className, classNames?.root)}\n      />\n    );\n  }\n\n  if (categories.length === 0) {\n    return (\n      <div\n        data-cimplify-category-grid\n        data-empty\n        className={cn(className, classNames?.root, classNames?.empty)}\n      >\n        <p>{emptyMessage ?? \"No categories found\"}</p>\n      </div>\n    );\n  }\n\n  const css = [\n    `#${gridId}{display:grid;grid-template-columns:repeat(${sm},1fr);gap:1rem}`,\n    `@media(min-width:768px){#${gridId}{grid-template-columns:repeat(${md},1fr)}}`,\n    `@media(min-width:1024px){#${gridId}{grid-template-columns:repeat(${lg},1fr)}}`,\n  ].join(\"\");\n\n  return (\n    <>\n      <style dangerouslySetInnerHTML={{ __html: css }} />\n      <div\n        id={gridId}\n        data-cimplify-category-grid\n        className={cn(className, classNames?.root)}\n      >\n        {categories.map((category: Category) => (\n          <button\n            key={category.id}\n            type=\"button\"\n            onClick={() => onSelect?.(category)}\n            data-cimplify-category-card\n            className={classNames?.item}\n          >\n            {renderCard ? (\n              renderCard(category)\n            ) : (\n              <>\n                <span data-cimplify-category-name className={classNames?.name}>\n                  {category.name}\n                </span>\n                {category.description && (\n                  <span data-cimplify-category-description className={classNames?.description}>\n                    {category.description}\n                  </span>\n                )}\n                {category.product_count != null && (\n                  <span data-cimplify-category-count className={classNames?.count}>\n                    {category.product_count} {category.product_count === 1 ? \"product\" : \"products\"}\n                  </span>\n                )}\n              </>\n            )}\n          </button>\n        ))}\n      </div>\n    </>\n  );\n}\n"
    }
  ]
}
