{
  "id": "ha-camera-feed",
  "name": "Camera Feed",
  "category": "smart-home",
  "tags": ["camera", "security", "monitor", "video"],
  "description": "Camera viewer with entity selector and snapshot refresh for security feeds.",
  "triggers": ["camera feed", "security camera", "baby monitor", "cam view"],
  "defaultSize": { "w": 4, "h": 4 },
  "source": "function CameraFeed() {\n  const [selected, setSelected] = React.useState('front_door');\n  const [lastRefresh, setLastRefresh] = React.useState(new Date());\n\n  const cameras = [\n    { id: 'front_door', name: 'Front Door' },\n    { id: 'backyard', name: 'Backyard' },\n    { id: 'garage', name: 'Garage' },\n    { id: 'living_room', name: 'Living Room' }\n  ];\n\n  const refresh = () => setLastRefresh(new Date());\n\n  React.useEffect(() => {\n    const interval = setInterval(refresh, 30000);\n    return () => clearInterval(interval);\n  }, []);\n\n  const canvasRef = React.useRef(null);\n\n  React.useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const ctx = canvas.getContext('2d');\n    ctx.fillStyle = '#0f172a';\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\n    ctx.fillStyle = '#1e293b';\n    for (let i = 0; i < 20; i++) {\n      ctx.fillRect(Math.random() * canvas.width, Math.random() * canvas.height, 2, 2);\n    }\n    ctx.fillStyle = '#334155';\n    ctx.font = '14px system-ui';\n    ctx.textAlign = 'center';\n    ctx.fillText(cameras.find(c => c.id === selected).name + ' Camera', canvas.width / 2, canvas.height / 2 - 10);\n    ctx.fillText('Live Feed Simulation', canvas.width / 2, canvas.height / 2 + 10);\n    ctx.fillStyle = '#ef4444';\n    ctx.beginPath();\n    ctx.arc(20, 20, 5, 0, Math.PI * 2);\n    ctx.fill();\n    ctx.fillStyle = '#ef4444';\n    ctx.font = '11px system-ui';\n    ctx.textAlign = 'left';\n    ctx.fillText('LIVE', 30, 24);\n  }, [selected, lastRefresh]);\n\n  return (\n    <div style={{ fontFamily: 'system-ui', background: '#111827', color: '#f3f4f6', width: '100%', height: '100%', padding: 16, borderRadius: 8, boxSizing: 'border-box', display: 'flex', flexDirection: 'column' }}>\n      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>\n        <span style={{ fontSize: 14, fontWeight: 600, color: '#9ca3af' }}>Camera Feed</span>\n        <button onClick={refresh} style={{ background: '#1f2937', color: '#f3f4f6', border: 'none', borderRadius: 6, padding: '4px 10px', fontSize: 12, cursor: 'pointer' }}>Refresh</button>\n      </div>\n      <div style={{ display: 'flex', gap: 6, marginBottom: 10 }}>\n        {cameras.map(c => (\n          <button key={c.id} onClick={() => setSelected(c.id)} style={{ flex: 1, padding: '6px 0', borderRadius: 6, border: 'none', background: selected === c.id ? '#3b82f6' : '#1f2937', color: '#fff', fontSize: 11, fontWeight: 600, cursor: 'pointer' }}>{c.name}</button>\n        ))}\n      </div>\n      <canvas ref={canvasRef} width={320} height={200} style={{ width: '100%', flex: 1, borderRadius: 6, background: '#0f172a' }} />\n      <div style={{ fontSize: 11, color: '#6b7280', marginTop: 6, textAlign: 'right' }}>Last refresh: {lastRefresh.toLocaleTimeString()}</div>\n    </div>\n  );\n}\nrender(<CameraFeed/>);",
  "placeholders": [{ "name": "REPLACE_WITH_CAMERA_ENTITY", "description": "Home Assistant camera entity ID", "default": "camera.front_door" }]
}
