{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "conversion-funnel",
  "title": "Conversion Funnel",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/conversion-funnel/ConversionFunnel.svelte",
      "content": "<!--\n  Conversion funnel: SmoothFunnel chart with count strip above and\n  stage-name + retention-from-previous strip below.\n\n  Works for any drop-off flow with 3-6 stages: hiring (applied ->\n  hired), e-commerce (sessions -> purchases), onboarding (signed up\n  -> activated), etc. Reads as a single horizontal \"flow\":\n\n    72K        38.2K       16.8K       5.6K\n    ╔══════╗╔════════╗╔══════════╗╔══════════╗\n    ║ 100% ║║  53%   ║║   23%    ║║    8%    ║\n    ╚══════╝╚════════╝╚══════════╝╚══════════╝\n    Views      Cart        Checkout    Purchase\n               -> 53%       -> 44%      -> 33%\n\n  The middle pill (inside each band) shows the share OF THE TOP\n  stage (100%, 53%, 23%, ...). The bottom retention number shows the\n  stage-to-stage conversion -- usually the more actionable signal.\n-->\n<script lang=\"ts\" module>\n  export interface FunnelBlockStage {\n    name: string\n    value: number\n  }\n\n  export interface ConversionFunnelProps {\n    data: FunnelBlockStage[]\n    /** SmoothFunnel container height. Defaults to 180. */\n    height?: number | string\n    /** Override colour palette. Defaults to the registry's chart-1..N\n     *  OKLCH tokens via CSS variables (so light/dark + theme-customizer\n     *  flips ripple through without any JS). Pass a literal hex array to\n     *  override. */\n    colors?: string[]\n    /** Compact number formatter for the count strip (default toLocaleString). */\n    format?: (n: number) => string\n    /** Hide the retention-from-previous footer on each non-first stage. */\n    hideRetention?: boolean\n    class?: string\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { SmoothFunnel } from '$lib/components/ui/smooth-funnel'\n\n  const DEFAULT_PALETTE = [\n    'var(--chart-1)',\n    'var(--chart-2)',\n    'var(--chart-3)',\n    'var(--chart-4)',\n    'var(--chart-5)',\n    'var(--chart-1)',\n  ]\n\n  let {\n    data,\n    height = 180,\n    colors,\n    format,\n    hideRetention = false,\n    class: className,\n  }: ConversionFunnelProps = $props()\n\n  const palette = $derived(colors ?? DEFAULT_PALETTE)\n  const fmt = (v: number) => (format ? format(v) : v.toLocaleString())\n  function retention(i: number) {\n    if (i === 0) return null\n    const prev = data[i - 1]?.value ?? 1\n    return Math.round(((data[i]?.value ?? 0) / prev) * 100)\n  }\n</script>\n\n<div data-uipkge data-slot=\"conversion-funnel\" class={cn('space-y-2', className)}>\n  <!-- Top: per-stage count -->\n  <div class=\"grid px-2 text-center\" style:grid-template-columns={`repeat(${data.length}, minmax(0, 1fr))`}>\n    {#each data as stage (stage.name)}\n      <div class=\"text-foreground text-base font-bold tabular-nums\">\n        {fmt(stage.value)}\n      </div>\n    {/each}\n  </div>\n\n  <!-- Funnel SVG -->\n  <SmoothFunnel {data} {height} colors={palette} />\n\n  <!-- Bottom: stage name + retention from previous -->\n  <div class=\"grid px-2 text-center\" style:grid-template-columns={`repeat(${data.length}, minmax(0, 1fr))`}>\n    {#each data as stage, i (stage.name)}\n      <div class=\"space-y-0.5\">\n        <p class=\"text-muted-foreground text-xs\">{stage.name}</p>\n        {#if !hideRetention && retention(i) !== null}\n          <p class=\"text-info text-xs font-semibold tabular-nums\">\n            → {retention(i)}% retained\n          </p>\n        {/if}\n      </div>\n    {/each}\n  </div>\n</div>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/conversion-funnel/ConversionFunnel.svelte"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/smooth-funnel.json"
  ],
  "description": "Horizontal conversion funnel with count strip above the SmoothFunnel chart and a stage-name + retention-from-previous footer below. Works for hiring (applied → hired), e-commerce (sessions → purchases), onboarding (signed up → activated). 3-6 stages. Theme-aware via OKLCH chart tokens.",
  "categories": [
    "analytics",
    "dashboard"
  ]
}