@magento/peregrine 11.0.0-beta.1 → 12.0.0-alpha.3
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/lib/Apollo/magentoGqlCacheLink.js +59 -0
- package/lib/List/item.js +12 -9
- package/lib/List/list.js +10 -7
- package/lib/Price/price.js +0 -1
- package/lib/context/cart.js +9 -10
- package/lib/hooks/hook-wrappers/useInformedFieldStateWrapper.js +27 -0
- package/lib/hooks/useDelayedTransition.js +127 -0
- package/lib/hooks/useDetectScrollWidth.js +77 -0
- package/lib/hooks/useInternalLink.js +21 -0
- package/lib/hooks/useIntersectionObserver.js +7 -0
- package/lib/hooks/useIsInViewport.js +44 -0
- package/lib/store/actions/app/actions.js +2 -1
- package/lib/store/reducers/app.js +8 -1
- package/lib/talons/AccountInformationPage/useAccountInformationPage.js +0 -1
- package/lib/talons/Adapter/useAdapter.js +23 -3
- package/lib/talons/AddressBookPage/useAddressBookPage.js +0 -10
- package/lib/talons/Breadcrumbs/breadcrumbs.gql.js +11 -2
- package/lib/talons/Breadcrumbs/useBreadcrumbs.js +19 -5
- package/lib/talons/CartPage/GiftCards/giftCardFragments.gql.ee.js +14 -0
- package/lib/talons/CartPage/GiftCards/giftCardFragments.gql.js +8 -0
- package/lib/talons/CartPage/GiftCards/giftCardQueries.gql.ee.js +73 -0
- package/lib/talons/CartPage/GiftCards/useGiftCards.js +25 -16
- package/lib/talons/CartPage/PriceAdjustments/CouponCode/couponCode.gql.js +56 -0
- package/lib/talons/CartPage/PriceAdjustments/CouponCode/couponCodeFragments.gql.js +10 -0
- package/lib/talons/CartPage/PriceAdjustments/{useCouponCode.js → CouponCode/useCouponCode.js} +10 -6
- package/lib/talons/CartPage/{GiftOptions → PriceAdjustments/GiftOptions}/client-schema.graphql +0 -0
- package/lib/talons/CartPage/PriceAdjustments/GiftOptions/giftOptions.gql.js +21 -0
- package/lib/talons/CartPage/{GiftOptions → PriceAdjustments/GiftOptions}/useGiftOptions.js +5 -3
- package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/shippingMethods.gql.js +43 -0
- package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/shippingMethodsFragments.gql.js +60 -0
- package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingForm.js +8 -9
- package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingMethods.js +7 -5
- package/lib/talons/CartPage/PriceAdjustments/ShippingMethods/useShippingRadios.js +1 -1
- package/lib/talons/CartPage/PriceSummary/priceSummary.gql.js +16 -0
- package/lib/talons/CartPage/PriceSummary/usePriceSummary.js +6 -5
- package/lib/talons/CartPage/ProductListing/EditModal/productForm.gql.js +78 -0
- package/lib/talons/CartPage/ProductListing/EditModal/productFormFragment.gql.js +47 -0
- package/lib/talons/CartPage/ProductListing/EditModal/useProductForm.js +18 -8
- package/lib/talons/CartPage/ProductListing/product.gql.js +4 -3
- package/lib/talons/CartPage/ProductListing/productListing.gql.ce.js +13 -1
- package/lib/talons/CartPage/ProductListing/productListing.gql.ee.js +13 -1
- package/lib/talons/CartPage/ProductListing/productListingFragments.gql.js +52 -0
- package/lib/talons/CartPage/ProductListing/useProduct.js +22 -18
- package/lib/talons/CartPage/ProductListing/useProductListing.js +8 -13
- package/lib/talons/CartPage/ProductListing/useQuantity.js +2 -1
- package/lib/talons/CartPage/cartPage.gql.js +16 -0
- package/lib/talons/CartPage/cartPageFragments.gql.js +21 -0
- package/lib/talons/CartPage/useCartPage.js +7 -6
- package/lib/talons/CategoryList/categoryList.gql.js +11 -2
- package/lib/talons/CategoryList/useCategoryList.js +8 -1
- package/lib/talons/CategoryList/useCategoryTile.js +10 -4
- package/lib/talons/CategoryTree/categoryTree.gql.js +11 -2
- package/lib/talons/CategoryTree/useCategoryTree.js +12 -3
- package/lib/talons/CheckoutPage/AddressBook/addressBook.gql.js +34 -0
- package/lib/talons/CheckoutPage/AddressBook/addressBookFragments.gql.js +31 -0
- package/lib/talons/CheckoutPage/AddressBook/useAddressBook.js +16 -8
- package/lib/talons/CheckoutPage/PaymentInformation/braintreeSummary.gql.js +1 -1
- package/lib/talons/CheckoutPage/PaymentInformation/editModal.gql.js +16 -0
- package/lib/talons/CheckoutPage/PaymentInformation/paymentInformation.gql.js +4 -8
- package/lib/talons/CheckoutPage/PaymentInformation/paymentMethods.gql.js +17 -0
- package/lib/talons/CheckoutPage/PaymentInformation/useBraintreeSummary.js +1 -1
- package/lib/talons/CheckoutPage/PaymentInformation/useEditModal.js +6 -5
- package/lib/talons/CheckoutPage/PaymentInformation/usePaymentInformation.js +22 -16
- package/lib/talons/CheckoutPage/PaymentInformation/usePaymentMethods.js +6 -3
- package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/customerForm.gql.js +55 -0
- package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/guestForm.gql.js +44 -0
- package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useCustomerForm.js +11 -14
- package/lib/talons/CheckoutPage/ShippingInformation/AddressForm/useGuestForm.js +6 -7
- package/lib/talons/CheckoutPage/ShippingInformation/shippingInformation.gql.js +54 -0
- package/lib/talons/CheckoutPage/ShippingInformation/shippingInformationFragments.gql.js +25 -0
- package/lib/talons/CheckoutPage/ShippingInformation/useShippingInformation.js +11 -6
- package/lib/talons/CheckoutPage/ShippingMethod/shippingMethod.gql.js +64 -0
- package/lib/talons/CheckoutPage/ShippingMethod/shippingMethodFragments.gql.js +64 -0
- package/lib/talons/CheckoutPage/{useShippingMethod.js → ShippingMethod/useShippingMethod.js} +11 -8
- package/lib/talons/Cms/cmsPage.gql.js +2 -2
- package/lib/talons/Cms/useCmsPage.js +2 -2
- package/lib/talons/CommunicationsPage/useCommunicationsPage.js +1 -2
- package/lib/talons/CreateAccount/createAccount.gql.js +3 -0
- package/lib/talons/CreateAccount/useCreateAccount.js +2 -4
- package/lib/talons/CreateAccountPage/useCreateAccountPage.js +38 -9
- package/lib/talons/FilterModal/useFilterList.js +17 -3
- package/lib/talons/FilterModal/useFilterModal.js +4 -5
- package/lib/talons/FilterSidebar/useFilterSidebar.js +4 -5
- package/lib/talons/ForgotPasswordPage/useForgotPasswordPage.js +46 -0
- package/lib/talons/FormError/useFormError.js +10 -3
- package/lib/talons/Gallery/__fixtures__/apolloMocks.js +8 -6
- package/lib/talons/Gallery/addToCart.gql.js +17 -0
- package/lib/talons/Gallery/gallery.gql.ce.js +4 -3
- package/lib/talons/Gallery/gallery.gql.ee.js +4 -3
- package/lib/talons/Gallery/useAddToCartButton.js +81 -0
- package/lib/talons/Gallery/useGallery.js +4 -7
- package/lib/talons/Gallery/useGalleryItem.js +7 -1
- package/lib/talons/Header/useCartTrigger.js +14 -7
- package/lib/talons/Link/useLink.js +68 -0
- package/lib/talons/MagentoRoute/magentoRoute.gql.js +12 -3
- package/lib/talons/MagentoRoute/useMagentoRoute.js +115 -30
- package/lib/talons/MegaMenu/megaMenu.gql.js +10 -4
- package/lib/talons/MegaMenu/useMegaMenu.js +61 -11
- package/lib/talons/MegaMenu/useMegaMenuItem.js +61 -0
- package/lib/talons/MegaMenu/useSubMenu.js +20 -0
- package/lib/talons/MiniCart/ProductList/productListFragments.gql.js +0 -1
- package/lib/talons/MiniCart/miniCart.gql.js +4 -3
- package/lib/talons/MiniCart/useMiniCart.js +15 -12
- package/lib/talons/Navigation/useNavigation.js +6 -1
- package/lib/talons/OrderHistoryPage/orderRow.gql.js +0 -1
- package/lib/talons/OrderHistoryPage/useOrderHistoryPage.js +2 -14
- package/lib/talons/PageLoadingIndicator/usePageLoadingIndicator.js +52 -0
- package/lib/talons/Postcode/usePostcode.js +2 -1
- package/lib/talons/ProductFullDetail/useProductFullDetail.js +30 -5
- package/lib/talons/Region/useRegion.js +12 -10
- package/lib/talons/RootComponents/Category/categoryFragments.gql.js +5 -4
- package/lib/talons/RootComponents/Product/productDetailFragment.gql.js +7 -0
- package/lib/talons/SavedPaymentsPage/useSavedPaymentsPage.js +1 -11
- package/lib/talons/SearchBar/useAutocomplete.js +1 -1
- package/lib/talons/SearchBar/useSearchField.js +2 -1
- package/lib/talons/SearchBar/useSuggestedCategory.js +4 -6
- package/lib/talons/SearchPage/searchPage.gql.js +10 -9
- package/lib/talons/SignIn/signIn.gql.js +3 -0
- package/lib/talons/SignInPage/useSignInPage.js +63 -0
- package/lib/talons/Wishlist/AddToListButton/helpers/useSingleWishlist.js +2 -2
- package/lib/talons/Wishlist/AddToListButton/useAddToListButton.ee.js +2 -1
- package/lib/talons/WishlistPage/useActionMenu.js +39 -5
- package/lib/talons/WishlistPage/useWishlist.js +4 -4
- package/lib/talons/WishlistPage/useWishlistPage.js +3 -11
- package/lib/talons/WishlistPage/wishlist.gql.js +1 -1
- package/lib/talons/WishlistPage/wishlistConfig.gql.ce.js +14 -0
- package/lib/talons/WishlistPage/wishlistConfig.gql.ee.js +15 -0
- package/lib/targets/peregrine-declare.js +0 -4
- package/lib/util/deriveErrorMessage.js +12 -6
- package/lib/util/images.js +3 -2
- package/lib/util/isSupportedProductType.js +5 -0
- package/lib/util/magentoRouteData.js +9 -0
- package/package.json +8 -8
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ApolloLink } from '@apollo/client';
|
|
2
|
+
import { BrowserPersistence } from '@magento/peregrine/lib/util';
|
|
3
|
+
|
|
4
|
+
// The name of the header to exchange with the server.
|
|
5
|
+
const CACHE_ID_HEADER = 'x-magento-cache-id';
|
|
6
|
+
// The key in local storage where we save the cache id
|
|
7
|
+
const LOCAL_STORAGE_KEY = 'magento_cache_id';
|
|
8
|
+
const storage = new BrowserPersistence();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The Magento GraphQL Cache Link class is an ApolloLink that is responsible for
|
|
12
|
+
* Venia sending the proper `x-magento-cache-id` header with each of its GraphQL requests.
|
|
13
|
+
*/
|
|
14
|
+
export default class MagentoGQLCacheLink extends ApolloLink {
|
|
15
|
+
// The links get reinstantiated on refresh.
|
|
16
|
+
// If we have an existing cache id value from a previous browsing session, use it.
|
|
17
|
+
#cacheId = storage.getItem(LOCAL_STORAGE_KEY) || null;
|
|
18
|
+
|
|
19
|
+
// Any time the cache id needs to be set, update both our internal variable and
|
|
20
|
+
// the value in local storage.
|
|
21
|
+
setCacheId(value) {
|
|
22
|
+
this.#cacheId = value;
|
|
23
|
+
storage.setItem(LOCAL_STORAGE_KEY, value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
request(operation, forward) {
|
|
27
|
+
// Attach the cache header to each outgoing request.
|
|
28
|
+
operation.setContext(previousContext => {
|
|
29
|
+
const { headers } = previousContext;
|
|
30
|
+
const withCacheHeader = {
|
|
31
|
+
...headers,
|
|
32
|
+
[CACHE_ID_HEADER]: this.#cacheId
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
...previousContext,
|
|
37
|
+
headers: withCacheHeader
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Update the cache id from each response.
|
|
42
|
+
const updateCacheId = data => {
|
|
43
|
+
const context = operation.getContext();
|
|
44
|
+
const { response } = context;
|
|
45
|
+
|
|
46
|
+
const responseCacheId = response.headers.get(CACHE_ID_HEADER);
|
|
47
|
+
|
|
48
|
+
if (responseCacheId) {
|
|
49
|
+
this.setCacheId(responseCacheId);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Purposefully don't modify the result,
|
|
53
|
+
// no other link needs to know about the cache id.
|
|
54
|
+
return data;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return forward(operation).map(updateCacheId);
|
|
58
|
+
}
|
|
59
|
+
}
|
package/lib/List/item.js
CHANGED
|
@@ -35,15 +35,18 @@ const Item = props => {
|
|
|
35
35
|
]);
|
|
36
36
|
const onFocus = useCallback(() => setFocus(key), [key, setFocus]);
|
|
37
37
|
|
|
38
|
-
const customProps =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
const customProps = useMemo(
|
|
39
|
+
() => ({
|
|
40
|
+
classes,
|
|
41
|
+
hasFocus,
|
|
42
|
+
isSelected,
|
|
43
|
+
item,
|
|
44
|
+
itemIndex,
|
|
45
|
+
onClick,
|
|
46
|
+
onFocus
|
|
47
|
+
}),
|
|
48
|
+
[classes, hasFocus, isSelected, item, itemIndex, onClick, onFocus]
|
|
49
|
+
);
|
|
47
50
|
|
|
48
51
|
const Root = useMemo(
|
|
49
52
|
() => fromRenderProp(render, Object.keys(customProps)),
|
package/lib/List/list.js
CHANGED
|
@@ -37,13 +37,16 @@ const List = props => {
|
|
|
37
37
|
...restProps
|
|
38
38
|
} = props;
|
|
39
39
|
|
|
40
|
-
const customProps =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
const customProps = useMemo(
|
|
41
|
+
() => ({
|
|
42
|
+
classes,
|
|
43
|
+
getItemKey,
|
|
44
|
+
items,
|
|
45
|
+
onSelectionChange,
|
|
46
|
+
selectionModel
|
|
47
|
+
}),
|
|
48
|
+
[classes, getItemKey, items, onSelectionChange, selectionModel]
|
|
49
|
+
);
|
|
47
50
|
|
|
48
51
|
const handleSelectionChange = useCallback(
|
|
49
52
|
selection => {
|
package/lib/Price/price.js
CHANGED
|
@@ -15,7 +15,6 @@ import { useIntl } from 'react-intl';
|
|
|
15
15
|
* [polyfill]: https://www.npmjs.com/package/intl
|
|
16
16
|
* [Intl.NumberFormat.prototype.formatToParts]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
18
|
const Price = props => {
|
|
20
19
|
const { locale } = useIntl();
|
|
21
20
|
const { value, currencyCode, classes } = props;
|
package/lib/context/cart.js
CHANGED
|
@@ -36,12 +36,6 @@ const CartContextProvider = props => {
|
|
|
36
36
|
}
|
|
37
37
|
}, [cartState]);
|
|
38
38
|
|
|
39
|
-
const derivedCartState = {
|
|
40
|
-
...cartState,
|
|
41
|
-
isEmpty: isCartEmpty(cartState),
|
|
42
|
-
derivedDetails
|
|
43
|
-
};
|
|
44
|
-
|
|
45
39
|
const cartApi = useMemo(
|
|
46
40
|
() => ({
|
|
47
41
|
actions,
|
|
@@ -50,10 +44,15 @@ const CartContextProvider = props => {
|
|
|
50
44
|
[actions, asyncActions]
|
|
51
45
|
);
|
|
52
46
|
|
|
53
|
-
const contextValue = useMemo(() =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
const contextValue = useMemo(() => {
|
|
48
|
+
const derivedCartState = {
|
|
49
|
+
...cartState,
|
|
50
|
+
isEmpty: isCartEmpty(cartState),
|
|
51
|
+
derivedDetails
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return [derivedCartState, cartApi];
|
|
55
|
+
}, [cartApi, cartState, derivedDetails]);
|
|
57
56
|
|
|
58
57
|
const [fetchCartId] = useMutation(CREATE_CART_MUTATION);
|
|
59
58
|
const fetchCartDetails = useAwaitQuery(CART_DETAILS_QUERY);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useFieldState } from 'informed';
|
|
3
|
+
|
|
4
|
+
const useInformedFieldStateWrapper = field => {
|
|
5
|
+
const [isInitialRender, setIsInitialRender] = useState(true);
|
|
6
|
+
const warn = console.warn;
|
|
7
|
+
// Temporarily override console warn to remove false positive warning from useFieldState
|
|
8
|
+
const regex = /^Attempting to get field (.*) but it does not exist$/g;
|
|
9
|
+
if (isInitialRender) {
|
|
10
|
+
console.warn = err => {
|
|
11
|
+
if (!err.match(regex)) {
|
|
12
|
+
warn(err);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
setIsInitialRender(false);
|
|
18
|
+
}, []);
|
|
19
|
+
const fieldState = useFieldState(field);
|
|
20
|
+
if (isInitialRender) {
|
|
21
|
+
console.warn = warn;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return fieldState;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default useInformedFieldStateWrapper;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { matchPath } from 'react-router';
|
|
3
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
4
|
+
import { useApolloClient } from '@apollo/client';
|
|
5
|
+
|
|
6
|
+
import { availableRoutes } from '@magento/venia-ui/lib/components/Routes/routes';
|
|
7
|
+
|
|
8
|
+
import { useAppContext } from '../context/app';
|
|
9
|
+
import { useRootComponents } from '../context/rootComponents';
|
|
10
|
+
import mergeOperations from '../util/shallowMerge';
|
|
11
|
+
import { getComponentData } from '../util/magentoRouteData';
|
|
12
|
+
import DEFAULT_OPERATIONS from '../talons/MagentoRoute/magentoRoute.gql';
|
|
13
|
+
import { getRootComponent } from '../talons/MagentoRoute/helpers';
|
|
14
|
+
|
|
15
|
+
const DELAY_MESSAGE_PREFIX = 'DELAY:';
|
|
16
|
+
|
|
17
|
+
const useDelayedTransition = () => {
|
|
18
|
+
const { pathname } = useLocation();
|
|
19
|
+
const history = useHistory();
|
|
20
|
+
const client = useApolloClient();
|
|
21
|
+
const operations = mergeOperations(DEFAULT_OPERATIONS);
|
|
22
|
+
const { resolveUrlQuery } = operations;
|
|
23
|
+
const [, setComponentMap] = useRootComponents();
|
|
24
|
+
const [, appApi] = useAppContext();
|
|
25
|
+
const { actions: appActions } = appApi;
|
|
26
|
+
const { setPageLoading } = appActions;
|
|
27
|
+
const unblock = useRef();
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
// Override globalThis.addEventListener to prevent binding beforeunload while we add our blocker
|
|
31
|
+
const originalWindowAddEventListener = globalThis.addEventListener;
|
|
32
|
+
globalThis.addEventListener = (type, listener, options) => {
|
|
33
|
+
if (type === 'beforeunload') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (typeof originalWindowAddEventListener === 'function') {
|
|
38
|
+
return originalWindowAddEventListener(type, listener, options);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
unblock.current = history.block(location => {
|
|
43
|
+
let currentPath = pathname;
|
|
44
|
+
|
|
45
|
+
if (process.env.USE_STORE_CODE_IN_URL === 'true') {
|
|
46
|
+
const storeCodes = AVAILABLE_STORE_VIEWS.map(
|
|
47
|
+
store => `\/?${store.code}`
|
|
48
|
+
).join('|');
|
|
49
|
+
const regex = new RegExp(`^${storeCodes}`);
|
|
50
|
+
currentPath = currentPath.replace(regex, '');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Ignore query string changes
|
|
54
|
+
if (location.pathname === currentPath) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Ignore hardcoded routes
|
|
59
|
+
const isInternalRoute = availableRoutes.some(
|
|
60
|
+
({ pattern: path, exact }) => {
|
|
61
|
+
return !!matchPath(location.pathname, {
|
|
62
|
+
path,
|
|
63
|
+
exact
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
if (isInternalRoute) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return `${DELAY_MESSAGE_PREFIX}${location.pathname}`;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
globalThis.addEventListener = originalWindowAddEventListener;
|
|
75
|
+
|
|
76
|
+
return () => {
|
|
77
|
+
if (typeof unblock.current === 'function') {
|
|
78
|
+
unblock.current();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}, [pathname, history]);
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
globalThis.handleRouteChangeConfirmation = async (message, proceed) => {
|
|
85
|
+
if (globalThis.avoidDelayedTransition) {
|
|
86
|
+
globalThis.avoidDelayedTransition = false;
|
|
87
|
+
if (typeof unblock.current === 'function') {
|
|
88
|
+
unblock.current();
|
|
89
|
+
}
|
|
90
|
+
return proceed(true);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
setPageLoading(true);
|
|
94
|
+
const currentPathname = message.replace(DELAY_MESSAGE_PREFIX, '');
|
|
95
|
+
|
|
96
|
+
const queryResult = await client.query({
|
|
97
|
+
query: resolveUrlQuery,
|
|
98
|
+
fetchPolicy: 'cache-first',
|
|
99
|
+
nextFetchPolicy: 'cache-first',
|
|
100
|
+
variables: { url: currentPathname }
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const { data } = queryResult;
|
|
104
|
+
const { route } = data || {};
|
|
105
|
+
const { type, ...routeData } = route || {};
|
|
106
|
+
|
|
107
|
+
if (type) {
|
|
108
|
+
const rootComponent = await getRootComponent(type);
|
|
109
|
+
setComponentMap(prevMap =>
|
|
110
|
+
new Map(prevMap).set(currentPathname, {
|
|
111
|
+
component: rootComponent,
|
|
112
|
+
...getComponentData(routeData),
|
|
113
|
+
type
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
setPageLoading(false);
|
|
119
|
+
if (typeof unblock.current === 'function') {
|
|
120
|
+
unblock.current();
|
|
121
|
+
}
|
|
122
|
+
proceed(true);
|
|
123
|
+
};
|
|
124
|
+
}, [client, resolveUrlQuery, setComponentMap, setPageLoading]);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default useDelayedTransition;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useLayoutEffect } from 'react';
|
|
2
|
+
import { makeVar } from '@apollo/client';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A hook that will detect if there is a scrollbar will be added to the viewport and
|
|
6
|
+
* will add its width value as a `--global-scrollbar-width` custom property to the body element,
|
|
7
|
+
* which can be used to calculate the full width of the viewport.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Check if the browser will add a scrollbar to the viewport
|
|
11
|
+
const getScrollBarWidth = () => {
|
|
12
|
+
const innerElement = document.createElement('div');
|
|
13
|
+
innerElement.style.cssText = 'width:100%;height:200px';
|
|
14
|
+
|
|
15
|
+
const outerElement = document.createElement('div');
|
|
16
|
+
outerElement.style.cssText =
|
|
17
|
+
'position:absolute;top:-50px;left:0px;visibility:hidden;width:50px;height:50px;overflow:hidden';
|
|
18
|
+
outerElement.appendChild(innerElement);
|
|
19
|
+
document.body.appendChild(outerElement);
|
|
20
|
+
const widthWithoutScroll = innerElement.offsetWidth;
|
|
21
|
+
outerElement.style.overflow = 'scroll';
|
|
22
|
+
let widthWithScroll = innerElement.offsetWidth;
|
|
23
|
+
if (widthWithoutScroll === widthWithScroll)
|
|
24
|
+
widthWithScroll = innerElement.clientWidth;
|
|
25
|
+
|
|
26
|
+
document.body.removeChild(outerElement);
|
|
27
|
+
|
|
28
|
+
return widthWithoutScroll - widthWithScroll;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Watching for body height changes, and setting custom property with scrollbar width, when scrollbar is present.
|
|
32
|
+
const createObserver = scrollBarWidth => {
|
|
33
|
+
return new globalThis.ResizeObserver(entries => {
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (entry.target.scrollHeight > globalThis.innerHeight) {
|
|
36
|
+
entry.target.style.setProperty(
|
|
37
|
+
'--global-scrollbar-width',
|
|
38
|
+
`${scrollBarWidth}px`
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
entry.target.style.setProperty(
|
|
42
|
+
'--global-scrollbar-width',
|
|
43
|
+
'0px'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
// Using Apollo reactive var to store observer status, in order to add observer only once.
|
|
50
|
+
const isObserverActive = makeVar(false);
|
|
51
|
+
|
|
52
|
+
export const useDetectScrollWidth = () => {
|
|
53
|
+
useLayoutEffect(() => {
|
|
54
|
+
if (isObserverActive()) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const scrollBarWidth = getScrollBarWidth();
|
|
58
|
+
const observer =
|
|
59
|
+
typeof globalThis.ResizeObserver !== 'undefined' &&
|
|
60
|
+
scrollBarWidth !== 0
|
|
61
|
+
? createObserver(scrollBarWidth)
|
|
62
|
+
: null;
|
|
63
|
+
|
|
64
|
+
if (observer) {
|
|
65
|
+
observer.observe(document.body);
|
|
66
|
+
isObserverActive(true);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return () => {
|
|
70
|
+
if (observer) {
|
|
71
|
+
observer.disconnect();
|
|
72
|
+
document.body.style.removeProperty('--global-scrollbar-width');
|
|
73
|
+
isObserverActive(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}, []);
|
|
77
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useAppContext } from '../context/app';
|
|
3
|
+
|
|
4
|
+
export const SHIMMER_TYPE_SUFFIX = '_SHIMMER';
|
|
5
|
+
|
|
6
|
+
export default rootType => {
|
|
7
|
+
const [, appApi] = useAppContext();
|
|
8
|
+
const { actions: appActions } = appApi;
|
|
9
|
+
const { setNextRootComponent } = appActions;
|
|
10
|
+
|
|
11
|
+
const type = `${rootType.toUpperCase()}${SHIMMER_TYPE_SUFFIX}`;
|
|
12
|
+
|
|
13
|
+
const setShimmerType = useCallback(() => {
|
|
14
|
+
globalThis.avoidDelayedTransition = true;
|
|
15
|
+
setNextRootComponent(type);
|
|
16
|
+
}, [setNextRootComponent, type]);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
setShimmerType
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import useIntersectionObserver from '@magento/peregrine/lib/hooks/useIntersectionObserver';
|
|
4
|
+
|
|
5
|
+
export const useIsInViewport = props => {
|
|
6
|
+
const { elementRef, renderOnce = true } = props;
|
|
7
|
+
const intersectionObserver = useIntersectionObserver();
|
|
8
|
+
const [isInViewport, setIsInViewport] = useState(false);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!elementRef || !elementRef.current || !intersectionObserver) {
|
|
12
|
+
setIsInViewport(true);
|
|
13
|
+
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Prevent init if already rendered once
|
|
18
|
+
if (isInViewport && renderOnce) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const htmlElement = elementRef.current;
|
|
23
|
+
const elementObserver = new IntersectionObserver(
|
|
24
|
+
(entries, observer) => {
|
|
25
|
+
const isIntersecting =
|
|
26
|
+
entries.some(entry => entry.isIntersecting) === true;
|
|
27
|
+
setIsInViewport(isIntersecting);
|
|
28
|
+
|
|
29
|
+
// Stop observing if already rendered once
|
|
30
|
+
if (isIntersecting && renderOnce) {
|
|
31
|
+
observer.unobserve(htmlElement);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
elementObserver.observe(htmlElement);
|
|
37
|
+
|
|
38
|
+
return () => {
|
|
39
|
+
elementObserver.unobserve(htmlElement);
|
|
40
|
+
};
|
|
41
|
+
}, [elementRef, intersectionObserver, isInViewport, renderOnce]);
|
|
42
|
+
|
|
43
|
+
return isInViewport;
|
|
44
|
+
};
|
|
@@ -16,7 +16,8 @@ const initialState = {
|
|
|
16
16
|
isPageLoading: false,
|
|
17
17
|
overlay: false,
|
|
18
18
|
pending: {},
|
|
19
|
-
searchOpen: false
|
|
19
|
+
searchOpen: false,
|
|
20
|
+
nextRootComponent: null
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
const reducerMap = {
|
|
@@ -51,6 +52,12 @@ const reducerMap = {
|
|
|
51
52
|
...state,
|
|
52
53
|
isPageLoading: !!payload
|
|
53
54
|
};
|
|
55
|
+
},
|
|
56
|
+
[actions.setNextRootComponent]: (state, { payload }) => {
|
|
57
|
+
return {
|
|
58
|
+
...state,
|
|
59
|
+
nextRootComponent: payload
|
|
60
|
+
};
|
|
54
61
|
}
|
|
55
62
|
};
|
|
56
63
|
|
|
@@ -7,12 +7,13 @@ import { RetryLink } from '@apollo/client/link/retry';
|
|
|
7
7
|
import { CachePersistor } from 'apollo-cache-persist';
|
|
8
8
|
import getWithPath from 'lodash.get';
|
|
9
9
|
import setWithPath from 'lodash.set';
|
|
10
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
10
|
+
import { useEffect, useMemo, useState, useCallback } from 'react';
|
|
11
11
|
|
|
12
12
|
import MutationQueueLink from '@adobe/apollo-link-mutation-queue';
|
|
13
13
|
import attachClient from '@magento/peregrine/lib/Apollo/attachClientToStore';
|
|
14
14
|
import { CACHE_PERSIST_PREFIX } from '@magento/peregrine/lib/Apollo/constants';
|
|
15
15
|
import typePolicies from '@magento/peregrine/lib/Apollo/policies';
|
|
16
|
+
import MagentoGQLCacheLink from '@magento/peregrine/lib/Apollo/magentoGqlCacheLink';
|
|
16
17
|
import { BrowserPersistence } from '@magento/peregrine/lib/util';
|
|
17
18
|
import shrinkQuery from '@magento/peregrine/lib/util/shrinkQuery';
|
|
18
19
|
|
|
@@ -160,6 +161,8 @@ export const useAdapter = props => {
|
|
|
160
161
|
[]
|
|
161
162
|
);
|
|
162
163
|
|
|
164
|
+
const magentoGqlCacheLink = useMemo(() => new MagentoGQLCacheLink(), []);
|
|
165
|
+
|
|
163
166
|
const apolloLink = useMemo(
|
|
164
167
|
() =>
|
|
165
168
|
ApolloLink.from([
|
|
@@ -168,11 +171,20 @@ export const useAdapter = props => {
|
|
|
168
171
|
mutationQueueLink,
|
|
169
172
|
retryLink,
|
|
170
173
|
authLink,
|
|
174
|
+
magentoGqlCacheLink,
|
|
171
175
|
storeLink,
|
|
172
176
|
errorLink,
|
|
173
177
|
httpLink
|
|
174
178
|
]),
|
|
175
|
-
[
|
|
179
|
+
[
|
|
180
|
+
authLink,
|
|
181
|
+
errorLink,
|
|
182
|
+
httpLink,
|
|
183
|
+
magentoGqlCacheLink,
|
|
184
|
+
mutationQueueLink,
|
|
185
|
+
retryLink,
|
|
186
|
+
storeLink
|
|
187
|
+
]
|
|
176
188
|
);
|
|
177
189
|
|
|
178
190
|
const apolloClient = useMemo(() => {
|
|
@@ -199,9 +211,17 @@ export const useAdapter = props => {
|
|
|
199
211
|
return client;
|
|
200
212
|
}, [apiBase, apolloLink]);
|
|
201
213
|
|
|
214
|
+
const getUserConfirmation = useCallback(async (message, callback) => {
|
|
215
|
+
if (typeof globalThis.handleRouteChangeConfirmation === 'function') {
|
|
216
|
+
return globalThis.handleRouteChangeConfirmation(message, callback);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return callback(globalThis.confirm(message));
|
|
220
|
+
}, []);
|
|
221
|
+
|
|
202
222
|
const apolloProps = { client: apolloClient };
|
|
203
223
|
const reduxProps = { store };
|
|
204
|
-
const routerProps = { basename };
|
|
224
|
+
const routerProps = { basename, getUserConfirmation };
|
|
205
225
|
const styleProps = { initialState: styles };
|
|
206
226
|
|
|
207
227
|
// perform blocking async work here
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { useHistory } from 'react-router-dom';
|
|
3
2
|
import { useMutation, useQuery } from '@apollo/client';
|
|
4
3
|
|
|
5
4
|
import { useAppContext } from '@magento/peregrine/lib/context/app';
|
|
@@ -38,8 +37,6 @@ export const useAddressBookPage = (props = {}) => {
|
|
|
38
37
|
] = useAppContext();
|
|
39
38
|
const [{ isSignedIn }] = useUserContext();
|
|
40
39
|
|
|
41
|
-
const history = useHistory();
|
|
42
|
-
|
|
43
40
|
const { data: customerAddressesData, loading } = useQuery(
|
|
44
41
|
getCustomerAddressesQuery,
|
|
45
42
|
{
|
|
@@ -85,13 +82,6 @@ export const useAddressBookPage = (props = {}) => {
|
|
|
85
82
|
// https://github.com/apollographql/apollo-feature-requests/issues/170
|
|
86
83
|
const [displayError, setDisplayError] = useState(false);
|
|
87
84
|
|
|
88
|
-
// If the user is no longer signed in, redirect to the home page.
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
if (!isSignedIn) {
|
|
91
|
-
history.push('/');
|
|
92
|
-
}
|
|
93
|
-
}, [history, isSignedIn]);
|
|
94
|
-
|
|
95
85
|
// Update the page indicator if the GraphQL query is in flight.
|
|
96
86
|
useEffect(() => {
|
|
97
87
|
setPageLoading(isRefetching);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { gql } from '@apollo/client';
|
|
2
2
|
|
|
3
|
+
export const GET_STORE_CONFIG_DATA = gql`
|
|
4
|
+
query GetStoreConfigForBreadcrumbs {
|
|
5
|
+
storeConfig {
|
|
6
|
+
id
|
|
7
|
+
category_url_suffix
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
3
12
|
export const GET_BREADCRUMBS = gql`
|
|
4
13
|
query GetBreadcrumbs($category_id: Int!) {
|
|
5
14
|
category(id: $category_id) {
|
|
@@ -13,11 +22,11 @@ export const GET_BREADCRUMBS = gql`
|
|
|
13
22
|
id
|
|
14
23
|
name
|
|
15
24
|
url_path
|
|
16
|
-
url_suffix
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
`;
|
|
20
28
|
|
|
21
29
|
export default {
|
|
22
|
-
getBreadcrumbsQuery: GET_BREADCRUMBS
|
|
30
|
+
getBreadcrumbsQuery: GET_BREADCRUMBS,
|
|
31
|
+
getStoreConfigQuery: GET_STORE_CONFIG_DATA
|
|
23
32
|
};
|