{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "dashboard-layout",
  "title": "Dashboard Layout",
  "type": "registry:block",
  "description": "Full dashboard shell — collapsible sidebar + sticky topbar (sidebar trigger, breadcrumb, theme switch, notifications) + main content children. Drop it around a page: `<DashboardLayout>{page}</DashboardLayout>`.",
  "categories": [
    "layout",
    "dashboard"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/dashboard-layout/dashboard-layout.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport { Bell, LayoutDashboard, Settings, Users } from 'lucide'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\nimport { icon } from '../../lib/icon'\n// Side-effect imports: register the composed elements for standalone use\n// (consumers who install only this block still get working primitives).\nimport '../../components/breadcrumb/breadcrumb'\nimport '../../components/button/button'\nimport '../../components/separator/separator'\nimport '../../components/sidebar/sidebar'\nimport '../../components/theme-switch/theme-switch'\n\nexport interface DashboardCrumb {\n  label: string\n  href?: string\n}\n\nconst NAV = [\n  { label: 'Dashboard', icon: LayoutDashboard, iconName: 'layout-dashboard' },\n  { label: 'People', icon: Users, iconName: 'users' },\n  { label: 'Settings', icon: Settings, iconName: 'settings' },\n]\n\n/**\n * <uip-dashboard-layout> — the registry DashboardLayout block as a web component.\n *\n * Class strings are React's DashboardLayout verbatim: collapsible-icon\n * sidebar + sticky topbar (sidebar trigger, breadcrumb, theme switch,\n * notifications) + main content. Page content goes in the default slot\n * (React's `children`). `breadcrumbs` is a property (no attribute —\n * structured data).\n *\n * React's `user` / `onProfileSelect` / `onCommandSelect` props are accepted\n * but unused in React itself (the sidebar owns the profile affordance), so\n * they are not ported. The notifications bell is a plain button, as in React.\n */\nexport class UipDashboardLayout extends LitElement {\n  static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n  // :host display can't be a utility class (the host has no template of its own).\n  static styles = [tailwind, css`:host { display: block; }`]\n\n  static properties = {\n    breadcrumbs: { attribute: false },\n  }\n\n  breadcrumbs: DashboardCrumb[] = [{ label: 'Dashboard' }]\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'dashboard-layout')\n  }\n\n  render() {\n    const crumbs = this.breadcrumbs.length ? this.breadcrumbs : [{ label: 'Dashboard' }]\n    return html`\n      <uip-sidebar-provider>\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        >\n          Skip to content\n        </a>\n        <uip-sidebar collapsible=\"icon\">\n          <uip-sidebar-header></uip-sidebar-header>\n          <uip-sidebar-content>\n            <uip-sidebar-group>\n              <uip-sidebar-group-content>\n                <uip-sidebar-menu>\n                  ${NAV.map(\n                    (item) => html`\n                      <uip-sidebar-menu-item>\n                        <uip-sidebar-menu-button tooltip=${item.label}>\n                          ${icon(item.icon, item.iconName)}<span>${item.label}</span>\n                        </uip-sidebar-menu-button>\n                      </uip-sidebar-menu-item>\n                    `,\n                  )}\n                </uip-sidebar-menu>\n              </uip-sidebar-group-content>\n            </uip-sidebar-group>\n          </uip-sidebar-content>\n          <uip-sidebar-rail></uip-sidebar-rail>\n        </uip-sidebar>\n        <uip-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              <uip-sidebar-trigger class=\"-ml-1\"></uip-sidebar-trigger>\n              <uip-separator orientation=\"vertical\" class=\"[&::part(base)]:mr-2 [&::part(base)]:h-4\"></uip-separator>\n              <uip-breadcrumb>\n                ${crumbs.map(\n                  (crumb, i) => html`\n                    <uip-breadcrumb-item class=${i === 0 ? 'hidden md:block' : ''}>\n                      ${crumb.href && i < crumbs.length - 1\n                        ? html`<uip-breadcrumb-link\n                            href=${crumb.href}\n                            class=\"text-muted-foreground/70 hover:text-foreground transition-colors\"\n                            >${crumb.label}</uip-breadcrumb-link\n                          >`\n                        : html`<uip-breadcrumb-page class=\"font-medium\">${crumb.label}</uip-breadcrumb-page>`}\n                    </uip-breadcrumb-item>\n                    ${i < crumbs.length - 1\n                      ? html`<uip-breadcrumb-separator\n                          class=${i === 0 ? 'hidden md:block' : ''}\n                        ></uip-breadcrumb-separator>`\n                      : ''}\n                  `,\n                )}\n              </uip-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                <uip-theme-switch variant=\"icon-only\"></uip-theme-switch>\n                <uip-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                  ${icon(Bell, 'bell', 'size-4')}\n                </uip-button>\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            <slot></slot>\n          </main>\n        </uip-sidebar-inset>\n      </uip-sidebar-provider>\n    `\n  }\n}\n\ncustomElements.get('uip-dashboard-layout') || customElements.define('uip-dashboard-layout', UipDashboardLayout)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-dashboard-layout': UipDashboardLayout\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/dashboard-layout/dashboard-layout.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/breadcrumb.json",
    "https://uipkge.dev/r/lit/button.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/separator.json",
    "https://uipkge.dev/r/lit/sidebar.json",
    "https://uipkge.dev/r/lit/theme-switch.json"
  ]
}
