{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "feature-drag-drop-organizer",
  "title": "Feature Drag Drop Organizer",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/feature-drag-drop-organizer/FeatureDragDropOrganizer.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { Activity, ArrowDown, ArrowRight, ArrowUp, Check, Copy, Eye, EyeOff, Layers, RotateCcw } from 'lucide-vue-next'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { cn } from '@/lib/utils'\n\nexport interface LayoutWidget {\n  id: string\n  name: string\n  category: string\n  visible: boolean\n  colSpan: number\n  previewSnippet: string\n}\n\nexport interface FeatureDragDropOrganizerProps {\n  title?: string\n  description?: string\n  class?: string\n}\n\nconst INITIAL_WIDGETS: LayoutWidget[] = [\n  {\n    id: 'widget-kpi',\n    name: 'Real-time KPI Metrics',\n    category: 'Analytics',\n    visible: true,\n    colSpan: 12,\n    previewSnippet: '3 Cards: $124.5k MRR • 18ms Latency • 99.99% Uptime',\n  },\n  {\n    id: 'widget-chart',\n    name: 'Traffic Sparkline Chart',\n    category: 'Telemetry',\n    visible: true,\n    colSpan: 8,\n    previewSnippet: 'SVG Real-time stream (35,000 req/s live)',\n  },\n  {\n    id: 'widget-nodes',\n    name: 'Edge PoP Status',\n    category: 'Infrastructure',\n    visible: true,\n    colSpan: 4,\n    previewSnippet: '8 global edge regions active (optimal)',\n  },\n  {\n    id: 'widget-feed',\n    name: 'Deployment Activity Feed',\n    category: 'Workflows',\n    visible: true,\n    colSpan: 12,\n    previewSnippet: 'sha-a81f9c deployed to edge via CLI (2 mins ago)',\n  },\n]\n\nconst props = withDefaults(defineProps<FeatureDragDropOrganizerProps>(), {\n  title: 'Arrange dashboard layouts intuitively with zero boilerplate.',\n  description:\n    'Customize widget order, toggle component visibility, and export clean declarative JSON layout schemas for your application.',\n})\n\nconst widgets = ref<LayoutWidget[]>([...INITIAL_WIDGETS])\nconst copied = ref(false)\n\nfunction moveWidget(index: number, direction: 'up' | 'down') {\n  const targetIndex = direction === 'up' ? index - 1 : index + 1\n  if (targetIndex < 0 || targetIndex >= widgets.value.length) return\n\n  const updated = [...widgets.value]\n  const [removed] = updated.splice(index, 1)\n  updated.splice(targetIndex, 0, removed)\n  widgets.value = updated\n}\n\nfunction toggleVisibility(index: number) {\n  widgets.value[index].visible = !widgets.value[index].visible\n}\n\nfunction resetLayout() {\n  widgets.value = JSON.parse(JSON.stringify(INITIAL_WIDGETS))\n}\n\nconst exportJson = computed(() => {\n  return JSON.stringify(\n    widgets.value.map((w, idx) => ({\n      order: idx,\n      id: w.id,\n      name: w.name,\n      visible: w.visible,\n      colSpan: w.colSpan,\n    })),\n    null,\n    2,\n  )\n})\n\nasync function copyJson() {\n  try {\n    await navigator.clipboard.writeText(exportJson.value)\n    copied.value = true\n    setTimeout(() => {\n      copied.value = false\n    }, 2000)\n  } catch {\n    // fallback\n  }\n}\n</script>\n\n<template>\n  <section\n    data-slot=\"feature-drag-drop-organizer\"\n    :class=\"cn('bg-background relative overflow-hidden py-16 sm:py-24', props.class)\"\n  >\n    <div class=\"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8\">\n      <!-- Section Header -->\n      <div class=\"mx-auto max-w-3xl space-y-4 text-center\">\n        <a\n          href=\"#layout-organizer\"\n          class=\"group border-border/80 bg-secondary/60 hover:bg-secondary text-foreground inline-flex items-center gap-2 rounded-full border px-3.5 py-1 text-xs font-medium shadow-2xs transition-colors\"\n        >\n          <Layers class=\"text-primary size-3.5\" />\n          <span>Composable Layout Workbench</span>\n          <ArrowRight class=\"text-muted-foreground size-3 transition-transform group-hover:translate-x-0.5\" />\n        </a>\n\n        <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl\">\n          {{ title }}\n        </h2>\n\n        <p class=\"text-muted-foreground text-base sm:text-lg\">\n          {{ description }}\n        </p>\n      </div>\n\n      <!-- Workbench Grid (2 Columns: Controls & Live Canvas) -->\n      <div class=\"mt-12 grid grid-cols-1 gap-6 lg:grid-cols-12\">\n        <!-- Left: Widget Re-ordering Controls (6 Cols) -->\n        <Card class=\"border-border bg-card flex flex-col justify-between shadow-xs lg:col-span-6\">\n          <CardContent class=\"space-y-5 p-6\">\n            <div class=\"border-border flex items-center justify-between border-b pb-3\">\n              <div class=\"flex items-center gap-2\">\n                <Layers class=\"text-primary size-4\" />\n                <span class=\"text-foreground text-sm font-semibold\">Widget Hierarchy</span>\n              </div>\n              <Button\n                variant=\"ghost\"\n                size=\"sm\"\n                class=\"text-muted-foreground hover:text-foreground h-7 gap-1 px-2 font-mono text-xs active:scale-95\"\n                @click=\"resetLayout\"\n              >\n                <RotateCcw class=\"size-3\" />\n                <span>Reset</span>\n              </Button>\n            </div>\n\n            <!-- Reorderable List of Widgets -->\n            <div class=\"space-y-2\">\n              <div\n                v-for=\"(widget, idx) in widgets\"\n                :key=\"widget.id\"\n                :class=\"\n                  cn(\n                    'flex items-center justify-between rounded-lg border p-3 transition-colors',\n                    widget.visible ? 'border-border bg-background' : 'border-border/60 bg-muted/30 opacity-60',\n                  )\n                \"\n              >\n                <div class=\"flex min-w-0 items-center gap-3\">\n                  <div class=\"text-muted-foreground flex items-center gap-1\">\n                    <button\n                      type=\"button\"\n                      :disabled=\"idx === 0\"\n                      class=\"hover:bg-muted rounded p-1 transition-[colors,transform] active:scale-90 disabled:opacity-30\"\n                      @click=\"moveWidget(idx, 'up')\"\n                    >\n                      <ArrowUp class=\"size-3.5\" />\n                    </button>\n                    <button\n                      type=\"button\"\n                      :disabled=\"idx === widgets.length - 1\"\n                      class=\"hover:bg-muted rounded p-1 transition-[colors,transform] active:scale-90 disabled:opacity-30\"\n                      @click=\"moveWidget(idx, 'down')\"\n                    >\n                      <ArrowDown class=\"size-3.5\" />\n                    </button>\n                  </div>\n\n                  <div class=\"min-w-0 space-y-0.5\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-foreground text-xs font-bold\">{{ widget.name }}</span>\n                      <Badge variant=\"outline\" class=\"border-border text-muted-foreground text-xs\">\n                        {{ widget.category }}\n                      </Badge>\n                    </div>\n                    <div class=\"text-muted-foreground truncate text-xs\">{{ widget.previewSnippet }}</div>\n                  </div>\n                </div>\n\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  class=\"text-muted-foreground hover:text-foreground size-8 shrink-0 active:scale-95\"\n                  @click=\"toggleVisibility(idx)\"\n                >\n                  <Eye v-if=\"widget.visible\" class=\"text-primary size-3.5\" />\n                  <EyeOff v-else class=\"size-3.5\" />\n                </Button>\n              </div>\n            </div>\n\n            <!-- Export JSON Box -->\n            <div class=\"border-border space-y-2 border-t pt-2\">\n              <div class=\"flex items-center justify-between text-xs\">\n                <span class=\"text-foreground font-medium\">Generated Layout JSON</span>\n                <Button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  class=\"h-6 gap-1 px-2 font-mono text-xs active:scale-95\"\n                  @click=\"copyJson\"\n                >\n                  <Check v-if=\"copied\" class=\"text-primary size-3\" />\n                  <Copy v-else class=\"size-3\" />\n                  <span>{{ copied ? 'Copied' : 'Copy JSON' }}</span>\n                </Button>\n              </div>\n              <pre\n                class=\"border-border bg-muted/40 text-muted-foreground max-h-32 overflow-y-auto rounded-lg border p-2.5 font-mono text-xs\"\n              ><code>{{ exportJson }}</code></pre>\n            </div>\n          </CardContent>\n        </Card>\n\n        <!-- Right: Live Canvas Preview (6 Cols) -->\n        <Card class=\"border-border bg-card flex flex-col justify-between shadow-xs lg:col-span-6\">\n          <CardContent class=\"space-y-4 p-6\">\n            <div class=\"border-border flex items-center justify-between border-b pb-3\">\n              <div class=\"flex items-center gap-2\">\n                <Activity class=\"text-success size-4\" />\n                <span class=\"text-foreground text-sm font-semibold\">Rendered Canvas Preview</span>\n              </div>\n              <span class=\"text-success font-mono text-xs\">Live Synchronized</span>\n            </div>\n\n            <!-- Simulated Dashboard Canvas with Reordered Components -->\n            <div class=\"border-border/80 bg-background/80 space-y-3 rounded-lg border p-4\">\n              <template v-for=\"widget in widgets\" :key=\"widget.id\">\n                <div\n                  v-if=\"widget.visible\"\n                  class=\"border-border bg-muted/30 space-y-1 rounded-lg border p-3 transition-colors\"\n                >\n                  <div class=\"text-foreground flex items-center justify-between text-xs font-semibold\">\n                    <span>{{ widget.name }}</span>\n                    <span class=\"text-muted-foreground font-mono text-xs\">col-span-{{ widget.colSpan }}</span>\n                  </div>\n                  <div class=\"text-muted-foreground text-xs\">{{ widget.previewSnippet }}</div>\n                </div>\n              </template>\n            </div>\n          </CardContent>\n        </Card>\n      </div>\n    </div>\n  </section>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/feature-drag-drop-organizer/FeatureDragDropOrganizer.vue"
    },
    {
      "path": "packages/registry-vue/blocks/feature-drag-drop-organizer/index.ts",
      "content": "export { default as FeatureDragDropOrganizer } from './FeatureDragDropOrganizer.vue'\nexport type { FeatureDragDropOrganizerProps, LayoutWidget } from './FeatureDragDropOrganizer.vue'\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/feature-drag-drop-organizer/index.ts"
    }
  ],
  "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"
  ],
  "description": "Interactive dashboard block layout organizer with position reordering, visibility toggling, and JSON schema export.",
  "categories": [
    "feature",
    "marketing"
  ]
}