kupos-ui-components-lib 10.4.11 → 10.4.13

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.
Files changed (93) hide show
  1. package/dist/assets/images/filter/bus.svg +19 -0
  2. package/dist/assets/images/filter/clock.svg +4 -0
  3. package/dist/assets/images/filter/filter.svg +3 -0
  4. package/dist/assets/images/filter/money.svg +12 -0
  5. package/dist/assets/images/filter/night.svg +5 -0
  6. package/dist/assets/images/filter/rise.svg +20 -0
  7. package/dist/assets/images/filter/search.svg +4 -0
  8. package/dist/assets/images/filter/seat.svg +4 -0
  9. package/dist/assets/images/filter/star.svg +10 -0
  10. package/dist/assets/images/filter/sun.svg +20 -0
  11. package/dist/assets/images/filter/sunset.svg +15 -0
  12. package/dist/assets/images/filter/track.svg +4 -0
  13. package/dist/components/FilterSortBar/FilterChip.d.ts +21 -0
  14. package/dist/components/FilterSortBar/FilterChip.js +42 -0
  15. package/dist/components/FilterSortBar/FilterSortBarMobile.d.ts +10 -0
  16. package/dist/components/FilterSortBar/FilterSortBarMobile.js +121 -0
  17. package/dist/components/FilterSortBar/FiltersMasterSheet.d.ts +16 -0
  18. package/dist/components/FilterSortBar/FiltersMasterSheet.js +111 -0
  19. package/dist/components/FilterSortBar/OptionCheckboxList.d.ts +13 -0
  20. package/dist/components/FilterSortBar/OptionCheckboxList.js +30 -0
  21. package/dist/components/FilterSortBar/PriceRangeSlider.d.ts +12 -0
  22. package/dist/components/FilterSortBar/PriceRangeSlider.js +113 -0
  23. package/dist/components/FilterSortBar/SheetFooter.d.ts +9 -0
  24. package/dist/components/FilterSortBar/SheetFooter.js +36 -0
  25. package/dist/components/FilterSortBar/SingleFilterSheet.d.ts +15 -0
  26. package/dist/components/FilterSortBar/SingleFilterSheet.js +21 -0
  27. package/dist/components/FilterSortBar/defaultIcons.d.ts +2 -0
  28. package/dist/components/FilterSortBar/defaultIcons.js +18 -0
  29. package/dist/components/FilterSortBar/icons.d.ts +50 -0
  30. package/dist/components/FilterSortBar/icons.js +67 -0
  31. package/dist/components/FilterSortBar/index.d.ts +4 -0
  32. package/dist/components/FilterSortBar/index.js +3 -0
  33. package/dist/components/FilterSortBar/types.d.ts +57 -0
  34. package/dist/components/FilterSortBar/types.js +8 -0
  35. package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +15 -8
  36. package/dist/components/PaymentSideBar/types.d.ts +3 -0
  37. package/dist/index.d.ts +4 -1
  38. package/dist/index.js +5 -0
  39. package/dist/styles.css +64 -0
  40. package/dist/ui/BottomSheet/BottomSheet.d.ts +2 -1
  41. package/dist/ui/BottomSheet/BottomSheet.js +2 -1
  42. package/package.json +1 -1
  43. package/patch.py +35 -0
  44. package/src/assets/images/filter/bus.svg +19 -0
  45. package/src/assets/images/filter/clock.svg +4 -0
  46. package/src/assets/images/filter/filter.svg +3 -0
  47. package/src/assets/images/filter/money.svg +12 -0
  48. package/src/assets/images/filter/night.svg +5 -0
  49. package/src/assets/images/filter/rise.svg +20 -0
  50. package/src/assets/images/filter/search.svg +4 -0
  51. package/src/assets/images/filter/seat.svg +4 -0
  52. package/src/assets/images/filter/star.svg +10 -0
  53. package/src/assets/images/filter/sun.svg +20 -0
  54. package/src/assets/images/filter/sunset.svg +15 -0
  55. package/src/assets/images/filter/track.svg +4 -0
  56. package/src/components/FilterSortBar/FilterChip.tsx +113 -0
  57. package/src/components/FilterSortBar/FilterSortBarMobile.tsx +236 -0
  58. package/src/components/FilterSortBar/FiltersMasterSheet.tsx +208 -0
  59. package/src/components/FilterSortBar/OptionCheckboxList.tsx +86 -0
  60. package/src/components/FilterSortBar/PriceRangeSlider.tsx +184 -0
  61. package/src/components/FilterSortBar/SheetFooter.tsx +61 -0
  62. package/src/components/FilterSortBar/SingleFilterSheet.tsx +82 -0
  63. package/src/components/FilterSortBar/defaultIcons.ts +29 -0
  64. package/src/components/FilterSortBar/icons.tsx +237 -0
  65. package/src/components/FilterSortBar/index.ts +15 -0
  66. package/src/components/FilterSortBar/types.ts +79 -0
  67. package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +553 -526
  68. package/src/components/PaymentSideBar/types.ts +3 -0
  69. package/src/index.ts +18 -0
  70. package/src/ui/BottomSheet/BottomSheet.tsx +4 -1
  71. package/src/ui/PaymentCardMobile/PaymentCardMobile.tsx +982 -0
  72. package/src/ui/PaymentCardMobile/index.ts +1 -0
  73. package/src/ui/SlidingModal/SlidingModal.tsx +145 -0
  74. package/src/ui/SlidingModal/index.ts +2 -0
  75. package/dist/assets/images/anims/service_list/60_percent_anim.json +0 -1
  76. package/dist/components/PaymentOptions/PaymentOptionsDesktop.d.ts +0 -4
  77. package/dist/components/PaymentOptions/PaymentOptionsDesktop.js +0 -5
  78. package/dist/components/PaymentOptions/PaymentOptionsMobile.d.ts +0 -4
  79. package/dist/components/PaymentOptions/PaymentOptionsMobile.js +0 -5
  80. package/dist/components/PaymentOptions/ResponsivePaymentOptions.d.ts +0 -3
  81. package/dist/components/PaymentOptions/ResponsivePaymentOptions.js +0 -10
  82. package/dist/components/PaymentOptions/index.d.ts +0 -5
  83. package/dist/components/PaymentOptions/index.js +0 -4
  84. package/dist/components/PaymentOptions/mobileTypes.d.ts +0 -0
  85. package/dist/components/PaymentOptions/mobileTypes.js +0 -0
  86. package/dist/components/PaymentOptions/type.d.ts +0 -4
  87. package/dist/components/PaymentOptions/type.js +0 -1
  88. package/dist/components/ServiceItem/ExpandedDropdown.d.ts +0 -19
  89. package/dist/components/ServiceItem/ExpandedDropdown.js +0 -28
  90. package/dist/components/ServiceItem/ServiceItemDesktopPeru.d.ts +0 -6
  91. package/dist/components/ServiceItem/ServiceItemDesktopPeru.js +0 -612
  92. package/dist/ui/TopAmenities/PromoCountdown.d.ts +0 -18
  93. package/dist/ui/TopAmenities/PromoCountdown.js +0 -55
@@ -0,0 +1,184 @@
1
+ import React, { useRef, useCallback } from "react";
2
+ import { PriceRangeValue } from "./types";
3
+
4
+ interface PriceRangeSliderProps {
5
+ value: PriceRangeValue;
6
+ onChange: (currentMin: number, currentMax: number) => void;
7
+ currencySign: string;
8
+ primaryColor: string;
9
+ minLabel?: string;
10
+ maxLabel?: string;
11
+ }
12
+
13
+ const THUMB_SIZE = 18;
14
+ const THUMB_RADIUS = THUMB_SIZE / 2;
15
+
16
+ const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));
17
+
18
+ const formatCurrency = (amount: number, sign: string) =>
19
+ sign + Math.round(amount).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
20
+
21
+ const PriceRangeSlider = ({
22
+ value,
23
+ onChange,
24
+ currencySign,
25
+ primaryColor,
26
+ minLabel = "Precio mínimo",
27
+ maxLabel = "Precio máximo",
28
+ }: PriceRangeSliderProps) => {
29
+ const { min, max, currentMin, currentMax } = value;
30
+ const trackRef = useRef<HTMLDivElement>(null);
31
+ const draggingRef = useRef<"min" | "max" | null>(null);
32
+
33
+ const range = Math.max(1, max - min);
34
+ const minPct = ((currentMin - min) / range) * 100;
35
+ const maxPct = ((currentMax - min) / range) * 100;
36
+
37
+ const valueFromClientX = useCallback(
38
+ (clientX: number) => {
39
+ const track = trackRef.current;
40
+ if (!track) return min;
41
+ const rect = track.getBoundingClientRect();
42
+ const pct = clamp((clientX - rect.left) / rect.width, 0, 1);
43
+ return Math.round(min + pct * range);
44
+ },
45
+ [min, range],
46
+ );
47
+
48
+ const handlePointerMove = useCallback(
49
+ (e: PointerEvent) => {
50
+ if (!draggingRef.current) return;
51
+ const next = valueFromClientX(e.clientX);
52
+ if (draggingRef.current === "min") {
53
+ onChange(clamp(next, min, currentMax), currentMax);
54
+ } else {
55
+ onChange(currentMin, clamp(next, currentMin, max));
56
+ }
57
+ },
58
+ [valueFromClientX, onChange, min, max, currentMin, currentMax],
59
+ );
60
+
61
+ const stopDragging = useCallback(() => {
62
+ draggingRef.current = null;
63
+ window.removeEventListener("pointermove", handlePointerMove);
64
+ window.removeEventListener("pointerup", stopDragging);
65
+ }, [handlePointerMove]);
66
+
67
+ const startDragging = (thumb: "min" | "max") => (e: React.PointerEvent) => {
68
+ e.preventDefault();
69
+ draggingRef.current = thumb;
70
+ window.addEventListener("pointermove", handlePointerMove);
71
+ window.addEventListener("pointerup", stopDragging);
72
+ };
73
+
74
+ return (
75
+ <div style={{ padding: "8px 4px 4px" }}>
76
+ <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 28 }}>
77
+ <div
78
+ style={{
79
+ flex: 1,
80
+ border: "1px solid #E5E5E5",
81
+ borderRadius: 8,
82
+ padding: "6px 10px 8px",
83
+ }}
84
+ >
85
+ <div style={{ fontSize: 11, color: "#9B9B9B", marginBottom: 2 }}>{minLabel}</div>
86
+ <div style={{ fontSize: 13, fontWeight: 700, color: "#464647" }}>
87
+ {formatCurrency(currentMin, currencySign)}
88
+ </div>
89
+ </div>
90
+ <span style={{ color: "#9B9B9B", fontSize: 13 }}>-</span>
91
+ <div
92
+ style={{
93
+ flex: 1,
94
+ border: "1px solid #E5E5E5",
95
+ borderRadius: 8,
96
+ padding: "6px 10px 8px",
97
+ }}
98
+ >
99
+ <div style={{ fontSize: 11, color: "#9B9B9B", marginBottom: 2 }}>{maxLabel}</div>
100
+ <div style={{ fontSize: 13, fontWeight: 700, color: "#464647" }}>
101
+ {formatCurrency(currentMax, currencySign)}
102
+ </div>
103
+ </div>
104
+ </div>
105
+
106
+ <div style={{ padding: `0 ${THUMB_RADIUS}px`, overflow: "visible" }}>
107
+ <div
108
+ ref={trackRef}
109
+ style={{
110
+ position: "relative",
111
+ height: THUMB_SIZE,
112
+ display: "flex",
113
+ alignItems: "center",
114
+ touchAction: "none",
115
+ overflow: "visible",
116
+ }}
117
+ >
118
+ <div
119
+ style={{
120
+ position: "absolute",
121
+ left: 0,
122
+ right: 0,
123
+ height: 3,
124
+ borderRadius: 2,
125
+ backgroundColor: "#E5E5E5",
126
+ }}
127
+ />
128
+ <div
129
+ style={{
130
+ position: "absolute",
131
+ left: `${minPct}%`,
132
+ right: `${100 - maxPct}%`,
133
+ height: 3,
134
+ borderRadius: 2,
135
+ backgroundColor: primaryColor,
136
+ }}
137
+ />
138
+ {(
139
+ [
140
+ ["min", minPct, currentMin] as const,
141
+ ["max", maxPct, currentMax] as const,
142
+ ]
143
+ ).map(([thumb, pct]) => (
144
+ <div
145
+ key={thumb}
146
+ onPointerDown={startDragging(thumb)}
147
+ role="slider"
148
+ aria-valuemin={min}
149
+ aria-valuemax={max}
150
+ aria-valuenow={thumb === "min" ? currentMin : currentMax}
151
+ style={{
152
+ position: "absolute",
153
+ left: `${pct}%`,
154
+ transform: "translateX(-50%)",
155
+ width: THUMB_SIZE,
156
+ height: THUMB_SIZE,
157
+ borderRadius: "50%",
158
+ backgroundColor: "#fff",
159
+ border: `2px solid ${primaryColor}`,
160
+ boxShadow: "0 1px 4px rgba(0,0,0,0.25)",
161
+ cursor: "grab",
162
+ zIndex: thumb === "min" ? 2 : 3,
163
+ }}
164
+ />
165
+ ))}
166
+ </div>
167
+ </div>
168
+ <div
169
+ style={{
170
+ display: "flex",
171
+ justifyContent: "space-between",
172
+ fontSize: 11,
173
+ color: "#9B9B9B",
174
+ marginTop: 8,
175
+ }}
176
+ >
177
+ <span>{formatCurrency(min, currencySign)}</span>
178
+ <span>{formatCurrency(max, currencySign)}</span>
179
+ </div>
180
+ </div>
181
+ );
182
+ };
183
+
184
+ export default PriceRangeSlider;
@@ -0,0 +1,61 @@
1
+ import React from "react";
2
+ import { FilterSortBarColors } from "./types";
3
+
4
+ interface SheetFooterProps {
5
+ onClear: () => void;
6
+ onApply: () => void;
7
+ colors: Pick<FilterSortBarColors, "primaryColor" | "primaryTextColor" | "buttonColor" | "buttonTextColor">;
8
+ }
9
+
10
+ const SheetFooter = ({ onClear, onApply, colors }: SheetFooterProps) => {
11
+ const buttonColor = colors.buttonColor || colors.primaryColor;
12
+ const buttonTextColor = colors.buttonTextColor || colors.primaryTextColor;
13
+
14
+ return (
15
+ <div
16
+ style={{
17
+ display: "flex",
18
+ gap: 12,
19
+ paddingTop: 16,
20
+ marginBottom: 8,
21
+ }}
22
+ >
23
+ <button
24
+ onClick={onClear}
25
+ style={{
26
+ flex: 1,
27
+ padding: "12px 16px",
28
+ borderRadius: 10,
29
+ border: "1px solid #E5E5E5",
30
+ background: "#fff",
31
+ color: "#464647",
32
+ fontSize: 14,
33
+ fontWeight: 600,
34
+ cursor: "pointer",
35
+ WebkitTapHighlightColor: "transparent",
36
+ }}
37
+ >
38
+ Borrar filtro
39
+ </button>
40
+ <button
41
+ onClick={onApply}
42
+ style={{
43
+ flex: 1,
44
+ padding: "12px 16px",
45
+ borderRadius: 10,
46
+ border: "none",
47
+ background: buttonColor,
48
+ color: buttonTextColor,
49
+ fontSize: 14,
50
+ fontWeight: 600,
51
+ cursor: "pointer",
52
+ WebkitTapHighlightColor: "transparent",
53
+ }}
54
+ >
55
+ Aplicar
56
+ </button>
57
+ </div>
58
+ );
59
+ };
60
+
61
+ export default SheetFooter;
@@ -0,0 +1,82 @@
1
+ import React from "react";
2
+ import { BottomSheet } from "../../ui/BottomSheet";
3
+ import { CloseIcon } from "./icons";
4
+ import OptionCheckboxList from "./OptionCheckboxList";
5
+ import PriceRangeSlider from "./PriceRangeSlider";
6
+ import SheetFooter from "./SheetFooter";
7
+ import { FilterCategory, FilterSortBarColors, FilterSortBarIcons } from "./types";
8
+
9
+ interface SingleFilterSheetProps {
10
+ category: FilterCategory | null;
11
+ onClose: () => void;
12
+ onToggleOption: (optionId: string) => void;
13
+ onPriceRangeChange: (currentMin: number, currentMax: number) => void;
14
+ onClear: () => void;
15
+ onApply: () => void;
16
+ currencySign: string;
17
+ colors: Required<FilterSortBarColors>;
18
+ icons?: FilterSortBarIcons;
19
+ }
20
+
21
+ const SingleFilterSheet = ({
22
+ category,
23
+ onClose,
24
+ onToggleOption,
25
+ onPriceRangeChange,
26
+ onClear,
27
+ onApply,
28
+ currencySign,
29
+ colors,
30
+ icons,
31
+ }: SingleFilterSheetProps) => {
32
+ return (
33
+ <BottomSheet isOpen={!!category} onClose={onClose} showBackdrop maxHeight="75vh">
34
+ {category && (
35
+ <div>
36
+ <div
37
+ style={{
38
+ display: "flex",
39
+ alignItems: "center",
40
+ justifyContent: "space-between",
41
+ marginBottom: 16,
42
+ }}
43
+ >
44
+ <span style={{ fontSize: 16, fontWeight: 700, color: "#464647" }}>
45
+ {category.sheetTitle || category.sectionLabel || category.label}
46
+ </span>
47
+ <div
48
+ onClick={onClose}
49
+ style={{ cursor: "pointer", padding: 4, WebkitTapHighlightColor: "transparent" }}
50
+ >
51
+ <CloseIcon size={14} src={icons?.closeIcon} />
52
+ </div>
53
+ </div>
54
+
55
+ <div style={{ maxHeight: "50vh", overflowY: "auto" }}>
56
+ {category.kind === "price" && category.priceRange ? (
57
+ <PriceRangeSlider
58
+ value={category.priceRange}
59
+ onChange={onPriceRangeChange}
60
+ currencySign={currencySign}
61
+ primaryColor={colors.primaryColor}
62
+ />
63
+ ) : (
64
+ <OptionCheckboxList
65
+ options={category.options || []}
66
+ kind={category.kind}
67
+ onToggle={onToggleOption}
68
+ primaryColor={colors.primaryColor}
69
+ starColor={colors.buttonColor || colors.primaryColor}
70
+ icons={icons}
71
+ />
72
+ )}
73
+ </div>
74
+
75
+ <SheetFooter onClear={onClear} onApply={onApply} colors={colors} />
76
+ </div>
77
+ )}
78
+ </BottomSheet>
79
+ );
80
+ };
81
+
82
+ export default SingleFilterSheet;
@@ -0,0 +1,29 @@
1
+ // Auto-generated default icon set for FilterSortBar, embedded as base64 data URIs
2
+ // so consumers (e.g. kupos-ssr-mweb) do not need to pass icon paths.
3
+ // Category/time-of-day icons come from src/assets/images/filter/*.svg.
4
+ // closeIcon and checkBoxIcon are intentionally NOT defaulted here — the
5
+ // checkbox sprite in particular is the same one the host app already uses
6
+ // for every other checkbox, so it must keep coming from the app's own
7
+ // assets via the `icons` prop rather than being baked into the library.
8
+ // Category icons recolor to white on selection via a CSS filter (see FilterChip),
9
+ // so a single asset per category is enough — no separate active variant needed.
10
+ import { FilterSortBarIcons } from "./types";
11
+
12
+ export const DEFAULT_ICONS: FilterSortBarIcons = {
13
+ filterIcon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjM5NTggNy4wMDAyNkg1LjE4ODcxTTUuMTg4NzEgNy4wMDAyNkM1LjE4ODcxIDYuNjYyOTkgNS4wNTQxNSA2LjMzOTU0IDQuODE1NjYgNi4xMDEwNUM0LjU3NzE4IDUuODYyNTcgNC4yNTM3MyA1LjcyODU5IDMuOTE2NDYgNS43Mjg1OUMzLjU3OTE5IDUuNzI4NTkgMy4yNTU3NCA1Ljg2MjU3IDMuMDE3MjYgNi4xMDEwNUMyLjc3ODc3IDYuMzM5NTQgMi42NDQ3OSA2LjY2Mjk5IDIuNjQ0NzkgNy4wMDAyNk01LjE4ODcxIDcuMDAwMjZDNS4xODg3MSA3LjMzNzUyIDUuMDU0MTUgNy42NjA5OCA0LjgxNTY2IDcuODk5NDZDNC41NzcxOCA4LjEzNzk0IDQuMjUzNzMgOC4yNzE5MiAzLjkxNjQ2IDguMjcxOTJDMy41NzkxOSA4LjI3MTkyIDMuMjU1NzQgOC4xMzc5NCAzLjAxNzI2IDcuODk5NDZDMi43Nzg3NyA3LjY2MDk4IDIuNjQ0NzkgNy4zMzc1MiAyLjY0NDc5IDcuMDAwMjZNMi42NDQ3OSA3LjAwMDI2SDEuNjA0MTNNMTIuMzk1OCAxMC44NTQzSDkuMDQyNzlNOS4wNDI3OSAxMC44NTQzQzkuMDQyNzkgMTEuMTkxNiA4LjkwODQ5IDExLjUxNTUgOC42Njk5NSAxMS43NTRDOC40MzE0MiAxMS45OTI1IDguMTA3ODkgMTIuMTI2NiA3Ljc3MDU0IDEyLjEyNjZDNy40MzMyOCAxMi4xMjY2IDcuMTA5ODIgMTEuOTkyIDYuODcxMzQgMTEuNzUzNUM2LjYzMjg2IDExLjUxNSA2LjQ5ODg4IDExLjE5MTYgNi40OTg4OCAxMC44NTQzTTkuMDQyNzkgMTAuODU0M0M5LjA0Mjc5IDEwLjUxNyA4LjkwODQ5IDEwLjE5MzcgOC42Njk5NSA5Ljk1NTIyQzguNDMxNDIgOS43MTY2OCA4LjEwNzg5IDkuNTgyNjcgNy43NzA1NCA5LjU4MjY3QzcuNDMzMjggOS41ODI2NyA3LjEwOTgyIDkuNzE2NjUgNi44NzEzNCA5Ljk1NTE0QzYuNjMyODYgMTAuMTkzNiA2LjQ5ODg4IDEwLjUxNyA2LjQ5ODg4IDEwLjg1NDNNNi40OTg4OCAxMC44NTQzSDEuNjA0MTNNMTIuMzk1OCAzLjE0NjE3SDEwLjU4NDVNMTAuNTg0NSAzLjE0NjE3QzEwLjU4NDUgMi45NzkxOCAxMC41NTExIDIuODEzODEgMTAuNDg3MiAyLjY1OTUzQzEwLjQyMzMgMi41MDUyNCAxMC4zMjk2IDIuMzY1MDYgMTAuMjExNSAyLjI0Njk3QzEwLjA5MzQgMi4xMjg4OCA5Ljk1MzIyIDIuMDM1MjEgOS43OTg5NCAxLjk3MTMxQzkuNjQ0NjUgMS45MDc0IDkuNDc5MjkgMS44NzQ1MSA5LjMxMjI5IDEuODc0NTFDOC45NzUwMyAxLjg3NDUxIDguNjUxNTcgMi4wMDg0OSA4LjQxMzA5IDIuMjQ2OTdDOC4xNzQ2MSAyLjQ4NTQ1IDguMDQwNjMgMi44MDg5MSA4LjA0MDYzIDMuMTQ2MTdNMTAuNTg0NSAzLjE0NjE3QzEwLjU4NDUgMy4zMTMxNyAxMC41NTExIDMuNDc4NTMgMTAuNDg3MiAzLjYzMjgyQzEwLjQyMzMgMy43ODcxMSAxMC4zMjk2IDMuOTI3MjkgMTAuMjExNSA0LjA0NTM4QzEwLjA5MzQgNC4xNjM0NiA5Ljk1MzIyIDQuMjU3MTMgOS43OTg5NCA0LjMyMTA0QzkuNjQ0NjUgNC4zODQ5NSA5LjQ3OTI5IDQuNDE3ODQgOS4zMTIyOSA0LjQxNzg0QzguOTc1MDMgNC40MTc4NCA4LjY1MTU3IDQuMjgzODYgOC40MTMwOSA0LjA0NTM4QzguMTc0NjEgMy44MDY4OSA4LjA0MDYzIDMuNDgzNDQgOC4wNDA2MyAzLjE0NjE3TTguMDQwNjMgMy4xNDYxN0gxLjYwNDEzIiBzdHJva2U9IiM0NjQ2NDciIHN0cm9rZS13aWR0aD0iMC44NzUiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",
14
+ searchIcon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUuNjg3NSAxMC4wNjI1QzguMTAzNzUgMTAuMDYyNSAxMC4wNjI1IDguMTAzNzUgMTAuMDYyNSA1LjY4NzVDMTAuMDYyNSAzLjI3MTI1IDguMTAzNzUgMS4zMTI1IDUuNjg3NSAxLjMxMjVDMy4yNzEyNSAxLjMxMjUgMS4zMTI1IDMuMjcxMjUgMS4zMTI1IDUuNjg3NUMxLjMxMjUgOC4xMDM3NSAzLjI3MTI1IDEwLjA2MjUgNS42ODc1IDEwLjA2MjVaIiBzdHJva2U9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTguNzUgOC43NUwxMS4zNzUgMTEuMzc1IiBzdHJva2U9IiM0NjQ2NDciIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K",
15
+ categoryIcons: {
16
+ time: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTcgMTIuMjVDOS44OTk1IDEyLjI1IDEyLjI1IDkuODk5NSAxMi4yNSA3QzEyLjI1IDQuMTAwNTEgOS44OTk1IDEuNzUgNyAxLjc1QzQuMTAwNTEgMS43NSAxLjc1IDQuMTAwNTEgMS43NSA3QzEuNzUgOS44OTk1IDQuMTAwNTEgMTIuMjUgNyAxMi4yNVoiIHN0cm9rZT0iIzQ2NDY0NyIgc3Ryb2tlLXdpZHRoPSIwLjk3NSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik03IDQuMDgzNVY3LjAwMDE2TDguNzUgOC43NTAxNiIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjAuOTc1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg==",
17
+ company: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF80MDEpIj4KPHBhdGggZD0iTTExLjgwNjIgMTIuNDI4N0gyLjE1MjA5QzIuMDQzNjIgMTIuNDI4NyAxLjkzOTQ4IDEyLjM3MzEgMS44ODc0MiAxMi4yODU2TDEuMDQ1NjcgMTAuODU3N0MxLjAxOTYzIDEwLjgxOCAxLjAxMDk2IDEwLjc3MDIgMS4wMTA5NiAxMC43MjY1VjAuOTQyNTkzQzEuMDEwOTYgMC40MjE1ODIgMS40NzA4OCAwIDIuMDM5MjggMEgxMS44NjI2QzEyLjQzMSAwIDEyLjg5MSAwLjQyMTU4MiAxMi44OTEgMC45NDI1OTNWMTAuNzI2NUMxMi44OTEgMTAuNzcwMiAxMi44Nzc5IDEwLjgxNCAxMi44NjA1IDEwLjg0OThMMTIuMDc5NSAxMi4yNzc1QzEyLjAyNzUgMTIuMzY5IDExLjkyMzMgMTIuNDI4NyAxMS44MTA1IDEyLjQyODdIMTEuODA2MlpNMi4zMyAxMS44NzU5SDExLjYxOTZMMTIuMjg3OCAxMC42NTg5VjAuOTQyNTkzQzEyLjI4NzggMC43Mjc4MjUgMTIuMDk2OSAwLjU1MjgyOSAxMS44NjI2IDAuNTUyODI5SDIuMDM5MjhDMS44MDQ5OCAwLjU1MjgyOSAxLjYxNDA2IDAuNzI3ODI1IDEuNjE0MDYgMC45NDI1OTNWMTAuNjU0OUwyLjMzNDMyIDExLjg3NTlIMi4zM1oiIGZpbGw9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTEyLjUzNTEgMi44MjgxNkgxLjM2MjM3QzEuMTk3NDkgMi44MjgxNiAxLjA2Mjk5IDIuNzA0ODYgMS4wNjI5OSAyLjU1MzczQzEuMDYyOTkgMi40MDI1OSAxLjE5NzQ5IDIuMjc5MyAxLjM2MjM3IDIuMjc5M0gxMi41MzUxQzEyLjcgMi4yNzkzIDEyLjgzNDQgMi40MDI1OSAxMi44MzQ0IDIuNTUzNzNDMTIuODM0NCAyLjcwNDg2IDEyLjcgMi44MjgxNiAxMi41MzUxIDIuODI4MTZaIiBmaWxsPSIjNDY0NjQ3Ii8+CjxwYXRoIGQ9Ik0xMi41MzQ5IDExLjAyMDVIMS4zNjIyMkMxLjE5NzM0IDExLjAyMDUgMS4wNjI4NCAxMC44OTcyIDEuMDYyODQgMTAuNzQ2MUMxLjA2Mjg0IDEwLjU5NSAxLjE5NzM0IDEwLjQ3MTcgMS4zNjIyMiAxMC40NzE3SDEyLjUzNDlDMTIuNjk5OCAxMC40NzE3IDEyLjgzNDMgMTAuNTk1IDEyLjgzNDMgMTAuNzQ2MUMxMi44MzQzIDEwLjg5NzIgMTIuNjk5OCAxMS4wMjA1IDEyLjUzNDkgMTEuMDIwNVoiIGZpbGw9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTEyLjI3OSA3LjkzMDY5SDEuNTIyODdDMS4zNTc5OSA3LjkzMDY5IDEuMjIzNDggNy44MDc0IDEuMjIzNDggNy42NTYyNkMxLjIyMzQ4IDcuNTA1MTMgMS4zNTc5OSA3LjM4MTg0IDEuNTIyODcgNy4zODE4NEgxMi4yNzlDMTIuNDQzOSA3LjM4MTg0IDEyLjU3ODQgNy41MDUxMyAxMi41Nzg0IDcuNjU2MjZDMTIuNTc4NCA3LjgwNzQgMTIuNDQzOSA3LjkzMDY5IDEyLjI3OSA3LjkzMDY5WiIgZmlsbD0iIzQ2NDY0NyIvPgo8cGF0aCBkPSJNMTIuNTY5OCA5Ljc5OTQ2SDEwLjAyMjhDOS43NDA3NiA5Ljc5OTQ2IDkuNTEwOCA5LjU4ODY4IDkuNTEwOCA5LjMzMDE1QzkuNTEwOCA5LjA3MTYzIDkuNzQwNzYgOC44NjA4NCAxMC4wMjI4IDguODYwODRIMTIuNTY5OCIgZmlsbD0iIzQ2NDY0NyIvPgo8cGF0aCBkPSJNMS4zNTM1MiA5Ljc5OTQ2SDMuOTAwNDZDNC4xODI0OCA5Ljc5OTQ2IDQuNDEyNDQgOS41ODg2OCA0LjQxMjQ0IDkuMzMwMTVDNC40MTI0NCA5LjA3MTYzIDQuMTgyNDggOC44NjA4NCAzLjkwMDQ2IDguODYwODRIMS4zNTM1MiIgZmlsbD0iIzQ2NDY0NyIvPgo8cGF0aCBkPSJNNC43MjkyMiAxMi4yOTc5VjEzLjI5MjJDNC43MjkyMiAxMy42ODIgNC4zODIxIDE0LjAwMDEgMy45NTY4OSAxNC4wMDAxSDMuMjgwMDJDMi44NTQ4IDE0LjAwMDEgMi41MDc2OSAxMy42ODIgMi41MDc2OSAxMy4yOTIyVjEyLjI5NzkiIGZpbGw9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTExLjU1ODggMTIuMjk3OVYxMy4yOTIyQzExLjU1ODggMTMuNjgyIDExLjIxMTcgMTQuMDAwMSAxMC43ODY1IDE0LjAwMDFIMTAuMTA5NkM5LjY4NDM5IDE0LjAwMDEgOS4zMzcyOCAxMy42ODIgOS4zMzcyOCAxMy4yOTIyVjEyLjI5NzkiIGZpbGw9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTEuMDUwMDIgMi45Nzg1MkgwLjIzODY0MUMwLjEwNjg0NCAyLjk3ODUyIDAgMy4wNzY0NiAwIDMuMTk3MjdWNi4wNDQ5NEMwIDYuMTY1NzQgMC4xMDY4NDQgNi4yNjM2NyAwLjIzODY0MSA2LjI2MzY3SDEuMDUwMDJDMS4xODE4MiA2LjI2MzY3IDEuMjg4NjYgNi4xNjU3NCAxLjI4ODY2IDYuMDQ0OTRWMy4xOTcyN0MxLjI4ODY2IDMuMDc2NDYgMS4xODE4MiAyLjk3ODUyIDEuMDUwMDIgMi45Nzg1MloiIGZpbGw9IiM0NjQ2NDciLz4KPHBhdGggZD0iTTEzLjY2MzEgMi45Nzg1MkgxMi44NTE4QzEyLjcxOTkgMi45Nzg1MiAxMi42MTMxIDMuMDc2NDYgMTIuNjEzMSAzLjE5NzI3VjYuMDQ0OTRDMTIuNjEzMSA2LjE2NTc0IDEyLjcxOTkgNi4yNjM2NyAxMi44NTE4IDYuMjYzNjdIMTMuNjYzMUMxMy43OTUgNi4yNjM2NyAxMy45MDE4IDYuMTY1NzQgMTMuOTAxOCA2LjA0NDk0VjMuMTk3MjdDMTMuOTAxOCAzLjA3NjQ2IDEzLjc5NSAyLjk3ODUyIDEzLjY2MzEgMi45Nzg1MloiIGZpbGw9IiM0NjQ2NDciLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yOTBfNDAxIj4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=",
18
+ price: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF80MTYpIj4KPHBhdGggZD0iTTExLjA2NyA3LjExNTIzQzEwLjk2MSA3LjExNTIzIDEwLjg3NTcgNy4yMDEyNyAxMC44NzU3IDcuMzA4MDhDMTAuODc1NyA3LjQ0MTU3IDEwLjc2NjggNy41NTEzNSAxMC42MzQ0IDcuNTUxMzVDMTAuNTAyIDcuNTUxMzUgMTAuMzkzMSA3LjQ0MTU3IDEwLjM5MzEgNy4zMDgwOEMxMC4zOTMxIDcuMjAxMjcgMTAuMzA3NyA3LjExNTIzIDEwLjIwMTggNy4xMTUyM0MxMC4wOTU4IDcuMTE1MjMgMTAuMDEwNSA3LjIwMTI3IDEwLjAxMDUgNy4zMDgwOEMxMC4wMTA1IDcuNjU1MTggMTAuMjkwMSA3LjkzNzAyIDEwLjYzNDQgNy45MzcwMkMxMC45Nzg3IDcuOTM3MDIgMTEuMjU4MyA3LjY1NTE4IDExLjI1ODMgNy4zMDgwOEMxMS4yNTgzIDcuMjAxMjcgMTEuMTcyOSA3LjExNTIzIDExLjA2NyA3LjExNTIzWiIgZmlsbD0iIzQ2NDY0NyIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjAuNTAzMTUzIi8+CjxwYXRoIGQ9Ik0xMi44NTI5IDcuMTQ3ODhMMTIuMzE3MyA2Ljk3NTgxQzEyLjI0OTYgNi45NTUwNCAxMi4xOTM3IDYuODk4NjggMTIuMTczMSA2LjgyNzQ3QzEyLjA2MTMgNi40NjU1MyAxMS44OTA2IDYuMTI0MzYgMTEuNjY2OSA1LjgxNTgyQzExLjU2MzkgNS42NzYzOCAxMS40NTIxIDUuNTM5OTEgMTEuMzI4NSA1LjQxMjM0QzExLjQwOCA1LjA2MjI2IDExLjQ0OTIgNC42Njc2OSAxMS40NDYyIDQuMzIzNTVDMTEuNDM3NCAzLjgzNDA0IDExLjM0MDMgMy41NDYyNyAxMS4xNDkgMy40NDUzOUMxMS4wNDYgMy4zOTIgMTAuNzMxMSAzLjIyNTg2IDkuMDMzMDggNC4wMDkwOEM4Ljk5MTg4IDQuMDI2ODggOC45NTY1NiA0LjA1MDYxIDguOTIxMjUgNC4wNzczMUM4LjgwNjQ4IDQuMDQ3NjQgOC42ODg3NiA0LjAxNzk3IDguNTcxMDUgMy45OTEyOEM4LjU1NjMzIDMuOTg4MzEgOC41NDE2MiAzLjk4NTM0IDguNTI2OSAzLjk4MjM4QzguNjY1MjIgMy42Nzk3NiA4Ljc0NDY4IDMuMzUwNDYgOC43NTkzOSAzLjAwOTI4QzguNzY1MjggMi45MDI0OCA4LjY4Mjg4IDIuODEzNDkgOC41NzY5MyAyLjgwNzU1QzguNDcwOTkgMi44MDE2MiA4LjM4MjcgMi44ODQ2OCA4LjM3NjgyIDIuOTkxNDlDOC4zNTMyOCAzLjU0OTIzIDguMTIwNzkgNC4wNzczMSA3LjcyOTM5IDQuNDcxODhDNy40OTM5NiA0LjcwOTIzIDcuMjIwMjcgNC44ODEzIDYuOTI1OTkgNC45ODgxQzYuNDE2ODcgNC45MTY4OSA1LjkwMTg3IDQuOTE2ODkgNS4zOTI3NiA0Ljk4ODFDNS4wOTg0NyA0Ljg4MTMgNC44MjQ3OSA0LjcwOTIzIDQuNTg5MzYgNC40NzE4OEM0LjE3MTQ3IDQuMDUwNjEgMy45Mzg5OSAzLjQ4NjkzIDMuOTM4OTkgMi44OTA2MkMzLjkzODk5IDIuMjk0MyA0LjE2ODUzIDEuNzMwNjMgNC41ODkzNiAxLjMwOTM1QzUuMDA3MjUgMC44ODgwNzYgNS41NjYzOSAwLjY1MzcwNCA2LjE1NzkgMC42NTM3MDRDNi43NDk0MiAwLjY1MzcwNCA3LjMwODU2IDAuODg1MTA5IDcuNzI2NDUgMS4zMDkzNUM3Ljg5NDE5IDEuNDc4NDYgOC4wMzU0NSAxLjY3NDI2IDguMTQxMzkgMS44ODQ5QzguMTg4NDggMS45Nzk4MyA4LjMwMzI1IDIuMDE4NCA4LjM5NzQyIDEuOTcwOTRDOC40OTE1OSAxLjkyMzQ2IDguNTI5ODUgMS44MDc3NiA4LjQ4Mjc2IDEuNzEyODNDOC4zNTkxNiAxLjQ2MzYyIDguMTk0MzYgMS4yMzgxNSA3Ljk5NzE5IDEuMDM5MzhDNy41MDU3MyAwLjU0MzkzNSA2Ljg1MjQyIDAuMjcwOTk2IDYuMTU3OSAwLjI3MDk5NkM1LjQ2MzM5IDAuMjcwOTk2IDQuODEwMDcgMC41NDM5MzUgNC4zMTg2MiAxLjAzOTM4QzMuODI3MTYgMS41MzQ4MiAzLjU1NjQyIDIuMTkzNDQgMy41NTY0MiAyLjg5MzU5QzMuNTU2NDIgMy41OTM3MyAzLjgyNzE2IDQuMjUyMzQgNC4zMTg2MiA0Ljc0Nzc5QzQuNDU5ODcgNC44OTAxOSA0LjYxMjkgNS4wMTQ3OSA0Ljc3NzcgNS4xMTU2N0M0LjY1OTk5IDUuMTQ1MzQgNC41NDIyNyA1LjE4MDkzIDQuNDI0NTYgNS4yMTk1MUM0LjMyNDUgNS4yNTIxNCA0LjI3MTUzIDUuMzYxOTEgNC4zMDM5IDUuNDYyNzdDNC4zMzYyNyA1LjU2MzY1IDQuNDQ1MTYgNS42MTcwNCA0LjU0NTIyIDUuNTg0NDFDNS41ODQwNSA1LjIzNDM0IDYuNzI4ODIgNS4yMzQzNCA3Ljc2NzY1IDUuNTg0NDFDNy43ODgyNSA1LjU5MDM0IDcuODA4ODUgNS41OTMzMSA3LjgyOTQ1IDUuNTkzMzFDNy45MDg5IDUuNTkzMzEgNy45ODI0OCA1LjU0Mjg3IDguMDA4OTYgNS40NjI3N0M4LjA0MTMzIDUuMzYxOTEgNy45ODgzNiA1LjI1MjE0IDcuODg4MyA1LjIxOTUxQzcuNzczNTMgNS4xODA5MyA3LjY1NTgyIDUuMTQ1MzQgNy41MzUxNiA1LjExNTY3QzcuNjk3MDIgNS4wMTE4MyA3Ljg1Mjk5IDQuODkwMTkgNy45OTQyNSA0Ljc0Nzc5QzguMTIwNzkgNC42MjAyMiA4LjIyOTY4IDQuNDgzNzUgOC4zMjY3OSA0LjMzODM4QzguMzc5NzYgNC4zNDcyOCA4LjQzMjczIDQuMzU5MTUgOC40ODI3NiA0LjM3MTAyQzguNTUwNDUgNC4zODU4NSA4LjYxODEzIDQuNDAwNjkgOC42ODU4MiA0LjQxODQ4QzguNjg1ODIgNC40MjczOSA4LjY4Mjg4IDQuNDM2MjggOC42Nzk5MyA0LjQ0MjIyQzguNTg1NzYgNC44ODcyMyA4LjU5MTY1IDUuMjc4ODMgOC42OTc1OSA1LjYxMTExQzguNzkxNzYgNS45MDc3OSA4Ljk2MjQ1IDYuMTQ4MDkgOS4yMDM3NiA2LjMyNjA5QzkuNDg5MjIgNi41MzY3MyA5LjgzMDU5IDYuNjI1NzMgMTAuMTQyNSA2LjYyNTczQzEwLjM3NSA2LjYyNTczIDEwLjU5MjggNi41NzUzIDEwLjc0ODggNi40ODMzM0MxMC45MjgzIDYuMzgyNDYgMTEuMDc4NCA2LjE2NTg4IDExLjE5NjEgNS44NDI1MkMxMS4yNTIgNS45MDc3OSAxMS4zMDIgNS45NzMwNSAxMS4zNTIgNi4wNDEyOEMxMS41NTIyIDYuMzE3MTkgMTEuNzAyMiA2LjYxOTggMTEuODAyMyA2Ljk0MDJDMTEuODYxMiA3LjEzMDA4IDEyLjAwODMgNy4yNzg0MSAxMi4xOTM3IDcuMzM3NzVMMTIuNzI5MyA3LjUwOTgyQzEyLjg3MDYgNy41NTQzMiAxMi45NjQ3IDcuNjg0ODUgMTIuOTY0NyA3LjgzMzE5VjguNzI5MTRDMTIuOTY0NyA4Ljg3NzQ4IDEyLjg3MDYgOS4wMDgwMSAxMi43MjkzIDkuMDUyNTJMMTEuODY3IDkuMzMxMzlDMTEuNzI4NyA5LjM3NTg5IDExLjYxMSA5LjQ3MDgzIDExLjUzNzQgOS42MDEzN0MxMS4xOTkgMTAuMTkxNyAxMC42NjM0IDEwLjY4MTIgOS45NTEyNSAxMS4wNTVDOS44Njg4NSAxMS4wOTk2IDkuODEyOTMgMTEuMTc2NyA5Ljc5NTI4IDExLjI2NTdMOS41MTg2NSAxMi43NDMxQzkuNTA5ODIgMTIuNzg0NyA5LjQ3NDUgMTIuODE0MyA5LjQzMzMgMTIuODE0M0g4LjUzMjc5QzguNDkxNTkgMTIuODE0MyA4LjQ1NjI4IDEyLjc4NDcgOC40NDc0NSAxMi43NDMxTDguMjk0NDIgMTEuOTI3M0M4LjI2NDk5IDExLjc2NzEgOC4xMTQ5IDExLjY2MDIgNy45NTMwNSAxMS42ODRDNy41NjQ1OSAxMS43NDM0IDcuMTY3MyAxMS43NzMgNi43NjcwOCAxMS43NzNDNi40Njk4NSAxMS43NzMgNi4xNzU1NiAxMS43NTUyIDUuODkzMDUgMTEuNzIyNkM1LjczNzA3IDExLjcwNDcgNS41OTI4NyAxMS44MTE2IDUuNTYzNDUgMTEuOTY1OUw1LjQxOTI1IDEyLjc0MDJDNS40MTA0MiAxMi43ODE2IDUuMzc1MSAxMi44MTE0IDUuMzMzOSAxMi44MTE0SDQuNDMzMzlDNC4zOTIxOSAxMi44MTE0IDQuMzU2ODcgMTIuNzgxNiA0LjM0ODA1IDEyLjc0MDJMNC4wODAyNSAxMS4zNDU4QzQuMDYyNTkgMTEuMjU2OCA0LjAwNjY3IDExLjE3OTYgMy45MjcyMiAxMS4xMzUxQzIuNzExODIgMTAuNDgyNSAyLjA3MDI3IDkuMzg3NzYgMi4wNzAyNyA3Ljk3NTZDMi4wNzAyNyA3LjI2MDYxIDIuMjI2MjQgNi42MzE2NiAyLjUyOTM2IDYuMDk3NjVDMi44MTQ4MiA1LjYwMjIxIDMuMjI5NzYgNS4xOTI4IDMuNzY4MyA0Ljg3ODMzQzMuODU5NTMgNC44MjQ5MyAzLjg5MTkgNC43MDkyMyAzLjgzODkzIDQuNjE3MjZDMy43ODU5NiA0LjUyNTI5IDMuNjcxMTkgNC40OTU2MiAzLjU3OTk2IDQuNTQ2MDVDMi41NDExMyA1LjE1MTI3IDEuOTE0MyA2LjA4ODc2IDEuNzQwNjcgNy4yNzU0NUMxLjcyMzAyIDcuMjc1NDUgMS43MDUzNiA3LjI3MjQ4IDEuNjg0NzYgNy4yNjk1MkMxLjY4NzcgNy4xNDE5NCAxLjY2NDE2IDcuMDExNDEgMS42MTQxMyA2Ljg4NjgxQzEuNTAyMyA2LjYxMDkgMS4yNzU3IDYuNDA5MTYgMS4wMzQzOSA2LjM3NjUzQzAuODQ2MDQ0IDYuMzQ5ODIgMC42NjM1ODcgNi40MzI5IDAuNTM5OTg3IDYuNTk5MDNDMC4zNTc1MyA2Ljg0MjMgMC4zODY5NTggNy4wMzIxNyAwLjQ0NTgxNiA3LjE1MDg1QzAuNTQyOTMgNy4zNDk2MiAwLjc4NzE4NyA3LjQ5MjAyIDEuMTk2MjQgNy41ODEwMkMxLjE4NDQ3IDcuNTk4ODIgMS4xNzI3IDcuNjEzNjYgMS4xNTc5OSA3LjYzMTQ2QzAuOTE2NjczIDcuOTM3MDIgMC42MzEyMTYgOC4wMDUyNiAwLjQ0NTgxNiA4LjAxMTE5QzAuMzM2OTMgOC4wMTQxNiAwLjI1MTU4NyA4LjEwMzE2IDAuMjUxNTg3IDguMjEyOTNIMC4yNjYzMDFDMC4yNjYzMDEgOC4zMjI3IDAuMzUxNjQ0IDguNDA4NzQgMC40NTc1ODcgOC40MTQ2N0MwLjQ3MjMwMSA4LjQxNDY3IDAuNDg3MDE2IDguNDE0NjcgMC41MDE3MyA4LjQxNDY3QzAuNzM3MTU5IDguNDE0NjcgMS4xMTA5IDguMzI4NjQgMS40NzI4NyA3Ljg3MTc2QzEuNTI4NzkgNy44MDA1NiAxLjU3NTg3IDcuNzIzNDMgMS42MTExOSA3LjY0NjI5QzEuNjQ2NSA3LjY0OTI2IDEuNjgxODIgNy42NTUxOCAxLjcxNDE5IDcuNjU4MTZDMS43MDgzIDcuNzYxOTkgMS43MDUzNiA3Ljg2ODc5IDEuNzA1MzYgNy45NzU2QzEuNzA1MzYgOC43NzY2MSAxLjg5MzcgOS40ODg2MiAyLjI2NzQ0IDEwLjA5MzhDMi42MTE3NiAxMC42NTE2IDMuMTAzMjIgMTEuMTExNCAzLjczMDA1IDExLjQ1NTVMMy45ODkwMiAxMi44MTE0QzQuMDMwMjIgMTMuMDMzOSA0LjIyNDQ1IDEzLjE5NDEgNC40NDgxIDEzLjE5NDFINS4zNDg2MkM1LjU3MjI3IDEzLjE5NDEgNS43NjY1IDEzLjAzMzkgNS44MDc3IDEyLjgxMTRMNS45NDAxMyAxMi4xMTEzQzYuMjEzODIgMTIuMTQwOSA2LjQ5NjMzIDEyLjE1NTcgNi43ODE3OSAxMi4xNTU3QzcuMTczMTkgMTIuMTU1NyA3LjU2NzUzIDEyLjEyOSA3Ljk1MDEgMTIuMDcyNkw4LjA4ODQyIDEyLjgxMTRDOC4xMjk2MiAxMy4wMzM5IDguMzIzODUgMTMuMTk0MSA4LjU0NzUgMTMuMTk0MUg5LjQ0ODAyQzkuNjcxNjggMTMuMTk0MSA5Ljg2NTkgMTMuMDMzOSA5LjkwNzEgMTIuODExNEwxMC4xNzc4IDExLjM3MjVDMTAuOTQgMTAuOTY2MSAxMS41MTEgMTAuNDM1IDExLjg4MTggOS43ODgyN0MxMS45MDgyIDkuNzQwOCAxMS45NDk0IDkuNzA4MTYgMTEuOTk2NSA5LjY5MzM0TDEyLjg1ODggOS40MTQ0NkMxMy4xNTkgOS4zMTY1NSAxMy4zNTkxIDkuMDQwNjUgMTMuMzU5MSA4LjcyMzIxVjcuODI3MjVDMTMuMzU5MSA3LjUwOTgyIDEzLjE1OSA3LjIzMzkxIDEyLjg1ODggNy4xMzYwMUwxMi44NTI5IDcuMTQ3ODhaTTExLjAzNDIgNC44NjY0NkMxMC45NjA2IDUuNDk4MzggMTAuNzYzNSA2LjAzODMyIDEwLjU2NjMgNi4xNTEwNkMxMC4zNDI2IDYuMjc4NjMgOS44MjE3NiA2LjMwNTMyIDkuNDMzMyA2LjAxNzU1QzkuMDQ0ODUgNS43Mjk3OCA4LjkxMjQyIDUuMjEzNTcgOS4wNTk1NiA0LjUyMjMyQzkuMDc0MjggNC40NTQwOCA5LjEyNDMgNC4zOTE3OCA5LjE4OTA1IDQuMzYyMTFDMTAuMTQyNSAzLjkyMzA0IDEwLjY5MjggMy43Nzc2NyAxMC44OTU5IDMuNzc3NjdDMTAuOTI1MyAzLjc3NzY3IDEwLjk0ODkgMy43ODA2NCAxMC45NjM2IDMuNzg2NTdDMTEuMDI1NCAzLjg1MTgzIDExLjEwNDggNC4yMjg2MiAxMS4wMzEzIDQuODY2NDZIMTEuMDM0MlpNMC44MDE5MDEgNi45OTY1N0MwLjc4MTMwMSA2Ljk1NTA0IDAuODI4Mzg3IDYuODgzODQgMC44NTc4MTYgNi44NDUyN0MwLjkwNDkwMSA2Ljc4Mjk3IDAuOTQ5MDQ0IDYuNzcxMSAwLjk4MTQxNiA2Ljc3MTFDMC45ODczMDIgNi43NzExIDAuOTk2MTMgNi43NzExIDEuMDAyMDIgNi43NzExQzEuMDkwMyA2Ljc4Mjk3IDEuMjEwOTYgNi44ODA4OCAxLjI3ODY0IDcuMDQ0MDRDMS4yOTMzNiA3LjA4MjYgMS4zMTM5NiA3LjE0NDkxIDEuMzE5ODQgNy4yMjUwMkMxLjA1NDk5IDcuMTY4NjQgMC44NTE5MyA3LjA5MTUxIDAuODA3Nzg3IDYuOTk5NTRMMC44MDE5MDEgNi45OTY1N1oiIGZpbGw9IiM0NjQ2NDciIHN0cm9rZT0iIzQ2NDY0NyIgc3Ryb2tlLXdpZHRoPSIwLjUwMzE1MyIvPgo8cGF0aCBkPSJNNi4zNDkyMiAyLjY3Mzc4VjEuOTg1NDlDNi41ODQ2NSAyLjAwMzI5IDYuNjcyOTMgMi4xMTAwOSA2Ljc1MjM5IDIuMTEwMDlDNi44NTI0NSAyLjExMDA5IDYuODk5NTMgMS45ODI1MiA2Ljg5OTUzIDEuOTE3MjZDNi44OTk1MyAxLjc1MTEyIDYuNTc1ODIgMS42Nzk5MiA2LjM0OTIyIDEuNjczOThWMS41ODIwMUM2LjM0OTIyIDEuNTQwNDggNi4yOTkxOSAxLjUwNDg4IDYuMjQ5MTYgMS41MDQ4OEM2LjE5MzI1IDEuNTA0ODggNi4xNTIwNSAxLjU0MzQ1IDYuMTUyMDUgMS41ODIwMVYxLjY3OTkyQzUuODM0MjIgMS43MTI1NSA1LjUxMzQ1IDEuODgxNjYgNS41MTM0NSAyLjMwODg2QzUuNTEzNDUgMi43MzYwOCA1Ljg0ODkzIDIuODYzNjQgNi4xNTIwNSAyLjk3MzQxVjMuNzY4NUM1LjgxMDY4IDMuNzQxNzkgNS43MTk0NSAzLjUwNDQ2IDUuNjA3NjIgMy41MDQ0NkM1LjUyMjI4IDMuNTA0NDYgNS40NTQ1OSAzLjYxNzE5IDUuNDU0NTkgMy42OTcyOUM1LjQ1NDU5IDMuODYzNDMgNS43MzcxIDQuMDg4OTEgNi4xNTIwNSA0LjA5NzhWNC4yMDE2NEM2LjE1MjA1IDQuMjQzMTggNi4xOTMyNSA0LjI3ODc3IDYuMjQ5MTYgNC4yNzg3N0M2LjI5OTE5IDQuMjc4NzcgNi4zNDkyMiA0LjI0MDIgNi4zNDkyMiA0LjIwMTY0VjQuMDg1OTNDNi43MTExOSA0LjAzNTUgNi45NjEzMyAzLjgwNDA5IDYuOTYxMzMgMy4zODg3NkM2Ljk2MTMzIDIuOTI4OTEgNi42NDM1IDIuNzgwNTcgNi4zNDkyMiAyLjY3MDhWMi42NzM3OFpNNi4xNzI2NSAyLjYwODVDNS45OTYwOCAyLjU0MDI3IDUuODQ4OTMgMi40NjkwNiA1Ljg0ODkzIDIuMjc2MjNDNS44NDg5MyAyLjEwMTIgNS45ODQzIDIuMDE1MTYgNi4xNzI2NSAxLjk5MTQzVjIuNjA4NVpNNi4zMzE1NiAzLjc2MjU3VjMuMDQ3NThDNi40OTYzNiAzLjExODc4IDYuNjI1ODUgMy4yMTM3MSA2LjYyNTg1IDMuNDI3MzJDNi42MjU4NSAzLjYyMDE1IDYuNTExMDggMy43Mjk5MiA2LjMzMTU2IDMuNzYyNTdaIiBmaWxsPSIjNDY0NjQ3IiBzdHJva2U9IiM0NjQ2NDciIHN0cm9rZS13aWR0aD0iMC41MDMxNTMiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yOTBfNDE2Ij4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=",
19
+ rating: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF8zNzcpIj4KPHBhdGggZD0iTTcuMDA0NTcgMC41NzI3NTRDNy4wMzcwMyAwLjU3Mjc1NCA3LjA1NzExIDAuNTgxMjI5IDcuMDY3MjMgMC41ODc2NjlDNy4wNzY0MSAwLjU5MzYwNSA3LjA4NTQ2IDAuNjAyMjc3IDcuMDkzNDMgMC42MTg3NDFMOC45MTk3NyA0LjQ5NTM0TDkuMDQ1MDkgNC43NjAwN0w5LjMxMzk3IDQuODAxMDlMMTMuNDA4NyA1LjQyMzc5QzEzLjQzMTUgNS40MjcxOCAxMy40NDkzIDUuNDM2MTQgMTMuNDYgNS40NDQ5MUwxMy40NzM2IDUuNDg1OTNDMTMuNDc1MSA1LjQ5MDU1IDEzLjQ3NTQgNS40OTUxMiAxMy40NzM2IDUuNTAyMDhDMTMuNDcxNSA1LjUxMDQyIDEzLjQ2NTEgNS41MjU4MyAxMy40NDg1IDUuNTQzMUwxMC40OTIgOC41NTk2MkwxMC4yODM1IDguNzcyMTVMMTAuMzM0OCA5LjA3OTE1TDExLjAzNDMgMTMuMzMxMUMxMS4wMzY2IDEzLjM0ODEgMTEuMDM1NCAxMy4zNjI4IDExLjAzMDkgMTMuMzc0NkMxMS4wMjY5IDEzLjM4NDkgMTEuMDE4MiAxMy4zOTQ5IDExLjAwNTkgMTMuNDA1N0MxMC45ODQ1IDEzLjQxODQgMTAuOTU5IDEzLjQyNjggMTAuOTQyMSAxMy40MjY4TDEwLjg5NjUgMTMuNDE0M0wxMC44ODk2IDEzLjQxMDZMNy4yMzM1NyAxMS4zOTM0TDYuOTk2NTkgMTEuMjYyOUw2Ljc1OTYxIDExLjM5MzRMMy4xMDU4IDEzLjQwOTRDMy4wNjc5MSAxMy40Mjk5IDMuMDI2OSAxMy40MjUgMi45OTg3IDEzLjQwMzFMMi45OTA3MyAxMy4zOTU3TDIuOTY0NTMgMTMuMzY2QzIuOTYyNjggMTMuMzYxIDIuOTYxNDYgMTMuMzUzNiAyLjk2MzM4IDEzLjM0MjNWMTMuMzM4NkwzLjY2NzQ4IDkuMDcwNDRMMy43MTc2MSA4Ljc2MzQ1TDMuNTA5MTIgOC41NTA5MUwwLjU0ODAxOSA1LjUyOTQzTDAuNTQzNDYxIDUuNTI0NDZMMC41MjUyMzIgNS40OTgzNUMwLjUyNDU2OCA1LjQ5NTQ3IDAuNTIzODM1IDUuNDg4NzcgMC41Mjc1MSA1LjQ3NzIzQzAuNTMxMzM3IDUuNDY1NDQgMC41Mzc4ODQgNS40NTQ5OSAwLjU0ODAxOSA1LjQ0NjE2QzAuNTU4NTg5IDUuNDM2OTYgMC41NzU0OSA1LjQyNzM1IDAuNTk5Mjg4IDUuNDIzNzlMNC42OTUxNSA0LjgwMTA5TDQuOTY1MTcgNC43NjAwN0w1LjA4OTM1IDQuNDk1MzRMNi45MTIyNyAwLjYyNzQ0MkM2LjkyNTk2IDAuNjAwMTA3IDYuOTYxMzQgMC41NzI4NjYgNy4wMDQ1NyAwLjU3Mjc1NFoiIHN0cm9rZT0iIzQ2NDY0NyIgc3Ryb2tlLXdpZHRoPSIwLjkiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yOTBfMzc3Ij4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=",
20
+ terminal: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTcuMzUxOTkgNy4yMzA5NkM4LjQ1NjU1IDcuMjMwOTYgOS4zNTE5OCA2LjMzNTUyIDkuMzUxOTggNS4yMzA5NUM5LjM1MTk4IDQuMTI2MzkgOC40NTY1NSAzLjIzMDk2IDcuMzUxOTkgMy4yMzA5NkM2LjI0NzQyIDMuMjMwOTYgNS4zNTE5OSA0LjEyNjM5IDUuMzUxOTkgNS4yMzA5NUM1LjM1MTk5IDYuMzM1NTIgNi4yNDc0MiA3LjIzMDk2IDcuMzUxOTkgNy4yMzA5NloiIHN0cm9rZT0iIzQ2NDY0NyIgc3Ryb2tlLXdpZHRoPSIxLjAyMTQzIi8+CjxwYXRoIGQ9Ik03LjUwNTg3IDEuMDc3MTVDNS4xMjU4NyAxLjA3NzE1IDMuMTk4MTggMi45MjEwMiAzLjE5ODE4IDUuMTk3NTVDMy4xOTgxOCA4LjgwMjkgNy41MDU4NyAxMi45MjMzIDcuNTA1ODcgMTIuOTIzM0M3LjUwNTg3IDEyLjkyMzMgMTEuODEzNSA4LjgwMjkgMTEuODEzNSA1LjE5NzU1QzExLjgxMzUgMi45MjEwMiA5Ljg4NTg3IDEuMDc3MTUgNy41MDU4NyAxLjA3NzE1WiIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjEuMDIxNDMiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg==",
21
+ seatType: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkuNTAwMDYgMS41SDQuNTAwMDVDMy42NzE2MyAxLjUgMy4wMDAwNiAyLjE3MTU4IDMuMDAwMDYgM1Y2QzMuMDAwMDYgNi44Mjg0MyAzLjY3MTYzIDcuNSA0LjUwMDA1IDcuNUg5LjUwMDA2QzEwLjMyODUgNy41IDExIDYuODI4NDMgMTEgNlYzQzExIDIuMTcxNTggMTAuMzI4NSAxLjUgOS41MDAwNiAxLjVaIiBzdHJva2U9IiM0NjQ2NDciIHN0cm9rZS13aWR0aD0iMS4wMjE0MyIvPgo8cGF0aCBkPSJNMi4wMDAwNiA3LjVIMTIuMDAwMVY5LjVDMTIuMDAwMSAxMC4wMzA0IDExLjc4OTMgMTAuNTM5MSAxMS40MTQyIDEwLjkxNDJDMTEuMDM5MiAxMS4yODkzIDEwLjUzMDUgMTEuNSAxMC4wMDAxIDExLjVINC4wMDAwNkMzLjQ2OTYzIDExLjUgMi45NjA5MSAxMS4yODkzIDIuNTg1ODQgMTAuOTE0MkMyLjIxMDc3IDEwLjUzOTEgMi4wMDAwNiAxMC4wMzA0IDIuMDAwMDYgOS41VjcuNVoiIHN0cm9rZT0iIzQ2NDY0NyIgc3Ryb2tlLXdpZHRoPSIxLjAyMTQzIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo=",
22
+ },
23
+ timeOfDayIcons: {
24
+ sunrise: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF80MjApIj4KPG1hc2sgaWQ9Im1hc2swXzI5MF80MjAiIHN0eWxlPSJtYXNrLXR5cGU6bHVtaW5hbmNlIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTQiIGhlaWdodD0iMTQiPgo8cGF0aCBkPSJNMTQgMEgwVjE0SDE0VjBaIiBmaWxsPSJ3aGl0ZSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazBfMjkwXzQyMCkiPgo8bWFzayBpZD0ibWFzazFfMjkwXzQyMCIgc3R5bGU9Im1hc2stdHlwZTpsdW1pbmFuY2UiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCI+CjxwYXRoIGQ9Ik0xNCAwSDBWMTRIMTRWMFoiIGZpbGw9IndoaXRlIi8+CjwvbWFzaz4KPGcgbWFzaz0idXJsKCNtYXNrMV8yOTBfNDIwKSI+CjxwYXRoIGQ9Ik0yLjMzMzU4IDEwLjQ5OThIMS4xNjY5TTMuNjgzNDggNy4xODMwNEwyLjg1ODUyIDYuMzU4MTFNMTAuMzE3IDcuMTgzMDRMMTEuMTQyIDYuMzU4MTFNMTIuODMzNiAxMC40OTk4SDExLjY2N000LjA4MzU4IDEwLjQ5OThDNC4wODM1OCA4Ljg4OTAxIDUuMzg5NDEgNy41ODMxNiA3LjAwMDIyIDcuNTgzMTZDOC42MTEwNiA3LjU4MzE2IDkuOTE2OTYgOC44ODkwMSA5LjkxNjk2IDEwLjQ5OThNMTIuODMzNiAxMi44MzMySDEuMTY2OU05LjMzMzYyIDMuNDk5ODRMNy4wMDAyMiAxLjE2NjVMNC42NjY5IDMuNDk5ODRNNy4wMDAyMiAxLjE2NjVWNS4yNDk4NCIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjEuMDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L2c+CjwvZz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yOTBfNDIwIj4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=",
25
+ morning: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF8zNzkpIj4KPG1hc2sgaWQ9Im1hc2swXzI5MF8zNzkiIHN0eWxlPSJtYXNrLXR5cGU6bHVtaW5hbmNlIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTQiIGhlaWdodD0iMTQiPgo8cGF0aCBkPSJNMTQgMEgwVjE0SDE0VjBaIiBmaWxsPSJ3aGl0ZSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazBfMjkwXzM3OSkiPgo8bWFzayBpZD0ibWFzazFfMjkwXzM3OSIgc3R5bGU9Im1hc2stdHlwZTpsdW1pbmFuY2UiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCI+CjxwYXRoIGQ9Ik0xNCAwSDBWMTRIMTRWMFoiIGZpbGw9IndoaXRlIi8+CjwvbWFzaz4KPGcgbWFzaz0idXJsKCNtYXNrMV8yOTBfMzc5KSI+CjxwYXRoIGQ9Ik03LjAwMDIyIDEuMTY2NVYyLjMzMzE3TTcuMDAwMjIgMTEuNjY2NVYxMi44MzMyTTIuMzMzNTggNi45OTk4NUgxLjE2NjlNMy42ODM0OCAzLjY4MzA3TDIuODU4NTIgMi44NTgxMU0xMC4zMTcxIDMuNjgzMDdMMTEuMTQyIDIuODU4MTFNMy42ODM0OCAxMC4zMTlMMi44NTg1MiAxMS4xNDM5TTEwLjMxNzEgMTAuMzE5TDExLjE0MiAxMS4xNDM5TTEyLjgzMzYgNi45OTk4NUgxMS42NjdNOS45MTY5NiA2Ljk5OTg1QzkuOTE2OTYgOC42MTA2MiA4LjYxMTA2IDkuOTE2NSA3LjAwMDIyIDkuOTE2NUM1LjM4OTQxIDkuOTE2NSA0LjA4MzU4IDguNjEwNjIgNC4wODM1OCA2Ljk5OTg1QzQuMDgzNTggNS4zODkwMSA1LjM4OTQxIDQuMDgzMTYgNy4wMDAyMiA0LjA4MzE2QzguNjExMDYgNC4wODMxNiA5LjkxNjk2IDUuMzg5MDEgOS45MTY5NiA2Ljk5OTg1WiIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjEuMDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L2c+CjwvZz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yOTBfMzc5Ij4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=",
26
+ sunset: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzI5MF8zOTIpIj4KPG1hc2sgaWQ9Im1hc2swXzI5MF8zOTIiIHN0eWxlPSJtYXNrLXR5cGU6bHVtaW5hbmNlIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iMTQiIGhlaWdodD0iMTQiPgo8cGF0aCBkPSJNMTQgMEgwVjE0SDE0VjBaIiBmaWxsPSJ3aGl0ZSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazBfMjkwXzM5MikiPgo8cGF0aCBkPSJNMy41MzUyOCAxMi4xOTg5QzQuMjQxMSAxMi41MTk3IDUuMTM5NDQgMTIuNTE5NyA1Ljg0NTMgMTIuMTk4OUM2LjU1MTEzIDExLjg3ODEgNy40NDk0OCAxMS44NzgxIDguMTU1MjkgMTIuMTk4OUM4Ljg2MTEgMTIuNTE5NyA5Ljc1OTUgMTIuNTE5NyAxMC40NjUzIDEyLjE5ODlNNy4wMDAyMiAxLjc1VjIuOTE2NjdNMi4zMzM1OCA3LjU4MzMxSDEuMTY2OU0zLjY4MzQ4IDQuMjY2NTdMMi44NTg1MiAzLjQ0MTYxTTEwLjMxNjggNC4yNjY1N0wxMS4xNDE4IDMuNDQxNjFNMTIuODMzNiA3LjU4MzMxSDExLjY2N000LjA4MzU4IDcuNTgzMzFDNC4wODM1OCA1Ljk3MjUyIDUuMzg5NDEgNC42NjY2NyA3LjAwMDIyIDQuNjY2NjdDOC42MTEwNiA0LjY2NjY3IDkuOTE2OTYgNS45NzI1MiA5LjkxNjk2IDcuNTgzMzFNMS4yMjUzIDEwLjE1NzNDMS45MzExMyA5LjgzNjQ5IDIuODI5NDcgOS44MzY0OSAzLjUzNTMgMTAuMTU3M0M0LjI0MTEzIDEwLjQ3ODIgNS4xMzk0NyAxMC40NzgyIDUuODQ1MyAxMC4xNTczQzYuNTUxMTMgOS44MzY0OSA3LjQ0OTQ4IDkuODM2NDkgOC4xNTUyOSAxMC4xNTczQzguODYxMSAxMC40NzgyIDkuNzU5NSAxMC40NzgyIDEwLjQ2NTMgMTAuMTU3M0MxMS4xNzExIDkuODM2NDkgMTIuMDY5NSA5LjgzNjQ5IDEyLjc3NTMgMTAuMTU3MyIgc3Ryb2tlPSIjNDY0NjQ3IiBzdHJva2Utd2lkdGg9IjEuMDUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L2c+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMjkwXzM5MiI+CjxyZWN0IHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K",
27
+ night: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyLjI1IDcuNDYwODFDMTIuMTU4MyA4LjQ1Mzc2IDExLjc4NTYgOS40MDAwNyAxMS4xNzU2IDEwLjE4OUMxMC41NjU3IDEwLjk3NzkgOS43NDM3MiAxMS41NzY4IDguODA1ODYgMTEuOTE1NUM3Ljg2NzkzIDEyLjI1NDMgNi44NTI5OSAxMi4zMTg5IDUuODc5NzEgMTIuMTAxOUM0LjkwNjQ0IDExLjg4NDkgNC4wMTUwOCAxMS4zOTUyIDMuMzA5OTcgMTAuNjlDMi42MDQ4NSA5Ljk4NDg5IDIuMTE1MTQgOS4wOTM1NiAxLjg5ODEyIDguMTIwMjhDMS42ODExIDcuMTQ3IDEuNzQ1NzYgNi4xMzIwNSAyLjA4NDUyIDUuMTk0MThDMi40MjMyOSA0LjI1NjI5IDMuMDIyMTYgMy40MzQzIDMuODExMDUgMi44MjQzNUM0LjU5OTk0IDIuMjE0NDIgNS41NDYyMiAxLjg0MTc3IDYuNTM5MTcgMS43NUM1Ljk1Nzg0IDIuNTM2NDkgNS42NzgwOSAzLjUwNTUxIDUuNzUwODEgNC40ODA4MkM1LjgyMzU1IDUuNDU2MTQgNi4yNDM5MiA2LjM3Mjk2IDYuOTM1NDggNy4wNjQ1NEM3LjYyNzA2IDcuNzU2MDcgOC41NDM4NSA4LjE3NjQ5IDkuNTE5MTYgOC4yNDkyMkMxMC40OTQ1IDguMzIxOTUgMTEuNDYzNSA4LjA0MjE2IDEyLjI1IDcuNDYwODFaIiBzdHJva2U9IiM0NjQ2NDciIHN0cm9rZS13aWR0aD0iMC45OTc1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTExLjM3NSAyLjUwODUzQzExLjYzMjcgMi41MDg1MyAxMS44NDE3IDIuMjk5NiAxMS44NDE3IDIuMDQxODZDMTEuODQxNyAxLjc4NDEzIDExLjYzMjcgMS41NzUyIDExLjM3NSAxLjU3NTJDMTEuMTE3MiAxLjU3NTIgMTAuOTA4MyAxLjc4NDEzIDEwLjkwODMgMi4wNDE4NkMxMC45MDgzIDIuMjk5NiAxMS4xMTcyIDIuNTA4NTMgMTEuMzc1IDIuNTA4NTNaIiBmaWxsPSIjNDY0NjQ3Ii8+CjxwYXRoIGQ9Ik0xMi41NDE3IDQuMTQxODlDMTIuNzM1IDQuMTQxODkgMTIuODkxNyAzLjk4NTIgMTIuODkxNyAzLjc5MTg5QzEyLjg5MTcgMy41OTg1OSAxMi43MzUgMy40NDE4OSAxMi41NDE3IDMuNDQxODlDMTIuMzQ4NCAzLjQ0MTg5IDEyLjE5MTcgMy41OTg1OSAxMi4xOTE3IDMuNzkxODlDMTIuMTkxNyAzLjk4NTIgMTIuMzQ4NCA0LjE0MTg5IDEyLjU0MTcgNC4xNDE4OVoiIGZpbGw9IiM0NjQ2NDciLz4KPC9zdmc+Cg==",
28
+ },
29
+ };
@@ -0,0 +1,237 @@
1
+ import React from "react";
2
+
3
+ /**
4
+ * Every icon here renders an <img> when a `src` (asset path from the consuming
5
+ * app, e.g. kupos-ssr-mweb's /public/assets) is supplied, and falls back to an
6
+ * inline SVG otherwise so the component still works with zero configuration.
7
+ */
8
+
9
+ export const CloseIcon = ({
10
+ size = 14,
11
+ color = "#464647",
12
+ src,
13
+ }: {
14
+ size?: number;
15
+ color?: string;
16
+ src?: string;
17
+ }) =>
18
+ src ? (
19
+ <img src={src} width={size} height={size} alt="" />
20
+ ) : (
21
+ <svg width={size} height={size} viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
22
+ <path d="M1 1L13 13M13 1L1 13" stroke={color} strokeWidth="1.6" strokeLinecap="round" />
23
+ </svg>
24
+ );
25
+
26
+ export const ChevronDownIcon = ({
27
+ size = 8,
28
+ color = "#464647",
29
+ open = false,
30
+ src,
31
+ }: {
32
+ size?: number;
33
+ color?: string;
34
+ open?: boolean;
35
+ src?: string;
36
+ }) =>
37
+ src ? (
38
+ <img
39
+ src={src}
40
+ width={size}
41
+ height={size * 0.6}
42
+ alt=""
43
+ style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform 0.2s ease", flexShrink: 0 }}
44
+ />
45
+ ) : (
46
+ <svg
47
+ width={size}
48
+ height={size * 0.6}
49
+ viewBox="0 0 10 6"
50
+ fill="none"
51
+ xmlns="http://www.w3.org/2000/svg"
52
+ style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform 0.2s ease", flexShrink: 0 }}
53
+ >
54
+ <path d="M1 1L5 5L9 1" stroke={color} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
55
+ </svg>
56
+ );
57
+
58
+ export const SearchIcon = ({
59
+ size = 16,
60
+ color = "#9B9B9B",
61
+ src,
62
+ }: {
63
+ size?: number;
64
+ color?: string;
65
+ src?: string;
66
+ }) =>
67
+ src ? (
68
+ <img src={src} width={size} height={size} alt="" />
69
+ ) : (
70
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
71
+ <circle cx="7" cy="7" r="5.5" stroke={color} strokeWidth="1.4" />
72
+ <path d="M11.5 11.5L15 15" stroke={color} strokeWidth="1.4" strokeLinecap="round" />
73
+ </svg>
74
+ );
75
+
76
+ export const FilterIcon = ({
77
+ size = 16,
78
+ color = "#464647",
79
+ src,
80
+ active,
81
+ }: {
82
+ size?: number;
83
+ color?: string;
84
+ src?: string;
85
+ /** When true and src is a raster icon, force it to pure white via CSS filter (no separate white asset needed). */
86
+ active?: boolean;
87
+ }) =>
88
+ src ? (
89
+ <img
90
+ src={src}
91
+ width={size}
92
+ height={size}
93
+ alt=""
94
+ style={active ? { filter: "brightness(0) invert(1)" } : undefined}
95
+ />
96
+ ) : (
97
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
98
+ <path d="M1.5 3H14.5M3.5 8H12.5M6 13H10" stroke={color} strokeWidth="1.4" strokeLinecap="round" />
99
+ </svg>
100
+ );
101
+
102
+ export const StarIcon = ({
103
+ size = 14,
104
+ filled = true,
105
+ color = "#FFB800",
106
+ filledSrc,
107
+ emptySrc,
108
+ }: {
109
+ size?: number;
110
+ filled?: boolean;
111
+ color?: string;
112
+ filledSrc?: string;
113
+ emptySrc?: string;
114
+ }) => {
115
+ const src = filled ? filledSrc : emptySrc;
116
+ if (src) return <img src={src} width={size} height={size} alt="" />;
117
+ return (
118
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
119
+ <path
120
+ d="M8 1.5L9.85 5.75L14.5 6.26L11 9.36L11.98 14L8 11.65L4.02 14L5 9.36L1.5 6.26L6.15 5.75L8 1.5Z"
121
+ fill={filled ? color : "#E5E5E5"}
122
+ />
123
+ </svg>
124
+ );
125
+ };
126
+
127
+ export type TimeOfDayVariant = "sunrise" | "morning" | "sunset" | "night";
128
+
129
+ const TIME_OF_DAY_RAYS = (cy: number, r: number, len: number) =>
130
+ [0, 45, 90, 135, 180, 225, 270, 315].map((deg) => {
131
+ const rad = (deg * Math.PI) / 180;
132
+ const x1 = 8 + Math.sin(rad) * (r + 1.5);
133
+ const y1 = cy - Math.cos(rad) * (r + 1.5);
134
+ const x2 = 8 + Math.sin(rad) * (r + 1.5 + len);
135
+ const y2 = cy - Math.cos(rad) * (r + 1.5 + len);
136
+ return { x1, y1, x2, y2 };
137
+ });
138
+
139
+ export const TimeOfDayIcon = ({
140
+ variant,
141
+ size = 16,
142
+ color = "#464647",
143
+ src,
144
+ }: {
145
+ variant: TimeOfDayVariant;
146
+ size?: number;
147
+ color?: string;
148
+ src?: string;
149
+ }) => {
150
+ if (src) return <img src={src} width={size} height={size} alt="" />;
151
+
152
+ if (variant === "night") {
153
+ return (
154
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
155
+ <path
156
+ d="M13.5 9.8A5.5 5.5 0 1 1 6.2 2.5a4.3 4.3 0 1 0 7.3 7.3Z"
157
+ stroke={color}
158
+ strokeWidth="1.2"
159
+ strokeLinejoin="round"
160
+ />
161
+ </svg>
162
+ );
163
+ }
164
+
165
+ if (variant === "morning") {
166
+ return (
167
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
168
+ <circle cx="8" cy="8" r="3.2" stroke={color} strokeWidth="1.2" />
169
+ {TIME_OF_DAY_RAYS(8, 3.2, 1.8).map((r, i) => (
170
+ <line key={i} x1={r.x1} y1={r.y1} x2={r.x2} y2={r.y2} stroke={color} strokeWidth="1.2" strokeLinecap="round" />
171
+ ))}
172
+ </svg>
173
+ );
174
+ }
175
+
176
+ // sunrise / sunset share the same "sun on the horizon" glyph, distinguished by the arrow direction.
177
+ const arrowUp = variant === "sunrise";
178
+ return (
179
+ <svg width={size} height={size} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
180
+ <path d="M4.3 9.5a3.7 3.7 0 0 1 7.4 0" stroke={color} strokeWidth="1.2" strokeLinecap="round" />
181
+ <line x1="2" y1="9.5" x2="14" y2="9.5" stroke={color} strokeWidth="1.2" strokeLinecap="round" />
182
+ <line x1="2.3" y1="12" x2="13.7" y2="12" stroke={color} strokeWidth="1" strokeLinecap="round" opacity="0.5" />
183
+ {arrowUp ? (
184
+ <path d="M8 1.5V5M8 1.5L6.2 3.3M8 1.5L9.8 3.3" stroke={color} strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
185
+ ) : (
186
+ <path d="M8 1.5V5M8 5L6.2 3.2M8 5L9.8 3.2" stroke={color} strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
187
+ )}
188
+ </svg>
189
+ );
190
+ };
191
+
192
+ export const CheckboxIcon = ({
193
+ size = 18,
194
+ checked = false,
195
+ color = "#FF5C60",
196
+ spriteSrc,
197
+ }: {
198
+ size?: number;
199
+ checked?: boolean;
200
+ color?: string;
201
+ /** 2x2 sprite sheet (checked/unchecked square states), e.g. new-sprite-icon.svg */
202
+ spriteSrc?: string;
203
+ }) => {
204
+ if (spriteSrc) {
205
+ return (
206
+ <div
207
+ style={{
208
+ display: "inline-block",
209
+ flexShrink: 0,
210
+ width: size,
211
+ height: size,
212
+ backgroundImage: `url(${spriteSrc})`,
213
+ backgroundRepeat: "no-repeat",
214
+ backgroundSize: "200% 200%",
215
+ backgroundPosition: checked ? "0% 100%" : "100% 100%",
216
+ }}
217
+ />
218
+ );
219
+ }
220
+ return (
221
+ <svg width={size} height={size} viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ flexShrink: 0 }}>
222
+ <rect
223
+ x="1"
224
+ y="1"
225
+ width="16"
226
+ height="16"
227
+ rx="4"
228
+ fill={checked ? color : "#fff"}
229
+ stroke={checked ? color : "#C0C0C0"}
230
+ strokeWidth="1.4"
231
+ />
232
+ {checked && (
233
+ <path d="M4.5 9.2L7.3 12L13.5 5.5" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
234
+ )}
235
+ </svg>
236
+ );
237
+ };
@@ -0,0 +1,15 @@
1
+ import FilterSortBarMobile from "./FilterSortBarMobile";
2
+
3
+ export { FilterSortBarMobile };
4
+ export { DEFAULT_CATEGORY_LABELS } from "./types";
5
+ export type {
6
+ FilterCategory,
7
+ FilterCategoryKey,
8
+ FilterCategoryKind,
9
+ FilterOptionItem,
10
+ PriceRangeValue,
11
+ FilterSortBarColors,
12
+ FilterSortBarIcons,
13
+ FilterSortBarMobileProps,
14
+ TimeOfDayVariant,
15
+ } from "./types";