{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "marketing-blocks",
"title": "Marketing blocks",
"description": "Page intro, stats, feature grid, callout, summary panel, and surface grid blocks.",
"dependencies": [],
"registryDependencies": [],
"files": [
{
"path": "src/blocks/marketing-blocks.tsx",
"content": "import type { ReactNode } from 'react'\nimport { View } from 'uniwind/components'\nimport { cn } from '../../reusables/lib/utils'\nimport { Badge, Card, CardContent, CardHeader, Separator, UIText } from '../reusables'\nimport type {\n BlockChromeProps,\n CalloutBlockProps,\n FeatureGridBlockProps,\n FeatureItem,\n PageIntroBlockProps,\n StatItem,\n StatsBlockProps,\n SummaryItem,\n SummaryPanelBlockProps,\n SurfaceGridBlockProps,\n SurfaceItem,\n} from './types'\n\nfunction BlockHeader({ className, description, eyebrow, title }: BlockChromeProps) {\n if (!eyebrow && !title && !description) {\n return null\n }\n\n return (\n \n {eyebrow ? {eyebrow} : null}\n {title ? {title} : null}\n {description ? {description} : null}\n \n )\n}\n\nfunction getBlockItemKey(prefix: string, index: number, value: ReactNode) {\n return typeof value === 'string' || typeof value === 'number' ? `${prefix}-${value}` : `${prefix}-${index}`\n}\n\nfunction ActionRow({ children }: { children: ReactNode }) {\n return {children}\n}\n\nfunction StatTile({ detail, label, value }: StatItem) {\n return (\n \n \n {label}\n {value}\n {detail ? {detail} : null}\n \n \n )\n}\n\nfunction StatGrid({ items }: { items: StatItem[] }) {\n return (\n \n {items.map((item, index) => (\n \n ))}\n \n )\n}\n\nfunction FeatureCard({ body, icon, kicker, title }: FeatureItem) {\n return (\n \n \n {icon ? {icon} : null}\n {kicker ? {kicker} : null}\n {title}\n {body}\n \n \n )\n}\n\nfunction SummaryItems({ items }: { items: SummaryItem[] }) {\n return (\n \n {items.map((item, index) => (\n \n {index > 0 ? : null}\n \n {item.label}\n {item.value}\n \n \n ))}\n \n )\n}\n\nfunction SurfaceCard({ action, body, icon, subtitle, title }: SurfaceItem) {\n return (\n \n \n {icon ? {icon} : null}\n \n {subtitle}\n {title}\n {body}\n \n {action ? {action} : null}\n \n \n )\n}\n\nfunction PageIntroBlock({ actions, aside, className, description, eyebrow, stats, title }: PageIntroBlockProps) {\n return (\n \n \n \n {actions ? {actions} : null}\n {stats?.length ? : null}\n \n {aside ? {aside} : null}\n \n )\n}\n\nfunction StatsBlock({ className, description, eyebrow, items, title }: StatsBlockProps) {\n return (\n \n \n \n \n )\n}\n\nfunction FeatureGridBlock({ className, description, eyebrow, items, title }: FeatureGridBlockProps) {\n return (\n \n \n \n {items.map((item, index) => (\n \n ))}\n \n \n )\n}\n\nfunction CalloutBlock({ actions, children, className, description, eyebrow, title }: CalloutBlockProps) {\n return (\n \n \n \n {actions ? {actions} : null}\n \n {children ? {children} : null}\n \n )\n}\n\nfunction SummaryPanelBlock({ className, description, eyebrow, footer, items, meta, title }: SummaryPanelBlockProps) {\n return (\n \n \n \n {meta ? {meta} : null}\n \n {items?.length ? : null}\n {footer ? {footer} : null}\n \n )\n}\n\nfunction SurfaceGridBlock({ className, description, eyebrow, items, title }: SurfaceGridBlockProps) {\n return (\n \n \n \n {items.map((item, index) => (\n \n ))}\n \n \n )\n}\n\nexport { CalloutBlock, FeatureGridBlock, PageIntroBlock, StatsBlock, SummaryPanelBlock, SurfaceGridBlock }\n",
"type": "registry:component"
},
{
"path": "src/blocks/types.ts",
"content": "import type { ReactNode } from 'react'\n\nexport interface BlockChromeProps {\n className?: string\n description?: ReactNode\n eyebrow?: ReactNode\n title?: ReactNode\n}\n\nexport interface StatItem {\n detail?: ReactNode\n label: ReactNode\n value: ReactNode\n}\n\nexport interface FeatureItem {\n body: ReactNode\n icon?: ReactNode\n kicker?: ReactNode\n title: ReactNode\n}\n\nexport interface SurfaceItem {\n action?: ReactNode\n body: ReactNode\n icon?: ReactNode\n subtitle: ReactNode\n title: ReactNode\n}\n\nexport interface SummaryItem {\n label: ReactNode\n value: ReactNode\n}\n\nexport interface PageIntroBlockProps extends BlockChromeProps {\n actions?: ReactNode\n aside?: ReactNode\n stats?: StatItem[]\n}\n\nexport interface StatsBlockProps extends BlockChromeProps {\n items: StatItem[]\n}\n\nexport interface FeatureGridBlockProps extends BlockChromeProps {\n items: FeatureItem[]\n}\n\nexport interface CalloutBlockProps extends BlockChromeProps {\n actions?: ReactNode\n children?: ReactNode\n}\n\nexport interface SummaryPanelBlockProps extends BlockChromeProps {\n footer?: ReactNode\n items?: SummaryItem[]\n meta?: ReactNode\n}\n\nexport interface SurfaceGridBlockProps extends BlockChromeProps {\n items: SurfaceItem[]\n}\n\nexport type { Hero3Props } from './marketing/hero3'\nexport type { ShoppingCartBlockProps, ShoppingCartItem } from './shopping-cart/types'\n\nexport interface Testimonial {\n quote: string\n name: string\n designation: string\n src: string\n}\n\nexport interface AnimatedTestimonialsBlockProps {\n testimonials: Testimonial[]\n autoplay?: boolean\n className?: string\n}\n",
"type": "registry:lib"
},
{
"path": "src/blocks/shopping-cart/types.ts",
"content": "import type { ReactNode } from 'react'\n\nexport interface ShoppingCartItem {\n id: string\n name: string\n image: string\n price: number\n quantity: number\n}\n\nexport interface ShoppingCartBlockProps {\n className?: string\n initialItems?: ShoppingCartItem[]\n emptyTitle?: ReactNode\n emptyDescription?: ReactNode\n title?: ReactNode\n totalLabel?: ReactNode\n continueShoppingLabel?: ReactNode\n checkoutLabel?: ReactNode\n onContinueShopping?: () => void\n onCheckout?: () => void\n}\n",
"type": "registry:lib"
}
],
"docs": "`types.ts` re-exports shopping-cart types; those files are included so the barrel resolves. Depends on `reusables` (Badge, Card, Separator, UIText) and `uniwind`.",
"categories": [
"blocks",
"marketing"
],
"type": "registry:block"
}