{"version":3,"file":"ScrollCarousel.BugD6dH3.mjs","names":["useCallback","useRef"],"sources":["https:/framerusercontent.com/modules/r71T8cDxZutYvkKqkfNH/ItOEe1GzoGkO818HjlWh/ScrollCarousel.js"],"sourcesContent":["import{jsx as _jsx}from\"react/jsx-runtime\";import{useCallback,useEffect,useRef}from\"react\";// Jeder Slider bekommt seine eigene Variable. Teilen sich zwei Slider eine,\n// gewinnt der, der zuletzt rendert - und die Bedienelemente steuern dann den\n// falschen Slider. Deshalb hat auch das Review-Carousel weiter unten eine\n// eigene.\n// Kartenreihe von \"Mobile Slider v2\" (Tap-to-Snap + Kategorie-Optionen)\nlet tapScrollContainer=null;// Laeuft ein programmatischer Sprung, ist das Einrasten kurz aus. Der Timer\n// schaltet es wieder ein - siehe scrollToSpot.\nlet snapRestoreTimer=null;let snapRestore=null;function getHorizontalGap(container){if(typeof window===\"undefined\")return 0;const computedStyle=window.getComputedStyle(container);const columnGap=Number.parseFloat(computedStyle.columnGap);if(Number.isFinite(columnGap))return columnGap;const gap=Number.parseFloat((computedStyle.gap||\"0\").split(\" \")[0]);return Number.isFinite(gap)?gap:0;}// Wird auf die Kategorie-Optionen von \"Mobile Slider v2\" gelegt, um dessen\n// Scroll nach einem Variantenwechsel auf den Start zu setzen.\nexport function withScrollToStart(Component){return props=>{const handleClick=useCallback(event=>{if(typeof props.onClick===\"function\"){props.onClick(event);}if(typeof window===\"undefined\")return;const scrollToStart=()=>{if(!tapScrollContainer)return;scrollToSpot(tapScrollContainer,0);};window.requestAnimationFrame(()=>{scrollToStart();});window.setTimeout(()=>{scrollToStart();},60);},[props]);return /*#__PURE__*/_jsx(Component,{...props,onClick:handleClick});};}// Snap-Slider (Mobile Slider v2):\n// - Gewischt wird frei, beim Loslassen rastet die naechste Karte mittig ein.\n// - Die erste Karte bleibt linksbuendig, die letzte rechtsbuendig - dadurch\n//   schaut am Rand ein Stueck der Nachbarkarte heraus und man sieht, dass es\n//   weitergeht.\n// - Weiterschalten per Tap gibt es bewusst nicht (auf Wunsch entfernt).\n// - Registriert den Container zusaetzlich fuer withScrollToStart.\n// Zielposition und passender Einrastpunkt einer Karte - beides aus derselben\n// Rechnung. Laufen die beiden auseinander, zieht der Browser nach dem Tap\n// wieder zurueck und der Slider wirkt kaputt.\nfunction snapSpotFor(el,index){const list=Array.from(el.children);const card=list[index];if(!card)return null;const maxScroll=Math.max(0,el.scrollWidth-el.clientWidth);if(index===0)return{target:0,align:\"start\"};const left=card.getBoundingClientRect().left-el.getBoundingClientRect().left+el.scrollLeft;const width=card.getBoundingClientRect().width;const centered=left-(el.clientWidth-width)/2;// Laege der mittige Punkt hinter dem Scroll-Ende, waere er nicht\n// erreichbar. Dann rastet die Karte rechtsbuendig ein.\nif(centered>=maxScroll)return{target:maxScroll,align:\"end\"};return{target:Math.max(0,centered),align:\"center\"};}// Sprung zu einer Position.\n//\n// Bewusst der schlichte Browser-Weg. Die Zwei-Karten-Kategorien machen nichts\n// anderes und funktionieren zuverlaessig - jede Sonderbehandlung fuer drei\n// Karten hat es bisher nur wackliger gemacht.\n//\n// Waehrend des Sprungs wird das Einrasten abgeschaltet. Sonst haelt\n// scroll-snap-stop: always die Bewegung schon an der ersten Karte an, die sie\n// ueberstreicht - der Ruecksprung auf den Anfang kaeme nach einem\n// Kategoriewechsel nie dort an.\nfunction scrollToSpot(el,target){if(typeof window===\"undefined\"){el.scrollTo({left:target});return;}let rafId=0;const restore=()=>{if(rafId){window.cancelAnimationFrame(rafId);rafId=0;}el.style.scrollSnapType=\"x mandatory\";el.removeEventListener(\"pointerdown\",restore);if(snapRestoreTimer){window.clearTimeout(snapRestoreTimer);snapRestoreTimer=null;}if(snapRestore===restore)snapRestore=null;};// withScrollToStart springt zweimal kurz hintereinander. Der vorige Lauf\n// wird zuerst abgeschlossen, sonst bleibt sein Listener haengen.\nif(snapRestore)snapRestore();el.style.scrollSnapType=\"none\";el.scrollTo({left:target,behavior:\"smooth\"});// Erst wieder einschalten, wenn die Bewegung durch ist. Greift der Nutzer\n// vorher ein, uebernimmt er - dann sofort.\nel.addEventListener(\"pointerdown\",restore,{passive:true});snapRestore=restore;// Sobald der Sprung angekommen oder zum Stillstand gekommen ist, wird das\n// Einrasten sofort wieder eingeschaltet. Ein fester Timer waere entweder\n// zu kurz - dann bricht der Sprung ab - oder zu lang, und der erste Wisch\n// danach rutscht ungebremst durch.\nconst startedAt=Date.now();let last=el.scrollLeft;let still=0;const step=()=>{rafId=0;const now=el.scrollLeft;if(Math.abs(now-target)<=1){restore();return;}still=now===last?still+1:0;last=now;// Stillstand zaehlt erst, wenn die Bewegung ueberhaupt Zeit hatte\n// anzulaufen.\nif(still>=3&&Date.now()-startedAt>150){restore();return;}rafId=window.requestAnimationFrame(step);};rafId=window.requestAnimationFrame(step);// Notbremse, falls der Sprung nie ankommt.\nsnapRestoreTimer=window.setTimeout(restore,1200);}export function withTapSnap(Component){return props=>{const ref=useRef(null);useEffect(()=>{const el=ref.current;if(typeof window===\"undefined\"||!el)return;el.style.scrollSnapType=\"x mandatory\";const applySnap=()=>{// Nichts zu scrollen? Dann sind Rastpunkte gegenstandslos,\n// und eine Messung waere hier ohnehin unbrauchbar.\nif(el.scrollWidth-el.clientWidth<=1)return;// Framer tauscht beim Kategoriewechsel die Karten im selben\n// Container aus - das Einrasten wird hier deshalb jedes Mal\n// nachgezogen. Nur waehrend eines programmatischen Sprungs\n// nicht: der schaltet es bewusst ab.\nif(!snapRestore)el.style.scrollSnapType=\"x mandatory\";const list=Array.from(el.children);list.forEach((child,index)=>{const spot=snapSpotFor(el,index);child.style.scrollSnapAlign=spot?spot.align:\"center\";// Ohne scrollSnapStop traegt ein harter Wisch mit seinem\n// Schwung ueber alle Karten hinweg bis ans Scroll-Ende.\n// Das Einrasten greift dann erst dort und wirkt wie\n// ausgefallen. \"always\" zwingt den Browser, an jedem\n// Punkt zu halten, den die Bewegung ueberstreicht:\n// ein Wisch, eine Karte - unabhaengig davon, wie hart\n// gewischt wurde.\n//\n// Programmatische Spruenge (Kategoriewechsel) waeren\n// davon genauso betroffen und wuerden an der ersten Karte\n// haengen bleiben - deshalb schaltet scrollToSpot das\n// Einrasten fuer die Dauer des Sprungs ab.\nchild.style.scrollSnapStop=\"always\";});};// Die Rastpunkte kommen aus getBoundingClientRect. Direkt nach\n// einem Kategoriewechsel stehen die neuen Karten aber noch nicht\n// an ihrem Platz - zu frueh gemessen liefert das falsche Punkte,\n// und der Slider wischt danach frei durch. In der Startkategorie\n// faellt das nie auf, weil dort beim Mount schon alles steht.\n// Deshalb wird nach jeder Aenderung mehrfach nachgemessen.\nlet timers=[];let frame=0;const scheduleApply=()=>{applySnap();if(frame)window.cancelAnimationFrame(frame);frame=window.requestAnimationFrame(()=>{frame=0;applySnap();});timers.forEach(id=>window.clearTimeout(id));timers=[150,450,900].map(ms=>window.setTimeout(applySnap,ms));};scheduleApply();// Beim Kategoriewechsel werden die Karten ausgetauscht, und beim\n// Drehen aendern sich die Breiten - beides macht die\n// Einrastpunkte ungueltig.\nconst onChildren=typeof MutationObserver===\"undefined\"?null:new MutationObserver(scheduleApply);if(onChildren)onChildren.observe(el,{childList:true});const onResize=typeof ResizeObserver===\"undefined\"?null:new ResizeObserver(scheduleApply);if(onResize)onResize.observe(el);return()=>{if(onChildren)onChildren.disconnect();if(onResize)onResize.disconnect();if(frame)window.cancelAnimationFrame(frame);timers.forEach(id=>window.clearTimeout(id));timers=[];};},[]);return /*#__PURE__*/_jsx(Component,{...props,ref:node=>{ref.current=node;if(node)tapScrollContainer=node;}});};}// ---------------------------------------------------------------------------\n// Testimonials: Endlos-Carousel\n//\n// Im Canvas liegen drei identische Durchlaeufe der Rezensions-Liste\n// nebeneinander im Scroll-Container. Gescrollt wird immer im mittleren\n// Durchlauf. Sobald die Position den mittleren Bereich verlaesst, wird sie um\n// genau eine Durchlauf-Breite zurueckgesetzt. Weil links und rechts exakt der\n// gleiche Inhalt steht, ist dieser Sprung nicht zu sehen - es fuehlt sich an\n// wie eine endlose Reihe.\n// ---------------------------------------------------------------------------\n// Testimonials: eigener Container, damit Pricing- und Review-Carousel sich nicht gegenseitig steuern\nlet reviewScrollContainer=null;// Waehrend eines weichen Scrollens (Pfeil-Klick) darf nicht umgesetzt werden,\n// sonst bricht die laufende Bewegung ab.\nlet wrapSuppressedUntil=0;let settleTimer=null;// Abstand zwischen zwei gleichartigen Geschwistern. Direkt aus den\n// gemessenen Positionen, damit Abstaende und Umbrueche keine Rolle spielen.\nfunction siblingStride(parent){if(!parent)return 0;const kids=parent.children;if(kids.length>=2){const first=kids[0].getBoundingClientRect();const second=kids[1].getBoundingClientRect();const stride=second.left-first.left;if(stride>0)return stride;}// Rueckfallebene, falls nur ein Kind vorhanden ist\nconst only=kids[0];if(!only)return 0;return only.getBoundingClientRect().width+getHorizontalGap(parent);}// Breite eines kompletten Durchlaufs inklusive Abstand zum naechsten.\nfunction loopPeriod(container){return siblingStride(container);}// Breite einer einzelnen Rezensionskarte inklusive Abstand.\nfunction reviewCardStep(container){return siblingStride(container.firstElementChild);}// Holt die Scroll-Position zurueck in den mittleren Durchlauf.\nfunction normalizeLoop(container){const period=loopPeriod(container);if(period<=0)return 0;const left=container.scrollLeft;const lower=period*.5;const wrapped=((left-lower)%period+period)%period+lower;if(Math.abs(wrapped-left)>1)container.scrollLeft=wrapped;return period;}// Waehrend der Finger auf dem Slider liegt, wird die Position nur dann\n// verschoben, wenn der Vorrat an Karten sonst ausgeht - ein Sprung mitten\n// im Ziehen wuerde sich sonst ruckelig anfuehlen.\nlet pointerIsDown=false;// Nach dem Ende einer weichen Bewegung noch einmal sauber einnorden.\nfunction scheduleSettle(container){if(typeof window===\"undefined\")return;if(settleTimer)window.clearTimeout(settleTimer);settleTimer=window.setTimeout(()=>{settleTimer=null;normalizeLoop(container);},260);}// Ein Schritt nach links oder rechts, ohne Anfang und ohne Ende.\nfunction stepReviews(direction){const container=reviewScrollContainer;if(!container||typeof window===\"undefined\")return;// Erst einnorden, dann bewegen - so bleibt das Ziel im mittleren Bereich.\nnormalizeLoop(container);const step=reviewCardStep(container);if(step<=0)return;wrapSuppressedUntil=Date.now()+800;container.scrollBy({left:step*direction,behavior:\"smooth\"});scheduleSettle(container);}// Wird auf den Scroll-Container der Testimonials gelegt.\nexport function withReviewScrollContainer(Component){return props=>{const ref=useRef(null);useEffect(()=>{const el=ref.current;if(typeof window===\"undefined\"||!el)return;let started=false;let frame=0;// Beim Start in den mittleren Durchlauf springen. Bilder und\n// Schriften veraendern die Breite noch nach dem Mount, deshalb\n// wird erst gestartet, wenn eine Breite messbar ist.\nconst start=()=>{if(started)return;const period=loopPeriod(el);if(period<=0)return;started=true;el.scrollLeft=period;};const observer=typeof ResizeObserver===\"undefined\"?null:new ResizeObserver(()=>{if(started)return;start();});if(observer){observer.observe(el);const track=el.firstElementChild;if(track)observer.observe(track);}start();const onScroll=()=>{if(!started||frame)return;frame=window.requestAnimationFrame(()=>{frame=0;// Laeuft gerade eine weiche Bewegung? Nicht stoeren.\nif(Date.now()<wrapSuppressedUntil){scheduleSettle(el);return;}if(pointerIsDown){// Nur eingreifen, wenn sonst der Vorrat ausgeht.\nconst period=loopPeriod(el);const left=el.scrollLeft;const runway=el.scrollWidth-el.clientWidth;const nearEdge=period>0&&(left<period*.15||left>runway-period*.15);if(!nearEdge){scheduleSettle(el);return;}}normalizeLoop(el);});};const onPointerDown=()=>{pointerIsDown=true;};const onPointerUp=()=>{pointerIsDown=false;scheduleSettle(el);};el.addEventListener(\"scroll\",onScroll,{passive:true});el.addEventListener(\"pointerdown\",onPointerDown,{passive:true});window.addEventListener(\"pointerup\",onPointerUp,{passive:true});window.addEventListener(\"pointercancel\",onPointerUp,{passive:true});return()=>{if(observer)observer.disconnect();el.removeEventListener(\"scroll\",onScroll);el.removeEventListener(\"pointerdown\",onPointerDown);window.removeEventListener(\"pointerup\",onPointerUp);window.removeEventListener(\"pointercancel\",onPointerUp);pointerIsDown=false;if(frame)window.cancelAnimationFrame(frame);if(settleTimer){window.clearTimeout(settleTimer);settleTimer=null;}};},[]);return /*#__PURE__*/_jsx(Component,{...props,ref:node=>{ref.current=node;if(node)reviewScrollContainer=node;}});};}// Testimonials: rechter Pfeil\nexport function withReviewScrollRight(Component){return props=>{const handleClick=useCallback(event=>{if(typeof props.onClick===\"function\")props.onClick(event);stepReviews(1);},[props]);return /*#__PURE__*/_jsx(Component,{...props,onClick:handleClick});};}// Testimonials: linker Pfeil\nexport function withReviewScrollLeft(Component){return props=>{const handleClick=useCallback(event=>{if(typeof props.onClick===\"function\")props.onClick(event);stepReviews(-1);},[props]);return /*#__PURE__*/_jsx(Component,{...props,onClick:handleClick});};}\nexport const __FramerMetadata__ = {\"exports\":{\"withReviewScrollContainer\":{\"type\":\"reactHoc\",\"name\":\"withReviewScrollContainer\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withReviewScrollRight\":{\"type\":\"reactHoc\",\"name\":\"withReviewScrollRight\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withScrollToStart\":{\"type\":\"reactHoc\",\"name\":\"withScrollToStart\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withTapSnap\":{\"type\":\"reactHoc\",\"name\":\"withTapSnap\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withReviewScrollLeft\":{\"type\":\"reactHoc\",\"name\":\"withReviewScrollLeft\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./ScrollCarousel.map"],"mappings":"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"}