@sonic-equipment/ui 167.0.0 → 169.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 (151) hide show
  1. package/dist/algolia/algolia-sonic-searchclient.d.ts +2 -1
  2. package/dist/algolia/algolia-sonic-searchclient.js +2 -2
  3. package/dist/background-overlay/background-overlay-manager.js +6 -0
  4. package/dist/background-overlay/background-overlay.d.ts +1 -1
  5. package/dist/base.css +59 -1
  6. package/dist/buttons/link/link.d.ts +1 -1
  7. package/dist/buttons/link/link.js +6 -4
  8. package/dist/cart-totals/cart-totals.js +1 -0
  9. package/dist/collapsables/accordion/accordion-item.js +3 -2
  10. package/dist/collapsables/cascading-component/cascading-component-container-context.js +1 -0
  11. package/dist/collapsables/cascading-component/cascading-component-container-provider.js +1 -0
  12. package/dist/collapsables/cascading-component/cascading-component-container.js +1 -0
  13. package/dist/collapsables/cascading-component/cascading-component.js +1 -0
  14. package/dist/collapsables/unmounter/unmounter.js +1 -0
  15. package/dist/config.js +12 -11
  16. package/dist/country-select/country-select.js +1 -0
  17. package/dist/country-selector/connected-country-selector.d.ts +6 -6
  18. package/dist/display/price/price.js +1 -0
  19. package/dist/drawer/drawer.d.ts +3 -2
  20. package/dist/drawer/drawer.js +15 -3
  21. package/dist/drawer/drawer.module.css.js +1 -1
  22. package/dist/drawer/use-drawer.js +1 -6
  23. package/dist/exports.d.ts +15 -5
  24. package/dist/footer/connected-footer.d.ts +6 -0
  25. package/dist/footer/connected-footer.js +13 -0
  26. package/dist/footer/footer.d.ts +8 -4
  27. package/dist/footer/footer.js +23 -2
  28. package/dist/footer/footer.model.d.ts +3 -15
  29. package/dist/forms/form/form.js +1 -0
  30. package/dist/forms/text-field/password-reveal-toggle/password-reveal-toggle.js +1 -0
  31. package/dist/global-search/global-search-provider/global-search-provider.d.ts +0 -6
  32. package/dist/global-search/global-search-provider/global-search-provider.js +3 -9
  33. package/dist/global-search/global-search-provider/use-search-disclosure.d.ts +1 -6
  34. package/dist/global-search/global-search-provider/use-search-disclosure.js +5 -9
  35. package/dist/global-search/global-search.d.ts +3 -1
  36. package/dist/global-search/global-search.js +7 -6
  37. package/dist/header/buttons/account/connected-account-button.d.ts +7 -0
  38. package/dist/header/buttons/account/connected-account-button.js +14 -0
  39. package/dist/header/buttons/cart/connected-cart-button.d.ts +7 -0
  40. package/dist/header/buttons/cart/connected-cart-button.js +14 -0
  41. package/dist/header/buttons/favorites/connected-favorites-button.d.ts +7 -0
  42. package/dist/header/buttons/favorites/connected-favorites-button.js +13 -0
  43. package/dist/header/{hamburger-button → buttons/hamburger}/hamburger-button.d.ts +2 -1
  44. package/dist/header/buttons/hamburger/hamburger-button.js +13 -0
  45. package/dist/header/buttons/hamburger/hamburger-button.module.css.js +3 -0
  46. package/dist/header/buttons/search/search-button.d.ts +7 -0
  47. package/dist/header/buttons/search/search-button.js +12 -0
  48. package/dist/header/connected-header.d.ts +5 -0
  49. package/dist/header/connected-header.js +12 -0
  50. package/dist/header/drawers/desktop-navigation-drawer.d.ts +8 -0
  51. package/dist/header/drawers/desktop-navigation-drawer.js +12 -0
  52. package/dist/header/drawers/desktop-navigation-drawer.module.css.js +3 -0
  53. package/dist/header/drawers/mobile-navigation-drawer.d.ts +7 -0
  54. package/dist/header/drawers/mobile-navigation-drawer.js +10 -0
  55. package/dist/header/drawers/mobile-navigation-drawer.module.css.js +3 -0
  56. package/dist/header/drawers/search-drawer.d.ts +5 -0
  57. package/dist/header/drawers/search-drawer.js +9 -0
  58. package/dist/header/header-layout/header-layout.d.ts +2 -1
  59. package/dist/header/header-layout/header-layout.js +3 -2
  60. package/dist/header/header-layout/header-layout.module.css.js +1 -1
  61. package/dist/header/header.d.ts +4 -2
  62. package/dist/header/header.js +64 -5
  63. package/dist/header/header.module.css.js +3 -0
  64. package/dist/header/link-list/navigation-link-list.d.ts +3 -2
  65. package/dist/header/link-list/navigation-link-list.js +3 -3
  66. package/dist/header/link-list/navigation-link-list.module.css.js +1 -1
  67. package/dist/header/sonic-logo/sonic-logo.d.ts +2 -1
  68. package/dist/header/sonic-logo/sonic-logo.js +4 -2
  69. package/dist/index.js +17 -6
  70. package/dist/intl/missing-translation-provider.js +1 -0
  71. package/dist/intl/translation-id.d.ts +1 -1
  72. package/dist/lists/menu-list/menu-list-back-button.js +1 -0
  73. package/dist/lists/menu-list/menu-list-item.d.ts +9 -21
  74. package/dist/lists/menu-list/menu-list-item.js +3 -8
  75. package/dist/lists/menu-list/menu-list.js +1 -0
  76. package/dist/lists/orderline-list/orderline-list.js +2 -2
  77. package/dist/media/zoom-image/zoom-image.js +1 -0
  78. package/dist/navigation/account-icon/account-icon.js +1 -0
  79. package/dist/navigation/cart-icon/cart-icon.js +2 -1
  80. package/dist/navigation/favorite-icon/favorite-icon.js +1 -0
  81. package/dist/navigation/mobile-navigation/mobile-navigation.d.ts +6 -3
  82. package/dist/navigation/mobile-navigation/mobile-navigation.js +8 -3
  83. package/dist/navigation/mobile-navigation/mobile-navigation.module.css.js +3 -0
  84. package/dist/navigation/panel-navigation/panel-navigation.d.ts +4 -16
  85. package/dist/navigation/panel-navigation/panel-navigation.js +5 -5
  86. package/dist/notifications/announcements/announcement-list.d.ts +7 -0
  87. package/dist/notifications/announcements/announcement-list.js +26 -0
  88. package/dist/notifications/announcements/announcement-list.module.css.js +3 -0
  89. package/dist/notifications/announcements/announcement.d.ts +2 -1
  90. package/dist/notifications/announcements/announcement.js +7 -3
  91. package/dist/notifications/announcements/announcement.module.css.js +1 -1
  92. package/dist/notifications/announcements/connected-announcement-list.d.ts +3 -0
  93. package/dist/notifications/announcements/connected-announcement-list.js +22 -0
  94. package/dist/notifications/announcements/use-filter-announcements.d.ts +2 -0
  95. package/dist/notifications/announcements/use-filter-announcements.js +35 -0
  96. package/dist/observers/intersection-observer.js +1 -0
  97. package/dist/pages/account/create-account-page/create-account-page.js +1 -0
  98. package/dist/pages/account/layouts/sign-in-page-layout/sign-in-page-layout.js +1 -0
  99. package/dist/pages/account/sign-in-page/sign-in-page.js +1 -0
  100. package/dist/pages/checkout/cart-page/cart-page.js +2 -1
  101. package/dist/pages/checkout/cart-page/components/empty-cart-page.js +1 -0
  102. package/dist/pages/checkout/components/billing-and-invoice-information.js +1 -0
  103. package/dist/pages/checkout/layouts/checkout-page-layout/checkout-page-layout.js +2 -1
  104. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +1 -0
  105. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page.js +1 -0
  106. package/dist/pages/checkout/payment-page/components/adyen-payment.js +1 -0
  107. package/dist/pages/checkout/payment-page/components/payment.js +1 -0
  108. package/dist/pages/checkout/payment-page/payment-page-content.js +2 -1
  109. package/dist/pages/checkout/payment-page/payment-page.js +1 -0
  110. package/dist/pages/checkout/shipping-page/components/currency-change-dialog.js +1 -0
  111. package/dist/pages/checkout/shipping-page/components/edit-address-form.js +1 -0
  112. package/dist/pages/checkout/shipping-page/components/readonly-address.js +1 -0
  113. package/dist/pages/checkout/shipping-page/components/sonic-address.js +1 -0
  114. package/dist/pages/checkout/shipping-page/shipping-page-content.js +2 -1
  115. package/dist/pages/checkout/shipping-page/shipping-page.js +1 -0
  116. package/dist/pages/components/page-meta-data/page-meta-data.js +4 -0
  117. package/dist/pages/product/product-details-page/components/product-details-panel/product-details-panel.js +1 -0
  118. package/dist/shared/api/bff/hooks/use-fetch-navigation-links.d.ts +2 -0
  119. package/dist/shared/api/bff/hooks/use-fetch-navigation-links.js +15 -0
  120. package/dist/shared/api/bff/model/bff.model.d.ts +30 -0
  121. package/dist/shared/api/bff/services/bff-service.d.ts +7 -1
  122. package/dist/shared/api/bff/services/bff-service.js +8 -1
  123. package/dist/shared/feature-flags/use-feature-flags.d.ts +1 -0
  124. package/dist/shared/feature-flags/use-feature-flags.js +1 -0
  125. package/dist/shared/ga/data-layer.js +4 -3
  126. package/dist/shared/hooks/use-mutation-observer.d.ts +3 -0
  127. package/dist/shared/hooks/use-mutation-observer.js +27 -0
  128. package/dist/shared/hooks/use-resize-observer.js +7 -1
  129. package/dist/shared/hooks/use-watch-css-property.js +1 -1
  130. package/dist/shared/routing/route-button.d.ts +1 -1
  131. package/dist/shared/routing/route-icon-button.d.ts +1 -1
  132. package/dist/shared/routing/route-link.d.ts +1 -1
  133. package/dist/shared/routing/with-routing.d.ts +2 -2
  134. package/dist/shared/routing/with-routing.js +5 -4
  135. package/dist/shared/utils/css.js +53 -0
  136. package/dist/styles.css +696 -476
  137. package/dist/toast/toast-provider.js +1 -0
  138. package/dist/tooltip/tooltip.js +1 -0
  139. package/dist/typography/heading/heading.js +1 -0
  140. package/package.json +1 -1
  141. package/dist/header/cart-icon/connected-cart-icon.d.ts +0 -3
  142. package/dist/header/cart-icon/connected-cart-icon.js +0 -14
  143. package/dist/header/hamburger-button/hamburger-button.js +0 -14
  144. package/dist/header/hamburger-button/hamburger-button.module.css.js +0 -3
  145. package/dist/notifications/announcements/announcement-provider.d.ts +0 -1
  146. package/dist/notifications/announcements/announcement-provider.js +0 -29
  147. package/dist/notifications/announcements/announcement-provider.module.css.js +0 -3
  148. package/dist/notifications/announcements/connected-announcement.d.ts +0 -5
  149. package/dist/notifications/announcements/connected-announcement.js +0 -27
  150. package/dist/shared/api/bff/model/announcement.model.d.ts +0 -12
  151. package/dist/shared/model/link.d.ts +0 -15
@@ -1,5 +1,6 @@
1
- export declare const createSonicSearchClient: ({ apiKey, appId, host, }: {
1
+ export declare const createSonicSearchClient: ({ apiKey, appId, host, protocol, }: {
2
2
  apiKey: string;
3
3
  appId: string;
4
4
  host: string | undefined;
5
+ protocol?: string;
5
6
  }) => import("algoliasearch").SearchClient;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import algoliasearch from 'algoliasearch';
3
3
 
4
- const createSonicSearchClient = ({ apiKey, appId, host, }) => {
4
+ const createSonicSearchClient = ({ apiKey, appId, host, protocol = 'https', }) => {
5
5
  const searchClient = algoliasearch(appId, apiKey);
6
6
  if (!host) {
7
7
  return searchClient;
@@ -9,7 +9,7 @@ const createSonicSearchClient = ({ apiKey, appId, host, }) => {
9
9
  const read = searchClient.transporter.read;
10
10
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
11
  // @ts-ignore
12
- searchClient.transporter.hosts = [{ accept: 1, protocol: 'https', url: host }];
12
+ searchClient.transporter.hosts = [{ accept: 1, protocol, url: host }];
13
13
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
14
14
  // @ts-ignore
15
15
  searchClient.transporter.timeouts = { connect: 3000, read: 3000, write: 3000 };
@@ -45,6 +45,9 @@ class BackgroundOverlayManager {
45
45
  * @private
46
46
  */
47
47
  static _removeElement() {
48
+ if (document) {
49
+ document.documentElement.style.overflow = 'unset';
50
+ }
48
51
  BackgroundOverlayManager._element?.classList.remove('visible');
49
52
  }
50
53
  /**
@@ -93,6 +96,9 @@ class BackgroundOverlayManager {
93
96
  return this._removeElement();
94
97
  BackgroundOverlayManager._getElement().style.zIndex =
95
98
  String(currentOverlayZindex);
99
+ if (document) {
100
+ document.documentElement.style.overflow = 'hidden';
101
+ }
96
102
  BackgroundOverlayManager._getElement().classList.add('visible');
97
103
  }
98
104
  /**
@@ -1,5 +1,5 @@
1
1
  import './background-overlay.module.css';
2
- type Position = 'in-front' | 'behind-header';
2
+ type Position = 'in-front' | 'behind-header' | 'behind-announcement';
3
3
  interface BackgroundOverlayProps {
4
4
  /** Whether the overlay is open or not. */
5
5
  isOpen: boolean;
package/dist/base.css CHANGED
@@ -1,4 +1,62 @@
1
- @import url('./spire-styles.css');
1
+ /* Spire default CSS below that needs to be countered in components for the timebeing
2
+ This CSS can be removed when Spire is dropped. This CSS is not included within Spire context
3
+ and only serves as a simulation of Spire styling in Storybook.
4
+ shared/reset.module.css contains reset styles that overwrite this Spire CSS */
5
+
6
+ html {
7
+ height: 100%;
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ body {
12
+ height: 100%;
13
+ margin: 0;
14
+ background: #fff;
15
+ color: #000;
16
+ font-size: 16px;
17
+ font-weight: 400;
18
+ -webkit-hyphens: auto;
19
+ hyphens: auto;
20
+ line-height: 1.5;
21
+ }
22
+
23
+ * {
24
+ font-weight: normal;
25
+ }
26
+
27
+ span,
28
+ p,
29
+ h1,
30
+ h2,
31
+ h3,
32
+ h4,
33
+ h5,
34
+ h6 {
35
+ padding: 0;
36
+ margin: 0;
37
+ font-size: inherit;
38
+ font-weight: inherit;
39
+ }
40
+
41
+ button:focus {
42
+ outline: none !important;
43
+ outline-width: 0 !important;
44
+ }
45
+
46
+ a:focus {
47
+ outline: none !important;
48
+ outline-width: 0 !important;
49
+ }
50
+
51
+ input[type='number']::-webkit-outer-spin-button,
52
+ input[type='number']::-webkit-inner-spin-button {
53
+ opacity: 1;
54
+ }
55
+
56
+ input[type='password'] {
57
+ font-family: 'Verdana', sans-serif !important;
58
+ font-size: 20px !important;
59
+ }
2
60
 
3
61
  /*********************************************************
4
62
  *
@@ -14,4 +14,4 @@ export interface LinkProps {
14
14
  target?: string;
15
15
  title?: string;
16
16
  }
17
- export declare function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }: LinkProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLElement>>;
@@ -1,19 +1,21 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
+ import { forwardRef } from 'react';
3
4
  import clsx from 'clsx';
4
5
  import styles from './link.module.css.js';
5
6
 
6
- function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }) {
7
+ const Link = forwardRef(({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }, ref) => {
7
8
  if (href) {
8
- return (jsx("a", { className: clsx({
9
+ return (jsx("a", { ref: ref, className: clsx({
9
10
  [styles.hover]: Boolean(href || onClick),
10
11
  [styles['has-underline']]: hasUnderline,
11
12
  }, styles['link'], color && styles[color], className), "data-disabled": isDisabled ? true : undefined, href: href, id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, target: target, title: title, ...rest, children: children }));
12
13
  }
13
- return (jsx("button", { className: clsx({
14
+ return (jsx("button", { ref: ref, className: clsx({
14
15
  [styles.hover]: Boolean(href || onClick),
15
16
  [styles['has-underline']]: hasUnderline,
16
17
  }, styles['link'], color && styles[color], 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 }));
17
- }
18
+ });
19
+ Link.displayName = 'Link';
18
20
 
19
21
  export { Link };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsxs, jsx } from 'react/jsx-runtime';
2
3
  import { Price } from '../display/price/price.js';
3
4
  import { FormattedMessage } from '../intl/formatted-message.js';
@@ -21,11 +21,12 @@ function AccordionItem({ _pseudo = 'none', allowCollapse = true, allowToggle = t
21
21
  const panelId = `panel-${id}`;
22
22
  return (jsxs("div", { className: clsx(className, ...ensureArray(borderType).map(type => styles[`border-type-${type}`]), styles['accordion-item'], isDisabled && styles.disabled, {
23
23
  [styles['is-open']]: isOpen,
24
- [styles['allow-toggle']]: allowToggle,
24
+ [styles['allow-collapse']]: allowCollapse,
25
+ [styles['allow-toggle']]: allowCollapse && allowToggle,
25
26
  }), "data-test-selector": dataTestSelector, children: [jsx("h3", { children: allowCollapse ? (jsxs("button", { "aria-controls": panelId, "aria-expanded": isOpen, className: clsx(styles.button, styles[_pseudo]), disabled: isDisabled, id: id, onClick: () => {
26
27
  if (allowToggle)
27
28
  toggle();
28
- }, type: "button", children: [title, jsx("span", { className: styles.icon, children: size === 'lg' ? (jsx(GlyphsChevronsBoldDownIcon, {})) : (jsx(GlyphsChevronsSlimDownIcon, {})) })] })) : (jsx("span", { className: styles.button, children: title })) }), jsx("div", { "aria-labelledby": id, className: styles.panel, id: panelId, role: "region", children: jsx("div", { className: styles.content, children: children }) })] }));
29
+ }, tabIndex: allowToggle ? 0 : -1, type: "button", children: [title, jsx("span", { className: styles.icon, children: size === 'lg' ? (jsx(GlyphsChevronsBoldDownIcon, {})) : (jsx(GlyphsChevronsSlimDownIcon, {})) })] })) : (jsx("span", { className: styles.button, children: title })) }), jsx("div", { "aria-labelledby": id, className: styles.panel, id: panelId, role: "region", children: jsx("div", { className: styles.content, children: children }) })] }));
29
30
  }
30
31
 
31
32
  export { AccordionItem };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext } from 'react';
2
3
 
3
4
  const CascadingComponentContainerContext = createContext(null);
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { useState, useMemo, useEffect } from 'react';
3
4
  import { voidFunction } from '../../shared/model/defaults.js';
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { CascadingComponentContainerProvider } from './cascading-component-container-provider.js';
3
4
 
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx, Fragment } from 'react/jsx-runtime';
2
3
  import { useState, useEffect, useCallback } from 'react';
3
4
  import { CSSTransition } from 'react-transition-group';
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { createContext, useState, useEffect, useMemo, useContext } from 'react';
3
4
 
package/dist/config.js CHANGED
@@ -4,11 +4,6 @@ import main from './shared/utils/merge.js';
4
4
  const env = (typeof process === 'undefined'
5
5
  ? { VITE_SHOP_API_URL: ""}
6
6
  : main({ ...process.env }, { VITE_SHOP_API_URL: ""}));
7
- const validateEnvVariable = (name, value) => {
8
- if (value)
9
- return value;
10
- throw new Error(`${name} is not defined`);
11
- };
12
7
  const configPerEnvironment = {
13
8
  local: () => ({
14
9
  ALGOLIA_API_KEY: 'e0edf30798a6b2e4e44fd25f0f2f9646',
@@ -31,12 +26,18 @@ const configPerEnvironment = {
31
26
  env?.VITE_SHOP_API_URL || 'https://localhost:8000',
32
27
  }),
33
28
  next: () => ({
34
- ALGOLIA_API_KEY: validateEnvVariable('ALGOLIA_API_KEY', env.ALGOLIA_API_KEY),
35
- ALGOLIA_APP_ID: validateEnvVariable('ALGOLIA_APP_ID', env.ALGOLIA_APP_ID),
36
- ALGOLIA_HOST: validateEnvVariable('ALGOLIA_HOST', env.ALGOLIA_HOST),
37
- BFF_API_URL: validateEnvVariable('BFF_API_URL', env.BFF_API_URL),
38
- COOKIE_DOMAIN: validateEnvVariable('COOKIE_DOMAIN', env.COOKIE_DOMAIN),
39
- SHOP_API_URL: validateEnvVariable('SHOP_API_URL', env.SHOP_API_URL),
29
+ // @ts-expect-error: process is not defined in the browser
30
+ ALGOLIA_API_KEY: process.env.ALGOLIA_API_KEY || '',
31
+ // @ts-expect-error: process is not defined in the browser
32
+ ALGOLIA_APP_ID: process.env.ALGOLIA_APP_ID || '',
33
+ // @ts-expect-error: process is not defined in the browser
34
+ ALGOLIA_HOST: process.env.ALGOLIA_HOST || '',
35
+ // @ts-expect-error: process is not defined in the browser
36
+ BFF_API_URL: process.env.BFF_API_URL || '',
37
+ // @ts-expect-error: process is not defined in the browser
38
+ COOKIE_DOMAIN: process.env.COOKIE_DOMAIN || '',
39
+ // @ts-expect-error: process is not defined in the browser
40
+ SHOP_API_URL: process.env.SHOP_API_URL || '',
40
41
  }),
41
42
  production: () => ({
42
43
  ALGOLIA_API_KEY: 'e31a3a53449eceb4d0f9273b9bcd9759',
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { useMemo } from 'react';
3
4
  import { SelectField } from '../forms/select-field/select-field.js';
@@ -1,13 +1,13 @@
1
1
  import { CountryCode, LanguageCode } from '../intl/types';
2
2
  import { Country, Language } from '../shared/model/countries-languages';
3
- interface ConnectedCountrySelectorProps {
3
+ export type OnCountryLanguageChangeHandler = (args: {
4
+ country: Country;
5
+ language: Language;
6
+ }) => void;
7
+ export interface ConnectedCountrySelectorProps {
4
8
  defaultCountryCode: CountryCode;
5
9
  defaultLanguageCode: LanguageCode;
6
- onChange?: (args: {
7
- country: Country;
8
- language: Language;
9
- }) => void;
10
+ onChange?: OnCountryLanguageChangeHandler;
10
11
  showCountry?: boolean;
11
12
  }
12
13
  export declare function ConnectedCountrySelector({ defaultCountryCode, defaultLanguageCode, onChange, showCountry, }: ConnectedCountrySelectorProps): import("react/jsx-runtime").JSX.Element | null;
13
- export {};
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsxs, jsx } from 'react/jsx-runtime';
2
3
  import clsx from 'clsx';
3
4
  import { useFormattedMessage } from '../../intl/use-formatted-message.js';
@@ -18,9 +18,10 @@ export interface DrawerProps {
18
18
  isInitialOpen?: boolean;
19
19
  isOpen?: boolean;
20
20
  onClose?: VoidFunction;
21
+ onClosed?: VoidFunction;
21
22
  position: 'top' | 'bottom' | 'left' | 'right';
22
23
  showBackgroundOverlay?: boolean;
23
- showUnderHeader?: boolean;
24
+ showUnder?: 'header' | 'announcement';
24
25
  timeout?: number;
25
26
  }
26
- export declare function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, instanceId, isInitialOpen, isOpen: isOpenControlled, onClose, position, showBackgroundOverlay, showUnderHeader, timeout, }: DrawerProps): import("react/jsx-runtime").JSX.Element;
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;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
3
  import { useRef, useEffect } from 'react';
3
4
  import { CSSTransition } from 'react-transition-group';
@@ -7,7 +8,7 @@ import { createAddEndListener } from '../collapsables/unmounter/utils.js';
7
8
  import { useDrawer } from './use-drawer.js';
8
9
  import styles from './drawer.module.css.js';
9
10
 
10
- function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, instanceId, isInitialOpen = false, isOpen: isOpenControlled, onClose, position, showBackgroundOverlay, showUnderHeader = false, timeout, }) {
11
+ function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, instanceId, isInitialOpen = false, isOpen: isOpenControlled, onClose, onClosed, position, showBackgroundOverlay, showUnder, timeout, }) {
11
12
  const wasOpenRef = useRef(isInitialOpen);
12
13
  const asideRef = useRef(null);
13
14
  const useDrawerResult = useDrawer({
@@ -22,7 +23,14 @@ function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, ins
22
23
  onClose?.();
23
24
  wasOpenRef.current = isOpen;
24
25
  }, [instanceId, isOpen, onClose]);
25
- return (jsxs(Fragment, { children: [jsx(CSSTransition, { mountOnEnter: true, unmountOnExit: true, addEndListener: createAddEndListener(asideRef), in: isOpen, nodeRef: asideRef, timeout: timeout, children: jsx("aside", { ref: asideRef, className: clsx(styles.drawer, styles[position], showUnderHeader && styles['under-header'], className), children: children instanceof Function ? children(useDrawerResult) : children }, `${groupId}-${instanceId}`) }, groupId), showBackgroundOverlay && (jsx(BackgroundOverlay, { isOpen: isOpen, onClick: () => {
26
+ useEffect(() => {
27
+ return close;
28
+ }, [close]);
29
+ useEffect(() => {
30
+ return onClosed;
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
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: () => {
26
34
  if (!allowCloseOnBackgroundClick)
27
35
  return;
28
36
  if (isControlled) {
@@ -31,7 +39,11 @@ function Drawer({ allowCloseOnBackgroundClick, children, className, groupId, ins
31
39
  else {
32
40
  close();
33
41
  }
34
- }, position: showUnderHeader ? 'behind-header' : 'in-front' }))] }));
42
+ }, position: showUnder === 'header'
43
+ ? 'behind-header'
44
+ : showUnder === 'announcement'
45
+ ? 'behind-announcement'
46
+ : 'in-front' }))] }));
35
47
  }
36
48
 
37
49
  export { Drawer };
@@ -1,3 +1,3 @@
1
- var styles = {"drawer":"drawer-module-5ARuA","left":"drawer-module-yjFdX","right":"drawer-module-bZLBV","top":"drawer-module-KiviE","bottom":"drawer-module-p-PYu","under-header":"drawer-module-0jRBQ"};
1
+ var styles = {"drawer":"drawer-module-5ARuA","left":"drawer-module-yjFdX","right":"drawer-module-bZLBV","top":"drawer-module-KiviE","bottom":"drawer-module-p-PYu","under-announcement":"drawer-module-0ZHVw","under-header":"drawer-module-0jRBQ"};
2
2
 
3
3
  export { styles as default };
@@ -12,18 +12,13 @@ function useDrawer({ groupId: _groupId, instanceId: _instanceId, isInitialOpen,
12
12
  useEffect(() => {
13
13
  if (isInitialOpen || isOpen)
14
14
  setOpenInstanceId(instanceId);
15
- return () => {
16
- if (isOpen) {
17
- setOpenInstanceId(undefined);
18
- }
19
- };
20
15
  // eslint-disable-next-line react-hooks/exhaustive-deps
21
16
  }, []);
22
17
  useEffect(() => {
23
18
  if (isOpenControlled) {
24
19
  setOpenInstanceId(instanceId);
25
20
  }
26
- else if (openInstanceId === instanceId) {
21
+ else if (isOpenControlled === false && openInstanceId === instanceId) {
27
22
  setOpenInstanceId(undefined);
28
23
  }
29
24
  // eslint-disable-next-line react-hooks/exhaustive-deps
package/dist/exports.d.ts CHANGED
@@ -86,6 +86,7 @@ export * from './drawer/use-drawer';
86
86
  export * from './filters/active-filters/active-filters';
87
87
  export * from './filters/multi-select/multi-select';
88
88
  export * from './filters/pagination/pagination';
89
+ export * from './footer/connected-footer';
89
90
  export * from './footer/footer';
90
91
  export * from './forms/checkbox-field/checkbox-field';
91
92
  export * from './forms/checkbox/checkbox';
@@ -129,8 +130,15 @@ export * from './global-search/search-section/search-list';
129
130
  export * from './global-search/search-section/search-list-item';
130
131
  export * from './global-search/search-section/search-section';
131
132
  export * from './global-search/types';
132
- export * from './header/cart-icon/connected-cart-icon';
133
- export * from './header/hamburger-button/hamburger-button';
133
+ export * from './header/buttons/account/connected-account-button';
134
+ export * from './header/buttons/cart/connected-cart-button';
135
+ export * from './header/buttons/favorites/connected-favorites-button';
136
+ export * from './header/buttons/hamburger/hamburger-button';
137
+ export * from './header/buttons/search/search-button';
138
+ export * from './header/connected-header';
139
+ export * from './header/drawers/desktop-navigation-drawer';
140
+ export * from './header/drawers/mobile-navigation-drawer';
141
+ export * from './header/drawers/search-drawer';
134
142
  export * from './header/header';
135
143
  export * from './header/header-layout/header-layout';
136
144
  export * from './header/link-list/navigation-link-list';
@@ -181,8 +189,9 @@ export * from './navigation/favorite-icon/favorite-icon';
181
189
  export * from './navigation/mobile-navigation/mobile-navigation';
182
190
  export * from './navigation/panel-navigation/panel-navigation';
183
191
  export * from './notifications/announcements/announcement';
184
- export * from './notifications/announcements/announcement-provider';
185
- export * from './notifications/announcements/connected-announcement';
192
+ export * from './notifications/announcements/announcement-list';
193
+ export * from './notifications/announcements/connected-announcement-list';
194
+ export * from './notifications/announcements/use-filter-announcements';
186
195
  export * from './observers/intersection-observer';
187
196
  export * from './pages/account/components/create-account-form/create-account-form';
188
197
  export * from './pages/account/components/sign-in-form/sign-in-form';
@@ -242,6 +251,7 @@ export * from './promos/promo-banner/promo-banner';
242
251
  export * from './promos/promo-banners/promo-banners';
243
252
  export * from './promos/promo-card/promo-card';
244
253
  export * from './shared/api/bff/hooks/use-fetch-announcements';
254
+ export * from './shared/api/bff/hooks/use-fetch-navigation-links';
245
255
  export * from './shared/api/bff/hooks/use-fetch-product-details-page-data';
246
256
  export * from './shared/api/bff/hooks/use-fetch-product-listing-page-data';
247
257
  export * from './shared/api/bff/services/bff-service';
@@ -318,6 +328,7 @@ export * from './shared/hooks/use-global-disclosure';
318
328
  export * from './shared/hooks/use-intersection-observer';
319
329
  export * from './shared/hooks/use-is-breakpoint';
320
330
  export * from './shared/hooks/use-is-scrolled-beyond-element';
331
+ export * from './shared/hooks/use-mutation-observer';
321
332
  export * from './shared/hooks/use-resize-observer';
322
333
  export * from './shared/hooks/use-script';
323
334
  export * from './shared/hooks/use-scroll-lock';
@@ -333,7 +344,6 @@ export * from './shared/model/currency';
333
344
  export * from './shared/model/defaults';
334
345
  export * from './shared/model/hit';
335
346
  export * from './shared/model/image';
336
- export * from './shared/model/link';
337
347
  export * from './shared/model/price';
338
348
  export * from './shared/providers/cart-provider';
339
349
  export * from './shared/providers/favorite-provider';
@@ -0,0 +1,6 @@
1
+ import { OnCountryLanguageChangeHandler } from '../country-selector/connected-country-selector';
2
+ import { NavigationLinkSource } from '../shared/api/bff/services/bff-service';
3
+ export declare function ConnectedFooter({ onCountryLanguageChange, source, }: {
4
+ onCountryLanguageChange: OnCountryLanguageChangeHandler;
5
+ source: NavigationLinkSource;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { ConnectedCountrySelector } from '../country-selector/connected-country-selector.js';
3
+ import { useCultureCode } from '../intl/use-culture-code.js';
4
+ import { useFetchNavigationLinks } from '../shared/api/bff/hooks/use-fetch-navigation-links.js';
5
+ import { Footer } from './footer.js';
6
+
7
+ function ConnectedFooter({ onCountryLanguageChange, source, }) {
8
+ const cultureCode = useCultureCode();
9
+ const { data } = useFetchNavigationLinks({ cultureCode, source });
10
+ return (jsx(Footer, { bottomLinks: data?.footer.bottomLinks || [], copyright: data?.footer.copyright || '', countrySelector: jsx(ConnectedCountrySelector, { defaultCountryCode: "NL", defaultLanguageCode: "EN", onChange: onCountryLanguageChange }), linkBlocks: data?.footer.linkBlocks || [] }));
11
+ }
12
+
13
+ export { ConnectedFooter };
@@ -1,9 +1,13 @@
1
1
  import { ReactNode } from 'react';
2
- import { FooterLink, LinkBlock } from './footer.model';
3
- export interface FooterProps {
4
- bottomLinks: FooterLink[];
2
+ import { NavigationLink } from '../shared/api/bff/model/bff.model';
3
+ export interface FooterBottomSectionProps {
4
+ bottomLinks: NavigationLink[];
5
5
  copyright: string;
6
6
  countrySelector: ReactNode;
7
- linkBlocks: LinkBlock[];
7
+ }
8
+ export interface FooterLinkBlockProps {
9
+ linkBlocks: NavigationLink[];
10
+ }
11
+ export interface FooterProps extends FooterBottomSectionProps, FooterLinkBlockProps {
8
12
  }
9
13
  export declare function Footer({ bottomLinks, copyright, countrySelector, linkBlocks, }: FooterProps): import("react/jsx-runtime").JSX.Element;
@@ -2,13 +2,34 @@
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { Accordion } from '../collapsables/accordion/accordion.js';
4
4
  import { AccordionItem } from '../collapsables/accordion/accordion-item.js';
5
+ import { logger } from '../logging/logger.js';
5
6
  import { useIsBreakpoint } from '../shared/hooks/use-is-breakpoint.js';
6
7
  import { RouteLink } from '../shared/routing/route-link.js';
7
8
  import styles from './footer.module.css.js';
8
9
 
9
- function Footer({ bottomLinks, copyright, countrySelector, linkBlocks, }) {
10
+ function BottomSection({ bottomLinks, copyright, countrySelector, }) {
11
+ return (jsxs("div", { className: styles['bottom-section'], children: [copyright && jsx("p", { className: styles.copyright, children: copyright }), bottomLinks.length > 0 && (jsx("div", { className: styles['bottom-links'], children: bottomLinks.map(link => (jsx(RouteLink, { className: styles['bottom-link'], href: link.url, target: link.openInNewTab ? '_blank' : undefined, children: link.title }, link.key))) })), countrySelector] }));
12
+ }
13
+ function LinkSection({ link }) {
10
14
  const isXl = useIsBreakpoint('xl');
11
- return (jsxs("footer", { className: styles.footer, children: [jsx("div", { className: styles['main-links'], children: linkBlocks.map(linkBlock => (jsx("div", { className: styles['link-block'], children: jsx(Accordion, { color: "white", hasLineSeparator: false, size: "lg", children: jsx(AccordionItem, { allowCollapse: !isXl, id: `link-block-${linkBlock.key}`, initialIsOpen: isXl, title: linkBlock.header, children: jsx("ul", { className: styles['list'], children: linkBlock.links.map(link => (jsx("li", { children: jsx(RouteLink, { href: link.externalLink || link.internalLink, target: link.openInNewTab ? '_blank' : undefined, children: link.title }) }, link.key))) }) }) }) }, linkBlock.key))) }), jsxs("div", { className: styles['bottom-section'], children: [jsx("p", { className: styles.copyright, children: copyright }), jsx("div", { className: styles['bottom-links'], children: bottomLinks.map(link => (jsx(RouteLink, { className: styles['bottom-link'], href: link.externalLink || link.internalLink, target: link.openInNewTab ? '_blank' : undefined, children: link.title }, link.key))) }), countrySelector] })] }));
15
+ return (jsx("div", { className: styles['link-block'], children: jsx(Accordion, { color: "white", hasLineSeparator: false, size: "lg", children: jsx(AccordionItem, { allowCollapse: !isXl, id: `link-block-${link.key}`, initialIsOpen: isXl, title: link.title, children: jsx("ul", { className: styles['list'], children: link.links?.map(link => jsx(Link, { link: link }, link.key)) }) }) }) }, link.key));
16
+ }
17
+ function Link({ link }) {
18
+ const type = link.type;
19
+ if (type === 'link' || type === 'category') {
20
+ return (jsx(RouteLink, { href: link.url, target: link.openInNewTab ? '_blank' : undefined, children: link.title }));
21
+ }
22
+ if (type === 'section') {
23
+ return jsx(LinkSection, { link: link });
24
+ }
25
+ logger.warn(`Unknown link type '${type}' in footer with key '${link.key}'`);
26
+ return null;
27
+ }
28
+ function FooterLinkBlock({ linkBlocks }) {
29
+ return (jsx("div", { className: styles['main-links'], children: linkBlocks.map(link => (jsx(Link, { link: link }, link.key))) }));
30
+ }
31
+ function Footer({ bottomLinks, copyright, countrySelector, linkBlocks, }) {
32
+ return (jsxs("footer", { className: styles.footer, children: [jsx(FooterLinkBlock, { linkBlocks: linkBlocks }), jsx(BottomSection, { bottomLinks: bottomLinks, copyright: copyright, countrySelector: countrySelector })] }));
12
33
  }
13
34
 
14
35
  export { Footer };
@@ -1,18 +1,6 @@
1
- export interface FooterLink {
2
- externalLink?: string;
3
- internalLink?: string;
4
- isButton: boolean;
5
- key: string;
6
- openInNewTab: boolean;
7
- title?: string;
8
- }
9
- export interface LinkBlock {
10
- header: string;
11
- key: string;
12
- links: FooterLink[];
13
- }
1
+ import { NavigationLink } from '../shared/api/bff/model/bff.model';
14
2
  export interface FooterModel {
15
- bottomLinks: FooterLink[];
3
+ bottomLinks: NavigationLink[];
16
4
  copyright: string;
17
- linkBlocks: LinkBlock[];
5
+ linkBlocks: NavigationLink[];
18
6
  }
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsxs, jsx } from 'react/jsx-runtime';
2
3
  import { useEffect } from 'react';
3
4
  import { Form as Form$1 } from 'react-aria-components';
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from 'react/jsx-runtime';
2
3
  import { Checkbox } from 'react-aria-components';
3
4
  import { StrokeDehashedIcon } from '../../../icons/stroke/stroke-dehashed-icon.js';
@@ -1,10 +1,4 @@
1
1
  import { SearchClient } from 'algoliasearch';
2
- export declare const GlobalSearchDisclosureContext: React.Context<{
3
- close: VoidFunction;
4
- isOpen: boolean;
5
- open: VoidFunction;
6
- toggle: VoidFunction;
7
- } | null>;
8
2
  export declare function GlobalSearchProvider({ children, searchClient, }: {
9
3
  children: React.ReactNode;
10
4
  searchClient: SearchClient;
@@ -1,15 +1,9 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { createContext, useMemo } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
4
3
  import { AlgoliaSearchProvider } from '../../algolia/algolia-search-provider.js';
5
- import { BackgroundOverlay } from '../../background-overlay/background-overlay.js';
6
- import { useDisclosure } from '../../shared/hooks/use-disclosure.js';
7
4
 
8
- const GlobalSearchDisclosureContext = createContext(null);
9
5
  function GlobalSearchProvider({ children, searchClient, }) {
10
- const { close, isOpen, open, toggle } = useDisclosure(false);
11
- const value = useMemo(() => ({ close, isOpen, open, toggle }), [close, isOpen, open, toggle]);
12
- return (jsx(AlgoliaSearchProvider, { searchClient: searchClient, children: jsxs(GlobalSearchDisclosureContext.Provider, { value: value, children: [children, jsx(BackgroundOverlay, { isOpen: isOpen, onClick: close, position: "behind-header" })] }) }));
6
+ return (jsx(AlgoliaSearchProvider, { searchClient: searchClient, children: children }));
13
7
  }
14
8
 
15
- export { GlobalSearchDisclosureContext, GlobalSearchProvider };
9
+ export { GlobalSearchProvider };
@@ -1,6 +1 @@
1
- export declare const useGlobalSearchDisclosure: () => {
2
- close: VoidFunction;
3
- isOpen: boolean;
4
- open: VoidFunction;
5
- toggle: VoidFunction;
6
- };
1
+ export declare const useGlobalSearchDisclosure: () => import("../../drawer/use-drawer").UseDrawerReturnType;
@@ -1,13 +1,9 @@
1
1
  "use client";
2
- import { useContext } from 'react';
3
- import { GlobalSearchDisclosureContext } from './global-search-provider.js';
2
+ import { useDrawer } from '../../drawer/use-drawer.js';
4
3
 
5
- const useGlobalSearchDisclosure = () => {
6
- const context = useContext(GlobalSearchDisclosureContext);
7
- if (!context) {
8
- throw new Error('useGlobalSearchDisclosure must be used within a GlobalSearchDisclosureProvider');
9
- }
10
- return context;
11
- };
4
+ const useGlobalSearchDisclosure = () => useDrawer({
5
+ groupId: 'drawers-header',
6
+ instanceId: 'global-search',
7
+ });
12
8
 
13
9
  export { useGlobalSearchDisclosure };
@@ -7,4 +7,6 @@ export declare function SearchRoot(): import("react/jsx-runtime").JSX.Element;
7
7
  * uses the autocomplete widgets
8
8
  * https://codesandbox.io/p/sandbox/github/algolia/autocomplete/tree/next/examples/two-column-layout
9
9
  */
10
- export declare function GlobalSearch(): import("react/jsx-runtime").JSX.Element;
10
+ export declare function GlobalSearch({ className }: {
11
+ className?: string;
12
+ }): import("react/jsx-runtime").JSX.Element;