{"version":3,"sources":["../../src/hooks/useWallPhotoCarousel.ts"],"names":[],"mappings":"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","file":"useWallPhotoCarousel.mjs","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { WallPost } from '../types/wall';\n\nexport interface UseWallPhotoCarouselOptions {\n  /**\n   * Posts to rotate through, newest-first. Pass the array from `useWallPosts`\n   * directly — the hook filters out posts without a `photoUrl` internally.\n   */\n  posts: WallPost[];\n  /** Auto-rotation interval in ms. 0 disables rotation. Default 10000. */\n  rotationMs?: number;\n}\n\nexport interface UseWallPhotoCarouselResult {\n  /** Posts that have a photoUrl, newest-first. */\n  items: WallPost[];\n  /** The currently displayed item, or null if nothing has a photo yet. */\n  active: WallPost | null;\n  /** Index of `active` in `items`. -1 if none. */\n  activeIndex: number;\n  /** Jump to a specific post id. Resets the rotation timer. */\n  setActive: (id: string) => void;\n}\n\n/**\n * Headless rotating-photo carousel for the non-AI wall mode. Mirrors the\n * `useWallScenes` ergonomics ({ items, active, activeIndex, setActive }) but\n * is driven by guest posts instead of AI-generated scenes.\n *\n * Behaviour:\n * - First load: active = items[0] (the newest post with a photo).\n * - Rotation tick: advance one slot; wrap at the end.\n * - New post arrives (id not seen before): jump to that post and reset the\n *   rotation timer so the new arrival gets a full cycle on screen.\n * - Posts deleted upstream: drop from `items`; if the active item disappears,\n *   fall back to items[0].\n */\nexport function useWallPhotoCarousel(\n  opts: UseWallPhotoCarouselOptions,\n): UseWallPhotoCarouselResult {\n  const rotationMs = opts.rotationMs ?? 10000;\n\n  const items = useMemo(\n    () => opts.posts.filter((p): p is WallPost & { photoUrl: string } => !!p.photoUrl),\n    [opts.posts],\n  );\n\n  const [activeId, setActiveId] = useState<string | null>(null);\n  const activeIdRef = useRef<string | null>(null);\n  const seenIdsRef = useRef<Set<string>>(new Set());\n  const rotationTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n  // Mirror the live `items` ids into a ref so the rotation interval can read\n  // the latest list without being torn down and recreated each render.\n  const itemIdsRef = useRef<string[]>([]);\n\n  const setActiveIdSync = useCallback((id: string | null) => {\n    activeIdRef.current = id;\n    setActiveId(id);\n  }, []);\n\n  const startRotation = useCallback(() => {\n    if (rotationMs <= 0) return;\n    if (rotationTimerRef.current) clearInterval(rotationTimerRef.current);\n    rotationTimerRef.current = setInterval(() => {\n      const ids = itemIdsRef.current;\n      if (ids.length <= 1) return;\n      const current = activeIdRef.current;\n      const idx = current ? ids.indexOf(current) : -1;\n      const next = ids[(idx + 1) % ids.length];\n      activeIdRef.current = next;\n      setActiveId(next);\n    }, rotationMs);\n  }, [rotationMs]);\n\n  useEffect(() => {\n    const ids = items.map(p => p.id);\n    itemIdsRef.current = ids;\n    const idSet = new Set(ids);\n\n    if (seenIdsRef.current.size === 0 && ids.length > 0) {\n      // First populated render — pin to the newest item and start rotation.\n      seenIdsRef.current = new Set(ids);\n      setActiveIdSync(ids[0]);\n      startRotation();\n      return;\n    }\n\n    const newIds = ids.filter(id => !seenIdsRef.current.has(id));\n    newIds.forEach(id => seenIdsRef.current.add(id));\n\n    if (newIds.length > 0) {\n      // New arrival — jump to the first new id and reset the timer so it gets\n      // a full cycle on screen.\n      setActiveIdSync(newIds[0]);\n      startRotation();\n      return;\n    }\n\n    // No new ids; ensure active is still valid after upstream deletions.\n    if (activeIdRef.current && !idSet.has(activeIdRef.current)) {\n      setActiveIdSync(ids[0] ?? null);\n      startRotation();\n    }\n  }, [items, setActiveIdSync, startRotation]);\n\n  // Cleanup rotation timer on unmount.\n  useEffect(() => {\n    return () => {\n      if (rotationTimerRef.current) clearInterval(rotationTimerRef.current);\n    };\n  }, []);\n\n  const setActive = useCallback(\n    (id: string) => {\n      setActiveIdSync(id);\n      startRotation();\n    },\n    [setActiveIdSync, startRotation],\n  );\n\n  const active = items.find(p => p.id === activeId) ?? items[0] ?? null;\n  const activeIndex = active ? items.findIndex(p => p.id === active.id) : -1;\n\n  return { items, active, activeIndex, setActive };\n}\n"]}