@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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1587 -3
- package/dist/index.mjs +1546 -3
- package/package.json +8 -7
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapfirst.ai/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "React hooks for MapFirst SDK - Reactive state management for map properties",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"README.md",
|
|
18
18
|
"EXAMPLES.md"
|
|
19
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup src/index.tsx --format esm,cjs --dts --clean",
|
|
22
|
+
"prepublishOnly": "pnpm build"
|
|
23
|
+
},
|
|
20
24
|
"keywords": [
|
|
21
25
|
"react",
|
|
22
26
|
"hooks",
|
|
@@ -30,19 +34,16 @@
|
|
|
30
34
|
"license": "MIT",
|
|
31
35
|
"repository": {
|
|
32
36
|
"type": "git",
|
|
33
|
-
"url": "https://github.com/
|
|
37
|
+
"url": "git+https://github.com/mapfirst-ai/mapfirst-sdk.git",
|
|
34
38
|
"directory": "packages/react"
|
|
35
39
|
},
|
|
36
40
|
"publishConfig": {
|
|
37
41
|
"access": "public"
|
|
38
42
|
},
|
|
39
43
|
"peerDependencies": {
|
|
40
|
-
"react": ">=17
|
|
44
|
+
"react": ">=17"
|
|
41
45
|
},
|
|
42
46
|
"dependencies": {
|
|
43
|
-
"@mapfirst.ai/core": "
|
|
44
|
-
},
|
|
45
|
-
"scripts": {
|
|
46
|
-
"build": "tsup src/index.tsx --format esm,cjs --dts --sourcemap --clean"
|
|
47
|
+
"@mapfirst.ai/core": "workspace:*"
|
|
47
48
|
}
|
|
48
49
|
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/components/SmartFilter.tsx","../src/components/smart-filter/FilterChips.tsx","../src/components/smart-filter/CloseButton.tsx","../src/components/Icons.tsx","../src/components/smart-filter/Chip.tsx","../src/components/smart-filter/MinRatingFilterChip.tsx","../src/hooks/useTranslation.ts","../src/components/smart-filter/utils.tsx","../src/components/smart-filter/PriceRangeFilterChip.tsx","../src/components/smart-filter/RestaurantPriceLevelChip.tsx","../src/components/smart-filter/TransformedQueryChip.tsx","../src/hooks/useFilterScroll.ts"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n// Export filter utilities from core\nexport {\n processApiFilters,\n convertToApiFilters,\n type ApiFiltersResponse,\n} from \"@mapfirst.ai/core\";\n\n// Export all components\nexport * from \"./components\";\n\n// Export all hooks\nexport * from \"./hooks\";\n\n// Import additional types for search functionality\ntype InitialRequestBody = {\n initial?: boolean;\n query?: string;\n bounds?: {\n sw: { lat: number; lng: number };\n ne: { lat: number; lng: number };\n };\n filters?: any;\n city?: string;\n country?: string;\n location_id?: number;\n longitude?: number;\n latitude?: number;\n radius?: number;\n};\n\ntype SmartFilter = {\n id: string;\n label: string;\n type:\n | \"amenity\"\n | \"hotelStyle\"\n | \"priceRange\"\n | \"minRating\"\n | \"starRating\"\n | \"primary_type\"\n | \"transformed_query\"\n | \"selected_restaurant_price_levels\";\n value: string;\n numericValue?: number;\n priceRange?: {\n min: number;\n max?: number;\n };\n propertyType?: PropertyType;\n priceLevels?: any[];\n};\n\n/**\n * Comprehensive hook for MapFirst SDK with all functionality in one place.\n * Creates a MapFirstCore instance with reactive state and provides all necessary methods.\n *\n * @example\n * ```tsx\n * // Initialize with location data\n * const {\n * instance,\n * state,\n * setPrimaryType,\n * setSelectedMarker,\n * propertiesSearch,\n * smartFilterSearch,\n * boundsSearch,\n * attachMapLibre,\n * attachGoogle,\n * attachMapbox\n * } = useMapFirst({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * console.log(state?.isSearching);\n * console.log(state?.selectedPropertyId);\n *\n * // Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance) {\n * attachMapLibre(mapLibreInstance, maplibregl, {\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance]);\n *\n * // Use search methods\n * await propertiesSearch.search({\n * body: { city: \"Paris\", country: \"France\" }\n * });\n *\n * await smartFilterSearch.search({\n * query: \"hotels near beach with pool\"\n * });\n *\n * await boundsSearch.perform();\n * ```\n */\nexport function useMapFirst(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onPendingBoundsChange: (pendingBounds) => {\n setState((prev) => (prev ? { ...prev, pendingBounds } : null));\n optionsRef.current.callbacks?.onPendingBoundsChange?.(pendingBounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Primary type control\n const setPrimaryType = React.useCallback((type: PropertyType) => {\n if (instanceRef.current) {\n instanceRef.current.setPrimaryType(type);\n }\n }, []);\n\n // Selected marker control\n const setSelectedMarker = React.useCallback((id: number | null) => {\n if (instanceRef.current) {\n instanceRef.current.setSelectedMarker(id);\n }\n }, []);\n\n // Use API control\n const setUseApi = React.useCallback(\n (useApi: boolean, autoLoad: boolean = true) => {\n if (instanceRef.current) {\n instanceRef.current.setUseApi(useApi, autoLoad);\n }\n },\n []\n );\n\n // Properties search\n const propertiesSearch = React.useMemo(\n () => ({\n search: async (options: {\n body: InitialRequestBody;\n beforeApplyProperties?: (data: any) => {\n price?: any;\n limit?: number;\n };\n smartFiltersClearable?: boolean;\n onError?: (error: unknown) => void;\n }) => {\n if (!instanceRef.current) {\n throw new Error(\"MapFirst instance not available\");\n }\n\n return await instanceRef.current.runPropertiesSearch(options);\n },\n }),\n []\n );\n\n // Smart filter search\n const smartFilterSearch = React.useMemo(\n () => ({\n search: async (options: {\n query?: string;\n filters?: SmartFilter[];\n onProcessFilters?: (\n filters: any,\n location_id?: number\n ) => {\n smartFilters?: SmartFilter[];\n price?: any;\n limit?: number;\n language?: string;\n };\n onError?: (error: unknown) => void;\n }) => {\n if (!instanceRef.current) {\n throw new Error(\"MapFirst instance not available\");\n }\n\n return await instanceRef.current.runSmartFilterSearch(options);\n },\n }),\n []\n );\n\n // Bounds search\n const boundsSearch = React.useMemo(\n () => ({\n perform: async () => {\n if (!instanceRef.current) {\n return null;\n }\n\n return await instanceRef.current.performBoundsSearch();\n },\n }),\n []\n );\n\n // Map attachment helpers\n const mapLibreAttachedRef = React.useRef(false);\n const attachMapLibre = React.useCallback(\n (\n map: any,\n maplibregl: MapLibreNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !mapLibreAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick: options?.onMarkerClick,\n });\n mapLibreAttachedRef.current = true;\n }\n },\n []\n );\n\n const googleMapsAttachedRef = React.useRef(false);\n const attachGoogle = React.useCallback(\n (\n map: any,\n google: GoogleMapsNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !googleMapsAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick: options?.onMarkerClick,\n });\n googleMapsAttachedRef.current = true;\n }\n },\n []\n );\n\n const mapboxAttachedRef = React.useRef(false);\n const attachMapbox = React.useCallback(\n (\n map: any,\n mapboxgl: MapboxNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !mapboxAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick: options?.onMarkerClick,\n });\n mapboxAttachedRef.current = true;\n }\n },\n []\n );\n\n return {\n instance: instanceRef.current,\n state,\n setPrimaryType,\n setSelectedMarker,\n setUseApi,\n propertiesSearch,\n smartFilterSearch,\n boundsSearch,\n attachMapLibre,\n attachGoogle,\n attachMapbox,\n };\n}\n","import { FunctionComponent, useCallback, CSSProperties } from \"react\";\r\nimport { FilterChips } from \"./smart-filter/FilterChips\";\r\nimport { useTranslation } from \"../hooks/useTranslation\";\r\nimport type { Filter } from \"./smart-filter/types\";\r\n\r\nexport interface SmartFilterProps {\r\n filters: Filter[];\r\n isSearching?: boolean;\r\n onFilterChange: (filters: Filter[]) => Promise<void> | void;\r\n customTranslations?: Record<string, string>;\r\n currency?: string;\r\n style?: CSSProperties;\r\n containerStyle?: CSSProperties;\r\n}\r\n\r\nconst containerStyles: CSSProperties = {\r\n position: \"relative\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: \"8px\",\r\n width: \"100%\",\r\n};\r\n/**\r\n * SmartFilter component for AI-powered search with filter chips.\r\n * Provides a search input with smart filtering capabilities.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { mapFirst, state } = useMapFirstCore({ ... });\r\n * const [filters, setFilters] = useState<Filter[]>([]);\r\n * const [searchValue, setSearchValue] = useState(\"\");\r\n *\r\n * const handleSearch = async (query: string, currentFilters?: Filter[]) => {\r\n * // Perform search using mapFirst.runSmartFilterSearch\r\n * const result = await mapFirst.runSmartFilterSearch({\r\n * query,\r\n * filters: currentFilters\r\n * });\r\n * // Update filters based on response\r\n * };\r\n *\r\n * return (\r\n * <SmartFilter\r\n * mapFirst={mapFirst}\r\n * filters={filters}\r\n * value={searchValue}\r\n * isSearching={state?.isSearching}\r\n * onSearch={handleSearch}\r\n * onFilterChange={setFilters}\r\n * onValueChange={setSearchValue}\r\n * />\r\n * );\r\n * ```\r\n */\r\nexport const SmartFilter: FunctionComponent<SmartFilterProps> = ({\r\n filters,\r\n isSearching = false,\r\n onFilterChange,\r\n customTranslations,\r\n currency = \"USD\",\r\n containerStyle,\r\n style,\r\n}) => {\r\n const { t, formatCurrency } = useTranslation(customTranslations);\r\n\r\n const minRatingSuffix = t(\"smartFilter.minRating.suffix\");\r\n const previousFiltersLabel = t(\"smartFilter.nav.previous\");\r\n const nextFiltersLabel = t(\"smartFilter.nav.next\");\r\n const clearAllLabel = t(\"smartFilter.clearAll\");\r\n\r\n const handleFilterChange = useCallback(\r\n async (nextFilters: Filter[], clearAll?: boolean) => {\r\n if (isSearching) {\r\n return;\r\n }\r\n try {\r\n await onFilterChange(nextFilters);\r\n } catch (error) {\r\n console.error(\"Filter change error:\", error);\r\n }\r\n },\r\n [isSearching, onFilterChange]\r\n );\r\n\r\n const resetFilters = useCallback(() => {\r\n void handleFilterChange([]);\r\n }, [handleFilterChange]);\r\n\r\n const clearAllFilters = useCallback(() => {\r\n void handleFilterChange([], true);\r\n }, [handleFilterChange]);\r\n\r\n return (\r\n <div style={{ ...containerStyles, ...containerStyle }}>\r\n {filters.length > 0 && (\r\n <FilterChips\r\n filters={filters}\r\n currency={currency}\r\n minRatingSuffix={minRatingSuffix}\r\n clearAllLabel={clearAllLabel}\r\n previousFiltersLabel={previousFiltersLabel}\r\n nextFiltersLabel={nextFiltersLabel}\r\n formatCurrency={formatCurrency}\r\n onFilterChange={handleFilterChange}\r\n onResetFilters={resetFilters}\r\n onClearAll={clearAllFilters}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React, { FunctionComponent, CSSProperties } from \"react\";\r\nimport { Chip } from \"./Chip\";\r\nimport { MinRatingFilterChip } from \"./MinRatingFilterChip\";\r\nimport { PriceRangeFilterChip } from \"./PriceRangeFilterChip\";\r\nimport { RestaurantPriceLevelChip } from \"./RestaurantPriceLevelChip\";\r\nimport { TransformedQueryChip } from \"./TransformedQueryChip\";\r\nimport { SearchIcon, NextIcon } from \"../Icons\";\r\nimport { useFilterScroll } from \"../../hooks/useFilterScroll\";\r\nimport type { Filter } from \"./types\";\r\n\r\nexport interface FilterChipsProps {\r\n filters: Filter[];\r\n currency: string;\r\n minRatingSuffix: string;\r\n clearAllLabel: string;\r\n previousFiltersLabel: string;\r\n nextFiltersLabel: string;\r\n formatCurrency: (value: number, currency?: string) => string;\r\n onFilterChange: (\r\n filters: Filter[],\r\n clearAll?: boolean\r\n ) => void | Promise<void>;\r\n onResetFilters: () => void;\r\n onClearAll: () => void;\r\n}\r\n\r\nconst containerStyles: CSSProperties = {\r\n position: \"relative\",\r\n width: \"100%\",\r\n};\r\n\r\nconst scrollContainerBase: CSSProperties = {\r\n display: \"flex\",\r\n gap: \"8px\",\r\n overflowX: \"auto\",\r\n alignItems: \"center\",\r\n width: \"100%\",\r\n scrollbarWidth: \"none\",\r\n msOverflowStyle: \"none\",\r\n};\r\n\r\nconst gradientStyles: CSSProperties = {\r\n pointerEvents: \"none\",\r\n position: \"absolute\",\r\n top: 0,\r\n bottom: 0,\r\n width: \"40px\",\r\n};\r\n\r\nconst navButtonStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: \"50%\",\r\n transform: \"translateY(-50%)\",\r\n backgroundColor: \"white\",\r\n color: \"#003c30\",\r\n border: \"1px solid #003c30\",\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n boxShadow: \"0 1px 3px rgba(0,0,0,0.1)\",\r\n cursor: \"pointer\",\r\n};\r\n\r\nexport const FilterChips: FunctionComponent<FilterChipsProps> = ({\r\n filters,\r\n currency,\r\n minRatingSuffix,\r\n clearAllLabel,\r\n previousFiltersLabel,\r\n nextFiltersLabel,\r\n formatCurrency,\r\n onFilterChange,\r\n onResetFilters,\r\n onClearAll,\r\n}) => {\r\n const { scrollerRef, atStart, atEnd, scrollByDir } = useFilterScroll(\r\n filters.length\r\n );\r\n const [navHover, setNavHover] = React.useState<\"prev\" | \"next\" | null>(null);\r\n const [clearHover, setClearHover] = React.useState(false);\r\n\r\n return (\r\n <div style={containerStyles}>\r\n <div\r\n ref={scrollerRef}\r\n style={{\r\n ...scrollContainerBase,\r\n padding: \"8px\",\r\n // Hide scrollbar for webkit browsers\r\n WebkitOverflowScrolling: \"touch\",\r\n }}\r\n >\r\n <style>\r\n {`\r\n div::-webkit-scrollbar {\r\n display: none;\r\n }\r\n `}\r\n </style>\r\n {filters.map((filter) => {\r\n const renderStandardChip = () => (\r\n <Chip\r\n key={filter.id}\r\n label={filter.label}\r\n icon={filter.icon}\r\n remove={() => {\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id));\r\n }}\r\n />\r\n );\r\n\r\n if (filter.type === \"minRating\") {\r\n const currentRating = filter.numericValue ?? Number(filter.value);\r\n if (!Number.isFinite(currentRating)) {\r\n return renderStandardChip();\r\n }\r\n\r\n return (\r\n <MinRatingFilterChip\r\n key={filter.id}\r\n rating={currentRating}\r\n onChange={(nextRating) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n numericValue: nextRating,\r\n value: String(nextRating),\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"starRating\") {\r\n const currentRating = filter.numericValue ?? Number(filter.value);\r\n if (!Number.isFinite(currentRating)) {\r\n return renderStandardChip();\r\n }\r\n\r\n return (\r\n <MinRatingFilterChip\r\n star\r\n key={filter.id}\r\n rating={currentRating}\r\n onChange={(nextRating) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n numericValue: nextRating,\r\n value: String(nextRating),\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"priceRange\" && filter.priceRange) {\r\n return (\r\n <PriceRangeFilterChip\r\n key={filter.id}\r\n priceRange={filter.priceRange}\r\n currency={currency}\r\n onChange={(nextRange) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n priceRange: nextRange,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"transformed_query\") {\r\n return (\r\n <TransformedQueryChip\r\n key={filter.id}\r\n value={filter.value}\r\n onChange={(nextValue) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n value: nextValue,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"selected_restaurant_price_levels\") {\r\n return (\r\n <RestaurantPriceLevelChip\r\n key={filter.id}\r\n values={filter.priceLevels ?? []}\r\n onChange={(nextLevels) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n priceLevels: nextLevels,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n return renderStandardChip();\r\n })}\r\n <button\r\n style={{\r\n flexShrink: 0,\r\n padding: \"4px 16px\",\r\n borderRadius: \"9999px\",\r\n cursor: \"pointer\",\r\n fontSize: \"14px\",\r\n userSelect: \"none\",\r\n backgroundColor: clearHover ? \"#eee\" : \"white\",\r\n color: \"black\",\r\n border: \"1px solid #03852e\",\r\n }}\r\n onClick={onClearAll}\r\n onMouseEnter={() => setClearHover(true)}\r\n onMouseLeave={() => setClearHover(false)}\r\n >\r\n {clearAllLabel}\r\n </button>\r\n </div>\r\n\r\n {!atStart && (\r\n <div\r\n aria-hidden=\"true\"\r\n style={{\r\n ...gradientStyles,\r\n left: 0,\r\n background: \"linear-gradient(to right, white, transparent)\",\r\n }}\r\n />\r\n )}\r\n\r\n {!atEnd && (\r\n <div\r\n aria-hidden=\"true\"\r\n style={{\r\n ...gradientStyles,\r\n right: 0,\r\n background: \"linear-gradient(to left, white, transparent)\",\r\n }}\r\n />\r\n )}\r\n\r\n {!atStart && (\r\n <button\r\n type=\"button\"\r\n aria-label={previousFiltersLabel}\r\n style={{\r\n ...navButtonStyles,\r\n left: \"4px\",\r\n transform: \"translateY(-50%) rotate(180deg)\",\r\n backgroundColor: navHover === \"prev\" ? \"#e5e5e5\" : \"white\",\r\n }}\r\n onClick={() => scrollByDir(\"prev\")}\r\n onMouseEnter={() => setNavHover(\"prev\")}\r\n onMouseLeave={() => setNavHover(null)}\r\n >\r\n <NextIcon style={{ width: \"20px\", height: \"20px\" }} />\r\n </button>\r\n )}\r\n\r\n {!atEnd && (\r\n <button\r\n type=\"button\"\r\n aria-label={nextFiltersLabel}\r\n style={{\r\n ...navButtonStyles,\r\n right: \"4px\",\r\n backgroundColor: navHover === \"next\" ? \"#e5e5e5\" : \"white\",\r\n }}\r\n onClick={() => scrollByDir(\"next\")}\r\n onMouseEnter={() => setNavHover(\"next\")}\r\n onMouseLeave={() => setNavHover(null)}\r\n >\r\n <NextIcon style={{ width: \"20px\", height: \"20px\" }} />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React, { CSSProperties } from \"react\";\r\nimport { CloseIcon } from \"../Icons\";\r\n\r\nexport interface CloseButtonProps {\r\n onClick: () => void;\r\n style?: CSSProperties;\r\n}\r\n\r\nconst closeButtonStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: \"-8px\",\r\n right: \"-8px\",\r\n padding: \"2px\",\r\n borderRadius: \"50%\",\r\n backgroundColor: \"white\",\r\n border: \"1px solid #03852e\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: \"background-color 0.2s\",\r\n};\r\n\r\nconst iconStyles: CSSProperties = {\r\n width: \"17px\",\r\n height: \"17px\",\r\n};\r\n\r\nexport const CloseButton: React.FC<CloseButtonProps> = ({ onClick, style }) => {\r\n const [isHovering, setIsHovering] = React.useState(false);\r\n\r\n return (\r\n <button\r\n style={{\r\n ...closeButtonStyles,\r\n backgroundColor: isHovering ? \"#e5e5e5\" : \"white\",\r\n ...style,\r\n }}\r\n onClick={onClick}\r\n onMouseEnter={() => setIsHovering(true)}\r\n onMouseLeave={() => setIsHovering(false)}\r\n aria-label=\"Remove filter\"\r\n >\r\n <CloseIcon style={iconStyles} />\r\n </button>\r\n );\r\n};\r\n","import React, { CSSProperties } from \"react\";\r\n\r\nexport interface IconProps {\r\n className?: string;\r\n style?: CSSProperties;\r\n}\r\n\r\nexport const SearchIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <path d=\"m21 21-4.35-4.35\" />\r\n </svg>\r\n);\r\n\r\nexport const CloseIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n);\r\n\r\nexport const EditIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\r\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\r\n </svg>\r\n);\r\n\r\nexport const NextIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <polyline points=\"9 18 15 12 9 6\" />\r\n </svg>\r\n);\r\n\r\nexport const StarIcon: React.FC<IconProps & { fill?: string }> = ({\r\n className,\r\n style,\r\n fill = \"none\",\r\n}) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill={fill}\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <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\" />\r\n </svg>\r\n);\r\n","import React, { CSSProperties, ReactNode } from \"react\";\r\nimport { CloseButton } from \"./CloseButton\";\r\n\r\nexport interface ChipProps {\r\n label: string | ReactNode;\r\n icon?: ReactNode;\r\n remove: () => void;\r\n style?: CSSProperties;\r\n}\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nexport const Chip: React.FC<ChipProps> = ({ label, icon, remove, style }) => {\r\n return (\r\n <div style={{ ...chipStyles, ...style }}>\r\n {icon && (\r\n <span style={{ display: \"flex\", alignItems: \"center\" }}>{icon}</span>\r\n )}\r\n <span style={{ whiteSpace: \"nowrap\" }}>{label}</span>\r\n <CloseButton onClick={remove} />\r\n </div>\r\n );\r\n};\r\n","import React, {\r\n FunctionComponent,\r\n useState,\r\n FocusEvent,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { StarIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport { formatRatingValue } from \"./utils\";\r\n\r\nconst chipContainerStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n gap: \"8px\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst starContainerStyles: CSSProperties = {\r\n display: \"flex\",\r\n gap: \"1px\",\r\n userSelect: \"none\",\r\n};\r\n\r\nconst circleBaseStyles: CSSProperties = {\r\n display: \"block\",\r\n width: \"12px\",\r\n height: \"12px\",\r\n borderRadius: \"50%\",\r\n border: \"1px solid #03852e\",\r\n pointerEvents: \"none\",\r\n};\r\n\r\nconst buttonBaseStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: 0,\r\n height: \"100%\",\r\n cursor: \"pointer\",\r\n backgroundColor: \"transparent\",\r\n border: \"none\",\r\n padding: 0,\r\n};\r\n\r\nexport const MinRatingFilterChip: FunctionComponent<{\r\n star?: boolean;\r\n rating: number;\r\n onChange: (rating: number) => void;\r\n onRemove: () => void;\r\n}> = ({ rating, onChange, onRemove, star = false }) => {\r\n const [hoverRating, setHoverRating] = useState<number | null>(null);\r\n const { t } = useTranslation();\r\n\r\n const displayRating = hoverRating ?? rating;\r\n const formatLabel = (value: number) =>\r\n star && value\r\n ? value.toString()\r\n : t(\"smartFilter.minRating.label\", { value: formatRatingValue(value) });\r\n const removeLabel = t(\"smartFilter.minRating.remove\");\r\n const setLabel = (value: number) =>\r\n t(\"smartFilter.minRating.setTo\", { rating: formatRatingValue(value) });\r\n\r\n const getFillForStar = (index: number) => {\r\n const starNumber = index + 1;\r\n if (displayRating >= starNumber) {\r\n return \"full\" as const;\r\n }\r\n if (displayRating >= starNumber - 0.5) {\r\n return \"half\" as const;\r\n }\r\n return \"empty\" as const;\r\n };\r\n\r\n const handleSelect = (nextRating: number) => {\r\n setHoverRating(null);\r\n if (nextRating === rating) {\r\n return;\r\n }\r\n onChange(nextRating);\r\n };\r\n\r\n const handleBlur = (event: FocusEvent<HTMLButtonElement>) => {\r\n const related = event.relatedTarget as HTMLElement | null;\r\n if (\r\n !related ||\r\n !(event.currentTarget as HTMLElement)\r\n .closest(\"[data-min-rating-chip]\")\r\n ?.contains(related)\r\n ) {\r\n setHoverRating(null);\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipContainerStyles} data-min-rating-chip>\r\n <div\r\n style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}\r\n onMouseLeave={() => setHoverRating(null)}\r\n >\r\n <div style={starContainerStyles}>\r\n {Array.from({ length: 5 }).map((_, index) => {\r\n const fillState = getFillForStar(index);\r\n const starNumber = index + 1;\r\n const halfValue = starNumber - 0.5;\r\n\r\n if (star) {\r\n return (\r\n <div\r\n key={index}\r\n style={{\r\n position: \"relative\",\r\n width: \"16px\",\r\n height: \"16px\",\r\n }}\r\n >\r\n <StarIcon\r\n fill={displayRating >= starNumber ? \"#03852e\" : \"none\"}\r\n style={{\r\n width: \"16px\",\r\n height: \"16px\",\r\n pointerEvents: \"none\",\r\n }}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: 0,\r\n width: \"50%\",\r\n borderRadius: \"50% 0 0 50%\",\r\n }}\r\n onMouseEnter={() => setHoverRating(halfValue)}\r\n onFocus={() => setHoverRating(halfValue)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(halfValue)}\r\n aria-label={setLabel(halfValue)}\r\n title={formatLabel(halfValue)}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: \"50%\",\r\n width: \"50%\",\r\n borderRadius: \"0 50% 50% 0\",\r\n }}\r\n onMouseEnter={() => setHoverRating(starNumber)}\r\n onFocus={() => setHoverRating(starNumber)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(starNumber)}\r\n aria-label={setLabel(starNumber)}\r\n title={formatLabel(starNumber)}\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n const circleStyles: CSSProperties =\r\n fillState === \"full\"\r\n ? { ...circleBaseStyles, backgroundColor: \"#03852e\" }\r\n : circleBaseStyles;\r\n\r\n const halfCircleStyles: CSSProperties = {\r\n ...circleBaseStyles,\r\n background:\r\n \"linear-gradient(90deg, #03852e 50%, transparent 50%)\",\r\n };\r\n\r\n return (\r\n <div\r\n key={index}\r\n style={{ position: \"relative\", width: \"12px\", height: \"12px\" }}\r\n >\r\n <span\r\n style={fillState === \"half\" ? halfCircleStyles : circleStyles}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: 0,\r\n width: \"50%\",\r\n borderRadius: \"50% 0 0 50%\",\r\n outline: \"2px solid transparent\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={() => setHoverRating(halfValue)}\r\n onFocus={() => setHoverRating(halfValue)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(halfValue)}\r\n aria-label={setLabel(halfValue)}\r\n title={formatLabel(halfValue)}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: \"50%\",\r\n width: \"50%\",\r\n borderRadius: \"0 50% 50% 0\",\r\n outline: \"2px solid transparent\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={() => setHoverRating(starNumber)}\r\n onFocus={() => setHoverRating(starNumber)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(starNumber)}\r\n aria-label={setLabel(starNumber)}\r\n title={formatLabel(starNumber)}\r\n />\r\n </div>\r\n );\r\n })}\r\n </div>\r\n <span style={{ whiteSpace: \"nowrap\" }}>\r\n {formatLabel(displayRating)}\r\n </span>\r\n </div>\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import { useCallback, useState } from \"react\";\r\n\r\nexport type Locale = \"en\" | \"es\" | \"de\" | \"fr\" | \"it\" | \"pt\";\r\n\r\ntype TranslationFunction = (\r\n key: string,\r\n params?: Record<string, any>\r\n) => string;\r\ntype FormatCurrencyFunction = (value: number, currency?: string) => string;\r\n\r\nconst defaultTranslations: Record<string, string> = {\r\n \"smartFilter.typingPrompt\":\r\n \"Search for hotels, restaurants, or attractions...\",\r\n \"smartFilter.nav.previous\": \"Previous filters\",\r\n \"smartFilter.nav.next\": \"Next filters\",\r\n \"smartFilter.toast.locationRequired\": \"Please select a location first\",\r\n \"smartFilter.clearAll\": \"Clear all\",\r\n \"smartFilter.minRating.suffix\": \"+\",\r\n \"smartFilter.minRating.label\": \"{{value}}+\",\r\n \"smartFilter.minRating.remove\": \"Remove rating filter\",\r\n \"smartFilter.minRating.setTo\": \"Set rating to {{rating}}\",\r\n \"smartFilter.priceRange.label\": \"Price Range\",\r\n \"smartFilter.priceRange.remove\": \"Remove price filter\",\r\n \"smartFilter.priceRange.edit\": \"Edit price\",\r\n \"smartFilter.transformedQuery.remove\": \"Remove search query\",\r\n \"smartFilter.transformedQuery.edit\": \"Edit search query\",\r\n \"smartFilter.restaurantPriceLevel.label\": \"Price Level\",\r\n \"smartFilter.restaurantPriceLevel.remove\": \"Remove price level filter\",\r\n \"smartFilter.restaurantPriceLevel.none\": \"Any\",\r\n \"smartFilter.restaurantPriceLevel.options.cheapEats\": \"Cheap Eats\",\r\n \"smartFilter.restaurantPriceLevel.options.midRange\": \"Mid Range\",\r\n \"smartFilter.restaurantPriceLevel.options.fineDining\": \"Fine Dining\",\r\n};\r\n\r\nconst formatCurrencyDefault: FormatCurrencyFunction = (\r\n value,\r\n currency = \"USD\"\r\n) => {\r\n return new Intl.NumberFormat(\"en-US\", {\r\n style: \"currency\",\r\n currency: currency,\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 0,\r\n }).format(value);\r\n};\r\n\r\n/**\r\n * Simple translation hook with default English translations.\r\n * Can be extended with custom translations and locales.\r\n */\r\nexport const useTranslation = (\r\n customTranslations?: Record<string, string>,\r\n customFormatCurrency?: FormatCurrencyFunction\r\n) => {\r\n const [locale, setLocale] = useState<Locale>(\"en\");\r\n\r\n const t: TranslationFunction = useCallback(\r\n (key: string, params?: Record<string, any>) => {\r\n const translations = { ...defaultTranslations, ...customTranslations };\r\n let translation = translations[key] || key;\r\n\r\n if (params) {\r\n Object.keys(params).forEach((paramKey) => {\r\n translation = translation.replace(\r\n new RegExp(`{{${paramKey}}}`, \"g\"),\r\n String(params[paramKey])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n },\r\n [customTranslations]\r\n );\r\n\r\n const formatCurrency = useCallback(\r\n (value: number, currency?: string) => {\r\n if (customFormatCurrency) {\r\n return customFormatCurrency(value, currency);\r\n }\r\n return formatCurrencyDefault(value, currency);\r\n },\r\n [customFormatCurrency]\r\n );\r\n\r\n return {\r\n t,\r\n locale,\r\n setLocale,\r\n formatCurrency,\r\n };\r\n};\r\n","import React, { ReactNode, CSSProperties } from \"react\";\r\n\r\nexport const renderStars = (rating: number): ReactNode[] => {\r\n const stars: ReactNode[] = [];\r\n const fullStars = Math.floor(rating);\r\n const hasHalfStar = rating % 1 !== 0;\r\n\r\n const baseStyles: CSSProperties = {\r\n display: \"block\",\r\n width: \"12px\",\r\n height: \"12px\",\r\n borderRadius: \"50%\",\r\n border: \"1px solid #03852e\",\r\n pointerEvents: \"none\",\r\n };\r\n\r\n const fullStarStyles: CSSProperties = {\r\n ...baseStyles,\r\n backgroundColor: \"#03852e\",\r\n };\r\n\r\n const halfStarStyles: CSSProperties = {\r\n ...baseStyles,\r\n background: \"linear-gradient(90deg, #03852e 50%, transparent 50%)\",\r\n };\r\n\r\n for (let i = 0; i < fullStars; i += 1) {\r\n stars.push(<span key={`full-${i}`} style={fullStarStyles} />);\r\n }\r\n\r\n if (hasHalfStar) {\r\n stars.push(<span key=\"half\" style={halfStarStyles} />);\r\n }\r\n\r\n const remainingStars = Math.max(0, 5 - Math.ceil(rating));\r\n for (let i = 0; i < remainingStars; i += 1) {\r\n stars.push(<span key={`empty-${i}`} style={baseStyles} />);\r\n }\r\n\r\n return stars;\r\n};\r\n\r\nexport const createMinRatingFilterLabel = (\r\n rating: number,\r\n suffix?: string\r\n): ReactNode => (\r\n <span style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}>\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: \"1px\",\r\n userSelect: \"none\",\r\n }}\r\n >\r\n {renderStars(rating)}\r\n </span>{\" \"}\r\n {suffix}\r\n </span>\r\n);\r\n\r\nexport const formatRatingValue = (rating: number): string => rating.toFixed(1);\r\n\r\nexport const createPriceRangeFilterLabel = (\r\n min: number,\r\n max: number | undefined,\r\n currency: string | undefined,\r\n formatCurrencyFn: (value: number, currency?: string) => string\r\n): string =>\r\n `${formatCurrencyFn(min, currency)} - ${formatCurrencyFn(\r\n max ?? 0,\r\n currency\r\n )}`;\r\n","import React, {\r\n ChangeEvent,\r\n FunctionComponent,\r\n KeyboardEvent,\r\n useEffect,\r\n useState,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { EditIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport type { PriceRangeValue } from \"./types\";\r\n\r\ntype Boundary = \"min\" | \"max\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst inputStyles: CSSProperties = {\r\n outline: \"none\",\r\n fontSize: \"16px\",\r\n backgroundColor: \"transparent\",\r\n borderRadius: \"2px\",\r\n padding: \"2px 8px\",\r\n width: \"64px\",\r\n textAlign: \"center\",\r\n border: \"none\",\r\n};\r\n\r\nconst editButtonStyles: CSSProperties = {\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.2s\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n color: \"#737373\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n};\r\n\r\ninterface PriceBoundaryChipProps {\r\n boundary: Boundary;\r\n label: string;\r\n value?: number;\r\n placeholder?: string;\r\n currency: string;\r\n isOptional?: boolean;\r\n showRemoveButton?: boolean;\r\n removeLabel?: string;\r\n editLabel?: string;\r\n showAddWhenEmpty?: boolean;\r\n onCommit: (value?: number) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nconst PriceBoundaryChip: FunctionComponent<PriceBoundaryChipProps> = ({\r\n boundary,\r\n label,\r\n value,\r\n placeholder,\r\n currency,\r\n isOptional = false,\r\n showRemoveButton = false,\r\n removeLabel,\r\n editLabel,\r\n showAddWhenEmpty = false,\r\n onCommit,\r\n onRemove,\r\n}) => {\r\n const [draft, setDraft] = useState<string>(\r\n value !== undefined ? String(value) : \"\"\r\n );\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editHover, setEditHover] = useState(false);\r\n const hasValue = value !== undefined;\r\n\r\n useEffect(() => {\r\n setDraft(value !== undefined ? String(value) : \"\");\r\n setIsEditing(false);\r\n }, [value]);\r\n\r\n const resetDraft = () => {\r\n setDraft(value !== undefined ? String(value) : \"\");\r\n };\r\n\r\n const commitValue = () => {\r\n if (draft.trim() === \"\") {\r\n if (isOptional) {\r\n onCommit(undefined);\r\n setDraft(\"\");\r\n return;\r\n }\r\n resetDraft();\r\n return;\r\n }\r\n\r\n const parsed = Number(draft);\r\n if (!Number.isFinite(parsed)) {\r\n resetDraft();\r\n return;\r\n }\r\n\r\n const normalized = Math.max(0, parsed);\r\n if (normalized === value) {\r\n resetDraft();\r\n return;\r\n }\r\n onCommit(normalized);\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n const next = event.target.value.replace(/[^\\d]/g, \"\");\r\n setDraft(next);\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n setIsEditing(false);\r\n return;\r\n }\r\n\r\n if (event.key === \"Escape\") {\r\n event.preventDefault();\r\n resetDraft();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n setIsEditing(false);\r\n return;\r\n }\r\n\r\n const allowed =\r\n (event.key.length === 1 && /[0-9]/.test(event.key)) ||\r\n event.key === \"Backspace\" ||\r\n event.key === \"Delete\" ||\r\n event.key === \"Tab\" ||\r\n event.key === \"ArrowLeft\" ||\r\n event.key === \"ArrowRight\" ||\r\n event.key === \"Home\" ||\r\n event.key === \"End\";\r\n\r\n if (!allowed) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <span\r\n style={{\r\n fontSize: \"10px\",\r\n textTransform: \"uppercase\",\r\n fontWeight: 600,\r\n letterSpacing: \"0.05em\",\r\n }}\r\n >\r\n {label}\r\n </span>\r\n {isEditing ? (\r\n <input\r\n value={draft}\r\n onChange={handleChange}\r\n onBlur={() => {\r\n commitValue();\r\n setIsEditing(false);\r\n }}\r\n onKeyDown={handleKeyDown}\r\n placeholder={placeholder}\r\n inputMode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n aria-label={label}\r\n style={inputStyles}\r\n autoFocus\r\n />\r\n ) : hasValue ? (\r\n <span style={{ fontSize: \"16px\" }}>\r\n {currency}\r\n {value}\r\n </span>\r\n ) : showAddWhenEmpty ? (\r\n <button\r\n type=\"button\"\r\n style={{\r\n fontSize: \"16px\",\r\n color: \"#737373\",\r\n cursor: \"pointer\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n padding: 0,\r\n }}\r\n onClick={() => setIsEditing(true)}\r\n aria-label={editLabel}\r\n >\r\n +\r\n </button>\r\n ) : (\r\n <span style={{ fontSize: \"16px\", color: \"#737373\" }}>-</span>\r\n )}\r\n {(!showAddWhenEmpty || (showAddWhenEmpty && isEditing)) && (\r\n <span style={{ color: \"#737373\", fontSize: \"12px\" }}>{currency}</span>\r\n )}\r\n {!isEditing && (!showAddWhenEmpty || hasValue) && (\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...editButtonStyles,\r\n backgroundColor: editHover ? \"#e5e5e5\" : \"transparent\",\r\n }}\r\n aria-label={editLabel}\r\n title={editLabel}\r\n onClick={() => setIsEditing(true)}\r\n onMouseEnter={() => setEditHover(true)}\r\n onMouseLeave={() => setEditHover(false)}\r\n >\r\n <EditIcon />\r\n </button>\r\n )}\r\n {showRemoveButton && <CloseButton onClick={onRemove} />}\r\n </div>\r\n );\r\n};\r\n\r\nexport const PriceRangeFilterChip: FunctionComponent<{\r\n priceRange: PriceRangeValue;\r\n currency: string;\r\n onChange: (range: PriceRangeValue) => void;\r\n onRemove: () => void;\r\n}> = ({ priceRange, currency, onChange, onRemove }) => {\r\n const { t } = useTranslation();\r\n\r\n const minLabel = \"Min\";\r\n const maxChipLabel = \"Max\";\r\n const removeLabel = t(\"smartFilter.priceRange.remove\");\r\n const editLabel = t(\"smartFilter.priceRange.edit\");\r\n\r\n const handleBoundaryCommit = (boundary: Boundary, nextValue?: number) => {\r\n const nextRange: PriceRangeValue = {\r\n min: priceRange.min,\r\n max: priceRange.max,\r\n };\r\n\r\n if (boundary === \"min\") {\r\n nextRange.min = nextValue;\r\n if (\r\n nextValue !== undefined &&\r\n priceRange.max !== undefined &&\r\n nextValue > priceRange.max\r\n ) {\r\n nextRange.max = nextValue;\r\n }\r\n } else {\r\n nextRange.max = nextValue;\r\n if (\r\n nextValue !== undefined &&\r\n priceRange.min !== undefined &&\r\n nextValue < priceRange.min\r\n ) {\r\n nextRange.min = nextValue;\r\n }\r\n }\r\n\r\n if (nextRange.min !== priceRange.min || nextRange.max !== priceRange.max) {\r\n onChange(nextRange);\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <PriceBoundaryChip\r\n boundary=\"min\"\r\n label={minLabel}\r\n value={priceRange.min}\r\n currency={currency}\r\n editLabel={editLabel}\r\n showRemoveButton={priceRange.min !== undefined && priceRange.min !== 0}\r\n onCommit={(value) => handleBoundaryCommit(\"min\", value)}\r\n onRemove={onRemove}\r\n />\r\n <PriceBoundaryChip\r\n boundary=\"max\"\r\n label={maxChipLabel}\r\n value={priceRange.max}\r\n currency={currency}\r\n isOptional\r\n showRemoveButton={priceRange.max !== undefined}\r\n removeLabel={removeLabel}\r\n editLabel={editLabel}\r\n showAddWhenEmpty\r\n onCommit={(value) => handleBoundaryCommit(\"max\", value)}\r\n onRemove={onRemove}\r\n />\r\n </>\r\n );\r\n};\r\n","import React, { ChangeEvent, FunctionComponent, CSSProperties } from \"react\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport type { PriceLevel } from \"@mapfirst.ai/core\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"16px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst PRICE_LEVEL_OPTIONS = [\r\n { value: \"Cheap Eats\" as PriceLevel, key: \"cheapEats\" },\r\n { value: \"Mid Range\" as PriceLevel, key: \"midRange\" },\r\n { value: \"Fine Dining\" as PriceLevel, key: \"fineDining\" },\r\n] as const;\r\n\r\nexport interface RestaurantPriceLevelChipProps {\r\n values: PriceLevel[];\r\n onChange: (values: PriceLevel[]) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nexport const RestaurantPriceLevelChip: FunctionComponent<\r\n RestaurantPriceLevelChipProps\r\n> = ({ values, onChange, onRemove }) => {\r\n const { t } = useTranslation();\r\n\r\n const label = t(\"smartFilter.restaurantPriceLevel.label\");\r\n const removeLabel = t(\"smartFilter.restaurantPriceLevel.remove\");\r\n const noneSelectedLabel = t(\"smartFilter.restaurantPriceLevel.none\");\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n const { value, checked } = event.target;\r\n const valueAsPriceLevel = value as PriceLevel;\r\n const selection = new Set(values);\r\n if (checked) {\r\n selection.add(valueAsPriceLevel);\r\n } else {\r\n selection.delete(valueAsPriceLevel);\r\n }\r\n const orderedSelection = PRICE_LEVEL_OPTIONS.filter((option) =>\r\n selection.has(option.value)\r\n ).map((option) => option.value);\r\n onChange(orderedSelection);\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexWrap: \"wrap\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontSize: \"10px\",\r\n textTransform: \"uppercase\",\r\n fontWeight: 600,\r\n letterSpacing: \"0.05em\",\r\n }}\r\n >\r\n {label}\r\n </span>\r\n <div style={{ display: \"flex\", gap: \"12px\" }}>\r\n {PRICE_LEVEL_OPTIONS.map((option) => {\r\n const optionLabel = t(\r\n `smartFilter.restaurantPriceLevel.options.${option.key}`\r\n );\r\n const checkboxId = `price-level-${option.key}`;\r\n return (\r\n <label\r\n key={option.value}\r\n htmlFor={checkboxId}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"4px\",\r\n fontSize: \"12px\",\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n <input\r\n id={checkboxId}\r\n type=\"checkbox\"\r\n value={option.value}\r\n checked={values.includes(option.value)}\r\n onChange={handleChange}\r\n style={{ accentColor: \"#03852e\", cursor: \"pointer\" }}\r\n />\r\n <span>{optionLabel}</span>\r\n </label>\r\n );\r\n })}\r\n {values.length === 0 && (\r\n <span style={{ fontSize: \"12px\", color: \"#737373\" }}>\r\n {noneSelectedLabel}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import React, {\r\n ChangeEvent,\r\n FunctionComponent,\r\n KeyboardEvent,\r\n useEffect,\r\n useRef,\r\n useState,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { EditIcon, SearchIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n userSelect: \"none\",\r\n height: \"34px\",\r\n};\r\n\r\nconst inputStyles: CSSProperties = {\r\n backgroundColor: \"#ececec\",\r\n borderRadius: \"2px\",\r\n padding: \"2px 8px\",\r\n outline: \"none\",\r\n fontSize: \"16px\",\r\n minWidth: \"8ch\",\r\n border: \"none\",\r\n};\r\n\r\nconst editButtonStyles: CSSProperties = {\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.2s\",\r\n color: \"#737373\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n};\r\n\r\nexport interface TransformedQueryChipProps {\r\n value: string;\r\n onChange: (nextValue: string) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nexport const TransformedQueryChip: FunctionComponent<\r\n TransformedQueryChipProps\r\n> = ({ value, onChange, onRemove }) => {\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const [draft, setDraft] = useState(value);\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editHover, setEditHover] = useState(false);\r\n const { t } = useTranslation();\r\n\r\n const removeLabel = t(\"smartFilter.transformedQuery.remove\");\r\n const editLabel = t(\"smartFilter.transformedQuery.edit\");\r\n\r\n useEffect(() => {\r\n setDraft(value);\r\n setIsEditing(false);\r\n }, [value]);\r\n\r\n const applyChanges = () => {\r\n const nextValue = draft.trim();\r\n if (!nextValue.length) {\r\n setDraft(value);\r\n return;\r\n }\r\n if (nextValue === value) {\r\n return;\r\n }\r\n onChange(nextValue);\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n setDraft(event.target.value);\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n return;\r\n }\r\n\r\n if (event.key === \"Escape\") {\r\n event.preventDefault();\r\n setDraft(value);\r\n (event.currentTarget as HTMLInputElement).blur();\r\n return;\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <SearchIcon style={{ width: \"16px\", height: \"16px\", color: \"#03852e\" }} />\r\n {isEditing ? (\r\n <input\r\n ref={inputRef}\r\n value={draft}\r\n onChange={handleChange}\r\n onBlur={() => {\r\n applyChanges();\r\n setIsEditing(false);\r\n }}\r\n onKeyDown={handleKeyDown}\r\n aria-label={editLabel}\r\n style={inputStyles}\r\n autoFocus\r\n />\r\n ) : (\r\n <span style={{ fontSize: \"16px\" }}>{value}</span>\r\n )}\r\n {!isEditing && (\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...editButtonStyles,\r\n backgroundColor: editHover ? \"#e5e5e5\" : \"transparent\",\r\n }}\r\n aria-label={editLabel}\r\n title={editLabel}\r\n onClick={() => setIsEditing(true)}\r\n onMouseEnter={() => setEditHover(true)}\r\n onMouseLeave={() => setEditHover(false)}\r\n >\r\n <EditIcon />\r\n </button>\r\n )}\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\nexport const useFilterScroll = (dependency: number) => {\r\n const scrollerRef = useRef<HTMLDivElement | null>(null);\r\n const [atStart, setAtStart] = useState(true);\r\n const [atEnd, setAtEnd] = useState(true);\r\n\r\n const updateScrollButtons = useCallback(() => {\r\n const el = scrollerRef.current;\r\n if (!el) {\r\n setAtStart(true);\r\n setAtEnd(true);\r\n return;\r\n }\r\n\r\n const { scrollLeft, scrollWidth, clientWidth } = el;\r\n setAtStart(scrollLeft <= 0);\r\n setAtEnd(scrollLeft + clientWidth >= scrollWidth - 1);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const el = scrollerRef.current;\r\n updateScrollButtons();\r\n if (!el) {\r\n return;\r\n }\r\n\r\n const handleScroll = () => updateScrollButtons();\r\n el.addEventListener(\"scroll\", handleScroll, { passive: true });\r\n window.addEventListener(\"resize\", updateScrollButtons);\r\n\r\n return () => {\r\n el.removeEventListener(\"scroll\", handleScroll);\r\n window.removeEventListener(\"resize\", updateScrollButtons);\r\n };\r\n }, [dependency, updateScrollButtons]);\r\n\r\n const scrollByDir = useCallback((dir: \"prev\" | \"next\") => {\r\n const el = scrollerRef.current;\r\n if (!el) {\r\n return;\r\n }\r\n\r\n const delta = el.clientWidth * 0.7;\r\n el.scrollBy({\r\n left: dir === \"next\" ? delta : -delta,\r\n behavior: \"smooth\",\r\n });\r\n }, []);\r\n\r\n return {\r\n scrollerRef,\r\n atStart,\r\n atEnd,\r\n scrollByDir,\r\n };\r\n};\r\n"],"mappings":"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","names":["index_exports","__export","Chip","CloseIcon","EditIcon","FilterChips","MinRatingFilterChip","NextIcon","PriceRangeFilterChip","RestaurantPriceLevelChip","SearchIcon","SmartFilter","StarIcon","TransformedQueryChip","createMinRatingFilterLabel","createPriceRangeFilterLabel","formatRatingValue","renderStars","useFilterScroll","useMapFirst","useTranslation","__toCommonJS","import_react","import_core","import_react","import_react","import_react","import_jsx_runtime","SearchIcon","className","style","CloseIcon","EditIcon","NextIcon","StarIcon","fill","import_jsx_runtime","closeButtonStyles","iconStyles","CloseButton","onClick","style","isHovering","setIsHovering","React","CloseIcon","import_jsx_runtime","chipStyles","Chip","label","icon","remove","style","CloseButton","import_react","import_react","defaultTranslations","formatCurrencyDefault","value","currency","useTranslation","customTranslations","customFormatCurrency","locale","setLocale","t","key","params","translation","paramKey","formatCurrency","import_jsx_runtime","renderStars","rating","stars","fullStars","hasHalfStar","baseStyles","fullStarStyles","halfStarStyles","i","remainingStars","createMinRatingFilterLabel","suffix","formatRatingValue","createPriceRangeFilterLabel","min","max","currency","formatCurrencyFn","import_jsx_runtime","chipContainerStyles","starContainerStyles","circleBaseStyles","buttonBaseStyles","MinRatingFilterChip","rating","onChange","onRemove","star","hoverRating","setHoverRating","t","useTranslation","displayRating","formatLabel","value","formatRatingValue","removeLabel","setLabel","getFillForStar","index","starNumber","handleSelect","nextRating","handleBlur","event","_a","related","_","fillState","halfValue","StarIcon","circleStyles","halfCircleStyles","CloseButton","import_react","import_jsx_runtime","chipStyles","inputStyles","editButtonStyles","PriceBoundaryChip","boundary","label","value","placeholder","currency","isOptional","showRemoveButton","removeLabel","editLabel","showAddWhenEmpty","onCommit","onRemove","draft","setDraft","isEditing","setIsEditing","editHover","setEditHover","hasValue","resetDraft","commitValue","parsed","normalized","event","next","EditIcon","CloseButton","PriceRangeFilterChip","priceRange","onChange","t","useTranslation","minLabel","maxChipLabel","handleBoundaryCommit","nextValue","nextRange","import_jsx_runtime","chipStyles","PRICE_LEVEL_OPTIONS","RestaurantPriceLevelChip","values","onChange","onRemove","t","useTranslation","label","removeLabel","noneSelectedLabel","handleChange","event","value","checked","valueAsPriceLevel","selection","orderedSelection","option","optionLabel","checkboxId","CloseButton","import_react","import_jsx_runtime","chipStyles","inputStyles","editButtonStyles","TransformedQueryChip","value","onChange","onRemove","inputRef","draft","setDraft","isEditing","setIsEditing","editHover","setEditHover","t","useTranslation","removeLabel","editLabel","applyChanges","nextValue","SearchIcon","event","EditIcon","CloseButton","import_react","useFilterScroll","dependency","scrollerRef","atStart","setAtStart","atEnd","setAtEnd","updateScrollButtons","el","scrollLeft","scrollWidth","clientWidth","handleScroll","scrollByDir","dir","delta","import_jsx_runtime","containerStyles","scrollContainerBase","gradientStyles","navButtonStyles","FilterChips","filters","currency","minRatingSuffix","clearAllLabel","previousFiltersLabel","nextFiltersLabel","formatCurrency","onFilterChange","onResetFilters","onClearAll","scrollerRef","atStart","atEnd","scrollByDir","useFilterScroll","navHover","setNavHover","React","clearHover","setClearHover","filter","_a","_b","_c","renderStandardChip","Chip","f","currentRating","MinRatingFilterChip","nextRating","nextFilters","PriceRangeFilterChip","nextRange","TransformedQueryChip","nextValue","RestaurantPriceLevelChip","nextLevels","NextIcon","import_jsx_runtime","containerStyles","SmartFilter","filters","isSearching","onFilterChange","customTranslations","currency","containerStyle","style","t","formatCurrency","useTranslation","minRatingSuffix","previousFiltersLabel","nextFiltersLabel","clearAllLabel","handleFilterChange","nextFilters","clearAll","error","resetFilters","clearAllFilters","FilterChips","useMapFirst","options","instanceRef","React","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","pendingBounds","center","zoom","location","loading","searching","instance","setPrimaryType","setSelectedMarker","setUseApi","useApi","autoLoad","propertiesSearch","smartFilterSearch","boundsSearch","mapLibreAttachedRef","attachMapLibre","map","maplibregl","googleMapsAttachedRef","attachGoogle","google","mapboxAttachedRef","attachMapbox","mapboxgl"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/components/SmartFilter.tsx","../src/components/smart-filter/FilterChips.tsx","../src/components/smart-filter/CloseButton.tsx","../src/components/Icons.tsx","../src/components/smart-filter/Chip.tsx","../src/components/smart-filter/MinRatingFilterChip.tsx","../src/hooks/useTranslation.ts","../src/components/smart-filter/utils.tsx","../src/components/smart-filter/PriceRangeFilterChip.tsx","../src/components/smart-filter/RestaurantPriceLevelChip.tsx","../src/components/smart-filter/TransformedQueryChip.tsx","../src/hooks/useFilterScroll.ts"],"sourcesContent":["import React from \"react\";\nimport {\n MapFirstCore,\n type MapFirstOptions,\n type BaseMapFirstOptions,\n type Property,\n type MapLibreNamespace,\n type GoogleMapsNamespace,\n type MapboxNamespace,\n type MapState,\n type PropertyType,\n} from \"@mapfirst.ai/core\";\n\n// Export filter utilities from core\nexport {\n processApiFilters,\n convertToApiFilters,\n type ApiFiltersResponse,\n} from \"@mapfirst.ai/core\";\n\n// Export all components\nexport * from \"./components\";\n\n// Export all hooks\nexport * from \"./hooks\";\n\n// Import additional types for search functionality\ntype InitialRequestBody = {\n initial?: boolean;\n query?: string;\n bounds?: {\n sw: { lat: number; lng: number };\n ne: { lat: number; lng: number };\n };\n filters?: any;\n city?: string;\n country?: string;\n location_id?: number;\n longitude?: number;\n latitude?: number;\n radius?: number;\n};\n\ntype SmartFilter = {\n id: string;\n label: string;\n type:\n | \"amenity\"\n | \"hotelStyle\"\n | \"priceRange\"\n | \"minRating\"\n | \"starRating\"\n | \"primary_type\"\n | \"transformed_query\"\n | \"selected_restaurant_price_levels\";\n value: string;\n numericValue?: number;\n priceRange?: {\n min: number;\n max?: number;\n };\n propertyType?: PropertyType;\n priceLevels?: any[];\n};\n\n/**\n * Comprehensive hook for MapFirst SDK with all functionality in one place.\n * Creates a MapFirstCore instance with reactive state and provides all necessary methods.\n *\n * @example\n * ```tsx\n * // Initialize with location data\n * const {\n * instance,\n * state,\n * setPrimaryType,\n * setSelectedMarker,\n * propertiesSearch,\n * smartFilterSearch,\n * boundsSearch,\n * attachMapLibre,\n * attachGoogle,\n * attachMapbox\n * } = useMapFirst({\n * initialLocationData: {\n * city: \"New York\",\n * country: \"United States\",\n * currency: \"USD\"\n * }\n * });\n *\n * // Access reactive state\n * console.log(state?.properties);\n * console.log(state?.isSearching);\n * console.log(state?.selectedPropertyId);\n *\n * // Attach map when ready\n * useEffect(() => {\n * if (mapLibreInstance) {\n * attachMapLibre(mapLibreInstance, maplibregl, {\n * onMarkerClick: (marker) => console.log(marker)\n * });\n * }\n * }, [mapLibreInstance]);\n *\n * // Use search methods\n * await propertiesSearch.search({\n * body: { city: \"Paris\", country: \"France\" }\n * });\n *\n * await smartFilterSearch.search({\n * query: \"hotels near beach with pool\"\n * });\n *\n * await boundsSearch.perform();\n * ```\n */\nexport function useMapFirst(options: BaseMapFirstOptions) {\n const instanceRef = React.useRef<MapFirstCore | null>(null);\n const [state, setState] = React.useState<MapState | null>(null);\n\n // Memoize the options to prevent recreation on every render\n const optionsRef = React.useRef(options);\n React.useEffect(() => {\n optionsRef.current = options;\n });\n\n React.useEffect(() => {\n const opts = optionsRef.current;\n\n // Create MapFirstCore instance without map using adapter-driven options\n const coreOptions: MapFirstOptions = {\n adapter: null as any, // Will be set when attachMap is called\n ...opts,\n callbacks: {\n ...opts.callbacks,\n // Add internal callbacks to trigger React re-renders\n onPropertiesChange: (properties) => {\n setState((prev) => (prev ? { ...prev, properties } : null));\n optionsRef.current.callbacks?.onPropertiesChange?.(properties);\n },\n onSelectedPropertyChange: (id) => {\n setState((prev) =>\n prev ? { ...prev, selectedPropertyId: id } : null\n );\n optionsRef.current.callbacks?.onSelectedPropertyChange?.(id);\n },\n onPrimaryTypeChange: (type) => {\n setState((prev) => (prev ? { ...prev, primary: type } : null));\n optionsRef.current.callbacks?.onPrimaryTypeChange?.(type);\n },\n onFiltersChange: (filters) => {\n setState((prev) => (prev ? { ...prev, filters } : null));\n optionsRef.current.callbacks?.onFiltersChange?.(filters);\n },\n onBoundsChange: (bounds) => {\n setState((prev) => (prev ? { ...prev, bounds } : null));\n optionsRef.current.callbacks?.onBoundsChange?.(bounds);\n },\n onPendingBoundsChange: (pendingBounds) => {\n setState((prev) => (prev ? { ...prev, pendingBounds } : null));\n optionsRef.current.callbacks?.onPendingBoundsChange?.(pendingBounds);\n },\n onCenterChange: (center, zoom) => {\n setState((prev) => (prev ? { ...prev, center, zoom } : null));\n optionsRef.current.callbacks?.onCenterChange?.(center, zoom);\n },\n onZoomChange: (zoom) => {\n setState((prev) => (prev ? { ...prev, zoom } : null));\n optionsRef.current.callbacks?.onZoomChange?.(zoom);\n },\n onActiveLocationChange: (location) => {\n setState((prev) =>\n prev ? { ...prev, activeLocation: location } : null\n );\n optionsRef.current.callbacks?.onActiveLocationChange?.(location);\n },\n onLoadingStateChange: (loading) => {\n setState((prev) =>\n prev ? { ...prev, initialLoading: loading } : null\n );\n optionsRef.current.callbacks?.onLoadingStateChange?.(loading);\n },\n onSearchingStateChange: (searching) => {\n setState((prev) =>\n prev ? { ...prev, isSearching: searching } : null\n );\n optionsRef.current.callbacks?.onSearchingStateChange?.(searching);\n },\n },\n };\n\n const instance = new MapFirstCore(coreOptions);\n instanceRef.current = instance;\n\n // Initialize state from SDK\n setState(instance.getState());\n\n return () => {\n instance.destroy();\n instanceRef.current = null;\n setState(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Primary type control\n const setPrimaryType = React.useCallback((type: PropertyType) => {\n if (instanceRef.current) {\n instanceRef.current.setPrimaryType(type);\n }\n }, []);\n\n // Selected marker control\n const setSelectedMarker = React.useCallback((id: number | null) => {\n if (instanceRef.current) {\n instanceRef.current.setSelectedMarker(id);\n }\n }, []);\n\n // Use API control\n const setUseApi = React.useCallback(\n (useApi: boolean, autoLoad: boolean = true) => {\n if (instanceRef.current) {\n instanceRef.current.setUseApi(useApi, autoLoad);\n }\n },\n []\n );\n\n // Properties search\n const propertiesSearch = React.useMemo(\n () => ({\n search: async (options: {\n body: InitialRequestBody;\n beforeApplyProperties?: (data: any) => {\n price?: any;\n limit?: number;\n };\n smartFiltersClearable?: boolean;\n onError?: (error: unknown) => void;\n }) => {\n if (!instanceRef.current) {\n throw new Error(\"MapFirst instance not available\");\n }\n\n return await instanceRef.current.runPropertiesSearch(options);\n },\n }),\n []\n );\n\n // Smart filter search\n const smartFilterSearch = React.useMemo(\n () => ({\n search: async (options: {\n query?: string;\n filters?: SmartFilter[];\n onProcessFilters?: (\n filters: any,\n location_id?: number\n ) => {\n smartFilters?: SmartFilter[];\n price?: any;\n limit?: number;\n language?: string;\n };\n onError?: (error: unknown) => void;\n }) => {\n if (!instanceRef.current) {\n throw new Error(\"MapFirst instance not available\");\n }\n\n return await instanceRef.current.runSmartFilterSearch(options);\n },\n }),\n []\n );\n\n // Bounds search\n const boundsSearch = React.useMemo(\n () => ({\n perform: async () => {\n if (!instanceRef.current) {\n return null;\n }\n\n return await instanceRef.current.performBoundsSearch();\n },\n }),\n []\n );\n\n // Map attachment helpers\n const mapLibreAttachedRef = React.useRef(false);\n const attachMapLibre = React.useCallback(\n (\n map: any,\n maplibregl: MapLibreNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !mapLibreAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"maplibre\",\n maplibregl,\n onMarkerClick: options?.onMarkerClick,\n });\n mapLibreAttachedRef.current = true;\n }\n },\n []\n );\n\n const googleMapsAttachedRef = React.useRef(false);\n const attachGoogle = React.useCallback(\n (\n map: any,\n google: GoogleMapsNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !googleMapsAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"google\",\n google,\n onMarkerClick: options?.onMarkerClick,\n });\n googleMapsAttachedRef.current = true;\n }\n },\n []\n );\n\n const mapboxAttachedRef = React.useRef(false);\n const attachMapbox = React.useCallback(\n (\n map: any,\n mapboxgl: MapboxNamespace,\n options?: { onMarkerClick?: (marker: Property) => void }\n ) => {\n if (instanceRef.current && map && !mapboxAttachedRef.current) {\n instanceRef.current.attachMap(map, {\n platform: \"mapbox\",\n mapboxgl,\n onMarkerClick: options?.onMarkerClick,\n });\n mapboxAttachedRef.current = true;\n }\n },\n []\n );\n\n return {\n instance: instanceRef.current,\n state,\n setPrimaryType,\n setSelectedMarker,\n setUseApi,\n propertiesSearch,\n smartFilterSearch,\n boundsSearch,\n attachMapLibre,\n attachGoogle,\n attachMapbox,\n };\n}\n","import { FunctionComponent, useCallback, CSSProperties } from \"react\";\r\nimport { FilterChips } from \"./smart-filter/FilterChips\";\r\nimport { useTranslation } from \"../hooks/useTranslation\";\r\nimport type { Filter } from \"./smart-filter/types\";\r\n\r\nexport interface SmartFilterProps {\r\n filters: Filter[];\r\n isSearching?: boolean;\r\n onFilterChange: (filters: Filter[]) => Promise<void> | void;\r\n customTranslations?: Record<string, string>;\r\n currency?: string;\r\n style?: CSSProperties;\r\n containerStyle?: CSSProperties;\r\n}\r\n\r\nconst containerStyles: CSSProperties = {\r\n position: \"relative\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: \"8px\",\r\n width: \"100%\",\r\n};\r\n/**\r\n * SmartFilter component for AI-powered search with filter chips.\r\n * Provides a search input with smart filtering capabilities.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { mapFirst, state } = useMapFirstCore({ ... });\r\n * const [filters, setFilters] = useState<Filter[]>([]);\r\n * const [searchValue, setSearchValue] = useState(\"\");\r\n *\r\n * const handleSearch = async (query: string, currentFilters?: Filter[]) => {\r\n * // Perform search using mapFirst.runSmartFilterSearch\r\n * const result = await mapFirst.runSmartFilterSearch({\r\n * query,\r\n * filters: currentFilters\r\n * });\r\n * // Update filters based on response\r\n * };\r\n *\r\n * return (\r\n * <SmartFilter\r\n * mapFirst={mapFirst}\r\n * filters={filters}\r\n * value={searchValue}\r\n * isSearching={state?.isSearching}\r\n * onSearch={handleSearch}\r\n * onFilterChange={setFilters}\r\n * onValueChange={setSearchValue}\r\n * />\r\n * );\r\n * ```\r\n */\r\nexport const SmartFilter: FunctionComponent<SmartFilterProps> = ({\r\n filters,\r\n isSearching = false,\r\n onFilterChange,\r\n customTranslations,\r\n currency = \"USD\",\r\n containerStyle,\r\n style,\r\n}) => {\r\n const { t, formatCurrency } = useTranslation(customTranslations);\r\n\r\n const minRatingSuffix = t(\"smartFilter.minRating.suffix\");\r\n const previousFiltersLabel = t(\"smartFilter.nav.previous\");\r\n const nextFiltersLabel = t(\"smartFilter.nav.next\");\r\n const clearAllLabel = t(\"smartFilter.clearAll\");\r\n\r\n const handleFilterChange = useCallback(\r\n async (nextFilters: Filter[], clearAll?: boolean) => {\r\n if (isSearching) {\r\n return;\r\n }\r\n try {\r\n await onFilterChange(nextFilters);\r\n } catch (error) {\r\n console.error(\"Filter change error:\", error);\r\n }\r\n },\r\n [isSearching, onFilterChange]\r\n );\r\n\r\n const resetFilters = useCallback(() => {\r\n void handleFilterChange([]);\r\n }, [handleFilterChange]);\r\n\r\n const clearAllFilters = useCallback(() => {\r\n void handleFilterChange([], true);\r\n }, [handleFilterChange]);\r\n\r\n return (\r\n <div style={{ ...containerStyles, ...containerStyle }}>\r\n {filters.length > 0 && (\r\n <FilterChips\r\n filters={filters}\r\n currency={currency}\r\n minRatingSuffix={minRatingSuffix}\r\n clearAllLabel={clearAllLabel}\r\n previousFiltersLabel={previousFiltersLabel}\r\n nextFiltersLabel={nextFiltersLabel}\r\n formatCurrency={formatCurrency}\r\n onFilterChange={handleFilterChange}\r\n onResetFilters={resetFilters}\r\n onClearAll={clearAllFilters}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React, { FunctionComponent, CSSProperties } from \"react\";\r\nimport { Chip } from \"./Chip\";\r\nimport { MinRatingFilterChip } from \"./MinRatingFilterChip\";\r\nimport { PriceRangeFilterChip } from \"./PriceRangeFilterChip\";\r\nimport { RestaurantPriceLevelChip } from \"./RestaurantPriceLevelChip\";\r\nimport { TransformedQueryChip } from \"./TransformedQueryChip\";\r\nimport { SearchIcon, NextIcon } from \"../Icons\";\r\nimport { useFilterScroll } from \"../../hooks/useFilterScroll\";\r\nimport type { Filter } from \"./types\";\r\n\r\nexport interface FilterChipsProps {\r\n filters: Filter[];\r\n currency: string;\r\n minRatingSuffix: string;\r\n clearAllLabel: string;\r\n previousFiltersLabel: string;\r\n nextFiltersLabel: string;\r\n formatCurrency: (value: number, currency?: string) => string;\r\n onFilterChange: (\r\n filters: Filter[],\r\n clearAll?: boolean\r\n ) => void | Promise<void>;\r\n onResetFilters: () => void;\r\n onClearAll: () => void;\r\n}\r\n\r\nconst containerStyles: CSSProperties = {\r\n position: \"relative\",\r\n width: \"100%\",\r\n};\r\n\r\nconst scrollContainerBase: CSSProperties = {\r\n display: \"flex\",\r\n gap: \"8px\",\r\n overflowX: \"auto\",\r\n alignItems: \"center\",\r\n width: \"100%\",\r\n scrollbarWidth: \"none\",\r\n msOverflowStyle: \"none\",\r\n};\r\n\r\nconst gradientStyles: CSSProperties = {\r\n pointerEvents: \"none\",\r\n position: \"absolute\",\r\n top: 0,\r\n bottom: 0,\r\n width: \"40px\",\r\n};\r\n\r\nconst navButtonStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: \"50%\",\r\n transform: \"translateY(-50%)\",\r\n backgroundColor: \"white\",\r\n color: \"#003c30\",\r\n border: \"1px solid #003c30\",\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n boxShadow: \"0 1px 3px rgba(0,0,0,0.1)\",\r\n cursor: \"pointer\",\r\n};\r\n\r\nexport const FilterChips: FunctionComponent<FilterChipsProps> = ({\r\n filters,\r\n currency,\r\n minRatingSuffix,\r\n clearAllLabel,\r\n previousFiltersLabel,\r\n nextFiltersLabel,\r\n formatCurrency,\r\n onFilterChange,\r\n onResetFilters,\r\n onClearAll,\r\n}) => {\r\n const { scrollerRef, atStart, atEnd, scrollByDir } = useFilterScroll(\r\n filters.length\r\n );\r\n const [navHover, setNavHover] = React.useState<\"prev\" | \"next\" | null>(null);\r\n const [clearHover, setClearHover] = React.useState(false);\r\n\r\n return (\r\n <div style={containerStyles}>\r\n <div\r\n ref={scrollerRef}\r\n style={{\r\n ...scrollContainerBase,\r\n padding: \"8px\",\r\n // Hide scrollbar for webkit browsers\r\n WebkitOverflowScrolling: \"touch\",\r\n }}\r\n >\r\n <style>\r\n {`\r\n div::-webkit-scrollbar {\r\n display: none;\r\n }\r\n `}\r\n </style>\r\n {filters.map((filter) => {\r\n const renderStandardChip = () => (\r\n <Chip\r\n key={filter.id}\r\n label={filter.label}\r\n icon={filter.icon}\r\n remove={() => {\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id));\r\n }}\r\n />\r\n );\r\n\r\n if (filter.type === \"minRating\") {\r\n const currentRating = filter.numericValue ?? Number(filter.value);\r\n if (!Number.isFinite(currentRating)) {\r\n return renderStandardChip();\r\n }\r\n\r\n return (\r\n <MinRatingFilterChip\r\n key={filter.id}\r\n rating={currentRating}\r\n onChange={(nextRating) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n numericValue: nextRating,\r\n value: String(nextRating),\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"starRating\") {\r\n const currentRating = filter.numericValue ?? Number(filter.value);\r\n if (!Number.isFinite(currentRating)) {\r\n return renderStandardChip();\r\n }\r\n\r\n return (\r\n <MinRatingFilterChip\r\n star\r\n key={filter.id}\r\n rating={currentRating}\r\n onChange={(nextRating) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n numericValue: nextRating,\r\n value: String(nextRating),\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"priceRange\" && filter.priceRange) {\r\n return (\r\n <PriceRangeFilterChip\r\n key={filter.id}\r\n priceRange={filter.priceRange}\r\n currency={currency}\r\n onChange={(nextRange) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n priceRange: nextRange,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"transformed_query\") {\r\n return (\r\n <TransformedQueryChip\r\n key={filter.id}\r\n value={filter.value}\r\n onChange={(nextValue) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n value: nextValue,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n if (filter.type === \"selected_restaurant_price_levels\") {\r\n return (\r\n <RestaurantPriceLevelChip\r\n key={filter.id}\r\n values={filter.priceLevels ?? []}\r\n onChange={(nextLevels) => {\r\n const nextFilters = filters.map((f) =>\r\n f.id === filter.id\r\n ? {\r\n ...f,\r\n priceLevels: nextLevels,\r\n }\r\n : f\r\n );\r\n void onFilterChange(nextFilters);\r\n }}\r\n onRemove={() =>\r\n void onFilterChange(filters.filter((f) => f.id !== filter.id))\r\n }\r\n />\r\n );\r\n }\r\n\r\n return renderStandardChip();\r\n })}\r\n <button\r\n style={{\r\n flexShrink: 0,\r\n padding: \"4px 16px\",\r\n borderRadius: \"9999px\",\r\n cursor: \"pointer\",\r\n fontSize: \"14px\",\r\n userSelect: \"none\",\r\n backgroundColor: clearHover ? \"#eee\" : \"white\",\r\n color: \"black\",\r\n border: \"1px solid #03852e\",\r\n }}\r\n onClick={onClearAll}\r\n onMouseEnter={() => setClearHover(true)}\r\n onMouseLeave={() => setClearHover(false)}\r\n >\r\n {clearAllLabel}\r\n </button>\r\n </div>\r\n\r\n {!atStart && (\r\n <div\r\n aria-hidden=\"true\"\r\n style={{\r\n ...gradientStyles,\r\n left: 0,\r\n background: \"linear-gradient(to right, white, transparent)\",\r\n }}\r\n />\r\n )}\r\n\r\n {!atEnd && (\r\n <div\r\n aria-hidden=\"true\"\r\n style={{\r\n ...gradientStyles,\r\n right: 0,\r\n background: \"linear-gradient(to left, white, transparent)\",\r\n }}\r\n />\r\n )}\r\n\r\n {!atStart && (\r\n <button\r\n type=\"button\"\r\n aria-label={previousFiltersLabel}\r\n style={{\r\n ...navButtonStyles,\r\n left: \"4px\",\r\n transform: \"translateY(-50%) rotate(180deg)\",\r\n backgroundColor: navHover === \"prev\" ? \"#e5e5e5\" : \"white\",\r\n }}\r\n onClick={() => scrollByDir(\"prev\")}\r\n onMouseEnter={() => setNavHover(\"prev\")}\r\n onMouseLeave={() => setNavHover(null)}\r\n >\r\n <NextIcon style={{ width: \"20px\", height: \"20px\" }} />\r\n </button>\r\n )}\r\n\r\n {!atEnd && (\r\n <button\r\n type=\"button\"\r\n aria-label={nextFiltersLabel}\r\n style={{\r\n ...navButtonStyles,\r\n right: \"4px\",\r\n backgroundColor: navHover === \"next\" ? \"#e5e5e5\" : \"white\",\r\n }}\r\n onClick={() => scrollByDir(\"next\")}\r\n onMouseEnter={() => setNavHover(\"next\")}\r\n onMouseLeave={() => setNavHover(null)}\r\n >\r\n <NextIcon style={{ width: \"20px\", height: \"20px\" }} />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React, { CSSProperties } from \"react\";\r\nimport { CloseIcon } from \"../Icons\";\r\n\r\nexport interface CloseButtonProps {\r\n onClick: () => void;\r\n style?: CSSProperties;\r\n}\r\n\r\nconst closeButtonStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: \"-8px\",\r\n right: \"-8px\",\r\n padding: \"2px\",\r\n borderRadius: \"50%\",\r\n backgroundColor: \"white\",\r\n border: \"1px solid #03852e\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: \"background-color 0.2s\",\r\n};\r\n\r\nconst iconStyles: CSSProperties = {\r\n width: \"17px\",\r\n height: \"17px\",\r\n};\r\n\r\nexport const CloseButton: React.FC<CloseButtonProps> = ({ onClick, style }) => {\r\n const [isHovering, setIsHovering] = React.useState(false);\r\n\r\n return (\r\n <button\r\n style={{\r\n ...closeButtonStyles,\r\n backgroundColor: isHovering ? \"#e5e5e5\" : \"white\",\r\n ...style,\r\n }}\r\n onClick={onClick}\r\n onMouseEnter={() => setIsHovering(true)}\r\n onMouseLeave={() => setIsHovering(false)}\r\n aria-label=\"Remove filter\"\r\n >\r\n <CloseIcon style={iconStyles} />\r\n </button>\r\n );\r\n};\r\n","import React, { CSSProperties } from \"react\";\r\n\r\nexport interface IconProps {\r\n className?: string;\r\n style?: CSSProperties;\r\n}\r\n\r\nexport const SearchIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <path d=\"m21 21-4.35-4.35\" />\r\n </svg>\r\n);\r\n\r\nexport const CloseIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n);\r\n\r\nexport const EditIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\r\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\r\n </svg>\r\n);\r\n\r\nexport const NextIcon: React.FC<IconProps> = ({ className, style }) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <polyline points=\"9 18 15 12 9 6\" />\r\n </svg>\r\n);\r\n\r\nexport const StarIcon: React.FC<IconProps & { fill?: string }> = ({\r\n className,\r\n style,\r\n fill = \"none\",\r\n}) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill={fill}\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n style={{ width: \"1em\", height: \"1em\", ...style }}\r\n >\r\n <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\" />\r\n </svg>\r\n);\r\n","import React, { CSSProperties, ReactNode } from \"react\";\r\nimport { CloseButton } from \"./CloseButton\";\r\n\r\nexport interface ChipProps {\r\n label: string | ReactNode;\r\n icon?: ReactNode;\r\n remove: () => void;\r\n style?: CSSProperties;\r\n}\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nexport const Chip: React.FC<ChipProps> = ({ label, icon, remove, style }) => {\r\n return (\r\n <div style={{ ...chipStyles, ...style }}>\r\n {icon && (\r\n <span style={{ display: \"flex\", alignItems: \"center\" }}>{icon}</span>\r\n )}\r\n <span style={{ whiteSpace: \"nowrap\" }}>{label}</span>\r\n <CloseButton onClick={remove} />\r\n </div>\r\n );\r\n};\r\n","import React, {\r\n FunctionComponent,\r\n useState,\r\n FocusEvent,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { StarIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport { formatRatingValue } from \"./utils\";\r\n\r\nconst chipContainerStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n gap: \"8px\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst starContainerStyles: CSSProperties = {\r\n display: \"flex\",\r\n gap: \"1px\",\r\n userSelect: \"none\",\r\n};\r\n\r\nconst circleBaseStyles: CSSProperties = {\r\n display: \"block\",\r\n width: \"12px\",\r\n height: \"12px\",\r\n borderRadius: \"50%\",\r\n border: \"1px solid #03852e\",\r\n pointerEvents: \"none\",\r\n};\r\n\r\nconst buttonBaseStyles: CSSProperties = {\r\n position: \"absolute\",\r\n top: 0,\r\n height: \"100%\",\r\n cursor: \"pointer\",\r\n backgroundColor: \"transparent\",\r\n border: \"none\",\r\n padding: 0,\r\n};\r\n\r\nexport const MinRatingFilterChip: FunctionComponent<{\r\n star?: boolean;\r\n rating: number;\r\n onChange: (rating: number) => void;\r\n onRemove: () => void;\r\n}> = ({ rating, onChange, onRemove, star = false }) => {\r\n const [hoverRating, setHoverRating] = useState<number | null>(null);\r\n const { t } = useTranslation();\r\n\r\n const displayRating = hoverRating ?? rating;\r\n const formatLabel = (value: number) =>\r\n star && value\r\n ? value.toString()\r\n : t(\"smartFilter.minRating.label\", { value: formatRatingValue(value) });\r\n const removeLabel = t(\"smartFilter.minRating.remove\");\r\n const setLabel = (value: number) =>\r\n t(\"smartFilter.minRating.setTo\", { rating: formatRatingValue(value) });\r\n\r\n const getFillForStar = (index: number) => {\r\n const starNumber = index + 1;\r\n if (displayRating >= starNumber) {\r\n return \"full\" as const;\r\n }\r\n if (displayRating >= starNumber - 0.5) {\r\n return \"half\" as const;\r\n }\r\n return \"empty\" as const;\r\n };\r\n\r\n const handleSelect = (nextRating: number) => {\r\n setHoverRating(null);\r\n if (nextRating === rating) {\r\n return;\r\n }\r\n onChange(nextRating);\r\n };\r\n\r\n const handleBlur = (event: FocusEvent<HTMLButtonElement>) => {\r\n const related = event.relatedTarget as HTMLElement | null;\r\n if (\r\n !related ||\r\n !(event.currentTarget as HTMLElement)\r\n .closest(\"[data-min-rating-chip]\")\r\n ?.contains(related)\r\n ) {\r\n setHoverRating(null);\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipContainerStyles} data-min-rating-chip>\r\n <div\r\n style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}\r\n onMouseLeave={() => setHoverRating(null)}\r\n >\r\n <div style={starContainerStyles}>\r\n {Array.from({ length: 5 }).map((_, index) => {\r\n const fillState = getFillForStar(index);\r\n const starNumber = index + 1;\r\n const halfValue = starNumber - 0.5;\r\n\r\n if (star) {\r\n return (\r\n <div\r\n key={index}\r\n style={{\r\n position: \"relative\",\r\n width: \"16px\",\r\n height: \"16px\",\r\n }}\r\n >\r\n <StarIcon\r\n fill={displayRating >= starNumber ? \"#03852e\" : \"none\"}\r\n style={{\r\n width: \"16px\",\r\n height: \"16px\",\r\n pointerEvents: \"none\",\r\n }}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: 0,\r\n width: \"50%\",\r\n borderRadius: \"50% 0 0 50%\",\r\n }}\r\n onMouseEnter={() => setHoverRating(halfValue)}\r\n onFocus={() => setHoverRating(halfValue)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(halfValue)}\r\n aria-label={setLabel(halfValue)}\r\n title={formatLabel(halfValue)}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: \"50%\",\r\n width: \"50%\",\r\n borderRadius: \"0 50% 50% 0\",\r\n }}\r\n onMouseEnter={() => setHoverRating(starNumber)}\r\n onFocus={() => setHoverRating(starNumber)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(starNumber)}\r\n aria-label={setLabel(starNumber)}\r\n title={formatLabel(starNumber)}\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n const circleStyles: CSSProperties =\r\n fillState === \"full\"\r\n ? { ...circleBaseStyles, backgroundColor: \"#03852e\" }\r\n : circleBaseStyles;\r\n\r\n const halfCircleStyles: CSSProperties = {\r\n ...circleBaseStyles,\r\n background:\r\n \"linear-gradient(90deg, #03852e 50%, transparent 50%)\",\r\n };\r\n\r\n return (\r\n <div\r\n key={index}\r\n style={{ position: \"relative\", width: \"12px\", height: \"12px\" }}\r\n >\r\n <span\r\n style={fillState === \"half\" ? halfCircleStyles : circleStyles}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: 0,\r\n width: \"50%\",\r\n borderRadius: \"50% 0 0 50%\",\r\n outline: \"2px solid transparent\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={() => setHoverRating(halfValue)}\r\n onFocus={() => setHoverRating(halfValue)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(halfValue)}\r\n aria-label={setLabel(halfValue)}\r\n title={formatLabel(halfValue)}\r\n />\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...buttonBaseStyles,\r\n left: \"50%\",\r\n width: \"50%\",\r\n borderRadius: \"0 50% 50% 0\",\r\n outline: \"2px solid transparent\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={() => setHoverRating(starNumber)}\r\n onFocus={() => setHoverRating(starNumber)}\r\n onBlur={handleBlur}\r\n onClick={() => handleSelect(starNumber)}\r\n aria-label={setLabel(starNumber)}\r\n title={formatLabel(starNumber)}\r\n />\r\n </div>\r\n );\r\n })}\r\n </div>\r\n <span style={{ whiteSpace: \"nowrap\" }}>\r\n {formatLabel(displayRating)}\r\n </span>\r\n </div>\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import { useCallback, useState } from \"react\";\r\n\r\nexport type Locale = \"en\" | \"es\" | \"de\" | \"fr\" | \"it\" | \"pt\";\r\n\r\ntype TranslationFunction = (\r\n key: string,\r\n params?: Record<string, any>\r\n) => string;\r\ntype FormatCurrencyFunction = (value: number, currency?: string) => string;\r\n\r\nconst defaultTranslations: Record<string, string> = {\r\n \"smartFilter.typingPrompt\":\r\n \"Search for hotels, restaurants, or attractions...\",\r\n \"smartFilter.nav.previous\": \"Previous filters\",\r\n \"smartFilter.nav.next\": \"Next filters\",\r\n \"smartFilter.toast.locationRequired\": \"Please select a location first\",\r\n \"smartFilter.clearAll\": \"Clear all\",\r\n \"smartFilter.minRating.suffix\": \"+\",\r\n \"smartFilter.minRating.label\": \"{{value}}+\",\r\n \"smartFilter.minRating.remove\": \"Remove rating filter\",\r\n \"smartFilter.minRating.setTo\": \"Set rating to {{rating}}\",\r\n \"smartFilter.priceRange.label\": \"Price Range\",\r\n \"smartFilter.priceRange.remove\": \"Remove price filter\",\r\n \"smartFilter.priceRange.edit\": \"Edit price\",\r\n \"smartFilter.transformedQuery.remove\": \"Remove search query\",\r\n \"smartFilter.transformedQuery.edit\": \"Edit search query\",\r\n \"smartFilter.restaurantPriceLevel.label\": \"Price Level\",\r\n \"smartFilter.restaurantPriceLevel.remove\": \"Remove price level filter\",\r\n \"smartFilter.restaurantPriceLevel.none\": \"Any\",\r\n \"smartFilter.restaurantPriceLevel.options.cheapEats\": \"Cheap Eats\",\r\n \"smartFilter.restaurantPriceLevel.options.midRange\": \"Mid Range\",\r\n \"smartFilter.restaurantPriceLevel.options.fineDining\": \"Fine Dining\",\r\n};\r\n\r\nconst formatCurrencyDefault: FormatCurrencyFunction = (\r\n value,\r\n currency = \"USD\"\r\n) => {\r\n return new Intl.NumberFormat(\"en-US\", {\r\n style: \"currency\",\r\n currency: currency,\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 0,\r\n }).format(value);\r\n};\r\n\r\n/**\r\n * Simple translation hook with default English translations.\r\n * Can be extended with custom translations and locales.\r\n */\r\nexport const useTranslation = (\r\n customTranslations?: Record<string, string>,\r\n customFormatCurrency?: FormatCurrencyFunction\r\n) => {\r\n const [locale, setLocale] = useState<Locale>(\"en\");\r\n\r\n const t: TranslationFunction = useCallback(\r\n (key: string, params?: Record<string, any>) => {\r\n const translations = { ...defaultTranslations, ...customTranslations };\r\n let translation = translations[key] || key;\r\n\r\n if (params) {\r\n Object.keys(params).forEach((paramKey) => {\r\n translation = translation.replace(\r\n new RegExp(`{{${paramKey}}}`, \"g\"),\r\n String(params[paramKey])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n },\r\n [customTranslations]\r\n );\r\n\r\n const formatCurrency = useCallback(\r\n (value: number, currency?: string) => {\r\n if (customFormatCurrency) {\r\n return customFormatCurrency(value, currency);\r\n }\r\n return formatCurrencyDefault(value, currency);\r\n },\r\n [customFormatCurrency]\r\n );\r\n\r\n return {\r\n t,\r\n locale,\r\n setLocale,\r\n formatCurrency,\r\n };\r\n};\r\n","import React, { ReactNode, CSSProperties } from \"react\";\r\n\r\nexport const renderStars = (rating: number): ReactNode[] => {\r\n const stars: ReactNode[] = [];\r\n const fullStars = Math.floor(rating);\r\n const hasHalfStar = rating % 1 !== 0;\r\n\r\n const baseStyles: CSSProperties = {\r\n display: \"block\",\r\n width: \"12px\",\r\n height: \"12px\",\r\n borderRadius: \"50%\",\r\n border: \"1px solid #03852e\",\r\n pointerEvents: \"none\",\r\n };\r\n\r\n const fullStarStyles: CSSProperties = {\r\n ...baseStyles,\r\n backgroundColor: \"#03852e\",\r\n };\r\n\r\n const halfStarStyles: CSSProperties = {\r\n ...baseStyles,\r\n background: \"linear-gradient(90deg, #03852e 50%, transparent 50%)\",\r\n };\r\n\r\n for (let i = 0; i < fullStars; i += 1) {\r\n stars.push(<span key={`full-${i}`} style={fullStarStyles} />);\r\n }\r\n\r\n if (hasHalfStar) {\r\n stars.push(<span key=\"half\" style={halfStarStyles} />);\r\n }\r\n\r\n const remainingStars = Math.max(0, 5 - Math.ceil(rating));\r\n for (let i = 0; i < remainingStars; i += 1) {\r\n stars.push(<span key={`empty-${i}`} style={baseStyles} />);\r\n }\r\n\r\n return stars;\r\n};\r\n\r\nexport const createMinRatingFilterLabel = (\r\n rating: number,\r\n suffix?: string\r\n): ReactNode => (\r\n <span style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}>\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: \"1px\",\r\n userSelect: \"none\",\r\n }}\r\n >\r\n {renderStars(rating)}\r\n </span>{\" \"}\r\n {suffix}\r\n </span>\r\n);\r\n\r\nexport const formatRatingValue = (rating: number): string => rating.toFixed(1);\r\n\r\nexport const createPriceRangeFilterLabel = (\r\n min: number,\r\n max: number | undefined,\r\n currency: string | undefined,\r\n formatCurrencyFn: (value: number, currency?: string) => string\r\n): string =>\r\n `${formatCurrencyFn(min, currency)} - ${formatCurrencyFn(\r\n max ?? 0,\r\n currency\r\n )}`;\r\n","import React, {\r\n ChangeEvent,\r\n FunctionComponent,\r\n KeyboardEvent,\r\n useEffect,\r\n useState,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { EditIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport type { PriceRangeValue } from \"./types\";\r\n\r\ntype Boundary = \"min\" | \"max\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst inputStyles: CSSProperties = {\r\n outline: \"none\",\r\n fontSize: \"16px\",\r\n backgroundColor: \"transparent\",\r\n borderRadius: \"2px\",\r\n padding: \"2px 8px\",\r\n width: \"64px\",\r\n textAlign: \"center\",\r\n border: \"none\",\r\n};\r\n\r\nconst editButtonStyles: CSSProperties = {\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.2s\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n color: \"#737373\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n};\r\n\r\ninterface PriceBoundaryChipProps {\r\n boundary: Boundary;\r\n label: string;\r\n value?: number;\r\n placeholder?: string;\r\n currency: string;\r\n isOptional?: boolean;\r\n showRemoveButton?: boolean;\r\n removeLabel?: string;\r\n editLabel?: string;\r\n showAddWhenEmpty?: boolean;\r\n onCommit: (value?: number) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nconst PriceBoundaryChip: FunctionComponent<PriceBoundaryChipProps> = ({\r\n boundary,\r\n label,\r\n value,\r\n placeholder,\r\n currency,\r\n isOptional = false,\r\n showRemoveButton = false,\r\n removeLabel,\r\n editLabel,\r\n showAddWhenEmpty = false,\r\n onCommit,\r\n onRemove,\r\n}) => {\r\n const [draft, setDraft] = useState<string>(\r\n value !== undefined ? String(value) : \"\"\r\n );\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editHover, setEditHover] = useState(false);\r\n const hasValue = value !== undefined;\r\n\r\n useEffect(() => {\r\n setDraft(value !== undefined ? String(value) : \"\");\r\n setIsEditing(false);\r\n }, [value]);\r\n\r\n const resetDraft = () => {\r\n setDraft(value !== undefined ? String(value) : \"\");\r\n };\r\n\r\n const commitValue = () => {\r\n if (draft.trim() === \"\") {\r\n if (isOptional) {\r\n onCommit(undefined);\r\n setDraft(\"\");\r\n return;\r\n }\r\n resetDraft();\r\n return;\r\n }\r\n\r\n const parsed = Number(draft);\r\n if (!Number.isFinite(parsed)) {\r\n resetDraft();\r\n return;\r\n }\r\n\r\n const normalized = Math.max(0, parsed);\r\n if (normalized === value) {\r\n resetDraft();\r\n return;\r\n }\r\n onCommit(normalized);\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n const next = event.target.value.replace(/[^\\d]/g, \"\");\r\n setDraft(next);\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n setIsEditing(false);\r\n return;\r\n }\r\n\r\n if (event.key === \"Escape\") {\r\n event.preventDefault();\r\n resetDraft();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n setIsEditing(false);\r\n return;\r\n }\r\n\r\n const allowed =\r\n (event.key.length === 1 && /[0-9]/.test(event.key)) ||\r\n event.key === \"Backspace\" ||\r\n event.key === \"Delete\" ||\r\n event.key === \"Tab\" ||\r\n event.key === \"ArrowLeft\" ||\r\n event.key === \"ArrowRight\" ||\r\n event.key === \"Home\" ||\r\n event.key === \"End\";\r\n\r\n if (!allowed) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <span\r\n style={{\r\n fontSize: \"10px\",\r\n textTransform: \"uppercase\",\r\n fontWeight: 600,\r\n letterSpacing: \"0.05em\",\r\n }}\r\n >\r\n {label}\r\n </span>\r\n {isEditing ? (\r\n <input\r\n value={draft}\r\n onChange={handleChange}\r\n onBlur={() => {\r\n commitValue();\r\n setIsEditing(false);\r\n }}\r\n onKeyDown={handleKeyDown}\r\n placeholder={placeholder}\r\n inputMode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n aria-label={label}\r\n style={inputStyles}\r\n autoFocus\r\n />\r\n ) : hasValue ? (\r\n <span style={{ fontSize: \"16px\" }}>\r\n {currency}\r\n {value}\r\n </span>\r\n ) : showAddWhenEmpty ? (\r\n <button\r\n type=\"button\"\r\n style={{\r\n fontSize: \"16px\",\r\n color: \"#737373\",\r\n cursor: \"pointer\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n padding: 0,\r\n }}\r\n onClick={() => setIsEditing(true)}\r\n aria-label={editLabel}\r\n >\r\n +\r\n </button>\r\n ) : (\r\n <span style={{ fontSize: \"16px\", color: \"#737373\" }}>-</span>\r\n )}\r\n {(!showAddWhenEmpty || (showAddWhenEmpty && isEditing)) && (\r\n <span style={{ color: \"#737373\", fontSize: \"12px\" }}>{currency}</span>\r\n )}\r\n {!isEditing && (!showAddWhenEmpty || hasValue) && (\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...editButtonStyles,\r\n backgroundColor: editHover ? \"#e5e5e5\" : \"transparent\",\r\n }}\r\n aria-label={editLabel}\r\n title={editLabel}\r\n onClick={() => setIsEditing(true)}\r\n onMouseEnter={() => setEditHover(true)}\r\n onMouseLeave={() => setEditHover(false)}\r\n >\r\n <EditIcon />\r\n </button>\r\n )}\r\n {showRemoveButton && <CloseButton onClick={onRemove} />}\r\n </div>\r\n );\r\n};\r\n\r\nexport const PriceRangeFilterChip: FunctionComponent<{\r\n priceRange: PriceRangeValue;\r\n currency: string;\r\n onChange: (range: PriceRangeValue) => void;\r\n onRemove: () => void;\r\n}> = ({ priceRange, currency, onChange, onRemove }) => {\r\n const { t } = useTranslation();\r\n\r\n const minLabel = \"Min\";\r\n const maxChipLabel = \"Max\";\r\n const removeLabel = t(\"smartFilter.priceRange.remove\");\r\n const editLabel = t(\"smartFilter.priceRange.edit\");\r\n\r\n const handleBoundaryCommit = (boundary: Boundary, nextValue?: number) => {\r\n const nextRange: PriceRangeValue = {\r\n min: priceRange.min,\r\n max: priceRange.max,\r\n };\r\n\r\n if (boundary === \"min\") {\r\n nextRange.min = nextValue;\r\n if (\r\n nextValue !== undefined &&\r\n priceRange.max !== undefined &&\r\n nextValue > priceRange.max\r\n ) {\r\n nextRange.max = nextValue;\r\n }\r\n } else {\r\n nextRange.max = nextValue;\r\n if (\r\n nextValue !== undefined &&\r\n priceRange.min !== undefined &&\r\n nextValue < priceRange.min\r\n ) {\r\n nextRange.min = nextValue;\r\n }\r\n }\r\n\r\n if (nextRange.min !== priceRange.min || nextRange.max !== priceRange.max) {\r\n onChange(nextRange);\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <PriceBoundaryChip\r\n boundary=\"min\"\r\n label={minLabel}\r\n value={priceRange.min}\r\n currency={currency}\r\n editLabel={editLabel}\r\n showRemoveButton={priceRange.min !== undefined && priceRange.min !== 0}\r\n onCommit={(value) => handleBoundaryCommit(\"min\", value)}\r\n onRemove={onRemove}\r\n />\r\n <PriceBoundaryChip\r\n boundary=\"max\"\r\n label={maxChipLabel}\r\n value={priceRange.max}\r\n currency={currency}\r\n isOptional\r\n showRemoveButton={priceRange.max !== undefined}\r\n removeLabel={removeLabel}\r\n editLabel={editLabel}\r\n showAddWhenEmpty\r\n onCommit={(value) => handleBoundaryCommit(\"max\", value)}\r\n onRemove={onRemove}\r\n />\r\n </>\r\n );\r\n};\r\n","import React, { ChangeEvent, FunctionComponent, CSSProperties } from \"react\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\nimport type { PriceLevel } from \"@mapfirst.ai/core\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"16px\",\r\n flexShrink: 0,\r\n height: \"34px\",\r\n};\r\n\r\nconst PRICE_LEVEL_OPTIONS = [\r\n { value: \"Cheap Eats\" as PriceLevel, key: \"cheapEats\" },\r\n { value: \"Mid Range\" as PriceLevel, key: \"midRange\" },\r\n { value: \"Fine Dining\" as PriceLevel, key: \"fineDining\" },\r\n] as const;\r\n\r\nexport interface RestaurantPriceLevelChipProps {\r\n values: PriceLevel[];\r\n onChange: (values: PriceLevel[]) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nexport const RestaurantPriceLevelChip: FunctionComponent<\r\n RestaurantPriceLevelChipProps\r\n> = ({ values, onChange, onRemove }) => {\r\n const { t } = useTranslation();\r\n\r\n const label = t(\"smartFilter.restaurantPriceLevel.label\");\r\n const removeLabel = t(\"smartFilter.restaurantPriceLevel.remove\");\r\n const noneSelectedLabel = t(\"smartFilter.restaurantPriceLevel.none\");\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n const { value, checked } = event.target;\r\n const valueAsPriceLevel = value as PriceLevel;\r\n const selection = new Set(values);\r\n if (checked) {\r\n selection.add(valueAsPriceLevel);\r\n } else {\r\n selection.delete(valueAsPriceLevel);\r\n }\r\n const orderedSelection = PRICE_LEVEL_OPTIONS.filter((option) =>\r\n selection.has(option.value)\r\n ).map((option) => option.value);\r\n onChange(orderedSelection);\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexWrap: \"wrap\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontSize: \"10px\",\r\n textTransform: \"uppercase\",\r\n fontWeight: 600,\r\n letterSpacing: \"0.05em\",\r\n }}\r\n >\r\n {label}\r\n </span>\r\n <div style={{ display: \"flex\", gap: \"12px\" }}>\r\n {PRICE_LEVEL_OPTIONS.map((option) => {\r\n const optionLabel = t(\r\n `smartFilter.restaurantPriceLevel.options.${option.key}`\r\n );\r\n const checkboxId = `price-level-${option.key}`;\r\n return (\r\n <label\r\n key={option.value}\r\n htmlFor={checkboxId}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"4px\",\r\n fontSize: \"12px\",\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n <input\r\n id={checkboxId}\r\n type=\"checkbox\"\r\n value={option.value}\r\n checked={values.includes(option.value)}\r\n onChange={handleChange}\r\n style={{ accentColor: \"#03852e\", cursor: \"pointer\" }}\r\n />\r\n <span>{optionLabel}</span>\r\n </label>\r\n );\r\n })}\r\n {values.length === 0 && (\r\n <span style={{ fontSize: \"12px\", color: \"#737373\" }}>\r\n {noneSelectedLabel}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import React, {\r\n ChangeEvent,\r\n FunctionComponent,\r\n KeyboardEvent,\r\n useEffect,\r\n useRef,\r\n useState,\r\n CSSProperties,\r\n} from \"react\";\r\nimport { EditIcon, SearchIcon } from \"../Icons\";\r\nimport { CloseButton } from \"./CloseButton\";\r\nimport { useTranslation } from \"../../hooks/useTranslation\";\r\n\r\nconst chipStyles: CSSProperties = {\r\n position: \"relative\",\r\n backgroundColor: \"white\",\r\n color: \"black\",\r\n fontSize: \"14px\",\r\n borderRadius: \"9999px\",\r\n padding: \"0 16px\",\r\n paddingRight: \"20px\",\r\n border: \"1px solid #03852e\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: 0,\r\n userSelect: \"none\",\r\n height: \"34px\",\r\n};\r\n\r\nconst inputStyles: CSSProperties = {\r\n backgroundColor: \"#ececec\",\r\n borderRadius: \"2px\",\r\n padding: \"2px 8px\",\r\n outline: \"none\",\r\n fontSize: \"16px\",\r\n minWidth: \"8ch\",\r\n border: \"none\",\r\n};\r\n\r\nconst editButtonStyles: CSSProperties = {\r\n padding: \"4px\",\r\n borderRadius: \"50%\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.2s\",\r\n color: \"#737373\",\r\n border: \"none\",\r\n backgroundColor: \"transparent\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n};\r\n\r\nexport interface TransformedQueryChipProps {\r\n value: string;\r\n onChange: (nextValue: string) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nexport const TransformedQueryChip: FunctionComponent<\r\n TransformedQueryChipProps\r\n> = ({ value, onChange, onRemove }) => {\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const [draft, setDraft] = useState(value);\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editHover, setEditHover] = useState(false);\r\n const { t } = useTranslation();\r\n\r\n const removeLabel = t(\"smartFilter.transformedQuery.remove\");\r\n const editLabel = t(\"smartFilter.transformedQuery.edit\");\r\n\r\n useEffect(() => {\r\n setDraft(value);\r\n setIsEditing(false);\r\n }, [value]);\r\n\r\n const applyChanges = () => {\r\n const nextValue = draft.trim();\r\n if (!nextValue.length) {\r\n setDraft(value);\r\n return;\r\n }\r\n if (nextValue === value) {\r\n return;\r\n }\r\n onChange(nextValue);\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\r\n setDraft(event.target.value);\r\n };\r\n\r\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n (event.currentTarget as HTMLInputElement).blur();\r\n return;\r\n }\r\n\r\n if (event.key === \"Escape\") {\r\n event.preventDefault();\r\n setDraft(value);\r\n (event.currentTarget as HTMLInputElement).blur();\r\n return;\r\n }\r\n };\r\n\r\n return (\r\n <div style={chipStyles}>\r\n <SearchIcon style={{ width: \"16px\", height: \"16px\", color: \"#03852e\" }} />\r\n {isEditing ? (\r\n <input\r\n ref={inputRef}\r\n value={draft}\r\n onChange={handleChange}\r\n onBlur={() => {\r\n applyChanges();\r\n setIsEditing(false);\r\n }}\r\n onKeyDown={handleKeyDown}\r\n aria-label={editLabel}\r\n style={inputStyles}\r\n autoFocus\r\n />\r\n ) : (\r\n <span style={{ fontSize: \"16px\" }}>{value}</span>\r\n )}\r\n {!isEditing && (\r\n <button\r\n type=\"button\"\r\n style={{\r\n ...editButtonStyles,\r\n backgroundColor: editHover ? \"#e5e5e5\" : \"transparent\",\r\n }}\r\n aria-label={editLabel}\r\n title={editLabel}\r\n onClick={() => setIsEditing(true)}\r\n onMouseEnter={() => setEditHover(true)}\r\n onMouseLeave={() => setEditHover(false)}\r\n >\r\n <EditIcon />\r\n </button>\r\n )}\r\n <CloseButton onClick={onRemove} />\r\n </div>\r\n );\r\n};\r\n","import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\nexport const useFilterScroll = (dependency: number) => {\r\n const scrollerRef = useRef<HTMLDivElement | null>(null);\r\n const [atStart, setAtStart] = useState(true);\r\n const [atEnd, setAtEnd] = useState(true);\r\n\r\n const updateScrollButtons = useCallback(() => {\r\n const el = scrollerRef.current;\r\n if (!el) {\r\n setAtStart(true);\r\n setAtEnd(true);\r\n return;\r\n }\r\n\r\n const { scrollLeft, scrollWidth, clientWidth } = el;\r\n setAtStart(scrollLeft <= 0);\r\n setAtEnd(scrollLeft + clientWidth >= scrollWidth - 1);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const el = scrollerRef.current;\r\n updateScrollButtons();\r\n if (!el) {\r\n return;\r\n }\r\n\r\n const handleScroll = () => updateScrollButtons();\r\n el.addEventListener(\"scroll\", handleScroll, { passive: true });\r\n window.addEventListener(\"resize\", updateScrollButtons);\r\n\r\n return () => {\r\n el.removeEventListener(\"scroll\", handleScroll);\r\n window.removeEventListener(\"resize\", updateScrollButtons);\r\n };\r\n }, [dependency, updateScrollButtons]);\r\n\r\n const scrollByDir = useCallback((dir: \"prev\" | \"next\") => {\r\n const el = scrollerRef.current;\r\n if (!el) {\r\n return;\r\n }\r\n\r\n const delta = el.clientWidth * 0.7;\r\n el.scrollBy({\r\n left: dir === \"next\" ? delta : -delta,\r\n behavior: \"smooth\",\r\n });\r\n }, []);\r\n\r\n return {\r\n scrollerRef,\r\n atStart,\r\n atEnd,\r\n scrollByDir,\r\n };\r\n};\r\n"],"mappings":"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","names":["React","MapFirstCore","processApiFilters","convertToApiFilters","useCallback","React","React","jsx","jsxs","SearchIcon","className","style","CloseIcon","EditIcon","NextIcon","StarIcon","fill","jsx","closeButtonStyles","iconStyles","CloseButton","onClick","style","isHovering","setIsHovering","React","CloseIcon","jsx","jsxs","chipStyles","Chip","label","icon","remove","style","CloseButton","useState","useCallback","useState","defaultTranslations","formatCurrencyDefault","value","currency","useTranslation","customTranslations","customFormatCurrency","locale","setLocale","t","key","params","translation","paramKey","formatCurrency","jsx","jsxs","renderStars","rating","stars","fullStars","hasHalfStar","baseStyles","fullStarStyles","halfStarStyles","i","remainingStars","createMinRatingFilterLabel","suffix","formatRatingValue","createPriceRangeFilterLabel","min","max","currency","formatCurrencyFn","jsx","jsxs","chipContainerStyles","starContainerStyles","circleBaseStyles","buttonBaseStyles","MinRatingFilterChip","rating","onChange","onRemove","star","hoverRating","setHoverRating","useState","t","useTranslation","displayRating","formatLabel","value","formatRatingValue","removeLabel","setLabel","getFillForStar","index","starNumber","handleSelect","nextRating","handleBlur","event","_a","related","_","fillState","halfValue","StarIcon","circleStyles","halfCircleStyles","CloseButton","useEffect","useState","Fragment","jsx","jsxs","chipStyles","inputStyles","editButtonStyles","PriceBoundaryChip","boundary","label","value","placeholder","currency","isOptional","showRemoveButton","removeLabel","editLabel","showAddWhenEmpty","onCommit","onRemove","draft","setDraft","useState","isEditing","setIsEditing","editHover","setEditHover","hasValue","useEffect","resetDraft","commitValue","parsed","normalized","event","next","EditIcon","CloseButton","PriceRangeFilterChip","priceRange","onChange","t","useTranslation","minLabel","maxChipLabel","handleBoundaryCommit","nextValue","nextRange","jsx","jsxs","chipStyles","PRICE_LEVEL_OPTIONS","RestaurantPriceLevelChip","values","onChange","onRemove","t","useTranslation","label","removeLabel","noneSelectedLabel","handleChange","event","value","checked","valueAsPriceLevel","selection","orderedSelection","option","optionLabel","checkboxId","CloseButton","useEffect","useRef","useState","jsx","jsxs","chipStyles","inputStyles","editButtonStyles","TransformedQueryChip","value","onChange","onRemove","inputRef","useRef","draft","setDraft","useState","isEditing","setIsEditing","editHover","setEditHover","t","useTranslation","removeLabel","editLabel","useEffect","applyChanges","nextValue","SearchIcon","event","EditIcon","CloseButton","useCallback","useEffect","useRef","useState","useFilterScroll","dependency","scrollerRef","atStart","setAtStart","atEnd","setAtEnd","updateScrollButtons","el","scrollLeft","scrollWidth","clientWidth","handleScroll","scrollByDir","dir","delta","jsx","jsxs","containerStyles","scrollContainerBase","gradientStyles","navButtonStyles","FilterChips","filters","currency","minRatingSuffix","clearAllLabel","previousFiltersLabel","nextFiltersLabel","formatCurrency","onFilterChange","onResetFilters","onClearAll","scrollerRef","atStart","atEnd","scrollByDir","useFilterScroll","navHover","setNavHover","React","clearHover","setClearHover","filter","_a","_b","_c","renderStandardChip","Chip","f","currentRating","MinRatingFilterChip","nextRating","nextFilters","PriceRangeFilterChip","nextRange","TransformedQueryChip","nextValue","RestaurantPriceLevelChip","nextLevels","NextIcon","jsx","containerStyles","SmartFilter","filters","isSearching","onFilterChange","customTranslations","currency","containerStyle","style","t","formatCurrency","useTranslation","minRatingSuffix","previousFiltersLabel","nextFiltersLabel","clearAllLabel","handleFilterChange","useCallback","nextFilters","clearAll","error","resetFilters","clearAllFilters","FilterChips","useMapFirst","options","instanceRef","React","state","setState","optionsRef","opts","coreOptions","properties","_a","_b","prev","id","type","filters","bounds","pendingBounds","center","zoom","location","loading","searching","instance","MapFirstCore","setPrimaryType","setSelectedMarker","setUseApi","useApi","autoLoad","propertiesSearch","smartFilterSearch","boundsSearch","mapLibreAttachedRef","attachMapLibre","map","maplibregl","googleMapsAttachedRef","attachGoogle","google","mapboxAttachedRef","attachMapbox","mapboxgl"]}
|