@mapfirst.ai/react 0.0.36 → 0.0.38

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,6 +1,1590 @@
1
- "use strict";var xe=Object.create;var q=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,Fe=Object.prototype.hasOwnProperty;var Re=(e,t)=>{for(var a in t)q(e,a,{get:t[a],enumerable:!0})},pe=(e,t,a,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Se(t))!Fe.call(e,s)&&s!==a&&q(e,s,{get:()=>t[s],enumerable:!(i=ve(t,s))||i.enumerable});return e};var re=(e,t,a)=>(a=e!=null?xe(ke(e)):{},pe(t||!e||!e.__esModule?q(a,"default",{value:e,enumerable:!0}):a,e)),Pe=e=>pe(q({},"__esModule",{value:!0}),e);var Ue={};Re(Ue,{Chip:()=>$,CloseIcon:()=>oe,EditIcon:()=>W,FilterChips:()=>J,MinRatingFilterChip:()=>V,NextIcon:()=>K,PriceRangeFilterChip:()=>Y,RestaurantPriceLevelChip:()=>Z,SearchIcon:()=>ne,SmartFilter:()=>be,StarIcon:()=>ie,TransformedQueryChip:()=>j,convertToApiFilters:()=>te.convertToApiFilters,createMinRatingFilterLabel:()=>Te,createPriceRangeFilterLabel:()=>Be,formatRatingValue:()=>U,processApiFilters:()=>te.processApiFilters,renderStars:()=>de,useFilterScroll:()=>X,useMapFirst:()=>$e,useTranslation:()=>I});module.exports=Pe(Ue);var P=re(require("react")),Ce=require("@mapfirst.ai/core"),te=require("@mapfirst.ai/core");var ee=require("react");var le=re(require("react"));var ue=re(require("react"));var M=require("react/jsx-runtime"),ne=({className:e,style:t})=>(0,M.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:e,style:{width:"1em",height:"1em",...t},children:[(0,M.jsx)("circle",{cx:"11",cy:"11",r:"8"}),(0,M.jsx)("path",{d:"m21 21-4.35-4.35"})]}),oe=({className:e,style:t})=>(0,M.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:e,style:{width:"1em",height:"1em",...t},children:[(0,M.jsx)("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),(0,M.jsx)("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}),W=({className:e,style:t})=>(0,M.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:e,style:{width:"1em",height:"1em",...t},children:[(0,M.jsx)("path",{d:"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}),(0,M.jsx)("path",{d:"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"})]}),K=({className:e,style:t})=>(0,M.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:e,style:{width:"1em",height:"1em",...t},children:(0,M.jsx)("polyline",{points:"9 18 15 12 9 6"})}),ie=({className:e,style:t,fill:a="none"})=>(0,M.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:a,stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:e,style:{width:"1em",height:"1em",...t},children:(0,M.jsx)("polygon",{points:"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"})});var ae=require("react/jsx-runtime"),Le={position:"absolute",top:"-8px",right:"-8px",padding:"2px",borderRadius:"50%",backgroundColor:"white",border:"1px solid #03852e",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s"},we={width:"17px",height:"17px"},B=({onClick:e,style:t})=>{let[a,i]=ue.default.useState(!1);return(0,ae.jsx)("button",{style:{...Le,backgroundColor:a?"#e5e5e5":"white",...t},onClick:e,onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),"aria-label":"Remove filter",children:(0,ae.jsx)(oe,{style:we})})};var O=require("react/jsx-runtime"),Me={position:"relative",backgroundColor:"white",color:"black",fontSize:"14px",borderRadius:"9999px",padding:"0 16px",paddingRight:"20px",border:"1px solid #03852e",display:"flex",alignItems:"center",gap:"8px",flexShrink:0,height:"34px"},$=({label:e,icon:t,remove:a,style:i})=>(0,O.jsxs)("div",{style:{...Me,...i},children:[t&&(0,O.jsx)("span",{style:{display:"flex",alignItems:"center"},children:t}),(0,O.jsx)("span",{style:{whiteSpace:"nowrap"},children:e}),(0,O.jsx)(B,{onClick:a})]});var me=require("react");var Q=require("react"),Ee={"smartFilter.typingPrompt":"Search for hotels, restaurants, or attractions...","smartFilter.nav.previous":"Previous filters","smartFilter.nav.next":"Next filters","smartFilter.toast.locationRequired":"Please select a location first","smartFilter.clearAll":"Clear all","smartFilter.minRating.suffix":"+","smartFilter.minRating.label":"{{value}}+","smartFilter.minRating.remove":"Remove rating filter","smartFilter.minRating.setTo":"Set rating to {{rating}}","smartFilter.priceRange.label":"Price Range","smartFilter.priceRange.remove":"Remove price filter","smartFilter.priceRange.edit":"Edit price","smartFilter.transformedQuery.remove":"Remove search query","smartFilter.transformedQuery.edit":"Edit search query","smartFilter.restaurantPriceLevel.label":"Price Level","smartFilter.restaurantPriceLevel.remove":"Remove price level filter","smartFilter.restaurantPriceLevel.none":"Any","smartFilter.restaurantPriceLevel.options.cheapEats":"Cheap Eats","smartFilter.restaurantPriceLevel.options.midRange":"Mid Range","smartFilter.restaurantPriceLevel.options.fineDining":"Fine Dining"},Ie=(e,t="USD")=>new Intl.NumberFormat("en-US",{style:"currency",currency:t,minimumFractionDigits:0,maximumFractionDigits:0}).format(e),I=(e,t)=>{let[a,i]=(0,Q.useState)("en"),s=(0,Q.useCallback)((h,c)=>{let m={...Ee,...e}[h]||h;return c&&Object.keys(c).forEach(g=>{m=m.replace(new RegExp(`{{${g}}}`,"g"),String(c[g]))}),m},[e]),y=(0,Q.useCallback)((h,c)=>t?t(h,c):Ie(h,c),[t]);return{t:s,locale:a,setLocale:i,formatCurrency:y}};var z=require("react/jsx-runtime"),de=e=>{let t=[],a=Math.floor(e),i=e%1!==0,s={display:"block",width:"12px",height:"12px",borderRadius:"50%",border:"1px solid #03852e",pointerEvents:"none"},y={...s,backgroundColor:"#03852e"},h={...s,background:"linear-gradient(90deg, #03852e 50%, transparent 50%)"};for(let l=0;l<a;l+=1)t.push((0,z.jsx)("span",{style:y},`full-${l}`));i&&t.push((0,z.jsx)("span",{style:h},"half"));let c=Math.max(0,5-Math.ceil(e));for(let l=0;l<c;l+=1)t.push((0,z.jsx)("span",{style:s},`empty-${l}`));return t},Te=(e,t)=>(0,z.jsxs)("span",{style:{display:"flex",alignItems:"center",gap:"4px"},children:[(0,z.jsx)("span",{style:{display:"flex",gap:"1px",userSelect:"none"},children:de(e)})," ",t]}),U=e=>e.toFixed(1),Be=(e,t,a,i)=>`${i(e,a)} - ${i(t!=null?t:0,a)}`;var E=require("react/jsx-runtime"),Ne={position:"relative",backgroundColor:"white",color:"black",fontSize:"14px",borderRadius:"9999px",padding:"0 16px",paddingRight:"20px",border:"1px solid #03852e",display:"flex",gap:"8px",alignItems:"center",justifyContent:"center",flexShrink:0,height:"34px"},Ae={display:"flex",gap:"1px",userSelect:"none"},se={display:"block",width:"12px",height:"12px",borderRadius:"50%",border:"1px solid #03852e",pointerEvents:"none"},G={position:"absolute",top:0,height:"100%",cursor:"pointer",backgroundColor:"transparent",border:"none",padding:0},V=({rating:e,onChange:t,onRemove:a,star:i=!1})=>{let[s,y]=(0,me.useState)(null),{t:h}=I(),c=s!=null?s:e,l=b=>i&&b?b.toString():h("smartFilter.minRating.label",{value:U(b)}),m=h("smartFilter.minRating.remove"),g=b=>h("smartFilter.minRating.setTo",{rating:U(b)}),x=b=>{let C=b+1;return c>=C?"full":c>=C-.5?"half":"empty"},f=b=>{y(null),b!==e&&t(b)},k=b=>{var v;let C=b.relatedTarget;(!C||!((v=b.currentTarget.closest("[data-min-rating-chip]"))!=null&&v.contains(C)))&&y(null)};return(0,E.jsxs)("div",{style:Ne,"data-min-rating-chip":!0,children:[(0,E.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"4px"},onMouseLeave:()=>y(null),children:[(0,E.jsx)("div",{style:Ae,children:Array.from({length:5}).map((b,C)=>{let v=x(C),p=C+1,n=p-.5;if(i)return(0,E.jsxs)("div",{style:{position:"relative",width:"16px",height:"16px"},children:[(0,E.jsx)(ie,{fill:c>=p?"#03852e":"none",style:{width:"16px",height:"16px",pointerEvents:"none"}}),(0,E.jsx)("button",{type:"button",style:{...G,left:0,width:"50%",borderRadius:"50% 0 0 50%"},onMouseEnter:()=>y(n),onFocus:()=>y(n),onBlur:k,onClick:()=>f(n),"aria-label":g(n),title:l(n)}),(0,E.jsx)("button",{type:"button",style:{...G,left:"50%",width:"50%",borderRadius:"0 50% 50% 0"},onMouseEnter:()=>y(p),onFocus:()=>y(p),onBlur:k,onClick:()=>f(p),"aria-label":g(p),title:l(p)})]},C);let S=v==="full"?{...se,backgroundColor:"#03852e"}:se,u={...se,background:"linear-gradient(90deg, #03852e 50%, transparent 50%)"};return(0,E.jsxs)("div",{style:{position:"relative",width:"12px",height:"12px"},children:[(0,E.jsx)("span",{style:v==="half"?u:S}),(0,E.jsx)("button",{type:"button",style:{...G,left:0,width:"50%",borderRadius:"50% 0 0 50%",outline:"2px solid transparent",outlineOffset:"1px"},onMouseEnter:()=>y(n),onFocus:()=>y(n),onBlur:k,onClick:()=>f(n),"aria-label":g(n),title:l(n)}),(0,E.jsx)("button",{type:"button",style:{...G,left:"50%",width:"50%",borderRadius:"0 50% 50% 0",outline:"2px solid transparent",outlineOffset:"1px"},onMouseEnter:()=>y(p),onFocus:()=>y(p),onBlur:k,onClick:()=>f(p),"aria-label":g(p),title:l(p)})]},C)})}),(0,E.jsx)("span",{style:{whiteSpace:"nowrap"},children:l(c)})]}),(0,E.jsx)(B,{onClick:a})]})};var _=require("react");var L=require("react/jsx-runtime"),De={position:"relative",backgroundColor:"white",color:"black",fontSize:"14px",borderRadius:"9999px",padding:"0 16px",border:"1px solid #03852e",display:"flex",alignItems:"center",gap:"8px",flexShrink:0,height:"34px"},He={outline:"none",fontSize:"16px",backgroundColor:"transparent",borderRadius:"2px",padding:"2px 8px",width:"64px",textAlign:"center",border:"none"},ze={padding:"4px",borderRadius:"50%",cursor:"pointer",transition:"background-color 0.2s",border:"none",backgroundColor:"transparent",color:"#737373",display:"flex",alignItems:"center",justifyContent:"center"},ge=({boundary:e,label:t,value:a,placeholder:i,currency:s,isOptional:y=!1,showRemoveButton:h=!1,removeLabel:c,editLabel:l,showAddWhenEmpty:m=!1,onCommit:g,onRemove:x})=>{let[f,k]=(0,_.useState)(a!==void 0?String(a):""),[b,C]=(0,_.useState)(!1),[v,p]=(0,_.useState)(!1),n=a!==void 0;(0,_.useEffect)(()=>{k(a!==void 0?String(a):""),C(!1)},[a]);let S=()=>{k(a!==void 0?String(a):"")},u=()=>{if(f.trim()===""){if(y){g(void 0),k("");return}S();return}let r=Number(f);if(!Number.isFinite(r)){S();return}let F=Math.max(0,r);if(F===a){S();return}g(F)};return(0,L.jsxs)("div",{style:De,children:[(0,L.jsx)("span",{style:{fontSize:"10px",textTransform:"uppercase",fontWeight:600,letterSpacing:"0.05em"},children:t}),b?(0,L.jsx)("input",{value:f,onChange:r=>{let F=r.target.value.replace(/[^\d]/g,"");k(F)},onBlur:()=>{u(),C(!1)},onKeyDown:r=>{if(r.key==="Enter"){r.preventDefault(),r.currentTarget.blur(),C(!1);return}if(r.key==="Escape"){r.preventDefault(),S(),r.currentTarget.blur(),C(!1);return}r.key.length===1&&/[0-9]/.test(r.key)||r.key==="Backspace"||r.key==="Delete"||r.key==="Tab"||r.key==="ArrowLeft"||r.key==="ArrowRight"||r.key==="Home"||r.key==="End"||r.preventDefault()},placeholder:i,inputMode:"numeric",pattern:"[0-9]*","aria-label":t,style:He,autoFocus:!0}):n?(0,L.jsxs)("span",{style:{fontSize:"16px"},children:[s,a]}):m?(0,L.jsx)("button",{type:"button",style:{fontSize:"16px",color:"#737373",cursor:"pointer",border:"none",backgroundColor:"transparent",padding:0},onClick:()=>C(!0),"aria-label":l,children:"+"}):(0,L.jsx)("span",{style:{fontSize:"16px",color:"#737373"},children:"-"}),(!m||m&&b)&&(0,L.jsx)("span",{style:{color:"#737373",fontSize:"12px"},children:s}),!b&&(!m||n)&&(0,L.jsx)("button",{type:"button",style:{...ze,backgroundColor:v?"#e5e5e5":"transparent"},"aria-label":l,title:l,onClick:()=>C(!0),onMouseEnter:()=>p(!0),onMouseLeave:()=>p(!1),children:(0,L.jsx)(W,{})}),h&&(0,L.jsx)(B,{onClick:x})]})},Y=({priceRange:e,currency:t,onChange:a,onRemove:i})=>{let{t:s}=I(),y="Min",h="Max",c=s("smartFilter.priceRange.remove"),l=s("smartFilter.priceRange.edit"),m=(g,x)=>{let f={min:e.min,max:e.max};g==="min"?(f.min=x,x!==void 0&&e.max!==void 0&&x>e.max&&(f.max=x)):(f.max=x,x!==void 0&&e.min!==void 0&&x<e.min&&(f.min=x)),(f.min!==e.min||f.max!==e.max)&&a(f)};return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(ge,{boundary:"min",label:y,value:e.min,currency:t,editLabel:l,showRemoveButton:e.min!==void 0&&e.min!==0,onCommit:g=>m("min",g),onRemove:i}),(0,L.jsx)(ge,{boundary:"max",label:h,value:e.max,currency:t,isOptional:!0,showRemoveButton:e.max!==void 0,removeLabel:c,editLabel:l,showAddWhenEmpty:!0,onCommit:g=>m("max",g),onRemove:i})]})};var T=require("react/jsx-runtime"),Oe={position:"relative",backgroundColor:"white",color:"black",fontSize:"14px",borderRadius:"9999px",padding:"0 16px",paddingRight:"20px",border:"1px solid #03852e",display:"flex",alignItems:"center",gap:"16px",flexShrink:0,height:"34px"},ye=[{value:"Cheap Eats",key:"cheapEats"},{value:"Mid Range",key:"midRange"},{value:"Fine Dining",key:"fineDining"}],Z=({values:e,onChange:t,onRemove:a})=>{let{t:i}=I(),s=i("smartFilter.restaurantPriceLevel.label"),y=i("smartFilter.restaurantPriceLevel.remove"),h=i("smartFilter.restaurantPriceLevel.none"),c=l=>{let{value:m,checked:g}=l.target,x=m,f=new Set(e);g?f.add(x):f.delete(x);let k=ye.filter(b=>f.has(b.value)).map(b=>b.value);t(k)};return(0,T.jsxs)("div",{style:Oe,children:[(0,T.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"8px",flexWrap:"wrap"},children:[(0,T.jsx)("span",{style:{fontSize:"10px",textTransform:"uppercase",fontWeight:600,letterSpacing:"0.05em"},children:s}),(0,T.jsxs)("div",{style:{display:"flex",gap:"12px"},children:[ye.map(l=>{let m=i(`smartFilter.restaurantPriceLevel.options.${l.key}`),g=`price-level-${l.key}`;return(0,T.jsxs)("label",{htmlFor:g,style:{display:"flex",alignItems:"center",gap:"4px",fontSize:"12px",cursor:"pointer"},children:[(0,T.jsx)("input",{id:g,type:"checkbox",value:l.value,checked:e.includes(l.value),onChange:c,style:{accentColor:"#03852e",cursor:"pointer"}}),(0,T.jsx)("span",{children:m})]},l.value)}),e.length===0&&(0,T.jsx)("span",{style:{fontSize:"12px",color:"#737373"},children:h})]})]}),(0,T.jsx)(B,{onClick:a})]})};var D=require("react");var A=require("react/jsx-runtime"),_e={position:"relative",backgroundColor:"white",color:"black",fontSize:"14px",borderRadius:"9999px",padding:"0 16px",paddingRight:"20px",border:"1px solid #03852e",display:"flex",alignItems:"center",gap:"8px",flexShrink:0,userSelect:"none",height:"34px"},We={backgroundColor:"#ececec",borderRadius:"2px",padding:"2px 8px",outline:"none",fontSize:"16px",minWidth:"8ch",border:"none"},Qe={padding:"4px",borderRadius:"50%",cursor:"pointer",transition:"background-color 0.2s",color:"#737373",border:"none",backgroundColor:"transparent",display:"flex",alignItems:"center",justifyContent:"center"},j=({value:e,onChange:t,onRemove:a})=>{let i=(0,D.useRef)(null),[s,y]=(0,D.useState)(e),[h,c]=(0,D.useState)(!1),[l,m]=(0,D.useState)(!1),{t:g}=I(),x=g("smartFilter.transformedQuery.remove"),f=g("smartFilter.transformedQuery.edit");(0,D.useEffect)(()=>{y(e),c(!1)},[e]);let k=()=>{let v=s.trim();if(!v.length){y(e);return}v!==e&&t(v)};return(0,A.jsxs)("div",{style:_e,children:[(0,A.jsx)(ne,{style:{width:"16px",height:"16px",color:"#03852e"}}),h?(0,A.jsx)("input",{ref:i,value:s,onChange:v=>{y(v.target.value)},onBlur:()=>{k(),c(!1)},onKeyDown:v=>{if(v.key==="Enter"){v.preventDefault(),v.currentTarget.blur();return}if(v.key==="Escape"){v.preventDefault(),y(e),v.currentTarget.blur();return}},"aria-label":f,style:We,autoFocus:!0}):(0,A.jsx)("span",{style:{fontSize:"16px"},children:e}),!h&&(0,A.jsx)("button",{type:"button",style:{...Qe,backgroundColor:l?"#e5e5e5":"transparent"},"aria-label":f,title:f,onClick:()=>c(!0),onMouseEnter:()=>m(!0),onMouseLeave:()=>m(!1),children:(0,A.jsx)(W,{})}),(0,A.jsx)(B,{onClick:a})]})};var N=require("react"),X=e=>{let t=(0,N.useRef)(null),[a,i]=(0,N.useState)(!0),[s,y]=(0,N.useState)(!0),h=(0,N.useCallback)(()=>{let l=t.current;if(!l){i(!0),y(!0);return}let{scrollLeft:m,scrollWidth:g,clientWidth:x}=l;i(m<=0),y(m+x>=g-1)},[]);(0,N.useEffect)(()=>{let l=t.current;if(h(),!l)return;let m=()=>h();return l.addEventListener("scroll",m,{passive:!0}),window.addEventListener("resize",h),()=>{l.removeEventListener("scroll",m),window.removeEventListener("resize",h)}},[e,h]);let c=(0,N.useCallback)(l=>{let m=t.current;if(!m)return;let g=m.clientWidth*.7;m.scrollBy({left:l==="next"?g:-g,behavior:"smooth"})},[]);return{scrollerRef:t,atStart:a,atEnd:s,scrollByDir:c}};var R=require("react/jsx-runtime"),Ve={position:"relative",width:"100%"},qe={display:"flex",gap:"8px",overflowX:"auto",alignItems:"center",width:"100%",scrollbarWidth:"none",msOverflowStyle:"none"},fe={pointerEvents:"none",position:"absolute",top:0,bottom:0,width:"40px"},he={position:"absolute",top:"50%",transform:"translateY(-50%)",backgroundColor:"white",color:"#003c30",border:"1px solid #003c30",padding:"4px",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 1px 3px rgba(0,0,0,0.1)",cursor:"pointer"},J=({filters:e,currency:t,minRatingSuffix:a,clearAllLabel:i,previousFiltersLabel:s,nextFiltersLabel:y,formatCurrency:h,onFilterChange:c,onResetFilters:l,onClearAll:m})=>{let{scrollerRef:g,atStart:x,atEnd:f,scrollByDir:k}=X(e.length),[b,C]=le.default.useState(null),[v,p]=le.default.useState(!1);return(0,R.jsxs)("div",{style:Ve,children:[(0,R.jsxs)("div",{ref:g,style:{...qe,padding:"8px",WebkitOverflowScrolling:"touch"},children:[(0,R.jsx)("style",{children:`
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.tsx
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Chip: () => Chip,
34
+ CloseIcon: () => CloseIcon,
35
+ EditIcon: () => EditIcon,
36
+ FilterChips: () => FilterChips,
37
+ MapFirstCore: () => import_core2.MapFirstCore,
38
+ MinRatingFilterChip: () => MinRatingFilterChip,
39
+ NextIcon: () => NextIcon,
40
+ PriceRangeFilterChip: () => PriceRangeFilterChip,
41
+ PropertiesFetchError: () => import_core2.PropertiesFetchError,
42
+ RestaurantPriceLevelChip: () => RestaurantPriceLevelChip,
43
+ SearchIcon: () => SearchIcon,
44
+ SmartFilter: () => SmartFilter,
45
+ StarIcon: () => StarIcon,
46
+ TransformedQueryChip: () => TransformedQueryChip,
47
+ convertToApiFilters: () => import_core2.convertToApiFilters,
48
+ createMinRatingFilterLabel: () => createMinRatingFilterLabel,
49
+ createPriceRangeFilterLabel: () => createPriceRangeFilterLabel,
50
+ fetchImages: () => import_core2.fetchImages,
51
+ fetchProperties: () => import_core2.fetchProperties,
52
+ formatRatingValue: () => formatRatingValue,
53
+ processApiFilters: () => import_core2.processApiFilters,
54
+ renderStars: () => renderStars,
55
+ useFilterScroll: () => useFilterScroll,
56
+ useMapFirst: () => useMapFirst,
57
+ useTranslation: () => useTranslation
58
+ });
59
+ module.exports = __toCommonJS(index_exports);
60
+ var import_react9 = __toESM(require("react"));
61
+ var import_core = require("@mapfirst.ai/core");
62
+ var import_core2 = require("@mapfirst.ai/core");
63
+
64
+ // src/components/SmartFilter.tsx
65
+ var import_react8 = require("react");
66
+
67
+ // src/components/smart-filter/FilterChips.tsx
68
+ var import_react7 = __toESM(require("react"));
69
+
70
+ // src/components/smart-filter/CloseButton.tsx
71
+ var import_react = __toESM(require("react"));
72
+
73
+ // src/components/Icons.tsx
74
+ var import_jsx_runtime = require("react/jsx-runtime");
75
+ var SearchIcon = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
76
+ "svg",
77
+ {
78
+ xmlns: "http://www.w3.org/2000/svg",
79
+ viewBox: "0 0 24 24",
80
+ fill: "none",
81
+ stroke: "currentColor",
82
+ strokeWidth: "2",
83
+ strokeLinecap: "round",
84
+ strokeLinejoin: "round",
85
+ className,
86
+ style: { width: "1em", height: "1em", ...style },
87
+ children: [
88
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "11", cy: "11", r: "8" }),
89
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21 21-4.35-4.35" })
90
+ ]
91
+ }
92
+ );
93
+ var CloseIcon = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
94
+ "svg",
95
+ {
96
+ xmlns: "http://www.w3.org/2000/svg",
97
+ viewBox: "0 0 24 24",
98
+ fill: "none",
99
+ stroke: "currentColor",
100
+ strokeWidth: "2",
101
+ strokeLinecap: "round",
102
+ strokeLinejoin: "round",
103
+ className,
104
+ style: { width: "1em", height: "1em", ...style },
105
+ children: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
108
+ ]
109
+ }
110
+ );
111
+ var EditIcon = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
112
+ "svg",
113
+ {
114
+ xmlns: "http://www.w3.org/2000/svg",
115
+ viewBox: "0 0 24 24",
116
+ fill: "none",
117
+ stroke: "currentColor",
118
+ strokeWidth: "2",
119
+ strokeLinecap: "round",
120
+ strokeLinejoin: "round",
121
+ className,
122
+ style: { width: "1em", height: "1em", ...style },
123
+ children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
126
+ ]
127
+ }
128
+ );
129
+ var NextIcon = ({ className, style }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
130
+ "svg",
131
+ {
132
+ xmlns: "http://www.w3.org/2000/svg",
133
+ viewBox: "0 0 24 24",
134
+ fill: "none",
135
+ stroke: "currentColor",
136
+ strokeWidth: "2",
137
+ strokeLinecap: "round",
138
+ strokeLinejoin: "round",
139
+ className,
140
+ style: { width: "1em", height: "1em", ...style },
141
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "9 18 15 12 9 6" })
142
+ }
143
+ );
144
+ var StarIcon = ({
145
+ className,
146
+ style,
147
+ fill = "none"
148
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
149
+ "svg",
150
+ {
151
+ xmlns: "http://www.w3.org/2000/svg",
152
+ viewBox: "0 0 24 24",
153
+ fill,
154
+ stroke: "currentColor",
155
+ strokeWidth: "2",
156
+ strokeLinecap: "round",
157
+ strokeLinejoin: "round",
158
+ className,
159
+ style: { width: "1em", height: "1em", ...style },
160
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })
161
+ }
162
+ );
163
+
164
+ // src/components/smart-filter/CloseButton.tsx
165
+ var import_jsx_runtime2 = require("react/jsx-runtime");
166
+ var closeButtonStyles = {
167
+ position: "absolute",
168
+ top: "-8px",
169
+ right: "-8px",
170
+ padding: "2px",
171
+ borderRadius: "50%",
172
+ backgroundColor: "white",
173
+ border: "1px solid #03852e",
174
+ cursor: "pointer",
175
+ display: "flex",
176
+ alignItems: "center",
177
+ justifyContent: "center",
178
+ transition: "background-color 0.2s"
179
+ };
180
+ var iconStyles = {
181
+ width: "17px",
182
+ height: "17px"
183
+ };
184
+ var CloseButton = ({ onClick, style }) => {
185
+ const [isHovering, setIsHovering] = import_react.default.useState(false);
186
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
187
+ "button",
188
+ {
189
+ style: {
190
+ ...closeButtonStyles,
191
+ backgroundColor: isHovering ? "#e5e5e5" : "white",
192
+ ...style
193
+ },
194
+ onClick,
195
+ onMouseEnter: () => setIsHovering(true),
196
+ onMouseLeave: () => setIsHovering(false),
197
+ "aria-label": "Remove filter",
198
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, { style: iconStyles })
199
+ }
200
+ );
201
+ };
202
+
203
+ // src/components/smart-filter/Chip.tsx
204
+ var import_jsx_runtime3 = require("react/jsx-runtime");
205
+ var chipStyles = {
206
+ position: "relative",
207
+ backgroundColor: "white",
208
+ color: "black",
209
+ fontSize: "14px",
210
+ borderRadius: "9999px",
211
+ padding: "0 16px",
212
+ paddingRight: "20px",
213
+ border: "1px solid #03852e",
214
+ display: "flex",
215
+ alignItems: "center",
216
+ gap: "8px",
217
+ flexShrink: 0,
218
+ height: "34px"
219
+ };
220
+ var Chip = ({ label, icon, remove, style }) => {
221
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...chipStyles, ...style }, children: [
222
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { display: "flex", alignItems: "center" }, children: icon }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { whiteSpace: "nowrap" }, children: label }),
224
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseButton, { onClick: remove })
225
+ ] });
226
+ };
227
+
228
+ // src/components/smart-filter/MinRatingFilterChip.tsx
229
+ var import_react3 = require("react");
230
+
231
+ // src/hooks/useTranslation.ts
232
+ var import_react2 = require("react");
233
+ var defaultTranslations = {
234
+ "smartFilter.typingPrompt": "Search for hotels, restaurants, or attractions...",
235
+ "smartFilter.nav.previous": "Previous filters",
236
+ "smartFilter.nav.next": "Next filters",
237
+ "smartFilter.toast.locationRequired": "Please select a location first",
238
+ "smartFilter.clearAll": "Clear all",
239
+ "smartFilter.minRating.suffix": "+",
240
+ "smartFilter.minRating.label": "{{value}}+",
241
+ "smartFilter.minRating.remove": "Remove rating filter",
242
+ "smartFilter.minRating.setTo": "Set rating to {{rating}}",
243
+ "smartFilter.priceRange.label": "Price Range",
244
+ "smartFilter.priceRange.remove": "Remove price filter",
245
+ "smartFilter.priceRange.edit": "Edit price",
246
+ "smartFilter.transformedQuery.remove": "Remove search query",
247
+ "smartFilter.transformedQuery.edit": "Edit search query",
248
+ "smartFilter.restaurantPriceLevel.label": "Price Level",
249
+ "smartFilter.restaurantPriceLevel.remove": "Remove price level filter",
250
+ "smartFilter.restaurantPriceLevel.none": "Any",
251
+ "smartFilter.restaurantPriceLevel.options.cheapEats": "Cheap Eats",
252
+ "smartFilter.restaurantPriceLevel.options.midRange": "Mid Range",
253
+ "smartFilter.restaurantPriceLevel.options.fineDining": "Fine Dining"
254
+ };
255
+ var formatCurrencyDefault = (value, currency = "USD") => {
256
+ return new Intl.NumberFormat("en-US", {
257
+ style: "currency",
258
+ currency,
259
+ minimumFractionDigits: 0,
260
+ maximumFractionDigits: 0
261
+ }).format(value);
262
+ };
263
+ var useTranslation = (customTranslations, customFormatCurrency) => {
264
+ const [locale, setLocale] = (0, import_react2.useState)("en");
265
+ const translations = (0, import_react2.useMemo)(
266
+ () => ({ ...defaultTranslations, ...customTranslations }),
267
+ [customTranslations]
268
+ );
269
+ const t = (0, import_react2.useCallback)(
270
+ (key, params) => {
271
+ let translation = translations[key] || key;
272
+ if (params) {
273
+ Object.keys(params).forEach((paramKey) => {
274
+ translation = translation.replace(
275
+ new RegExp(`{{${paramKey}}}`, "g"),
276
+ String(params[paramKey])
277
+ );
278
+ });
279
+ }
280
+ return translation;
281
+ },
282
+ [translations]
283
+ );
284
+ const formatCurrency = (0, import_react2.useCallback)(
285
+ (value, currency) => {
286
+ if (customFormatCurrency) {
287
+ return customFormatCurrency(value, currency);
288
+ }
289
+ return formatCurrencyDefault(value, currency);
290
+ },
291
+ [customFormatCurrency]
292
+ );
293
+ return {
294
+ t,
295
+ locale,
296
+ setLocale,
297
+ formatCurrency
298
+ };
299
+ };
300
+
301
+ // src/components/smart-filter/utils.tsx
302
+ var import_jsx_runtime4 = require("react/jsx-runtime");
303
+ var STAR_BASE_STYLES = {
304
+ display: "block",
305
+ width: "12px",
306
+ height: "12px",
307
+ borderRadius: "50%",
308
+ border: "1px solid #03852e",
309
+ pointerEvents: "none"
310
+ };
311
+ var STAR_FULL_STYLES = {
312
+ ...STAR_BASE_STYLES,
313
+ backgroundColor: "#03852e"
314
+ };
315
+ var STAR_HALF_STYLES = {
316
+ ...STAR_BASE_STYLES,
317
+ background: "linear-gradient(90deg, #03852e 50%, transparent 50%)"
318
+ };
319
+ var MIN_RATING_LABEL_STYLES = {
320
+ display: "flex",
321
+ alignItems: "center",
322
+ gap: "4px"
323
+ };
324
+ var MIN_RATING_STARS_WRAPPER_STYLES = {
325
+ display: "flex",
326
+ gap: "1px",
327
+ userSelect: "none"
328
+ };
329
+ var renderStars = (rating) => {
330
+ const stars = [];
331
+ const fullStars = Math.floor(rating);
332
+ const hasHalfStar = rating % 1 !== 0;
333
+ for (let i = 0; i < fullStars; i += 1) {
334
+ stars.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: STAR_FULL_STYLES }, `full-${i}`));
335
+ }
336
+ if (hasHalfStar) {
337
+ stars.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: STAR_HALF_STYLES }, "half"));
338
+ }
339
+ const remainingStars = Math.max(0, 5 - Math.ceil(rating));
340
+ for (let i = 0; i < remainingStars; i += 1) {
341
+ stars.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: STAR_BASE_STYLES }, `empty-${i}`));
342
+ }
343
+ return stars;
344
+ };
345
+ var createMinRatingFilterLabel = (rating, suffix) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: MIN_RATING_LABEL_STYLES, children: [
346
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: MIN_RATING_STARS_WRAPPER_STYLES, children: renderStars(rating) }),
347
+ " ",
348
+ suffix
349
+ ] });
350
+ var formatRatingValue = (rating) => rating.toFixed(1);
351
+ var createPriceRangeFilterLabel = (min, max, currency, formatCurrencyFn) => `${formatCurrencyFn(min, currency)} - ${formatCurrencyFn(
352
+ max != null ? max : 0,
353
+ currency
354
+ )}`;
355
+
356
+ // src/components/smart-filter/MinRatingFilterChip.tsx
357
+ var import_jsx_runtime5 = require("react/jsx-runtime");
358
+ var chipContainerStyles = {
359
+ position: "relative",
360
+ backgroundColor: "white",
361
+ color: "black",
362
+ fontSize: "14px",
363
+ borderRadius: "9999px",
364
+ padding: "0 16px",
365
+ paddingRight: "20px",
366
+ border: "1px solid #03852e",
367
+ display: "flex",
368
+ gap: "8px",
369
+ alignItems: "center",
370
+ justifyContent: "center",
371
+ flexShrink: 0,
372
+ height: "34px"
373
+ };
374
+ var starContainerStyles = {
375
+ display: "flex",
376
+ gap: "1px",
377
+ userSelect: "none"
378
+ };
379
+ var circleBaseStyles = {
380
+ display: "block",
381
+ width: "12px",
382
+ height: "12px",
383
+ borderRadius: "50%",
384
+ border: "1px solid #03852e",
385
+ pointerEvents: "none"
386
+ };
387
+ var buttonBaseStyles = {
388
+ position: "absolute",
389
+ top: 0,
390
+ height: "100%",
391
+ cursor: "pointer",
392
+ backgroundColor: "transparent",
393
+ border: "none",
394
+ padding: 0
395
+ };
396
+ var MinRatingFilterChip = ({ rating, onChange, onRemove, star = false }) => {
397
+ const [hoverRating, setHoverRating] = (0, import_react3.useState)(null);
398
+ const { t } = useTranslation();
399
+ const displayRating = hoverRating != null ? hoverRating : rating;
400
+ const formatLabel = (value) => star && value ? value.toString() : t("smartFilter.minRating.label", { value: formatRatingValue(value) });
401
+ const removeLabel = t("smartFilter.minRating.remove");
402
+ const setLabel = (value) => t("smartFilter.minRating.setTo", { rating: formatRatingValue(value) });
403
+ const getFillForStar = (index) => {
404
+ const starNumber = index + 1;
405
+ if (displayRating >= starNumber) {
406
+ return "full";
407
+ }
408
+ if (displayRating >= starNumber - 0.5) {
409
+ return "half";
410
+ }
411
+ return "empty";
412
+ };
413
+ const handleSelect = (nextRating) => {
414
+ setHoverRating(null);
415
+ if (nextRating === rating) {
416
+ return;
417
+ }
418
+ onChange(nextRating);
419
+ };
420
+ const handleBlur = (event) => {
421
+ var _a;
422
+ const related = event.relatedTarget;
423
+ if (!related || !((_a = event.currentTarget.closest("[data-min-rating-chip]")) == null ? void 0 : _a.contains(related))) {
424
+ setHoverRating(null);
425
+ }
426
+ };
427
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: chipContainerStyles, "data-min-rating-chip": true, children: [
428
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
429
+ "div",
430
+ {
431
+ style: { display: "flex", alignItems: "center", gap: "4px" },
432
+ onMouseLeave: () => setHoverRating(null),
433
+ children: [
434
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: starContainerStyles, children: Array.from({ length: 5 }).map((_, index) => {
435
+ const fillState = getFillForStar(index);
436
+ const starNumber = index + 1;
437
+ const halfValue = starNumber - 0.5;
438
+ if (star) {
439
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
440
+ "div",
441
+ {
442
+ style: {
443
+ position: "relative",
444
+ width: "16px",
445
+ height: "16px"
446
+ },
447
+ children: [
448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
449
+ StarIcon,
450
+ {
451
+ fill: displayRating >= starNumber ? "#03852e" : "none",
452
+ style: {
453
+ width: "16px",
454
+ height: "16px",
455
+ pointerEvents: "none"
456
+ }
457
+ }
458
+ ),
459
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
460
+ "button",
461
+ {
462
+ type: "button",
463
+ style: {
464
+ ...buttonBaseStyles,
465
+ left: 0,
466
+ width: "50%",
467
+ borderRadius: "50% 0 0 50%"
468
+ },
469
+ onMouseEnter: () => setHoverRating(halfValue),
470
+ onFocus: () => setHoverRating(halfValue),
471
+ onBlur: handleBlur,
472
+ onClick: () => handleSelect(halfValue),
473
+ "aria-label": setLabel(halfValue),
474
+ title: formatLabel(halfValue)
475
+ }
476
+ ),
477
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
478
+ "button",
479
+ {
480
+ type: "button",
481
+ style: {
482
+ ...buttonBaseStyles,
483
+ left: "50%",
484
+ width: "50%",
485
+ borderRadius: "0 50% 50% 0"
486
+ },
487
+ onMouseEnter: () => setHoverRating(starNumber),
488
+ onFocus: () => setHoverRating(starNumber),
489
+ onBlur: handleBlur,
490
+ onClick: () => handleSelect(starNumber),
491
+ "aria-label": setLabel(starNumber),
492
+ title: formatLabel(starNumber)
493
+ }
494
+ )
495
+ ]
496
+ },
497
+ index
498
+ );
499
+ }
500
+ const circleStyles = fillState === "full" ? { ...circleBaseStyles, backgroundColor: "#03852e" } : circleBaseStyles;
501
+ const halfCircleStyles = {
502
+ ...circleBaseStyles,
503
+ background: "linear-gradient(90deg, #03852e 50%, transparent 50%)"
504
+ };
505
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
506
+ "div",
507
+ {
508
+ style: { position: "relative", width: "12px", height: "12px" },
509
+ children: [
510
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
511
+ "span",
512
+ {
513
+ style: fillState === "half" ? halfCircleStyles : circleStyles
514
+ }
515
+ ),
516
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
517
+ "button",
518
+ {
519
+ type: "button",
520
+ style: {
521
+ ...buttonBaseStyles,
522
+ left: 0,
523
+ width: "50%",
524
+ borderRadius: "50% 0 0 50%",
525
+ outline: "2px solid transparent",
526
+ outlineOffset: "1px"
527
+ },
528
+ onMouseEnter: () => setHoverRating(halfValue),
529
+ onFocus: () => setHoverRating(halfValue),
530
+ onBlur: handleBlur,
531
+ onClick: () => handleSelect(halfValue),
532
+ "aria-label": setLabel(halfValue),
533
+ title: formatLabel(halfValue)
534
+ }
535
+ ),
536
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
537
+ "button",
538
+ {
539
+ type: "button",
540
+ style: {
541
+ ...buttonBaseStyles,
542
+ left: "50%",
543
+ width: "50%",
544
+ borderRadius: "0 50% 50% 0",
545
+ outline: "2px solid transparent",
546
+ outlineOffset: "1px"
547
+ },
548
+ onMouseEnter: () => setHoverRating(starNumber),
549
+ onFocus: () => setHoverRating(starNumber),
550
+ onBlur: handleBlur,
551
+ onClick: () => handleSelect(starNumber),
552
+ "aria-label": setLabel(starNumber),
553
+ title: formatLabel(starNumber)
554
+ }
555
+ )
556
+ ]
557
+ },
558
+ index
559
+ );
560
+ }) }),
561
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { whiteSpace: "nowrap" }, children: formatLabel(displayRating) })
562
+ ]
563
+ }
564
+ ),
565
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseButton, { onClick: onRemove })
566
+ ] });
567
+ };
568
+
569
+ // src/components/smart-filter/PriceRangeFilterChip.tsx
570
+ var import_react4 = require("react");
571
+ var import_jsx_runtime6 = require("react/jsx-runtime");
572
+ var chipStyles2 = {
573
+ position: "relative",
574
+ backgroundColor: "white",
575
+ color: "black",
576
+ fontSize: "14px",
577
+ borderRadius: "9999px",
578
+ padding: "0 16px",
579
+ border: "1px solid #03852e",
580
+ display: "flex",
581
+ alignItems: "center",
582
+ gap: "8px",
583
+ flexShrink: 0,
584
+ height: "34px"
585
+ };
586
+ var inputStyles = {
587
+ outline: "none",
588
+ fontSize: "16px",
589
+ backgroundColor: "transparent",
590
+ borderRadius: "2px",
591
+ padding: "2px 8px",
592
+ width: "64px",
593
+ textAlign: "center",
594
+ border: "none"
595
+ };
596
+ var editButtonStyles = {
597
+ padding: "4px",
598
+ borderRadius: "50%",
599
+ cursor: "pointer",
600
+ transition: "background-color 0.2s",
601
+ border: "none",
602
+ backgroundColor: "transparent",
603
+ color: "#737373",
604
+ display: "flex",
605
+ alignItems: "center",
606
+ justifyContent: "center"
607
+ };
608
+ var PriceBoundaryChip = ({
609
+ label,
610
+ value,
611
+ placeholder,
612
+ currency,
613
+ isOptional = false,
614
+ showRemoveButton = false,
615
+ editLabel,
616
+ showAddWhenEmpty = false,
617
+ onCommit,
618
+ onRemove
619
+ }) => {
620
+ const [draft, setDraft] = (0, import_react4.useState)(
621
+ value !== void 0 ? String(value) : ""
622
+ );
623
+ const [isEditing, setIsEditing] = (0, import_react4.useState)(false);
624
+ const [editHover, setEditHover] = (0, import_react4.useState)(false);
625
+ const hasValue = value !== void 0;
626
+ (0, import_react4.useEffect)(() => {
627
+ setDraft(value !== void 0 ? String(value) : "");
628
+ setIsEditing(false);
629
+ }, [value]);
630
+ const resetDraft = () => {
631
+ setDraft(value !== void 0 ? String(value) : "");
632
+ };
633
+ const commitValue = () => {
634
+ if (draft.trim() === "") {
635
+ if (isOptional) {
636
+ onCommit(void 0);
637
+ setDraft("");
638
+ return;
639
+ }
640
+ resetDraft();
641
+ return;
642
+ }
643
+ const parsed = Number(draft);
644
+ if (!Number.isFinite(parsed)) {
645
+ resetDraft();
646
+ return;
647
+ }
648
+ const normalized = Math.max(0, parsed);
649
+ if (normalized === value) {
650
+ resetDraft();
651
+ return;
652
+ }
653
+ onCommit(normalized);
654
+ };
655
+ const handleChange = (event) => {
656
+ const next = event.target.value.replace(/[^\d]/g, "");
657
+ setDraft(next);
658
+ };
659
+ const handleKeyDown = (event) => {
660
+ if (event.key === "Enter") {
661
+ event.preventDefault();
662
+ event.currentTarget.blur();
663
+ setIsEditing(false);
664
+ return;
665
+ }
666
+ if (event.key === "Escape") {
667
+ event.preventDefault();
668
+ resetDraft();
669
+ event.currentTarget.blur();
670
+ setIsEditing(false);
671
+ return;
672
+ }
673
+ const allowed = event.key.length === 1 && /[0-9]/.test(event.key) || event.key === "Backspace" || event.key === "Delete" || event.key === "Tab" || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Home" || event.key === "End";
674
+ if (!allowed) {
675
+ event.preventDefault();
676
+ }
677
+ };
678
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: chipStyles2, children: [
679
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
680
+ "span",
681
+ {
682
+ style: {
683
+ fontSize: "10px",
684
+ textTransform: "uppercase",
685
+ fontWeight: 600,
686
+ letterSpacing: "0.05em"
687
+ },
688
+ children: label
689
+ }
690
+ ),
691
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
692
+ "input",
693
+ {
694
+ value: draft,
695
+ onChange: handleChange,
696
+ onBlur: () => {
697
+ commitValue();
698
+ setIsEditing(false);
699
+ },
700
+ onKeyDown: handleKeyDown,
701
+ placeholder,
702
+ inputMode: "numeric",
703
+ pattern: "[0-9]*",
704
+ "aria-label": label,
705
+ style: inputStyles,
706
+ autoFocus: true
707
+ }
708
+ ) : hasValue ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontSize: "16px" }, children: [
709
+ currency,
710
+ value
711
+ ] }) : showAddWhenEmpty ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
712
+ "button",
713
+ {
714
+ type: "button",
715
+ style: {
716
+ fontSize: "16px",
717
+ color: "#737373",
718
+ cursor: "pointer",
719
+ border: "none",
720
+ backgroundColor: "transparent",
721
+ padding: 0
722
+ },
723
+ onClick: () => setIsEditing(true),
724
+ "aria-label": editLabel,
725
+ children: "+"
726
+ }
727
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "16px", color: "#737373" }, children: "-" }),
728
+ (!showAddWhenEmpty || showAddWhenEmpty && isEditing) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "#737373", fontSize: "12px" }, children: currency }),
729
+ !isEditing && (!showAddWhenEmpty || hasValue) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
730
+ "button",
731
+ {
732
+ type: "button",
733
+ style: {
734
+ ...editButtonStyles,
735
+ backgroundColor: editHover ? "#e5e5e5" : "transparent"
736
+ },
737
+ "aria-label": editLabel,
738
+ title: editLabel,
739
+ onClick: () => setIsEditing(true),
740
+ onMouseEnter: () => setEditHover(true),
741
+ onMouseLeave: () => setEditHover(false),
742
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EditIcon, {})
743
+ }
744
+ ),
745
+ showRemoveButton && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CloseButton, { onClick: onRemove })
746
+ ] });
747
+ };
748
+ var PriceRangeFilterChip = ({ priceRange, currency, onChange, onRemove }) => {
749
+ const { t } = useTranslation();
750
+ const minLabel = "Min";
751
+ const maxChipLabel = "Max";
752
+ const editLabel = t("smartFilter.priceRange.edit");
753
+ const handleBoundaryCommit = (boundary, nextValue) => {
754
+ const nextRange = {
755
+ min: priceRange.min,
756
+ max: priceRange.max
757
+ };
758
+ if (boundary === "min") {
759
+ nextRange.min = nextValue;
760
+ if (nextValue !== void 0 && priceRange.max !== void 0 && nextValue > priceRange.max) {
761
+ nextRange.max = nextValue;
762
+ }
763
+ } else {
764
+ nextRange.max = nextValue;
765
+ if (nextValue !== void 0 && priceRange.min !== void 0 && nextValue < priceRange.min) {
766
+ nextRange.min = nextValue;
767
+ }
768
+ }
769
+ if (nextRange.min !== priceRange.min || nextRange.max !== priceRange.max) {
770
+ onChange(nextRange);
771
+ }
772
+ };
773
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
774
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
775
+ PriceBoundaryChip,
776
+ {
777
+ label: minLabel,
778
+ value: priceRange.min,
779
+ currency,
780
+ editLabel,
781
+ showRemoveButton: priceRange.min !== void 0 && priceRange.min !== 0,
782
+ onCommit: (value) => handleBoundaryCommit("min", value),
783
+ onRemove
784
+ }
785
+ ),
786
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
787
+ PriceBoundaryChip,
788
+ {
789
+ label: maxChipLabel,
790
+ value: priceRange.max,
791
+ currency,
792
+ isOptional: true,
793
+ showRemoveButton: priceRange.max !== void 0,
794
+ editLabel,
795
+ showAddWhenEmpty: true,
796
+ onCommit: (value) => handleBoundaryCommit("max", value),
797
+ onRemove
798
+ }
799
+ )
800
+ ] });
801
+ };
802
+
803
+ // src/components/smart-filter/RestaurantPriceLevelChip.tsx
804
+ var import_jsx_runtime7 = require("react/jsx-runtime");
805
+ var chipStyles3 = {
806
+ position: "relative",
807
+ backgroundColor: "white",
808
+ color: "black",
809
+ fontSize: "14px",
810
+ borderRadius: "9999px",
811
+ padding: "0 16px",
812
+ paddingRight: "20px",
813
+ border: "1px solid #03852e",
814
+ display: "flex",
815
+ alignItems: "center",
816
+ gap: "16px",
817
+ flexShrink: 0,
818
+ height: "34px"
819
+ };
820
+ var PRICE_LEVEL_OPTIONS = [
821
+ { value: "Cheap Eats", key: "cheapEats" },
822
+ { value: "Mid Range", key: "midRange" },
823
+ { value: "Fine Dining", key: "fineDining" }
824
+ ];
825
+ var RestaurantPriceLevelChip = ({ values, onChange, onRemove }) => {
826
+ const { t } = useTranslation();
827
+ const label = t("smartFilter.restaurantPriceLevel.label");
828
+ const removeLabel = t("smartFilter.restaurantPriceLevel.remove");
829
+ const noneSelectedLabel = t("smartFilter.restaurantPriceLevel.none");
830
+ const handleChange = (event) => {
831
+ const { value, checked } = event.target;
832
+ const valueAsPriceLevel = value;
833
+ const selection = new Set(values);
834
+ if (checked) {
835
+ selection.add(valueAsPriceLevel);
836
+ } else {
837
+ selection.delete(valueAsPriceLevel);
838
+ }
839
+ const orderedSelection = PRICE_LEVEL_OPTIONS.filter(
840
+ (option) => selection.has(option.value)
841
+ ).map((option) => option.value);
842
+ onChange(orderedSelection);
843
+ };
844
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: chipStyles3, children: [
845
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
846
+ "div",
847
+ {
848
+ style: {
849
+ display: "flex",
850
+ alignItems: "center",
851
+ gap: "8px",
852
+ flexWrap: "wrap"
853
+ },
854
+ children: [
855
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
856
+ "span",
857
+ {
858
+ style: {
859
+ fontSize: "10px",
860
+ textTransform: "uppercase",
861
+ fontWeight: 600,
862
+ letterSpacing: "0.05em"
863
+ },
864
+ children: label
865
+ }
866
+ ),
867
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: "12px" }, children: [
868
+ PRICE_LEVEL_OPTIONS.map((option) => {
869
+ const optionLabel = t(
870
+ `smartFilter.restaurantPriceLevel.options.${option.key}`
871
+ );
872
+ const checkboxId = `price-level-${option.key}`;
873
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
874
+ "label",
875
+ {
876
+ htmlFor: checkboxId,
877
+ style: {
878
+ display: "flex",
879
+ alignItems: "center",
880
+ gap: "4px",
881
+ fontSize: "12px",
882
+ cursor: "pointer"
883
+ },
884
+ children: [
885
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
886
+ "input",
887
+ {
888
+ id: checkboxId,
889
+ type: "checkbox",
890
+ value: option.value,
891
+ checked: values.includes(option.value),
892
+ onChange: handleChange,
893
+ style: { accentColor: "#03852e", cursor: "pointer" }
894
+ }
895
+ ),
896
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: optionLabel })
897
+ ]
898
+ },
899
+ option.value
900
+ );
901
+ }),
902
+ values.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: "12px", color: "#737373" }, children: noneSelectedLabel })
903
+ ] })
904
+ ]
905
+ }
906
+ ),
907
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseButton, { onClick: onRemove })
908
+ ] });
909
+ };
910
+
911
+ // src/components/smart-filter/TransformedQueryChip.tsx
912
+ var import_react5 = require("react");
913
+ var import_jsx_runtime8 = require("react/jsx-runtime");
914
+ var chipStyles4 = {
915
+ position: "relative",
916
+ backgroundColor: "white",
917
+ color: "black",
918
+ fontSize: "14px",
919
+ borderRadius: "9999px",
920
+ padding: "0 16px",
921
+ paddingRight: "20px",
922
+ border: "1px solid #03852e",
923
+ display: "flex",
924
+ alignItems: "center",
925
+ gap: "8px",
926
+ flexShrink: 0,
927
+ userSelect: "none",
928
+ height: "34px"
929
+ };
930
+ var inputStyles2 = {
931
+ backgroundColor: "#ececec",
932
+ borderRadius: "2px",
933
+ padding: "2px 8px",
934
+ outline: "none",
935
+ fontSize: "16px",
936
+ minWidth: "8ch",
937
+ border: "none"
938
+ };
939
+ var editButtonStyles2 = {
940
+ padding: "4px",
941
+ borderRadius: "50%",
942
+ cursor: "pointer",
943
+ transition: "background-color 0.2s",
944
+ color: "#737373",
945
+ border: "none",
946
+ backgroundColor: "transparent",
947
+ display: "flex",
948
+ alignItems: "center",
949
+ justifyContent: "center"
950
+ };
951
+ var TransformedQueryChip = ({ value, onChange, onRemove }) => {
952
+ const inputRef = (0, import_react5.useRef)(null);
953
+ const [draft, setDraft] = (0, import_react5.useState)(value);
954
+ const [isEditing, setIsEditing] = (0, import_react5.useState)(false);
955
+ const [editHover, setEditHover] = (0, import_react5.useState)(false);
956
+ const { t } = useTranslation();
957
+ const removeLabel = t("smartFilter.transformedQuery.remove");
958
+ const editLabel = t("smartFilter.transformedQuery.edit");
959
+ (0, import_react5.useEffect)(() => {
960
+ setDraft(value);
961
+ setIsEditing(false);
962
+ }, [value]);
963
+ const applyChanges = () => {
964
+ const nextValue = draft.trim();
965
+ if (!nextValue.length) {
966
+ setDraft(value);
967
+ return;
968
+ }
969
+ if (nextValue === value) {
970
+ return;
971
+ }
972
+ onChange(nextValue);
973
+ };
974
+ const handleChange = (event) => {
975
+ setDraft(event.target.value);
976
+ };
977
+ const handleKeyDown = (event) => {
978
+ if (event.key === "Enter") {
979
+ event.preventDefault();
980
+ event.currentTarget.blur();
981
+ return;
982
+ }
983
+ if (event.key === "Escape") {
984
+ event.preventDefault();
985
+ setDraft(value);
986
+ event.currentTarget.blur();
987
+ return;
988
+ }
989
+ };
990
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: chipStyles4, children: [
991
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SearchIcon, { style: { width: "16px", height: "16px", color: "#03852e" } }),
992
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
993
+ "input",
994
+ {
995
+ ref: inputRef,
996
+ value: draft,
997
+ onChange: handleChange,
998
+ onBlur: () => {
999
+ applyChanges();
1000
+ setIsEditing(false);
1001
+ },
1002
+ onKeyDown: handleKeyDown,
1003
+ "aria-label": editLabel,
1004
+ style: inputStyles2,
1005
+ autoFocus: true
1006
+ }
1007
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "16px" }, children: value }),
1008
+ !isEditing && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1009
+ "button",
1010
+ {
1011
+ type: "button",
1012
+ style: {
1013
+ ...editButtonStyles2,
1014
+ backgroundColor: editHover ? "#e5e5e5" : "transparent"
1015
+ },
1016
+ "aria-label": editLabel,
1017
+ title: editLabel,
1018
+ onClick: () => setIsEditing(true),
1019
+ onMouseEnter: () => setEditHover(true),
1020
+ onMouseLeave: () => setEditHover(false),
1021
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EditIcon, {})
1022
+ }
1023
+ ),
1024
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseButton, { onClick: onRemove })
1025
+ ] });
1026
+ };
1027
+
1028
+ // src/hooks/useFilterScroll.ts
1029
+ var import_react6 = require("react");
1030
+ var useFilterScroll = (dependency) => {
1031
+ const scrollerRef = (0, import_react6.useRef)(null);
1032
+ const [atStart, setAtStart] = (0, import_react6.useState)(true);
1033
+ const [atEnd, setAtEnd] = (0, import_react6.useState)(true);
1034
+ const updateScrollButtons = (0, import_react6.useCallback)(() => {
1035
+ const el = scrollerRef.current;
1036
+ if (!el) {
1037
+ setAtStart(true);
1038
+ setAtEnd(true);
1039
+ return;
1040
+ }
1041
+ const { scrollLeft, scrollWidth, clientWidth } = el;
1042
+ setAtStart(scrollLeft <= 0);
1043
+ setAtEnd(scrollLeft + clientWidth >= scrollWidth - 1);
1044
+ }, []);
1045
+ (0, import_react6.useEffect)(() => {
1046
+ const el = scrollerRef.current;
1047
+ updateScrollButtons();
1048
+ if (!el) {
1049
+ return;
1050
+ }
1051
+ const handleScroll = () => updateScrollButtons();
1052
+ el.addEventListener("scroll", handleScroll, { passive: true });
1053
+ window.addEventListener("resize", updateScrollButtons);
1054
+ return () => {
1055
+ el.removeEventListener("scroll", handleScroll);
1056
+ window.removeEventListener("resize", updateScrollButtons);
1057
+ };
1058
+ }, [dependency, updateScrollButtons]);
1059
+ const scrollByDir = (0, import_react6.useCallback)((dir) => {
1060
+ const el = scrollerRef.current;
1061
+ if (!el) {
1062
+ return;
1063
+ }
1064
+ const delta = el.clientWidth * 0.7;
1065
+ el.scrollBy({
1066
+ left: dir === "next" ? delta : -delta,
1067
+ behavior: "smooth"
1068
+ });
1069
+ }, []);
1070
+ return {
1071
+ scrollerRef,
1072
+ atStart,
1073
+ atEnd,
1074
+ scrollByDir
1075
+ };
1076
+ };
1077
+
1078
+ // src/components/smart-filter/FilterChips.tsx
1079
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1080
+ var containerStyles = {
1081
+ position: "relative",
1082
+ width: "100%"
1083
+ };
1084
+ var scrollContainerBase = {
1085
+ display: "flex",
1086
+ gap: "8px",
1087
+ overflowX: "auto",
1088
+ alignItems: "center",
1089
+ width: "100%",
1090
+ scrollbarWidth: "none",
1091
+ msOverflowStyle: "none"
1092
+ };
1093
+ var gradientStyles = {
1094
+ pointerEvents: "none",
1095
+ position: "absolute",
1096
+ top: 0,
1097
+ bottom: 0,
1098
+ width: "40px"
1099
+ };
1100
+ var navButtonStyles = {
1101
+ position: "absolute",
1102
+ top: "50%",
1103
+ transform: "translateY(-50%)",
1104
+ backgroundColor: "white",
1105
+ color: "#003c30",
1106
+ border: "1px solid #003c30",
1107
+ padding: "4px",
1108
+ borderRadius: "50%",
1109
+ display: "flex",
1110
+ alignItems: "center",
1111
+ justifyContent: "center",
1112
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
1113
+ cursor: "pointer"
1114
+ };
1115
+ var FilterChips = ({
1116
+ filters,
1117
+ currency,
1118
+ minRatingSuffix: _minRatingSuffix,
1119
+ clearAllLabel,
1120
+ previousFiltersLabel,
1121
+ nextFiltersLabel,
1122
+ formatCurrency: _formatCurrency,
1123
+ onFilterChange,
1124
+ onResetFilters: _onResetFilters,
1125
+ onClearAll
1126
+ }) => {
1127
+ const { scrollerRef, atStart, atEnd, scrollByDir } = useFilterScroll(
1128
+ filters.length
1129
+ );
1130
+ const [navHover, setNavHover] = import_react7.default.useState(null);
1131
+ const [clearHover, setClearHover] = import_react7.default.useState(false);
1132
+ const removeFilter = import_react7.default.useCallback(
1133
+ (filterId) => {
1134
+ void onFilterChange(filters.filter((f) => f.id !== filterId));
1135
+ },
1136
+ [filters, onFilterChange]
1137
+ );
1138
+ const patchFilter = import_react7.default.useCallback(
1139
+ (filterId, patch) => {
1140
+ const nextFilters = filters.map(
1141
+ (f) => f.id === filterId ? { ...f, ...patch } : f
1142
+ );
1143
+ void onFilterChange(nextFilters);
1144
+ },
1145
+ [filters, onFilterChange]
1146
+ );
1147
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: containerStyles, children: [
1148
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1149
+ "div",
1150
+ {
1151
+ ref: scrollerRef,
1152
+ style: {
1153
+ ...scrollContainerBase,
1154
+ padding: "8px",
1155
+ // Hide scrollbar for webkit browsers
1156
+ WebkitOverflowScrolling: "touch"
1157
+ },
1158
+ children: [
1159
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
2
1160
  div::-webkit-scrollbar {
3
1161
  display: none;
4
1162
  }
5
- `}),e.map(n=>{var u,o,d;let S=()=>(0,R.jsx)($,{label:n.label,icon:n.icon,remove:()=>{c(e.filter(r=>r.id!==n.id))}},n.id);if(n.type==="minRating"){let r=(u=n.numericValue)!=null?u:Number(n.value);return Number.isFinite(r)?(0,R.jsx)(V,{rating:r,onChange:F=>{let w=e.map(H=>H.id===n.id?{...H,numericValue:F,value:String(F)}:H);c(w)},onRemove:()=>void c(e.filter(F=>F.id!==n.id))},n.id):S()}if(n.type==="starRating"){let r=(o=n.numericValue)!=null?o:Number(n.value);return Number.isFinite(r)?(0,R.jsx)(V,{star:!0,rating:r,onChange:F=>{let w=e.map(H=>H.id===n.id?{...H,numericValue:F,value:String(F)}:H);c(w)},onRemove:()=>void c(e.filter(F=>F.id!==n.id))},n.id):S()}return n.type==="priceRange"&&n.priceRange?(0,R.jsx)(Y,{priceRange:n.priceRange,currency:t,onChange:r=>{let F=e.map(w=>w.id===n.id?{...w,priceRange:r}:w);c(F)},onRemove:()=>void c(e.filter(r=>r.id!==n.id))},n.id):n.type==="transformed_query"?(0,R.jsx)(j,{value:n.value,onChange:r=>{let F=e.map(w=>w.id===n.id?{...w,value:r}:w);c(F)},onRemove:()=>void c(e.filter(r=>r.id!==n.id))},n.id):n.type==="selected_restaurant_price_levels"?(0,R.jsx)(Z,{values:(d=n.priceLevels)!=null?d:[],onChange:r=>{let F=e.map(w=>w.id===n.id?{...w,priceLevels:r}:w);c(F)},onRemove:()=>void c(e.filter(r=>r.id!==n.id))},n.id):S()}),(0,R.jsx)("button",{style:{flexShrink:0,padding:"4px 16px",borderRadius:"9999px",cursor:"pointer",fontSize:"14px",userSelect:"none",backgroundColor:v?"#eee":"white",color:"black",border:"1px solid #03852e"},onClick:m,onMouseEnter:()=>p(!0),onMouseLeave:()=>p(!1),children:i})]}),!x&&(0,R.jsx)("div",{"aria-hidden":"true",style:{...fe,left:0,background:"linear-gradient(to right, white, transparent)"}}),!f&&(0,R.jsx)("div",{"aria-hidden":"true",style:{...fe,right:0,background:"linear-gradient(to left, white, transparent)"}}),!x&&(0,R.jsx)("button",{type:"button","aria-label":s,style:{...he,left:"4px",transform:"translateY(-50%) rotate(180deg)",backgroundColor:b==="prev"?"#e5e5e5":"white"},onClick:()=>k("prev"),onMouseEnter:()=>C("prev"),onMouseLeave:()=>C(null),children:(0,R.jsx)(K,{style:{width:"20px",height:"20px"}})}),!f&&(0,R.jsx)("button",{type:"button","aria-label":y,style:{...he,right:"4px",backgroundColor:b==="next"?"#e5e5e5":"white"},onClick:()=>k("next"),onMouseEnter:()=>C("next"),onMouseLeave:()=>C(null),children:(0,R.jsx)(K,{style:{width:"20px",height:"20px"}})})]})};var ce=require("react/jsx-runtime"),Ke={position:"relative",display:"flex",flexDirection:"column",gap:"8px",width:"100%"},be=({filters:e,isSearching:t=!1,onFilterChange:a,customTranslations:i,currency:s="USD",containerStyle:y,style:h})=>{let{t:c,formatCurrency:l}=I(i),m=c("smartFilter.minRating.suffix"),g=c("smartFilter.nav.previous"),x=c("smartFilter.nav.next"),f=c("smartFilter.clearAll"),k=(0,ee.useCallback)(async(v,p)=>{if(!t)try{await a(v)}catch(n){console.error("Filter change error:",n)}},[t,a]),b=(0,ee.useCallback)(()=>{k([])},[k]),C=(0,ee.useCallback)(()=>{k([],!0)},[k]);return(0,ce.jsx)("div",{style:{...Ke,...y},children:e.length>0&&(0,ce.jsx)(J,{filters:e,currency:s,minRatingSuffix:m,clearAllLabel:f,previousFiltersLabel:g,nextFiltersLabel:x,formatCurrency:l,onFilterChange:k,onResetFilters:b,onClearAll:C})})};function $e(e){let t=P.default.useRef(null),[a,i]=P.default.useState(null),s=P.default.useRef(e);P.default.useEffect(()=>{s.current=e}),P.default.useEffect(()=>{let p=s.current,n={adapter:null,...p,callbacks:{...p.callbacks,onPropertiesChange:u=>{var o,d;i(r=>r?{...r,properties:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onPropertiesChange)==null||d.call(o,u)},onSelectedPropertyChange:u=>{var o,d;i(r=>r?{...r,selectedPropertyId:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onSelectedPropertyChange)==null||d.call(o,u)},onPrimaryTypeChange:u=>{var o,d;i(r=>r?{...r,primary:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onPrimaryTypeChange)==null||d.call(o,u)},onFiltersChange:u=>{var o,d;i(r=>r?{...r,filters:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onFiltersChange)==null||d.call(o,u)},onBoundsChange:u=>{var o,d;i(r=>r?{...r,bounds:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onBoundsChange)==null||d.call(o,u)},onPendingBoundsChange:u=>{var o,d;i(r=>r?{...r,pendingBounds:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onPendingBoundsChange)==null||d.call(o,u)},onCenterChange:(u,o)=>{var d,r;i(F=>F?{...F,center:u,zoom:o}:null),(r=(d=s.current.callbacks)==null?void 0:d.onCenterChange)==null||r.call(d,u,o)},onZoomChange:u=>{var o,d;i(r=>r?{...r,zoom:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onZoomChange)==null||d.call(o,u)},onActiveLocationChange:u=>{var o,d;i(r=>r?{...r,activeLocation:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onActiveLocationChange)==null||d.call(o,u)},onLoadingStateChange:u=>{var o,d;i(r=>r?{...r,initialLoading:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onLoadingStateChange)==null||d.call(o,u)},onSearchingStateChange:u=>{var o,d;i(r=>r?{...r,isSearching:u}:null),(d=(o=s.current.callbacks)==null?void 0:o.onSearchingStateChange)==null||d.call(o,u)}}},S=new Ce.MapFirstCore(n);return t.current=S,i(S.getState()),()=>{S.destroy(),t.current=null,i(null)}},[]);let y=P.default.useCallback(p=>{t.current&&t.current.setPrimaryType(p)},[]),h=P.default.useCallback(p=>{t.current&&t.current.setSelectedMarker(p)},[]),c=P.default.useCallback((p,n=!0)=>{t.current&&t.current.setUseApi(p,n)},[]),l=P.default.useMemo(()=>({search:async p=>{if(!t.current)throw new Error("MapFirst instance not available");return await t.current.runPropertiesSearch(p)}}),[]),m=P.default.useMemo(()=>({search:async p=>{if(!t.current)throw new Error("MapFirst instance not available");return await t.current.runSmartFilterSearch(p)}}),[]),g=P.default.useMemo(()=>({perform:async()=>t.current?await t.current.performBoundsSearch():null}),[]),x=P.default.useRef(!1),f=P.default.useCallback((p,n,S)=>{t.current&&p&&!x.current&&(t.current.attachMap(p,{platform:"maplibre",maplibregl:n,onMarkerClick:S==null?void 0:S.onMarkerClick}),x.current=!0)},[]),k=P.default.useRef(!1),b=P.default.useCallback((p,n,S)=>{t.current&&p&&!k.current&&(t.current.attachMap(p,{platform:"google",google:n,onMarkerClick:S==null?void 0:S.onMarkerClick}),k.current=!0)},[]),C=P.default.useRef(!1),v=P.default.useCallback((p,n,S)=>{t.current&&p&&!C.current&&(t.current.attachMap(p,{platform:"mapbox",mapboxgl:n,onMarkerClick:S==null?void 0:S.onMarkerClick}),C.current=!0)},[]);return{instance:t.current,state:a,setPrimaryType:y,setSelectedMarker:h,setUseApi:c,propertiesSearch:l,smartFilterSearch:m,boundsSearch:g,attachMapLibre:f,attachGoogle:b,attachMapbox:v}}0&&(module.exports={Chip,CloseIcon,EditIcon,FilterChips,MinRatingFilterChip,NextIcon,PriceRangeFilterChip,RestaurantPriceLevelChip,SearchIcon,SmartFilter,StarIcon,TransformedQueryChip,convertToApiFilters,createMinRatingFilterLabel,createPriceRangeFilterLabel,formatRatingValue,processApiFilters,renderStars,useFilterScroll,useMapFirst,useTranslation});
6
- //# sourceMappingURL=index.js.map
1163
+ ` }),
1164
+ filters.map((filter) => {
1165
+ var _a, _b;
1166
+ const renderStandardChip = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1167
+ Chip,
1168
+ {
1169
+ label: filter.label,
1170
+ icon: filter.icon,
1171
+ remove: () => removeFilter(filter.id)
1172
+ },
1173
+ filter.id
1174
+ );
1175
+ if (filter.type === "minRating" || filter.type === "starRating") {
1176
+ const currentRating = (_a = filter.numericValue) != null ? _a : Number(filter.value);
1177
+ if (!Number.isFinite(currentRating)) {
1178
+ return renderStandardChip();
1179
+ }
1180
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1181
+ MinRatingFilterChip,
1182
+ {
1183
+ star: filter.type === "starRating",
1184
+ rating: currentRating,
1185
+ onChange: (nextRating) => {
1186
+ patchFilter(filter.id, {
1187
+ numericValue: nextRating,
1188
+ value: String(nextRating)
1189
+ });
1190
+ },
1191
+ onRemove: () => removeFilter(filter.id)
1192
+ },
1193
+ filter.id
1194
+ );
1195
+ }
1196
+ if (filter.type === "priceRange" && filter.priceRange) {
1197
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1198
+ PriceRangeFilterChip,
1199
+ {
1200
+ priceRange: filter.priceRange,
1201
+ currency,
1202
+ onChange: (nextRange) => {
1203
+ patchFilter(filter.id, { priceRange: nextRange });
1204
+ },
1205
+ onRemove: () => removeFilter(filter.id)
1206
+ },
1207
+ filter.id
1208
+ );
1209
+ }
1210
+ if (filter.type === "transformed_query") {
1211
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1212
+ TransformedQueryChip,
1213
+ {
1214
+ value: filter.value,
1215
+ onChange: (nextValue) => {
1216
+ patchFilter(filter.id, { value: nextValue });
1217
+ },
1218
+ onRemove: () => removeFilter(filter.id)
1219
+ },
1220
+ filter.id
1221
+ );
1222
+ }
1223
+ if (filter.type === "selected_restaurant_price_levels") {
1224
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1225
+ RestaurantPriceLevelChip,
1226
+ {
1227
+ values: (_b = filter.priceLevels) != null ? _b : [],
1228
+ onChange: (nextLevels) => {
1229
+ patchFilter(filter.id, { priceLevels: nextLevels });
1230
+ },
1231
+ onRemove: () => removeFilter(filter.id)
1232
+ },
1233
+ filter.id
1234
+ );
1235
+ }
1236
+ return renderStandardChip();
1237
+ }),
1238
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1239
+ "button",
1240
+ {
1241
+ style: {
1242
+ flexShrink: 0,
1243
+ padding: "4px 16px",
1244
+ borderRadius: "9999px",
1245
+ cursor: "pointer",
1246
+ fontSize: "14px",
1247
+ userSelect: "none",
1248
+ backgroundColor: clearHover ? "#eee" : "white",
1249
+ color: "black",
1250
+ border: "1px solid #03852e"
1251
+ },
1252
+ onClick: onClearAll,
1253
+ onMouseEnter: () => setClearHover(true),
1254
+ onMouseLeave: () => setClearHover(false),
1255
+ children: clearAllLabel
1256
+ }
1257
+ )
1258
+ ]
1259
+ }
1260
+ ),
1261
+ !atStart && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1262
+ "div",
1263
+ {
1264
+ "aria-hidden": "true",
1265
+ style: {
1266
+ ...gradientStyles,
1267
+ left: 0,
1268
+ background: "linear-gradient(to right, white, transparent)"
1269
+ }
1270
+ }
1271
+ ),
1272
+ !atEnd && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1273
+ "div",
1274
+ {
1275
+ "aria-hidden": "true",
1276
+ style: {
1277
+ ...gradientStyles,
1278
+ right: 0,
1279
+ background: "linear-gradient(to left, white, transparent)"
1280
+ }
1281
+ }
1282
+ ),
1283
+ !atStart && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1284
+ "button",
1285
+ {
1286
+ type: "button",
1287
+ "aria-label": previousFiltersLabel,
1288
+ style: {
1289
+ ...navButtonStyles,
1290
+ left: "4px",
1291
+ transform: "translateY(-50%) rotate(180deg)",
1292
+ backgroundColor: navHover === "prev" ? "#e5e5e5" : "white"
1293
+ },
1294
+ onClick: () => scrollByDir("prev"),
1295
+ onMouseEnter: () => setNavHover("prev"),
1296
+ onMouseLeave: () => setNavHover(null),
1297
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(NextIcon, { style: { width: "20px", height: "20px" } })
1298
+ }
1299
+ ),
1300
+ !atEnd && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1301
+ "button",
1302
+ {
1303
+ type: "button",
1304
+ "aria-label": nextFiltersLabel,
1305
+ style: {
1306
+ ...navButtonStyles,
1307
+ right: "4px",
1308
+ backgroundColor: navHover === "next" ? "#e5e5e5" : "white"
1309
+ },
1310
+ onClick: () => scrollByDir("next"),
1311
+ onMouseEnter: () => setNavHover("next"),
1312
+ onMouseLeave: () => setNavHover(null),
1313
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(NextIcon, { style: { width: "20px", height: "20px" } })
1314
+ }
1315
+ )
1316
+ ] });
1317
+ };
1318
+
1319
+ // src/components/SmartFilter.tsx
1320
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1321
+ var containerStyles2 = {
1322
+ position: "relative",
1323
+ display: "flex",
1324
+ flexDirection: "column",
1325
+ gap: "8px",
1326
+ width: "100%"
1327
+ };
1328
+ var SmartFilter = ({
1329
+ filters,
1330
+ isSearching = false,
1331
+ onFilterChange,
1332
+ customTranslations,
1333
+ currency = "USD",
1334
+ containerStyle,
1335
+ style
1336
+ }) => {
1337
+ const { t, formatCurrency } = useTranslation(customTranslations);
1338
+ const minRatingSuffix = t("smartFilter.minRating.suffix");
1339
+ const previousFiltersLabel = t("smartFilter.nav.previous");
1340
+ const nextFiltersLabel = t("smartFilter.nav.next");
1341
+ const clearAllLabel = t("smartFilter.clearAll");
1342
+ const handleFilterChange = (0, import_react8.useCallback)(
1343
+ async (nextFilters, clearAll) => {
1344
+ if (isSearching) {
1345
+ return;
1346
+ }
1347
+ try {
1348
+ await onFilterChange(nextFilters);
1349
+ } catch (error) {
1350
+ console.error("Filter change error:", error);
1351
+ }
1352
+ },
1353
+ [isSearching, onFilterChange]
1354
+ );
1355
+ const resetFilters = (0, import_react8.useCallback)(() => {
1356
+ void handleFilterChange([]);
1357
+ }, [handleFilterChange]);
1358
+ const clearAllFilters = (0, import_react8.useCallback)(() => {
1359
+ void handleFilterChange([], true);
1360
+ }, [handleFilterChange]);
1361
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { ...containerStyles2, ...containerStyle, ...style }, children: filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1362
+ FilterChips,
1363
+ {
1364
+ filters,
1365
+ currency,
1366
+ minRatingSuffix,
1367
+ clearAllLabel,
1368
+ previousFiltersLabel,
1369
+ nextFiltersLabel,
1370
+ formatCurrency,
1371
+ onFilterChange: handleFilterChange,
1372
+ onResetFilters: resetFilters,
1373
+ onClearAll: clearAllFilters
1374
+ }
1375
+ ) });
1376
+ };
1377
+
1378
+ // src/index.tsx
1379
+ function updateStateField(setState, key, value) {
1380
+ setState((prev) => prev ? { ...prev, [key]: value } : null);
1381
+ }
1382
+ function forwardCallback(optionsRef, key, ...args) {
1383
+ var _a;
1384
+ const callback = (_a = optionsRef.current.callbacks) == null ? void 0 : _a[key];
1385
+ callback == null ? void 0 : callback(...args);
1386
+ }
1387
+ function attachMapOnce(instanceRef, attachedRef, map, config) {
1388
+ if (!instanceRef.current || !map || attachedRef.current) {
1389
+ return;
1390
+ }
1391
+ instanceRef.current.attachMap(map, config);
1392
+ attachedRef.current = true;
1393
+ }
1394
+ function useMapFirst(options) {
1395
+ const instanceRef = import_react9.default.useRef(null);
1396
+ const [state, setState] = import_react9.default.useState(null);
1397
+ const optionsRef = import_react9.default.useRef(options);
1398
+ import_react9.default.useEffect(() => {
1399
+ optionsRef.current = options;
1400
+ });
1401
+ import_react9.default.useEffect(() => {
1402
+ const opts = optionsRef.current;
1403
+ const coreOptions = {
1404
+ adapter: null,
1405
+ // Will be set when attachMap is called
1406
+ ...opts,
1407
+ callbacks: {
1408
+ ...opts.callbacks,
1409
+ // Add internal callbacks to trigger React re-renders
1410
+ onPropertiesChange: (properties) => {
1411
+ updateStateField(setState, "properties", properties);
1412
+ forwardCallback(optionsRef, "onPropertiesChange", properties);
1413
+ },
1414
+ onSelectedPropertyChange: (id) => {
1415
+ updateStateField(setState, "selectedPropertyId", id);
1416
+ forwardCallback(optionsRef, "onSelectedPropertyChange", id);
1417
+ },
1418
+ onPrimaryTypeChange: (type) => {
1419
+ updateStateField(setState, "primary", type);
1420
+ forwardCallback(optionsRef, "onPrimaryTypeChange", type);
1421
+ },
1422
+ onFiltersChange: (filters) => {
1423
+ updateStateField(setState, "filters", filters);
1424
+ forwardCallback(optionsRef, "onFiltersChange", filters);
1425
+ },
1426
+ onBoundsChange: (bounds) => {
1427
+ updateStateField(setState, "bounds", bounds);
1428
+ forwardCallback(optionsRef, "onBoundsChange", bounds);
1429
+ },
1430
+ onPendingBoundsChange: (pendingBounds) => {
1431
+ updateStateField(setState, "pendingBounds", pendingBounds);
1432
+ forwardCallback(optionsRef, "onPendingBoundsChange", pendingBounds);
1433
+ },
1434
+ onCenterChange: (center, zoom) => {
1435
+ setState((prev) => prev ? { ...prev, center, zoom } : null);
1436
+ forwardCallback(optionsRef, "onCenterChange", center, zoom);
1437
+ },
1438
+ onZoomChange: (zoom) => {
1439
+ updateStateField(setState, "zoom", zoom);
1440
+ forwardCallback(optionsRef, "onZoomChange", zoom);
1441
+ },
1442
+ onActiveLocationChange: (location) => {
1443
+ updateStateField(setState, "activeLocation", location);
1444
+ forwardCallback(optionsRef, "onActiveLocationChange", location);
1445
+ },
1446
+ onLoadingStateChange: (loading) => {
1447
+ updateStateField(setState, "initialLoading", loading);
1448
+ forwardCallback(optionsRef, "onLoadingStateChange", loading);
1449
+ },
1450
+ onSearchingStateChange: (searching) => {
1451
+ updateStateField(setState, "isSearching", searching);
1452
+ forwardCallback(optionsRef, "onSearchingStateChange", searching);
1453
+ }
1454
+ }
1455
+ };
1456
+ const instance = new import_core.MapFirstCore(coreOptions);
1457
+ instanceRef.current = instance;
1458
+ setState(instance.getState());
1459
+ return () => {
1460
+ instance.destroy();
1461
+ instanceRef.current = null;
1462
+ setState(null);
1463
+ };
1464
+ }, []);
1465
+ const setPrimaryType = import_react9.default.useCallback((type) => {
1466
+ if (instanceRef.current) {
1467
+ instanceRef.current.setPrimaryType(type);
1468
+ }
1469
+ }, []);
1470
+ const setSelectedMarker = import_react9.default.useCallback((id) => {
1471
+ if (instanceRef.current) {
1472
+ instanceRef.current.setSelectedMarker(id);
1473
+ }
1474
+ }, []);
1475
+ const setUseApi = import_react9.default.useCallback(
1476
+ (useApi, autoLoad = true) => {
1477
+ if (instanceRef.current) {
1478
+ instanceRef.current.setUseApi(useApi, autoLoad);
1479
+ }
1480
+ },
1481
+ []
1482
+ );
1483
+ const propertiesSearch = import_react9.default.useMemo(
1484
+ () => ({
1485
+ search: async (options2) => {
1486
+ if (!instanceRef.current) {
1487
+ throw new Error("MapFirst instance not available");
1488
+ }
1489
+ return await instanceRef.current.runPropertiesSearch(options2);
1490
+ }
1491
+ }),
1492
+ []
1493
+ );
1494
+ const smartFilterSearch = import_react9.default.useMemo(
1495
+ () => ({
1496
+ search: async (options2) => {
1497
+ if (!instanceRef.current) {
1498
+ throw new Error("MapFirst instance not available");
1499
+ }
1500
+ return await instanceRef.current.runSmartFilterSearch(options2);
1501
+ }
1502
+ }),
1503
+ []
1504
+ );
1505
+ const boundsSearch = import_react9.default.useMemo(
1506
+ () => ({
1507
+ perform: async () => {
1508
+ if (!instanceRef.current) {
1509
+ return null;
1510
+ }
1511
+ return await instanceRef.current.performBoundsSearch();
1512
+ }
1513
+ }),
1514
+ []
1515
+ );
1516
+ const mapLibreAttachedRef = import_react9.default.useRef(false);
1517
+ const attachMapLibre = import_react9.default.useCallback(
1518
+ (map, maplibregl, options2) => {
1519
+ attachMapOnce(instanceRef, mapLibreAttachedRef, map, {
1520
+ platform: "maplibre",
1521
+ maplibregl,
1522
+ onMarkerClick: options2 == null ? void 0 : options2.onMarkerClick
1523
+ });
1524
+ },
1525
+ []
1526
+ );
1527
+ const googleMapsAttachedRef = import_react9.default.useRef(false);
1528
+ const attachGoogle = import_react9.default.useCallback(
1529
+ (map, google, options2) => {
1530
+ attachMapOnce(instanceRef, googleMapsAttachedRef, map, {
1531
+ platform: "google",
1532
+ google,
1533
+ onMarkerClick: options2 == null ? void 0 : options2.onMarkerClick
1534
+ });
1535
+ },
1536
+ []
1537
+ );
1538
+ const mapboxAttachedRef = import_react9.default.useRef(false);
1539
+ const attachMapbox = import_react9.default.useCallback(
1540
+ (map, mapboxgl, options2) => {
1541
+ attachMapOnce(instanceRef, mapboxAttachedRef, map, {
1542
+ platform: "mapbox",
1543
+ mapboxgl,
1544
+ onMarkerClick: options2 == null ? void 0 : options2.onMarkerClick
1545
+ });
1546
+ },
1547
+ []
1548
+ );
1549
+ return {
1550
+ instance: instanceRef.current,
1551
+ state,
1552
+ setPrimaryType,
1553
+ setSelectedMarker,
1554
+ setUseApi,
1555
+ propertiesSearch,
1556
+ smartFilterSearch,
1557
+ boundsSearch,
1558
+ attachMapLibre,
1559
+ attachGoogle,
1560
+ attachMapbox
1561
+ };
1562
+ }
1563
+ // Annotate the CommonJS export names for ESM import in node:
1564
+ 0 && (module.exports = {
1565
+ Chip,
1566
+ CloseIcon,
1567
+ EditIcon,
1568
+ FilterChips,
1569
+ MapFirstCore,
1570
+ MinRatingFilterChip,
1571
+ NextIcon,
1572
+ PriceRangeFilterChip,
1573
+ PropertiesFetchError,
1574
+ RestaurantPriceLevelChip,
1575
+ SearchIcon,
1576
+ SmartFilter,
1577
+ StarIcon,
1578
+ TransformedQueryChip,
1579
+ convertToApiFilters,
1580
+ createMinRatingFilterLabel,
1581
+ createPriceRangeFilterLabel,
1582
+ fetchImages,
1583
+ fetchProperties,
1584
+ formatRatingValue,
1585
+ processApiFilters,
1586
+ renderStars,
1587
+ useFilterScroll,
1588
+ useMapFirst,
1589
+ useTranslation
1590
+ });