This commit is contained in:
2025-11-07 00:46:35 +01:00
parent 2118f002d1
commit c3f837b90f
143 changed files with 4223 additions and 9686 deletions

77
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,77 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
// Lightweight scroll-reveal setup for elements with `.section` or `[data-reveal]`.
// Respects prefers-reduced-motion and observes dynamically added nodes.
function setupReveal() {
const w = window as unknown as { __revealSetupDone?: boolean }
if (w.__revealSetupDone) return
w.__revealSetupDone = true
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
const selector = '.section, [data-reveal]'
// If reduced motion is preferred, mark everything visible and skip observers
if (prefersReduced) {
document.querySelectorAll(selector).forEach((el) => el.classList.add('reveal-visible'))
return
}
const seen = new WeakSet<Element>()
const io = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.classList.add('reveal-visible')
io.unobserve(entry.target)
}
}
},
{ threshold: 0.12, rootMargin: '0px 0px -10% 0px' },
)
const observeExisting = () => {
document.querySelectorAll(selector).forEach((el) => {
if (!seen.has(el)) {
seen.add(el)
io.observe(el)
}
})
}
// Observe current DOM
observeExisting()
// Observe future DOM mutations (e.g., route changes render new sections)
const mo = new MutationObserver((mutations) => {
let needsScan = false
for (const m of mutations) {
if (m.type === 'childList' && (m.addedNodes?.length ?? 0) > 0) {
needsScan = true
}
if (needsScan) break
}
if (needsScan) observeExisting()
})
mo.observe(document.documentElement, { childList: true, subtree: true })
// Cleanup on HMR disposal (Vite dev) to avoid duplicate observers
if (import.meta && import.meta.hot) {
import.meta.hot.dispose(() => {
io.disconnect()
mo.disconnect()
w.__revealSetupDone = false
})
}
}
// Initialize after first render tick
queueMicrotask(setupReveal)