Files
spa/.planning
julian 17439de34f feat: task 2.8 camera control trio + follow toggle
- src/map/core/map-pref-store.ts: mapFollow boolean (default true) +
  setter. Persisted via trm-map-prefs.
- src/map/core/camera/default-camera.tsx: <MapDefaultCamera /> fits
  the snapshot's bounds once per activeEventId change. Uses a
  fittedFor ref; resets to null when activeEventId becomes null.
  Single-point events centre+zoom 12; multi-point fitBounds with
  padding capped at min(canvas*0.1, 80).
- src/map/core/camera/selected-device.tsx: <MapSelectedDevice />
  pans+zooms on selection change, smooth pans on subsequent position
  updates with mapFollow on. Separate effect listens for user-gesture
  movestart (originalEvent truthy) and flips mapFollow off.
- src/map/core/camera/map-camera.tsx: <MapCamera coordinates> imperative
  one-shot. Phase 2 doesn't use it; primitive for replay (Phase 4) and
  future "fit to all" UI.
- src/map/core/follow-toggle.tsx: <FollowToggle /> icon-button using
  Lucide Locate/LocateOff. Sits below the trails toggle.
- src/routes/_authed/monitor.tsx: renders FollowToggle, MapDefaultCamera,
  MapSelectedDevice.

Deviations:
- Manual-pan listener uses an inline { originalEvent?: unknown } type
  instead of MapLibre's MapMouseEvent|MapTouchEvent union (typing
  friction across version bumps).
- MapDefaultCamera clears fittedFor on activeEventId === null so
  re-selecting the same event later re-fits.

Bundle: main 395KB / 120KB gz, no measurable change.
2026-05-03 09:33:08 +02:00
..