@sonic-equipment/ui 170.0.0 → 171.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 (68) hide show
  1. package/dist/algolia/algolia-query-string-routing.js +2 -2
  2. package/dist/buttons/button/button.js +3 -6
  3. package/dist/buttons/icon-button/icon-button.d.ts +2 -1
  4. package/dist/buttons/icon-button/icon-button.js +5 -8
  5. package/dist/buttons/link/link.js +4 -7
  6. package/dist/carousel/carousel.js +3 -3
  7. package/dist/carousel/usp-carousel/usp-carousel.js +1 -1
  8. package/dist/drawer/drawer.d.ts +2 -1
  9. package/dist/drawer/drawer.js +2 -2
  10. package/dist/drawer/use-drawer.js +1 -0
  11. package/dist/exports.d.ts +1 -0
  12. package/dist/forms/select-field/select-field.js +1 -0
  13. package/dist/global-search/search-result-panel/sections/with-results.js +3 -4
  14. package/dist/header/buttons/account/connected-account-button.js +1 -1
  15. package/dist/header/buttons/cart/connected-cart-button.js +1 -1
  16. package/dist/header/drawers/desktop-navigation-drawer.js +2 -1
  17. package/dist/header/drawers/mobile-navigation-drawer.js +2 -1
  18. package/dist/header/drawers/search-drawer.js +1 -1
  19. package/dist/header/header.js +1 -1
  20. package/dist/header/link-list/navigation-link-list.d.ts +2 -1
  21. package/dist/header/link-list/navigation-link-list.js +4 -3
  22. package/dist/header/sonic-logo/sonic-logo.d.ts +2 -1
  23. package/dist/header/sonic-logo/sonic-logo.js +3 -2
  24. package/dist/index.js +1 -0
  25. package/dist/lists/menu-list/menu-list-back-button.d.ts +2 -1
  26. package/dist/lists/menu-list/menu-list-back-button.js +2 -2
  27. package/dist/lists/menu-list/menu-list-header.d.ts +2 -1
  28. package/dist/lists/menu-list/menu-list-header.js +2 -2
  29. package/dist/lists/menu-list/menu-list-item.d.ts +2 -1
  30. package/dist/lists/menu-list/menu-list-item.js +2 -2
  31. package/dist/lists/menu-list/menu-list.js +1 -1
  32. package/dist/media/image-lightbox/image-lightbox.js +3 -3
  33. package/dist/navigation/cart-icon/cart-icon.js +1 -1
  34. package/dist/navigation/mobile-navigation/mobile-navigation.js +1 -1
  35. package/dist/navigation/panel-navigation/panel-navigation.d.ts +2 -1
  36. package/dist/navigation/panel-navigation/panel-navigation.js +4 -4
  37. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/modules/free-mode.js +1 -1
  38. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/modules/thumbs.js +1 -1
  39. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/swiper-core.js +30 -15
  40. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/update-on-virtual-data.js +1 -0
  41. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/update-swiper.js +4 -2
  42. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/utils.js +13 -1
  43. package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/swiper-react.js +2 -2
  44. package/dist/notifications/announcements/announcement-list.js +1 -1
  45. package/dist/notifications/announcements/announcement.js +2 -2
  46. package/dist/pages/checkout/payment-page/hooks/use-get-adyen-redirect-result.js +1 -0
  47. package/dist/shared/api/storefront/hooks/cart/use-fetch-cart-by-id.d.ts +1 -1
  48. package/dist/shared/api/storefront/hooks/cart/use-fetch-current-cart.d.ts +1 -1
  49. package/dist/shared/api/storefront/hooks/website/use-fetch-countries-with-languages.d.ts +1 -1
  50. package/dist/shared/hooks/use-debounced-callback.js +1 -0
  51. package/dist/shared/hooks/use-enable-mobile-zoom.js +1 -0
  52. package/dist/shared/hooks/use-intersection-observer.js +1 -0
  53. package/dist/shared/hooks/use-mutation-observer.js +1 -0
  54. package/dist/shared/hooks/use-resize-observer.js +1 -0
  55. package/dist/shared/routing/types.d.ts +1 -0
  56. package/dist/shared/routing/use-route-link.d.ts +8 -0
  57. package/dist/shared/routing/use-route-link.js +24 -0
  58. package/dist/styles.css +2 -2
  59. package/package.json +45 -45
  60. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/routers/history.js +0 -0
  61. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/stateMappings/simple.js +0 -0
  62. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/utils/documentation.js +0 -0
  63. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/utils/logger.js +0 -0
  64. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/utils/noop.js +0 -0
  65. /package/dist/node_modules/.pnpm/{instantsearch.js@4.78.0_algoliasearch@4.24.0 → instantsearch.js@4.78.3_algoliasearch@4.24.0}/node_modules/instantsearch.js/es/lib/utils/safelyRunOnBrowser.js +0 -0
  66. /package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/modules/navigation.js +0 -0
  67. /package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/create-element-if-not-defined.js +0 -0
  68. /package/dist/node_modules/.pnpm/{swiper@11.2.5 → swiper@11.2.8}/node_modules/swiper/shared/ssr-window.esm.js +0 -0
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import simpleStateMapping from '../node_modules/.pnpm/instantsearch.js@4.78.0_algoliasearch@4.24.0/node_modules/instantsearch.js/es/lib/stateMappings/simple.js';
3
- import historyRouter from '../node_modules/.pnpm/instantsearch.js@4.78.0_algoliasearch@4.24.0/node_modules/instantsearch.js/es/lib/routers/history.js';
2
+ import simpleStateMapping from '../node_modules/.pnpm/instantsearch.js@4.78.3_algoliasearch@4.24.0/node_modules/instantsearch.js/es/lib/stateMappings/simple.js';
3
+ import historyRouter from '../node_modules/.pnpm/instantsearch.js@4.78.3_algoliasearch@4.24.0/node_modules/instantsearch.js/es/lib/routers/history.js';
4
4
 
5
5
  function createQueryStringRouting({ algoliaIndex, hierarchicalCategories, }) {
6
6
  return {
@@ -4,14 +4,11 @@ import { isValidElement } from 'react';
4
4
  import clsx from 'clsx';
5
5
  import { ProgressCircle } from '../../loading/progress-circle.js';
6
6
  import { GlyphsArrowBoldCapsRightIcon } from '../../icons/glyph/glyphs-arrow-boldcaps-right-icon.js';
7
- import { buildHref } from '../../shared/routing/route-utils.js';
8
- import { useBasePath } from '../../shared/routing/use-base-path.js';
9
- import { useRouteLinkElement } from '../../shared/routing/use-route-link-element.js';
7
+ import { useRouteLink } from '../../shared/routing/use-route-link.js';
10
8
  import buttonStyles from './button.module.css.js';
11
9
 
12
10
  function Button({ _pseudo = 'none', children: _children, className, color = 'primary', condensed, 'data-test-selector': dataTestSelector, form, href, icon, iconPosition = 'left', isDisabled, isLoading = false, isValidating = true, name, onClick, route, size = 'lg', type = 'button', value, variant = 'solid', withArrow = false, }) {
13
- const basePath = useBasePath();
14
- const RouteLinkElement = useRouteLinkElement();
11
+ const { getRouteLinkProps, RouteLinkElement } = useRouteLink();
15
12
  const handleButtonClick = (e) => {
16
13
  if (onClick)
17
14
  onClick(e);
@@ -30,7 +27,7 @@ function Button({ _pseudo = 'none', children: _children, className, color = 'pri
30
27
  const children = (jsxs(Fragment, { children: [showIconOnLeft && iconElement, jsx("span", { className: buttonStyles.children, children: isLoading ? (isLoading === true ? _children : isLoading) : _children }), withArrow && (jsx(GlyphsArrowBoldCapsRightIcon, { className: buttonStyles['right-arrow-icon'] })), showIconOnRight && iconElement, isLoading && (jsx(ProgressCircle, { className: buttonStyles.spinner, size: "sm", variant: color === 'primary' ? 'white' : 'gray' }))] }));
31
28
  if (href) {
32
29
  const Element = RouteLinkElement || 'a';
33
- return (jsx(Element, { className: classNames, "data-disabled": isDisabled ? true : undefined, "data-test-selector": dataTestSelector, href: buildHref({ basePath, href }), onClick: onClick, route: route, type: type, children: children }));
30
+ return (jsx(Element, { className: classNames, "data-disabled": isDisabled ? true : undefined, "data-test-selector": dataTestSelector, onClick: onClick, route: route, type: type, ...getRouteLinkProps(href, route), children: children }));
34
31
  }
35
32
  return (jsx("button", { className: classNames, "data-disabled": isDisabled ? true : undefined, "data-test-selector": dataTestSelector, disabled: isDisabled, form: form, formNoValidate: isValidating ? undefined : true, name: name, onClick: handleButtonClick, type: type, value: value, children: children }));
36
33
  }
@@ -4,6 +4,7 @@ export interface IconButtonProps {
4
4
  children: ReactNode;
5
5
  className?: string;
6
6
  color?: 'primary' | 'secondary' | 'current-color';
7
+ 'data-test-selector'?: string;
7
8
  href?: string;
8
9
  isDisabled?: boolean;
9
10
  onClick?: (event: MouseEvent<HTMLElement>) => void;
@@ -13,4 +14,4 @@ export interface IconButtonProps {
13
14
  title?: string;
14
15
  type?: 'button' | 'submit' | 'reset';
15
16
  }
16
- export declare function IconButton({ children, className: _className, color, href, isDisabled, onClick, size, target, title, type, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function IconButton({ children, className: _className, color, 'data-test-selector': dataTestSelector, href, isDisabled, onClick, route, size, target, title, type, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -1,14 +1,11 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import clsx from 'clsx';
4
- import { buildHref } from '../../shared/routing/route-utils.js';
5
- import { useBasePath } from '../../shared/routing/use-base-path.js';
6
- import { useRouteLinkElement } from '../../shared/routing/use-route-link-element.js';
4
+ import { useRouteLink } from '../../shared/routing/use-route-link.js';
7
5
  import styles from './icon-button.module.css.js';
8
6
 
9
- function IconButton({ children, className: _className, color = 'primary', href, isDisabled, onClick, size = 'md', target, title, type = 'button', ...rest }) {
10
- const basePath = useBasePath();
11
- const RouteLinkElement = useRouteLinkElement();
7
+ function IconButton({ children, className: _className, color = 'primary', 'data-test-selector': dataTestSelector, href, isDisabled, onClick, route, size = 'md', target, title, type = 'button', ...rest }) {
8
+ const { getRouteLinkProps, RouteLinkElement } = useRouteLink();
12
9
  const handleButtonClick = (e) => {
13
10
  e.preventDefault();
14
11
  e.stopPropagation();
@@ -17,9 +14,9 @@ function IconButton({ children, className: _className, color = 'primary', href,
17
14
  const className = clsx(styles['icon-button'], styles[size], styles[color], _className);
18
15
  if (href) {
19
16
  const Element = RouteLinkElement || 'a';
20
- return (jsx(Element, { className: className, "data-disabled": isDisabled ? true : undefined, href: buildHref({ basePath, href }), onClick: onClick, target: target, title: title, ...rest, children: children }));
17
+ return (jsx(Element, { className: className, "data-disabled": isDisabled ? true : undefined, "data-test-selector": dataTestSelector, onClick: onClick, target: target, title: title, ...getRouteLinkProps(href, route), ...rest, children: children }));
21
18
  }
22
- return (jsx("button", { className: className, "data-disabled": isDisabled ? true : undefined, disabled: isDisabled, onClick: handleButtonClick, title: title, type: type, ...rest, children: children }));
19
+ return (jsx("button", { className: className, "data-disabled": isDisabled ? true : undefined, "data-test-selector": dataTestSelector, disabled: isDisabled, onClick: handleButtonClick, title: title, type: type, ...rest, children: children }));
23
20
  }
24
21
 
25
22
  export { IconButton };
@@ -2,21 +2,18 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
  import clsx from 'clsx';
5
- import { buildHref } from '../../shared/routing/route-utils.js';
6
- import { useBasePath } from '../../shared/routing/use-base-path.js';
7
- import { useRouteLinkElement } from '../../shared/routing/use-route-link-element.js';
5
+ import { useRouteLink } from '../../shared/routing/use-route-link.js';
8
6
  import styles from './link.module.css.js';
9
7
 
10
- const Link = forwardRef(({ children, className: _className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }, ref) => {
11
- const basePath = useBasePath();
12
- const RouteLinkElement = useRouteLinkElement();
8
+ const Link = forwardRef(({ children, className: _className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, route, tabIndex, target, title, ...rest }, ref) => {
9
+ const { getRouteLinkProps, RouteLinkElement } = useRouteLink();
13
10
  const className = clsx({
14
11
  [styles.hover]: Boolean(href || onClick),
15
12
  [styles['has-underline']]: hasUnderline,
16
13
  }, styles['link'], color && styles[color], _className);
17
14
  if (href) {
18
15
  const Element = RouteLinkElement || 'a';
19
- return (jsx(Element, { ref: ref, className: className, "data-disabled": isDisabled ? true : undefined, href: buildHref({ basePath, href }), id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, target: target, title: title, ...rest, children: children }));
16
+ return (jsx(Element, { ref: ref, className: className, "data-disabled": isDisabled ? true : undefined, id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, target: target, title: title, ...getRouteLinkProps(href, route), ...rest, children: children }));
20
17
  }
21
18
  return (jsx("button", { ref: ref, className: className, "data-disabled": isDisabled ? true : undefined, disabled: isDisabled ? true : undefined, id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, title: title, type: "button", ...rest, children: children }));
22
19
  });
@@ -2,9 +2,9 @@
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { useState, useRef, useMemo } from 'react';
4
4
  import clsx from 'clsx';
5
- import Navigation from '../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/modules/navigation.js';
6
- import freeMode from '../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/modules/free-mode.js';
7
- import { Swiper, SwiperSlide } from '../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/swiper-react.js';
5
+ import Navigation from '../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/modules/navigation.js';
6
+ import freeMode from '../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/modules/free-mode.js';
7
+ import { Swiper, SwiperSlide } from '../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/swiper-react.js';
8
8
  import { breakpoints } from '../shared/utils/breakpoints.js';
9
9
  import { deepMerge } from '../shared/utils/merge.js';
10
10
  import { CarouselNavigationButton } from './carousel-navigation-button.js';
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { useRef, useState } from 'react';
4
- import { Swiper, SwiperSlide } from '../../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/swiper-react.js';
4
+ import { Swiper, SwiperSlide } from '../../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/swiper-react.js';
5
5
  import { CarouselPagination } from '../pagination/pagination.js';
6
6
  import styles from './usp-carousel.module.css.js';
7
7
 
@@ -13,6 +13,7 @@ export interface DrawerProps {
13
13
  allowCloseOnBackgroundClick?: boolean;
14
14
  children: ReactNode | ((args: ChildrenFunctionArgs) => ReactNode);
15
15
  className?: string;
16
+ 'data-test-selector'?: string;
16
17
  groupId?: string;
17
18
  instanceId?: string;
18
19
  isInitialOpen?: boolean;
@@ -24,4 +25,4 @@ export interface DrawerProps {
24
25
  showUnder?: 'header' | 'announcement';
25
26
  timeout?: number;
26
27
  }
27
- export declare function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, instanceId, isInitialOpen, isOpen: isOpenControlled, onClose, onClosed, position, showBackgroundOverlay, showUnder, timeout, }: DrawerProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function Drawer({ allowCloseOnBackgroundClick, children, className, 'data-test-selector': dataTestSelector, groupId, instanceId, isInitialOpen, isOpen: isOpenControlled, onClose, onClosed, position, showBackgroundOverlay, showUnder, timeout, }: DrawerProps): import("react/jsx-runtime").JSX.Element;
@@ -8,7 +8,7 @@ import { createAddEndListener } from '../collapsables/unmounter/utils.js';
8
8
  import { useDrawer } from './use-drawer.js';
9
9
  import styles from './drawer.module.css.js';
10
10
 
11
- function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, instanceId, isInitialOpen = false, isOpen: isOpenControlled, onClose, onClosed, position, showBackgroundOverlay, showUnder, timeout, }) {
11
+ function Drawer({ allowCloseOnBackgroundClick, children, className, 'data-test-selector': dataTestSelector, groupId, instanceId, isInitialOpen = false, isOpen: isOpenControlled, onClose, onClosed, position, showBackgroundOverlay, showUnder, timeout, }) {
12
12
  const wasOpenRef = useRef(isInitialOpen);
13
13
  const asideRef = useRef(null);
14
14
  const useDrawerResult = useDrawer({
@@ -30,7 +30,7 @@ function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, ins
30
30
  return onClosed;
31
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
32
32
  }, []);
33
- return (jsxs(Fragment, { children: [jsx(CSSTransition, { mountOnEnter: true, unmountOnExit: true, addEndListener: createAddEndListener(asideRef), in: isOpen, nodeRef: asideRef, onExited: onClosed, timeout: timeout, children: jsx("aside", { ref: asideRef, className: clsx(styles.drawer, styles[position], showUnder === 'header' && styles['under-header'], showUnder === 'announcement' && styles['under-announcement'], className), children: children instanceof Function ? children(useDrawerResult) : children }, `${groupId}-${instanceId}`) }, groupId), showBackgroundOverlay && (jsx(BackgroundOverlay, { isOpen: isOpen, onClick: () => {
33
+ return (jsxs(Fragment, { children: [jsx(CSSTransition, { mountOnEnter: true, unmountOnExit: true, addEndListener: createAddEndListener(asideRef), in: isOpen, nodeRef: asideRef, onExited: onClosed, timeout: timeout, children: jsx("aside", { ref: asideRef, className: clsx(styles.drawer, styles[position], showUnder === 'header' && styles['under-header'], showUnder === 'announcement' && styles['under-announcement'], className), "data-test-selector": dataTestSelector, children: children instanceof Function ? children(useDrawerResult) : children }, `${groupId}-${instanceId}`) }, groupId), showBackgroundOverlay && (jsx(BackgroundOverlay, { isOpen: isOpen, onClick: () => {
34
34
  if (!allowCloseOnBackgroundClick)
35
35
  return;
36
36
  if (isControlled) {
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useEffect, useCallback, useMemo } from 'react';
2
3
  import { useGlobalState } from '../shared/providers/global-state-provider.js';
3
4
  import { createUUID } from '../shared/utils/uuid.js';
package/dist/exports.d.ts CHANGED
@@ -355,6 +355,7 @@ export * from './shared/routing/types';
355
355
  export * from './shared/routing/use-base-path';
356
356
  export * from './shared/routing/use-navigate';
357
357
  export * from './shared/routing/use-on-navigate';
358
+ export * from './shared/routing/use-route-link';
358
359
  export * from './shared/routing/use-route-link-element';
359
360
  export * from './shared/routing/with-routing';
360
361
  export * from './shared/utils/array';
@@ -19,6 +19,7 @@ function SelectField({ className, 'data-test-selector': dataTestSelector, defaul
19
19
  onChange?.(key);
20
20
  };
21
21
  useEffect(() => {
22
+ // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
22
23
  setSelectedKey(selectedOption);
23
24
  }, [selectedOption]);
24
25
  return (jsx(Select, { "aria-label": label, className: clsx(styles['select-field'], styles[size], styles[variant], {
@@ -1,5 +1,4 @@
1
1
  "use client";
2
- import { createElement } from 'react';
3
2
  import { jsx, jsxs } from 'react/jsx-runtime';
4
3
  import clsx from 'clsx';
5
4
  import { useAlgoliaInsights } from '../../../algolia/use-algolia-insights.js';
@@ -56,10 +55,10 @@ function SuggestionsSection() {
56
55
  function ProductHitCard({ autocomplete, hit, index, source, }) {
57
56
  const { close } = useGlobalSearchDisclosure();
58
57
  const { sendAddToCartFromSearchEvent, sendAddToWishListFromSearchEvent, sendProductClickFromSearchEvent, } = useAlgoliaInsights();
59
- return (createElement(ConnectedProductCard, { ...autocomplete.getItemProps({
58
+ return (jsx(ConnectedProductCard, { ...autocomplete.getItemProps({
60
59
  item: hit.hit,
61
60
  source,
62
- }), key: hit.storefrontId, href: hit.storefrontSlug, id: hit.storefrontId, image: {
61
+ }), href: hit.storefrontSlug, id: hit.storefrontId, image: {
63
62
  fit: 'contain',
64
63
  image: hit.image,
65
64
  title: hit.name,
@@ -87,7 +86,7 @@ function ProductHitCard({ autocomplete, hit, index, source, }) {
87
86
  isVatIncluded: hit.isVatIncluded,
88
87
  originalPrice: hit.originalPrice,
89
88
  price: hit.price,
90
- }, sku: hit.id, tags: hit.labels, title: jsx(Highlight, { attribute: "name", hit: hit.hit }) }));
89
+ }, sku: hit.id, tags: hit.labels, title: jsx(Highlight, { attribute: "name", hit: hit.hit }) }, hit.storefrontId));
91
90
  }
92
91
  function ProductResultsSection() {
93
92
  const { autocomplete, products: collection } = useAlgoliaSearch();
@@ -8,7 +8,7 @@ import { useFetchSession } from '../../../shared/api/storefront/hooks/authentica
8
8
  function ConnectedAccountButton({ className, 'data-test-selector': dataTestSelector, href, onClick, }) {
9
9
  const t = useFormattedMessage();
10
10
  const { data: { isAuthenticated } = {} } = useFetchSession();
11
- return (jsx(IconButton, { className: className, "data-test-selector": dataTestSelector, href: href, onClick: onClick, children: jsx(AccountIcon, { "aria-label": isAuthenticated ? t('My account') : t('Sign in or create account'), isAuthenticated: isAuthenticated }) }));
11
+ return (jsx(IconButton, { className: className, "data-authenticated": isAuthenticated ? true : false, "data-test-selector": dataTestSelector, href: href, onClick: onClick, children: jsx(AccountIcon, { "aria-label": isAuthenticated ? t('My account') : t('Sign in or create account'), isAuthenticated: isAuthenticated }) }));
12
12
  }
13
13
 
14
14
  export { ConnectedAccountButton };
@@ -8,7 +8,7 @@ import { useFetchCurrentCartCount } from '../../../shared/api/storefront/hooks/c
8
8
  function ConnectedCartButton({ className, 'data-test-selector': dataTestSelector, href, onClick, }) {
9
9
  const count = useFetchCurrentCartCount();
10
10
  const t = useFormattedMessage();
11
- return (jsx(IconButton, { className: className, "data-test-selector": dataTestSelector, href: href, onClick: onClick, children: jsx(CartIcon, { "aria-label": t('Shopping cart'), count: count }) }));
11
+ return (jsx(IconButton, { className: className, "data-count": count, "data-test-selector": dataTestSelector, href: href, onClick: onClick, children: jsx(CartIcon, { "aria-label": t('Shopping cart'), count: count }) }));
12
12
  }
13
13
 
14
14
  export { ConnectedCartButton };
@@ -1,10 +1,11 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { Drawer } from '../../drawer/drawer.js';
3
4
  import { PanelNavigation } from '../../navigation/panel-navigation/panel-navigation.js';
4
5
  import styles from './desktop-navigation-drawer.module.css.js';
5
6
 
6
7
  function DesktopNavigationDrawer({ groupId, instanceId, onClosed, submenu, }) {
7
- return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, className: styles['desktop-navigation-drawer'], groupId: groupId, instanceId: instanceId, onClosed: onClosed, position: "top", showUnder: "header", children: submenu && (jsx(PanelNavigation, { header: submenu.url
8
+ return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, className: styles['desktop-navigation-drawer'], "data-test-selector": "desktopNavigationDrawer", groupId: groupId, instanceId: instanceId, onClosed: onClosed, position: "top", showUnder: "header", children: submenu && (jsx(PanelNavigation, { "data-test-selector": "desktopNavigationPanel", header: submenu.url
8
9
  ? { href: submenu.url, title: submenu.title }
9
10
  : submenu.title, id: `panels-${submenu.key}`, links: submenu.links }, submenu.key)) }));
10
11
  }
@@ -1,10 +1,11 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { Drawer } from '../../drawer/drawer.js';
3
4
  import { MobileNavigation } from '../../navigation/mobile-navigation/mobile-navigation.js';
4
5
  import styles from './mobile-navigation-drawer.module.css.js';
5
6
 
6
7
  function MobileNavigationDrawer({ groupId, instanceId, links, }) {
7
- return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, className: styles['mobile-navigation-drawer'], groupId: groupId, instanceId: instanceId, position: "left", showUnder: "announcement", children: ({ close, isOpen }) => (jsx(MobileNavigation, { id: "mobile-navigation", isActive: isOpen, links: links, onActiveChange: close })) }));
8
+ return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, className: styles['mobile-navigation-drawer'], "data-test-selector": "mobileNavigationDrawer", groupId: groupId, instanceId: instanceId, position: "left", showUnder: "announcement", children: ({ close, isOpen }) => (jsx(MobileNavigation, { id: "mobile-navigation", isActive: isOpen, links: links, onActiveChange: close })) }));
8
9
  }
9
10
 
10
11
  export { MobileNavigationDrawer };
@@ -3,7 +3,7 @@ import { Drawer } from '../../drawer/drawer.js';
3
3
  import { SearchRoot } from '../../global-search/global-search.js';
4
4
 
5
5
  function SearchDrawer({ groupId, instanceId }) {
6
- return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, groupId: groupId, instanceId: instanceId, position: "top", showUnder: "header", children: jsx(SearchRoot, {}) }));
6
+ return (jsx(Drawer, { allowCloseOnBackgroundClick: true, showBackgroundOverlay: true, "data-test-selector": "searchDrawer", groupId: groupId, instanceId: instanceId, position: "top", showUnder: "header", children: jsx(SearchRoot, {}) }));
7
7
  }
8
8
 
9
9
  export { SearchDrawer };
@@ -65,7 +65,7 @@ function Header({ className, links, sticky }) {
65
65
  if (activeSubmenu)
66
66
  setDesktopNavigationOpen(true);
67
67
  }, [activeSubmenu, setDesktopNavigationOpen]);
68
- return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { href: PATHS.HOME, title: t('Home') }), mainNavigation: jsx(NavigationLinkList, { activeLink: activeSubmenu, links: links, onSubmenuToggle: link => toggleActiveSubmenu(link) }), navigationActions: jsxs(Fragment, { children: [jsx(ConnectedAccountButton, { href: PATHS.ACCOUNT }), jsx(ConnectedFavoritesButton, { href: PATHS.FAVORITES }), jsx(ConnectedCartButton, { href: PATHS.CART })] }), search: jsx(SearchButton, { "aria-controls": "global-search", isActive: searchOpen, onActiveChange: toggleSearch }) }) }), jsx(SearchDrawer, { groupId: searchGroupId, instanceId: searchInstanceId }), !isXl && (jsx(MobileNavigationDrawer, { groupId: mobileNavigationDrawer.groupId, instanceId: mobileNavigationDrawer.instanceId, links: links })), isXl && (jsx(DesktopNavigationDrawer, { groupId: desktopNavigationDrawer.groupId, instanceId: desktopNavigationDrawer.instanceId, onClosed: () => setActiveSubmenu(undefined), submenu: activeSubmenu }))] }));
68
+ return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), "data-test-selector": "pageHeader", children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "pageHeaderHamburgerButton", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { "data-test-selector": "pageHeaderLogo", href: PATHS.HOME, title: t('Home') }), mainNavigation: jsx(NavigationLinkList, { activeLink: activeSubmenu, "data-test-selector": "pageHeaderMainNavigation", links: links, onSubmenuToggle: link => toggleActiveSubmenu(link) }), navigationActions: jsxs(Fragment, { children: [jsx(ConnectedAccountButton, { "data-test-selector": "pageHeaderAccountButton", href: PATHS.ACCOUNT }), jsx(ConnectedFavoritesButton, { "data-test-selector": "pageHeaderFavoritesButton", href: PATHS.FAVORITES }), jsx(ConnectedCartButton, { "data-test-selector": "pageHeaderCartButton", href: PATHS.CART })] }), search: jsx(SearchButton, { "aria-controls": "global-search", "data-test-selector": "pageHeaderSearchButton", isActive: searchOpen, onActiveChange: toggleSearch }) }) }), jsx(SearchDrawer, { groupId: searchGroupId, instanceId: searchInstanceId }), !isXl && (jsx(MobileNavigationDrawer, { groupId: mobileNavigationDrawer.groupId, instanceId: mobileNavigationDrawer.instanceId, links: links })), isXl && (jsx(DesktopNavigationDrawer, { groupId: desktopNavigationDrawer.groupId, instanceId: desktopNavigationDrawer.instanceId, onClosed: () => setActiveSubmenu(undefined), submenu: activeSubmenu }))] }));
69
69
  }
70
70
 
71
71
  export { Header };
@@ -1,7 +1,8 @@
1
1
  import { NavigationLink } from '../../shared/api/bff/model/bff.model';
2
2
  export interface LinkListProps {
3
3
  activeLink?: NavigationLink;
4
+ 'data-test-selector'?: string;
4
5
  links: NavigationLink[];
5
6
  onSubmenuToggle: (link: NavigationLink) => void;
6
7
  }
7
- export declare function NavigationLinkList({ activeLink, links, onSubmenuToggle, }: LinkListProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function NavigationLinkList({ activeLink, 'data-test-selector': dataTestSelector, links, onSubmenuToggle, }: LinkListProps): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,13 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from 'react/jsx-runtime';
2
3
  import { Link } from '../../buttons/link/link.js';
3
4
  import { GlyphsChevronsBoldDownIcon } from '../../icons/glyph/glyphs-chevrons-bold-down-icon.js';
4
5
  import styles from './navigation-link-list.module.css.js';
5
6
 
6
- function NavigationLinkList({ activeLink, links, onSubmenuToggle, }) {
7
- return (jsx("ul", { className: styles['navigation-link-list'], children: links.map(link => {
7
+ function NavigationLinkList({ activeLink, 'data-test-selector': dataTestSelector, links, onSubmenuToggle, }) {
8
+ return (jsx("ul", { className: styles['navigation-link-list'], "data-test-selector": dataTestSelector, children: links.map(link => {
8
9
  if (link.links && link.links.length > 0) {
9
- return (jsx("li", { className: activeLink === link ? styles['active'] : undefined, children: jsxs(Link, { "aria-controls": `panels-${link.key}`, "aria-expanded": activeLink === link, className: styles.link, onClick: () => onSubmenuToggle(link), target: link.openInNewTab ? '_blank' : undefined, children: [link.title, jsx(GlyphsChevronsBoldDownIcon, { className: styles.chevron })] }) }, link.key));
10
+ return (jsx("li", { className: activeLink === link ? styles['active'] : undefined, children: jsxs(Link, { "aria-controls": `panels-${link.key}`, "aria-expanded": activeLink === link, className: styles.link, "data-test-selector": `navigationLink-${link.key}`, onClick: () => onSubmenuToggle(link), target: link.openInNewTab ? '_blank' : undefined, children: [link.title, jsx(GlyphsChevronsBoldDownIcon, { className: styles.chevron, role: "presentation" })] }) }, link.key));
10
11
  }
11
12
  return (jsx("li", { children: jsx(Link, { className: styles.link, href: link.url, children: link.title }) }, link.key));
12
13
  }) }));
@@ -1,6 +1,7 @@
1
1
  export interface SonicLogoProps {
2
2
  className?: string;
3
+ 'data-test-selector'?: string;
3
4
  href?: string;
4
5
  title?: string;
5
6
  }
6
- export declare function SonicLogo({ className, href, title }: SonicLogoProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function SonicLogo({ className, 'data-test-selector': dataTestSelector, href, title, }: SonicLogoProps): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,13 @@
1
+ "use client";
1
2
  import { jsx, jsxs } from 'react/jsx-runtime';
2
3
  import clsx from 'clsx';
3
4
  import { Link } from '../../buttons/link/link.js';
4
5
  import { useFormattedMessage } from '../../intl/use-formatted-message.js';
5
6
  import styles from './sonic-logo.module.css.js';
6
7
 
7
- function SonicLogo({ className, href, title }) {
8
+ function SonicLogo({ className, 'data-test-selector': dataTestSelector, href, title, }) {
8
9
  const t = useFormattedMessage();
9
- return (jsx(Link, { className: clsx(styles.wrapper, className), href: href, title: title, children: jsx("svg", { "aria-label": t('Sonic Equipment'), className: styles['sonic-logo'], viewBox: "0 0 100 24", xmlns: "http://www.w3.org/2000/svg", children: jsxs("g", { fill: "none", fillRule: "evenodd", children: [jsx("path", { className: styles.letters, d: "M11.87 8.65c1.815 0 3.286 1.482 3.286 3.311 0 6.595-5.325 11.962-11.87 11.962C1.471 23.923 0 22.44 0 20.612c0-1.766 1.372-3.21 3.1-3.307l.186-.005c2.848 0 5.179-2.277 5.293-5.12l.005-.219c0-1.829 1.471-3.311 3.286-3.311zm0-8.65c1.815 0 3.286 1.483 3.286 3.311 0 1.766-1.371 3.21-3.1 3.307l-.186.005c-2.849 0-5.178 2.277-5.293 5.118l-.004.22c0 1.829-1.472 3.311-3.287 3.311C1.472 15.272 0 13.79 0 11.961 0 5.366 5.325 0 11.87 0zm6.155 12.016c0 6.596 5.325 11.963 11.87 11.963 6.545 0 11.87-5.367 11.87-11.963 0-6.595-5.325-11.96-11.87-11.96-6.545 0-11.87 5.365-11.87 11.96zm6.572 0c0-2.943 2.376-5.338 5.298-5.338 2.92 0 5.297 2.395 5.297 5.338 0 2.945-2.376 5.34-5.297 5.34-2.922 0-5.298-2.395-5.298-5.34zM82.251 3.56c-4.628 4.663-4.628 12.251 0 16.915 4.628 4.663 12.158 4.663 16.786 0a3.33 3.33 0 0 0 .001-4.683 3.268 3.268 0 0 0-4.501-.138l-.146.138a5.278 5.278 0 0 1-7.494 0c-2.064-2.081-2.064-5.468.001-7.549a5.275 5.275 0 0 1 7.313-.174l.18.173a3.268 3.268 0 0 0 4.647 0 3.33 3.33 0 0 0 0-4.684c-4.63-4.663-12.16-4.662-16.787.002zm-12.868-.13v17.148c0 1.828 1.47 3.311 3.285 3.311 1.816 0 3.287-1.483 3.287-3.311V3.429c0-1.829-1.471-3.312-3.287-3.312-1.815 0-3.285 1.483-3.285 3.312zM48.063.075c-1.814 0-3.285 1.483-3.285 3.311V20.69c0 1.828 1.471 3.311 3.286 3.311s3.286-1.483 3.286-3.311V6.698h2.95c2.92 0 5.297 2.394 5.297 5.338v8.653c0 1.828 1.471 3.311 3.286 3.311s3.286-1.483 3.286-3.311v-8.653C66.17 5.44 60.844.075 54.3.075h-6.235z" }), jsx("path", { className: styles.dot, d: "M35.27 12.017c0 2.991-2.406 5.416-5.375 5.416-2.97 0-5.376-2.425-5.376-5.416 0-2.992 2.407-5.417 5.376-5.417 2.969 0 5.375 2.425 5.375 5.417" })] }) }) }));
10
+ return (jsx(Link, { className: clsx(styles.wrapper, className), "data-test-selector": dataTestSelector, href: href, title: title, children: jsx("svg", { "aria-label": t('Sonic Equipment'), className: styles['sonic-logo'], viewBox: "0 0 100 24", xmlns: "http://www.w3.org/2000/svg", children: jsxs("g", { fill: "none", fillRule: "evenodd", children: [jsx("path", { className: styles.letters, d: "M11.87 8.65c1.815 0 3.286 1.482 3.286 3.311 0 6.595-5.325 11.962-11.87 11.962C1.471 23.923 0 22.44 0 20.612c0-1.766 1.372-3.21 3.1-3.307l.186-.005c2.848 0 5.179-2.277 5.293-5.12l.005-.219c0-1.829 1.471-3.311 3.286-3.311zm0-8.65c1.815 0 3.286 1.483 3.286 3.311 0 1.766-1.371 3.21-3.1 3.307l-.186.005c-2.849 0-5.178 2.277-5.293 5.118l-.004.22c0 1.829-1.472 3.311-3.287 3.311C1.472 15.272 0 13.79 0 11.961 0 5.366 5.325 0 11.87 0zm6.155 12.016c0 6.596 5.325 11.963 11.87 11.963 6.545 0 11.87-5.367 11.87-11.963 0-6.595-5.325-11.96-11.87-11.96-6.545 0-11.87 5.365-11.87 11.96zm6.572 0c0-2.943 2.376-5.338 5.298-5.338 2.92 0 5.297 2.395 5.297 5.338 0 2.945-2.376 5.34-5.297 5.34-2.922 0-5.298-2.395-5.298-5.34zM82.251 3.56c-4.628 4.663-4.628 12.251 0 16.915 4.628 4.663 12.158 4.663 16.786 0a3.33 3.33 0 0 0 .001-4.683 3.268 3.268 0 0 0-4.501-.138l-.146.138a5.278 5.278 0 0 1-7.494 0c-2.064-2.081-2.064-5.468.001-7.549a5.275 5.275 0 0 1 7.313-.174l.18.173a3.268 3.268 0 0 0 4.647 0 3.33 3.33 0 0 0 0-4.684c-4.63-4.663-12.16-4.662-16.787.002zm-12.868-.13v17.148c0 1.828 1.47 3.311 3.285 3.311 1.816 0 3.287-1.483 3.287-3.311V3.429c0-1.829-1.471-3.312-3.287-3.312-1.815 0-3.285 1.483-3.285 3.312zM48.063.075c-1.814 0-3.285 1.483-3.285 3.311V20.69c0 1.828 1.471 3.311 3.286 3.311s3.286-1.483 3.286-3.311V6.698h2.95c2.92 0 5.297 2.394 5.297 5.338v8.653c0 1.828 1.471 3.311 3.286 3.311s3.286-1.483 3.286-3.311v-8.653C66.17 5.44 60.844.075 54.3.075h-6.235z" }), jsx("path", { className: styles.dot, d: "M35.27 12.017c0 2.991-2.406 5.416-5.375 5.416-2.97 0-5.376-2.425-5.376-5.416 0-2.992 2.407-5.417 5.376-5.417 2.969 0 5.375 2.425 5.375 5.417" })] }) }) }));
10
11
  }
11
12
 
12
13
  export { SonicLogo };
package/dist/index.js CHANGED
@@ -354,6 +354,7 @@ export { buildHref } from './shared/routing/route-utils.js';
354
354
  export { useBasePath } from './shared/routing/use-base-path.js';
355
355
  export { useNavigate } from './shared/routing/use-navigate.js';
356
356
  export { useOnNavigate } from './shared/routing/use-on-navigate.js';
357
+ export { useRouteLink } from './shared/routing/use-route-link.js';
357
358
  export { useRouteLinkElement } from './shared/routing/use-route-link-element.js';
358
359
  export { withRouting } from './shared/routing/with-routing.js';
359
360
  export { ensureArray } from './shared/utils/array.js';
@@ -1,7 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
2
  interface MenuListBackButtonProps {
3
3
  children: ReactNode;
4
+ 'data-test-selector'?: string;
4
5
  onClick: VoidFunction;
5
6
  }
6
- export declare function MenuListBackButton({ children, onClick, }: MenuListBackButtonProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function MenuListBackButton({ children, 'data-test-selector': dataTestSelector, onClick, }: MenuListBackButtonProps): import("react/jsx-runtime").JSX.Element;
7
8
  export {};
@@ -3,8 +3,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { GlyphsChevronsSlimLeftIcon } from '../../icons/glyph/glyphs-chevrons-slim-left-icon.js';
4
4
  import styles from './menu-list.module.css.js';
5
5
 
6
- function MenuListBackButton({ children, onClick, }) {
7
- return (jsxs("button", { className: styles['menu-list-back-button'], onClick: onClick, type: "button", children: [jsx(GlyphsChevronsSlimLeftIcon, { className: styles['icon'], role: "presentation" }), children] }));
6
+ function MenuListBackButton({ children, 'data-test-selector': dataTestSelector, onClick, }) {
7
+ return (jsxs("button", { className: styles['menu-list-back-button'], "data-test-selector": dataTestSelector, onClick: onClick, type: "button", children: [jsx(GlyphsChevronsSlimLeftIcon, { className: styles['icon'], role: "presentation" }), children] }));
8
8
  }
9
9
 
10
10
  export { MenuListBackButton };
@@ -1,7 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
2
  interface MenuListHeaderProps {
3
3
  children: ReactNode;
4
+ 'data-test-selector'?: string;
4
5
  href?: string;
5
6
  }
6
- export declare function MenuListHeader({ children, href }: MenuListHeaderProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function MenuListHeader({ children, 'data-test-selector': dataTestSelector, href, }: MenuListHeaderProps): import("react/jsx-runtime").JSX.Element;
7
8
  export {};
@@ -3,8 +3,8 @@ import { Link } from '../../buttons/link/link.js';
3
3
  import { GlyphsArrowBlackCapsRightIcon } from '../../icons/glyph/glyphs-arrow-blackcaps-right-icon.js';
4
4
  import styles from './menu-list.module.css.js';
5
5
 
6
- function MenuListHeader({ children, href }) {
7
- return (jsxs("h2", { className: styles['menu-list-header'], children: [href && (jsxs(Link, { href: href, children: [children, jsx(GlyphsArrowBlackCapsRightIcon, { className: styles['icon'], role: "presentation" })] })), !href && children] }));
6
+ function MenuListHeader({ children, 'data-test-selector': dataTestSelector, href, }) {
7
+ return (jsxs("h2", { className: styles['menu-list-header'], "data-test-selector": dataTestSelector, children: [href && (jsxs(Link, { href: href, children: [children, jsx(GlyphsArrowBlackCapsRightIcon, { className: styles['icon'], role: "presentation" })] })), !href && children] }));
8
8
  }
9
9
 
10
10
  export { MenuListHeader };
@@ -4,6 +4,7 @@ export interface MenuListItemProps {
4
4
  'aria-controls'?: string;
5
5
  badge?: ReactNode;
6
6
  children: ReactNode | string;
7
+ 'data-test-selector'?: string;
7
8
  hasChildren?: boolean;
8
9
  href?: string;
9
10
  image?: ImageType;
@@ -11,4 +12,4 @@ export interface MenuListItemProps {
11
12
  onClick?: VoidFunction;
12
13
  openInNewTab?: boolean;
13
14
  }
14
- export declare function MenuListItem({ 'aria-controls': ariaControls, badge, children, hasChildren, href, image, isSelected, onClick, openInNewTab, }: MenuListItemProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function MenuListItem({ 'aria-controls': ariaControls, badge, children, 'data-test-selector': dataTestSelector, hasChildren, href, image, isSelected, onClick, openInNewTab, ...rest }: MenuListItemProps): import("react/jsx-runtime").JSX.Element;
@@ -7,9 +7,9 @@ import { useFormattedMessage } from '../../intl/use-formatted-message.js';
7
7
  import { Image } from '../../media/image/image.js';
8
8
  import styles from './menu-list.module.css.js';
9
9
 
10
- function MenuListItem({ 'aria-controls': ariaControls, badge, children, hasChildren, href, image, isSelected, onClick, openInNewTab, }) {
10
+ function MenuListItem({ 'aria-controls': ariaControls, badge, children, 'data-test-selector': dataTestSelector, hasChildren, href, image, isSelected, onClick, openInNewTab, ...rest }) {
11
11
  const t = useFormattedMessage();
12
- return (jsxs("li", { "aria-owns": ariaControls, className: clsx(styles['menu-list-item'], isSelected && styles['selected'], hasChildren && styles['has-children']), children: [image && (jsx("span", { className: styles['image'], role: "presentation", children: jsx(Image, { fit: "contain", image: image, title: "" }) })), badge && jsx("span", { className: styles['badge'], children: badge }), jsx(Link, { "aria-controls": ariaControls, "aria-expanded": ariaControls && isSelected, "aria-haspopup": hasChildren ? 'true' : undefined, className: styles['label'], href: href, onClick: onClick, role: hasChildren ? 'menuitem' : undefined, target: openInNewTab ? '_blank' : undefined, children: children }), hasChildren && (jsx(GlyphsChevronsSlimRightIcon, { "aria-description": `(${t('Submenu')})`, className: styles['icon'] }))] }));
12
+ return (jsxs("li", { "aria-owns": ariaControls, className: clsx(styles['menu-list-item'], isSelected && styles['selected'], hasChildren && styles['has-children']), "data-test-selector": dataTestSelector, ...rest, children: [image && (jsx("span", { className: styles['image'], role: "presentation", children: jsx(Image, { fit: "contain", image: image, title: "" }) })), badge && jsx("span", { className: styles['badge'], children: badge }), jsx(Link, { "aria-controls": ariaControls, "aria-expanded": ariaControls && isSelected, "aria-haspopup": hasChildren ? 'true' : undefined, className: styles['label'], href: href, onClick: onClick, role: hasChildren ? 'menuitem' : undefined, target: openInNewTab ? '_blank' : undefined, children: children }), hasChildren && (jsx(GlyphsChevronsSlimRightIcon, { "aria-description": `(${t('Submenu')})`, className: styles['icon'] }))] }));
13
13
  }
14
14
 
15
15
  export { MenuListItem };
@@ -8,7 +8,7 @@ import styles from './menu-list.module.css.js';
8
8
  function MenuList({ back, children, header, scrollable = true, variant = 'default', }) {
9
9
  const headerTitle = typeof header === 'string' ? header : header?.title;
10
10
  const headerHref = typeof header === 'string' ? undefined : header?.href;
11
- return (jsxs("section", { className: clsx(styles['menu-list'], styles[variant], scrollable && styles['scrollable']), role: "menu", children: [back && (jsx(MenuListBackButton, { onClick: back.onClick, children: back.title })), jsxs("div", { className: styles['scroll-area'], children: [header && (jsx(MenuListHeader, { href: headerHref, children: headerTitle })), jsx("ul", { className: styles['list'], children: children })] })] }));
11
+ return (jsxs("section", { className: clsx(styles['menu-list'], styles[variant], scrollable && styles['scrollable']), role: "menu", children: [back && (jsx(MenuListBackButton, { "data-test-selector": "menuListBackButton", onClick: back.onClick, children: back.title })), jsxs("div", { className: styles['scroll-area'], "data-test-selector": "menuListScrollArea", children: [header && (jsx(MenuListHeader, { "data-test-selector": "menuListHeader", href: headerHref, children: headerTitle })), jsx("ul", { className: styles['list'], children: children })] })] }));
12
12
  }
13
13
 
14
14
  export { MenuList };
@@ -2,9 +2,9 @@
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { useState, useRef } from 'react';
4
4
  import clsx from 'clsx';
5
- import Navigation from '../../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/modules/navigation.js';
6
- import Thumb from '../../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/modules/thumbs.js';
7
- import { Swiper, SwiperSlide } from '../../node_modules/.pnpm/swiper@11.2.5/node_modules/swiper/swiper-react.js';
5
+ import Navigation from '../../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/modules/navigation.js';
6
+ import Thumb from '../../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/modules/thumbs.js';
7
+ import { Swiper, SwiperSlide } from '../../node_modules/.pnpm/swiper@11.2.8/node_modules/swiper/swiper-react.js';
8
8
  import { CarouselNavigationButton } from '../../carousel/carousel-navigation-button.js';
9
9
  import { CarouselPagination } from '../../carousel/pagination/pagination.js';
10
10
  import { Image } from '../image/image.js';
@@ -7,7 +7,7 @@ import { useFormattedMessage } from '../../intl/use-formatted-message.js';
7
7
 
8
8
  function CartIcon({ 'aria-label': ariaLabel, count }) {
9
9
  const t = useFormattedMessage();
10
- return (jsx(IconWithBadge, { "aria-label": ariaLabel, badge: count && count > 0 ? (jsx(Badge, { "aria-label": count && count > 0 ? `(${t('Number of products')})` : undefined, count: count })) : undefined, "data-test-selector": "cartIcon", icon: jsx(SolidCartIcon, { role: "presentation" }) }));
10
+ return (jsx(IconWithBadge, { "aria-label": ariaLabel, badge: count && count > 0 ? (jsx(Badge, { "aria-label": count && count > 0 ? `(${t('Number of products')})` : undefined, count: count })) : undefined, "data-foo": "foo", "data-test-selector": "cartIcon", icon: jsx(SolidCartIcon, { role: "presentation" }) }));
11
11
  }
12
12
 
13
13
  export { CartIcon };
@@ -19,7 +19,7 @@ function MobileNavigation({ id, isActive, links, onActiveChange, }) {
19
19
  const t = useFormattedMessage();
20
20
  const { data: { isAuthenticated } = {} } = useFetchSession();
21
21
  const cartCount = useFetchCurrentCartCount();
22
- return (jsxs("section", { "aria-label": t('Main menu'), className: clsx(styles['mobile-navigation'], isActive && styles['active']), id: id, children: [jsxs("header", { className: styles['header'], children: [jsx("div", { className: styles['logo'], role: "presentation", children: jsx(SonicLogo, {}) }), jsx("div", { className: styles['hamburger'], children: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", isActive: isActive, onActiveChange: onActiveChange }) })] }), jsx(PanelNavigation, { allowBack: true, className: styles['panels'], isNarrow: true, links: links, variant: "primary", children: jsxs(MenuList, { header: t('My Sonic'), scrollable: false, children: [jsx(MenuListItem, { badge: jsx(AccountIcon, { isAuthenticated: isAuthenticated }), href: PATHS.ACCOUNT, children: isAuthenticated ? t('My account') : t('Sign in or create account') }), jsx(MenuListItem, { badge: jsx(FavoriteIcon, {}), href: PATHS.FAVORITES, children: t('Favorites') }), jsx(MenuListItem, { badge: jsx(CartIcon, { count: cartCount }), href: PATHS.CART, children: t('Shopping cart') })] }) })] }));
22
+ return (jsxs("section", { "aria-label": t('Main menu'), className: clsx(styles['mobile-navigation'], isActive && styles['active']), "data-test-selector": "mobileNavigationMenu", id: id, children: [jsxs("header", { className: styles['header'], children: [jsx("div", { className: styles['logo'], role: "presentation", children: jsx(SonicLogo, {}) }), jsx("div", { className: styles['hamburger'], children: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "mobileNavigationHamburgerButton", isActive: isActive, onActiveChange: onActiveChange }) })] }), jsx(PanelNavigation, { allowBack: true, className: styles['panels'], "data-test-selector": "mobileNavigationPanel", isNarrow: true, links: links, variant: "primary", children: jsxs(MenuList, { header: t('My Sonic'), scrollable: false, children: [jsx(MenuListItem, { badge: jsx(AccountIcon, { isAuthenticated: isAuthenticated }), "data-authenticated": isAuthenticated ? true : false, "data-test-selector": "mobileNavigationAccountButton", href: PATHS.ACCOUNT, children: isAuthenticated ? t('My account') : t('Sign in or create account') }), jsx(MenuListItem, { badge: jsx(FavoriteIcon, {}), "data-test-selector": "mobileNavigationFavoritesButton", href: PATHS.FAVORITES, children: t('Favorites') }), jsx(MenuListItem, { badge: jsx(CartIcon, { count: cartCount }), "data-count": cartCount, "data-test-selector": "mobileNavigationCartButton", href: PATHS.CART, children: t('Shopping cart') })] }) })] }));
23
23
  }
24
24
 
25
25
  export { MobileNavigation };
@@ -4,6 +4,7 @@ export interface PanelNavigationProps {
4
4
  allowBack?: boolean;
5
5
  children?: ReactNode;
6
6
  className?: string;
7
+ 'data-test-selector'?: string;
7
8
  header?: string | {
8
9
  href: string;
9
10
  title: string;
@@ -13,4 +14,4 @@ export interface PanelNavigationProps {
13
14
  links?: NavigationLink[];
14
15
  variant?: 'primary';
15
16
  }
16
- export declare function PanelNavigation({ allowBack, children, className, header, id, isNarrow, links, variant, }: PanelNavigationProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function PanelNavigation({ allowBack, children, className, 'data-test-selector': dataTestSelector, header, id, isNarrow, links, variant, }: PanelNavigationProps): import("react/jsx-runtime").JSX.Element;
@@ -37,9 +37,9 @@ const NavigationMenu = forwardRef(({ allowBack, back, children, className, heade
37
37
  setSelectedNavigationVisible(Boolean(selectedNavigationLink));
38
38
  }, [selectedNavigationLink]);
39
39
  const t = useFormattedMessage();
40
- return (jsxs(Fragment, { children: [jsxs("div", { ref: multiRef(ref, menuRef), className: clsx(styles['panel'], isNarrow && styles['narrow'], className), id: id, children: [jsx(MenuList, { back: back, header: header, scrollable: scrollable, variant: variant, children: links?.map(link => link.links && link.links.length > 0 ? (jsx(MenuListItem, { hasChildren: true, "aria-controls": `menu-${link.key}`, image: link.image, isSelected: selectedNavigationLink?.key === link.key, onClick: () => setSelectedNavigationLink(selectedNavigationLink?.key === link.key
40
+ return (jsxs(Fragment, { children: [jsxs("div", { ref: multiRef(ref, menuRef), className: clsx(styles['panel'], isNarrow && styles['narrow'], className), "data-test-selector": "panelNavigation", id: id, children: [jsx(MenuList, { back: back, header: header, scrollable: scrollable, variant: variant, children: links?.map(link => link.links && link.links.length > 0 ? (jsx(MenuListItem, { hasChildren: true, "aria-controls": `menu-${link.key}`, "data-test-selector": "panelNavigationItem", image: link.image, isSelected: selectedNavigationLink?.key === link.key, onClick: () => setSelectedNavigationLink(selectedNavigationLink?.key === link.key
41
41
  ? undefined
42
- : link), children: link.title }, link.key)) : (jsx(MenuListItem, { href: link.url, image: link.image, openInNewTab: link.openInNewTab, children: link.title }, link.key))) }), children] }), jsx(CascadingComponent, { isVisible: selectedNavigationVisible, nodeRef: submenuRef, onEntered: onFocus(submenuRef), onExited: onFocus(menuRef), onUnmounted: onUnmounted, children: jsx(NavigationMenu, { ref: submenuRef, allowBack: allowBack, back: allowBack
42
+ : link), children: link.title }, link.key)) : (jsx(MenuListItem, { "data-test-selector": "panelNavigationItem", href: link.url, image: link.image, openInNewTab: link.openInNewTab, children: link.title }, link.key))) }), children] }), jsx(CascadingComponent, { isVisible: selectedNavigationVisible, nodeRef: submenuRef, onEntered: onFocus(submenuRef), onExited: onFocus(menuRef), onUnmounted: onUnmounted, children: jsx(NavigationMenu, { ref: submenuRef, allowBack: allowBack, back: allowBack
43
43
  ? {
44
44
  onClick: () => {
45
45
  setSelectedNavigationVisible(false);
@@ -62,8 +62,8 @@ const NavigationMenu = forwardRef(({ allowBack, back, children, className, heade
62
62
  : [] }, selectedNavigationLink?.key) })] }));
63
63
  });
64
64
  NavigationMenu.displayName = 'NavigationMenu';
65
- function PanelNavigation({ allowBack, children, className, header, id, isNarrow, links, variant, }) {
66
- return (jsx("section", { className: clsx(styles['panel-navigation'], className), id: id, children: jsx(CascadingComponentContainer, { children: jsx("div", { className: clsx(styles['panels'], isNarrow && styles['narrow']), children: jsx(NavigationMenu, { allowBack: allowBack, className: children ? styles['top-panel'] : undefined, header: header, id: "panel-navigation-first-level", isNarrow: isNarrow, links: links, scrollable: children ? false : undefined, variant: variant, children: children }) }) }) }));
65
+ function PanelNavigation({ allowBack, children, className, 'data-test-selector': dataTestSelector, header, id, isNarrow, links, variant, }) {
66
+ return (jsx("section", { className: clsx(styles['panel-navigation'], className), "data-test-selector": dataTestSelector, id: id, children: jsx(CascadingComponentContainer, { children: jsx("div", { className: clsx(styles['panels'], isNarrow && styles['narrow']), children: jsx(NavigationMenu, { allowBack: allowBack, className: children ? styles['top-panel'] : undefined, header: header, id: "panel-navigation-first-level", isNarrow: isNarrow, links: links, scrollable: children ? false : undefined, variant: variant, children: children }) }) }) }));
67
67
  }
68
68
 
69
69
  export { PanelNavigation };
@@ -1,4 +1,4 @@
1
- import { d as now, k as elementTransitionEnd } from '../shared/utils.js';
1
+ import { f as now, l as elementTransitionEnd } from '../shared/utils.js';
2
2
 
3
3
  function freeMode(_ref) {
4
4
  let {
@@ -1,5 +1,5 @@
1
1
  import { g as getDocument } from '../shared/ssr-window.esm.js';
2
- import { l as isObject, e as elementChildren } from '../shared/utils.js';
2
+ import { o as isObject, e as elementChildren } from '../shared/utils.js';
3
3
 
4
4
  function Thumb(_ref) {
5
5
  let {
@@ -1,5 +1,5 @@
1
1
  import { a as getWindow, g as getDocument } from './ssr-window.esm.js';
2
- import { w as extend, u as showWarning, e as elementChildren, n as nextTick, t as animateCSSModeScroll, j as getTranslate, q as elementNextAll, r as elementPrevAll, s as setCSSProperty, p as elementStyle, f as elementOuterSize, h as elementIndex, c as createElement, x as deleteProps, v as elementIsChildOf, d as now, a as elementParents } from './utils.js';
2
+ import { x as extend, v as showWarning, e as elementChildren, n as nextTick, u as animateCSSModeScroll, k as getTranslate, r as elementNextAll, t as elementPrevAll, a as setCSSProperty, q as elementStyle, h as elementOuterSize, i as elementIndex, c as createElement, y as deleteProps, w as elementIsChildOf, f as now, b as elementParents } from './utils.js';
3
3
 
4
4
  let support;
5
5
  function calcSupport() {
@@ -1310,11 +1310,9 @@ function transitionEmit(_ref) {
1310
1310
  if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset';
1311
1311
  }
1312
1312
  swiper.emit(`transition${step}`);
1313
- if (runCallbacks && activeIndex !== previousIndex) {
1314
- if (dir === 'reset') {
1315
- swiper.emit(`slideResetTransition${step}`);
1316
- return;
1317
- }
1313
+ if (runCallbacks && dir === 'reset') {
1314
+ swiper.emit(`slideResetTransition${step}`);
1315
+ } else if (runCallbacks && activeIndex !== previousIndex) {
1318
1316
  swiper.emit(`slideChangeTransition${step}`);
1319
1317
  if (dir === 'next') {
1320
1318
  swiper.emit(`slideNextTransition${step}`);
@@ -1810,7 +1808,7 @@ var slide = {
1810
1808
  slideToClickedSlide
1811
1809
  };
1812
1810
 
1813
- function loopCreate(slideRealIndex) {
1811
+ function loopCreate(slideRealIndex, initial) {
1814
1812
  const swiper = this;
1815
1813
  const {
1816
1814
  params,
@@ -1858,7 +1856,8 @@ function loopCreate(slideRealIndex) {
1858
1856
  }
1859
1857
  swiper.loopFix({
1860
1858
  slideRealIndex,
1861
- direction: params.centeredSlides ? undefined : 'next'
1859
+ direction: params.centeredSlides ? undefined : 'next',
1860
+ initial
1862
1861
  });
1863
1862
  }
1864
1863
 
@@ -1869,6 +1868,7 @@ function loopFix(_temp) {
1869
1868
  direction,
1870
1869
  setTranslate,
1871
1870
  activeSlideIndex,
1871
+ initial,
1872
1872
  byController,
1873
1873
  byMousewheel
1874
1874
  } = _temp === void 0 ? {} : _temp;
@@ -1883,7 +1883,8 @@ function loopFix(_temp) {
1883
1883
  params
1884
1884
  } = swiper;
1885
1885
  const {
1886
- centeredSlides
1886
+ centeredSlides,
1887
+ initialSlide
1887
1888
  } = params;
1888
1889
  swiper.allowSlidePrev = true;
1889
1890
  swiper.allowSlideNext = true;
@@ -1919,14 +1920,16 @@ function loopFix(_temp) {
1919
1920
  loopedSlides += params.loopAdditionalSlides;
1920
1921
  swiper.loopedSlides = loopedSlides;
1921
1922
  const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
1922
- if (slides.length < slidesPerView + loopedSlides) {
1923
- showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled and not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
1923
+ if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
1924
+ showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
1924
1925
  } else if (gridEnabled && params.grid.fill === 'row') {
1925
1926
  showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
1926
1927
  }
1927
1928
  const prependSlidesIndexes = [];
1928
1929
  const appendSlidesIndexes = [];
1929
- let activeIndex = swiper.activeIndex;
1930
+ const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length;
1931
+ const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !centeredSlides;
1932
+ let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex;
1930
1933
  if (typeof activeSlideIndex === 'undefined') {
1931
1934
  activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
1932
1935
  } else {
@@ -1936,7 +1939,6 @@ function loopFix(_temp) {
1936
1939
  const isPrev = direction === 'prev' || !direction;
1937
1940
  let slidesPrepended = 0;
1938
1941
  let slidesAppended = 0;
1939
- const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length;
1940
1942
  const activeColIndex = gridEnabled ? slides[activeSlideIndex].column : activeSlideIndex;
1941
1943
  const activeColIndexWithShift = activeColIndex + (centeredSlides && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0);
1942
1944
  // prepend last slides before start
@@ -1958,6 +1960,9 @@ function loopFix(_temp) {
1958
1960
  }
1959
1961
  } else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) {
1960
1962
  slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup);
1963
+ if (isInitialOverflow) {
1964
+ slidesAppended = Math.max(slidesAppended, slidesPerView - cols + initialSlide + 1);
1965
+ }
1961
1966
  for (let i = 0; i < slidesAppended; i += 1) {
1962
1967
  const index = i - Math.floor(i / cols) * cols;
1963
1968
  if (gridEnabled) {
@@ -1973,6 +1978,14 @@ function loopFix(_temp) {
1973
1978
  requestAnimationFrame(() => {
1974
1979
  swiper.__preventObserver__ = false;
1975
1980
  });
1981
+ if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
1982
+ if (appendSlidesIndexes.includes(activeSlideIndex)) {
1983
+ appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1);
1984
+ }
1985
+ if (prependSlidesIndexes.includes(activeSlideIndex)) {
1986
+ prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1);
1987
+ }
1988
+ }
1976
1989
  if (isPrev) {
1977
1990
  prependSlidesIndexes.forEach(index => {
1978
1991
  slides[index].swiperLoopMoveDOM = true;
@@ -2329,7 +2342,9 @@ function onTouchMove(event) {
2329
2342
  data.isMoved = false;
2330
2343
  return;
2331
2344
  }
2332
- } else if (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate()) {
2345
+ } else if (rtl && (pageX > touches.startX && -swiper.translate <= swiper.maxTranslate() || pageX < touches.startX && -swiper.translate >= swiper.minTranslate())) {
2346
+ return;
2347
+ } else if (!rtl && (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate())) {
2333
2348
  return;
2334
2349
  }
2335
2350
  }
@@ -3794,7 +3809,7 @@ class Swiper {
3794
3809
 
3795
3810
  // Create loop
3796
3811
  if (swiper.params.loop) {
3797
- swiper.loopCreate();
3812
+ swiper.loopCreate(undefined, true);
3798
3813
  }
3799
3814
 
3800
3815
  // Attach events
@@ -122,6 +122,7 @@ const updateOnVirtualData = swiper => {
122
122
  swiper.updateSlides();
123
123
  swiper.updateProgress();
124
124
  swiper.updateSlidesClasses();
125
+ swiper.emit('_virtualUpdated');
125
126
  if (swiper.parallax && swiper.params.parallax && swiper.params.parallax.enabled) {
126
127
  swiper.parallax.setTranslate();
127
128
  }
@@ -1,3 +1,5 @@
1
+ import { s as setInnerHTML } from './utils.js';
2
+
1
3
  /* underscore in name -> watch for changes */
2
4
  const paramsList = ['eventsPrefix', 'injectStyles', 'injectStylesUrls', 'modules', 'init', '_direction', 'oneWayMovement', 'swiperElementNodeName', 'touchEventsTarget', 'initialSlide', '_speed', 'cssMode', 'updateOnWindowResize', 'resizeObserver', 'nested', 'focusableElements', '_enabled', '_width', '_height', 'preventInteractionOnTransition', 'userAgent', 'url', '_edgeSwipeDetection', '_edgeSwipeThreshold', '_freeMode', '_autoHeight', 'setWrapperSize', 'virtualTranslate', '_effect', 'breakpoints', 'breakpointsBase', '_spaceBetween', '_slidesPerView', 'maxBackfaceHiddenSlides', '_grid', '_slidesPerGroup', '_slidesPerGroupSkip', '_slidesPerGroupAuto', '_centeredSlides', '_centeredSlidesBounds', '_slidesOffsetBefore', '_slidesOffsetAfter', 'normalizeSlideIndex', '_centerInsufficientSlides', '_watchOverflow', 'roundLengths', 'touchRatio', 'touchAngle', 'simulateTouch', '_shortSwipes', '_longSwipes', 'longSwipesRatio', 'longSwipesMs', '_followFinger', 'allowTouchMove', '_threshold', 'touchMoveStopPropagation', 'touchStartPreventDefault', 'touchStartForcePreventDefault', 'touchReleaseOnEdges', 'uniqueNavElements', '_resistance', '_resistanceRatio', '_watchSlidesProgress', '_grabCursor', 'preventClicks', 'preventClicksPropagation', '_slideToClickedSlide', '_loop', 'loopAdditionalSlides', 'loopAddBlankSlides', 'loopPreventsSliding', '_rewind', '_allowSlidePrev', '_allowSlideNext', '_swipeHandler', '_noSwiping', 'noSwipingClass', 'noSwipingSelector', 'passiveListeners', 'containerModifierClass', 'slideClass', 'slideActiveClass', 'slideVisibleClass', 'slideFullyVisibleClass', 'slideNextClass', 'slidePrevClass', 'slideBlankClass', 'wrapperClass', 'lazyPreloaderClass', 'lazyPreloadPrevNext', 'runCallbacksOnInit', 'observer', 'observeParents', 'observeSlideChildren',
3
5
  // modules
@@ -192,14 +194,14 @@ function updateSwiper(_ref) {
192
194
  if (!nextEl || typeof nextEl === 'string') {
193
195
  nextEl = document.createElement('div');
194
196
  nextEl.classList.add('swiper-button-next');
195
- nextEl.innerHTML = swiper.hostEl.constructor.nextButtonSvg;
197
+ setInnerHTML(nextEl, swiper.hostEl.constructor.nextButtonSvg);
196
198
  nextEl.part.add('button-next');
197
199
  swiper.el.appendChild(nextEl);
198
200
  }
199
201
  if (!prevEl || typeof prevEl === 'string') {
200
202
  prevEl = document.createElement('div');
201
203
  prevEl.classList.add('swiper-button-prev');
202
- prevEl.innerHTML = swiper.hostEl.constructor.prevButtonSvg;
204
+ setInnerHTML(prevEl, swiper.hostEl.constructor.prevButtonSvg);
203
205
  prevEl.part.add('button-prev');
204
206
  swiper.el.appendChild(prevEl);
205
207
  }
@@ -299,5 +299,17 @@ function elementOuterSize(el, size, includeMargins) {
299
299
  function makeElementsArray(el) {
300
300
  return (Array.isArray(el) ? el : [el]).filter(e => !!e);
301
301
  }
302
+ function setInnerHTML(el, html) {
303
+ if (html === void 0) {
304
+ html = '';
305
+ }
306
+ if (typeof trustedTypes !== 'undefined') {
307
+ el.innerHTML = trustedTypes.createPolicy('html', {
308
+ createHTML: s => s
309
+ }).createHTML(html);
310
+ } else {
311
+ el.innerHTML = html;
312
+ }
313
+ }
302
314
 
303
- export { elementParents as a, createElement as c, now as d, elementChildren as e, elementOuterSize as f, elementIndex as h, classesToTokens as i, getTranslate as j, elementTransitionEnd as k, isObject as l, makeElementsArray as m, nextTick as n, elementStyle as p, elementNextAll as q, elementPrevAll as r, setCSSProperty as s, animateCSSModeScroll as t, showWarning as u, elementIsChildOf as v, extend as w, deleteProps as x };
315
+ export { setCSSProperty as a, elementParents as b, createElement as c, elementChildren as e, now as f, elementOuterSize as h, elementIndex as i, classesToTokens as j, getTranslate as k, elementTransitionEnd as l, makeElementsArray as m, nextTick as n, isObject as o, elementStyle as q, elementNextAll as r, setInnerHTML as s, elementPrevAll as t, animateCSSModeScroll as u, showWarning as v, elementIsChildOf as w, extend as x, deleteProps as y };
@@ -4,7 +4,7 @@ import { g as getParams, m as mountSwiper, a as getChangedParams, u as updateOnV
4
4
  import { d as uniqueClasses, w as wrapperClass, n as needsNavigation, b as needsScrollbar, a as needsPagination, e as extend, u as updateSwiper } from './shared/update-swiper.js';
5
5
 
6
6
  /**
7
- * Swiper React 11.2.5
7
+ * Swiper React 11.2.8
8
8
  * Most modern mobile touch slider and framework with hardware accelerated transitions
9
9
  * https://swiperjs.com
10
10
  *
@@ -12,7 +12,7 @@ import { d as uniqueClasses, w as wrapperClass, n as needsNavigation, b as needs
12
12
  *
13
13
  * Released under the MIT License
14
14
  *
15
- * Released on: March 3, 2025
15
+ * Released on: May 23, 2025
16
16
  */
17
17
 
18
18
 
@@ -15,7 +15,7 @@ function AnnouncementList({ announcements, className, onDismiss, sticky, }) {
15
15
  const height = Math.floor(size.height);
16
16
  document?.documentElement.style.setProperty('--announcements-height', `${height}px`);
17
17
  });
18
- return (jsx("section", { ref: announcementRef, className: clsx(styles['announcement-list'], sticky && styles['sticky'], className), children: jsx(TransitionGroup, { className: styles['list'], role: "list", children: filteredAnnouncements.map(announcement => (jsx(CSSTransition, { classNames: {
18
+ return (jsx("section", { ref: announcementRef, className: clsx(styles['announcement-list'], sticky && styles['sticky'], className), "data-test-selector": "announcementList", children: jsx(TransitionGroup, { className: styles['list'], role: "list", children: filteredAnnouncements.map(announcement => (jsx(CSSTransition, { classNames: {
19
19
  enter: styles['enter'],
20
20
  enterActive: styles['enter-active'],
21
21
  exit: styles['exit'],
@@ -26,8 +26,8 @@ const iconMap = {
26
26
  sales: jsx(SolidSaleIcon, {}),
27
27
  };
28
28
  const Announcement = forwardRef(({ announcement: { href, id, subType, text, title, type }, className, onDismiss, }, ref) => {
29
- return (jsx("div", { ref: multiRef(ref), className: clsx(styles.announcement, styles[type], styles[subType], className), role: "listitem", children: jsxs("div", { className: styles.wrapper, children: [jsx("div", { className: styles.icon, role: "presentation", children: iconMap[subType] }), jsxs("div", { className: styles.content, children: [jsx("h2", { className: styles.title, children: title }), text &&
30
- (href ? (jsxs(Link, { className: styles.link, href: href, children: [text, jsx(GlyphsArrowSemiBoldRightIcon, {})] })) : (jsx("p", { className: styles.text, children: text })))] }), jsx(IconButton, { className: styles.close, color: "current-color", onClick: () => onDismiss?.(id), children: jsx(StrokeCloseboxIcon, {}) })] }) }));
29
+ return (jsx("div", { ref: multiRef(ref), className: clsx(styles.announcement, styles[type], styles[subType], className), "data-id": id, "data-sub-type": subType, "data-test-selector": "announcement", "data-type": type, role: "listitem", children: jsxs("div", { className: styles.wrapper, children: [jsx("div", { className: styles.icon, role: "presentation", children: iconMap[subType] }), jsxs("div", { className: styles.content, children: [jsx("h2", { className: styles.title, "data-test-selector": "announcementTitle", children: title }), text &&
30
+ (href ? (jsxs(Link, { className: styles.link, "data-test-selector": "announcementLink", href: href, children: [text, jsx(GlyphsArrowSemiBoldRightIcon, {})] })) : (jsx("p", { className: styles.text, children: text })))] }), jsx(IconButton, { className: styles.close, color: "current-color", "data-test-selector": "announcementCloseButton", onClick: () => onDismiss?.(id), children: jsx(StrokeCloseboxIcon, {}) })] }) }));
31
31
  });
32
32
  Announcement.displayName = 'Announcement';
33
33
 
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef } from 'react';
2
3
  import qs from 'query-string';
3
4
 
@@ -5,4 +5,4 @@ export interface UseFetchCartByIdArgs<T> {
5
5
  id: string;
6
6
  select?: (data: CartModel) => T;
7
7
  }
8
- export declare function useFetchCartById<T = CartModel>({ enabled, forceRecalculation, id, select, }: UseFetchCartByIdArgs<T>): import("@tanstack/react-query").UseQueryResult<T, Error>;
8
+ export declare function useFetchCartById<T = CartModel>({ enabled, forceRecalculation, id, select, }: UseFetchCartByIdArgs<T>): import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<T>, Error>;
@@ -1,3 +1,3 @@
1
1
  import { CartModel } from '../../model/storefront.model';
2
2
  import { UseFetchCartByIdArgs } from './use-fetch-cart-by-id';
3
- export declare function useFetchCurrentCart<T = CartModel>(args?: Omit<UseFetchCartByIdArgs<T>, 'id'>): import("@tanstack/react-query").UseQueryResult<T, Error>;
3
+ export declare function useFetchCurrentCart<T = CartModel>(args?: Omit<UseFetchCartByIdArgs<T>, 'id'>): import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<T>, Error>;
@@ -2,4 +2,4 @@ import { Country } from '../../model/storefront.model';
2
2
  export declare function useFetchCountriesWithLanguages<TReturnType = Country[]>({ enabled, select, }?: {
3
3
  enabled?: boolean;
4
4
  select?: (data: Country[]) => TReturnType;
5
- }): import("@tanstack/react-query").UseQueryResult<TReturnType, Error>;
5
+ }): import("@tanstack/react-query").UseQueryResult<import("@tanstack/react-query").NoInfer<TReturnType>, Error>;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useCallback } from 'react';
2
3
 
3
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useEffect } from 'react';
2
3
 
3
4
  function useEnableMobileZoom({ isEnabled }) {
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useState, useRef, useEffect } from 'react';
2
3
 
3
4
  function useIntersectionObserver({ isDisabled, observables, onIntersectingChange, }) {
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useEffect } from 'react';
2
3
 
3
4
  function useMutationObserver(onChange, options) {
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useEffect } from 'react';
2
3
 
3
4
  function useResizeObserver(resizeCallback) {
@@ -6,6 +6,7 @@ export interface RouteContext {
6
6
  }
7
7
  export interface RouteLinkElementProps extends React.HTMLProps<HTMLAnchorElement> {
8
8
  href: string;
9
+ onNavigate: () => void;
9
10
  route?: NavigateOptions;
10
11
  }
11
12
  export interface NavigateOptions {
@@ -0,0 +1,8 @@
1
+ import { NavigateOptions } from './types';
2
+ export declare function useRouteLink(): {
3
+ RouteLinkElement: React.ElementType<import("./types").RouteLinkElementProps> | undefined;
4
+ getRouteLinkProps: (href: string, route?: NavigateOptions) => {
5
+ href: string;
6
+ onNavigate: () => void;
7
+ };
8
+ };
@@ -0,0 +1,24 @@
1
+ import { useCallback } from 'react';
2
+ import { buildHref } from './route-utils.js';
3
+ import { useBasePath } from './use-base-path.js';
4
+ import { useOnNavigate } from './use-on-navigate.js';
5
+ import { useRouteLinkElement } from './use-route-link-element.js';
6
+
7
+ function useRouteLink() {
8
+ const basePath = useBasePath();
9
+ const RouteLinkElement = useRouteLinkElement();
10
+ const triggerCallbacks = useOnNavigate();
11
+ const getRouteLinkProps = useCallback((href, route) => {
12
+ href = buildHref({ basePath, href });
13
+ return {
14
+ href,
15
+ onNavigate: () => triggerCallbacks(href, route),
16
+ };
17
+ }, [basePath, triggerCallbacks]);
18
+ return {
19
+ RouteLinkElement,
20
+ getRouteLinkProps,
21
+ };
22
+ }
23
+
24
+ export { useRouteLink };
package/dist/styles.css CHANGED
@@ -3379,7 +3379,7 @@ html {
3379
3379
  }
3380
3380
 
3381
3381
  /**
3382
- * Swiper 11.2.5
3382
+ * Swiper 11.2.8
3383
3383
  * Most modern mobile touch slider and framework with hardware accelerated transitions
3384
3384
  * https://swiperjs.com
3385
3385
  *
@@ -3387,7 +3387,7 @@ html {
3387
3387
  *
3388
3388
  * Released under the MIT License
3389
3389
  *
3390
- * Released on: March 3, 2025
3390
+ * Released on: May 23, 2025
3391
3391
  */
3392
3392
 
3393
3393
  /* FONT_START */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonic-equipment/ui",
3
- "version": "170.0.0",
3
+ "version": "171.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -52,59 +52,59 @@
52
52
  "devDependencies": {
53
53
  "@chromatic-com/storybook": "^3.2.6",
54
54
  "@csstools/postcss-global-data": "3.0.0",
55
- "@eslint-react/eslint-plugin": "^1.35.0",
55
+ "@eslint-react/eslint-plugin": "^1.50.0",
56
56
  "@rollup/plugin-alias": "5.1.1",
57
57
  "@rollup/plugin-commonjs": "28.0.3",
58
58
  "@rollup/plugin-node-resolve": "16.0.1",
59
59
  "@rollup/plugin-replace": "6.0.2",
60
60
  "@rollup/plugin-typescript": "12.1.2",
61
- "@storybook/addon-docs": "^8.6.7",
62
- "@storybook/addon-essentials": "^8.6.7",
63
- "@storybook/addon-interactions": "^8.6.7",
64
- "@storybook/addon-links": "^8.6.7",
65
- "@storybook/addon-viewport": "^8.6.7",
66
- "@storybook/blocks": "^8.6.7",
67
- "@storybook/preview-api": "^8.6.7",
68
- "@storybook/react": "^8.6.7",
69
- "@storybook/react-vite": "^8.6.7",
70
- "@storybook/test": "^8.6.7",
61
+ "@storybook/addon-docs": "^8.6.14",
62
+ "@storybook/addon-essentials": "^8.6.14",
63
+ "@storybook/addon-interactions": "^8.6.14",
64
+ "@storybook/addon-links": "^8.6.14",
65
+ "@storybook/addon-viewport": "^8.6.14",
66
+ "@storybook/blocks": "^8.6.14",
67
+ "@storybook/preview-api": "^8.6.14",
68
+ "@storybook/react": "^8.6.14",
69
+ "@storybook/react-vite": "^8.6.14",
70
+ "@storybook/test": "^8.6.14",
71
71
  "@total-typescript/ts-reset": "^0.6.1",
72
72
  "@types/js-cookie": "3.0.6",
73
- "@types/node": "22.13.10",
73
+ "@types/node": "22.15.23",
74
74
  "@types/postcss-import": "14.0.3",
75
75
  "@types/react": "18.3.12",
76
76
  "@types/react-dom": "18.3.1",
77
- "@typescript-eslint/eslint-plugin": "8.26.1",
78
- "@typescript-eslint/parser": "8.26.1",
77
+ "@typescript-eslint/eslint-plugin": "8.33.0",
78
+ "@typescript-eslint/parser": "8.33.0",
79
79
  "@typescript/lib-dom": "npm:typescript-partial-lib-dom@^1.1.0",
80
- "@vitejs/plugin-react": "4.3.4",
80
+ "@vitejs/plugin-react": "4.5.0",
81
81
  "autoprefixer": "10.4.21",
82
82
  "concurrently": "9.1.2",
83
83
  "eslint": "8.57.0",
84
- "eslint-config-prettier": "10.1.1",
85
- "eslint-import-resolver-typescript": "3.9.1",
84
+ "eslint-config-prettier": "10.1.5",
85
+ "eslint-import-resolver-typescript": "3.10.1",
86
86
  "eslint-plugin-css-modules": "^2.12.0",
87
- "eslint-plugin-formatjs": "^5.2.14",
87
+ "eslint-plugin-formatjs": "^5.3.1",
88
88
  "eslint-plugin-import": "2.31.0",
89
89
  "eslint-plugin-jsx-a11y": "^6.10.2",
90
- "eslint-plugin-mdx": "3.2.0",
91
- "eslint-plugin-prettier": "5.2.3",
92
- "eslint-plugin-react": "7.37.4",
90
+ "eslint-plugin-mdx": "3.4.2",
91
+ "eslint-plugin-prettier": "5.4.0",
92
+ "eslint-plugin-react": "7.37.5",
93
93
  "eslint-plugin-react-hooks": "5.2.0",
94
94
  "eslint-plugin-simple-import-sort": "12.1.1",
95
95
  "eslint-plugin-sort-destructure-keys": "2.0.0",
96
96
  "eslint-plugin-sort-keys-fix": "1.1.2",
97
97
  "eslint-plugin-ssr-friendly": "^1.3.0",
98
- "eslint-plugin-storybook": "^0.11.6",
98
+ "eslint-plugin-storybook": "^0.12.0",
99
99
  "eslint-plugin-typescript-sort-keys": "3.3.0",
100
100
  "eslint-plugin-unicorn": "^56.0.1",
101
101
  "eslint-plugin-unused-imports": "4.1.4",
102
102
  "http-server": "14.1.1",
103
103
  "husky": "9.1.7",
104
- "instantsearch.js": "4.78.0",
105
- "nodemon": "3.1.9",
104
+ "instantsearch.js": "4.78.3",
105
+ "nodemon": "3.1.10",
106
106
  "postcss": "8.5.3",
107
- "postcss-custom-media": "11.0.5",
107
+ "postcss-custom-media": "11.0.6",
108
108
  "postcss-import": "16.1.0",
109
109
  "postcss-nested": "7.0.2",
110
110
  "prettier": "3.5.3",
@@ -112,44 +112,44 @@
112
112
  "react-dom": "18.3.1",
113
113
  "react-json-view": "1.21.3",
114
114
  "rimraf": "6.0.1",
115
- "rollup": "4.36.0",
115
+ "rollup": "4.41.1",
116
116
  "rollup-plugin-peer-deps-external": "2.2.4",
117
117
  "rollup-plugin-postcss": "4.0.2",
118
118
  "rollup-plugin-preserve-directives": "^0.4.0",
119
- "storybook": "^8.6.7",
120
- "stylelint": "16.16.0",
119
+ "storybook": "^8.6.14",
120
+ "stylelint": "16.19.1",
121
121
  "stylelint-config-css-modules": "4.4.0",
122
122
  "stylelint-config-idiomatic-order": "10.0.0",
123
123
  "stylelint-config-standard": "37.0.0",
124
- "typescript": "5.8.2",
125
- "typescript-eslint": "^8.26.1",
126
- "vite": "6.2.2",
124
+ "typescript": "5.8.3",
125
+ "typescript-eslint": "^8.33.0",
126
+ "vite": "6.3.5",
127
127
  "vite-tsconfig-paths": "5.1.4",
128
- "vitest": "3.0.9"
128
+ "vitest": "3.1.4"
129
129
  },
130
130
  "dependencies": {
131
131
  "@adyen/adyen-web": "5.32.0",
132
- "@algolia/autocomplete-core": "1.18.1",
133
- "@algolia/autocomplete-plugin-query-suggestions": "1.18.1",
134
- "@algolia/autocomplete-plugin-recent-searches": "1.18.1",
135
- "@algolia/autocomplete-preset-algolia": "1.18.1",
132
+ "@algolia/autocomplete-core": "1.19.2",
133
+ "@algolia/autocomplete-plugin-query-suggestions": "1.19.2",
134
+ "@algolia/autocomplete-plugin-recent-searches": "1.19.2",
135
+ "@algolia/autocomplete-preset-algolia": "1.19.2",
136
136
  "@algolia/client-search": "4.24.0",
137
- "@tanstack/react-query": "5.69.0",
138
- "@tanstack/react-query-devtools": "5.69.0",
137
+ "@tanstack/react-query": "5.77.2",
138
+ "@tanstack/react-query-devtools": "5.77.2",
139
139
  "@types/react-transition-group": "4.4.12",
140
140
  "algoliasearch": "4.24.0",
141
141
  "clsx": "2.1.1",
142
142
  "fast-equals": "5.2.2",
143
- "instantsearch.js": "4.78.0",
143
+ "instantsearch.js": "4.78.3",
144
144
  "js-cookie": "3.0.5",
145
- "query-string": "9.1.1",
146
- "react-aria": "3.38.1",
147
- "react-aria-components": "1.7.1",
148
- "react-instantsearch": "7.15.4",
145
+ "query-string": "9.2.0",
146
+ "react-aria": "3.40.0",
147
+ "react-aria-components": "1.9.0",
148
+ "react-instantsearch": "7.15.8",
149
149
  "react-toastify": "10.0.6",
150
150
  "react-transition-group": "4.4.5",
151
151
  "search-insights": "2.17.3",
152
- "swiper": "11.2.5"
152
+ "swiper": "11.2.8"
153
153
  },
154
154
  "publishConfig": {
155
155
  "access": "public"