@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.
- package/.eslintignore +7 -0
- package/.eslintrc.js +25 -0
- package/.prettierignore +4 -0
- package/.prettierrc.yaml +7 -0
- package/CHANGELOG.md +173 -0
- package/LICENSE +14 -0
- package/README.md +48 -0
- package/app/assets/svg/account.svg +3 -0
- package/app/assets/svg/alert.svg +3 -0
- package/app/assets/svg/basket.svg +3 -0
- package/app/assets/svg/brand-logo.svg +10 -0
- package/app/assets/svg/cc-amex.svg +7 -0
- package/app/assets/svg/cc-cvv.svg +8 -0
- package/app/assets/svg/cc-discover.svg +14 -0
- package/app/assets/svg/cc-mastercard.svg +8 -0
- package/app/assets/svg/cc-visa.svg +11 -0
- package/app/assets/svg/check-circle.svg +3 -0
- package/app/assets/svg/check.svg +3 -0
- package/app/assets/svg/chevron-down.svg +3 -0
- package/app/assets/svg/chevron-left.svg +3 -0
- package/app/assets/svg/chevron-right.svg +3 -0
- package/app/assets/svg/chevron-up.svg +3 -0
- package/app/assets/svg/close.svg +3 -0
- package/app/assets/svg/dashboard.svg +4 -0
- package/app/assets/svg/figma-logo.svg +14 -0
- package/app/assets/svg/file.svg +3 -0
- package/app/assets/svg/filter.svg +3 -0
- package/app/assets/svg/flag-ca.svg +5 -0
- package/app/assets/svg/flag-cn.svg +19 -0
- package/app/assets/svg/flag-fr.svg +19 -0
- package/app/assets/svg/flag-gb.svg +16 -0
- package/app/assets/svg/flag-it.svg +29 -0
- package/app/assets/svg/flag-jp.svg +10 -0
- package/app/assets/svg/flag-us.svg +7 -0
- package/app/assets/svg/github-logo.svg +40 -0
- package/app/assets/svg/hamburger.svg +8 -0
- package/app/assets/svg/heart-solid.svg +7 -0
- package/app/assets/svg/heart.svg +3 -0
- package/app/assets/svg/info.svg +3 -0
- package/app/assets/svg/like.svg +4 -0
- package/app/assets/svg/location.svg +3 -0
- package/app/assets/svg/lock.svg +3 -0
- package/app/assets/svg/paypal.svg +19 -0
- package/app/assets/svg/plug.svg +3 -0
- package/app/assets/svg/plus.svg +3 -0
- package/app/assets/svg/receipt.svg +3 -0
- package/app/assets/svg/search.svg +8 -0
- package/app/assets/svg/signout.svg +3 -0
- package/app/assets/svg/social-facebook.svg +3 -0
- package/app/assets/svg/social-instagram.svg +3 -0
- package/app/assets/svg/social-pinterest.svg +4 -0
- package/app/assets/svg/social-twitter.svg +3 -0
- package/app/assets/svg/social-youtube.svg +3 -0
- package/app/assets/svg/user.svg +3 -0
- package/app/assets/svg/visibility-off.svg +5 -0
- package/app/assets/svg/visibility.svg +3 -0
- package/app/components/_app/index.jsx +401 -0
- package/app/components/_app/index.test.js +85 -0
- package/app/components/_app/partials/above-header.jsx +10 -0
- package/app/components/_app-config/index.jsx +125 -0
- package/app/components/_app-config/index.test.js +77 -0
- package/app/components/_error/index.jsx +142 -0
- package/app/components/_error/index.test.js +25 -0
- package/app/components/action-card/index.jsx +75 -0
- package/app/components/address-display/index.jsx +30 -0
- package/app/components/basic-tile/index.jsx +65 -0
- package/app/components/basic-tile/index.test.js +23 -0
- package/app/components/breadcrumb/index.jsx +67 -0
- package/app/components/breadcrumb/index.test.js +30 -0
- package/app/components/confirmation-modal/index.jsx +111 -0
- package/app/components/confirmation-modal/index.test.js +98 -0
- package/app/components/drawer-menu/index.jsx +405 -0
- package/app/components/drawer-menu/index.test.js +33 -0
- package/app/components/dynamic-image/index.jsx +56 -0
- package/app/components/field/index.jsx +161 -0
- package/app/components/footer/index.jsx +269 -0
- package/app/components/footer/index.test.js +22 -0
- package/app/components/forms/address-fields.jsx +49 -0
- package/app/components/forms/credit-card-fields.jsx +149 -0
- package/app/components/forms/form-action-buttons.jsx +55 -0
- package/app/components/forms/login-fields.jsx +31 -0
- package/app/components/forms/password-requirements.jsx +99 -0
- package/app/components/forms/post-checkout-registration-fields.jsx +43 -0
- package/app/components/forms/profile-fields.jsx +36 -0
- package/app/components/forms/promo-code-fields.jsx +43 -0
- package/app/components/forms/registration-fields.jsx +42 -0
- package/app/components/forms/reset-password-fields.jsx +31 -0
- package/app/components/forms/state-province-options.jsx +75 -0
- package/app/components/forms/update-password-fields.jsx +49 -0
- package/app/components/forms/useAddressFields.jsx +196 -0
- package/app/components/forms/useCreditCardFields.jsx +146 -0
- package/app/components/forms/useLoginFields.jsx +52 -0
- package/app/components/forms/useProfileFields.jsx +95 -0
- package/app/components/forms/usePromoCodeFields.jsx +39 -0
- package/app/components/forms/useRegistrationFields.jsx +136 -0
- package/app/components/forms/useResetPasswordFields.jsx +40 -0
- package/app/components/forms/useUpdatePasswordFields.jsx +89 -0
- package/app/components/header/index.jsx +290 -0
- package/app/components/header/index.test.js +217 -0
- package/app/components/hero/index.jsx +84 -0
- package/app/components/hero/index.test.js +40 -0
- package/app/components/icons/index.jsx +158 -0
- package/app/components/icons/index.test.js +20 -0
- package/app/components/image-gallery/index.jsx +176 -0
- package/app/components/image-gallery/index.test.js +485 -0
- package/app/components/item-variant/index.jsx +33 -0
- package/app/components/item-variant/item-attributes.jsx +107 -0
- package/app/components/item-variant/item-image.jsx +73 -0
- package/app/components/item-variant/item-name.jsx +28 -0
- package/app/components/item-variant/item-price.jsx +117 -0
- package/app/components/link/index.jsx +32 -0
- package/app/components/link/index.test.js +72 -0
- package/app/components/links-list/index.jsx +89 -0
- package/app/components/links-list/index.test.js +62 -0
- package/app/components/list-menu/index.jsx +280 -0
- package/app/components/list-menu/index.test.js +44 -0
- package/app/components/loading-spinner/index.jsx +46 -0
- package/app/components/locale-selector/index.jsx +124 -0
- package/app/components/locale-selector/index.test.js +37 -0
- package/app/components/locale-text/index.jsx +97 -0
- package/app/components/locale-text/index.test.js +36 -0
- package/app/components/login/index.jsx +96 -0
- package/app/components/nested-accordion/index.jsx +185 -0
- package/app/components/nested-accordion/index.test.js +98 -0
- package/app/components/offline-banner/index.jsx +40 -0
- package/app/components/offline-banner/index.test.js +15 -0
- package/app/components/offline-boundary/index.jsx +104 -0
- package/app/components/offline-boundary/index.test.js +123 -0
- package/app/components/order-summary/index.jsx +331 -0
- package/app/components/page-action-placeholder/index.jsx +50 -0
- package/app/components/pagination/index.jsx +134 -0
- package/app/components/pagination/index.test.js +25 -0
- package/app/components/product-item/index.jsx +146 -0
- package/app/components/product-item/index.test.js +38 -0
- package/app/components/product-scroller/index.jsx +172 -0
- package/app/components/product-scroller/index.test.js +98 -0
- package/app/components/product-tile/index.jsx +195 -0
- package/app/components/product-tile/index.test.js +96 -0
- package/app/components/product-view/index.jsx +538 -0
- package/app/components/product-view/index.test.js +224 -0
- package/app/components/product-view-modal/index.jsx +48 -0
- package/app/components/product-view-modal/index.test.js +72 -0
- package/app/components/promo-code/index.jsx +162 -0
- package/app/components/promo-popover/index.jsx +83 -0
- package/app/components/quantity-picker/index.jsx +58 -0
- package/app/components/radio-card/index.jsx +75 -0
- package/app/components/recommended-products/index.jsx +227 -0
- package/app/components/register/index.jsx +114 -0
- package/app/components/reset-password/index.jsx +87 -0
- package/app/components/responsive/index.jsx +29 -0
- package/app/components/scroll-to-top/index.jsx +24 -0
- package/app/components/scroll-to-top/index.test.js +46 -0
- package/app/components/search/index.jsx +279 -0
- package/app/components/search/index.test.js +127 -0
- package/app/components/search/partials/recent-searches.jsx +76 -0
- package/app/components/search/partials/search-suggestions.jsx +45 -0
- package/app/components/search/partials/suggestions.jsx +43 -0
- package/app/components/section/index.jsx +68 -0
- package/app/components/seo/index.jsx +33 -0
- package/app/components/social-icons/index.jsx +101 -0
- package/app/components/social-icons/index.test.js +30 -0
- package/app/components/swatch-group/index.jsx +77 -0
- package/app/components/swatch-group/index.test.js +136 -0
- package/app/components/swatch-group/swatch.jsx +94 -0
- package/app/components/toggle-card/index.jsx +97 -0
- package/app/components/with-registration/index.jsx +58 -0
- package/app/components/with-registration/index.test.js +85 -0
- package/app/constants.js +109 -0
- package/app/contexts/index.js +92 -0
- package/app/hooks/einstein-mock-data.js +916 -0
- package/app/hooks/index.js +17 -0
- package/app/hooks/use-add-to-cart-modal.js +344 -0
- package/app/hooks/use-add-to-cart-modal.test.js +625 -0
- package/app/hooks/use-auth-modal.js +337 -0
- package/app/hooks/use-auth-modal.test.js +365 -0
- package/app/hooks/use-currency.js +20 -0
- package/app/hooks/use-currency.test.js +41 -0
- package/app/hooks/use-current-basket.js +39 -0
- package/app/hooks/use-current-customer.js +29 -0
- package/app/hooks/use-derived-product.js +77 -0
- package/app/hooks/use-derived-product.test.js +69 -0
- package/app/hooks/use-einstein.js +512 -0
- package/app/hooks/use-einstein.test.js +224 -0
- package/app/hooks/use-intersection-observer.js +64 -0
- package/app/hooks/use-limit-urls.js +31 -0
- package/app/hooks/use-limit-urls.test.js +40 -0
- package/app/hooks/use-multi-site.js +36 -0
- package/app/hooks/use-multi-site.test.js +53 -0
- package/app/hooks/use-navigation.js +37 -0
- package/app/hooks/use-navigation.test.js +109 -0
- package/app/hooks/use-page-urls.js +35 -0
- package/app/hooks/use-page-urls.test.js +39 -0
- package/app/hooks/use-pdp-search-params.js +16 -0
- package/app/hooks/use-pdp-search-params.test.js +52 -0
- package/app/hooks/use-previous.js +17 -0
- package/app/hooks/use-product-view-modal.js +93 -0
- package/app/hooks/use-product-view-modal.test.js +172 -0
- package/app/hooks/use-search-params.js +96 -0
- package/app/hooks/use-search-params.test.js +91 -0
- package/app/hooks/use-sort-urls.js +33 -0
- package/app/hooks/use-sort-urls.test.js +42 -0
- package/app/hooks/use-toast.js +68 -0
- package/app/hooks/use-toast.test.js +58 -0
- package/app/hooks/use-variant.js +32 -0
- package/app/hooks/use-variant.test.js +81 -0
- package/app/hooks/use-variation-attributes.js +138 -0
- package/app/hooks/use-variation-attributes.test.js +119 -0
- package/app/hooks/use-variation-params.js +31 -0
- package/app/hooks/use-variation-params.test.js +73 -0
- package/app/hooks/use-wish-list.js +42 -0
- package/app/main.jsx +14 -0
- package/app/mocks/basket-with-suit.js +146 -0
- package/app/mocks/empty-basket.js +39 -0
- package/app/mocks/mock-data.js +5632 -0
- package/app/mocks/product-set-winter-lookM.js +1224 -0
- package/app/mocks/searchResults.js +144 -0
- package/app/mocks/variant-750518699578M.js +434 -0
- package/app/page-designer/README.md +102 -0
- package/app/page-designer/assets/image-tile/index.jsx +51 -0
- package/app/page-designer/assets/image-tile/index.test.js +30 -0
- package/app/page-designer/assets/image-with-text/index.jsx +140 -0
- package/app/page-designer/assets/image-with-text/index.test.js +38 -0
- package/app/page-designer/assets/index.js +9 -0
- package/app/page-designer/index.js +10 -0
- package/app/page-designer/layouts/carousel/index.jsx +222 -0
- package/app/page-designer/layouts/carousel/index.test.js +43 -0
- package/app/page-designer/layouts/index.js +14 -0
- package/app/page-designer/layouts/mobileGrid1r1c/index.jsx +36 -0
- package/app/page-designer/layouts/mobileGrid1r1c/index.test.js +35 -0
- package/app/page-designer/layouts/mobileGrid2r1c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r1c/index.test.js +47 -0
- package/app/page-designer/layouts/mobileGrid2r2c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r2c/index.test.js +71 -0
- package/app/page-designer/layouts/mobileGrid2r3c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r3c/index.test.js +95 -0
- package/app/page-designer/layouts/mobileGrid3r1c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid3r1c/index.test.js +59 -0
- package/app/page-designer/layouts/mobileGrid3r2c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid3r2c/index.test.js +95 -0
- package/app/page-designer/utils.js +14 -0
- package/app/pages/account/addresses.jsx +382 -0
- package/app/pages/account/addresses.test.js +120 -0
- package/app/pages/account/constant.js +57 -0
- package/app/pages/account/index.jsx +237 -0
- package/app/pages/account/index.test.js +188 -0
- package/app/pages/account/order-detail.jsx +397 -0
- package/app/pages/account/order-history.jsx +264 -0
- package/app/pages/account/orders.jsx +30 -0
- package/app/pages/account/orders.test.js +95 -0
- package/app/pages/account/profile.jsx +357 -0
- package/app/pages/account/wishlist/index.jsx +195 -0
- package/app/pages/account/wishlist/index.mock.js +1481 -0
- package/app/pages/account/wishlist/index.test.js +56 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.jsx +170 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.mock.js +1623 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.test.js +99 -0
- package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.jsx +120 -0
- package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.test.js +391 -0
- package/app/pages/cart/index.jsx +476 -0
- package/app/pages/cart/index.test.js +481 -0
- package/app/pages/cart/partials/cart-cta.jsx +46 -0
- package/app/pages/cart/partials/cart-secondary-button-group.jsx +135 -0
- package/app/pages/cart/partials/cart-secondary-button-group.test.js +103 -0
- package/app/pages/cart/partials/cart-skeleton.jsx +93 -0
- package/app/pages/cart/partials/cart-title.jsx +27 -0
- package/app/pages/cart/partials/empty-cart.jsx +86 -0
- package/app/pages/checkout/confirmation.jsx +541 -0
- package/app/pages/checkout/confirmation.mock.js +450 -0
- package/app/pages/checkout/confirmation.test.js +114 -0
- package/app/pages/checkout/index.jsx +169 -0
- package/app/pages/checkout/index.test.js +582 -0
- package/app/pages/checkout/partials/cc-radio-group.jsx +122 -0
- package/app/pages/checkout/partials/checkout-footer.jsx +140 -0
- package/app/pages/checkout/partials/checkout-footer.test.js +16 -0
- package/app/pages/checkout/partials/checkout-header.jsx +54 -0
- package/app/pages/checkout/partials/checkout-header.test.js +16 -0
- package/app/pages/checkout/partials/checkout-skeleton.jsx +52 -0
- package/app/pages/checkout/partials/contact-info.jsx +251 -0
- package/app/pages/checkout/partials/contact-info.test.js +43 -0
- package/app/pages/checkout/partials/payment-form.jsx +97 -0
- package/app/pages/checkout/partials/payment.jsx +276 -0
- package/app/pages/checkout/partials/shipping-address-selection.jsx +377 -0
- package/app/pages/checkout/partials/shipping-address.jsx +132 -0
- package/app/pages/checkout/partials/shipping-options.jsx +232 -0
- package/app/pages/checkout/util/checkout-context.js +94 -0
- package/app/pages/home/data.js +134 -0
- package/app/pages/home/index.jsx +301 -0
- package/app/pages/home/index.test.js +23 -0
- package/app/pages/login/index.jsx +123 -0
- package/app/pages/login/index.test.js +229 -0
- package/app/pages/login-redirect/index.jsx +23 -0
- package/app/pages/login-redirect/index.test.js +16 -0
- package/app/pages/page-not-found/index.jsx +90 -0
- package/app/pages/page-not-found/index.test.js +31 -0
- package/app/pages/product-detail/index.jsx +394 -0
- package/app/pages/product-detail/index.mock.js +197 -0
- package/app/pages/product-detail/index.test.js +162 -0
- package/app/pages/product-detail/partials/information-accordion.jsx +121 -0
- package/app/pages/product-list/index.jsx +735 -0
- package/app/pages/product-list/index.test.js +180 -0
- package/app/pages/product-list/partials/above-page-header.jsx +10 -0
- package/app/pages/product-list/partials/checkbox-refinements.jsx +41 -0
- package/app/pages/product-list/partials/checkbox-refinements.test.js +53 -0
- package/app/pages/product-list/partials/color-refinements.jsx +88 -0
- package/app/pages/product-list/partials/empty-results.jsx +118 -0
- package/app/pages/product-list/partials/link-refinements.jsx +38 -0
- package/app/pages/product-list/partials/page-header.jsx +42 -0
- package/app/pages/product-list/partials/radio-refinements.jsx +60 -0
- package/app/pages/product-list/partials/refinements.jsx +144 -0
- package/app/pages/product-list/partials/selected-refinements.jsx +100 -0
- package/app/pages/product-list/partials/size-refinements.jsx +55 -0
- package/app/pages/registration/index.jsx +87 -0
- package/app/pages/registration/index.test.jsx +132 -0
- package/app/pages/reset-password/index.jsx +112 -0
- package/app/pages/reset-password/index.test.jsx +141 -0
- package/app/request-processor.js +118 -0
- package/app/request-processor.test.js +23 -0
- package/app/routes.jsx +111 -0
- package/app/routes.test.js +13 -0
- package/app/ssr.js +70 -0
- package/app/static/ico/favicon.ico +0 -0
- package/app/static/img/global/app-icon-192.png +0 -0
- package/app/static/img/global/app-icon-512.png +0 -0
- package/app/static/img/global/apple-touch-icon.png +0 -0
- package/app/static/img/hero.png +0 -0
- package/app/static/manifest.json +19 -0
- package/app/static/robots.txt +2 -0
- package/app/theme/components/base/accordion.js +21 -0
- package/app/theme/components/base/alert.js +17 -0
- package/app/theme/components/base/badge.js +25 -0
- package/app/theme/components/base/button.js +77 -0
- package/app/theme/components/base/checkbox.js +30 -0
- package/app/theme/components/base/container.js +17 -0
- package/app/theme/components/base/drawer.js +26 -0
- package/app/theme/components/base/formLabel.js +13 -0
- package/app/theme/components/base/icon.js +13 -0
- package/app/theme/components/base/input.js +44 -0
- package/app/theme/components/base/modal.js +11 -0
- package/app/theme/components/base/popover.js +61 -0
- package/app/theme/components/base/radio.js +33 -0
- package/app/theme/components/base/select.js +15 -0
- package/app/theme/components/base/skeleton.js +12 -0
- package/app/theme/components/base/tooltip.js +19 -0
- package/app/theme/components/project/_app.js +25 -0
- package/app/theme/components/project/breadcrumb.js +25 -0
- package/app/theme/components/project/checkout-footer.js +35 -0
- package/app/theme/components/project/drawer-menu.js +66 -0
- package/app/theme/components/project/footer.js +84 -0
- package/app/theme/components/project/header.js +84 -0
- package/app/theme/components/project/image-gallery.js +59 -0
- package/app/theme/components/project/links-list.js +43 -0
- package/app/theme/components/project/list-menu.js +91 -0
- package/app/theme/components/project/locale-selector.js +42 -0
- package/app/theme/components/project/nested-accordion.js +26 -0
- package/app/theme/components/project/offline-banner.js +25 -0
- package/app/theme/components/project/pagination.js +22 -0
- package/app/theme/components/project/product-tile.js +32 -0
- package/app/theme/components/project/social-icons.js +52 -0
- package/app/theme/components/project/swatch-group.js +115 -0
- package/app/theme/foundations/colors.js +170 -0
- package/app/theme/foundations/gradients.js +9 -0
- package/app/theme/foundations/layerStyles.js +41 -0
- package/app/theme/foundations/shadows.js +9 -0
- package/app/theme/foundations/sizes.js +18 -0
- package/app/theme/foundations/space.js +9 -0
- package/app/theme/foundations/styles.js +21 -0
- package/app/theme/index.js +104 -0
- package/app/utils/cc-utils.js +112 -0
- package/app/utils/cc-utils.test.js +41 -0
- package/app/utils/image-groups-utils.js +62 -0
- package/app/utils/image-groups-utils.test.js +65 -0
- package/app/utils/locale.js +78 -0
- package/app/utils/locale.test.js +112 -0
- package/app/utils/password-utils.js +21 -0
- package/app/utils/phone-utils.js +22 -0
- package/app/utils/phone-utils.test.js +15 -0
- package/app/utils/product-utils.js +35 -0
- package/app/utils/product-utils.test.js +51 -0
- package/app/utils/responsive-image.js +198 -0
- package/app/utils/responsive-image.test.js +170 -0
- package/app/utils/routes-utils.js +111 -0
- package/app/utils/routes-utils.test.js +291 -0
- package/app/utils/site-utils.js +222 -0
- package/app/utils/site-utils.test.js +376 -0
- package/app/utils/test-utils.js +257 -0
- package/app/utils/url.js +291 -0
- package/app/utils/url.test.js +421 -0
- package/app/utils/utils.js +201 -0
- package/app/utils/utils.test.js +182 -0
- package/babel.config.js +7 -0
- package/cache-hash-config.json +8 -0
- package/config/default.js +64 -0
- package/config/mocks/default.js +131 -0
- package/config/sites.js +78 -0
- package/jest-setup.js +191 -0
- package/jest.config.js +50 -0
- package/jsconfig.json +13 -0
- package/package.json +105 -0
- package/scripts/extract-default-messages.js +92 -0
- package/tests/lighthouserc.js +37 -0
- package/translations/README.md +127 -0
- package/translations/compiled/de-DE.json +3212 -0
- package/translations/compiled/en-GB.json +3212 -0
- package/translations/compiled/en-US.json +3212 -0
- package/translations/compiled/en-XA.json +6948 -0
- package/translations/compiled/es-MX.json +3216 -0
- package/translations/compiled/fr-FR.json +3216 -0
- package/translations/compiled/it-IT.json +3188 -0
- package/translations/compiled/ja-JP.json +3200 -0
- package/translations/compiled/ko-KR.json +3180 -0
- package/translations/compiled/pt-BR.json +3220 -0
- package/translations/compiled/zh-CN.json +3212 -0
- package/translations/compiled/zh-TW.json +3208 -0
- package/translations/de-DE.json +1417 -0
- package/translations/en-GB.json +1417 -0
- package/translations/en-US.json +1417 -0
- package/translations/es-MX.json +1417 -0
- package/translations/fr-FR.json +1417 -0
- package/translations/it-IT.json +1417 -0
- package/translations/ja-JP.json +1417 -0
- package/translations/ko-KR.json +1417 -0
- package/translations/pt-BR.json +1417 -0
- package/translations/zh-CN.json +1417 -0
- package/translations/zh-TW.json +1417 -0
- package/worker/main.js +36 -0
|
@@ -0,0 +1,84 @@
|
|
|
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 PropTypes from 'prop-types'
|
|
10
|
+
import {Box, Flex, Heading, Stack, Image} from '@chakra-ui/react'
|
|
11
|
+
|
|
12
|
+
const Hero = ({title, img, actions, ...props}) => {
|
|
13
|
+
const {src, alt} = img
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Box
|
|
17
|
+
marginBottom={{base: 0, md: 10}}
|
|
18
|
+
height={{lg: 'xl'}}
|
|
19
|
+
position={{lg: 'relative'}}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
<Stack
|
|
23
|
+
align={'center'}
|
|
24
|
+
spacing={{base: 8, md: 10}}
|
|
25
|
+
paddingTop={{base: 12, md: 10}}
|
|
26
|
+
paddingBottom={{base: 6, md: 10}}
|
|
27
|
+
direction={{base: 'column', lg: 'row'}}
|
|
28
|
+
>
|
|
29
|
+
<Stack flex={1} spacing={{base: 5, md: 8}}>
|
|
30
|
+
<Heading
|
|
31
|
+
as="h1"
|
|
32
|
+
fontSize={{base: '4xl', md: '5xl', lg: '6xl'}}
|
|
33
|
+
maxWidth={{base: '75%', md: '50%', lg: 'md'}}
|
|
34
|
+
>
|
|
35
|
+
{title}
|
|
36
|
+
</Heading>
|
|
37
|
+
|
|
38
|
+
{actions && <Box width={{base: 'full', lg: 'inherit'}}>{actions}</Box>}
|
|
39
|
+
</Stack>
|
|
40
|
+
<Flex
|
|
41
|
+
flex={1}
|
|
42
|
+
justify={'center'}
|
|
43
|
+
align={'center'}
|
|
44
|
+
position={'relative'}
|
|
45
|
+
width={'full'}
|
|
46
|
+
paddingTop={{base: 4, lg: 0}}
|
|
47
|
+
>
|
|
48
|
+
<Box position={'relative'} width={{base: 'full', md: '80%', lg: 'full'}}>
|
|
49
|
+
<Image
|
|
50
|
+
fit={'cover'}
|
|
51
|
+
align={'center'}
|
|
52
|
+
width={'100%'}
|
|
53
|
+
height={'100%'}
|
|
54
|
+
src={src}
|
|
55
|
+
alt={alt}
|
|
56
|
+
/>
|
|
57
|
+
</Box>
|
|
58
|
+
</Flex>
|
|
59
|
+
</Stack>
|
|
60
|
+
</Box>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Hero.displayName = 'Hero'
|
|
65
|
+
|
|
66
|
+
Hero.propTypes = {
|
|
67
|
+
/**
|
|
68
|
+
* Hero component image
|
|
69
|
+
*/
|
|
70
|
+
img: PropTypes.shape({
|
|
71
|
+
src: PropTypes.string,
|
|
72
|
+
alt: PropTypes.string
|
|
73
|
+
}),
|
|
74
|
+
/**
|
|
75
|
+
* Hero component main title
|
|
76
|
+
*/
|
|
77
|
+
title: PropTypes.string,
|
|
78
|
+
/**
|
|
79
|
+
* Call to action component(s)
|
|
80
|
+
*/
|
|
81
|
+
actions: PropTypes.element
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default Hero
|
|
@@ -0,0 +1,40 @@
|
|
|
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 {fireEvent} from '@testing-library/react'
|
|
9
|
+
import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
10
|
+
import Hero from '@salesforce/retail-react-app/app/components/hero/index'
|
|
11
|
+
|
|
12
|
+
test('Hero renders without errors', () => {
|
|
13
|
+
const data = {
|
|
14
|
+
title: 'title',
|
|
15
|
+
actions: undefined,
|
|
16
|
+
img: {
|
|
17
|
+
src: 'src',
|
|
18
|
+
alt: 'alt'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const {getByText} = renderWithProviders(<Hero {...data} />)
|
|
22
|
+
expect(getByText(/title/i)).toBeInTheDocument()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('Hero renders actions and event handlers', () => {
|
|
26
|
+
const onClick = jest.fn()
|
|
27
|
+
const data = {
|
|
28
|
+
title: 'title',
|
|
29
|
+
actions: <button data-testid="button" onClick={onClick}></button>,
|
|
30
|
+
img: {
|
|
31
|
+
src: 'src',
|
|
32
|
+
alt: 'alt'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const {getByTestId} = renderWithProviders(<Hero {...data} />)
|
|
36
|
+
const button = getByTestId('button')
|
|
37
|
+
expect(button).toBeInTheDocument()
|
|
38
|
+
fireEvent.click(button)
|
|
39
|
+
expect(onClick).toHaveBeenCalledTimes(1)
|
|
40
|
+
})
|
|
@@ -0,0 +1,158 @@
|
|
|
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, {forwardRef} from 'react'
|
|
8
|
+
import {Icon, useTheme} from '@chakra-ui/react'
|
|
9
|
+
|
|
10
|
+
// Our own SVG imports. These will be extracted to a single sprite sheet by the
|
|
11
|
+
// svg-sprite-loader webpack plugin at build time and injected in the <body> tag
|
|
12
|
+
// during SSR.
|
|
13
|
+
// NOTE: Another solution would be to use `require-context.macro` package to accomplish
|
|
14
|
+
// importing icon svg's.
|
|
15
|
+
import '@salesforce/retail-react-app/app/assets/svg/alert.svg'
|
|
16
|
+
import '@salesforce/retail-react-app/app/assets/svg/account.svg'
|
|
17
|
+
import '@salesforce/retail-react-app/app/assets/svg/basket.svg'
|
|
18
|
+
import '@salesforce/retail-react-app/app/assets/svg/check.svg'
|
|
19
|
+
import '@salesforce/retail-react-app/app/assets/svg/check-circle.svg'
|
|
20
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-up.svg'
|
|
21
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-down.svg'
|
|
22
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-right.svg'
|
|
23
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-left.svg'
|
|
24
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-right.svg'
|
|
25
|
+
import '@salesforce/retail-react-app/app/assets/svg/chevron-up.svg'
|
|
26
|
+
import '@salesforce/retail-react-app/app/assets/svg/dashboard.svg'
|
|
27
|
+
import '@salesforce/retail-react-app/app/assets/svg/figma-logo.svg'
|
|
28
|
+
import '@salesforce/retail-react-app/app/assets/svg/filter.svg'
|
|
29
|
+
import '@salesforce/retail-react-app/app/assets/svg/file.svg'
|
|
30
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-ca.svg'
|
|
31
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-us.svg'
|
|
32
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-gb.svg'
|
|
33
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-fr.svg'
|
|
34
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-it.svg'
|
|
35
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-cn.svg'
|
|
36
|
+
import '@salesforce/retail-react-app/app/assets/svg/flag-jp.svg'
|
|
37
|
+
import '@salesforce/retail-react-app/app/assets/svg/github-logo.svg'
|
|
38
|
+
import '@salesforce/retail-react-app/app/assets/svg/hamburger.svg'
|
|
39
|
+
import '@salesforce/retail-react-app/app/assets/svg/info.svg'
|
|
40
|
+
import '@salesforce/retail-react-app/app/assets/svg/social-facebook.svg'
|
|
41
|
+
import '@salesforce/retail-react-app/app/assets/svg/social-instagram.svg'
|
|
42
|
+
import '@salesforce/retail-react-app/app/assets/svg/social-twitter.svg'
|
|
43
|
+
import '@salesforce/retail-react-app/app/assets/svg/social-youtube.svg'
|
|
44
|
+
import '@salesforce/retail-react-app/app/assets/svg/like.svg'
|
|
45
|
+
import '@salesforce/retail-react-app/app/assets/svg/lock.svg'
|
|
46
|
+
import '@salesforce/retail-react-app/app/assets/svg/plug.svg'
|
|
47
|
+
import '@salesforce/retail-react-app/app/assets/svg/plus.svg'
|
|
48
|
+
import '@salesforce/retail-react-app/app/assets/svg/receipt.svg'
|
|
49
|
+
import '@salesforce/retail-react-app/app/assets/svg/search.svg'
|
|
50
|
+
import '@salesforce/retail-react-app/app/assets/svg/signout.svg'
|
|
51
|
+
import '@salesforce/retail-react-app/app/assets/svg/user.svg'
|
|
52
|
+
import '@salesforce/retail-react-app/app/assets/svg/visibility.svg'
|
|
53
|
+
import '@salesforce/retail-react-app/app/assets/svg/visibility-off.svg'
|
|
54
|
+
import '@salesforce/retail-react-app/app/assets/svg/heart.svg'
|
|
55
|
+
import '@salesforce/retail-react-app/app/assets/svg/heart-solid.svg'
|
|
56
|
+
import '@salesforce/retail-react-app/app/assets/svg/close.svg'
|
|
57
|
+
|
|
58
|
+
// For non-square SVGs, we can use the symbol data from the import to set the
|
|
59
|
+
// proper viewBox attribute on the Icon wrapper.
|
|
60
|
+
import AmexSymbol from '@salesforce/retail-react-app/app/assets/svg/cc-amex.svg'
|
|
61
|
+
import BrandLogoSymbol from '@salesforce/retail-react-app/app/assets/svg/brand-logo.svg'
|
|
62
|
+
import CVVSymbol from '@salesforce/retail-react-app/app/assets/svg/cc-cvv.svg'
|
|
63
|
+
import DiscoverSymbol from '@salesforce/retail-react-app/app/assets/svg/cc-discover.svg'
|
|
64
|
+
import LocationSymbol from '@salesforce/retail-react-app/app/assets/svg/location.svg'
|
|
65
|
+
import MastercardSymbol from '@salesforce/retail-react-app/app/assets/svg/cc-mastercard.svg'
|
|
66
|
+
import PaypalSymbol from '@salesforce/retail-react-app/app/assets/svg/paypal.svg'
|
|
67
|
+
import SocialPinterestSymbol from '@salesforce/retail-react-app/app/assets/svg/social-pinterest.svg'
|
|
68
|
+
import VisaSymbol from '@salesforce/retail-react-app/app/assets/svg/cc-visa.svg'
|
|
69
|
+
|
|
70
|
+
// TODO: We're hardcoding the `viewBox` for these imported SVGs temporarily as the
|
|
71
|
+
// SVG loader plugin is not properly providing us the symbol data on the client side.
|
|
72
|
+
AmexSymbol.viewBox = AmexSymbol.viewBox || '0 0 38 22'
|
|
73
|
+
BrandLogoSymbol.viewBox = BrandLogoSymbol.viewBox || '0 0 46 32'
|
|
74
|
+
CVVSymbol.viewBox = CVVSymbol.viewBox || '0 0 41 24'
|
|
75
|
+
DiscoverSymbol.viewBox = DiscoverSymbol.viewBox || '0 0 38 22'
|
|
76
|
+
LocationSymbol.viewBox = LocationSymbol.viewBox || '0 0 16 21'
|
|
77
|
+
MastercardSymbol.viewBox = MastercardSymbol.viewBox || '0 0 38 22'
|
|
78
|
+
PaypalSymbol.viewBox = PaypalSymbol.viewBox || '0 0 80 20'
|
|
79
|
+
SocialPinterestSymbol.viewBox = SocialPinterestSymbol.viewBox || '0 0 21 20'
|
|
80
|
+
VisaSymbol.viewBox = VisaSymbol.viewBox || '0 0 38 22'
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A helper for creating a Chakra-wrapped icon from our own SVG imports via sprite sheet.
|
|
84
|
+
* @param {string} name - the filename of the imported svg (does not include extension)
|
|
85
|
+
*/
|
|
86
|
+
/* istanbul ignore next */
|
|
87
|
+
const icon = (name, passProps) => {
|
|
88
|
+
const displayName = name
|
|
89
|
+
.toLowerCase()
|
|
90
|
+
.replace(/(?:^|[\s-/])\w/g, (match) => match.toUpperCase())
|
|
91
|
+
.replace(/-/g, '')
|
|
92
|
+
const component = forwardRef((props, ref) => {
|
|
93
|
+
const theme = useTheme()
|
|
94
|
+
const baseStyle = theme?.components?.Icon?.baseStyle
|
|
95
|
+
return (
|
|
96
|
+
<Icon ref={ref} {...baseStyle} {...passProps} {...props}>
|
|
97
|
+
<use role="presentation" xlinkHref={`#${name}`} />
|
|
98
|
+
</Icon>
|
|
99
|
+
)
|
|
100
|
+
})
|
|
101
|
+
component.displayName = `${displayName}Icon`
|
|
102
|
+
return component
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Export Chakra icon components that use our SVG sprite symbol internally
|
|
106
|
+
// For non-square SVGs, we can use the symbol data from the import to set the
|
|
107
|
+
// proper viewBox attribute on the Icon wrapper.
|
|
108
|
+
export const AmexIcon = icon('cc-amex', {viewBox: AmexSymbol.viewBox})
|
|
109
|
+
export const AlertIcon = icon('alert')
|
|
110
|
+
export const AccountIcon = icon('account')
|
|
111
|
+
export const BrandLogo = icon('brand-logo', {viewBox: BrandLogoSymbol.viewBox})
|
|
112
|
+
export const BasketIcon = icon('basket')
|
|
113
|
+
export const CheckIcon = icon('check')
|
|
114
|
+
export const CheckCircleIcon = icon('check-circle')
|
|
115
|
+
export const ChevronDownIcon = icon('chevron-down')
|
|
116
|
+
export const ChevronLeftIcon = icon('chevron-left')
|
|
117
|
+
export const ChevronRightIcon = icon('chevron-right')
|
|
118
|
+
export const ChevronUpIcon = icon('chevron-up')
|
|
119
|
+
export const CVVIcon = icon('cc-cvv', {viewBox: CVVSymbol.viewBox})
|
|
120
|
+
export const DashboardIcon = icon('dashboard')
|
|
121
|
+
export const DiscoverIcon = icon('cc-discover', {viewBox: DiscoverSymbol.viewBox})
|
|
122
|
+
export const FigmaLogo = icon('figma-logo')
|
|
123
|
+
export const FilterIcon = icon('filter')
|
|
124
|
+
export const FileIcon = icon('file')
|
|
125
|
+
export const FlagCAIcon = icon('flag-ca')
|
|
126
|
+
export const FlagUSIcon = icon('flag-us')
|
|
127
|
+
export const FlagGBIcon = icon('flag-gb')
|
|
128
|
+
export const FlagFRIcon = icon('flag-fr')
|
|
129
|
+
export const FlagITIcon = icon('flag-it')
|
|
130
|
+
export const FlagCNIcon = icon('flag-cn')
|
|
131
|
+
export const FlagJPIcon = icon('flag-jp')
|
|
132
|
+
export const GithubLogo = icon('github-logo')
|
|
133
|
+
export const HamburgerIcon = icon('hamburger')
|
|
134
|
+
export const InfoIcon = icon('info')
|
|
135
|
+
export const LikeIcon = icon('like')
|
|
136
|
+
export const LockIcon = icon('lock')
|
|
137
|
+
export const LocationIcon = icon('location')
|
|
138
|
+
export const PaypalIcon = icon('paypal', {viewBox: PaypalSymbol.viewBox})
|
|
139
|
+
export const PlugIcon = icon('plug')
|
|
140
|
+
export const PlusIcon = icon('plus')
|
|
141
|
+
export const MastercardIcon = icon('cc-mastercard', {viewBox: MastercardSymbol.viewBox})
|
|
142
|
+
export const ReceiptIcon = icon('receipt')
|
|
143
|
+
export const SearchIcon = icon('search')
|
|
144
|
+
export const SocialFacebookIcon = icon('social-facebook')
|
|
145
|
+
export const SocialInstagramIcon = icon('social-instagram')
|
|
146
|
+
export const SocialPinterestIcon = icon('social-pinterest', {
|
|
147
|
+
viewBox: SocialPinterestSymbol.viewBox
|
|
148
|
+
})
|
|
149
|
+
export const SocialTwitterIcon = icon('social-twitter')
|
|
150
|
+
export const SocialYoutubeIcon = icon('social-youtube')
|
|
151
|
+
export const SignoutIcon = icon('signout')
|
|
152
|
+
export const UserIcon = icon('user')
|
|
153
|
+
export const VisaIcon = icon('cc-visa', {viewBox: VisaSymbol.viewBox})
|
|
154
|
+
export const VisibilityIcon = icon('visibility')
|
|
155
|
+
export const VisibilityOffIcon = icon('visibility-off')
|
|
156
|
+
export const HeartIcon = icon('heart')
|
|
157
|
+
export const HeartSolidIcon = icon('heart-solid')
|
|
158
|
+
export const CloseIcon = icon('close')
|
|
@@ -0,0 +1,20 @@
|
|
|
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 {within} from '@testing-library/dom'
|
|
9
|
+
import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
10
|
+
import * as Icons from '@salesforce/retail-react-app/app/components/icons/index'
|
|
11
|
+
|
|
12
|
+
test('renders svg icons with Chakra Icon component', () => {
|
|
13
|
+
renderWithProviders(<Icons.CheckIcon />)
|
|
14
|
+
const svg = document.querySelector('.chakra-icon')
|
|
15
|
+
const use = within(svg).getByRole('presentation')
|
|
16
|
+
expect(svg).toBeInTheDocument()
|
|
17
|
+
expect(use).toBeInTheDocument()
|
|
18
|
+
expect(svg).toHaveAttribute('viewBox', '0 0 24 24')
|
|
19
|
+
expect(use).toHaveAttribute('xlink:href', '#check')
|
|
20
|
+
})
|
|
@@ -0,0 +1,176 @@
|
|
|
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, {useState, useMemo, useEffect} from 'react'
|
|
9
|
+
import PropTypes from 'prop-types'
|
|
10
|
+
import {useLocation} from 'react-router-dom'
|
|
11
|
+
|
|
12
|
+
// Chakra Components
|
|
13
|
+
import {
|
|
14
|
+
AspectRatio,
|
|
15
|
+
Box,
|
|
16
|
+
Img,
|
|
17
|
+
Flex,
|
|
18
|
+
|
|
19
|
+
// Hooks
|
|
20
|
+
Skeleton as ChakraSkeleton,
|
|
21
|
+
ListItem,
|
|
22
|
+
List,
|
|
23
|
+
useMultiStyleConfig
|
|
24
|
+
} from '@chakra-ui/react'
|
|
25
|
+
import {findImageGroupBy} from '@salesforce/retail-react-app/app/utils/image-groups-utils'
|
|
26
|
+
import DynamicImage from '@salesforce/retail-react-app/app/components/dynamic-image'
|
|
27
|
+
|
|
28
|
+
const EnterKeyNumber = 13
|
|
29
|
+
|
|
30
|
+
const LARGE = 'large'
|
|
31
|
+
const SMALL = 'small'
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The skeleton representation of the image gallery component. Use this component while
|
|
35
|
+
* you are waiting for product data to be returnd from the server.
|
|
36
|
+
*/
|
|
37
|
+
export const Skeleton = ({size}) => {
|
|
38
|
+
const styles = useMultiStyleConfig('ImageGallery', {size})
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Box data-testid="sf-image-gallery-skeleton">
|
|
42
|
+
<Flex flexDirection="column">
|
|
43
|
+
<AspectRatio ratio={1} {...styles.heroImageSkeleton}>
|
|
44
|
+
<ChakraSkeleton />
|
|
45
|
+
</AspectRatio>
|
|
46
|
+
<Flex>
|
|
47
|
+
{new Array(4).fill(0).map((_, index) => (
|
|
48
|
+
<AspectRatio ratio={1} {...styles.thumbnailImageSkeleton} key={index}>
|
|
49
|
+
<ChakraSkeleton />
|
|
50
|
+
</AspectRatio>
|
|
51
|
+
))}
|
|
52
|
+
</Flex>
|
|
53
|
+
</Flex>
|
|
54
|
+
</Box>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
Skeleton.propTypes = {
|
|
59
|
+
size: PropTypes.bool
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The image gallery displays a hero image and thumbnails below it. You can control which
|
|
64
|
+
* image groups that are use by passing in the current selected variation values.
|
|
65
|
+
*/
|
|
66
|
+
const ImageGallery = ({imageGroups = [], selectedVariationAttributes = {}, size, lazy = false}) => {
|
|
67
|
+
const [selectedIndex, setSelectedIndex] = useState(0)
|
|
68
|
+
const styles = useMultiStyleConfig('ImageGallery', {size})
|
|
69
|
+
const location = useLocation()
|
|
70
|
+
|
|
71
|
+
// Get the 'hero' image for the current variation.
|
|
72
|
+
const heroImageGroup = useMemo(
|
|
73
|
+
() =>
|
|
74
|
+
findImageGroupBy(imageGroups, {
|
|
75
|
+
viewType: LARGE,
|
|
76
|
+
selectedVariationAttributes
|
|
77
|
+
}),
|
|
78
|
+
[selectedVariationAttributes]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
// reset the selected index when location search changes
|
|
83
|
+
setSelectedIndex(0)
|
|
84
|
+
}, [location.search])
|
|
85
|
+
|
|
86
|
+
// Get a memoized image group used for the thumbnails. We use the `useMemo` hook
|
|
87
|
+
// so we don't have to waste time filtering the image groups each render if the
|
|
88
|
+
// selected variation attributes haven't changed.
|
|
89
|
+
const thumbnailImageGroup = useMemo(
|
|
90
|
+
() =>
|
|
91
|
+
findImageGroupBy(imageGroups, {
|
|
92
|
+
viewType: SMALL,
|
|
93
|
+
selectedVariationAttributes
|
|
94
|
+
}),
|
|
95
|
+
[selectedVariationAttributes]
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
const heroImage = heroImageGroup?.images?.[selectedIndex]
|
|
99
|
+
const thumbnailImages = thumbnailImageGroup?.images || []
|
|
100
|
+
const loadingStrategy = lazy ? 'lazy' : 'eager'
|
|
101
|
+
|
|
102
|
+
const heroImageMaxWidth = styles.heroImage.maxWidth[3] // in px
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Flex direction="column">
|
|
106
|
+
{heroImage && (
|
|
107
|
+
<Box {...styles.heroImageGroup}>
|
|
108
|
+
<AspectRatio {...styles.heroImage} ratio={1}>
|
|
109
|
+
<DynamicImage
|
|
110
|
+
src={`${heroImage.disBaseLink || heroImage.link}[?sw={width}&q=60]`}
|
|
111
|
+
widths={{
|
|
112
|
+
base: '100vw',
|
|
113
|
+
lg: heroImageMaxWidth
|
|
114
|
+
}}
|
|
115
|
+
imageProps={{
|
|
116
|
+
alt: heroImage.alt,
|
|
117
|
+
loading: loadingStrategy
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
</AspectRatio>
|
|
121
|
+
</Box>
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
<List display={'flex'} flexWrap={'wrap'}>
|
|
125
|
+
{thumbnailImages.map((image, index) => {
|
|
126
|
+
const selected = index === selectedIndex
|
|
127
|
+
return (
|
|
128
|
+
<ListItem
|
|
129
|
+
{...styles.thumbnailImageItem}
|
|
130
|
+
tabIndex={0}
|
|
131
|
+
key={index}
|
|
132
|
+
data-testid="image-gallery-thumbnails"
|
|
133
|
+
onKeyDown={(e) => {
|
|
134
|
+
if (e.keyCode === EnterKeyNumber) {
|
|
135
|
+
return setSelectedIndex(index)
|
|
136
|
+
}
|
|
137
|
+
}}
|
|
138
|
+
onClick={() => setSelectedIndex(index)}
|
|
139
|
+
borderColor={`${selected ? 'black' : ''}`}
|
|
140
|
+
borderWidth={`${selected ? '1px' : 0}`}
|
|
141
|
+
>
|
|
142
|
+
<AspectRatio ratio={1}>
|
|
143
|
+
<Img
|
|
144
|
+
alt={image.alt}
|
|
145
|
+
src={image.disBaseLink || image.link}
|
|
146
|
+
loading={loadingStrategy}
|
|
147
|
+
/>
|
|
148
|
+
</AspectRatio>
|
|
149
|
+
</ListItem>
|
|
150
|
+
)
|
|
151
|
+
})}
|
|
152
|
+
</List>
|
|
153
|
+
</Flex>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
ImageGallery.propTypes = {
|
|
158
|
+
/**
|
|
159
|
+
* The images array to be rendered
|
|
160
|
+
*/
|
|
161
|
+
imageGroups: PropTypes.array,
|
|
162
|
+
/**
|
|
163
|
+
* The current selected variation values
|
|
164
|
+
*/
|
|
165
|
+
selectedVariationAttributes: PropTypes.object,
|
|
166
|
+
/**
|
|
167
|
+
* Size of the Image gallery, this will be used to determined the max width from styles
|
|
168
|
+
*/
|
|
169
|
+
size: PropTypes.string,
|
|
170
|
+
/**
|
|
171
|
+
* Determines whether the image will be lazy loaded or not
|
|
172
|
+
*/
|
|
173
|
+
lazy: PropTypes.bool
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export default ImageGallery
|