{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "dashboard-layout",
  "title": "Dashboard Layout",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/dashboard-layout/dashboard-layout.component.ts",
      "content": "// Full dashboard shell — collapsible sidebar + sticky topbar (sidebar trigger, breadcrumb,\n// command palette affordance, theme switch, notifications) + main content projection.\n// Drop it around a page: `<ui-dashboard-layout>page</ui-dashboard-layout>`.\n//\n// NOTE (Angular port): mirrors the React port 1:1 — the Vue original composes the\n// `sidebar-02`, `command-palette`, and `notifications-popover` blocks, which don't exist in\n// the Angular registry. Until they're ported, the sidebar body is a minimal inline nav and\n// notifications is a plain Bell button. Swap them for the dedicated blocks once available.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { Bell, LayoutDashboard, LucideAngularModule, Settings, Users } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport {\n  UiBreadcrumbComponent,\n  UiBreadcrumbItemComponent,\n  UiBreadcrumbLinkComponent,\n  UiBreadcrumbListComponent,\n  UiBreadcrumbPageComponent,\n  UiBreadcrumbSeparatorComponent,\n} from '@/ui/breadcrumb/breadcrumb.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiSidebarComponent,\n  UiSidebarContentComponent,\n  UiSidebarGroupComponent,\n  UiSidebarGroupContentComponent,\n  UiSidebarHeaderComponent,\n  UiSidebarInsetComponent,\n  UiSidebarMenuButtonComponent,\n  UiSidebarMenuComponent,\n  UiSidebarMenuItemComponent,\n  UiSidebarProviderComponent,\n  UiSidebarRailComponent,\n  UiSidebarTriggerComponent,\n} from '@/ui/sidebar/sidebar.component'\nimport { UiThemeSwitchComponent } from '@/ui/theme-switch/theme-switch.component'\n\nexport interface DashboardCrumb {\n  label: string\n  href?: string\n}\n\nconst NAV = [\n  { label: 'Dashboard', icon: LayoutDashboard },\n  { label: 'People', icon: Users },\n  { label: 'Settings', icon: Settings },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-dashboard-layout, [ui-dashboard-layout]',\n  standalone: true,\n  // React renders the provider itself: the host stays out of layout and `class` goes to the provider.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBreadcrumbComponent,\n    UiBreadcrumbItemComponent,\n    UiBreadcrumbLinkComponent,\n    UiBreadcrumbListComponent,\n    UiBreadcrumbPageComponent,\n    UiBreadcrumbSeparatorComponent,\n    UiButtonComponent,\n    UiSeparatorComponent,\n    UiSidebarComponent,\n    UiSidebarContentComponent,\n    UiSidebarGroupComponent,\n    UiSidebarGroupContentComponent,\n    UiSidebarHeaderComponent,\n    UiSidebarInsetComponent,\n    UiSidebarMenuButtonComponent,\n    UiSidebarMenuComponent,\n    UiSidebarMenuItemComponent,\n    UiSidebarProviderComponent,\n    UiSidebarRailComponent,\n    UiSidebarTriggerComponent,\n    UiThemeSwitchComponent,\n  ],\n  template: `\n    <!-- UiSidebarProvider hardcodes data-slot=\"sidebar-wrapper\" on its host, so the block's\n         data-slot lives on this root (matches React's provider-level slot for consumers). -->\n    <div data-slot=\"dashboard-layout\" [class]=\"rootClass\">\n      <ui-sidebar-provider [class]=\"rootClass\">\n        <a\n          href=\"#main-content\"\n          class=\"bg-background text-foreground ring-ring sr-only z-50 rounded-md text-sm font-medium shadow-md ring-2 focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:px-3 focus:py-2\"\n          >Skip to content</a\n        >\n        <ui-sidebar collapsible=\"icon\">\n          <ui-sidebar-header />\n          <ui-sidebar-content>\n            <ui-sidebar-group>\n              <ui-sidebar-group-content>\n                <ui-sidebar-menu>\n                  @for (item of nav; track item.label) {\n                    <ui-sidebar-menu-item>\n                      <ui-sidebar-menu-button [tooltip]=\"item.label\">\n                        <lucide-icon [img]=\"item.icon\" />\n                        <span>{{ item.label }}</span>\n                      </ui-sidebar-menu-button>\n                    </ui-sidebar-menu-item>\n                  }\n                </ui-sidebar-menu>\n              </ui-sidebar-group-content>\n            </ui-sidebar-group>\n          </ui-sidebar-content>\n          <ui-sidebar-rail />\n        </ui-sidebar>\n        <ui-sidebar-inset>\n          <header\n            class=\"bg-background/80 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-30 flex h-14 w-full shrink-0 items-center justify-between border-b px-4 backdrop-blur-xl transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12\"\n          >\n            <div class=\"flex items-center gap-2\">\n              <ui-sidebar-trigger class=\"-ml-1\" />\n              <ui-separator orientation=\"vertical\" class=\"mr-2 h-4\" />\n              <ui-breadcrumb>\n                <ui-breadcrumb-list>\n                  @for (crumb of crumbs; track crumb.label; let i = $index; let last = $last) {\n                    <ui-breadcrumb-item [class]=\"i === 0 ? 'hidden md:block' : ''\">\n                      @if (crumb.href && !last) {\n                        <ui-breadcrumb-link\n                          [href]=\"crumb.href\"\n                          class=\"text-muted-foreground/70 hover:text-foreground transition-colors\"\n                        >\n                          {{ crumb.label }}\n                        </ui-breadcrumb-link>\n                      } @else {\n                        <ui-breadcrumb-page class=\"font-medium\">{{ crumb.label }}</ui-breadcrumb-page>\n                      }\n                    </ui-breadcrumb-item>\n                    @if (!last) {\n                      <ui-breadcrumb-separator [class]=\"i === 0 ? 'hidden md:block' : ''\" />\n                    }\n                  }\n                </ui-breadcrumb-list>\n              </ui-breadcrumb>\n            </div>\n            <div class=\"flex items-center gap-1 px-2 sm:gap-3\">\n              <div class=\"flex items-center gap-0.5\">\n                <ui-theme-switch variant=\"icon-only\" />\n                <button\n                  ui-button\n                  variant=\"ghost\"\n                  size=\"icon\"\n                  class=\"text-muted-foreground hover:text-foreground relative size-8 rounded-lg\"\n                  aria-label=\"Notifications\"\n                >\n                  <lucide-icon [img]=\"Bell\" class=\"size-4\" />\n                </button>\n                <!-- ProfileMenu removed from header: the sidebar's NavUser\n                   footer already owns the profile/account affordance. The\n                   block still accepts a user input so consumers can wire\n                   it into the sidebar or a custom slot. -->\n              </div>\n            </div>\n          </header>\n          <main id=\"main-content\" tabindex=\"-1\" class=\"flex flex-1 flex-col px-4 pt-4 pb-4 outline-none lg:px-6 lg:pt-6 lg:pb-6\">\n            <ng-content />\n          </main>\n        </ui-sidebar-inset>\n      </ui-sidebar-provider>\n    </div>\n  `,\n})\nexport class UiDashboardLayoutComponent {\n  protected readonly Bell = Bell\n  protected readonly nav = NAV.map((n) => ({ ...n }))\n\n  @Input() breadcrumbs: DashboardCrumb[] = [{ label: 'Dashboard' }]\n  @Input() user: { name: string; email: string; avatar?: string } = { name: 'Alex Morgan', email: 'alex@example.com' }\n  @Input('class') className?: string\n\n  get crumbs(): DashboardCrumb[] {\n    return this.breadcrumbs?.length ? this.breadcrumbs : [{ label: 'Dashboard' }]\n  }\n\n  get rootClass(): string {\n    return cn(this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/dashboard-layout/dashboard-layout.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/dashboard-layout/index.ts",
      "content": "export { UiDashboardLayoutComponent, type DashboardCrumb } from './dashboard-layout.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/dashboard-layout/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/theme-switch.json",
    "https://uipkge.dev/r/angular/sidebar.json",
    "https://uipkge.dev/r/angular/breadcrumb.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/separator.json"
  ],
  "description": "Full dashboard shell — collapsible sidebar + sticky topbar (sidebar trigger, breadcrumb, theme switch, notifications) + main content projection. Drop it around a page: `<ui-dashboard-layout>page</ui-dashboard-layout>`.",
  "categories": [
    "layout",
    "dashboard"
  ]
}