{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "Silk-TS-CSS",
	"title": "Silk",
	"description": "Smooth waves background with soft lighting.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "Silk/Silk.tsx",
			"content": "/* eslint-disable react/no-unknown-property */\nimport React, { forwardRef, useMemo, useRef, useLayoutEffect, useEffect } from 'react';\nimport { Canvas, useFrame, useThree, type RootState } from '@react-three/fiber';\nimport { Color, Mesh, ShaderMaterial } from 'three';\nimport { type IUniform } from 'three';\n\ntype NormalizedRGB = [number, number, number];\n\nconst hexToNormalizedRGB = (hex: string): NormalizedRGB => {\n  const clean = hex.replace('#', '');\n  const r = parseInt(clean.slice(0, 2), 16) / 255;\n  const g = parseInt(clean.slice(2, 4), 16) / 255;\n  const b = parseInt(clean.slice(4, 6), 16) / 255;\n  return [r, g, b];\n};\n\ninterface UniformValue<T = number | Color> {\n  value: T;\n}\n\ninterface SilkUniforms {\n  uSpeed: UniformValue<number>;\n  uScale: UniformValue<number>;\n  uNoiseIntensity: UniformValue<number>;\n  uColor: UniformValue<Color>;\n  uRotation: UniformValue<number>;\n  uLightMode: UniformValue<number>;\n  uTime: UniformValue<number>;\n  [uniform: string]: IUniform;\n}\n\nconst vertexShader = `\nvarying vec2 vUv;\nvarying vec3 vPosition;\n\nvoid main() {\n  vPosition = position;\n  vUv = uv;\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst fragmentShader = `\nvarying vec2 vUv;\nvarying vec3 vPosition;\n\nuniform float uTime;\nuniform vec3  uColor;\nuniform float uSpeed;\nuniform float uScale;\nuniform float uRotation;\nuniform float uNoiseIntensity;\nuniform float uLightMode;\n\nconst float e = 2.71828182845904523536;\n\nfloat noise(vec2 texCoord) {\n  float G = e;\n  vec2  r = (G * sin(G * texCoord));\n  return fract(r.x * r.y * (1.0 + texCoord.x));\n}\n\nvec2 rotateUvs(vec2 uv, float angle) {\n  float c = cos(angle);\n  float s = sin(angle);\n  mat2  rot = mat2(c, -s, s, c);\n  return rot * uv;\n}\n\nvoid main() {\n  float rnd        = noise(gl_FragCoord.xy);\n  vec2  uv         = rotateUvs(vUv * uScale, uRotation);\n  vec2  tex        = uv * uScale;\n  float tOffset    = uSpeed * uTime;\n\n  tex.y += 0.03 * sin(8.0 * tex.x - tOffset);\n\n  float pattern = 0.6 +\n                  0.4 * sin(5.0 * (tex.x + tex.y +\n                                   cos(3.0 * tex.x + 5.0 * tex.y) +\n                                   0.02 * tOffset) +\n                           sin(20.0 * (tex.x + tex.y - 0.1 * tOffset)));\n\n  float grain = rnd / 15.0 * uNoiseIntensity;\n  vec3 result = uColor * pattern - vec3(grain);\nif (uLightMode > 0.5) {\n  float fold = smoothstep(0.28, 0.9, pattern);\n  float specular = smoothstep(0.72, 0.98, pattern);\n  vec3 shadowColor = uColor * 0.72;\n  vec3 bodyColor = min(uColor * 1.18, vec3(1.0));\n  vec3 lightBase = mix(shadowColor, bodyColor, fold);\n  lightBase = mix(lightBase, vec3(1.0), specular * 0.92);\n  float fineNoise = noise(gl_FragCoord.xy * 0.63 + vec2(17.0, 41.0));\n  float grainSignal = (rnd + fineNoise - 1.0);\n  float grainStrength = clamp(uNoiseIntensity * 0.038, 0.0, 0.16);\n  result = lightBase + grainSignal * grainStrength;\n}\n  gl_FragColor = vec4(clamp(result, 0.0, 1.0), 1.0);\n}\n`;\n\ninterface SilkPlaneProps {\n  uniforms: SilkUniforms;\n}\n\nconst SilkPlane = forwardRef<Mesh, SilkPlaneProps>(function SilkPlane({ uniforms }, ref) {\n  const { viewport } = useThree();\n\n  useLayoutEffect(() => {\n    const mesh = ref as React.MutableRefObject<Mesh | null>;\n    if (mesh.current) {\n      mesh.current.scale.set(viewport.width, viewport.height, 1);\n    }\n  }, [ref, viewport]);\n\n  useFrame((_state: RootState, delta: number) => {\n    const mesh = ref as React.MutableRefObject<Mesh | null>;\n    if (mesh.current) {\n      const material = mesh.current.material as ShaderMaterial & {\n        uniforms: SilkUniforms;\n      };\n      material.uniforms.uTime.value += 0.1 * delta;\n    }\n  });\n\n  return (\n    <mesh ref={ref}>\n      <planeGeometry args={[1, 1, 1, 1]} />\n      <shaderMaterial uniforms={uniforms} vertexShader={vertexShader} fragmentShader={fragmentShader} />\n    </mesh>\n  );\n});\nSilkPlane.displayName = 'SilkPlane';\n\nexport interface SilkProps {\n  speed?: number;\n  scale?: number;\n  color?: string;\n  noiseIntensity?: number;\n  rotation?: number;\n  lightMode?: boolean;\n}\n\nconst Silk: React.FC<SilkProps> = ({\n  speed = 5,\n  scale = 1,\n  color = '#7B7481',\n  noiseIntensity = 1.5,\n  rotation = 0,\n  lightMode = false\n}) => {\n  const meshRef = useRef<Mesh>(null);\n\n  const uniforms = useMemo<SilkUniforms>(\n    () => ({\n      uSpeed: { value: speed },\n      uScale: { value: scale },\n      uNoiseIntensity: { value: noiseIntensity },\n      uColor: { value: new Color(...hexToNormalizedRGB(color)) },\n      uRotation: { value: rotation },\n      uLightMode: { value: lightMode ? 1 : 0 },\n      uTime: { value: 0 }\n    }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    []\n  );\n\n  useEffect(() => {\n    uniforms.uSpeed.value = speed;\n    uniforms.uScale.value = scale;\n    uniforms.uNoiseIntensity.value = noiseIntensity;\n    uniforms.uColor.value.setRGB(...hexToNormalizedRGB(color));\n    uniforms.uRotation.value = rotation;\n    uniforms.uLightMode.value = lightMode ? 1 : 0;\n  }, [speed, scale, noiseIntensity, color, rotation, lightMode, uniforms]);\n\n  return (\n    <Canvas dpr={[1, 2]} frameloop=\"always\">\n      <SilkPlane ref={meshRef} uniforms={uniforms} />\n    </Canvas>\n  );\n};\n\nexport default Silk;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"@react-three/fiber@^9.3.0",
		"three@^0.180.0"
	]
}