@duffel/components 3.4.1 → 3.4.3--canary.0

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 (35) hide show
  1. package/README.md +1 -1
  2. package/components/DuffelCardForm/DuffelCardForm.d.ts +2 -1
  3. package/components/DuffelCardForm/lib/getIFrameEventListener.d.ts +2 -2
  4. package/components/DuffelCardForm/lib/getIFrameOriginForEnvironment.d.ts +2 -0
  5. package/components/DuffelCardForm/lib/getIframeURL.d.ts +2 -0
  6. package/components/DuffelCardForm/lib/getPathnameForIntent.d.ts +2 -0
  7. package/components/DuffelCardForm/lib/postMessageToCreateCardForTemporaryUse.d.ts +1 -0
  8. package/components/DuffelCardForm/lib/postMessageToSaveCard.d.ts +1 -0
  9. package/components/DuffelCardForm/lib/postMessageWithStyles.d.ts +2 -0
  10. package/components/DuffelCardForm/lib/types.d.ts +60 -17
  11. package/components/DuffelCardForm/lib/useDuffelCardFormActions.d.ts +24 -0
  12. package/components/DuffelNGSView/DuffelNGSView.d.ts +7 -0
  13. package/components/DuffelNGSView/NGSShelfInfoCard.d.ts +7 -0
  14. package/components/DuffelNGSView/NGSSliceFareCard.d.ts +11 -0
  15. package/components/DuffelNGSView/SliceSummary.d.ts +7 -0
  16. package/components/DuffelNGSView/lib/get-max-baggages-for-offer-slice.d.ts +8 -0
  17. package/components/DuffelNGSView/lib/group-offers-for-ngs-view.d.ts +3 -0
  18. package/components/DuffelNGSView/lib/index.d.ts +56 -0
  19. package/components/DuffelNGSView/lib/sort-ngs-rows.d.ts +4 -0
  20. package/components/shared/Icon.d.ts +14 -0
  21. package/components/shared/RadioButton.d.ts +1 -0
  22. package/components/shared/SliceCarriersTitle.d.ts +7 -0
  23. package/custom-elements.js +27 -27
  24. package/custom-elements.js.map +3 -3
  25. package/index.d.ts +3 -1
  26. package/index.js +15 -15
  27. package/index.js.map +4 -4
  28. package/lib/colors.d.ts +1 -0
  29. package/package.json +3 -3
  30. package/stories/DuffelNGSView.stories.d.ts +5 -0
  31. package/stories/NGSShelfInfoCard.stories.d.ts +3 -0
  32. package/stories/NGSSliceFareCard.stories.d.ts +4 -0
  33. package/stories/SliceCarriersTitle.stories.d.ts +10 -0
  34. package/stories/SliceSummary.stories.d.ts +6 -0
  35. package/tsconfig.tsbuildinfo +1 -1
package/README.md CHANGED
@@ -125,7 +125,7 @@ If you are not in a node environment and can't rely on npm to install the packag
125
125
  document.querySelector("duffel-ancillaries");
126
126
 
127
127
  duffelAncillariesElement.addEventListener("onPayloadReady", (event) =>
128
- console.log("onPayloadReady\n", event.detail)
128
+ console.log("onPayloadReady\n", event.detail),
129
129
  );
130
130
  ```
131
131
 
@@ -1,3 +1,4 @@
1
1
  import * as React from "react";
2
2
  import { DuffelCardFormProps } from "./lib/types";
3
- export declare const DuffelCardForm: React.FC<DuffelCardFormProps>;
3
+ import { DuffelCardFormActions } from "./lib/useDuffelCardFormActions";
4
+ export declare const DuffelCardForm: React.ForwardRefExoticComponent<DuffelCardFormProps & React.RefAttributes<DuffelCardFormActions>>;
@@ -2,6 +2,6 @@ import { DuffelCardFormProps } from "./types";
2
2
  type Inputs = {
3
3
  setIFrameHeight: (height: string) => void;
4
4
  postMessageWithStyles: () => void;
5
- } & Pick<DuffelCardFormProps, "onValidateSuccess" | "onValidateFailure" | "onCreateCardForTemporaryUseSuccess" | "onCreateCardForTemporaryUseFailure">;
6
- export declare function getIFrameEventListener(baseUrl: string, { postMessageWithStyles, setIFrameHeight, onValidateSuccess, onValidateFailure, onCreateCardForTemporaryUseSuccess, onCreateCardForTemporaryUseFailure, }: Inputs): (event: MessageEvent) => void;
5
+ } & Pick<DuffelCardFormProps, "onValidateSuccess" | "onValidateFailure" | "onCreateCardForTemporaryUseSuccess" | "onCreateCardForTemporaryUseFailure" | "onSaveCardSuccess" | "onSaveCardFailure">;
6
+ export declare function getIFrameEventListener(iFrameURL: URL, { postMessageWithStyles, setIFrameHeight, onValidateSuccess, onValidateFailure, onCreateCardForTemporaryUseSuccess, onCreateCardForTemporaryUseFailure, onSaveCardSuccess, onSaveCardFailure, }: Inputs): (event: MessageEvent) => void;
7
7
  export {};
@@ -0,0 +1,2 @@
1
+ import { DuffelCardFormProps } from "./types";
2
+ export declare function getIFrameOriginForEnvironment(tokenProxyEnvironment: DuffelCardFormProps["tokenProxyEnvironment"]): string;
@@ -0,0 +1,2 @@
1
+ import { DuffelCardFormProps } from "./types";
2
+ export declare function getIframeURL(tokenProxyEnvironment: DuffelCardFormProps["tokenProxyEnvironment"], intent: DuffelCardFormProps["intent"], clientKey: DuffelCardFormProps["clientKey"], savedCardData: DuffelCardFormProps["savedCardData"]): URL;
@@ -0,0 +1,2 @@
1
+ import { DuffelCardFormIntent } from "./types";
2
+ export declare function getPathnameForIntent(intent: DuffelCardFormIntent): string;
@@ -0,0 +1 @@
1
+ export declare function postMessageToCreateCardForTemporaryUse(iFrameReference: React.RefObject<HTMLIFrameElement>, baseUrl: URL): void;
@@ -0,0 +1 @@
1
+ export declare function postMessageToSaveCard(iFrameReference: React.RefObject<HTMLIFrameElement>, baseUrl: URL): void;
@@ -0,0 +1,2 @@
1
+ import { DuffelCardFormStyles } from "./types";
2
+ export declare function postMessageWithStyles(iFrameReference: React.RefObject<HTMLIFrameElement>, baseUrl: URL, styles: DuffelCardFormStyles | undefined): void;
@@ -1,11 +1,23 @@
1
- export interface CreateCardForTemporaryUseData {
1
+ interface CommonCardData {
2
2
  id: string;
3
+ last_4_digits: string;
3
4
  live_mode: false;
4
5
  }
5
- export interface CreateCardForTemporaryUseError {
6
+ interface CardActionError {
6
7
  status: number;
7
8
  message: string;
8
9
  }
10
+ export interface CreateCardForTemporaryUseData extends CommonCardData {
11
+ saved: false;
12
+ /** The card will no longer be available for use after this time. */
13
+ unavailable_at: string;
14
+ }
15
+ export interface SaveCardData extends CommonCardData {
16
+ saved: true;
17
+ unavailable_at: null;
18
+ }
19
+ export type SaveCardError = CardActionError;
20
+ export type CreateCardForTemporaryUseError = CardActionError;
9
21
  /**
10
22
  * An object where each key value pair is a style to be applied.
11
23
  * e.g. { 'background-image': 'red', 'color': '#000', 'margin-inline': '8px' }
@@ -28,10 +40,11 @@ export interface DuffelCardFormStyles {
28
40
  sectionTitle?: StylesMap;
29
41
  layoutGrid?: StylesMap;
30
42
  }
31
- export type DuffelCardFormActions = "validate" | "create-card-for-temporary-use";
43
+ export type DuffelCardFormAction = "validate" | "save-card" | "create-card-for-temporary-use";
44
+ export type DuffelCardFormIntent = "to-create-card-for-temporary-use" | "to-use-saved-card" | "to-save-card";
32
45
  export interface DuffelCardFormProps {
33
46
  /**
34
- * The client key present in the Quote object.
47
+ * The client key retrieved from the Duffel API.
35
48
  */
36
49
  clientKey: string;
37
50
  /**
@@ -45,37 +58,67 @@ export interface DuffelCardFormProps {
45
58
  */
46
59
  tokenProxyEnvironment?: "development" | "staging" | "production";
47
60
  /**
48
- * The actions you'd like the component to perform.
49
- *
50
- * This prop is a dependecy of a useEffect hook in the component
51
- * and so when it's changed it will perform the action you specify.
52
- *
53
- * The action `create-card-for-temporary-use` will only happen once `validate` has been successful.
61
+ * The card intent defines what the form is meant to look like.
62
+ * It can be one of:
54
63
  *
64
+ * - `to-create-card-for-temporary-use`: The full form will be shown. You may also use this intent for the use case of using and saving the card.
65
+ * - `to-use-saved-card`: When using this intent also provide the saved card ID. Only a cvv field will be rendered.
66
+ * - `to-save-card`: The form will be shown without the cvv field. This only allows you to save a card for future use,
67
+ * but not create an id for immediate, temporary use. For the use case of saving during checkout or save + use, use the `to-create-card-for-temporary-use` intent.
68
+ */
69
+ intent: DuffelCardFormIntent;
70
+ /**
71
+ * Once a card is saved, in order to use it, travellers need to enter its cvv.
72
+ * When using the `use-saved-card` intent, you must provide the card ID.
55
73
  */
56
- actions: DuffelCardFormActions[];
74
+ savedCardData?: {
75
+ id: string;
76
+ brand: string;
77
+ };
57
78
  /**
58
79
  * This function will be called when the card form validation has been successful.
59
80
  */
60
- onValidateSuccess: () => void;
81
+ onValidateSuccess?: () => void;
61
82
  /**
62
83
  * If the card form validation is successful but data is changed afterwards,
63
84
  * making it invalid, this function will be called.
64
85
  */
65
- onValidateFailure: () => void;
86
+ onValidateFailure?: () => void;
66
87
  /**
67
88
  * This function will be called when the card has been created for temporary use.
68
89
  *
69
90
  * This callback will only be triggered if the `create-card-for-temporary-use`
70
- * action is present in the `actions` prop.
91
+ * action is present in the `actions` prop. Alternatively,
92
+ * you may use the `triggerCreateCardForTemporaryUse` function from the
93
+ * `useDuffelCardFormActions` hook.
71
94
  */
72
- onCreateCardForTemporaryUseSuccess: (data: CreateCardForTemporaryUseData) => void;
95
+ onCreateCardForTemporaryUseSuccess?: (data: CreateCardForTemporaryUseData) => void;
73
96
  /**
74
97
  * This function will be called when the component has failed to create the card for temporary use.
75
98
  *
76
99
  * This callback will only be triggered if the `create-card-for-temporary-use`
77
- * action is present in the `actions` prop.
100
+ * action is present in the `actions` prop. Alternatively,
101
+ * you may use the `triggerCreateCardForTemporaryUse` function from the
102
+ * `useDuffelCardFormActions` hook.
103
+ */
104
+ onCreateCardForTemporaryUseFailure?: (error: CreateCardForTemporaryUseError) => void;
105
+ /**
106
+ * This function will be called when the card has been saved.
107
+ *
108
+ * This callback will only be triggered if the `save-card`
109
+ * action is present in the `actions` prop. Alternatively,
110
+ * you may use the `triggerSaveCard` function from the
111
+ * `useDuffelCardFormActions` hook.
112
+ */
113
+ onSaveCardSuccess?: (data: SaveCardData) => void;
114
+ /**
115
+ * This function will be called when saving the card has failed.
116
+ *
117
+ * This callback will only be triggered if the `save-card`
118
+ * action is present in the `actions` prop. Alternatively,
119
+ * you may use the `triggerSaveCard` function from the
120
+ * `useDuffelCardFormActions` hook.
78
121
  */
79
- onCreateCardForTemporaryUseFailure: (error: CreateCardForTemporaryUseError) => void;
122
+ onSaveCardFailure?: (error: SaveCardError) => void;
80
123
  }
81
124
  export {};
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ export interface DuffelCardFormActions {
3
+ saveCard: () => void;
4
+ createCardForTemporaryUse: () => void;
5
+ }
6
+ export interface UseDuffelCardFormActionsHook {
7
+ /**
8
+ * The ref you should pass to the DuffelCardForm component.
9
+ */
10
+ ref: React.RefObject<DuffelCardFormActions>;
11
+ /**
12
+ * Call this function to tell the component to save the card.
13
+ */
14
+ saveCard: () => void;
15
+ /**
16
+ * Call this function to tell the component to create a card for temporary use.
17
+ */
18
+ createCardForTemporaryUse: () => void;
19
+ }
20
+ /**
21
+ * This hook abstracts the ref for convenience and readability.
22
+ * Add `ref` to the `DuffelCardForm` `ref` prop and call the functions to trigger the actions you'd like.
23
+ */
24
+ export declare function useDuffelCardFormActions(): UseDuffelCardFormActionsHook;
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import { OfferWithNGS } from "./lib";
3
+ export interface DuffelNGSViewProps {
4
+ offers: OfferWithNGS[];
5
+ sliceIndex: number;
6
+ }
7
+ export declare const DuffelNGSView: React.FC<DuffelNGSViewProps>;
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import { NGSShelf } from "./lib";
3
+ export interface NGSShelfInfoCardProps {
4
+ ngs_shelf: NGSShelf;
5
+ className?: string;
6
+ }
7
+ export declare const NGSShelfInfoCard: React.FC<NGSShelfInfoCardProps>;
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ import { OfferWithNGS } from "./lib";
3
+ export interface NGSSliceFareCardProps {
4
+ offer: OfferWithNGS;
5
+ sliceIndex: number;
6
+ selected?: boolean;
7
+ onSelect?: () => void;
8
+ compareToAmount?: number;
9
+ className?: string;
10
+ }
11
+ export declare const NGSSliceFareCard: React.FC<NGSSliceFareCardProps>;
@@ -0,0 +1,7 @@
1
+ /// <reference types="@duffel/api" />
2
+ import { OfferSlice } from "@duffel/api/types";
3
+ import React from "react";
4
+ export interface SliceSummaryProps {
5
+ slice: OfferSlice;
6
+ }
7
+ export declare const SliceSummary: React.FC<SliceSummaryProps>;
@@ -0,0 +1,8 @@
1
+ import { OfferAvailableServiceBaggageMetadata, OfferSlice, OfferSliceSegmentPassenger } from "@duffel/api/types";
2
+ /**
3
+ * Returns the passenger baggages object with the largest quantity of baggages
4
+ * of a specified type for a slice. Baggage quantity can (very occasionally)
5
+ * vary across passengers and segments in a slice, so the 'max' baggages can
6
+ * be used as the baseline for a slice.
7
+ */
8
+ export declare const getMaxBaggagesForOfferSlice: (offerSlice: OfferSlice, type: OfferAvailableServiceBaggageMetadata["type"]) => OfferSliceSegmentPassenger["baggages"];
@@ -0,0 +1,3 @@
1
+ import { NGSShelf, OfferSliceWithNGS, OfferWithNGS } from ".";
2
+ export type NGSOfferRow = Record<"slice", OfferSliceWithNGS> & Record<NGSShelf, OfferWithNGS | null>;
3
+ export declare const groupOffersForNGSView: (offers: OfferWithNGS[], sliceIndex: number) => NGSOfferRow[];
@@ -0,0 +1,56 @@
1
+ /// <reference types="@duffel/api" />
2
+ import { IconName } from "@components/shared/Icon";
3
+ import { Offer, OfferSlice, OfferSliceSegment, OfferSliceSegmentPassenger } from "@duffel/api/types";
4
+ export declare const NGS_SHELVES: readonly ["1", "2", "3", "4", "5"];
5
+ export type NGSShelf = (typeof NGS_SHELVES)[number];
6
+ type SeatWithNGS = {
7
+ type: string;
8
+ flatness: string;
9
+ };
10
+ type CabinWithNGS = {
11
+ amenities: {
12
+ seat: SeatWithNGS;
13
+ power: {
14
+ available: boolean;
15
+ };
16
+ wifi: {
17
+ available: boolean;
18
+ cost: "free" | "paid" | "free or paid" | "n/a";
19
+ };
20
+ };
21
+ layout: {
22
+ type: string;
23
+ };
24
+ };
25
+ type OfferSliceSegmentPassengerWithNGS = OfferSliceSegmentPassenger & {
26
+ cabin: CabinWithNGS;
27
+ ticket_attributes: {
28
+ advanced_selection_available: boolean;
29
+ };
30
+ };
31
+ export type OfferSliceSegmentWithNGS = OfferSliceSegment & {
32
+ passengers: OfferSliceSegmentPassengerWithNGS[];
33
+ };
34
+ export type OfferSliceWithNGS = OfferSlice & {
35
+ segments: OfferSliceSegmentWithNGS[];
36
+ ngs_shelf: NGSShelf;
37
+ };
38
+ export type OfferWithNGS = Offer & {
39
+ slices: OfferSliceWithNGS[];
40
+ };
41
+ type SeatType = "Standard seat" | "Extra legroom" | "Larger seat" | "Lie flat bed" | "Lie flat suite";
42
+ type ShelfInfo = {
43
+ short_title: string;
44
+ full_title: string;
45
+ description: string;
46
+ seat: {
47
+ description: SeatType;
48
+ icon: IconName;
49
+ };
50
+ checked_bag: boolean;
51
+ seat_selection: boolean;
52
+ icon: IconName;
53
+ };
54
+ export declare const SEAT_ICONS_MAP: Record<SeatType, IconName>;
55
+ export declare const NGS_SHELF_INFO: Record<NGSShelf, ShelfInfo>;
56
+ export {};
@@ -0,0 +1,4 @@
1
+ import { NGSShelf } from ".";
2
+ import { NGSOfferRow } from "./group-offers-for-ngs-view";
3
+ export type SortDirection = "asc" | "desc";
4
+ export declare const sortNGSRows: (rows: NGSOfferRow[], sortShelf: NGSShelf, sortDirection: SortDirection) => NGSOfferRow[];
@@ -3,10 +3,18 @@ import * as React from "react";
3
3
  export declare const ICON_MAP: {
4
4
  accessible: import("react/jsx-runtime").JSX.Element;
5
5
  add: import("react/jsx-runtime").JSX.Element;
6
+ airline_seat_flat: import("react/jsx-runtime").JSX.Element;
7
+ airline_seat_individual_suite: import("react/jsx-runtime").JSX.Element;
8
+ airline_seat_legroom_extra: import("react/jsx-runtime").JSX.Element;
9
+ airline_seat_recline_extra: import("react/jsx-runtime").JSX.Element;
10
+ airline_seat_recline_normal: import("react/jsx-runtime").JSX.Element;
11
+ airplane_ticket: import("react/jsx-runtime").JSX.Element;
6
12
  apartment: import("react/jsx-runtime").JSX.Element;
13
+ arrow_downward: import("react/jsx-runtime").JSX.Element;
7
14
  arrow_forward: import("react/jsx-runtime").JSX.Element;
8
15
  arrow_left: import("react/jsx-runtime").JSX.Element;
9
16
  arrow_right: import("react/jsx-runtime").JSX.Element;
17
+ arrow_upward: import("react/jsx-runtime").JSX.Element;
10
18
  atm: import("react/jsx-runtime").JSX.Element;
11
19
  autorenew: import("react/jsx-runtime").JSX.Element;
12
20
  bakery_dining: import("react/jsx-runtime").JSX.Element;
@@ -14,8 +22,10 @@ export declare const ICON_MAP: {
14
22
  bedroom_parent: import("react/jsx-runtime").JSX.Element;
15
23
  brunch_dining: import("react/jsx-runtime").JSX.Element;
16
24
  cabin_bag: import("react/jsx-runtime").JSX.Element;
25
+ carry_on_bag_inactive: import("react/jsx-runtime").JSX.Element;
17
26
  check: import("react/jsx-runtime").JSX.Element;
18
27
  check_circle: import("react/jsx-runtime").JSX.Element;
28
+ check_small: import("react/jsx-runtime").JSX.Element;
19
29
  checked_bag: import("react/jsx-runtime").JSX.Element;
20
30
  chevron: import("react/jsx-runtime").JSX.Element;
21
31
  child_care: import("react/jsx-runtime").JSX.Element;
@@ -23,6 +33,7 @@ export declare const ICON_MAP: {
23
33
  closet: import("react/jsx-runtime").JSX.Element;
24
34
  concierge: import("react/jsx-runtime").JSX.Element;
25
35
  credit_card: import("react/jsx-runtime").JSX.Element;
36
+ currency_exchange: import("react/jsx-runtime").JSX.Element;
26
37
  dinner_dining: import("react/jsx-runtime").JSX.Element;
27
38
  exit_row: import("react/jsx-runtime").JSX.Element;
28
39
  exit_row_right: import("react/jsx-runtime").JSX.Element;
@@ -40,6 +51,7 @@ export declare const ICON_MAP: {
40
51
  local_bar: import("react/jsx-runtime").JSX.Element;
41
52
  local_parking: import("react/jsx-runtime").JSX.Element;
42
53
  loyalty: import("react/jsx-runtime").JSX.Element;
54
+ luggage: import("react/jsx-runtime").JSX.Element;
43
55
  meeting_room: import("react/jsx-runtime").JSX.Element;
44
56
  minus: import("react/jsx-runtime").JSX.Element;
45
57
  no_airplane: import("react/jsx-runtime").JSX.Element;
@@ -55,9 +67,11 @@ export declare const ICON_MAP: {
55
67
  seat: import("react/jsx-runtime").JSX.Element;
56
68
  seat_paid_indicator: import("react/jsx-runtime").JSX.Element;
57
69
  shield_with_moon: import("react/jsx-runtime").JSX.Element;
70
+ shopping_bag: import("react/jsx-runtime").JSX.Element;
58
71
  spa: import("react/jsx-runtime").JSX.Element;
59
72
  stairs: import("react/jsx-runtime").JSX.Element;
60
73
  star: import("react/jsx-runtime").JSX.Element;
74
+ unfold_more: import("react/jsx-runtime").JSX.Element;
61
75
  wallet: import("react/jsx-runtime").JSX.Element;
62
76
  warning: import("react/jsx-runtime").JSX.Element;
63
77
  wifi: import("react/jsx-runtime").JSX.Element;
@@ -2,5 +2,6 @@ import * as React from "react";
2
2
  export interface RadioButtonProps {
3
3
  value: string;
4
4
  checked?: boolean;
5
+ className?: string;
5
6
  }
6
7
  export declare const RadioButton: React.FC<RadioButtonProps>;
@@ -0,0 +1,7 @@
1
+ /// <reference types="@duffel/api" />
2
+ import { OfferSlice } from "@duffel/api/types";
3
+ import * as React from "react";
4
+ export interface SliceCarriersTitleProps {
5
+ slice: OfferSlice;
6
+ }
7
+ export declare const SliceCarriersTitle: React.FC<SliceCarriersTitleProps>;