{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "empty-state",
  "title": "Empty State",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-angular/components/empty-state/empty-state.component.ts",
      "content": "import {\n  Component,\n  Directive,\n  Input,\n  OnChanges,\n  OnDestroy,\n  TemplateRef,\n  ViewContainerRef,\n  inject,\n  ChangeDetectionStrategy,\n} from '@angular/core'\nimport { cn } from '@/lib/utils'\n\nexport type EmptyStateHeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\nconst ICON_CLASS = 'text-muted-foreground mx-auto mb-3 size-10'\n\n/**\n * Renders the `icon` template and styles its root element(s) the way React styles the Lucide\n * `icon` component it receives (`className` + aria-hidden), so consumers pass a bare svg.\n */\n@Directive({ selector: '[uiEmptyStateIcon]', standalone: true })\nexport class UiEmptyStateIconDirective implements OnChanges, OnDestroy {\n  @Input('uiEmptyStateIcon') template: TemplateRef<unknown> | null = null\n  private readonly vcr = inject(ViewContainerRef)\n\n  ngOnChanges(): void {\n    this.vcr.clear()\n    if (!this.template) return\n    const view = this.vcr.createEmbeddedView(this.template)\n    view.detectChanges()\n    for (const node of view.rootNodes) {\n      if (!(node instanceof Element)) continue\n      node.setAttribute('class', cn(node.getAttribute('class') ?? '', ICON_CLASS))\n      node.setAttribute('aria-hidden', 'true')\n    }\n  }\n\n  ngOnDestroy(): void {\n    this.vcr.clear()\n  }\n}\n\n/**\n * Angular port of UIPKGE EmptyState (React `EmptyState`). Centered placeholder: optional icon\n * (an `<ng-template>` holding an svg — React's Lucide `icon` prop), a heading rendered as\n * `headingTag`, a description, and projected actions. Live region: role=\"status\" + polite by\n * default, role=\"alert\" + assertive for errors.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-empty-state, [ui-empty-state]',\n  standalone: true,\n  imports: [UiEmptyStateIconDirective],\n  host: {\n    '[attr.role]': 'role',\n    '[attr.aria-live]': 'ariaLive',\n    // `title` is an input (the heading text), never a native tooltip on the host.\n    '[attr.title]': 'null',\n    '[class]': 'hostClass',\n  },\n  template: `\n    @if (icon) {\n      <ng-container [uiEmptyStateIcon]=\"icon\" />\n    }\n    @if (title) {\n      @switch (headingTag) {\n        @case ('h1') {\n          <h1 class=\"text-foreground font-medium\">{{ title }}</h1>\n        }\n        @case ('h2') {\n          <h2 class=\"text-foreground font-medium\">{{ title }}</h2>\n        }\n        @case ('h4') {\n          <h4 class=\"text-foreground font-medium\">{{ title }}</h4>\n        }\n        @case ('h5') {\n          <h5 class=\"text-foreground font-medium\">{{ title }}</h5>\n        }\n        @case ('h6') {\n          <h6 class=\"text-foreground font-medium\">{{ title }}</h6>\n        }\n        @default {\n          <h3 class=\"text-foreground font-medium\">{{ title }}</h3>\n        }\n      }\n    }\n    @if (description) {\n      <p class=\"text-muted-foreground mt-1 max-w-sm text-sm\">{{ description }}</p>\n    }\n    <ng-content />\n  `,\n})\nexport class UiEmptyStateComponent {\n  /** Icon template (e.g. `<ng-template #icon><svg>…</svg></ng-template>`); styled size-10 + muted. */\n  @Input() icon?: TemplateRef<unknown> | null\n  @Input() title?: string\n  @Input() description?: string\n  @Input() role: 'status' | 'alert' = 'status'\n  @Input() headingTag: EmptyStateHeadingTag = 'h3'\n  @Input('class') className?: string\n\n  get hostClass(): string {\n    return cn('flex flex-col items-center py-12 text-center', this.className)\n  }\n\n  get ariaLive(): string {\n    return this.role === 'alert' ? 'assertive' : 'polite'\n  }\n}\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/empty-state/empty-state.component.ts"
    },
    {
      "path": "packages/registry-angular/components/empty-state/index.ts",
      "content": "export { UiEmptyStateComponent, UiEmptyStateIconDirective, type EmptyStateHeadingTag } from './empty-state.component'\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/empty-state/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Centered placeholder with icon, headline, supporting text, and one or two actions. Drop into empty lists, blank dashboards, and unauthenticated views — the standard \"nothing here yet\" pattern.",
  "categories": [
    "feedback"
  ]
}