{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "comparison-migration-path",
  "title": "Comparison — Migration Path",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/comparison-migration-path/comparison-migration-path.component.ts",
      "content": "// Migration-focused comparison pairing what a team keeps, what changes, and what is\n// retired when moving from an existing tool, with an effort estimate per row.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { ArrowRight, Check, LucideAngularModule, Minus, RefreshCw } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type MigrationVerdict = 'keep' | 'change' | 'retire'\n\nexport interface MigrationPathRow {\n  area: string\n  verdict: MigrationVerdict\n  detail: string\n  effort: string\n}\n\n// verdict drives the icon and tone, so rows stay declarative and a new row\n// cannot forget to style itself.\nconst defaultRows: MigrationPathRow[] = [\n  {\n    area: 'Warehouse and models',\n    verdict: 'keep',\n    detail: 'Untouched. We read from them, nothing is rewritten.',\n    effort: 'None',\n  },\n  {\n    area: 'dbt project',\n    verdict: 'keep',\n    detail: 'Imported as metric sources; your DAG keeps running.',\n    effort: 'Half a day',\n  },\n  {\n    area: 'Dashboard layouts',\n    verdict: 'change',\n    detail: 'Rebuilt against certified metrics, usually faster than the original.',\n    effort: '1–2 weeks',\n  },\n  {\n    area: 'Metric formulas',\n    verdict: 'change',\n    detail: 'Moved from dashboard config into versioned files.',\n    effort: '1 week',\n  },\n  {\n    area: 'Per-dashboard permissions',\n    verdict: 'retire',\n    detail: 'Replaced by row-level scope from your IdP.',\n    effort: 'None',\n  },\n  {\n    area: 'Bespoke extract jobs',\n    verdict: 'retire',\n    detail: 'Deleted once the metrics they fed are certified.',\n    effort: 'None',\n  },\n]\n\nconst verdictMeta: Record<MigrationVerdict, { label: string; class: string }> = {\n  keep: { label: 'Keep', class: 'text-success' },\n  change: { label: 'Change', class: 'text-muted-foreground' },\n  retire: { label: 'Retire', class: 'text-muted-foreground/60' },\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-comparison-migration-path, [ui-comparison-migration-path]',\n  standalone: true,\n  // React renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <section data-slot=\"comparison-migration-path\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-5xl px-6 py-20 lg:py-28\">\n        <div class=\"max-w-2xl\">\n          <span ui-badge variant=\"secondary\">Migration</span>\n          <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">What actually changes</h2>\n          <p class=\"text-muted-foreground mt-3 text-lg\">\n            Most of the stack stays exactly where it is. The effort column is measured from real rollouts.\n          </p>\n        </div>\n\n        <div ui-card class=\"mt-10\">\n          <div ui-card-content class=\"p-0\">\n            <table ui-table>\n              <thead ui-table-header>\n                <tr ui-table-row>\n                  <th ui-table-head>Area</th>\n                  <th ui-table-head class=\"w-28\">Verdict</th>\n                  <th ui-table-head>What happens</th>\n                  <th ui-table-head class=\"w-32 text-right\">Effort</th>\n                </tr>\n              </thead>\n              <tbody ui-table-body>\n                @for (row of rows; track row.area) {\n                  <tr ui-table-row>\n                    <td ui-table-cell class=\"font-medium\">{{ row.area }}</td>\n                    <td ui-table-cell>\n                      <span [class]=\"'inline-flex items-center gap-1.5 text-xs ' + verdictClass(row.verdict)\">\n                        @if (row.verdict === 'keep') {\n                          <lucide-icon [img]=\"Check\" class=\"size-3.5\" aria-hidden=\"true\" />\n                        } @else if (row.verdict === 'change') {\n                          <lucide-icon [img]=\"RefreshCw\" class=\"size-3.5\" aria-hidden=\"true\" />\n                        } @else {\n                          <lucide-icon [img]=\"Minus\" class=\"size-3.5\" aria-hidden=\"true\" />\n                        }\n                        {{ verdictLabel(row.verdict) }}\n                      </span>\n                    </td>\n                    <td ui-table-cell class=\"text-muted-foreground text-sm\">{{ row.detail }}</td>\n                    <td ui-table-cell class=\"text-right font-mono text-xs\">{{ row.effort }}</td>\n                  </tr>\n                }\n              </tbody>\n            </table>\n\n            <ui-separator />\n            <p class=\"text-muted-foreground px-6 py-4 text-xs leading-relaxed\">\n              Effort assumes one engineer and one analyst part-time. Teams with more than about 200 existing dashboards\n              usually stage the rebuild by department rather than doing it in one pass.\n            </p>\n          </div>\n        </div>\n\n        <button ui-button class=\"mt-6\">\n          Get a migration estimate\n          <lucide-icon [img]=\"ArrowRight\" class=\"ml-2 size-4\" aria-hidden=\"true\" />\n        </button>\n      </div>\n    </section>\n  `,\n})\nexport class UiComparisonMigrationPathComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly Check = Check\n  protected readonly Minus = Minus\n  protected readonly RefreshCw = RefreshCw\n\n  @Input() rows: MigrationPathRow[] = defaultRows\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n\n  verdictLabel(v: MigrationVerdict): string {\n    return verdictMeta[v].label\n  }\n\n  verdictClass(v: MigrationVerdict): string {\n    return verdictMeta[v].class\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/comparison-migration-path/comparison-migration-path.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/comparison-migration-path/index.ts",
      "content": "export {\n  UiComparisonMigrationPathComponent,\n  type MigrationVerdict,\n  type MigrationPathRow,\n} from './comparison-migration-path.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/comparison-migration-path/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Migration-focused comparison pairing what a team keeps, what changes, and what is retired when moving from an existing tool, with an effort estimate per row.",
  "categories": [
    "marketing"
  ]
}