export type GridMode = 'bento' | 'uniform' export function useGridMode() { const cookie = useCookie('grid-mode', { default: () => 'bento', maxAge: 60 * 60 * 24 * 365, sameSite: 'lax', }) // useState ist über alle Komponenten geteilt — die Cookie-Ref ist es nicht zuverlässig const mode = useState('grid-mode', () => cookie.value) const uniform = computed(() => mode.value === 'uniform') const animating = ref(false) async function toggle() { const next: GridMode = uniform.value ? 'bento' : 'uniform' if (!import.meta.client || animating.value) { mode.value = next cookie.value = next return } // FLIP: alte Positionen messen, solange das DOM noch den alten Zustand zeigt const tiles = Array.from(document.querySelectorAll('.upload-tile')) const oldRects = tiles.map(el => el.getBoundingClientRect()) animating.value = true mode.value = next cookie.value = next await nextTick() tiles.forEach((el, i) => { const oldR = oldRects[i] const newR = el.getBoundingClientRect() const dx = oldR.left - newR.left const dy = oldR.top - newR.top const sx = newR.width ? oldR.width / newR.width : 1 const sy = newR.height ? oldR.height / newR.height : 1 if (!dx && !dy && sx === 1 && sy === 1) return el.animate( [ { transformOrigin: 'top left', transform: `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})` }, { transformOrigin: 'top left', transform: 'none' }, ], { duration: 400, easing: 'cubic-bezier(0.2, 0, 0, 1)' }, ) }) setTimeout(() => { animating.value = false }, 400) } return { mode, uniform, toggle } }