@fynd-design-engineering/fynd-one-v2 3.3.66 → 3.3.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("[media-card]").forEach(
|
|
1
|
+
"use strict";(()=>{document.addEventListener("DOMContentLoaded",()=>{let t=document.querySelectorAll("[media-card]"),s=window.innerWidth<992;t.forEach(e=>{let o=e.getAttribute("media-card"),n=e.getAttribute("media-card-hover")!=="false";o==="image"?f(e,n):o==="video-on-hover"?s?m(e,!1):p(e,n):o==="video-on-loop"&&m(e,n)})});function f(t,s){let e=t.querySelector("img");e&&(e.style.transition="transform 200ms ease",s&&(t.addEventListener("mouseenter",()=>{e.style.transform="scale(1)"}),t.addEventListener("mouseleave",()=>{e.style.transform="scale(1)"})))}function r(t,s=4){return t.play().catch(()=>new Promise((e,o)=>{if(s<=0){o();return}setTimeout(()=>{r(t,s-1).then(e).catch(o)},120)}))}function p(t,s){let e=t.querySelector("video"),o=t.querySelector("img");if(!e||!o||!!!(e.currentSrc||e.src))return;e.muted=!0,e.playsInline=!0,o.style.transition="opacity 200ms ease",e.style.transition="opacity 200ms ease, transform 200ms ease",e.style.transform="scale(1)",e.style.opacity="0",e.style.display="block",o.style.opacity="1";let n=!1,l=!1,i=()=>e.readyState>=HTMLMediaElement.HAVE_FUTURE_DATA,a=()=>{o.style.opacity="0",e.style.opacity="1"},d=()=>{o.style.opacity="1",e.style.opacity="0"},u=()=>{l=!0,n&&(e.loop=!0,r(e).catch(()=>{}))};e.addEventListener("ended",u),s&&(t.addEventListener("mouseenter",()=>{if(n=!0,e.style.transform="scale(1)",a(),i())r(e).catch(()=>{});else{let y=()=>{e.removeEventListener("canplay",y),a(),r(e).catch(()=>{})};e.addEventListener("canplay",y,{once:!0}),e.load()}}),t.addEventListener("mouseleave",()=>{n=!1,e.style.transform="scale(1)",e.loop=!1,e.pause(),d()}))}function m(t,s){let e=t.querySelector("video"),o=t.querySelector("img");if(!e||!!!(e.currentSrc||e.src))return;e.muted=!0,e.playsInline=!0,e.loop=!0,o&&(o.style.transition="opacity 200ms ease",o.style.opacity="1"),e.style.transition="opacity 200ms ease, transform 200ms ease",e.style.transform="scale(1)",e.style.opacity="0",e.style.display="block";let n=()=>e.readyState>=HTMLMediaElement.HAVE_FUTURE_DATA,l=()=>{o&&(o.style.opacity="0"),e.style.opacity="1"},i=()=>{l(),r(e).catch(()=>{})};if(n())i();else{let a=()=>{e.removeEventListener("canplay",a),i()};e.addEventListener("canplay",a,{once:!0}),e.load()}s&&(t.addEventListener("mouseenter",()=>{e.style.transform="scale(1)"}),t.addEventListener("mouseleave",()=>{e.style.transform="scale(1)"}))}})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../bin/live-reload.js", "../../src/global/media-card.ts"],
|
|
4
|
-
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n // console.log(\"Live reload disabled: not running on localhost\");\n}\n", "document.addEventListener(\"DOMContentLoaded\", () => {\n const cards = document.querySelectorAll<HTMLElement>(\"[media-card]\");\n\n cards.forEach(card => {\n const type = card.getAttribute(\"media-card\");\n const hoverAttr = card.getAttribute(\"media-card-hover\");\n const enableHover = hoverAttr !== \"false\";\n\n if (type === \"image\") {\n setupImageHover(card, enableHover);\n } else if (type === \"video-on-hover\") {\n setupVideoHover(card, enableHover);\n } else if (type === \"video-on-loop\") {\n setupVideoLoop(card, enableHover);\n }\n });\n});\n\nfunction setupImageHover(card: HTMLElement, enableHover: boolean) {\n const img = card.querySelector<HTMLImageElement>(\"img\");\n if (!img) return;\n\n img.style.transition = \"transform 200ms ease\";\n\n if (!enableHover) return;\n\n card.addEventListener(\"mouseenter\", () => {\n img.style.transform = \"scale(1
|
|
5
|
-
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AAAA,EAEP;;;ACVA,WAAS,iBAAiB,oBAAoB,MAAM;AAChD,UAAM,QAAQ,SAAS,iBAA8B,cAAc;
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n // console.log(\"Live reload disabled: not running on localhost\");\n}\n", "document.addEventListener(\"DOMContentLoaded\", () => {\n const cards = document.querySelectorAll<HTMLElement>(\"[media-card]\");\n const isSmallViewport = window.innerWidth < 992;\n\n cards.forEach(card => {\n const type = card.getAttribute(\"media-card\");\n const hoverAttr = card.getAttribute(\"media-card-hover\");\n const enableHover = hoverAttr !== \"false\";\n\n if (type === \"image\") {\n setupImageHover(card, enableHover);\n\n } else if (type === \"video-on-hover\") {\n // On small devices, treat hover videos like loop videos\n if (isSmallViewport) {\n setupVideoLoop(card, false);\n } else {\n setupVideoHover(card, enableHover);\n }\n\n } else if (type === \"video-on-loop\") {\n setupVideoLoop(card, enableHover);\n }\n });\n});\n\nfunction setupImageHover(card: HTMLElement, enableHover: boolean) {\n const img = card.querySelector<HTMLImageElement>(\"img\");\n if (!img) return;\n\n img.style.transition = \"transform 200ms ease\";\n\n if (!enableHover) return;\n\n card.addEventListener(\"mouseenter\", () => {\n img.style.transform = \"scale(1)\";\n });\n\n card.addEventListener(\"mouseleave\", () => {\n img.style.transform = \"scale(1)\";\n });\n}\n\nfunction attemptVideoPlay(video: HTMLVideoElement, retries = 4): Promise<void> {\n return video.play().catch(() => {\n return new Promise<void>((resolve, reject) => {\n if (retries <= 0) {\n reject();\n return;\n }\n\n setTimeout(() => {\n attemptVideoPlay(video, retries - 1).then(resolve).catch(reject);\n }, 120);\n });\n });\n}\n\nfunction setupVideoHover(card: HTMLElement, enableHover: boolean) {\n const video = card.querySelector<HTMLVideoElement>(\"video\");\n const img = card.querySelector<HTMLImageElement>(\"img\");\n if (!video || !img) return;\n\n const hasSrc = Boolean(video.currentSrc || video.src);\n if (!hasSrc) return;\n\n video.muted = true;\n video.playsInline = true;\n\n img.style.transition = \"opacity 200ms ease\";\n video.style.transition = \"opacity 200ms ease, transform 200ms ease\";\n video.style.transform = \"scale(1)\";\n video.style.opacity = \"0\";\n video.style.display = \"block\";\n img.style.opacity = \"1\";\n\n let hovering = false;\n let firstFullPlayDone = false;\n\n const isVideoReady = () =>\n video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA;\n\n const showVideo = () => {\n img.style.opacity = \"0\";\n video.style.opacity = \"1\";\n };\n\n const showImage = () => {\n img.style.opacity = \"1\";\n video.style.opacity = \"0\";\n };\n\n const onEnded = () => {\n firstFullPlayDone = true;\n if (hovering) {\n video.loop = true;\n attemptVideoPlay(video).catch(() => { });\n }\n };\n\n video.addEventListener(\"ended\", onEnded);\n\n if (!enableHover) return;\n\n card.addEventListener(\"mouseenter\", () => {\n hovering = true;\n video.style.transform = \"scale(1)\";\n showVideo();\n\n if (isVideoReady()) {\n attemptVideoPlay(video).catch(() => { });\n } else {\n const onCanPlay = () => {\n video.removeEventListener(\"canplay\", onCanPlay);\n showVideo();\n attemptVideoPlay(video).catch(() => { });\n };\n\n video.addEventListener(\"canplay\", onCanPlay, { once: true });\n video.load();\n }\n });\n\n card.addEventListener(\"mouseleave\", () => {\n hovering = false;\n video.style.transform = \"scale(1)\";\n video.loop = false;\n\n video.pause();\n showImage();\n });\n}\n\nfunction setupVideoLoop(card: HTMLElement, enableHover: boolean) {\n const video = card.querySelector<HTMLVideoElement>(\"video\");\n const img = card.querySelector<HTMLImageElement>(\"img\");\n if (!video) return;\n\n const hasSrc = Boolean(video.currentSrc || video.src);\n if (!hasSrc) return;\n\n video.muted = true;\n video.playsInline = true;\n video.loop = true;\n\n if (img) {\n img.style.transition = \"opacity 200ms ease\";\n img.style.opacity = \"1\";\n }\n\n video.style.transition = \"opacity 200ms ease, transform 200ms ease\";\n video.style.transform = \"scale(1)\";\n video.style.opacity = \"0\";\n video.style.display = \"block\";\n\n const isVideoReady = () =>\n video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA;\n\n const showVideo = () => {\n if (img) img.style.opacity = \"0\";\n video.style.opacity = \"1\";\n };\n\n const startPlayback = () => {\n showVideo();\n attemptVideoPlay(video).catch(() => { });\n };\n\n if (isVideoReady()) {\n startPlayback();\n } else {\n const onCanPlay = () => {\n video.removeEventListener(\"canplay\", onCanPlay);\n startPlayback();\n };\n\n video.addEventListener(\"canplay\", onCanPlay, { once: true });\n video.load();\n }\n\n if (enableHover) {\n card.addEventListener(\"mouseenter\", () => {\n video.style.transform = \"scale(1)\";\n });\n\n card.addEventListener(\"mouseleave\", () => {\n video.style.transform = \"scale(1)\";\n });\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{async function h(){try{let e=await fetch("https://ipwho.is/");if(!e.ok)throw new Error("Failed to fetch geolocation");let n=await e.json();return n.success===!1?(console.error("Geolocation lookup failed:",n.message),null):{ip:n.ip,country:n.country,region:n.region,city:n.city,latitude:n.latitude,longitude:n.longitude,isp:n.connection?.isp||"",timezone:n.timezone?.id||""}}catch(e){return console.error("Error fetching geolocation:",e),null}}var b="geo:data:v1",d="geo_country",g=7*24*60*60*1e3;function w(e,n,t){document.cookie=`${encodeURIComponent(e)}=${encodeURIComponent(n)}; Max-Age=${t}; Path=/; SameSite=Lax; Secure`}function C(e){let n=`${encodeURIComponent(e)}=`,t=document.cookie.split("; ");for(let o of t)if(o.startsWith(n))return decodeURIComponent(o.slice(n.length));return null}function A(e){try{let n=localStorage.getItem(e);if(!n)return null;let t=JSON.parse(n);return!t?.expiresAt||Date.now()>t.expiresAt?(localStorage.removeItem(e),null):t.data}catch{return localStorage.removeItem(e),null}}function B(e,n,t){let o={data:n,expiresAt:Date.now()+t};try{localStorage.setItem(e,JSON.stringify(o))}catch{}}async function f(e){if(typeof window>"u")return null;if(!(e?.forceRefresh??!1)){let o=A(b);if(o)return window.__GEO=o,C(d)||w(d,o.country??"",Math.floor(g/1e3)),o}let t=null;try{t=await h()}catch(o){console.warn("getGeolocation() failed; defaulting to India:",o)}return t||(t={country:"India"}),B(b,t,g),w(d,t.country??"",Math.floor(g/1e3)),window.__GEO=t,t}function v(){return C(d)}function x(e,n,t="auto"){let r=(window||{}).gsap;if(!r){console.warn("GSAP not found on window. Did you include it globally?");return}let i=document.querySelector(e),u=document.querySelector(n);if(!i||!u){console.warn("openBanner: Element(s) not found for selectors:",{mainSelector:e,innerSelector:n});return}r.set(i,{height:0,overflow:"hidden"}),r.set(u,{opacity:0});let s=r.timeline();return s.to(i,{height:t,duration:.5,ease:"power2.out"}),s.to(u,{opacity:1,duration:.3,ease:"power1.out"},.2),s}function S(e,n,t=0){let r=(window||{}).gsap;if(!r){console.warn("GSAP not found on window. Did you include it globally?");return}let i=document.querySelector(e),u=document.querySelector(n);if(!i||!u){console.warn("closeBanner: Element(s) not found for selectors:",{mainSelector:e,innerSelector:n});return}r.set(i,{overflow:"hidden"});let s=r.timeline();return s.to(u,{opacity:0,duration:.25,ease:"power1.out"}),s.to(i,{height:t,duration:.45,ease:"power2.inOut"},.2),s}function E(e,n,t){let o=new Date;o.setTime(o.getTime()+t*60*60*1e3),document.cookie=`${e}=${n}; expires=${o.toUTCString()}; path=/`}function T(e){let n=document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return n?n[2]:null}function m(){let e=window.innerWidth;return e>=992?"desktop":e>=768?"tablet":e>=480?"mobileLandscape":"mobilePortrait"}var l=[{country:"united arab emirates",aliases:["uae","u.a.e","united arab emirates"],countryCode:"ae",url:"/ae",tagline:"You're in the UAE. Welcome!"},{country:"saudi arabia",aliases:["saudi","ksa","kingdom of saudi arabia"],countryCode:"sa",url:"/sa",tagline:"Hello Saudi Arabia!"},{country:"south africa",aliases:["rsa"],countryCode:"za",url:"/za",tagline:"Hi South Africa!"},{country:"malaysia",countryCode:"my",url:"/my",tagline:"Selamat datang, Malaysia!"},{country:"indonesia",aliases:["idn"],countryCode:"id",url:"/id",tagline:"Halo Indonesia!"},{country:"philippines",aliases:["phl","the philippines"],countryCode:"ph",url:"/ph",tagline:"Kumusta, Philippines!"},{country:"india",aliases:["bharat"],countryCode:"in",url:"/in",tagline:"This country is India. Hi some text"},{country:"global",aliases:["global","rest of world","others"],countryCode:"global",url:"/global",tagline:"This is rest of world. Hi some text"}];function c(e){return(e??"").trim().toLowerCase()}function k(e){let n=e.trim();return n?n.startsWith("/")?n:`/${n}`:"/"}async function $(){if(typeof window>"u")return null;let e=v();if(e)return c(e);let n=await f();return c(n?.country)}function L(e){let n=c(e);if(!n)return null;let t=l.find(i=>c(i.countryCode)===n);if(t)return t;let o=l.find(i=>c(i.country)===n);if(o)return o;let r=l.find(i=>(i.aliases??[]).some(u=>c(u)===n));return r||null}function p(){let e=l.find(n=>n.country==="global");if(!e)throw new Error("[geo-banner] Global config not found in COUNTRY_CONFIG");return e}function N(e){if(typeof window>"u")return;let n=c(e),t=l.find(r=>c(r.countryCode)===n)||p(),o=document.querySelector('[fynd-banner-field="link"]');if(o){let r=window.location.origin;o.href=`${r}${k(t.url)}`}}function R(e,n){let t=L(n)??l.find(s=>s.country==="global");if(!t)return console.warn("[geo-banner] No matching config for",n),!1;let o=t.countryCode,r=Array.from(e.options),i=r.find(s=>c(s.value)===c(o));if(!i)return console.warn("[geo-banner] No matching <option> for",o,"on",e),!1;let u=e.value;return e.value=i.value,e.value!==i.value&&(e.selectedIndex=r.indexOf(i)),r.forEach(s=>s.selected=s===i),u!==e.value&&(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))),console.log("[geo-banner] Select updated \u2192",t.country,"(",t.countryCode,")"),!0}function q(e){if(typeof window>"u")return;let n=c(e),t=l.find(i=>c(i.countryCode)===n)||p(),o=document.querySelector("#geoswitch-select")||document.querySelector('[fynd-banner-field="geoswitch"]');o?(console.log(`country code is ${t.countryCode}`),R(o,t.countryCode),o.value=t.countryCode,o.dispatchEvent(new Event("change",{bubbles:!0}))):console.warn('[geo-banner] Select not found: #geoswitch-select / [fynd-banner-field="geoswitch"]');let r=document.querySelector('[fynd-banner-field="link"]');if(r){let i=window.location.origin;r.href=`${i}${k(t.url)}`}}async function G(){if(typeof window>"u")return p();document.readyState==="loading"&&await new Promise(r=>{document.addEventListener("DOMContentLoaded",()=>r(),{once:!0})});let e=await $(),t=L(e)??p();console.log("[geo-banner] rawCountry:",e,"\u2192 resolved:",t.countryCode),q(t.countryCode);let o=document.querySelector('[fynd-banner-field="geoswitch"]');return o&&!o.__geoHandlerAttached&&(o.addEventListener("change",r=>{let i=r.target.value;N(i)}),o.__geoHandlerAttached=!0),t}var I={"/global":{mode:"country",countries:["India"]},"/":{mode:"notCountry",countries:["India"]}},M='[fynd-navigation="ip-banner"]',D='[fynd-navigation="ip-banner-inner"]',F='[fynd-navigation="ip-banner-close"]',se=document.querySelector('[fynd-navigation="announcement-bar"]'),ce=document.querySelector('[fynd-navigation="announcement-list"]'),a={ipbanner:{visibility:!1,height:{desktop:"56px",tablet:"60px",mobileLandscape:"120px",mobilePortrait:"120px"}},announcementbar:{visibility:!
|
|
1
|
+
"use strict";(()=>{async function h(){try{let e=await fetch("https://ipwho.is/");if(!e.ok)throw new Error("Failed to fetch geolocation");let n=await e.json();return n.success===!1?(console.error("Geolocation lookup failed:",n.message),null):{ip:n.ip,country:n.country,region:n.region,city:n.city,latitude:n.latitude,longitude:n.longitude,isp:n.connection?.isp||"",timezone:n.timezone?.id||""}}catch(e){return console.error("Error fetching geolocation:",e),null}}var b="geo:data:v1",d="geo_country",g=7*24*60*60*1e3;function w(e,n,t){document.cookie=`${encodeURIComponent(e)}=${encodeURIComponent(n)}; Max-Age=${t}; Path=/; SameSite=Lax; Secure`}function C(e){let n=`${encodeURIComponent(e)}=`,t=document.cookie.split("; ");for(let o of t)if(o.startsWith(n))return decodeURIComponent(o.slice(n.length));return null}function A(e){try{let n=localStorage.getItem(e);if(!n)return null;let t=JSON.parse(n);return!t?.expiresAt||Date.now()>t.expiresAt?(localStorage.removeItem(e),null):t.data}catch{return localStorage.removeItem(e),null}}function B(e,n,t){let o={data:n,expiresAt:Date.now()+t};try{localStorage.setItem(e,JSON.stringify(o))}catch{}}async function f(e){if(typeof window>"u")return null;if(!(e?.forceRefresh??!1)){let o=A(b);if(o)return window.__GEO=o,C(d)||w(d,o.country??"",Math.floor(g/1e3)),o}let t=null;try{t=await h()}catch(o){console.warn("getGeolocation() failed; defaulting to India:",o)}return t||(t={country:"India"}),B(b,t,g),w(d,t.country??"",Math.floor(g/1e3)),window.__GEO=t,t}function v(){return C(d)}function x(e,n,t="auto"){let r=(window||{}).gsap;if(!r){console.warn("GSAP not found on window. Did you include it globally?");return}let i=document.querySelector(e),u=document.querySelector(n);if(!i||!u){console.warn("openBanner: Element(s) not found for selectors:",{mainSelector:e,innerSelector:n});return}r.set(i,{height:0,overflow:"hidden"}),r.set(u,{opacity:0});let s=r.timeline();return s.to(i,{height:t,duration:.5,ease:"power2.out"}),s.to(u,{opacity:1,duration:.3,ease:"power1.out"},.2),s}function S(e,n,t=0){let r=(window||{}).gsap;if(!r){console.warn("GSAP not found on window. Did you include it globally?");return}let i=document.querySelector(e),u=document.querySelector(n);if(!i||!u){console.warn("closeBanner: Element(s) not found for selectors:",{mainSelector:e,innerSelector:n});return}r.set(i,{overflow:"hidden"});let s=r.timeline();return s.to(u,{opacity:0,duration:.25,ease:"power1.out"}),s.to(i,{height:t,duration:.45,ease:"power2.inOut"},.2),s}function E(e,n,t){let o=new Date;o.setTime(o.getTime()+t*60*60*1e3),document.cookie=`${e}=${n}; expires=${o.toUTCString()}; path=/`}function T(e){let n=document.cookie.match(new RegExp("(^| )"+e+"=([^;]+)"));return n?n[2]:null}function m(){let e=window.innerWidth;return e>=992?"desktop":e>=768?"tablet":e>=480?"mobileLandscape":"mobilePortrait"}var l=[{country:"united arab emirates",aliases:["uae","u.a.e","united arab emirates"],countryCode:"ae",url:"/ae",tagline:"You're in the UAE. Welcome!"},{country:"saudi arabia",aliases:["saudi","ksa","kingdom of saudi arabia"],countryCode:"sa",url:"/sa",tagline:"Hello Saudi Arabia!"},{country:"south africa",aliases:["rsa"],countryCode:"za",url:"/za",tagline:"Hi South Africa!"},{country:"malaysia",countryCode:"my",url:"/my",tagline:"Selamat datang, Malaysia!"},{country:"indonesia",aliases:["idn"],countryCode:"id",url:"/id",tagline:"Halo Indonesia!"},{country:"philippines",aliases:["phl","the philippines"],countryCode:"ph",url:"/ph",tagline:"Kumusta, Philippines!"},{country:"india",aliases:["bharat"],countryCode:"in",url:"/in",tagline:"This country is India. Hi some text"},{country:"global",aliases:["global","rest of world","others"],countryCode:"global",url:"/global",tagline:"This is rest of world. Hi some text"}];function c(e){return(e??"").trim().toLowerCase()}function k(e){let n=e.trim();return n?n.startsWith("/")?n:`/${n}`:"/"}async function $(){if(typeof window>"u")return null;let e=v();if(e)return c(e);let n=await f();return c(n?.country)}function L(e){let n=c(e);if(!n)return null;let t=l.find(i=>c(i.countryCode)===n);if(t)return t;let o=l.find(i=>c(i.country)===n);if(o)return o;let r=l.find(i=>(i.aliases??[]).some(u=>c(u)===n));return r||null}function p(){let e=l.find(n=>n.country==="global");if(!e)throw new Error("[geo-banner] Global config not found in COUNTRY_CONFIG");return e}function N(e){if(typeof window>"u")return;let n=c(e),t=l.find(r=>c(r.countryCode)===n)||p(),o=document.querySelector('[fynd-banner-field="link"]');if(o){let r=window.location.origin;o.href=`${r}${k(t.url)}`}}function R(e,n){let t=L(n)??l.find(s=>s.country==="global");if(!t)return console.warn("[geo-banner] No matching config for",n),!1;let o=t.countryCode,r=Array.from(e.options),i=r.find(s=>c(s.value)===c(o));if(!i)return console.warn("[geo-banner] No matching <option> for",o,"on",e),!1;let u=e.value;return e.value=i.value,e.value!==i.value&&(e.selectedIndex=r.indexOf(i)),r.forEach(s=>s.selected=s===i),u!==e.value&&(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))),console.log("[geo-banner] Select updated \u2192",t.country,"(",t.countryCode,")"),!0}function q(e){if(typeof window>"u")return;let n=c(e),t=l.find(i=>c(i.countryCode)===n)||p(),o=document.querySelector("#geoswitch-select")||document.querySelector('[fynd-banner-field="geoswitch"]');o?(console.log(`country code is ${t.countryCode}`),R(o,t.countryCode),o.value=t.countryCode,o.dispatchEvent(new Event("change",{bubbles:!0}))):console.warn('[geo-banner] Select not found: #geoswitch-select / [fynd-banner-field="geoswitch"]');let r=document.querySelector('[fynd-banner-field="link"]');if(r){let i=window.location.origin;r.href=`${i}${k(t.url)}`}}async function G(){if(typeof window>"u")return p();document.readyState==="loading"&&await new Promise(r=>{document.addEventListener("DOMContentLoaded",()=>r(),{once:!0})});let e=await $(),t=L(e)??p();console.log("[geo-banner] rawCountry:",e,"\u2192 resolved:",t.countryCode),q(t.countryCode);let o=document.querySelector('[fynd-banner-field="geoswitch"]');return o&&!o.__geoHandlerAttached&&(o.addEventListener("change",r=>{let i=r.target.value;N(i)}),o.__geoHandlerAttached=!0),t}var I={"/global":{mode:"country",countries:["India"]},"/":{mode:"notCountry",countries:["India"]}},M='[fynd-navigation="ip-banner"]',D='[fynd-navigation="ip-banner-inner"]',F='[fynd-navigation="ip-banner-close"]',se=document.querySelector('[fynd-navigation="announcement-bar"]'),ce=document.querySelector('[fynd-navigation="announcement-list"]'),a={ipbanner:{visibility:!1,height:{desktop:"56px",tablet:"60px",mobileLandscape:"120px",mobilePortrait:"120px"}},announcementbar:{visibility:!1,height:{desktop:"40px",tablet:"40px",mobileLandscape:"40px",mobilePortrait:"46px"}},default:{visibility:!0,height:{desktop:"70px",tablet:"64px",mobileLandscape:"40px",mobilePortrait:"64px"}}};window.navigationData=a;function y(e,n){let t=o=>{if(typeof o=="number")return o;let r=parseInt(o,10);return isNaN(r)?0:r};return`${t(e)+t(n)}px`}function H(e,n){let t=o=>{if(typeof o=="number")return o;let r=parseInt(o,10);return isNaN(r)?0:r};return`${t(e)-t(n)}px`}var P=e=>{try{let n=e.split("?")[0].split("#")[0];return n==="/"?"/":n.replace(/\/+$/,"")||"/"}catch{return"/"}};function U(e){let n=P(e),t="";for(let o of Object.keys(I)){let r=P(o);(n===r||n.startsWith(r+"/"))&&r.length>t.length&&(t=r)}return t?{key:t,rule:I[t]}:null}function Y(e,n){let t=U(e);if(!t)return!1;let{rule:o}=t,r=(n?.country||"").toLowerCase();switch(o.mode){case"always":return!0;case"country":return o.countries.some(i=>i.toLowerCase()===r);case"notCountry":return!o.countries.some(i=>i.toLowerCase()===r);case"predicate":return!!o.test?.(n);default:return!1}}function z(){let e=document.querySelector('[fynd-navigation="announcement-swiper"]');if(e&&!e.__swiperInstance)try{let n=window.Swiper,t=new n(e,{slidesPerView:1,spaceBetween:0,effect:"fade",fadeEffect:{crossFade:!0},autoplay:{delay:3e3,disableOnInteraction:!1},loop:!0,speed:1e3,allowTouchMove:!1,on:{init:function(){this.slides.length<=1&&this.autoplay&&typeof this.autoplay.stop=="function"&&this.autoplay.stop()}}});e.__swiperInstance=t}catch(n){console.warn("Announcement Swiper init failed:",n)}}function _(){let e='[fynd-navigation="dropdown-container"]',n=document.querySelector(e);if(!n){console.warn(`initDesktopDropdownMenu: element not found: ${e}`);return}let t=m?.()??"unknown";if(t!=="desktop"){n.style.transition=n.style.transition||"transform 0.3s ease",n.style.transform="translateY(0px)";return}let o=a.default.height?.[t],r=!1;if(a.announcementbar?.visibility){let i=a.announcementbar.height?.[t];o=y(o,i),o=H(o,"46px"),r=!0}a.ipbanner?.visibility&&(o=y(o,"0px"),r||(o=H(o,"46px"))),n.style.transform=`translateY(${o})`}function O(){let e=document.querySelector('[fynd-navigation="spacer"][data-wf--navigation-spacer--variant="dynamic"]');if(!e){console.warn("initNavigationSpacer: spacer element not found");return}let n=r=>{if(typeof r=="number")return r;if(typeof r=="string"){let i=parseFloat(r);return Number.isFinite(i)?i:0}return 0},t=m?.()??"desktop",o=a.default.height?.[t];if(a.announcementbar?.visibility){let r=a.announcementbar.height?.[t];o=y(o,r)}if(a.ipbanner?.visibility){let r=n(a.ipbanner.height?.[t]);o=y(o,r)}e.style.height=`${o}`}async function K(){if(T("ipBannerClosed")==="true"){a.ipbanner.visibility=!1;return}let n=await f(),t=window.location.pathname||"/",o=Y(t,n??void 0),r=await G();if(o&&r){x(M,D,a.ipbanner.height.desktop),a.ipbanner.visibility=!0;let i=document.querySelector(F);i&&i.addEventListener("click",()=>{S(M,D),E("ipBannerClosed","true",24),a.ipbanner.visibility=!1,_(),O()})}else a.ipbanner.visibility=!1}document.addEventListener("DOMContentLoaded",async()=>{await K(),z(),_(),O()});})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../bin/live-reload.js", "../../src/global/geolocation/main.ts", "../../src/global/geolocation/geolocation-cached.ts", "../../src/global/animation/toggle-banner.ts", "../../src/utils/cookies.ts", "../../src/global/screen-type.ts", "../../src/navigation/country-detection/main.ts", "../../src/navigation/initialization.ts"],
|
|
4
|
-
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n // console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// Define the type for returned geolocation data\n// Remider for adding Fallback: ipinfo.io (HTTPS, requires token)\nexport type GeoData = {\n ip: string;\n country: string;\n region: string;\n city: string;\n latitude: number;\n longitude: number;\n isp: string;\n timezone: string;\n };\n \n // Exported function that can be reused anywhere\n export async function getGeolocation(): Promise<GeoData | null> {\n try {\n const response = await fetch(\"https://ipwho.is/\");\n if (!response.ok) {\n throw new Error(\"Failed to fetch geolocation\");\n }\n \n const data = await response.json();\n \n if (data.success === false) {\n console.error(\"Geolocation lookup failed:\", data.message);\n return null;\n }\n \n return {\n ip: data.ip,\n country: data.country,\n region: data.region,\n city: data.city,\n latitude: data.latitude,\n longitude: data.longitude,\n isp: data.connection?.isp || \"\",\n timezone: data.timezone?.id || \"\"\n };\n } catch (error) {\n console.error(\"Error fetching geolocation:\", error);\n return null;\n }\n }\n\n //used in /src/navigation/initialization.ts for displaying ip banner", "import { GeoData, getGeolocation } from \"./main\";\n\nconst GEO_CACHE_KEY = \"geo:data:v1\";\nconst GEO_COOKIE_KEY = \"geo_country\";\nconst GEO_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\n\ntype Cached<T> = { data: T; expiresAt: number };\n\n// --- Cookie helpers ---\nfunction setCookie(name: string, value: string, maxAgeSec: number) {\n document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(\n value\n )}; Max-Age=${maxAgeSec}; Path=/; SameSite=Lax; Secure`;\n}\n\nfunction getCookie(name: string): string | null {\n const key = `${encodeURIComponent(name)}=`;\n const parts = document.cookie.split(\"; \");\n for (const p of parts) {\n if (p.startsWith(key)) return decodeURIComponent(p.slice(key.length));\n }\n return null;\n}\n\nfunction clearCookie(name: string) {\n document.cookie = `${encodeURIComponent(\n name\n )}=; Max-Age=0; Path=/; SameSite=Lax; Secure`;\n}\n\n// --- LocalStorage helpers ---\nfunction readCache<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Cached<T>;\n if (!parsed?.expiresAt || Date.now() > parsed.expiresAt) {\n localStorage.removeItem(key);\n return null;\n }\n return parsed.data;\n } catch {\n localStorage.removeItem(key);\n return null;\n }\n}\n\nfunction writeCache<T>(key: string, data: T, ttlMs: number) {\n const payload: Cached<T> = { data, expiresAt: Date.now() + ttlMs };\n try {\n localStorage.setItem(key, JSON.stringify(payload));\n } catch {\n // ignore quota errors\n }\n}\n\n// --- Public API ---\nexport async function getGeolocationCached(options?: {\n forceRefresh?: boolean;\n}): Promise<GeoData | null> {\n if (typeof window === \"undefined\") return null;\n\n const forceRefresh = options?.forceRefresh ?? false;\n\n if (!forceRefresh) {\n const cached = readCache<GeoData>(GEO_CACHE_KEY);\n if (cached) {\n (window as any).__GEO = cached;\n if (!getCookie(GEO_COOKIE_KEY)) {\n setCookie(\n GEO_COOKIE_KEY,\n cached.country ?? \"\",\n Math.floor(GEO_TTL_MS / 1000)\n );\n }\n return cached;\n }\n }\n\n // \u2B07\uFE0F changed block starts here\n let geo: GeoData | null = null;\n try {\n geo = await getGeolocation();\n } catch (e) {\n console.warn(\"getGeolocation() failed; defaulting to India:\", e);\n }\n\n if (!geo) {\n // Fallback to India if the fetch failed or returned invalid data\n geo = { country: \"India\" } as GeoData;\n }\n\n writeCache(GEO_CACHE_KEY, geo, GEO_TTL_MS);\n setCookie(GEO_COOKIE_KEY, geo.country ?? \"\", Math.floor(GEO_TTL_MS / 1000));\n (window as any).__GEO = geo;\n return geo;\n // \u2B06\uFE0F changed block ends here\n}\n\nexport function getGeoCountryFromCookie(): string | null {\n return getCookie(GEO_COOKIE_KEY);\n}\n\nexport function clearGeolocationCache() {\n try {\n localStorage.removeItem(GEO_CACHE_KEY);\n } catch {}\n clearCookie(GEO_COOKIE_KEY);\n if (typeof window !== \"undefined\") {\n (window as any).__GEO = undefined;\n }\n}\n", "// toggleBanner.ts\n// Utility functions to open/close a banner using GSAP with optional target height.\n\nexport function openBanner(\n mainSelector: string,\n innerSelector: string,\n targetHeight: string | number = \"auto\" // default stays \"auto\"\n) {\n const w = (window as any) || {};\n const gsap = w.gsap as any;\n if (!gsap) {\n console.warn(\"GSAP not found on window. Did you include it globally?\");\n return;\n }\n\n const mainEl = document.querySelector<HTMLElement>(mainSelector);\n const innerEl = document.querySelector<HTMLElement>(innerSelector);\n\n if (!mainEl || !innerEl) {\n console.warn(\"openBanner: Element(s) not found for selectors:\", {\n mainSelector,\n innerSelector,\n });\n return;\n }\n\n // Ensure clean start\n gsap.set(mainEl, { height: 0, overflow: \"hidden\" });\n gsap.set(innerEl, { opacity: 0 });\n\n const tl = gsap.timeline();\n\n // Animate main from height: 0 -> targetHeight\n tl.to(mainEl, {\n height: targetHeight,\n duration: 0.5,\n ease: \"power2.out\",\n });\n\n // After 0.2s, fade inner to 1\n tl.to(\n innerEl,\n {\n opacity: 1,\n duration: 0.3,\n ease: \"power1.out\",\n },\n 0.2\n );\n\n return tl;\n}\n\nexport function closeBanner(\n mainSelector: string,\n innerSelector: string,\n targetHeight: string | number = 0 // default collapse fully\n) {\n const w = (window as any) || {};\n const gsap = w.gsap as any;\n if (!gsap) {\n console.warn(\"GSAP not found on window. Did you include it globally?\");\n return;\n }\n\n const mainEl = document.querySelector<HTMLElement>(mainSelector);\n const innerEl = document.querySelector<HTMLElement>(innerSelector);\n\n if (!mainEl || !innerEl) {\n console.warn(\"closeBanner: Element(s) not found for selectors:\", {\n mainSelector,\n innerSelector,\n });\n return;\n }\n\n gsap.set(mainEl, { overflow: \"hidden\" });\n\n const tl = gsap.timeline();\n\n // Fade inner out\n tl.to(innerEl, {\n opacity: 0,\n duration: 0.25,\n ease: \"power1.out\",\n });\n\n // Collapse height to targetHeight (default 0)\n tl.to(\n mainEl,\n {\n height: targetHeight,\n duration: 0.45,\n ease: \"power2.inOut\",\n },\n 0.2\n );\n\n return tl;\n}", "export function setCookie(name: string, value: string, hours: number) {\n const date = new Date();\n date.setTime(date.getTime() + hours * 60 * 60 * 1000);\n document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/`;\n }\n \n export function getCookie(name: string): string | null {\n const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));\n return match ? match[2] : null;\n }", "// screen-type.ts\n// Utility to get the current screen type\n// Breakpoints:\n// - Desktop: 992px+\n// - Tablet: 768px\u2013991px\n// - Mobile Landscape: 480px\u2013767px\n// - Mobile Portrait: under 480px\n\nexport type ScreenType = \"desktop\" | \"tablet\" | \"mobileLandscape\" | \"mobilePortrait\";\n\nexport function getScreenType(): ScreenType {\n const width = window.innerWidth;\n\n if (width >= 992) {\n return \"desktop\";\n } else if (width >= 768) {\n return \"tablet\";\n } else if (width >= 480) {\n return \"mobileLandscape\";\n } else {\n return \"mobilePortrait\";\n }\n}", "// geo.ts\nimport { getGeoCountryFromCookie, getGeolocationCached } from \"src/global/geolocation/geolocation-cached\";\nimport { GeoData } from \"src/global/geolocation/main\";\n\n/** Your banner config */\ntype CountryConfig = {\n country: string; // canonical lowercase name\n countryCode: string; // ISO-2 lowercase code (e.g., \"in\")\n url: string; // leading-slash path (e.g., \"/in\")\n tagline: string; // banner text/html\n aliases?: string[]; // optional extra names to match against\n};\n\nexport const COUNTRY_CONFIG: CountryConfig[] = [\n {\n country: \"united arab emirates\",\n aliases: [\"uae\", \"u.a.e\", \"united arab emirates\"],\n countryCode: \"ae\",\n url: \"/ae\",\n tagline: \"You're in the UAE. Welcome!\"\n },\n {\n country: \"saudi arabia\",\n aliases: [\"saudi\", \"ksa\", \"kingdom of saudi arabia\"],\n countryCode: \"sa\",\n url: \"/sa\",\n tagline: \"Hello Saudi Arabia!\"\n },\n {\n country: \"south africa\",\n aliases: [\"rsa\"],\n countryCode: \"za\",\n url: \"/za\",\n tagline: \"Hi South Africa!\"\n },\n {\n country: \"malaysia\",\n countryCode: \"my\",\n url: \"/my\",\n tagline: \"Selamat datang, Malaysia!\"\n },\n {\n country: \"indonesia\",\n aliases: [\"idn\"],\n countryCode: \"id\",\n url: \"/id\",\n tagline: \"Halo Indonesia!\"\n },\n {\n country: \"philippines\",\n aliases: [\"phl\", \"the philippines\"],\n countryCode: \"ph\",\n url: \"/ph\",\n tagline: \"Kumusta, Philippines!\"\n },\n {\n country: \"india\",\n aliases: [\"bharat\"],\n countryCode: \"in\",\n url: \"/in\",\n tagline: \"This country is India. Hi some text\"\n },\n // \uD83D\uDC47 fallback\n {\n country: \"global\",\n aliases: [\"global\", \"rest of world\", \"others\"],\n countryCode: \"global\", // keep lowercase for consistency\n url: \"/global\",\n tagline: \"This is rest of world. Hi some text\"\n }\n];\n\n/** Utility: normalize strings for comparisons */\nfunction norm(s: string | null | undefined): string {\n return (s ?? \"\").trim().toLowerCase();\n}\n\n/** Utility: ensure URL starts with a single leading slash */\nfunction toPath(path: string): string {\n const p = path.trim();\n if (!p) return \"/\";\n return p.startsWith(\"/\") ? p : `/${p}`;\n}\n\n/** Determine user's country as a *string* (might be name or code depending on your geo source) */\nexport async function getUserCountry(): Promise<string | null> {\n if (typeof window === \"undefined\") return null;\n\n // 1) Cookie fast-path\n const cookieCountry = getGeoCountryFromCookie();\n if (cookieCountry) return norm(cookieCountry);\n\n // 2) Cached or network\n const geo: GeoData | null = await getGeolocationCached();\n return norm((geo as any)?.country);\n}\n\n/** Find matching config by country *name* or *ISO-2 code* with aliases */\nfunction findCountryConfig(input: string | null): CountryConfig | null {\n const v = norm(input);\n if (!v) return null;\n\n const byCode = COUNTRY_CONFIG.find(c => norm(c.countryCode) === v);\n if (byCode) return byCode;\n\n const byName = COUNTRY_CONFIG.find(c => norm(c.country) === v);\n if (byName) return byName;\n\n const byAlias = COUNTRY_CONFIG.find(c => (c.aliases ?? []).some(a => norm(a) === v));\n if (byAlias) return byAlias;\n\n return null;\n}\n\n/** Helper to fetch the global config */\nfunction getGlobalConfig(): CountryConfig {\n const g = COUNTRY_CONFIG.find(c => c.country === \"global\");\n if (!g) throw new Error(\"[geo-banner] Global config not found in COUNTRY_CONFIG\");\n return g;\n}\n\nfunction updateBannerLink(countryCode?: string | null): void {\n if (typeof window === \"undefined\") return;\n\n const code = norm(countryCode);\n const conf =\n COUNTRY_CONFIG.find(c => norm(c.countryCode) === code) ||\n getGlobalConfig();\n\n const linkEl = document.querySelector<HTMLAnchorElement>('[fynd-banner-field=\"link\"]');\n if (linkEl) {\n const base = window.location.origin;\n linkEl.href = `${base}${toPath(conf.url)}`;\n }\n}\n\nexport function setSelectValueSafely(selectEl: HTMLSelectElement, desired: string) {\n // 1) resolve config\n const conf =\n findCountryConfig(desired) ??\n COUNTRY_CONFIG.find(c => c.country === \"global\");\n if (!conf) {\n console.warn(\"[geo-banner] No matching config for\", desired);\n return false;\n }\n const desiredCode = conf.countryCode; // assume already normalized/lowercase\n\n // 2) find matching option (normalize both sides)\n const opts = Array.from(selectEl.options);\n const opt = opts.find(o => norm(o.value) === norm(desiredCode));\n if (!opt) {\n console.warn(\"[geo-banner] No matching <option> for\", desiredCode, \"on\", selectEl);\n return false;\n }\n\n // 3) update the <select> itself (more reliable than toggling option.selected)\n const prev = selectEl.value;\n selectEl.value = opt.value;\n\n // if some browsers/frameworks didn\u2019t adopt .value, force selectedIndex too\n if (selectEl.value !== opt.value) {\n selectEl.selectedIndex = opts.indexOf(opt);\n }\n\n // 4) (optional) keep options\u2019 selected flags in sync\n opts.forEach(o => (o.selected = o === opt));\n\n // 5) fire events frameworks listen to\n if (prev !== selectEl.value) {\n selectEl.dispatchEvent(new Event(\"input\", { bubbles: true }));\n selectEl.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n\n console.log(\"[geo-banner] Select updated \u2192\", conf.country, \"(\", conf.countryCode, \")\");\n return true;\n}\n\n/** Update the banner content for a given countryCode (lowercase ISO-2) with global fallback */\nexport function updateBannerContent(countryCode?: string | null): void {\n if (typeof window === \"undefined\") return;\n\n const code = norm(countryCode);\n const conf =\n COUNTRY_CONFIG.find(c => norm(c.countryCode) === code) ||\n getGlobalConfig();\n // 1) Set <select fynd-banner-field=\"geoswitch\"> value (robustly)\n const selectEl =\n document.querySelector<HTMLSelectElement>('#geoswitch-select') ||\n document.querySelector<HTMLSelectElement>('[fynd-banner-field=\"geoswitch\"]');\n\n if (selectEl) {\n console.log(`country code is ${conf.countryCode}`)\n setSelectValueSafely(selectEl, conf.countryCode);\n selectEl.value = conf.countryCode; // or \"global\", etc.\n\n selectEl.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else {\n console.warn('[geo-banner] Select not found: #geoswitch-select / [fynd-banner-field=\"geoswitch\"]');\n }\n\n // // 2) Update banner text (unchanged)\n // const textEl = document.querySelector<HTMLElement>('[fynd-banner-field=\"banner-text\"]');\n // if (textEl) textEl.innerHTML = conf.tagline;\n\n // 3) Update link href (unchanged)\n const linkEl = document.querySelector<HTMLAnchorElement>('[fynd-banner-field=\"link\"]');\n if (linkEl) {\n const base = window.location.origin;\n linkEl.href = `${base}${toPath(conf.url)}`;\n }\n}\n\n/**\n * Main entry: detect country and update banner if it matches one of the configured countries.\n * Always falls back to global if no match is found.\n */\nexport async function initCountryDetection(): Promise<CountryConfig> {\n if (typeof window === \"undefined\") return getGlobalConfig();\n\n if (document.readyState === \"loading\") {\n await new Promise<void>(resolve => {\n document.addEventListener(\"DOMContentLoaded\", () => resolve(), { once: true });\n });\n }\n\n const rawCountry = await getUserCountry();\n const match = findCountryConfig(rawCountry);\n const resolved = match ?? getGlobalConfig();\n\n // Debug visibility\n console.log(\"[geo-banner] rawCountry:\", rawCountry, \"\u2192 resolved:\", resolved.countryCode);\n\n // \u2705 Always update from the resolved config (guarantees global fallback)\n updateBannerContent(resolved.countryCode);\n\n // (If you also attached the select change listener, keep that here)\n const selectEl = document.querySelector<HTMLSelectElement>('[fynd-banner-field=\"geoswitch\"]');\n if (selectEl && !(selectEl as any).__geoHandlerAttached) {\n selectEl.addEventListener(\"change\", (e) => {\n const value = (e.target as HTMLSelectElement).value;\n updateBannerLink(value); // only updates href on change\n });\n (selectEl as any).__geoHandlerAttached = true;\n }\n\n return resolved;\n}", "import { getGeolocationCached } from \"src/global/geolocation/geolocation-cached\";\nimport { closeBanner, openBanner } from \"src/global/animation/toggle-banner\";\nimport { getCookie, setCookie } from \"$utils/cookies\";\nimport { getScreenType } from \"src/global/screen-type\";\nimport { initCountryDetection } from \"./country-detection/main\";\n\n/**\n * Banner rules by route (normalized, no trailing slash).\n * Modes:\n * - { mode: \"always\" }\n * - { mode: \"country\", countries: [...] } \u2192 open if geo.country matches (case-insensitive)\n * - { mode: \"notCountry\", countries: [...] } \u2192 open if geo.country does NOT match\n * - { mode: \"predicate\", test: (geo) => boolean }\n */\nconst bannerRouteRules: Record<\n string,\n | { mode: \"always\" }\n | { mode: \"country\"; countries: string[] }\n | { mode: \"notCountry\"; countries: string[] }\n | { mode: \"predicate\"; test: (geo?: any) => boolean }\n> = {\n \"/global\": { mode: \"country\", countries: [\"India\"] },\n \"/\": { mode: \"notCountry\", countries: [\"India\"] },\n};\n\n// Elements\nconst ipBannerMain = '[fynd-navigation=\"ip-banner\"]';\nconst ipBannerInner = '[fynd-navigation=\"ip-banner-inner\"]';\nconst closeIpBanner = '[fynd-navigation=\"ip-banner-close\"]';\n\nconst announcementBar = document.querySelector(\n '[fynd-navigation=\"announcement-bar\"]'\n);\nconst announcementList = document.querySelector(\n '[fynd-navigation=\"announcement-list\"]'\n);\n\n// Global navigation state\nconst navigationData = {\n ipbanner: {\n visibility: false,\n height: {\n desktop: \"56px\",\n tablet: \"60px\",\n mobileLandscape: \"120px\",\n mobilePortrait: \"120px\",\n },\n },\n announcementbar: {\n visibility: true,\n height: {\n desktop: \"40px\",\n tablet: \"40px\",\n mobileLandscape: \"40px\",\n mobilePortrait: \"46px\",\n },\n },\n default: {\n visibility: true,\n height: {\n desktop: \"70px\",\n tablet: \"64px\",\n mobileLandscape: \"40px\",\n mobilePortrait: \"64px\",\n },\n },\n};\n(window as any).navigationData = navigationData;\n\n// --- Utils -------------------------------------------------------------------\n\nfunction addPx(a: string | number, b: string | number): string {\n const toNumber = (val: string | number): number => {\n if (typeof val === \"number\") return val;\n const num = parseInt(val, 10);\n return isNaN(num) ? 0 : num;\n };\n return `${toNumber(a) + toNumber(b)}px`;\n}\n\nfunction subtractPx(a: string | number, b: string | number): string {\n const toNumber = (val: string | number): number => {\n if (typeof val === \"number\") return val;\n const num = parseInt(val, 10);\n return isNaN(num) ? 0 : num;\n };\n return `${toNumber(a) - toNumber(b)}px`;\n}\n\nconst normalizePath = (p: string) => {\n try {\n const urlPath = p.split(\"?\")[0].split(\"#\")[0];\n if (urlPath === \"/\") return \"/\";\n return urlPath.replace(/\\/+$/, \"\") || \"/\";\n } catch {\n return \"/\";\n }\n};\n\n// Longest-prefix match, so \"/india/offers\" matches \"/india\"\nfunction getMatchingRule(pathname: string) {\n const path = normalizePath(pathname);\n let bestKey = \"\";\n for (const key of Object.keys(bannerRouteRules)) {\n const normKey = normalizePath(key);\n if (path === normKey || path.startsWith(normKey + \"/\")) {\n if (normKey.length > bestKey.length) bestKey = normKey;\n }\n }\n return bestKey ? { key: bestKey, rule: bannerRouteRules[bestKey] } : null;\n}\n\nfunction shouldOpenBannerForPage(pathname: string, geo?: { country?: string }) {\n const match = getMatchingRule(pathname);\n if (!match) return false;\n\n const { rule } = match;\n const visitorCountry = (geo?.country || \"\").toLowerCase();\n\n switch (rule.mode) {\n case \"always\":\n return true;\n case \"country\":\n return rule.countries.some((c) => c.toLowerCase() === visitorCountry);\n case \"notCountry\":\n return !rule.countries.some((c) => c.toLowerCase() === visitorCountry);\n case \"predicate\":\n return !!rule.test?.(geo);\n default:\n return false;\n }\n}\n\n// --- Announcement Bar --------------------------------------------------------\n\nfunction initAnnouncementBar() {\n const swiperEl = document.querySelector<HTMLElement>(\n '[fynd-navigation=\"announcement-swiper\"]'\n );\n\n // Initialize swiper if present\n if (swiperEl && !(swiperEl as any).__swiperInstance) {\n try {\n const Swiper = (window as any).Swiper;\n const swiper = new Swiper(swiperEl, {\n slidesPerView: 1,\n spaceBetween: 0,\n effect: \"fade\",\n fadeEffect: { crossFade: true },\n autoplay: { delay: 3000, disableOnInteraction: false },\n loop: true,\n speed: 1000,\n allowTouchMove: false,\n on: {\n init: function (this: any): void {\n if (\n this.slides.length <= 1 &&\n this.autoplay &&\n typeof this.autoplay.stop === \"function\"\n ) {\n this.autoplay.stop();\n }\n },\n },\n });\n (swiperEl as any).__swiperInstance = swiper;\n } catch (err) {\n console.warn(\"Announcement Swiper init failed:\", err);\n }\n }\n\n // // Visibility & cleanup\n // if (announcementBar && announcementList && announcementList.children.length > 0) {\n // navigationData.announcementbar.visibility = true;\n // } else {\n // navigationData.announcementbar.visibility = false;\n // if (announcementBar && announcementBar.parentNode) {\n // if (swiperEl && (swiperEl as any).__swiperInstance) {\n // (swiperEl as any).__swiperInstance.destroy(true, true);\n // (swiperEl as any).__swiperInstance = undefined;\n // }\n // announcementBar.parentNode.removeChild(announcementBar);\n // }\n // }\n}\n\n// --- Desktop Dropdown Positioning -------------------------------------------\n\nfunction initDesktopDropdownMenu() {\n const selector = '[fynd-navigation=\"dropdown-container\"]';\n const el = document.querySelector<HTMLElement>(selector);\n if (!el) {\n console.warn(`initDesktopDropdownMenu: element not found: ${selector}`);\n return;\n }\n\n const screenType = getScreenType?.() ?? \"unknown\";\n\n // Not desktop \u2192 reset transform\n if (screenType !== \"desktop\") {\n el.style.transition = el.style.transition || \"transform 0.3s ease\";\n el.style.transform = \"translateY(0px)\";\n return;\n }\n\n // Compute total stacked height\n let total = navigationData.default.height?.[screenType];\n let subtractFlag = false;\n\n if (navigationData.announcementbar?.visibility) {\n const h = navigationData.announcementbar.height?.[screenType];\n total = addPx(total, h);\n total = subtractPx(total, \"46px\");\n subtractFlag = true;\n }\n\n if (navigationData.ipbanner?.visibility) {\n // Currently not offsetting desktop for IP banner\n const h = \"0px\";\n total = addPx(total, h);\n if (!subtractFlag) {\n total = subtractPx(total, \"46px\");\n }\n }\n\n // Offset dropdown under nav (minus header overlap 46px)\n el.style.transform = `translateY(${total})`;\n}\n\n// --- Dynamic Spacer ----------------------------------------------------------\n\nfunction initNavigationSpacer() {\n const spacer = document.querySelector<HTMLElement>(\n '[fynd-navigation=\"spacer\"][data-wf--navigation-spacer--variant=\"dynamic\"]'\n );\n\n if (!spacer) {\n console.warn(\"initNavigationSpacer: spacer element not found\");\n return;\n }\n\n const toPx = (v?: string | number): number => {\n if (typeof v === \"number\") return v;\n if (typeof v === \"string\") {\n const n = parseFloat(v);\n return Number.isFinite(n) ? n : 0;\n }\n return 0;\n };\n\n const screenType = getScreenType?.() ?? \"desktop\";\n let total = navigationData.default.height?.[screenType];\n\n if (navigationData.announcementbar?.visibility) {\n const h = navigationData.announcementbar.height?.[screenType];\n total = addPx(total, h);\n }\n\n if (navigationData.ipbanner?.visibility) {\n const h = toPx(navigationData.ipbanner.height?.[screenType]);\n total = addPx(total, h);\n }\n\n spacer.style.height = `${total}`;\n}\n\n// --- IP Banner ---------------------------------------------------------------\n\nasync function initIpBanner() {\n const ipClosed = getCookie(\"ipBannerClosed\") === \"true\";\n if (ipClosed) {\n navigationData.ipbanner.visibility = false;\n return;\n }\n\n const geo = await getGeolocationCached();\n const path = window.location.pathname || \"/\";\n const allowByRoute = shouldOpenBannerForPage(path, geo ?? undefined);\n\n const countryReady = await initCountryDetection();\n\n if (allowByRoute && countryReady) {\n openBanner(\n ipBannerMain,\n ipBannerInner,\n navigationData.ipbanner.height.desktop\n );\n navigationData.ipbanner.visibility = true;\n\n const closeBtn = document.querySelector<HTMLElement>(closeIpBanner);\n if (closeBtn) {\n closeBtn.addEventListener(\"click\", () => {\n closeBanner(ipBannerMain, ipBannerInner);\n setCookie(\"ipBannerClosed\", \"true\", 24);\n navigationData.ipbanner.visibility = false;\n initDesktopDropdownMenu();\n initNavigationSpacer();\n });\n }\n } else {\n navigationData.ipbanner.visibility = false;\n }\n}\n\n// --- Init --------------------------------------------------------------------\n\ndocument.addEventListener(\"DOMContentLoaded\", async () => {\n await initIpBanner();\n initAnnouncementBar();\n initDesktopDropdownMenu();\n initNavigationSpacer();\n});\n"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n // console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// Define the type for returned geolocation data\n// Remider for adding Fallback: ipinfo.io (HTTPS, requires token)\nexport type GeoData = {\n ip: string;\n country: string;\n region: string;\n city: string;\n latitude: number;\n longitude: number;\n isp: string;\n timezone: string;\n };\n \n // Exported function that can be reused anywhere\n export async function getGeolocation(): Promise<GeoData | null> {\n try {\n const response = await fetch(\"https://ipwho.is/\");\n if (!response.ok) {\n throw new Error(\"Failed to fetch geolocation\");\n }\n \n const data = await response.json();\n \n if (data.success === false) {\n console.error(\"Geolocation lookup failed:\", data.message);\n return null;\n }\n \n return {\n ip: data.ip,\n country: data.country,\n region: data.region,\n city: data.city,\n latitude: data.latitude,\n longitude: data.longitude,\n isp: data.connection?.isp || \"\",\n timezone: data.timezone?.id || \"\"\n };\n } catch (error) {\n console.error(\"Error fetching geolocation:\", error);\n return null;\n }\n }\n\n //used in /src/navigation/initialization.ts for displaying ip banner", "import { GeoData, getGeolocation } from \"./main\";\n\nconst GEO_CACHE_KEY = \"geo:data:v1\";\nconst GEO_COOKIE_KEY = \"geo_country\";\nconst GEO_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\n\ntype Cached<T> = { data: T; expiresAt: number };\n\n// --- Cookie helpers ---\nfunction setCookie(name: string, value: string, maxAgeSec: number) {\n document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(\n value\n )}; Max-Age=${maxAgeSec}; Path=/; SameSite=Lax; Secure`;\n}\n\nfunction getCookie(name: string): string | null {\n const key = `${encodeURIComponent(name)}=`;\n const parts = document.cookie.split(\"; \");\n for (const p of parts) {\n if (p.startsWith(key)) return decodeURIComponent(p.slice(key.length));\n }\n return null;\n}\n\nfunction clearCookie(name: string) {\n document.cookie = `${encodeURIComponent(\n name\n )}=; Max-Age=0; Path=/; SameSite=Lax; Secure`;\n}\n\n// --- LocalStorage helpers ---\nfunction readCache<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(key);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Cached<T>;\n if (!parsed?.expiresAt || Date.now() > parsed.expiresAt) {\n localStorage.removeItem(key);\n return null;\n }\n return parsed.data;\n } catch {\n localStorage.removeItem(key);\n return null;\n }\n}\n\nfunction writeCache<T>(key: string, data: T, ttlMs: number) {\n const payload: Cached<T> = { data, expiresAt: Date.now() + ttlMs };\n try {\n localStorage.setItem(key, JSON.stringify(payload));\n } catch {\n // ignore quota errors\n }\n}\n\n// --- Public API ---\nexport async function getGeolocationCached(options?: {\n forceRefresh?: boolean;\n}): Promise<GeoData | null> {\n if (typeof window === \"undefined\") return null;\n\n const forceRefresh = options?.forceRefresh ?? false;\n\n if (!forceRefresh) {\n const cached = readCache<GeoData>(GEO_CACHE_KEY);\n if (cached) {\n (window as any).__GEO = cached;\n if (!getCookie(GEO_COOKIE_KEY)) {\n setCookie(\n GEO_COOKIE_KEY,\n cached.country ?? \"\",\n Math.floor(GEO_TTL_MS / 1000)\n );\n }\n return cached;\n }\n }\n\n // \u2B07\uFE0F changed block starts here\n let geo: GeoData | null = null;\n try {\n geo = await getGeolocation();\n } catch (e) {\n console.warn(\"getGeolocation() failed; defaulting to India:\", e);\n }\n\n if (!geo) {\n // Fallback to India if the fetch failed or returned invalid data\n geo = { country: \"India\" } as GeoData;\n }\n\n writeCache(GEO_CACHE_KEY, geo, GEO_TTL_MS);\n setCookie(GEO_COOKIE_KEY, geo.country ?? \"\", Math.floor(GEO_TTL_MS / 1000));\n (window as any).__GEO = geo;\n return geo;\n // \u2B06\uFE0F changed block ends here\n}\n\nexport function getGeoCountryFromCookie(): string | null {\n return getCookie(GEO_COOKIE_KEY);\n}\n\nexport function clearGeolocationCache() {\n try {\n localStorage.removeItem(GEO_CACHE_KEY);\n } catch {}\n clearCookie(GEO_COOKIE_KEY);\n if (typeof window !== \"undefined\") {\n (window as any).__GEO = undefined;\n }\n}\n", "// toggleBanner.ts\n// Utility functions to open/close a banner using GSAP with optional target height.\n\nexport function openBanner(\n mainSelector: string,\n innerSelector: string,\n targetHeight: string | number = \"auto\" // default stays \"auto\"\n) {\n const w = (window as any) || {};\n const gsap = w.gsap as any;\n if (!gsap) {\n console.warn(\"GSAP not found on window. Did you include it globally?\");\n return;\n }\n\n const mainEl = document.querySelector<HTMLElement>(mainSelector);\n const innerEl = document.querySelector<HTMLElement>(innerSelector);\n\n if (!mainEl || !innerEl) {\n console.warn(\"openBanner: Element(s) not found for selectors:\", {\n mainSelector,\n innerSelector,\n });\n return;\n }\n\n // Ensure clean start\n gsap.set(mainEl, { height: 0, overflow: \"hidden\" });\n gsap.set(innerEl, { opacity: 0 });\n\n const tl = gsap.timeline();\n\n // Animate main from height: 0 -> targetHeight\n tl.to(mainEl, {\n height: targetHeight,\n duration: 0.5,\n ease: \"power2.out\",\n });\n\n // After 0.2s, fade inner to 1\n tl.to(\n innerEl,\n {\n opacity: 1,\n duration: 0.3,\n ease: \"power1.out\",\n },\n 0.2\n );\n\n return tl;\n}\n\nexport function closeBanner(\n mainSelector: string,\n innerSelector: string,\n targetHeight: string | number = 0 // default collapse fully\n) {\n const w = (window as any) || {};\n const gsap = w.gsap as any;\n if (!gsap) {\n console.warn(\"GSAP not found on window. Did you include it globally?\");\n return;\n }\n\n const mainEl = document.querySelector<HTMLElement>(mainSelector);\n const innerEl = document.querySelector<HTMLElement>(innerSelector);\n\n if (!mainEl || !innerEl) {\n console.warn(\"closeBanner: Element(s) not found for selectors:\", {\n mainSelector,\n innerSelector,\n });\n return;\n }\n\n gsap.set(mainEl, { overflow: \"hidden\" });\n\n const tl = gsap.timeline();\n\n // Fade inner out\n tl.to(innerEl, {\n opacity: 0,\n duration: 0.25,\n ease: \"power1.out\",\n });\n\n // Collapse height to targetHeight (default 0)\n tl.to(\n mainEl,\n {\n height: targetHeight,\n duration: 0.45,\n ease: \"power2.inOut\",\n },\n 0.2\n );\n\n return tl;\n}", "export function setCookie(name: string, value: string, hours: number) {\n const date = new Date();\n date.setTime(date.getTime() + hours * 60 * 60 * 1000);\n document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/`;\n }\n \n export function getCookie(name: string): string | null {\n const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));\n return match ? match[2] : null;\n }", "// screen-type.ts\n// Utility to get the current screen type\n// Breakpoints:\n// - Desktop: 992px+\n// - Tablet: 768px\u2013991px\n// - Mobile Landscape: 480px\u2013767px\n// - Mobile Portrait: under 480px\n\nexport type ScreenType = \"desktop\" | \"tablet\" | \"mobileLandscape\" | \"mobilePortrait\";\n\nexport function getScreenType(): ScreenType {\n const width = window.innerWidth;\n\n if (width >= 992) {\n return \"desktop\";\n } else if (width >= 768) {\n return \"tablet\";\n } else if (width >= 480) {\n return \"mobileLandscape\";\n } else {\n return \"mobilePortrait\";\n }\n}", "// geo.ts\nimport { getGeoCountryFromCookie, getGeolocationCached } from \"src/global/geolocation/geolocation-cached\";\nimport { GeoData } from \"src/global/geolocation/main\";\n\n/** Your banner config */\ntype CountryConfig = {\n country: string; // canonical lowercase name\n countryCode: string; // ISO-2 lowercase code (e.g., \"in\")\n url: string; // leading-slash path (e.g., \"/in\")\n tagline: string; // banner text/html\n aliases?: string[]; // optional extra names to match against\n};\n\nexport const COUNTRY_CONFIG: CountryConfig[] = [\n {\n country: \"united arab emirates\",\n aliases: [\"uae\", \"u.a.e\", \"united arab emirates\"],\n countryCode: \"ae\",\n url: \"/ae\",\n tagline: \"You're in the UAE. Welcome!\"\n },\n {\n country: \"saudi arabia\",\n aliases: [\"saudi\", \"ksa\", \"kingdom of saudi arabia\"],\n countryCode: \"sa\",\n url: \"/sa\",\n tagline: \"Hello Saudi Arabia!\"\n },\n {\n country: \"south africa\",\n aliases: [\"rsa\"],\n countryCode: \"za\",\n url: \"/za\",\n tagline: \"Hi South Africa!\"\n },\n {\n country: \"malaysia\",\n countryCode: \"my\",\n url: \"/my\",\n tagline: \"Selamat datang, Malaysia!\"\n },\n {\n country: \"indonesia\",\n aliases: [\"idn\"],\n countryCode: \"id\",\n url: \"/id\",\n tagline: \"Halo Indonesia!\"\n },\n {\n country: \"philippines\",\n aliases: [\"phl\", \"the philippines\"],\n countryCode: \"ph\",\n url: \"/ph\",\n tagline: \"Kumusta, Philippines!\"\n },\n {\n country: \"india\",\n aliases: [\"bharat\"],\n countryCode: \"in\",\n url: \"/in\",\n tagline: \"This country is India. Hi some text\"\n },\n // \uD83D\uDC47 fallback\n {\n country: \"global\",\n aliases: [\"global\", \"rest of world\", \"others\"],\n countryCode: \"global\", // keep lowercase for consistency\n url: \"/global\",\n tagline: \"This is rest of world. Hi some text\"\n }\n];\n\n/** Utility: normalize strings for comparisons */\nfunction norm(s: string | null | undefined): string {\n return (s ?? \"\").trim().toLowerCase();\n}\n\n/** Utility: ensure URL starts with a single leading slash */\nfunction toPath(path: string): string {\n const p = path.trim();\n if (!p) return \"/\";\n return p.startsWith(\"/\") ? p : `/${p}`;\n}\n\n/** Determine user's country as a *string* (might be name or code depending on your geo source) */\nexport async function getUserCountry(): Promise<string | null> {\n if (typeof window === \"undefined\") return null;\n\n // 1) Cookie fast-path\n const cookieCountry = getGeoCountryFromCookie();\n if (cookieCountry) return norm(cookieCountry);\n\n // 2) Cached or network\n const geo: GeoData | null = await getGeolocationCached();\n return norm((geo as any)?.country);\n}\n\n/** Find matching config by country *name* or *ISO-2 code* with aliases */\nfunction findCountryConfig(input: string | null): CountryConfig | null {\n const v = norm(input);\n if (!v) return null;\n\n const byCode = COUNTRY_CONFIG.find(c => norm(c.countryCode) === v);\n if (byCode) return byCode;\n\n const byName = COUNTRY_CONFIG.find(c => norm(c.country) === v);\n if (byName) return byName;\n\n const byAlias = COUNTRY_CONFIG.find(c => (c.aliases ?? []).some(a => norm(a) === v));\n if (byAlias) return byAlias;\n\n return null;\n}\n\n/** Helper to fetch the global config */\nfunction getGlobalConfig(): CountryConfig {\n const g = COUNTRY_CONFIG.find(c => c.country === \"global\");\n if (!g) throw new Error(\"[geo-banner] Global config not found in COUNTRY_CONFIG\");\n return g;\n}\n\nfunction updateBannerLink(countryCode?: string | null): void {\n if (typeof window === \"undefined\") return;\n\n const code = norm(countryCode);\n const conf =\n COUNTRY_CONFIG.find(c => norm(c.countryCode) === code) ||\n getGlobalConfig();\n\n const linkEl = document.querySelector<HTMLAnchorElement>('[fynd-banner-field=\"link\"]');\n if (linkEl) {\n const base = window.location.origin;\n linkEl.href = `${base}${toPath(conf.url)}`;\n }\n}\n\nexport function setSelectValueSafely(selectEl: HTMLSelectElement, desired: string) {\n // 1) resolve config\n const conf =\n findCountryConfig(desired) ??\n COUNTRY_CONFIG.find(c => c.country === \"global\");\n if (!conf) {\n console.warn(\"[geo-banner] No matching config for\", desired);\n return false;\n }\n const desiredCode = conf.countryCode; // assume already normalized/lowercase\n\n // 2) find matching option (normalize both sides)\n const opts = Array.from(selectEl.options);\n const opt = opts.find(o => norm(o.value) === norm(desiredCode));\n if (!opt) {\n console.warn(\"[geo-banner] No matching <option> for\", desiredCode, \"on\", selectEl);\n return false;\n }\n\n // 3) update the <select> itself (more reliable than toggling option.selected)\n const prev = selectEl.value;\n selectEl.value = opt.value;\n\n // if some browsers/frameworks didn\u2019t adopt .value, force selectedIndex too\n if (selectEl.value !== opt.value) {\n selectEl.selectedIndex = opts.indexOf(opt);\n }\n\n // 4) (optional) keep options\u2019 selected flags in sync\n opts.forEach(o => (o.selected = o === opt));\n\n // 5) fire events frameworks listen to\n if (prev !== selectEl.value) {\n selectEl.dispatchEvent(new Event(\"input\", { bubbles: true }));\n selectEl.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n\n console.log(\"[geo-banner] Select updated \u2192\", conf.country, \"(\", conf.countryCode, \")\");\n return true;\n}\n\n/** Update the banner content for a given countryCode (lowercase ISO-2) with global fallback */\nexport function updateBannerContent(countryCode?: string | null): void {\n if (typeof window === \"undefined\") return;\n\n const code = norm(countryCode);\n const conf =\n COUNTRY_CONFIG.find(c => norm(c.countryCode) === code) ||\n getGlobalConfig();\n // 1) Set <select fynd-banner-field=\"geoswitch\"> value (robustly)\n const selectEl =\n document.querySelector<HTMLSelectElement>('#geoswitch-select') ||\n document.querySelector<HTMLSelectElement>('[fynd-banner-field=\"geoswitch\"]');\n\n if (selectEl) {\n console.log(`country code is ${conf.countryCode}`)\n setSelectValueSafely(selectEl, conf.countryCode);\n selectEl.value = conf.countryCode; // or \"global\", etc.\n\n selectEl.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } else {\n console.warn('[geo-banner] Select not found: #geoswitch-select / [fynd-banner-field=\"geoswitch\"]');\n }\n\n // // 2) Update banner text (unchanged)\n // const textEl = document.querySelector<HTMLElement>('[fynd-banner-field=\"banner-text\"]');\n // if (textEl) textEl.innerHTML = conf.tagline;\n\n // 3) Update link href (unchanged)\n const linkEl = document.querySelector<HTMLAnchorElement>('[fynd-banner-field=\"link\"]');\n if (linkEl) {\n const base = window.location.origin;\n linkEl.href = `${base}${toPath(conf.url)}`;\n }\n}\n\n/**\n * Main entry: detect country and update banner if it matches one of the configured countries.\n * Always falls back to global if no match is found.\n */\nexport async function initCountryDetection(): Promise<CountryConfig> {\n if (typeof window === \"undefined\") return getGlobalConfig();\n\n if (document.readyState === \"loading\") {\n await new Promise<void>(resolve => {\n document.addEventListener(\"DOMContentLoaded\", () => resolve(), { once: true });\n });\n }\n\n const rawCountry = await getUserCountry();\n const match = findCountryConfig(rawCountry);\n const resolved = match ?? getGlobalConfig();\n\n // Debug visibility\n console.log(\"[geo-banner] rawCountry:\", rawCountry, \"\u2192 resolved:\", resolved.countryCode);\n\n // \u2705 Always update from the resolved config (guarantees global fallback)\n updateBannerContent(resolved.countryCode);\n\n // (If you also attached the select change listener, keep that here)\n const selectEl = document.querySelector<HTMLSelectElement>('[fynd-banner-field=\"geoswitch\"]');\n if (selectEl && !(selectEl as any).__geoHandlerAttached) {\n selectEl.addEventListener(\"change\", (e) => {\n const value = (e.target as HTMLSelectElement).value;\n updateBannerLink(value); // only updates href on change\n });\n (selectEl as any).__geoHandlerAttached = true;\n }\n\n return resolved;\n}", "import { getGeolocationCached } from \"src/global/geolocation/geolocation-cached\";\nimport { closeBanner, openBanner } from \"src/global/animation/toggle-banner\";\nimport { getCookie, setCookie } from \"$utils/cookies\";\nimport { getScreenType } from \"src/global/screen-type\";\nimport { initCountryDetection } from \"./country-detection/main\";\n\n/**\n * Banner rules by route (normalized, no trailing slash).\n * Modes:\n * - { mode: \"always\" }\n * - { mode: \"country\", countries: [...] } \u2192 open if geo.country matches (case-insensitive)\n * - { mode: \"notCountry\", countries: [...] } \u2192 open if geo.country does NOT match\n * - { mode: \"predicate\", test: (geo) => boolean }\n */\nconst bannerRouteRules: Record<\n string,\n | { mode: \"always\" }\n | { mode: \"country\"; countries: string[] }\n | { mode: \"notCountry\"; countries: string[] }\n | { mode: \"predicate\"; test: (geo?: any) => boolean }\n> = {\n \"/global\": { mode: \"country\", countries: [\"India\"] },\n \"/\": { mode: \"notCountry\", countries: [\"India\"] },\n};\n\n// Elements\nconst ipBannerMain = '[fynd-navigation=\"ip-banner\"]';\nconst ipBannerInner = '[fynd-navigation=\"ip-banner-inner\"]';\nconst closeIpBanner = '[fynd-navigation=\"ip-banner-close\"]';\n\nconst announcementBar = document.querySelector(\n '[fynd-navigation=\"announcement-bar\"]'\n);\nconst announcementList = document.querySelector(\n '[fynd-navigation=\"announcement-list\"]'\n);\n\n// Global navigation state\nconst navigationData = {\n ipbanner: {\n visibility: false,\n height: {\n desktop: \"56px\",\n tablet: \"60px\",\n mobileLandscape: \"120px\",\n mobilePortrait: \"120px\",\n },\n },\n announcementbar: {\n visibility: false,\n height: {\n desktop: \"40px\",\n tablet: \"40px\",\n mobileLandscape: \"40px\",\n mobilePortrait: \"46px\",\n },\n },\n default: {\n visibility: true,\n height: {\n desktop: \"70px\",\n tablet: \"64px\",\n mobileLandscape: \"40px\",\n mobilePortrait: \"64px\",\n },\n },\n};\n(window as any).navigationData = navigationData;\n\n// --- Utils -------------------------------------------------------------------\n\nfunction addPx(a: string | number, b: string | number): string {\n const toNumber = (val: string | number): number => {\n if (typeof val === \"number\") return val;\n const num = parseInt(val, 10);\n return isNaN(num) ? 0 : num;\n };\n return `${toNumber(a) + toNumber(b)}px`;\n}\n\nfunction subtractPx(a: string | number, b: string | number): string {\n const toNumber = (val: string | number): number => {\n if (typeof val === \"number\") return val;\n const num = parseInt(val, 10);\n return isNaN(num) ? 0 : num;\n };\n return `${toNumber(a) - toNumber(b)}px`;\n}\n\nconst normalizePath = (p: string) => {\n try {\n const urlPath = p.split(\"?\")[0].split(\"#\")[0];\n if (urlPath === \"/\") return \"/\";\n return urlPath.replace(/\\/+$/, \"\") || \"/\";\n } catch {\n return \"/\";\n }\n};\n\n// Longest-prefix match, so \"/india/offers\" matches \"/india\"\nfunction getMatchingRule(pathname: string) {\n const path = normalizePath(pathname);\n let bestKey = \"\";\n for (const key of Object.keys(bannerRouteRules)) {\n const normKey = normalizePath(key);\n if (path === normKey || path.startsWith(normKey + \"/\")) {\n if (normKey.length > bestKey.length) bestKey = normKey;\n }\n }\n return bestKey ? { key: bestKey, rule: bannerRouteRules[bestKey] } : null;\n}\n\nfunction shouldOpenBannerForPage(pathname: string, geo?: { country?: string }) {\n const match = getMatchingRule(pathname);\n if (!match) return false;\n\n const { rule } = match;\n const visitorCountry = (geo?.country || \"\").toLowerCase();\n\n switch (rule.mode) {\n case \"always\":\n return true;\n case \"country\":\n return rule.countries.some((c) => c.toLowerCase() === visitorCountry);\n case \"notCountry\":\n return !rule.countries.some((c) => c.toLowerCase() === visitorCountry);\n case \"predicate\":\n return !!rule.test?.(geo);\n default:\n return false;\n }\n}\n\n// --- Announcement Bar --------------------------------------------------------\n\nfunction initAnnouncementBar() {\n const swiperEl = document.querySelector<HTMLElement>(\n '[fynd-navigation=\"announcement-swiper\"]'\n );\n\n // Initialize swiper if present\n if (swiperEl && !(swiperEl as any).__swiperInstance) {\n try {\n const Swiper = (window as any).Swiper;\n const swiper = new Swiper(swiperEl, {\n slidesPerView: 1,\n spaceBetween: 0,\n effect: \"fade\",\n fadeEffect: { crossFade: true },\n autoplay: { delay: 3000, disableOnInteraction: false },\n loop: true,\n speed: 1000,\n allowTouchMove: false,\n on: {\n init: function (this: any): void {\n if (\n this.slides.length <= 1 &&\n this.autoplay &&\n typeof this.autoplay.stop === \"function\"\n ) {\n this.autoplay.stop();\n }\n },\n },\n });\n (swiperEl as any).__swiperInstance = swiper;\n } catch (err) {\n console.warn(\"Announcement Swiper init failed:\", err);\n }\n }\n\n // // Visibility & cleanup\n // if (announcementBar && announcementList && announcementList.children.length > 0) {\n // navigationData.announcementbar.visibility = true;\n // } else {\n // navigationData.announcementbar.visibility = false;\n // if (announcementBar && announcementBar.parentNode) {\n // if (swiperEl && (swiperEl as any).__swiperInstance) {\n // (swiperEl as any).__swiperInstance.destroy(true, true);\n // (swiperEl as any).__swiperInstance = undefined;\n // }\n // announcementBar.parentNode.removeChild(announcementBar);\n // }\n // }\n}\n\n// --- Desktop Dropdown Positioning -------------------------------------------\n\nfunction initDesktopDropdownMenu() {\n const selector = '[fynd-navigation=\"dropdown-container\"]';\n const el = document.querySelector<HTMLElement>(selector);\n if (!el) {\n console.warn(`initDesktopDropdownMenu: element not found: ${selector}`);\n return;\n }\n\n const screenType = getScreenType?.() ?? \"unknown\";\n\n // Not desktop \u2192 reset transform\n if (screenType !== \"desktop\") {\n el.style.transition = el.style.transition || \"transform 0.3s ease\";\n el.style.transform = \"translateY(0px)\";\n return;\n }\n\n // Compute total stacked height\n let total = navigationData.default.height?.[screenType];\n let subtractFlag = false;\n\n if (navigationData.announcementbar?.visibility) {\n const h = navigationData.announcementbar.height?.[screenType];\n total = addPx(total, h);\n total = subtractPx(total, \"46px\");\n subtractFlag = true;\n }\n\n if (navigationData.ipbanner?.visibility) {\n // Currently not offsetting desktop for IP banner\n const h = \"0px\";\n total = addPx(total, h);\n if (!subtractFlag) {\n total = subtractPx(total, \"46px\");\n }\n }\n\n // Offset dropdown under nav (minus header overlap 46px)\n el.style.transform = `translateY(${total})`;\n}\n\n// --- Dynamic Spacer ----------------------------------------------------------\n\nfunction initNavigationSpacer() {\n const spacer = document.querySelector<HTMLElement>(\n '[fynd-navigation=\"spacer\"][data-wf--navigation-spacer--variant=\"dynamic\"]'\n );\n\n if (!spacer) {\n console.warn(\"initNavigationSpacer: spacer element not found\");\n return;\n }\n\n const toPx = (v?: string | number): number => {\n if (typeof v === \"number\") return v;\n if (typeof v === \"string\") {\n const n = parseFloat(v);\n return Number.isFinite(n) ? n : 0;\n }\n return 0;\n };\n\n const screenType = getScreenType?.() ?? \"desktop\";\n let total = navigationData.default.height?.[screenType];\n\n if (navigationData.announcementbar?.visibility) {\n const h = navigationData.announcementbar.height?.[screenType];\n total = addPx(total, h);\n }\n\n if (navigationData.ipbanner?.visibility) {\n const h = toPx(navigationData.ipbanner.height?.[screenType]);\n total = addPx(total, h);\n }\n\n spacer.style.height = `${total}`;\n}\n\n// --- IP Banner ---------------------------------------------------------------\n\nasync function initIpBanner() {\n const ipClosed = getCookie(\"ipBannerClosed\") === \"true\";\n if (ipClosed) {\n navigationData.ipbanner.visibility = false;\n return;\n }\n\n const geo = await getGeolocationCached();\n const path = window.location.pathname || \"/\";\n const allowByRoute = shouldOpenBannerForPage(path, geo ?? undefined);\n\n const countryReady = await initCountryDetection();\n\n if (allowByRoute && countryReady) {\n openBanner(\n ipBannerMain,\n ipBannerInner,\n navigationData.ipbanner.height.desktop\n );\n navigationData.ipbanner.visibility = true;\n\n const closeBtn = document.querySelector<HTMLElement>(closeIpBanner);\n if (closeBtn) {\n closeBtn.addEventListener(\"click\", () => {\n closeBanner(ipBannerMain, ipBannerInner);\n setCookie(\"ipBannerClosed\", \"true\", 24);\n navigationData.ipbanner.visibility = false;\n initDesktopDropdownMenu();\n initNavigationSpacer();\n });\n }\n } else {\n navigationData.ipbanner.visibility = false;\n }\n}\n\n// --- Init --------------------------------------------------------------------\n\ndocument.addEventListener(\"DOMContentLoaded\", async () => {\n await initIpBanner();\n initAnnouncementBar();\n initDesktopDropdownMenu();\n initNavigationSpacer();\n});\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["setCookie", "getCookie", "getCookie", "setCookie"]
|
|
7
7
|
}
|
package/package.json
CHANGED