{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "progress", "type": "registry:ui", "title": "Progress", "description": "Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.", "files": [ { "path": "registry/new-york/ui/progress.tsx", "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface ProgressProps {\n value?: number;\n onChange?: (value: number) => void;\n className?: string;\n}\n\nfunction Progress({ className, value = 0, onChange, ...props }: ProgressProps) {\n const trackRef = React.useRef(null);\n const [dragging, setDragging] = React.useState(false);\n\n const clamp = (val: number) => Math.max(0, Math.min(100, val));\n\n const getValueFromEvent = (clientX: number) => {\n if (!trackRef.current) return value;\n const rect = trackRef.current.getBoundingClientRect();\n const percent = ((clientX - rect.left) / rect.width) * 100;\n return clamp(Math.round(percent));\n };\n\n const handlePointerDown = (e: React.PointerEvent) => {\n e.preventDefault();\n setDragging(true);\n const newVal = getValueFromEvent(e.clientX);\n onChange?.(newVal);\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n };\n\n const handlePointerMove = (e: React.PointerEvent) => {\n if (!dragging) return;\n const newVal = getValueFromEvent(e.clientX);\n onChange?.(newVal);\n };\n\n const handlePointerUp = () => {\n setDragging(false);\n };\n\n return (\n
\n {/* Track */}\n \n {/* Filled indicator */}\n \n\n {/* Thumb with percentage inside */}\n \n \n {value}%\n \n
\n \n \n );\n}\n\nexport { Progress };\n", "type": "registry:ui" } ] }