{
  "name": "picturelight",
  "title": "PictureLight",
  "type": "registry:component",
  "description": "A brass picture light on one or two arms that washes the face below it: over a picture on a wall, or on the top of a bookshelf. Can light only after dusk.",
  "dependencies": [
    "@runek/core@^0.15.0",
    "three@^0.184.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "PictureLight.tsx",
      "content": "import { useSun, useWorld, type WorldComponentProps } from '@runek/core'\nimport { useMemo } from 'react'\nimport { Object3D } from 'three'\n\nexport interface PictureLightProps extends WorldComponentProps {\n  /** Length of the hood, in units. */\n  width?: number\n  /** How far the hood stands out from the mount, in units. */\n  reach?: number\n  /** How far below the mount the light falls, in units: the picture's or the shelf's height. */\n  fall?: number\n  /** Hood, arms, and back plate; defaults to the palette's `accent` (brass). */\n  color?: string\n  /** The light and the glowing bulb. */\n  lightColor?: string\n  /** Light strength. */\n  intensity?: number\n  /** Switched on. */\n  on?: boolean\n  /** Light only while the world's sun is down. */\n  nightOnly?: boolean\n}\n\n/**\n * A picture light: a brass hood on one or two arms (two past 0.6 m), washing the face below it.\n * Its origin is the mount point on a vertical face, which it stands out from along local +Z: fix\n * it over a picture on a `Wall`, or on the top front edge of a `Bookshelf` to light the books.\n * Accepts `seed` for the contract; it has no seeded variation. Decorative: no collider.\n */\nexport function PictureLight({\n  position = [0, 0, 0],\n  rotation = [0, 0, 0],\n  width = 0.5,\n  reach = 0.16,\n  fall = 1.2,\n  color,\n  lightColor = '#ffe6c0',\n  intensity = 6,\n  on = true,\n  nightOnly = false,\n}: PictureLightProps) {\n  const { unit, palette } = useWorld()\n  const sun = useSun()\n  const lit = on && (!nightOnly || !sun.day)\n  const brass = color ?? palette.accent\n  const W = width * unit\n  const Z = reach * unit\n  const rise = 0.06 * unit\n  const hoodR = 0.035 * unit\n  const arms = width > 0.6 ? [-W * 0.3, W * 0.3] : [0]\n  const armLen = Math.hypot(Z, rise)\n  const armTilt = Math.atan2(Z, rise)\n\n  const target = useMemo(() => new Object3D(), [])\n  const metal = <meshStandardMaterial color={brass} metalness={0.75} roughness={0.3} />\n\n  return (\n    <group position={position} rotation={rotation}>\n      {arms.map((x) => (\n        <group key={x} position={[x, 0, 0]}>\n          <mesh position={[0, 0, 0.004 * unit]}>\n            <boxGeometry args={[0.05 * unit, 0.07 * unit, 0.008 * unit]} />\n            {metal}\n          </mesh>\n          <mesh position={[0, rise / 2, Z / 2]} rotation={[armTilt, 0, 0]}>\n            <cylinderGeometry args={[0.005 * unit, 0.005 * unit, armLen, 8]} />\n            {metal}\n          </mesh>\n        </group>\n      ))}\n      {/* the hood: a half tube along X, opening down and back toward the face it lights */}\n      <group position={[0, rise, Z]} rotation={[-0.5, 0, 0]}>\n        <mesh rotation={[0, 0, Math.PI / 2]} castShadow>\n          <cylinderGeometry args={[hoodR, hoodR, W, 18, 1, true, 0, Math.PI]} />\n          <meshStandardMaterial color={brass} metalness={0.75} roughness={0.3} side={2} />\n        </mesh>\n        {[-1, 1].map((s) => (\n          <mesh key={s} position={[(s * W) / 2, 0, 0]} rotation={[0, (s * Math.PI) / 2, 0]}>\n            <circleGeometry args={[hoodR, 18, 0, Math.PI]} />\n            {metal}\n          </mesh>\n        ))}\n        <mesh position={[0, -hoodR * 0.3, 0]} rotation={[0, 0, Math.PI / 2]}>\n          <cylinderGeometry args={[0.008 * unit, 0.008 * unit, W * 0.9, 8]} />\n          <meshStandardMaterial\n            color=\"#fff6e0\"\n            emissive={lightColor}\n            emissiveIntensity={lit ? 2 : 0}\n            toneMapped={!lit}\n          />\n        </mesh>\n      </group>\n      <primitive object={target} position={[0, -fall * unit * 0.6, 0]} />\n      {lit && (\n        <spotLight\n          position={[0, rise - hoodR, Z]}\n          target={target}\n          color={lightColor}\n          intensity={intensity}\n          distance={(fall + 1) * unit}\n          angle={0.9}\n          penumbra={0.8}\n          decay={2}\n        />\n      )}\n    </group>\n  )\n}\n",
      "type": "registry:component"
    }
  ]
}
