{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "feature-flags-manager",
  "title": "Feature Flags Manager",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/feature-flags-manager/FeatureFlagsManager.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport {\n  Check,\n  Copy,\n  Flag,\n  History,\n  MoreHorizontal,\n  Plus,\n  Search,\n  ShieldAlert,\n  Sliders,\n  SlidersHorizontal,\n  Trash2,\n  Zap,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card } from '@/components/ui/card'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Progress } from '@/components/ui/progress'\nimport { Switch } from '@/components/ui/switch'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport interface EnvironmentState {\n  production: boolean\n  staging: boolean\n  development: boolean\n}\n\nexport interface FeatureFlag {\n  id: string\n  name: string\n  key: string\n  description: string\n  tags: string[]\n  enabled: boolean\n  rollout: number\n  targetingRules: string\n  environments: EnvironmentState\n  evaluationCount?: string\n  lastUpdated?: string\n}\n\nconst defaultFlags: FeatureFlag[] = [\n  {\n    id: 'ff-1',\n    name: 'New Checkout Experience',\n    key: 'new-checkout-v2',\n    description: 'Modern multi-step checkout flow with one-click payment options.',\n    tags: ['Frontend', 'Beta', 'Core'],\n    enabled: true,\n    rollout: 50,\n    targetingRules: \"plan === 'enterprise' && country === 'US'\",\n    environments: {\n      production: true,\n      staging: true,\n      development: false,\n    },\n    evaluationCount: '1.8M/day',\n    lastUpdated: '10 min ago',\n  },\n  {\n    id: 'ff-2',\n    name: 'Dark Mode V2 Beta',\n    key: 'dark-mode-beta',\n    description: 'High-contrast OKLCH dark palette with custom system theme sync.',\n    tags: ['Frontend', 'Beta'],\n    enabled: true,\n    rollout: 100,\n    targetingRules: 'beta_tester === true',\n    environments: {\n      production: true,\n      staging: true,\n      development: true,\n    },\n    evaluationCount: '920K/day',\n    lastUpdated: '2 hours ago',\n  },\n  {\n    id: 'ff-3',\n    name: 'AI Auto Complete',\n    key: 'ai-auto-complete',\n    description: 'LLM-assisted syntax suggestion and context-aware auto-completion.',\n    tags: ['AI', 'Core', 'Beta'],\n    enabled: true,\n    rollout: 25,\n    targetingRules: \"org_tier IN ['growth', 'enterprise']\",\n    environments: {\n      production: true,\n      staging: true,\n      development: false,\n    },\n    evaluationCount: '640K/day',\n    lastUpdated: '1 day ago',\n  },\n  {\n    id: 'ff-4',\n    name: 'GraphQL API v2 Gateway',\n    key: 'graphql-api-v2',\n    description: 'High-throughput GraphQL federation engine replacing legacy REST proxy.',\n    tags: ['Backend', 'Core'],\n    enabled: false,\n    rollout: 0,\n    targetingRules: 'internal_team === true',\n    environments: {\n      production: false,\n      staging: true,\n      development: true,\n    },\n    evaluationCount: '480K/day',\n    lastUpdated: '3 days ago',\n  },\n  {\n    id: 'ff-5',\n    name: 'Crypto Payments Pilot',\n    key: 'crypto-payments',\n    description: 'USDC and Ethereum settlement rail for international enterprise invoices.',\n    tags: ['Core', 'Beta'],\n    enabled: false,\n    rollout: 10,\n    targetingRules: \"country IN ['US', 'DE', 'SG'] && plan === 'enterprise'\",\n    environments: {\n      production: false,\n      staging: true,\n      development: false,\n    },\n    evaluationCount: '120K/day',\n    lastUpdated: '5 days ago',\n  },\n]\n\ninterface Props {\n  initialFlags?: FeatureFlag[]\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {})\n\nconst flags = ref<FeatureFlag[]>(props.initialFlags ? [...props.initialFlags] : [...defaultFlags])\nconst searchQuery = ref('')\nconst selectedStatus = ref<'all' | 'enabled' | 'disabled'>('all')\nconst copiedKey = ref<string | null>(null)\n\nfunction toggleFlag(id: string) {\n  flags.value = flags.value.map((flag) => {\n    if (flag.id === id) {\n      return { ...flag, enabled: !flag.enabled }\n    }\n    return flag\n  })\n}\n\nfunction deleteFlag(id: string) {\n  flags.value = flags.value.filter((flag) => flag.id !== id)\n}\n\nfunction copyFlagKey(key: string) {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(key)\n    copiedKey.value = key\n    setTimeout(() => {\n      if (copiedKey.value === key) copiedKey.value = null\n    }, 2000)\n  }\n}\n\nconst filteredFlags = computed(() => {\n  const query = searchQuery.value.trim().toLowerCase()\n  return flags.value.filter((flag) => {\n    if (selectedStatus.value === 'enabled' && !flag.enabled) return false\n    if (selectedStatus.value === 'disabled' && flag.enabled) return false\n\n    if (!query) return true\n    const matchName = flag.name.toLowerCase().includes(query)\n    const matchKey = flag.key.toLowerCase().includes(query)\n    const matchDesc = flag.description.toLowerCase().includes(query)\n    const matchTag = flag.tags.some((t) => t.toLowerCase().includes(query))\n    return matchName || matchKey || matchDesc || matchTag\n  })\n})\n</script>\n\n<template>\n  <div data-slot=\"feature-flags-manager\" :class=\"cn('w-full space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div>\n        <h2 class=\"text-foreground text-2xl font-bold tracking-tight\">Feature Flags</h2>\n        <p class=\"text-muted-foreground mt-1 text-sm\">\n          Safely deploy features with percentage rollouts, user targeting, and kill switches.\n        </p>\n      </div>\n      <div class=\"flex items-center gap-2\">\n        <Button>\n          <Plus aria-hidden=\"true\" class=\"size-4\" />\n          Create Flag\n        </Button>\n      </div>\n    </div>\n\n    <!-- Summary Metric Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <Card class=\"p-4 shadow-xs\">\n        <div class=\"flex items-center justify-between gap-x-2\">\n          <span class=\"text-muted-foreground text-xs font-medium\">Total Flags</span>\n          <div class=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-md\">\n            <Flag aria-hidden=\"true\" class=\"size-4\" />\n          </div>\n        </div>\n        <div class=\"mt-2\">\n          <div class=\"text-foreground text-2xl font-bold tracking-tight\">24</div>\n          <p class=\"text-muted-foreground mt-1 text-xs\">5 in current scope</p>\n        </div>\n      </Card>\n\n      <Card class=\"p-4 shadow-xs\">\n        <div class=\"flex items-center justify-between gap-x-2\">\n          <span class=\"text-muted-foreground text-xs font-medium\">Active Rollouts</span>\n          <div class=\"bg-info/10 text-info flex size-8 items-center justify-center rounded-md\">\n            <SlidersHorizontal aria-hidden=\"true\" class=\"size-4\" />\n          </div>\n        </div>\n        <div class=\"mt-2\">\n          <div class=\"text-foreground text-2xl font-bold tracking-tight\">8</div>\n          <p class=\"text-muted-foreground mt-1 text-xs\">Gradual traffic ramps</p>\n        </div>\n      </Card>\n\n      <Card class=\"p-4 shadow-xs\">\n        <div class=\"flex items-center justify-between gap-x-2\">\n          <span class=\"text-muted-foreground text-xs font-medium\">Kill-Switches Armed</span>\n          <div class=\"bg-warning/10 text-warning flex size-8 items-center justify-center rounded-md\">\n            <ShieldAlert aria-hidden=\"true\" class=\"size-4\" />\n          </div>\n        </div>\n        <div class=\"mt-2\">\n          <div class=\"text-foreground text-2xl font-bold tracking-tight\">3</div>\n          <p class=\"text-muted-foreground mt-1 text-xs\">Instant emergency trip</p>\n        </div>\n      </Card>\n\n      <Card class=\"p-4 shadow-xs\">\n        <div class=\"flex items-center justify-between gap-x-2\">\n          <span class=\"text-muted-foreground text-xs font-medium\">Evaluation Volume</span>\n          <div class=\"bg-success/10 text-success flex size-8 items-center justify-center rounded-md\">\n            <Zap aria-hidden=\"true\" class=\"size-4\" />\n          </div>\n        </div>\n        <div class=\"mt-2\">\n          <div class=\"text-foreground text-2xl font-bold tracking-tight\">4.2M/day</div>\n          <p class=\"text-muted-foreground mt-1 text-xs\">99.99% cache hit · 1.2ms p99</p>\n        </div>\n      </Card>\n    </div>\n\n    <!-- Filter & Search Toolbar -->\n    <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n      <div class=\"flex flex-1 flex-wrap items-center gap-2\">\n        <div class=\"relative w-full sm:w-80\">\n          <Search\n            aria-hidden=\"true\"\n            class=\"text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2\"\n          />\n          <Input\n            v-model=\"searchQuery\"\n            placeholder=\"Search flags by name, key, or tag...\"\n            class=\"h-9 pl-8.5 text-xs sm:text-sm\"\n          />\n        </div>\n\n        <div class=\"border-border bg-muted/30 flex items-center rounded-lg border p-0.5\">\n          <button\n            type=\"button\"\n            :class=\"\n              cn(\n                'min-h-6 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                selectedStatus === 'all'\n                  ? 'bg-background text-foreground shadow-xs'\n                  : 'text-muted-foreground hover:text-foreground',\n              )\n            \"\n            @click=\"selectedStatus = 'all'\"\n          >\n            All\n          </button>\n          <button\n            type=\"button\"\n            :class=\"\n              cn(\n                'min-h-6 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                selectedStatus === 'enabled'\n                  ? 'bg-background text-foreground shadow-xs'\n                  : 'text-muted-foreground hover:text-foreground',\n              )\n            \"\n            @click=\"selectedStatus = 'enabled'\"\n          >\n            Enabled\n          </button>\n          <button\n            type=\"button\"\n            :class=\"\n              cn(\n                'min-h-6 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                selectedStatus === 'disabled'\n                  ? 'bg-background text-foreground shadow-xs'\n                  : 'text-muted-foreground hover:text-foreground',\n              )\n            \"\n            @click=\"selectedStatus = 'disabled'\"\n          >\n            Disabled\n          </button>\n        </div>\n      </div>\n\n      <div class=\"flex items-center gap-2\">\n        <span class=\"text-muted-foreground text-xs tabular-nums\">\n          Showing {{ filteredFlags.length }} of {{ flags.length }} flags\n        </span>\n      </div>\n    </div>\n\n    <!-- Feature Flags Table -->\n    <div class=\"bg-card border-border overflow-hidden rounded-xl border shadow-xs\">\n      <div class=\"overflow-x-auto\">\n        <Table class=\"max-w-[920px] min-w-full\">\n          <TableHeader>\n            <TableRow class=\"bg-muted/40 hover:bg-transparent\">\n              <TableHead class=\"w-[300px]\">Flag</TableHead>\n              <TableHead class=\"w-[130px]\">Status</TableHead>\n              <TableHead class=\"w-[160px]\">Rollout</TableHead>\n              <TableHead class=\"min-w-[240px]\">Targeting Rules</TableHead>\n              <TableHead class=\"w-[160px]\">Environments</TableHead>\n              <TableHead class=\"w-[50px] text-right\"><span class=\"sr-only\">Actions</span></TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            <TableRow\n              v-for=\"flag in filteredFlags\"\n              :key=\"flag.id\"\n              :class=\"cn('hover:bg-muted/40 transition-colors', !flag.enabled && 'opacity-75 dark:opacity-70')\"\n            >\n              <!-- Flag Name, Key, Description & Tags -->\n              <TableCell class=\"py-3.5 align-top\">\n                <div class=\"space-y-1\">\n                  <div class=\"flex items-center gap-2\">\n                    <span class=\"text-foreground text-sm font-semibold\">{{ flag.name }}</span>\n                  </div>\n                  <div class=\"flex items-center gap-1.5\">\n                    <code\n                      class=\"bg-muted/70 text-muted-foreground border-border/50 rounded border px-1.5 py-0.5 font-mono text-xs select-all\"\n                    >\n                      {{ flag.key }}\n                    </code>\n                    <button\n                      type=\"button\"\n                      class=\"text-muted-foreground hover:text-foreground hover:bg-muted inline-flex min-h-6 min-w-6 items-center justify-center rounded p-0.5 transition-colors\"\n                      :title=\"copiedKey === flag.key ? 'Copied!' : 'Copy key'\"\n                      @click=\"copyFlagKey(flag.key)\"\n                    >\n                      <Check v-if=\"copiedKey === flag.key\" class=\"text-success size-3\" />\n                      <Copy v-else class=\"size-3\" />\n                      <span class=\"sr-only\">Copy {{ flag.key }}</span>\n                    </button>\n                  </div>\n                  <p class=\"text-muted-foreground line-clamp-1 pt-0.5 text-xs\">\n                    {{ flag.description }}\n                  </p>\n                  <div class=\"flex flex-wrap items-center gap-1 pt-1\">\n                    <Badge\n                      v-for=\"tag in flag.tags\"\n                      :key=\"tag\"\n                      variant=\"outline\"\n                      class=\"text-muted-foreground px-1.5 py-0 text-xs font-normal\"\n                    >\n                      {{ tag }}\n                    </Badge>\n                  </div>\n                </div>\n              </TableCell>\n\n              <!-- Master Status Switch -->\n              <TableCell class=\"py-3.5 align-middle\">\n                <div class=\"flex items-center gap-2.5\">\n                  <Switch\n                    :model-value=\"flag.enabled\"\n                    :aria-label=\"`Toggle ${flag.name}`\"\n                    @update:model-value=\"toggleFlag(flag.id)\"\n                  />\n                  <span\n                    :class=\"\n                      cn(\n                        'text-xs font-medium',\n                        flag.enabled ? 'text-success dark:text-success' : 'text-muted-foreground',\n                      )\n                    \"\n                  >\n                    {{ flag.enabled ? 'Enabled' : 'Disabled' }}\n                  </span>\n                </div>\n              </TableCell>\n\n              <!-- Rollout % Visual Progress Bar -->\n              <TableCell class=\"py-3.5 align-middle\">\n                <div class=\"max-w-[130px] space-y-1.5\">\n                  <div class=\"flex items-center justify-between gap-x-2 text-xs\">\n                    <span class=\"text-foreground font-semibold tabular-nums\">\n                      {{ flag.enabled ? `${flag.rollout}%` : '0%' }}\n                    </span>\n                    <span class=\"text-muted-foreground text-xs\">\n                      {{ flag.enabled ? (flag.rollout === 100 ? 'All users' : 'Ramp') : 'Inactive' }}\n                    </span>\n                  </div>\n                  <Progress :model-value=\"flag.enabled ? flag.rollout : 0\" class=\"h-1.5\" />\n                </div>\n              </TableCell>\n\n              <!-- Targeting Rules Summary -->\n              <TableCell class=\"py-3.5 align-middle\">\n                <div class=\"flex items-center\">\n                  <code\n                    class=\"border-border/60 bg-muted/40 text-foreground/80 inline-flex max-w-[260px] items-center gap-1 truncate rounded border px-2 py-1 font-mono text-xs\"\n                    :title=\"flag.targetingRules\"\n                  >\n                    <span class=\"text-muted-foreground font-sans text-xs\">Target:</span>\n                    <span class=\"truncate\">{{ flag.targetingRules }}</span>\n                  </code>\n                </div>\n              </TableCell>\n\n              <!-- Environment Badges -->\n              <TableCell class=\"py-3.5 align-middle\">\n                <div class=\"flex items-center gap-1\">\n                  <span\n                    :class=\"\n                      cn(\n                        'inline-flex items-center gap-1 rounded border px-1.5 py-0.5 font-mono text-xs font-medium',\n                        flag.environments.production\n                          ? 'bg-success/10 text-success border-success/20'\n                          : 'bg-muted/40 text-muted-foreground border-transparent opacity-60',\n                      )\n                    \"\n                  >\n                    <span\n                      :class=\"\n                        cn(\n                          'size-1.5 rounded-full',\n                          flag.environments.production ? 'bg-success' : 'bg-muted-foreground/40',\n                        )\n                      \"\n                    />\n                    Prod\n                  </span>\n                  <span\n                    :class=\"\n                      cn(\n                        'inline-flex items-center gap-1 rounded border px-1.5 py-0.5 font-mono text-xs font-medium',\n                        flag.environments.staging\n                          ? 'bg-success/10 text-success border-success/20'\n                          : 'bg-muted/40 text-muted-foreground border-transparent opacity-60',\n                      )\n                    \"\n                  >\n                    <span\n                      :class=\"\n                        cn('size-1.5 rounded-full', flag.environments.staging ? 'bg-success' : 'bg-muted-foreground/40')\n                      \"\n                    />\n                    Stg\n                  </span>\n                  <span\n                    :class=\"\n                      cn(\n                        'inline-flex items-center gap-1 rounded border px-1.5 py-0.5 font-mono text-xs font-medium',\n                        flag.environments.development\n                          ? 'bg-success/10 text-success border-success/20'\n                          : 'bg-muted/40 text-muted-foreground border-transparent opacity-60',\n                      )\n                    \"\n                  >\n                    <span\n                      :class=\"\n                        cn(\n                          'size-1.5 rounded-full',\n                          flag.environments.development ? 'bg-success' : 'bg-muted-foreground/40',\n                        )\n                      \"\n                    />\n                    Dev\n                  </span>\n                </div>\n              </TableCell>\n\n              <!-- Actions Dropdown -->\n              <TableCell class=\"py-3.5 text-right align-middle\">\n                <DropdownMenu>\n                  <DropdownMenuTrigger as-child>\n                    <Button variant=\"ghost\" size=\"icon-sm\" class=\"text-muted-foreground hover:text-foreground\">\n                      <MoreHorizontal aria-hidden=\"true\" class=\"size-4\" />\n                      <span class=\"sr-only\">Actions for {{ flag.name }}</span>\n                    </Button>\n                  </DropdownMenuTrigger>\n                  <DropdownMenuContent align=\"end\">\n                    <DropdownMenuItem>\n                      <Sliders aria-hidden=\"true\" class=\"mr-2 size-4\" />\n                      Edit rules\n                    </DropdownMenuItem>\n                    <DropdownMenuItem>\n                      <History aria-hidden=\"true\" class=\"mr-2 size-4\" />\n                      Audit history\n                    </DropdownMenuItem>\n                    <DropdownMenuItem @click=\"copyFlagKey(flag.key)\">\n                      <Copy aria-hidden=\"true\" class=\"mr-2 size-4\" />\n                      Copy flag key\n                    </DropdownMenuItem>\n                    <DropdownMenuSeparator />\n                    <DropdownMenuItem\n                      variant=\"destructive\"\n                      class=\"text-destructive focus:text-destructive\"\n                      @click=\"deleteFlag(flag.id)\"\n                    >\n                      <Trash2 aria-hidden=\"true\" class=\"mr-2 size-4\" />\n                      Delete flag\n                    </DropdownMenuItem>\n                  </DropdownMenuContent>\n                </DropdownMenu>\n              </TableCell>\n            </TableRow>\n\n            <!-- Empty State -->\n            <TableRow v-if=\"filteredFlags.length === 0\">\n              <TableCell colspan=\"6\" class=\"text-muted-foreground h-36 text-center\">\n                <div class=\"flex flex-col items-center justify-center space-y-1.5\">\n                  <Search class=\"text-muted-foreground/40 size-6\" />\n                  <p class=\"text-foreground text-sm font-medium\">No feature flags found</p>\n                  <p class=\"text-muted-foreground text-xs\">\n                    No flags match your search or filter criteria. Try adjusting your query.\n                  </p>\n                </div>\n              </TableCell>\n            </TableRow>\n          </TableBody>\n        </Table>\n      </div>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/FeatureFlagsManager.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "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/dropdown-menu.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/switch.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "LaunchDarkly and PostHog style feature flags management dashboard: top header with search and create flag button, summary KPI metric cards, master status switch, percentage rollout indicators, targeting rules summary, environment statuses, and action menus.",
  "categories": [
    "devops",
    "dashboard",
    "app",
    "data"
  ]
}