{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "header-mega-menu",
  "title": "Header — Mega Menu",
  "type": "registry:block",
  "description": "Navbar whose product and resources items open a full-width mega panel of grouped, described links plus a highlighted feature card, keyboard navigable and closing on Escape.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "header",
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/header-mega-menu/header-mega-menu.ts",
      "content": "import { LitElement, css, html } from 'lit'\nimport {\n  ArrowRight,\n  BarChart3,\n  BookOpen,\n  Boxes,\n  Layers,\n  LifeBuoy,\n  Lock,\n  Menu,\n  Workflow,\n  type IconNode,\n} 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/button/button'\nimport '../../components/navigation-menu/navigation-menu'\nimport '../../components/separator/separator'\nimport '../../components/sheet/sheet'\n\ninterface MegaItem {\n  icon: IconNode\n  iconName: string\n  title: string\n  body: string\n}\n\ninterface MegaMenu {\n  label: string\n  groups: { heading: string; items: MegaItem[] }[]\n  highlight: { title: string; body: string; cta: string }\n}\n\n// `iconName` beside each icon node: lucide nodes don't carry their kebab-case\n// name, which icon() needs for the lucide-<name> class.\nconst menus: MegaMenu[] = [\n  {\n    label: 'Product',\n    groups: [\n      {\n        heading: 'Core',\n        items: [\n          { icon: Boxes, iconName: 'boxes', title: 'Metric layer', body: 'Versioned definitions your whole org shares.' },\n          {\n            icon: BarChart3,\n            iconName: 'chart-column',\n            title: 'Dashboards',\n            body: 'Composed from certified metrics, not raw SQL.',\n          },\n          { icon: Workflow, iconName: 'workflow', title: 'Pipelines', body: 'Scheduled materialisation with cost ceilings.' },\n        ],\n      },\n      {\n        heading: 'Governance',\n        items: [\n          { icon: Lock, iconName: 'lock', title: 'Row-level access', body: 'Scope evaluated per query, per identity.' },\n          {\n            icon: BookOpen,\n            iconName: 'book-open',\n            title: 'Change history',\n            body: 'Every definition edit reviewed and revertible.',\n          },\n          {\n            icon: LifeBuoy,\n            iconName: 'life-buoy',\n            title: 'Audit exports',\n            body: 'Generated from the same history, not by hand.',\n          },\n        ],\n      },\n    ],\n    highlight: {\n      title: 'Ship your first dashboard today',\n      body: 'Connect a warehouse, publish one certified metric, and invite the team. No migration required.',\n      cta: 'Start the walkthrough',\n    },\n  },\n  {\n    label: 'Resources',\n    groups: [\n      {\n        heading: 'Learn',\n        items: [\n          {\n            icon: BookOpen,\n            iconName: 'book-open',\n            title: 'Documentation',\n            body: 'Setup, modelling, and the access model.',\n          },\n          { icon: Layers, iconName: 'layers', title: 'Guides', body: 'Reconciliation and first-close checklists.' },\n          {\n            icon: BarChart3,\n            iconName: 'chart-column',\n            title: 'Benchmarks',\n            body: 'Close speed across 240 finance teams.',\n          },\n        ],\n      },\n      {\n        heading: 'Support',\n        items: [\n          {\n            icon: LifeBuoy,\n            iconName: 'life-buoy',\n            title: 'Help centre',\n            body: 'Answers to the questions support gets most.',\n          },\n          { icon: Workflow, iconName: 'workflow', title: 'Status', body: 'Live uptime and incident history.' },\n          { icon: Lock, iconName: 'lock', title: 'Trust centre', body: 'SOC 2, subprocessors, and data residency.' },\n        ],\n      },\n    ],\n    highlight: {\n      title: 'Read the rollout plan',\n      body: 'The five-week implementation we run for every customer, written down so you can run it yourself.',\n      cta: 'Open the plan',\n    },\n  },\n]\n\nconst plainLinks = [\n  { label: 'Pricing', href: '#pricing' },\n  { label: 'Customers', href: '#customers' },\n]\n\n/**\n * <uip-header-mega-menu> — the registry HeaderMegaMenu block as a web component.\n *\n * Class strings are React's HeaderMegaMenu verbatim. React state (useState)\n * becomes @state fields; the desktop dropdowns become <uip-navigation-menu>\n * (trigger/content slots, panel content stays light DOM) and the mobile menu\n * becomes <uip-sheet> (open + open-change). Arrow-key movement and Escape\n * come from the navigation-menu primitive.\n */\nexport class UipHeaderMegaMenu 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    open: { state: true },\n  }\n\n  private open = false\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', 'header-mega-menu')\n  }\n\n  render() {\n    return html`\n      <header data-slot=\"header-mega-menu\" class=\"border-border bg-background/90 border-b backdrop-blur\">\n        <div class=\"mx-auto flex h-16 max-w-6xl items-center gap-6 px-6\">\n          <a href=\"#top\" class=\"flex shrink-0 items-center gap-2 font-semibold tracking-tight\">\n            ${icon(Layers, 'layers', 'text-primary size-5')}\n            Northwind\n          </a>\n\n          <!-- Plain wrapper carries the responsive class: display utilities\n               can't go on the uip-navigation-menu host (its :host display wins). -->\n          <div class=\"hidden lg:flex\">\n            <uip-navigation-menu>\n              ${menus.map(\n                (menu) => html`\n                  <uip-navigation-menu-item>\n                    <span slot=\"trigger\">${menu.label}</span>\n                    <div slot=\"content\" class=\"grid w-[46rem] grid-cols-[1fr_1fr_16rem] gap-6 p-6\">\n                      ${menu.groups.map(\n                        (group) => html`\n                          <div>\n                            <p class=\"text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase\">\n                              ${group.heading}\n                            </p>\n                            <ul class=\"mt-3 space-y-1\">\n                              ${group.items.map(\n                                (item) => html`\n                                  <li>\n                                    <a\n                                      href=\"#\"\n                                      class=\"hover:bg-muted focus-visible:ring-ring flex gap-3 rounded-md p-2 transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n                                    >\n                                      ${icon(item.icon, item.iconName, 'text-muted-foreground mt-0.5 size-4 shrink-0')}\n                                      <span class=\"min-w-0\">\n                                        <span class=\"block text-sm font-medium\">${item.title}</span>\n                                        <span class=\"text-muted-foreground block text-xs leading-snug\"\n                                          >${item.body}</span\n                                        >\n                                      </span>\n                                    </a>\n                                  </li>\n                                `,\n                              )}\n                            </ul>\n                          </div>\n                        `,\n                      )}\n                      <div class=\"bg-muted/50 flex flex-col rounded-lg p-4\">\n                        <p class=\"text-sm font-semibold\">${menu.highlight.title}</p>\n                        <p class=\"text-muted-foreground mt-2 text-xs leading-relaxed\">${menu.highlight.body}</p>\n                        <uip-button variant=\"link\" class=\"mt-auto h-auto justify-start p-0 pt-4 text-xs\">\n                          ${menu.highlight.cta} ${icon(ArrowRight, 'arrow-right', 'ml-1 size-3')}\n                        </uip-button>\n                      </div>\n                    </div>\n                  </uip-navigation-menu-item>\n                `,\n              )}\n              ${plainLinks.map(\n                (link) => html`\n                  <uip-navigation-menu-item>\n                    <uip-navigation-menu-link href=${link.href} trigger-style>${link.label}</uip-navigation-menu-link>\n                  </uip-navigation-menu-item>\n                `,\n              )}\n            </uip-navigation-menu>\n          </div>\n\n          <div class=\"ml-auto flex items-center gap-2\">\n            <!-- Plain spans carry the responsive classes: display utilities\n                 can't go on uip-* hosts (their :host display wins). sm:contents\n                 keeps the primitives direct flex items with the row's gap. -->\n            <span class=\"hidden sm:contents\">\n              <uip-button variant=\"ghost\" size=\"sm\">Sign in</uip-button>\n            </span>\n            <span class=\"hidden sm:contents\">\n              <uip-separator orientation=\"vertical\" class=\"[&::part(base)]:h-5!\"></uip-separator>\n            </span>\n            <uip-button size=\"sm\">Book a demo</uip-button>\n          </div>\n\n          <div class=\"ml-auto lg:hidden\">\n            <uip-sheet\n              side=\"right\"\n              heading=\"Menu\"\n              .open=${this.open}\n              @open-change=${(e: CustomEvent<{ open: boolean }>) => {\n                this.open = e.detail.open\n              }}\n            >\n              <uip-button slot=\"trigger\" variant=\"ghost\" size=\"icon\" aria-label=\"Open navigation menu\">\n                ${icon(Menu, 'menu', 'size-5')}\n              </uip-button>\n              <nav class=\"mt-6 grid gap-5\" aria-label=\"Mobile\">\n                ${menus.map(\n                  (menu) => html`\n                    <div>\n                      <p class=\"text-muted-foreground/70 text-xs font-medium tracking-wide uppercase\">${menu.label}</p>\n                      <ul class=\"mt-2 grid gap-1\">\n                        ${menu.groups.map((group) =>\n                          group.items.map(\n                            (item) => html`\n                              <li>\n                                <a\n                                  href=\"#\"\n                                  class=\"hover:bg-muted block rounded-md px-3 py-2 text-sm font-medium transition-colors\"\n                                  @click=${() => {\n                                    this.open = false\n                                  }}\n                                >\n                                  ${item.title}\n                                </a>\n                              </li>\n                            `,\n                          ),\n                        )}\n                      </ul>\n                    </div>\n                  `,\n                )}\n                <uip-separator></uip-separator>\n                ${plainLinks.map(\n                  (link) => html`<a\n                    href=${link.href}\n                    class=\"hover:bg-muted rounded-md px-3 py-2 text-sm font-medium transition-colors\"\n                    @click=${() => {\n                      this.open = false\n                    }}\n                  >\n                    ${link.label}\n                  </a>`,\n                )}\n                <uip-separator></uip-separator>\n                <div class=\"grid gap-2\">\n                  <uip-button variant=\"outline\">Sign in</uip-button>\n                  <uip-button>Book a demo</uip-button>\n                </div>\n              </nav>\n            </uip-sheet>\n          </div>\n        </div>\n      </header>\n    `\n  }\n}\n\ncustomElements.get('uip-header-mega-menu') || customElements.define('uip-header-mega-menu', UipHeaderMegaMenu)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-header-mega-menu': UipHeaderMegaMenu\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/header-mega-menu/header-mega-menu.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/button.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/navigation-menu.json",
    "https://uipkge.dev/r/lit/separator.json",
    "https://uipkge.dev/r/lit/sheet.json"
  ]
}
