/* Effecten met GSAP, volgens de motion-regels van de Van Emous-huisstijl: tekst fadet 28px omhoog, uitvoer cubic-bezier(0.22, 1, 0.36, 1), alles uit bij prefers-reduced-motion, en na 3 s is alles hoe dan ook zichtbaar (zie de fx-wait-klasse in base.html). */ (() => { const root = document.documentElement; const reveal = () => root.classList.remove('fx-wait'); if (!window.gsap || matchMedia('(prefers-reduced-motion: reduce)').matches) return reveal(); gsap.registerEase?.('vanEmous', p => { // cubic-bezier(0.22, 1, 0.36, 1) benaderd: zachte, lange uitloop return 1 - Math.pow(1 - p, 4); }); const ease = 'vanEmous'; const $$ = (sel, ctx = document) => Array.from(ctx.querySelectorAll(sel)); const tl = gsap.timeline({ defaults: { ease, duration: 0.7 } }); // paginakop en meldingen const head = document.querySelector('.head'); if (head) tl.from(head.children, { y: 28, autoAlpha: 0, stagger: 0.08 }, 0); tl.from($$('.flash'), { y: -12, autoAlpha: 0, duration: 0.5 }, 0.05); // tegels, kaarten en filters in een golf const blocks = $$('.kpi, .filters, main .card, .portal-main .card, .auth .card, .auth > img'); tl.from(blocks.slice(0, 18), { y: 24, autoAlpha: 0, stagger: 0.05, clearProps: 'transform' }, 0.1); // tabelrijen kort na hun kaart (alleen de eerste, de rest staat er meteen) $$('.card tbody').forEach(tbody => { const rows = $$(':scope > tr', tbody).slice(0, 20); if (rows.length) tl.from(rows, { x: -8, autoAlpha: 0, duration: 0.45, stagger: 0.025 }, 0.3); }); tl.from($$('.timeline li').slice(0, 12), { y: 12, autoAlpha: 0, duration: 0.5, stagger: 0.04 }, 0.3); tl.from($$('.file, .member, .task').slice(0, 24), { y: 12, autoAlpha: 0, duration: 0.5, stagger: 0.03 }, 0.3); // balkjes groeien vanaf links / onder tl.from($$('.bar .fill'), { scaleX: 0, transformOrigin: '0 50%', duration: 1.1, stagger: 0.06 }, 0.35); tl.from($$('.cols .c'), { scaleY: 0, transformOrigin: '50% 100%', duration: 0.9, stagger: 0.04 }, 0.35); // kerncijfers tellen op (gehele getallen en eurobedragen) const nl = (n, dec) => n.toLocaleString('nl-NL', { minimumFractionDigits: dec, maximumFractionDigits: dec }); $$('.kpi .value').forEach(el => { const text = el.textContent.trim(); const euro = /^€\s?[\d.]+,\d{2}$/.test(text); if (!euro && !/^\d+$/.test(text)) return; const target = parseFloat(text.replace(/[€\s.]/g, '').replace(',', '.')); if (!target) return; const counter = { v: 0 }; tl.to(counter, { v: target, duration: 1.2, ease: 'power2.out', onUpdate: () => { el.textContent = euro ? '€ ' + nl(counter.v, 2) : nl(Math.round(counter.v), 0); }, onComplete: () => { el.textContent = text; }, }, 0.25); }); reveal(); setTimeout(() => tl.progress(1), 3000); // nieuwe offerteregel en geopende dialoog laten invliegen document.addEventListener('crm:row', e => gsap.from(e.detail, { y: -8, autoAlpha: 0, duration: 0.4, ease })); $$('dialog').forEach(d => new MutationObserver(() => { if (d.open) gsap.fromTo(d, { y: 16, autoAlpha: 0, scale: 0.98 }, { y: 0, autoAlpha: 1, scale: 1, duration: 0.45, ease }); }).observe(d, { attributes: true, attributeFilter: ['open'] })); })();