@sonic-equipment/ui 152.0.0 → 154.0.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.
Files changed (39) hide show
  1. package/dist/address-info-display/address-info-display.js +2 -2
  2. package/dist/badges/badge/icon-with-badge/icon-with-badge.d.ts +2 -1
  3. package/dist/badges/badge/icon-with-badge/icon-with-badge.js +2 -2
  4. package/dist/badges/tag/tag.js +1 -1
  5. package/dist/cards/orderline-card/connected-remove-button.js +1 -1
  6. package/dist/cards/orderline-card/orderline-card.js +1 -1
  7. package/dist/country-select/country-select.js +1 -1
  8. package/dist/delivery-time/delivery-time.js +1 -1
  9. package/dist/display/price/price.js +1 -1
  10. package/dist/header/cart-icon/connected-cart-icon.js +1 -1
  11. package/dist/lists/orderline-list/orderline-list.js +1 -1
  12. package/dist/media/image/image.d.ts +2 -1
  13. package/dist/media/image/image.js +3 -3
  14. package/dist/modals/confirmation/confirmation-dialog.d.ts +2 -1
  15. package/dist/modals/confirmation/confirmation-dialog.js +2 -2
  16. package/dist/modals/dialog/dialog.d.ts +2 -1
  17. package/dist/modals/dialog/dialog.js +3 -3
  18. package/dist/pages/account/sign-in-page/sign-in-page.js +1 -1
  19. package/dist/pages/checkout/cart-page/cart-page.js +2 -2
  20. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +1 -1
  21. package/dist/pages/checkout/payment-page/payment-page-content.js +1 -1
  22. package/dist/pages/checkout/payment-page/payment-page.js +6 -3
  23. package/dist/pages/checkout/shipping-page/components/currency-change-dialog.js +1 -1
  24. package/dist/pages/checkout/shipping-page/components/readonly-address.js +3 -3
  25. package/dist/pages/checkout/shipping-page/components/sonic-address.js +1 -1
  26. package/dist/pages/checkout/shipping-page/shipping-page-content.js +1 -1
  27. package/dist/pages/components/page/page.d.ts +2 -1
  28. package/dist/pages/components/page/page.js +3 -3
  29. package/dist/pages/components/page-container/page-container.d.ts +2 -1
  30. package/dist/pages/components/page-container/page-container.js +2 -2
  31. package/dist/pages/error-page/error-page.js +1 -1
  32. package/dist/pages/product/product-details-page/product-details.js +1 -1
  33. package/dist/pages/product/product-listing-page/product-listing.js +1 -1
  34. package/dist/pages/product/search-result-page/search-results-page.js +1 -1
  35. package/dist/sign-in-form/sign-in-form.js +2 -2
  36. package/dist/styles.css +6 -14
  37. package/dist/typography/heading/heading.d.ts +3 -1
  38. package/dist/typography/heading/heading.js +2 -1
  39. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import styles from './address-info-display.module.css.js';
3
3
 
4
4
  function AddressInfoDisplay({ address, 'data-test-selector': dataTestSelector, }) {
5
5
  const { address1, address2, address3, city, companyName, country, email, firstName, lastName, phone, postalCode, } = address;
6
- return (jsxs("address", { className: styles.address, "data-test-selector": dataTestSelector, children: [(firstName || lastName) && (jsx("p", { "data-test-selector": "addressInfoDisplay_name", children: `${firstName} ${lastName}` })), companyName && (jsx("p", { "data-test-selector": "addressInfoDisplay_companyName", children: companyName })), address1 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address1", children: address1 })), address2 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address2", children: address2 })), address3 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address3", children: address3 })), (postalCode || city) && (jsxs("p", { children: [postalCode && (jsxs("span", { "data-test-selector": "addressInfoDisplay_postalCode", children: [postalCode, ' '] })), city && (jsx("span", { "data-test-selector": "addressInfoDisplay_city", children: city }))] })), country && (jsx("p", { "data-test-selector": "addressInfoDisplay_country", children: country })), phone && jsx("p", { "data-test-selector": "addressInfoDisplay_phone", children: phone }), email && jsx("p", { "data-test-selector": "addressInfoDisplay_email", children: email })] }));
6
+ return (jsxs("address", { className: styles.address, "data-test-selector": dataTestSelector, children: [(firstName || lastName) && (jsxs("p", { "data-test-selector": "addressInfoDisplay_name", children: [jsx("span", { "data-test-selector": "addressInfoDisplay_name_firstName", children: firstName }), ` `, jsx("span", { "data-test-selector": "addressInfoDisplay_name_lastName", children: lastName })] })), companyName && (jsx("p", { "data-test-selector": "addressInfoDisplay_companyName", children: companyName })), address1 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address1", children: address1 })), address2 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address2", children: address2 })), address3 && (jsx("p", { "data-test-selector": "addressInfoDisplay_address3", children: address3 })), (postalCode || city) && (jsxs("p", { children: [postalCode && (jsxs(Fragment, { children: [jsx("span", { "data-test-selector": "addressInfoDisplay_postalCode", children: postalCode }), ' '] })), city && (jsx("span", { "data-test-selector": "addressInfoDisplay_city", children: city }))] })), country && (jsx("p", { "data-test-selector": "addressInfoDisplay_country", children: country })), phone && jsx("p", { "data-test-selector": "addressInfoDisplay_phone", children: phone }), email && jsx("p", { "data-test-selector": "addressInfoDisplay_email", children: email })] }));
7
7
  }
8
8
 
9
9
  export { AddressInfoDisplay };
@@ -1,6 +1,7 @@
1
1
  import { ReactNode } from 'react';
2
2
  export interface IconWithBadgeProps {
3
3
  badge: ReactNode;
4
+ 'data-test-selector'?: string;
4
5
  icon: ReactNode;
5
6
  }
6
- export declare function IconWithBadge({ badge, icon }: IconWithBadgeProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function IconWithBadge({ badge, 'data-test-selector': dataTestSelector, icon, }: IconWithBadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import styles from './icon-with-badge.module.css.js';
3
3
 
4
- function IconWithBadge({ badge, icon }) {
5
- return (jsxs("div", { className: styles['icon-with-badge'], children: [icon, jsx("div", { className: styles['badge-wrapper'], children: badge })] }));
4
+ function IconWithBadge({ badge, 'data-test-selector': dataTestSelector, icon, }) {
5
+ return (jsxs("div", { className: styles['icon-with-badge'], children: [icon, jsx("div", { className: styles['badge-wrapper'], "data-test-selector": dataTestSelector, children: badge })] }));
6
6
  }
7
7
 
8
8
  export { IconWithBadge };
@@ -4,7 +4,7 @@ import styles from './tag.module.css.js';
4
4
  function Tag({ children }) {
5
5
  if (!children)
6
6
  return null;
7
- return (jsxs("div", { className: styles.tag, children: [jsx("div", { className: styles.body, children: children }), jsx("svg", { className: styles.shape, height: "16", viewBox: "0 0 9 16", width: "9", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M1.92461763,0 L0,0 L0,16 L1.92461763,16 L6.4117887,16 L8.87489381,7.57121588 C9.23711515,6.3325062 8.79482383,4.99454094 7.78060408,4.2560794 L1.92461763,0 Z", fill: "currentColor" }) })] }));
7
+ return (jsxs("div", { className: styles.tag, children: [jsx("div", { className: styles.body, "data-test-selector": "tag", children: children }), jsx("svg", { className: styles.shape, height: "16", viewBox: "0 0 9 16", width: "9", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M1.92461763,0 L0,0 L0,16 L1.92461763,16 L6.4117887,16 L8.87489381,7.57121588 C9.23711515,6.3325062 8.79482383,4.99454094 7.78060408,4.2560794 L1.92461763,0 Z", fill: "currentColor" }) })] }));
8
8
  }
9
9
 
10
10
  export { Tag };
@@ -13,7 +13,7 @@ function ConnectedRemoveButton({ id: productId, onRemove: _onRemove, }) {
13
13
  close();
14
14
  _onRemove(productId);
15
15
  }
16
- return (jsxs(Fragment, { children: [jsx(IconButton, { color: "secondary", onClick: open, children: jsx(StrokeTrashIcon, {}) }), jsx(ConfirmationDialog, { isOpen: isOpen, onCancel: close, onConfirm: onRemove, title: t('Are you sure you want to remove this item from your cart?') })] }));
16
+ return (jsxs(Fragment, { children: [jsx(IconButton, { color: "secondary", onClick: open, children: jsx(StrokeTrashIcon, {}) }), jsx(ConfirmationDialog, { "data-test-selector": "removeItemFromCartConfirmationDialog", isOpen: isOpen, onCancel: close, onConfirm: onRemove, title: t('Are you sure you want to remove this item from your cart?') })] }));
17
17
  }
18
18
 
19
19
  export { ConnectedRemoveButton };
@@ -12,7 +12,7 @@ import styles from './orderline-card.module.css.js';
12
12
 
13
13
  function OrderLineCard(props) {
14
14
  const { deliveryDate, href, image, isReadonly, price, productId, sku, tags, title, } = props;
15
- return (jsxs(RouteLink, { className: clsx(styles['orderline-card'], isReadonly && styles.readonly), href: href, id: productId, isDisabled: isReadonly, children: [jsx("div", { className: styles['image-container'], role: "presentation", children: jsx(Image, { ...image, fit: "contain" }) }), jsx(Heading, { className: styles.title, size: "xxxs", tag: "h3", children: title }), tags && tags.length > 0 && (jsx("div", { className: styles.tags, children: tags.map(tag => (jsx(Tag, { children: jsx(FormattedMessage, { fallbackValue: tag, id: `tag.${tag.toLowerCase()}` }) }, tag))) })), jsx(ProductSku, { className: styles.sku, sku: sku }), isReadonly ? (jsx("p", { className: styles.amount, children: jsx(FormattedMessage, { id: "Amount: {0}", replacementValues: { '0': props.quantity.toString() } }) })) : (jsx("div", { className: styles['add-to-cart-button'], children: props.addToCartButton })), jsx(Price, { className: styles.price, currencyCode: price.currencyCode, originalPrice: price.originalTotalPrice, price: price.totalPrice, pricePerUnit: price.pricePerUnit, variant: "sonic" }), deliveryDate && (jsx(DeliveryTime, { className: styles.delivery, deliveryDate: deliveryDate })), !isReadonly && jsx("div", { className: styles.remove, children: props.removeButton })] }));
15
+ return (jsxs(RouteLink, { className: clsx(styles['orderline-card'], isReadonly && styles.readonly), "data-test-selector": "orderLineListItem", href: href, id: productId, isDisabled: isReadonly, children: [jsx("div", { className: styles['image-container'], role: "presentation", children: jsx(Image, { "data-test-selector": "orderLineCardImage", ...image, fit: "contain" }) }), jsx(Heading, { className: styles.title, "data-test-selector": "orderLineCardTitle", size: "xxxs", tag: "h3", children: title }), tags && tags.length > 0 && (jsx("div", { className: styles.tags, children: tags.map(tag => (jsx(Tag, { children: jsx(FormattedMessage, { fallbackValue: tag, id: `tag.${tag.toLowerCase()}` }) }, tag))) })), jsx(ProductSku, { className: styles.sku, sku: sku }), isReadonly ? (jsx("p", { className: styles.amount, children: jsx(FormattedMessage, { id: "Amount: {0}", replacementValues: { '0': props.quantity.toString() } }) })) : (jsx("div", { className: styles['add-to-cart-button'], children: props.addToCartButton })), jsx(Price, { className: styles.price, currencyCode: price.currencyCode, "data-test-selector": "orderLineCardPrice", originalPrice: price.originalTotalPrice, price: price.totalPrice, pricePerUnit: price.pricePerUnit, variant: "sonic" }), deliveryDate && (jsx(DeliveryTime, { className: styles.delivery, deliveryDate: deliveryDate })), !isReadonly && (jsx("div", { className: styles.remove, "data-test-selector": "orderLineCardRemove", children: props.removeButton }))] }));
16
16
  }
17
17
 
18
18
  export { OrderLineCard };
@@ -20,7 +20,7 @@ function CountrySelect({ countries, countryNameInLanguageOfCountry = false, 'dat
20
20
  }), {}),
21
21
  // eslint-disable-next-line react-hooks/exhaustive-deps
22
22
  [countries]);
23
- return (jsx(Select, { "data-test-selector": dataTestSelector, defaultSelectedOption: defaultSelectedCountry?.id, isDisabled: isDisabled, isRequired: isRequired, label: t('Country'), name: name, onChange: value => onCountryChange?.(countries.find(country => country.id === value)), options: countryOptions, selectedOption: selectedCountry?.id, showLabel: showLabel, showPlaceholder: false, variant: "solid" }));
23
+ return (jsx(Select, { "data-key": selectedCountry?.id, "data-test-selector": dataTestSelector, defaultSelectedOption: defaultSelectedCountry?.id, isDisabled: isDisabled, isRequired: isRequired, label: t('Country'), name: name, onChange: value => onCountryChange?.(countries.find(country => country.id === value)), options: countryOptions, selectedOption: selectedCountry?.id, showLabel: showLabel, showPlaceholder: false, variant: "solid" }));
24
24
  }
25
25
 
26
26
  export { CountrySelect };
@@ -10,7 +10,7 @@ import styles from './delivery-time.module.css.js';
10
10
  function DeliveryTime({ className, deliveryDate }) {
11
11
  const t = useFormattedMessage();
12
12
  const { number, unit } = getDateUnitObject(deliveryDate);
13
- return (jsxs("div", { className: clsx(styles['delivery-time'], className), children: [jsx("p", { children: jsx(FormattedMessage, { id: "Delivery expected in {0} {1}", replacementValues: {
13
+ return (jsxs("div", { className: clsx(styles['delivery-time'], className), children: [jsx("p", { "data-test-selector": "deliveryTime", children: jsx(FormattedMessage, { id: "Delivery expected in {0} {1}", replacementValues: {
14
14
  '0': number.toString(),
15
15
  '1': t.pluralize('unit', unit, number),
16
16
  } }) }), jsx(InfoIconTooltip, { variant: "stroke", children: jsx(FormattedMessage, { id: "The expected delivery is an indication based on the product availability and the shipping location." }) })] }));
@@ -24,7 +24,7 @@ function Price({ className, currencyCode, 'data-test-selector': dataTestSelector
24
24
  const { cultureCode: defaultLocale } = useIntl();
25
25
  const priceLocale = locale || defaultLocale;
26
26
  const showOriginalPrice = originalPrice !== undefined && price !== originalPrice;
27
- return (jsxs("div", { className: clsx(styles['price'], styles[variant], className), "data-currency-code": currencyCode, "data-current-price": price, "data-locale": priceLocale, "data-original-price": originalPrice, "data-price-per-unit": pricePerUnit, "data-test-selector": dataTestSelector, "data-unit-amount": pricePerUnit && unitAmount, "data-unit-type": pricePerUnit && unitType, "data-vat": isVatIncluded === null ? undefined : isVatIncluded, style: style, children: [showOriginalPrice && (jsx(SinglePrice, { className: styles['original-price'], currencyCode: currencyCode, isOld: showOriginalPrice, locale: priceLocale, price: originalPrice, small: variant === 'sonic', variant: variant })), jsx(SinglePrice, { className: styles['current-price'], currencyCode: currencyCode, isDiscount: showOriginalPrice, locale: priceLocale, price: price, variant: variant }), pricePerUnit && (jsxs("span", { className: styles['price-per-unit'], children: [jsx(SinglePrice, { currencyCode: currencyCode, locale: priceLocale, price: pricePerUnit }), "/", unitAmount > 1 && unitAmount, t.pluralize('priceUnit', unitType, unitAmount)] })), isVatIncluded !== null && (jsx("span", { className: styles.vat, children: t(isVatIncluded ? 'Incl. VAT' : 'Excl. VAT') }))] }));
27
+ return (jsxs("div", { className: clsx(styles['price'], styles[variant], className), "data-currency-code": currencyCode, "data-current-price": price, "data-locale": priceLocale, "data-original-price": originalPrice, "data-price-per-unit": pricePerUnit, "data-test-selector": dataTestSelector || 'price', "data-unit-amount": pricePerUnit && unitAmount, "data-unit-type": pricePerUnit && unitType, "data-vat": isVatIncluded === null ? undefined : isVatIncluded, style: style, children: [showOriginalPrice && (jsx(SinglePrice, { className: styles['original-price'], currencyCode: currencyCode, isOld: showOriginalPrice, locale: priceLocale, price: originalPrice, small: variant === 'sonic', variant: variant })), jsx(SinglePrice, { className: styles['current-price'], currencyCode: currencyCode, isDiscount: showOriginalPrice, locale: priceLocale, price: price, variant: variant }), pricePerUnit && (jsxs("span", { className: styles['price-per-unit'], children: [jsx(SinglePrice, { currencyCode: currencyCode, locale: priceLocale, price: pricePerUnit }), "/", unitAmount > 1 && unitAmount, t.pluralize('priceUnit', unitType, unitAmount)] })), isVatIncluded !== null && (jsx("span", { className: styles.vat, children: t(isVatIncluded ? 'Incl. VAT' : 'Excl. VAT') }))] }));
28
28
  }
29
29
 
30
30
  export { Price };
@@ -8,7 +8,7 @@ import { RouteIconButton } from '../../shared/routing/route-icon-button.js';
8
8
 
9
9
  function ConnectedCartIcon({ href }) {
10
10
  const count = useFetchCurrentCartCount();
11
- return (jsx(RouteIconButton, { "data-test-selector": "cartIcon", href: href, children: jsx(IconWithBadge, { badge: count ? jsx(Badge, { count: count }) : undefined, icon: jsx(SolidCartIcon, {}) }) }));
11
+ return (jsx(RouteIconButton, { "data-test-selector": "cartIcon", href: href, children: jsx(IconWithBadge, { badge: count ? jsx(Badge, { count: count }) : undefined, "data-test-selector": "cartIconCount", icon: jsx(SolidCartIcon, {}) }) }));
12
12
  }
13
13
 
14
14
  export { ConnectedCartIcon };
@@ -20,7 +20,7 @@ function OrderLineList({ children, onRemoveAll }) {
20
20
  return;
21
21
  open();
22
22
  }
23
- return (jsxs(Fragment, { children: [jsxs("div", { className: styles['orderline-list'], children: [jsxs("div", { className: styles.header, children: [jsx("p", { className: styles.count, children: `${count} ${productString.toLowerCase()}` }), onRemoveAll && (jsxs(Link, { className: styles['lnk-remove-all'], color: "primary", "data-test-selector": "cartlineHeader_removeAll", onClick: handleRemoveAll, children: [jsx(StrokeTrashIcon, {}), jsx(FormattedMessage, { id: "Remove all" })] }))] }), jsx("div", { className: styles.items, children:
23
+ return (jsxs(Fragment, { children: [jsxs("div", { className: styles['orderline-list'], children: [jsxs("div", { className: styles.header, children: [jsxs("p", { className: styles.count, children: [jsx("span", { "data-test-selector": "orderLineListCount", children: count }), ` ${productString.toLowerCase()}`] }), onRemoveAll && (jsxs(Link, { className: styles['lnk-remove-all'], color: "primary", "data-test-selector": "cartlineHeader_removeAll", onClick: handleRemoveAll, children: [jsx(StrokeTrashIcon, {}), jsx(FormattedMessage, { id: "Remove all" })] }))] }), jsx("div", { className: styles.items, children:
24
24
  // eslint-disable-next-line @eslint-react/no-children-map
25
25
  Children.map(children, (child, index) => (
26
26
  // eslint-disable-next-line @eslint-react/no-array-index-key
@@ -1,6 +1,7 @@
1
1
  import { type ImageType, ResponsiveImageType } from '../../shared/model/image';
2
2
  interface ImageProps {
3
3
  className?: string;
4
+ 'data-test-selector'?: string;
4
5
  fallbackSrc?: string;
5
6
  fit?: 'contain' | 'cover';
6
7
  height?: number;
@@ -10,5 +11,5 @@ interface ImageProps {
10
11
  title: string;
11
12
  width?: number;
12
13
  }
13
- export declare function Image({ className, fallbackSrc, fit, height, image, loading, title, width, }: ImageProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function Image({ className, 'data-test-selector': dataTestSelector, fallbackSrc, fit, height, image, loading, title, width, }: ImageProps): import("react/jsx-runtime").JSX.Element;
14
15
  export {};
@@ -5,7 +5,7 @@ import clsx from 'clsx';
5
5
  import { isResponsiveImage } from '../../shared/model/image.js';
6
6
  import styles from './image.module.css.js';
7
7
 
8
- function Image({ className, fallbackSrc = 'https://res.cloudinary.com/dkz9eknwh/image/upload/v1716545808/images/product-card/fallback_p6ngjz.svg', fit = 'cover', height, image, loading = 'eager', title, width, }) {
8
+ function Image({ className, 'data-test-selector': dataTestSelector, fallbackSrc = 'https://res.cloudinary.com/dkz9eknwh/image/upload/v1716545808/images/product-card/fallback_p6ngjz.svg', fit = 'cover', height, image, loading = 'eager', title, width, }) {
9
9
  const [hasError, setHasError] = useState(false);
10
10
  const handleError = () => {
11
11
  setHasError(true);
@@ -21,9 +21,9 @@ function Image({ className, fallbackSrc = 'https://res.cloudinary.com/dkz9eknwh/
21
21
  width,
22
22
  };
23
23
  if (isResponsiveImage(image)) {
24
- return jsx(PictureComponent, { ...props, hasError: hasError, image: image });
24
+ return (jsx(PictureComponent, { ...props, "data-test-selector": dataTestSelector, hasError: hasError, image: image }));
25
25
  }
26
- return jsx(ImageComponent, { ...props, hasError: hasError, image: image });
26
+ return (jsx(ImageComponent, { ...props, "data-test-selector": dataTestSelector, hasError: hasError, image: image }));
27
27
  }
28
28
  function createSrcSet(image) {
29
29
  return ([
@@ -1,10 +1,11 @@
1
1
  interface ConfirmationDialogProps {
2
2
  cancelLabel?: string;
3
+ 'data-test-selector'?: string;
3
4
  isOpen: boolean;
4
5
  onCancel: VoidFunction;
5
6
  onConfirm: VoidFunction;
6
7
  submitLabel?: string;
7
8
  title: string;
8
9
  }
9
- export declare function ConfirmationDialog({ cancelLabel, isOpen, onCancel, onConfirm, submitLabel, title, }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function ConfirmationDialog({ cancelLabel, 'data-test-selector': dataTestSelector, isOpen, onCancel, onConfirm, submitLabel, title, }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
10
11
  export {};
@@ -4,9 +4,9 @@ import { useFormattedMessage } from '../../intl/use-formatted-message.js';
4
4
  import { Dialog } from '../dialog/dialog.js';
5
5
  import styles from './confirmation-dialog.module.css.js';
6
6
 
7
- function ConfirmationDialog({ cancelLabel = 'Cancel', isOpen, onCancel, onConfirm, submitLabel = 'Continue', title, }) {
7
+ function ConfirmationDialog({ cancelLabel = 'Cancel', 'data-test-selector': dataTestSelector, isOpen, onCancel, onConfirm, submitLabel = 'Continue', title, }) {
8
8
  const t = useFormattedMessage();
9
- return (jsx(Dialog, { isDismissable: true, cancelLabel: t(cancelLabel), className: { dialog: styles['confirmation-dialog'] }, isOpen: isOpen, onOpenChange: onCancel, onSubmit: onConfirm, submitLabel: t(submitLabel), title: title }));
9
+ return (jsx(Dialog, { isDismissable: true, cancelLabel: t(cancelLabel), className: { dialog: styles['confirmation-dialog'] }, "data-test-selector": dataTestSelector, isOpen: isOpen, onOpenChange: onCancel, onSubmit: onConfirm, submitLabel: t(submitLabel), title: title }));
10
10
  }
11
11
 
12
12
  export { ConfirmationDialog };
@@ -17,6 +17,7 @@ interface DialogProps extends Omit<ModalProps, 'children' | 'className'> {
17
17
  heading?: string;
18
18
  modal?: string;
19
19
  };
20
+ 'data-test-selector'?: string;
20
21
  footer?: ReactNode | ((props: DialogFooterProps) => ReactNode);
21
22
  hideTitle?: boolean;
22
23
  onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;
@@ -29,5 +30,5 @@ interface DialogFooterProps {
29
30
  close: VoidFunction;
30
31
  submitLabel: string;
31
32
  }
32
- export declare function Dialog({ allowClose, cancelLabel, children, className, footer, hasCloseButton, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel, title, validationErrors, }: DialogProps): import("react/jsx-runtime").JSX.Element;
33
+ export declare function Dialog({ allowClose, cancelLabel, children, className, 'data-test-selector': dataTestSelector, footer, hasCloseButton, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel, title, validationErrors, }: DialogProps): import("react/jsx-runtime").JSX.Element;
33
34
  export {};
@@ -14,15 +14,15 @@ import styles from './dialog.module.css.js';
14
14
  function Footer({ cancelLabel, close, submitLabel }) {
15
15
  return (jsxs(Fragment, { children: [jsx(Button, { withArrow: true, color: "primary", "data-test-selector": "dialogSubmit", size: "md", type: "submit", children: jsx(FormattedMessage, { id: submitLabel }) }), jsx(Button, { color: "secondary", "data-test-selector": "dialogCancel", onClick: close, size: "md", variant: "outline", children: jsx(FormattedMessage, { id: cancelLabel }) })] }));
16
16
  }
17
- function Dialog({ allowClose = true, cancelLabel = 'Close', children, className, footer = Footer, hasCloseButton = true, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel = 'Submit', title, validationErrors, }) {
17
+ function Dialog({ allowClose = true, cancelLabel = 'Close', children, className, 'data-test-selector': dataTestSelector = 'dialog', footer = Footer, hasCloseButton = true, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel = 'Submit', title, validationErrors, }) {
18
18
  const t = useFormattedMessage();
19
- return (jsx(Modal, { className: clsx(styles['modal-overlay'], typeof className === 'string' ? className : className?.modal), hasCloseButton: false, isDismissable: isDismissable, isFullScreen: isFullScreen, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: shouldCloseOnInteractOutside, children: jsx(Dialog$1, { "aria-label": title, className: clsx(styles.dialog, typeof className === 'string' ? undefined : className?.dialog), "data-test-selector": "dialog", children: ({ close }) => (jsxs(Form, { className: clsx(styles.form, typeof className === 'string' ? undefined : className?.form), onSubmit: e => {
19
+ return (jsx(Modal, { className: clsx(styles['modal-overlay'], typeof className === 'string' ? className : className?.modal), hasCloseButton: false, isDismissable: isDismissable, isFullScreen: isFullScreen, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: shouldCloseOnInteractOutside, children: jsx(Dialog$1, { "aria-label": title, className: clsx(styles.dialog, typeof className === 'string' ? undefined : className?.dialog), "data-test-selector": dataTestSelector, children: ({ close }) => (jsxs(Form, { className: clsx(styles.form, typeof className === 'string' ? undefined : className?.form), onSubmit: e => {
20
20
  e.preventDefault();
21
21
  e.stopPropagation();
22
22
  onSubmit?.(e);
23
23
  }, validationErrors: validationErrors, children: [jsxs("header", { className: clsx(styles.header, typeof className === 'string' ? undefined : className?.header), children: [!hideTitle && (jsx(Heading, { className: clsx(styles.heading, typeof className === 'string'
24
24
  ? undefined
25
- : className?.heading), size: "xs", children: title })), hasCloseButton && (jsx("div", { className: clsx(styles.close, typeof className === 'string'
25
+ : className?.heading), size: "xs", tag: "h2", children: title })), hasCloseButton && (jsx("div", { className: clsx(styles.close, typeof className === 'string'
26
26
  ? undefined
27
27
  : className?.close), children: jsx(IconButton, { "aria-label": t('Close'), color: "secondary", isDisabled: !allowClose, onClick: close, children: jsx(StrokeCloseboxIcon, {}) }) }))] }), jsx("div", { className: clsx(styles.content, typeof className === 'string' ? undefined : className?.content), children: children instanceof Function ? children({ close }) : children }), jsx("footer", { className: clsx(styles.footer, typeof className === 'string' ? undefined : className?.footer), children: footer instanceof Function
28
28
  ? footer({ cancelLabel, close, submitLabel })
@@ -63,7 +63,7 @@ function SignInPage({ returnUrl } = {}) {
63
63
  const onRecoverPasswordDialogOpen = () => {
64
64
  setRecoverPasswordDialogOpen(true);
65
65
  };
66
- return (jsxs(Fragment, { children: [jsx(Page, { fullHeight: true, fluid: true, children: jsx(SignInPageLayout, { fullHeight: true, image: IMAGE, children: jsx(SignInForm, { allowGuestSignIn: allowGuestSignIn, createAccountPath: createAccountPath, errorMessage: errorMessage, initialEmail: session?.isGuest ? '' : session?.email, initialRememberMe: session?.rememberMe, isDisabled: !session || isSuccess, isPendingGuestSignIn: isPendingCreateGuest, isPendingUserSignIn: isPendingSignIn, onRecoverPasswordDialogOpen: onRecoverPasswordDialogOpen, onSubmit: onSubmit }) }) }), jsx(RecoverPasswordDialog, { isOpen: isRecoverPasswordDialogOpen, onOpenChange: isOpen => setRecoverPasswordDialogOpen(isOpen) })] }));
66
+ return (jsxs(Fragment, { children: [jsx(Page, { fullHeight: true, "data-test-selector": "signInPage", fluid: true, children: jsx(SignInPageLayout, { fullHeight: true, image: IMAGE, children: jsx(SignInForm, { allowGuestSignIn: allowGuestSignIn, createAccountPath: createAccountPath, errorMessage: errorMessage, initialEmail: session?.isGuest ? '' : session?.email, initialRememberMe: session?.rememberMe, isDisabled: !session || isSuccess, isPendingGuestSignIn: isPendingCreateGuest, isPendingUserSignIn: isPendingSignIn, onRecoverPasswordDialogOpen: onRecoverPasswordDialogOpen, onSubmit: onSubmit }) }) }), jsx(RecoverPasswordDialog, { isOpen: isRecoverPasswordDialogOpen, onOpenChange: isOpen => setRecoverPasswordDialogOpen(isOpen) })] }));
67
67
  }
68
68
 
69
69
  export { SignInPage };
@@ -81,7 +81,7 @@ function CartContent({ cartLines }) {
81
81
  throw new Error(`Currency code not found for symbol ${currentCart.currencySymbol}`);
82
82
  return (jsx(CheckoutPageLayout, { actions: {
83
83
  primary: (jsx(RouteButton, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", href: "/CheckoutShipping", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
84
- secondary: (jsx(RouteButton, { color: "secondary", href: isAuthenticated ? undefined : PATHS.SIGN_IN, onClick: () => {
84
+ secondary: (jsx(RouteButton, { color: "secondary", "data-test-selector": "saveCartForLaterButton", href: isAuthenticated ? undefined : PATHS.SIGN_IN, onClick: () => {
85
85
  if (!isAuthenticated)
86
86
  return;
87
87
  saveCartForLater.mutate({ cart: currentCart });
@@ -112,7 +112,7 @@ function CartPage() {
112
112
  return (jsx(Page, { breadcrumb: [
113
113
  { href: PATHS.HOME, label: 'home' },
114
114
  { href: PATHS.CART, label: t('Cart') },
115
- ], canonicalUrl: PATHS.CART, title: t('Cart'), children: cartLines?.length ? (jsx(CartContent, { cartLines: cartLines })) : (jsx(EmptyCart, {})) }));
115
+ ], canonicalUrl: PATHS.CART, "data-test-selector": "cartPage", title: t('Cart'), children: cartLines?.length ? (jsx(CartContent, { cartLines: cartLines })) : (jsx(EmptyCart, {})) }));
116
116
  }
117
117
 
118
118
  export { CartPage };
@@ -50,7 +50,7 @@ function OrderConfirmationPageContent({ cart, }) {
50
50
  href: `${PATHS.ORDER_CONFIRMATION}?cartId=${cart.id}`,
51
51
  label: t('Order confirmation'),
52
52
  },
53
- ], title: t('Order confirmation'), children: jsx(CheckoutPageLayout, { actions: {
53
+ ], "data-test-selector": "orderConfirmationPage", title: t('Order confirmation'), children: jsx(CheckoutPageLayout, { actions: {
54
54
  primary: (jsx(RouteButton, { withArrow: true, "data-test-selector": "checkoutReviewAndSubmit_continueShopping", href: "/", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
55
55
  secondary: (jsxs(Fragment, { children: [cart.canSaveOrder && (jsx(RouteButton, { color: "secondary", onClick: () => {
56
56
  saveCartForLater.mutate({ cart });
@@ -26,7 +26,7 @@ function PaymentPageContent({ atp, cart, formId, hasAtp, isProcessing, isValidat
26
26
  href: PATHS.REVIEW_AND_SUBMIT,
27
27
  label: t('Review and payment'),
28
28
  },
29
- ], title: t('Review and payment'), children: jsxs(CheckoutPageLayout, { actions: {
29
+ ], "data-test-selector": "paymentPage", title: t('Review and payment'), children: jsxs(CheckoutPageLayout, { actions: {
30
30
  primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutReviewAndSubmit_placeOrder", form: formId, isDisabled: isProcessing, isLoading: isProcessing ? (jsx(FormattedMessage, { id: "Processing" })) : isValidatingVAT ? (jsx(FormattedMessage, { id: "Validating" })) : (false), type: "submit", children: jsx(FormattedMessage, { id: "Pay" }) })),
31
31
  }, mobileSummary: jsx(CartTotalsSummary, { currencyCode: currencyCode, totalAmount: cart.orderGrandTotal }), overview: jsx(CartTotals, { currencyCode: currencyCode, deliveryDate: hasAtp ? undefined : cart.requestedDeliveryDate, fulfillmentMethod: cart.fulfillmentMethod, isPayByInvoice: (cart.paymentOptions?.paymentMethods?.length || 1) <= 1 &&
32
32
  cart.paymentMethod?.name === 'PBI', shippingCost: cart.shippingAndHandling, subtotal: cart.orderSubTotal, tax: cart.totalTax, total: cart.orderGrandTotal, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate || 0 }), children: [jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Payment" }), children: jsx(CheckoutPageSectionContent, { children: jsx(Payment, { atp: atp, cart: cart, form: formId, isProcessing: isProcessing, onPaymentComplete: onPaymentComplete, onProcessing: setIsProcessing, onValidatingVAT: setIsValidatingVAT }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Order" }), children: jsx(CheckoutPageSectionContent, { stretch: true, children: jsx(OrderLineList, { children: cart.cartLines?.map(cartLine => (jsx(OrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
@@ -19,7 +19,7 @@ function PaymentPage() {
19
19
  forceRecalculation: !hasReturnedFromAdyen,
20
20
  });
21
21
  const { data: atp, isLoading: isAtpLoading } = useFetchCurrentCheckoutAtp();
22
- const hasAtp = atp && atp.length > 1;
22
+ const hasAtp = atp !== undefined && atp.length > 1;
23
23
  const isLoading = isLoadingCart || isAtpLoading;
24
24
  const [isProcessing, setIsProcessing] = useState(false);
25
25
  const [isValidating, setIsValidating] = useState(false);
@@ -45,16 +45,19 @@ function PaymentPage() {
45
45
  }, [cart, navigate, isAuthenticated, isNavigating]);
46
46
  if (error)
47
47
  return jsx(ErrorPage, { error: error });
48
+ if (!isAtpLoading && !atp)
49
+ return jsx(ErrorPage, { error: new Error('ATP not found') });
48
50
  if (isLoading || isNavigating)
49
51
  return jsx(LoadingPage, {});
50
52
  if (!isAuthenticated ||
51
- hasNo(atp) ||
52
53
  hasNo(cart) ||
53
54
  hasNo(cart.cartLines) ||
54
55
  cart.cartLines.length === 0 ||
55
56
  hasNo(cart.billTo?.address1))
56
57
  return null;
57
- return (jsx(PaymentPageContent, { atp: atp, cart: cart, formId: PAYMENT_FORM_ID, hasAtp: Boolean(hasAtp), isProcessing: isProcessing, isValidatingVAT: isValidating, onPaymentComplete: onPaymentComplete, setIsProcessing: setIsProcessing, setIsValidatingVAT: setIsValidating }));
58
+ if (!atp)
59
+ throw new Error('Unexpected condition: ATP is undefined');
60
+ return (jsx(PaymentPageContent, { atp: atp, cart: cart, formId: PAYMENT_FORM_ID, hasAtp: hasAtp, isProcessing: isProcessing, isValidatingVAT: isValidating, onPaymentComplete: onPaymentComplete, setIsProcessing: setIsProcessing, setIsValidatingVAT: setIsValidating }));
58
61
  }
59
62
 
60
63
  export { PaymentPage };
@@ -7,7 +7,7 @@ import { PATHS } from '../../../paths.js';
7
7
 
8
8
  function CurrencyChangeDialog({ isOpen, onOpenChange, onSubmit, }) {
9
9
  const t = useFormattedMessage();
10
- return (jsx(Dialog, { isOpen: isOpen, onOpenChange: onOpenChange, onSubmit: onSubmit, shouldCloseOnInteractOutside: true, submitLabel: "Continue", title: t('Currency Change'), children: jsxs("p", { children: [jsx(FormattedMessage, { id: "You selected a country where we invoice in a different currency. This will result in your cart being converted to the new currency. If you would like to review your order, " }), jsx(RouteLink, { hasUnderline: true, color: "secondary", href: PATHS.CART, onClick: onSubmit, children: jsx(FormattedMessage, { id: "please go back to your cart." }) }), ' ', jsx(FormattedMessage, { id: "If you want to proceed, click the continue button. If you want to change your country, close this message and select a different country." })] }) }));
10
+ return (jsx(Dialog, { "data-test-selector": "currencyChangeDialog", isOpen: isOpen, onOpenChange: onOpenChange, onSubmit: onSubmit, shouldCloseOnInteractOutside: true, submitLabel: "Continue", title: t('Currency Change'), children: jsxs("p", { children: [jsx(FormattedMessage, { id: "You selected a country where we invoice in a different currency. This will result in your cart being converted to the new currency. If you would like to review your order, " }), jsx(RouteLink, { hasUnderline: true, color: "secondary", href: PATHS.CART, onClick: onSubmit, children: jsx(FormattedMessage, { id: "please go back to your cart." }) }), ' ', jsx(FormattedMessage, { id: "If you want to proceed, click the continue button. If you want to change your country, close this message and select a different country." })] }) }));
11
11
  }
12
12
 
13
13
  export { CurrencyChangeDialog };
@@ -16,7 +16,7 @@ import styles from './readonly-address.module.css.js';
16
16
 
17
17
  function ReadOnlyAddresses({ billTo, isLoading, isPickup, notes, onSubmit, shipTo, }) {
18
18
  const t = useFormattedMessage();
19
- return (jsxs(Form, { "data-test-selector": "billToAddressForm", id: EDIT_ADDRESS_FORM_ID, onSubmit: e => {
19
+ return (jsxs(Form, { id: EDIT_ADDRESS_FORM_ID, onSubmit: e => {
20
20
  e.preventDefault();
21
21
  const formData = new FormData(e.currentTarget);
22
22
  onSubmit({
@@ -36,7 +36,7 @@ function ReadOnlyAddresses({ billTo, isLoading, isPickup, notes, onSubmit, shipT
36
36
  lastName: billTo.lastName,
37
37
  phone: billTo.phone,
38
38
  postalCode: billTo.postalCode,
39
- } })), jsx("div", { className: styles.notes, children: jsx(TextField, { defaultValue: notes, isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] })] }), jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: [!isPickup && (jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: PATHS.ACCOUNT_ADDRESSES, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit shipping address" }), " >"] }) })), jsx(CheckoutPageSectionContent, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs(Fragment, { children: [jsx(Checkbox, { className: styles['use-invoice-checkbox'], "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), shipTo && (jsx(AddressInfoDisplay, { address: {
39
+ }, "data-test-selector": "billToAddress" })), jsx("div", { className: styles.notes, children: jsx(TextField, { defaultValue: notes, isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] })] }), jsxs(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: [!isPickup && (jsx(CheckoutPageSectionLink, { children: jsxs(RouteLink, { color: "secondary", href: PATHS.ACCOUNT_ADDRESSES, isDisabled: isLoading, children: [jsx(FormattedMessage, { id: "Edit shipping address" }), " >"] }) })), jsx(CheckoutPageSectionContent, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs(Fragment, { children: [jsx(Checkbox, { className: styles['use-invoice-checkbox'], "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), shipTo && (jsx(AddressInfoDisplay, { address: {
40
40
  address1: shipTo.address1,
41
41
  address2: shipTo.address2,
42
42
  address3: shipTo.address3,
@@ -48,7 +48,7 @@ function ReadOnlyAddresses({ billTo, isLoading, isPickup, notes, onSubmit, shipT
48
48
  lastName: shipTo.lastName,
49
49
  phone: shipTo.phone,
50
50
  postalCode: shipTo.postalCode,
51
- } }))] })) })] })] }));
51
+ }, "data-test-selector": "shipToAddress" }))] })) })] })] }));
52
52
  }
53
53
 
54
54
  export { ReadOnlyAddresses };
@@ -3,7 +3,7 @@ import { FormattedMessage } from '../../../../intl/formatted-message.js';
3
3
  import styles from './sonic-address.module.css.js';
4
4
 
5
5
  function SonicAddress() {
6
- return (jsx("div", { className: styles['sonic-address'], children: jsx(FormattedMessage, { id: "Sonic address" }) }));
6
+ return (jsx("div", { className: styles['sonic-address'], "data-test-selector": "pickupAddressSonic", children: jsx(FormattedMessage, { id: "Sonic address" }) }));
7
7
  }
8
8
 
9
9
  export { SonicAddress };
@@ -30,7 +30,7 @@ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulf
30
30
  href: PATHS.CHECKOUT_SHIPPING,
31
31
  label: t('Shipping details'),
32
32
  },
33
- ], title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
33
+ ], "data-test-selector": "shippingPage", title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
34
34
  primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: EDIT_ADDRESS_FORM_ID, isDisabled: isPatching, isLoading: isPatching || isPatchingSession ? (jsx(FormattedMessage, { id: "Updating address" })) : undefined, type: "submit", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
35
35
  }, mobileSummary: jsx(CartTotalsSummary, { currencyCode: currencyCode, totalAmount: cart.orderGrandTotal }), overview: jsx(CartTotals, { currencyCode: currencyCode, fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
36
36
  ? cart.fulfillmentMethod
@@ -5,8 +5,9 @@ export interface PageProps extends PageMetaDataProps {
5
5
  breadcrumb?: BreadcrumbLink[];
6
6
  children: ReactNode;
7
7
  className?: string;
8
+ 'data-test-selector'?: string;
8
9
  fluid?: boolean;
9
10
  fullHeight?: boolean;
10
11
  title?: string;
11
12
  }
12
- export declare function Page({ alternateLanguageUrls, breadcrumb, canonicalUrl, children, className, fluid, fullHeight, meta, openGraph, title, windowTitle, }: PageProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Page({ alternateLanguageUrls, breadcrumb, canonicalUrl, children, className, 'data-test-selector': dataTestSelector, fluid, fullHeight, meta, openGraph, title, windowTitle, }: PageProps): import("react/jsx-runtime").JSX.Element;
@@ -6,10 +6,10 @@ import { PageContainer } from '../page-container/page-container.js';
6
6
  import { PageMetaData } from '../page-meta-data/page-meta-data.js';
7
7
 
8
8
  function PageTitle({ children }) {
9
- return (jsx(Heading, { italic: true, uppercase: true, breakpoints: { lg: 'm', xxl: 'xl' }, size: "s", tag: "h1", children: children }));
9
+ return (jsx(Heading, { italic: true, uppercase: true, breakpoints: { lg: 'm', xxl: 'xl' }, "data-test-selector": "pageTitle", size: "s", tag: "h1", children: children }));
10
10
  }
11
- function Page({ alternateLanguageUrls, breadcrumb, canonicalUrl, children, className, fluid, fullHeight, meta, openGraph, title, windowTitle, }) {
12
- return (jsxs(Fragment, { children: [jsx(PageMetaData, { alternateLanguageUrls: alternateLanguageUrls, canonicalUrl: canonicalUrl, meta: meta, openGraph: openGraph, windowTitle: windowTitle }), jsx(PageContainer, { breadcrumbSlot: breadcrumb && jsx(Breadcrumb, { links: breadcrumb }), className: className, fluid: fluid, fullHeight: fullHeight, titleSlot: title && jsx(PageTitle, { children: title }), children: children })] }));
11
+ function Page({ alternateLanguageUrls, breadcrumb, canonicalUrl, children, className, 'data-test-selector': dataTestSelector, fluid, fullHeight, meta, openGraph, title, windowTitle, }) {
12
+ return (jsxs(Fragment, { children: [jsx(PageMetaData, { alternateLanguageUrls: alternateLanguageUrls, canonicalUrl: canonicalUrl, meta: meta, openGraph: openGraph, windowTitle: windowTitle }), jsx(PageContainer, { breadcrumbSlot: breadcrumb && jsx(Breadcrumb, { links: breadcrumb }), className: className, "data-test-selector": dataTestSelector, fluid: fluid, fullHeight: fullHeight, titleSlot: title && jsx(PageTitle, { children: title }), children: children })] }));
13
13
  }
14
14
 
15
15
  export { Page };
@@ -1,8 +1,9 @@
1
1
  import { ReactNode } from 'react';
2
- export declare function PageContainer({ breadcrumbSlot, children, className, fluid, fullHeight, titleSlot, }: {
2
+ export declare function PageContainer({ breadcrumbSlot, children, className, 'data-test-selector': dataTestSelector, fluid, fullHeight, titleSlot, }: {
3
3
  breadcrumbSlot?: ReactNode;
4
4
  children: ReactNode;
5
5
  className?: string;
6
+ 'data-test-selector'?: string;
6
7
  fluid?: boolean;
7
8
  fullHeight?: boolean;
8
9
  titleSlot?: ReactNode;
@@ -3,8 +3,8 @@ import clsx from 'clsx';
3
3
  import resetStyles from '../../../shared/reset.module.css.js';
4
4
  import styles from './page-container.module.css.js';
5
5
 
6
- function PageContainer({ breadcrumbSlot, children, className, fluid, fullHeight, titleSlot, }) {
7
- return (jsx("div", { className: clsx(styles['page-container'], resetStyles.reset, fullHeight && styles['full-height'], fluid && styles['fluid'], className), children: jsxs("main", { className: styles['page-main'], children: [breadcrumbSlot && (jsx("div", { className: styles.breadcrumb, children: breadcrumbSlot })), titleSlot && jsx("div", { className: styles.title, children: titleSlot }), jsx("div", { className: styles.content, children: children })] }) }));
6
+ function PageContainer({ breadcrumbSlot, children, className, 'data-test-selector': dataTestSelector, fluid, fullHeight, titleSlot, }) {
7
+ return (jsx("div", { className: clsx(styles['page-container'], resetStyles.reset, fullHeight && styles['full-height'], fluid && styles['fluid'], className), "data-test-selector": dataTestSelector, children: jsxs("main", { className: styles['page-main'], children: [breadcrumbSlot && (jsx("div", { className: styles.breadcrumb, children: breadcrumbSlot })), titleSlot && jsx("div", { className: styles.title, children: titleSlot }), jsx("div", { className: styles.content, children: children })] }) }));
8
8
  }
9
9
 
10
10
  export { PageContainer };
@@ -20,7 +20,7 @@ function ErrorPage({ error }) {
20
20
  return (jsx(Page, { breadcrumb: [
21
21
  { href: PATHS.HOME, label: 'Home' },
22
22
  { href: PATHS.HOME, label: 'Error' },
23
- ], title: "Something went wrong", children: environment !== 'production' && (jsxs(Fragment, { children: [jsx(Heading, { size: "l", children: isRequestError(error) ? (jsxs(Fragment, { children: [error.status, " - ", error.statusText || 'Unknown error'] })) : (jsx(Fragment, { children: error.message })) }), isRequestError(error) && (jsxs(Fragment, { children: [jsx(Heading, { size: "xs", children: "Error details" }), jsx(Heading, { size: "xxs", children: "Body" }), jsx("pre", { children: JSON.stringify(error.body, null, 2) }), jsx(Heading, { size: "xxs", children: "Options" }), jsx("pre", { children: JSON.stringify(error.options, null, 2) })] }))] })) }));
23
+ ], "data-test-selector": "errorPage", title: "Something went wrong", children: environment !== 'production' && (jsxs(Fragment, { children: [jsx(Heading, { size: "l", children: isRequestError(error) ? (jsxs(Fragment, { children: [error.status, " - ", error.statusText || 'Unknown error'] })) : (jsx(Fragment, { children: error.message })) }), isRequestError(error) && (jsxs(Fragment, { children: [jsx(Heading, { size: "xs", children: "Error details" }), jsx(Heading, { size: "xxs", children: "Body" }), jsx("pre", { children: JSON.stringify(error.body, null, 2) }), jsx(Heading, { size: "xxs", children: "Options" }), jsx("pre", { children: JSON.stringify(error.options, null, 2) })] }))] })) }));
24
24
  }
25
25
 
26
26
  export { ErrorPage };
@@ -20,7 +20,7 @@ function ProductDetails({ data, priceComponent, recentlyViewedComponent, }) {
20
20
  },
21
21
  product,
22
22
  });
23
- return (jsx(Page, { alternateLanguageUrls: page.alternateLanguageUrls, breadcrumb: breadCrumb, canonicalUrl: page.canonicalPath, meta: {
23
+ return (jsx(Page, { alternateLanguageUrls: page.alternateLanguageUrls, breadcrumb: breadCrumb, canonicalUrl: page.canonicalPath, "data-test-selector": "productDetailsPage", meta: {
24
24
  description: page.metaDescription,
25
25
  keywords: page.metaKeywords,
26
26
  }, openGraph: {
@@ -24,7 +24,7 @@ import styles from './product-listing-page.module.css.js';
24
24
  function ProductListing({ data, searchClient, }) {
25
25
  const languageCode = useLanguageCode();
26
26
  const category = data.breadCrumb.slice(1).map(breadCrumb => breadCrumb.label);
27
- return (jsx(AlgoliaProvider, { categoryPages: data.categoryPages, hierarchicalCategories: data.hierarchicalCategories, languageCode: languageCode, offlineSearchClient: offlineSearchClient, searchClient: searchClient, children: jsx(Page, { alternateLanguageUrls: data.page.alternateLanguageUrls, breadcrumb: data.breadCrumb, canonicalUrl: data.page.canonicalPath, className: styles['product-listing'], meta: {
27
+ return (jsx(AlgoliaProvider, { categoryPages: data.categoryPages, hierarchicalCategories: data.hierarchicalCategories, languageCode: languageCode, offlineSearchClient: offlineSearchClient, searchClient: searchClient, children: jsx(Page, { alternateLanguageUrls: data.page.alternateLanguageUrls, breadcrumb: data.breadCrumb, canonicalUrl: data.page.canonicalPath, className: styles['product-listing'], "data-test-selector": "productListingPage", meta: {
28
28
  description: data.page.metaDescription,
29
29
  keywords: data.page.metaKeywords,
30
30
  }, openGraph: {
@@ -31,7 +31,7 @@ function SearchResultsPage({ location, searchClient, }) {
31
31
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
32
32
  , {
33
33
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
34
- canonicalUrl: typeof window === 'undefined' ? '' : window.location.href, className: styles['search-results'], title: t("'{0}' in all products", {
34
+ canonicalUrl: typeof window === 'undefined' ? '' : window.location.href, className: styles['search-results'], "data-test-selector": "searchResultsPage", title: t("'{0}' in all products", {
35
35
  replacementValues: { 0: keyword },
36
36
  }), windowTitle: `${t('Search')} - ${t('Sonic Equipment')}`, children: jsx(SearchResultsPageContent, { keyword: keyword }) }) }));
37
37
  }
@@ -49,11 +49,11 @@ function SignInForm({ allowGuestSignIn = false, createAccountPath, errorMessage,
49
49
  },
50
50
  });
51
51
  };
52
- return (jsxs(Form, { "aria-label": title, autoComplete: "off", className: clsx(styles['sign-in-form'], styles['form']), onSubmit: handleSubmit, validationBehavior: "native", children: [jsx("header", { className: styles['form-header'], children: jsx(Heading, { "data-test-selector": "PageTitle", italic: true, size: "m", tag: "h1", uppercase: true, children: title }) }), errorMessage === 'Access denied' && (jsx(Message, { type: "danger", children: t('Your email and password were not recognized.') })), errorMessage === 'Unexpected error' && (jsx(Message, { type: "danger", children: t('An unexpected error occured. Please try again.') })), jsxs("fieldset", { className: clsx(styles['form-fieldset'], styles['columns']), children: [jsx("div", { className: styles['form-segment'], children: jsx(TextField, { "data-test-selector": "signIn_userName", defaultValue: initialEmail, isDisabled: isDisabled, isRequired: true, label: t('Email'), name: "email", showLabel: true, type: "email", validate: value => {
52
+ return (jsxs(Form, { "aria-label": title, autoComplete: "off", className: clsx(styles['sign-in-form'], styles['form']), onSubmit: handleSubmit, validationBehavior: "native", children: [jsx("header", { className: styles['form-header'], children: jsx(Heading, { "data-test-selector": "pageTitle", italic: true, size: "m", tag: "h1", uppercase: true, children: title }) }), errorMessage === 'Access denied' && (jsx(Message, { type: "danger", children: t('Your email and password were not recognized.') })), errorMessage === 'Unexpected error' && (jsx(Message, { type: "danger", children: t('An unexpected error occured. Please try again.') })), jsxs("fieldset", { className: clsx(styles['form-fieldset'], styles['columns']), children: [jsx("div", { className: styles['form-segment'], children: jsx(TextField, { "data-test-selector": "signIn_userName", defaultValue: initialEmail, isDisabled: isDisabled, isRequired: true, label: t('Email'), name: "email", showLabel: true, type: "email", validate: value => {
53
53
  if (!value)
54
54
  return value;
55
55
  return (validateEmail(value) || t('Please enter a valid email address'));
56
- } }) }), jsx("div", { className: styles['form-segment'], children: jsx(TextField, { "data-test-selector": "signIn_password", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", showLabel: true, type: "password" }) })] }), jsxs("footer", { className: styles['form-footer'], children: [jsx("div", { className: styles['form-segment'], children: jsx(Switch, { className: styles['floating'], defaultSelected: initialRememberMe, isDisabled: isDisabled, name: "rememberMe", value: "true", children: t('Remember me') }) }), jsx("div", { className: styles['form-segment'], children: jsx(Button, { "data-test-selector": "signIn_submit", isDisabled: isDisabled, isLoading: isPendingUserSignIn && t('Signing in…'), type: "submit", withArrow: true, children: t('sign in') }) }), jsxs("div", { className: styles['form-segment'], children: [jsx("p", { children: jsx(Link, { color: "primary", "data-test-selector": "signIn_forgotPassword", hasUnderline: true, isDisabled: isDisabled, onClick: onRecoverPasswordDialogOpen, children: t('Forgot password?') }) }), jsx("p", { children: jsxs(Fragment, { children: [t('New user?'), ' ', jsx(RouteLink, { "data-test-selector": "signInCreateNewAccount_createNewAccount", hasUnderline: true, href: createAccountPath, isDisabled: isDisabled, children: t('create account') })] }) })] }), allowGuestSignIn && (jsx("div", { className: styles['form-segment'], children: jsx(Button, { color: "secondary", isDisabled: isDisabled, isLoading: isPendingGuestSignIn && t('Signing in…'), isValidating: false, name: GUEST_SIGN_IN_BUTTON_NAME, type: "submit", value: "true", variant: "outline", children: t('Or continue as guest') }) }))] })] }));
56
+ } }) }), jsx("div", { className: styles['form-segment'], children: jsx(TextField, { "data-test-selector": "signIn_password", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", showLabel: true, type: "password" }) })] }), jsxs("footer", { className: styles['form-footer'], children: [jsx("div", { className: styles['form-segment'], children: jsx(Switch, { className: styles['floating'], defaultSelected: initialRememberMe, isDisabled: isDisabled, name: "rememberMe", value: "true", children: t('Remember me') }) }), jsx("div", { className: styles['form-segment'], children: jsx(Button, { "data-test-selector": "signIn_submit", isDisabled: isDisabled, isLoading: isPendingUserSignIn && t('Signing in…'), type: "submit", withArrow: true, children: t('sign in') }) }), jsxs("div", { className: styles['form-segment'], children: [jsx("p", { children: jsx(Link, { color: "primary", "data-test-selector": "signIn_forgotPassword", hasUnderline: true, isDisabled: isDisabled, onClick: onRecoverPasswordDialogOpen, children: t('Forgot password?') }) }), jsx("p", { children: jsxs(Fragment, { children: [t('New user?'), ' ', jsx(RouteLink, { "data-test-selector": "signInCreateNewAccount_createNewAccount", hasUnderline: true, href: createAccountPath, isDisabled: isDisabled, children: t('create account') })] }) })] }), allowGuestSignIn && (jsx("div", { className: styles['form-segment'], children: jsx(Button, { color: "secondary", "data-test-selector": "continueAsGuest", isDisabled: isDisabled, isLoading: isPendingGuestSignIn && t('Signing in…'), isValidating: false, name: GUEST_SIGN_IN_BUTTON_NAME, type: "submit", value: "true", variant: "outline", children: t('Or continue as guest') }) }))] })] }));
57
57
  }
58
58
 
59
59
  export { SignInForm };
package/dist/styles.css CHANGED
@@ -2937,12 +2937,10 @@
2937
2937
 
2938
2938
  @container (inline-size >= 576px) {.orderline-card-module-AMTMm {
2939
2939
  padding: 32px 64px 32px 0;
2940
- grid-template:
2941
- repeat(3, minmax(0, min-content)) minmax(8px, 1fr) repeat(
2940
+ grid-template: repeat(3, minmax(0, min-content)) minmax(8px, 1fr) repeat(
2942
2941
  2,
2943
2942
  minmax(0, min-content)
2944
- )
2945
- / 143px 1fr auto;
2943
+ ) / 143px 1fr auto;
2946
2944
  grid-template-areas:
2947
2945
  'image tags tags'
2948
2946
  'image title title'
@@ -3004,8 +3002,7 @@
3004
3002
  var(--space-8),
3005
3003
  1fr
3006
3004
  )
3007
- repeat(2, minmax(0, min-content))
3008
- / 1fr;
3005
+ repeat(2, minmax(0, min-content)) / 1fr;
3009
3006
  grid-template-areas:
3010
3007
  'image'
3011
3008
  '.'
@@ -3096,13 +3093,10 @@
3096
3093
  .product-card-module-pLaiB {
3097
3094
  --box-shadow: var(--box-shadow-heavy);
3098
3095
 
3099
- grid-template:
3100
- 204px var(--space-8) repeat(3, minmax(0, min-content)) minmax(
3096
+ grid-template: 204px var(--space-8) repeat(3, minmax(0, min-content)) minmax(
3101
3097
  var(--space-16),
3102
3098
  1fr
3103
- )
3104
- minmax(0, min-content)
3105
- / 1fr minmax(0, min-content);
3099
+ ) minmax(0, min-content) / 1fr minmax(0, min-content);
3106
3100
  grid-template-areas:
3107
3101
  'image image'
3108
3102
  '. .'
@@ -3949,9 +3943,7 @@
3949
3943
 
3950
3944
  @media (width >= 768px) {
3951
3945
  .usp-carousel-module-UCbpX .usp-carousel-module-msaeJ {
3952
- left: calc(
3953
- ((100% - var(--image-max-width)) / 2) + var(--image-max-width)
3954
- );
3946
+ left: calc((100% - var(--image-max-width)) / 2 + var(--image-max-width));
3955
3947
  }
3956
3948
  }
3957
3949
 
@@ -8,12 +8,14 @@ export interface HeadingProps {
8
8
  breakpoints?: Partial<Record<Breakpoint, Size>>;
9
9
  children: React.ReactNode;
10
10
  className?: string;
11
+ 'data-test-selector'?: string;
11
12
  italic?: boolean;
12
13
  size?: Size;
13
14
  tag?: Tag;
14
15
  uppercase?: boolean;
15
16
  }
16
- export declare function Heading({ bold, breakpoints, children, className, italic, size, tag, uppercase, }: HeadingProps): React.ReactElement<{
17
+ export declare function Heading({ bold, breakpoints, children, className, 'data-test-selector': dataTestSelector, italic, size, tag, uppercase, }: HeadingProps): React.ReactElement<{
17
18
  className: string;
19
+ 'data-test-selector': string;
18
20
  }, string | React.JSXElementConstructor<any>>;
19
21
  export {};
@@ -14,7 +14,7 @@ const sizeToTag = {
14
14
  xxs: 'h6',
15
15
  xxxs: 'h6',
16
16
  };
17
- function Heading({ bold = true, breakpoints, children, className, italic, size = 'xxl', tag, uppercase, }) {
17
+ function Heading({ bold = true, breakpoints, children, className, 'data-test-selector': dataTestSelector = 'heading', italic, size = 'xxl', tag, uppercase, }) {
18
18
  return createElement(tag || sizeToTag[size], {
19
19
  className: clsx(className, styles.heading, styles[size], breakpoints &&
20
20
  Object.entries(breakpoints).map(([breakpoint, bpSize]) => styles[`${breakpoint}-${bpSize}`]), {
@@ -22,6 +22,7 @@ function Heading({ bold = true, breakpoints, children, className, italic, size =
22
22
  [styles.italic]: italic,
23
23
  [styles.bold]: bold,
24
24
  }),
25
+ 'data-test-selector': dataTestSelector,
25
26
  }, children);
26
27
  }
27
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonic-equipment/ui",
3
- "version": "152.0.0",
3
+ "version": "154.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {