@shopgate/engage 7.32.0-beta.7 → 7.32.0-beta.9
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/account/components/Profile/Profile.provider.d.ts +1 -1
- package/account/components/Profile/ProfileAddressBook.d.ts.map +1 -1
- package/account/components/Profile/ProfileAddressBook.js +13 -22
- package/account/components/Profile/ProfileAddressCard.d.ts.map +1 -1
- package/account/components/Profile/ProfileAddressCard.js +8 -18
- package/account/components/Profile/ProfileForm.d.ts.map +1 -1
- package/account/components/Profile/ProfileForm.js +15 -42
- package/account/components/ProfileContact/ProfileContact.js +13 -21
- package/admin-preview/components/FrontendSettingsPreviewBridge/FrontendSettingsPreviewBridge.d.ts.map +1 -1
- package/admin-preview/components/FrontendSettingsPreviewBridge/FrontendSettingsPreviewBridge.js +41 -7
- package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts +7 -0
- package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts.map +1 -1
- package/admin-preview/initialization/_internal/initialFrontendSettings.d.ts +32 -0
- package/admin-preview/initialization/_internal/initialFrontendSettings.d.ts.map +1 -0
- package/admin-preview/initialization/_internal/initialFrontendSettings.js +43 -0
- package/admin-preview/initialization/awaitInitialFrontendSettings.d.ts +22 -0
- package/admin-preview/initialization/awaitInitialFrontendSettings.d.ts.map +1 -0
- package/admin-preview/initialization/awaitInitialFrontendSettings.js +84 -0
- package/back-in-stock/components/BackInStockButton/index.js +5 -5
- package/cart/components/CartItem/CartItemProductLayout.js +1 -0
- package/cart/components/CartItem/CartItemProductLayoutWideRemoveItem.js +7 -14
- package/cart/components/CartItem/CartItemQuantityPicker.js +1 -0
- package/cart/components/CartItems/CartItemCardReservationLabelChangeStore.js +6 -24
- package/cart/components/CartSummaryWide/CartSummaryWide.js +2 -2
- package/cart/components/CartSummaryWide/CartSummaryWideCheckoutButton.js +9 -23
- package/cart/components/PaymentBar/PaymentBarCheckoutButton.js +8 -30
- package/cart/components/PaymentBar/testUtils/mockFactories.js +4 -11
- package/category/components/CategoryImage/index.js +13 -2
- package/checkout/components/AddressBook/AddressList.js +14 -23
- package/checkout/components/Checkout/CheckoutActions.js +4 -3
- package/checkout/components/Checkout/CheckoutAddress.js +8 -0
- package/checkout/components/Checkout/CheckoutSection.js +6 -2
- package/checkout/components/CheckoutConfirmation/CheckoutConfirmation.js +6 -7
- package/checkout/components/ResponsiveBackButton/ResponsiveBackButton.js +7 -17
- package/components/Badge/spec.js +6 -29
- package/components/Card/Card.js +1 -1
- package/components/ChipLayout/index.js +2 -4
- package/components/NavigationHandler/connector.js +1 -1
- package/components/NavigationHandler/index.d.ts +2 -2
- package/components/NavigationHandler/spec.js +10 -1
- package/components/Paper/Paper.d.ts +1 -2
- package/components/Paper/Paper.d.ts.map +1 -1
- package/components/Paper/spec.js +5 -22
- package/components/Tabs/components/Tab.d.ts.map +1 -1
- package/components/Tabs/components/Tab.js +14 -16
- package/components/Typography/Typography.d.ts +1 -1
- package/components/v2/Button/Button.d.ts +24 -13
- package/components/v2/Button/Button.d.ts.map +1 -1
- package/components/v2/Button/Button.js +139 -41
- package/components/v2/ButtonBase/ButtonBase.d.ts +50 -10
- package/components/v2/ButtonBase/ButtonBase.d.ts.map +1 -1
- package/components/v2/ButtonBase/ButtonBase.js +192 -17
- package/components/v2/ButtonBase/hooks.d.ts +0 -1
- package/components/v2/ButtonBase/hooks.d.ts.map +1 -1
- package/components/v2/ButtonBase/hooks.js +36 -12
- package/components/v2/ButtonGroup/ButtonGroup.d.ts +11 -5
- package/components/v2/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/components/v2/ButtonGroup/ButtonGroup.js +49 -26
- package/components/v2/CircularProgress/CircularProgress.d.ts.map +1 -1
- package/components/v2/CircularProgress/CircularProgress.js +10 -5
- package/core/hooks/useNavigation.d.ts +10 -2
- package/core/hooks/useNavigation.d.ts.map +1 -1
- package/core/hooks/useNavigation.js +1 -2
- package/core/initialization/index.d.ts.map +1 -1
- package/core/initialization/index.js +24 -5
- package/core/router/conductor.d.ts +9 -0
- package/core/router/helpers.d.ts +28 -15
- package/core/router/helpers.d.ts.map +1 -1
- package/core/router/helpers.js +8 -8
- package/development/components/DevelopmentSettings/DevelopmentSettings.js +3 -3
- package/favorites/components/FavoriteButtonWide/FavoriteButtonWide.js +7 -17
- package/favorites/components/List/List.d.ts.map +1 -1
- package/favorites/components/List/List.js +0 -1
- package/favorites/components/List/ListContent.js +4 -5
- package/favorites/components/Lists/Lists.js +4 -5
- package/filter/components/FilterPageContent/components/ApplyButton/index.js +8 -10
- package/filter/components/FilterPageContent/components/ResetButton/index.js +8 -6
- package/locations/components/ChangeLocationButton/ChangeLocationButton.js +10 -14
- package/locations/components/FulfillmentSlotSwitcher/FulfillmentSlotDialog.js +4 -8
- package/locations/components/FulfillmentSlotSwitcher/FulfillmentSlotSwitcher.js +1 -1
- package/locations/components/FulfillmentSlotSwitcher/FulfillmentSlotSwitcherBar.js +8 -13
- package/locations/components/FulfillmentSlotSwitcher/FulfillmentSlotSwitcherDefault.js +10 -10
- package/locations/components/GlobalLocationSwitcher/GlobalLocationSwitcherBar.js +8 -14
- package/locations/components/GlobalLocationSwitcher/GlobalLocationSwitcherDefault.js +9 -10
- package/locations/components/ReserveForm/ReserveForm.js +6 -7
- package/locations/components/StoreDetails/components/GetDirectionsButton.js +2 -4
- package/locations/components/StoreDetails/components/StoreDetails.js +5 -10
- package/locations/components/StoreDetails/components/StoresNearbyListItem.js +13 -21
- package/locations/components/StoreFinder/StoreFinderSelectLocationButton.js +5 -11
- package/locations/components/StoreFinder/StoreFinderStoreInfoButton.js +5 -11
- package/locations/components/StoreList/StoreListSearch.js +1 -0
- package/locations/components/StoreList/StoreSelectLocationButton.js +5 -11
- package/login/components/ForgotPassword/ForgotPassword.js +11 -23
- package/orders/components/OrderDetails/OrderDetailsAuthenticate.js +5 -7
- package/package.json +7 -7
- package/page/components/NotFound.d.ts.map +1 -1
- package/page/components/NotFound.js +7 -6
- package/page/components/ResponsiveWidgetImage/ResponsiveWidgetImage.d.ts +1 -1
- package/page/components/ResponsiveWidgetImage/ResponsiveWidgetImage.js +2 -2
- package/page/components/WidgetVideo/WidgetVideo.d.ts +1 -1
- package/page/components/WidgetVideo/WidgetVideo.d.ts.map +1 -1
- package/page/helpers/index.d.ts +5 -2
- package/page/helpers/index.d.ts.map +1 -1
- package/page/helpers/index.js +8 -5
- package/page/widgets/Button/Button.js +2 -3
- package/page/widgets/NestedCategoryFilter/NestedCategoryFilter.js +8 -8
- package/page/widgets/ProductList/ProductList.js +18 -14
- package/page/widgets/Video/hooks.d.ts +2 -2
- package/product/components/ProductCard/index.js +7 -1
- package/product/components/ProductGrid/components/Item/components/ItemDetails/index.js +6 -1
- package/product/components/ProductGrid/components/Item/components/ItemImage/index.js +1 -11
- package/product/components/ProductGrid/components/Item/index.js +3 -2
- package/product/components/ProductGrid/components/Layout/index.js +2 -1
- package/product/components/ProductGridPrice/index.js +0 -1
- package/product/components/ProductImage/ProductImage.d.ts.map +1 -1
- package/product/components/ProductImage/ProductImage.js +7 -2
- package/product/components/ProductImage/ProductImagePlaceholder.js +3 -3
- package/product/components/ProductSlider/index.js +1 -1
- package/product/components/UnitQuantityPicker/UnitQuantityPicker.d.ts.map +1 -1
- package/product/components/UnitQuantityPicker/UnitQuantityPicker.js +15 -33
- package/push-opt-in/components/PushOptInModal/index.js +4 -4
- package/registration/components/Registration/RegistrationFormActions.js +4 -4
- package/reviews/components/Reviews/components/AllReviewsLink/index.js +6 -6
- package/reviews/components/Reviews/components/Header/components/WriteReviewLink/index.js +4 -3
- package/reviews/components/Reviews/components/Header/components/WriteReviewLink/spec.js +28 -22
- package/reviews/components/Reviews/spec.js +5 -6
- package/settings/reducers/appSettings.d.ts.map +1 -1
- package/settings/reducers/appSettings.js +18 -2
- package/settings/selectors/appSettings.d.ts +37 -2
- package/settings/selectors/appSettings.d.ts.map +1 -1
- package/settings/selectors/appSettings.js +30 -1
- package/settings/types/appSettings.d.ts +42 -2
- package/settings/types/appSettings.d.ts.map +1 -1
- package/settings/types/appSettings.js +124 -1
- package/styles/helpers/index.d.ts +1 -0
- package/styles/helpers/index.js +1 -0
- package/styles/helpers/loadFontCss.d.ts +22 -0
- package/styles/helpers/loadFontCss.d.ts.map +1 -0
- package/styles/helpers/loadFontCss.js +138 -0
- package/styles/helpers/loadThemeCss.d.ts.map +1 -1
- package/styles/helpers/loadThemeCss.js +11 -0
- package/styles/index.d.ts +1 -1
- package/styles/index.d.ts.map +1 -1
- package/styles/theme/createDefaultThemeOptions/index.d.ts.map +1 -1
- package/styles/theme/createDefaultThemeOptions/index.js +94 -3
- package/styles/theme/createTheme/createComponents.types.d.ts +25 -0
- package/styles/theme/createTheme/createComponents.types.d.ts.map +1 -1
- package/styles/theme/createTheme/createComponents.types.js +28 -3
- package/styles/theme/createTheme/createShape.d.ts +2 -3
- package/styles/theme/createTheme/createShape.d.ts.map +1 -1
- package/styles/theme/createTheme/createShape.js +1 -2
- package/styles/theme/createTheme/createThemeFromColorScheme.d.ts +3 -1
- package/styles/theme/createTheme/createThemeFromColorScheme.d.ts.map +1 -1
- package/styles/theme/createTheme/createThemeFromColorScheme.js +4 -2
- package/styles/theme/createTheme/createTypography.d.ts +2 -1
- package/styles/theme/createTheme/createTypography.js +58 -18
- package/styles/theme/createTheme/index.d.ts +2 -2
- package/styles/theme/createTheme/index.d.ts.map +1 -1
- package/styles/theme/createTheme/index.js +2 -2
- package/styles/theme/createTheme/types.d.ts +9 -2
- package/styles/theme/createTheme/types.d.ts.map +1 -1
- package/styles/theme/createTheme/types.js +6 -0
- package/styles/theme/hooks/useColorScheme.d.ts +2 -2
- package/styles/theme/hooks/useColorScheme.d.ts.map +1 -1
- package/styles/theme/hooks/useColorScheme.js +1 -1
- package/styles/theme/hooks/useMediaQuery.d.ts +7 -0
- package/styles/theme/hooks/useMediaQuery.d.ts.map +1 -1
- package/styles/theme/hooks/useMediaQuery.js +5 -5
- package/styles/theme/hooks/useTheme.js +1 -1
- package/styles/theme/index.d.ts +3 -1
- package/styles/theme/index.d.ts.map +1 -1
- package/styles/theme/providers/ColorSchemeContext.d.ts +30 -9
- package/styles/theme/providers/ColorSchemeContext.d.ts.map +1 -1
- package/styles/theme/providers/ColorSchemeContext.js +8 -0
- package/styles/theme/providers/ThemeContext.d.ts +3 -0
- package/styles/theme/providers/ThemeContext.d.ts.map +1 -0
- package/styles/theme/providers/ThemeContext.js +2 -0
- package/styles/theme/providers/ThemeProvider.d.ts +2 -2
- package/styles/theme/providers/ThemeProvider.d.ts.map +1 -1
- package/styles/theme/providers/ThemeProvider.js +58 -16
- package/styles/theme/utils/color.d.ts +12 -12
- package/styles/theme/utils/color.d.ts.map +1 -1
- package/tracking/components/CookieConsentModal/index.js +3 -4
- package/tracking/components/PrivacySettings/index.js +3 -3
- package/cart/components/PaymentBar/PaymentBarReserveButton.connector.js +0 -6
- package/cart/components/PaymentBar/PaymentBarReserveButton.js +0 -71
- package/locations/components/StoreFinder/StoreFinderGetDirectionsButton.connector.js +0 -16
- package/locations/components/StoreFinder/StoreFinderGetDirectionsButton.js +0 -52
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
* The ButtonBase component serves as a foundational button element that can be extended with
|
|
4
|
-
* additional styles and functionality. It handles basic button behavior, including disabled
|
|
5
|
-
* state and type validation.
|
|
6
|
-
*/
|
|
7
|
-
declare const ButtonBase: React.ForwardRefExoticComponent<ButtonBaseOwnProps & React.ButtonHTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>>;
|
|
2
|
+
import type { NavigationState } from '@shopgate/engage/core/router/helpers';
|
|
8
3
|
declare const useStyles: (params: void, muiStyleOverridesParams?: {
|
|
9
4
|
props: Record<string, unknown>;
|
|
10
5
|
ownerState?: Record<string, unknown> | undefined;
|
|
@@ -14,9 +9,41 @@ declare const useStyles: (params: void, muiStyleOverridesParams?: {
|
|
|
14
9
|
css: import("tss-react").Css;
|
|
15
10
|
cx: import("tss-react").Cx;
|
|
16
11
|
};
|
|
17
|
-
export interface
|
|
12
|
+
export interface LinkOptions {
|
|
18
13
|
/**
|
|
19
|
-
*
|
|
14
|
+
* Meta state to attach to the target route.
|
|
15
|
+
*/
|
|
16
|
+
state?: NavigationState;
|
|
17
|
+
/**
|
|
18
|
+
* Where to open the target, e.g. `_blank`. Read by the router when the target is an external
|
|
19
|
+
* or a native link.
|
|
20
|
+
*/
|
|
21
|
+
target?: string;
|
|
22
|
+
/**
|
|
23
|
+
* If true, the current route is replaced instead of a new one being pushed.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
replace?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface ButtonBaseOwnProps<C extends React.ElementType = 'button'> {
|
|
29
|
+
/**
|
|
30
|
+
* The element or component rendered as the root node. Defaults to `button`, or to `a` on web
|
|
31
|
+
* builds when `href` is set. Note that a non focusable element (e.g. `div`) needs its own
|
|
32
|
+
* `tabIndex` to stay keyboard operable.
|
|
33
|
+
*/
|
|
34
|
+
component?: C;
|
|
35
|
+
/**
|
|
36
|
+
* Renders the button as a link to this path. Navigation goes through the app router rather than
|
|
37
|
+
* the browser, so external and native URLs are handled as well.
|
|
38
|
+
*/
|
|
39
|
+
href?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Navigation options. Only meaningful together with `href`.
|
|
42
|
+
*/
|
|
43
|
+
linkOptions?: LinkOptions;
|
|
44
|
+
/**
|
|
45
|
+
* If true, the button will be disabled and not respond to user interactions. Rendered as the
|
|
46
|
+
* native attribute on a button, and as `aria-disabled` on any other element.
|
|
20
47
|
* @default false
|
|
21
48
|
*/
|
|
22
49
|
disabled?: boolean;
|
|
@@ -25,16 +52,29 @@ export interface ButtonBaseOwnProps {
|
|
|
25
52
|
* @default false
|
|
26
53
|
*/
|
|
27
54
|
disableRipple?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* If true, the `engage__button-base` css hook is not rendered. Set by wrappers that provide a
|
|
57
|
+
* hook of their own, such as `Button`.
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
disableBaseClassName?: boolean;
|
|
28
61
|
/**
|
|
29
62
|
* Custom class name for the button.
|
|
30
63
|
*/
|
|
31
64
|
className?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Value for the `data-test-id` attribute of the button.
|
|
67
|
+
*/
|
|
68
|
+
testId?: string;
|
|
32
69
|
/**
|
|
33
70
|
* Override or extend the styles applied to the component.
|
|
34
71
|
*/
|
|
35
72
|
classes?: Partial<ReturnType<typeof useStyles>['classes']>;
|
|
36
73
|
children: React.ReactNode;
|
|
37
74
|
}
|
|
38
|
-
export type ButtonBaseProps = ButtonBaseOwnProps & React.
|
|
39
|
-
|
|
75
|
+
export type ButtonBaseProps<C extends React.ElementType = 'button'> = ButtonBaseOwnProps<C> & Omit<React.ComponentPropsWithRef<C>, keyof ButtonBaseOwnProps<C>>;
|
|
76
|
+
declare const _default: <C extends React.ElementType = "button">(props: ButtonBaseProps<C> & {
|
|
77
|
+
ref?: React.ComponentPropsWithRef<C>["ref"];
|
|
78
|
+
}) => React.ReactElement | null;
|
|
79
|
+
export default _default;
|
|
40
80
|
//# sourceMappingURL=ButtonBase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ButtonBase.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonBase/ButtonBase.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ButtonBase.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonBase/ButtonBase.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAOrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AA0Q5E,QAAA,MAAM,SAAS;;cArLJ,CAAC;;;;;;CAuNV,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,QAAQ;IACxE;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,QAAQ,IAChE,kBAAkB,CAAC,CAAC,CAAC,GACrB,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,MAAM,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;wBAQhC,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,QAAQ,EACzE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;CAAE,KACxE,KAAK,CAAC,YAAY,GAAG,IAAI;AAF9B,wBAE+B"}
|
|
@@ -1,87 +1,254 @@
|
|
|
1
1
|
import "core-js/modules/es.array.includes.js";
|
|
2
|
-
import
|
|
2
|
+
import "core-js/modules/es.string.replace.js";
|
|
3
|
+
import React, { forwardRef, useEffect } from 'react';
|
|
3
4
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
4
5
|
import { useReduceMotion } from '@shopgate/engage/a11y/hooks';
|
|
6
|
+
// Imported from the defining modules instead of the `core` barrels on purpose: `core/hooks` imports
|
|
7
|
+
// from `engage/components`, so going through a barrel would create a circular import.
|
|
8
|
+
import { useNavigation } from '@shopgate/engage/core/hooks/useNavigation';
|
|
9
|
+
import { hasWebBridge } from '@shopgate/engage/core/helpers/bridge';
|
|
5
10
|
import Ripple from "./Ripple";
|
|
6
11
|
import { usePressRipple } from "./hooks";
|
|
7
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
13
|
const supportedButtonTypes = ['button', 'submit', 'reset'];
|
|
9
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Whether a pointer position sits within the bounds of an element.
|
|
17
|
+
* @param element The element to measure.
|
|
18
|
+
* @param clientX Horizontal position of the pointer.
|
|
19
|
+
* @param clientY Vertical position of the pointer.
|
|
20
|
+
* @returns Whether the position is inside the element.
|
|
21
|
+
*/
|
|
22
|
+
const containsPoint = (element, clientX, clientY) => {
|
|
23
|
+
const {
|
|
24
|
+
top,
|
|
25
|
+
right,
|
|
26
|
+
bottom,
|
|
27
|
+
left
|
|
28
|
+
} = element.getBoundingClientRect();
|
|
29
|
+
return clientX >= left && clientX <= right && clientY >= top && clientY <= bottom;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Props read off the resolved element rather than declared on `ButtonBaseOwnProps`. Typed loosely
|
|
34
|
+
* because the element type is generic - `React.ComponentPropsWithRef<C>` keeps consumers exact.
|
|
35
|
+
*/
|
|
36
|
+
|
|
10
37
|
/**
|
|
11
38
|
* The ButtonBase component serves as a foundational button element that can be extended with
|
|
12
39
|
* additional styles and functionality. It handles basic button behavior, including disabled
|
|
13
40
|
* state and type validation.
|
|
14
41
|
*/
|
|
15
|
-
|
|
42
|
+
function ButtonBase(props, ref) {
|
|
16
43
|
const {
|
|
44
|
+
component,
|
|
45
|
+
href,
|
|
46
|
+
linkOptions,
|
|
17
47
|
disabled = false,
|
|
18
48
|
disableRipple: disableRippleProp = false,
|
|
49
|
+
disableBaseClassName = false,
|
|
50
|
+
className,
|
|
51
|
+
classes: classesProp,
|
|
52
|
+
testId,
|
|
53
|
+
children,
|
|
54
|
+
...rest
|
|
55
|
+
} = props;
|
|
56
|
+
const {
|
|
19
57
|
type = 'button',
|
|
58
|
+
onClick,
|
|
59
|
+
onKeyDown,
|
|
20
60
|
onPointerDown,
|
|
21
61
|
onPointerUp,
|
|
22
62
|
onPointerLeave,
|
|
23
63
|
onPointerCancel,
|
|
24
|
-
className,
|
|
25
|
-
children,
|
|
26
64
|
...other
|
|
27
|
-
} =
|
|
65
|
+
} = rest;
|
|
28
66
|
const {
|
|
29
67
|
classes,
|
|
30
68
|
cx
|
|
31
69
|
} = useStyles(undefined, {
|
|
32
70
|
props: {
|
|
33
|
-
classes:
|
|
71
|
+
classes: classesProp
|
|
34
72
|
}
|
|
35
73
|
});
|
|
36
74
|
const {
|
|
37
75
|
ripples,
|
|
38
76
|
start,
|
|
39
|
-
end
|
|
77
|
+
end,
|
|
78
|
+
clearAll
|
|
40
79
|
} = usePressRipple();
|
|
41
80
|
const reduceMotion = useReduceMotion();
|
|
81
|
+
const {
|
|
82
|
+
push,
|
|
83
|
+
replace
|
|
84
|
+
} = useNavigation();
|
|
42
85
|
const disableRipple = disableRippleProp || reduceMotion;
|
|
86
|
+
|
|
87
|
+
// A button that disables itself on click gets `pointer-events: none`, which makes the browser
|
|
88
|
+
// drop the pointer capture. The pointer up then lands somewhere else and the ripple would never
|
|
89
|
+
// be told to finish, so it's cleared here instead.
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (disabled) {
|
|
92
|
+
clearAll();
|
|
93
|
+
}
|
|
94
|
+
}, [disabled, clearAll]);
|
|
95
|
+
|
|
96
|
+
// A real anchor is only safe on web builds. Inside the app webview `preventDefault()` sometimes
|
|
97
|
+
// fails and the page navigates for real, so link buttons stay `<button>` there.
|
|
98
|
+
const Component = component || (href && hasWebBridge() ? 'a' : 'button');
|
|
99
|
+
const isButtonElement = Component === 'button';
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Hands the target over to the app router. Deferred like the `Link` component does, so the
|
|
103
|
+
* current event finishes dispatching before the route changes.
|
|
104
|
+
*/
|
|
105
|
+
const navigate = () => {
|
|
106
|
+
if (!href) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const state = {
|
|
110
|
+
...linkOptions?.state,
|
|
111
|
+
...(linkOptions?.target ? {
|
|
112
|
+
target: linkOptions.target
|
|
113
|
+
} : {})
|
|
114
|
+
};
|
|
115
|
+
const params = {
|
|
116
|
+
pathname: href,
|
|
117
|
+
...(Object.keys(state).length ? {
|
|
118
|
+
state
|
|
119
|
+
} : {})
|
|
120
|
+
};
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
if (linkOptions?.replace) {
|
|
123
|
+
replace(params);
|
|
124
|
+
} else {
|
|
125
|
+
push(params);
|
|
126
|
+
}
|
|
127
|
+
}, 0);
|
|
128
|
+
};
|
|
129
|
+
const handleClick = event => {
|
|
130
|
+
if (disabled) {
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// The pointer capture taken on pointer down redirects the release to this element, so a pointer
|
|
136
|
+
// that went up somewhere else still arrives here as a click. Without the capture the browser
|
|
137
|
+
// would have dropped it. Keyboard activation reports no button presses and carries no position,
|
|
138
|
+
// so it never takes this path.
|
|
139
|
+
if (event.detail > 0 && !containsPoint(event.currentTarget, event.clientX, event.clientY)) {
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
onClick?.(event);
|
|
144
|
+
if (!href || event.defaultPrevented) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
event.preventDefault();
|
|
148
|
+
navigate();
|
|
149
|
+
};
|
|
150
|
+
const handleKeyDown = event => {
|
|
151
|
+
onKeyDown?.(event);
|
|
152
|
+
if (isButtonElement || disabled || event.defaultPrevented) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Only buttons activate on Enter and Space. Preventing the default also stops an anchor from
|
|
160
|
+
// firing its own click on Enter, so the element is activated exactly once.
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
event.currentTarget.click();
|
|
163
|
+
};
|
|
43
164
|
const handlePointerDown = event => {
|
|
44
|
-
if (
|
|
165
|
+
if (disabled) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (!disableRipple) {
|
|
45
169
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
46
170
|
start(event);
|
|
47
171
|
}
|
|
48
172
|
onPointerDown?.(event);
|
|
49
173
|
};
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Gives up pointer capture that was taken on pointer down. While an element captures the pointer,
|
|
177
|
+
* hit testing is redirected to it, so it keeps matching `:hover` and never receives a leave event.
|
|
178
|
+
* @param event The pointer event.
|
|
179
|
+
*/
|
|
180
|
+
const releaseCapture = event => {
|
|
181
|
+
const target = event.currentTarget;
|
|
182
|
+
if (target.hasPointerCapture?.(event.pointerId)) {
|
|
183
|
+
target.releasePointerCapture(event.pointerId);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
50
186
|
const handlePointerUp = event => {
|
|
187
|
+
releaseCapture(event);
|
|
51
188
|
if (!disableRipple) {
|
|
52
189
|
end(event.pointerId);
|
|
53
190
|
}
|
|
191
|
+
if (disabled) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
54
194
|
onPointerUp?.(event);
|
|
55
195
|
};
|
|
56
196
|
const handlePointerCancel = event => {
|
|
197
|
+
releaseCapture(event);
|
|
57
198
|
if (!disableRipple) {
|
|
58
199
|
end(event.pointerId);
|
|
59
200
|
}
|
|
201
|
+
if (disabled) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
60
204
|
onPointerCancel?.(event);
|
|
61
205
|
};
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Fires whenever the capture taken on pointer down ends - including when the browser drops it
|
|
209
|
+
* because the element stopped being hit testable. Without this the ripple would stay behind.
|
|
210
|
+
* @param event The pointer event.
|
|
211
|
+
*/
|
|
212
|
+
const handleLostPointerCapture = event => {
|
|
213
|
+
if (!disableRipple) {
|
|
214
|
+
end(event.pointerId);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
62
217
|
const handlePointerLeave = event => {
|
|
63
218
|
if (!disableRipple && event.buttons === 1) {
|
|
64
219
|
end(event.pointerId);
|
|
65
220
|
}
|
|
221
|
+
if (disabled) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
66
224
|
onPointerLeave?.(event);
|
|
67
225
|
};
|
|
68
|
-
return /*#__PURE__*/_jsxs(
|
|
226
|
+
return /*#__PURE__*/_jsxs(Component, {
|
|
69
227
|
ref: ref,
|
|
70
|
-
|
|
71
|
-
|
|
228
|
+
"data-test-id": testId,
|
|
229
|
+
className: cx(classes.root, !disableBaseClassName && 'engage__button-base', className),
|
|
230
|
+
onClick: handleClick,
|
|
231
|
+
onKeyDown: handleKeyDown,
|
|
72
232
|
onPointerDown: handlePointerDown,
|
|
73
233
|
onPointerUp: handlePointerUp,
|
|
74
234
|
onPointerCancel: handlePointerCancel,
|
|
75
|
-
onPointerLeave: handlePointerLeave
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
235
|
+
onPointerLeave: handlePointerLeave,
|
|
236
|
+
onLostPointerCapture: handleLostPointerCapture,
|
|
237
|
+
...(isButtonElement ? {
|
|
238
|
+
disabled,
|
|
239
|
+
type: supportedButtonTypes.includes(type) ? type : 'button'
|
|
240
|
+
} : {
|
|
241
|
+
'aria-disabled': disabled || undefined,
|
|
242
|
+
...(href ? {
|
|
243
|
+
href
|
|
244
|
+
} : {})
|
|
245
|
+
}),
|
|
79
246
|
...other,
|
|
80
247
|
children: [children, !disableRipple && /*#__PURE__*/_jsx(Ripple, {
|
|
81
248
|
ripples: ripples
|
|
82
249
|
})]
|
|
83
250
|
});
|
|
84
|
-
}
|
|
251
|
+
}
|
|
85
252
|
const useStyles = makeStyles({
|
|
86
253
|
name: 'ButtonBase'
|
|
87
254
|
})({
|
|
@@ -109,9 +276,17 @@ const useStyles = makeStyles({
|
|
|
109
276
|
borderStyle: 'none'
|
|
110
277
|
},
|
|
111
278
|
'&:disabled': {
|
|
279
|
+
cursor: 'not-allowed'
|
|
280
|
+
},
|
|
281
|
+
'&[aria-disabled="true"]': {
|
|
112
282
|
pointerEvents: 'none',
|
|
113
283
|
cursor: 'default'
|
|
114
284
|
}
|
|
115
285
|
}
|
|
116
286
|
});
|
|
117
|
-
|
|
287
|
+
const ButtonBaseWithRef = /*#__PURE__*/forwardRef(ButtonBase);
|
|
288
|
+
ButtonBaseWithRef.displayName = 'ButtonBase';
|
|
289
|
+
|
|
290
|
+
// `forwardRef` erases the generic, so the call signature is restored with a cast. Same approach as
|
|
291
|
+
// the Typography component.
|
|
292
|
+
export default ButtonBaseWithRef;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonBase/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonBase/hooks.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc;;mBAYM,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC;qBAqC7B,MAAM;;EA2C3C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { RIPPLE_MIN_VISIBLE_MS } from "./constants";
|
|
3
3
|
/**
|
|
4
4
|
* Manages the active ripple queue.
|
|
@@ -12,39 +12,63 @@ import { RIPPLE_MIN_VISIBLE_MS } from "./constants";
|
|
|
12
12
|
export function usePressRipple() {
|
|
13
13
|
const [ripples, setRipples] = useState([]);
|
|
14
14
|
const nextKey = useRef(0);
|
|
15
|
-
const
|
|
15
|
+
const startedAtByKey = useRef(new Map());
|
|
16
|
+
const activeKeyByPointer = useRef(new Map());
|
|
17
|
+
const pendingTimeouts = useRef(new Set());
|
|
18
|
+
useEffect(() => () => {
|
|
19
|
+
pendingTimeouts.current.forEach(timeoutId => window.clearTimeout(timeoutId));
|
|
20
|
+
pendingTimeouts.current.clear();
|
|
21
|
+
}, []);
|
|
16
22
|
const start = useCallback(event => {
|
|
17
23
|
const element = event.currentTarget;
|
|
18
24
|
const rect = element.getBoundingClientRect();
|
|
19
|
-
const
|
|
20
|
-
const
|
|
25
|
+
const hasPointerPosition = Number.isFinite(event.clientX) && Number.isFinite(event.clientY);
|
|
26
|
+
const rippleX = hasPointerPosition ? Math.round(event.clientX - rect.left) : Math.round(element.clientWidth / 2);
|
|
27
|
+
const rippleY = hasPointerPosition ? Math.round(event.clientY - rect.top) : Math.round(element.clientHeight / 2);
|
|
21
28
|
const sizeX = Math.max(element.clientWidth - rippleX, rippleX) * 2 + 2;
|
|
22
29
|
const sizeY = Math.max(element.clientHeight - rippleY, rippleY) * 2 + 2;
|
|
23
30
|
const rippleSize = Math.sqrt(sizeX ** 2 + sizeY ** 2);
|
|
24
|
-
startedAtByPointer.current.set(event.pointerId, performance.now());
|
|
25
31
|
nextKey.current += 1;
|
|
32
|
+
const key = nextKey.current;
|
|
33
|
+
startedAtByKey.current.set(key, performance.now());
|
|
34
|
+
|
|
35
|
+
// A mouse reuses one pointerId for every press, so the pointer only ever points at the newest
|
|
36
|
+
// one. Keying the rest by ripple instead means an earlier press can no longer end this one.
|
|
37
|
+
activeKeyByPointer.current.set(event.pointerId, key);
|
|
26
38
|
setRipples(prev => [].concat(prev, [{
|
|
27
|
-
key
|
|
28
|
-
pointerId: event.pointerId,
|
|
39
|
+
key,
|
|
29
40
|
x: rippleX,
|
|
30
41
|
y: rippleY,
|
|
31
42
|
size: rippleSize
|
|
32
43
|
}]));
|
|
33
44
|
}, []);
|
|
34
45
|
const end = useCallback(pointerId => {
|
|
35
|
-
const
|
|
46
|
+
const key = activeKeyByPointer.current.get(pointerId);
|
|
47
|
+
if (key == null) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Pointer up, cancel, leave and lost capture can all fire for a single press, and the press is
|
|
52
|
+
// over after whichever comes first.
|
|
53
|
+
activeKeyByPointer.current.delete(pointerId);
|
|
54
|
+
const startedAt = startedAtByKey.current.get(key);
|
|
36
55
|
if (startedAt == null) {
|
|
37
56
|
return;
|
|
38
57
|
}
|
|
39
58
|
const elapsed = performance.now() - startedAt;
|
|
40
59
|
const delay = Math.max(0, RIPPLE_MIN_VISIBLE_MS - elapsed);
|
|
41
|
-
window.setTimeout(() => {
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
const timeoutId = window.setTimeout(() => {
|
|
61
|
+
pendingTimeouts.current.delete(timeoutId);
|
|
62
|
+
setRipples(prev => prev.filter(ripple => ripple.key !== key));
|
|
63
|
+
startedAtByKey.current.delete(key);
|
|
44
64
|
}, delay);
|
|
65
|
+
pendingTimeouts.current.add(timeoutId);
|
|
45
66
|
}, []);
|
|
46
67
|
const clearAll = useCallback(() => {
|
|
47
|
-
|
|
68
|
+
pendingTimeouts.current.forEach(timeoutId => window.clearTimeout(timeoutId));
|
|
69
|
+
pendingTimeouts.current.clear();
|
|
70
|
+
startedAtByKey.current.clear();
|
|
71
|
+
activeKeyByPointer.current.clear();
|
|
48
72
|
setRipples([]);
|
|
49
73
|
}, []);
|
|
50
74
|
return {
|
|
@@ -8,7 +8,7 @@ declare const useStyles: (params: Omit<ButtonGroupOwnProps, "children">, muiStyl
|
|
|
8
8
|
props: Record<string, unknown>;
|
|
9
9
|
ownerState?: Record<string, unknown> | undefined;
|
|
10
10
|
} | undefined) => {
|
|
11
|
-
classes: Record<"root" | "disabled" | "
|
|
11
|
+
classes: Record<"root" | "disabled" | "vertical" | "enableElevation" | "fullWidth" | "grouped" | "groupedHorizontal" | "groupedVertical" | "groupedContained" | "groupedContainedHorizontal" | "groupedContainedVertical" | "groupedOutlined" | "groupedOutlinedHorizontal" | "groupedOutlinedVertical" | "groupedText" | "groupedTextHorizontal" | "groupedTextVertical", string>;
|
|
12
12
|
theme: import("@shopgate/engage/styles").Theme;
|
|
13
13
|
css: import("tss-react").Css;
|
|
14
14
|
cx: import("tss-react").Cx;
|
|
@@ -24,21 +24,27 @@ export interface ButtonGroupOwnProps {
|
|
|
24
24
|
* @default 'medium'
|
|
25
25
|
*/
|
|
26
26
|
size?: 'small' | 'medium' | 'large';
|
|
27
|
+
/**
|
|
28
|
+
* If true, the buttons use reduced padding.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
dense?: boolean;
|
|
27
32
|
/**
|
|
28
33
|
* The orientation of the buttons in the group.
|
|
29
34
|
* @default 'horizontal'
|
|
30
35
|
*/
|
|
31
36
|
orientation?: 'horizontal' | 'vertical';
|
|
32
37
|
/**
|
|
33
|
-
* If true,
|
|
38
|
+
* If true, a drop shadow is added to the group. Button groups are flat by default.
|
|
34
39
|
* @default false
|
|
35
40
|
*/
|
|
36
|
-
|
|
41
|
+
enableElevation?: boolean;
|
|
37
42
|
/**
|
|
38
|
-
* The color of the component.
|
|
43
|
+
* The color of the component. Besides the palette colors, `cta` is supported. It resolves to the
|
|
44
|
+
* merchant configurable call to action color from `components.ctaButton`.
|
|
39
45
|
* @default 'inherit'
|
|
40
46
|
*/
|
|
41
|
-
color?: PaletteColorsWithMain | 'inherit';
|
|
47
|
+
color?: PaletteColorsWithMain | 'inherit' | 'cta';
|
|
42
48
|
/**
|
|
43
49
|
* If true, the buttons will take up the full width of their container.
|
|
44
50
|
* @default false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ButtonGroup.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonGroup/ButtonGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE;;GAEG;AACH,QAAA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"ButtonGroup.d.ts","sourceRoot":"","sources":["../../../../components/v2/ButtonGroup/ButtonGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE;;GAEG;AACH,QAAA,MAAM,WAAW,mIAsEf,CAAC;AAQH,QAAA,MAAM,SAAS;;cAyB8B,CAAC;;;;;;CAqH5C,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;IAC5C;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,qBAAqB,GAAG,SAAS,GAAG,KAAK,CAAC;IAClD;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;AAIzF,eAAe,WAAW,CAAC"}
|