@duffel/components 2.7.20 → 3.0.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 (345) hide show
  1. package/.circleci/config.yml +67 -0
  2. package/.eslintrc.js +47 -0
  3. package/.github/renovate.json +16 -0
  4. package/.github/workflows/autoapprove.yml +18 -0
  5. package/.github/workflows/release.yml +89 -0
  6. package/.husky/post-commit +4 -0
  7. package/.husky/pre-commit +4 -0
  8. package/.nvmrc +1 -0
  9. package/.prettierignore +2 -0
  10. package/.storybook/Storyshots.test.js +3 -0
  11. package/.storybook/__snapshots__/Storyshots.test.js.snap +48318 -0
  12. package/.storybook/main.ts +33 -0
  13. package/.storybook/preview.tsx +28 -0
  14. package/.tool-versions +1 -0
  15. package/CONTRIBUTING.md +83 -0
  16. package/README.md +53 -15
  17. package/__mocks__/styleMock.js +6 -0
  18. package/babel.config.js +20 -0
  19. package/commitlint.config.js +4 -0
  20. package/config/esbuild.base.config.js +18 -0
  21. package/config/esbuild.cdn.config.js +51 -0
  22. package/config/esbuild.dev.config.js +46 -0
  23. package/config/esbuild.react.config.js +42 -0
  24. package/jest.config.ts +14 -0
  25. package/package.json +135 -193
  26. package/react-dist/components/DuffelAncillaries/Card.d.ts +14 -0
  27. package/react-dist/components/DuffelAncillaries/Counter.d.ts +10 -0
  28. package/react-dist/components/DuffelAncillaries/DuffelAncillaries.d.ts +3 -0
  29. package/react-dist/components/DuffelAncillaries/DuffelAncillariesCustomElement.d.ts +13 -0
  30. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionCard.d.ts +11 -0
  31. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionController.d.ts +13 -0
  32. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionModal.d.ts +11 -0
  33. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionModalBody.d.ts +11 -0
  34. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionModalBodyPassenger.d.ts +13 -0
  35. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionModalFooter.d.ts +14 -0
  36. package/react-dist/components/DuffelAncillaries/bags/BaggageSelectionModalHeader.d.ts +9 -0
  37. package/react-dist/components/DuffelAncillaries/bags/IncludedBaggageBanner.d.ts +7 -0
  38. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionCard.d.ts +10 -0
  39. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModal.d.ts +11 -0
  40. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalBody.d.ts +7 -0
  41. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalBodyListItem.d.ts +4 -0
  42. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalFooter.d.ts +11 -0
  43. package/react-dist/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalHeader.d.ts +2 -0
  44. package/react-dist/components/DuffelAncillaries/seats/Amenity.d.ts +6 -0
  45. package/react-dist/components/DuffelAncillaries/seats/DeckSelect.d.ts +15 -0
  46. package/react-dist/components/DuffelAncillaries/seats/Element.d.ts +15 -0
  47. package/react-dist/components/DuffelAncillaries/seats/EmptyElement.d.ts +2 -0
  48. package/react-dist/components/DuffelAncillaries/seats/ExitElement.d.ts +6 -0
  49. package/react-dist/components/DuffelAncillaries/seats/Legend.d.ts +12 -0
  50. package/react-dist/components/DuffelAncillaries/seats/Row.d.ts +13 -0
  51. package/react-dist/components/DuffelAncillaries/seats/RowSection.d.ts +17 -0
  52. package/react-dist/components/DuffelAncillaries/seats/SeatElement.d.ts +13 -0
  53. package/react-dist/components/DuffelAncillaries/seats/SeatInfo.d.ts +7 -0
  54. package/react-dist/components/DuffelAncillaries/seats/SeatMap.d.ts +12 -0
  55. package/react-dist/components/DuffelAncillaries/seats/SeatMapUnavailable.d.ts +2 -0
  56. package/react-dist/components/DuffelAncillaries/seats/SeatSelectionCard.d.ts +13 -0
  57. package/react-dist/components/DuffelAncillaries/seats/SeatSelectionModal.d.ts +13 -0
  58. package/react-dist/components/DuffelAncillaries/seats/SeatSelectionModalBody.d.ts +4 -0
  59. package/react-dist/components/DuffelAncillaries/seats/SeatSelectionModalFooter.d.ts +16 -0
  60. package/react-dist/components/DuffelAncillaries/seats/SeatSelectionModalHeader.d.ts +10 -0
  61. package/react-dist/components/DuffelAncillaries/seats/SeatUnavailable.d.ts +5 -0
  62. package/react-dist/components/DuffelPayments/DuffelPayments.d.ts +11 -0
  63. package/react-dist/components/DuffelPayments/DuffelPaymentsCustomElement.d.ts +14 -0
  64. package/react-dist/components/shared/AnimatedLoaderEllipsis.d.ts +2 -0
  65. package/react-dist/components/shared/Button.d.ts +23 -0
  66. package/react-dist/components/shared/ErrorBoundary.d.ts +13 -0
  67. package/react-dist/components/shared/FetchOfferErrorState.d.ts +5 -0
  68. package/react-dist/components/shared/Icon.d.ts +44 -0
  69. package/react-dist/components/shared/IconButton.d.ts +16 -0
  70. package/react-dist/components/shared/Modal.d.ts +11 -0
  71. package/react-dist/components/shared/NonIdealState.d.ts +4 -0
  72. package/react-dist/components/shared/Stamp.d.ts +7 -0
  73. package/react-dist/components/shared/Tabs.d.ts +16 -0
  74. package/react-dist/custom-elements.d.ts +6 -0
  75. package/react-dist/custom-elements.js +37 -0
  76. package/react-dist/custom-elements.js.map +7 -0
  77. package/react-dist/index.d.ts +7 -0
  78. package/react-dist/index.js +37 -0
  79. package/react-dist/index.js.map +7 -0
  80. package/react-dist/lib/captureErrorInSentry.d.ts +1 -0
  81. package/react-dist/lib/compileCreateOrderPayload.d.ts +14 -0
  82. package/react-dist/lib/createPriceFormatters.d.ts +12 -0
  83. package/react-dist/lib/fetchFromDuffelAPI.d.ts +8 -0
  84. package/react-dist/lib/fetchFromFixtures.d.ts +4 -0
  85. package/react-dist/lib/formatAvailableServices.d.ts +12 -0
  86. package/react-dist/lib/formatDate.d.ts +2 -0
  87. package/react-dist/lib/formatSeatMaps.d.ts +4 -0
  88. package/react-dist/lib/getBaggageServiceDescription.d.ts +2 -0
  89. package/react-dist/lib/getCabinsForSegmentAndDeck.d.ts +2 -0
  90. package/react-dist/lib/getCurrencyForSeatMaps.d.ts +10 -0
  91. package/react-dist/lib/getCurrencyForServices.d.ts +11 -0
  92. package/react-dist/lib/getFirstSeatElementMatchingCriteria.d.ts +3 -0
  93. package/react-dist/lib/getPassengerBySegmentList.d.ts +6 -0
  94. package/react-dist/lib/getPassengerInitials.d.ts +1 -0
  95. package/react-dist/lib/getPassengerMapById.d.ts +3 -0
  96. package/react-dist/lib/getPassengerName.d.ts +3 -0
  97. package/react-dist/lib/getRowNumber.d.ts +2 -0
  98. package/react-dist/lib/getSegmentList.d.ts +2 -0
  99. package/react-dist/lib/getServicePriceMapById.d.ts +3 -0
  100. package/react-dist/lib/getSymbols.d.ts +2 -0
  101. package/react-dist/lib/getTotalAmountForServices.d.ts +6 -0
  102. package/react-dist/lib/getTotalQuantity.d.ts +2 -0
  103. package/react-dist/lib/hasService.d.ts +2 -0
  104. package/react-dist/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.d.ts +3 -0
  105. package/react-dist/lib/hasWings.d.ts +2 -0
  106. package/react-dist/lib/isBaggageService.d.ts +2 -0
  107. package/react-dist/lib/isCancelForAnyReasonService.d.ts +2 -0
  108. package/react-dist/lib/isFixtureOfferId.d.ts +2 -0
  109. package/react-dist/lib/isPayloadComplete.d.ts +2 -0
  110. package/react-dist/lib/isSeatElement.d.ts +2 -0
  111. package/react-dist/lib/logging.d.ts +46 -0
  112. package/react-dist/lib/moneyStringFormatter.d.ts +8 -0
  113. package/react-dist/lib/offerIsExpired.d.ts +2 -0
  114. package/react-dist/lib/retrieveOffer.d.ts +2 -0
  115. package/react-dist/lib/retrieveOfferFromDuffelAPI.d.ts +1 -0
  116. package/react-dist/lib/retrieveSeatMaps.d.ts +2 -0
  117. package/react-dist/lib/retrieveSeatMapsFromDuffelAPI.d.ts +1 -0
  118. package/react-dist/lib/setBodyScrollability.d.ts +1 -0
  119. package/react-dist/lib/validateProps.d.ts +7 -0
  120. package/react-dist/lib/withPlural.d.ts +1 -0
  121. package/react-dist/types/Aircraft.d.ts +14 -0
  122. package/react-dist/types/Airline.d.ts +14 -0
  123. package/react-dist/types/Airport.d.ts +44 -0
  124. package/react-dist/types/City.d.ts +18 -0
  125. package/react-dist/types/CreateOrderPayload.d.ts +72 -0
  126. package/react-dist/types/CurrencyConversion.d.ts +10 -0
  127. package/react-dist/types/DuffelAncillariesProps.d.ts +70 -0
  128. package/react-dist/types/Offer.d.ts +711 -0
  129. package/react-dist/types/Order.d.ts +8 -0
  130. package/react-dist/types/Place.d.ts +8 -0
  131. package/react-dist/types/SeatMap.d.ts +190 -0
  132. package/react-dist/types/index.d.ts +11 -0
  133. package/scripts/generate-fixture.ts +200 -0
  134. package/scripts/upload-to-cdn.sh +34 -0
  135. package/scripts.tsconfig.json +11 -0
  136. package/src/components/DuffelAncillaries/Card.tsx +126 -0
  137. package/src/components/DuffelAncillaries/Counter.tsx +40 -0
  138. package/src/components/DuffelAncillaries/DuffelAncillaries.tsx +344 -0
  139. package/src/components/DuffelAncillaries/DuffelAncillariesCustomElement.tsx +124 -0
  140. package/src/components/DuffelAncillaries/bags/BaggageSelectionCard.tsx +96 -0
  141. package/src/components/DuffelAncillaries/bags/BaggageSelectionController.tsx +88 -0
  142. package/src/components/DuffelAncillaries/bags/BaggageSelectionModal.tsx +81 -0
  143. package/src/components/DuffelAncillaries/bags/BaggageSelectionModalBody.tsx +60 -0
  144. package/src/components/DuffelAncillaries/bags/BaggageSelectionModalBodyPassenger.tsx +122 -0
  145. package/src/components/DuffelAncillaries/bags/BaggageSelectionModalFooter.tsx +81 -0
  146. package/src/components/DuffelAncillaries/bags/BaggageSelectionModalHeader.tsx +76 -0
  147. package/src/components/DuffelAncillaries/bags/IncludedBaggageBanner.tsx +51 -0
  148. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionCard.tsx +90 -0
  149. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModal.tsx +63 -0
  150. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalBody.tsx +56 -0
  151. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalBodyListItem.tsx +11 -0
  152. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalFooter.tsx +74 -0
  153. package/src/components/DuffelAncillaries/cancel_for_any_reason/CfarSelectionModalHeader.tsx +9 -0
  154. package/src/components/DuffelAncillaries/seats/Amenity.tsx +21 -0
  155. package/src/components/DuffelAncillaries/seats/DeckSelect.tsx +27 -0
  156. package/src/components/DuffelAncillaries/seats/Element.tsx +52 -0
  157. package/src/components/DuffelAncillaries/seats/EmptyElement.tsx +5 -0
  158. package/src/components/DuffelAncillaries/seats/ExitElement.tsx +17 -0
  159. package/src/components/DuffelAncillaries/seats/Legend.tsx +60 -0
  160. package/src/components/DuffelAncillaries/seats/Row.tsx +47 -0
  161. package/src/components/DuffelAncillaries/seats/RowSection.tsx +78 -0
  162. package/src/components/DuffelAncillaries/seats/SeatElement.tsx +120 -0
  163. package/src/components/DuffelAncillaries/seats/SeatInfo.tsx +32 -0
  164. package/src/components/DuffelAncillaries/seats/SeatMap.tsx +81 -0
  165. package/src/components/DuffelAncillaries/seats/SeatMapUnavailable.tsx +21 -0
  166. package/src/components/DuffelAncillaries/seats/SeatSelectionCard.tsx +103 -0
  167. package/src/components/DuffelAncillaries/seats/SeatSelectionModal.tsx +142 -0
  168. package/src/components/DuffelAncillaries/seats/SeatSelectionModalBody.tsx +13 -0
  169. package/src/components/DuffelAncillaries/seats/SeatSelectionModalFooter.tsx +82 -0
  170. package/src/components/DuffelAncillaries/seats/SeatSelectionModalHeader.tsx +87 -0
  171. package/src/components/DuffelAncillaries/seats/SeatUnavailable.tsx +14 -0
  172. package/src/components/DuffelPayments/DuffelPayments.tsx +218 -0
  173. package/src/components/DuffelPayments/DuffelPaymentsCustomElement.tsx +130 -0
  174. package/src/components/shared/AnimatedLoaderEllipsis.tsx +5 -0
  175. package/src/components/shared/Button.tsx +63 -0
  176. package/src/components/shared/ErrorBoundary.tsx +54 -0
  177. package/src/components/shared/FetchOfferErrorState.tsx +35 -0
  178. package/src/components/shared/Icon.tsx +152 -0
  179. package/src/components/shared/IconButton.tsx +42 -0
  180. package/src/components/shared/Modal.tsx +40 -0
  181. package/src/components/shared/NonIdealState.tsx +28 -0
  182. package/src/components/shared/Stamp.tsx +29 -0
  183. package/src/components/shared/Tabs.tsx +36 -0
  184. package/src/custom-elements.ts +13 -0
  185. package/src/examples/client-side/README.md +30 -0
  186. package/src/examples/client-side/index.html +57 -0
  187. package/src/examples/full-stack/README.md +34 -0
  188. package/src/examples/full-stack/index.html +48 -0
  189. package/src/examples/full-stack/server.mjs +158 -0
  190. package/src/examples/just-typescript/README.md +37 -0
  191. package/src/examples/just-typescript/package.json +16 -0
  192. package/src/examples/just-typescript/src/index.html +23 -0
  193. package/src/examples/just-typescript/src/index.ts +36 -0
  194. package/src/examples/just-typescript/yarn.lock +154 -0
  195. package/src/examples/payments-custom-element/README.md +17 -0
  196. package/src/examples/payments-custom-element/index.html +43 -0
  197. package/src/examples/payments-just-typescript/README.md +37 -0
  198. package/src/examples/payments-just-typescript/package.json +16 -0
  199. package/src/examples/payments-just-typescript/src/index.html +23 -0
  200. package/src/examples/payments-just-typescript/src/index.ts +18 -0
  201. package/src/examples/payments-just-typescript/yarn.lock +154 -0
  202. package/src/examples/react-app/README.md +37 -0
  203. package/src/examples/react-app/package.json +20 -0
  204. package/src/examples/react-app/src/index.html +19 -0
  205. package/src/examples/react-app/src/index.tsx +48 -0
  206. package/src/examples/react-app/yarn.lock +219 -0
  207. package/src/fixtures/offers/off_0000AUde3KwTztSRK1cznH.json +497 -0
  208. package/src/fixtures/offers/off_0000AVx4lUFFKW8PsPeQeQ.json +307 -0
  209. package/src/fixtures/offers/off_1.json +497 -0
  210. package/src/fixtures/passengers/mock_passengers.ts +26 -0
  211. package/src/fixtures/seat-maps/off_0000AUde3KwTztSRK1cznH.json +6852 -0
  212. package/src/fixtures/seat-maps/off_0000AVx4lUFFKW8PsPeQeQ.json +1 -0
  213. package/src/fixtures/seat-maps/off_1.json +6852 -0
  214. package/src/index.ts +7 -0
  215. package/src/lib/captureErrorInSentry.ts +42 -0
  216. package/src/lib/compileCreateOrderPayload.ts +63 -0
  217. package/src/lib/createPriceFormatters.ts +73 -0
  218. package/src/lib/fetchFromDuffelAPI.ts +54 -0
  219. package/src/lib/fetchFromFixtures.ts +18 -0
  220. package/src/lib/formatAvailableServices.ts +91 -0
  221. package/src/lib/formatDate.ts +20 -0
  222. package/src/lib/formatSeatMaps.ts +81 -0
  223. package/src/lib/getBaggageServiceDescription.ts +42 -0
  224. package/src/lib/getCabinsForSegmentAndDeck.ts +4 -0
  225. package/src/lib/getCurrencyForSeatMaps.ts +22 -0
  226. package/src/lib/getCurrencyForServices.ts +24 -0
  227. package/src/lib/getFirstSeatElementMatchingCriteria.ts +22 -0
  228. package/src/lib/getPassengerBySegmentList.ts +10 -0
  229. package/src/lib/getPassengerInitials.ts +6 -0
  230. package/src/lib/getPassengerMapById.ts +17 -0
  231. package/src/lib/getPassengerName.ts +37 -0
  232. package/src/lib/getRowNumber.ts +16 -0
  233. package/src/lib/getSegmentList.ts +7 -0
  234. package/src/lib/getServicePriceMapById.ts +20 -0
  235. package/src/lib/getSymbols.ts +22 -0
  236. package/src/lib/getTotalAmountForServices.ts +72 -0
  237. package/src/lib/getTotalQuantity.ts +5 -0
  238. package/src/lib/hasService.ts +24 -0
  239. package/src/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.ts +35 -0
  240. package/src/lib/hasWings.ts +8 -0
  241. package/src/lib/isBaggageService.ts +8 -0
  242. package/src/lib/isCancelForAnyReasonService.ts +9 -0
  243. package/src/lib/isFixtureOfferId.ts +4 -0
  244. package/src/lib/isPayloadComplete.ts +11 -0
  245. package/src/lib/isSeatElement.ts +10 -0
  246. package/src/lib/logging.ts +120 -0
  247. package/src/lib/moneyStringFormatter.ts +34 -0
  248. package/src/lib/offerIsExpired.ts +5 -0
  249. package/src/lib/retrieveOffer.ts +54 -0
  250. package/src/lib/retrieveOfferFromDuffelAPI.ts +13 -0
  251. package/src/lib/retrieveSeatMaps.ts +55 -0
  252. package/src/lib/retrieveSeatMapsFromDuffelAPI.ts +13 -0
  253. package/src/lib/setBodyScrollability.ts +7 -0
  254. package/src/lib/validateProps.ts +37 -0
  255. package/src/lib/withPlural.ts +8 -0
  256. package/src/stories/BaggageSelectionModalHeader.stories.tsx +21 -0
  257. package/src/stories/Button.stories.tsx +69 -0
  258. package/src/stories/DuffelAncillaries.stories.tsx +126 -0
  259. package/src/stories/DuffelPayments.stories.tsx +34 -0
  260. package/src/stories/Icon.stories.tsx +35 -0
  261. package/src/stories/IconButton.stories.tsx +25 -0
  262. package/src/styles/colors.css +22 -0
  263. package/src/styles/components/Amenity.css +23 -0
  264. package/src/styles/components/BaggageDisplay.css +25 -0
  265. package/src/styles/components/Button.css +161 -0
  266. package/src/styles/components/Card.css +52 -0
  267. package/src/styles/components/CfarSelectionModal.css +34 -0
  268. package/src/styles/components/Counter.css +18 -0
  269. package/src/styles/components/DuffelPayments.css +42 -0
  270. package/src/styles/components/IconButton.css +63 -0
  271. package/src/styles/components/Legend.css +58 -0
  272. package/src/styles/components/Loader.css +37 -0
  273. package/src/styles/components/LoadingState.css +81 -0
  274. package/src/styles/components/Modal.css +84 -0
  275. package/src/styles/components/PassengerSelect.css +93 -0
  276. package/src/styles/components/PassengersLayout.css +90 -0
  277. package/src/styles/components/Row.css +70 -0
  278. package/src/styles/components/Seat.css +57 -0
  279. package/src/styles/components/SeatInfo.css +61 -0
  280. package/src/styles/components/SeatMap.css +24 -0
  281. package/src/styles/components/SeatSelect.css +92 -0
  282. package/src/styles/components/Segment.css +17 -0
  283. package/src/styles/components/SelectionSegment.css +10 -0
  284. package/src/styles/components/Summary.css +70 -0
  285. package/src/styles/components/Tabs.css +49 -0
  286. package/src/styles/flex.css +5 -0
  287. package/src/styles/font-families.css +47 -0
  288. package/src/styles/global.css +51 -0
  289. package/src/styles/margin.css +3 -0
  290. package/src/styles/spacing.css +18 -0
  291. package/src/styles/transitions.css +3 -0
  292. package/src/styles/typography.css +13 -0
  293. package/src/tests/components/DuffelAncillaries.test.tsx +342 -0
  294. package/src/tests/lib/createPriceFormatters.test.tsx +152 -0
  295. package/src/tests/lib/formatAvailableServices.test.tsx +79 -0
  296. package/src/tests/lib/formatSeatMaps.test.tsx +49 -0
  297. package/src/tests/lib/getCurrencyForServices.test.tsx +44 -0
  298. package/src/tests/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.test.ts +86 -0
  299. package/src/tests/lib/logging.test.tsx +32 -0
  300. package/src/tests/lib/moneyStringFormatter.test.tsx +12 -0
  301. package/src/tests/lib/validateProps.test.tsx +57 -0
  302. package/src/types/Aircraft.ts +16 -0
  303. package/src/types/Airline.ts +16 -0
  304. package/src/types/Airport.ts +54 -0
  305. package/src/types/City.ts +21 -0
  306. package/src/types/CreateOrderPayload.ts +99 -0
  307. package/src/types/CurrencyConversion.ts +10 -0
  308. package/src/types/DuffelAncillariesProps.ts +108 -0
  309. package/src/types/Offer.ts +851 -0
  310. package/src/types/Order.ts +6 -0
  311. package/src/types/Place.ts +6 -0
  312. package/src/types/SeatMap.ts +231 -0
  313. package/src/types/index.ts +11 -0
  314. package/tsconfig.json +52 -0
  315. package/LICENSE +0 -21
  316. package/dist/AdditionalBaggage.esm.js +0 -1
  317. package/dist/AdditionalBaggage.js +0 -1
  318. package/dist/AdditionalBaggage.min.css +0 -408
  319. package/dist/AdditionalBaggage.umd.min.js +0 -2
  320. package/dist/AdditionalBaggage.umd.min.js.LICENSE.txt +0 -60
  321. package/dist/AdditionalBaggageSelection.esm.js +0 -1
  322. package/dist/AdditionalBaggageSelection.js +0 -1
  323. package/dist/AdditionalBaggageSelection.min.css +0 -744
  324. package/dist/AdditionalBaggageSelection.umd.min.js +0 -2
  325. package/dist/AdditionalBaggageSelection.umd.min.js.LICENSE.txt +0 -93
  326. package/dist/CardPayment.esm.js +0 -2
  327. package/dist/CardPayment.esm.js.LICENSE.txt +0 -6
  328. package/dist/CardPayment.js +0 -2
  329. package/dist/CardPayment.js.LICENSE.txt +0 -6
  330. package/dist/CardPayment.min.css +0 -233
  331. package/dist/CardPayment.umd.min.js +0 -2
  332. package/dist/CardPayment.umd.min.js.LICENSE.txt +0 -61
  333. package/dist/SeatSelection.esm.js +0 -1
  334. package/dist/SeatSelection.js +0 -1
  335. package/dist/SeatSelection.min.css +0 -1127
  336. package/dist/SeatSelection.umd.min.js +0 -2
  337. package/dist/SeatSelection.umd.min.js.LICENSE.txt +0 -60
  338. package/dist/duffel-components.d.ts +0 -1614
  339. package/dist/duffel-components.esm.js +0 -2
  340. package/dist/duffel-components.esm.js.LICENSE.txt +0 -6
  341. package/dist/duffel-components.js +0 -2
  342. package/dist/duffel-components.js.LICENSE.txt +0 -6
  343. package/dist/duffel-components.min.css +0 -1280
  344. package/dist/duffel-components.umd.min.js +0 -2
  345. package/dist/duffel-components.umd.min.js.LICENSE.txt +0 -102
@@ -0,0 +1,74 @@
1
+ import { Button } from "@components/shared/Button";
2
+ import { Icon } from "@components/shared/Icon";
3
+ import { moneyStringFormatter } from "@lib/moneyStringFormatter";
4
+ import React from "react";
5
+ import { CreateOrderPayloadServices } from "../../../types/CreateOrderPayload";
6
+ import { OfferAvailableServiceCancelForAnyReason } from "../../../types/Offer";
7
+
8
+ export interface CfarSelectionModalFooterProps {
9
+ service: OfferAvailableServiceCancelForAnyReason;
10
+ selectedServices: CreateOrderPayloadServices;
11
+ onAddCfarService: () => void;
12
+ onRemoveCfarService: () => void;
13
+ onClose: () => void;
14
+ }
15
+
16
+ export const CfarSelectionModalFooter: React.FC<
17
+ CfarSelectionModalFooterProps
18
+ > = ({
19
+ service,
20
+ selectedServices,
21
+ onAddCfarService,
22
+ onRemoveCfarService,
23
+ onClose,
24
+ }) => {
25
+ const serviceIncluded = selectedServices.some(({ id }) => id == service.id);
26
+ const formattedPrice = moneyStringFormatter(service.total_currency)(
27
+ +service.total_amount
28
+ );
29
+
30
+ return (
31
+ <div className="cfar-modal-footer">
32
+ <Button
33
+ size={48}
34
+ variant={serviceIncluded ? "destructive" : "outlined"}
35
+ onClick={serviceIncluded ? onRemoveCfarService : onClose}
36
+ >
37
+ {serviceIncluded ? "Remove protection" : "Don’t protect trip"}
38
+ </Button>
39
+
40
+ {!serviceIncluded && (
41
+ <Button
42
+ size={48}
43
+ data-testid="confirm-selection-for-cfar"
44
+ onClick={onAddCfarService}
45
+ >
46
+ Add protection for {formattedPrice}
47
+ </Button>
48
+ )}
49
+
50
+ {serviceIncluded && <ProtectedTripBanner />}
51
+ </div>
52
+ );
53
+ };
54
+
55
+ const ProtectedTripBanner: React.FC = () => (
56
+ <div
57
+ style={{
58
+ display: "flex",
59
+ alignItems: "center",
60
+ justifyContent: "center",
61
+ columnGap: "8px",
62
+ backgroundColor: "var(--GREY-100)",
63
+ padding: "var(--space-12)",
64
+ borderRadius: "var(--BUTTON-RADIUS)",
65
+ }}
66
+ >
67
+ <Icon
68
+ size={20}
69
+ name="shield_with_moon"
70
+ style={{ fill: "rgb(var(--ACCENT))" }}
71
+ />
72
+ Your trip is protected
73
+ </div>
74
+ );
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+
3
+ export const CfarSelectionModalHeader: React.FC = () => (
4
+ <div style={{ padding: "24px 24px 16px" }}>
5
+ <h2 className="h3--semibold" style={{ marginBlock: 0 }}>
6
+ Cancel for any reason
7
+ </h2>
8
+ </div>
9
+ );
@@ -0,0 +1,21 @@
1
+ import { Icon, IconName } from "@components/shared/Icon";
2
+ import classNames from "classnames";
3
+ import * as React from "react";
4
+ import { SeatMapCabinRowSectionElementAmenity } from "../../../types/SeatMap";
5
+
6
+ const amenitiesWithoutWrapper = ["bassinet", "exit_row"];
7
+
8
+ export interface AmenityProps {
9
+ type: SeatMapCabinRowSectionElementAmenity;
10
+ }
11
+
12
+ export const Amenity: React.FC<AmenityProps> = ({ type }) => (
13
+ <div
14
+ className={classNames("map-element map-element--amenity", {
15
+ "map-element--wrapped": !amenitiesWithoutWrapper.includes(type),
16
+ })}
17
+ aria-label={type.toString()}
18
+ >
19
+ <Icon name={type as IconName} size={16} />
20
+ </div>
21
+ );
@@ -0,0 +1,27 @@
1
+ import { Tabs } from "@components/shared/Tabs";
2
+ import * as React from "react";
3
+
4
+ export interface DeckSelectProps {
5
+ /**
6
+ * The currently selected deck number
7
+ */
8
+ value: number;
9
+ /**
10
+ * What to do when the user selects a deck
11
+ */
12
+ setValue: (value: number) => void;
13
+ }
14
+
15
+ /**
16
+ * The deck selection component for the seat map.
17
+ */
18
+ export const DeckSelect: React.FC<DeckSelectProps> = ({ value, setValue }) => {
19
+ const options = ["Lower deck", "Upper deck"];
20
+ return (
21
+ <Tabs
22
+ options={options}
23
+ value={options[value]}
24
+ onChange={(item) => setValue(options.indexOf(item))}
25
+ />
26
+ );
27
+ };
@@ -0,0 +1,52 @@
1
+ import { isSeatElement } from "@lib/isSeatElement";
2
+ import * as React from "react";
3
+ import { CreateOrderPayloadSeatService } from "../../../types/CreateOrderPayload";
4
+ import { SeatMapCabinRowSectionElement } from "../../../types/SeatMap";
5
+ import { Amenity } from "./Amenity";
6
+ import { EmptyElement } from "./EmptyElement";
7
+ import { ExitElement } from "./ExitElement";
8
+ import { SeatElement } from "./SeatElement";
9
+
10
+ interface ElementProps {
11
+ sectionIndex: number;
12
+ elementIndex: number;
13
+ element: SeatMapCabinRowSectionElement;
14
+ selectedServicesMap: Record<string, CreateOrderPayloadSeatService>;
15
+ onSeatToggled: (seatService: CreateOrderPayloadSeatService) => void;
16
+ currentPassengerId: string;
17
+ currentSegmentId: string;
18
+ currentPassengerName: string;
19
+ }
20
+
21
+ export const Element: React.FC<ElementProps> = ({
22
+ element,
23
+ elementIndex,
24
+ sectionIndex,
25
+ onSeatToggled,
26
+ selectedServicesMap,
27
+ currentPassengerId,
28
+ currentSegmentId,
29
+ currentPassengerName,
30
+ }) => {
31
+ return (
32
+ <>
33
+ {isSeatElement(element) ? (
34
+ <SeatElement
35
+ currentSegmentId={currentSegmentId}
36
+ currentPassengerId={currentPassengerId}
37
+ currentPassengerName={currentPassengerName}
38
+ selectedServicesMap={selectedServicesMap}
39
+ key={elementIndex}
40
+ element={element}
41
+ onSeatToggled={onSeatToggled}
42
+ />
43
+ ) : element.type === "empty" ? (
44
+ <EmptyElement key={elementIndex} />
45
+ ) : element.type === "exit_row" ? (
46
+ <ExitElement key={elementIndex} isRight={sectionIndex > 0} />
47
+ ) : (
48
+ <Amenity key={elementIndex} type={element.type} />
49
+ )}
50
+ </>
51
+ );
52
+ };
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+
3
+ export const EmptyElement: React.FC = () => (
4
+ <div className="map-element map-element--empty" />
5
+ );
@@ -0,0 +1,17 @@
1
+ import { Icon } from "@components/shared/Icon";
2
+ import classNames from "classnames";
3
+ import * as React from "react";
4
+
5
+ interface ExitElementProps {
6
+ isRight: boolean;
7
+ }
8
+
9
+ export const ExitElement: React.FC<ExitElementProps> = ({ isRight }) => (
10
+ <div
11
+ className={classNames("map-element map-element--exit", {
12
+ "map-element--exit--right": isRight,
13
+ })}
14
+ >
15
+ {isRight ? <Icon name="exit_row_right" /> : <Icon name="exit_row" />}
16
+ </div>
17
+ );
@@ -0,0 +1,60 @@
1
+ import { Icon, IconName } from "@components/shared/Icon";
2
+ import * as React from "react";
3
+ import { SeatMapCabinRowSectionElementAmenity } from "../../../types/SeatMap";
4
+
5
+ export interface LegendProps {
6
+ /**
7
+ * The set of additional symbols to display
8
+ */
9
+ symbols: Set<SeatMapCabinRowSectionElementAmenity>;
10
+ }
11
+
12
+ /**
13
+ * The legend for the seat map.
14
+ */
15
+ export const Legend: React.FC<LegendProps> = ({ symbols }) => (
16
+ <div className="seat-map__legend">
17
+ <span className="seat-map__legend-item">
18
+ <span
19
+ className="seat-map__legend-seat seat-map__legend-seat--fee-payable"
20
+ aria-label="Additional cost for seat"
21
+ >
22
+ <Icon
23
+ name="seat_paid_indicator"
24
+ className="seat-map__legend-seat--fee-payable-indicator"
25
+ size={12}
26
+ />
27
+ </span>
28
+ Additional Cost
29
+ </span>
30
+ <span className="seat-map__legend-item">
31
+ <span
32
+ className="seat-map__legend-seat seat-map__legend-seat--included"
33
+ aria-label="Included seat"
34
+ />
35
+ Included
36
+ </span>
37
+ <span className="seat-map__legend-item">
38
+ <span
39
+ className="seat-map__legend-seat seat-map__legend-seat--selected"
40
+ aria-label="Selected seat"
41
+ />
42
+ Selected
43
+ </span>
44
+ <span className="seat-map__legend-item">
45
+ <span className="seat-map__legend-seat" aria-label="Unavailable seat">
46
+ <Icon name="close" size={14} />
47
+ </span>
48
+ Unavailable
49
+ </span>
50
+ {[...symbols].map((symbol) => (
51
+ <span
52
+ key={symbol}
53
+ className="seat-map__legend-item seat-map__legend-item--symbol"
54
+ >
55
+ <Icon name={symbol as IconName} size={20} />
56
+ {symbol.split("_")[0]}
57
+ </span>
58
+ ))}
59
+ </div>
60
+ );
@@ -0,0 +1,47 @@
1
+ import { getRowNumber } from "@lib/getRowNumber";
2
+ import * as React from "react";
3
+ import { CreateOrderPayloadSeatService } from "../../../types/CreateOrderPayload";
4
+ import { SeatMapCabinRow } from "../../../types/SeatMap";
5
+ import { RowSection } from "./RowSection";
6
+
7
+ export interface RowProps {
8
+ row: SeatMapCabinRow;
9
+ hasWings: boolean;
10
+ selectedServicesMap: Record<string, CreateOrderPayloadSeatService>;
11
+ onSeatToggled: (seatService: CreateOrderPayloadSeatService) => void;
12
+ currentPassengerId: string;
13
+ currentPassengerName: string;
14
+ currentSegmentId: string;
15
+ }
16
+
17
+ export const Row: React.FC<RowProps> = ({
18
+ row,
19
+ hasWings,
20
+ onSeatToggled,
21
+ selectedServicesMap,
22
+ currentPassengerId,
23
+ currentPassengerName,
24
+ currentSegmentId,
25
+ }) => {
26
+ const rowNumber = getRowNumber(row);
27
+
28
+ return (
29
+ <>
30
+ {row.sections.map((section, sectionIndex) => (
31
+ <RowSection
32
+ key={sectionIndex}
33
+ row={row}
34
+ rowNumber={rowNumber}
35
+ hasWings={hasWings}
36
+ section={section}
37
+ sectionIndex={sectionIndex}
38
+ selectedServicesMap={selectedServicesMap}
39
+ onSeatToggled={onSeatToggled}
40
+ currentPassengerId={currentPassengerId}
41
+ currentPassengerName={currentPassengerName}
42
+ currentSegmentId={currentSegmentId}
43
+ />
44
+ ))}
45
+ </>
46
+ );
47
+ };
@@ -0,0 +1,78 @@
1
+ import classNames from "classnames";
2
+ import * as React from "react";
3
+ import { CreateOrderPayloadSeatService } from "../../../types/CreateOrderPayload";
4
+ import {
5
+ SeatMapCabinRow,
6
+ SeatMapCabinRowSection,
7
+ } from "../../../types/SeatMap";
8
+ import { Element } from "./Element";
9
+ import { EmptyElement } from "./EmptyElement";
10
+
11
+ interface RowSectionProps {
12
+ row: SeatMapCabinRow;
13
+ rowNumber: string | null;
14
+ hasWings: boolean;
15
+ section: SeatMapCabinRowSection;
16
+ sectionIndex: number;
17
+ selectedServicesMap: Record<string, CreateOrderPayloadSeatService>;
18
+ onSeatToggled: (seatService: CreateOrderPayloadSeatService) => void;
19
+ currentPassengerId: string;
20
+ currentPassengerName: string;
21
+ currentSegmentId: string;
22
+ }
23
+
24
+ export const RowSection: React.FC<RowSectionProps> = ({
25
+ row,
26
+ rowNumber,
27
+ hasWings,
28
+ section,
29
+ sectionIndex,
30
+ onSeatToggled,
31
+ selectedServicesMap,
32
+ currentPassengerId,
33
+ currentPassengerName,
34
+ currentSegmentId,
35
+ }) => {
36
+ const rowLength = Object.keys(row.sections).length;
37
+ const isOneSectionRow = rowLength === 1;
38
+
39
+ return (
40
+ <React.Fragment key={sectionIndex}>
41
+ <div
42
+ className={classNames("map-section", {
43
+ "map-section--left": sectionIndex === 0,
44
+ "map-section--right": !isOneSectionRow
45
+ ? sectionIndex === rowLength - 1
46
+ : false,
47
+ "map-section--wing": hasWings,
48
+ })}
49
+ >
50
+ {section.elements.length > 0 ? (
51
+ section.elements.map((element, elementIndex) => (
52
+ <React.Fragment key={elementIndex}>
53
+ <Element
54
+ sectionIndex={sectionIndex}
55
+ elementIndex={elementIndex}
56
+ element={element}
57
+ selectedServicesMap={selectedServicesMap}
58
+ onSeatToggled={onSeatToggled}
59
+ currentPassengerId={currentPassengerId}
60
+ currentSegmentId={currentSegmentId}
61
+ currentPassengerName={currentPassengerName}
62
+ />
63
+ </React.Fragment>
64
+ ))
65
+ ) : (
66
+ <EmptyElement />
67
+ )}
68
+ </div>
69
+ {(sectionIndex < rowLength - 1 ||
70
+ (isOneSectionRow && sectionIndex < rowLength)) && (
71
+ <span className="map-section__aisle">{rowNumber}</span>
72
+ )}
73
+ {isOneSectionRow && sectionIndex === row.sections.length - 1 && (
74
+ <EmptyElement />
75
+ )}
76
+ </React.Fragment>
77
+ );
78
+ };
@@ -0,0 +1,120 @@
1
+ import { Icon } from "@components/shared/Icon";
2
+ import { getPassengerInitials } from "@lib/getPassengerInitials";
3
+ import { moneyStringFormatter } from "@lib/moneyStringFormatter";
4
+ import classNames from "classnames";
5
+ import * as React from "react";
6
+ import { CreateOrderPayloadSeatService } from "../../../types/CreateOrderPayload";
7
+ import { SeatMapCabinRowSectionElementSeat } from "../../../types/SeatMap";
8
+ import { SeatInfo } from "./SeatInfo";
9
+ import { SeatUnavailable } from "./SeatUnavailable";
10
+
11
+ interface SeatElementProps {
12
+ element: SeatMapCabinRowSectionElementSeat;
13
+ currentSegmentId: string;
14
+ currentPassengerId: string;
15
+ currentPassengerName: string;
16
+ onSeatToggled: (seatService: CreateOrderPayloadSeatService) => void;
17
+ selectedServicesMap: Record<string, CreateOrderPayloadSeatService>;
18
+ }
19
+
20
+ export const SeatElement: React.FC<SeatElementProps> = ({
21
+ element,
22
+ currentPassengerId,
23
+ currentSegmentId,
24
+ currentPassengerName,
25
+ onSeatToggled,
26
+ selectedServicesMap,
27
+ }) => {
28
+ const seatServiceFromElement = element.available_services.find(
29
+ (service) => service.passenger_id === currentPassengerId
30
+ );
31
+ if (!seatServiceFromElement) return <SeatUnavailable seat={element} />;
32
+
33
+ const selectedServiceFromMap = Object.values(selectedServicesMap).find(
34
+ (service) =>
35
+ service.serviceInformation?.designator === element.designator &&
36
+ service.serviceInformation?.segmentId === currentSegmentId
37
+ );
38
+
39
+ const isSeatSelected = selectedServiceFromMap != undefined;
40
+
41
+ const seatLabel = isSeatSelected
42
+ ? getPassengerInitials(
43
+ selectedServiceFromMap.serviceInformation?.passengerName
44
+ )
45
+ : element.designator.charAt(element.designator.length - 1);
46
+
47
+ const isFeePayable =
48
+ !isNaN(+seatServiceFromElement?.total_amount) &&
49
+ +seatServiceFromElement?.total_amount !== 0;
50
+
51
+ const isSeatSelectionAvaiable =
52
+ !isSeatSelected &&
53
+ seatServiceFromElement.passenger_id === currentPassengerId;
54
+
55
+ const isActionable =
56
+ !isSeatSelected ||
57
+ (isSeatSelected &&
58
+ currentSegmentId ===
59
+ selectedServiceFromMap.serviceInformation?.segmentId &&
60
+ currentPassengerId ===
61
+ selectedServiceFromMap.serviceInformation?.passengerId);
62
+
63
+ const seatClassName = classNames("map-element", "map-element__seat", {
64
+ "map-element--available": isSeatSelectionAvaiable,
65
+ "map-element--selected": isSeatSelected,
66
+ "map-element--actionable": isActionable,
67
+ });
68
+
69
+ const priceLabel = moneyStringFormatter(
70
+ seatServiceFromElement.total_currency
71
+ )(+seatServiceFromElement.total_amount);
72
+
73
+ const isSeatInfoDisplayed =
74
+ isSeatSelected &&
75
+ currentSegmentId === selectedServiceFromMap.serviceInformation?.segmentId &&
76
+ currentPassengerId ===
77
+ selectedServiceFromMap.serviceInformation?.passengerId;
78
+
79
+ return (
80
+ <>
81
+ <button
82
+ data-testid={`seat-${element.designator}`}
83
+ id={element.designator}
84
+ className={seatClassName}
85
+ onClick={() => {
86
+ if (!isActionable) return;
87
+ onSeatToggled({
88
+ quantity: isSeatSelected ? 0 : 1,
89
+ id: seatServiceFromElement.id,
90
+ serviceInformation: {
91
+ type: "seat",
92
+ segmentId: currentSegmentId,
93
+ passengerId: currentPassengerId,
94
+ passengerName: currentPassengerName,
95
+ designator: element.designator,
96
+ disclosures: element.disclosures,
97
+ total_amount: seatServiceFromElement.total_amount,
98
+ total_currency: seatServiceFromElement.total_currency,
99
+ },
100
+ });
101
+ }}
102
+ aria-label={`${element.designator} ${
103
+ element.name || "Seat"
104
+ } ${priceLabel}`}
105
+ >
106
+ {isFeePayable && (
107
+ <Icon
108
+ name="seat_paid_indicator"
109
+ className="map-element--fee-payable"
110
+ size={16}
111
+ />
112
+ )}
113
+ {seatLabel}
114
+ </button>
115
+ {isSeatInfoDisplayed && (
116
+ <SeatInfo seat={element} service={seatServiceFromElement} />
117
+ )}
118
+ </>
119
+ );
120
+ };
@@ -0,0 +1,32 @@
1
+ import { moneyStringFormatter } from "@lib/moneyStringFormatter";
2
+ import * as React from "react";
3
+ import {
4
+ SeatMapCabinRowSectionAvailableService,
5
+ SeatMapCabinRowSectionElementSeat,
6
+ } from "../../../types/SeatMap";
7
+
8
+ export interface SeatInfoProps {
9
+ seat: SeatMapCabinRowSectionElementSeat | null;
10
+ service: SeatMapCabinRowSectionAvailableService | undefined;
11
+ }
12
+
13
+ export const SeatInfo: React.FC<SeatInfoProps> = ({ seat, service }) => {
14
+ const price = service
15
+ ? moneyStringFormatter(service.total_currency)(+service.total_amount)
16
+ : "";
17
+
18
+ return (
19
+ <div className="seat-info">
20
+ <div className="seat-info__details">
21
+ <strong>{seat?.designator}</strong>
22
+ <span>{seat?.name || "Seat"} </span>
23
+ <strong>{price}</strong>
24
+ </div>
25
+ {seat?.disclosures.map((disclosure, index) => (
26
+ <div key={index} className="seat-info__disclosure">
27
+ {disclosure}
28
+ </div>
29
+ ))}
30
+ </div>
31
+ );
32
+ };
@@ -0,0 +1,81 @@
1
+ import { getCabinsForSegmentAndDeck } from "@lib/getCabinsForSegmentAndDeck";
2
+ import { getSymbols } from "@lib/getSymbols";
3
+ import { hasWings } from "@lib/hasWings";
4
+ import classNames from "classnames";
5
+ import * as React from "react";
6
+ import { CreateOrderPayloadSeatService } from "../../../types/CreateOrderPayload";
7
+ import { SeatMap as SeatMapType } from "../../../types/SeatMap";
8
+ import { DeckSelect } from "./DeckSelect";
9
+ import { Legend } from "./Legend";
10
+ import { Row } from "./Row";
11
+ import { SeatMapUnavailable } from "./SeatMapUnavailable";
12
+
13
+ export interface SeatMapProps {
14
+ seatMap: SeatMapType;
15
+ selectedServicesMap: Record<string, CreateOrderPayloadSeatService>;
16
+ onSeatToggled: (seatService: CreateOrderPayloadSeatService) => void;
17
+ currentPassengerId: string;
18
+ currentPassengerName: string;
19
+ currentSegmentId: string;
20
+ }
21
+
22
+ export const SeatMap: React.FC<SeatMapProps> = ({
23
+ seatMap,
24
+ onSeatToggled,
25
+ selectedServicesMap,
26
+ currentPassengerId,
27
+ currentPassengerName,
28
+ currentSegmentId,
29
+ }) => {
30
+ const [selectedDeck, setSelectedDeck] = React.useState(0);
31
+
32
+ const cabins = getCabinsForSegmentAndDeck(selectedDeck, seatMap);
33
+ const hasMultipleDecks = cabins.length !== seatMap.cabins.length;
34
+ const anyHasWings = seatMap.cabins.some((cabin) => cabin.wings);
35
+
36
+ if (!cabins || !cabins.length) {
37
+ return <SeatMapUnavailable />;
38
+ }
39
+
40
+ const symbols = getSymbols(cabins);
41
+
42
+ return (
43
+ <div
44
+ className={classNames("seat-map", {
45
+ "seat-map--wings": anyHasWings,
46
+ })}
47
+ >
48
+ {hasMultipleDecks && (
49
+ <DeckSelect
50
+ value={selectedDeck}
51
+ setValue={(value) => {
52
+ setSelectedDeck(value);
53
+ }}
54
+ />
55
+ )}
56
+ <div className="seat-map__legend-container">
57
+ <Legend symbols={symbols} />
58
+ </div>
59
+ {cabins.map((cabin, cabinIndex) => (
60
+ <div
61
+ key={`cabin-${cabinIndex}`}
62
+ className="seat-map__map-container"
63
+ style={{ "--CABIN-AISLES": cabin.aisles } as React.CSSProperties}
64
+ >
65
+ {cabin.rows.map((row, rowIndex) => (
66
+ <Row
67
+ key={rowIndex}
68
+ row={row}
69
+ hasWings={hasWings(cabin, rowIndex)}
70
+ onSeatToggled={onSeatToggled}
71
+ selectedServicesMap={selectedServicesMap}
72
+ currentPassengerId={currentPassengerId}
73
+ currentPassengerName={currentPassengerName}
74
+ currentSegmentId={currentSegmentId}
75
+ />
76
+ ))}
77
+ </div>
78
+ ))}
79
+ </div>
80
+ );
81
+ };
@@ -0,0 +1,21 @@
1
+ import { NonIdealState } from "@components/shared/NonIdealState";
2
+ import * as React from "react";
3
+
4
+ export const SeatMapUnavailable: React.FC = () => (
5
+ <NonIdealState>
6
+ <p style={{ marginBlock: "0" }} className="p1--semibold">
7
+ Seat selection unavailable
8
+ </p>
9
+ <p
10
+ className="p1--regular"
11
+ style={{
12
+ color: "var(--GREY-600)",
13
+ marginBlock: "12px",
14
+ textAlign: "center",
15
+ }}
16
+ >
17
+ Unfortunately seat selection is not available for this flight. A seat will
18
+ be allocated by the airline.
19
+ </p>
20
+ </NonIdealState>
21
+ );