{"version":3,"file":"Scroll_Color_Text.HaCls8Jr.mjs","names":["useRef","useState","useMemo","React.Fragment","__esmMin","le","x","init_ssg_sandbox_shims","pe","init_npm_react_18_3_1","ce","p","init_jsx_runtime","_e","de","window","useTransform","useReducedMotion","motion","useMotionValue","init_framer_motion_DhsWWWsN","addPropertyControls","RenderTarget","init_framer_B1b760uK","ControlType","Letter","opacity","progress","range","color","from","to","char","useRevealProgress","raf","update","vh","v","inSticky","trackRef","r","span","finishAt","selfRef","schedule","ScrollColorText","props","ref","setInSticky","reduceMotion","stickyAware","el","revealProgress","highlightSet","highlightWords","normalize","lines","text","line","totalChars","n","w","renderContent","index","renderWords","words","target","word","highlightColor","endColor","letters","start","end","ci","scrollYProgress","startColor","wi","li","align","font","justify","style","textBalance","init_Scroll_Color_Text","s"],"sources":["https:/framerusercontent.com/modules/q5Fo9la5EkxxAN46JrSi/Fydq9iUW2gLj4BoPdIs0/Scroll_Color_Text.js"],"sourcesContent":["// Scroll Color Text — Synapse code component.\n// Reveals a heading letter by letter as it scrolls through the viewport: each letter\n// fades from 0.2 to 1 opacity and shifts from Start Color to End Color on a staggered\n// window of scroll progress (\"start 0.8\" -> \"start 0.2\"). Words listed in Highlight\n// Words (comma-separated, case- and punctuation-insensitive) end on Highlight Color.\n// Line breaks typed in Text are kept.\n// Controls: Text, Font (extended, alignment included), Start Color, End Color,\n// Highlight Words, Highlight Color, Text Balance (text-wrap: balance).\n// Sticky Aware: inside a sticky section the reveal follows the section's scroll track and\n// completes at Finish At (0-1) of it.\n// On the canvas the text shows its start colours (no scroll animation).\n// Reduced motion: renders the final colours with no scroll animation.\nimport{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import*as React from\"react\";import{useRef,useMemo,useState,useLayoutEffect,useEffect}from\"react\";import{addPropertyControls,ControlType,RenderTarget}from\"framer\";import{motion,useMotionValue,useTransform,useReducedMotion}from\"framer-motion\";const normalize=s=>s.toLowerCase().replace(RegExp(\"[^\\\\p{L}\\\\p{N}]+\",\"gu\"),\"\");function Letter({char,progress,range,from,to}){const opacity=useTransform(progress,range,[.2,1]);const color=useTransform(progress,range,[from,to]);return /*#__PURE__*/_jsx(motion.span,{style:{display:\"inline-block\",opacity,color},children:char});}// Scroll progress (0-1) measured directly from element positions on every scroll frame.\n// Sticky mode: progress across the sticky section's track (track top at viewport top -> track\n// bottom at viewport bottom), completing at `finishAt`. Normal mode: the text's own top moving\n// from 80% to 20% of the viewport height. Listens in the capture phase so it also works when\n// the page scrolls inside a container (e.g. editor previews).\nfunction useRevealProgress(selfRef,trackRef,inSticky,finishAt){const progress=useMotionValue(0);useEffect(()=>{// Canvas, thumbnails and exports show the start state; animate only in preview and live.\nif(RenderTarget.current()!==RenderTarget.preview){progress.set(0);return;}let raf=0;const update=()=>{raf=0;const vh=window.innerHeight||1;let v=0;if(inSticky&&trackRef.current){const r=trackRef.current.getBoundingClientRect();const span=Math.max(1,r.height-vh);v=-r.top/span/Math.max(.05,finishAt);}else if(selfRef.current){const r=selfRef.current.getBoundingClientRect();v=(.8*vh-r.top)/(.6*vh);}progress.set(Math.min(1,Math.max(0,v)));};const schedule=()=>{if(!raf)raf=requestAnimationFrame(update);};update();window.addEventListener(\"scroll\",schedule,{passive:true,capture:true});window.addEventListener(\"resize\",schedule);return()=>{window.removeEventListener(\"scroll\",schedule,{capture:true});window.removeEventListener(\"resize\",schedule);if(raf)cancelAnimationFrame(raf);};},[inSticky,finishAt]);return progress;}/**\r\n * @framerSupportedLayoutWidth any-prefer-fixed\r\n * @framerSupportedLayoutHeight auto\r\n */export default function ScrollColorText(props){const{text=\"Most marketing agencies guess with your ad spend. We use math.\",font={},startColor=\"rgba(255, 255, 255, 0.12)\",endColor=\"#FFFFFF\",highlightWords=\"math\",highlightColor=\"#FF5B19\",textBalance=true,stickyAware=true,finishAt=.8,style}=props;const ref=useRef(null);const trackRef=useRef(null);const[inSticky,setInSticky]=useState(false);const reduceMotion=useReducedMotion();// Inside a sticky section the text never moves while the section is stuck, so its own\n// position can't drive the reveal. Follow the sticky section's scroll track instead.\nuseLayoutEffect(()=>{if(!stickyAware||typeof window===\"undefined\")return setInSticky(false);let el=ref.current?.parentElement??null;while(el&&el!==document.body){if(getComputedStyle(el).position===\"sticky\"&&el.parentElement){trackRef.current=el.parentElement;return setInSticky(true);}el=el.parentElement;}setInSticky(false);},[stickyAware]);const revealProgress=useRevealProgress(ref,trackRef,inSticky,finishAt);const highlightSet=useMemo(()=>new Set((highlightWords||\"\").split(\",\").map(normalize).filter(Boolean)),[highlightWords]);// Line breaks typed in the Text field are kept; words wrap normally within a line.\nconst lines=(text||\"\").split(/\\r?\\n/).map(line=>line.split(/\\s+/).filter(Boolean));const totalChars=lines.flat().reduce((n,w)=>n+w.length,0)||1;const renderContent=scrollYProgress=>{let index=0;const renderWords=words=>words.map((word,wi)=>{const isHighlight=highlightSet.has(normalize(word));const target=isHighlight?highlightColor:endColor;const letters=Array.from(word).map((char,ci)=>{const start=index/totalChars;const end=start+1/totalChars;index++;if(reduceMotion){return /*#__PURE__*/_jsx(\"span\",{style:{display:\"inline-block\",color:target},children:char},ci);}return /*#__PURE__*/_jsx(Letter,{char:char,progress:scrollYProgress,range:[start,end],from:startColor,to:target},ci);});// Each word is its own flex item, so lines wrap at the container edge in every browser.\n    return /*#__PURE__*/_jsx(\"span\",{style:{display:\"inline-block\",whiteSpace:\"nowrap\",marginRight:wi<words.length-1?\"0.27em\":0},children:letters},wi);});return lines.map((words,li)=>/*#__PURE__*/_jsxs(React.Fragment,{children:[li>0?/*#__PURE__*/_jsx(\"span\",{\"aria-hidden\":true,style:{flexBasis:\"100%\",height:0}}):null,renderWords(words)]},li));};const align=String(font?.textAlign||font?.textAlignment||\"left\");const justify=align===\"center\"?\"center\":align===\"right\"||align===\"end\"?\"flex-end\":\"flex-start\";return /*#__PURE__*/_jsx(\"div\",{ref:ref,style:{...style,margin:0,...font,// Layout rules come after the font so nothing in it can stop wrapping.\nposition:\"relative\",width:\"100%\",maxWidth:\"100%\",minWidth:0,boxSizing:\"border-box\",whiteSpace:\"normal\",display:\"flex\",flexWrap:\"wrap\",alignItems:\"baseline\",justifyContent:justify,color:endColor,textWrap:textBalance?\"balance\":\"wrap\",wordBreak:\"normal\",overflowWrap:\"normal\"},children:renderContent(revealProgress)});}ScrollColorText.displayName=\"Scroll Color Text\";addPropertyControls(ScrollColorText,{text:{type:ControlType.String,title:\"Text\",displayTextArea:true,defaultValue:\"Most marketing agencies guess with your ad spend. We use math.\"},font:{type:ControlType.Font,title:\"Font\",controls:\"extended\",defaultFontType:\"sans-serif\",defaultValue:{fontSize:90,lineHeight:\"1em\",letterSpacing:\"-0.04em\",textAlign:\"center\"}},startColor:{type:ControlType.Color,title:\"Start Color\",defaultValue:\"rgba(255, 255, 255, 0.12)\"},endColor:{type:ControlType.Color,title:\"End Color\",defaultValue:\"#FFFFFF\"},highlightWords:{type:ControlType.String,title:\"Highlight Words\",defaultValue:\"math\",placeholder:\"math, data\"},highlightColor:{type:ControlType.Color,title:\"Highlight Color\",defaultValue:\"#FF5B19\"},stickyAware:{type:ControlType.Boolean,title:\"Sticky Aware\",defaultValue:true,enabledTitle:\"On\",disabledTitle:\"Off\",description:\"Inside a sticky section, reveal over the section's scroll track.\"},finishAt:{type:ControlType.Number,title:\"Finish At\",defaultValue:.8,min:.1,max:1,step:.05,hidden:p=>!p.stickyAware},textBalance:{type:ControlType.Boolean,title:\"Text Balance\",defaultValue:true,enabledTitle:\"On\",disabledTitle:\"Off\"}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"ScrollColorText\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\",\"framerSupportedLayoutHeight\":\"auto\",\"framerSupportedLayoutWidth\":\"any-prefer-fixed\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./Scroll_Color_Text.map"],"mappings":"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"}