{
	"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
	"name": "smooth-cursor",
	"title": "Smooth Cursor",
	"type": "registry:block",
	"description": "A smooth animated cursor component with spring physics that follows mouse movement with rotation and scale effects.",
	"dependencies": [
		"motion-sv"
	],
	"files": [
		{
			"content": "<script lang=\"ts\">\n\timport { onMount } from \"svelte\";\n\timport { motion, useSpring } from \"motion-sv\";\n\timport type { Snippet } from \"svelte\";\n\n\tinterface Position {\n\t\tx: number;\n\t\ty: number;\n\t}\n\n\tinterface SmoothCursorProps {\n\t\tcursor?: Snippet;\n\t\tspringConfig?: {\n\t\t\tdamping: number;\n\t\t\tstiffness: number;\n\t\t\tmass: number;\n\t\t\trestDelta: number;\n\t\t};\n\t}\n\n\tlet {\n\t\tcursor,\n\t\tspringConfig = {\n\t\t\tdamping: 45,\n\t\t\tstiffness: 400,\n\t\t\tmass: 1,\n\t\t\trestDelta: 0.001,\n\t\t},\n\t}: SmoothCursorProps = $props();\n\n\tlet isMoving = $state(false);\n\tlet lastMousePos = $state<Position>({ x: 0, y: 0 });\n\tlet velocity = $state<Position>({ x: 0, y: 0 });\n\tlet lastUpdateTime = $state(Date.now());\n\tlet previousAngle = $state(0);\n\tlet accumulatedRotation = $state(0);\n\n\tlet cursorX = $derived(useSpring(0, springConfig));\n\tlet cursorY = $derived(useSpring(0, springConfig));\n\tlet rotation = $derived(\n\t\tuseSpring(0, {\n\t\t\t...springConfig,\n\t\t\tdamping: 60,\n\t\t\tstiffness: 300,\n\t\t})\n\t);\n\tlet scale = $derived(\n\t\tuseSpring(1, {\n\t\t\t...springConfig,\n\t\t\tdamping: 35,\n\t\t\tstiffness: 500,\n\t\t})\n\t);\n\n\tonMount(() => {\n\t\tconst updateVelocity = (currentPos: Position) => {\n\t\t\tconst currentTime = Date.now();\n\t\t\tconst deltaTime = currentTime - lastUpdateTime;\n\n\t\t\tif (deltaTime > 0) {\n\t\t\t\tvelocity = {\n\t\t\t\t\tx: (currentPos.x - lastMousePos.x) / deltaTime,\n\t\t\t\t\ty: (currentPos.y - lastMousePos.y) / deltaTime,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlastUpdateTime = currentTime;\n\t\t\tlastMousePos = currentPos;\n\t\t};\n\n\t\tconst smoothMouseMove = (e: MouseEvent) => {\n\t\t\tlet currentPos: Position = { x: e.clientX, y: e.clientY };\n\t\t\tupdateVelocity(currentPos);\n\n\t\t\tconst speed = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2));\n\n\t\t\tcursorX.set(currentPos.x);\n\t\t\tcursorY.set(currentPos.y);\n\n\t\t\tif (speed > 0.1) {\n\t\t\t\tconst currentAngle = Math.atan2(velocity.y, velocity.x) * (180 / Math.PI) + 90;\n\n\t\t\t\tlet angleDiff = currentAngle - previousAngle;\n\t\t\t\tif (angleDiff > 180) angleDiff -= 360;\n\t\t\t\tif (angleDiff < -180) angleDiff += 360;\n\t\t\t\taccumulatedRotation += angleDiff;\n\t\t\t\trotation.set(accumulatedRotation);\n\t\t\t\tpreviousAngle = currentAngle;\n\n\t\t\t\tscale.set(0.95);\n\t\t\t\tisMoving = true;\n\n\t\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\t\tscale.set(1);\n\t\t\t\t\tisMoving = false;\n\t\t\t\t}, 150);\n\n\t\t\t\treturn () => clearTimeout(timeout);\n\t\t\t}\n\t\t};\n\n\t\tlet rafId: number;\n\t\tconst throttledMouseMove = (e: MouseEvent) => {\n\t\t\tif (rafId) return;\n\n\t\t\trafId = requestAnimationFrame(() => {\n\t\t\t\tsmoothMouseMove(e);\n\t\t\t\trafId = 0;\n\t\t\t});\n\t\t};\n\n\t\tdocument.body.style.cursor = \"none\";\n\t\twindow.addEventListener(\"mousemove\", throttledMouseMove);\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"mousemove\", throttledMouseMove);\n\t\t\tdocument.body.style.cursor = \"auto\";\n\t\t\tif (rafId) cancelAnimationFrame(rafId);\n\t\t};\n\t});\n</script>\n\n<motion.div\n\tstyle={{\n\t\tposition: \"fixed\",\n\t\tleft: cursorX,\n\t\ttop: cursorY,\n\t\ttranslateX: \"-50%\",\n\t\ttranslateY: \"-50%\",\n\t\trotate: rotation,\n\t\tscale: scale,\n\t\tzIndex: 100,\n\t\tpointerEvents: \"none\",\n\t\twillChange: \"transform\",\n\t}}\n\tinitial={{ scale: 0 }}\n\tanimate={{ scale: 1 }}\n\ttransition={{\n\t\ttype: \"spring\",\n\t\tstiffness: 400,\n\t\tdamping: 30,\n\t}}\n>\n\t{#if cursor}\n\t\t{@render cursor()}\n\t{:else}\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth={50}\n\t\t\theight={54}\n\t\t\tviewBox=\"0 0 50 54\"\n\t\t\tfill=\"none\"\n\t\t\tstyle=\"scale: 0.5\"\n\t\t>\n\t\t\t<g filter=\"url(#filter0_d_91_7928)\">\n\t\t\t\t<path\n\t\t\t\t\td=\"M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t/>\n\t\t\t\t<path\n\t\t\t\t\td=\"M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z\"\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t\tstroke-width={2.25825}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t\t<defs>\n\t\t\t\t<filter\n\t\t\t\t\tid=\"filter0_d_91_7928\"\n\t\t\t\t\tx={0.602397}\n\t\t\t\t\ty={0.952444}\n\t\t\t\t\twidth={49.0584}\n\t\t\t\t\theight={52.428}\n\t\t\t\t\tfilterUnits=\"userSpaceOnUse\"\n\t\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t\t>\n\t\t\t\t\t<feFlood flood-opacity={0} result=\"BackgroundImageFix\" />\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tin=\"SourceAlpha\"\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n\t\t\t\t\t\tresult=\"hardAlpha\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feOffset dy={2.25825} />\n\t\t\t\t\t<feGaussianBlur stdDeviation={2.25825} />\n\t\t\t\t\t<feComposite in2=\"hardAlpha\" operator=\"out\" />\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feBlend\n\t\t\t\t\t\tmode=\"normal\"\n\t\t\t\t\t\tin2=\"BackgroundImageFix\"\n\t\t\t\t\t\tresult=\"effect1_dropShadow_91_7928\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feBlend\n\t\t\t\t\t\tmode=\"normal\"\n\t\t\t\t\t\tin=\"SourceGraphic\"\n\t\t\t\t\t\tin2=\"effect1_dropShadow_91_7928\"\n\t\t\t\t\t\tresult=\"shape\"\n\t\t\t\t\t/>\n\t\t\t\t</filter>\n\t\t\t</defs>\n\t\t</svg>\n\t{/if}\n</motion.div>\n",
			"type": "registry:component",
			"target": "magic/smooth-cursor/smooth-cursor.svelte"
		},
		{
			"content": "export { default as SmoothCursor } from \"./smooth-cursor.svelte\";\n",
			"type": "registry:file",
			"target": "magic/smooth-cursor/index.ts"
		}
	]
}