@qite/tide-components 1.0.14-preview.1 → 1.0.14-preview.2

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.
@@ -29746,7 +29746,9 @@ const TrajectItinerary = ({ trajectEntry, packagingEntry, translations }) => {
29746
29746
  .map((node) => {
29747
29747
  const guids = node.lineGuids?.length ? node.lineGuids : [node.lineGuid];
29748
29748
  const lines = guids.map((guid) => linesByGuid.get(guid)).filter((x) => !!x);
29749
- return { node, lines };
29749
+ const groupKey = lines.length ? getLineGroupKey(lines[0]) : '';
29750
+ const active = groupKey ? getGroupLines(packagingEntry.lines ?? [], groupKey)[0] : undefined;
29751
+ return { node, lines: active ?? lines };
29750
29752
  });
29751
29753
  const claimed = new Set(nodes.flatMap((item) => item.lines.map((line) => line.guid)));
29752
29754
  const extras = (packagingEntry.lines ?? []).filter((line) => !claimed.has(line.guid)).filter(isMeaningfulItineraryLine);
@@ -35696,6 +35698,25 @@ const BookPackagingEntry = ({ activeSearchSeed, isLoading, isConfirmationPage })
35696
35698
  React__default["default"].createElement(WLSidebar, { activeSearchSeed: activeSearchSeed, packagingAccoResult: selectedPackagingAccoResult }))));
35697
35699
  };
35698
35700
 
35701
+ // A horizontally scrolling row of cards whose selected cards sit first. Choosing a card moves it to the front of the row
35702
+ const TrajectCardRow = ({ selectionKey, children }) => {
35703
+ const ref = React.useRef(null);
35704
+ const previousKey = React.useRef(selectionKey);
35705
+ React.useEffect(() => {
35706
+ if (previousKey.current === selectionKey)
35707
+ return;
35708
+ previousKey.current = selectionKey;
35709
+ const row = ref.current;
35710
+ if (!row || row.scrollLeft === 0)
35711
+ return;
35712
+ if (typeof row.scrollTo === 'function')
35713
+ row.scrollTo({ left: 0, behavior: 'smooth' });
35714
+ else
35715
+ row.scrollLeft = 0;
35716
+ }, [selectionKey]);
35717
+ return (React__default["default"].createElement("div", { ref: ref, className: "search__results__cards search__results__cards--scroll" }, children));
35718
+ };
35719
+
35699
35720
  const useTrajectDayActivities = () => {
35700
35721
  const context = React.useContext(SearchResultsConfigurationContext);
35701
35722
  const dispatch = reactRedux.useDispatch();
@@ -35897,7 +35918,7 @@ const TrajectResults = ({ isLoading }) => {
35897
35918
  node.preferredAccommodationName,
35898
35919
  " \u2014 ",
35899
35920
  translations.SRP.NO_RESULTS))),
35900
- React__default["default"].createElement("div", { className: "search__results__cards search__results__cards--scroll" }, [selected, ...configured, ...fill].map((result) => (React__default["default"].createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE, selectedLabel: bookedMode && matchesCode(result, node.code ?? '') ? translations.SHARED.BOOKED : undefined })))),
35921
+ React__default["default"].createElement(TrajectCardRow, { selectionKey: selected.code }, [selected, ...configured, ...fill].map((result) => (React__default["default"].createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE })))),
35901
35922
  remaining > 0 && !hideShowMoreResults && (React__default["default"].createElement("div", { className: "search__results__cards__actions" },
35902
35923
  React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => handleShowMore(item) },
35903
35924
  translations.SRP.SHOW_MORE,
@@ -35944,6 +35965,7 @@ const TrajectResults = ({ isLoading }) => {
35944
35965
  };
35945
35966
  /** The lines a suggested activity put on the entry, which is also how we know it was added. */
35946
35967
  const getAddedExcursionLines = (result) => (editablePackagingEntry?.lines ?? []).filter((line) => line.serviceType === EXCURSION_SERVICE_TYPE && line.productCode === result.code && dateFns.isSameDay(new Date(line.from), new Date(result.fromDate)));
35968
+ const isActivitySelected = ({ result, item }) => item ? trajectNodeAvailability[item.line.guid]?.selectedCode === result.code : getAddedExcursionLines(result).length > 0;
35947
35969
  const handleToggleActivity = (result) => {
35948
35970
  const added = getAddedExcursionLines(result);
35949
35971
  if (added.length) {
@@ -35982,7 +36004,9 @@ const TrajectResults = ({ isLoading }) => {
35982
36004
  const renderDayActivities = (day) => {
35983
36005
  const items = getDayExcursionItems(day.order);
35984
36006
  const suggestions = trajectDaySuggestions[day.order];
35985
- const cards = buildDayActivityCards(items, trajectNodeAvailability, suggestions?.results ?? []);
36007
+ const allCards = buildDayActivityCards(items, trajectNodeAvailability, suggestions?.results ?? []);
36008
+ const selectedCards = allCards.filter(isActivitySelected);
36009
+ const cards = [...selectedCards, ...allCards.filter((card) => !isActivitySelected(card))];
35986
36010
  const nodesResolving = items.some((item) => (trajectNodeAvailability[item.line.guid]?.status ?? 'loading') === 'loading');
35987
36011
  const isSearching = suggestions?.status === 'loading';
35988
36012
  // A day is worth filling only if the party is staying somewhere that night. The day they fly
@@ -36001,7 +36025,7 @@ const TrajectResults = ({ isLoading }) => {
36001
36025
  React__default["default"].createElement("h3", null,
36002
36026
  React__default["default"].createElement("strong", null, translations.SRP.ACTIVITIES)))),
36003
36027
  (nodesResolving || isSearching) && !cards.length && React__default["default"].createElement(Spinner, { label: translations.SRP.LOADING_ACTIVITIES }),
36004
- !!cards.length && React__default["default"].createElement("div", { className: "search__results__cards search__results__cards--scroll" }, visible.map(renderActivityCard)),
36028
+ !!cards.length && (React__default["default"].createElement(TrajectCardRow, { selectionKey: selectedCards.map((card) => card.result.code).join('|') }, visible.map(renderActivityCard))),
36005
36029
  !nodesResolving && !isSearching && !cards.length && (!!items.length || !!suggestions) && (React__default["default"].createElement("div", { className: "no-results" }, translations.SRP.NO_RESULTS)),
36006
36030
  React__default["default"].createElement("div", { className: "search__results__cards__actions" },
36007
36031
  awaitsRequest && (React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => loadDay(day) }, translations.SRP.SHOW_ACTIVITIES)),
@@ -36016,7 +36040,7 @@ const TrajectResults = ({ isLoading }) => {
36016
36040
  * found for themselves is added to the trip or taken back off it.
36017
36041
  */
36018
36042
  const renderActivityCard = ({ result, item }) => {
36019
- const isSelected = item ? trajectNodeAvailability[item.line.guid]?.selectedCode === result.code : getAddedExcursionLines(result).length > 0;
36043
+ const isSelected = isActivitySelected({ result, item });
36020
36044
  const isBookedCard = !!item && bookedMode && matchesCode(result, item.node.code ?? '');
36021
36045
  return (React__default["default"].createElement(TrajectNodeCard, { key: `activity-${result.code}`, node: item?.node, result: result, isSelected: isSelected, languageCode: context.languageCode, translations: translations, onSelect: () => (item ? handleSelect(item, result.code) : handleToggleActivity(result)), selectLabel: item ? undefined : translations.SRP.ADD, selectedLabel: item ? (isBookedCard ? translations.SHARED.BOOKED : undefined) : translations.SRP.REMOVE }));
36022
36046
  };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface TrajectCardRowProps {
3
+ selectionKey: string;
4
+ children: React.ReactNode;
5
+ }
6
+ declare const TrajectCardRow: React.FC<TrajectCardRowProps>;
7
+ export default TrajectCardRow;
@@ -29717,7 +29717,9 @@ const TrajectItinerary = ({ trajectEntry, packagingEntry, translations }) => {
29717
29717
  .map((node) => {
29718
29718
  const guids = node.lineGuids?.length ? node.lineGuids : [node.lineGuid];
29719
29719
  const lines = guids.map((guid) => linesByGuid.get(guid)).filter((x) => !!x);
29720
- return { node, lines };
29720
+ const groupKey = lines.length ? getLineGroupKey(lines[0]) : '';
29721
+ const active = groupKey ? getGroupLines(packagingEntry.lines ?? [], groupKey)[0] : undefined;
29722
+ return { node, lines: active ?? lines };
29721
29723
  });
29722
29724
  const claimed = new Set(nodes.flatMap((item) => item.lines.map((line) => line.guid)));
29723
29725
  const extras = (packagingEntry.lines ?? []).filter((line) => !claimed.has(line.guid)).filter(isMeaningfulItineraryLine);
@@ -35667,6 +35669,25 @@ const BookPackagingEntry = ({ activeSearchSeed, isLoading, isConfirmationPage })
35667
35669
  React__default.createElement(WLSidebar, { activeSearchSeed: activeSearchSeed, packagingAccoResult: selectedPackagingAccoResult }))));
35668
35670
  };
35669
35671
 
35672
+ // A horizontally scrolling row of cards whose selected cards sit first. Choosing a card moves it to the front of the row
35673
+ const TrajectCardRow = ({ selectionKey, children }) => {
35674
+ const ref = useRef(null);
35675
+ const previousKey = useRef(selectionKey);
35676
+ useEffect(() => {
35677
+ if (previousKey.current === selectionKey)
35678
+ return;
35679
+ previousKey.current = selectionKey;
35680
+ const row = ref.current;
35681
+ if (!row || row.scrollLeft === 0)
35682
+ return;
35683
+ if (typeof row.scrollTo === 'function')
35684
+ row.scrollTo({ left: 0, behavior: 'smooth' });
35685
+ else
35686
+ row.scrollLeft = 0;
35687
+ }, [selectionKey]);
35688
+ return (React__default.createElement("div", { ref: ref, className: "search__results__cards search__results__cards--scroll" }, children));
35689
+ };
35690
+
35670
35691
  const useTrajectDayActivities = () => {
35671
35692
  const context = useContext(SearchResultsConfigurationContext);
35672
35693
  const dispatch = useDispatch();
@@ -35868,7 +35889,7 @@ const TrajectResults = ({ isLoading }) => {
35868
35889
  node.preferredAccommodationName,
35869
35890
  " \u2014 ",
35870
35891
  translations.SRP.NO_RESULTS))),
35871
- React__default.createElement("div", { className: "search__results__cards search__results__cards--scroll" }, [selected, ...configured, ...fill].map((result) => (React__default.createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE, selectedLabel: bookedMode && matchesCode(result, node.code ?? '') ? translations.SHARED.BOOKED : undefined })))),
35892
+ React__default.createElement(TrajectCardRow, { selectionKey: selected.code }, [selected, ...configured, ...fill].map((result) => (React__default.createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE })))),
35872
35893
  remaining > 0 && !hideShowMoreResults && (React__default.createElement("div", { className: "search__results__cards__actions" },
35873
35894
  React__default.createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => handleShowMore(item) },
35874
35895
  translations.SRP.SHOW_MORE,
@@ -35915,6 +35936,7 @@ const TrajectResults = ({ isLoading }) => {
35915
35936
  };
35916
35937
  /** The lines a suggested activity put on the entry, which is also how we know it was added. */
35917
35938
  const getAddedExcursionLines = (result) => (editablePackagingEntry?.lines ?? []).filter((line) => line.serviceType === EXCURSION_SERVICE_TYPE && line.productCode === result.code && isSameDay(new Date(line.from), new Date(result.fromDate)));
35939
+ const isActivitySelected = ({ result, item }) => item ? trajectNodeAvailability[item.line.guid]?.selectedCode === result.code : getAddedExcursionLines(result).length > 0;
35918
35940
  const handleToggleActivity = (result) => {
35919
35941
  const added = getAddedExcursionLines(result);
35920
35942
  if (added.length) {
@@ -35953,7 +35975,9 @@ const TrajectResults = ({ isLoading }) => {
35953
35975
  const renderDayActivities = (day) => {
35954
35976
  const items = getDayExcursionItems(day.order);
35955
35977
  const suggestions = trajectDaySuggestions[day.order];
35956
- const cards = buildDayActivityCards(items, trajectNodeAvailability, suggestions?.results ?? []);
35978
+ const allCards = buildDayActivityCards(items, trajectNodeAvailability, suggestions?.results ?? []);
35979
+ const selectedCards = allCards.filter(isActivitySelected);
35980
+ const cards = [...selectedCards, ...allCards.filter((card) => !isActivitySelected(card))];
35957
35981
  const nodesResolving = items.some((item) => (trajectNodeAvailability[item.line.guid]?.status ?? 'loading') === 'loading');
35958
35982
  const isSearching = suggestions?.status === 'loading';
35959
35983
  // A day is worth filling only if the party is staying somewhere that night. The day they fly
@@ -35972,7 +35996,7 @@ const TrajectResults = ({ isLoading }) => {
35972
35996
  React__default.createElement("h3", null,
35973
35997
  React__default.createElement("strong", null, translations.SRP.ACTIVITIES)))),
35974
35998
  (nodesResolving || isSearching) && !cards.length && React__default.createElement(Spinner, { label: translations.SRP.LOADING_ACTIVITIES }),
35975
- !!cards.length && React__default.createElement("div", { className: "search__results__cards search__results__cards--scroll" }, visible.map(renderActivityCard)),
35999
+ !!cards.length && (React__default.createElement(TrajectCardRow, { selectionKey: selectedCards.map((card) => card.result.code).join('|') }, visible.map(renderActivityCard))),
35976
36000
  !nodesResolving && !isSearching && !cards.length && (!!items.length || !!suggestions) && (React__default.createElement("div", { className: "no-results" }, translations.SRP.NO_RESULTS)),
35977
36001
  React__default.createElement("div", { className: "search__results__cards__actions" },
35978
36002
  awaitsRequest && (React__default.createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => loadDay(day) }, translations.SRP.SHOW_ACTIVITIES)),
@@ -35987,7 +36011,7 @@ const TrajectResults = ({ isLoading }) => {
35987
36011
  * found for themselves is added to the trip or taken back off it.
35988
36012
  */
35989
36013
  const renderActivityCard = ({ result, item }) => {
35990
- const isSelected = item ? trajectNodeAvailability[item.line.guid]?.selectedCode === result.code : getAddedExcursionLines(result).length > 0;
36014
+ const isSelected = isActivitySelected({ result, item });
35991
36015
  const isBookedCard = !!item && bookedMode && matchesCode(result, item.node.code ?? '');
35992
36016
  return (React__default.createElement(TrajectNodeCard, { key: `activity-${result.code}`, node: item?.node, result: result, isSelected: isSelected, languageCode: context.languageCode, translations: translations, onSelect: () => (item ? handleSelect(item, result.code) : handleToggleActivity(result)), selectLabel: item ? undefined : translations.SRP.ADD, selectedLabel: item ? (isBookedCard ? translations.SHARED.BOOKED : undefined) : translations.SRP.REMOVE }));
35993
36017
  };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface TrajectCardRowProps {
3
+ selectionKey: string;
4
+ children: React.ReactNode;
5
+ }
6
+ declare const TrajectCardRow: React.FC<TrajectCardRowProps>;
7
+ export default TrajectCardRow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-components",
3
- "version": "1.0.14-preview.1",
3
+ "version": "1.0.14-preview.2",
4
4
  "description": "React components for Tide (booking, product availability, form, ...)",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",