@salesforce/retail-react-app 1.0.0-preview.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 (425) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.js +25 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc.yaml +7 -0
  5. package/CHANGELOG.md +173 -0
  6. package/LICENSE +14 -0
  7. package/README.md +48 -0
  8. package/app/assets/svg/account.svg +3 -0
  9. package/app/assets/svg/alert.svg +3 -0
  10. package/app/assets/svg/basket.svg +3 -0
  11. package/app/assets/svg/brand-logo.svg +10 -0
  12. package/app/assets/svg/cc-amex.svg +7 -0
  13. package/app/assets/svg/cc-cvv.svg +8 -0
  14. package/app/assets/svg/cc-discover.svg +14 -0
  15. package/app/assets/svg/cc-mastercard.svg +8 -0
  16. package/app/assets/svg/cc-visa.svg +11 -0
  17. package/app/assets/svg/check-circle.svg +3 -0
  18. package/app/assets/svg/check.svg +3 -0
  19. package/app/assets/svg/chevron-down.svg +3 -0
  20. package/app/assets/svg/chevron-left.svg +3 -0
  21. package/app/assets/svg/chevron-right.svg +3 -0
  22. package/app/assets/svg/chevron-up.svg +3 -0
  23. package/app/assets/svg/close.svg +3 -0
  24. package/app/assets/svg/dashboard.svg +4 -0
  25. package/app/assets/svg/figma-logo.svg +14 -0
  26. package/app/assets/svg/file.svg +3 -0
  27. package/app/assets/svg/filter.svg +3 -0
  28. package/app/assets/svg/flag-ca.svg +5 -0
  29. package/app/assets/svg/flag-cn.svg +19 -0
  30. package/app/assets/svg/flag-fr.svg +19 -0
  31. package/app/assets/svg/flag-gb.svg +16 -0
  32. package/app/assets/svg/flag-it.svg +29 -0
  33. package/app/assets/svg/flag-jp.svg +10 -0
  34. package/app/assets/svg/flag-us.svg +7 -0
  35. package/app/assets/svg/github-logo.svg +40 -0
  36. package/app/assets/svg/hamburger.svg +8 -0
  37. package/app/assets/svg/heart-solid.svg +7 -0
  38. package/app/assets/svg/heart.svg +3 -0
  39. package/app/assets/svg/info.svg +3 -0
  40. package/app/assets/svg/like.svg +4 -0
  41. package/app/assets/svg/location.svg +3 -0
  42. package/app/assets/svg/lock.svg +3 -0
  43. package/app/assets/svg/paypal.svg +19 -0
  44. package/app/assets/svg/plug.svg +3 -0
  45. package/app/assets/svg/plus.svg +3 -0
  46. package/app/assets/svg/receipt.svg +3 -0
  47. package/app/assets/svg/search.svg +8 -0
  48. package/app/assets/svg/signout.svg +3 -0
  49. package/app/assets/svg/social-facebook.svg +3 -0
  50. package/app/assets/svg/social-instagram.svg +3 -0
  51. package/app/assets/svg/social-pinterest.svg +4 -0
  52. package/app/assets/svg/social-twitter.svg +3 -0
  53. package/app/assets/svg/social-youtube.svg +3 -0
  54. package/app/assets/svg/user.svg +3 -0
  55. package/app/assets/svg/visibility-off.svg +5 -0
  56. package/app/assets/svg/visibility.svg +3 -0
  57. package/app/components/_app/index.jsx +401 -0
  58. package/app/components/_app/index.test.js +85 -0
  59. package/app/components/_app/partials/above-header.jsx +10 -0
  60. package/app/components/_app-config/index.jsx +125 -0
  61. package/app/components/_app-config/index.test.js +77 -0
  62. package/app/components/_error/index.jsx +142 -0
  63. package/app/components/_error/index.test.js +25 -0
  64. package/app/components/action-card/index.jsx +75 -0
  65. package/app/components/address-display/index.jsx +30 -0
  66. package/app/components/basic-tile/index.jsx +65 -0
  67. package/app/components/basic-tile/index.test.js +23 -0
  68. package/app/components/breadcrumb/index.jsx +67 -0
  69. package/app/components/breadcrumb/index.test.js +30 -0
  70. package/app/components/confirmation-modal/index.jsx +111 -0
  71. package/app/components/confirmation-modal/index.test.js +98 -0
  72. package/app/components/drawer-menu/index.jsx +405 -0
  73. package/app/components/drawer-menu/index.test.js +33 -0
  74. package/app/components/dynamic-image/index.jsx +56 -0
  75. package/app/components/field/index.jsx +161 -0
  76. package/app/components/footer/index.jsx +269 -0
  77. package/app/components/footer/index.test.js +22 -0
  78. package/app/components/forms/address-fields.jsx +49 -0
  79. package/app/components/forms/credit-card-fields.jsx +149 -0
  80. package/app/components/forms/form-action-buttons.jsx +55 -0
  81. package/app/components/forms/login-fields.jsx +31 -0
  82. package/app/components/forms/password-requirements.jsx +99 -0
  83. package/app/components/forms/post-checkout-registration-fields.jsx +43 -0
  84. package/app/components/forms/profile-fields.jsx +36 -0
  85. package/app/components/forms/promo-code-fields.jsx +43 -0
  86. package/app/components/forms/registration-fields.jsx +42 -0
  87. package/app/components/forms/reset-password-fields.jsx +31 -0
  88. package/app/components/forms/state-province-options.jsx +75 -0
  89. package/app/components/forms/update-password-fields.jsx +49 -0
  90. package/app/components/forms/useAddressFields.jsx +196 -0
  91. package/app/components/forms/useCreditCardFields.jsx +146 -0
  92. package/app/components/forms/useLoginFields.jsx +52 -0
  93. package/app/components/forms/useProfileFields.jsx +95 -0
  94. package/app/components/forms/usePromoCodeFields.jsx +39 -0
  95. package/app/components/forms/useRegistrationFields.jsx +136 -0
  96. package/app/components/forms/useResetPasswordFields.jsx +40 -0
  97. package/app/components/forms/useUpdatePasswordFields.jsx +89 -0
  98. package/app/components/header/index.jsx +290 -0
  99. package/app/components/header/index.test.js +217 -0
  100. package/app/components/hero/index.jsx +84 -0
  101. package/app/components/hero/index.test.js +40 -0
  102. package/app/components/icons/index.jsx +158 -0
  103. package/app/components/icons/index.test.js +20 -0
  104. package/app/components/image-gallery/index.jsx +176 -0
  105. package/app/components/image-gallery/index.test.js +485 -0
  106. package/app/components/item-variant/index.jsx +33 -0
  107. package/app/components/item-variant/item-attributes.jsx +107 -0
  108. package/app/components/item-variant/item-image.jsx +73 -0
  109. package/app/components/item-variant/item-name.jsx +28 -0
  110. package/app/components/item-variant/item-price.jsx +117 -0
  111. package/app/components/link/index.jsx +32 -0
  112. package/app/components/link/index.test.js +72 -0
  113. package/app/components/links-list/index.jsx +89 -0
  114. package/app/components/links-list/index.test.js +62 -0
  115. package/app/components/list-menu/index.jsx +280 -0
  116. package/app/components/list-menu/index.test.js +44 -0
  117. package/app/components/loading-spinner/index.jsx +46 -0
  118. package/app/components/locale-selector/index.jsx +124 -0
  119. package/app/components/locale-selector/index.test.js +37 -0
  120. package/app/components/locale-text/index.jsx +97 -0
  121. package/app/components/locale-text/index.test.js +36 -0
  122. package/app/components/login/index.jsx +96 -0
  123. package/app/components/nested-accordion/index.jsx +185 -0
  124. package/app/components/nested-accordion/index.test.js +98 -0
  125. package/app/components/offline-banner/index.jsx +40 -0
  126. package/app/components/offline-banner/index.test.js +15 -0
  127. package/app/components/offline-boundary/index.jsx +104 -0
  128. package/app/components/offline-boundary/index.test.js +123 -0
  129. package/app/components/order-summary/index.jsx +331 -0
  130. package/app/components/page-action-placeholder/index.jsx +50 -0
  131. package/app/components/pagination/index.jsx +134 -0
  132. package/app/components/pagination/index.test.js +25 -0
  133. package/app/components/product-item/index.jsx +146 -0
  134. package/app/components/product-item/index.test.js +38 -0
  135. package/app/components/product-scroller/index.jsx +172 -0
  136. package/app/components/product-scroller/index.test.js +98 -0
  137. package/app/components/product-tile/index.jsx +195 -0
  138. package/app/components/product-tile/index.test.js +96 -0
  139. package/app/components/product-view/index.jsx +538 -0
  140. package/app/components/product-view/index.test.js +224 -0
  141. package/app/components/product-view-modal/index.jsx +48 -0
  142. package/app/components/product-view-modal/index.test.js +72 -0
  143. package/app/components/promo-code/index.jsx +162 -0
  144. package/app/components/promo-popover/index.jsx +83 -0
  145. package/app/components/quantity-picker/index.jsx +58 -0
  146. package/app/components/radio-card/index.jsx +75 -0
  147. package/app/components/recommended-products/index.jsx +227 -0
  148. package/app/components/register/index.jsx +114 -0
  149. package/app/components/reset-password/index.jsx +87 -0
  150. package/app/components/responsive/index.jsx +29 -0
  151. package/app/components/scroll-to-top/index.jsx +24 -0
  152. package/app/components/scroll-to-top/index.test.js +46 -0
  153. package/app/components/search/index.jsx +279 -0
  154. package/app/components/search/index.test.js +127 -0
  155. package/app/components/search/partials/recent-searches.jsx +76 -0
  156. package/app/components/search/partials/search-suggestions.jsx +45 -0
  157. package/app/components/search/partials/suggestions.jsx +43 -0
  158. package/app/components/section/index.jsx +68 -0
  159. package/app/components/seo/index.jsx +33 -0
  160. package/app/components/social-icons/index.jsx +101 -0
  161. package/app/components/social-icons/index.test.js +30 -0
  162. package/app/components/swatch-group/index.jsx +77 -0
  163. package/app/components/swatch-group/index.test.js +136 -0
  164. package/app/components/swatch-group/swatch.jsx +94 -0
  165. package/app/components/toggle-card/index.jsx +97 -0
  166. package/app/components/with-registration/index.jsx +58 -0
  167. package/app/components/with-registration/index.test.js +85 -0
  168. package/app/constants.js +109 -0
  169. package/app/contexts/index.js +92 -0
  170. package/app/hooks/einstein-mock-data.js +916 -0
  171. package/app/hooks/index.js +17 -0
  172. package/app/hooks/use-add-to-cart-modal.js +344 -0
  173. package/app/hooks/use-add-to-cart-modal.test.js +625 -0
  174. package/app/hooks/use-auth-modal.js +337 -0
  175. package/app/hooks/use-auth-modal.test.js +365 -0
  176. package/app/hooks/use-currency.js +20 -0
  177. package/app/hooks/use-currency.test.js +41 -0
  178. package/app/hooks/use-current-basket.js +39 -0
  179. package/app/hooks/use-current-customer.js +29 -0
  180. package/app/hooks/use-derived-product.js +77 -0
  181. package/app/hooks/use-derived-product.test.js +69 -0
  182. package/app/hooks/use-einstein.js +512 -0
  183. package/app/hooks/use-einstein.test.js +224 -0
  184. package/app/hooks/use-intersection-observer.js +64 -0
  185. package/app/hooks/use-limit-urls.js +31 -0
  186. package/app/hooks/use-limit-urls.test.js +40 -0
  187. package/app/hooks/use-multi-site.js +36 -0
  188. package/app/hooks/use-multi-site.test.js +53 -0
  189. package/app/hooks/use-navigation.js +37 -0
  190. package/app/hooks/use-navigation.test.js +109 -0
  191. package/app/hooks/use-page-urls.js +35 -0
  192. package/app/hooks/use-page-urls.test.js +39 -0
  193. package/app/hooks/use-pdp-search-params.js +16 -0
  194. package/app/hooks/use-pdp-search-params.test.js +52 -0
  195. package/app/hooks/use-previous.js +17 -0
  196. package/app/hooks/use-product-view-modal.js +93 -0
  197. package/app/hooks/use-product-view-modal.test.js +172 -0
  198. package/app/hooks/use-search-params.js +96 -0
  199. package/app/hooks/use-search-params.test.js +91 -0
  200. package/app/hooks/use-sort-urls.js +33 -0
  201. package/app/hooks/use-sort-urls.test.js +42 -0
  202. package/app/hooks/use-toast.js +68 -0
  203. package/app/hooks/use-toast.test.js +58 -0
  204. package/app/hooks/use-variant.js +32 -0
  205. package/app/hooks/use-variant.test.js +81 -0
  206. package/app/hooks/use-variation-attributes.js +138 -0
  207. package/app/hooks/use-variation-attributes.test.js +119 -0
  208. package/app/hooks/use-variation-params.js +31 -0
  209. package/app/hooks/use-variation-params.test.js +73 -0
  210. package/app/hooks/use-wish-list.js +42 -0
  211. package/app/main.jsx +14 -0
  212. package/app/mocks/basket-with-suit.js +146 -0
  213. package/app/mocks/empty-basket.js +39 -0
  214. package/app/mocks/mock-data.js +5632 -0
  215. package/app/mocks/product-set-winter-lookM.js +1224 -0
  216. package/app/mocks/searchResults.js +144 -0
  217. package/app/mocks/variant-750518699578M.js +434 -0
  218. package/app/page-designer/README.md +102 -0
  219. package/app/page-designer/assets/image-tile/index.jsx +51 -0
  220. package/app/page-designer/assets/image-tile/index.test.js +30 -0
  221. package/app/page-designer/assets/image-with-text/index.jsx +140 -0
  222. package/app/page-designer/assets/image-with-text/index.test.js +38 -0
  223. package/app/page-designer/assets/index.js +9 -0
  224. package/app/page-designer/index.js +10 -0
  225. package/app/page-designer/layouts/carousel/index.jsx +222 -0
  226. package/app/page-designer/layouts/carousel/index.test.js +43 -0
  227. package/app/page-designer/layouts/index.js +14 -0
  228. package/app/page-designer/layouts/mobileGrid1r1c/index.jsx +36 -0
  229. package/app/page-designer/layouts/mobileGrid1r1c/index.test.js +35 -0
  230. package/app/page-designer/layouts/mobileGrid2r1c/index.jsx +37 -0
  231. package/app/page-designer/layouts/mobileGrid2r1c/index.test.js +47 -0
  232. package/app/page-designer/layouts/mobileGrid2r2c/index.jsx +37 -0
  233. package/app/page-designer/layouts/mobileGrid2r2c/index.test.js +71 -0
  234. package/app/page-designer/layouts/mobileGrid2r3c/index.jsx +37 -0
  235. package/app/page-designer/layouts/mobileGrid2r3c/index.test.js +95 -0
  236. package/app/page-designer/layouts/mobileGrid3r1c/index.jsx +37 -0
  237. package/app/page-designer/layouts/mobileGrid3r1c/index.test.js +59 -0
  238. package/app/page-designer/layouts/mobileGrid3r2c/index.jsx +37 -0
  239. package/app/page-designer/layouts/mobileGrid3r2c/index.test.js +95 -0
  240. package/app/page-designer/utils.js +14 -0
  241. package/app/pages/account/addresses.jsx +382 -0
  242. package/app/pages/account/addresses.test.js +120 -0
  243. package/app/pages/account/constant.js +57 -0
  244. package/app/pages/account/index.jsx +237 -0
  245. package/app/pages/account/index.test.js +188 -0
  246. package/app/pages/account/order-detail.jsx +397 -0
  247. package/app/pages/account/order-history.jsx +264 -0
  248. package/app/pages/account/orders.jsx +30 -0
  249. package/app/pages/account/orders.test.js +95 -0
  250. package/app/pages/account/profile.jsx +357 -0
  251. package/app/pages/account/wishlist/index.jsx +195 -0
  252. package/app/pages/account/wishlist/index.mock.js +1481 -0
  253. package/app/pages/account/wishlist/index.test.js +56 -0
  254. package/app/pages/account/wishlist/partials/wishlist-primary-action.jsx +170 -0
  255. package/app/pages/account/wishlist/partials/wishlist-primary-action.mock.js +1623 -0
  256. package/app/pages/account/wishlist/partials/wishlist-primary-action.test.js +99 -0
  257. package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.jsx +120 -0
  258. package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.test.js +391 -0
  259. package/app/pages/cart/index.jsx +476 -0
  260. package/app/pages/cart/index.test.js +481 -0
  261. package/app/pages/cart/partials/cart-cta.jsx +46 -0
  262. package/app/pages/cart/partials/cart-secondary-button-group.jsx +135 -0
  263. package/app/pages/cart/partials/cart-secondary-button-group.test.js +103 -0
  264. package/app/pages/cart/partials/cart-skeleton.jsx +93 -0
  265. package/app/pages/cart/partials/cart-title.jsx +27 -0
  266. package/app/pages/cart/partials/empty-cart.jsx +86 -0
  267. package/app/pages/checkout/confirmation.jsx +541 -0
  268. package/app/pages/checkout/confirmation.mock.js +450 -0
  269. package/app/pages/checkout/confirmation.test.js +114 -0
  270. package/app/pages/checkout/index.jsx +169 -0
  271. package/app/pages/checkout/index.test.js +582 -0
  272. package/app/pages/checkout/partials/cc-radio-group.jsx +122 -0
  273. package/app/pages/checkout/partials/checkout-footer.jsx +140 -0
  274. package/app/pages/checkout/partials/checkout-footer.test.js +16 -0
  275. package/app/pages/checkout/partials/checkout-header.jsx +54 -0
  276. package/app/pages/checkout/partials/checkout-header.test.js +16 -0
  277. package/app/pages/checkout/partials/checkout-skeleton.jsx +52 -0
  278. package/app/pages/checkout/partials/contact-info.jsx +251 -0
  279. package/app/pages/checkout/partials/contact-info.test.js +43 -0
  280. package/app/pages/checkout/partials/payment-form.jsx +97 -0
  281. package/app/pages/checkout/partials/payment.jsx +276 -0
  282. package/app/pages/checkout/partials/shipping-address-selection.jsx +377 -0
  283. package/app/pages/checkout/partials/shipping-address.jsx +132 -0
  284. package/app/pages/checkout/partials/shipping-options.jsx +232 -0
  285. package/app/pages/checkout/util/checkout-context.js +94 -0
  286. package/app/pages/home/data.js +134 -0
  287. package/app/pages/home/index.jsx +301 -0
  288. package/app/pages/home/index.test.js +23 -0
  289. package/app/pages/login/index.jsx +123 -0
  290. package/app/pages/login/index.test.js +229 -0
  291. package/app/pages/login-redirect/index.jsx +23 -0
  292. package/app/pages/login-redirect/index.test.js +16 -0
  293. package/app/pages/page-not-found/index.jsx +90 -0
  294. package/app/pages/page-not-found/index.test.js +31 -0
  295. package/app/pages/product-detail/index.jsx +394 -0
  296. package/app/pages/product-detail/index.mock.js +197 -0
  297. package/app/pages/product-detail/index.test.js +162 -0
  298. package/app/pages/product-detail/partials/information-accordion.jsx +121 -0
  299. package/app/pages/product-list/index.jsx +735 -0
  300. package/app/pages/product-list/index.test.js +180 -0
  301. package/app/pages/product-list/partials/above-page-header.jsx +10 -0
  302. package/app/pages/product-list/partials/checkbox-refinements.jsx +41 -0
  303. package/app/pages/product-list/partials/checkbox-refinements.test.js +53 -0
  304. package/app/pages/product-list/partials/color-refinements.jsx +88 -0
  305. package/app/pages/product-list/partials/empty-results.jsx +118 -0
  306. package/app/pages/product-list/partials/link-refinements.jsx +38 -0
  307. package/app/pages/product-list/partials/page-header.jsx +42 -0
  308. package/app/pages/product-list/partials/radio-refinements.jsx +60 -0
  309. package/app/pages/product-list/partials/refinements.jsx +144 -0
  310. package/app/pages/product-list/partials/selected-refinements.jsx +100 -0
  311. package/app/pages/product-list/partials/size-refinements.jsx +55 -0
  312. package/app/pages/registration/index.jsx +87 -0
  313. package/app/pages/registration/index.test.jsx +132 -0
  314. package/app/pages/reset-password/index.jsx +112 -0
  315. package/app/pages/reset-password/index.test.jsx +141 -0
  316. package/app/request-processor.js +118 -0
  317. package/app/request-processor.test.js +23 -0
  318. package/app/routes.jsx +111 -0
  319. package/app/routes.test.js +13 -0
  320. package/app/ssr.js +70 -0
  321. package/app/static/ico/favicon.ico +0 -0
  322. package/app/static/img/global/app-icon-192.png +0 -0
  323. package/app/static/img/global/app-icon-512.png +0 -0
  324. package/app/static/img/global/apple-touch-icon.png +0 -0
  325. package/app/static/img/hero.png +0 -0
  326. package/app/static/manifest.json +19 -0
  327. package/app/static/robots.txt +2 -0
  328. package/app/theme/components/base/accordion.js +21 -0
  329. package/app/theme/components/base/alert.js +17 -0
  330. package/app/theme/components/base/badge.js +25 -0
  331. package/app/theme/components/base/button.js +77 -0
  332. package/app/theme/components/base/checkbox.js +30 -0
  333. package/app/theme/components/base/container.js +17 -0
  334. package/app/theme/components/base/drawer.js +26 -0
  335. package/app/theme/components/base/formLabel.js +13 -0
  336. package/app/theme/components/base/icon.js +13 -0
  337. package/app/theme/components/base/input.js +44 -0
  338. package/app/theme/components/base/modal.js +11 -0
  339. package/app/theme/components/base/popover.js +61 -0
  340. package/app/theme/components/base/radio.js +33 -0
  341. package/app/theme/components/base/select.js +15 -0
  342. package/app/theme/components/base/skeleton.js +12 -0
  343. package/app/theme/components/base/tooltip.js +19 -0
  344. package/app/theme/components/project/_app.js +25 -0
  345. package/app/theme/components/project/breadcrumb.js +25 -0
  346. package/app/theme/components/project/checkout-footer.js +35 -0
  347. package/app/theme/components/project/drawer-menu.js +66 -0
  348. package/app/theme/components/project/footer.js +84 -0
  349. package/app/theme/components/project/header.js +84 -0
  350. package/app/theme/components/project/image-gallery.js +59 -0
  351. package/app/theme/components/project/links-list.js +43 -0
  352. package/app/theme/components/project/list-menu.js +91 -0
  353. package/app/theme/components/project/locale-selector.js +42 -0
  354. package/app/theme/components/project/nested-accordion.js +26 -0
  355. package/app/theme/components/project/offline-banner.js +25 -0
  356. package/app/theme/components/project/pagination.js +22 -0
  357. package/app/theme/components/project/product-tile.js +32 -0
  358. package/app/theme/components/project/social-icons.js +52 -0
  359. package/app/theme/components/project/swatch-group.js +115 -0
  360. package/app/theme/foundations/colors.js +170 -0
  361. package/app/theme/foundations/gradients.js +9 -0
  362. package/app/theme/foundations/layerStyles.js +41 -0
  363. package/app/theme/foundations/shadows.js +9 -0
  364. package/app/theme/foundations/sizes.js +18 -0
  365. package/app/theme/foundations/space.js +9 -0
  366. package/app/theme/foundations/styles.js +21 -0
  367. package/app/theme/index.js +104 -0
  368. package/app/utils/cc-utils.js +112 -0
  369. package/app/utils/cc-utils.test.js +41 -0
  370. package/app/utils/image-groups-utils.js +62 -0
  371. package/app/utils/image-groups-utils.test.js +65 -0
  372. package/app/utils/locale.js +78 -0
  373. package/app/utils/locale.test.js +112 -0
  374. package/app/utils/password-utils.js +21 -0
  375. package/app/utils/phone-utils.js +22 -0
  376. package/app/utils/phone-utils.test.js +15 -0
  377. package/app/utils/product-utils.js +35 -0
  378. package/app/utils/product-utils.test.js +51 -0
  379. package/app/utils/responsive-image.js +198 -0
  380. package/app/utils/responsive-image.test.js +170 -0
  381. package/app/utils/routes-utils.js +111 -0
  382. package/app/utils/routes-utils.test.js +291 -0
  383. package/app/utils/site-utils.js +222 -0
  384. package/app/utils/site-utils.test.js +376 -0
  385. package/app/utils/test-utils.js +257 -0
  386. package/app/utils/url.js +291 -0
  387. package/app/utils/url.test.js +421 -0
  388. package/app/utils/utils.js +201 -0
  389. package/app/utils/utils.test.js +182 -0
  390. package/babel.config.js +7 -0
  391. package/cache-hash-config.json +8 -0
  392. package/config/default.js +64 -0
  393. package/config/mocks/default.js +131 -0
  394. package/config/sites.js +78 -0
  395. package/jest-setup.js +191 -0
  396. package/jest.config.js +50 -0
  397. package/jsconfig.json +13 -0
  398. package/package.json +105 -0
  399. package/scripts/extract-default-messages.js +92 -0
  400. package/tests/lighthouserc.js +37 -0
  401. package/translations/README.md +127 -0
  402. package/translations/compiled/de-DE.json +3212 -0
  403. package/translations/compiled/en-GB.json +3212 -0
  404. package/translations/compiled/en-US.json +3212 -0
  405. package/translations/compiled/en-XA.json +6948 -0
  406. package/translations/compiled/es-MX.json +3216 -0
  407. package/translations/compiled/fr-FR.json +3216 -0
  408. package/translations/compiled/it-IT.json +3188 -0
  409. package/translations/compiled/ja-JP.json +3200 -0
  410. package/translations/compiled/ko-KR.json +3180 -0
  411. package/translations/compiled/pt-BR.json +3220 -0
  412. package/translations/compiled/zh-CN.json +3212 -0
  413. package/translations/compiled/zh-TW.json +3208 -0
  414. package/translations/de-DE.json +1417 -0
  415. package/translations/en-GB.json +1417 -0
  416. package/translations/en-US.json +1417 -0
  417. package/translations/es-MX.json +1417 -0
  418. package/translations/fr-FR.json +1417 -0
  419. package/translations/it-IT.json +1417 -0
  420. package/translations/ja-JP.json +1417 -0
  421. package/translations/ko-KR.json +1417 -0
  422. package/translations/pt-BR.json +1417 -0
  423. package/translations/zh-CN.json +1417 -0
  424. package/translations/zh-TW.json +1417 -0
  425. package/worker/main.js +36 -0
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ import React from 'react'
8
+ import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
9
+ import {Button} from '@chakra-ui/react'
10
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
11
+ import {screen, waitFor} from '@testing-library/react'
12
+ import userEvent from '@testing-library/user-event'
13
+
14
+ jest.setTimeout(60000)
15
+ const MockedComponent = (props) => {
16
+ const showToast = useToast()
17
+
18
+ const renderToast = () => {
19
+ showToast({
20
+ ...props,
21
+ title: 'Demo Notification',
22
+ status: 'success',
23
+ duration: 1000,
24
+ variant: 'subtle'
25
+ })
26
+ }
27
+ return (
28
+ <>
29
+ <Button onClick={renderToast}>show toast</Button>
30
+ </>
31
+ )
32
+ }
33
+
34
+ // Set up and clean up
35
+ beforeEach(() => {
36
+ jest.resetModules()
37
+ })
38
+
39
+ test('renders toast with action', async () => {
40
+ const user = userEvent.setup()
41
+ const handleActionClick = jest.fn()
42
+ const toastAction = <Button onClick={handleActionClick}>action</Button>
43
+
44
+ renderWithProviders(<MockedComponent action={toastAction} />)
45
+
46
+ const toastTrigger = await screen.findByRole('button', {name: /show toast/i})
47
+ await user.click(toastTrigger)
48
+
49
+ await waitFor(() => {
50
+ // Chakra UI renders multiple elements with toast title in DOM for accessibility.
51
+ // We need to assert the actual text within the alert
52
+ expect(screen.getByRole('alert')).toHaveTextContent(/demo notification/i)
53
+ })
54
+
55
+ const toastActionTrigger = await screen.findByRole('button', {name: /action/i})
56
+ await user.click(toastActionTrigger)
57
+ expect(handleActionClick).toHaveBeenCalledTimes(1)
58
+ })
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ // Hooks
9
+ import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
10
+
11
+ /**
12
+ * This hook returns the currently selected
13
+ * variant or undefined. NOTE: All attributes must be selected before a variant
14
+ * will be returned.
15
+ *
16
+ * @param {Object} product
17
+ * @returns {Object} the currently selected `Variant` object.
18
+ */
19
+ export const useVariant = (product = {}, isProductPartOfSet = false) => {
20
+ const {variants = []} = product
21
+ const variationParams = useVariationParams(product, isProductPartOfSet)
22
+
23
+ // Get a filtered array of variants. The resulting array will only have variants
24
+ // which have all the current variation params values set.
25
+ const filteredVariants = variants.filter(({variationValues}) =>
26
+ // A single liner that will return true if the current variation has all the
27
+ // same attribute values as the passing in params.
28
+ Object.keys(variationParams).every((key) => variationValues[key] === variationParams[key])
29
+ )
30
+
31
+ return filteredVariants.length === 1 ? filteredVariants[0] : undefined
32
+ }
@@ -0,0 +1,81 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import React from 'react'
9
+ import {Router} from 'react-router'
10
+
11
+ import {render} from '@testing-library/react'
12
+ import {createMemoryHistory} from 'history'
13
+ import {useVariant} from '@salesforce/retail-react-app/app/hooks/use-variant'
14
+
15
+ // Below is a partial product used for mocking purposes. Note: only the properties
16
+ // that are used in the hook at defined.
17
+ const MockProduct = {
18
+ variationAttributes: [
19
+ {id: 'color', name: 'Color', values: []},
20
+ {id: 'size', name: 'Size', values: []}
21
+ ],
22
+ variants: [
23
+ {
24
+ orderable: true,
25
+ price: 195,
26
+ productId: '883360352473M',
27
+ variationValues: {
28
+ color: 'B9W',
29
+ size: '34'
30
+ }
31
+ },
32
+ {
33
+ orderable: true,
34
+ price: 195,
35
+ productId: '883360492148M',
36
+ variationValues: {
37
+ color: 'DKL',
38
+ size: '34'
39
+ }
40
+ }
41
+ ]
42
+ }
43
+
44
+ const MockComponent = () => {
45
+ const variant = useVariant(MockProduct)
46
+ return (
47
+ <script data-testid="variant" type="application/json">
48
+ {JSON.stringify(variant)}
49
+ </script>
50
+ )
51
+ }
52
+
53
+ describe('The useVariant', () => {
54
+ test('returns undefined when a single variant cannot be deduced from the location search params.', () => {
55
+ const history = createMemoryHistory()
56
+ history.push('/test/path?size=34')
57
+
58
+ const wrapper = render(
59
+ <Router history={history}>
60
+ <MockComponent />
61
+ </Router>
62
+ )
63
+
64
+ expect(wrapper.getByTestId('variant').text).toBe('')
65
+ })
66
+
67
+ test('returns the correct variant when one can be deduced from the location search params.', () => {
68
+ const history = createMemoryHistory()
69
+ history.push('/test/path?size=34&color=DKL')
70
+
71
+ const wrapper = render(
72
+ <Router history={history}>
73
+ <MockComponent />
74
+ </Router>
75
+ )
76
+
77
+ expect(wrapper.getByTestId('variant').text).toBe(
78
+ '{"orderable":true,"price":195,"productId":"883360492148M","variationValues":{"color":"DKL","size":"34"}}'
79
+ )
80
+ })
81
+ })
@@ -0,0 +1,138 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import {useMemo} from 'react'
9
+ import {useLocation} from 'react-router-dom'
10
+
11
+ // Other Hooks
12
+ import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
13
+
14
+ // Utils
15
+ import {updateSearchParams} from '@salesforce/retail-react-app/app/utils/url'
16
+ import {usePDPSearchParams} from '@salesforce/retail-react-app/app/hooks/use-pdp-search-params'
17
+
18
+ /**
19
+ * Return the first image in the `swatch` type image group for a given
20
+ * variation value of a product.
21
+ *
22
+ * @param {Object} product
23
+ * @param {Object} variationValue
24
+ * @returns {Object} image
25
+ */
26
+ const getVariantValueSwatch = (product, variationValue) => {
27
+ const {imageGroups = []} = product
28
+
29
+ const imageGroup = imageGroups
30
+ .filter(({viewType}) => viewType === 'swatch')
31
+ .find(({variationAttributes = []}) => {
32
+ const colorAttribute = variationAttributes.find(({id}) => id === 'color')
33
+ const colorValues = colorAttribute?.values || []
34
+
35
+ // A single image can represent multiple variation values, so we only need
36
+ // ensure the variation values appears in once of the images represented values.
37
+ return colorValues.some(({value}) => value === variationValue.value)
38
+ })
39
+
40
+ return imageGroup?.images?.[0]
41
+ }
42
+
43
+ /**
44
+ * Build a product href
45
+ *
46
+ * @param {Object} product
47
+ * @param {Object} params
48
+ * @param {Object} location
49
+ * @returns {String} a product url for the current variation value.
50
+ */
51
+ const buildVariantValueHref = ({
52
+ pathname,
53
+ existingParams,
54
+ newParams,
55
+ productId,
56
+ isProductPartOfSet
57
+ }) => {
58
+ const [allParams, productParams] = existingParams
59
+
60
+ if (isProductPartOfSet) {
61
+ updateSearchParams(productParams, newParams)
62
+ allParams.set(productId, productParams.toString())
63
+ } else {
64
+ updateSearchParams(allParams, newParams)
65
+ }
66
+
67
+ return `${pathname}?${allParams.toString()}`
68
+ }
69
+
70
+ /**
71
+ * Determine if a products variant attribute value is orderable without having to
72
+ * load the variant in question, but filtering the list of variants with the
73
+ * passed in attribute values.
74
+ *
75
+ * @param {Object} product
76
+ * @param {Object} variationParams
77
+ * @returns
78
+ */
79
+ const isVariantValueOrderable = (product, variationParams) => {
80
+ return product.variants
81
+ .filter(({variationValues}) =>
82
+ Object.keys(variationParams).every(
83
+ (key) => variationValues[key] === variationParams[key]
84
+ )
85
+ )
86
+ .some(({orderable}) => orderable)
87
+ }
88
+
89
+ /**
90
+ * Use a decorated version of a product variation attributes. This version
91
+ * will have the following additions: which variation attribute is selected,
92
+ * each value will have a product url, the swatch image if there is one, and
93
+ * an updated orderable flag.
94
+ *
95
+ * @param {Object} product
96
+ * @returns {Array} a decorated variation attributes list.
97
+ *
98
+ */
99
+ export const useVariationAttributes = (product = {}, isProductPartOfSet = false) => {
100
+ const {variationAttributes = []} = product
101
+ const location = useLocation()
102
+ const variationParams = useVariationParams(product, isProductPartOfSet)
103
+
104
+ const existingParams = usePDPSearchParams(product.id)
105
+
106
+ return useMemo(
107
+ () =>
108
+ variationAttributes.map((variationAttribute) => ({
109
+ ...variationAttribute,
110
+ selectedValue: {
111
+ name: variationAttribute.values.find(
112
+ ({value}) => value === variationParams?.[variationAttribute.id]
113
+ )?.name,
114
+ value: variationParams?.[variationAttribute.id]
115
+ },
116
+ values: variationAttribute.values.map((value) => {
117
+ const params = {
118
+ ...variationParams,
119
+ [variationAttribute.id]: value.value
120
+ }
121
+
122
+ return {
123
+ ...value,
124
+ image: getVariantValueSwatch(product, value),
125
+ href: buildVariantValueHref({
126
+ pathname: location.pathname,
127
+ existingParams,
128
+ newParams: params,
129
+ productId: product.id,
130
+ isProductPartOfSet
131
+ }),
132
+ orderable: isVariantValueOrderable(product, params)
133
+ }
134
+ })
135
+ })),
136
+ [location.search, product]
137
+ )
138
+ }
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import React from 'react'
9
+ import {Router} from 'react-router'
10
+
11
+ import {render} from '@testing-library/react'
12
+ import {createMemoryHistory} from 'history'
13
+ import {useVariationAttributes} from '@salesforce/retail-react-app/app/hooks/use-variation-attributes'
14
+
15
+ // Below is a partial product used for mocking purposes. Note: only the properties
16
+ // that are used in the hook at defined.
17
+ const MockProduct = {
18
+ master: {
19
+ masterId: '73910532M',
20
+ orderable: true,
21
+ price: 195
22
+ },
23
+ imageGroups: [
24
+ {
25
+ images: [
26
+ {
27
+ alt: 'Basic Leg Trousers, , swatch',
28
+ disBaseLink:
29
+ 'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
30
+ link: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
31
+ title: 'Basic Leg Trousers, '
32
+ }
33
+ ],
34
+ viewType: 'swatch'
35
+ },
36
+ {
37
+ images: [
38
+ {
39
+ alt: 'Basic Leg Trousers, Black, swatch',
40
+ disBaseLink:
41
+ 'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
42
+ link: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
43
+ title: 'Basic Leg Trousers, Black'
44
+ }
45
+ ],
46
+ variationAttributes: [
47
+ {
48
+ id: 'color',
49
+ values: [
50
+ {
51
+ value: '001'
52
+ }
53
+ ]
54
+ }
55
+ ],
56
+ viewType: 'swatch'
57
+ }
58
+ ],
59
+ variants: [
60
+ {
61
+ orderable: true,
62
+ price: 195,
63
+ productId: '883858858302M',
64
+ variationValues: {
65
+ color: '001',
66
+ size: '28'
67
+ }
68
+ }
69
+ ],
70
+ variationAttributes: [
71
+ {
72
+ id: 'color',
73
+ name: 'Color',
74
+ values: [
75
+ {
76
+ name: 'Black',
77
+ orderable: true,
78
+ value: '001'
79
+ }
80
+ ]
81
+ },
82
+ {
83
+ id: 'size',
84
+ name: 'Size',
85
+ values: [
86
+ {
87
+ name: '28',
88
+ orderable: true,
89
+ value: '28'
90
+ }
91
+ ]
92
+ }
93
+ ]
94
+ }
95
+
96
+ const MockComponent = () => {
97
+ const params = useVariationAttributes(MockProduct)
98
+
99
+ return (
100
+ <script data-testid="variationAttributes" type="application/json">
101
+ {JSON.stringify(params)}
102
+ </script>
103
+ )
104
+ }
105
+
106
+ describe('The useVariationAttributes', () => {
107
+ test('returns variation attributes decorated with hrefs and images.', () => {
108
+ const history = createMemoryHistory()
109
+ history.push('/test/path?color=blue&size=2')
110
+ const wrapper = render(
111
+ <Router history={history}>
112
+ <MockComponent />
113
+ </Router>
114
+ )
115
+ expect(wrapper.getByTestId('variationAttributes').text).toBe(
116
+ '[{"id":"color","name":"Color","values":[{"name":"Black","orderable":false,"value":"001","image":{"alt":"Basic Leg Trousers, Black, swatch","disBaseLink":"https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg","link":"https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg","title":"Basic Leg Trousers, Black"},"href":"/test/path?color=001&size=2"}],"selectedValue":{"value":"blue"}},{"id":"size","name":"Size","values":[{"name":"28","orderable":false,"value":"28","href":"/test/path?color=blue&size=28"}],"selectedValue":{"value":"2"}}]'
117
+ )
118
+ })
119
+ })
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import {usePDPSearchParams} from '@salesforce/retail-react-app/app/hooks/use-pdp-search-params'
9
+
10
+ /*
11
+ * This hook will return only the params that are also product attributes for the
12
+ * passed in product object.
13
+ */
14
+ export const useVariationParams = (product = {}, isProductPartOfSet = false) => {
15
+ const {variationAttributes = [], variationValues = {}} = product
16
+
17
+ const [allParams, productParams] = usePDPSearchParams(product.id)
18
+ const params = isProductPartOfSet ? productParams : allParams
19
+
20
+ // Using all the variation attribute id from the array generated below, get
21
+ // the value if there is one from the location search params and add it to the
22
+ // accumulator.
23
+ const variationParams = variationAttributes
24
+ .map(({id}) => id)
25
+ .reduce((acc, key) => {
26
+ let value = params.get(`${key}`) || variationValues?.[key]
27
+ return value ? {...acc, [key]: value} : acc
28
+ }, {})
29
+
30
+ return variationParams
31
+ }
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import React from 'react'
9
+ import {Router} from 'react-router'
10
+
11
+ import {render} from '@testing-library/react'
12
+ import {createMemoryHistory} from 'history'
13
+ import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
14
+
15
+ // Below is a partial product used for mocking purposes. Note: only the properties
16
+ // that are used in the hook at defined.
17
+ const MockProduct = {
18
+ variationAttributes: [
19
+ {id: 'color', name: 'Color', values: []},
20
+ {id: 'size', name: 'Size', values: []}
21
+ ]
22
+ }
23
+
24
+ const MockComponent = () => {
25
+ const params = useVariationParams(MockProduct)
26
+
27
+ return (
28
+ <script data-testid="params" type="application/json">
29
+ {JSON.stringify(params)}
30
+ </script>
31
+ )
32
+ }
33
+
34
+ describe('The useVariationParams', () => {
35
+ test('returns correct params when there are no non-product params in the url.', () => {
36
+ const history = createMemoryHistory()
37
+ history.push('/test/path?color=blue&size=2')
38
+
39
+ const wrapper = render(
40
+ <Router history={history}>
41
+ <MockComponent />
42
+ </Router>
43
+ )
44
+
45
+ expect(wrapper.getByTestId('params').text).toBe('{"color":"blue","size":"2"}')
46
+ })
47
+
48
+ test('returns correct params when there are non-product params in the url.', () => {
49
+ const history = createMemoryHistory()
50
+ history.push('/test/path?color=blue&size=2&nonproductattribute=true')
51
+
52
+ const wrapper = render(
53
+ <Router history={history}>
54
+ <MockComponent />
55
+ </Router>
56
+ )
57
+
58
+ expect(wrapper.getByTestId('params').text).toBe('{"color":"blue","size":"2"}')
59
+ })
60
+
61
+ test('returns correct params when there is only a subset product params in the url.', () => {
62
+ const history = createMemoryHistory()
63
+ history.push('/test/path?color=blue')
64
+
65
+ const wrapper = render(
66
+ <Router history={history}>
67
+ <MockComponent />
68
+ </Router>
69
+ )
70
+
71
+ expect(wrapper.getByTestId('params').text).toBe('{"color":"blue"}')
72
+ })
73
+ })
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright (c) 2022, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ import {useCustomerProductLists, useShopperCustomersMutation} from '@salesforce/commerce-sdk-react'
9
+ import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer'
10
+ const onClient = typeof window !== 'undefined'
11
+ // TODO: remove `listId` input -> use the first list of type wish_list instead
12
+ // (mimic the logic in the other older hook 'use-wishlist.js')
13
+ export const useWishList = ({listId = ''} = {}) => {
14
+ const {data: customer} = useCurrentCustomer()
15
+ const {customerId} = customer
16
+ const createCustomerProductList = useShopperCustomersMutation('createCustomerProductList')
17
+ const {data: productLists, ...restOfQuery} = useCustomerProductLists(
18
+ {
19
+ parameters: {customerId}
20
+ },
21
+ {
22
+ onSuccess: (data) => {
23
+ if (!data.total) {
24
+ createCustomerProductList.mutate({
25
+ parameters: {customerId},
26
+ // we only use one type of product lists for now
27
+ body: {type: 'wish_list'}
28
+ })
29
+ }
30
+ },
31
+ enabled: onClient && Boolean(customerId)
32
+ }
33
+ )
34
+
35
+ const wishLists = productLists?.data?.filter((list) => list.type === 'wish_list') || []
36
+ const currentWishlist = wishLists.find((list) => list.id === listId)
37
+
38
+ return {
39
+ data: !listId ? wishLists[0] : currentWishlist,
40
+ ...restOfQuery
41
+ }
42
+ }
package/app/main.jsx ADDED
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ import {start, registerServiceWorker} from '@salesforce/pwa-kit-react-sdk/ssr/browser/main'
8
+
9
+ const main = () => {
10
+ // The path to your service worker should match what is set up in ssr.js
11
+ return Promise.all([start(), registerServiceWorker('/worker.js')])
12
+ }
13
+
14
+ main()