{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "demo-guided-tour",
  "title": "Demo — Guided Tour",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/demo-guided-tour/demo-guided-tour.component.ts",
      "content": "// Step-through product tour where next and previous move a highlight across a mocked\n// interface, with a step counter, progress bar and a skip control. Port of the React\n// block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport { ArrowLeft, ArrowRight, LucideAngularModule } 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 { UiProgressComponent } from '@/ui/progress/progress.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\n\nexport interface GuidedTourStep {\n  target: string\n  title: string\n  body: string\n}\n\nexport interface GuidedTourPanel {\n  id: string\n  label: string\n  rows: string[]\n}\n\n// Each step names the panel it highlights, so the copy and the mock cannot\n// drift apart when someone reorders the tour.\nexport const GUIDED_TOUR_STEPS: GuidedTourStep[] = [\n  {\n    target: 'catalog',\n    title: 'Start from the catalogue',\n    body: 'Every table we mirrored, with its freshness. Pick what the metric reads from.',\n  },\n  {\n    target: 'definition',\n    title: 'Write the definition',\n    body: 'The window, the owner, and the joins. This is the file that opens a pull request.',\n  },\n  {\n    target: 'consumers',\n    title: 'See who it affects',\n    body: 'Before publishing, the consumer list shows every dashboard and export that resolves it.',\n  },\n  {\n    target: 'history',\n    title: 'Check the history',\n    body: 'Every prior version with its reviewer, and a one-click revert to any of them.',\n  },\n]\n\nexport const GUIDED_TOUR_PANELS: GuidedTourPanel[] = [\n  { id: 'catalog', label: 'Catalogue', rows: ['warehouse.orders', 'warehouse.refunds', 'warehouse.fx_rates'] },\n  {\n    id: 'definition',\n    label: 'revenue_net.yml',\n    rows: ['window: trailing_28d', 'owner: finance-analytics', 'joins: refunds, fx'],\n  },\n  { id: 'consumers', label: 'Consumers', rows: ['Exec summary', 'Finance close pack', 'Partner API'] },\n  {\n    id: 'history',\n    label: 'History',\n    rows: ['v128 · 14 Feb · A. Reyes', 'v127 · 02 Jan · A. Reyes', 'v126 · 11 Dec · M. Ellery'],\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-demo-guided-tour, [ui-demo-guided-tour]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"demo-guided-tour\"',\n    '[class]': 'hostClass',\n  },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiProgressComponent,\n    UiSeparatorComponent,\n  ],\n  template: `\n    <div class=\"mx-auto max-w-5xl px-6 py-20 lg:py-28\">\n      <div class=\"flex flex-wrap items-end justify-between gap-6\">\n        <div class=\"max-w-xl\">\n          <span ui-badge variant=\"secondary\">Guided tour</span>\n          <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Four screens, ninety seconds</h2>\n        </div>\n        <button ui-button variant=\"ghost\" size=\"sm\">Skip and just read the docs</button>\n      </div>\n\n      <div class=\"mt-10 grid gap-6 lg:grid-cols-[1fr_1.3fr] lg:gap-10\">\n        <div>\n          <div ui-progress [value]=\"progress()\" class=\"h-1\" aria-label=\"Tour progress\"></div>\n          <p class=\"text-muted-foreground mt-3 font-mono text-xs\">Step {{ index() + 1 }} of {{ steps.length }}</p>\n\n          <!-- min-h holds the copy block at its tallest so the controls do not\n               move between steps. -->\n          <div class=\"min-h-[7rem]\">\n            <h3 class=\"mt-4 text-xl font-semibold tracking-tight\">{{ current().title }}</h3>\n            <p class=\"text-muted-foreground mt-2 leading-relaxed\">{{ current().body }}</p>\n          </div>\n\n          <div class=\"mt-5 flex items-center gap-2\">\n            <button ui-button variant=\"outline\" size=\"sm\" [disabled]=\"index() === 0\" (click)=\"back()\">\n              <lucide-icon [img]=\"ArrowLeft\" class=\"mr-1.5 size-3.5\" />\n              Back\n            </button>\n            <button ui-button size=\"sm\" [disabled]=\"index() === steps.length - 1\" (click)=\"next()\">\n              Next\n              <lucide-icon [img]=\"ArrowRight\" class=\"ml-1.5 size-3.5\" />\n            </button>\n          </div>\n        </div>\n\n        <div ui-card>\n          <div ui-card-content class=\"space-y-2 p-4\">\n            @for (panel of panels; track panel.id) {\n              <div class=\"rounded-lg border p-3 transition-colors\" [class]=\"panelClass(panel.id)\">\n                <div class=\"flex items-center justify-between gap-3\">\n                  <p class=\"font-mono text-xs font-medium\">{{ panel.label }}</p>\n                  @if (panel.id === current().target) {\n                    <span ui-badge variant=\"secondary\">This step</span>\n                  }\n                </div>\n                <ui-separator class=\"my-2\" />\n                <ul class=\"space-y-1\">\n                  @for (row of panel.rows; track row) {\n                    <li class=\"text-muted-foreground truncate font-mono text-xs\">\n                      {{ row }}\n                    </li>\n                  }\n                </ul>\n              </div>\n            }\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiDemoGuidedTourComponent {\n  protected readonly ArrowLeft = ArrowLeft\n  protected readonly ArrowRight = ArrowRight\n\n  @Input('class') className?: string\n\n  readonly steps = GUIDED_TOUR_STEPS\n  readonly panels = GUIDED_TOUR_PANELS\n\n  readonly index = signal(0)\n  readonly current = computed(() => this.steps[this.index()] ?? this.steps[0]!)\n  readonly progress = computed(() => ((this.index() + 1) / this.steps.length) * 100)\n\n  get hostClass(): string {\n    return cn('bg-background block w-full', this.className)\n  }\n\n  panelClass(id: string): string {\n    return cn(id === this.current().target ? 'border-primary bg-muted/40' : 'border-border bg-background opacity-60')\n  }\n\n  next(): void {\n    this.index.update((i) => Math.min(i + 1, this.steps.length - 1))\n  }\n\n  back(): void {\n    this.index.update((i) => Math.max(i - 1, 0))\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/demo-guided-tour/demo-guided-tour.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/demo-guided-tour/index.ts",
      "content": "export {\n  UiDemoGuidedTourComponent,\n  GUIDED_TOUR_STEPS,\n  GUIDED_TOUR_PANELS,\n  type GuidedTourStep,\n  type GuidedTourPanel,\n} from './demo-guided-tour.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/demo-guided-tour/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/progress.json",
    "https://uipkge.dev/r/angular/separator.json"
  ],
  "description": "Step-through product tour where next and previous move a highlight across a mocked interface, with a step counter and a skip control.",
  "categories": [
    "marketing"
  ]
}