@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,51 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ import React from 'react'
8
+ import PropTypes from 'prop-types'
9
+ import {Box, Image} from '@chakra-ui/react'
10
+
11
+ /**
12
+ * Simple ImageTile component that can be used inside any Layout component.
13
+ * @param image Object containing the image url, _type and focalPoint.
14
+ * @returns {JSX.Element}
15
+ */
16
+ export const ImageTile = ({image}) => {
17
+ return (
18
+ <Box className={'image-tile'}>
19
+ <figure className={'image-tile-figure'}>
20
+ <picture>
21
+ <source srcSet={image?.src?.tablet} media="(min-width: 48em)" />
22
+ <source srcSet={image?.src?.desktop} media="(min-width: 64em)" />
23
+ <Image
24
+ className={'image-tile-image'}
25
+ data-testid={'image-tile-image'}
26
+ src={image?.src?.mobile ? image?.src?.mobile : image?.url}
27
+ ignoreFallback={true}
28
+ alt={image?.alt}
29
+ title={image?.alt}
30
+ />
31
+ </picture>
32
+ </figure>
33
+ </Box>
34
+ )
35
+ }
36
+
37
+ ImageTile.propTypes = {
38
+ image: PropTypes.shape({
39
+ _type: PropTypes.string,
40
+ focalPoint: PropTypes.shape({
41
+ _type: PropTypes.string,
42
+ x: PropTypes.number,
43
+ y: PropTypes.number
44
+ }),
45
+ url: PropTypes.string,
46
+ alt: PropTypes.string,
47
+ src: PropTypes.string || PropTypes.object
48
+ })
49
+ }
50
+
51
+ export default ImageTile
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Copyright (c) 2023, 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 {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
9
+ import ImageTile from '@salesforce/retail-react-app/app/page-designer/assets/image-tile/index'
10
+ import {getAssetUrl} from '@salesforce/pwa-kit-react-sdk/ssr/universal/utils'
11
+
12
+ test('ImageTile renders without errors', () => {
13
+ const {getByTestId} = renderWithProviders(
14
+ <ImageTile
15
+ image={{
16
+ _type: 'Image',
17
+ focalPoint: {
18
+ _type: 'Imagefocalpoint',
19
+ x: 0.5,
20
+ y: 0.5
21
+ },
22
+ url: `${getAssetUrl('static/img/hero.png')}`
23
+ }}
24
+ />
25
+ )
26
+
27
+ const image = getByTestId('image-tile-image')
28
+
29
+ expect(image).toHaveAttribute('src', `${getAssetUrl('static/img/hero.png')}`)
30
+ })
@@ -0,0 +1,140 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ import React from 'react'
8
+ import PropTypes from 'prop-types'
9
+ import {Box, Image, Link as ChakraLink, Text} from '@chakra-ui/react'
10
+ import Link from '@salesforce/retail-react-app/app/components/link'
11
+ import {isAbsoluteURL} from '@salesforce/retail-react-app/app/page-designer/utils'
12
+
13
+ /**
14
+ * Image with text component
15
+ *
16
+ * @param {object} props
17
+ * @param {string} - props.ITCLink - Image Link.
18
+ * @param {string} - props.ITCText - Text Below Image.
19
+ * @param {image} - props.image - Image.
20
+ * @param {string} - props.heading - Text Overlay.
21
+ * @param {string} - props.alt - The image alt text shown by the component.
22
+ * @returns {React.ReactElement} - ImageWithText component.
23
+ */
24
+ export const ImageWithText = ({ITCLink, ITCText, image, heading, alt}) => {
25
+ const hasCaption = ITCText || heading
26
+ const isAbsolute = isAbsoluteURL(ITCLink)
27
+ const LinkWrapper = isAbsolute ? ChakraLink : Link
28
+ const linkProps = isAbsolute ? {href: ITCLink} : {to: ITCLink}
29
+
30
+ return (
31
+ <Box className={'image-with-text'}>
32
+ <Box
33
+ as="figure"
34
+ className={'image-with-text-figure'}
35
+ position={'relative'}
36
+ margin={0}
37
+ width={'100%'}
38
+ >
39
+ <picture>
40
+ <source srcSet={image?.src?.tablet} media="(min-width: 48em)" />
41
+ <source srcSet={image?.src?.desktop} media="(min-width: 64em)" />
42
+ <LinkWrapper {...linkProps}>
43
+ <Image
44
+ className={'image-with-text-image'}
45
+ data-testid={'image-with-text-image'}
46
+ src={image?.src?.mobile ? image?.src?.mobile : image?.url}
47
+ ignoreFallback={true}
48
+ alt={alt}
49
+ title={alt}
50
+ filter={'brightness(40%)'}
51
+ />
52
+ </LinkWrapper>
53
+ </picture>
54
+ {hasCaption && (
55
+ <Text as="figcaption">
56
+ {heading && (
57
+ <Box
58
+ className={'image-with-text-heading-container'}
59
+ position={'absolute'}
60
+ top={'50%'}
61
+ width={'100%'}
62
+ padding={'15px'}
63
+ textAlign={{base: 'center', sm: 'left'}}
64
+ >
65
+ <Text
66
+ as="span"
67
+ className={'image-with-text-heading-text'}
68
+ color={'white'}
69
+ >
70
+ {/* The `dangerouslySetInnerHTML` is safe to use in this context. */}
71
+ {/* The HTML in the response from Page Designer API is already sanitized. */}
72
+ <Box
73
+ dangerouslySetInnerHTML={{
74
+ __html: heading
75
+ }}
76
+ sx={{
77
+ ['h1, h2, h3, h4, h5, h6']: {
78
+ fontSize: 'revert',
79
+ fontWeight: 'revert'
80
+ },
81
+ p: {
82
+ display: 'flex',
83
+ alignItems: 'center',
84
+ justifyContent: 'center'
85
+ }
86
+ }}
87
+ />
88
+ </Text>
89
+ </Box>
90
+ )}
91
+ {ITCText && (
92
+ <Box>
93
+ <Text as="span" className={'image-with-text-text-underneath'}>
94
+ {/* The `dangerouslySetInnerHTML` is safe to use in this context. */}
95
+ {/* The HTML in the response from Page Designer API is already sanitized. */}
96
+ <Box
97
+ dangerouslySetInnerHTML={{
98
+ __html: ITCText
99
+ }}
100
+ sx={{
101
+ p: {
102
+ display: 'flex',
103
+ alignItems: 'center',
104
+ justifyContent: 'center'
105
+ }
106
+ }}
107
+ />
108
+ </Text>
109
+ </Box>
110
+ )}
111
+ </Text>
112
+ )}
113
+ </Box>
114
+ </Box>
115
+ )
116
+ }
117
+
118
+ ImageWithText.propTypes = {
119
+ ITCLink: PropTypes.string,
120
+ ITCText: PropTypes.string,
121
+ image: PropTypes.shape({
122
+ _type: PropTypes.string,
123
+ focalPoint: PropTypes.shape({
124
+ _type: PropTypes.string,
125
+ x: PropTypes.number,
126
+ y: PropTypes.number
127
+ }),
128
+ metaData: PropTypes.shape({
129
+ _type: PropTypes.string,
130
+ height: PropTypes.number,
131
+ width: PropTypes.number
132
+ }),
133
+ url: PropTypes.string,
134
+ src: PropTypes.string || PropTypes.object
135
+ }).isRequired,
136
+ heading: PropTypes.string,
137
+ alt: PropTypes.string
138
+ }
139
+
140
+ export default ImageWithText
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ import React from 'react'
8
+ import ImageWithText from '@salesforce/retail-react-app/app/page-designer/assets/image-with-text/index'
9
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
10
+
11
+ const SAMPLE_DATA = {
12
+ ITCLink: 'https://salesforce.com',
13
+ ITCText:
14
+ '<p><em>Text</em> <strong>Below</strong> <u>Image</u> <s>test</s> Image With Text Component <a href="https://zzrf-001.dx.commercecloud.salesforce.com/s/RefArchGlobal/homepage-example.html?lang=en_US" target="_self" data-link-type="page" data-link-label="homepage-example" data-content-page-id="homepage-example">Home-page example link</a><img src="https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw89c1031d/images/myaccount_addresses.png" alt="alt tag myaccount_addresses image"></p>',
15
+ image: {
16
+ _type: 'Image',
17
+ focalPoint: {
18
+ _type: 'Imagefocalpoint',
19
+ x: 0.5,
20
+ y: 0.5
21
+ },
22
+ metaData: {
23
+ _type: 'Imagemetadata',
24
+ height: 1280,
25
+ width: 1920
26
+ },
27
+ url: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw34c389b5/images/SearchBanner/search.jpg'
28
+ },
29
+ heading:
30
+ '<p><em>Text</em> <strong>Overlay</strong> <s>test</s> <u>Image</u> With Text <a href="https://zzrf-001.dx.commercecloud.salesforce.com/s/RefArchGlobal/mens/?lang=en_US" target="_self" data-link-type="category" data-link-label="Mens" data-category-id="mens" data-category-catalog-id="storefront-catalog-m-en">Component Link</a><img src="https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw2d9142bf/images/myaccount_registry.png" alt="alt text myaccount_registry image"></p>',
31
+ alt: 'Alt Text test Image With Text Component'
32
+ }
33
+
34
+ test('Page renders correct component', () => {
35
+ const {getByText} = renderWithProviders(<ImageWithText {...SAMPLE_DATA} />)
36
+
37
+ expect(getByText(/image with text component/i)).toBeInTheDocument()
38
+ })
@@ -0,0 +1,9 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ export * from './image-tile'
9
+ export * from './image-with-text'
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Copyright (c) 2023, 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 {Page, pageType} from '@salesforce/retail-react-app/app/page-designer/core'
9
+
10
+ export {Page, pageType}
@@ -0,0 +1,222 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ import React, {Fragment, useCallback, useMemo, useRef, useState} from 'react'
8
+ import PropTypes from 'prop-types'
9
+ import {
10
+ AspectRatio,
11
+ Box,
12
+ Heading,
13
+ IconButton,
14
+ Stack,
15
+ useBreakpoint,
16
+ useBreakpointValue
17
+ } from '@chakra-ui/react'
18
+ import {Component, regionPropType} from '@salesforce/commerce-sdk-react/components'
19
+ import {ChevronLeftIcon, ChevronRightIcon} from '@salesforce/retail-react-app/app/components/icons'
20
+ import {useEffect} from 'react'
21
+
22
+ /**
23
+ * Display child components in a carousel slider manner. Configurations include the number of
24
+ * children to display in view as well as whether or not to show controls and position indicators.
25
+ *
26
+ * @param {PageProps} props
27
+ * @param {string} props.textHeading - Heading text for the carousel.
28
+ * @param {boolean} props.xsCarouselIndicators - Show/Hide carousel indicators/pips on "xs" screens.
29
+ * @param {boolean} props.smCarouselIndicators - Show/Hide carousel indicators/pips on "sm" screens.
30
+ * @param {boolean} props.mdCarouselIndicators - Show/Hide carousel indicators/pips on "md" screens.
31
+ * @param {boolean} props.xsCarouselControls - Show/Hide carousel forward/back controls on "xs" screens.
32
+ * @param {boolean} props.smCarouselControls - Show/Hide carousel forward/back controls on "sm" screens.
33
+ * @param {number} props.xsCarouselSlidesToDisplay - Number of children that will be rendered in view on "xs" screens.
34
+ * @param {number} props.smCarouselSlidesToDisplay - Number of children that will be rendered in view on "sm" screens.
35
+ * @param {number} props.mdCarouselSlidesToDisplay - Number of children that will be rendered in view on "md" screens.
36
+ * @param {Object []} props.region - The regions passed internally to this component by the `commerce-sdk-react` Page component.
37
+ * @returns {React.ReactElement} - Carousel component.
38
+ */
39
+ export const Carousel = (props = {}) => {
40
+ const scrollRef = useRef()
41
+ const breakpoint = useBreakpoint()
42
+ const [hasOverflow, setHasOverflow] = useState(false)
43
+
44
+ const {
45
+ textHeadline,
46
+ xsCarouselIndicators = false,
47
+ smCarouselIndicators = false,
48
+ mdCarouselIndicators = false,
49
+ xsCarouselControls = false,
50
+ smCarouselControls = false,
51
+ xsCarouselSlidesToDisplay = 1,
52
+ smCarouselSlidesToDisplay = 1,
53
+ mdCarouselSlidesToDisplay = 1,
54
+ // Internally Provided
55
+ regions
56
+ } = props
57
+
58
+ const controlDisplay = useMemo(() => {
59
+ return {
60
+ base: xsCarouselControls && hasOverflow ? 'block' : 'none',
61
+ sm: xsCarouselControls && hasOverflow ? 'block' : 'none',
62
+ md: smCarouselControls && hasOverflow ? 'block' : 'none',
63
+ lg: hasOverflow ? 'block' : 'none'
64
+ }
65
+ }, [hasOverflow])
66
+
67
+ const itemSpacing = 4
68
+ // Calculate the width of each item in the carousel, accounting for the spacing between the items.
69
+ const itemWidth = {
70
+ base: `calc(${100 / xsCarouselSlidesToDisplay}% - ${
71
+ ((xsCarouselSlidesToDisplay - 1) * (itemSpacing * 4)) / xsCarouselSlidesToDisplay
72
+ }px)`,
73
+ sm: `calc(${100 / xsCarouselSlidesToDisplay}% - ${
74
+ ((xsCarouselSlidesToDisplay - 1) * (itemSpacing * 4)) / xsCarouselSlidesToDisplay
75
+ }px)`,
76
+ md: `calc(${100 / smCarouselSlidesToDisplay}% - ${
77
+ ((smCarouselSlidesToDisplay - 1) * (itemSpacing * 4)) / smCarouselSlidesToDisplay
78
+ }px)`,
79
+ lg: `calc(${100 / mdCarouselSlidesToDisplay}% - ${
80
+ ((mdCarouselSlidesToDisplay - 1) * (itemSpacing * 4)) / mdCarouselSlidesToDisplay
81
+ }px)`
82
+ }
83
+
84
+ const overflowXScroll = {
85
+ base: xsCarouselIndicators ? 'block' : 'none',
86
+ sm: xsCarouselIndicators ? 'block' : 'none',
87
+ md: smCarouselIndicators ? 'block' : 'none',
88
+ lg: mdCarouselIndicators ? 'block' : 'none'
89
+ }
90
+ const overflowXScrollValue = useBreakpointValue(overflowXScroll)
91
+
92
+ const components = regions[0]?.components || []
93
+ const itemCount = components.length
94
+
95
+ // Scroll the container left or right by 100%. Passing no args or `1`
96
+ // scrolls to the right, and passing `-1` scrolls left.
97
+ const scroll = useCallback((direction = 1) => {
98
+ scrollRef.current?.scrollBy({
99
+ top: 0,
100
+ left: (direction * window.innerWidth) / itemCount,
101
+ behavior: 'smooth'
102
+ })
103
+ })
104
+
105
+ // Our indicator implementation uses the scrollbar to show the context of the current
106
+ // item selected. Because MacOS hides scroll bars after they come to rest we need to
107
+ // force them to show. Please note that this feature only works on web-kit browsers,
108
+ // for all other browsers the scroller/indicator will be shown.
109
+ const style = {
110
+ '.scroll-indicator::-webkit-scrollbar': {
111
+ display: overflowXScrollValue,
112
+ ['-webkit-appearance']: `none`,
113
+ height: `8px`
114
+ },
115
+ '.scroll-indicator::-webkit-scrollbar-thumb': {
116
+ backgroundColor: 'rgba(0, 0, 0, 0.5)'
117
+ }
118
+ }
119
+
120
+ useEffect(() => {
121
+ const {clientWidth, scrollWidth} = scrollRef.current
122
+ setHasOverflow(scrollWidth > clientWidth)
123
+ }, [breakpoint, props])
124
+
125
+ return (
126
+ <Box className={'carousel'} sx={style} position="relative" data-testid="carousel">
127
+ <Stack className={'carousel-container'} data-testid="carousel-container" spacing={6}>
128
+ {textHeadline && (
129
+ <Heading as="h2" fontSize="xl" textAlign="center">
130
+ {textHeadline}
131
+ </Heading>
132
+ )}
133
+
134
+ <Stack
135
+ ref={scrollRef}
136
+ className={'carousel-container-items scroll-indicator'}
137
+ data-testid="carousel-container-items"
138
+ direction="row"
139
+ spacing={itemSpacing}
140
+ wrap="nowrap"
141
+ overflowX="scroll"
142
+ sx={{
143
+ scrollPadding: 0,
144
+ scrollSnapType: 'x mandatory',
145
+ WebkitOverflowScrolling: 'touch'
146
+ }}
147
+ >
148
+ {components.map((component, index) => (
149
+ <Box
150
+ key={component?.id || index}
151
+ flex="0 0 auto"
152
+ width={itemWidth}
153
+ style={{scrollSnapAlign: 'start'}}
154
+ >
155
+ <AspectRatio ratio={0.75}>
156
+ <Component component={component} />
157
+ </AspectRatio>
158
+ </Box>
159
+ ))}
160
+ </Stack>
161
+ </Stack>
162
+
163
+ {/* Button Controls */}
164
+ <Fragment>
165
+ <Box
166
+ display={controlDisplay}
167
+ position="absolute"
168
+ top="50%"
169
+ left={{base: 1, lg: 4}}
170
+ transform="translateY(-50%)"
171
+ >
172
+ {/* boxShadow requires !important --> https://github.com/chakra-ui/chakra-ui/issues/3553 */}
173
+ <IconButton
174
+ data-testid="carousel-nav-left"
175
+ aria-label="Scroll carousel left"
176
+ icon={<ChevronLeftIcon color="black" />}
177
+ borderRadius="full"
178
+ colorScheme="whiteAlpha"
179
+ boxShadow={'0 3px 10px rgb(0 0 0 / 20%) !important'}
180
+ onClick={() => scroll(-1)}
181
+ />
182
+ </Box>
183
+
184
+ <Box
185
+ display={controlDisplay}
186
+ position="absolute"
187
+ top="50%"
188
+ right={{base: 1, lg: 4}}
189
+ transform="translateY(-50%)"
190
+ >
191
+ {/* boxShadow requires !important --> https://github.com/chakra-ui/chakra-ui/issues/3553 */}
192
+ <IconButton
193
+ data-testid="carousel-nav-right"
194
+ aria-label="Scroll carousel right"
195
+ icon={<ChevronRightIcon color="black" />}
196
+ borderRadius="full"
197
+ colorScheme="whiteAlpha"
198
+ boxShadow={'0 3px 10px rgb(0 0 0 / 20%) !important'}
199
+ onClick={() => scroll(1)}
200
+ />
201
+ </Box>
202
+ </Fragment>
203
+ </Box>
204
+ )
205
+ }
206
+
207
+ Carousel.propTypes = {
208
+ regions: PropTypes.arrayOf(regionPropType).isRequired,
209
+ textHeadline: PropTypes.string,
210
+ xsCarouselIndicators: PropTypes.bool,
211
+ smCarouselIndicators: PropTypes.bool,
212
+ mdCarouselIndicators: PropTypes.bool,
213
+ xsCarouselControls: PropTypes.bool,
214
+ smCarouselControls: PropTypes.bool,
215
+ xsCarouselSlidesToDisplay: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
216
+ smCarouselSlidesToDisplay: PropTypes.oneOf([1, 2, 3, 4, 5, 6]),
217
+ mdCarouselSlidesToDisplay: PropTypes.oneOf([1, 2, 3, 4, 5, 6])
218
+ }
219
+
220
+ Carousel.displayName = 'Carousel'
221
+
222
+ export default Carousel
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Copyright (c) 2023, 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 {
9
+ renderWithProviders,
10
+ withPageProvider
11
+ } from '@salesforce/retail-react-app/app/utils/test-utils'
12
+ import Carousel from '@salesforce/retail-react-app/app/page-designer/layouts/carousel/index'
13
+
14
+ const SAMPLE_REGION = {
15
+ id: 'TEST_REGION',
16
+ components: [
17
+ {
18
+ id: 'TEST_COMPONENT',
19
+ typeId: 'test-component',
20
+ data: {}
21
+ }
22
+ ]
23
+ }
24
+
25
+ test('Carousel renders without errors', () => {
26
+ const {getByTestId} = renderWithProviders(<Carousel regions={[]} />)
27
+
28
+ expect(getByTestId('carousel')).toBeDefined()
29
+ expect(getByTestId('carousel-container')).toBeDefined()
30
+ expect(getByTestId('carousel-container-items')).toBeDefined()
31
+ expect(getByTestId('carousel-nav-left')).toBeDefined()
32
+ expect(getByTestId('carousel-nav-left')).toBeDefined()
33
+ })
34
+
35
+ test('Carousel renders region/children without errors', () => {
36
+ const CarouselWithPageProvider = withPageProvider(Carousel)
37
+ const {getByTestId} = renderWithProviders(
38
+ <CarouselWithPageProvider regions={[SAMPLE_REGION]} />
39
+ )
40
+
41
+ expect(getByTestId('carousel')).toBeDefined()
42
+ expect(getByTestId('carousel-container-items').childElementCount).toBe(1)
43
+ })
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ export * from './carousel'
9
+ export * from './mobileGrid1r1c'
10
+ export * from './mobileGrid2r1c'
11
+ export * from './mobileGrid2r2c'
12
+ export * from './mobileGrid2r3c'
13
+ export * from './mobileGrid3r1c'
14
+ export * from './mobileGrid3r2c'
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright (c) 2023, 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
+ import React from 'react'
8
+ import PropTypes from 'prop-types'
9
+ import {SimpleGrid} from '@chakra-ui/react'
10
+ import {Region, regionPropType} from '@salesforce/commerce-sdk-react/components'
11
+
12
+ /**
13
+ * This layout component displays its children in a 1 x 1 grid on both mobile and desktop.
14
+ *
15
+ * @param {componentProps} props
16
+ * @param {regionType []} props.regions - The page designer regions for this component.
17
+ * @param {object} props.data - The data for the component.
18
+ * @param {string} props.typeId - A mapping of typeId's to react components representing the type.
19
+ * @returns {React.ReactElement} - Grid component.
20
+ */
21
+ export const MobileGrid1r1c = ({regions}) => (
22
+ <SimpleGrid className="mobile-1r-1c" columns={1}>
23
+ {regions.map((region) => (
24
+ <Region key={region.id} region={region} />
25
+ ))}
26
+ </SimpleGrid>
27
+ )
28
+
29
+ MobileGrid1r1c.displayName = 'MobileGrid1r1c'
30
+
31
+ MobileGrid1r1c.propTypes = {
32
+ // Internally Provided
33
+ regions: PropTypes.arrayOf(regionPropType).isRequired
34
+ }
35
+
36
+ export default MobileGrid1r1c
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright (c) 2023, 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 {
9
+ renderWithProviders,
10
+ withPageProvider
11
+ } from '@salesforce/retail-react-app/app/utils/test-utils'
12
+ import MobileGrid1r1c from '@salesforce/retail-react-app/app/page-designer/layouts/mobileGrid1r1c/index'
13
+
14
+ test('MobileGrid1r1c renders without errors', () => {
15
+ const MobileGrid1r1cWithPageProvider = withPageProvider(MobileGrid1r1c)
16
+ renderWithProviders(
17
+ <MobileGrid1r1cWithPageProvider
18
+ regions={[
19
+ {
20
+ components: [
21
+ {
22
+ data: {
23
+ richText: '<p>Column 1</p>'
24
+ },
25
+ id: '6790e4a41380d31bf54b648e9c',
26
+ typeId: 'commerce_assets.editorialRichText'
27
+ }
28
+ ],
29
+ id: 'column1'
30
+ }
31
+ ]}
32
+ />
33
+ )
34
+ expect(document.querySelector('.mobile-1r-1c')).not.toBeNull()
35
+ })