{
  "$schema": "https://www.cooki-ui.design/schema/registry-item.json",
  "name": "electro-border",
  "type": "registry:ui",
  "title": "Electro Border Shield",
  "description": "Dynamic electric distortion border with procedural SVG turbulence filter displacement, glowing aura, and responsive resizing.",
  "category": "cards",
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "tags": [
    "card",
    "border",
    "electric",
    "svg-filter",
    "displacement-map",
    "turbulence",
    "glow",
    "hologram"
  ],
  "files": [
    {
      "path": "registry/cards/electro-border/electro-border.tsx",
      "type": "registry:ui",
      "target": "components/ui/electro-border.tsx",
      "content": "import React, { useRef, useLayoutEffect, useEffect, useId, CSSProperties } from 'react'\nimport { Zap, ShieldCheck, Cpu } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface ElectroBorderProps {\n  children?: React.ReactNode\n  borderColor?: string\n  borderWidth?: number\n  animationSpeed?: number\n  distortion?: number\n  glow?: boolean\n  aura?: boolean\n  glowBlur?: number\n  radius?: string\n  className?: string\n  style?: CSSProperties\n}\n\nconst toRGBA = (color: string, alpha = 1): string => {\n  if (!color) return `rgba(99,102,241,${alpha})`\n  if (color.startsWith('#')) {\n    const hex =\n      color.length === 4\n        ? `#${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}`\n        : color\n    if (hex.length === 7) {\n      const r = parseInt(hex.slice(1, 3), 16)\n      const g = parseInt(hex.slice(3, 5), 16)\n      const b = parseInt(hex.slice(5, 7), 16)\n      return `rgba(${r}, ${g}, ${b}, ${alpha})`\n    }\n  }\n  return color\n}\n\nexport const ElectroBorder: React.FC<ElectroBorderProps> = ({\n  children,\n  borderColor = '#6366f1',\n  borderWidth = 2,\n  animationSpeed = 1,\n  distortion = 0.5,\n  glow = true,\n  aura = true,\n  glowBlur = 12,\n  radius = '1.25rem',\n  className,\n  style,\n}) => {\n  const rootRef = useRef<HTMLDivElement>(null)\n  const svgRef = useRef<SVGSVGElement>(null)\n  const rawId = useId()\n  const filterId = `electro-filter-${rawId.replace(/[:]/g, '')}`\n\n  const updateFilter = () => {\n    if (!rootRef.current || !svgRef.current) return\n    const { width, height } = rootRef.current.getBoundingClientRect()\n    if (width === 0 || height === 0) return\n\n    const svg = svgRef.current\n    const dxAnimations = svg.querySelectorAll<SVGAnimateElement>('animate[attributeName=\"dx\"]')\n    const dyAnimations = svg.querySelectorAll<SVGAnimateElement>('animate[attributeName=\"dy\"]')\n\n    dxAnimations.forEach((a, i) =>\n      a.setAttribute('values', i % 2 === 0 ? `${width};0` : `0;-${width}`)\n    )\n    dyAnimations.forEach((a, i) =>\n      a.setAttribute('values', i % 2 === 0 ? `${height};0` : `0;-${height}`)\n    )\n\n    const duration = Math.max(0.01, 5 / animationSpeed)\n    ;[...dxAnimations, ...dyAnimations].forEach((a) =>\n      a.setAttribute('dur', `${duration}s`)\n    )\n\n    const disp = svg.querySelector('feDisplacementMap')\n    if (disp) disp.setAttribute('scale', `${28 * distortion}`)\n\n    requestAnimationFrame(() => {\n      ;[...dxAnimations, ...dyAnimations].forEach((a: any) => {\n        if (a.beginElement) a.beginElement()\n      })\n    })\n  }\n\n  useLayoutEffect(() => {\n    const observer = new ResizeObserver(() => updateFilter())\n    if (rootRef.current) observer.observe(rootRef.current)\n    updateFilter()\n    return () => observer.disconnect()\n  }, [])\n\n  useEffect(() => {\n    updateFilter()\n  }, [animationSpeed, distortion])\n\n  const radiusStyle: CSSProperties = { borderRadius: radius }\n\n  const defaultChild = (\n    <div className=\"flex flex-col gap-3 p-6 text-zinc-900 dark:text-white bg-white/95 dark:bg-zinc-950/90 rounded-[inherit] w-full max-w-[340px]\">\n      <div className=\"flex items-center justify-between\">\n        <div className=\"flex items-center gap-2\">\n          <div className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-indigo-500/10 text-indigo-500 dark:text-cyan-400 border border-indigo-500/20\">\n            <Zap className=\"h-4 w-4\" />\n          </div>\n          <span className=\"font-mono text-xs font-bold uppercase tracking-wider\">\n            Plasma Shield\n          </span>\n        </div>\n        <span className=\"font-mono text-[10px] text-indigo-500 dark:text-cyan-400 font-semibold px-2 py-0.5 rounded-full bg-indigo-500/10 border border-indigo-500/20\">\n          ACTIVE\n        </span>\n      </div>\n      <p className=\"text-xs text-zinc-600 dark:text-zinc-400 leading-relaxed\">\n        Animated SVG displacement turbulence creates organic distortion waves along the contour edges.\n      </p>\n      <div className=\"flex items-center justify-between pt-2 border-t border-zinc-200/60 dark:border-white/5 font-mono text-[10px] text-zinc-500\">\n        <span className=\"flex items-center gap-1\">\n          <Cpu className=\"h-3 w-3 text-indigo-500\" /> 120Hz V-Sync\n        </span>\n        <span className=\"flex items-center gap-1\">\n          <ShieldCheck className=\"h-3 w-3 text-emerald-500\" /> Encrypted\n        </span>\n      </div>\n    </div>\n  )\n\n  return (\n    <div\n      ref={rootRef}\n      className={cn('relative isolate inline-block', className)}\n      style={style}\n    >\n      <svg\n        ref={svgRef}\n        className=\"absolute w-0 h-0 pointer-events-none\"\n        aria-hidden\n        focusable=\"false\"\n      >\n        <defs>\n          <filter id={filterId} x=\"-200%\" y=\"-200%\" width=\"500%\" height=\"500%\">\n            <feTurbulence\n              type=\"turbulence\"\n              baseFrequency=\"0.03\"\n              numOctaves=\"2\"\n              result=\"turbulence\"\n            />\n            <feOffset in=\"turbulence\" result=\"offset1\">\n              <animate attributeName=\"dx\" dur=\"5s\" repeatCount=\"indefinite\" />\n              <animate attributeName=\"dy\" dur=\"5s\" repeatCount=\"indefinite\" />\n            </feOffset>\n            <feOffset in=\"turbulence\" result=\"offset2\">\n              <animate attributeName=\"dx\" dur=\"5s\" repeatCount=\"indefinite\" />\n              <animate attributeName=\"dy\" dur=\"5s\" repeatCount=\"indefinite\" />\n            </feOffset>\n            <feMerge result=\"merged\">\n              <feMergeNode in=\"offset1\" />\n              <feMergeNode in=\"offset2\" />\n            </feMerge>\n            <feDisplacementMap\n              in=\"SourceGraphic\"\n              in2=\"merged\"\n              scale=\"20\"\n              xChannelSelector=\"R\"\n              yChannelSelector=\"G\"\n            />\n          </filter>\n        </defs>\n      </svg>\n\n      {aura && (\n        <div\n          className=\"absolute inset-0 pointer-events-none transition-all duration-300\"\n          style={{\n            ...radiusStyle,\n            transform: 'scale(1.04)',\n            background: `radial-gradient(circle at 50% 50%, ${toRGBA(borderColor, 0.45)} 0%, transparent 70%)`,\n            filter: `blur(${glowBlur * 1.4}px)`,\n            opacity: 0.65,\n            zIndex: -2,\n          }}\n        />\n      )}\n\n      <div\n        className=\"absolute inset-0 pointer-events-none\"\n        style={{\n          ...radiusStyle,\n          border: `${borderWidth}px solid ${borderColor}`,\n          filter: `url(#${filterId})`,\n          zIndex: 1,\n        }}\n      />\n\n      {glow && (\n        <div\n          className=\"absolute inset-0 pointer-events-none\"\n          style={{\n            ...radiusStyle,\n            border: `${borderWidth}px solid ${toRGBA(borderColor, 0.8)}`,\n            filter: `blur(${glowBlur}px)`,\n            opacity: 0.4,\n            zIndex: 0,\n          }}\n        />\n      )}\n\n      <div className=\"relative z-10\" style={radiusStyle}>\n        {children || defaultChild}\n      </div>\n    </div>\n  )\n}\n\nexport default ElectroBorder\n"
    }
  ],
  "tailwind": {
    "required": true
  },
  "framework": [
    "react",
    "nextjs",
    "vite"
  ]
}