{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "rough-rect", "title": "RoughRect", "description": "Hand-drawn rectangle wrapper with optional children.", "dependencies": [ "roughjs" ], "registryDependencies": [ "https://www.bydefaulthuman.fun/r/use-rough.json", "https://www.bydefaulthuman.fun/r/crumble-theme.json", "https://www.bydefaulthuman.fun/r/rough-lib.json", "utils" ], "files": [ { "path": "registry/new-york/primitives/rough-rect.tsx", "content": "\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { randomSeed, type CrumbleTheme } from \"@/lib/rough\";\nimport { useRough } from \"@/hooks/use-rough\";\n\nexport interface RoughRectProps {\n animateOnHover?: boolean;\n children?: ReactNode;\n className?: string;\n fill?: string;\n id?: string;\n onClick?: () => void;\n padding?: number;\n rounded?: boolean;\n stroke?: string;\n style?: CSSProperties;\n theme?: CrumbleTheme;\n}\n\nexport function RoughRect({\n animateOnHover: animateOnHoverProp,\n children,\n className,\n fill,\n id,\n onClick,\n padding = 8,\n rounded = false,\n stroke,\n style,\n theme: themeProp,\n}: RoughRectProps) {\n const containerRef = useRef(null);\n const mountSeed = useRef(randomSeed());\n const { drawRect, svgRef, theme, animateOnHover } = useRough({\n stableId: id,\n theme: themeProp,\n variant: \"border\",\n });\n const shouldAnimateHover = animateOnHoverProp ?? animateOnHover;\n\n const draw = useCallback(\n (reseed = false) => {\n const svg = svgRef.current;\n const container = containerRef.current;\n\n if (!svg || !container) return;\n\n svg.replaceChildren();\n\n const width = container.offsetWidth;\n const height = container.offsetHeight;\n const inset = 2;\n\n svg.setAttribute(\"width\", String(width));\n svg.setAttribute(\"height\", String(height));\n svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n\n const node = drawRect(\n inset,\n inset,\n width - inset * 2,\n height - inset * 2,\n {\n fill: fill ?? \"none\",\n stroke: stroke ?? \"currentColor\",\n ...(rounded && { roughness: 0.5 }),\n seed: reseed ? randomSeed() : id ? undefined : mountSeed.current,\n },\n );\n\n if (node) {\n svg.appendChild(node);\n }\n },\n [drawRect, fill, id, rounded, stroke, svgRef],\n );\n\n useEffect(() => {\n draw();\n }, [draw]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const observer = new ResizeObserver(() => draw());\n observer.observe(container);\n\n return () => observer.disconnect();\n }, [draw]);\n\n return (\n {\n if (shouldAnimateHover) draw(true);\n }}\n onMouseLeave={() => {\n if (shouldAnimateHover) draw(false);\n }}\n style={style}\n >\n \n
\n {children}\n
\n \n );\n}\n", "type": "registry:ui", "target": "components/crumble/primitives/rough-rect.tsx" } ], "type": "registry:ui" }