{ "name": "angle-slider-controlled-demo", "type": "registry:example", "dependencies": [ "motion", "lucide-react" ], "registryDependencies": [ "angle-slider", "button" ], "files": [ { "path": "examples/angle-slider-controlled-demo.tsx", "type": "registry:example", "content": "\"use client\";\n\nimport { RotateCcwIcon, ShuffleIcon } from \"lucide-react\";\nimport { animate } from \"motion/react\";\nimport * as React from \"react\";\nimport {\n AngleSlider,\n AngleSliderRange,\n AngleSliderThumb,\n AngleSliderTrack,\n AngleSliderValue,\n} from \"@/registry/bases/base/ui/angle-slider\";\nimport { Button } from \"@/registry/bases/base/ui/button\";\n\nexport default function AngleSliderControlledDemo() {\n const [value, setValue] = React.useState([180]);\n const animationRef = React.useRef | null>(null);\n\n const animateToValue = React.useCallback(\n (targetValue: number) => {\n if (animationRef.current) {\n animationRef.current.stop();\n }\n\n const currentValue = value[0] ?? 0;\n\n let diff = targetValue - currentValue;\n if (diff > 180) {\n diff -= 360;\n } else if (diff < -180) {\n diff += 360;\n }\n\n animationRef.current = animate(0, diff, {\n duration: 0.4,\n ease: [0.25, 0.46, 0.45, 0.94],\n onUpdate: (progress: number) => {\n const animatedValue = currentValue + progress;\n const normalizedValue = Math.round(\n ((animatedValue % 360) + 360) % 360,\n );\n setValue([normalizedValue]);\n },\n onComplete: () => {\n setValue([targetValue]);\n animationRef.current = null;\n },\n });\n },\n [value],\n );\n\n const onReset = React.useCallback(() => {\n animateToValue(0);\n }, [animateToValue]);\n\n const onRandomize = React.useCallback(() => {\n animateToValue(Math.floor(Math.random() * 360));\n }, [animateToValue]);\n\n React.useEffect(() => {\n return () => {\n if (animationRef.current) {\n animationRef.current.stop();\n }\n };\n }, []);\n\n return (\n
\n
\n \n \n
\n \n \n \n \n \n \n \n
\n );\n}\n", "target": "" } ] }