'use client'; import { useEffect } from 'react'; type Edge = 'top' | 'bottom' | 'left' | 'right'; interface ToolbarState { edge: Edge; ratio: number; collapsed: boolean; enabled: boolean; defaultAction?: string; } interface ReactGrabAPI { setToolbarState: (state: Partial) => void; onToolbarStateChange: (cb: (state: ToolbarState) => void) => () => void; } declare global { interface Window { __REACT_GRAB__?: ReactGrabAPI; } } const MOBILE_QUERY = '(max-width: 1023.98px)'; const DESKTOP_KEY = 'react-grab-toolbar-state-desktop'; const MOBILE_KEY = 'react-grab-toolbar-state-mobile'; const DESKTOP_DEFAULT: Partial = { edge: 'bottom', ratio: 0.5, collapsed: false, }; const MOBILE_DEFAULT: Partial = { edge: 'right', ratio: 0.5, collapsed: false, }; export function ReactGrabViewportSync() { useEffect(() => { if (process.env.NODE_ENV !== 'development') return; const cleanups: Array<() => void> = []; let pollId: number | undefined; const wireUp = (api: ReactGrabAPI) => { const mql = window.matchMedia(MOBILE_QUERY); const keyFor = () => (mql.matches ? MOBILE_KEY : DESKTOP_KEY); const defaultFor = () => (mql.matches ? MOBILE_DEFAULT : DESKTOP_DEFAULT); let suppressNextWrite = false; const apply = () => { const stored = localStorage.getItem(keyFor()); suppressNextWrite = true; api.setToolbarState(stored ? (JSON.parse(stored) as ToolbarState) : defaultFor()); }; apply(); const unsubscribe = api.onToolbarStateChange((state) => { if (suppressNextWrite) { suppressNextWrite = false; return; } localStorage.setItem(keyFor(), JSON.stringify(state)); }); mql.addEventListener('change', apply); cleanups.push(unsubscribe, () => mql.removeEventListener('change', apply)); }; const tryWire = () => { const api = window.__REACT_GRAB__; if (!api) return false; wireUp(api); return true; }; if (!tryWire()) { pollId = window.setInterval(() => { if (tryWire() && pollId !== undefined) { window.clearInterval(pollId); pollId = undefined; } }, 100); window.setTimeout(() => { if (pollId !== undefined) { window.clearInterval(pollId); pollId = undefined; } }, 5000); } return () => { if (pollId !== undefined) window.clearInterval(pollId); cleanups.forEach((fn) => fn()); }; }, []); return null; }