{"version":3,"file":"Teletype.CP245ujN.mjs","names":["useRef","useState","useCallback","useLayoutEffect","useEffect"],"sources":["https:/framerusercontent.com/modules/S1jRTHrIvxcUK3l3x8GY/0fWDBJZh83PLIroxHtsl/Teletype.js"],"sourcesContent":["// Teletype: apply to a text layer. Its letters appear one by one as scrambled\n// wire-service characters, then settle into the real text, left to right.\n// The layer keeps its own text style; each letter's width is locked while it\n// scrambles so lines never jump, and the original text is put back at the end.\n//   withTeletype        plays when the layer scrolls into view\n//   withTeletypeOnLoad  plays on page load (several layers go one after another)\nimport{jsx as _jsx}from\"react/jsx-runtime\";import{forwardRef,useCallback,useEffect,useLayoutEffect,useRef,useState}from\"react\";import{useIsStaticRenderer}from\"framer\";import{useInView,useReducedMotion}from\"framer-motion\";const GLYPHS=\"#/%&*+=<>?@$0123456789ABCDEFGHJKLMNPQRSTUVWXYZ\";const SCRAMBLE_MS=420// how long each letter scrambles before settling\n;const TICK_MS=55// how often a scrambling letter swaps glyph\n;const STAGGER_MS=32// gap between letters starting\n;const MAX_SPREAD_MS=1100// long lines speed up so the last letter starts by then\n;const LOAD_DELAY_MS=150// first on-load layer\n;const LOAD_GAP_MS=260// each further on-load layer waits this much longer\n;const useIsomorphicLayoutEffect=typeof window!==\"undefined\"?useLayoutEffect:useEffect;// On-load layers queue up in the order they mount.\nlet loadQueue=0;let lastLoadMount=0;function nextLoadDelay(){const now=typeof performance!==\"undefined\"?performance.now():0;if(now-lastLoadMount>1500)loadQueue=0;lastLoadMount=now;return LOAD_DELAY_MS+LOAD_GAP_MS*loadQueue++;}function randomGlyph(){return GLYPHS[Math.floor(Math.random()*GLYPHS.length)];}// Runs the effect on the layer's own text. Returns a cleanup that stops it\n// and restores the original text nodes.\nfunction teletype(element,onDone){const walker=document.createTreeWalker(element,NodeFilter.SHOW_TEXT);const nodes=[];while(walker.nextNode()){const node=walker.currentNode;if(node.nodeValue&&node.nodeValue.trim())nodes.push(node);}// Measure every letter in the untouched text first, so kerning is kept\n// and the split-up letters take exactly the same room (same line breaks).\nconst scale=element.offsetWidth?element.getBoundingClientRect().width/element.offsetWidth||1:1;const range=document.createRange();const advances=[];for(const node of nodes){let offset=0;for(const char of Array.from(node.nodeValue??\"\")){if(!/\\s/.test(char)){range.setStart(node,offset);range.setEnd(node,offset+char.length);advances.push(range.getBoundingClientRect().width/scale);}offset+=char.length;}}const swaps=[];const cells=[];for(const node of nodes){const wrap=document.createElement(\"span\");for(const part of(node.nodeValue??\"\").split(/(\\s+)/)){if(!part)continue;if(/^\\s+$/.test(part)){wrap.appendChild(document.createTextNode(part));continue;}// Keep each word together so it wraps exactly like the real text.\nconst word=document.createElement(\"span\");word.style.display=\"inline-block\";word.style.whiteSpace=\"nowrap\";for(const char of Array.from(part)){const cell=document.createElement(\"span\");cell.textContent=char;cell.style.display=\"inline-block\";word.appendChild(cell);cells.push(cell);}wrap.appendChild(word);}node.parentNode?.replaceChild(wrap,node);swaps.push({original:node,replacement:wrap});}// Lock every letter to its measured width so swapping glyphs never\n// reflows the line.\ncells.forEach((cell,i)=>{cell.dataset.char=cell.textContent??\"\";cell.style.width=`${advances[i]??0}px`;cell.style.letterSpacing=\"0\";cell.style.textAlign=\"center\";cell.style.opacity=\"0\";});let restored=false;const restore=()=>{if(restored)return;restored=true;for(const{original,replacement}of swaps){replacement.parentNode?.replaceChild(original,replacement);}};const stagger=Math.min(STAGGER_MS,MAX_SPREAD_MS/Math.max(1,cells.length));const start=performance.now();let lastTick=-Infinity;let frame=0;const step=now=>{const elapsed=now-start;const tick=now-lastTick>=TICK_MS;if(tick)lastTick=now;let finished=true;cells.forEach((cell,i)=>{const begin=i*stagger;if(elapsed<begin){finished=false;return;}if(elapsed<begin+SCRAMBLE_MS){finished=false;if(cell.style.opacity===\"0\"){cell.style.opacity=\"1\";cell.textContent=randomGlyph();}else if(tick){cell.textContent=randomGlyph();}return;}if(cell.textContent!==cell.dataset.char){cell.textContent=cell.dataset.char??\"\";cell.style.opacity=\"1\";}});if(finished){restore();onDone();}else{frame=requestAnimationFrame(step);}};frame=requestAnimationFrame(step);return()=>{cancelAnimationFrame(frame);restore();};}function useTeletype(mode,forwardedRef,style){const isStatic=useIsStaticRenderer();const reduceMotion=useReducedMotion();const element=useRef(null);const[phase,setPhase]=useState(isStatic?\"done\":\"waiting\");const inView=useInView(element,{once:true,amount:.35});const setRef=useCallback(node=>{element.current=node;if(typeof forwardedRef===\"function\")forwardedRef(node);else if(forwardedRef)forwardedRef.current=node;},[forwardedRef]);// Never leave text hidden: no element to work on, or reduced motion, means\n// the text simply shows.\nuseEffect(()=>{if(!element.current||reduceMotion)setPhase(\"done\");},[reduceMotion]);// On load: take a place in the queue once, then start.\nuseEffect(()=>{if(phase!==\"waiting\"||mode!==\"load\")return;const timer=window.setTimeout(()=>setPhase(\"running\"),nextLoadDelay());return()=>window.clearTimeout(timer);},[phase,mode]);// In view: start as soon as enough of the layer is on screen.\nuseEffect(()=>{if(phase===\"waiting\"&&mode===\"view\"&&inView)setPhase(\"running\");},[phase,mode,inView]);useIsomorphicLayoutEffect(()=>{if(phase!==\"running\"||!element.current)return;return teletype(element.current,()=>setPhase(\"done\"));},[phase]);return{ref:setRef,style:phase===\"waiting\"?{...style,opacity:0}:style};}export function withTeletype(Component){return /*#__PURE__*/forwardRef(function Teletype(props,ref){const teletypeProps=useTeletype(\"view\",ref,props.style);return /*#__PURE__*/_jsx(Component,{...props,...teletypeProps});});}export function withTeletypeOnLoad(Component){return /*#__PURE__*/forwardRef(function TeletypeOnLoad(props,ref){const teletypeProps=useTeletype(\"load\",ref,props.style);return /*#__PURE__*/_jsx(Component,{...props,...teletypeProps});});}\nexport const __FramerMetadata__ = {\"exports\":{\"withTeletype\":{\"type\":\"reactHoc\",\"name\":\"withTeletype\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withTeletypeOnLoad\":{\"type\":\"reactHoc\",\"name\":\"withTeletypeOnLoad\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./Teletype.map"],"mappings":"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"}