@mapfirst.ai/core 0.0.30 → 0.0.31

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.
package/dist/index.js CHANGED
@@ -1,33 +1,2628 @@
1
- "use strict";var O=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var me=Object.prototype.hasOwnProperty;var de=(i,e)=>{for(var t in e)O(i,t,{get:e[t],enumerable:!0})},ue=(i,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ce(e))!me.call(i,r)&&r!==t&&O(i,r,{get:()=>e[r],enumerable:!(a=le(e,r))||a.enumerable});return i};var fe=i=>ue(O({},"__esModule",{value:!0}),i);var _e={};de(_e,{MapFirstCore:()=>V,PropertiesFetchError:()=>F,convertToApiFilters:()=>ae,fetchImages:()=>$,fetchProperties:()=>oe,processApiFilters:()=>re});module.exports=fe(_e);function z(i,{insertAt:e}={}){if(!i||typeof document=="undefined")return;let t=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css",e==="top"&&t.firstChild?t.insertBefore(a,t.firstChild):t.appendChild(a),a.styleSheet?a.styleSheet.cssText=i:a.appendChild(document.createTextNode(i))}z(`.mapfirst-marker-root{display:flex;z-index:20;flex-direction:column;align-items:center;pointer-events:auto}.mapfirst-marker-pill{border:2px solid;border-radius:999px;padding:8px;font-size:16px;font-weight:600;font-family:system-ui,-apple-system,sans-serif;box-shadow:0 4px 6px #6b728080;display:flex;align-items:center;justify-content:center;position:relative;transition:transform .2s;transform-origin:center bottom}.mapfirst-marker-pill-pending{background:#ffffff80;backdrop-filter:blur(4px);border-color:transparent;cursor:default}.mapfirst-marker-pill-active{background:#012b11;border-color:#fff;color:#fff;cursor:pointer}.mapfirst-marker-pill-active.mapfirst-marker-non-primary{background:#ffffffb3;border-color:#03852e80;color:#03852e80;padding:4px}.mapfirst-marker-pill-active.mapfirst-marker-selected{background:#fff;border-color:#03852e;color:#03852e;transform:scale(1.2)}.mapfirst-marker-pill-active:hover{transform:scale(1.2)}.mapfirst-marker-badge{position:absolute;top:-12px;right:-20px}.mapfirst-marker-award-container{position:relative;width:32px;height:32px}.mapfirst-marker-award-back{position:absolute;stroke:#f5f5f5;stroke-width:2px}.mapfirst-marker-award-dot{position:absolute;top:6.2px;left:6.3px;width:18.5px;height:18.5px;border-radius:50%;z-index:1}.mapfirst-marker-award-dot-type-0{background:#ffef0e}.mapfirst-marker-award-dot-type-1{background:#01ea5b}.mapfirst-marker-award-front{position:relative;z-index:2;color:#012b11}.mapfirst-marker-rating-badge{display:flex;align-items:center;justify-content:center;border-radius:999px;background:#03852e;color:#fff;font-size:12px;line-height:1;box-shadow:0 2px 4px #0003;padding:2px 6px;border:2px solid #ffffff;font-weight:400}.mapfirst-marker-content{display:flex;align-items:center}.mapfirst-marker-loading-video{width:20px;height:20px;display:block}.mapfirst-dot-marker-container{display:flex;z-index:10;align-items:center;justify-content:center;pointer-events:auto}.mapfirst-dot-marker-button{width:20px;height:20px;border-radius:999px;border:2px solid #ffffff;box-shadow:0 2px 4px #6b728066;transition:transform .2s;outline:none;transform-origin:center center}.mapfirst-dot-marker-button-pending{background:#d1d5db;cursor:default}.mapfirst-dot-marker-button-active{background:#012b11;cursor:pointer}.mapfirst-dot-marker-button-active.mapfirst-dot-marker-non-primary{background:#ffffffb3;border-color:#03852e33}.mapfirst-dot-marker-button-active.mapfirst-dot-marker-selected{background:#fff;border-color:#03852e}.mapfirst-dot-marker-button-active:hover{transform:scale(1.2)}.mapfirst-dot-marker-button-active:focus{outline:2px solid #ffffff;outline-offset:2px}.mapfirst-property-hover-card{position:absolute;width:270px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;overflow:hidden;display:flex;pointer-events:auto;z-index:9999;transition:opacity .2s;height:120px;text-decoration:none;color:inherit}.mapfirst-property-hover-card img{width:120px;height:120px;object-fit:cover;flex-shrink:0}.mapfirst-property-hover-image{width:120px;height:120px;flex-shrink:0}.mapfirst-property-hover-image-placeholder{background-color:#e5e7eb}.mapfirst-property-hover-details{display:flex;flex-direction:column;padding:8px 12px;flex:1;gap:4px}.mapfirst-property-hover-name{font-size:12px;font-weight:600;color:#1a1a1a;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.3}.mapfirst-property-hover-rating{display:flex;align-items:center;gap:4px;font-size:12px}.mapfirst-property-hover-rating .rating-value{font-weight:600;color:#1a1a1a}.mapfirst-property-hover-rating .stars{display:flex;gap:1px;font-size:10px;line-height:1;align-items:center}.mapfirst-property-hover-rating .reviews{color:#666;font-size:11px}.mapfirst-property-hover-price{font-size:12px;color:#666;margin-top:2px}.mapfirst-property-hover-price strong{color:#1a1a1a;font-weight:600}.mapfirst-property-hover-learn-more{font-size:12px;color:#03852e;text-decoration:none;font-weight:500;margin-top:auto;pointer-events:auto;display:inline-block}.mapfirst-property-hover-learn-more:hover{text-decoration:underline}
2
- `);var he='<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor"><path d="M12 3.953a7.442 7.442 0 1 0 .001 14.884A7.442 7.442 0 0 0 12 3.953m0 14.05a6.61 6.61 0 1 1 0-13.218 6.61 6.61 0 0 1 0 13.219M10.343 11.9a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.821 0m5.134 0a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.82 0m.82-1.897.84-.913h-1.863A5.8 5.8 0 0 0 12 8.08a5.77 5.77 0 0 0-3.27 1.008H6.862l.84.913a2.567 2.567 0 1 0 3.475 3.78l.823.896.823-.895a2.568 2.568 0 1 0 3.474-3.78m-6.865 3.634a1.738 1.738 0 1 1 0-3.476 1.738 1.738 0 0 1 0 3.476M12 11.85c0-1.143-.832-2.124-1.929-2.543A5 5 0 0 1 12 8.92a5 5 0 0 1 1.928.386c-1.096.42-1.927 1.4-1.927 2.543m2.566 1.787a1.738 1.738 0 1 1 .001-3.476 1.738 1.738 0 0 1 0 3.476m-8.456 3.719s-.377-.946-1.396-1.903c-1.02-.957-2.303-1.132-2.303-1.132s.457 1.02 1.54 2.04c1.086 1.017 2.159.995 2.159.995m2.568 1.41s-.524-.511-1.479-.883-1.861-.191-1.861-.191.598.54 1.615.935c1.016.397 1.725.139 1.725.139m2.493.505s-.545-.224-1.357-.196-1.415.47-1.415.47.608.222 1.473.193 1.3-.467 1.3-.467m-6.186-4.203s-.175-1.008-.974-2.154c-.8-1.147-2.015-1.578-2.015-1.578s.238 1.098 1.089 2.319c.85 1.22 1.9 1.413 1.9 1.413m-1.003-3.071s.195-1.021-.134-2.393c-.328-1.371-1.294-2.21-1.294-2.21s-.17 1.128.18 2.589c.35 1.46 1.248 2.014 1.248 2.014"></path><path d="M17.887 17.355s.377-.946 1.396-1.903c1.02-.957 2.303-1.132 2.303-1.132s-.457 1.02-1.54 2.04c-1.086 1.017-2.159.995-2.159.995m-2.567 1.41s.524-.511 1.479-.883 1.861-.191 1.861-.191-.598.54-1.615.935c-1.016.397-1.725.139-1.725.139m-2.493.505s.545-.224 1.357-.196 1.415.47 1.415.47-.608.222-1.473.193-1.3-.467-1.3-.467m6.186-4.203s.175-1.008.974-2.154c.8-1.147 2.015-1.578 2.015-1.578s-.238 1.098-1.089 2.319c-.85 1.22-1.9 1.413-1.9 1.413m1.003-3.071s-.195-1.021.133-2.393c.33-1.371 1.293-2.21 1.293-2.21s.17 1.128-.18 2.589c-.349 1.46-1.246 2.014-1.246 2.014M12 20.047a.413.413 0 1 0 0-.827.413.413 0 0 0 0 .827"></path></svg>',ge='<svg viewBox="0 0 24 24" width="32" height="32"><path d="M12 3.953a7.442 7.442 0 1 0 .001 14.884A7.442 7.442 0 0 0 12 3.953m0 14.05a6.61 6.61 0 1 1 0-13.218 6.61 6.61 0 0 1 0 13.219M10.343 11.9a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.821 0m5.134 0a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.82 0m.82-1.897.84-.913h-1.863A5.8 5.8 0 0 0 12 8.08a5.77 5.77 0 0 0-3.27 1.008H6.862l.84.913a2.567 2.567 0 1 0 3.475 3.78l.823.896.823-.895a2.568 2.568 0 1 0 3.474-3.78m-6.865 3.634a1.738 1.738 0 1 1 0-3.476 1.738 1.738 0 0 1 0 3.476M12 11.85c0-1.143-.832-2.124-1.929-2.543A5 5 0 0 1 12 8.92a5 5 0 0 1 1.928.386c-1.096.42-1.927 1.4-1.927 2.543m2.566 1.787a1.738 1.738 0 1 1 .001-3.476 1.738 1.738 0 0 1 0 3.476m-8.456 3.719s-.377-.946-1.396-1.903c-1.02-.957-2.303-1.132-2.303-1.132s.457 1.02 1.54 2.04c1.086 1.017 2.159.995 2.159.995m2.568 1.41s-.524-.511-1.479-.883-1.861-.191-1.861-.191.598.54 1.615.935c1.016.397 1.725.139 1.725.139m2.493.505s-.545-.224-1.357-.196-1.415.47-1.415.47.608.222 1.473.193 1.3-.467 1.3-.467m-6.186-4.203s-.175-1.008-.974-2.154c-.8-1.147-2.015-1.578-2.015-1.578s.238 1.098 1.089 2.319c.85 1.22 1.9 1.413 1.9 1.413m-1.003-3.071s.195-1.021-.134-2.393c-.328-1.371-1.294-2.21-1.294-2.21s-.17 1.128.18 2.589c.35 1.46 1.248 2.014 1.248 2.014"></path><path d="M17.887 17.355s.377-.946 1.396-1.903c1.02-.957 2.303-1.132 2.303-1.132s-.457 1.02-1.54 2.04c-1.086 1.017-2.159.995-2.159.995m-2.567 1.41s.524-.511 1.479-.883 1.861-.191 1.861-.191-.598.54-1.615.935c-1.016.397-1.725.139-1.725.139m-2.493.505s.545-.224 1.357-.196 1.415.47 1.415.47-.608.222-1.473.193-1.3-.467-1.3-.467m6.186-4.203s.175-1.008.974-2.154c.8-1.147 2.015-1.578 2.015-1.578s-.238 1.098-1.089 2.319c-.85 1.22-1.9 1.413-1.9 1.413m1.003-3.071s-.195-1.021.133-2.393c.33-1.371 1.293-2.21 1.293-2.21s.17 1.128-.18 2.589c-.349 1.46-1.246 2.014-1.246 2.014M12 20.047a.413.413 0 1 0 0-.827.413.413 0 0 0 0 .827"></path></svg>',ye='<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.051 6.549v.003l1.134 1.14 3.241-3.25.003-.002 1.134 1.136-3.243 3.252 1.134 1.14a1 1 0 0 0 .09-.008c.293-.05.573-.324.72-.474l.005-.006 2.596-2.603L22 8.016l-2.597 2.604a3.73 3.73 0 0 1-1.982 1.015 4.3 4.3 0 0 1-3.162-.657l-.023-.016-.026-.018-1.366 1.407 8.509 8.512L20.219 22l-.002-.002-6.654-6.663-2.597 2.76-7.3-7.315C1.967 8.948 1.531 6.274 2.524 4.198c.241-.504.566-.973.978-1.386l8.154 8.416 1.418-1.423-.039-.045c-.858-1.002-1.048-2.368-.62-3.595a4.15 4.15 0 0 1 .983-1.561L16 2l1.135 1.138-2.598 2.602-.047.045c-.16.151-.394.374-.433.678zM3.809 5.523c-.362 1.319-.037 2.905 1.06 4.103L10.93 15.7l1.408-1.496zM2.205 20.697 3.34 21.84l4.543-4.552-1.135-1.143z"/></svg>',be='<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.56 7.5H3.75a.25.25 0 0 0-.25.25v10c0 .138.112.25.25.25h16.5a.25.25 0 0 0 .25-.25v-10a.25.25 0 0 0-.25-.25h-3.81l-2-2H9.56zM8.94 4h6.12l2 2h3.19c.966 0 1.75.784 1.75 1.75v10a1.75 1.75 0 0 1-1.75 1.75H3.75A1.75 1.75 0 0 1 2 17.75v-10C2 6.784 2.784 6 3.75 6h3.19z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12 9.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5M7.75 12a4.25 4.25 0 1 1 8.5 0 4.25 4.25 0 0 1-8.5 0"/></svg>',Me='<video class="mapfirst-marker-loading-video" src="https://api.mapfirst.ai/static/images/loading.webm" autoplay loop muted></video>';function E(i,e,t,a){if(i.dataset.hasHoverCard==="true")return;i.dataset.hasHoverCard="true";let r=ve(t),n=null,s=null,m=null,p=()=>{n&&(clearTimeout(n),n=null),s&&(clearTimeout(s),s=null),m&&(cancelAnimationFrame(m),m=null),r.parentElement&&r.remove()},f=()=>{if(r.parentElement){let o=i.parentElement;for(;o&&getComputedStyle(o).position==="static";)o=o.parentElement;o&&(Z(r,i,o),m=requestAnimationFrame(f))}},y=(o=!1)=>{s&&(clearTimeout(s),s=null);let d=()=>{let u=i.parentElement;for(;u&&getComputedStyle(u).position==="static";)u=u.parentElement;u&&(u.appendChild(r),Z(r,i,u),Pe(r,t),m=requestAnimationFrame(f))};o?d():n=setTimeout(d,300)},M=()=>{a||(n&&(clearTimeout(n),n=null),m&&(cancelAnimationFrame(m),m=null),s=setTimeout(()=>{r.parentElement&&r.remove()},100))};a&&y(!0),e.addEventListener("mouseenter",()=>y(!1)),e.addEventListener("mouseleave",M),r.addEventListener("mouseenter",()=>{s&&(clearTimeout(s),s=null),!m&&r.parentElement&&(m=requestAnimationFrame(f))}),r.addEventListener("mouseleave",M);let l=new MutationObserver(o=>{for(let d of o)for(let u of d.removedNodes)if(u===i||u.contains(i)){p(),l.disconnect();return}});if(i.parentElement)l.observe(i.parentElement,{childList:!0,subtree:!0});else{let o=setInterval(()=>{i.parentElement&&(l.observe(i.parentElement,{childList:!0,subtree:!0}),clearInterval(o))},100)}}function ke(i){return`https://api.mapfirst.ai/static/images/${i.toLowerCase().replace(/\s+/g,"").replace(/&/g,"")}.webp`}function ve(i){var p,f,y,M,l,o;let e=(y=(f=(p=i.pricing)==null?void 0:p.offer)==null?void 0:f.clickUrl)!=null?y:i.url,t=document.createElement(e?"a":"div");t.className="mapfirst-property-hover-card",t.setAttribute("data-marker-id",i.tripadvisor_id.toString()),e&&(t.href=e,t.target="_blank");let a=i.rating||0,r=i.reviews||0,n=(o=(l=(M=i.pricing)==null?void 0:M.offer)==null?void 0:l.displayPrice)!=null?o:i.price_level,s=()=>{let d=Math.floor(a),u=a%1!==0,b=[],g=`
3
- display: inline-block;
4
- width: 8px;
5
- height: 8px;
6
- border: 1px solid #03852e;
7
- border-radius: 9999px;
8
- `;for(let h=0;h<d;h++)b.push(`<span style="${g} background-color: #03852e;"></span>`);u&&b.push(`<span style="${g} background: linear-gradient(90deg, #03852e 50%, transparent 50%);"></span>`);let c=5-Math.ceil(a);for(let h=0;h<c;h++)b.push(`<span style="${g}"></span>`);return b.join("")},m=ke(i.type);return t.innerHTML=`
9
- <div
10
- class="mapfirst-property-hover-image mapfirst-property-hover-image-placeholder"
11
- data-tripadvisor-id="${i.tripadvisor_id}"
12
- data-default-image="${m}"
13
- ></div>
14
- <div class="mapfirst-property-hover-details">
15
- <div class="mapfirst-property-hover-name">${i.name}</div>
16
- <div class="mapfirst-property-hover-rating">
17
- <span class="rating-value">${a.toFixed(1)}</span>
18
- <span class="stars">${s()}</span>
19
- <span class="reviews">(${r})</span>
20
- </div>
21
- ${i.type==="Accommodation"&&n?`
22
- <div class="mapfirst-property-hover-price">
23
- Starting at <strong>${n}</strong>
24
- </div>
25
- `:""}
26
- ${e?`
27
- <span class="mapfirst-property-hover-learn-more">
28
- Learn More
29
- </span>
30
- `:""}
31
- </div>
32
- `,t}function Pe(i,e){let t=i.querySelector(".mapfirst-property-hover-image");if(t&&e.tripadvisor_id&&!t.dataset.imageLoaded){t.dataset.imageLoaded="loading";let a=t.dataset.defaultImage;$(e.tripadvisor_id,1).then(r=>{if(r&&t){let n=document.createElement("img");n.src=r,n.alt=e.name,n.style.width="100%",n.style.height="100%",n.style.objectFit="cover",t.innerHTML="",t.appendChild(n),t.classList.remove("mapfirst-property-hover-image-placeholder"),t.dataset.imageLoaded="true"}else throw new Error("No image URL")}).catch(()=>{if(a&&t){let r=document.createElement("img");r.src=a,r.alt=e.name,r.style.width="100%",r.style.height="100%",r.style.objectFit="cover",t.innerHTML="",t.appendChild(r),t.classList.remove("mapfirst-property-hover-image-placeholder"),t.dataset.imageLoaded="false"}})}}function Z(i,e,t){let a=e.getBoundingClientRect(),r=t.getBoundingClientRect(),n=270,s=120,m=12,p=r.right-a.right,f=a.left-r.left,y=r.bottom-a.bottom,M=a.top-r.top,l=a.left-r.left+a.width/2-n/2,o=a.top-r.top+a.height+m;l<0?l=8:l+n>r.width&&(l=r.width-n-8),y<s+m&&M>y&&(o=a.top-r.top-s-m),i.style.left=`${l}px`,i.style.top=`${o}px`}function W(i,e,t,a){var u,b,g,c,h,v,A,T,x;if(typeof document=="undefined")return null;let r=i.marker,n=r.type===e,s=t===r.tripadvisor_id,m=r.type==="Accommodation",p=(b=(u=r.pricing)==null?void 0:u.offer)==null?void 0:b.displayPrice,f=m&&!p,y=(()=>{if(r.rating===void 0||r.rating===null)return null;let L=typeof r.rating=="number"?r.rating:Number(r.rating);return Number.isNaN(L)||L<=0?null:L.toFixed(1)})(),M=document.createElement("div");M.className="mapfirst-marker-root",M.style.zIndex=s?"20":n?"12":"11";let l=(h=(c=(g=r.pricing)==null?void 0:g.offer)==null?void 0:c.clickUrl)!=null?h:r.url,o=document.createElement(l?"a":"div");if(l&&(o.href=l,o.target="_blank",o.style.textDecoration="none"),o.className=f?"mapfirst-marker-pill mapfirst-marker-pill-pending":`mapfirst-marker-pill mapfirst-marker-pill-active${s?" mapfirst-marker-selected":n?"":" mapfirst-marker-non-primary"}`,!f&&((v=r.awards)!=null&&v.length||y)){let L=document.createElement("div");if(L.className="mapfirst-marker-badge",n||(L.style.opacity="0.2"),L.className="mapfirst-marker-badge",(A=r.awards)!=null&&A.length&&r.awards[0].type){let k=document.createElement("div");k.className="mapfirst-marker-award-container";let P=document.createElement("div");P.className="mapfirst-marker-award-back",P.innerHTML=ge;let C=document.createElement("div");C.className=`mapfirst-marker-award-dot mapfirst-marker-award-dot-type-${r.awards[0].type}`;let w=document.createElement("div");w.className="mapfirst-marker-award-front",w.innerHTML=he,k.appendChild(P),k.appendChild(C),k.appendChild(w),L.appendChild(k)}else y&&(L.className="mapfirst-marker-badge mapfirst-marker-rating-badge",L.textContent=y);o.appendChild(L)}let d=document.createElement("span");return d.className="mapfirst-marker-content",m?(x=(T=r.pricing)==null?void 0:T.offer)!=null&&x.displayPrice?(d.innerHTML=r.pricing.offer.displayPrice,d.dataset.price=r.pricing.offer.displayPrice):(d.innerHTML=Me,d.dataset.price=""):r.type==="Eat & Drink"?d.innerHTML=ye:r.type==="Attraction"&&(d.innerHTML=be),o.appendChild(d),o.addEventListener("click",L=>{L.stopPropagation(),f||a==null||a(r)}),f||E(M,o,r,s),M.appendChild(o),M}function X(i,e,t,a){var M,l,o;if(typeof document=="undefined")return null;let r=i.marker,n=r.type===e,s=t===r.tripadvisor_id,p=r.type==="Accommodation"&&((l=(M=r.pricing)==null?void 0:M.offer)==null?void 0:l.availability)!=="available",f=document.createElement("div");f.className="mapfirst-dot-marker-container",f.style.zIndex=s?"20":n?"3":"1";let y=document.createElement("div");return y.className=p?"mapfirst-dot-marker-button mapfirst-dot-marker-button-pending":`mapfirst-dot-marker-button mapfirst-dot-marker-button-active${s?" mapfirst-dot-marker-selected":n?"":" mapfirst-dot-marker-non-primary"}`,y.title=(o=r.name)!=null?o:String(r.tripadvisor_id),y.addEventListener("click",d=>{d.stopPropagation(),p||a==null||a(r)}),f.appendChild(y),p||E(f,y,r,s),f}var xe='<video class="mapfirst-marker-loading-video" src="https://api.mapfirst.ai/static/images/loading.webm" autoplay loop muted></video>';function q(i,e,t,a,r){var f,y,M,l,o,d,u,b,g,c;let n=(y=(f=i.querySelector(".mapfirst-marker-pill"))==null?void 0:f.classList.contains("mapfirst-marker-pill-pending"))!=null?y:!1,s=i;s.style.zIndex=t?"20":e?"12":"11";let m=s.querySelector(".mapfirst-marker-pill");m&&(a?m.className="mapfirst-marker-pill mapfirst-marker-pill-pending":m.className=`mapfirst-marker-pill mapfirst-marker-pill-active${t?" mapfirst-marker-selected":e?"":" mapfirst-marker-non-primary"}`);let p=s.querySelector(".mapfirst-marker-badge");if(p instanceof HTMLElement&&(p.style.opacity=!e&&!t?"0.2":""),n&&!a&&r){let h=s.querySelector(".mapfirst-marker-pill");h instanceof HTMLElement&&E(s,h,r,t)}if(r&&r.type==="Accommodation"){let h=s.querySelector(".mapfirst-marker-content");if(h instanceof HTMLElement){let v=(l=(M=r.pricing)==null?void 0:M.offer)==null?void 0:l.displayPrice;h.dataset.price!==v&&(v?(h.innerHTML=v,h.dataset.price=v):(h.innerHTML=xe,h.dataset.price=""))}}if(r){let h=document.querySelector(`.mapfirst-property-hover-card[data-marker-id="${r.tripadvisor_id}"]`);if(h){let v=r.rating||0,A=r.reviews||0,T=(u=(d=(o=r.pricing)==null?void 0:o.offer)==null?void 0:d.displayPrice)!=null?u:r.price_level,x=h.querySelector(".rating-value");if(x){let P=v.toFixed(1);x.textContent!==P&&(x.textContent=P)}let L=h.querySelector(".reviews");if(L){let P=`(${A})`;L.textContent!==P&&(L.textContent=P)}if(r.type==="Accommodation"&&T){let P=h.querySelector(".mapfirst-property-hover-price");if(!P){P=document.createElement("div"),P.className="mapfirst-property-hover-price";let C=h.querySelector(".mapfirst-property-hover-details"),w=h.querySelector(".mapfirst-property-hover-learn-more");C&&(w?C.insertBefore(P,w):C.appendChild(P))}if(P){let C=`Starting at <strong>${T}</strong>`;P.innerHTML!==C&&(P.innerHTML=C)}}let k=(c=(g=(b=r.pricing)==null?void 0:b.offer)==null?void 0:g.clickUrl)!=null?c:r.url;k&&h instanceof HTMLAnchorElement&&h.href!==k&&(h.href=k)}}}function j(i,e,t,a){let r=i;r.style.zIndex=t?"20":e?"3":"1";let n=r.querySelector(".mapfirst-dot-marker-button");n&&(a?n.className="mapfirst-dot-marker-button mapfirst-dot-marker-button-pending":n.className=`mapfirst-dot-marker-button mapfirst-dot-marker-button-active${t?" mapfirst-dot-marker-selected":e?"":" mapfirst-dot-marker-non-primary"}`)}function J(i){let e=i.match(/^(?:primary|dot)-(\d+)-/);return e?parseInt(e[1],10):null}var I=class{constructor(e,t){this.markerCache=new Map;this.primaryType="Accommodation";this.selectedMarkerId=null;this.mapInstance=e,this.onMarkerClick=t}render(e,t,a){var n,s,m,p,f,y,M,l;t&&t!==this.primaryType&&(this.primaryType=t),a!==void 0&&(this.selectedMarkerId=a);let r=new Set(e.map(o=>o.key));for(let[o,d]of this.markerCache.entries())r.has(o)||(this.removeMarkerFromMap(d.marker),this.markerCache.delete(o));for(let o of e){let d=Le(o.marker.location);if(!d)continue;let u=this.markerCache.get(o.key);if(u){let b=o.marker.type===this.primaryType,g=this.selectedMarkerId===o.marker.tripadvisor_id,c=o.marker.type==="Accommodation",h=o.kind==="primary"?c&&!((s=(n=o.marker.pricing)==null?void 0:n.offer)!=null&&s.displayPrice):c&&((p=(m=o.marker.pricing)==null?void 0:m.offer)==null?void 0:p.availability)!=="available",v=this.getMarkerElement(u.marker);v&&(o.kind==="primary"?q(v,b,g,h,o.marker):j(v,b,g,h));try{this.updateMarkerPosition(u.marker,d)}catch{this.removeMarkerFromMap(u.marker),this.markerCache.delete(o.key),this.createAndAddMarker(o,d)}}else{let b=o.marker.tripadvisor_id,g,c;for(let[h,v]of this.markerCache.entries())if(J(h)===b&&v.kind===o.kind){g=v,c=h;break}if(g&&c){let h=o.marker.type===this.primaryType,v=this.selectedMarkerId===o.marker.tripadvisor_id,A=o.marker.type==="Accommodation",T=o.kind==="primary"?A&&!((y=(f=o.marker.pricing)==null?void 0:f.offer)!=null&&y.displayPrice):A&&((l=(M=o.marker.pricing)==null?void 0:M.offer)==null?void 0:l.availability)!=="available",x=this.getMarkerElement(g.marker);x&&(o.kind==="primary"?q(x,h,v,T,o.marker):j(x,h,v,T)),this.updateMarkerZIndex(g.marker,o,h,v),this.markerCache.delete(c),this.markerCache.set(o.key,g);try{this.updateMarkerPosition(g.marker,d)}catch{}}else this.createAndAddMarker(o,d)}}}destroy(){for(let e of this.markerCache.values())this.removeMarkerFromMap(e.marker);this.markerCache.clear()}createAndAddMarker(e,t){let a=e.kind==="primary"?W(e,this.primaryType,this.selectedMarkerId,this.onMarkerClick):X(e,this.primaryType,this.selectedMarkerId,this.onMarkerClick);if(!a)return;let r=e.marker.type===this.primaryType,n=this.selectedMarkerId===e.marker.tripadvisor_id;try{let s=this.createMarker(a,t,e,r,n);s&&this.markerCache.set(e.key,{key:e.key,marker:s,kind:e.kind,parentId:e.kind==="dot"?e.parentId:void 0})}catch(s){console.error("Error creating marker",s)}}updateMarkerZIndex(e,t,a,r){}};function Le(i){return typeof(i==null?void 0:i.lon)!="number"||typeof(i==null?void 0:i.lat)!="number"||Number.isNaN(i.lon)||Number.isNaN(i.lat)?null:{lon:i.lon,lat:i.lat}}var B=class extends I{constructor(e){var t;super(e.mapInstance,e.onMarkerClick),this.MarkerCtor=(t=e.maplibregl)==null?void 0:t.Marker}render(e,t,a){this.MarkerCtor&&super.render(e,t,a)}createMarker(e,t,a){return this.MarkerCtor?new this.MarkerCtor({element:e,anchor:a.kind==="primary"?"bottom":"center"}).setLngLat([t.lon,t.lat]).addTo(this.mapInstance):null}removeMarkerFromMap(e){try{e.remove()}catch{}}updateMarkerPosition(e,t){e.setLngLat([t.lon,t.lat])}getMarkerElement(e){return e.getElement()}};var _=class extends I{constructor(e){super(e.mapInstance,e.onMarkerClick),this.google=e.google}render(e,t,a){var r,n;if(!((n=(r=this.google)==null?void 0:r.marker)!=null&&n.AdvancedMarkerElement)){console.warn("AdvancedMarkerElement not available");return}super.render(e,t,a)}createMarker(e,t,a,r,n){var m,p;if(!((p=(m=this.google)==null?void 0:m.marker)!=null&&p.AdvancedMarkerElement))return null;let s=a.kind==="primary"?n?20:r?12:11:n?20:r?3:1;return new this.google.marker.AdvancedMarkerElement({map:this.mapInstance,position:{lat:t.lat,lng:t.lon},content:e,zIndex:s})}removeMarkerFromMap(e){try{e.map=null}catch(t){console.error("Error removing marker",t)}}updateMarkerPosition(e,t){e.position={lat:t.lat,lng:t.lon}}getMarkerElement(e){let t=e.content;return t instanceof HTMLElement?t:null}updateMarkerZIndex(e,t,a,r){let n=t.kind==="primary"?r?20:a?12:11:r?20:a?3:1;e.zIndex=n}};var R=class extends I{constructor(e){var t;super(e.mapInstance,e.onMarkerClick),this.MarkerCtor=(t=e.mapboxgl)==null?void 0:t.Marker}render(e,t,a){this.MarkerCtor&&super.render(e,t,a)}createMarker(e,t,a){return this.MarkerCtor?new this.MarkerCtor({element:e,anchor:a.kind==="primary"?"bottom":"center"}).setLngLat([t.lon,t.lat]).addTo(this.mapInstance):null}removeMarkerFromMap(e){try{e.remove()}catch{}}updateMarkerPosition(e,t){e.setLngLat([t.lon,t.lat])}getMarkerElement(e){return e.getElement()}};var S=class{constructor(e){this.map=e}getMap(){return this.map}setupImpressionTracking(e){if(typeof window=="undefined"||!window.IntersectionObserver)return;let t=this.getContainer();if(!t)return;let a=new IntersectionObserver(s=>{s.forEach(m=>{m.isIntersecting&&(e(),a.disconnect())})},{threshold:.1});a.observe(t);let r=()=>a.disconnect(),n=this.cleanup.bind(this);this.cleanup=()=>{r(),n()}}};var H=class extends S{constructor(t){super(t);this.cleanupFns=[]}initialize(t){return this.markerManager=new B({mapInstance:this.map,maplibregl:t.maplibregl,onMarkerClick:t.onMarkerClick}),t.onRefresh&&this.attachEventListeners(t.onRefresh),t.onMapMoveEnd&&this.attachBoundsTracking(t.onMapMoveEnd),this.markerManager}attachBoundsTracking(t){if(!this.map||typeof this.map.on!="function")return;let a=()=>{let n=this.getMapBounds();t(n)},r=()=>{let n=this.getMapBounds();t(n)};this.map.loaded&&this.map.loaded()?r():(this.map.once("load",r),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off("load",r)})),this.map.on("moveend",a),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off("moveend",a)})}attachEventListeners(t){if(!this.map||typeof this.map.on!="function")return;["move","zoom","dragend","pitch","rotate"].forEach(r=>{this.map.on(r,t),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off(r,t)})})}getMarkerManager(){return this.markerManager}getContainer(){var t,a;return((a=(t=this.map)==null?void 0:t.getContainer)==null?void 0:a.call(t))||null}cleanup(){for(let t of this.cleanupFns)try{t()}catch{}this.cleanupFns.length=0}getMap(){return this.map}getCenter(){let t=this.map.getCenter();return{lng:t.lng,lat:t.lat}}getZoom(){return this.map.getZoom()}getBearing(){return this.map.getBearing()}getPitch(){return this.map.getPitch()}getMapBounds(){let t=this.map.getBounds(),a=t.getSouthWest(),r=t.getNorthEast();return{sw:{lat:a.lat,lng:a.lng},ne:{lat:r.lat,lng:r.lng}}}project(t){return this.map.project({lng:t[0],lat:t[1]})}on(t,a){this.map.on(t,a)}off(t,a){this.map.off(t,a)}resize(){this.map.resize()}remove(){this.cleanup(),this.map.remove()}};var D=class extends S{constructor(t){super(t);this.cleanupFns=[];this.initializeOverlayView()}initialize(t){return this.markerManager=new _({mapInstance:this.map,google:t.google,onMarkerClick:t.onMarkerClick}),t.onRefresh&&this.attachEventListeners(t.onRefresh),t.onMapMoveEnd&&this.attachBoundsTracking(t.onMapMoveEnd,t.google),this.markerManager}attachBoundsTracking(t,a){if(!this.map)return;let r=()=>{let s=this.getMapBounds();t(s)};r();let n=a.event.addListener(this.map,"idle",r);this.cleanupFns.push(()=>{a.event.removeListener(n)})}attachEventListeners(t){let a=["center_changed","zoom_changed","drag","heading_changed","tilt_changed"],r=[];a.forEach(n=>{let s=this.map.addListener(n,t);r.push(s)}),this.cleanupFns.push(()=>{r.forEach(n=>{try{n.remove()}catch{}})})}getMarkerManager(){return this.markerManager}getContainer(){var t,a;return((a=(t=this.map)==null?void 0:t.getDiv)==null?void 0:a.call(t))||null}cleanup(){for(let t of this.cleanupFns)try{t()}catch{}this.cleanupFns.length=0}initializeOverlayView(){var r;let t=(r=globalThis.google)==null?void 0:r.maps;if(!t)return;let a=t.OverlayView;a&&(this.overlayView=new a,this.overlayView.draw=function(){},this.overlayView.setMap(this.map))}getMap(){return this.map}getCenter(){let t=this.map.getCenter();return t?{lng:t.lng(),lat:t.lat()}:{lng:0,lat:0}}getZoom(){var t;return(t=this.map.getZoom())!=null?t:0}getBearing(){var t;return(t=this.map.getHeading())!=null?t:0}getPitch(){var t;return(t=this.map.getTilt())!=null?t:0}getMapBounds(){let t=this.map.getBounds();if(!t)return{sw:{lat:0,lng:0},ne:{lat:0,lng:0}};let a=t.getSouthWest(),r=t.getNorthEast();return{sw:{lat:a.lat(),lng:a.lng()},ne:{lat:r.lat(),lng:r.lng()}}}project(t){var m;if(!this.overlayView)return{x:0,y:0};let a=this.overlayView.getProjection();if(!a)return{x:0,y:0};let r=(m=globalThis.google)==null?void 0:m.maps;if(!r)return{x:0,y:0};let n=new r.LatLng(t[1],t[0]),s=a.fromLatLngToContainerPixel(n);return s?{x:s.x,y:s.y}:{x:0,y:0}}on(t,a){this.map.addListener(t,a)}off(t,a){var n;let r=(n=globalThis.google)==null?void 0:n.maps;r!=null&&r.event&&r.event.clearListeners(this.map,t)}resize(){var a;let t=(a=globalThis.google)==null?void 0:a.maps;t!=null&&t.event&&t.event.trigger(this.map,"resize")}remove(){this.cleanup(),this.overlayView&&(this.overlayView.setMap(null),this.overlayView=null)}};var N=class extends S{constructor(t){super(t);this.cleanupFns=[]}initialize(t){return this.markerManager=new R({mapInstance:this.map,mapboxgl:t.mapboxgl,onMarkerClick:t.onMarkerClick}),t.onRefresh&&this.attachEventListeners(t.onRefresh),t.onMapMoveEnd&&this.attachBoundsTracking(t.onMapMoveEnd),this.markerManager}attachBoundsTracking(t){if(!this.map||typeof this.map.on!="function")return;let a=()=>{let n=this.getMapBounds();t(n)},r=()=>{let n=this.getMapBounds();t(n)};this.map.loaded&&this.map.loaded()?r():(this.map.once("load",r),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off("load",r)})),this.map.on("moveend",a),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off("moveend",a)})}attachEventListeners(t){if(!this.map||typeof this.map.on!="function")return;["move","zoom","dragend","pitch","rotate"].forEach(r=>{this.map.on(r,t),this.cleanupFns.push(()=>{typeof this.map.off=="function"&&this.map.off(r,t)})})}getMarkerManager(){return this.markerManager}getContainer(){var t,a;return((a=(t=this.map)==null?void 0:t.getContainer)==null?void 0:a.call(t))||null}cleanup(){for(let t of this.cleanupFns)try{t()}catch{}this.cleanupFns.length=0}getMap(){return this.map}getCenter(){let t=this.map.getCenter();return{lng:t.lng,lat:t.lat}}getZoom(){return this.map.getZoom()}getBearing(){return this.map.getBearing()}getPitch(){return this.map.getPitch()}getMapBounds(){let t=this.map.getBounds(),a=t.getSouthWest(),r=t.getNorthEast();return{sw:{lat:a.lat,lng:a.lng},ne:{lat:r.lat,lng:r.lng}}}project(t){return this.map.project({lng:t[0],lat:t[1]})}on(t,a){this.map.on(t,a)}off(t,a){this.map.off(t,a)}resize(){this.map.resize()}remove(){this.cleanup(),this.map.remove()}};function ee(i){let e=i.getCenter();return{longitude:e.lng,latitude:e.lat,zoom:i.getZoom(),bearing:i.getBearing(),pitch:i.getPitch()}}var Te=[{zoom:6,threshold:120},{zoom:8,threshold:108},{zoom:10,threshold:92},{zoom:12,threshold:80},{zoom:14,threshold:68},{zoom:16,threshold:56}];function te(i){for(let e of Te)if(i<=e.zoom)return e.threshold;return 48}function G({primaryType:i,markers:e,map:t,selectedMarkerId:a,zoom:r,collisionThresholdPx:n,dotCollisionThresholdPx:s}){if(!e.length)return[];if(!t)return e.map(u=>({kind:"primary",marker:u,key:`primary-${u.tripadvisor_id}`}));let m=e.map((u,b)=>{let g=u.location;if(typeof(g==null?void 0:g.lon)!="number"||typeof(g==null?void 0:g.lat)!="number")return null;let{x:c,y:h}=t.project([g.lon,g.lat]);return{marker:u,index:b,x:c,y:h}}).filter(u=>!!u);if(!m.length)return[];let p=te(r),f=Ce(r),y=m.map((u,b)=>b),M=u=>y[u]===u?u:(y[u]=M(y[u]),y[u]),l=(u,b)=>{let g=M(u),c=M(b);g!==c&&(y[c]=g)};for(let u=0;u<m.length;u+=1)for(let b=u+1;b<m.length;b+=1){let g=m[u].x-m[b].x,c=m[u].y-m[b].y;Math.hypot(g,c)<=p&&l(u,b)}let o=new Map;for(let u of m){let b=M(u.index),g=o.get(b);g?g.push(u):o.set(b,[u])}let d=[];return o.forEach(u=>{var x,L;if(u.length===1){let[{marker:k}]=u,P=k.type===i,C=a===k.tripadvisor_id;d.push({kind:"primary",marker:k,key:`primary-${k.tripadvisor_id}-p${P?1:0}-s${C?1:0}-${(x=k.pricing)==null?void 0:x.availability}`});return}let b=[...u].sort((k,P)=>we(P.marker,k.marker,i)),[g,...c]=b,h=g.marker.type===i,v=a===g.marker.tripadvisor_id;if(d.push({kind:"primary",marker:g.marker,key:`primary-${g.marker.tripadvisor_id}-p${h?1:0}-s${v?1:0}-${(L=g.marker.pricing)==null?void 0:L.availability}`}),!c.length)return;let A=[],T=[];if(c.forEach(k=>{var P;if(a&&k.marker.tripadvisor_id===a){let C=k.marker.type===i;d.push({kind:"primary",marker:k.marker,key:`primary-${k.marker.tripadvisor_id}-p${C?1:0}-s1-${(P=k.marker.pricing)==null?void 0:P.availability}`});return}Ae(g,k)<=f?A.push(k):T.push(k)}),A.forEach(k=>{var C;let P=k.marker.type===i;d.push({kind:"dot",marker:k.marker,key:`dot-${k.marker.tripadvisor_id}-p${P?1:0}-s0-${(C=k.marker.pricing)==null?void 0:C.availability}`,parentId:g.marker.tripadvisor_id})}),T.length){let k=G({markers:T.map(P=>P.marker),map:t,selectedMarkerId:a,zoom:r,primaryType:i,collisionThresholdPx:n,dotCollisionThresholdPx:s});d.push(...k)}}),d}function Ae(i,e){return Math.hypot(i.x-e.x,i.y-e.y)}function Ce(i){let e=te(i);return Math.max(48,e)}function we(i,e,t){var p,f;let a=i.type===t,r=e.type===t;if(a&&!r)return 1;if(!a&&r)return-1;let n=Y(i)-Y(e);if(n!==0)return n;let s=Q(i)-Q(e);if(s!==0)return s;let m=((p=i.reviews)!=null?p:0)-((f=e.reviews)!=null?f:0);return m!==0?m:i.tripadvisor_id-e.tripadvisor_id}function Y(i){if(typeof i.rating=="number")return i.rating;if(i.rating===void 0||i.rating===null)return-1/0;let e=Number(i.rating);return Number.isNaN(e)?-1/0:e}function Q(i){var t,a,r;if(!((a=(t=i.pricing)==null?void 0:t.offer)!=null&&a.price))return-1/0;let e=Number(((r=i.pricing.offer.displayPrice)!=null?r:"0").replace(/[^0-9.,-]+/g,"").replace(/,/g,""));return Number.isNaN(e)?-1/0:e}function re(i){let e=[];return i.amenities&&Array.isArray(i.amenities)&&i.amenities.forEach(t=>{e.push({id:`amenity-${t}`,label:t,type:"amenity",value:t})}),i.hotelStyle&&Array.isArray(i.hotelStyle)&&i.hotelStyle.forEach(t=>{e.push({id:`hotelStyle-${t}`,label:t,type:"hotelStyle",value:t})}),i.price&&e.push({id:"priceRange",label:"Price Range",type:"priceRange",value:`${i.price.min}-${i.price.max}`,priceRange:i.price}),typeof i.minRating=="number"&&Number.isFinite(i.minRating)&&e.push({id:"minRating",label:`${i.minRating}+`,type:"minRating",value:String(i.minRating),numericValue:i.minRating}),typeof i.starRating=="number"&&Number.isFinite(i.starRating)&&e.push({id:"starRating",label:`${i.starRating} Stars`,type:"starRating",value:String(i.starRating),numericValue:i.starRating}),i.transformed_query&&e.push({id:"transformed_query",label:i.transformed_query,type:"transformed_query",value:i.transformed_query}),i.selected_restaurant_price_levels&&e.push({id:"selected_restaurant_price_levels",label:i.selected_restaurant_price_levels.join(", "),type:"selected_restaurant_price_levels",value:i.selected_restaurant_price_levels.join(", "),priceLevels:i.selected_restaurant_price_levels}),e}function ae(i){return i.map(e=>{let t={id:e.id,label:typeof e.label=="string"?e.label:String(e.label||""),type:e.type,value:e.value};if(e.numericValue!==void 0&&(t.numericValue=e.numericValue),e.priceRange){let a=e.priceRange.min,r=e.priceRange.max;a!==void 0&&(t.priceRange={min:a,...r!==void 0&&{max:r}})}return e.priceLevels&&(t.priceLevels=e.priceLevels),t})}var Ie={prod:"https://api.mapfirst.ai",test:"https://api.mapfirst.ai/test"},F=class extends Error{constructor({message:e,status:t,code:a}){super(e),this.name="PropertiesFetchError",this.status=t,this.code=a}};async function $(i,e=1){try{let t=await fetch(`https://l4detuz832.execute-api.us-east-1.amazonaws.com/dev/photo?id=${i}&limit=${e}`);if(!t.ok)return null;let a=await t.json();if(a.photos&&a.photos.length>0){let r=a.photos[0].FullSizeURL.url;if((await fetch(r)).ok)return r}return null}catch(t){return console.debug("Failed to fetch images:",t),null}}async function oe(i,e,t,{signal:a}={}){var s,m;let r;try{document.referrer&&(r=document.referrer)}catch(p){console.error(p)}let n=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Source":"SDK",...t&&{"X-API-Key":t},...r&&{"X-Referer":r}},body:JSON.stringify(e),signal:a});if(!n.ok){let p=`Unexpected response: ${n.status}`,f;try{let y=await n.json();p=(m=(s=y.detail)!=null?s:y.error)!=null?m:p,f=y.code}catch{}throw new F({message:p,status:n.status,code:f})}return await n.json()}function ie(i){return typeof i=="string"?i:i.toISOString().slice(0,10)}var ne="Accommodation";function Se(){let e=new Date(Date.now()+864e6),t=(6-e.getDay()+7)%7,a=new Date(e.getTime()+t*864e5),r=a.getDay(),n=r===0?6:6-r,s=new Date(a.getTime()+(n+1)*864e5);return{checkIn:a,checkOut:s}}var V=class{constructor(e){this.options=e;this.adapter=null;this.properties=[];this.selectedMarkerId=null;this.destroyed=!1;this.clusterItems=[];this.isMapAttached=!1;var r,n,s,m,p,f,y,M,l,o,d,u,b,g,c,h,v,A,T,x,L;if(this.properties=[...(r=e.properties)!=null?r:[]],this.primaryType=e.primaryType,this.selectedMarkerId=(n=e.selectedMarkerId)!=null?n:null,this.useApi=(s=e.useApi)!=null?s:!0,this.environment=(m=e.environment)!=null?m:"prod",this.apiUrl=(p=e.apiUrl)!=null?p:Ie[this.environment],this.apiKey=e.apiKey,this.requestBody=e.requestBody,this.currentPlatform=e.platform,!this.useApi&&e.platform&&e.platform!=="maplibre")throw new Error("When useApi is false, only maplibre platform is supported. Google Maps and Mapbox require API usage.");let t=se(e);this.fitBoundsPadding={top:(y=(f=e.fitBoundsPadding)==null?void 0:f.top)!=null?y:t?0:50,bottom:(l=(M=e.fitBoundsPadding)==null?void 0:M.bottom)!=null?l:t?0:160,left:(d=(o=e.fitBoundsPadding)==null?void 0:o.left)!=null?d:t?0:50,right:(b=(u=e.fitBoundsPadding)==null?void 0:u.right)!=null?b:t?0:50};let a=Se();this.state={center:(g=e.initialLocationData)!=null&&g.latitude&&e.initialLocationData.longitude?[e.initialLocationData.latitude,e.initialLocationData.longitude]:[0,0],zoom:(h=(c=e.initialLocationData)==null?void 0:c.zoom)!=null?h:0,bounds:(A=(v=e.initialLocationData)==null?void 0:v.bounds)!=null?A:null,pendingBounds:null,tempBounds:null,properties:this.properties,primary:(T=this.primaryType)!=null?T:ne,selectedPropertyId:this.selectedMarkerId,initialLoading:!0,isSearching:!1,firstCallDone:!1,filters:{checkIn:a.checkIn,checkOut:a.checkOut,numAdults:2,numRooms:1,...((x=e.initialLocationData)==null?void 0:x.currency)&&{currency:e.initialLocationData.currency}},activeLocation:{country:"",location_id:null,locationName:"",coordinates:[0,0]},isFlyToAnimating:!1,...e.state},this.callbacks=(L=e.callbacks)!=null?L:{},this.hasMapInstance(e)&&(this.adapter=this.createAdapter(e),this.isMapAttached=!0,this.refresh()),e.initialLocationData?this.initializeFromLocationData(e.initialLocationData):this.requestBody&&this.isMapAttached&&this.autoLoadProperties()}hasMapInstance(e){return!!("adapter"in e&&e.adapter||"mapInstance"in e&&e.mapInstance)}async initializeFromLocationData(e){var t;if(!this.useApi){console.warn("initializeFromLocationData requires API usage. Set useApi to true.");return}try{let{city:a,state:r,country:n,query:s,latitude:m,longitude:p,radius:f,bounds:y}=e,M={filters:this.getFilters(),initial:!0,query:s,latitude:m,longitude:p,radius:f,bounds:y},l=[a,r].filter(Boolean).join(", ");if(n||l){let o=await fetch(`${this.apiUrl}/geo-lookup2?${new URLSearchParams({...n&&{country_code:n},...l&&{q:l}}).toString()}`,{headers:{...this.apiKey&&{"X-API-Key":this.apiKey}}});if(o.ok){let d=await o.json();M.city=["country","island","state"].includes(d.type)?void 0:d.name,M.state=d.type==="state"?d.name:["country","island","county"].includes(d.type)?void 0:d.state,M.country=["country","island"].includes(d.type)?d.name:d.country,M.location_id=d.id,M.latitude=d.lat,M.longitude=d.lon,this.setActiveLocation({city:a,state:r,country:n,location_id:(t=d.id)!=null?t:null,locationName:[a,r,n].filter(Boolean).join(", "),...d.lon&&d.lat&&{coordinates:[d.lat,d.lon]}}),d.lon&&d.lat&&this.setState({center:[d.lat,d.lon],zoom:a?12:r?8:5})}else this.handleError(new Error(`Geo mapping fetch failed: ${o.statusText}`),"initializeFromLocationData")}this.requestBody=M,this.isMapAttached&&await this.autoLoadProperties()}catch(a){this.handleError(a,"initializeFromLocationData")}}async autoLoadProperties(){if(!this.useApi){console.warn("autoLoadProperties requires API usage. Set useApi to true.");return}if(!this.requestBody)return;let e={filters:this.getFilters(),initial:!0,...this.requestBody};await this.runPropertiesSearch({body:e,onError:t=>{var a,r;this.handleError(t,"autoLoadProperties"),(r=(a=this.callbacks).onPropertiesLoadError)==null||r.call(a,t)}})}attachMap(e,t){if(!this.useApi&&t.platform!=="maplibre")throw new Error("When useApi is false, only maplibre platform is supported. Google Maps and Mapbox require API usage.");if(this.isMapAttached&&(console.warn("Map is already attached. Destroying previous adapter."),this.adapter)){let r=this.adapter.getMarkerManager();r==null||r.destroy(),this.adapter.cleanup()}let a={...this.options,platform:t.platform,mapInstance:e,maplibregl:t.maplibregl,google:t.google,mapboxgl:t.mapboxgl,onMarkerClick:t.onMarkerClick};this.currentPlatform=t.platform,this.adapter=this.createAdapter(a),this.isMapAttached=!0,this.refresh(),this.requestBody&&!this.state.firstCallDone&&this.autoLoadProperties()}createAdapter(e){return Ee(e)&&e.mapInstance?this.initializeAdapter(new H(e.mapInstance),{maplibregl:e.maplibregl,onMarkerClick:e.onMarkerClick}):se(e)&&e.mapInstance?this.initializeAdapter(new D(e.mapInstance),{google:e.google,onMarkerClick:e.onMarkerClick}):Be(e)&&e.mapInstance?this.initializeAdapter(new N(e.mapInstance),{mapboxgl:e.mapboxgl,onMarkerClick:e.onMarkerClick}):"adapter"in e&&e.adapter?e.adapter:null}initializeAdapter(e,t){return e.initialize({...t,onMarkerClick:a=>{var r;a.location&&this.flyMapTo(a.location.lon,a.location.lat,14),a.type!==this.primaryType&&this.setPrimaryType(a.type),this.setSelectedMarker(a.tripadvisor_id===this.selectedMarkerId?null:a.tripadvisor_id),(r=t.onMarkerClick)==null||r.call(t,a)},onRefresh:()=>this.refresh(),onMapMoveEnd:a=>{this.state.tempBounds===null?(this.setTempBounds(a),this.setPendingBounds(null)):this.handleMapMoveEnd(a)}}),this.useApi&&e.setupImpressionTracking(()=>{}),e}_setProperties(e){var t,a;this.ensureAlive(),this.properties=[...e.filter(r=>{var n;return r.type==="Accommodation"?((n=r.pricing)==null?void 0:n.availability)!=="unavailable":!0})],this.updateState({properties:this.properties}),(a=(t=this.callbacks).onPropertiesChange)==null||a.call(t,e),this.refresh()}addProperty(e){var t,a;this.ensureAlive(),this.properties=[...this.properties,e],this.updateState({properties:this.properties}),(a=(t=this.callbacks).onPropertiesChange)==null||a.call(t,this.properties),this.refresh()}clearProperties(){var e,t;this.ensureAlive(),this.properties=[],this.updateState({properties:[]}),(t=(e=this.callbacks).onPropertiesChange)==null||t.call(e,[]),this.refresh()}setPrimaryType(e){var t,a;this.ensureAlive(),this.primaryType!==e&&(this.primaryType=e,this.updateState({primary:e}),(a=(t=this.callbacks).onPrimaryTypeChange)==null||a.call(t,e),this.refresh())}setSelectedMarker(e){var t,a;if(this.ensureAlive(),this.selectedMarkerId!==e){if(e!==null){let r=this.properties.find(n=>n.tripadvisor_id===e);r&&r.type!==this.primaryType&&this.setPrimaryType(r.type)}this.selectedMarkerId=e,this.updateState({selectedPropertyId:e}),(a=(t=this.callbacks).onSelectedPropertyChange)==null||a.call(t,e),this.refresh()}}getState(){return{...this.state}}handleError(e,t="MapFirstCore"){let a=e instanceof Error?e.message:String(e),r=e instanceof Error?e:new Error(a);console.error(`[${t}]`,a),this.callbacks.onError&&this.callbacks.onError(r,t)}updateState(e){this.state={...this.state,...e}}setState(e){var a,r,n,s,m,p,f,y,M,l,o,d,u,b,g,c;let t={...this.state};this.updateState(e),e.center!==void 0&&e.center!==t.center&&((r=(a=this.callbacks).onCenterChange)==null||r.call(a,e.center,this.state.zoom)),e.zoom!==void 0&&e.zoom!==t.zoom&&((s=(n=this.callbacks).onZoomChange)==null||s.call(n,e.zoom)),e.bounds!==void 0&&e.bounds!==t.bounds&&((p=(m=this.callbacks).onBoundsChange)==null||p.call(m,e.bounds)),e.pendingBounds!==void 0&&e.pendingBounds!==t.pendingBounds&&((y=(f=this.callbacks).onPendingBoundsChange)==null||y.call(f,e.pendingBounds)),e.filters!==void 0&&e.filters!==t.filters&&((l=(M=this.callbacks).onFiltersChange)==null||l.call(M,e.filters)),e.activeLocation!==void 0&&e.activeLocation!==t.activeLocation&&((d=(o=this.callbacks).onActiveLocationChange)==null||d.call(o,e.activeLocation)),e.initialLoading!==void 0&&e.initialLoading!==t.initialLoading&&((b=(u=this.callbacks).onLoadingStateChange)==null||b.call(u,e.initialLoading)),e.isSearching!==void 0&&e.isSearching!==t.isSearching&&((c=(g=this.callbacks).onSearchingStateChange)==null||c.call(g,e.isSearching))}setFilters(e){this.setState({filters:e})}setActiveLocation(e){this.setState({activeLocation:e})}setBounds(e){this.setState({bounds:e})}setPendingBounds(e){this.setState({pendingBounds:e})}setTempBounds(e){this.setState({tempBounds:e})}setLoading(e){this.setState({initialLoading:e})}setSearching(e){this.setState({isSearching:e})}setFlyToAnimating(e){this.setState({isFlyToAnimating:e})}handleMapMoveEnd(e){if(this.state.isFlyToAnimating){this.setState({isFlyToAnimating:!1,tempBounds:e,pendingBounds:null});return}let t=this.state.tempBounds;if(!t){this.setState({tempBounds:e,pendingBounds:e});return}let a=.01;Math.abs(e.sw.lat-t.sw.lat)>a||Math.abs(e.sw.lng-t.sw.lng)>a||Math.abs(e.ne.lat-t.ne.lat)>a||Math.abs(e.ne.lng-t.ne.lng)>a?this.setState({pendingBounds:e}):this.setState({pendingBounds:null})}flyMapTo(e,t,a,r=!0){if(this.ensureAlive(),this.setState({center:[t,e]}),typeof a=="number"&&this.setState({zoom:a}),!this.adapter)return;let n=this.adapter.getMap();if(n){if(this.currentPlatform==="google"){this.setFlyToAnimating(!1),n.setCenter({lat:t,lng:e}),a!==null&&typeof a=="number"&&n.setZoom(a!=null?a:13);return}if(r===!1){this.setFlyToAnimating(!1),n.jumpTo&&n.jumpTo({center:[e,t],...a!==null&&{zoom:a!=null?a:13}});return}this.setFlyToAnimating(!0),n.flyTo&&n.flyTo({center:[e,t],...a!==null&&{zoom:a!=null?a:13}})}}flyToPOIs(e,t,a=!0){var s,m;if(this.ensureAlive(),!this.adapter)return;let r=this.adapter.getMap();if(!r)return;let n=e;if((!n||n.length===0)&&(n=this.properties.filter(p=>p.location!==void 0&&(t!==void 0?p.type===t:!0)).map(p=>({lat:p.location.lat,lng:p.location.lon}))),!(!n||n.length===0)){if(n.length===1){let p=n[0];this.currentPlatform==="google"?(r.setCenter({lat:p.lat,lng:p.lng}),r.setZoom(13)):r.flyTo&&r.flyTo({center:[p.lng,p.lat],zoom:13})}else if(this.currentPlatform==="google"){let p=(m=(s=window.google)==null?void 0:s.maps)==null?void 0:m.LatLngBounds;if(p){let f=new p;n.forEach(y=>{f.extend({lat:y.lat,lng:y.lng})}),a&&this.setFlyToAnimating(!0),r.fitBounds(f,this.fitBoundsPadding)}}else if(r.fitBounds){let p=[[n[0].lng,n[0].lat],[n[0].lng,n[0].lat]];n.forEach(f=>{p[0][0]=Math.min(p[0][0],f.lng),p[0][1]=Math.min(p[0][1],f.lat),p[1][0]=Math.max(p[1][0],f.lng),p[1][1]=Math.max(p[1][1],f.lat)}),a&&this.setFlyToAnimating(!0),r.fitBounds(p,{padding:this.fitBoundsPadding,animate:a})}}}getFilters(){let e={...this.state.filters};return e.checkIn instanceof Date&&(e.checkIn=ie(e.checkIn)),e.checkOut instanceof Date&&(e.checkOut=ie(e.checkOut)),e}async pollForPricing({pollingLink:e,maxAttempts:t=15,delayMs:a=2e3,isCancelled:r,price:n,limit:s}){var l,o,d,u,b;if(this.ensureAlive(),!this.useApi)return console.warn("pollForPricing requires API usage. Set useApi to true."),{completed:!1};if(!e)return{completed:!1};let m=!1,p,f=this.getFilters();s&&(f.limit=s);let y={filters:f,pollingLink:e},M;try{document.referrer&&(M=document.referrer)}catch(g){console.error(g)}for(let g=0;g<t;g++){if(r!=null&&r())return{completed:m,pollData:p};try{let c=await fetch(`${this.apiUrl}/ta-polling?pollingNumber=${g}`,{method:"POST",body:JSON.stringify(y),headers:{"Content-Type":"application/json","X-Source":"SDK",...this.apiKey&&{"X-API-Key":this.apiKey},...M&&{"X-Referer":M}}});if(!c.ok)throw new F({message:`Poll failed: ${c.status}`,status:c.status});if(p=await c.json(),r!=null&&r())return{completed:m,pollData:p};let h=(o=(l=p==null?void 0:p.success)==null?void 0:l.results)!=null?o:[];if(h.length>0&&this.setProperties(v=>{let A=new Set(h.map(x=>x.tripadvisor_id)),T=v.filter(x=>x.type!=="Accommodation"||A.has(x.tripadvisor_id));return h.forEach(x=>{var k,P,C,w,U,K;if(!x.location)return;(P=(k=x.pricing)==null?void 0:k.offer)!=null&&P.price&&n&&(((w=(C=x.pricing)==null?void 0:C.offer)==null?void 0:w.price)<(n==null?void 0:n.min)||((K=(U=x.pricing)==null?void 0:U.offer)==null?void 0:K.price)>(n==null?void 0:n.max))&&(x.pricing.availability="unavailable");let L=T.findIndex(pe=>pe.tripadvisor_id===x.tripadvisor_id);L>=0?T[L]=x:T.push(x)}),T}),(d=p==null?void 0:p.success)!=null&&d.isComplete){m=!0,this.setSearching(!1);break}}catch(c){this.handleError(c,"pollForPricing"),(b=(u=this.callbacks).onPropertiesLoadError)==null||b.call(u,c);break}g<t-1&&await new Promise(c=>setTimeout(c,a))}return{completed:m,pollData:p}}setProperties(e){let t=e(this.properties);this._setProperties(t)}mostCommonTypeFromProperties(e){let t=e.reduce((a,r)=>(a[r.type]=(a[r.type]||0)+1,a),{});return Object.entries(t).reduce((a,r)=>t[a[0]]>t[r[0]]?a:r)[0]}async runPropertiesSearch({body:e,beforeApplyProperties:t,smartFiltersClearable:a,onError:r}){var n,s,m,p,f,y,M;if(this.ensureAlive(),!this.useApi)return console.warn("runPropertiesSearch requires API usage. Set useApi to true."),r==null||r(new Error("API usage is disabled")),null;this.setState({firstCallDone:!1}),this.setSearching(!0),this.clearProperties();try{let l=await oe(`${this.apiUrl}/properties`,e,this.apiKey);this.updateActiveLocationFromResponse(l);let o=null,d=30,u=l.filters.primary_type;if(t){let c=t(l);o=(n=c.price)!=null?n:null,d=(s=c.limit)!=null?s:30}let b=l.properties.some(c=>!!c.location),g=o?l.properties.map(c=>{var h;return(h=c.pricing)!=null&&h.offer?{...c,pricing:{...c.pricing,availability:c.pricing.offer.price&&(c.pricing.offer.price<o.min||c.pricing.offer.price>o.max)?"unavailable":c.pricing.availability}}:c}):l.properties;if(this._setProperties(g),b&&this.flyToPOIs(l.properties.filter(c=>!!c.location&&(l.filters.primary_type?c.type===l.filters.primary_type:!0)).map(c=>({lat:c.location.lat,lng:c.location.lon})),void 0,e.initial!==!0),l.filters.primary_type&&l.properties.filter(c=>{var h;return c.type===l.filters.primary_type&&(c.type==="Accommodation"?((h=c.pricing)==null?void 0:h.availability)!=="unavailable":!0)}).length>0)u=l.filters.primary_type,this.setPrimaryType(l.filters.primary_type);else if(l.properties.length>0){let c=this.mostCommonTypeFromProperties(l.properties);this.setPrimaryType(c),u=c}if(this.setState({firstCallDone:!0}),l.isComplete===!1&&l.pollingLink){let{completed:c,pollData:h}=await this.pollForPricing({pollingLink:l.pollingLink,...o&&{price:o},...d&&{limit:d}});if(c&&((m=h==null?void 0:h.success)!=null&&m.results)&&h.success.results.filter(v=>{var A;return v.type===l.filters.primary_type&&(v.type==="Accommodation"?((A=v.pricing)==null?void 0:A.availability)!=="unavailable":!0)}).length===0&&u&&u!==l.filters.primary_type){let v=this.mostCommonTypeFromProperties(l.properties);this.setPrimaryType(v)}c&&this.refresh()}else l.isComplete===!0&&this.setSearching(!1);return b||(l.properties.some(c=>!!c.location)?this.flyToPOIs(l.properties.filter(c=>!!c.location&&(l.filters.primary_type?c.type===l.filters.primary_type:!0)).map(c=>({lat:c.location.lat,lng:c.location.lon})),void 0,e.initial!==!0):(p=l.filters.location)!=null&&p.latitude&&((f=l.filters.location)!=null&&f.longitude)&&this.flyMapTo(l.filters.location.longitude,l.filters.location.latitude,12,e.initial!==!0)),l}catch(l){return this.handleError(l,"runPropertiesSearch"),r==null||r(l),(M=(y=this.callbacks).onPropertiesLoadError)==null||M.call(y,l),this.clearProperties(),this.setState({firstCallDone:!0}),this.setSearching(!1),null}}async performBoundsSearch(){var n;if(this.ensureAlive(),!this.useApi)return console.warn("performBoundsSearch requires API usage. Set useApi to true."),null;if(!this.state.pendingBounds)return null;let e=this.getFilters(),t={bounds:this.state.pendingBounds,filters:e},a=(n=e==null?void 0:e.price)!=null?n:void 0,r=await this.runPropertiesSearch({body:t,beforeApplyProperties:()=>({price:a!=null?a:null})});return r&&(this.setBounds(this.state.pendingBounds),this.setTempBounds(this.state.pendingBounds),this.setPendingBounds(null)),r}updateActiveLocationFromResponse(e){var m,p,f,y;let t=(m=e.location_id)!=null?m:null,a=(f=(p=e.filters.location)==null?void 0:p.city)!=null?f:void 0,r=((y=e.filters.location)==null?void 0:y.country)||"",n=e.filters.location?[e.filters.location.latitude,e.filters.location.longitude]:void 0;if(!n)return;let s=this.state.activeLocation;(t!==(s==null?void 0:s.location_id)||a!==(s==null?void 0:s.city)||r!==(s==null?void 0:s.country))&&this.setActiveLocation({city:a,country:r,location_id:t,locationName:a&&r?`${a}, ${r}`:r||"",coordinates:n})}async runSmartFilterSearch({query:e,filters:t,onProcessFilters:a,onError:r}){if(this.ensureAlive(),!this.useApi)return console.warn("runSmartFilterSearch requires API usage. Set useApi to true."),r==null||r(new Error("API usage is disabled")),null;let n=this.getFilters(),s=this.getState();if(t&&t.length>0){let p=new Set,f=new Set,y,M,l,o,d,u;t.forEach(b=>{var g,c,h;switch(b.type){case"amenity":p.add(b.value);break;case"hotelStyle":f.add(b.value);break;case"priceRange":b.priceRange&&(y={min:b.priceRange.min,max:(g=b.priceRange.max)!=null?g:0});break;case"minRating":M=(c=b.numericValue)!=null?c:Number(b.value);break;case"starRating":l=(h=b.numericValue)!=null?h:Number(b.value);break;case"primary_type":o=b.propertyType;break;case"transformed_query":d=b.value;break;case"selected_restaurant_price_levels":u=b.priceLevels;break}}),n={...n,...p.size>0&&{amenities:Array.from(p)},...f.size>0&&{hotelStyle:Array.from(f)},...y&&{price:y},...M!==void 0&&{minRating:M},...l!==void 0&&{starRating:l},...o&&{primary_type:o},...d&&{transformed_query:d},...u&&{selected_restaurant_price_levels:u}}}else e||(n.minRating=4);let m={filters:n,...e&&{query:e},...s.bounds?{bounds:s.bounds}:s.activeLocation.location_id?{location_id:s.activeLocation.location_id}:s.activeLocation.coordinates?{latitude:s.activeLocation.coordinates[0],longitude:s.activeLocation.coordinates[1]}:{}};return this.runPropertiesSearch({body:m,beforeApplyProperties:a?p=>{var y,M;let f=a(p.filters,p.location_id);return{price:(y=f.price)!=null?y:null,limit:(M=f.limit)!=null?M:30}}:void 0,smartFiltersClearable:!!e,onError:r})}getClusters(){return this.ensureAlive(),[...this.clusterItems]}setUseApi(e,t=!0){this.ensureAlive(),this.useApi=e,!e&&this.currentPlatform&&this.currentPlatform!=="maplibre"&&console.warn("When useApi is false, only maplibre platform is supported. Please switch to maplibre."),e||this.clearProperties(),e&&t&&(this.options.initialLocationData?this.initializeFromLocationData(this.options.initialLocationData):this.requestBody&&this.isMapAttached&&this.autoLoadProperties())}setApiKey(e){this.ensureAlive();let t=this.apiKey;this.apiKey=e,t!==this.apiKey&&this.isMapAttached&&(this.refresh(),this.useApi&&(this.options.initialLocationData?this.initializeFromLocationData(this.options.initialLocationData):this.requestBody&&this.autoLoadProperties()))}getApiKey(){return this.apiKey}refresh(){var r,n,s;if(this.ensureAlive(),!this.adapter)return;let e=this.safeExtractViewState(),t=this.resolvePrimaryType();this.clusterItems=G({primaryType:t,markers:this.properties,map:this.adapter,selectedMarkerId:this.selectedMarkerId,zoom:(r=e==null?void 0:e.zoom)!=null?r:0}),this.adapter.getMarkerManager().render(this.clusterItems,t,this.selectedMarkerId),(s=(n=this.options).onClusterUpdate)==null||s.call(n,this.clusterItems,e)}destroy(){this.destroyed||(this.adapter&&(this.adapter.getMarkerManager().destroy(),this.adapter.cleanup()),this.clusterItems=[],this.properties=[],this.destroyed=!0,this.isMapAttached=!1)}resolvePrimaryType(){var e,t,a;return(a=(t=this.primaryType)!=null?t:(e=this.properties.find(r=>r.type))==null?void 0:e.type)!=null?a:ne}safeExtractViewState(){if(!this.adapter)return null;try{return ee(this.adapter)}catch{return null}}ensureAlive(){if(this.destroyed)throw new Error("MapFirstCore instance has been destroyed")}};function Ee(i){return i.platform==="maplibre"}function se(i){return i.platform==="google"}function Be(i){return i.platform==="mapbox"}0&&(module.exports={MapFirstCore,PropertiesFetchError,convertToApiFilters,fetchImages,fetchProperties,processApiFilters});
33
- //# sourceMappingURL=index.js.map
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ MapFirstCore: () => MapFirstCore,
24
+ PropertiesFetchError: () => PropertiesFetchError,
25
+ convertToApiFilters: () => convertToApiFilters,
26
+ fetchImages: () => fetchImages,
27
+ fetchProperties: () => fetchProperties,
28
+ processApiFilters: () => processApiFilters
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // #style-inject:#style-inject
33
+ function styleInject(css, { insertAt } = {}) {
34
+ if (!css || typeof document === "undefined") return;
35
+ const head = document.head || document.getElementsByTagName("head")[0];
36
+ const style = document.createElement("style");
37
+ style.type = "text/css";
38
+ if (insertAt === "top") {
39
+ if (head.firstChild) {
40
+ head.insertBefore(style, head.firstChild);
41
+ } else {
42
+ head.appendChild(style);
43
+ }
44
+ } else {
45
+ head.appendChild(style);
46
+ }
47
+ if (style.styleSheet) {
48
+ style.styleSheet.cssText = css;
49
+ } else {
50
+ style.appendChild(document.createTextNode(css));
51
+ }
52
+ }
53
+
54
+ // src/markers.css
55
+ styleInject(".mapfirst-marker-root {\n display: flex;\n z-index: 20;\n flex-direction: column;\n align-items: center;\n pointer-events: auto;\n}\n.mapfirst-marker-pill {\n border: 2px solid;\n border-radius: 999px;\n padding: 8px 8px;\n font-size: 16px;\n font-weight: 600;\n font-family:\n system-ui,\n -apple-system,\n sans-serif;\n box-shadow: 0 4px 6px rgba(107, 114, 128, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n transition: transform 0.2s;\n transform-origin: center bottom;\n}\n.mapfirst-marker-pill-pending {\n background: rgba(255, 255, 255, 0.5);\n backdrop-filter: blur(4px);\n border-color: transparent;\n cursor: default;\n}\n.mapfirst-marker-pill-active {\n background: #012b11;\n border-color: #ffffff;\n color: #ffffff;\n cursor: pointer;\n}\n.mapfirst-marker-pill-active.mapfirst-marker-non-primary {\n background: rgba(255, 255, 255, 0.7);\n border-color: rgba(3, 133, 46, 0.5);\n color: rgba(3, 133, 46, 0.5);\n padding: 4px;\n}\n.mapfirst-marker-pill-active.mapfirst-marker-selected {\n background: #ffffff;\n border-color: #03852e;\n color: #03852e;\n transform: scale(1.2);\n}\n.mapfirst-marker-pill-active:hover {\n transform: scale(1.2);\n}\n.mapfirst-marker-badge {\n position: absolute;\n top: -12px;\n right: -20px;\n}\n.mapfirst-marker-award-container {\n position: relative;\n width: 32px;\n height: 32px;\n}\n.mapfirst-marker-award-back {\n position: absolute;\n stroke: #f5f5f5;\n stroke-width: 2px;\n}\n.mapfirst-marker-award-dot {\n position: absolute;\n top: 6.2px;\n left: 6.3px;\n width: 18.5px;\n height: 18.5px;\n border-radius: 50%;\n z-index: 1;\n}\n.mapfirst-marker-award-dot-type-0 {\n background: #ffef0e;\n}\n.mapfirst-marker-award-dot-type-1 {\n background: #01ea5b;\n}\n.mapfirst-marker-award-front {\n position: relative;\n z-index: 2;\n color: #012b11;\n}\n.mapfirst-marker-rating-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 999px;\n background: #03852e;\n color: #ffffff;\n font-size: 12px;\n line-height: 1;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border: 2px solid #ffffff;\n font-weight: 400;\n}\n.mapfirst-marker-content {\n display: flex;\n align-items: center;\n}\n.mapfirst-marker-loading-video {\n width: 20px;\n height: 20px;\n display: block;\n}\n.mapfirst-dot-marker-container {\n display: flex;\n z-index: 10;\n align-items: center;\n justify-content: center;\n pointer-events: auto;\n}\n.mapfirst-dot-marker-button {\n width: 20px;\n height: 20px;\n border-radius: 999px;\n border: 2px solid #ffffff;\n box-shadow: 0 2px 4px rgba(107, 114, 128, 0.4);\n transition: transform 0.2s;\n outline: none;\n transform-origin: center center;\n}\n.mapfirst-dot-marker-button-pending {\n background: #d1d5db;\n cursor: default;\n}\n.mapfirst-dot-marker-button-active {\n background: #012b11;\n cursor: pointer;\n}\n.mapfirst-dot-marker-button-active.mapfirst-dot-marker-non-primary {\n background: rgba(255, 255, 255, 0.7);\n border-color: rgba(3, 133, 46, 0.2);\n}\n.mapfirst-dot-marker-button-active.mapfirst-dot-marker-selected {\n background: #ffffff;\n border-color: #03852e;\n}\n.mapfirst-dot-marker-button-active:hover {\n transform: scale(1.2);\n}\n.mapfirst-dot-marker-button-active:focus {\n outline: 2px solid #ffffff;\n outline-offset: 2px;\n}\n.mapfirst-property-hover-card {\n position: absolute;\n width: 270px;\n background: #ffffff;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n display: flex;\n pointer-events: auto;\n z-index: 9999;\n transition: opacity 0.2s;\n height: 120px;\n text-decoration: none;\n color: inherit;\n}\n.mapfirst-property-hover-card img {\n width: 120px;\n height: 120px;\n object-fit: cover;\n flex-shrink: 0;\n}\n.mapfirst-property-hover-image {\n width: 120px;\n height: 120px;\n flex-shrink: 0;\n}\n.mapfirst-property-hover-image-placeholder {\n background-color: #e5e7eb;\n}\n.mapfirst-property-hover-details {\n display: flex;\n flex-direction: column;\n padding: 8px 12px;\n flex: 1;\n gap: 4px;\n}\n.mapfirst-property-hover-name {\n font-size: 12px;\n font-weight: 600;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n line-height: 1.3;\n}\n.mapfirst-property-hover-rating {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n}\n.mapfirst-property-hover-rating .rating-value {\n font-weight: 600;\n color: #1a1a1a;\n}\n.mapfirst-property-hover-rating .stars {\n display: flex;\n gap: 1px;\n font-size: 10px;\n line-height: 1;\n align-items: center;\n}\n.mapfirst-property-hover-rating .reviews {\n color: #666;\n font-size: 11px;\n}\n.mapfirst-property-hover-price {\n font-size: 12px;\n color: #666;\n margin-top: 2px;\n}\n.mapfirst-property-hover-price strong {\n color: #1a1a1a;\n font-weight: 600;\n}\n.mapfirst-property-hover-learn-more {\n font-size: 12px;\n color: #03852e;\n text-decoration: none;\n font-weight: 500;\n margin-top: auto;\n pointer-events: auto;\n display: inline-block;\n}\n.mapfirst-property-hover-learn-more:hover {\n text-decoration: underline;\n}\n");
56
+
57
+ // src/marker-style-utils.ts
58
+ var PRIMARY_Z_INDEX = {
59
+ selected: 20,
60
+ primary: 12,
61
+ secondary: 11
62
+ };
63
+ var DOT_Z_INDEX = {
64
+ selected: 20,
65
+ primary: 3,
66
+ secondary: 1
67
+ };
68
+ var LOADING_VIDEO_HTML = `<video class="mapfirst-marker-loading-video" src="https://api.mapfirst.ai/static/images/loading.webm" autoplay loop muted></video>`;
69
+ function getPrimaryMarkerZIndex(isPrimaryType, isSelected) {
70
+ if (isSelected) return PRIMARY_Z_INDEX.selected;
71
+ return isPrimaryType ? PRIMARY_Z_INDEX.primary : PRIMARY_Z_INDEX.secondary;
72
+ }
73
+ function getDotMarkerZIndex(isPrimaryType, isSelected) {
74
+ if (isSelected) return DOT_Z_INDEX.selected;
75
+ return isPrimaryType ? DOT_Z_INDEX.primary : DOT_Z_INDEX.secondary;
76
+ }
77
+ function getPrimaryMarkerPillClass(isPending, isPrimaryType, isSelected) {
78
+ if (isPending) {
79
+ return "mapfirst-marker-pill mapfirst-marker-pill-pending";
80
+ }
81
+ return `mapfirst-marker-pill mapfirst-marker-pill-active${isSelected ? " mapfirst-marker-selected" : !isPrimaryType ? " mapfirst-marker-non-primary" : ""}`;
82
+ }
83
+ function getDotMarkerButtonClass(isPending, isPrimaryType, isSelected) {
84
+ if (isPending) {
85
+ return "mapfirst-dot-marker-button mapfirst-dot-marker-button-pending";
86
+ }
87
+ return `mapfirst-dot-marker-button mapfirst-dot-marker-button-active${isSelected ? " mapfirst-dot-marker-selected" : !isPrimaryType ? " mapfirst-dot-marker-non-primary" : ""}`;
88
+ }
89
+
90
+ // src/marker.ts
91
+ var AWARD_SVG = `<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor"><path d="M12 3.953a7.442 7.442 0 1 0 .001 14.884A7.442 7.442 0 0 0 12 3.953m0 14.05a6.61 6.61 0 1 1 0-13.218 6.61 6.61 0 0 1 0 13.219M10.343 11.9a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.821 0m5.134 0a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.82 0m.82-1.897.84-.913h-1.863A5.8 5.8 0 0 0 12 8.08a5.77 5.77 0 0 0-3.27 1.008H6.862l.84.913a2.567 2.567 0 1 0 3.475 3.78l.823.896.823-.895a2.568 2.568 0 1 0 3.474-3.78m-6.865 3.634a1.738 1.738 0 1 1 0-3.476 1.738 1.738 0 0 1 0 3.476M12 11.85c0-1.143-.832-2.124-1.929-2.543A5 5 0 0 1 12 8.92a5 5 0 0 1 1.928.386c-1.096.42-1.927 1.4-1.927 2.543m2.566 1.787a1.738 1.738 0 1 1 .001-3.476 1.738 1.738 0 0 1 0 3.476m-8.456 3.719s-.377-.946-1.396-1.903c-1.02-.957-2.303-1.132-2.303-1.132s.457 1.02 1.54 2.04c1.086 1.017 2.159.995 2.159.995m2.568 1.41s-.524-.511-1.479-.883-1.861-.191-1.861-.191.598.54 1.615.935c1.016.397 1.725.139 1.725.139m2.493.505s-.545-.224-1.357-.196-1.415.47-1.415.47.608.222 1.473.193 1.3-.467 1.3-.467m-6.186-4.203s-.175-1.008-.974-2.154c-.8-1.147-2.015-1.578-2.015-1.578s.238 1.098 1.089 2.319c.85 1.22 1.9 1.413 1.9 1.413m-1.003-3.071s.195-1.021-.134-2.393c-.328-1.371-1.294-2.21-1.294-2.21s-.17 1.128.18 2.589c.35 1.46 1.248 2.014 1.248 2.014"></path><path d="M17.887 17.355s.377-.946 1.396-1.903c1.02-.957 2.303-1.132 2.303-1.132s-.457 1.02-1.54 2.04c-1.086 1.017-2.159.995-2.159.995m-2.567 1.41s.524-.511 1.479-.883 1.861-.191 1.861-.191-.598.54-1.615.935c-1.016.397-1.725.139-1.725.139m-2.493.505s.545-.224 1.357-.196 1.415.47 1.415.47-.608.222-1.473.193-1.3-.467-1.3-.467m6.186-4.203s.175-1.008.974-2.154c.8-1.147 2.015-1.578 2.015-1.578s-.238 1.098-1.089 2.319c-.85 1.22-1.9 1.413-1.9 1.413m1.003-3.071s-.195-1.021.133-2.393c.33-1.371 1.293-2.21 1.293-2.21s.17 1.128-.18 2.589c-.349 1.46-1.246 2.014-1.246 2.014M12 20.047a.413.413 0 1 0 0-.827.413.413 0 0 0 0 .827"></path></svg>`;
92
+ var AWARD_BACK_SVG = `<svg viewBox="0 0 24 24" width="32" height="32"><path d="M12 3.953a7.442 7.442 0 1 0 .001 14.884A7.442 7.442 0 0 0 12 3.953m0 14.05a6.61 6.61 0 1 1 0-13.218 6.61 6.61 0 0 1 0 13.219M10.343 11.9a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.821 0m5.134 0a.91.91 0 1 1-1.821 0 .91.91 0 0 1 1.82 0m.82-1.897.84-.913h-1.863A5.8 5.8 0 0 0 12 8.08a5.77 5.77 0 0 0-3.27 1.008H6.862l.84.913a2.567 2.567 0 1 0 3.475 3.78l.823.896.823-.895a2.568 2.568 0 1 0 3.474-3.78m-6.865 3.634a1.738 1.738 0 1 1 0-3.476 1.738 1.738 0 0 1 0 3.476M12 11.85c0-1.143-.832-2.124-1.929-2.543A5 5 0 0 1 12 8.92a5 5 0 0 1 1.928.386c-1.096.42-1.927 1.4-1.927 2.543m2.566 1.787a1.738 1.738 0 1 1 .001-3.476 1.738 1.738 0 0 1 0 3.476m-8.456 3.719s-.377-.946-1.396-1.903c-1.02-.957-2.303-1.132-2.303-1.132s.457 1.02 1.54 2.04c1.086 1.017 2.159.995 2.159.995m2.568 1.41s-.524-.511-1.479-.883-1.861-.191-1.861-.191.598.54 1.615.935c1.016.397 1.725.139 1.725.139m2.493.505s-.545-.224-1.357-.196-1.415.47-1.415.47.608.222 1.473.193 1.3-.467 1.3-.467m-6.186-4.203s-.175-1.008-.974-2.154c-.8-1.147-2.015-1.578-2.015-1.578s.238 1.098 1.089 2.319c.85 1.22 1.9 1.413 1.9 1.413m-1.003-3.071s.195-1.021-.134-2.393c-.328-1.371-1.294-2.21-1.294-2.21s-.17 1.128.18 2.589c.35 1.46 1.248 2.014 1.248 2.014"></path><path d="M17.887 17.355s.377-.946 1.396-1.903c1.02-.957 2.303-1.132 2.303-1.132s-.457 1.02-1.54 2.04c-1.086 1.017-2.159.995-2.159.995m-2.567 1.41s.524-.511 1.479-.883 1.861-.191 1.861-.191-.598.54-1.615.935c-1.016.397-1.725.139-1.725.139m-2.493.505s.545-.224 1.357-.196 1.415.47 1.415.47-.608.222-1.473.193-1.3-.467-1.3-.467m6.186-4.203s.175-1.008.974-2.154c.8-1.147 2.015-1.578 2.015-1.578s-.238 1.098-1.089 2.319c-.85 1.22-1.9 1.413-1.9 1.413m1.003-3.071s-.195-1.021.133-2.393c.33-1.371 1.293-2.21 1.293-2.21s.17 1.128-.18 2.589c-.349 1.46-1.246 2.014-1.246 2.014M12 20.047a.413.413 0 1 0 0-.827.413.413 0 0 0 0 .827"></path></svg>`;
93
+ var EAT_DRINK_SVG = `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.051 6.549v.003l1.134 1.14 3.241-3.25.003-.002 1.134 1.136-3.243 3.252 1.134 1.14a1 1 0 0 0 .09-.008c.293-.05.573-.324.72-.474l.005-.006 2.596-2.603L22 8.016l-2.597 2.604a3.73 3.73 0 0 1-1.982 1.015 4.3 4.3 0 0 1-3.162-.657l-.023-.016-.026-.018-1.366 1.407 8.509 8.512L20.219 22l-.002-.002-6.654-6.663-2.597 2.76-7.3-7.315C1.967 8.948 1.531 6.274 2.524 4.198c.241-.504.566-.973.978-1.386l8.154 8.416 1.418-1.423-.039-.045c-.858-1.002-1.048-2.368-.62-3.595a4.15 4.15 0 0 1 .983-1.561L16 2l1.135 1.138-2.598 2.602-.047.045c-.16.151-.394.374-.433.678zM3.809 5.523c-.362 1.319-.037 2.905 1.06 4.103L10.93 15.7l1.408-1.496zM2.205 20.697 3.34 21.84l4.543-4.552-1.135-1.143z"/></svg>`;
94
+ var ATTRACTION_SVG = `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.56 7.5H3.75a.25.25 0 0 0-.25.25v10c0 .138.112.25.25.25h16.5a.25.25 0 0 0 .25-.25v-10a.25.25 0 0 0-.25-.25h-3.81l-2-2H9.56zM8.94 4h6.12l2 2h3.19c.966 0 1.75.784 1.75 1.75v10a1.75 1.75 0 0 1-1.75 1.75H3.75A1.75 1.75 0 0 1 2 17.75v-10C2 6.784 2.784 6 3.75 6h3.19z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12 9.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5M7.75 12a4.25 4.25 0 1 1 8.5 0 4.25 4.25 0 0 1-8.5 0"/></svg>`;
95
+ var STAR_BASE_STYLE = "display:inline-block;width:8px;height:8px;border:1px solid #03852e;border-radius:9999px;";
96
+ var STAR_HALF_STYLE = "linear-gradient(90deg, #03852e 50%, transparent 50%)";
97
+ var STAR_KIND_CACHE = /* @__PURE__ */ new Map();
98
+ function setupHoverCard(root, pill, marker, isSelected) {
99
+ if (root.dataset.hasHoverCard === "true") return;
100
+ root.dataset.hasHoverCard = "true";
101
+ const propertyCard = createPropertyCard(marker);
102
+ let hoverTimeout = null;
103
+ let hideTimeout = null;
104
+ let positionUpdateFrame = null;
105
+ const cleanupCard = () => {
106
+ if (hoverTimeout) {
107
+ clearTimeout(hoverTimeout);
108
+ hoverTimeout = null;
109
+ }
110
+ if (hideTimeout) {
111
+ clearTimeout(hideTimeout);
112
+ hideTimeout = null;
113
+ }
114
+ if (positionUpdateFrame) {
115
+ cancelAnimationFrame(positionUpdateFrame);
116
+ positionUpdateFrame = null;
117
+ }
118
+ if (propertyCard.parentElement) {
119
+ propertyCard.remove();
120
+ }
121
+ };
122
+ const updateCardPosition = () => {
123
+ if (propertyCard.parentElement) {
124
+ let mapContainer = root.parentElement;
125
+ while (mapContainer && getComputedStyle(mapContainer).position === "static") {
126
+ mapContainer = mapContainer.parentElement;
127
+ }
128
+ if (mapContainer) {
129
+ positionCard(propertyCard, root, mapContainer);
130
+ positionUpdateFrame = requestAnimationFrame(updateCardPosition);
131
+ }
132
+ }
133
+ };
134
+ const showCard = (immediate = false) => {
135
+ if (hideTimeout) {
136
+ clearTimeout(hideTimeout);
137
+ hideTimeout = null;
138
+ }
139
+ const doShow = () => {
140
+ let mapContainer = root.parentElement;
141
+ while (mapContainer && getComputedStyle(mapContainer).position === "static") {
142
+ mapContainer = mapContainer.parentElement;
143
+ }
144
+ if (mapContainer) {
145
+ mapContainer.appendChild(propertyCard);
146
+ positionCard(propertyCard, root, mapContainer);
147
+ loadCardImage(propertyCard, marker);
148
+ positionUpdateFrame = requestAnimationFrame(updateCardPosition);
149
+ }
150
+ };
151
+ if (immediate) {
152
+ doShow();
153
+ } else {
154
+ hoverTimeout = setTimeout(doShow, 300);
155
+ }
156
+ };
157
+ const hideCard = () => {
158
+ if (isSelected) return;
159
+ if (hoverTimeout) {
160
+ clearTimeout(hoverTimeout);
161
+ hoverTimeout = null;
162
+ }
163
+ if (positionUpdateFrame) {
164
+ cancelAnimationFrame(positionUpdateFrame);
165
+ positionUpdateFrame = null;
166
+ }
167
+ hideTimeout = setTimeout(() => {
168
+ if (propertyCard.parentElement) {
169
+ propertyCard.remove();
170
+ }
171
+ }, 100);
172
+ };
173
+ if (isSelected) {
174
+ showCard(true);
175
+ }
176
+ pill.addEventListener("mouseenter", () => showCard(false));
177
+ pill.addEventListener("mouseleave", hideCard);
178
+ propertyCard.addEventListener("mouseenter", () => {
179
+ if (hideTimeout) {
180
+ clearTimeout(hideTimeout);
181
+ hideTimeout = null;
182
+ }
183
+ if (!positionUpdateFrame && propertyCard.parentElement) {
184
+ positionUpdateFrame = requestAnimationFrame(updateCardPosition);
185
+ }
186
+ });
187
+ propertyCard.addEventListener("mouseleave", hideCard);
188
+ const observer = new MutationObserver((mutations) => {
189
+ for (const mutation of mutations) {
190
+ for (const removedNode of mutation.removedNodes) {
191
+ if (removedNode === root || removedNode.contains(root)) {
192
+ cleanupCard();
193
+ observer.disconnect();
194
+ return;
195
+ }
196
+ }
197
+ }
198
+ });
199
+ if (root.parentElement) {
200
+ observer.observe(root.parentElement, { childList: true, subtree: true });
201
+ } else {
202
+ const checkParent = setInterval(() => {
203
+ if (root.parentElement) {
204
+ observer.observe(root.parentElement, {
205
+ childList: true,
206
+ subtree: true
207
+ });
208
+ clearInterval(checkParent);
209
+ }
210
+ }, 100);
211
+ }
212
+ }
213
+ function getDefaultImageForType(type) {
214
+ const normalizedType = type.toLowerCase().replace(/\s+/g, "").replace(/&/g, "");
215
+ return `https://api.mapfirst.ai/static/images/${normalizedType}.webp`;
216
+ }
217
+ function createPropertyCard(marker) {
218
+ var _a, _b, _c, _d, _e, _f, _g;
219
+ const url = (_c = (_b = (_a = marker.pricing) == null ? void 0 : _a.offer) == null ? void 0 : _b.clickUrl) != null ? _c : marker.url;
220
+ const rating = marker.rating || 0;
221
+ const reviews = marker.reviews || 0;
222
+ const displayPrice = (_f = (_e = (_d = marker.pricing) == null ? void 0 : _d.offer) == null ? void 0 : _e.displayPrice) != null ? _f : marker.price_level;
223
+ const defaultImageUrl = getDefaultImageForType(marker.type);
224
+ const card = document.createElement(url ? "a" : "div");
225
+ card.className = "mapfirst-property-hover-card";
226
+ card.setAttribute("data-marker-id", marker.tripadvisor_id.toString());
227
+ if (url) {
228
+ card.href = url;
229
+ card.target = "_blank";
230
+ }
231
+ const imageContainer = document.createElement("div");
232
+ imageContainer.className = "mapfirst-property-hover-image mapfirst-property-hover-image-placeholder";
233
+ imageContainer.dataset.tripadvisorId = marker.tripadvisor_id.toString();
234
+ imageContainer.dataset.defaultImage = defaultImageUrl;
235
+ const details = document.createElement("div");
236
+ details.className = "mapfirst-property-hover-details";
237
+ const name = document.createElement("div");
238
+ name.className = "mapfirst-property-hover-name";
239
+ name.textContent = (_g = marker.name) != null ? _g : "";
240
+ const ratingContainer = document.createElement("div");
241
+ ratingContainer.className = "mapfirst-property-hover-rating";
242
+ const ratingValue = document.createElement("span");
243
+ ratingValue.className = "rating-value";
244
+ ratingValue.textContent = rating.toFixed(1);
245
+ const stars = document.createElement("span");
246
+ stars.className = "stars";
247
+ stars.appendChild(renderCardStars(rating));
248
+ const reviewsText = document.createElement("span");
249
+ reviewsText.className = "reviews";
250
+ reviewsText.textContent = `(${reviews})`;
251
+ ratingContainer.append(ratingValue, stars, reviewsText);
252
+ details.append(name, ratingContainer);
253
+ if (marker.type === "Accommodation" && displayPrice) {
254
+ const price = document.createElement("div");
255
+ price.className = "mapfirst-property-hover-price";
256
+ price.append("Starting at ");
257
+ const strong = document.createElement("strong");
258
+ strong.textContent = displayPrice;
259
+ price.appendChild(strong);
260
+ details.appendChild(price);
261
+ }
262
+ if (url) {
263
+ const learnMore = document.createElement("span");
264
+ learnMore.className = "mapfirst-property-hover-learn-more";
265
+ learnMore.textContent = "Learn More";
266
+ details.appendChild(learnMore);
267
+ }
268
+ card.append(imageContainer, details);
269
+ return card;
270
+ }
271
+ function renderCardStars(rating) {
272
+ const fragment = document.createDocumentFragment();
273
+ const fullStars = Math.floor(rating);
274
+ const hasHalfStar = rating % 1 !== 0;
275
+ const cacheKey = `${fullStars}:${hasHalfStar}`;
276
+ const cached = STAR_KIND_CACHE.get(cacheKey);
277
+ if (cached) {
278
+ for (const star of cached) {
279
+ fragment.appendChild(createCardStar(star));
280
+ }
281
+ return fragment;
282
+ }
283
+ const stars = [];
284
+ for (let i = 0; i < fullStars; i += 1) {
285
+ stars.push("full");
286
+ }
287
+ if (hasHalfStar) {
288
+ stars.push("half");
289
+ }
290
+ const remainingStars = 5 - Math.ceil(rating);
291
+ for (let i = 0; i < remainingStars; i += 1) {
292
+ stars.push("empty");
293
+ }
294
+ STAR_KIND_CACHE.set(cacheKey, stars);
295
+ for (const star of stars) {
296
+ fragment.appendChild(createCardStar(star));
297
+ }
298
+ return fragment;
299
+ }
300
+ function createCardStar(kind) {
301
+ const star = document.createElement("span");
302
+ star.style.cssText = STAR_BASE_STYLE;
303
+ if (kind === "full") {
304
+ star.style.backgroundColor = "#03852e";
305
+ } else if (kind === "half") {
306
+ star.style.background = STAR_HALF_STYLE;
307
+ }
308
+ return star;
309
+ }
310
+ function loadCardImage(card, marker) {
311
+ const imgContainer = card.querySelector(
312
+ ".mapfirst-property-hover-image"
313
+ );
314
+ if (imgContainer && marker.tripadvisor_id && !imgContainer.dataset.imageLoaded) {
315
+ imgContainer.dataset.imageLoaded = "loading";
316
+ const defaultImageUrl = imgContainer.dataset.defaultImage;
317
+ fetchImages(marker.tripadvisor_id, 1).then((imageUrl) => {
318
+ if (imageUrl && imgContainer) {
319
+ setCardImage(imgContainer, imageUrl, marker.name);
320
+ imgContainer.classList.remove(
321
+ "mapfirst-property-hover-image-placeholder"
322
+ );
323
+ imgContainer.dataset.imageLoaded = "true";
324
+ } else {
325
+ throw new Error("No image URL");
326
+ }
327
+ }).catch(() => {
328
+ if (defaultImageUrl && imgContainer) {
329
+ setCardImage(imgContainer, defaultImageUrl, marker.name);
330
+ imgContainer.classList.remove(
331
+ "mapfirst-property-hover-image-placeholder"
332
+ );
333
+ imgContainer.dataset.imageLoaded = "false";
334
+ }
335
+ });
336
+ }
337
+ }
338
+ function setCardImage(container, imageUrl, alt) {
339
+ const img = document.createElement("img");
340
+ img.src = imageUrl;
341
+ img.alt = alt != null ? alt : "";
342
+ img.style.width = "100%";
343
+ img.style.height = "100%";
344
+ img.style.objectFit = "cover";
345
+ container.innerHTML = "";
346
+ container.appendChild(img);
347
+ }
348
+ function positionCard(card, markerElement, mapContainer) {
349
+ const markerRect = markerElement.getBoundingClientRect();
350
+ const containerRect = mapContainer.getBoundingClientRect();
351
+ const cardWidth = 270;
352
+ const cardHeight = 120;
353
+ const offset = 12;
354
+ const spaceRight = containerRect.right - markerRect.right;
355
+ const spaceLeft = markerRect.left - containerRect.left;
356
+ const spaceBottom = containerRect.bottom - markerRect.bottom;
357
+ const spaceTop = markerRect.top - containerRect.top;
358
+ let left = markerRect.left - containerRect.left + markerRect.width / 2 - cardWidth / 2;
359
+ let top = markerRect.top - containerRect.top + markerRect.height + offset;
360
+ if (left < 0) {
361
+ left = 8;
362
+ } else if (left + cardWidth > containerRect.width) {
363
+ left = containerRect.width - cardWidth - 8;
364
+ }
365
+ if (spaceBottom < cardHeight + offset && spaceTop > spaceBottom) {
366
+ top = markerRect.top - containerRect.top - cardHeight - offset;
367
+ }
368
+ card.style.left = `${left}px`;
369
+ card.style.top = `${top}px`;
370
+ }
371
+ function createPrimaryMarkerElement(item, primaryType, selectedMarkerId, onMarkerClick) {
372
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
373
+ if (typeof document === "undefined") {
374
+ return null;
375
+ }
376
+ const marker = item.marker;
377
+ const isPrimaryType = marker.type === primaryType;
378
+ const isSelected = selectedMarkerId === marker.tripadvisor_id;
379
+ const isAccommodation = marker.type === "Accommodation";
380
+ const hasPrice = (_b = (_a = marker.pricing) == null ? void 0 : _a.offer) == null ? void 0 : _b.displayPrice;
381
+ const isPending = isAccommodation && !hasPrice;
382
+ const ratingLabel = (() => {
383
+ if (marker.rating === void 0 || marker.rating === null) return null;
384
+ const numeric = typeof marker.rating === "number" ? marker.rating : Number(marker.rating);
385
+ if (Number.isNaN(numeric) || numeric <= 0) return null;
386
+ return numeric.toFixed(1);
387
+ })();
388
+ const root = document.createElement("div");
389
+ root.className = "mapfirst-marker-root";
390
+ root.style.zIndex = String(getPrimaryMarkerZIndex(isPrimaryType, isSelected));
391
+ const markerUrl = (_e = (_d = (_c = marker.pricing) == null ? void 0 : _c.offer) == null ? void 0 : _d.clickUrl) != null ? _e : marker.url;
392
+ const pill = document.createElement(markerUrl ? "a" : "div");
393
+ if (markerUrl) {
394
+ pill.href = markerUrl;
395
+ pill.target = "_blank";
396
+ pill.style.textDecoration = "none";
397
+ }
398
+ pill.className = getPrimaryMarkerPillClass(
399
+ isPending,
400
+ isPrimaryType,
401
+ isSelected
402
+ );
403
+ if (!isPending && (((_f = marker.awards) == null ? void 0 : _f.length) || ratingLabel)) {
404
+ const badge = document.createElement("div");
405
+ badge.className = "mapfirst-marker-badge";
406
+ if (!isPrimaryType) {
407
+ badge.style.opacity = "0.2";
408
+ }
409
+ badge.className = "mapfirst-marker-badge";
410
+ if (((_g = marker.awards) == null ? void 0 : _g.length) && marker.awards[0].type) {
411
+ const awardContainer = document.createElement("div");
412
+ awardContainer.className = "mapfirst-marker-award-container";
413
+ const backLayer = document.createElement("div");
414
+ backLayer.className = "mapfirst-marker-award-back";
415
+ backLayer.innerHTML = AWARD_BACK_SVG;
416
+ const colorDot = document.createElement("div");
417
+ colorDot.className = `mapfirst-marker-award-dot mapfirst-marker-award-dot-type-${marker.awards[0].type}`;
418
+ const frontLayer = document.createElement("div");
419
+ frontLayer.className = "mapfirst-marker-award-front";
420
+ frontLayer.innerHTML = AWARD_SVG;
421
+ awardContainer.appendChild(backLayer);
422
+ awardContainer.appendChild(colorDot);
423
+ awardContainer.appendChild(frontLayer);
424
+ badge.appendChild(awardContainer);
425
+ } else if (ratingLabel) {
426
+ badge.className = "mapfirst-marker-badge mapfirst-marker-rating-badge";
427
+ badge.textContent = ratingLabel;
428
+ }
429
+ pill.appendChild(badge);
430
+ }
431
+ const content = document.createElement("span");
432
+ content.className = "mapfirst-marker-content";
433
+ if (isAccommodation) {
434
+ if ((_i = (_h = marker.pricing) == null ? void 0 : _h.offer) == null ? void 0 : _i.displayPrice) {
435
+ content.innerHTML = marker.pricing.offer.displayPrice;
436
+ content.dataset.price = marker.pricing.offer.displayPrice;
437
+ } else {
438
+ content.innerHTML = LOADING_VIDEO_HTML;
439
+ content.dataset.price = "";
440
+ }
441
+ } else if (marker.type === "Eat & Drink") {
442
+ content.innerHTML = EAT_DRINK_SVG;
443
+ } else if (marker.type === "Attraction") {
444
+ content.innerHTML = ATTRACTION_SVG;
445
+ }
446
+ pill.appendChild(content);
447
+ pill.addEventListener("click", (evt) => {
448
+ evt.stopPropagation();
449
+ if (!isPending) {
450
+ onMarkerClick == null ? void 0 : onMarkerClick(marker);
451
+ }
452
+ });
453
+ if (!isPending) {
454
+ setupHoverCard(root, pill, marker, isSelected);
455
+ }
456
+ root.appendChild(pill);
457
+ return root;
458
+ }
459
+
460
+ // src/dotmarker.ts
461
+ function createDotMarkerElement(item, primaryType, selectedMarkerId, onMarkerClick) {
462
+ var _a, _b, _c;
463
+ if (typeof document === "undefined") {
464
+ return null;
465
+ }
466
+ const marker = item.marker;
467
+ const isPrimaryType = marker.type === primaryType;
468
+ const isSelected = selectedMarkerId === marker.tripadvisor_id;
469
+ const isAccommodation = marker.type === "Accommodation";
470
+ const isPending = isAccommodation && ((_b = (_a = marker.pricing) == null ? void 0 : _a.offer) == null ? void 0 : _b.availability) !== "available";
471
+ const container = document.createElement("div");
472
+ container.className = "mapfirst-dot-marker-container";
473
+ container.style.zIndex = String(getDotMarkerZIndex(isPrimaryType, isSelected));
474
+ const button = document.createElement("div");
475
+ button.className = getDotMarkerButtonClass(
476
+ isPending,
477
+ isPrimaryType,
478
+ isSelected
479
+ );
480
+ button.title = (_c = marker.name) != null ? _c : String(marker.tripadvisor_id);
481
+ button.addEventListener("click", (evt) => {
482
+ evt.stopPropagation();
483
+ if (!isPending) {
484
+ onMarkerClick == null ? void 0 : onMarkerClick(marker);
485
+ }
486
+ });
487
+ container.appendChild(button);
488
+ if (!isPending) {
489
+ setupHoverCard(container, button, marker, isSelected);
490
+ }
491
+ return container;
492
+ }
493
+
494
+ // src/marker-updater.ts
495
+ function updatePrimaryMarkerElement(element, isPrimaryType, isSelected, isPending, marker) {
496
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
497
+ const wasPending = (_b = (_a = element.querySelector(".mapfirst-marker-pill")) == null ? void 0 : _a.classList.contains("mapfirst-marker-pill-pending")) != null ? _b : false;
498
+ const root = element;
499
+ root.style.zIndex = String(getPrimaryMarkerZIndex(isPrimaryType, isSelected));
500
+ const pill = root.querySelector(".mapfirst-marker-pill");
501
+ if (pill) {
502
+ pill.className = getPrimaryMarkerPillClass(
503
+ isPending,
504
+ isPrimaryType,
505
+ isSelected
506
+ );
507
+ }
508
+ const badge = root.querySelector(".mapfirst-marker-badge");
509
+ if (badge instanceof HTMLElement) {
510
+ badge.style.opacity = !isPrimaryType && !isSelected ? "0.2" : "";
511
+ }
512
+ if (wasPending && !isPending && marker) {
513
+ const pill2 = root.querySelector(".mapfirst-marker-pill");
514
+ if (pill2 instanceof HTMLElement) {
515
+ setupHoverCard(root, pill2, marker, isSelected);
516
+ }
517
+ }
518
+ if (marker && marker.type === "Accommodation") {
519
+ const content = root.querySelector(".mapfirst-marker-content");
520
+ if (content instanceof HTMLElement) {
521
+ const displayPrice = (_d = (_c = marker.pricing) == null ? void 0 : _c.offer) == null ? void 0 : _d.displayPrice;
522
+ const currentPrice = content.dataset.price;
523
+ if (currentPrice !== displayPrice) {
524
+ if (displayPrice) {
525
+ content.innerHTML = displayPrice;
526
+ content.dataset.price = displayPrice;
527
+ } else {
528
+ content.innerHTML = LOADING_VIDEO_HTML;
529
+ content.dataset.price = "";
530
+ }
531
+ }
532
+ }
533
+ }
534
+ if (marker) {
535
+ const hoverCard = document.querySelector(
536
+ `.mapfirst-property-hover-card[data-marker-id="${marker.tripadvisor_id}"]`
537
+ );
538
+ if (hoverCard) {
539
+ const rating = marker.rating || 0;
540
+ const reviews = marker.reviews || 0;
541
+ const displayPrice = (_g = (_f = (_e = marker.pricing) == null ? void 0 : _e.offer) == null ? void 0 : _f.displayPrice) != null ? _g : marker.price_level;
542
+ const ratingValueEl = hoverCard.querySelector(".rating-value");
543
+ if (ratingValueEl) {
544
+ const newRating = rating.toFixed(1);
545
+ if (ratingValueEl.textContent !== newRating) {
546
+ ratingValueEl.textContent = newRating;
547
+ }
548
+ }
549
+ const reviewsEl = hoverCard.querySelector(".reviews");
550
+ if (reviewsEl) {
551
+ const newReviews = `(${reviews})`;
552
+ if (reviewsEl.textContent !== newReviews) {
553
+ reviewsEl.textContent = newReviews;
554
+ }
555
+ }
556
+ if (marker.type === "Accommodation" && displayPrice) {
557
+ let priceEl = hoverCard.querySelector(".mapfirst-property-hover-price");
558
+ if (!priceEl) {
559
+ priceEl = document.createElement("div");
560
+ priceEl.className = "mapfirst-property-hover-price";
561
+ const detailsEl = hoverCard.querySelector(
562
+ ".mapfirst-property-hover-details"
563
+ );
564
+ const learnMoreEl = hoverCard.querySelector(
565
+ ".mapfirst-property-hover-learn-more"
566
+ );
567
+ if (detailsEl) {
568
+ if (learnMoreEl) {
569
+ detailsEl.insertBefore(priceEl, learnMoreEl);
570
+ } else {
571
+ detailsEl.appendChild(priceEl);
572
+ }
573
+ }
574
+ }
575
+ if (priceEl) {
576
+ const newPriceHtml = `Starting at <strong>${displayPrice}</strong>`;
577
+ if (priceEl.innerHTML !== newPriceHtml) {
578
+ priceEl.innerHTML = newPriceHtml;
579
+ }
580
+ }
581
+ }
582
+ const url = (_j = (_i = (_h = marker.pricing) == null ? void 0 : _h.offer) == null ? void 0 : _i.clickUrl) != null ? _j : marker.url;
583
+ if (url && hoverCard instanceof HTMLAnchorElement && hoverCard.href !== url) {
584
+ hoverCard.href = url;
585
+ }
586
+ }
587
+ }
588
+ }
589
+ function updateDotMarkerElement(element, isPrimaryType, isSelected, isPending) {
590
+ const container = element;
591
+ container.style.zIndex = String(getDotMarkerZIndex(isPrimaryType, isSelected));
592
+ const button = container.querySelector(".mapfirst-dot-marker-button");
593
+ if (button) {
594
+ button.className = getDotMarkerButtonClass(
595
+ isPending,
596
+ isPrimaryType,
597
+ isSelected
598
+ );
599
+ }
600
+ }
601
+ function extractMarkerIdFromKey(key) {
602
+ const match = key.match(/^(?:primary|dot)-(\d+)-/);
603
+ return match ? parseInt(match[1], 10) : null;
604
+ }
605
+
606
+ // src/adapters/markermanager.ts
607
+ var BaseMarkerManager = class {
608
+ constructor(mapInstance, onMarkerClick) {
609
+ this.markerCache = /* @__PURE__ */ new Map();
610
+ this.primaryType = "Accommodation";
611
+ this.selectedMarkerId = null;
612
+ this.mapInstance = mapInstance;
613
+ this.onMarkerClick = onMarkerClick;
614
+ }
615
+ render(items, primaryType, selectedMarkerId) {
616
+ if (primaryType && primaryType !== this.primaryType) {
617
+ this.primaryType = primaryType;
618
+ }
619
+ if (selectedMarkerId !== void 0) {
620
+ this.selectedMarkerId = selectedMarkerId;
621
+ }
622
+ const newKeys = new Set(items.map((item) => item.key));
623
+ for (const [key, entry] of this.markerCache.entries()) {
624
+ if (!newKeys.has(key)) {
625
+ this.removeMarkerFromMap(entry.marker);
626
+ this.markerCache.delete(key);
627
+ }
628
+ }
629
+ for (const item of items) {
630
+ const coords = safeLatLon(item.marker.location);
631
+ if (!coords) continue;
632
+ const existing = this.markerCache.get(item.key);
633
+ if (existing) {
634
+ const displayState = this.getDisplayState(item);
635
+ this.updateMarkerElement(existing.marker, item, displayState);
636
+ try {
637
+ this.updateMarkerPosition(existing.marker, coords);
638
+ } catch {
639
+ this.removeMarkerFromMap(existing.marker);
640
+ this.markerCache.delete(item.key);
641
+ this.createAndAddMarker(item, coords);
642
+ }
643
+ } else {
644
+ const existingMatch = this.findMatchingMarkerEntry(item);
645
+ const existingEntry = existingMatch == null ? void 0 : existingMatch.entry;
646
+ const existingKey = existingMatch == null ? void 0 : existingMatch.key;
647
+ if (existingEntry && existingKey) {
648
+ const displayState = this.getDisplayState(item);
649
+ this.updateMarkerElement(existingEntry.marker, item, displayState);
650
+ this.updateMarkerZIndex(
651
+ existingEntry.marker,
652
+ item,
653
+ displayState.isPrimaryType,
654
+ displayState.isSelected
655
+ );
656
+ this.markerCache.delete(existingKey);
657
+ this.markerCache.set(item.key, {
658
+ ...existingEntry,
659
+ key: item.key,
660
+ parentId: item.kind === "dot" ? item.parentId : void 0
661
+ });
662
+ try {
663
+ this.updateMarkerPosition(existingEntry.marker, coords);
664
+ } catch {
665
+ }
666
+ } else {
667
+ this.createAndAddMarker(item, coords);
668
+ }
669
+ }
670
+ }
671
+ }
672
+ destroy() {
673
+ for (const entry of this.markerCache.values()) {
674
+ this.removeMarkerFromMap(entry.marker);
675
+ }
676
+ this.markerCache.clear();
677
+ }
678
+ createAndAddMarker(item, coords) {
679
+ const element = item.kind === "primary" ? createPrimaryMarkerElement(
680
+ item,
681
+ this.primaryType,
682
+ this.selectedMarkerId,
683
+ this.onMarkerClick
684
+ ) : createDotMarkerElement(
685
+ item,
686
+ this.primaryType,
687
+ this.selectedMarkerId,
688
+ this.onMarkerClick
689
+ );
690
+ if (!element) return;
691
+ const displayState = this.getDisplayState(item);
692
+ try {
693
+ const marker = this.createMarker(
694
+ element,
695
+ coords,
696
+ item,
697
+ displayState.isPrimaryType,
698
+ displayState.isSelected
699
+ );
700
+ if (marker) {
701
+ this.markerCache.set(item.key, {
702
+ key: item.key,
703
+ marker,
704
+ kind: item.kind,
705
+ parentId: item.kind === "dot" ? item.parentId : void 0
706
+ });
707
+ }
708
+ } catch (error) {
709
+ console.error("Error creating marker", error);
710
+ }
711
+ }
712
+ updateMarkerZIndex(marker, item, isPrimaryType, isSelected) {
713
+ }
714
+ getDisplayState(item) {
715
+ var _a, _b, _c, _d;
716
+ const isPrimaryType = item.marker.type === this.primaryType;
717
+ const isSelected = this.selectedMarkerId === item.marker.tripadvisor_id;
718
+ const isAccommodation = item.marker.type === "Accommodation";
719
+ const isPending = item.kind === "primary" ? isAccommodation && !((_b = (_a = item.marker.pricing) == null ? void 0 : _a.offer) == null ? void 0 : _b.displayPrice) : isAccommodation && ((_d = (_c = item.marker.pricing) == null ? void 0 : _c.offer) == null ? void 0 : _d.availability) !== "available";
720
+ return { isPrimaryType, isSelected, isPending };
721
+ }
722
+ updateMarkerElement(marker, item, displayState) {
723
+ const element = this.getMarkerElement(marker);
724
+ if (!element) {
725
+ return;
726
+ }
727
+ if (item.kind === "primary") {
728
+ updatePrimaryMarkerElement(
729
+ element,
730
+ displayState.isPrimaryType,
731
+ displayState.isSelected,
732
+ displayState.isPending,
733
+ item.marker
734
+ );
735
+ return;
736
+ }
737
+ updateDotMarkerElement(
738
+ element,
739
+ displayState.isPrimaryType,
740
+ displayState.isSelected,
741
+ displayState.isPending
742
+ );
743
+ }
744
+ findMatchingMarkerEntry(item) {
745
+ const markerId = item.marker.tripadvisor_id;
746
+ for (const [key, entry] of this.markerCache.entries()) {
747
+ if (extractMarkerIdFromKey(key) === markerId && entry.kind === item.kind) {
748
+ return { key, entry };
749
+ }
750
+ }
751
+ return null;
752
+ }
753
+ };
754
+ function safeLatLon(location) {
755
+ if (typeof (location == null ? void 0 : location.lon) !== "number" || typeof (location == null ? void 0 : location.lat) !== "number") {
756
+ return null;
757
+ }
758
+ if (Number.isNaN(location.lon) || Number.isNaN(location.lat)) {
759
+ return null;
760
+ }
761
+ return { lon: location.lon, lat: location.lat };
762
+ }
763
+
764
+ // src/adapters/mapgl/markermanager.ts
765
+ var BaseMapGLMarkerManager = class extends BaseMarkerManager {
766
+ constructor(options) {
767
+ var _a;
768
+ super(options.mapInstance, options.onMarkerClick);
769
+ this.MarkerCtor = (_a = options.namespace) == null ? void 0 : _a.Marker;
770
+ }
771
+ render(items, primaryType, selectedMarkerId) {
772
+ if (!this.MarkerCtor) {
773
+ return;
774
+ }
775
+ super.render(items, primaryType, selectedMarkerId);
776
+ }
777
+ createMarker(element, coords, item) {
778
+ if (!this.MarkerCtor) return null;
779
+ return new this.MarkerCtor({
780
+ element,
781
+ anchor: item.kind === "primary" ? "bottom" : "center"
782
+ }).setLngLat([coords.lon, coords.lat]).addTo(this.mapInstance);
783
+ }
784
+ removeMarkerFromMap(marker) {
785
+ try {
786
+ marker.remove();
787
+ } catch {
788
+ }
789
+ }
790
+ updateMarkerPosition(marker, coords) {
791
+ marker.setLngLat([coords.lon, coords.lat]);
792
+ }
793
+ getMarkerElement(marker) {
794
+ return marker.getElement();
795
+ }
796
+ };
797
+
798
+ // src/adapters/maplibre/markermanager.ts
799
+ var MapLibreMarkerManager = class extends BaseMapGLMarkerManager {
800
+ constructor(options) {
801
+ super({
802
+ mapInstance: options.mapInstance,
803
+ namespace: options.maplibregl,
804
+ onMarkerClick: options.onMarkerClick
805
+ });
806
+ }
807
+ };
808
+
809
+ // src/adapters/google/markermanager.ts
810
+ var GoogleMapsMarkerManager = class extends BaseMarkerManager {
811
+ constructor(options) {
812
+ super(options.mapInstance, options.onMarkerClick);
813
+ this.google = options.google;
814
+ }
815
+ render(items, primaryType, selectedMarkerId) {
816
+ var _a, _b;
817
+ if (!((_b = (_a = this.google) == null ? void 0 : _a.marker) == null ? void 0 : _b.AdvancedMarkerElement)) {
818
+ console.warn("AdvancedMarkerElement not available");
819
+ return;
820
+ }
821
+ super.render(items, primaryType, selectedMarkerId);
822
+ }
823
+ createMarker(element, coords, item, isPrimaryType, isSelected) {
824
+ var _a, _b;
825
+ if (!((_b = (_a = this.google) == null ? void 0 : _a.marker) == null ? void 0 : _b.AdvancedMarkerElement)) return null;
826
+ const zIndex = item.kind === "primary" ? getPrimaryMarkerZIndex(isPrimaryType, isSelected) : getDotMarkerZIndex(isPrimaryType, isSelected);
827
+ return new this.google.marker.AdvancedMarkerElement({
828
+ map: this.mapInstance,
829
+ position: { lat: coords.lat, lng: coords.lon },
830
+ content: element,
831
+ zIndex
832
+ });
833
+ }
834
+ removeMarkerFromMap(marker) {
835
+ try {
836
+ marker.map = null;
837
+ } catch (error) {
838
+ console.error("Error removing marker", error);
839
+ }
840
+ }
841
+ updateMarkerPosition(marker, coords) {
842
+ marker.position = { lat: coords.lat, lng: coords.lon };
843
+ }
844
+ getMarkerElement(marker) {
845
+ const element = marker.content;
846
+ return element instanceof HTMLElement ? element : null;
847
+ }
848
+ updateMarkerZIndex(marker, item, isPrimaryType, isSelected) {
849
+ marker.zIndex = item.kind === "primary" ? getPrimaryMarkerZIndex(isPrimaryType, isSelected) : getDotMarkerZIndex(isPrimaryType, isSelected);
850
+ }
851
+ };
852
+
853
+ // src/adapters/mapbox/markermanager.ts
854
+ var MapboxMarkerManager = class extends BaseMapGLMarkerManager {
855
+ constructor(options) {
856
+ super({
857
+ mapInstance: options.mapInstance,
858
+ namespace: options.mapboxgl,
859
+ onMarkerClick: options.onMarkerClick
860
+ });
861
+ }
862
+ };
863
+
864
+ // src/adapters/index.ts
865
+ var MapAdapter = class {
866
+ constructor(map) {
867
+ this.map = map;
868
+ }
869
+ /**
870
+ * Get the underlying map instance
871
+ * @returns {any} The native map instance
872
+ */
873
+ getMap() {
874
+ return this.map;
875
+ }
876
+ /**
877
+ * Set up impression tracking when map becomes visible
878
+ * @param {() => void} onImpression Callback to invoke when map is visible
879
+ */
880
+ setupImpressionTracking(onImpression) {
881
+ if (typeof window === "undefined" || !window.IntersectionObserver) {
882
+ return;
883
+ }
884
+ const container = this.getContainer();
885
+ if (!container) {
886
+ return;
887
+ }
888
+ const observer = new IntersectionObserver(
889
+ (entries) => {
890
+ entries.forEach((entry) => {
891
+ if (entry.isIntersecting) {
892
+ onImpression();
893
+ observer.disconnect();
894
+ }
895
+ });
896
+ },
897
+ { threshold: 0.1 }
898
+ );
899
+ observer.observe(container);
900
+ const cleanup = () => observer.disconnect();
901
+ const originalCleanup = this.cleanup.bind(this);
902
+ this.cleanup = () => {
903
+ cleanup();
904
+ originalCleanup();
905
+ };
906
+ }
907
+ };
908
+
909
+ // src/adapters/mapgl/adapter.ts
910
+ var MAP_GL_REFRESH_EVENTS = ["move", "zoom", "dragend", "pitch", "rotate"];
911
+ var BaseMapGLAdapter = class extends MapAdapter {
912
+ constructor(map, markerManagerFactory) {
913
+ super(map);
914
+ this.markerManagerFactory = markerManagerFactory;
915
+ this.cleanupFns = [];
916
+ }
917
+ initialize(options) {
918
+ this.markerManager = this.markerManagerFactory({
919
+ mapInstance: this.map,
920
+ namespace: this.getNamespace(options),
921
+ onMarkerClick: options.onMarkerClick
922
+ });
923
+ if (options.onRefresh) {
924
+ this.attachEventListeners(options.onRefresh);
925
+ }
926
+ if (options.onMapMoveEnd) {
927
+ this.attachBoundsTracking(options.onMapMoveEnd);
928
+ }
929
+ return this.markerManager;
930
+ }
931
+ attachBoundsTracking(onMapMoveEnd) {
932
+ if (!this.map || typeof this.map.on !== "function") {
933
+ return;
934
+ }
935
+ const handleMoveEnd = () => {
936
+ const bounds = this.getMapBounds();
937
+ onMapMoveEnd(bounds);
938
+ };
939
+ const handleLoad = () => {
940
+ const bounds = this.getMapBounds();
941
+ onMapMoveEnd(bounds);
942
+ };
943
+ if (this.map.loaded && this.map.loaded()) {
944
+ handleLoad();
945
+ } else {
946
+ this.map.once("load", handleLoad);
947
+ this.cleanupFns.push(() => {
948
+ if (typeof this.map.off === "function") {
949
+ this.map.off("load", handleLoad);
950
+ }
951
+ });
952
+ }
953
+ this.map.on("moveend", handleMoveEnd);
954
+ this.cleanupFns.push(() => {
955
+ if (typeof this.map.off === "function") {
956
+ this.map.off("moveend", handleMoveEnd);
957
+ }
958
+ });
959
+ }
960
+ attachEventListeners(onRefresh) {
961
+ if (!this.map || typeof this.map.on !== "function") {
962
+ return;
963
+ }
964
+ MAP_GL_REFRESH_EVENTS.forEach((eventName) => {
965
+ this.map.on(eventName, onRefresh);
966
+ this.cleanupFns.push(() => {
967
+ if (typeof this.map.off === "function") {
968
+ this.map.off(eventName, onRefresh);
969
+ }
970
+ });
971
+ });
972
+ }
973
+ getMarkerManager() {
974
+ return this.markerManager;
975
+ }
976
+ getContainer() {
977
+ var _a, _b;
978
+ return ((_b = (_a = this.map) == null ? void 0 : _a.getContainer) == null ? void 0 : _b.call(_a)) || null;
979
+ }
980
+ cleanup() {
981
+ for (const cleanup of this.cleanupFns) {
982
+ try {
983
+ cleanup();
984
+ } catch {
985
+ }
986
+ }
987
+ this.cleanupFns.length = 0;
988
+ }
989
+ getMap() {
990
+ return this.map;
991
+ }
992
+ getCenter() {
993
+ const center = this.map.getCenter();
994
+ return { lng: center.lng, lat: center.lat };
995
+ }
996
+ getZoom() {
997
+ return this.map.getZoom();
998
+ }
999
+ getBearing() {
1000
+ return this.map.getBearing();
1001
+ }
1002
+ getPitch() {
1003
+ return this.map.getPitch();
1004
+ }
1005
+ getMapBounds() {
1006
+ const bounds = this.map.getBounds();
1007
+ const sw = bounds.getSouthWest();
1008
+ const ne = bounds.getNorthEast();
1009
+ return {
1010
+ sw: { lat: sw.lat, lng: sw.lng },
1011
+ ne: { lat: ne.lat, lng: ne.lng }
1012
+ };
1013
+ }
1014
+ project(lngLat) {
1015
+ return this.map.project({ lng: lngLat[0], lat: lngLat[1] });
1016
+ }
1017
+ on(event, handler) {
1018
+ this.map.on(event, handler);
1019
+ }
1020
+ off(event, handler) {
1021
+ this.map.off(event, handler);
1022
+ }
1023
+ resize() {
1024
+ this.map.resize();
1025
+ }
1026
+ remove() {
1027
+ this.cleanup();
1028
+ this.map.remove();
1029
+ }
1030
+ };
1031
+
1032
+ // src/adapters/maplibre/index.ts
1033
+ var MapLibreAdapter = class extends BaseMapGLAdapter {
1034
+ constructor(map) {
1035
+ super(map, ({ mapInstance, namespace, onMarkerClick }) => {
1036
+ return new MapLibreMarkerManager({
1037
+ mapInstance,
1038
+ maplibregl: namespace,
1039
+ onMarkerClick
1040
+ });
1041
+ });
1042
+ }
1043
+ getNamespace(options) {
1044
+ return options.maplibregl;
1045
+ }
1046
+ };
1047
+
1048
+ // src/adapters/google/index.ts
1049
+ var GoogleMapsAdapter = class extends MapAdapter {
1050
+ constructor(map) {
1051
+ super(map);
1052
+ this.cleanupFns = [];
1053
+ this.initializeOverlayView();
1054
+ }
1055
+ initialize(options) {
1056
+ this.markerManager = new GoogleMapsMarkerManager({
1057
+ mapInstance: this.map,
1058
+ google: options.google,
1059
+ onMarkerClick: options.onMarkerClick
1060
+ });
1061
+ if (options.onRefresh) {
1062
+ this.attachEventListeners(options.onRefresh);
1063
+ }
1064
+ if (options.onMapMoveEnd) {
1065
+ this.attachBoundsTracking(options.onMapMoveEnd, options.google);
1066
+ }
1067
+ return this.markerManager;
1068
+ }
1069
+ attachBoundsTracking(onMapMoveEnd, google) {
1070
+ if (!this.map) {
1071
+ return;
1072
+ }
1073
+ const handleIdle = () => {
1074
+ const bounds = this.getMapBounds();
1075
+ onMapMoveEnd(bounds);
1076
+ };
1077
+ handleIdle();
1078
+ const listener = google.event.addListener(this.map, "idle", handleIdle);
1079
+ this.cleanupFns.push(() => {
1080
+ google.event.removeListener(listener);
1081
+ });
1082
+ }
1083
+ attachEventListeners(onRefresh) {
1084
+ const events = [
1085
+ "center_changed",
1086
+ "zoom_changed",
1087
+ "drag",
1088
+ "heading_changed",
1089
+ "tilt_changed"
1090
+ ];
1091
+ const listeners = [];
1092
+ events.forEach((eventName) => {
1093
+ const listener = this.map.addListener(eventName, onRefresh);
1094
+ listeners.push(listener);
1095
+ });
1096
+ this.cleanupFns.push(() => {
1097
+ listeners.forEach((listener) => {
1098
+ try {
1099
+ listener.remove();
1100
+ } catch {
1101
+ }
1102
+ });
1103
+ });
1104
+ }
1105
+ getMarkerManager() {
1106
+ return this.markerManager;
1107
+ }
1108
+ getContainer() {
1109
+ var _a, _b;
1110
+ return ((_b = (_a = this.map) == null ? void 0 : _a.getDiv) == null ? void 0 : _b.call(_a)) || null;
1111
+ }
1112
+ cleanup() {
1113
+ for (const cleanup of this.cleanupFns) {
1114
+ try {
1115
+ cleanup();
1116
+ } catch {
1117
+ }
1118
+ }
1119
+ this.cleanupFns.length = 0;
1120
+ }
1121
+ initializeOverlayView() {
1122
+ var _a;
1123
+ const googleMaps = (_a = globalThis.google) == null ? void 0 : _a.maps;
1124
+ if (!googleMaps) return;
1125
+ const OverlayView = googleMaps.OverlayView;
1126
+ if (!OverlayView) return;
1127
+ this.overlayView = new OverlayView();
1128
+ this.overlayView.draw = function() {
1129
+ };
1130
+ this.overlayView.setMap(this.map);
1131
+ }
1132
+ getMap() {
1133
+ return this.map;
1134
+ }
1135
+ getCenter() {
1136
+ const center = this.map.getCenter();
1137
+ if (!center) {
1138
+ return { lng: 0, lat: 0 };
1139
+ }
1140
+ return { lng: center.lng(), lat: center.lat() };
1141
+ }
1142
+ getZoom() {
1143
+ var _a;
1144
+ return (_a = this.map.getZoom()) != null ? _a : 0;
1145
+ }
1146
+ getBearing() {
1147
+ var _a;
1148
+ return (_a = this.map.getHeading()) != null ? _a : 0;
1149
+ }
1150
+ getPitch() {
1151
+ var _a;
1152
+ return (_a = this.map.getTilt()) != null ? _a : 0;
1153
+ }
1154
+ getMapBounds() {
1155
+ const bounds = this.map.getBounds();
1156
+ if (!bounds) {
1157
+ return {
1158
+ sw: { lat: 0, lng: 0 },
1159
+ ne: { lat: 0, lng: 0 }
1160
+ };
1161
+ }
1162
+ const sw = bounds.getSouthWest();
1163
+ const ne = bounds.getNorthEast();
1164
+ return {
1165
+ sw: { lat: sw.lat(), lng: sw.lng() },
1166
+ ne: { lat: ne.lat(), lng: ne.lng() }
1167
+ };
1168
+ }
1169
+ project(lngLat) {
1170
+ var _a;
1171
+ if (!this.overlayView) {
1172
+ return { x: 0, y: 0 };
1173
+ }
1174
+ const projection = this.overlayView.getProjection();
1175
+ if (!projection) {
1176
+ return { x: 0, y: 0 };
1177
+ }
1178
+ const googleMaps = (_a = globalThis.google) == null ? void 0 : _a.maps;
1179
+ if (!googleMaps) {
1180
+ return { x: 0, y: 0 };
1181
+ }
1182
+ const latLng = new googleMaps.LatLng(lngLat[1], lngLat[0]);
1183
+ const point = projection.fromLatLngToContainerPixel(latLng);
1184
+ if (!point) {
1185
+ return { x: 0, y: 0 };
1186
+ }
1187
+ return {
1188
+ x: point.x,
1189
+ y: point.y
1190
+ };
1191
+ }
1192
+ on(event, handler) {
1193
+ this.map.addListener(event, handler);
1194
+ }
1195
+ off(event, handler) {
1196
+ var _a;
1197
+ const googleMaps = (_a = globalThis.google) == null ? void 0 : _a.maps;
1198
+ if (googleMaps == null ? void 0 : googleMaps.event) {
1199
+ googleMaps.event.clearListeners(this.map, event);
1200
+ }
1201
+ }
1202
+ resize() {
1203
+ var _a;
1204
+ const googleMaps = (_a = globalThis.google) == null ? void 0 : _a.maps;
1205
+ if (googleMaps == null ? void 0 : googleMaps.event) {
1206
+ googleMaps.event.trigger(this.map, "resize");
1207
+ }
1208
+ }
1209
+ remove() {
1210
+ this.cleanup();
1211
+ if (this.overlayView) {
1212
+ this.overlayView.setMap(null);
1213
+ this.overlayView = null;
1214
+ }
1215
+ }
1216
+ };
1217
+
1218
+ // src/adapters/mapbox/index.ts
1219
+ var MapboxAdapter = class extends BaseMapGLAdapter {
1220
+ constructor(map) {
1221
+ super(map, ({ mapInstance, namespace, onMarkerClick }) => {
1222
+ return new MapboxMarkerManager({
1223
+ mapInstance,
1224
+ mapboxgl: namespace,
1225
+ onMarkerClick
1226
+ });
1227
+ });
1228
+ }
1229
+ getNamespace(options) {
1230
+ return options.mapboxgl;
1231
+ }
1232
+ };
1233
+
1234
+ // src/utils/clustering.ts
1235
+ function extractViewState(mapInstance) {
1236
+ const center = mapInstance.getCenter();
1237
+ return {
1238
+ longitude: center.lng,
1239
+ latitude: center.lat,
1240
+ zoom: mapInstance.getZoom(),
1241
+ bearing: mapInstance.getBearing(),
1242
+ pitch: mapInstance.getPitch()
1243
+ };
1244
+ }
1245
+ var COLLISION_THRESHOLD_PX_ZOOM_BREAKPOINTS = [
1246
+ { zoom: 6, threshold: 120 },
1247
+ { zoom: 8, threshold: 108 },
1248
+ { zoom: 10, threshold: 92 },
1249
+ { zoom: 12, threshold: 80 },
1250
+ { zoom: 14, threshold: 68 },
1251
+ { zoom: 16, threshold: 56 }
1252
+ ];
1253
+ function resolveCollisionThreshold(zoom) {
1254
+ for (const breakpoint of COLLISION_THRESHOLD_PX_ZOOM_BREAKPOINTS) {
1255
+ if (zoom <= breakpoint.zoom) {
1256
+ return breakpoint.threshold;
1257
+ }
1258
+ }
1259
+ return 48;
1260
+ }
1261
+ function clusterMarkers({
1262
+ primaryType,
1263
+ markers,
1264
+ map,
1265
+ selectedMarkerId,
1266
+ zoom,
1267
+ collisionThresholdPx,
1268
+ dotCollisionThresholdPx
1269
+ }) {
1270
+ if (!markers.length) return [];
1271
+ if (!map) {
1272
+ return markers.map((marker) => createSimplePrimaryClusterItem(marker));
1273
+ }
1274
+ const projected = markers.map((marker, index) => {
1275
+ const location = marker.location;
1276
+ if (typeof (location == null ? void 0 : location.lon) !== "number" || typeof (location == null ? void 0 : location.lat) !== "number") {
1277
+ return null;
1278
+ }
1279
+ const { x, y } = map.project([location.lon, location.lat]);
1280
+ return { marker, x, y };
1281
+ }).filter((value) => Boolean(value)).map((value, index) => ({ ...value, index }));
1282
+ if (!projected.length) {
1283
+ return [];
1284
+ }
1285
+ const threshold = resolveCollisionThreshold(zoom);
1286
+ const dotThreshold = resolveDotCollisionThreshold(zoom);
1287
+ const parent = projected.map((_, idx) => idx);
1288
+ const find = (i) => {
1289
+ if (parent[i] === i) return i;
1290
+ parent[i] = find(parent[i]);
1291
+ return parent[i];
1292
+ };
1293
+ const union = (a, b) => {
1294
+ const rootA = find(a);
1295
+ const rootB = find(b);
1296
+ if (rootA === rootB) return;
1297
+ parent[rootB] = rootA;
1298
+ };
1299
+ for (let i = 0; i < projected.length; i += 1) {
1300
+ for (let j = i + 1; j < projected.length; j += 1) {
1301
+ const dx = projected[i].x - projected[j].x;
1302
+ const dy = projected[i].y - projected[j].y;
1303
+ if (Math.hypot(dx, dy) <= threshold) {
1304
+ union(i, j);
1305
+ }
1306
+ }
1307
+ }
1308
+ const groups = /* @__PURE__ */ new Map();
1309
+ for (const item of projected) {
1310
+ const root = find(item.index);
1311
+ const group = groups.get(root);
1312
+ if (group) {
1313
+ group.push(item);
1314
+ } else {
1315
+ groups.set(root, [item]);
1316
+ }
1317
+ }
1318
+ const clustered = [];
1319
+ groups.forEach((groupItems) => {
1320
+ if (groupItems.length === 1) {
1321
+ const [{ marker }] = groupItems;
1322
+ clustered.push(
1323
+ createPrimaryClusterItem(marker, primaryType, selectedMarkerId)
1324
+ );
1325
+ return;
1326
+ }
1327
+ const sorted = [...groupItems].sort(
1328
+ (a, b) => compareMarkers(b.marker, a.marker, primaryType)
1329
+ );
1330
+ const [primary, ...rest] = sorted;
1331
+ clustered.push(
1332
+ createPrimaryClusterItem(primary.marker, primaryType, selectedMarkerId)
1333
+ );
1334
+ if (!rest.length) return;
1335
+ const dotCandidates = [];
1336
+ const remainder = [];
1337
+ rest.forEach((item) => {
1338
+ if (selectedMarkerId && item.marker.tripadvisor_id === selectedMarkerId) {
1339
+ clustered.push(createPrimaryClusterItem(item.marker, primaryType, true));
1340
+ return;
1341
+ }
1342
+ if (distancePx(primary, item) <= dotThreshold) {
1343
+ dotCandidates.push(item);
1344
+ } else {
1345
+ remainder.push(item);
1346
+ }
1347
+ });
1348
+ dotCandidates.forEach((item) => {
1349
+ clustered.push(createDotClusterItem(item.marker, primaryType, primary));
1350
+ });
1351
+ if (remainder.length) {
1352
+ const followUp = clusterMarkers({
1353
+ markers: remainder.map((item) => item.marker),
1354
+ map,
1355
+ selectedMarkerId,
1356
+ zoom,
1357
+ primaryType,
1358
+ collisionThresholdPx,
1359
+ dotCollisionThresholdPx
1360
+ });
1361
+ clustered.push(...followUp);
1362
+ }
1363
+ });
1364
+ return clustered;
1365
+ }
1366
+ function createSimplePrimaryClusterItem(marker) {
1367
+ return {
1368
+ kind: "primary",
1369
+ marker,
1370
+ key: `primary-${marker.tripadvisor_id}`
1371
+ };
1372
+ }
1373
+ function createPrimaryClusterItem(marker, primaryType, selected) {
1374
+ const isPrimary = marker.type === primaryType;
1375
+ const isSelected = typeof selected === "boolean" ? selected : selected === marker.tripadvisor_id;
1376
+ return {
1377
+ kind: "primary",
1378
+ marker,
1379
+ key: buildClusterKey("primary", marker, isPrimary, isSelected)
1380
+ };
1381
+ }
1382
+ function createDotClusterItem(marker, primaryType, parent) {
1383
+ const isPrimary = marker.type === primaryType;
1384
+ return {
1385
+ kind: "dot",
1386
+ marker,
1387
+ key: buildClusterKey("dot", marker, isPrimary, false),
1388
+ parentId: parent.marker.tripadvisor_id
1389
+ };
1390
+ }
1391
+ function buildClusterKey(kind, marker, isPrimary, isSelected) {
1392
+ var _a;
1393
+ return `${kind}-${marker.tripadvisor_id}-p${isPrimary ? 1 : 0}-s${isSelected ? 1 : 0}-${(_a = marker.pricing) == null ? void 0 : _a.availability}`;
1394
+ }
1395
+ function distancePx(a, b) {
1396
+ return Math.hypot(a.x - b.x, a.y - b.y);
1397
+ }
1398
+ function resolveDotCollisionThreshold(zoom) {
1399
+ const base = resolveCollisionThreshold(zoom);
1400
+ return Math.max(48, base);
1401
+ }
1402
+ function compareMarkers(a, b, primaryType) {
1403
+ var _a, _b;
1404
+ const aIsPrimary = a.type === primaryType;
1405
+ const bIsPrimary = b.type === primaryType;
1406
+ if (aIsPrimary && !bIsPrimary) return 1;
1407
+ if (!aIsPrimary && bIsPrimary) return -1;
1408
+ const ratingDiff = resolveRating(a) - resolveRating(b);
1409
+ if (ratingDiff !== 0) return ratingDiff;
1410
+ const priceDiff = resolvePrice(a) - resolvePrice(b);
1411
+ if (priceDiff !== 0) return priceDiff;
1412
+ const reviewsDiff = ((_a = a.reviews) != null ? _a : 0) - ((_b = b.reviews) != null ? _b : 0);
1413
+ if (reviewsDiff !== 0) return reviewsDiff;
1414
+ return a.tripadvisor_id - b.tripadvisor_id;
1415
+ }
1416
+ function resolveRating(marker) {
1417
+ if (typeof marker.rating === "number") return marker.rating;
1418
+ if (marker.rating === void 0 || marker.rating === null) return -Infinity;
1419
+ const parsed = Number(marker.rating);
1420
+ return Number.isNaN(parsed) ? -Infinity : parsed;
1421
+ }
1422
+ function resolvePrice(marker) {
1423
+ var _a, _b, _c;
1424
+ if (!((_b = (_a = marker.pricing) == null ? void 0 : _a.offer) == null ? void 0 : _b.price)) return -Infinity;
1425
+ const numeric = Number(
1426
+ ((_c = marker.pricing.offer.displayPrice) != null ? _c : "0").replace(/[^0-9.,-]+/g, "").replace(/,/g, "")
1427
+ );
1428
+ return Number.isNaN(numeric) ? -Infinity : numeric;
1429
+ }
1430
+
1431
+ // src/utils/filters.ts
1432
+ function processApiFilters(apiFilters) {
1433
+ const filters = [];
1434
+ const addBasicFilters = (values, type, prefix) => {
1435
+ if (!values || !Array.isArray(values)) return;
1436
+ values.forEach((value) => {
1437
+ filters.push({
1438
+ id: `${prefix}-${value}`,
1439
+ label: value,
1440
+ type,
1441
+ value
1442
+ });
1443
+ });
1444
+ };
1445
+ addBasicFilters(apiFilters.amenities, "amenity", "amenity");
1446
+ addBasicFilters(apiFilters.hotelStyle, "hotelStyle", "hotelStyle");
1447
+ if (apiFilters.price) {
1448
+ filters.push({
1449
+ id: "priceRange",
1450
+ label: "Price Range",
1451
+ type: "priceRange",
1452
+ value: `${apiFilters.price.min}-${apiFilters.price.max}`,
1453
+ priceRange: apiFilters.price
1454
+ });
1455
+ }
1456
+ if (typeof apiFilters.minRating === "number" && Number.isFinite(apiFilters.minRating)) {
1457
+ filters.push({
1458
+ id: "minRating",
1459
+ label: `${apiFilters.minRating}+`,
1460
+ type: "minRating",
1461
+ value: String(apiFilters.minRating),
1462
+ numericValue: apiFilters.minRating
1463
+ });
1464
+ }
1465
+ if (typeof apiFilters.starRating === "number" && Number.isFinite(apiFilters.starRating)) {
1466
+ filters.push({
1467
+ id: "starRating",
1468
+ label: `${apiFilters.starRating} Stars`,
1469
+ type: "starRating",
1470
+ value: String(apiFilters.starRating),
1471
+ numericValue: apiFilters.starRating
1472
+ });
1473
+ }
1474
+ if (apiFilters.transformed_query) {
1475
+ filters.push({
1476
+ id: "transformed_query",
1477
+ label: apiFilters.transformed_query,
1478
+ type: "transformed_query",
1479
+ value: apiFilters.transformed_query
1480
+ });
1481
+ }
1482
+ if (apiFilters.selected_restaurant_price_levels) {
1483
+ const joinedPriceLevels = apiFilters.selected_restaurant_price_levels.join(
1484
+ ", "
1485
+ );
1486
+ filters.push({
1487
+ id: "selected_restaurant_price_levels",
1488
+ label: joinedPriceLevels,
1489
+ type: "selected_restaurant_price_levels",
1490
+ value: joinedPriceLevels,
1491
+ priceLevels: apiFilters.selected_restaurant_price_levels
1492
+ });
1493
+ }
1494
+ return filters;
1495
+ }
1496
+ function convertToApiFilters(filters) {
1497
+ return filters.map((filter) => {
1498
+ const apiFilter = {
1499
+ id: filter.id,
1500
+ label: typeof filter.label === "string" ? filter.label : String(filter.label || ""),
1501
+ type: filter.type,
1502
+ value: filter.value
1503
+ };
1504
+ if (filter.numericValue !== void 0) {
1505
+ apiFilter.numericValue = filter.numericValue;
1506
+ }
1507
+ if (filter.priceRange) {
1508
+ const min = filter.priceRange.min;
1509
+ const max = filter.priceRange.max;
1510
+ if (min !== void 0) {
1511
+ apiFilter.priceRange = {
1512
+ min,
1513
+ ...max !== void 0 && { max }
1514
+ };
1515
+ }
1516
+ }
1517
+ if (filter.priceLevels) {
1518
+ apiFilter.priceLevels = filter.priceLevels;
1519
+ }
1520
+ return apiFilter;
1521
+ });
1522
+ }
1523
+
1524
+ // src/index.ts
1525
+ var API_URLS = {
1526
+ prod: "https://api.mapfirst.ai",
1527
+ test: "https://api.mapfirst.ai/test"
1528
+ };
1529
+ var API_DISABLED_ERROR_MESSAGE = "API usage is disabled";
1530
+ var USE_API_FALSE_PLATFORM_ERROR = "When useApi is false, only maplibre platform is supported. Google Maps and Mapbox require API usage.";
1531
+ var USE_API_FALSE_PLATFORM_WARNING = "When useApi is false, only maplibre platform is supported. Please switch to maplibre.";
1532
+ function getDocumentReferrer() {
1533
+ try {
1534
+ return document.referrer || void 0;
1535
+ } catch (error) {
1536
+ console.error(error);
1537
+ return void 0;
1538
+ }
1539
+ }
1540
+ function createSdkHeaders(apiKey, referrer) {
1541
+ return {
1542
+ "Content-Type": "application/json",
1543
+ "X-Source": "SDK",
1544
+ ...apiKey && { "X-API-Key": apiKey },
1545
+ ...referrer && { "X-Referer": referrer }
1546
+ };
1547
+ }
1548
+ var PropertiesFetchError = class extends Error {
1549
+ constructor({
1550
+ message,
1551
+ status,
1552
+ code
1553
+ }) {
1554
+ super(message);
1555
+ this.name = "PropertiesFetchError";
1556
+ this.status = status;
1557
+ this.code = code;
1558
+ }
1559
+ };
1560
+ async function fetchImages(tripadvisorId, limit = 1) {
1561
+ try {
1562
+ const response = await fetch(
1563
+ `https://l4detuz832.execute-api.us-east-1.amazonaws.com/dev/photo?id=${tripadvisorId}&limit=${limit}`
1564
+ );
1565
+ if (!response.ok) {
1566
+ return null;
1567
+ }
1568
+ const data = await response.json();
1569
+ if (data.photos && data.photos.length > 0) {
1570
+ const imageUrl = data.photos[0]["FullSizeURL"].url;
1571
+ const imageResponse = await fetch(imageUrl);
1572
+ if (imageResponse.ok) {
1573
+ return imageUrl;
1574
+ }
1575
+ }
1576
+ return null;
1577
+ } catch (error) {
1578
+ console.debug("Failed to fetch images:", error);
1579
+ return null;
1580
+ }
1581
+ }
1582
+ async function fetchProperties(url, body, apiKey, { signal } = {}) {
1583
+ var _a, _b;
1584
+ const referrer = getDocumentReferrer();
1585
+ const response = await fetch(url, {
1586
+ method: "POST",
1587
+ headers: createSdkHeaders(apiKey, referrer),
1588
+ body: JSON.stringify(body),
1589
+ signal
1590
+ });
1591
+ if (!response.ok) {
1592
+ let message = `Unexpected response: ${response.status}`;
1593
+ let code;
1594
+ try {
1595
+ const errorBody = await response.json();
1596
+ message = (_b = (_a = errorBody.detail) != null ? _a : errorBody.error) != null ? _b : message;
1597
+ code = errorBody.code;
1598
+ } catch {
1599
+ }
1600
+ throw new PropertiesFetchError({ message, status: response.status, code });
1601
+ }
1602
+ return await response.json();
1603
+ }
1604
+ function toISO(date) {
1605
+ if (typeof date === "string") return date;
1606
+ return date.toISOString().slice(0, 10);
1607
+ }
1608
+ var DEFAULT_PRIMARY_TYPE = "Accommodation";
1609
+ function getDefaultDates() {
1610
+ const dayMs = 24 * 60 * 60 * 1e3;
1611
+ const base = new Date(Date.now() + 10 * dayMs);
1612
+ const daysUntilSaturday = (6 - base.getDay() + 7) % 7;
1613
+ const checkIn = new Date(base.getTime() + daysUntilSaturday * dayMs);
1614
+ const startDay = checkIn.getDay();
1615
+ const daysUntilWeekend = startDay === 0 ? 6 : 6 - startDay;
1616
+ const checkOut = new Date(checkIn.getTime() + (daysUntilWeekend + 1) * dayMs);
1617
+ return { checkIn, checkOut };
1618
+ }
1619
+ var MapFirstCore = class {
1620
+ constructor(options) {
1621
+ this.options = options;
1622
+ this.adapter = null;
1623
+ this.properties = [];
1624
+ this.selectedMarkerId = null;
1625
+ this.destroyed = false;
1626
+ this.clusterItems = [];
1627
+ this.isMapAttached = false;
1628
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
1629
+ this.properties = [...(_a = options.properties) != null ? _a : []];
1630
+ this.primaryType = options.primaryType;
1631
+ this.selectedMarkerId = (_b = options.selectedMarkerId) != null ? _b : null;
1632
+ this.useApi = (_c = options.useApi) != null ? _c : true;
1633
+ this.environment = (_d = options.environment) != null ? _d : "prod";
1634
+ this.apiUrl = (_e = options.apiUrl) != null ? _e : API_URLS[this.environment];
1635
+ this.apiKey = options.apiKey;
1636
+ this.requestBody = options.requestBody;
1637
+ this.currentPlatform = options.platform;
1638
+ this.assertPlatformSupportForNoApi(options.platform, "throw");
1639
+ const isGoogleMaps = isGoogleMapsOptions(options);
1640
+ this.fitBoundsPadding = {
1641
+ top: (_g = (_f = options.fitBoundsPadding) == null ? void 0 : _f.top) != null ? _g : isGoogleMaps ? 0 : 50,
1642
+ bottom: (_i = (_h = options.fitBoundsPadding) == null ? void 0 : _h.bottom) != null ? _i : isGoogleMaps ? 0 : 160,
1643
+ left: (_k = (_j = options.fitBoundsPadding) == null ? void 0 : _j.left) != null ? _k : isGoogleMaps ? 0 : 50,
1644
+ right: (_m = (_l = options.fitBoundsPadding) == null ? void 0 : _l.right) != null ? _m : isGoogleMaps ? 0 : 50
1645
+ };
1646
+ const defaultDates = getDefaultDates();
1647
+ this.state = {
1648
+ center: ((_n = options.initialLocationData) == null ? void 0 : _n.latitude) && options.initialLocationData.longitude ? [
1649
+ options.initialLocationData.latitude,
1650
+ options.initialLocationData.longitude
1651
+ ] : [0, 0],
1652
+ zoom: (_p = (_o = options.initialLocationData) == null ? void 0 : _o.zoom) != null ? _p : 0,
1653
+ bounds: (_r = (_q = options.initialLocationData) == null ? void 0 : _q.bounds) != null ? _r : null,
1654
+ pendingBounds: null,
1655
+ tempBounds: null,
1656
+ properties: this.properties,
1657
+ primary: (_s = this.primaryType) != null ? _s : DEFAULT_PRIMARY_TYPE,
1658
+ selectedPropertyId: this.selectedMarkerId,
1659
+ initialLoading: true,
1660
+ isSearching: false,
1661
+ firstCallDone: false,
1662
+ filters: {
1663
+ checkIn: defaultDates.checkIn,
1664
+ checkOut: defaultDates.checkOut,
1665
+ numAdults: 2,
1666
+ numRooms: 1,
1667
+ ...((_t = options.initialLocationData) == null ? void 0 : _t.currency) && {
1668
+ currency: options.initialLocationData.currency
1669
+ }
1670
+ },
1671
+ activeLocation: {
1672
+ country: "",
1673
+ location_id: null,
1674
+ locationName: "",
1675
+ coordinates: [0, 0]
1676
+ },
1677
+ isFlyToAnimating: false,
1678
+ ...options.state
1679
+ };
1680
+ this.callbacks = (_u = options.callbacks) != null ? _u : {};
1681
+ if (this.hasMapInstance(options)) {
1682
+ this.adapter = this.createAdapter(options);
1683
+ this.isMapAttached = true;
1684
+ this.refresh();
1685
+ }
1686
+ if (options.initialLocationData) {
1687
+ this.initializeFromLocationData(options.initialLocationData);
1688
+ } else if (this.requestBody && this.isMapAttached) {
1689
+ this.autoLoadProperties();
1690
+ }
1691
+ }
1692
+ hasMapInstance(options) {
1693
+ if ("adapter" in options && options.adapter) return true;
1694
+ if ("mapInstance" in options && options.mapInstance) return true;
1695
+ return false;
1696
+ }
1697
+ assertPlatformSupportForNoApi(platform, mode) {
1698
+ if (this.useApi || !platform || platform === "maplibre") {
1699
+ return;
1700
+ }
1701
+ if (mode === "throw") {
1702
+ throw new Error(USE_API_FALSE_PLATFORM_ERROR);
1703
+ }
1704
+ console.warn(USE_API_FALSE_PLATFORM_WARNING);
1705
+ }
1706
+ ensureApiEnabled(method, onError) {
1707
+ if (this.useApi) return true;
1708
+ console.warn(`${method} requires API usage. Set useApi to true.`);
1709
+ onError == null ? void 0 : onError(new Error(API_DISABLED_ERROR_MESSAGE));
1710
+ return false;
1711
+ }
1712
+ async initializeFromLocationData(locationData) {
1713
+ var _a;
1714
+ if (!this.ensureApiEnabled("initializeFromLocationData")) {
1715
+ return;
1716
+ }
1717
+ try {
1718
+ const {
1719
+ city,
1720
+ state,
1721
+ country,
1722
+ query,
1723
+ latitude,
1724
+ longitude,
1725
+ radius,
1726
+ bounds
1727
+ } = locationData;
1728
+ const requestBody = {
1729
+ filters: this.getFilters(),
1730
+ initial: true,
1731
+ query,
1732
+ latitude,
1733
+ longitude,
1734
+ radius,
1735
+ bounds
1736
+ };
1737
+ const location = [city, state].filter(Boolean).join(", ");
1738
+ if (country || location) {
1739
+ const geoResponse = await fetch(
1740
+ `${this.apiUrl}/geo-lookup2?${new URLSearchParams({
1741
+ ...country && { country_code: country },
1742
+ ...location && { q: location }
1743
+ }).toString()}`,
1744
+ {
1745
+ headers: {
1746
+ ...this.apiKey && {
1747
+ "X-API-Key": this.apiKey
1748
+ }
1749
+ }
1750
+ }
1751
+ );
1752
+ if (geoResponse.ok) {
1753
+ const place = await geoResponse.json();
1754
+ requestBody.city = !["country", "island", "state"].includes(
1755
+ place.type
1756
+ ) ? place.name : void 0;
1757
+ requestBody.state = place.type === "state" ? place.name : !["country", "island", "county"].includes(place.type) ? place.state : void 0;
1758
+ requestBody.country = ["country", "island"].includes(place.type) ? place.name : place.country;
1759
+ requestBody.location_id = place.id;
1760
+ requestBody.latitude = place.lat;
1761
+ requestBody.longitude = place.lon;
1762
+ this.setActiveLocation({
1763
+ city,
1764
+ state,
1765
+ country,
1766
+ location_id: (_a = place.id) != null ? _a : null,
1767
+ locationName: [city, state, country].filter(Boolean).join(", "),
1768
+ ...place.lon && place.lat && { coordinates: [place.lat, place.lon] }
1769
+ });
1770
+ if (place.lon && place.lat) {
1771
+ this.setState({
1772
+ center: [place.lat, place.lon],
1773
+ zoom: city ? 12 : state ? 8 : 5
1774
+ });
1775
+ }
1776
+ } else {
1777
+ this.handleError(
1778
+ new Error(`Geo mapping fetch failed: ${geoResponse.statusText}`),
1779
+ "initializeFromLocationData"
1780
+ );
1781
+ }
1782
+ }
1783
+ this.requestBody = requestBody;
1784
+ if (this.isMapAttached) {
1785
+ await this.autoLoadProperties();
1786
+ }
1787
+ } catch (error) {
1788
+ this.handleError(error, "initializeFromLocationData");
1789
+ }
1790
+ }
1791
+ async autoLoadProperties() {
1792
+ if (!this.ensureApiEnabled("autoLoadProperties")) {
1793
+ return;
1794
+ }
1795
+ if (!this.requestBody) return;
1796
+ const defaultRequestBody = {
1797
+ filters: this.getFilters(),
1798
+ initial: true,
1799
+ ...this.requestBody
1800
+ };
1801
+ await this.runPropertiesSearch({
1802
+ body: defaultRequestBody,
1803
+ onError: (error) => {
1804
+ var _a, _b;
1805
+ this.handleError(error, "autoLoadProperties");
1806
+ (_b = (_a = this.callbacks).onPropertiesLoadError) == null ? void 0 : _b.call(_a, error);
1807
+ }
1808
+ });
1809
+ }
1810
+ attachMap(mapInstance, config) {
1811
+ this.assertPlatformSupportForNoApi(config.platform, "throw");
1812
+ if (this.isMapAttached) {
1813
+ console.warn("Map is already attached. Destroying previous adapter.");
1814
+ if (this.adapter) {
1815
+ const markerManager = this.adapter.getMarkerManager();
1816
+ markerManager == null ? void 0 : markerManager.destroy();
1817
+ this.adapter.cleanup();
1818
+ }
1819
+ }
1820
+ const adapterConfig = {
1821
+ ...this.options,
1822
+ platform: config.platform,
1823
+ mapInstance,
1824
+ maplibregl: config.maplibregl,
1825
+ google: config.google,
1826
+ mapboxgl: config.mapboxgl,
1827
+ onMarkerClick: config.onMarkerClick
1828
+ };
1829
+ this.currentPlatform = config.platform;
1830
+ this.adapter = this.createAdapter(adapterConfig);
1831
+ this.isMapAttached = true;
1832
+ this.refresh();
1833
+ if (this.requestBody && !this.state.firstCallDone) {
1834
+ this.autoLoadProperties();
1835
+ }
1836
+ }
1837
+ createAdapter(options) {
1838
+ if (isMapLibreOptions(options) && options.mapInstance) {
1839
+ return this.initializeAdapter(new MapLibreAdapter(options.mapInstance), {
1840
+ maplibregl: options.maplibregl,
1841
+ onMarkerClick: options.onMarkerClick
1842
+ });
1843
+ }
1844
+ if (isGoogleMapsOptions(options) && options.mapInstance) {
1845
+ return this.initializeAdapter(
1846
+ new GoogleMapsAdapter(options.mapInstance),
1847
+ { google: options.google, onMarkerClick: options.onMarkerClick }
1848
+ );
1849
+ }
1850
+ if (isMapboxOptions(options) && options.mapInstance) {
1851
+ return this.initializeAdapter(new MapboxAdapter(options.mapInstance), {
1852
+ mapboxgl: options.mapboxgl,
1853
+ onMarkerClick: options.onMarkerClick
1854
+ });
1855
+ }
1856
+ if ("adapter" in options && options.adapter) {
1857
+ return options.adapter;
1858
+ }
1859
+ return null;
1860
+ }
1861
+ initializeAdapter(adapter, config) {
1862
+ adapter.initialize({
1863
+ ...config,
1864
+ onMarkerClick: (marker) => {
1865
+ var _a;
1866
+ if (marker.location) {
1867
+ this.flyMapTo(marker.location.lon, marker.location.lat, 14);
1868
+ }
1869
+ if (marker.type !== this.primaryType) {
1870
+ this.setPrimaryType(marker.type);
1871
+ }
1872
+ this.setSelectedMarker(
1873
+ marker.tripadvisor_id === this.selectedMarkerId ? null : marker.tripadvisor_id
1874
+ );
1875
+ (_a = config.onMarkerClick) == null ? void 0 : _a.call(config, marker);
1876
+ },
1877
+ onRefresh: () => this.refresh(),
1878
+ onMapMoveEnd: (bounds) => {
1879
+ if (this.state.tempBounds === null) {
1880
+ this.setTempBounds(bounds);
1881
+ this.setPendingBounds(null);
1882
+ } else {
1883
+ this.handleMapMoveEnd(bounds);
1884
+ }
1885
+ }
1886
+ });
1887
+ if (this.useApi) {
1888
+ adapter.setupImpressionTracking(() => {
1889
+ });
1890
+ }
1891
+ return adapter;
1892
+ }
1893
+ _setProperties(properties) {
1894
+ var _a, _b;
1895
+ this.ensureAlive();
1896
+ this.properties = [
1897
+ ...properties.filter(
1898
+ (x) => {
1899
+ var _a2, _b2, _c, _d, _e, _f;
1900
+ return !!x.location && (x.type !== "Accommodation" || ((_b2 = (_a2 = x.pricing) == null ? void 0 : _a2.offer) == null ? void 0 : _b2.availability) === "available" || ((_d = (_c = x.pricing) == null ? void 0 : _c.offer) == null ? void 0 : _d.availability) === "pending" || ((_f = (_e = x.pricing) == null ? void 0 : _e.offer) == null ? void 0 : _f.displayPrice));
1901
+ }
1902
+ )
1903
+ ];
1904
+ this.updateState({
1905
+ properties: this.properties
1906
+ });
1907
+ (_b = (_a = this.callbacks).onPropertiesChange) == null ? void 0 : _b.call(_a, properties);
1908
+ this.refresh();
1909
+ }
1910
+ addProperty(property) {
1911
+ var _a, _b;
1912
+ this.ensureAlive();
1913
+ this.properties = [...this.properties, property];
1914
+ this.updateState({ properties: this.properties });
1915
+ (_b = (_a = this.callbacks).onPropertiesChange) == null ? void 0 : _b.call(_a, this.properties);
1916
+ this.refresh();
1917
+ }
1918
+ clearProperties() {
1919
+ var _a, _b;
1920
+ this.ensureAlive();
1921
+ this.properties = [];
1922
+ this.updateState({ properties: [] });
1923
+ (_b = (_a = this.callbacks).onPropertiesChange) == null ? void 0 : _b.call(_a, []);
1924
+ this.refresh();
1925
+ }
1926
+ setPrimaryType(primary) {
1927
+ var _a, _b;
1928
+ this.ensureAlive();
1929
+ if (this.primaryType === primary) return;
1930
+ this.primaryType = primary;
1931
+ this.updateState({ primary });
1932
+ (_b = (_a = this.callbacks).onPrimaryTypeChange) == null ? void 0 : _b.call(_a, primary);
1933
+ this.refresh();
1934
+ }
1935
+ setSelectedMarker(markerId) {
1936
+ var _a, _b;
1937
+ this.ensureAlive();
1938
+ if (this.selectedMarkerId === markerId) return;
1939
+ if (markerId !== null) {
1940
+ const marker = this.properties.find((p) => p.tripadvisor_id === markerId);
1941
+ if (marker && marker.type !== this.primaryType) {
1942
+ this.setPrimaryType(marker.type);
1943
+ }
1944
+ }
1945
+ this.selectedMarkerId = markerId;
1946
+ this.updateState({ selectedPropertyId: markerId });
1947
+ (_b = (_a = this.callbacks).onSelectedPropertyChange) == null ? void 0 : _b.call(_a, markerId);
1948
+ this.refresh();
1949
+ }
1950
+ // State management methods
1951
+ getState() {
1952
+ return { ...this.state };
1953
+ }
1954
+ // Centralized error handler
1955
+ handleError(error, context = "MapFirstCore") {
1956
+ const errorMessage = error instanceof Error ? error.message : String(error);
1957
+ const errorObj = error instanceof Error ? error : new Error(errorMessage);
1958
+ console.error(`[${context}]`, errorMessage);
1959
+ if (this.callbacks.onError) {
1960
+ this.callbacks.onError(errorObj, context);
1961
+ }
1962
+ }
1963
+ updateState(update) {
1964
+ this.state = { ...this.state, ...update };
1965
+ }
1966
+ setState(newState) {
1967
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
1968
+ const prevState = { ...this.state };
1969
+ this.updateState(newState);
1970
+ if (newState.center !== void 0 && newState.center !== prevState.center) {
1971
+ (_b = (_a = this.callbacks).onCenterChange) == null ? void 0 : _b.call(_a, newState.center, this.state.zoom);
1972
+ }
1973
+ if (newState.zoom !== void 0 && newState.zoom !== prevState.zoom) {
1974
+ (_d = (_c = this.callbacks).onZoomChange) == null ? void 0 : _d.call(_c, newState.zoom);
1975
+ }
1976
+ if (newState.bounds !== void 0 && newState.bounds !== prevState.bounds) {
1977
+ (_f = (_e = this.callbacks).onBoundsChange) == null ? void 0 : _f.call(_e, newState.bounds);
1978
+ }
1979
+ if (newState.pendingBounds !== void 0 && newState.pendingBounds !== prevState.pendingBounds) {
1980
+ (_h = (_g = this.callbacks).onPendingBoundsChange) == null ? void 0 : _h.call(_g, newState.pendingBounds);
1981
+ }
1982
+ if (newState.filters !== void 0 && newState.filters !== prevState.filters) {
1983
+ (_j = (_i = this.callbacks).onFiltersChange) == null ? void 0 : _j.call(_i, newState.filters);
1984
+ }
1985
+ if (newState.activeLocation !== void 0 && newState.activeLocation !== prevState.activeLocation) {
1986
+ (_l = (_k = this.callbacks).onActiveLocationChange) == null ? void 0 : _l.call(_k, newState.activeLocation);
1987
+ }
1988
+ if (newState.initialLoading !== void 0 && newState.initialLoading !== prevState.initialLoading) {
1989
+ (_n = (_m = this.callbacks).onLoadingStateChange) == null ? void 0 : _n.call(_m, newState.initialLoading);
1990
+ }
1991
+ if (newState.isSearching !== void 0 && newState.isSearching !== prevState.isSearching) {
1992
+ (_p = (_o = this.callbacks).onSearchingStateChange) == null ? void 0 : _p.call(_o, newState.isSearching);
1993
+ }
1994
+ }
1995
+ setFilters(filters) {
1996
+ this.setState({ filters });
1997
+ }
1998
+ setActiveLocation(location) {
1999
+ this.setState({ activeLocation: location });
2000
+ }
2001
+ setBounds(bounds) {
2002
+ this.setState({ bounds });
2003
+ }
2004
+ setPendingBounds(bounds) {
2005
+ this.setState({ pendingBounds: bounds });
2006
+ }
2007
+ setTempBounds(bounds) {
2008
+ this.setState({ tempBounds: bounds });
2009
+ }
2010
+ setLoading(loading) {
2011
+ this.setState({ initialLoading: loading });
2012
+ }
2013
+ setSearching(searching) {
2014
+ this.setState({ isSearching: searching });
2015
+ }
2016
+ setFlyToAnimating(animating) {
2017
+ this.setState({ isFlyToAnimating: animating });
2018
+ }
2019
+ handleMapMoveEnd(bounds) {
2020
+ if (this.state.isFlyToAnimating) {
2021
+ this.setState({
2022
+ isFlyToAnimating: false,
2023
+ tempBounds: bounds,
2024
+ pendingBounds: null
2025
+ });
2026
+ return;
2027
+ }
2028
+ const tempBounds = this.state.tempBounds;
2029
+ if (!tempBounds) {
2030
+ this.setState({
2031
+ tempBounds: bounds,
2032
+ pendingBounds: bounds
2033
+ });
2034
+ return;
2035
+ }
2036
+ const delta = 0.01;
2037
+ const hasChanged = Math.abs(bounds.sw.lat - tempBounds.sw.lat) > delta || Math.abs(bounds.sw.lng - tempBounds.sw.lng) > delta || Math.abs(bounds.ne.lat - tempBounds.ne.lat) > delta || Math.abs(bounds.ne.lng - tempBounds.ne.lng) > delta;
2038
+ if (hasChanged) {
2039
+ this.setState({ pendingBounds: bounds });
2040
+ } else {
2041
+ this.setState({ pendingBounds: null });
2042
+ }
2043
+ }
2044
+ flyMapTo(longitude, latitude, zoom, animation = true) {
2045
+ this.ensureAlive();
2046
+ this.setState({ center: [latitude, longitude] });
2047
+ if (typeof zoom === "number") {
2048
+ this.setState({ zoom });
2049
+ }
2050
+ if (!this.adapter) return;
2051
+ const mapInstance = this.adapter.getMap();
2052
+ if (!mapInstance) return;
2053
+ if (this.currentPlatform === "google") {
2054
+ this.setFlyToAnimating(false);
2055
+ mapInstance.setCenter({ lat: latitude, lng: longitude });
2056
+ if (zoom !== null && typeof zoom === "number") {
2057
+ mapInstance.setZoom(zoom != null ? zoom : 13);
2058
+ }
2059
+ return;
2060
+ }
2061
+ if (animation === false) {
2062
+ this.setFlyToAnimating(false);
2063
+ if (mapInstance.jumpTo) {
2064
+ mapInstance.jumpTo({
2065
+ center: [longitude, latitude],
2066
+ ...zoom !== null && { zoom: zoom != null ? zoom : 13 }
2067
+ });
2068
+ }
2069
+ return;
2070
+ }
2071
+ this.setFlyToAnimating(true);
2072
+ if (mapInstance.flyTo) {
2073
+ mapInstance.flyTo({
2074
+ center: [longitude, latitude],
2075
+ ...zoom !== null && { zoom: zoom != null ? zoom : 13 }
2076
+ });
2077
+ }
2078
+ }
2079
+ extractPoiPoints(properties, type) {
2080
+ return properties.filter(
2081
+ (property) => property.location !== void 0 && (type !== void 0 ? property.type === type : true)
2082
+ ).map((property) => ({
2083
+ lat: property.location.lat,
2084
+ lng: property.location.lon
2085
+ }));
2086
+ }
2087
+ flyToPOIs(pois, type, animate = true) {
2088
+ var _a, _b;
2089
+ this.ensureAlive();
2090
+ if (!this.adapter) return;
2091
+ const mapInstance = this.adapter.getMap();
2092
+ if (!mapInstance) return;
2093
+ let points = pois;
2094
+ if (!points || points.length === 0) {
2095
+ points = this.extractPoiPoints(this.properties, type);
2096
+ }
2097
+ if (!points || points.length === 0) return;
2098
+ if (points.length === 1) {
2099
+ const poi = points[0];
2100
+ if (this.currentPlatform === "google") {
2101
+ mapInstance.setCenter({ lat: poi.lat, lng: poi.lng });
2102
+ mapInstance.setZoom(13);
2103
+ } else if (mapInstance.flyTo) {
2104
+ mapInstance.flyTo({
2105
+ center: [poi.lng, poi.lat],
2106
+ zoom: 13
2107
+ });
2108
+ }
2109
+ } else {
2110
+ if (this.currentPlatform === "google") {
2111
+ const LatLngBounds = (_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.LatLngBounds;
2112
+ if (LatLngBounds) {
2113
+ const bounds = new LatLngBounds();
2114
+ points.forEach((poi) => {
2115
+ bounds.extend({ lat: poi.lat, lng: poi.lng });
2116
+ });
2117
+ if (animate) {
2118
+ this.setFlyToAnimating(true);
2119
+ }
2120
+ mapInstance.fitBounds(bounds, this.fitBoundsPadding);
2121
+ }
2122
+ } else if (mapInstance.fitBounds) {
2123
+ const bounds = [
2124
+ [points[0].lng, points[0].lat],
2125
+ [points[0].lng, points[0].lat]
2126
+ ];
2127
+ points.forEach((poi) => {
2128
+ bounds[0][0] = Math.min(bounds[0][0], poi.lng);
2129
+ bounds[0][1] = Math.min(bounds[0][1], poi.lat);
2130
+ bounds[1][0] = Math.max(bounds[1][0], poi.lng);
2131
+ bounds[1][1] = Math.max(bounds[1][1], poi.lat);
2132
+ });
2133
+ if (animate) {
2134
+ this.setFlyToAnimating(true);
2135
+ }
2136
+ mapInstance.fitBounds(bounds, {
2137
+ padding: this.fitBoundsPadding,
2138
+ animate
2139
+ });
2140
+ }
2141
+ }
2142
+ }
2143
+ getFilters() {
2144
+ const filters = { ...this.state.filters };
2145
+ if (filters.checkIn instanceof Date) {
2146
+ filters.checkIn = toISO(filters.checkIn);
2147
+ }
2148
+ if (filters.checkOut instanceof Date) {
2149
+ filters.checkOut = toISO(filters.checkOut);
2150
+ }
2151
+ return filters;
2152
+ }
2153
+ async pollForPricing({
2154
+ pollingLink,
2155
+ maxAttempts = 15,
2156
+ delayMs = 2e3,
2157
+ isCancelled,
2158
+ price,
2159
+ limit
2160
+ }) {
2161
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2162
+ this.ensureAlive();
2163
+ if (!this.ensureApiEnabled("pollForPricing")) {
2164
+ return { completed: false };
2165
+ }
2166
+ if (!pollingLink) {
2167
+ return { completed: false };
2168
+ }
2169
+ let completed = false;
2170
+ let pollData = void 0;
2171
+ const filters = this.getFilters();
2172
+ if (limit) {
2173
+ filters.limit = limit;
2174
+ }
2175
+ const body = {
2176
+ filters,
2177
+ pollingLink
2178
+ };
2179
+ const referrer = getDocumentReferrer();
2180
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
2181
+ if (isCancelled == null ? void 0 : isCancelled()) {
2182
+ return { completed, pollData };
2183
+ }
2184
+ try {
2185
+ const pollResp = await fetch(
2186
+ `${this.apiUrl}/ta-polling?pollingNumber=${attempt}`,
2187
+ {
2188
+ method: "POST",
2189
+ body: JSON.stringify(body),
2190
+ headers: createSdkHeaders(this.apiKey, referrer)
2191
+ }
2192
+ );
2193
+ if (!pollResp.ok) {
2194
+ throw new PropertiesFetchError({
2195
+ message: `Poll failed: ${pollResp.status}`,
2196
+ status: pollResp.status
2197
+ });
2198
+ }
2199
+ pollData = await pollResp.json();
2200
+ if (isCancelled == null ? void 0 : isCancelled()) {
2201
+ return { completed, pollData };
2202
+ }
2203
+ const results = (_b = (_a = pollData == null ? void 0 : pollData.success) == null ? void 0 : _a.results) != null ? _b : [];
2204
+ const unsupportedIds = new Set(
2205
+ (_e = (_d = (_c = pollData == null ? void 0 : pollData.success) == null ? void 0 : _c.invalidHotelIds) == null ? void 0 : _d.map(Number)) != null ? _e : []
2206
+ );
2207
+ const unsupportedIds2 = new Set(
2208
+ (_h = (_g = (_f = pollData == null ? void 0 : pollData.success) == null ? void 0 : _f.unsupportedHotelIds) == null ? void 0 : _g.map(Number)) != null ? _h : []
2209
+ );
2210
+ if (results.length > 0 || unsupportedIds.size > 0) {
2211
+ this.setProperties((prev) => {
2212
+ var _a2;
2213
+ const updatedProperties = prev.filter(
2214
+ (property) => !unsupportedIds.has(property.tripadvisor_id) && !unsupportedIds2.has(property.tripadvisor_id)
2215
+ );
2216
+ results.forEach((property) => {
2217
+ var _a3, _b2, _c2, _d2, _e2, _f2;
2218
+ if (!property.location) return;
2219
+ if (((_b2 = (_a3 = property.pricing) == null ? void 0 : _a3.offer) == null ? void 0 : _b2.price) && price && (((_d2 = (_c2 = property.pricing) == null ? void 0 : _c2.offer) == null ? void 0 : _d2.price) < (price == null ? void 0 : price.min) || ((_f2 = (_e2 = property.pricing) == null ? void 0 : _e2.offer) == null ? void 0 : _f2.price) > (price == null ? void 0 : price.max))) {
2220
+ property.pricing.availability = "unavailable";
2221
+ }
2222
+ const existingIndex = updatedProperties.findIndex(
2223
+ (h) => h.tripadvisor_id === property.tripadvisor_id
2224
+ );
2225
+ if (existingIndex >= 0) {
2226
+ updatedProperties[existingIndex] = property;
2227
+ } else {
2228
+ updatedProperties.push(property);
2229
+ }
2230
+ });
2231
+ if ((_a2 = pollData == null ? void 0 : pollData.success) == null ? void 0 : _a2.isComplete) {
2232
+ return updatedProperties.filter(
2233
+ (property) => {
2234
+ var _a3, _b2, _c2, _d2, _e2, _f2;
2235
+ return property.type !== "Accommodation" || ((_b2 = (_a3 = property.pricing) == null ? void 0 : _a3.offer) == null ? void 0 : _b2.availability) === "available" || ((_d2 = (_c2 = property.pricing) == null ? void 0 : _c2.offer) == null ? void 0 : _d2.availability) === "pending" || ((_f2 = (_e2 = property.pricing) == null ? void 0 : _e2.offer) == null ? void 0 : _f2.displayPrice);
2236
+ }
2237
+ );
2238
+ }
2239
+ return updatedProperties;
2240
+ });
2241
+ }
2242
+ if ((_i = pollData == null ? void 0 : pollData.success) == null ? void 0 : _i.isComplete) {
2243
+ completed = true;
2244
+ this.setSearching(false);
2245
+ break;
2246
+ }
2247
+ } catch (error) {
2248
+ this.handleError(error, "pollForPricing");
2249
+ (_k = (_j = this.callbacks).onPropertiesLoadError) == null ? void 0 : _k.call(_j, error);
2250
+ break;
2251
+ }
2252
+ if (attempt < maxAttempts - 1) {
2253
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
2254
+ }
2255
+ }
2256
+ return { completed, pollData };
2257
+ }
2258
+ setProperties(updater) {
2259
+ const updatedProperties = updater(this.properties);
2260
+ this._setProperties(updatedProperties);
2261
+ }
2262
+ mostCommonTypeFromProperties(properties) {
2263
+ const typeCounts = properties.reduce(
2264
+ (counts, property) => {
2265
+ counts[property.type] = (counts[property.type] || 0) + 1;
2266
+ return counts;
2267
+ },
2268
+ {}
2269
+ );
2270
+ return Object.entries(typeCounts).reduce(
2271
+ (a, b) => typeCounts[a[0]] > typeCounts[b[0]] ? a : b
2272
+ )[0];
2273
+ }
2274
+ async runPropertiesSearch({
2275
+ body,
2276
+ beforeApplyProperties,
2277
+ smartFiltersClearable,
2278
+ onError
2279
+ }) {
2280
+ var _a, _b, _c, _d, _e, _f, _g;
2281
+ this.ensureAlive();
2282
+ if (!this.ensureApiEnabled("runPropertiesSearch", onError)) {
2283
+ return null;
2284
+ }
2285
+ this.setState({ firstCallDone: false });
2286
+ this.setSearching(true);
2287
+ this.clearProperties();
2288
+ try {
2289
+ const data = await fetchProperties(
2290
+ `${this.apiUrl}/properties`,
2291
+ body,
2292
+ this.apiKey
2293
+ );
2294
+ this.updateActiveLocationFromResponse(data);
2295
+ let price = null;
2296
+ let limit = 30;
2297
+ let primary_type = data.filters.primary_type;
2298
+ if (beforeApplyProperties) {
2299
+ const result = beforeApplyProperties(data);
2300
+ price = (_a = result.price) != null ? _a : null;
2301
+ limit = (_b = result.limit) != null ? _b : 30;
2302
+ }
2303
+ const flown = data.properties.some((x) => !!x.location);
2304
+ const primaryTypePoiPoints = this.extractPoiPoints(
2305
+ data.properties,
2306
+ data.filters.primary_type
2307
+ );
2308
+ const filteredProperties = price ? data.properties.map(
2309
+ (x) => {
2310
+ var _a2;
2311
+ return ((_a2 = x.pricing) == null ? void 0 : _a2.offer) ? {
2312
+ ...x,
2313
+ pricing: {
2314
+ ...x.pricing,
2315
+ availability: x.pricing.offer.price && (x.pricing.offer.price < price.min || x.pricing.offer.price > price.max) ? "unavailable" : x.pricing.availability
2316
+ }
2317
+ } : x;
2318
+ }
2319
+ ) : data.properties;
2320
+ this._setProperties(filteredProperties);
2321
+ if (flown) {
2322
+ this.flyToPOIs(primaryTypePoiPoints, void 0, body.initial !== true);
2323
+ }
2324
+ if (data.filters.primary_type && data.properties.filter(
2325
+ (property) => {
2326
+ var _a2, _b2, _c2, _d2, _e2, _f2;
2327
+ return property.type === data.filters.primary_type && (property.type !== "Accommodation" || ((_b2 = (_a2 = property.pricing) == null ? void 0 : _a2.offer) == null ? void 0 : _b2.availability) === "available" || ((_d2 = (_c2 = property.pricing) == null ? void 0 : _c2.offer) == null ? void 0 : _d2.availability) === "pending" || ((_f2 = (_e2 = property.pricing) == null ? void 0 : _e2.offer) == null ? void 0 : _f2.displayPrice));
2328
+ }
2329
+ ).length > 0) {
2330
+ primary_type = data.filters.primary_type;
2331
+ this.setPrimaryType(data.filters.primary_type);
2332
+ } else if (data.properties.length > 0) {
2333
+ const mostCommonType = this.mostCommonTypeFromProperties(
2334
+ data.properties
2335
+ );
2336
+ this.setPrimaryType(mostCommonType);
2337
+ primary_type = mostCommonType;
2338
+ }
2339
+ this.setState({ firstCallDone: true });
2340
+ if (data.isComplete === false && data.pollingLink) {
2341
+ const { completed, pollData } = await this.pollForPricing({
2342
+ pollingLink: data.pollingLink,
2343
+ ...price && { price },
2344
+ ...limit && { limit }
2345
+ });
2346
+ if (completed && ((_c = pollData == null ? void 0 : pollData.success) == null ? void 0 : _c.results) && pollData.success.results.filter(
2347
+ (property) => {
2348
+ var _a2;
2349
+ return property.type === data.filters.primary_type && (property.type === "Accommodation" ? ((_a2 = property.pricing) == null ? void 0 : _a2.availability) !== "unavailable" : true);
2350
+ }
2351
+ ).length === 0 && primary_type && primary_type !== data.filters.primary_type) {
2352
+ const mostCommonType = this.mostCommonTypeFromProperties(
2353
+ data.properties
2354
+ );
2355
+ this.setPrimaryType(mostCommonType);
2356
+ }
2357
+ if (completed) {
2358
+ this.refresh();
2359
+ }
2360
+ } else if (data.isComplete === true) {
2361
+ this.setSearching(false);
2362
+ }
2363
+ if (!flown) {
2364
+ if (((_d = data.filters.location) == null ? void 0 : _d.latitude) && ((_e = data.filters.location) == null ? void 0 : _e.longitude)) {
2365
+ this.flyMapTo(
2366
+ data.filters.location.longitude,
2367
+ data.filters.location.latitude,
2368
+ 12,
2369
+ body.initial !== true
2370
+ );
2371
+ }
2372
+ }
2373
+ return data;
2374
+ } catch (error) {
2375
+ this.handleError(error, "runPropertiesSearch");
2376
+ onError == null ? void 0 : onError(error);
2377
+ (_g = (_f = this.callbacks).onPropertiesLoadError) == null ? void 0 : _g.call(_f, error);
2378
+ this.clearProperties();
2379
+ this.setState({ firstCallDone: true });
2380
+ this.setSearching(false);
2381
+ return null;
2382
+ }
2383
+ }
2384
+ async performBoundsSearch() {
2385
+ var _a;
2386
+ this.ensureAlive();
2387
+ if (!this.ensureApiEnabled("performBoundsSearch")) {
2388
+ return null;
2389
+ }
2390
+ if (!this.state.pendingBounds) {
2391
+ return null;
2392
+ }
2393
+ const filters = this.getFilters();
2394
+ const body = {
2395
+ bounds: this.state.pendingBounds,
2396
+ filters
2397
+ };
2398
+ const priceFilter = (_a = filters == null ? void 0 : filters.price) != null ? _a : void 0;
2399
+ const result = await this.runPropertiesSearch({
2400
+ body,
2401
+ beforeApplyProperties: () => {
2402
+ return { price: priceFilter != null ? priceFilter : null };
2403
+ }
2404
+ });
2405
+ if (result) {
2406
+ this.setBounds(this.state.pendingBounds);
2407
+ this.setTempBounds(this.state.pendingBounds);
2408
+ this.setPendingBounds(null);
2409
+ }
2410
+ return result;
2411
+ }
2412
+ updateActiveLocationFromResponse(data) {
2413
+ var _a, _b, _c, _d;
2414
+ const newLocationId = (_a = data.location_id) != null ? _a : null;
2415
+ const newCity = (_c = (_b = data.filters.location) == null ? void 0 : _b.city) != null ? _c : void 0;
2416
+ const newCountry = ((_d = data.filters.location) == null ? void 0 : _d.country) || "";
2417
+ const newCoordinates = data.filters.location ? [data.filters.location.latitude, data.filters.location.longitude] : void 0;
2418
+ if (!newCoordinates) return;
2419
+ const currentLocation = this.state.activeLocation;
2420
+ if (newLocationId !== (currentLocation == null ? void 0 : currentLocation.location_id) || newCity !== (currentLocation == null ? void 0 : currentLocation.city) || newCountry !== (currentLocation == null ? void 0 : currentLocation.country)) {
2421
+ this.setActiveLocation({
2422
+ city: newCity,
2423
+ country: newCountry,
2424
+ location_id: newLocationId,
2425
+ locationName: newCity && newCountry ? `${newCity}, ${newCountry}` : newCountry || "",
2426
+ coordinates: newCoordinates
2427
+ });
2428
+ }
2429
+ }
2430
+ async runSmartFilterSearch({
2431
+ query,
2432
+ filters,
2433
+ onProcessFilters,
2434
+ onError
2435
+ }) {
2436
+ this.ensureAlive();
2437
+ if (!this.ensureApiEnabled("runSmartFilterSearch", onError)) {
2438
+ return null;
2439
+ }
2440
+ let filterPayload = this.getFilters();
2441
+ const state = this.getState();
2442
+ if (filters && filters.length > 0) {
2443
+ const amenities = /* @__PURE__ */ new Set();
2444
+ const hotelStyle = /* @__PURE__ */ new Set();
2445
+ let price;
2446
+ let minRating;
2447
+ let starRating;
2448
+ let primary_type;
2449
+ let transformed_query;
2450
+ let selected_restaurant_price_levels;
2451
+ filters.forEach((filter) => {
2452
+ var _a, _b, _c;
2453
+ switch (filter.type) {
2454
+ case "amenity":
2455
+ amenities.add(filter.value);
2456
+ break;
2457
+ case "hotelStyle":
2458
+ hotelStyle.add(filter.value);
2459
+ break;
2460
+ case "priceRange":
2461
+ if (filter.priceRange) {
2462
+ price = {
2463
+ min: filter.priceRange.min,
2464
+ max: (_a = filter.priceRange.max) != null ? _a : 0
2465
+ };
2466
+ }
2467
+ break;
2468
+ case "minRating":
2469
+ minRating = (_b = filter.numericValue) != null ? _b : Number(filter.value);
2470
+ break;
2471
+ case "starRating":
2472
+ starRating = (_c = filter.numericValue) != null ? _c : Number(filter.value);
2473
+ break;
2474
+ case "primary_type":
2475
+ primary_type = filter.propertyType;
2476
+ break;
2477
+ case "transformed_query":
2478
+ transformed_query = filter.value;
2479
+ break;
2480
+ case "selected_restaurant_price_levels":
2481
+ selected_restaurant_price_levels = filter.priceLevels;
2482
+ break;
2483
+ }
2484
+ });
2485
+ filterPayload = {
2486
+ ...filterPayload,
2487
+ ...amenities.size > 0 && { amenities: Array.from(amenities) },
2488
+ ...hotelStyle.size > 0 && { hotelStyle: Array.from(hotelStyle) },
2489
+ ...price && { price },
2490
+ ...minRating !== void 0 && { minRating },
2491
+ ...starRating !== void 0 && { starRating },
2492
+ ...primary_type && { primary_type },
2493
+ ...transformed_query && { transformed_query },
2494
+ ...selected_restaurant_price_levels && {
2495
+ selected_restaurant_price_levels
2496
+ }
2497
+ };
2498
+ } else if (!query) {
2499
+ filterPayload.minRating = 4;
2500
+ }
2501
+ const body = {
2502
+ filters: filterPayload,
2503
+ ...query && { query },
2504
+ ...state.bounds ? { bounds: state.bounds } : state.activeLocation.location_id ? { location_id: state.activeLocation.location_id } : state.activeLocation.coordinates ? {
2505
+ latitude: state.activeLocation.coordinates[0],
2506
+ longitude: state.activeLocation.coordinates[1]
2507
+ } : {}
2508
+ };
2509
+ return this.runPropertiesSearch({
2510
+ body,
2511
+ beforeApplyProperties: onProcessFilters ? (data) => {
2512
+ var _a, _b;
2513
+ const result = onProcessFilters(data.filters, data.location_id);
2514
+ return {
2515
+ price: (_a = result.price) != null ? _a : null,
2516
+ limit: (_b = result.limit) != null ? _b : 30
2517
+ };
2518
+ } : void 0,
2519
+ smartFiltersClearable: !!query,
2520
+ onError
2521
+ });
2522
+ }
2523
+ getClusters() {
2524
+ this.ensureAlive();
2525
+ return [...this.clusterItems];
2526
+ }
2527
+ setUseApi(useApi, autoLoad = true) {
2528
+ this.ensureAlive();
2529
+ this.useApi = useApi;
2530
+ if (!useApi) {
2531
+ this.assertPlatformSupportForNoApi(this.currentPlatform, "warn");
2532
+ }
2533
+ if (!useApi) {
2534
+ this.clearProperties();
2535
+ }
2536
+ if (useApi && autoLoad) {
2537
+ if (this.options.initialLocationData) {
2538
+ this.initializeFromLocationData(this.options.initialLocationData);
2539
+ } else if (this.requestBody && this.isMapAttached) {
2540
+ this.autoLoadProperties();
2541
+ }
2542
+ }
2543
+ }
2544
+ setApiKey(apiKey) {
2545
+ this.ensureAlive();
2546
+ const oldKey = this.apiKey;
2547
+ this.apiKey = apiKey;
2548
+ if (oldKey !== this.apiKey && this.isMapAttached) {
2549
+ this.refresh();
2550
+ if (this.useApi) {
2551
+ if (this.options.initialLocationData) {
2552
+ this.initializeFromLocationData(this.options.initialLocationData);
2553
+ } else if (this.requestBody) {
2554
+ this.autoLoadProperties();
2555
+ }
2556
+ }
2557
+ }
2558
+ }
2559
+ getApiKey() {
2560
+ return this.apiKey;
2561
+ }
2562
+ refresh() {
2563
+ var _a, _b, _c;
2564
+ this.ensureAlive();
2565
+ if (!this.adapter) return;
2566
+ const viewState = this.safeExtractViewState();
2567
+ const primaryType = this.resolvePrimaryType();
2568
+ this.clusterItems = clusterMarkers({
2569
+ primaryType,
2570
+ markers: this.properties,
2571
+ map: this.adapter,
2572
+ selectedMarkerId: this.selectedMarkerId,
2573
+ zoom: (_a = viewState == null ? void 0 : viewState.zoom) != null ? _a : 0
2574
+ });
2575
+ const markerManager = this.adapter.getMarkerManager();
2576
+ markerManager.render(this.clusterItems, primaryType, this.selectedMarkerId);
2577
+ (_c = (_b = this.options).onClusterUpdate) == null ? void 0 : _c.call(_b, this.clusterItems, viewState);
2578
+ }
2579
+ destroy() {
2580
+ if (this.destroyed) {
2581
+ return;
2582
+ }
2583
+ if (this.adapter) {
2584
+ const markerManager = this.adapter.getMarkerManager();
2585
+ markerManager.destroy();
2586
+ this.adapter.cleanup();
2587
+ }
2588
+ this.clusterItems = [];
2589
+ this.properties = [];
2590
+ this.destroyed = true;
2591
+ this.isMapAttached = false;
2592
+ }
2593
+ resolvePrimaryType() {
2594
+ var _a, _b, _c;
2595
+ return (_c = (_b = this.primaryType) != null ? _b : (_a = this.properties.find((marker) => marker.type)) == null ? void 0 : _a.type) != null ? _c : DEFAULT_PRIMARY_TYPE;
2596
+ }
2597
+ safeExtractViewState() {
2598
+ if (!this.adapter) return null;
2599
+ try {
2600
+ return extractViewState(this.adapter);
2601
+ } catch {
2602
+ return null;
2603
+ }
2604
+ }
2605
+ ensureAlive() {
2606
+ if (this.destroyed) {
2607
+ throw new Error("MapFirstCore instance has been destroyed");
2608
+ }
2609
+ }
2610
+ };
2611
+ function isMapLibreOptions(options) {
2612
+ return options.platform === "maplibre";
2613
+ }
2614
+ function isGoogleMapsOptions(options) {
2615
+ return options.platform === "google";
2616
+ }
2617
+ function isMapboxOptions(options) {
2618
+ return options.platform === "mapbox";
2619
+ }
2620
+ // Annotate the CommonJS export names for ESM import in node:
2621
+ 0 && (module.exports = {
2622
+ MapFirstCore,
2623
+ PropertiesFetchError,
2624
+ convertToApiFilters,
2625
+ fetchImages,
2626
+ fetchProperties,
2627
+ processApiFilters
2628
+ });