@travelswitchhq/flight-search-react 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -80,7 +80,6 @@ var flightSearchWidgetStyles = `
80
80
  -webkit-font-smoothing: antialiased;
81
81
  -moz-osx-font-smoothing: grayscale;
82
82
  -webkit-tap-highlight-color: transparent;
83
- background: var(--sw-widget-bg);
84
83
  *,
85
84
  *::before,
86
85
  *::after {
@@ -196,10 +195,10 @@ var flightSearchWidgetStyles = `
196
195
  min-width: 0;
197
196
  overflow: visible;
198
197
  }
199
- .sw-srh-form-fieldsw-is-invalid {
198
+ .sw-srh-form-field.sw-is-invalid {
200
199
  box-shadow: inset 0 0 0 1px var(--sw-error);
201
200
  }
202
- .sw-srh-form-fieldsw-is-invalid label {
201
+ .sw-srh-form-field.sw-is-invalid label {
203
202
  color: var(--sw-error);
204
203
  }
205
204
  .sw-custom-dropdown.sw-has-error .sw-custom-dropdown-trigger {
@@ -208,7 +207,7 @@ var flightSearchWidgetStyles = `
208
207
  .sw-custom-dropdown.sw-has-error .sw-custom-dropdown-trigger::placeholder {
209
208
  color: var(--sw-error) !important;
210
209
  }
211
- .sw-form-field label {
210
+ .sw-srh-form-field label {
212
211
  display: block;
213
212
  width: 100%;
214
213
  margin: 0;
@@ -222,6 +221,13 @@ var flightSearchWidgetStyles = `
222
221
  text-overflow: ellipsis;
223
222
  text-align: initial;
224
223
  }
224
+ .sw-field-error {
225
+ margin: 2px 0 0;
226
+ color: #f60b0b !important;
227
+ font-size: 12px;
228
+ font-weight: 500;
229
+ line-height: 1.2;
230
+ }
225
231
  .p-button-label {
226
232
  flex: unset;
227
233
  }
@@ -317,6 +323,10 @@ padding-inline-start: 25px;
317
323
  border-radius: var(--sw-radius);
318
324
  box-shadow: var(--sw-widget-shadow);
319
325
  }
326
+ .p-autocomplete-panel ul {
327
+ margin-bottom: 0 !important;
328
+ padding-left: 0 !important;
329
+ }
320
330
  .sw-dropdown::-webkit-scrollbar {
321
331
  display: none;
322
332
  }
@@ -1005,6 +1015,9 @@ padding-inline-start: 25px;
1005
1015
  font-size: 12px;
1006
1016
  font-weight: 400;
1007
1017
  }
1018
+ .sw-airline-autocomplete .p-autocomplete-loader {
1019
+ display: none !important;
1020
+ }
1008
1021
  .sw-fsrh-adv-cont {
1009
1022
  display: flex;
1010
1023
  align-items: center;
@@ -1487,6 +1500,10 @@ function formatDisplayDate(date) {
1487
1500
  if (!date || !(date instanceof Date) || isNaN(date.getTime())) return "Select date";
1488
1501
  return date.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" });
1489
1502
  }
1503
+ var isEmptyLocationValue = (value, placeholder) => {
1504
+ const trimmed = (value ?? "").trim();
1505
+ return trimmed.length === 0 || trimmed === placeholder;
1506
+ };
1490
1507
  function FlightSearchWidget({
1491
1508
  config,
1492
1509
  ssoUser
@@ -1549,6 +1566,8 @@ function FlightSearchWidget({
1549
1566
  const [isOriginDropdownOpen, setIsOriginDropdownOpen] = (0, import_react.useState)(false);
1550
1567
  const [isDestinationDropdownOpen, setIsDestinationDropdownOpen] = (0, import_react.useState)(false);
1551
1568
  const [isRoomsGuestsMenuOpen, setIsRoomsGuestsMenuOpen] = (0, import_react.useState)(false);
1569
+ const [roundTripMinDate, setRoundTripMinDate] = (0, import_react.useState)(/* @__PURE__ */ new Date());
1570
+ const [activeRoundTripField, setActiveRoundTripField] = (0, import_react.useState)("departure");
1552
1571
  const originDropdownRef = (0, import_react.useRef)(null);
1553
1572
  const firstOriginDesktopInputRef = (0, import_react.useRef)(null);
1554
1573
  const destinationDropdownRef = (0, import_react.useRef)(null);
@@ -1758,6 +1777,12 @@ function FlightSearchWidget({
1758
1777
  getAirlineListBySearch(value).then(setAirlineSuggestions);
1759
1778
  }, DEBOUNCE_MS);
1760
1779
  }, [getAirlineListBySearch]);
1780
+ (0, import_react.useEffect)(() => {
1781
+ if (typeof window === "undefined") return;
1782
+ if (window.matchMedia("(max-width: 768px)").matches) {
1783
+ setIsOriginDropdownOpen(false);
1784
+ }
1785
+ }, []);
1761
1786
  (0, import_react.useEffect)(() => () => {
1762
1787
  if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
1763
1788
  if (airlineSearchDebounceRef.current) clearTimeout(airlineSearchDebounceRef.current);
@@ -2001,7 +2026,12 @@ function FlightSearchWidget({
2001
2026
  };
2002
2027
  const extractAirportCode = (location) => {
2003
2028
  const match = location.match(/\(([A-Z]{3})\)/);
2004
- return match ? match[1] : location;
2029
+ return match ? match[1] : location.trim();
2030
+ };
2031
+ const getComparableLocation = (location) => {
2032
+ const code = extractAirportCode(location).trim().toUpperCase();
2033
+ if (code.length === 3 && /^[A-Z]{3}$/.test(code)) return code;
2034
+ return location.trim().toLowerCase().replace(/\s+/g, " ");
2005
2035
  };
2006
2036
  const MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
2007
2037
  const formatDate = (date) => {
@@ -2162,13 +2192,22 @@ function FlightSearchWidget({
2162
2192
  const segmentsToValidate = isMultiCityOrCustom ? segments : segments.slice(0, 1);
2163
2193
  const nextErrors = {};
2164
2194
  segmentsToValidate.forEach((segment, index) => {
2165
- const originInvalid = !isValidLocationValue(segment.origin, "Origin");
2166
- const destinationInvalid = !isValidLocationValue(segment.destination, "Destination");
2195
+ const originValue = typeof segment.origin === "string" ? segment.origin : "";
2196
+ const destinationValue = typeof segment.destination === "string" ? segment.destination : "";
2197
+ const originInvalid = isEmptyLocationValue(originValue, "Origin");
2198
+ const destinationInvalid = isEmptyLocationValue(destinationValue, "Destination");
2167
2199
  if (originInvalid || destinationInvalid) {
2168
2200
  nextErrors[index] = {
2169
2201
  origin: originInvalid,
2170
2202
  destination: destinationInvalid
2171
2203
  };
2204
+ return;
2205
+ }
2206
+ if (getComparableLocation(originValue) === getComparableLocation(destinationValue)) {
2207
+ nextErrors[index] = {
2208
+ origin: true,
2209
+ destination: true
2210
+ };
2172
2211
  }
2173
2212
  });
2174
2213
  if (Object.keys(nextErrors).length > 0) {
@@ -2275,6 +2314,47 @@ function FlightSearchWidget({
2275
2314
  if (prev instanceof Date && !isNaN(prev.getTime())) return prev;
2276
2315
  return today;
2277
2316
  };
2317
+ const openRoundTripCalendar = (mode) => {
2318
+ const today = /* @__PURE__ */ new Date();
2319
+ const selectedDeparture = segments[0]?.dateRange?.[0] ?? segments[0]?.departureDate ?? null;
2320
+ const validDeparture = selectedDeparture instanceof Date && !isNaN(selectedDeparture.getTime()) ? selectedDeparture : today;
2321
+ setActiveRoundTripField(mode);
2322
+ setRoundTripMinDate(mode === "return" ? validDeparture : today);
2323
+ dateRangeCalendarRef.current?.show?.();
2324
+ mobileDateRangeCalendarRef.current?.show?.();
2325
+ };
2326
+ const applyRoundTripRangeChange = (range) => {
2327
+ setSegments((prev) => {
2328
+ const updated = [...prev];
2329
+ if (!updated[0]) return prev;
2330
+ const current = updated[0];
2331
+ const currentDeparture = current.dateRange?.[0] ?? current.departureDate ?? /* @__PURE__ */ new Date();
2332
+ if (activeRoundTripField === "return") {
2333
+ const pickedReturn = range?.[1] ?? range?.[0] ?? currentDeparture;
2334
+ const safeReturn = pickedReturn instanceof Date && pickedReturn.getTime() >= currentDeparture.getTime() ? pickedReturn : currentDeparture;
2335
+ updated[0] = {
2336
+ ...current,
2337
+ dateRange: [currentDeparture, safeReturn],
2338
+ departureDate: currentDeparture,
2339
+ returnDate: safeReturn
2340
+ };
2341
+ return updated;
2342
+ }
2343
+ updated[0] = {
2344
+ ...current,
2345
+ dateRange: range,
2346
+ departureDate: range?.[0] ?? /* @__PURE__ */ new Date(),
2347
+ returnDate: range?.[1] ?? /* @__PURE__ */ new Date()
2348
+ };
2349
+ return updated;
2350
+ });
2351
+ if (activeRoundTripField === "return") {
2352
+ setTimeout(() => {
2353
+ dateRangeCalendarRef.current?.hide?.();
2354
+ mobileDateRangeCalendarRef.current?.hide?.();
2355
+ }, 50);
2356
+ }
2357
+ };
2278
2358
  const renderFlightSegment = (index, segment, isMultiCityOrCustom) => {
2279
2359
  const canRemove = segments.length > 2 && index > 0 && isMultiCityOrCustom;
2280
2360
  const originRef = (el) => {
@@ -2414,10 +2494,7 @@ function FlightSearchWidget({
2414
2494
  renderAirportDropdown(0, "destination", destinationDropdownRef, isDestinationDropdownOpen, () => setIsDestinationDropdownOpen(true))
2415
2495
  ] }),
2416
2496
  (tripType === "round-trip" || tripType === "one-way") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-srh-wrap sw-pos-rel mobiBox", children: tripType === "round-trip" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2417
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { cursor: "pointer" }, onClick: () => {
2418
- dateRangeCalendarRef.current?.show?.();
2419
- mobileDateRangeCalendarRef.current?.show?.();
2420
- }, className: "sw-srh-form-field sw-com-cal", children: [
2497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { cursor: "pointer" }, onClick: () => openRoundTripCalendar("departure"), className: "sw-srh-form-field sw-com-cal", children: [
2421
2498
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2422
2499
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "Departure" }),
2423
2500
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: segments[0]?.dateRange?.[0]?.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" }) })
@@ -2431,23 +2508,15 @@ function FlightSearchWidget({
2431
2508
  appendTo: "self",
2432
2509
  selectionMode: "range",
2433
2510
  value: segments[0]?.dateRange ?? null,
2434
- minDate: /* @__PURE__ */ new Date(),
2511
+ minDate: roundTripMinDate,
2435
2512
  onChange: (e) => {
2436
2513
  const range = e.value;
2437
- setSegments((prev) => {
2438
- const u = [...prev];
2439
- if (!u[0]) return prev;
2440
- u[0] = {
2441
- ...u[0],
2442
- dateRange: range,
2443
- departureDate: range?.[0] ?? /* @__PURE__ */ new Date(),
2444
- returnDate: range?.[1] ?? /* @__PURE__ */ new Date()
2445
- };
2446
- return u;
2447
- });
2448
- if (range?.[0] && range?.[1]) setTimeout(() => {
2449
- dateRangeCalendarRef.current?.hide?.();
2450
- }, 150);
2514
+ applyRoundTripRangeChange(range);
2515
+ if (activeRoundTripField === "departure" && range?.[0] && range?.[1]) {
2516
+ setTimeout(() => {
2517
+ dateRangeCalendarRef.current?.hide?.();
2518
+ }, 150);
2519
+ }
2451
2520
  },
2452
2521
  dateFormat: "dd M yy",
2453
2522
  placeholder: "Select date range",
@@ -2463,20 +2532,10 @@ function FlightSearchWidget({
2463
2532
  appendTo: "self",
2464
2533
  selectionMode: "range",
2465
2534
  value: segments[0]?.dateRange ?? null,
2466
- minDate: /* @__PURE__ */ new Date(),
2535
+ minDate: roundTripMinDate,
2467
2536
  onChange: (e) => {
2468
2537
  const range = e.value;
2469
- setSegments((prev) => {
2470
- const u = [...prev];
2471
- if (!u[0]) return prev;
2472
- u[0] = {
2473
- ...u[0],
2474
- dateRange: range,
2475
- departureDate: range?.[0] ?? /* @__PURE__ */ new Date(),
2476
- returnDate: range?.[1] ?? /* @__PURE__ */ new Date()
2477
- };
2478
- return u;
2479
- });
2538
+ applyRoundTripRangeChange(range);
2480
2539
  },
2481
2540
  dateFormat: "dd M yy",
2482
2541
  placeholder: "Select date range",
@@ -2506,10 +2565,7 @@ function FlightSearchWidget({
2506
2565
  }
2507
2566
  )
2508
2567
  ] }),
2509
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { cursor: "pointer" }, className: "sw-srh-form-field sw-com-cal", onClick: () => {
2510
- dateRangeCalendarRef.current?.show?.();
2511
- mobileDateRangeCalendarRef.current?.show?.();
2512
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2568
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { cursor: "pointer" }, className: "sw-srh-form-field sw-com-cal", onClick: () => openRoundTripCalendar("return"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2513
2569
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { children: "Return" }),
2514
2570
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: (segments[0]?.dateRange?.[1] ?? segments[0]?.dateRange?.[0])?.toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" }) })
2515
2571
  ] }) })
@@ -2770,6 +2826,7 @@ function FlightSearchWidget({
2770
2826
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2771
2827
  import_autocomplete.AutoComplete,
2772
2828
  {
2829
+ className: "sw-airline-autocomplete",
2773
2830
  value: selectedAirlines,
2774
2831
  suggestions: airlineSuggestions,
2775
2832
  completeMethod: (e) => {