@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,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
|
+
})
|