{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "sql-query-notebook",
  "title": "Sql Query Notebook",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/sql-query-notebook/SqlQueryNotebook.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  BarChart3,\n  Check,\n  Clock,\n  Copy,\n  Database,\n  Download,\n  FileCode2,\n  FileText,\n  Layers,\n  Loader2,\n  Play,\n  Plus,\n  Table2,\n  Target,\n  Terminal,\n  Trash2,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\ninterface CohortRow {\n  signup_cohort: string\n  cohort_label: string\n  total_customers: number\n  avg_mrr: number\n  cohort_ltv: number\n  expansion_rate: string\n  retention_score: number\n}\n\nconst props = defineProps<{\n  class?: HTMLAttributes['class']\n}>()\n\n// --- State ---\nconst isRunningAll = ref(false)\nconst isCellRunning = ref(false)\nconst lastSaved = ref('Autosaved 1m ago')\nconst activeCell = ref<'doc' | 'sql' | 'extra'>('sql')\nconst activeResultTab = ref<'table' | 'chart'>('table')\nconst copiedSql = ref(false)\nconst copiedCsv = ref(false)\nconst hoveredSqlLine = ref<number | null>(null)\nconst executionTime = ref('1.24s')\nconst rowCount = ref(14290)\nconst lastExecutionTimestamp = ref('14:28:40')\nconst showMarkdownEditor = ref(false)\nconst showExtraCell = ref(false)\nconst extraCellRunning = ref(false)\n\nconst markdownContent = ref(\n  '# Cohort Retention & Expansion Query: Grouping by monthly signup cohort to evaluate customer lifetime value (LTV) trajectory and expansion MRR across enterprise tiers. Filtered for 2026 activations from the primary subscriptions warehouse.',\n)\n\nconst sqlQuery = `SELECT \n  DATE_TRUNC('month', created_at) AS signup_cohort,\n  COUNT(DISTINCT customer_id) AS total_customers,\n  ROUND(AVG(mrr), 2) AS avg_mrr,\n  ROUND(SUM(lifetime_value), 2) AS cohort_ltv\nFROM analytics.fct_subscriptions\nWHERE created_at >= '2026-01-01'\nGROUP BY 1 ORDER BY 1 DESC;`\n\nconst cohortResults: CohortRow[] = [\n  {\n    signup_cohort: '2026-06-01',\n    cohort_label: 'Jun 2026',\n    total_customers: 4820,\n    avg_mrr: 248.5,\n    cohort_ltv: 1428500.0,\n    expansion_rate: '+18.4%',\n    retention_score: 94,\n  },\n  {\n    signup_cohort: '2026-05-01',\n    cohort_label: 'May 2026',\n    total_customers: 3940,\n    avg_mrr: 232.1,\n    cohort_ltv: 1148200.0,\n    expansion_rate: '+14.1%',\n    retention_score: 89,\n  },\n  {\n    signup_cohort: '2026-04-01',\n    cohort_label: 'Apr 2026',\n    total_customers: 3110,\n    avg_mrr: 219.8,\n    cohort_ltv: 924100.0,\n    expansion_rate: '+11.8%',\n    retention_score: 85,\n  },\n  {\n    signup_cohort: '2026-03-01',\n    cohort_label: 'Mar 2026',\n    total_customers: 2420,\n    avg_mrr: 198.4,\n    cohort_ltv: 682900.0,\n    expansion_rate: '+8.6%',\n    retention_score: 81,\n  },\n]\n\nconst sqlLines = computed(() => sqlQuery.split('\\n'))\n\nconst totalCustomersSum = computed(() => {\n  return cohortResults.reduce((acc, r) => acc + r.total_customers, 0)\n})\n\nconst totalLtvSum = computed(() => {\n  return cohortResults.reduce((acc, r) => acc + r.cohort_ltv, 0)\n})\n\nconst maxCohortLtv = computed(() => {\n  return Math.max(...cohortResults.map((r) => r.cohort_ltv))\n})\n\n// --- SQL Syntax Highlighter ---\nfunction highlightSqlLine(line: string): string {\n  if (!line.trim()) return '&nbsp;'\n\n  const escaped = line.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n\n  // Single line comments\n  if (/^\\s*--/.test(escaped)) {\n    return `<span class=\"text-zinc-500 italic\">${escaped}</span>`\n  }\n\n  // Every emitted <span> is parked behind a letter-only placeholder so later\n  // passes cannot match inside the markup they already produced.\n  const parked: string[] = []\n  const park = (html: string) => {\n    const key = String(parked.length)\n      .split('')\n      .map((d) => String.fromCharCode(97 + Number(d)))\n      .join('')\n    parked.push(html)\n    return `\\u0000${key}\\u0000`\n  }\n\n  let out = escaped\n\n  // Strings (Emerald)\n  out = out.replace(/(['\"])(?:(?=(\\\\?))\\2.)*?\\1/g, (m) => park(`<span class=\"text-success font-normal\">${m}</span>`))\n\n  // SQL Functions (Sky / Blue)\n  out = out.replace(\n    /\\b(DATE_TRUNC|COUNT|DISTINCT|ROUND|AVG|SUM|MIN|MAX|COALESCE|CAST|CONCAT|NOW|CURRENT_TIMESTAMP)\\b/g,\n    (m) => park(`<span class=\"text-info font-semibold\">${m}</span>`),\n  )\n\n  // SQL Keywords (Tokenized)\n  out = out.replace(\n    /\\b(SELECT|FROM|WHERE|GROUP BY|ORDER BY|GROUP|ORDER|BY|DESC|ASC|AS|AND|OR|NOT|IN|ON|JOIN|LEFT|RIGHT|INNER|OUTER|LIMIT|HAVING|UNION|ALL|CASE|WHEN|THEN|ELSE|END|WITH)\\b/g,\n    (m) => park(`<span class=\"text-chart-1 font-semibold\">${m}</span>`),\n  )\n\n  // Numbers (Amber)\n  out = out.replace(/\\b(\\d+(\\.\\d+)?)\\b/g, (m) => park(`<span class=\"text-warning font-mono\">${m}</span>`))\n\n  // Restore every parked span\n  return out.replace(/\\u0000([a-j]+)\\u0000/g, (_, key: string) => {\n    const idx = Number(\n      key\n        .split('')\n        .map((c: string) => String(c.charCodeAt(0) - 97))\n        .join(''),\n    )\n    return parked[idx] ?? ''\n  })\n}\n\n// --- Actions ---\nfunction handleRunAll() {\n  if (isRunningAll.value) return\n  isRunningAll.value = true\n  isCellRunning.value = true\n\n  setTimeout(() => {\n    isCellRunning.value = false\n    isRunningAll.value = false\n    const now = new Date()\n    lastExecutionTimestamp.value = now.toTimeString().split(' ')[0]\n    executionTime.value = (1.18 + Math.random() * 0.15).toFixed(2) + 's'\n    lastSaved.value = 'Saved just now'\n  }, 620)\n}\n\nfunction handleRunCell() {\n  if (isCellRunning.value) return\n  isCellRunning.value = true\n\n  setTimeout(() => {\n    isCellRunning.value = false\n    const now = new Date()\n    lastExecutionTimestamp.value = now.toTimeString().split(' ')[0]\n    executionTime.value = (1.15 + Math.random() * 0.2).toFixed(2) + 's'\n  }, 480)\n}\n\nfunction handleCopySql() {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(sqlQuery)\n    copiedSql.value = true\n    setTimeout(() => {\n      copiedSql.value = false\n    }, 2000)\n  }\n}\n\nfunction handleExportCsv() {\n  const csvHeaders = 'signup_cohort,total_customers,avg_mrr,cohort_ltv\\n'\n  const csvRows = cohortResults\n    .map((r) => `${r.signup_cohort},${r.total_customers},${r.avg_mrr},${r.cohort_ltv}`)\n    .join('\\n')\n  const csvContent = csvHeaders + csvRows\n\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(csvContent)\n    copiedCsv.value = true\n    setTimeout(() => {\n      copiedCsv.value = false\n    }, 2000)\n  }\n}\n\nfunction handleAddCell() {\n  showExtraCell.value = true\n  activeCell.value = 'extra'\n}\n\nfunction handleRunExtraCell() {\n  extraCellRunning.value = true\n  setTimeout(() => {\n    extraCellRunning.value = false\n  }, 450)\n}\n\nfunction handleKeyDown(e: KeyboardEvent) {\n  if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n    e.preventDefault()\n    handleRunAll()\n  }\n}\n\nonMounted(() => {\n  if (typeof window !== 'undefined') {\n    window.addEventListener('keydown', handleKeyDown)\n  }\n})\n\nonUnmounted(() => {\n  if (typeof window !== 'undefined') {\n    window.removeEventListener('keydown', handleKeyDown)\n  }\n})\n</script>\n\n<template>\n  <div\n    data-slot=\"sql-query-notebook\"\n    :class=\"\n      cn('bg-background text-foreground border-border w-full overflow-hidden rounded-xl border shadow-xs', props.class)\n    \"\n  >\n    <!-- Top Notebook Header -->\n    <header class=\"border-border bg-card/70 border-b px-4 py-3.5 sm:px-6\">\n      <div class=\"flex flex-col gap-3.5 lg:flex-row lg:items-center lg:justify-between\">\n        <!-- Notebook Identity & Metadata -->\n        <div class=\"flex items-start gap-3\">\n          <div class=\"bg-primary/10 text-primary mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg\">\n            <FileCode2 class=\"size-4.5\" />\n          </div>\n          <div class=\"space-y-1\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <h1 class=\"text-foreground text-sm font-semibold tracking-tight sm:text-base\">\n                Customer Churn &amp; Cohort Analysis · Q3 2026\n              </h1>\n              <Badge variant=\"secondary\" class=\"font-mono text-xs\">v2.4</Badge>\n            </div>\n\n            <div class=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-xs\">\n              <div class=\"flex items-center gap-1.5\">\n                <span class=\"relative flex size-2\">\n                  <span class=\"bg-success absolute inline-flex h-full w-full rounded-full opacity-75\" />\n                  <span class=\"bg-success relative inline-flex size-2 rounded-full\" />\n                </span>\n                <span class=\"text-foreground/90 font-medium\">Snowflake Production Warehouse</span>\n                <span class=\"text-muted-foreground\">· Large Cluster</span>\n              </div>\n              <div class=\"flex items-center gap-1\">\n                <Clock class=\"size-3.5 opacity-70\" />\n                <span>{{ lastSaved }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Global Action Controls -->\n        <div class=\"flex flex-wrap items-center gap-2\">\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"h-8 gap-1.5 text-xs shadow-none\"\n            title=\"Append SQL query cell\"\n            @click=\"handleAddCell\"\n          >\n            <Plus class=\"size-3.5\" />\n            <span>Add SQL Cell</span>\n          </Button>\n\n          <Button size=\"sm\" class=\"h-8 gap-1.5 text-xs font-medium\" :disabled=\"isRunningAll\" @click=\"handleRunAll\">\n            <Loader2 v-if=\"isRunningAll\" class=\"size-3.5 animate-spin\" />\n            <Play v-else class=\"size-3.5 fill-current\" />\n            <span>{{ isRunningAll ? 'Running Notebook...' : 'Run All Cells' }}</span>\n            <kbd\n              class=\"border-primary-foreground/30 bg-primary-foreground/10 hidden rounded border px-1 font-mono text-xs sm:inline\"\n            >\n              ⌘↵\n            </kbd>\n          </Button>\n        </div>\n      </div>\n    </header>\n\n    <!-- Notebook Content Stream Container -->\n    <main class=\"space-y-4 p-4 sm:p-6\">\n      <!-- CELL 1: Markdown Documentation Cell -->\n      <Card\n        :class=\"\n          cn(\n            'border-border relative overflow-hidden shadow-none transition-colors',\n            activeCell === 'doc' ? 'ring-primary/20 ring-2' : '',\n          )\n        \"\n        @click=\"activeCell = 'doc'\"\n      >\n        <!-- Cell Left Focus Strip -->\n        <div\n          :class=\"\n            cn(\n              'absolute top-0 bottom-0 left-0 w-1 transition-colors',\n              activeCell === 'doc' ? 'bg-primary' : 'bg-transparent',\n            )\n          \"\n        />\n\n        <!-- Cell Top Toolbar -->\n        <div class=\"border-border bg-muted/30 flex items-center justify-between border-b px-4 py-2\">\n          <div class=\"flex items-center gap-2\">\n            <Badge variant=\"outline\" class=\"font-mono text-xs font-semibold uppercase\"> [MD] Doc </Badge>\n            <span class=\"text-muted-foreground text-xs\">Methodology &amp; Hypothesis</span>\n          </div>\n\n          <div class=\"flex items-center gap-2\">\n            <Button\n              variant=\"ghost\"\n              size=\"sm\"\n              class=\"text-muted-foreground hover:text-foreground h-6 px-2 text-xs\"\n              @click.stop=\"showMarkdownEditor = !showMarkdownEditor\"\n            >\n              <FileText class=\"mr-1 size-3\" />\n              {{ showMarkdownEditor ? 'Preview' : 'Source' }}\n            </Button>\n          </div>\n        </div>\n\n        <!-- Cell Content Body -->\n        <CardContent class=\"p-4 sm:p-5\">\n          <div v-if=\"showMarkdownEditor\" class=\"space-y-2\">\n            <textarea\n              v-model=\"markdownContent\"\n              rows=\"3\"\n              class=\"border-input bg-muted/20 text-foreground focus-visible:ring-ring w-full rounded-md border p-3 font-mono text-xs leading-relaxed outline-none focus-visible:ring-2\"\n            />\n          </div>\n\n          <div v-else class=\"space-y-3\">\n            <div class=\"border-border/60 border-b pb-2\">\n              <h2 class=\"text-foreground text-base font-semibold tracking-tight\">\n                Cohort Retention &amp; Expansion Query\n              </h2>\n              <p class=\"text-muted-foreground mt-1 text-xs leading-relaxed\">\n                Grouping by monthly signup cohort to evaluate customer lifetime value (LTV) trajectory and expansion MRR\n                across enterprise tiers. Filtered for 2026 activations from the primary subscriptions warehouse.\n              </p>\n            </div>\n\n            <!-- Metadata Parameter Badges -->\n            <div class=\"flex flex-wrap items-center gap-2 pt-0.5\">\n              <div\n                class=\"border-border bg-muted/40 text-muted-foreground flex flex-wrap items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n              >\n                <Database class=\"text-foreground/70 size-3.5\" />\n                <span>Source:</span>\n                <span class=\"text-foreground font-mono font-medium\">analytics.fct_subscriptions</span>\n              </div>\n              <div\n                class=\"border-border bg-muted/40 text-muted-foreground flex flex-wrap items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n              >\n                <Target class=\"text-warning size-3.5\" />\n                <span>Target Retention:</span>\n                <span class=\"text-foreground font-medium\">> 118% Net Expansion</span>\n              </div>\n              <div\n                class=\"border-border bg-muted/40 text-muted-foreground flex flex-wrap items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\"\n              >\n                <Layers class=\"text-foreground/70 size-3.5\" />\n                <span>Granularity:</span>\n                <span class=\"text-foreground font-mono font-medium\">DATE_TRUNC('month')</span>\n              </div>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- CELL 2: SQL Query Execution Cell -->\n      <Card\n        :class=\"\n          cn(\n            'border-border relative overflow-hidden shadow-none transition-colors',\n            activeCell === 'sql' ? 'ring-primary/20 ring-2' : '',\n          )\n        \"\n        @click=\"activeCell = 'sql'\"\n      >\n        <!-- Cell Left Focus Strip -->\n        <div\n          :class=\"\n            cn(\n              'absolute top-0 bottom-0 left-0 w-1 transition-colors',\n              activeCell === 'sql' ? 'bg-primary' : 'bg-transparent',\n            )\n          \"\n        />\n\n        <!-- Cell Toolbar -->\n        <div class=\"border-border bg-muted/30 flex flex-wrap items-center justify-between gap-2 border-b px-4 py-2\">\n          <!-- Left: Cell # & Status -->\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <Badge variant=\"default\" class=\"bg-primary text-primary-foreground font-mono text-xs font-semibold\">\n              [1] SQL\n            </Badge>\n            <Badge variant=\"secondary\" class=\"font-mono text-xs\"> Snowflake SQL </Badge>\n\n            <div\n              class=\"border-border/80 bg-background/80 flex items-center gap-1.5 rounded-md border px-2 py-0.5 text-xs\"\n            >\n              <span\n                :class=\"\n                  cn(\n                    'size-1.5 rounded-full transition-colors',\n                    isCellRunning ? 'bg-warning animate-pulse' : 'bg-success',\n                  )\n                \"\n              />\n              <span class=\"text-muted-foreground font-mono\">\n                {{ isCellRunning ? 'Executing query...' : `${executionTime} · ${rowCount.toLocaleString()} rows` }}\n              </span>\n            </div>\n          </div>\n\n          <!-- Right: Cell Actions -->\n          <div class=\"flex items-center gap-1.5\">\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"h-7 gap-1 px-2.5 text-xs shadow-none\"\n              title=\"Copy SQL Query\"\n              @click.stop=\"handleCopySql\"\n            >\n              <Check v-if=\"copiedSql\" class=\"text-success size-3\" />\n              <Copy v-else class=\"size-3\" />\n              <span>{{ copiedSql ? 'Copied' : 'Copy SQL' }}</span>\n            </Button>\n\n            <Button\n              size=\"sm\"\n              class=\"h-7 gap-1 px-2.5 text-xs font-medium\"\n              :disabled=\"isCellRunning\"\n              @click.stop=\"handleRunCell\"\n            >\n              <Loader2 v-if=\"isCellRunning\" class=\"size-3 animate-spin\" />\n              <Play v-else class=\"size-3 fill-current\" />\n              <span>Run Cell</span>\n              <kbd\n                class=\"border-primary-foreground/30 bg-primary-foreground/10 ml-0.5 rounded border px-1 font-mono text-xs\"\n              >\n                ^↵\n              </kbd>\n            </Button>\n          </div>\n        </div>\n\n        <!-- Code Editor Body (Dark Theme) -->\n        <div\n          class=\"relative flex overflow-x-auto bg-zinc-950 py-3 font-mono text-xs leading-relaxed text-zinc-100 select-text\"\n        >\n          <!-- Line Numbers Gutter -->\n          <div class=\"flex flex-col border-r border-zinc-800/80 px-3 text-right text-zinc-600 select-none\">\n            <span\n              v-for=\"(_, idx) in sqlLines\"\n              :key=\"idx\"\n              :class=\"\n                cn('h-5 leading-5 transition-colors', hoveredSqlLine === idx + 1 ? 'font-semibold text-zinc-300' : '')\n              \"\n            >\n              {{ idx + 1 }}\n            </span>\n          </div>\n\n          <!-- Code Lines with Syntax Colors -->\n          <div class=\"flex-1 px-4 whitespace-pre\">\n            <div\n              v-for=\"(line, idx) in sqlLines\"\n              :key=\"idx\"\n              :class=\"\n                cn(\n                  'group flex h-5 items-center rounded-xs px-1 leading-5 transition-colors',\n                  hoveredSqlLine === idx + 1 ? 'bg-zinc-800/40' : '',\n                )\n              \"\n              @mouseenter=\"hoveredSqlLine = idx + 1\"\n              @mouseleave=\"hoveredSqlLine = null\"\n            >\n              <span v-html=\"highlightSqlLine(line)\" />\n            </div>\n          </div>\n        </div>\n\n        <!-- Tabular Query Results & Output Grid -->\n        <div class=\"border-border border-t\">\n          <!-- Results Header & Actions Bar -->\n          <div class=\"border-border bg-card flex flex-wrap items-center justify-between gap-2 border-b px-4 py-2\">\n            <div class=\"flex items-center gap-2\">\n              <div class=\"flex items-center gap-1.5\">\n                <Table2 class=\"text-primary size-4\" />\n                <span class=\"text-foreground text-xs font-semibold\">Query Output</span>\n              </div>\n              <Badge variant=\"secondary\" class=\"font-mono text-xs\"> 4 cohorts · 14,290 records </Badge>\n              <span class=\"text-muted-foreground hidden font-mono text-xs sm:inline\">\n                Last run: {{ lastExecutionTimestamp }}\n              </span>\n            </div>\n\n            <!-- Action Controls: Tabs & Export -->\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <div class=\"border-border bg-muted/40 flex items-center rounded-lg border p-0.5\">\n                <button\n                  type=\"button\"\n                  :class=\"\n                    cn(\n                      'flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                      activeResultTab === 'table'\n                        ? 'bg-background text-foreground shadow-xs'\n                        : 'text-muted-foreground hover:text-foreground',\n                    )\n                  \"\n                  @click=\"activeResultTab = 'table'\"\n                >\n                  <Table2 class=\"size-3.5\" />\n                  <span>Table</span>\n                </button>\n                <button\n                  type=\"button\"\n                  :class=\"\n                    cn(\n                      'flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                      activeResultTab === 'chart'\n                        ? 'bg-background text-foreground shadow-xs'\n                        : 'text-muted-foreground hover:text-foreground',\n                    )\n                  \"\n                  @click=\"activeResultTab = 'chart'\"\n                >\n                  <BarChart3 class=\"size-3.5\" />\n                  <span>Chart</span>\n                </button>\n              </div>\n\n              <Button\n                aria-label=\"Download attachment\"\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"h-7 gap-1 px-2.5 text-xs shadow-none\"\n                @click=\"handleExportCsv\"\n              >\n                <Check v-if=\"copiedCsv\" class=\"text-success size-3\" />\n                <Download v-else class=\"size-3\" />\n                <span>{{ copiedCsv ? 'Copied CSV!' : 'Export CSV' }}</span>\n              </Button>\n\n              <Button\n                v-if=\"activeResultTab === 'table'\"\n                variant=\"secondary\"\n                size=\"sm\"\n                class=\"h-7 gap-1 px-2.5 text-xs\"\n                @click=\"activeResultTab = 'chart'\"\n              >\n                <BarChart3 class=\"size-3\" />\n                <span>Visualize as Chart</span>\n              </Button>\n            </div>\n          </div>\n\n          <!-- View 1: Tabular Results Grid -->\n          <div v-if=\"activeResultTab === 'table'\" class=\"overflow-x-auto\">\n            <Table>\n              <TableHeader>\n                <TableRow class=\"bg-muted/40 hover:bg-muted/40\">\n                  <TableHead class=\"text-xs font-semibold\">\n                    <div class=\"flex items-center gap-1.5\">\n                      <span>signup_cohort</span>\n                      <Badge variant=\"outline\" class=\"text-muted-foreground py-0 text-xs font-normal\">DATE</Badge>\n                    </div>\n                  </TableHead>\n                  <TableHead class=\"text-right text-xs font-semibold\">\n                    <div class=\"flex items-center justify-end gap-1.5\">\n                      <span>total_customers</span>\n                      <Badge variant=\"outline\" class=\"text-muted-foreground py-0 text-xs font-normal\">INT</Badge>\n                    </div>\n                  </TableHead>\n                  <TableHead class=\"text-right text-xs font-semibold\">\n                    <div class=\"flex items-center justify-end gap-1.5\">\n                      <span>avg_mrr</span>\n                      <Badge variant=\"outline\" class=\"text-muted-foreground py-0 text-xs font-normal\">NUMERIC</Badge>\n                    </div>\n                  </TableHead>\n                  <TableHead class=\"text-right text-xs font-semibold\">\n                    <div class=\"flex items-center justify-end gap-1.5\">\n                      <span>cohort_ltv</span>\n                      <Badge variant=\"outline\" class=\"text-muted-foreground py-0 text-xs font-normal\">CURRENCY</Badge>\n                    </div>\n                  </TableHead>\n                  <TableHead class=\"text-right text-xs font-semibold\">\n                    <span>expansion_velocity</span>\n                  </TableHead>\n                </TableRow>\n              </TableHeader>\n              <TableBody>\n                <TableRow\n                  v-for=\"(row, idx) in cohortResults\"\n                  :key=\"row.signup_cohort\"\n                  :class=\"cn('text-xs transition-colors', idx % 2 === 1 ? 'bg-muted/15' : '')\"\n                >\n                  <TableCell class=\"font-mono font-medium\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-muted-foreground font-mono text-xs\">{{ idx + 1 }}</span>\n                      <span class=\"text-foreground font-semibold\">{{ row.signup_cohort }}</span>\n                      <Badge variant=\"secondary\" class=\"font-sans text-xs font-normal\">\n                        {{ row.cohort_label }}\n                      </Badge>\n                    </div>\n                  </TableCell>\n                  <TableCell class=\"text-foreground text-right font-mono font-medium tabular-nums\">\n                    {{ row.total_customers.toLocaleString() }}\n                  </TableCell>\n                  <TableCell class=\"text-foreground text-right font-mono tabular-nums\">\n                    ${{ row.avg_mrr.toFixed(2) }}\n                  </TableCell>\n                  <TableCell class=\"text-foreground text-right font-mono font-semibold tabular-nums\">\n                    ${{\n                      row.cohort_ltv.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })\n                    }}\n                  </TableCell>\n                  <TableCell class=\"text-right\">\n                    <span class=\"bg-success/10 text-success rounded-md px-2 py-0.5 font-mono text-xs font-semibold\">\n                      {{ row.expansion_rate }}\n                    </span>\n                  </TableCell>\n                </TableRow>\n              </TableBody>\n            </Table>\n\n            <!-- Table Summary Footer -->\n            <div\n              class=\"border-border bg-muted/20 flex flex-wrap items-center justify-between gap-3 border-t px-4 py-2.5 text-xs\"\n            >\n              <span class=\"text-muted-foreground font-mono\"> 4 of 4 cohort partitions loaded · 0 errors </span>\n              <div class=\"flex flex-wrap items-center gap-4\">\n                <span class=\"text-muted-foreground\">\n                  Total Active Accounts:\n                  <strong class=\"text-foreground font-mono tabular-nums\">{{\n                    totalCustomersSum.toLocaleString()\n                  }}</strong>\n                </span>\n                <span class=\"text-muted-foreground\">\n                  Cumulative Cohort LTV:\n                  <strong class=\"text-foreground font-mono tabular-nums\"\n                    >${{ totalLtvSum.toLocaleString('en-US', { minimumFractionDigits: 2 }) }}</strong\n                  >\n                </span>\n              </div>\n            </div>\n          </div>\n\n          <!-- View 2: Chart Visualization -->\n          <div v-else class=\"space-y-5 p-4 sm:p-6\">\n            <div class=\"flex flex-col justify-between gap-2 sm:flex-row sm:items-center\">\n              <div>\n                <h3 class=\"text-foreground text-sm font-semibold\">Cohort Lifetime Value Trajectory</h3>\n                <p class=\"text-muted-foreground text-xs\">\n                  Progression of cumulative customer LTV and expansion momentum by activation month.\n                </p>\n              </div>\n              <Badge variant=\"outline\" class=\"font-mono text-xs\"> Snowflake Snowpark Analytics </Badge>\n            </div>\n\n            <!-- Bar Chart Distribution -->\n            <div class=\"space-y-3.5\">\n              <div\n                v-for=\"item in cohortResults\"\n                :key=\"item.signup_cohort\"\n                class=\"border-border/60 bg-card space-y-1.5 rounded-lg border p-3 shadow-none\"\n              >\n                <div class=\"flex items-center justify-between text-xs\">\n                  <div class=\"flex items-center gap-2\">\n                    <span class=\"font-mono font-semibold\">{{ item.cohort_label }}</span>\n                    <span class=\"text-muted-foreground font-mono\">({{ item.signup_cohort }})</span>\n                    <Badge variant=\"secondary\" class=\"font-mono text-xs\">\n                      {{ item.total_customers.toLocaleString() }} customers\n                    </Badge>\n                  </div>\n                  <div class=\"flex items-center gap-3\">\n                    <span class=\"text-muted-foreground font-mono\">Avg MRR: ${{ item.avg_mrr.toFixed(2) }}</span>\n                    <span class=\"text-foreground font-mono font-bold tabular-nums\">\n                      ${{ item.cohort_ltv.toLocaleString('en-US', { minimumFractionDigits: 2 }) }}\n                    </span>\n                  </div>\n                </div>\n\n                <!-- Visual Bar Fill -->\n                <div class=\"bg-muted/60 relative h-3.5 w-full overflow-hidden rounded-full\">\n                  <div\n                    class=\"bg-primary absolute top-0 bottom-0 left-0 rounded-full transition-colors duration-500\"\n                    :style=\"{ width: `${(item.cohort_ltv / maxCohortLtv) * 100}%` }\"\n                  />\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </Card>\n\n      <!-- CELL 3: Downstream Python / Added Cell (Toggled or Interactive) -->\n      <Card\n        v-if=\"showExtraCell\"\n        :class=\"\n          cn(\n            'border-border relative overflow-hidden shadow-none transition-colors',\n            activeCell === 'extra' ? 'ring-primary/20 ring-2' : '',\n          )\n        \"\n        @click=\"activeCell = 'extra'\"\n      >\n        <!-- Cell Left Focus Strip -->\n        <div\n          :class=\"\n            cn(\n              'absolute top-0 bottom-0 left-0 w-1 transition-colors',\n              activeCell === 'extra' ? 'bg-primary' : 'bg-transparent',\n            )\n          \"\n        />\n\n        <div class=\"border-border bg-muted/30 flex items-center justify-between border-b px-4 py-2\">\n          <div class=\"flex items-center gap-2\">\n            <Badge variant=\"secondary\" class=\"font-mono text-xs font-semibold\"> [2] Python </Badge>\n            <span class=\"text-muted-foreground text-xs\">Downstream Snowpark Dataframe</span>\n          </div>\n\n          <div class=\"flex items-center gap-1.5\">\n            <Button\n              size=\"sm\"\n              class=\"h-7 gap-1 px-2.5 text-xs\"\n              :disabled=\"extraCellRunning\"\n              @click.stop=\"handleRunExtraCell\"\n            >\n              <Loader2 v-if=\"extraCellRunning\" class=\"size-3 animate-spin\" />\n              <Play v-else class=\"size-3 fill-current\" />\n              <span>Run</span>\n            </Button>\n            <Button\n              variant=\"ghost\"\n              size=\"sm\"\n              class=\"text-muted-foreground hover:text-destructive h-7 px-2\"\n              aria-label=\"Delete query cell\"\n              @click.stop=\"showExtraCell = false\"\n            >\n              <Trash2 class=\"size-3\" />\n            </Button>\n          </div>\n        </div>\n\n        <div class=\"bg-zinc-950 p-4 font-mono text-xs leading-relaxed text-zinc-300\">\n          <pre\n            class=\"text-zinc-400\"\n          ><code><span class=\"text-chart-1\">import</span> snowflake.snowpark <span class=\"text-chart-1\">as</span> snowpark\n<span class=\"text-chart-1\">import</span> polars <span class=\"text-chart-1\">as</span> pl\n\n<span class=\"text-zinc-500\"># Read Cell [1] tabular results and compute hazard rate</span>\ndf = cell_1_results.to_pandas()\ndf[<span class=\"text-success\">'expansion_velocity'</span>] = df[<span class=\"text-success\">'cohort_ltv'</span>] / df[<span class=\"text-success\">'total_customers'</span>]\n<span class=\"text-info\">print</span>(f<span class=\"text-success\">\"Average cohort customer value: \\${df['expansion_velocity'].mean():.2f}\"</span>)</code></pre>\n        </div>\n\n        <div class=\"border-border bg-muted/20 border-t p-3 font-mono text-xs\">\n          <div class=\"text-muted-foreground flex items-center gap-2\">\n            <Terminal class=\"text-success size-3.5\" />\n            <span>Output:</span>\n            <span class=\"text-success font-semibold\">Average cohort customer value: $292.77</span>\n          </div>\n        </div>\n      </Card>\n    </main>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/SqlQueryNotebook.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/table.json"
  ],
  "description": "Hex, Deepnote, and Jupyter style SQL analytical query notebook with documentation cells, executable Snowflake SQL editor with syntax coloring, live tabular results grid, CSV export, and chart visualization.",
  "categories": [
    "devops",
    "app"
  ]
}