{"version":3,"file":"FavButtonDriver.Dkw-e-ya.mjs","names":["React.useState","React.useCallback"],"sources":["https:/framerusercontent.com/modules/gZlcEAsddEQ9GbKW5Rc2/ToUXj1ApKtW2XM9bBWKV/FavButtonDriver.js"],"sourcesContent":["// FavButtonDriver.tsx — global write coordinator (no lost clicks across cards)\nimport{jsx as _jsx}from\"react/jsx-runtime\";import*as React from\"react\";import{addPropertyControls,ControlType}from\"framer\";const FAVORITES_FIELD=\"Favorites\";const hasWindow=()=>typeof window!==\"undefined\";const w=()=>hasWindow()?window:undefined;const hasOutseta=()=>!!w()?.Outseta?.getUser;const sleep=ms=>new Promise(r=>setTimeout(r,ms));/* ---------------- parse / stringify ---------------- */function parseFavorites(raw){if(!raw)return[];try{if(typeof raw===\"string\"&&raw.trim().startsWith(\"[\")){const arr=JSON.parse(raw);return Array.isArray(arr)?arr.map(String):[];}if(Array.isArray(raw))return raw.map(String);}catch{}return String(raw).split(/[\\n,]/).map(s=>s.trim()).filter(Boolean);}const toJSONText=ids=>JSON.stringify(Array.from(new Set(ids)));function getBoot(){const win=w();if(!win)return{promise:null,listeners:new Set};win.__OP_FAV_BOOT__||={promise:null,listeners:new Set};return win.__OP_FAV_BOOT__;}function onFavEvent(cb){const b=getBoot();b.listeners.add(cb);return()=>{b.listeners.delete(cb);};}async function bootFavoritesOnce(){const b=getBoot();if(b.promise)return b.promise;b.promise=(async()=>{if(!hasWindow()||!hasOutseta()){try{getBoot().listeners.forEach(fn=>fn({type:\"boot\",favs:[],user:null}));}catch{}return null;}try{const user=await w().Outseta.getUser();const favs=parseFavorites(user?.[FAVORITES_FIELD]??user?.CustomProperties?.[FAVORITES_FIELD]);try{getBoot().listeners.forEach(fn=>fn({type:\"boot\",favs,user}));}catch{}return{user,favs};}catch{try{getBoot().listeners.forEach(fn=>fn({type:\"boot\",favs:[],user:null}));}catch{}return null;}})();return b.promise;}function emitPatch(id,add,user){try{getBoot().listeners.forEach(fn=>fn({type:\"patch\",id,add,user}));}catch{}}function getStore(){const win=w();if(!win)return{desired:new Set,seeded:false,inFlight:false,needsWrite:false};win.__OP_FAV_STORE__||={desired:new Set,seeded:false,inFlight:false,needsWrite:false};return win.__OP_FAV_STORE__;}/** Call once per page: seed desired set from Outseta boot */async function ensureSeeded(){const store=getStore();if(store.seeded)return;const res=await bootFavoritesOnce();if(res){store.desired=new Set(res.favs||[]);store.seeded=true;}else{// still mark seeded so clicks can proceed; writer will retry when Outseta is ready\nstore.seeded=true;}}/** Schedule a write so server matches store.desired (coalesces rapid changes) */async function scheduleWrite(){const store=getStore();if(store.inFlight){store.needsWrite=true;return;}store.inFlight=true;try{let spin=0;while(true){store.needsWrite=false;// Ensure Outseta is available; don't throw UI off if it's not ready yet\nif(!hasWindow()||!hasOutseta()){if(spin++>15)break;// ~4.5s max\nawait sleep(300);continue;}// Read current server list\nconst user=await w().Outseta.getUser();const onServer=new Set(parseFavorites(user?.[FAVORITES_FIELD]??user?.CustomProperties?.[FAVORITES_FIELD]));const want=new Set(getStore().desired);// If already matched, we’re done unless something changed mid-flight\nconst sameSize=onServer.size===want.size;const sameContent=sameSize&&[...want].every(id=>onServer.has(id));if(sameContent){if(!store.needsWrite)break;else continue;// loop and write again to catch new intents\n}// Write full desired list (atomic “last write wins” with full set)\nconst nextList=[...want];const updated=await user.update({[FAVORITES_FIELD]:toJSONText(nextList)});// Emit patches for others listening (only for diffs)\nconst after=new Set(nextList);for(const id of new Set([...onServer,...after])){const add=after.has(id);const was=onServer.has(id);if(add!==was)emitPatch(id,add,updated||user);}// If more changes queued during write, loop again\nif(!store.needsWrite)break;}}catch{// swallow; UI already reflects desired set; next click will resync\n}finally{getStore().inFlight=false;if(getStore().needsWrite)scheduleWrite();}}/* ---------------- icons ---------------- */const HEART_TUNED=\"M12 21c0 0-5.92-3.96-8.45-6.68C1.82 12.52 2.25 10.01 3.9 8.46c1.67-1.56 4.22-1.44 5.86.2L12 10.9l2.24-2.24c1.64-1.64 4.19-1.76 5.86-.2 1.66 1.55 2.09 4.06-.65 5.86C17.92 17.04 12 21 12 21z\";const HEART_CLASSIC=\"M12 21s-6.4-4.1-9-7.1C1.1 12 1 9.6 2.6 8.1c1.7-1.6 4.4-1.3 6 .3L12 11l3.4-2.6c1.6-1.6 4.3-1.9 6-.3 1.6 1.5 1.5 3.9-0.3 5.8C18.4 16.9 12 21 12 21z\";function HeartOutline({d,color,strokeWidth,scale=1,y=0}){return /*#__PURE__*/_jsx(\"svg\",{width:\"20\",height:\"20\",viewBox:\"0 0 24 24\",\"aria-hidden\":\"true\",children:/*#__PURE__*/_jsx(\"g\",{transform:`translate(0,${y}) scale(${scale}) translate(${12-12*scale},${12-12*scale})`,children:/*#__PURE__*/_jsx(\"path\",{d:d,fill:\"none\",stroke:color,strokeWidth:strokeWidth,strokeLinecap:\"round\",strokeLinejoin:\"round\",vectorEffect:\"non-scaling-stroke\"})})});}function HeartFilled({d,color,scale=1,y=0}){return /*#__PURE__*/_jsx(\"svg\",{width:\"20\",height:\"20\",viewBox:\"0 0 24 24\",\"aria-hidden\":\"true\",children:/*#__PURE__*/_jsx(\"g\",{transform:`translate(0,${y}) scale(${scale}) translate(${12-12*scale},${12-12*scale})`,children:/*#__PURE__*/_jsx(\"path\",{d:d,fill:color})})});}/* ---------------- component ---------------- */export default function FavButtonDriver({itemId,size,strokeWidth,hoverBg,inactiveStroke,activeHeart,hoverShadow,heartScale,heartYOffset,heartStyle}){const[isFav,setIsFav]=React.useState(false);const[hovered,setHovered]=React.useState(false);// Boot once per page & subscribe\nReact.useEffect(()=>{let alive=true;(async()=>{await ensureSeeded();const store=getStore();// reflect current desired state (seeded from boot or empty)\nsetIsFav(store.desired.has(itemId));})();const off=onFavEvent(ev=>{if(!alive)return;if(ev.type===\"boot\"){const store=getStore();store.desired=new Set(ev.favs||[]);store.seeded=true;setIsFav(store.desired.has(itemId));}else if(ev.type===\"patch\"&&ev.id===itemId){setIsFav(ev.add);}});return()=>{alive=false;off();};},[itemId]);const toggle=React.useCallback(()=>{const store=getStore();// Make sure we have a seed so desired is defined\nif(!store.seeded)store.seeded=true;// Instant local flip\nsetIsFav(v=>{const next=!v;// Update global desired set\nif(next)store.desired.add(itemId);else store.desired.delete(itemId);// Broadcast immediate patch so other hearts/cards sync visually\nemitPatch(itemId,next,null);// Ask coordinator to write the *whole* desired set\nscheduleWrite();return next;});},[itemId]);const d=heartStyle===\"Rounded\"?HEART_TUNED:HEART_CLASSIC;const styles={width:size,height:size,display:\"inline-flex\",alignItems:\"center\",justifyContent:\"center\",cursor:\"pointer\",border:\"none\",outline:\"none\",appearance:\"none\",background:hovered?hoverBg:\"transparent\",borderRadius:size,userSelect:\"none\",transition:\"background 120ms ease\",boxShadow:hovered&&hoverShadow?\"0 2px 8px rgba(0,0,0,0.08)\":\"none\"};return /*#__PURE__*/_jsx(\"button\",{\"data-testid\":\"fav-btn\",onClick:e=>{e.stopPropagation();e.preventDefault();toggle();},onPointerDown:e=>e.stopPropagation(),onTouchStart:e=>e.stopPropagation(),onMouseEnter:()=>setHovered(true),onMouseLeave:()=>setHovered(false),\"aria-pressed\":isFav,title:isFav?\"Remove from favourites\":\"Add to favourites\",style:styles,children:isFav?/*#__PURE__*/_jsx(HeartFilled,{d:d,color:activeHeart,scale:heartScale,y:heartYOffset}):/*#__PURE__*/_jsx(HeartOutline,{d:d,color:inactiveStroke,strokeWidth:strokeWidth,scale:heartScale,y:heartYOffset})});}/* ---------------- Framer controls ---------------- */addPropertyControls(FavButtonDriver,{itemId:{type:ControlType.String,title:\"Item ID\"},size:{type:ControlType.Number,title:\"Size\",defaultValue:32,min:20,max:80,step:1},strokeWidth:{type:ControlType.Number,title:\"Outline\",defaultValue:2.4,min:1,max:4,step:.1},hoverBg:{type:ControlType.Color,title:\"Hover BG\",defaultValue:\"#FFFFFF\"},inactiveStroke:{type:ControlType.Color,title:\"Default Heart\",defaultValue:\"#0E0E0E\"},activeHeart:{type:ControlType.Color,title:\"Active Heart\",defaultValue:\"#0E0E0E\"},hoverShadow:{type:ControlType.Boolean,title:\"Hover Shadow\",defaultValue:false},heartScale:{type:ControlType.Number,title:\"Heart Scale\",defaultValue:.965,min:.9,max:1.08,step:.005},heartYOffset:{type:ControlType.Number,title:\"Heart Y Offset\",defaultValue:.25,min:-2,max:2,step:.05},heartStyle:{type:ControlType.SegmentedEnum,title:\"Heart\",options:[\"Rounded\",\"Classic\"],optionTitles:[\"Rounded\",\"Classic\"],defaultValue:\"Rounded\"}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"FavButtonDriver\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./FavButtonDriver.map"],"mappings":"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"}