@salesforce/retail-react-app 1.0.0 → 1.1.0-dev.1

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 (249) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/app/components/_app/index.jsx +6 -2
  3. package/app/components/_app-config/index.jsx +1 -1
  4. package/app/components/_app-config/index.test.js +3 -1
  5. package/app/components/_error/index.jsx +9 -1
  6. package/app/components/action-card/index.jsx +1 -1
  7. package/app/components/address-display/index.jsx +1 -1
  8. package/app/components/basic-tile/index.jsx +7 -1
  9. package/app/components/breadcrumb/index.jsx +1 -1
  10. package/app/components/confirmation-modal/index.jsx +1 -1
  11. package/app/components/confirmation-modal/index.test.js +1 -1
  12. package/app/components/drawer-menu/index.jsx +1 -1
  13. package/app/components/dynamic-image/index.jsx +1 -1
  14. package/app/components/field/index.jsx +1 -1
  15. package/app/components/footer/index.jsx +2 -2
  16. package/app/components/forms/address-fields.jsx +6 -1
  17. package/app/components/forms/credit-card-fields.jsx +9 -1
  18. package/app/components/forms/form-action-buttons.jsx +1 -1
  19. package/app/components/forms/login-fields.jsx +1 -1
  20. package/app/components/forms/password-requirements.jsx +1 -1
  21. package/app/components/forms/post-checkout-registration-fields.jsx +1 -1
  22. package/app/components/forms/profile-fields.jsx +1 -1
  23. package/app/components/forms/promo-code-fields.jsx +1 -1
  24. package/app/components/forms/registration-fields.jsx +1 -1
  25. package/app/components/forms/reset-password-fields.jsx +1 -1
  26. package/app/components/forms/update-password-fields.jsx +6 -1
  27. package/app/components/header/index.jsx +1 -1
  28. package/app/components/header/index.test.js +4 -2
  29. package/app/components/hero/index.jsx +7 -1
  30. package/app/components/icons/index.jsx +1 -1
  31. package/app/components/image-gallery/index.jsx +1 -1
  32. package/app/components/item-variant/item-attributes.jsx +1 -1
  33. package/app/components/item-variant/item-image.jsx +1 -1
  34. package/app/components/item-variant/item-price.jsx +1 -1
  35. package/app/components/link/index.jsx +1 -1
  36. package/app/components/links-list/index.jsx +8 -1
  37. package/app/components/links-list/index.test.js +4 -1
  38. package/app/components/list-menu/index.jsx +1 -1
  39. package/app/components/loading-spinner/index.jsx +1 -1
  40. package/app/components/locale-selector/index.jsx +1 -1
  41. package/app/components/login/index.jsx +7 -1
  42. package/app/components/nested-accordion/index.jsx +1 -1
  43. package/app/components/offline-banner/index.jsx +1 -1
  44. package/app/components/offline-boundary/index.jsx +1 -1
  45. package/app/components/order-summary/index.jsx +9 -1
  46. package/app/components/page-action-placeholder/index.jsx +1 -1
  47. package/app/components/pagination/index.jsx +1 -1
  48. package/app/components/product-item/index.jsx +1 -1
  49. package/app/components/product-scroller/index.jsx +8 -1
  50. package/app/components/product-tile/index.jsx +1 -1
  51. package/app/components/product-view/index.jsx +17 -4
  52. package/app/components/product-view/index.test.js +26 -1
  53. package/app/components/product-view-modal/index.jsx +7 -1
  54. package/app/components/product-view-modal/index.test.js +1 -1
  55. package/app/components/promo-code/index.jsx +1 -1
  56. package/app/components/promo-popover/index.jsx +1 -1
  57. package/app/components/quantity-picker/index.jsx +6 -1
  58. package/app/components/radio-card/index.jsx +1 -1
  59. package/app/components/recommended-products/index.jsx +1 -1
  60. package/app/components/register/index.jsx +7 -1
  61. package/app/components/reset-password/index.jsx +1 -1
  62. package/app/components/responsive/index.jsx +1 -1
  63. package/app/components/search/index.jsx +1 -1
  64. package/app/components/search/partials/recent-searches.jsx +1 -1
  65. package/app/components/search/partials/search-suggestions.jsx +1 -1
  66. package/app/components/search/partials/suggestions.jsx +1 -1
  67. package/app/components/section/index.jsx +7 -1
  68. package/app/components/shared/theme/index.jsx +10 -0
  69. package/app/components/shared/ui/Accordion/index.jsx +8 -0
  70. package/app/components/shared/ui/AccordionButton/index.jsx +8 -0
  71. package/app/components/shared/ui/AccordionIcon/index.jsx +8 -0
  72. package/app/components/shared/ui/AccordionItem/index.jsx +8 -0
  73. package/app/components/shared/ui/AccordionPanel/index.jsx +8 -0
  74. package/app/components/shared/ui/Alert/index.jsx +8 -0
  75. package/app/components/shared/ui/AlertDialog/index.jsx +8 -0
  76. package/app/components/shared/ui/AlertDialogBody/index.jsx +8 -0
  77. package/app/components/shared/ui/AlertDialogContent/index.jsx +8 -0
  78. package/app/components/shared/ui/AlertDialogFooter/index.jsx +8 -0
  79. package/app/components/shared/ui/AlertDialogHeader/index.jsx +8 -0
  80. package/app/components/shared/ui/AlertDialogOverlay/index.jsx +8 -0
  81. package/app/components/shared/ui/AlertIcon/index.jsx +8 -0
  82. package/app/components/shared/ui/AlertTitle/index.jsx +8 -0
  83. package/app/components/shared/ui/AspectRatio/index.jsx +8 -0
  84. package/app/components/shared/ui/Badge/index.jsx +8 -0
  85. package/app/components/shared/ui/Box/index.jsx +8 -0
  86. package/app/components/shared/ui/Breadcrumb/index.jsx +8 -0
  87. package/app/components/shared/ui/BreadcrumbItem/index.jsx +8 -0
  88. package/app/components/shared/ui/BreadcrumbLink/index.jsx +8 -0
  89. package/app/components/shared/ui/Button/index.jsx +8 -0
  90. package/app/components/shared/ui/ButtonGroup/index.jsx +8 -0
  91. package/app/components/shared/ui/Center/index.jsx +8 -0
  92. package/app/components/shared/ui/ChakraProvider/index.jsx +8 -0
  93. package/app/components/shared/ui/Checkbox/index.jsx +8 -0
  94. package/app/components/shared/ui/CloseButton/index.jsx +8 -0
  95. package/app/components/shared/ui/Container/index.jsx +8 -0
  96. package/app/components/shared/ui/Divider/index.jsx +8 -0
  97. package/app/components/shared/ui/Drawer/index.jsx +8 -0
  98. package/app/components/shared/ui/DrawerBody/index.jsx +8 -0
  99. package/app/components/shared/ui/DrawerCloseButton/index.jsx +8 -0
  100. package/app/components/shared/ui/DrawerContent/index.jsx +8 -0
  101. package/app/components/shared/ui/DrawerFooter/index.jsx +8 -0
  102. package/app/components/shared/ui/DrawerHeader/index.jsx +8 -0
  103. package/app/components/shared/ui/DrawerOverlay/index.jsx +8 -0
  104. package/app/components/shared/ui/Fade/index.jsx +8 -0
  105. package/app/components/shared/ui/Flex/index.jsx +8 -0
  106. package/app/components/shared/ui/FormControl/index.jsx +8 -0
  107. package/app/components/shared/ui/FormErrorMessage/index.jsx +8 -0
  108. package/app/components/shared/ui/FormLabel/index.jsx +8 -0
  109. package/app/components/shared/ui/Grid/index.jsx +8 -0
  110. package/app/components/shared/ui/GridItem/index.jsx +8 -0
  111. package/app/components/shared/ui/HStack/index.jsx +8 -0
  112. package/app/components/shared/ui/Heading/index.jsx +8 -0
  113. package/app/components/shared/ui/Icon/index.jsx +8 -0
  114. package/app/components/shared/ui/IconButton/index.jsx +8 -0
  115. package/app/components/shared/ui/Image/index.jsx +8 -0
  116. package/app/components/shared/ui/Img/index.jsx +8 -0
  117. package/app/components/shared/ui/Input/index.jsx +8 -0
  118. package/app/components/shared/ui/InputGroup/index.jsx +8 -0
  119. package/app/components/shared/ui/InputLeftElement/index.jsx +8 -0
  120. package/app/components/shared/ui/InputRightElement/index.jsx +8 -0
  121. package/app/components/shared/ui/Link/index.jsx +8 -0
  122. package/app/components/shared/ui/List/index.jsx +8 -0
  123. package/app/components/shared/ui/ListItem/index.jsx +8 -0
  124. package/app/components/shared/ui/Modal/index.jsx +8 -0
  125. package/app/components/shared/ui/ModalBody/index.jsx +8 -0
  126. package/app/components/shared/ui/ModalCloseButton/index.jsx +8 -0
  127. package/app/components/shared/ui/ModalContent/index.jsx +8 -0
  128. package/app/components/shared/ui/ModalFooter/index.jsx +8 -0
  129. package/app/components/shared/ui/ModalHeader/index.jsx +8 -0
  130. package/app/components/shared/ui/ModalOverlay/index.jsx +8 -0
  131. package/app/components/shared/ui/Popover/index.jsx +8 -0
  132. package/app/components/shared/ui/PopoverArrow/index.jsx +8 -0
  133. package/app/components/shared/ui/PopoverBody/index.jsx +8 -0
  134. package/app/components/shared/ui/PopoverCloseButton/index.jsx +8 -0
  135. package/app/components/shared/ui/PopoverContent/index.jsx +8 -0
  136. package/app/components/shared/ui/PopoverFooter/index.jsx +8 -0
  137. package/app/components/shared/ui/PopoverHeader/index.jsx +8 -0
  138. package/app/components/shared/ui/PopoverTrigger/index.jsx +8 -0
  139. package/app/components/shared/ui/Portal/index.jsx +8 -0
  140. package/app/components/shared/ui/Radio/index.jsx +8 -0
  141. package/app/components/shared/ui/RadioGroup/index.jsx +8 -0
  142. package/app/components/shared/ui/Select/index.jsx +8 -0
  143. package/app/components/shared/ui/SimpleGrid/index.jsx +8 -0
  144. package/app/components/shared/ui/Skeleton/index.jsx +8 -0
  145. package/app/components/shared/ui/Spacer/index.jsx +8 -0
  146. package/app/components/shared/ui/Spinner/index.jsx +8 -0
  147. package/app/components/shared/ui/Stack/index.jsx +8 -0
  148. package/app/components/shared/ui/StackDivider/index.jsx +8 -0
  149. package/app/components/shared/ui/StylesProvider/index.jsx +8 -0
  150. package/app/components/shared/ui/Text/index.jsx +8 -0
  151. package/app/components/shared/ui/Tooltip/index.jsx +8 -0
  152. package/app/components/shared/ui/VStack/index.jsx +8 -0
  153. package/app/components/shared/ui/Wrap/index.jsx +8 -0
  154. package/app/components/shared/ui/WrapItem/index.jsx +8 -0
  155. package/app/components/shared/ui/createStylesContext/index.jsx +8 -0
  156. package/app/components/shared/ui/extendTheme/index.jsx +8 -0
  157. package/app/components/shared/ui/index.jsx +107 -0
  158. package/app/components/shared/ui/useBreakpoint/index.jsx +8 -0
  159. package/app/components/shared/ui/useBreakpointValue/index.jsx +8 -0
  160. package/app/components/shared/ui/useDisclosure/index.jsx +8 -0
  161. package/app/components/shared/ui/useMediaQuery/index.jsx +8 -0
  162. package/app/components/shared/ui/useMultiStyleConfig/index.jsx +8 -0
  163. package/app/components/shared/ui/useNumberInput/index.jsx +8 -0
  164. package/app/components/shared/ui/useRadio/index.jsx +8 -0
  165. package/app/components/shared/ui/useRadioGroup/index.jsx +8 -0
  166. package/app/components/shared/ui/useStyleConfig/index.jsx +8 -0
  167. package/app/components/shared/ui/useStyles/index.jsx +8 -0
  168. package/app/components/shared/ui/useTheme/index.jsx +8 -0
  169. package/app/components/shared/ui/useToast/index.jsx +8 -0
  170. package/app/components/shared/util/SkipNavContent/index.jsx +8 -0
  171. package/app/components/shared/util/SkipNavLink/index.jsx +8 -0
  172. package/app/components/shared/util/index.jsx +9 -0
  173. package/app/components/social-icons/index.jsx +1 -1
  174. package/app/components/swatch-group/index.jsx +6 -1
  175. package/app/components/swatch-group/index.test.js +1 -1
  176. package/app/components/swatch-group/swatch.jsx +6 -1
  177. package/app/components/toggle-card/index.jsx +7 -1
  178. package/app/components/with-registration/index.test.js +1 -1
  179. package/app/hooks/use-add-to-cart-modal.js +1 -1
  180. package/app/hooks/use-auth-modal.js +1 -1
  181. package/app/hooks/use-current-basket.js +3 -6
  182. package/app/hooks/use-toast.js +1 -1
  183. package/app/hooks/use-toast.test.js +1 -1
  184. package/app/page-designer/README.md +2 -2
  185. package/app/page-designer/assets/image-tile/index.jsx +1 -1
  186. package/app/page-designer/assets/image-with-text/index.jsx +6 -1
  187. package/app/page-designer/layouts/carousel/index.jsx +1 -1
  188. package/app/page-designer/layouts/mobileGrid1r1c/index.jsx +1 -1
  189. package/app/page-designer/layouts/mobileGrid2r1c/index.jsx +1 -1
  190. package/app/page-designer/layouts/mobileGrid2r2c/index.jsx +1 -1
  191. package/app/page-designer/layouts/mobileGrid2r3c/index.jsx +1 -1
  192. package/app/page-designer/layouts/mobileGrid3r1c/index.jsx +1 -1
  193. package/app/page-designer/layouts/mobileGrid3r2c/index.jsx +1 -1
  194. package/app/pages/account/addresses.jsx +1 -1
  195. package/app/pages/account/index.jsx +1 -1
  196. package/app/pages/account/order-detail.jsx +1 -1
  197. package/app/pages/account/order-history.jsx +1 -1
  198. package/app/pages/account/profile.jsx +1 -1
  199. package/app/pages/account/wishlist/index.jsx +1 -1
  200. package/app/pages/account/wishlist/partials/wishlist-primary-action.jsx +1 -1
  201. package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.jsx +5 -1
  202. package/app/pages/cart/index.jsx +9 -1
  203. package/app/pages/cart/partials/cart-cta.jsx +1 -1
  204. package/app/pages/cart/partials/cart-secondary-button-group.jsx +1 -1
  205. package/app/pages/cart/partials/cart-skeleton.jsx +1 -1
  206. package/app/pages/cart/partials/cart-title.jsx +1 -1
  207. package/app/pages/cart/partials/empty-cart.jsx +7 -1
  208. package/app/pages/checkout/confirmation.jsx +1 -1
  209. package/app/pages/checkout/index.jsx +10 -1
  210. package/app/pages/checkout/index.test.js +10 -0
  211. package/app/pages/checkout/partials/cc-radio-group.jsx +9 -1
  212. package/app/pages/checkout/partials/checkout-footer.jsx +1 -1
  213. package/app/pages/checkout/partials/checkout-header.jsx +7 -1
  214. package/app/pages/checkout/partials/checkout-skeleton.jsx +8 -1
  215. package/app/pages/checkout/partials/contact-info.jsx +8 -2
  216. package/app/pages/checkout/partials/payment-form.jsx +9 -1
  217. package/app/pages/checkout/partials/payment.jsx +10 -1
  218. package/app/pages/checkout/partials/shipping-address-selection.jsx +8 -1
  219. package/app/pages/checkout/partials/shipping-options.jsx +10 -1
  220. package/app/pages/home/index.jsx +1 -1
  221. package/app/pages/login/index.jsx +1 -1
  222. package/app/pages/page-not-found/index.jsx +8 -1
  223. package/app/pages/product-detail/index.jsx +8 -1
  224. package/app/pages/product-detail/index.mock.js +14 -0
  225. package/app/pages/product-detail/index.test.js +69 -6
  226. package/app/pages/product-detail/partials/information-accordion.jsx +1 -1
  227. package/app/pages/product-list/index.jsx +1 -1
  228. package/app/pages/product-list/partials/checkbox-refinements.jsx +1 -1
  229. package/app/pages/product-list/partials/color-refinements.jsx +9 -1
  230. package/app/pages/product-list/partials/empty-results.jsx +7 -1
  231. package/app/pages/product-list/partials/link-refinements.jsx +1 -1
  232. package/app/pages/product-list/partials/page-header.jsx +1 -1
  233. package/app/pages/product-list/partials/radio-refinements.jsx +7 -1
  234. package/app/pages/product-list/partials/refinements.jsx +1 -1
  235. package/app/pages/product-list/partials/selected-refinements.jsx +1 -1
  236. package/app/pages/product-list/partials/size-refinements.jsx +6 -1
  237. package/app/pages/registration/index.jsx +1 -1
  238. package/app/pages/reset-password/index.jsx +7 -1
  239. package/app/routes.jsx +1 -1
  240. package/app/ssr.js +9 -8
  241. package/app/theme/components/project/_app.js +1 -1
  242. package/app/theme/index.js +1 -1
  243. package/app/utils/responsive-image.js +1 -1
  244. package/app/utils/test-utils.js +1 -1
  245. package/config/default.js +1 -1
  246. package/config/mocks/default.js +1 -1
  247. package/jest-setup.js +3 -2
  248. package/jsconfig.json +1 -1
  249. package/package.json +6 -6
@@ -7,7 +7,15 @@
7
7
  import React from 'react'
8
8
  import PropTypes from 'prop-types'
9
9
  import {FormattedMessage} from 'react-intl'
10
- import {Box, Button, Stack, Text, SimpleGrid, FormControl, FormErrorMessage} from '@chakra-ui/react'
10
+ import {
11
+ Box,
12
+ Button,
13
+ Stack,
14
+ Text,
15
+ SimpleGrid,
16
+ FormControl,
17
+ FormErrorMessage
18
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
11
19
  import {PlusIcon} from '@salesforce/retail-react-app/app/components/icons'
12
20
  import {RadioCard, RadioCardGroup} from '@salesforce/retail-react-app/app/components/radio-card'
13
21
  import {getCreditCardIcon} from '@salesforce/retail-react-app/app/utils/cc-utils'
@@ -17,7 +17,7 @@ import {
17
17
  Flex,
18
18
  Spacer,
19
19
  useStyles
20
- } from '@chakra-ui/react'
20
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
21
21
  import LinksList from '@salesforce/retail-react-app/app/components/links-list'
22
22
  import {
23
23
  VisaIcon,
@@ -6,7 +6,13 @@
6
6
  */
7
7
  import React from 'react'
8
8
  import {FormattedMessage} from 'react-intl'
9
- import {Badge, Box, Button, Flex, Center} from '@chakra-ui/react'
9
+ import {
10
+ Badge,
11
+ Box,
12
+ Button,
13
+ Flex,
14
+ Center
15
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
16
  import Link from '@salesforce/retail-react-app/app/components/link'
11
17
  import {BasketIcon, BrandLogo} from '@salesforce/retail-react-app/app/components/icons'
12
18
  import {HOME_HREF} from '@salesforce/retail-react-app/app/constants'
@@ -5,7 +5,14 @@
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
7
  import React from 'react'
8
- import {Box, Container, Grid, GridItem, Skeleton, Stack} from '@chakra-ui/react'
8
+ import {
9
+ Box,
10
+ Container,
11
+ Grid,
12
+ GridItem,
13
+ Skeleton,
14
+ Stack
15
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
9
16
 
10
17
  const CheckoutSkeleton = () => {
11
18
  return (
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: BSD-3-Clause
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- import React, {useRef, useState} from 'react'
7
+ import React, {useEffect, useRef, useState} from 'react'
8
8
  import PropTypes from 'prop-types'
9
9
  import {
10
10
  Alert,
@@ -20,7 +20,7 @@ import {
20
20
  Container,
21
21
  Stack,
22
22
  Text
23
- } from '@chakra-ui/react'
23
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
24
24
  import {useForm} from 'react-hook-form'
25
25
  import {FormattedMessage, useIntl} from 'react-intl'
26
26
  import {useCheckout} from '@salesforce/retail-react-app/app/pages/checkout/util/checkout-context'
@@ -96,6 +96,12 @@ const ContactInfo = () => {
96
96
  authModal.onOpen()
97
97
  }
98
98
 
99
+ useEffect(() => {
100
+ if (!showPasswordField) {
101
+ form.unregister('password')
102
+ }
103
+ }, [showPasswordField])
104
+
99
105
  return (
100
106
  <ToggleCard
101
107
  id="step-0"
@@ -7,7 +7,15 @@
7
7
  import React from 'react'
8
8
  import {FormattedMessage, FormattedNumber, useIntl} from 'react-intl'
9
9
  import PropTypes from 'prop-types'
10
- import {Box, Flex, Radio, RadioGroup, Stack, Text, Tooltip} from '@chakra-ui/react'
10
+ import {
11
+ Box,
12
+ Flex,
13
+ Radio,
14
+ RadioGroup,
15
+ Stack,
16
+ Text,
17
+ Tooltip
18
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
11
19
  import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
12
20
  import {LockIcon, PaypalIcon} from '@salesforce/retail-react-app/app/components/icons'
13
21
  import CreditCardFields from '@salesforce/retail-react-app/app/components/forms/credit-card-fields'
@@ -7,7 +7,16 @@
7
7
  import React, {useState} from 'react'
8
8
  import PropTypes from 'prop-types'
9
9
  import {FormattedMessage, useIntl} from 'react-intl'
10
- import {Box, Button, Checkbox, Container, Heading, Stack, Text, Divider} from '@chakra-ui/react'
10
+ import {
11
+ Box,
12
+ Button,
13
+ Checkbox,
14
+ Container,
15
+ Heading,
16
+ Stack,
17
+ Text,
18
+ Divider
19
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
11
20
  import {useForm} from 'react-hook-form'
12
21
  import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
13
22
  import {useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'
@@ -7,7 +7,14 @@
7
7
  import React, {useState, useEffect} from 'react'
8
8
  import PropTypes from 'prop-types'
9
9
  import {defineMessage, FormattedMessage, useIntl} from 'react-intl'
10
- import {Box, Button, Container, Heading, SimpleGrid, Stack} from '@chakra-ui/react'
10
+ import {
11
+ Box,
12
+ Button,
13
+ Container,
14
+ Heading,
15
+ SimpleGrid,
16
+ Stack
17
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
11
18
  import {useForm, Controller} from 'react-hook-form'
12
19
  import {shallowEquals} from '@salesforce/retail-react-app/app/utils/utils'
13
20
  import {RadioCard, RadioCardGroup} from '@salesforce/retail-react-app/app/components/radio-card'
@@ -6,7 +6,16 @@
6
6
  */
7
7
  import React, {useEffect} from 'react'
8
8
  import {FormattedMessage, FormattedNumber, useIntl} from 'react-intl'
9
- import {Box, Button, Container, Flex, Radio, RadioGroup, Stack, Text} from '@chakra-ui/react'
9
+ import {
10
+ Box,
11
+ Button,
12
+ Container,
13
+ Flex,
14
+ Radio,
15
+ RadioGroup,
16
+ Stack,
17
+ Text
18
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
19
  import {useForm, Controller} from 'react-hook-form'
11
20
  import {useCheckout} from '@salesforce/retail-react-app/app/pages/checkout/util/checkout-context'
12
21
  import {ChevronDownIcon} from '@salesforce/retail-react-app/app/components/icons'
@@ -21,7 +21,7 @@ import {
21
21
  Stack,
22
22
  Container,
23
23
  Link
24
- } from '@chakra-ui/react'
24
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
25
25
 
26
26
  // Project Components
27
27
  import Hero from '@salesforce/retail-react-app/app/components/hero'
@@ -8,7 +8,7 @@
8
8
  import React, {useEffect} from 'react'
9
9
  import PropTypes from 'prop-types'
10
10
  import {useIntl, defineMessage} from 'react-intl'
11
- import {Box, Container} from '@chakra-ui/react'
11
+ import {Box, Container} from '@salesforce/retail-react-app/app/components/shared/ui'
12
12
  import {
13
13
  AuthHelpers,
14
14
  useAuthHelper,
@@ -6,7 +6,14 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Box, Heading, Flex, Button, Stack, Text} from '@chakra-ui/react'
9
+ import {
10
+ Box,
11
+ Heading,
12
+ Flex,
13
+ Button,
14
+ Stack,
15
+ Text
16
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
17
  import {Helmet} from 'react-helmet'
11
18
  import {useIntl} from 'react-intl'
12
19
  import {useServerContext} from '@salesforce/pwa-kit-react-sdk/ssr/universal/hooks'
@@ -11,7 +11,7 @@ import {Helmet} from 'react-helmet'
11
11
  import {FormattedMessage, useIntl} from 'react-intl'
12
12
 
13
13
  // Components
14
- import {Box, Button, Stack} from '@chakra-ui/react'
14
+ import {Box, Button, Stack} from '@salesforce/retail-react-app/app/components/shared/ui'
15
15
  import {
16
16
  useProduct,
17
17
  useCategory,
@@ -61,6 +61,7 @@ const ProductDetail = () => {
61
61
  if (res) {
62
62
  res.set('Cache-Control', `max-age=${MAX_CACHE_AGE}`)
63
63
  }
64
+ const isBasketLoading = !basket?.basketId
64
65
 
65
66
  /*************************** Product Detail and Category ********************/
66
67
  const {productId} = useParams()
@@ -264,6 +265,7 @@ const ProductDetail = () => {
264
265
  addToCart={handleProductSetAddToCart}
265
266
  addToWishlist={handleAddToWishlist}
266
267
  isProductLoading={isProductLoading}
268
+ isBasketLoading={isBasketLoading}
267
269
  isWishlistLoading={isWishlistLoading}
268
270
  validateOrderability={handleProductSetValidation}
269
271
  />
@@ -310,6 +312,7 @@ const ProductDetail = () => {
310
312
  }
311
313
  }}
312
314
  isProductLoading={isProductLoading}
315
+ isBasketLoading={isBasketLoading}
313
316
  isWishlistLoading={isWishlistLoading}
314
317
  />
315
318
  <InformationAccordion product={childProduct} />
@@ -331,6 +334,7 @@ const ProductDetail = () => {
331
334
  }
332
335
  addToWishlist={handleAddToWishlist}
333
336
  isProductLoading={isProductLoading}
337
+ isBasketLoading={isBasketLoading}
334
338
  isWishlistLoading={isWishlistLoading}
335
339
  />
336
340
  <InformationAccordion product={product} />
@@ -367,6 +371,9 @@ const ProductDetail = () => {
367
371
  />
368
372
 
369
373
  <RecommendedProducts
374
+ // The Recently Viewed recommender doesn't use `products`, so instead we
375
+ // provide a key to update the recommendations on navigation.
376
+ key={location.key}
370
377
  title={
371
378
  <FormattedMessage
372
379
  defaultMessage="Recently Viewed"
@@ -195,3 +195,17 @@ export const basketWithProductSet = {
195
195
  taxation: 'gross',
196
196
  tax_total: null
197
197
  }
198
+
199
+ export const einsteinRecommendation = {
200
+ recs: [
201
+ {
202
+ id: '11736753M',
203
+ product_name: 'Summer Bomber Jacket',
204
+ image_url:
205
+ 'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZCU_007/on/demandware.static/-/Sites-apparel-m-catalog/default/dw5e894c3a/images/large/B0574182_001_L1.jpg',
206
+ product_url:
207
+ 'https://zzcu-007.sandbox.us01.dx.commercecloud.salesforce.com/mens-summer-bomber-jacket/11736753M.html?lang=en_US'
208
+ }
209
+ ],
210
+ recoUUID: '79e9f44e-c4d3-405a-ae4c-eba7b4bfdd4a'
211
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2021, salesforce.com, inc.
2
+ * Copyright (c) 2023, Salesforce, Inc.
3
3
  * All rights reserved.
4
4
  * SPDX-License-Identifier: BSD-3-Clause
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
@@ -15,8 +15,12 @@ import {Route, Switch} from 'react-router-dom'
15
15
  import {rest} from 'msw'
16
16
  import ProductDetail from '.'
17
17
  import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
18
- import {basketWithProductSet} from '@salesforce/retail-react-app/app/pages/product-detail/index.mock'
18
+ import {
19
+ basketWithProductSet,
20
+ einsteinRecommendation
21
+ } from '@salesforce/retail-react-app/app/pages/product-detail/index.mock'
19
22
  import mockedProductSet from '@salesforce/retail-react-app/app/mocks/product-set-winter-lookM'
23
+ import userEvent from '@testing-library/user-event'
20
24
 
21
25
  jest.setTimeout(60000)
22
26
 
@@ -26,7 +30,7 @@ const MockedComponent = () => {
26
30
  return (
27
31
  <Switch>
28
32
  <Route
29
- path="/en-GB/product/:productId"
33
+ path="/uk/en-GB/product/:productId"
30
34
  render={(props) => <ProductDetail {...props} />}
31
35
  />
32
36
  </Switch>
@@ -51,7 +55,7 @@ beforeEach(() => {
51
55
 
52
56
  // Since we're testing some navigation logic, we are using a simple Router
53
57
  // around our component. We need to initialize the default route/path here.
54
- window.history.pushState({}, 'ProductDetail', '/en-GB/product/test-product')
58
+ window.history.pushState({}, 'ProductDetail', '/uk/en-GB/product/test-product')
55
59
  })
56
60
 
57
61
  afterEach(() => {
@@ -100,8 +104,13 @@ describe('product set', () => {
100
104
  })
101
105
 
102
106
  test('add the set to cart successfully', async () => {
103
- const urlPathAfterSelectingAllVariants =
104
- '/en-GB/product/winter-lookM?25518447M=color%3DJJ5FUXX%26size%3D9MD&25518704M=color%3DJJ2XNXX%26size%3D9MD&25772717M=color%3DTAUPETX%26size%3D070%26width%3DM'
107
+ const urlPathAfterSelectingAllVariants = `/uk/en-GB/product/winter-lookM?${new URLSearchParams(
108
+ {
109
+ '25518447M': 'color=JJ5FUXX&size=9MD',
110
+ '25518704M': 'color=JJ2XNXX&size=9MD',
111
+ '25772717M': 'color=TAUPETX&size=070&width=M'
112
+ }
113
+ )}`
105
114
  window.history.pushState({}, 'ProductDetail', urlPathAfterSelectingAllVariants)
106
115
 
107
116
  // Initial basket is necessary to add items to it
@@ -160,3 +169,57 @@ describe('product set', () => {
160
169
  })
161
170
  })
162
171
  })
172
+
173
+ describe('Recommended Products', () => {
174
+ let fetchMock
175
+ beforeAll(() => {
176
+ // This is probably more complex than it needs to be? I tried using jest-fetch-mock and msw,
177
+ // but I couldn't get those working...
178
+ fetchMock = jest.spyOn(global, 'fetch').mockImplementation(async (url) => {
179
+ const json = url.endsWith('viewed-recently-einstein') ? einsteinRecommendation : {}
180
+ return new Response(JSON.stringify(json))
181
+ })
182
+ })
183
+ beforeEach(() => {
184
+ fetchMock.mockClear()
185
+ })
186
+ afterAll(() => {
187
+ fetchMock.mockRestore()
188
+ })
189
+ test('Recently Viewed gets updated when navigating between products', async () => {
190
+ global.server.use(
191
+ // Use a single product (and not a product set)
192
+ rest.get('*/products/:productId', (req, res, ctx) => {
193
+ return res(ctx.json(productsResponse.data[0]))
194
+ }),
195
+ rest.get('*/products', (req, res, ctx) => {
196
+ return res(ctx.json({}))
197
+ })
198
+ )
199
+ const user = userEvent.setup({advanceTimers: jest.advanceTimersByTime})
200
+ renderWithProviders(<MockedComponent />)
201
+
202
+ // If we poll for updates immediately, the test output is flooded with errors:
203
+ // "Warning: An update to WrappedComponent inside a test was not wrapped in act(...)."
204
+ // If we wait to poll until the component is updated, then the errors disappear. Using a
205
+ // timeout is clearly a suboptimal solution, but I don't know the "correct" way to fix it.
206
+ let done = false
207
+ setTimeout(() => (done = true), 200)
208
+ await waitFor(() => expect(done).toBeTruthy())
209
+
210
+ expect(await screen.findAllByText(/Long Sleeve Crew Neck/)).toHaveLength(2)
211
+ expect(await screen.findByText(/Summer Bomber Jacket/)).toBeInTheDocument()
212
+
213
+ // We requested Recently Viewed products on the first page load, but we
214
+ // only want to check against the second page load
215
+ fetchMock.mockClear()
216
+ await user.click(screen.getByText(/Summer Bomber Jacket/))
217
+
218
+ // The scope of this test means we just care about the Recently Viewed component being
219
+ // updated - we don't need to wait for the rest of the page loading
220
+ expect(fetchMock).toHaveBeenCalledWith(
221
+ expect.stringMatching(/viewed-recently-einstein$/),
222
+ expect.any(Object)
223
+ )
224
+ })
225
+ })
@@ -15,7 +15,7 @@ import {
15
15
  AccordionIcon,
16
16
  Box,
17
17
  Stack
18
- } from '@chakra-ui/react'
18
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
19
19
  import {useIntl} from 'react-intl'
20
20
 
21
21
  const InformationAccordion = ({product}) => {
@@ -43,7 +43,7 @@ import {
43
43
  DrawerOverlay,
44
44
  DrawerContent,
45
45
  DrawerCloseButton
46
- } from '@chakra-ui/react'
46
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
47
47
 
48
48
  // Project Components
49
49
  import Pagination from '@salesforce/retail-react-app/app/components/pagination'
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Box, Checkbox, Stack} from '@chakra-ui/react'
9
+ import {Box, Checkbox, Stack} from '@salesforce/retail-react-app/app/components/shared/ui'
10
10
  import PropTypes from 'prop-types'
11
11
 
12
12
  const CheckboxRefinements = ({filter, toggleFilter, selectedFilters}) => {
@@ -6,7 +6,15 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Box, SimpleGrid, HStack, Text, Button, Center, useMultiStyleConfig} from '@chakra-ui/react'
9
+ import {
10
+ Box,
11
+ SimpleGrid,
12
+ HStack,
13
+ Text,
14
+ Button,
15
+ Center,
16
+ useMultiStyleConfig
17
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
18
  import PropTypes from 'prop-types'
11
19
  import {cssColorGroups} from '@salesforce/retail-react-app/app/constants'
12
20
 
@@ -6,7 +6,13 @@
6
6
  */
7
7
 
8
8
  import React, {Fragment} from 'react'
9
- import {Button, Text, Flex, Stack, Link} from '@chakra-ui/react'
9
+ import {
10
+ Button,
11
+ Text,
12
+ Flex,
13
+ Stack,
14
+ Link
15
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
16
  import PropTypes from 'prop-types'
11
17
  import {Link as RouteLink} from 'react-router-dom'
12
18
  import {defineMessage, FormattedMessage, useIntl} from 'react-intl'
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Stack, Text} from '@chakra-ui/react'
9
+ import {Stack, Text} from '@salesforce/retail-react-app/app/components/shared/ui'
10
10
  import PropTypes from 'prop-types'
11
11
  import Link from '@salesforce/retail-react-app/app/components/link'
12
12
 
@@ -8,7 +8,7 @@
8
8
  import React from 'react'
9
9
  import PropTypes from 'prop-types'
10
10
  // Components
11
- import {Box, Heading, Flex, Text, Fade} from '@chakra-ui/react'
11
+ import {Box, Heading, Flex, Text, Fade} from '@salesforce/retail-react-app/app/components/shared/ui'
12
12
 
13
13
  // Project Components
14
14
  import Breadcrumb from '@salesforce/retail-react-app/app/components/breadcrumb'
@@ -6,7 +6,13 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Box, Text, Radio, RadioGroup, Stack} from '@chakra-ui/react'
9
+ import {
10
+ Box,
11
+ Text,
12
+ Radio,
13
+ RadioGroup,
14
+ Stack
15
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
16
  import PropTypes from 'prop-types'
11
17
 
12
18
  const RadioRefinements = ({filter, toggleFilter, selectedFilters}) => {
@@ -15,7 +15,7 @@ import {
15
15
  AccordionButton,
16
16
  AccordionPanel,
17
17
  AccordionIcon
18
- } from '@chakra-ui/react'
18
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
19
19
  import PropTypes from 'prop-types'
20
20
  import ColorRefinements from '@salesforce/retail-react-app/app/pages/product-list/partials/color-refinements'
21
21
  import SizeRefinements from '@salesforce/retail-react-app/app/pages/product-list/partials/size-refinements'
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {Box, Button, Wrap, WrapItem} from '@chakra-ui/react'
9
+ import {Box, Button, Wrap, WrapItem} from '@salesforce/retail-react-app/app/components/shared/ui'
10
10
  import PropTypes from 'prop-types'
11
11
  import {CloseIcon} from '@salesforce/retail-react-app/app/components/icons'
12
12
 
@@ -6,7 +6,12 @@
6
6
  */
7
7
 
8
8
  import React from 'react'
9
- import {SimpleGrid, Button, Center, useMultiStyleConfig} from '@chakra-ui/react'
9
+ import {
10
+ SimpleGrid,
11
+ Button,
12
+ Center,
13
+ useMultiStyleConfig
14
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
10
15
  import PropTypes from 'prop-types'
11
16
 
12
17
  const SizeRefinements = ({filter, toggleFilter, selectedFilters}) => {
@@ -8,7 +8,7 @@
8
8
  import React, {useEffect} from 'react'
9
9
  import PropTypes from 'prop-types'
10
10
  import {useIntl} from 'react-intl'
11
- import {Box, Container} from '@chakra-ui/react'
11
+ import {Box, Container} from '@salesforce/retail-react-app/app/components/shared/ui'
12
12
  import {AuthHelpers, useAuthHelper, useCustomerType} from '@salesforce/commerce-sdk-react'
13
13
  import {useForm} from 'react-hook-form'
14
14
  import {useLocation} from 'react-router-dom'
@@ -8,7 +8,13 @@
8
8
  import React, {useState, useEffect} from 'react'
9
9
  import PropTypes from 'prop-types'
10
10
  import {FormattedMessage} from 'react-intl'
11
- import {Box, Button, Container, Stack, Text} from '@chakra-ui/react'
11
+ import {
12
+ Box,
13
+ Button,
14
+ Container,
15
+ Stack,
16
+ Text
17
+ } from '@salesforce/retail-react-app/app/components/shared/ui'
12
18
  import {useForm} from 'react-hook-form'
13
19
  import {
14
20
  useShopperCustomersMutation,
package/app/routes.jsx CHANGED
@@ -17,7 +17,7 @@ import loadable from '@loadable/component'
17
17
  import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
18
18
 
19
19
  // Components
20
- import {Skeleton} from '@chakra-ui/react'
20
+ import {Skeleton} from '@salesforce/retail-react-app/app/components/shared/ui'
21
21
  import {configureRoutes} from '@salesforce/retail-react-app/app/utils/routes-utils'
22
22
 
23
23
  const fallback = <Skeleton height="75vh" width="100%" />
package/app/ssr.js CHANGED
@@ -4,14 +4,14 @@
4
4
  * SPDX-License-Identifier: BSD-3-Clause
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- /* eslint-disable @typescript-eslint/no-var-requires */
7
+
8
8
  'use strict'
9
9
 
10
- const path = require('path')
11
- const {getRuntime} = require('@salesforce/pwa-kit-runtime/ssr/server/express')
12
- const {isRemote} = require('@salesforce/pwa-kit-runtime/utils/ssr-server')
13
- const {getConfig} = require('@salesforce/pwa-kit-runtime/utils/ssr-config')
14
- const helmet = require('helmet')
10
+ import path from 'path'
11
+ import {getRuntime} from '@salesforce/pwa-kit-runtime/ssr/server/express'
12
+ import {isRemote} from '@salesforce/pwa-kit-runtime/utils/ssr-server'
13
+ import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
14
+ import helmet from 'helmet'
15
15
 
16
16
  const options = {
17
17
  // The build directory (an absolute path)
@@ -27,7 +27,8 @@ const options = {
27
27
  port: 3000,
28
28
 
29
29
  // The protocol on which the development Express app listens.
30
- // Note that http://localhost is treated as a secure context for development.
30
+ // Note that http://localhost is treated as a secure context for development,
31
+ // except by Safari.
31
32
  protocol: 'http'
32
33
  }
33
34
 
@@ -67,4 +68,4 @@ const {handler} = runtime.createHandler(options, (app) => {
67
68
  })
68
69
  // SSR requires that we export a single handler function called 'get', that
69
70
  // supports AWS use of the server that we created above.
70
- exports.get = handler
71
+ export const get = handler
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: BSD-3-Clause
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- import theme from '@chakra-ui/theme'
7
+ import theme from '@salesforce/retail-react-app/app/components/shared/theme'
8
8
 
9
9
  export default {
10
10
  baseStyle: {
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: BSD-3-Clause
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- import {extendTheme} from '@chakra-ui/react'
7
+ import {extendTheme} from '@salesforce/retail-react-app/app/components/shared/ui'
8
8
 
9
9
  // Foundational style overrides
10
10
  import styles from '@salesforce/retail-react-app/app/theme/foundations/styles'
@@ -5,7 +5,7 @@
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
7
 
8
- import theme from '@chakra-ui/theme'
8
+ import theme from '@salesforce/retail-react-app/app/components/shared/theme'
9
9
 
10
10
  /**
11
11
  * @param {Object} breakpoints
@@ -7,7 +7,7 @@
7
7
  import React, {useEffect, useRef} from 'react'
8
8
  import {render} from '@testing-library/react'
9
9
  import {BrowserRouter as Router} from 'react-router-dom'
10
- import {ChakraProvider} from '@chakra-ui/react'
10
+ import {ChakraProvider} from '@salesforce/retail-react-app/app/components/shared/ui'
11
11
  import PropTypes from 'prop-types'
12
12
 
13
13
  import theme from '@salesforce/retail-react-app/app/theme'
package/config/default.js CHANGED
@@ -49,7 +49,7 @@ module.exports = {
49
49
  '**/*.json'
50
50
  ],
51
51
  ssrParameters: {
52
- ssrFunctionNodeVersion: '16.x',
52
+ ssrFunctionNodeVersion: '18.x',
53
53
  proxyConfigs: [
54
54
  {
55
55
  host: 'kv7kzm78.api.commercecloud.salesforce.com',