{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "border-beam",
  "title": "Border Beam",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-angular/components/border-beam/border-beam.component.ts",
      "content": "import { Component, Input, OnDestroy, OnInit, booleanAttribute, signal, ChangeDetectionStrategy } from '@angular/core'\nimport { cn } from '@/lib/utils'\n\n/**\n * Rotating conic light beam that traces the border ring of its parent (React `BorderBeam`).\n * Place inside a `relative` parent; the overlay is absolutely positioned, pointer-events-none\n * and masked down to a ring of `size` px. Keyframes and the `--uipkge-border-angle` @property\n * ship in the canonical tailwind tokens. prefers-reduced-motion renders a static beam.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-border-beam, [ui-border-beam]',\n  standalone: true,\n  host: {\n    'data-uipkge': '',\n    'data-slot': 'border-beam',\n    'aria-hidden': 'true',\n    '[class]': 'hostClass',\n    '[style]': 'beamStyle',\n  },\n  template: ``,\n})\nexport class UiBorderBeamComponent implements OnInit, OnDestroy {\n  /** Ring thickness in px. */\n  @Input() size = 2\n  /** Seconds per revolution. */\n  @Input() duration = 6\n  /** Seconds; negative values offset the beam's starting position around the ring. */\n  @Input() delay = 0\n  /** Any CSS color for the beam highlight. */\n  @Input() color = 'var(--primary)'\n  /** Freeze the beam in place (animation-play-state: paused). */\n  @Input({ transform: booleanAttribute }) paused = false\n  @Input('class') className?: string\n\n  // Signal: flipped by a media-query listener, outside any template event.\n  private readonly reducedMotion = signal(false)\n  private query?: MediaQueryList\n  private readonly onChange = (event: MediaQueryListEvent) => this.reducedMotion.set(event.matches)\n\n  ngOnInit(): void {\n    if (typeof window === 'undefined' || !window.matchMedia) return\n    this.query = window.matchMedia('(prefers-reduced-motion: reduce)')\n    this.reducedMotion.set(this.query.matches)\n    this.query.addEventListener?.('change', this.onChange)\n  }\n\n  ngOnDestroy(): void {\n    this.query?.removeEventListener?.('change', this.onChange)\n  }\n\n  get hostClass(): string {\n    return cn('pointer-events-none absolute inset-0 rounded-[inherit]', this.className)\n  }\n\n  get beamStyle(): Record<string, string | null> {\n    const reduced = this.reducedMotion()\n    const mask = 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)'\n    return {\n      padding: `${this.size}px`,\n      background: reduced\n        ? `conic-gradient(from 45deg, transparent 0deg, transparent 290deg, ${this.color} 330deg, transparent 360deg)`\n        : `conic-gradient(from var(--uipkge-border-angle), transparent 0deg, transparent 290deg, ${this.color} 330deg, transparent 360deg)`,\n      animation: reduced ? 'none' : `uipkge-border-beam ${this.duration}s linear infinite ${this.delay}s`,\n      'animation-play-state': !reduced && this.paused ? 'paused' : null,\n      '-webkit-mask': mask,\n      '-webkit-mask-composite': 'xor',\n      mask,\n      'mask-composite': 'exclude',\n    }\n  }\n}\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/border-beam/border-beam.component.ts"
    },
    {
      "path": "packages/registry-angular/components/border-beam/index.ts",
      "content": "export { UiBorderBeamComponent } from './border-beam.component'\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/border-beam/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Rotating conic light beam that traces the border ring of its parent. Place inside a `relative` parent (e.g. a Card); the overlay is absolutely positioned, pointer-events-none, and masked down to a ring of `size` px thickness. Tune `duration`, `delay`, and `color`, or set `paused` to freeze it. Keyframes and the `--uipkge-border-angle` @property ship in the canonical tailwind tokens — re-pull init/tailwind if upgrading.",
  "categories": [
    "feedback",
    "motion"
  ]
}