diff --git a/app/components/book/BookPdfReader.vue b/app/components/book/BookPdfReader.vue index cf52c7c..819023e 100644 --- a/app/components/book/BookPdfReader.vue +++ b/app/components/book/BookPdfReader.vue @@ -1,13 +1,12 @@ @@ -42,6 +42,7 @@ const bookData = useBookData() await bookData.init() const overlayRef = ref() +const iframeRef = ref() const isOpen = computed({ get: () => props.modelValue, @@ -138,15 +139,4 @@ onUnmounted(() => { background: white; } -/* Overlay transitions */ -.pdf-overlay-enter-active { - animation: pdf-enter 0.4s cubic-bezier(0.16, 1, 0.3, 1) both; -} -.pdf-overlay-leave-active { - animation: pdf-enter 0.3s cubic-bezier(0.7, 0, 0.84, 0) reverse both; -} -@keyframes pdf-enter { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} diff --git a/app/components/home/AxisBlock.vue b/app/components/home/AxisBlock.vue index a901ab7..a235edc 100644 --- a/app/components/home/AxisBlock.vue +++ b/app/components/home/AxisBlock.vue @@ -72,17 +72,25 @@
- -
- {{ action.label }} - +
diff --git a/app/components/home/BookSection.vue b/app/components/home/BookSection.vue index edd4de0..5ebe77c 100644 --- a/app/components/home/BookSection.vue +++ b/app/components/home/BookSection.vue @@ -5,13 +5,12 @@
-
- -
+
@@ -88,7 +87,12 @@ const titleLine2 = computed(() => titleParts.value[1]) } .book-cover-3d { + width: 100%; + max-width: 360px; aspect-ratio: 3 / 4; + background-size: 200% auto; + background-position: right center; + background-repeat: no-repeat; border-radius: 0.75rem; overflow: hidden; border: 1px solid hsl(var(--color-text) / 0.1); @@ -97,7 +101,6 @@ const titleLine2 = computed(() => titleParts.value[1]) 0 0 0 1px hsl(var(--color-text) / 0.08); transition: transform 0.5s cubic-bezier(0.645, 0.045, 0.355, 1), box-shadow 0.5s ease; - max-width: 360px; } .book-cover-3d--compact { @@ -111,12 +114,6 @@ const titleLine2 = computed(() => titleParts.value[1]) 0 0 0 1px hsl(var(--color-primary) / 0.2); } -.book-cover-img { - width: 200%; - height: 100%; - object-fit: cover; - transform: translateX(-50%); -} .book-heading { font-size: clamp(1.625rem, 4vw, 2.125rem); diff --git a/app/pages/economique/modele-eco/[slug].vue b/app/pages/economique/modele-eco/[slug].vue index 56c4adb..13cb4e1 100644 --- a/app/pages/economique/modele-eco/[slug].vue +++ b/app/pages/economique/modele-eco/[slug].vue @@ -43,6 +43,11 @@ definePageMeta({ const route = useRoute() const slug = route.params.slug as string +// Scroll to top when navigating between chapters (component reused by Vue Router) +watch(() => slug, () => { + if (import.meta.client) window.scrollTo({ top: 0, behavior: 'instant' }) +}) + // Initialize guided mode useGuidedMode() diff --git a/app/router.options.ts b/app/router.options.ts new file mode 100644 index 0000000..be3f008 --- /dev/null +++ b/app/router.options.ts @@ -0,0 +1,9 @@ +import type { RouterConfig } from '@nuxt/schema' + +export default { + scrollBehavior(to, _from, savedPosition) { + if (savedPosition) return savedPosition + if (to.hash) return { el: to.hash, behavior: 'smooth' } + return { top: 0, behavior: 'instant' } + }, +} diff --git a/public/pdf/une-economie-du-don.pdf b/public/pdf/une-economie-du-don.pdf index c9cf7ee..c8343ee 100644 Binary files a/public/pdf/une-economie-du-don.pdf and b/public/pdf/une-economie-du-don.pdf differ diff --git a/public/pdfjs/viewer.html b/public/pdfjs/viewer.html index 9146dd2..43e87d6 100644 --- a/public/pdfjs/viewer.html +++ b/public/pdfjs/viewer.html @@ -158,24 +158,6 @@ html, body { visibility: hidden; } -/* Page turn transition */ -.page-slot canvas { - transition: opacity 1s ease-out, transform 1s ease-out; -} - -.page-slot canvas.entering { - opacity: 0; - transform: translateX(var(--enter-dir, 20px)); - transition: none; -} - -.page-slot canvas.leaving { - opacity: 0; - transform: translateX(var(--leave-dir, -20px)); - position: absolute; - transition: opacity 1.2s ease-in, transform 1.2s ease-in; -} - /* Navigation bar */ .nav-bar { display: flex; @@ -300,8 +282,6 @@ let currentSpread = 0; // index into spreads[] let spreads = []; // [[1], [2,3], [4,5], ...] — page 1 alone (cover), then pairs let pageCanvasCache = new Map(); let outlinePageMap = []; // [{item, pageNum}] for highlighting -let isAnimating = false; - function buildSpreads(numPages) { spreads = []; // Page 1 = couverture seule @@ -347,33 +327,14 @@ async function renderPageCanvas(pageNum) { return canvas; } -async function showSpread(index, animate = true) { +async function showSpread(index) { if (index < 0 || index >= spreads.length) return; - if (isAnimating) return; - const prevIndex = currentSpread; - const direction = index > prevIndex ? 1 : -1; // 1 = forward, -1 = back currentSpread = index; - const pages = spreads[index]; const slotLeft = document.getElementById('slotLeft'); const slotRight = document.getElementById('slotRight'); - // Collect old canvases for fade-out - const oldCanvases = [...slotLeft.querySelectorAll('canvas'), ...slotRight.querySelectorAll('canvas')]; - const shouldAnimate = animate && oldCanvases.length > 0; - - if (shouldAnimate) { - isAnimating = true; - // Fade out old canvases with directional slide - oldCanvases.forEach(c => { - c.style.setProperty('--leave-dir', `${-direction * 20}px`); - c.classList.add('leaving'); - }); - // Wait for fade-out to mostly complete - await new Promise(r => setTimeout(r, 500)); - } - slotLeft.innerHTML = ''; slotRight.innerHTML = ''; slotLeft.className = 'page-slot'; @@ -381,40 +342,17 @@ async function showSpread(index, animate = true) { if (pages.length === 1) { const canvas = await renderPageCanvas(pages[0]); - if (shouldAnimate) { - canvas.style.setProperty('--enter-dir', `${direction * 20}px`); - canvas.classList.add('entering'); - } slotLeft.appendChild(canvas); slotRight.className = 'page-slot empty'; - if (shouldAnimate) { - // Double rAF ensures the browser has painted the initial state before transitioning - requestAnimationFrame(() => requestAnimationFrame(() => canvas.classList.remove('entering'))); - } } else { const [left, right] = await Promise.all([ renderPageCanvas(pages[0]), renderPageCanvas(pages[1]), ]); - if (shouldAnimate) { - left.style.setProperty('--enter-dir', `${direction * 20}px`); - right.style.setProperty('--enter-dir', `${direction * 20}px`); - left.classList.add('entering'); - right.classList.add('entering'); - } slotLeft.appendChild(left); slotRight.appendChild(right); - if (shouldAnimate) { - requestAnimationFrame(() => requestAnimationFrame(() => { - left.classList.remove('entering'); - right.classList.remove('entering'); - })); - } } - if (shouldAnimate) setTimeout(() => { isAnimating = false; }, 1100); - else isAnimating = false; - updateNav(); highlightOutline(); }