{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "referral-program-widget",
  "title": "Referral Program Widget",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/referral-program-widget/ReferralProgramWidget.vue",
      "content": "<script lang=\"ts\">\nexport interface MilestoneTier {\n  id: string\n  tier: number\n  referralsRequired: number\n  title: string\n  reward: string\n  description: string\n  status: 'completed' | 'in-progress' | 'upcoming'\n}\n\nexport interface ReferralActivity {\n  id: string\n  name: string\n  email: string\n  initials: string\n  signedUpAt: string\n  status: 'paid' | 'pending'\n  rewardAmount: string\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport { Check, Clock, Copy, Gift, Lock, Mail, Share2, Target, Trophy, Users, Wallet } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\ninterface Props {\n  referralUrl?: string\n  referralCode?: string\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  referralUrl: 'https://uipkge.dev/invite/elena-rostova',\n  referralCode: 'ELENA25',\n})\n\nconst copiedLink = ref(false)\nconst copiedCode = ref(false)\n\nconst tiers: MilestoneTier[] = [\n  {\n    id: 'tier-1',\n    tier: 1,\n    referralsRequired: 1,\n    title: '$25 Account Credit',\n    reward: '$25 Credit',\n    description: 'Instant credit applied directly to your renewal balance.',\n    status: 'completed',\n  },\n  {\n    id: 'tier-2',\n    tier: 2,\n    referralsRequired: 5,\n    title: '$125 Credit + Exclusive Swag Kit',\n    reward: '$125 + Swag Kit',\n    description: 'Premium organic cotton hoodie and engineering desk kit.',\n    status: 'completed',\n  },\n  {\n    id: 'tier-3',\n    tier: 3,\n    referralsRequired: 10,\n    title: '$250 Credit + 1-Year Free Pro Plan',\n    reward: '$250 + Pro Plan',\n    description: '6 of 10 referred · 4 more needed to unlock full Pro tier.',\n    status: 'in-progress',\n  },\n  {\n    id: 'tier-4',\n    tier: 4,\n    referralsRequired: 25,\n    title: '$1,000 Credit + VIP Lifetime Access',\n    reward: '$1,000 + VIP Pass',\n    description: 'Direct Slack channel access to core founders and private beta track.',\n    status: 'upcoming',\n  },\n]\n\nconst recentReferrals: ReferralActivity[] = [\n  {\n    id: 'ref-1',\n    name: 'Marcus Vance',\n    email: 'marcus.v@acme.com',\n    initials: 'MV',\n    signedUpAt: 'Oct 14, 2024',\n    status: 'paid',\n    rewardAmount: '$25.00',\n  },\n  {\n    id: 'ref-2',\n    name: 'Sarah Jenkins',\n    email: 's.jenkins@designcorp.io',\n    initials: 'SJ',\n    signedUpAt: 'Oct 02, 2024',\n    status: 'paid',\n    rewardAmount: '$25.00',\n  },\n  {\n    id: 'ref-3',\n    name: 'Devon Lane',\n    email: 'devon@lane.co',\n    initials: 'DL',\n    signedUpAt: 'Sep 28, 2024',\n    status: 'pending',\n    rewardAmount: '$25.00',\n  },\n  {\n    id: 'ref-4',\n    name: 'Priya Patel',\n    email: 'priya.patel@fintech.io',\n    initials: 'PP',\n    signedUpAt: 'Sep 15, 2024',\n    status: 'paid',\n    rewardAmount: '$25.00',\n  },\n]\n\nconst twitterShareUrl = computed(() => {\n  const text = 'Get $25 off your first year with my invite link:'\n  return `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(props.referralUrl)}`\n})\n\nconst linkedinShareUrl = computed(() => {\n  return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(props.referralUrl)}`\n})\n\nconst emailShareUrl = computed(() => {\n  const subject = 'Get $25 off your subscription'\n  const body = `Hey,\\n\\nUse my invite link to get $25 off your first year:\\n${props.referralUrl}\\n\\nUse invite code ${props.referralCode} at checkout!`\n  return `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`\n})\n\nasync function copyToClipboard(text: string, type: 'link' | 'code') {\n  try {\n    if (navigator?.clipboard?.writeText) {\n      await navigator.clipboard.writeText(text)\n    }\n  } catch {\n    // Fallback if clipboard API is unavailable\n  }\n\n  if (type === 'link') {\n    copiedLink.value = true\n    setTimeout(() => {\n      copiedLink.value = false\n    }, 2000)\n  } else {\n    copiedCode.value = true\n    setTimeout(() => {\n      copiedCode.value = false\n    }, 2000)\n  }\n}\n</script>\n\n<template>\n  <div data-slot=\"referral-program-widget\" :class=\"cn('mx-auto w-full max-w-5xl space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"space-y-4\">\n      <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <div class=\"flex items-center gap-2\">\n            <Badge variant=\"secondary\" class=\"gap-1.5 font-medium\">\n              <Gift class=\"text-primary size-3.5\" aria-hidden=\"true\" />\n              Give $25, Get $25\n            </Badge>\n          </div>\n          <h1 class=\"text-foreground mt-2 text-2xl font-bold tracking-tight sm:text-3xl\">\n            Refer Friends &amp; Earn Credits\n          </h1>\n          <p class=\"text-muted-foreground mt-1 max-w-2xl text-sm sm:text-base\">\n            Give your network $25 off their first year, and earn $25 credit for every active referral.\n          </p>\n        </div>\n      </div>\n\n      <!-- Referral Balance Card -->\n      <Card class=\"border-border/80 shadow-xs\">\n        <CardContent class=\"p-4 sm:p-6\">\n          <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"flex items-center gap-4\">\n              <div\n                class=\"bg-primary/10 text-primary border-primary/20 flex size-12 shrink-0 items-center justify-center rounded-xl border\"\n              >\n                <Wallet class=\"size-6\" aria-hidden=\"true\" />\n              </div>\n              <div>\n                <p class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">Referral Balance</p>\n                <div class=\"mt-0.5 flex flex-wrap items-baseline gap-2\">\n                  <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums sm:text-3xl\">\n                    $150.00\n                  </span>\n                  <span class=\"text-muted-foreground text-sm font-medium\">Available Credit</span>\n                  <span class=\"text-foreground text-sm font-semibold tabular-nums\"> 6 Successful Referrals </span>\n                </div>\n              </div>\n            </div>\n            <div class=\"flex items-center gap-2\">\n              <Badge variant=\"outline\" class=\"text-xs font-medium tabular-nums\"> 1 Pending ($25.00) </Badge>\n              <Button size=\"sm\" variant=\"outline\"> Redeem Credits </Button>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Share Your Referral Link Card -->\n    <Card class=\"border-border/80 shadow-xs\">\n      <CardHeader class=\"pb-4\">\n        <div class=\"flex items-center gap-2\">\n          <Share2 class=\"text-primary size-4\" aria-hidden=\"true\" />\n          <CardTitle class=\"text-base font-semibold\">Share Your Referral Link</CardTitle>\n        </div>\n        <CardDescription>\n          Send your personal invite link or share directly across social channels to earn rewards instantly.\n        </CardDescription>\n      </CardHeader>\n      <CardContent class=\"space-y-4\">\n        <!-- Referral URL & Copy Action -->\n        <div class=\"flex flex-col gap-2 sm:flex-row\">\n          <div class=\"relative flex-1\">\n            <Input\n              :model-value=\"referralUrl\"\n              readonly\n              class=\"bg-muted/30 font-mono text-xs sm:text-sm\"\n              aria-label=\"Your custom referral URL\"\n            />\n          </div>\n          <Button\n            type=\"button\"\n            :variant=\"copiedLink ? 'outline' : 'default'\"\n            class=\"shrink-0 gap-1.5\"\n            @click=\"copyToClipboard(referralUrl, 'link')\"\n          >\n            <Check v-if=\"copiedLink\" class=\"text-success size-4\" aria-hidden=\"true\" />\n            <Copy v-else class=\"size-4\" aria-hidden=\"true\" />\n            <span>{{ copiedLink ? 'Copied Link' : 'Copy Link' }}</span>\n          </Button>\n        </div>\n\n        <Separator />\n\n        <!-- Social Share & Code Bar -->\n        <div class=\"flex flex-wrap items-center justify-between gap-2.5\">\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <!-- Share on X / Twitter -->\n            <Button\n              as=\"a\"\n              :href=\"twitterShareUrl\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"gap-1.5 text-xs font-medium\"\n            >\n              <svg class=\"size-3.5 shrink-0\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n                <path\n                  d=\"M18.24 2.25h3.31l-7.23 8.26 8.5 11.24h-6.66l-5.21-6.82-5.97 6.82H1.68l7.73-8.84L1.25 2.25h6.83l4.71 6.23zm-1.16 17.52h1.83L7.08 4.13H5.12z\"\n                />\n              </svg>\n              Share to X\n            </Button>\n\n            <!-- Share to LinkedIn -->\n            <Button\n              as=\"a\"\n              :href=\"linkedinShareUrl\"\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"gap-1.5 text-xs font-medium\"\n            >\n              <svg class=\"size-3.5 shrink-0\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n                <path\n                  d=\"M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28zM5.34 7.43a2.06 2.06 0 110-4.13 2.06 2.06 0 010 4.13zm1.78 13.02H3.56V9h3.56v11.45zM22.22 0H1.77C.79 0 0 .77 0 1.73v20.54C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.73V1.73C24 .77 23.2 0 22.22 0z\"\n                />\n              </svg>\n              Share to LinkedIn\n            </Button>\n\n            <!-- Share via Email -->\n            <Button as=\"a\" :href=\"emailShareUrl\" variant=\"outline\" size=\"sm\" class=\"gap-1.5 text-xs font-medium\">\n              <Mail class=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n              Share via Email\n            </Button>\n          </div>\n\n          <!-- Invite Code Button -->\n          <Button\n            type=\"button\"\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"gap-1.5 text-xs font-medium\"\n            @click=\"copyToClipboard(referralCode, 'code')\"\n          >\n            <Check v-if=\"copiedCode\" class=\"text-success size-3.5\" aria-hidden=\"true\" />\n            <Copy v-else class=\"text-muted-foreground size-3.5\" aria-hidden=\"true\" />\n            <span>Invite Code:</span>\n            <span class=\"text-foreground font-mono font-semibold\">{{ referralCode }}</span>\n            <span v-if=\"copiedCode\" class=\"text-success text-xs font-medium\">Copied!</span>\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Milestone Rewards Progress Stepper -->\n    <Card class=\"border-border/80 shadow-xs\">\n      <CardHeader class=\"pb-4\">\n        <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <div class=\"flex items-center gap-2\">\n              <Trophy class=\"text-warning size-4\" aria-hidden=\"true\" />\n              <CardTitle class=\"text-base font-semibold\">Milestone Rewards</CardTitle>\n            </div>\n            <CardDescription>\n              Reach referral milestones to unlock credit bonuses, swag, and exclusive plan access.\n            </CardDescription>\n          </div>\n          <Badge variant=\"outline\" class=\"w-fit gap-1 text-xs tabular-nums\">\n            <Target class=\"text-primary size-3\" aria-hidden=\"true\" />\n            Tier 3 In Progress · 6 / 10 Referrals\n          </Badge>\n        </div>\n      </CardHeader>\n      <CardContent class=\"space-y-6\">\n        <!-- Progress Stepper Track Header -->\n        <div class=\"border-border/70 bg-muted/40 space-y-2 rounded-lg border p-4\">\n          <div class=\"flex flex-wrap items-center justify-between gap-2 text-xs sm:text-sm\">\n            <span class=\"text-foreground font-medium\">\n              Current Target: Tier 3 ($250 Credit + 1-Year Free Pro Plan)\n            </span>\n            <span class=\"text-muted-foreground font-semibold tabular-nums\"> 60% (6 of 10 referrals) </span>\n          </div>\n          <Progress :model-value=\"60\" class=\"h-2\" />\n          <p class=\"text-muted-foreground text-xs\">4 more successful referrals needed to unlock Tier 3 rewards.</p>\n        </div>\n\n        <!-- 4 Milestone Tiers Grid -->\n        <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n          <div\n            v-for=\"tier in tiers\"\n            :key=\"tier.id\"\n            :class=\"\n              cn(\n                'relative flex flex-col justify-between rounded-lg border p-4 transition-colors',\n                tier.status === 'completed' && 'border-success/30 bg-success/5',\n                tier.status === 'in-progress' && 'border-primary/50 bg-primary/5 ring-primary/20 shadow-xs ring-1',\n                tier.status === 'upcoming' && 'border-border/60 bg-muted/20 opacity-80',\n              )\n            \"\n          >\n            <div class=\"space-y-2.5\">\n              <div class=\"flex items-center justify-between gap-2\">\n                <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                  Tier {{ tier.tier }} · {{ tier.referralsRequired }}\n                  {{ tier.referralsRequired === 1 ? 'Referral' : 'Referrals' }}\n                </span>\n\n                <Badge v-if=\"tier.status === 'completed'\" variant=\"success\" class=\"gap-1 text-xs\">\n                  <Check class=\"size-3\" aria-hidden=\"true\" />\n                  Completed\n                </Badge>\n                <Badge v-else-if=\"tier.status === 'in-progress'\" variant=\"default\" class=\"gap-1 text-xs\">\n                  In Progress (6/10)\n                </Badge>\n                <Badge v-else variant=\"secondary\" class=\"text-muted-foreground gap-1 text-xs\">\n                  <Lock class=\"size-3\" aria-hidden=\"true\" />\n                  Upcoming\n                </Badge>\n              </div>\n\n              <div>\n                <p class=\"text-foreground text-sm font-semibold\">\n                  {{ tier.title }}\n                </p>\n                <p class=\"text-muted-foreground mt-1 text-xs leading-relaxed\">\n                  {{ tier.description }}\n                </p>\n              </div>\n            </div>\n\n            <div class=\"border-border/50 mt-4 border-t pt-3\">\n              <div class=\"flex items-center justify-between text-xs\">\n                <span class=\"text-muted-foreground\">Reward Perk:</span>\n                <span class=\"text-foreground font-semibold tabular-nums\">{{ tier.reward }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Recent Referrals Activity Table -->\n    <Card class=\"border-border/80 shadow-xs\">\n      <CardHeader class=\"pb-4\">\n        <div class=\"flex items-center justify-between gap-2\">\n          <div>\n            <div class=\"flex items-center gap-2\">\n              <Users class=\"text-primary size-4\" aria-hidden=\"true\" />\n              <CardTitle class=\"text-base font-semibold\">Recent Referrals</CardTitle>\n            </div>\n            <CardDescription>\n              Track recent invitees, activation statuses, and credited referral payouts.\n            </CardDescription>\n          </div>\n          <Badge variant=\"outline\" class=\"text-xs font-medium tabular-nums\"> 4 Recent Signups </Badge>\n        </div>\n      </CardHeader>\n      <CardContent class=\"p-0 sm:p-6 sm:pt-0\">\n        <div class=\"overflow-x-auto\">\n          <Table density=\"cozy\">\n            <TableHeader>\n              <TableRow>\n                <TableHead>Invitee</TableHead>\n                <TableHead>Signed Up</TableHead>\n                <TableHead>Status</TableHead>\n                <TableHead class=\"text-right\">Reward Amount</TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              <TableRow v-for=\"referral in recentReferrals\" :key=\"referral.id\">\n                <TableCell>\n                  <div class=\"flex items-center gap-3\">\n                    <Avatar class=\"size-8 shrink-0\">\n                      <AvatarFallback class=\"text-xs font-semibold\">\n                        {{ referral.initials }}\n                      </AvatarFallback>\n                    </Avatar>\n                    <div class=\"min-w-0\">\n                      <p class=\"text-foreground truncate text-sm font-medium\">\n                        {{ referral.name }}\n                      </p>\n                      <p class=\"text-muted-foreground truncate text-xs\">\n                        {{ referral.email }}\n                      </p>\n                    </div>\n                  </div>\n                </TableCell>\n                <TableCell class=\"text-muted-foreground text-xs whitespace-nowrap sm:text-sm\">\n                  {{ referral.signedUpAt }}\n                </TableCell>\n                <TableCell>\n                  <Badge v-if=\"referral.status === 'paid'\" variant=\"success\" class=\"gap-1 text-xs\">\n                    <Check class=\"size-3\" aria-hidden=\"true\" />\n                    Reward Paid $25\n                  </Badge>\n                  <Badge v-else variant=\"warning\" class=\"gap-1 text-xs\">\n                    <Clock class=\"size-3\" aria-hidden=\"true\" />\n                    Pending Activation\n                  </Badge>\n                </TableCell>\n                <TableCell class=\"text-right text-xs font-medium tabular-nums sm:text-sm\">\n                  <span :class=\"referral.status === 'paid' ? 'text-success font-semibold' : 'text-muted-foreground'\">\n                    {{ referral.status === 'paid' ? `+${referral.rewardAmount}` : referral.rewardAmount }}\n                  </span>\n                </TableCell>\n              </TableRow>\n            </TableBody>\n          </Table>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/ReferralProgramWidget.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Rewardful and Viral Loops-style customer referral program and milestone reward tracker. Features a balance summary header with available credits and referral counts, shareable link and code copy actions with quick social sharing, a 4-tier milestone stepper with dynamic progress, and a recent referrals activity table with payout statuses.",
  "categories": [
    "marketing",
    "dashboard"
  ]
}