@hotelcard/ui 0.0.15 → 0.0.17

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.

Potentially problematic release.


This version of @hotelcard/ui might be problematic. Click here for more details.

package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -24,31 +34,47 @@ __export(index_exports, {
24
34
  Benefits: () => Benefits,
25
35
  Block: () => Block,
26
36
  Button: () => Button,
37
+ CATEGORY_OPTIONS: () => CATEGORY_OPTIONS,
27
38
  Card: () => Card,
28
39
  Checkbox: () => Checkbox,
40
+ CheckboxFilter: () => CheckboxFilter,
29
41
  ChevronLeftIcon: () => ChevronLeftIcon,
30
42
  ChevronRightIcon: () => ChevronRightIcon2,
31
43
  Chip: () => Chip,
44
+ CollapsibleFilterSection: () => CollapsibleFilterSection,
32
45
  DateSelector: () => DateSelector,
33
46
  Divider: () => Divider,
34
47
  Dropdown: () => Dropdown,
35
48
  DualCalendar: () => DualCalendar,
49
+ ExperienceFilter: () => ExperienceFilter,
36
50
  FAQ: () => FAQ,
51
+ FilterCheckboxItem: () => FilterCheckboxItem,
52
+ FilterModal: () => FilterModal,
53
+ FilterPanel: () => FilterPanel,
37
54
  GuestContent: () => GuestContent,
38
55
  HeartIcon: () => HeartIcon3,
39
56
  HotelCard: () => HotelCard,
40
57
  HotelCardContent: () => HotelCardContent,
41
58
  HotelCardImage: () => HotelCardImage,
42
59
  HotelCardUIProvider: () => HotelCardUIProvider,
60
+ HotelCategoryFilter: () => HotelCategoryFilter,
43
61
  Input: () => Input,
62
+ MealsFilter: () => MealsFilter,
44
63
  Modal: () => Modal,
45
64
  Pin: () => Pin,
46
65
  PinIcon: () => PinIcon2,
66
+ PriceRangeFilter: () => PriceRangeFilter,
67
+ REVIEW_OPTIONS: () => REVIEW_OPTIONS,
47
68
  RadioButton: () => RadioButton,
48
69
  Rating: () => Rating,
70
+ RegionsFilter: () => RegionsFilter,
49
71
  ReviewCard: () => ReviewCard,
72
+ ReviewsFilter: () => ReviewsFilter,
50
73
  SectionHeader: () => SectionHeader,
74
+ SelectedFiltersRow: () => SelectedFiltersRow,
51
75
  StarIcon: () => StarIcon4,
76
+ TransportFilter: () => TransportFilter,
77
+ WellnessFilter: () => WellnessFilter,
52
78
  WhenContent: () => WhenContent,
53
79
  calculateDiscount: () => calculateDiscount,
54
80
  formatDate: () => formatDate,
@@ -2973,9 +2999,1333 @@ var HotelCard = ({
2973
2999
  ] });
2974
3000
  };
2975
3001
 
2976
- // src/components/icons/HeartIcon.tsx
3002
+ // src/components/Filters/FilterCheckboxItem.module.css
3003
+ var FilterCheckboxItem_default = {};
3004
+
3005
+ // src/components/Filters/FilterCheckboxItem.tsx
2977
3006
  var import_jsx_runtime26 = require("react/jsx-runtime");
2978
- var HeartIcon3 = ({ filled = false, className = "", size = 24 }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3007
+ var FilterCheckboxItem = ({
3008
+ id,
3009
+ label,
3010
+ count,
3011
+ checked,
3012
+ disabled = false,
3013
+ onChange,
3014
+ className = "",
3015
+ trackName
3016
+ }) => {
3017
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3018
+ "label",
3019
+ {
3020
+ className: `${FilterCheckboxItem_default.filterRow} ${disabled ? FilterCheckboxItem_default.filterRowDisabled : ""} ${className}`,
3021
+ tabIndex: disabled ? -1 : 0,
3022
+ "data-track": trackName,
3023
+ children: [
3024
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: FilterCheckboxItem_default.checkboxLabel, children: [
3025
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: FilterCheckboxItem_default.checkboxButton, children: [
3026
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3027
+ "input",
3028
+ {
3029
+ id,
3030
+ type: "checkbox",
3031
+ className: FilterCheckboxItem_default.checkbox,
3032
+ checked,
3033
+ disabled,
3034
+ onChange
3035
+ }
3036
+ ),
3037
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: `${FilterCheckboxItem_default.checkboxBox} ${disabled ? FilterCheckboxItem_default.checkboxBoxDisabled : ""}`, children: checked && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { viewBox: "0 0 12 10", fill: "none", className: FilterCheckboxItem_default.checkIcon, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3038
+ "path",
3039
+ {
3040
+ d: "M1 5L4.5 8.5L11 1",
3041
+ stroke: "currentColor",
3042
+ strokeWidth: "2",
3043
+ strokeLinecap: "round",
3044
+ strokeLinejoin: "round"
3045
+ }
3046
+ ) }) })
3047
+ ] }),
3048
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: `${FilterCheckboxItem_default.filterLabel} ${disabled ? FilterCheckboxItem_default.filterLabelDisabled : ""}`, children: label })
3049
+ ] }),
3050
+ count !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: `${FilterCheckboxItem_default.filterCount} ${disabled ? FilterCheckboxItem_default.filterCountDisabled : ""}`, children: count })
3051
+ ]
3052
+ }
3053
+ );
3054
+ };
3055
+
3056
+ // src/components/Filters/CollapsibleFilterSection.tsx
3057
+ var import_react15 = __toESM(require("react"), 1);
3058
+
3059
+ // src/components/Filters/CollapsibleFilterSection.module.css
3060
+ var CollapsibleFilterSection_default = {};
3061
+
3062
+ // src/components/Filters/CollapsibleFilterSection.tsx
3063
+ var import_jsx_runtime27 = require("react/jsx-runtime");
3064
+ var CollapsibleFilterSection = ({
3065
+ title,
3066
+ children,
3067
+ defaultExpanded = true,
3068
+ showAllText,
3069
+ showLessText,
3070
+ hasShowAll = false,
3071
+ initialItemsToShow = 5,
3072
+ className = ""
3073
+ }) => {
3074
+ const { t } = useUIContext();
3075
+ const [isExpanded, setIsExpanded] = (0, import_react15.useState)(defaultExpanded);
3076
+ const [showAll, setShowAll] = (0, import_react15.useState)(false);
3077
+ const resolvedShowAllText = showAllText ?? t("filter.show-all", "Show all");
3078
+ const resolvedShowLessText = showLessText ?? t("filter.show-less", "Show less");
3079
+ (0, import_react15.useEffect)(() => {
3080
+ if (defaultExpanded && !isExpanded) {
3081
+ setIsExpanded(true);
3082
+ }
3083
+ }, [defaultExpanded]);
3084
+ const toggleExpanded = () => {
3085
+ setIsExpanded(!isExpanded);
3086
+ };
3087
+ const toggleShowAll = () => {
3088
+ setShowAll(!showAll);
3089
+ };
3090
+ const childrenArray = import_react15.default.Children.toArray(children);
3091
+ const shouldShowToggle = hasShowAll && childrenArray.length > initialItemsToShow;
3092
+ const displayedChildren = shouldShowToggle && !showAll ? childrenArray.slice(0, initialItemsToShow) : childrenArray;
3093
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: `${CollapsibleFilterSection_default.section} ${className}`, children: [
3094
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3095
+ "button",
3096
+ {
3097
+ type: "button",
3098
+ className: CollapsibleFilterSection_default.header,
3099
+ onClick: toggleExpanded,
3100
+ "aria-expanded": isExpanded,
3101
+ children: [
3102
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: CollapsibleFilterSection_default.title, children: title }),
3103
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3104
+ "svg",
3105
+ {
3106
+ className: `${CollapsibleFilterSection_default.chevron} ${isExpanded ? CollapsibleFilterSection_default.chevronExpanded : ""}`,
3107
+ viewBox: "0 0 24 24",
3108
+ fill: "none",
3109
+ "aria-hidden": "true",
3110
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3111
+ "path",
3112
+ {
3113
+ d: "M6 9L12 15L18 9",
3114
+ stroke: "currentColor",
3115
+ strokeWidth: "2",
3116
+ strokeLinecap: "round",
3117
+ strokeLinejoin: "round"
3118
+ }
3119
+ )
3120
+ }
3121
+ )
3122
+ ]
3123
+ }
3124
+ ),
3125
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3126
+ "div",
3127
+ {
3128
+ className: `${CollapsibleFilterSection_default.content} ${isExpanded ? CollapsibleFilterSection_default.contentExpanded : ""}`,
3129
+ "aria-hidden": !isExpanded,
3130
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: CollapsibleFilterSection_default.contentInner, children: [
3131
+ displayedChildren,
3132
+ shouldShowToggle && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3133
+ "button",
3134
+ {
3135
+ type: "button",
3136
+ className: CollapsibleFilterSection_default.showAllButton,
3137
+ onClick: toggleShowAll,
3138
+ children: [
3139
+ showAll ? resolvedShowLessText : resolvedShowAllText,
3140
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3141
+ "svg",
3142
+ {
3143
+ className: `${CollapsibleFilterSection_default.showAllChevron} ${showAll ? CollapsibleFilterSection_default.showAllChevronUp : ""}`,
3144
+ viewBox: "0 0 24 24",
3145
+ fill: "none",
3146
+ "aria-hidden": "true",
3147
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3148
+ "path",
3149
+ {
3150
+ d: "M6 9L12 15L18 9",
3151
+ stroke: "currentColor",
3152
+ strokeWidth: "2",
3153
+ strokeLinecap: "round",
3154
+ strokeLinejoin: "round"
3155
+ }
3156
+ )
3157
+ }
3158
+ )
3159
+ ]
3160
+ }
3161
+ )
3162
+ ] })
3163
+ }
3164
+ )
3165
+ ] });
3166
+ };
3167
+
3168
+ // src/components/Filters/PriceRangeFilter.tsx
3169
+ var import_react16 = require("react");
3170
+
3171
+ // src/components/Filters/PriceRangeFilter.module.css
3172
+ var PriceRangeFilter_default = {};
3173
+
3174
+ // src/components/Filters/PriceRangeFilter.tsx
3175
+ var import_jsx_runtime28 = require("react/jsx-runtime");
3176
+ var DEFAULT_HISTOGRAM = [
3177
+ 12,
3178
+ 25,
3179
+ 38,
3180
+ 45,
3181
+ 52,
3182
+ 48,
3183
+ 42,
3184
+ 35,
3185
+ 28,
3186
+ 22,
3187
+ 18,
3188
+ 15,
3189
+ 12,
3190
+ 10,
3191
+ 8,
3192
+ 6,
3193
+ 5,
3194
+ 4,
3195
+ 3,
3196
+ 2
3197
+ ];
3198
+ var PriceRangeFilter = ({
3199
+ minPrice,
3200
+ maxPrice,
3201
+ value,
3202
+ onChange,
3203
+ onApply,
3204
+ histogram = DEFAULT_HISTOGRAM,
3205
+ currency,
3206
+ onDragStart,
3207
+ onDragEnd,
3208
+ debounceDelay = 500
3209
+ }) => {
3210
+ const { t, currency: contextCurrency } = useUIContext();
3211
+ const displayCurrency = currency ?? contextCurrency;
3212
+ const sliderRef = (0, import_react16.useRef)(null);
3213
+ const [isDragging, setIsDragging] = (0, import_react16.useState)(null);
3214
+ const [isDraggingExternal, setIsDraggingExternal] = (0, import_react16.useState)(false);
3215
+ const lastValueRef = (0, import_react16.useRef)(value);
3216
+ const timeoutRef = (0, import_react16.useRef)(null);
3217
+ const [minInputValue, setMinInputValue] = (0, import_react16.useState)("");
3218
+ const [maxInputValue, setMaxInputValue] = (0, import_react16.useState)("");
3219
+ const [minInputFocused, setMinInputFocused] = (0, import_react16.useState)(false);
3220
+ const [maxInputFocused, setMaxInputFocused] = (0, import_react16.useState)(false);
3221
+ const range = maxPrice - minPrice;
3222
+ const minPercent = range > 0 ? (value.min - minPrice) / range * 100 : 0;
3223
+ const maxPercent = range > 0 ? (value.max - minPrice) / range * 100 : 100;
3224
+ const maxHistogramValue = Math.max(...histogram, 1);
3225
+ const getBarActive = (0, import_react16.useCallback)((index) => {
3226
+ const barStartPercent = index / histogram.length * 100;
3227
+ const barEndPercent = (index + 1) / histogram.length * 100;
3228
+ return barStartPercent < maxPercent && barEndPercent > minPercent;
3229
+ }, [histogram.length, minPercent, maxPercent]);
3230
+ const trackInset = 12;
3231
+ const triggerOnApply = (0, import_react16.useCallback)((newValue) => {
3232
+ if (!onApply) return;
3233
+ if (timeoutRef.current) {
3234
+ clearTimeout(timeoutRef.current);
3235
+ }
3236
+ timeoutRef.current = setTimeout(() => {
3237
+ onApply(newValue);
3238
+ }, debounceDelay);
3239
+ }, [onApply, debounceDelay]);
3240
+ const handleDrag = (0, import_react16.useCallback)((clientX) => {
3241
+ if (!sliderRef.current || !isDragging) return;
3242
+ const rect = sliderRef.current.getBoundingClientRect();
3243
+ const trackWidth = rect.width - trackInset * 2;
3244
+ const trackLeft = rect.left + trackInset;
3245
+ const percent = Math.max(0, Math.min(100, (clientX - trackLeft) / trackWidth * 100));
3246
+ const newValue = Math.round(minPrice + percent / 100 * range);
3247
+ let newMin = value.min;
3248
+ let newMax = value.max;
3249
+ if (isDragging === "min") {
3250
+ const clampedValue = Math.min(newValue, value.max - 1);
3251
+ newMin = Math.max(minPrice, clampedValue);
3252
+ } else {
3253
+ const clampedValue = Math.max(newValue, value.min + 1);
3254
+ newMax = Math.min(maxPrice, clampedValue);
3255
+ }
3256
+ const newRange = { min: newMin, max: newMax };
3257
+ onChange(newRange);
3258
+ lastValueRef.current = newRange;
3259
+ if (!isDraggingExternal) {
3260
+ triggerOnApply(newRange);
3261
+ }
3262
+ }, [isDragging, minPrice, maxPrice, range, value, onChange, isDraggingExternal, triggerOnApply]);
3263
+ const handleMouseDown = (handle) => (e) => {
3264
+ e.preventDefault();
3265
+ setIsDragging(handle);
3266
+ setIsDraggingExternal(true);
3267
+ onDragStart?.();
3268
+ };
3269
+ const handleTouchStart = (handle) => (e) => {
3270
+ e.preventDefault();
3271
+ setIsDragging(handle);
3272
+ setIsDraggingExternal(true);
3273
+ onDragStart?.();
3274
+ };
3275
+ const handleDragEnd = (0, import_react16.useCallback)(() => {
3276
+ if (isDraggingExternal && onApply) {
3277
+ onApply(lastValueRef.current);
3278
+ }
3279
+ setIsDragging(null);
3280
+ setIsDraggingExternal(false);
3281
+ onDragEnd?.();
3282
+ }, [isDraggingExternal, onApply, onDragEnd]);
3283
+ (0, import_react16.useEffect)(() => {
3284
+ if (!isDragging) return;
3285
+ const handleMouseMove = (e) => {
3286
+ handleDrag(e.clientX);
3287
+ };
3288
+ const handleTouchMove = (e) => {
3289
+ if (e.touches.length > 0) {
3290
+ handleDrag(e.touches[0].clientX);
3291
+ }
3292
+ };
3293
+ document.addEventListener("mousemove", handleMouseMove);
3294
+ document.addEventListener("mouseup", handleDragEnd);
3295
+ document.addEventListener("touchmove", handleTouchMove, { passive: false });
3296
+ document.addEventListener("touchend", handleDragEnd);
3297
+ return () => {
3298
+ document.removeEventListener("mousemove", handleMouseMove);
3299
+ document.removeEventListener("mouseup", handleDragEnd);
3300
+ document.removeEventListener("touchmove", handleTouchMove);
3301
+ document.removeEventListener("touchend", handleDragEnd);
3302
+ if (timeoutRef.current) {
3303
+ clearTimeout(timeoutRef.current);
3304
+ }
3305
+ };
3306
+ }, [isDragging, handleDrag, handleDragEnd]);
3307
+ const handleMinInputFocus = () => {
3308
+ setMinInputFocused(true);
3309
+ setMinInputValue(value.min.toString());
3310
+ };
3311
+ const handleMaxInputFocus = () => {
3312
+ setMaxInputFocused(true);
3313
+ setMaxInputValue(value.max.toString());
3314
+ };
3315
+ const handleMinInputChange = (e) => {
3316
+ const val = e.target.value.replace(/[^0-9]/g, "");
3317
+ setMinInputValue(val);
3318
+ };
3319
+ const handleMaxInputChange = (e) => {
3320
+ const val = e.target.value.replace(/[^0-9]/g, "");
3321
+ setMaxInputValue(val);
3322
+ };
3323
+ const handleMinInputBlur = () => {
3324
+ setMinInputFocused(false);
3325
+ const numValue = parseInt(minInputValue, 10);
3326
+ if (!isNaN(numValue)) {
3327
+ const clampedValue = Math.max(minPrice, Math.min(numValue, value.max - 1));
3328
+ const newRange = { min: clampedValue, max: value.max };
3329
+ onChange(newRange);
3330
+ if (onApply) {
3331
+ triggerOnApply(newRange);
3332
+ }
3333
+ }
3334
+ };
3335
+ const handleMaxInputBlur = () => {
3336
+ setMaxInputFocused(false);
3337
+ const numValue = parseInt(maxInputValue, 10);
3338
+ if (!isNaN(numValue)) {
3339
+ const clampedValue = Math.min(maxPrice, Math.max(numValue, value.min + 1));
3340
+ const newRange = { min: value.min, max: clampedValue };
3341
+ onChange(newRange);
3342
+ if (onApply) {
3343
+ triggerOnApply(newRange);
3344
+ }
3345
+ }
3346
+ };
3347
+ (0, import_react16.useEffect)(() => {
3348
+ return () => {
3349
+ if (timeoutRef.current) {
3350
+ clearTimeout(timeoutRef.current);
3351
+ }
3352
+ };
3353
+ }, []);
3354
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: PriceRangeFilter_default.priceRangeWrapper, children: [
3355
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: PriceRangeFilter_default.priceInputs, children: [
3356
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: PriceRangeFilter_default.priceInputWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3357
+ "input",
3358
+ {
3359
+ type: "text",
3360
+ inputMode: "numeric",
3361
+ className: PriceRangeFilter_default.priceInput,
3362
+ value: minInputFocused ? minInputValue : `${displayCurrency} ${value.min}`,
3363
+ onChange: handleMinInputChange,
3364
+ onFocus: handleMinInputFocus,
3365
+ onBlur: handleMinInputBlur,
3366
+ "aria-label": t("filter.min-price", "Minimum price")
3367
+ }
3368
+ ) }),
3369
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: PriceRangeFilter_default.priceInputDivider, children: "\u2014" }),
3370
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: PriceRangeFilter_default.priceInputWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3371
+ "input",
3372
+ {
3373
+ type: "text",
3374
+ inputMode: "numeric",
3375
+ className: PriceRangeFilter_default.priceInput,
3376
+ value: maxInputFocused ? maxInputValue : `${displayCurrency} ${value.max}`,
3377
+ onChange: handleMaxInputChange,
3378
+ onFocus: handleMaxInputFocus,
3379
+ onBlur: handleMaxInputBlur,
3380
+ "aria-label": t("filter.max-price", "Maximum price")
3381
+ }
3382
+ ) })
3383
+ ] }),
3384
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: PriceRangeFilter_default.histogram, children: histogram.map((histValue, index) => {
3385
+ const height = histValue / maxHistogramValue * 100;
3386
+ const isActive = getBarActive(index);
3387
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3388
+ "div",
3389
+ {
3390
+ className: `${PriceRangeFilter_default.histogramBar} ${isActive ? PriceRangeFilter_default.histogramBarActive : ""}`,
3391
+ style: { height: `${Math.max(height, 10)}%` }
3392
+ },
3393
+ index
3394
+ );
3395
+ }) }),
3396
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: PriceRangeFilter_default.sliderContainer, ref: sliderRef, children: [
3397
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: PriceRangeFilter_default.sliderTrack }),
3398
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3399
+ "div",
3400
+ {
3401
+ className: PriceRangeFilter_default.sliderActiveTrack,
3402
+ style: {
3403
+ left: `calc(12px + (100% - 24px) * ${minPercent / 100})`,
3404
+ width: `calc((100% - 24px) * ${(maxPercent - minPercent) / 100})`
3405
+ }
3406
+ }
3407
+ ),
3408
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3409
+ "div",
3410
+ {
3411
+ className: `${PriceRangeFilter_default.sliderHandle} ${isDragging === "min" ? PriceRangeFilter_default.sliderHandleActive : ""}`,
3412
+ style: { left: `calc(12px + (100% - 24px) * ${minPercent / 100})` },
3413
+ onMouseDown: handleMouseDown("min"),
3414
+ onTouchStart: handleTouchStart("min"),
3415
+ role: "slider",
3416
+ "aria-label": t("filter.min-price", "Minimum price"),
3417
+ "aria-valuenow": value.min,
3418
+ "aria-valuemin": minPrice,
3419
+ "aria-valuemax": value.max,
3420
+ tabIndex: 0
3421
+ }
3422
+ ),
3423
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3424
+ "div",
3425
+ {
3426
+ className: `${PriceRangeFilter_default.sliderHandle} ${isDragging === "max" ? PriceRangeFilter_default.sliderHandleActive : ""}`,
3427
+ style: { left: `calc(12px + (100% - 24px) * ${maxPercent / 100})` },
3428
+ onMouseDown: handleMouseDown("max"),
3429
+ onTouchStart: handleTouchStart("max"),
3430
+ role: "slider",
3431
+ "aria-label": t("filter.max-price", "Maximum price"),
3432
+ "aria-valuenow": value.max,
3433
+ "aria-valuemin": value.min,
3434
+ "aria-valuemax": maxPrice,
3435
+ tabIndex: 0
3436
+ }
3437
+ )
3438
+ ] })
3439
+ ] });
3440
+ };
3441
+
3442
+ // src/components/Filters/HotelCategoryFilter.module.css
3443
+ var HotelCategoryFilter_default = {};
3444
+
3445
+ // src/components/Filters/HotelCategoryFilter.tsx
3446
+ var import_jsx_runtime29 = require("react/jsx-runtime");
3447
+ var CATEGORY_OPTIONS = [
3448
+ { value: "5", stars: 5, label: null },
3449
+ { value: "4", stars: 4, label: null },
3450
+ { value: "3", stars: 3, label: null },
3451
+ { value: "2", stars: 2, label: null },
3452
+ { value: "swiss_lodge", stars: 0, label: "Swiss Lodge" },
3453
+ { value: "not_classified", stars: 0, label: "No category" }
3454
+ ];
3455
+ var HotelCategoryFilter = ({
3456
+ selected,
3457
+ counts = {},
3458
+ onChange,
3459
+ className = ""
3460
+ }) => {
3461
+ const { t } = useUIContext();
3462
+ const handleToggle = (value) => {
3463
+ if (selected.includes(value)) {
3464
+ onChange(selected.filter((v) => v !== value));
3465
+ } else {
3466
+ onChange([...selected, value]);
3467
+ }
3468
+ };
3469
+ const getLabel = (option) => {
3470
+ if (option.stars > 0) return null;
3471
+ if (option.value === "swiss_lodge") return t("filter.swiss-lodge", "Swiss Lodge");
3472
+ if (option.value === "not_classified") return t("filter.no-category", "No category");
3473
+ return option.label;
3474
+ };
3475
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className, children: [
3476
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: HotelCategoryFilter_default.filterList, children: CATEGORY_OPTIONS.map((option) => {
3477
+ const count = counts[option.value];
3478
+ const isDisabled = count === 0 && !selected.includes(option.value);
3479
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3480
+ FilterCheckboxItem,
3481
+ {
3482
+ id: `category-${option.value}`,
3483
+ label: option.stars > 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: HotelCategoryFilter_default.starsContainer, children: Array.from({ length: option.stars }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { className: HotelCategoryFilter_default.starIcon, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "M12 0L14.6942 8.2918H23.4127L16.3593 13.4164L19.0534 21.7082L12 16.5836L4.94658 21.7082L7.64074 13.4164L0.587322 8.2918H9.30583L12 0Z" }) }, i)) }) : getLabel(option),
3484
+ count,
3485
+ checked: selected.includes(option.value),
3486
+ disabled: isDisabled,
3487
+ onChange: () => handleToggle(option.value),
3488
+ trackName: `filter-category-${option.value}`
3489
+ },
3490
+ option.value
3491
+ );
3492
+ }) }),
3493
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: HotelCategoryFilter_default.footer, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: HotelCategoryFilter_default.footerText, children: t("filter.hotellerie-suisse", "Classification HotellerieSuisse") }) })
3494
+ ] });
3495
+ };
3496
+
3497
+ // src/components/Filters/ReviewsFilter.module.css
3498
+ var ReviewsFilter_default = {};
3499
+
3500
+ // src/components/Filters/ReviewsFilter.tsx
3501
+ var import_jsx_runtime30 = require("react/jsx-runtime");
3502
+ var REVIEW_OPTIONS = [
3503
+ { value: "excellent", labelKey: "rating-excellent", range: "(4.4+)" },
3504
+ { value: "very_good", labelKey: "rating-very-good", range: "(4.1 \u2013 4.3)" },
3505
+ { value: "good", labelKey: "rating-good", range: "(3.8 \u2013 4.0)" },
3506
+ { value: "fair", labelKey: "rating-fair", range: "(3.5 \u2013 3.7)" },
3507
+ { value: "no_rating", labelKey: "rating-none", range: "" }
3508
+ ];
3509
+ var ReviewsFilter = ({
3510
+ selected,
3511
+ counts = {},
3512
+ onChange,
3513
+ className = "",
3514
+ isPlaceSearchActive = false
3515
+ }) => {
3516
+ const { t } = useUIContext();
3517
+ const handleToggle = (value) => {
3518
+ if (selected.includes(value)) {
3519
+ onChange(selected.filter((v) => v !== value));
3520
+ } else {
3521
+ onChange([...selected, value]);
3522
+ }
3523
+ };
3524
+ const getRatingLabel = (labelKey) => {
3525
+ const labelMap = {
3526
+ "rating-excellent": t("label.rating-excellent", "Excellent"),
3527
+ "rating-very-good": t("label.rating-very-good", "Very Good"),
3528
+ "rating-good": t("label.rating-good", "Good"),
3529
+ "rating-fair": t("label.rating-fair", "Fair"),
3530
+ "rating-none": t("label.rating-none", "No rating")
3531
+ };
3532
+ return labelMap[labelKey] ?? labelKey;
3533
+ };
3534
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className, children: [
3535
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: ReviewsFilter_default.filterList, children: REVIEW_OPTIONS.map((option) => {
3536
+ const count = counts[option.value];
3537
+ const isDisabled = !isPlaceSearchActive && count === 0 && !selected.includes(option.value);
3538
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
3539
+ FilterCheckboxItem,
3540
+ {
3541
+ id: `review-${option.value}`,
3542
+ label: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
3543
+ getRatingLabel(option.labelKey),
3544
+ option.range && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: ReviewsFilter_default.filterRange, children: [
3545
+ " ",
3546
+ option.range
3547
+ ] })
3548
+ ] }),
3549
+ count,
3550
+ checked: selected.includes(option.value),
3551
+ disabled: isDisabled,
3552
+ onChange: () => handleToggle(option.value),
3553
+ trackName: `filter-review-${option.value}`
3554
+ },
3555
+ option.value
3556
+ );
3557
+ }) }),
3558
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: ReviewsFilter_default.footer, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: ReviewsFilter_default.footerText, children: t("filter.trustyou", "Reviews from TrustYou\xAE") }) })
3559
+ ] });
3560
+ };
3561
+
3562
+ // src/components/Filters/ExperienceFilter.tsx
3563
+ var import_react17 = require("react");
3564
+
3565
+ // src/components/Filters/ExperienceFilter.module.css
3566
+ var ExperienceFilter_default = {};
3567
+
3568
+ // src/components/Filters/ExperienceFilter.tsx
3569
+ var import_jsx_runtime31 = require("react/jsx-runtime");
3570
+ var ExperienceFilter = ({
3571
+ selected,
3572
+ themes = [],
3573
+ onChange,
3574
+ className = ""
3575
+ }) => {
3576
+ const { t } = useUIContext();
3577
+ const [expanded, setExpanded] = (0, import_react17.useState)(false);
3578
+ const visibleThemes = expanded ? themes : themes.slice(0, 5);
3579
+ const hasMoreThemes = themes.length > 5;
3580
+ const handleToggle = (value) => {
3581
+ if (selected.includes(value)) {
3582
+ onChange(selected.filter((v) => v !== value));
3583
+ } else {
3584
+ onChange([...selected, value]);
3585
+ }
3586
+ };
3587
+ if (themes.length === 0) {
3588
+ return null;
3589
+ }
3590
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: `${ExperienceFilter_default.filterList} ${className}`, children: [
3591
+ visibleThemes.map((theme) => {
3592
+ const themeIdStr = String(theme.id);
3593
+ const isDisabled = theme.count === 0 && !selected.includes(themeIdStr);
3594
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3595
+ FilterCheckboxItem,
3596
+ {
3597
+ id: `experience-${theme.id}`,
3598
+ label: theme.name,
3599
+ count: theme.count > 0 ? theme.count : void 0,
3600
+ checked: selected.includes(themeIdStr),
3601
+ disabled: isDisabled,
3602
+ onChange: () => handleToggle(themeIdStr),
3603
+ trackName: `filter-experience-${theme.id}`
3604
+ },
3605
+ theme.id
3606
+ );
3607
+ }),
3608
+ hasMoreThemes && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
3609
+ "button",
3610
+ {
3611
+ type: "button",
3612
+ className: ExperienceFilter_default.showMoreBtn,
3613
+ onClick: () => setExpanded(!expanded),
3614
+ children: [
3615
+ expanded ? t("filter.show-less", "Show less") : t("filter.show-all", "Show all"),
3616
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: `${ExperienceFilter_default.arrowIcon} ${expanded ? ExperienceFilter_default.arrowUp : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("path", { d: "M9.36927 13.9061C9.71908 14.2535 10.2847 14.2535 10.6308 13.9061L16.4069 8.1803C16.7567 7.83285 16.7567 7.27102 16.4069 6.92727C16.0571 6.58352 15.4915 6.57983 15.1454 6.92727L10.0019 12.0247L4.85845 6.92727C4.50864 6.57983 3.94299 6.57983 3.5969 6.92727C3.25081 7.27472 3.24709 7.83655 3.5969 8.1803L9.37299 13.9061H9.36927Z", fill: "currentColor" }) }) })
3617
+ ]
3618
+ }
3619
+ )
3620
+ ] });
3621
+ };
3622
+
3623
+ // src/components/Filters/RegionsFilter.tsx
3624
+ var import_react18 = require("react");
3625
+
3626
+ // src/components/Filters/RegionsFilter.module.css
3627
+ var RegionsFilter_default = {};
3628
+
3629
+ // src/components/Filters/RegionsFilter.tsx
3630
+ var import_jsx_runtime32 = require("react/jsx-runtime");
3631
+ var RegionsFilter = ({
3632
+ regions,
3633
+ selected,
3634
+ onChange,
3635
+ className = "",
3636
+ isPlaceSearchActive = false
3637
+ }) => {
3638
+ const { t } = useUIContext();
3639
+ const [expandedCountries, setExpandedCountries] = (0, import_react18.useState)(/* @__PURE__ */ new Set(["country_215"]));
3640
+ const hasInitializedRef = (0, import_react18.useRef)(false);
3641
+ (0, import_react18.useEffect)(() => {
3642
+ if (hasInitializedRef.current) return;
3643
+ if (regions.length === 0 || selected.length === 0) return;
3644
+ const countriesWithSelectedRegions = /* @__PURE__ */ new Set();
3645
+ regions.forEach((region) => {
3646
+ if (region.subRegions?.some((sub) => selected.includes(sub.value))) {
3647
+ countriesWithSelectedRegions.add(region.value);
3648
+ }
3649
+ });
3650
+ if (countriesWithSelectedRegions.size > 0) {
3651
+ setExpandedCountries(countriesWithSelectedRegions);
3652
+ hasInitializedRef.current = true;
3653
+ }
3654
+ }, [regions, selected]);
3655
+ const handleCountryToggle = (countryValue) => {
3656
+ setExpandedCountries((prev) => {
3657
+ const next = new Set(prev);
3658
+ if (next.has(countryValue)) {
3659
+ next.delete(countryValue);
3660
+ } else {
3661
+ next.add(countryValue);
3662
+ }
3663
+ return next;
3664
+ });
3665
+ };
3666
+ const handleRegionToggle = (regionValue) => {
3667
+ if (selected.includes(regionValue)) {
3668
+ onChange(selected.filter((r) => r !== regionValue));
3669
+ } else {
3670
+ onChange([...selected, regionValue]);
3671
+ }
3672
+ };
3673
+ if (regions.length === 0) {
3674
+ return null;
3675
+ }
3676
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: `${RegionsFilter_default.filterList} ${className}`, children: regions.map((region) => {
3677
+ const hasSubRegions = region.subRegions && region.subRegions.length > 0;
3678
+ const isExpanded = expandedCountries.has(region.value);
3679
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: RegionsFilter_default.regionItem, children: [
3680
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
3681
+ "button",
3682
+ {
3683
+ type: "button",
3684
+ className: `${RegionsFilter_default.countryRow} ${isExpanded ? RegionsFilter_default.countryRowExpanded : ""}`,
3685
+ onClick: () => handleCountryToggle(region.value),
3686
+ "aria-expanded": isExpanded,
3687
+ disabled: isPlaceSearchActive,
3688
+ children: [
3689
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: RegionsFilter_default.countryInfo, children: [
3690
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: RegionsFilter_default.countryName, children: region.label }),
3691
+ region.count !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: RegionsFilter_default.countBadge, children: region.count })
3692
+ ] }),
3693
+ hasSubRegions && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3694
+ "svg",
3695
+ {
3696
+ xmlns: "http://www.w3.org/2000/svg",
3697
+ width: "20",
3698
+ height: "20",
3699
+ viewBox: "0 0 20 20",
3700
+ fill: "none",
3701
+ className: `${RegionsFilter_default.chevron} ${isExpanded ? RegionsFilter_default.chevronExpanded : ""}`,
3702
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M9.36927 13.9061C9.71908 14.2535 10.2847 14.2535 10.6308 13.9061L16.4069 8.18027C16.7567 7.83283 16.7567 7.271 16.4069 6.92725C16.0571 6.5835 15.4915 6.5798 15.1454 6.92725L10.0019 12.0247L4.85845 6.92725C4.50864 6.5798 3.94299 6.5798 3.5969 6.92725C3.25081 7.2747 3.24709 7.83652 3.5969 8.18027L9.37299 13.9061H9.36927Z", fill: "#6B7280" })
3703
+ }
3704
+ )
3705
+ ]
3706
+ }
3707
+ ),
3708
+ hasSubRegions && isExpanded && (() => {
3709
+ const hasSelectableRegions = region.subRegions.some(
3710
+ (sr) => sr.count === void 0 || sr.count > 0
3711
+ );
3712
+ const subValues = region.subRegions.map((sr) => sr.value);
3713
+ const hasSelectedRegions = subValues.some((v) => selected.includes(v));
3714
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: RegionsFilter_default.mobileSelectAllActions, children: [
3715
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3716
+ "button",
3717
+ {
3718
+ type: "button",
3719
+ className: RegionsFilter_default.selectAllBtn,
3720
+ disabled: !hasSelectableRegions,
3721
+ onClick: () => {
3722
+ const selectableSubValues = region.subRegions.filter((sr) => sr.count === void 0 || sr.count > 0).map((sr) => sr.value);
3723
+ const merged = Array.from(/* @__PURE__ */ new Set([...selected, ...selectableSubValues]));
3724
+ onChange(merged);
3725
+ },
3726
+ children: t("filter.select-all", "Select all")
3727
+ }
3728
+ ),
3729
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3730
+ "button",
3731
+ {
3732
+ type: "button",
3733
+ className: RegionsFilter_default.resetAllBtn,
3734
+ disabled: !hasSelectedRegions,
3735
+ onClick: () => {
3736
+ onChange(selected.filter((v) => !subValues.includes(v)));
3737
+ },
3738
+ children: t("filter.reset", "Reset")
3739
+ }
3740
+ )
3741
+ ] });
3742
+ })(),
3743
+ hasSubRegions && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: RegionsFilter_default.subRegions, children: region.subRegions.map((subRegion) => {
3744
+ const isDisabled = subRegion.count === 0 && !selected.includes(subRegion.value) || isPlaceSearchActive && !selected.includes(subRegion.value);
3745
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3746
+ FilterCheckboxItem,
3747
+ {
3748
+ id: `region-${subRegion.value}`,
3749
+ label: subRegion.label,
3750
+ count: subRegion.count,
3751
+ checked: selected.includes(subRegion.value),
3752
+ disabled: isDisabled,
3753
+ onChange: () => handleRegionToggle(subRegion.value),
3754
+ trackName: `filter-region-${subRegion.value}`
3755
+ },
3756
+ subRegion.value
3757
+ );
3758
+ }) })
3759
+ ] }, region.value);
3760
+ }) });
3761
+ };
3762
+
3763
+ // src/components/Filters/CheckboxFilter.module.css
3764
+ var CheckboxFilter_default = {};
3765
+
3766
+ // src/components/Filters/CheckboxFilter.tsx
3767
+ var import_jsx_runtime33 = require("react/jsx-runtime");
3768
+ var CheckboxFilter = ({
3769
+ selected,
3770
+ counts = {},
3771
+ options = [],
3772
+ onChange,
3773
+ className = "",
3774
+ trackPrefix = "filter"
3775
+ }) => {
3776
+ const handleToggle = (value) => {
3777
+ if (selected.includes(value)) {
3778
+ onChange(selected.filter((v) => v !== value));
3779
+ } else {
3780
+ onChange([...selected, value]);
3781
+ }
3782
+ };
3783
+ if (options.length === 0) {
3784
+ return null;
3785
+ }
3786
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: `${CheckboxFilter_default.filterList} ${className}`, children: options.map((option) => {
3787
+ const count = counts[option.key];
3788
+ const isDisabled = count === 0 && !selected.includes(option.key);
3789
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3790
+ FilterCheckboxItem,
3791
+ {
3792
+ id: `${trackPrefix}-${option.key}`,
3793
+ label: option.name,
3794
+ count,
3795
+ checked: selected.includes(option.key),
3796
+ disabled: isDisabled,
3797
+ onChange: () => handleToggle(option.key),
3798
+ trackName: `filter-${trackPrefix}-${option.key}`
3799
+ },
3800
+ option.key
3801
+ );
3802
+ }) });
3803
+ };
3804
+ var MealsFilter = (props) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CheckboxFilter, { ...props, trackPrefix: "meals" });
3805
+ var TransportFilter = (props) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CheckboxFilter, { ...props, trackPrefix: "transport" });
3806
+ var WellnessFilter = (props) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CheckboxFilter, { ...props, trackPrefix: "wellness" });
3807
+
3808
+ // src/components/Filters/SelectedFiltersRow.module.css
3809
+ var SelectedFiltersRow_default = {};
3810
+
3811
+ // src/components/Filters/SelectedFiltersRow.tsx
3812
+ var import_jsx_runtime34 = require("react/jsx-runtime");
3813
+ var SelectedFiltersRow = ({
3814
+ filters,
3815
+ onRemove,
3816
+ onClearAll,
3817
+ className = ""
3818
+ }) => {
3819
+ const { t } = useUIContext();
3820
+ if (filters.length === 0) {
3821
+ return null;
3822
+ }
3823
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: `${SelectedFiltersRow_default.container} ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: SelectedFiltersRow_default.chipsWrapper, children: [
3824
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { className: SelectedFiltersRow_default.selectedText, children: [
3825
+ t("filter.selected", "Selected:"),
3826
+ " "
3827
+ ] }),
3828
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: SelectedFiltersRow_default.chips, children: [
3829
+ filters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3830
+ Chip,
3831
+ {
3832
+ label: filter.label,
3833
+ size: "small",
3834
+ state: "idle",
3835
+ removable: true,
3836
+ onRemove: () => onRemove(filter)
3837
+ },
3838
+ filter.id
3839
+ )),
3840
+ onClearAll && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3841
+ Button,
3842
+ {
3843
+ variant: "link",
3844
+ className: SelectedFiltersRow_default.clearAllBtn,
3845
+ onClick: onClearAll,
3846
+ children: t("filter.clear-all", "Clear all")
3847
+ }
3848
+ )
3849
+ ] })
3850
+ ] }) });
3851
+ };
3852
+
3853
+ // src/components/Filters/FilterPanel.tsx
3854
+ var import_react19 = require("react");
3855
+
3856
+ // src/components/Filters/FilterPanel.module.css
3857
+ var FilterPanel_default = {};
3858
+
3859
+ // src/components/Filters/FilterPanel.tsx
3860
+ var import_jsx_runtime35 = require("react/jsx-runtime");
3861
+ var DISCOUNT_OPTIONS = [
3862
+ { value: "50", label: "50%" },
3863
+ { value: "30", label: "30%" },
3864
+ { value: "10", label: "10%" }
3865
+ ];
3866
+ var OPTIONS_FILTER = [
3867
+ { value: "instant_booking", labelKey: "filter.instant-booking" }
3868
+ ];
3869
+ var FilterPanel = ({
3870
+ onFilterChange,
3871
+ className = "",
3872
+ isLoading = false,
3873
+ priceHistogram,
3874
+ minPrice = 50,
3875
+ maxPrice = 500,
3876
+ regions = [],
3877
+ discountCounts = {},
3878
+ optionsCounts = {},
3879
+ categoryCounts = {},
3880
+ themes = [],
3881
+ mealsCounts = {},
3882
+ reviewsCounts = {},
3883
+ transportCounts = {},
3884
+ wellnessCounts = {},
3885
+ servicesCounts = {},
3886
+ filterOptions,
3887
+ selectedDiscounts: externalDiscounts,
3888
+ selectedOptions: externalOptions,
3889
+ selectedExperiences: externalExperiences,
3890
+ selectedRegions: externalRegions,
3891
+ selectedCategories: externalCategories,
3892
+ selectedMeals: externalMeals,
3893
+ selectedReviews: externalReviews,
3894
+ selectedTransport: externalTransport,
3895
+ selectedWellness: externalWellness,
3896
+ selectedServices: externalServices,
3897
+ selectedPriceRange: externalPriceRange
3898
+ }) => {
3899
+ const { t, currency } = useUIContext();
3900
+ const hasInitialLoadRef = (0, import_react19.useRef)(false);
3901
+ if (!hasInitialLoadRef.current) {
3902
+ if (regions.length > 0 || priceHistogram && priceHistogram.length > 0 || Object.keys(discountCounts).length > 0 || Object.keys(categoryCounts).length > 0) {
3903
+ hasInitialLoadRef.current = true;
3904
+ }
3905
+ }
3906
+ const [priceMin, setPriceMin] = (0, import_react19.useState)(externalPriceRange?.min ?? minPrice);
3907
+ const [priceMax, setPriceMax] = (0, import_react19.useState)(externalPriceRange?.max ?? maxPrice);
3908
+ const [selectedRegions, setSelectedRegions] = (0, import_react19.useState)(externalRegions ?? []);
3909
+ const [selectedDiscounts, setSelectedDiscounts] = (0, import_react19.useState)(externalDiscounts ?? []);
3910
+ const [selectedOptions, setSelectedOptions] = (0, import_react19.useState)(externalOptions ?? []);
3911
+ const [selectedCategories, setSelectedCategories] = (0, import_react19.useState)(externalCategories ?? []);
3912
+ const [selectedExperiences, setSelectedExperiences] = (0, import_react19.useState)(externalExperiences ?? []);
3913
+ const [selectedMeals, setSelectedMeals] = (0, import_react19.useState)(externalMeals ?? []);
3914
+ const [selectedReviews, setSelectedReviews] = (0, import_react19.useState)(externalReviews ?? []);
3915
+ const [selectedTransport, setSelectedTransport] = (0, import_react19.useState)(externalTransport ?? []);
3916
+ const [selectedWellness, setSelectedWellness] = (0, import_react19.useState)(externalWellness ?? []);
3917
+ const [selectedServices, setSelectedServices] = (0, import_react19.useState)(externalServices ?? []);
3918
+ (0, import_react19.useEffect)(() => {
3919
+ if (externalPriceRange) {
3920
+ setPriceMin(externalPriceRange.min);
3921
+ setPriceMax(externalPriceRange.max);
3922
+ } else {
3923
+ setPriceMin(minPrice);
3924
+ setPriceMax(maxPrice);
3925
+ }
3926
+ }, [externalPriceRange, minPrice, maxPrice]);
3927
+ (0, import_react19.useEffect)(() => {
3928
+ if (externalDiscounts !== void 0) setSelectedDiscounts(externalDiscounts);
3929
+ }, [externalDiscounts]);
3930
+ (0, import_react19.useEffect)(() => {
3931
+ if (externalOptions !== void 0) setSelectedOptions(externalOptions);
3932
+ }, [externalOptions]);
3933
+ (0, import_react19.useEffect)(() => {
3934
+ if (externalExperiences !== void 0) setSelectedExperiences(externalExperiences);
3935
+ }, [externalExperiences]);
3936
+ (0, import_react19.useEffect)(() => {
3937
+ if (externalRegions !== void 0) setSelectedRegions(externalRegions);
3938
+ }, [externalRegions]);
3939
+ (0, import_react19.useEffect)(() => {
3940
+ if (externalCategories !== void 0) setSelectedCategories(externalCategories);
3941
+ }, [externalCategories]);
3942
+ (0, import_react19.useEffect)(() => {
3943
+ if (externalMeals !== void 0) setSelectedMeals(externalMeals);
3944
+ }, [externalMeals]);
3945
+ (0, import_react19.useEffect)(() => {
3946
+ if (externalReviews !== void 0) setSelectedReviews(externalReviews);
3947
+ }, [externalReviews]);
3948
+ (0, import_react19.useEffect)(() => {
3949
+ if (externalTransport !== void 0) setSelectedTransport(externalTransport);
3950
+ }, [externalTransport]);
3951
+ (0, import_react19.useEffect)(() => {
3952
+ if (externalWellness !== void 0) setSelectedWellness(externalWellness);
3953
+ }, [externalWellness]);
3954
+ (0, import_react19.useEffect)(() => {
3955
+ if (externalServices !== void 0) setSelectedServices(externalServices);
3956
+ }, [externalServices]);
3957
+ const handlePriceChange = (value) => {
3958
+ setPriceMin(value.min);
3959
+ setPriceMax(value.max);
3960
+ };
3961
+ const handlePriceSearch = (0, import_react19.useCallback)(async (range) => {
3962
+ await onFilterChange?.({ priceRange: range });
3963
+ }, [onFilterChange]);
3964
+ const debouncedFetch = useDebounce(handlePriceSearch, 500);
3965
+ const handlePriceApply = (range) => {
3966
+ debouncedFetch(range);
3967
+ };
3968
+ const handleDiscountToggle = (discountValue) => {
3969
+ setSelectedDiscounts((prev) => {
3970
+ const newDiscounts = prev.includes(discountValue) ? prev.filter((d) => d !== discountValue) : [...prev, discountValue];
3971
+ onFilterChange?.({ discounts: newDiscounts });
3972
+ return newDiscounts;
3973
+ });
3974
+ };
3975
+ const handleOptionToggle = (optionValue) => {
3976
+ setSelectedOptions((prev) => {
3977
+ const newOptions = prev.includes(optionValue) ? prev.filter((o) => o !== optionValue) : [...prev, optionValue];
3978
+ onFilterChange?.({ options: newOptions });
3979
+ return newOptions;
3980
+ });
3981
+ };
3982
+ const handleServicesChange = (values) => {
3983
+ setSelectedServices(values);
3984
+ onFilterChange?.({ services: values });
3985
+ };
3986
+ const handleRegionsChange = (values) => {
3987
+ setSelectedRegions(values);
3988
+ onFilterChange?.({ regions: values });
3989
+ };
3990
+ const handleExperienceChange = (values) => {
3991
+ setSelectedExperiences(values);
3992
+ onFilterChange?.({ experiences: values });
3993
+ };
3994
+ const handleCategoriesChange = (values) => {
3995
+ setSelectedCategories(values);
3996
+ onFilterChange?.({ categories: values });
3997
+ };
3998
+ const handleMealsChange = (values) => {
3999
+ setSelectedMeals(values);
4000
+ onFilterChange?.({ meals: values });
4001
+ };
4002
+ const handleReviewsChange = (values) => {
4003
+ setSelectedReviews(values);
4004
+ onFilterChange?.({ ratings: values });
4005
+ };
4006
+ const handleTransportChange = (values) => {
4007
+ setSelectedTransport(values);
4008
+ onFilterChange?.({ transport: values });
4009
+ };
4010
+ const handleWellnessChange = (values) => {
4011
+ setSelectedWellness(values);
4012
+ onFilterChange?.({ wellness: values });
4013
+ };
4014
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("aside", { className: `${FilterPanel_default.filterPanel} ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: FilterPanel_default.content, children: [
4015
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4016
+ CollapsibleFilterSection,
4017
+ {
4018
+ title: t("filter.destination", "Destination"),
4019
+ defaultExpanded: true,
4020
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4021
+ RegionsFilter,
4022
+ {
4023
+ regions,
4024
+ selected: selectedRegions,
4025
+ onChange: handleRegionsChange
4026
+ }
4027
+ )
4028
+ }
4029
+ ),
4030
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4031
+ CollapsibleFilterSection,
4032
+ {
4033
+ title: t("filter.experience", "Experience"),
4034
+ defaultExpanded: selectedExperiences.length > 0,
4035
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4036
+ ExperienceFilter,
4037
+ {
4038
+ selected: selectedExperiences,
4039
+ themes,
4040
+ onChange: handleExperienceChange
4041
+ }
4042
+ )
4043
+ }
4044
+ ),
4045
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4046
+ CollapsibleFilterSection,
4047
+ {
4048
+ title: t("filter.price", "Price"),
4049
+ defaultExpanded: true,
4050
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4051
+ PriceRangeFilter,
4052
+ {
4053
+ minPrice,
4054
+ maxPrice,
4055
+ value: { min: priceMin, max: priceMax },
4056
+ onChange: handlePriceChange,
4057
+ onApply: handlePriceApply,
4058
+ histogram: priceHistogram,
4059
+ currency
4060
+ }
4061
+ )
4062
+ }
4063
+ ),
4064
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4065
+ CollapsibleFilterSection,
4066
+ {
4067
+ title: t("filter.discount", "Discount"),
4068
+ defaultExpanded: true,
4069
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: FilterPanel_default.discountList, children: DISCOUNT_OPTIONS.map((option) => {
4070
+ const count = discountCounts[option.value];
4071
+ const isDisabled = count === 0 && !selectedDiscounts.includes(option.value);
4072
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4073
+ FilterCheckboxItem,
4074
+ {
4075
+ id: `discount-${option.value}`,
4076
+ label: option.label,
4077
+ count,
4078
+ checked: selectedDiscounts.includes(option.value),
4079
+ disabled: isDisabled,
4080
+ onChange: () => handleDiscountToggle(option.value)
4081
+ },
4082
+ option.value
4083
+ );
4084
+ }) })
4085
+ }
4086
+ ),
4087
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4088
+ CollapsibleFilterSection,
4089
+ {
4090
+ title: t("filter.options", "Options"),
4091
+ defaultExpanded: selectedOptions.length > 0 || selectedServices.length > 0,
4092
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: FilterPanel_default.discountList, children: [
4093
+ OPTIONS_FILTER.map((option) => {
4094
+ const count = optionsCounts[option.value];
4095
+ const isDisabled = count === 0 && !selectedOptions.includes(option.value);
4096
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4097
+ FilterCheckboxItem,
4098
+ {
4099
+ id: `option-${option.value}`,
4100
+ label: t(option.labelKey, "Instantly bookable"),
4101
+ count,
4102
+ checked: selectedOptions.includes(option.value),
4103
+ disabled: isDisabled,
4104
+ onChange: () => handleOptionToggle(option.value)
4105
+ },
4106
+ option.value
4107
+ );
4108
+ }),
4109
+ filterOptions?.services?.map((option) => {
4110
+ const count = servicesCounts[option.key];
4111
+ const isDisabled = count === 0 && !selectedServices.includes(option.key);
4112
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4113
+ FilterCheckboxItem,
4114
+ {
4115
+ id: `service-${option.key}`,
4116
+ label: option.name,
4117
+ count,
4118
+ checked: selectedServices.includes(option.key),
4119
+ disabled: isDisabled,
4120
+ onChange: () => handleServicesChange(
4121
+ selectedServices.includes(option.key) ? selectedServices.filter((v) => v !== option.key) : [...selectedServices, option.key]
4122
+ )
4123
+ },
4124
+ option.key
4125
+ );
4126
+ })
4127
+ ] })
4128
+ }
4129
+ ),
4130
+ filterOptions?.meals && filterOptions.meals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4131
+ CollapsibleFilterSection,
4132
+ {
4133
+ title: t("filter.meals", "Meals"),
4134
+ defaultExpanded: selectedMeals.length > 0,
4135
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4136
+ MealsFilter,
4137
+ {
4138
+ selected: selectedMeals,
4139
+ counts: mealsCounts,
4140
+ options: filterOptions.meals,
4141
+ onChange: handleMealsChange
4142
+ }
4143
+ )
4144
+ }
4145
+ ),
4146
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4147
+ CollapsibleFilterSection,
4148
+ {
4149
+ title: t("filter.hotel-category", "Hotel category"),
4150
+ defaultExpanded: true,
4151
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4152
+ HotelCategoryFilter,
4153
+ {
4154
+ selected: selectedCategories,
4155
+ counts: categoryCounts,
4156
+ onChange: handleCategoriesChange
4157
+ }
4158
+ )
4159
+ }
4160
+ ),
4161
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4162
+ CollapsibleFilterSection,
4163
+ {
4164
+ title: t("filter.reviews", "Reviews"),
4165
+ defaultExpanded: selectedReviews.length > 0,
4166
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4167
+ ReviewsFilter,
4168
+ {
4169
+ selected: selectedReviews,
4170
+ counts: reviewsCounts,
4171
+ onChange: handleReviewsChange
4172
+ }
4173
+ )
4174
+ }
4175
+ ),
4176
+ filterOptions?.transport && filterOptions.transport.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4177
+ CollapsibleFilterSection,
4178
+ {
4179
+ title: t("filter.mobility", "Mobility"),
4180
+ defaultExpanded: selectedTransport.length > 0,
4181
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4182
+ TransportFilter,
4183
+ {
4184
+ selected: selectedTransport,
4185
+ counts: transportCounts,
4186
+ options: filterOptions.transport,
4187
+ onChange: handleTransportChange
4188
+ }
4189
+ )
4190
+ }
4191
+ ),
4192
+ filterOptions?.wellness && filterOptions.wellness.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4193
+ CollapsibleFilterSection,
4194
+ {
4195
+ title: t("filter.wellness-spa", "Wellness & Spa"),
4196
+ defaultExpanded: selectedWellness.length > 0,
4197
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4198
+ WellnessFilter,
4199
+ {
4200
+ selected: selectedWellness,
4201
+ counts: wellnessCounts,
4202
+ options: filterOptions.wellness,
4203
+ onChange: handleWellnessChange
4204
+ }
4205
+ )
4206
+ }
4207
+ )
4208
+ ] }) });
4209
+ };
4210
+
4211
+ // src/components/Filters/FilterModal.tsx
4212
+ var import_react20 = require("react");
4213
+
4214
+ // src/components/Filters/FilterModal.module.css
4215
+ var FilterModal_default = {};
4216
+
4217
+ // src/components/Filters/FilterModal.tsx
4218
+ var import_jsx_runtime36 = require("react/jsx-runtime");
4219
+ var CloseIcon3 = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M0.275391 1.59961C-0.0917969 1.23242 -0.0917969 0.638672 0.275391 0.275391C0.642578 -0.0878906 1.23633 -0.0917969 1.59961 0.275391L7.49805 6.17383L13.3965 0.275391C13.7637 -0.0917969 14.3574 -0.0917969 14.7207 0.275391C15.084 0.642578 15.0879 1.23633 14.7207 1.59961L8.82226 7.49805L14.7207 13.3965C15.0879 13.7637 15.0879 14.3574 14.7207 14.7207C14.3535 15.084 13.7598 15.0879 13.3965 14.7207L7.49805 8.82226L1.59961 14.7207C1.23242 15.0879 0.638672 15.0879 0.275391 14.7207C-0.0878906 14.3535 -0.0917969 13.7598 0.275391 13.3965L6.17383 7.49805L0.275391 1.59961Z", fill: "#1F2937" }) });
4220
+ var FilterModal = ({
4221
+ isOpen,
4222
+ onClose,
4223
+ resultCount = 0,
4224
+ selectedFilters = [],
4225
+ onRemoveFilter,
4226
+ onClearAllFilters,
4227
+ onFilterChange,
4228
+ selectedDiscounts = [],
4229
+ selectedOptions = [],
4230
+ selectedCategories = [],
4231
+ selectedExperiences = [],
4232
+ selectedRegions = [],
4233
+ selectedMeals = [],
4234
+ selectedWellness = [],
4235
+ selectedServices = [],
4236
+ selectedTransport = [],
4237
+ selectedReviews = [],
4238
+ selectedPriceRange,
4239
+ minPrice = 0,
4240
+ maxPrice = 500,
4241
+ regions = [],
4242
+ ...filterPanelProps
4243
+ }) => {
4244
+ const { t } = useUIContext();
4245
+ const hasSelectedFilters = selectedFilters.length > 0;
4246
+ (0, import_react20.useEffect)(() => {
4247
+ if (isOpen) {
4248
+ document.body.style.overflow = "hidden";
4249
+ return () => {
4250
+ document.body.style.overflow = "";
4251
+ };
4252
+ }
4253
+ }, [isOpen]);
4254
+ if (!isOpen) return null;
4255
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: FilterModal_default.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: FilterModal_default.modal, children: [
4256
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: FilterModal_default.header, children: [
4257
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h2", { className: FilterModal_default.title, children: t("filter.filters", "Filters") }),
4258
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4259
+ Button,
4260
+ {
4261
+ variant: "secondary",
4262
+ size: "small",
4263
+ iconOnly: true,
4264
+ onClick: onClose,
4265
+ "aria-label": t("filter.close", "Close"),
4266
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CloseIcon3, {})
4267
+ }
4268
+ )
4269
+ ] }),
4270
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: FilterModal_default.content, children: [
4271
+ selectedFilters.length > 0 && onRemoveFilter && onClearAllFilters && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: FilterModal_default.selectedFilters, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4272
+ SelectedFiltersRow,
4273
+ {
4274
+ filters: selectedFilters,
4275
+ onRemove: onRemoveFilter,
4276
+ onClearAll: onClearAllFilters
4277
+ }
4278
+ ) }),
4279
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4280
+ FilterPanel,
4281
+ {
4282
+ ...filterPanelProps,
4283
+ onFilterChange,
4284
+ selectedDiscounts,
4285
+ selectedOptions,
4286
+ selectedCategories,
4287
+ selectedExperiences,
4288
+ selectedRegions,
4289
+ selectedMeals,
4290
+ selectedWellness,
4291
+ selectedServices,
4292
+ selectedTransport,
4293
+ selectedReviews,
4294
+ selectedPriceRange,
4295
+ minPrice,
4296
+ maxPrice,
4297
+ regions,
4298
+ className: FilterModal_default.filterPanel
4299
+ }
4300
+ )
4301
+ ] }),
4302
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: FilterModal_default.footer, children: [
4303
+ onClearAllFilters && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4304
+ Button,
4305
+ {
4306
+ variant: "link",
4307
+ className: FilterModal_default.footerLink,
4308
+ onClick: onClearAllFilters,
4309
+ disabled: !hasSelectedFilters,
4310
+ children: t("filter.clear-all", "Clear all")
4311
+ }
4312
+ ),
4313
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4314
+ Button,
4315
+ {
4316
+ variant: "primary",
4317
+ size: "medium",
4318
+ onClick: onClose,
4319
+ children: t("filter.show-results", "Show {count} results").replace("{count}", String(resultCount))
4320
+ }
4321
+ )
4322
+ ] })
4323
+ ] }) });
4324
+ };
4325
+
4326
+ // src/components/icons/HeartIcon.tsx
4327
+ var import_jsx_runtime37 = require("react/jsx-runtime");
4328
+ var HeartIcon3 = ({ filled = false, className = "", size = 24 }) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2979
4329
  "svg",
2980
4330
  {
2981
4331
  width: size,
@@ -2987,14 +4337,14 @@ var HeartIcon3 = ({ filled = false, className = "", size = 24 }) => /* @__PURE__
2987
4337
  strokeWidth: 2,
2988
4338
  strokeLinecap: "round",
2989
4339
  strokeLinejoin: "round",
2990
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })
4340
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })
2991
4341
  }
2992
4342
  );
2993
4343
  HeartIcon3.displayName = "HeartIcon";
2994
4344
 
2995
4345
  // src/components/icons/StarIcon.tsx
2996
- var import_jsx_runtime27 = require("react/jsx-runtime");
2997
- var StarIcon4 = ({ filled = true, className = "", size = 9 }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
4346
+ var import_jsx_runtime38 = require("react/jsx-runtime");
4347
+ var StarIcon4 = ({ filled = true, className = "", size = 9 }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
2998
4348
  "svg",
2999
4349
  {
3000
4350
  xmlns: "http://www.w3.org/2000/svg",
@@ -3004,22 +4354,22 @@ var StarIcon4 = ({ filled = true, className = "", size = 9 }) => /* @__PURE__ */
3004
4354
  fill: "none",
3005
4355
  className,
3006
4356
  children: [
3007
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("g", { clipPath: "url(#clip0_star_icon)", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4357
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("g", { clipPath: "url(#clip0_star_icon)", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3008
4358
  "path",
3009
4359
  {
3010
4360
  d: "M4.80018 0.366577C4.93104 0.366577 5.05173 0.440968 5.11135 0.557659L6.18011 2.66102L8.50521 3.03152C8.63462 3.05194 8.74222 3.14383 8.78294 3.26927C8.82365 3.39472 8.79021 3.53183 8.6986 3.62518L7.03366 5.29533L7.40155 7.6277C7.42191 7.75752 7.3681 7.88879 7.26195 7.9661C7.15581 8.04341 7.01476 8.05508 6.89843 7.99528L4.80018 6.92463L2.70192 7.99528C2.58559 8.05508 2.44454 8.04341 2.33839 7.9661C2.23225 7.88879 2.17844 7.75898 2.1988 7.6277L2.56523 5.29533L0.901751 3.62518C0.808689 3.53183 0.776699 3.39472 0.817413 3.26927C0.858128 3.14383 0.964277 3.05194 1.09515 3.03152L3.42024 2.66102L4.49045 0.557659C4.55007 0.440968 4.67076 0.366577 4.80163 0.366577H4.80018Z",
3011
4361
  fill: filled ? "#1F2937" : "#D1D5DB"
3012
4362
  }
3013
4363
  ) }),
3014
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("clipPath", { id: "clip0_star_icon", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("rect", { width: "8", height: "8", fill: "white", transform: "translate(0.800049 0.199951)" }) }) })
4364
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("clipPath", { id: "clip0_star_icon", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("rect", { width: "8", height: "8", fill: "white", transform: "translate(0.800049 0.199951)" }) }) })
3015
4365
  ]
3016
4366
  }
3017
4367
  );
3018
4368
  StarIcon4.displayName = "StarIcon";
3019
4369
 
3020
4370
  // src/components/icons/ChevronLeftIcon.tsx
3021
- var import_jsx_runtime28 = require("react/jsx-runtime");
3022
- var ChevronLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4371
+ var import_jsx_runtime39 = require("react/jsx-runtime");
4372
+ var ChevronLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3023
4373
  "svg",
3024
4374
  {
3025
4375
  xmlns: "http://www.w3.org/2000/svg",
@@ -3032,14 +4382,14 @@ var ChevronLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, imp
3032
4382
  strokeLinecap: "round",
3033
4383
  strokeLinejoin: "round",
3034
4384
  className,
3035
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("polyline", { points: "15 18 9 12 15 6" })
4385
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("polyline", { points: "15 18 9 12 15 6" })
3036
4386
  }
3037
4387
  );
3038
4388
  ChevronLeftIcon.displayName = "ChevronLeftIcon";
3039
4389
 
3040
4390
  // src/components/icons/ChevronRightIcon.tsx
3041
- var import_jsx_runtime29 = require("react/jsx-runtime");
3042
- var ChevronRightIcon2 = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4391
+ var import_jsx_runtime40 = require("react/jsx-runtime");
4392
+ var ChevronRightIcon2 = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
3043
4393
  "svg",
3044
4394
  {
3045
4395
  xmlns: "http://www.w3.org/2000/svg",
@@ -3052,14 +4402,14 @@ var ChevronRightIcon2 = ({ className = "", size = 20 }) => /* @__PURE__ */ (0, i
3052
4402
  strokeLinecap: "round",
3053
4403
  strokeLinejoin: "round",
3054
4404
  className,
3055
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("polyline", { points: "9 18 15 12 9 6" })
4405
+ children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("polyline", { points: "9 18 15 12 9 6" })
3056
4406
  }
3057
4407
  );
3058
4408
  ChevronRightIcon2.displayName = "ChevronRightIcon";
3059
4409
 
3060
4410
  // src/components/icons/PinIcon.tsx
3061
- var import_jsx_runtime30 = require("react/jsx-runtime");
3062
- var PinIcon2 = ({ className = "", size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
4411
+ var import_jsx_runtime41 = require("react/jsx-runtime");
4412
+ var PinIcon2 = ({ className = "", size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
3063
4413
  "svg",
3064
4414
  {
3065
4415
  xmlns: "http://www.w3.org/2000/svg",
@@ -3069,7 +4419,7 @@ var PinIcon2 = ({ className = "", size = 16 }) => /* @__PURE__ */ (0, import_jsx
3069
4419
  fill: "none",
3070
4420
  className,
3071
4421
  children: [
3072
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
4422
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3073
4423
  "path",
3074
4424
  {
3075
4425
  fillRule: "evenodd",
@@ -3078,7 +4428,7 @@ var PinIcon2 = ({ className = "", size = 16 }) => /* @__PURE__ */ (0, import_jsx
3078
4428
  fill: "currentColor"
3079
4429
  }
3080
4430
  ),
3081
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
4431
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3082
4432
  "path",
3083
4433
  {
3084
4434
  fillRule: "evenodd",
@@ -3127,31 +4477,47 @@ var calculateDiscount = (originalPrice, discountedPrice) => {
3127
4477
  Benefits,
3128
4478
  Block,
3129
4479
  Button,
4480
+ CATEGORY_OPTIONS,
3130
4481
  Card,
3131
4482
  Checkbox,
4483
+ CheckboxFilter,
3132
4484
  ChevronLeftIcon,
3133
4485
  ChevronRightIcon,
3134
4486
  Chip,
4487
+ CollapsibleFilterSection,
3135
4488
  DateSelector,
3136
4489
  Divider,
3137
4490
  Dropdown,
3138
4491
  DualCalendar,
4492
+ ExperienceFilter,
3139
4493
  FAQ,
4494
+ FilterCheckboxItem,
4495
+ FilterModal,
4496
+ FilterPanel,
3140
4497
  GuestContent,
3141
4498
  HeartIcon,
3142
4499
  HotelCard,
3143
4500
  HotelCardContent,
3144
4501
  HotelCardImage,
3145
4502
  HotelCardUIProvider,
4503
+ HotelCategoryFilter,
3146
4504
  Input,
4505
+ MealsFilter,
3147
4506
  Modal,
3148
4507
  Pin,
3149
4508
  PinIcon,
4509
+ PriceRangeFilter,
4510
+ REVIEW_OPTIONS,
3150
4511
  RadioButton,
3151
4512
  Rating,
4513
+ RegionsFilter,
3152
4514
  ReviewCard,
4515
+ ReviewsFilter,
3153
4516
  SectionHeader,
4517
+ SelectedFiltersRow,
3154
4518
  StarIcon,
4519
+ TransportFilter,
4520
+ WellnessFilter,
3155
4521
  WhenContent,
3156
4522
  calculateDiscount,
3157
4523
  formatDate,