{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "spider-sense-wrapper", "dependencies": [ "@mojs/core" ], "registryDependencies": [ "https://powui.dev/r/general-utils.json" ], "files": [ { "path": "src/components/ui/spiderSenseWrapper.tsx", "content": "\"use client\";\n\n/**\n * Credits to Mike Quinn for the original snippet which inspired this whole project\n * https://codepen.io/mprquinn/pen/OmOMrR\n */\n\nimport { pickRandomFromArray } from \"@/utils/general\";\nimport mojs from \"@mojs/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\n\nfunction throttle(\n fn: (...args: Args) => void,\n ms: number,\n): (...args: Args) => void {\n let lastTime = 0;\n return (...args: Args) => {\n const now = Date.now();\n if (now - lastTime < ms) return;\n lastTime = now;\n fn(...args);\n };\n}\n\nexport const COLORS_LIST = [\n {\n name: \"Vibrant Red\",\n hex: \"#FF0000\",\n },\n {\n name: \"Electric Blue\",\n hex: \"#00FFFF\",\n },\n {\n name: \"Bright Orange\",\n hex: \"#FF8C00\",\n },\n {\n name: \"Lime Green\",\n hex: \"#32CD32\",\n },\n {\n name: \"Shocking Pink\",\n hex: \"#FF1493\",\n },\n {\n name: \"Deep Magenta\",\n hex: \"#FF00FF\",\n },\n {\n name: \"Sunny Yellow\",\n hex: \"#FFD700\",\n },\n {\n name: \"Royal Blue\",\n hex: \"#4169E1\",\n },\n {\n name: \"Fluorescent Green\",\n hex: \"#00FF7F\",\n },\n {\n name: \"Hot Pink\",\n hex: \"#FF69B4\",\n },\n {\n name: \"Electric Violet\",\n hex: \"#8A2BE2\",\n },\n {\n name: \"Crimson Red\",\n hex: \"#DC143C\",\n },\n {\n name: \"Aqua Marine\",\n hex: \"#7FFFD4\",\n },\n {\n name: \"Gold\",\n hex: \"#FFBF00\",\n },\n {\n name: \"Deep Sky Blue\",\n hex: \"#00BFFF\",\n },\n];\n\nconst SpiderSenseWrapper = (\n props: React.PropsWithChildren<{\n children: React.ReactNode;\n shape?: \"zigzag\" | \"line\";\n color?: string;\n trigger?: \"hover\" | \"click\" | \"mount\" | \"manual\";\n getManualTrigger?: (trigger: () => void) => void;\n containerClassName?: string;\n }>,\n) => {\n const {\n children,\n color,\n shape,\n trigger = \"hover\",\n getManualTrigger,\n containerClassName,\n } = props;\n\n const containerRef = useRef(null);\n\n const shootLines = useCallback(() => {\n if (!containerRef.current) return;\n const windowWidth = window.innerWidth,\n windowHeight = window.innerHeight;\n const itemDim = containerRef.current.getBoundingClientRect(),\n itemSize = {\n x: itemDim.right - itemDim.left,\n y: itemDim.bottom - itemDim.top,\n };\n\n const chosenColor =\n color ?? pickRandomFromArray(COLORS_LIST.map((x) => x.hex));\n const chosenShape = shape ?? pickRandomFromArray([\"line\", \"zigzag\"]);\n\n const averageRadius = (itemSize.x + itemSize.y) / 4;\n const circumference = Math.PI * (itemSize.x + itemSize.y);\n\n const burst = new mojs.Burst({\n left: itemDim.left + itemSize.x / 2 + window.scrollX,\n top: itemDim.top + itemSize.y / 2 + window.scrollY,\n radiusX: itemSize.x + averageRadius / 5,\n radiusY: itemSize.y + averageRadius / 5,\n count: Math.max(4, circumference / 50),\n\n children: {\n shape: chosenShape,\n radius: averageRadius / 6,\n scale: {\n [windowWidth / (itemDim.width * 6)]:\n windowHeight / (itemDim.height * 6),\n },\n fill: \"none\",\n points: 7,\n stroke: chosenColor,\n strokeDasharray: \"100%\",\n strokeDashoffset: { \"-100%\": \"100%\" },\n strokeWidth: averageRadius / 30,\n duration: 500,\n easing: \"quad.out\",\n isShowEnd: false,\n },\n });\n\n burst.play();\n }, [color, shape]);\n\n const throttledShootLines = useMemo(\n () => throttle(shootLines, 400),\n [shootLines],\n );\n\n useEffect(() => {\n getManualTrigger?.(throttledShootLines);\n }, [getManualTrigger, throttledShootLines]);\n\n const registerRef = useCallback(\n (node: HTMLDivElement | null) => {\n if (node) {\n containerRef.current = node;\n if (trigger === \"mount\") {\n setTimeout(throttledShootLines, 0);\n }\n }\n },\n [throttledShootLines],\n );\n\n return (\n {}}\n onClick={trigger === \"click\" ? throttledShootLines : () => {}}\n className={containerClassName}\n >\n {children}\n \n );\n};\n\nexport { SpiderSenseWrapper };\n", "type": "registry:ui" } ], "type": "registry:ui" }