{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "circuit-board",
  "type": "registry:block",
  "title": "Circuit board",
  "description": "Circuit board",
  "files": [
    {
      "path": "components/usages/circuitboardusage.tsx",
      "content": "import React from \"react\";\n\nimport CircuitBoard from \"@/registry/open-source/circuit-board\";\n\nexport default function Usage() {\n\treturn (\n\t\t<div className=\"h-screen w-full flex items-center justify-center relative overflow-hidden bg-background\">\n\t\t\t<CircuitBoard>\n\t\t\t\t<div className=\"relative z-10 flex flex-col items-center justify-center w-full h-full text-center max-w-[700px] mx-auto px-5 py-10 md:py-0 lg:lg:px-0 text-white\">\n\t\t\t\t\t<button className=\"py-1.5 pl-5 backdrop-blur-md pr-6 border-gray-600 rounded-full text-[0.9rem] border mb-4\">\n\t\t\t\t\t\t✨ Introducing dbs\n\t\t\t\t\t</button>\n\n\t\t\t\t\t<h1 className=\"text-[2rem] lg:text-[3rem] font-bold leading-[40px] lg:leading-[50px]\">\n\t\t\t\t\t\tOpen-Source UI Components & Templates Library\n\t\t\t\t\t</h1>\n\n\t\t\t\t\t<p className=\"text-white/80 max-w-[700px] mt-3\">\n\t\t\t\t\t\tdbs is an Tailwind CSS components library for any needs. Comes\n\t\t\t\t\t\twith UI examples & blocks, templates, Icons, Color Palette and\n\t\t\t\t\t\tmore.\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<div className=\"flex items-center flex-col md:flex-row gap-3 justify-center 425px:gap-6 mt-10 md:mt-12\">\n\t\t\t\t\t\t<button className=\"bg-[#0FABCA] pl-5 pr-4 border border-[#0FABCA] rounded-lg py-3 flex items-center gap-2 text-[1rem] group\">\n\t\t\t\t\t\t\tBrowse Components\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button className=\"border-2 border-[#0FABCA] pl-5 pr-4 rounded-lg py-3 flex items-center gap-2 text-[1rem] group\">\n\t\t\t\t\t\t\tBrowse Templates\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</CircuitBoard>\n\t\t\t;{\" \"}\n\t\t</div>\n\t);\n}\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/circuitboardusage.tsx",
      "content": "import React from \"react\";\n\nimport CircuitBoard from \"@/registry/open-source/circuit-board\";\n\nexport default function Usage() {\n\treturn (\n\t\t<div className=\"h-screen w-full flex items-center justify-center relative overflow-hidden bg-background\">\n\t\t\t<CircuitBoard>\n\t\t\t\t<div className=\"relative z-10 flex flex-col items-center justify-center w-full h-full text-center max-w-[700px] mx-auto px-5 py-10 md:py-0 lg:lg:px-0 text-white\">\n\t\t\t\t\t<button className=\"py-1.5 pl-5 backdrop-blur-md pr-6 border-gray-600 rounded-full text-[0.9rem] border mb-4\">\n\t\t\t\t\t\t✨ Introducing dbs\n\t\t\t\t\t</button>\n\n\t\t\t\t\t<h1 className=\"text-[2rem] lg:text-[3rem] font-bold leading-[40px] lg:leading-[50px]\">\n\t\t\t\t\t\tOpen-Source UI Components & Templates Library\n\t\t\t\t\t</h1>\n\n\t\t\t\t\t<p className=\"text-white/80 max-w-[700px] mt-3\">\n\t\t\t\t\t\tdbs is an Tailwind CSS components library for any needs. Comes\n\t\t\t\t\t\twith UI examples & blocks, templates, Icons, Color Palette and\n\t\t\t\t\t\tmore.\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<div className=\"flex items-center flex-col md:flex-row gap-3 justify-center 425px:gap-6 mt-10 md:mt-12\">\n\t\t\t\t\t\t<button className=\"bg-[#0FABCA] pl-5 pr-4 border border-[#0FABCA] rounded-lg py-3 flex items-center gap-2 text-[1rem] group\">\n\t\t\t\t\t\t\tBrowse Components\n\t\t\t\t\t\t</button>\n\t\t\t\t\t\t<button className=\"border-2 border-[#0FABCA] pl-5 pr-4 rounded-lg py-3 flex items-center gap-2 text-[1rem] group\">\n\t\t\t\t\t\t\tBrowse Templates\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</CircuitBoard>\n\t\t\t;{\" \"}\n\t\t</div>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/circuit-board.tsx",
      "content": "import { useEffect, useRef, useState } from \"react\";\n\n// Credit:\n// https://zenui.net/\n\nconst CircuitBoard = ({ children }) => {\n\tconst canvasRef = useRef(null);\n\tconst [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });\n\tconst [dimensions, setDimensions] = useState({ width: 0, height: 0 });\n\tconst circuitNodesRef = useRef([]);\n\tconst circuitPathsRef = useRef([]);\n\tconst animationRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tconst ctx = canvas.getContext(\"2d\");\n\n\t\tconst handleResize = () => {\n\t\t\tconst { innerWidth, innerHeight, devicePixelRatio = 1 } = window;\n\n\t\t\tcanvas.width = innerWidth * devicePixelRatio;\n\t\t\tcanvas.height = innerHeight * devicePixelRatio;\n\t\t\tcanvas.style.width = `${innerWidth}px`;\n\t\t\tcanvas.style.height = `${innerHeight}px`;\n\n\t\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tctx.scale(devicePixelRatio, devicePixelRatio);\n\n\t\t\tsetDimensions({ width: innerWidth, height: innerHeight });\n\t\t\tgenerateCircuit(innerWidth, innerHeight);\n\t\t};\n\n\t\tconst generateCircuit = (width, height) => {\n\t\t\tconst nodeCount = width < 768 ? 30 : 50;\n\t\t\tconst nodes = [];\n\t\t\tconst gridSize = Math.sqrt(nodeCount);\n\t\t\tconst cellWidth = width / gridSize;\n\t\t\tconst cellHeight = height / gridSize;\n\n\t\t\tfor (let i = 0; i < gridSize; i++) {\n\t\t\t\tfor (let j = 0; j < gridSize; j++) {\n\t\t\t\t\tconst x =\n\t\t\t\t\t\ti * cellWidth +\n\t\t\t\t\t\tMath.random() * (cellWidth * 0.6) +\n\t\t\t\t\t\tcellWidth * 0.2;\n\t\t\t\t\tconst y =\n\t\t\t\t\t\tj * cellHeight +\n\t\t\t\t\t\tMath.random() * (cellHeight * 0.6) +\n\t\t\t\t\t\tcellHeight * 0.2;\n\n\t\t\t\t\tnodes.push({\n\t\t\t\t\t\tx,\n\t\t\t\t\t\ty,\n\t\t\t\t\t\tsize: Math.random() * 3 + 2,\n\t\t\t\t\t\tisActive: false,\n\t\t\t\t\t\tactivationLevel: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst paths = [];\n\t\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\t\tconst node = nodes[i];\n\t\t\t\tconst connections = findClosestNodes(\n\t\t\t\t\tnode,\n\t\t\t\t\tnodes,\n\t\t\t\t\t2 + Math.floor(Math.random() * 3)\n\t\t\t\t);\n\t\t\t\tfor (const target of connections) {\n\t\t\t\t\tconst exists = paths.some(\n\t\t\t\t\t\t(p) =>\n\t\t\t\t\t\t\t(p.from === i && p.to === target) ||\n\t\t\t\t\t\t\t(p.from === target && p.to === i)\n\t\t\t\t\t);\n\t\t\t\t\tif (!exists && i !== target) {\n\t\t\t\t\t\tpaths.push({\n\t\t\t\t\t\t\tfrom: i,\n\t\t\t\t\t\t\tto: target,\n\t\t\t\t\t\t\tisActive: false,\n\t\t\t\t\t\t\tactivationLevel: 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcircuitNodesRef.current = nodes;\n\t\t\tcircuitPathsRef.current = paths;\n\t\t};\n\n\t\tconst findClosestNodes = (node, nodes, count) => {\n\t\t\tconst distances = nodes.map((n, index) => {\n\t\t\t\tconst dx = node.x - n.x;\n\t\t\t\tconst dy = node.y - n.y;\n\t\t\t\treturn { index, distance: Math.sqrt(dx * dx + dy * dy) };\n\t\t\t});\n\n\t\t\treturn distances\n\t\t\t\t.filter((d) => d.distance > 0)\n\t\t\t\t.sort((a, b) => a.distance - b.distance)\n\t\t\t\t.slice(0, count)\n\t\t\t\t.map((d) => d.index);\n\t\t};\n\n\t\thandleResize();\n\t\twindow.addEventListener(\"resize\", handleResize);\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"resize\", handleResize);\n\t\t\tif (animationRef.current) cancelAnimationFrame(animationRef.current);\n\t\t};\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst handleMouseMove = (e) => {\n\t\t\tconst rect = canvasRef.current.getBoundingClientRect();\n\t\t\tconst x = e.clientX - rect.left;\n\t\t\tconst y = e.clientY - rect.top;\n\t\t\tsetMousePosition({ x, y });\n\t\t};\n\n\t\twindow.addEventListener(\"mousemove\", handleMouseMove);\n\t\treturn () => window.removeEventListener(\"mousemove\", handleMouseMove);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!dimensions.width) return;\n\n\t\tconst canvas = canvasRef.current;\n\t\tconst ctx = canvas.getContext(\"2d\");\n\n\t\tconst animate = () => {\n\t\t\tctx.clearRect(0, 0, dimensions.width, dimensions.height);\n\n\t\t\tconst nodes = circuitNodesRef.current;\n\t\t\tconst paths = circuitPathsRef.current;\n\n\t\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\t\tconst node = nodes[i];\n\t\t\t\tconst dx = node.x - mousePosition.x;\n\t\t\t\tconst dy = node.y - mousePosition.y;\n\t\t\t\tconst distance = Math.sqrt(dx * dx + dy * dy);\n\n\t\t\t\tif (distance < 150) {\n\t\t\t\t\tnode.isActive = true;\n\t\t\t\t\tnode.activationLevel = Math.min(1, node.activationLevel + 0.05);\n\t\t\t\t} else {\n\t\t\t\t\tnode.activationLevel = Math.max(0, node.activationLevel - 0.02);\n\t\t\t\t\tif (node.activationLevel <= 0) node.isActive = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const path of paths) {\n\t\t\t\tconst fromNode = nodes[path.from];\n\t\t\t\tconst toNode = nodes[path.to];\n\n\t\t\t\tif (fromNode.isActive || toNode.isActive) {\n\t\t\t\t\tpath.isActive = true;\n\t\t\t\t\tpath.activationLevel = Math.min(1, path.activationLevel + 0.03);\n\t\t\t\t} else {\n\t\t\t\t\tpath.activationLevel = Math.max(0, path.activationLevel - 0.01);\n\t\t\t\t\tif (path.activationLevel <= 0) path.isActive = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tctx.strokeStyle = \"rgba(50, 50, 70, 0.3)\";\n\t\t\tctx.lineWidth = 1;\n\t\t\tfor (const path of paths) {\n\t\t\t\tif (!path.isActive) {\n\t\t\t\t\tconst fromNode = nodes[path.from];\n\t\t\t\t\tconst toNode = nodes[path.to];\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(fromNode.x, fromNode.y);\n\t\t\t\t\tctx.lineTo(toNode.x, toNode.y);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const path of paths) {\n\t\t\t\tif (path.isActive && path.activationLevel > 0) {\n\t\t\t\t\tconst fromNode = nodes[path.from];\n\t\t\t\t\tconst toNode = nodes[path.to];\n\n\t\t\t\t\tctx.strokeStyle = `rgba(0, 200, 255, ${path.activationLevel * 0.2})`;\n\t\t\t\t\tctx.lineWidth = 3;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(fromNode.x, fromNode.y);\n\t\t\t\t\tctx.lineTo(toNode.x, toNode.y);\n\t\t\t\t\tctx.stroke();\n\n\t\t\t\t\tctx.strokeStyle = `rgba(100, 220, 255, ${path.activationLevel})`;\n\t\t\t\t\tctx.lineWidth = 1;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.moveTo(fromNode.x, fromNode.y);\n\t\t\t\t\tctx.lineTo(toNode.x, toNode.y);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const node of nodes) {\n\t\t\t\tif (!node.isActive) {\n\t\t\t\t\tctx.fillStyle = \"rgba(100, 100, 120, 0.5)\";\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.arc(node.x, node.y, node.size, 0, Math.PI * 2);\n\t\t\t\t\tctx.fill();\n\t\t\t\t} else {\n\t\t\t\t\tconst gradient = ctx.createRadialGradient(\n\t\t\t\t\t\tnode.x,\n\t\t\t\t\t\tnode.y,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tnode.x,\n\t\t\t\t\t\tnode.y,\n\t\t\t\t\t\tnode.size * 3\n\t\t\t\t\t);\n\t\t\t\t\tgradient.addColorStop(\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t`rgba(0, 200, 255, ${node.activationLevel})`\n\t\t\t\t\t);\n\t\t\t\t\tgradient.addColorStop(1, \"rgba(0, 200, 255, 0)\");\n\t\t\t\t\tctx.fillStyle = gradient;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.arc(node.x, node.y, node.size * 3, 0, Math.PI * 2);\n\t\t\t\t\tctx.fill();\n\n\t\t\t\t\tctx.fillStyle = `rgba(100, 220, 255, ${node.activationLevel})`;\n\t\t\t\t\tctx.beginPath();\n\t\t\t\t\tctx.arc(node.x, node.y, node.size, 0, Math.PI * 2);\n\t\t\t\t\tctx.fill();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst gradient = ctx.createRadialGradient(\n\t\t\t\tmousePosition.x,\n\t\t\t\tmousePosition.y,\n\t\t\t\t0,\n\t\t\t\tmousePosition.x,\n\t\t\t\tmousePosition.y,\n\t\t\t\t150\n\t\t\t);\n\t\t\tgradient.addColorStop(0, \"rgba(0, 200, 255, 0.1)\");\n\t\t\tgradient.addColorStop(1, \"rgba(0, 200, 255, 0)\");\n\t\t\tctx.fillStyle = gradient;\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(mousePosition.x, mousePosition.y, 150, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\n\t\t\tanimationRef.current = requestAnimationFrame(animate);\n\t\t};\n\n\t\tanimate();\n\n\t\treturn () => {\n\t\t\tif (animationRef.current) cancelAnimationFrame(animationRef.current);\n\t\t};\n\t}, [dimensions, mousePosition]);\n\n\treturn (\n\t\t<div className=\"relative w-full min-h-[500px] flex items-center justify-center flex-col overflow-hidden rounded-high bg-gray-900\">\n\t\t\t<canvas ref={canvasRef} className=\"absolute inset-0 w-full h-full\" />\n\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n\nexport default CircuitBoard;\n",
      "type": "registry:ui"
    }
  ]
}