{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "conversion-funnel",
  "title": "Conversion Funnel",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/conversion-funnel/ConversionFunnel.vue",
      "content": "<script setup lang=\"ts\">\n/**\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 */\nimport { computed } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\nimport { SmoothFunnel } from '@/components/ui/charts/smooth-funnel'\n\ninterface Stage {\n  name: string\n  value: number\n}\n\ninterface Props {\n  data: Stage[]\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?: HTMLAttributes['class']\n}\n\nconst 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\nconst props = withDefaults(defineProps<Props>(), {\n  height: 180,\n  hideRetention: false,\n})\n\nconst palette = computed(() => props.colors ?? DEFAULT_PALETTE)\nconst fmt = (v: number) => (props.format ? props.format(v) : v.toLocaleString())\nconst retention = (i: number) => {\n  if (i === 0) return null\n  const prev = props.data[i - 1]?.value ?? 1\n  return Math.round((props.data[i]!.value / prev) * 100)\n}\n</script>\n\n<template>\n  <div data-uipkge data-slot=\"conversion-funnel\" :class=\"cn('space-y-2', props.class)\">\n    <!-- Top: per-stage count -->\n    <div class=\"grid px-2 text-center\" :style=\"{ gridTemplateColumns: `repeat(${data.length}, minmax(0, 1fr))` }\">\n      <div v-for=\"stage in data\" :key=\"`top-${stage.name}`\" class=\"text-foreground text-base font-bold tabular-nums\">\n        {{ fmt(stage.value) }}\n      </div>\n    </div>\n\n    <!-- Funnel SVG -->\n    <SmoothFunnel :data=\"data\" :height=\"height\" :colors=\"palette\" />\n\n    <!-- Bottom: stage name + retention from previous -->\n    <div class=\"grid px-2 text-center\" :style=\"{ gridTemplateColumns: `repeat(${data.length}, minmax(0, 1fr))` }\">\n      <div v-for=\"(stage, i) in data\" :key=\"`bot-${stage.name}`\" class=\"space-y-0.5\">\n        <p class=\"text-muted-foreground text-xs\">{{ stage.name }}</p>\n        <p v-if=\"!hideRetention && retention(i) !== null\" class=\"text-info text-[10px] font-semibold tabular-nums\">\n          → {{ retention(i) }}% retained\n        </p>\n      </div>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/ConversionFunnel.vue"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/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": [
    "dashboard",
    "analytics"
  ]
}