@sonic-equipment/ui 141.0.0 → 142.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 (140) hide show
  1. package/dist/address-info-display/address-info-display.d.ts +6 -0
  2. package/dist/{address/address.js → address-info-display/address-info-display.js} +3 -3
  3. package/dist/address-info-display/address-info-display.module.css.js +3 -0
  4. package/dist/algolia/algolia-filter-panel.js +2 -2
  5. package/dist/algolia/algolia-search-provider.js +22 -11
  6. package/dist/background-overlay/background-overlay.js +4 -7
  7. package/dist/badges/badge/badge.js +4 -8
  8. package/dist/base.css +2 -0
  9. package/dist/breadcrumbs/breadcrumb.js +4 -4
  10. package/dist/buttons/add-to-cart-button/add-to-cart-button.js +27 -40
  11. package/dist/buttons/add-to-cart-button/connected-add-to-cart-button.js +19 -2
  12. package/dist/buttons/favorite/connected-favorite-button.js +12 -18
  13. package/dist/buttons/favorite/favorite-button.d.ts +1 -1
  14. package/dist/buttons/icon-button/icon-button.d.ts +4 -2
  15. package/dist/buttons/icon-button/icon-button.js +5 -2
  16. package/dist/buttons/link/link.d.ts +12 -5
  17. package/dist/buttons/link/link.js +10 -4
  18. package/dist/carousel/card-carousel/card-carousel.js +3 -2
  19. package/dist/carousel/carousel-navigation-button.js +1 -1
  20. package/dist/carousel/carousel.js +8 -8
  21. package/dist/carousel/pagination/pagination.d.ts +1 -1
  22. package/dist/carousel/usp-carousel/product-usp-carousel-slide.js +3 -1
  23. package/dist/carousel/usp-carousel/product-usp-carousel.js +1 -1
  24. package/dist/carousel/usp-carousel/usp-carousel.js +3 -1
  25. package/dist/country-select/country-select.d.ts +27 -0
  26. package/dist/{country-selector/country-select → country-select}/country-select.js +7 -4
  27. package/dist/country-select/hooks/use-countries.d.ts +12 -0
  28. package/dist/country-select/hooks/use-countries.js +51 -0
  29. package/dist/country-selector/country-selector-dialog/country-selector-dialog.js +11 -9
  30. package/dist/country-selector/country-selector-trigger/country-selector-trigger.d.ts +1 -1
  31. package/dist/country-selector/use-countries-languages.d.ts +3 -3
  32. package/dist/country-selector/use-countries-languages.js +3 -1
  33. package/dist/exports.d.ts +12 -4
  34. package/dist/filters/active-filters/active-filters.d.ts +1 -1
  35. package/dist/forms/number-field/number-field.js +5 -1
  36. package/dist/forms/select/select.js +3 -2
  37. package/dist/forms/textarea/textarea.js +1 -1
  38. package/dist/global-search/global-search-provider/global-search-provider.js +3 -2
  39. package/dist/global-search/search-highlight/highlight.js +1 -0
  40. package/dist/global-search/search-result-panel/sections/no-search.js +3 -1
  41. package/dist/header/header.d.ts +5 -1
  42. package/dist/header/header.js +5 -2
  43. package/dist/header/link-list/navigation-link-list.d.ts +6 -0
  44. package/dist/header/link-list/navigation-link-list.js +15 -0
  45. package/dist/header/link-list/navigation-link-list.module.css.js +3 -0
  46. package/dist/index.js +15 -7
  47. package/dist/info-icon-tooltip/info-icon-tooltip.d.ts +3 -1
  48. package/dist/info-icon-tooltip/info-icon-tooltip.js +5 -5
  49. package/dist/intl/intl-context.js +2 -1
  50. package/dist/intl/intl-provider.js +7 -6
  51. package/dist/intl/missing-translation-provider.js +6 -5
  52. package/dist/intl/translation-id.d.ts +1 -1
  53. package/dist/lists/feature-list/feature-list.js +3 -1
  54. package/dist/lists/orderline-list/orderline-list.d.ts +1 -1
  55. package/dist/lists/orderline-list/orderline-list.js +6 -1
  56. package/dist/lists/product-overview-grid/product-overview-grid.js +5 -1
  57. package/dist/media/image/image.d.ts +1 -1
  58. package/dist/media/image-lightbox/image-lightbox.js +6 -2
  59. package/dist/media/zoom-image/zoom-image.d.ts +1 -1
  60. package/dist/message/message.d.ts +2 -1
  61. package/dist/message/message.js +2 -2
  62. package/dist/modals/favorite/add-to-favorite-dialog.d.ts +1 -1
  63. package/dist/modals/modal/modal.js +2 -1
  64. package/dist/notifications/announcements/connected-announcement.js +1 -1
  65. package/dist/pages/checkout/components/billing-and-invoice-information.js +2 -2
  66. package/dist/pages/checkout/layouts/checkout-page-layout/checkout-page-layout.js +3 -1
  67. package/dist/pages/checkout/payment-page/components/payment.js +1 -2
  68. package/dist/pages/checkout/shipping-page/components/currency-change-dialog.d.ts +6 -0
  69. package/dist/pages/checkout/shipping-page/components/currency-change-dialog.js +13 -0
  70. package/dist/pages/checkout/shipping-page/components/edit-address-form.d.ts +12 -10
  71. package/dist/pages/checkout/shipping-page/components/edit-address-form.js +11 -4
  72. package/dist/pages/checkout/shipping-page/components/edit-address-form.module.css.js +1 -1
  73. package/dist/pages/checkout/shipping-page/components/readonly-address.d.ts +2 -2
  74. package/dist/pages/checkout/shipping-page/components/readonly-address.js +6 -4
  75. package/dist/pages/checkout/shipping-page/hooks/use-patch-shipping-details.d.ts +4 -4
  76. package/dist/pages/checkout/shipping-page/hooks/use-patch-shipping-details.js +8 -4
  77. package/dist/pages/checkout/shipping-page/shipping-page.js +68 -17
  78. package/dist/pages/components/page-container/page-container.js +2 -1
  79. package/dist/pages/error-page/error-page.js +4 -1
  80. package/dist/pages/product/product-details-page/components/product-details-panel/product-details-panel.js +3 -1
  81. package/dist/pages/product/product-listing-page/no-results/no-results.js +3 -3
  82. package/dist/pages/product/product-listing-page/product-listing-page-category-carousel/product-listing-page-category-carousel.js +1 -1
  83. package/dist/pages/product/product-listing-page/product-listing-page-provider/product-listing-page-provider.js +3 -2
  84. package/dist/pages/product/search-result-page/search-results-page-category-carousel/search-results-page-category-carousel.js +1 -1
  85. package/dist/promos/promo-banners/promo-banners.d.ts +6 -5
  86. package/dist/promos/promo-banners/promo-banners.js +6 -5
  87. package/dist/promos/promo-card/promo-card.d.ts +1 -1
  88. package/dist/shared/api/bff/model/bff.model.d.ts +13 -0
  89. package/dist/shared/api/storefront/hooks/cart/use-delete-cart-line-by-id.d.ts +2 -2
  90. package/dist/shared/api/storefront/hooks/cart/use-delete-current-cart.d.ts +2 -2
  91. package/dist/shared/api/storefront/hooks/cart/use-save-cart-for-later.d.ts +2 -2
  92. package/dist/shared/api/storefront/hooks/customer/use-patch-bill-to-address.d.ts +1 -1
  93. package/dist/shared/api/storefront/hooks/website/use-fetch-countries-with-languages.d.ts +4 -2
  94. package/dist/shared/api/storefront/hooks/website/use-fetch-countries-with-languages.js +3 -2
  95. package/dist/shared/api/storefront/hooks/website/{use-fetch-countries.d.ts → use-fetch-country-models.d.ts} +1 -1
  96. package/dist/shared/api/storefront/hooks/website/use-fetch-country-models.js +16 -0
  97. package/dist/shared/api/storefront/model/storefront.model.d.ts +21 -1
  98. package/dist/shared/api/storefront/services/customer-service.d.ts +3 -3
  99. package/dist/shared/api/storefront/services/customer-service.js +1 -1
  100. package/dist/shared/api/storefront/services/website-service.d.ts +1 -3
  101. package/dist/shared/api/storefront/services/website-service.js +4 -45
  102. package/dist/shared/data/cart.data.d.ts +2 -0
  103. package/dist/shared/data/cart.data.js +650 -0
  104. package/dist/shared/data/countries-languages.data.d.ts +11 -0
  105. package/dist/shared/data/countries-languages.data.js +61 -0
  106. package/dist/shared/hooks/use-breakpoint.js +2 -2
  107. package/dist/shared/hooks/use-cookie.d.ts +1 -0
  108. package/dist/shared/hooks/use-cookie.js +13 -7
  109. package/dist/shared/hooks/use-disclosure.d.ts +3 -3
  110. package/dist/shared/hooks/use-is-breakpoint.js +1 -1
  111. package/dist/shared/hooks/use-is-scrolled-beyond-element.d.ts +1 -0
  112. package/dist/shared/hooks/use-is-scrolled-beyond-element.js +26 -0
  113. package/dist/shared/hooks/use-scroll-to.d.ts +1 -1
  114. package/dist/shared/hooks/use-scroll-to.js +2 -2
  115. package/dist/shared/model/countries-languages.d.ts +3 -1
  116. package/dist/shared/model/countries-languages.js +32 -0
  117. package/dist/shared/model/defaults.d.ts +1 -0
  118. package/dist/shared/model/defaults.js +3 -0
  119. package/dist/shared/model/image.d.ts +1 -1
  120. package/dist/shared/model/link.d.ts +15 -0
  121. package/dist/shared/providers/favorite-provider.d.ts +3 -3
  122. package/dist/shared/providers/global-state-provider.js +2 -1
  123. package/dist/shared/reset.module.css.js +3 -0
  124. package/dist/shared/routing/with-routing.js +1 -0
  125. package/dist/shared/utils/local-storage.d.ts +1 -7
  126. package/dist/shared/utils/local-storage.js +4 -4
  127. package/dist/shared/utils/number.d.ts +1 -0
  128. package/dist/shared/utils/number.js +10 -0
  129. package/dist/sidebar/sidebar-provider.js +4 -1
  130. package/dist/sidebar/use-sidebar.js +4 -3
  131. package/dist/sign-in-form/sign-in-form.js +2 -1
  132. package/dist/styles.css +68 -5
  133. package/dist/tooltip/tooltip.js +6 -3
  134. package/package.json +17 -14
  135. package/dist/address/address.d.ts +0 -6
  136. package/dist/address/address.module.css.js +0 -3
  137. package/dist/country-selector/country-select/country-select.d.ts +0 -27
  138. package/dist/shared/api/storefront/hooks/website/use-fetch-countries.js +0 -15
  139. package/dist/shared/model/countries.d.ts +0 -225
  140. package/dist/shared/model/countries.js +0 -260
@@ -1,16 +1,18 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useRef, useEffect } from 'react';
3
+ import { useCountries } from '../../../country-select/hooks/use-countries.js';
3
4
  import { useFetchSession } from '../../../shared/api/storefront/hooks/authentication/use-fetch-session.js';
4
5
  import { usePatchSession } from '../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
5
6
  import { useFetchCurrentCart } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart.js';
6
7
  import { useFetchFulfillmentMethodsForCurrentCart } from '../../../shared/api/storefront/hooks/customer/use-fetch-fulfillment-methods-for-current-cart.js';
7
- import { useFetchCountries } from '../../../shared/api/storefront/hooks/website/use-fetch-countries.js';
8
8
  import { useDataLayer } from '../../../shared/ga/use-data-layer.js';
9
+ import { useDisclosure } from '../../../shared/hooks/use-disclosure.js';
9
10
  import { useNavigate } from '../../../shared/routing/use-navigate.js';
10
11
  import { hasNo } from '../../../shared/utils/types.js';
11
12
  import { ErrorPage } from '../../error-page/error-page.js';
12
13
  import { LoadingPage } from '../../loading-page/loading-page.js';
13
14
  import { PATHS } from '../../paths.js';
15
+ import { CurrencyChangeDialog } from './components/currency-change-dialog.js';
14
16
  import { EditAddressesForm } from './components/edit-address-form.js';
15
17
  import { ReadOnlyAddresses } from './components/readonly-address.js';
16
18
  import { usePatchShippingDetails } from './hooks/use-patch-shipping-details.js';
@@ -21,9 +23,14 @@ function ShippingPage() {
21
23
  const gaEventPushed = useRef(false);
22
24
  const { data: cart, error: errorFetchCart, isLoading: isLoadingCart, refetch: refetchCart, } = useFetchCurrentCart();
23
25
  const { data: session } = useFetchSession();
24
- const { data: countries, isLoading: isLoadingCountries } = useFetchCountries({
26
+ const { countries, currentCountry: selectedCountry, isFetching: isLoadingCountries, } = useCountries({
25
27
  enabled: hasNo(cart?.billTo?.address1) || Boolean(session?.isGuest),
26
28
  });
29
+ const currentCountry = countries && cart?.billTo?.country
30
+ ? countries.find(country => country.id === cart.billTo?.country?.id)
31
+ : selectedCountry;
32
+ const { close: closeCurrencyWarningDialog, isOpen: currencyWarningDialogIsOpen, open: openCurrencyWarningDialog, toggle: toggleCurrencyWarningDialog, } = useDisclosure();
33
+ const formData = useRef();
27
34
  const { data: fulfillmentMethods, isLoading: isLoadingFulfillmentMethods } = useFetchFulfillmentMethodsForCurrentCart();
28
35
  const { isLoading: isPatchingSession, mutate: patchSession } = usePatchSession();
29
36
  const { error: errorPatchBillingAddress, isError, isLoading: isPatching, isSuccess, mutate: patchShippingDetails, } = usePatchShippingDetails();
@@ -76,24 +83,63 @@ function ShippingPage() {
76
83
  if (!isAuthenticated ||
77
84
  hasNo(session) ||
78
85
  hasNo(cart) ||
86
+ hasNo(countries) ||
79
87
  hasNo(cart.cartLines) ||
80
88
  cart.cartLines.length === 0 ||
81
89
  hasNo(cart.billTo) ||
82
90
  (hasNo(cart.billTo.address1) && hasNo(countries)))
91
+ // TODO: Return error page, but first check all the conditions
83
92
  return null;
84
- return (jsx(ShippingPageContent, { cart: cart, editAddress: jsx(EditAddressesForm, { billTo: cart.billTo, countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
85
- if (!cart.billTo)
86
- return;
87
- await patchShippingDetails({
88
- billTo: { ...cart.billTo, ...address },
89
- cart,
90
- notes,
91
- });
92
- dataLayer.push(createEcommerceEvent({
93
- cart,
94
- event: { event: 'add_shipping_info' },
95
- }));
96
- } }), errorPatchBillingAddress: errorPatchBillingAddress, fulfillmentMethods: fulfillmentMethods, isGuest: session.isGuest, isLoadingFulfillmentMethods: isLoadingFulfillmentMethods, isPatching: isPatching, isPatchingSession: isPatchingSession, onChangeFulfillmentMethod: async (value) => {
93
+ async function handleSubmit({ address, cart, notes, }) {
94
+ if (!cart.billTo)
95
+ throw new Error('No billTo address found');
96
+ await patchShippingDetails({
97
+ billTo: {
98
+ ...cart.billTo,
99
+ address1: address.address1,
100
+ address2: address.address2,
101
+ address3: address.address3,
102
+ attention: address.attention,
103
+ city: address.city,
104
+ companyName: address.companyName,
105
+ country: { id: address.country.id },
106
+ email: address.email,
107
+ firstName: address.firstName,
108
+ lastName: address.lastName,
109
+ phone: address.phone,
110
+ postalCode: address.postalCode,
111
+ },
112
+ cart,
113
+ notes,
114
+ });
115
+ dataLayer.push(createEcommerceEvent({
116
+ cart,
117
+ event: { event: 'add_shipping_info' },
118
+ }));
119
+ }
120
+ return (jsx(ShippingPageContent, { cart: cart, editAddress: jsxs(Fragment, { children: [jsx(EditAddressesForm, { billTo: cart.billTo, countries: countries, currentCountry: currentCountry, isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
121
+ if (!cart.billTo)
122
+ return;
123
+ formData.current = { address, notes };
124
+ /* When the currency changes, depending on the country,
125
+ * we need to show a dialog to ask the customer if they
126
+ * want to review their cart with the new currency */
127
+ if (address.country.currencyCode === currentCountry?.currencyCode) {
128
+ handleSubmit({ address, cart, notes });
129
+ }
130
+ else {
131
+ openCurrencyWarningDialog();
132
+ }
133
+ } }), jsx(CurrencyChangeDialog, { isOpen: currencyWarningDialogIsOpen, onOpenChange: toggleCurrencyWarningDialog, onSubmit: () => {
134
+ if (!formData.current)
135
+ return;
136
+ closeCurrencyWarningDialog();
137
+ handleSubmit({
138
+ address: formData.current.address,
139
+ cart,
140
+ notes: formData.current.notes,
141
+ });
142
+ } })] }), errorPatchBillingAddress: errorPatchBillingAddress, fulfillmentMethods: fulfillmentMethods, isGuest: session.isGuest, isLoadingFulfillmentMethods: isLoadingFulfillmentMethods, isPatching: isPatching, isPatchingSession: isPatchingSession, onChangeFulfillmentMethod: async (value) => {
97
143
  await patchSession({
98
144
  session: {
99
145
  ...session,
@@ -104,7 +150,12 @@ function ShippingPage() {
104
150
  }, readOnlyAddress: jsx(ReadOnlyAddresses, { billTo: cart.billTo, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ notes }) => {
105
151
  if (!cart.billTo)
106
152
  return;
107
- await patchShippingDetails({ cart, notes });
153
+ if (notes === undefined) {
154
+ navigate(PATHS.REVIEW_AND_SUBMIT);
155
+ }
156
+ else {
157
+ await patchShippingDetails({ cart, notes });
158
+ }
108
159
  dataLayer.push(createEcommerceEvent({
109
160
  cart,
110
161
  event: { event: 'add_shipping_info' },
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import clsx from 'clsx';
3
+ import resetStyles from '../../../shared/reset.module.css.js';
3
4
  import styles from './page-container.module.css.js';
4
5
 
5
6
  function PageContainer({ breadcrumbSlot, children, className, fluid, fullHeight, titleSlot, }) {
6
- return (jsx("div", { className: clsx(styles['page-container'], fullHeight && styles['full-height'], fluid && styles['fluid'], className), children: jsxs("main", { className: styles['page-main'], children: [breadcrumbSlot && (jsx("div", { className: styles.breadcrumb, children: breadcrumbSlot })), titleSlot && jsx("div", { className: styles.title, children: titleSlot }), jsx("div", { className: styles.content, children: children })] }) }));
7
+ return (jsx("div", { className: clsx(styles['page-container'], resetStyles.reset, fullHeight && styles['full-height'], fluid && styles['fluid'], className), children: jsxs("main", { className: styles['page-main'], children: [breadcrumbSlot && (jsx("div", { className: styles.breadcrumb, children: breadcrumbSlot })), titleSlot && jsx("div", { className: styles.title, children: titleSlot }), jsx("div", { className: styles.content, children: children })] }) }));
7
8
  }
8
9
 
9
10
  export { PageContainer };
@@ -9,10 +9,13 @@ import { PATHS } from '../paths.js';
9
9
 
10
10
  function ErrorPage({ error }) {
11
11
  useEffect(() => {
12
- setTimeout(() => {
12
+ const timeoutId = setTimeout(() => {
13
13
  if (!isRequestError(error))
14
14
  throw error;
15
15
  }, 0);
16
+ return () => {
17
+ clearTimeout(timeoutId);
18
+ };
16
19
  }, [error]);
17
20
  return (jsx(Page, { breadcrumb: [
18
21
  { href: PATHS.HOME, label: 'Home' },
@@ -23,7 +23,9 @@ function ProductDetailsPanel({ priceComponent, product, }) {
23
23
  sendAddToWishListFromProductDetailsPageEvent({
24
24
  objectId: product.productNumber,
25
25
  });
26
- }, productId: product.storefrontId }))] })] }), jsxs("div", { children: [jsx(Heading, { italic: true, className: styles['product-features-heading'], size: "xxs", children: jsx(FormattedMessage, { id: "Product Features" }) }), product.content.htmlContent && (jsx(ShowAll, { initialHeight: 216, children: jsx("div", { className: styles.description, dangerouslySetInnerHTML: {
26
+ }, productId: product.storefrontId }))] })] }), jsxs("div", { children: [jsx(Heading, { italic: true, className: styles['product-features-heading'], size: "xxs", children: jsx(FormattedMessage, { id: "Product Features" }) }), product.content.htmlContent && (jsx(ShowAll, { initialHeight: 216, children: jsx("div", { className: styles.description,
27
+ // eslint-disable-next-line @eslint-react/dom/no-dangerously-set-innerhtml
28
+ dangerouslySetInnerHTML: {
27
29
  __html: product.content.htmlContent,
28
30
  } }) }))] }), jsx("div", { children: jsxs(Accordion, { indented: true, borderType: ['top', 'middle-accentuated'], children: [product.attributeTypes.length > 0 && (jsx(AccordionItem, { id: "specification", title: jsx(FormattedMessage, { id: "Specifications" }), children: jsx(FeatureList, { className: styles['feature-list'], features: product.attributeTypes.map(attribute => ({
29
31
  id: `${attribute.id}`,
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { FormattedMessage } from '../../../../intl/formatted-message.js';
4
- import { useBreakpoint } from '../../../../shared/hooks/use-breakpoint.js';
4
+ import { useIsBreakpoint } from '../../../../shared/hooks/use-is-breakpoint.js';
5
5
  import { RouteButton } from '../../../../shared/routing/route-button.js';
6
6
  import { Heading } from '../../../../typography/heading/heading.js';
7
7
  import styles from './no-results.module.css.js';
8
8
 
9
9
  function NoResults({ content, title }) {
10
- const { lg } = useBreakpoint();
11
- return (jsxs("div", { className: styles['no-results'], children: [jsx(Heading, { bold: false, className: styles.title, size: lg ? 's' : 'xs', tag: "h2", children: title }), jsx("p", { className: styles.body, children: content }), jsx("div", { className: styles.buttons, children: jsx(RouteButton, { withArrow: true, "data-test-selector": "buttonContinueShopping", href: "/", size: "md", children: jsx(FormattedMessage, { id: "Continue shopping" }) }) })] }));
10
+ const isLg = useIsBreakpoint('lg');
11
+ return (jsxs("div", { className: styles['no-results'], children: [jsx(Heading, { bold: false, className: styles.title, size: isLg ? 's' : 'xs', tag: "h2", children: title }), jsx("p", { className: styles.body, children: content }), jsx("div", { className: styles.buttons, children: jsx(RouteButton, { withArrow: true, "data-test-selector": "buttonContinueShopping", href: "/", size: "md", children: jsx(FormattedMessage, { id: "Continue shopping" }) }) })] }));
12
12
  }
13
13
 
14
14
  export { NoResults };
@@ -16,7 +16,7 @@ function ProductListingPageCategoryCarousel({ currentCategoryPath, }) {
16
16
  return (jsx(CategoryCarousel, { categoryCards: categories.map((category, index) => (jsx(CategoryCard, { href: category.href, image: {
17
17
  image: category.image,
18
18
  title: category.name,
19
- }, title: category.name }, index))) }));
19
+ }, title: category.name }, category.href || index))) }));
20
20
  }
21
21
 
22
22
  export { ProductListingPageCategoryCarousel };
@@ -1,10 +1,11 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useContext } from 'react';
3
+ import { useMemo, useContext } from 'react';
4
4
  import { ProductListingPageContext } from './product-listing-page-context.js';
5
5
 
6
6
  function ProductListingPageProvider({ children, data, error, isError, isLoading, }) {
7
- return (jsx(ProductListingPageContext.Provider, { value: { data, error, isError, isLoading }, children: children }));
7
+ const value = useMemo(() => ({ data, error, isError, isLoading }), [data, error, isError, isLoading]);
8
+ return (jsx(ProductListingPageContext.Provider, { value: value, children: children }));
8
9
  }
9
10
  function useProductListingPageProvider() {
10
11
  return useContext(ProductListingPageContext);
@@ -16,7 +16,7 @@ function SearchResultsPageCategoryCarousel() {
16
16
  return (jsx(CategoryCarousel, { categoryCards: categories.map((category, index) => (jsx(CategoryCard, { href: category.href, image: {
17
17
  image: category.image,
18
18
  title: category.name,
19
- }, title: category.name }, index))) }));
19
+ }, title: category.name }, category.href + category.name || index))) }));
20
20
  }
21
21
 
22
22
  export { SearchResultsPageCategoryCarousel };
@@ -1,8 +1,9 @@
1
1
  import { ResponsiveImageType } from '../../shared/model/image';
2
+ export interface PromoBannersData {
3
+ href: string;
4
+ image: ResponsiveImageType;
5
+ }
2
6
  export interface PromoBannersProps {
3
- promoBannersData?: Array<{
4
- href: string;
5
- image: ResponsiveImageType;
6
- }>;
7
+ promoBannersData?: PromoBannersData[];
7
8
  }
8
- export declare function PromoBanners({ promoBannersData }: PromoBannersProps): import("react/jsx-runtime").JSX.Element | null;
9
+ export declare function PromoBanners({ promoBannersData, }: PromoBannersProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,16 +1,17 @@
1
1
  "use client";
2
2
  import { jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { Carousel } from '../../carousel/carousel.js';
4
- import { useBreakpoint } from '../../shared/hooks/use-breakpoint.js';
4
+ import { useIsBreakpoint } from '../../shared/hooks/use-is-breakpoint.js';
5
5
  import { PromoBanner } from '../promo-banner/promo-banner.js';
6
6
  import styles from './promo-banners.module.css.js';
7
7
 
8
- function PromoBanners({ promoBannersData = [] }) {
9
- const { lg } = useBreakpoint();
10
- const promoBanners = promoBannersData.map((promoBanner, index) => (jsx(PromoBanner, { href: promoBanner.href, image: promoBanner.image, variant: index % 2 === 0 ? 'lg' : 'sm' }, `promo-banner-${index}`)));
8
+ const defaultPromoBannersData = [];
9
+ function PromoBanners({ promoBannersData = defaultPromoBannersData, }) {
10
+ const isLg = useIsBreakpoint('lg');
11
+ const promoBanners = promoBannersData.map((promoBanner, index) => (jsx(PromoBanner, { href: promoBanner.href, image: promoBanner.image, variant: index % 2 === 0 ? 'lg' : 'sm' }, `promo-banner-${promoBanner.href || index}`)));
11
12
  if (promoBannersData.length === 0)
12
13
  return null;
13
- return (jsx("div", { className: styles.promos, children: lg ? (jsx(Fragment, { children: promoBanners })) : (jsx(Carousel, { hasNavigation: false, hasOverflow: false, slides: promoBanners, spaceBetween: 16 })) }));
14
+ return (jsx("div", { className: styles.promos, children: isLg ? (jsx(Fragment, { children: promoBanners })) : (jsx(Carousel, { hasNavigation: false, hasOverflow: false, slides: promoBanners, spaceBetween: 16 })) }));
14
15
  }
15
16
 
16
17
  export { PromoBanners };
@@ -2,6 +2,6 @@ import { ImageType } from '../../shared/model/image';
2
2
  export interface PromoCardProps {
3
3
  href: string;
4
4
  image: ImageType;
5
- onClick?: () => void;
5
+ onClick?: VoidFunction;
6
6
  }
7
7
  export declare function PromoCard({ href, image, onClick }: PromoCardProps): import("react/jsx-runtime").JSX.Element;
@@ -159,4 +159,17 @@ export interface ProductListingPageDataResponse {
159
159
  page: PageModel;
160
160
  promoBanners: PromoBanners | null;
161
161
  }
162
+ export interface Language {
163
+ cultureCode: string;
164
+ description: string;
165
+ id: string;
166
+ languageCode: string;
167
+ }
168
+ export interface Country {
169
+ abbreviation: string;
170
+ currencyCode: string;
171
+ id: string;
172
+ languages: Language[];
173
+ name: string;
174
+ }
162
175
  export {};
@@ -1,6 +1,6 @@
1
1
  interface UseDeleteCartLineByIdArgs {
2
- onError?: () => void;
3
- onSuccess?: () => void;
2
+ onError?: VoidFunction;
3
+ onSuccess?: VoidFunction;
4
4
  }
5
5
  export declare function useDeleteCartLineById({ onError, onSuccess, }?: UseDeleteCartLineByIdArgs): import("@tanstack/react-query").UseMutationResult<void, Error, {
6
6
  cartLineId: string;
@@ -1,7 +1,7 @@
1
1
  import { CartModel } from '../../model/storefront.model';
2
2
  interface UseDeleteCurrentCartArgs {
3
- onError?: () => void;
4
- onSuccess?: () => void;
3
+ onError?: VoidFunction;
4
+ onSuccess?: VoidFunction;
5
5
  }
6
6
  export declare const useDeleteCurrentCart: ({ onError, onSuccess, }?: UseDeleteCurrentCartArgs) => import("@tanstack/react-query").UseMutationResult<CartModel, Error, void, unknown>;
7
7
  export {};
@@ -1,7 +1,7 @@
1
1
  import { CartModel } from '../../model/storefront.model';
2
2
  interface UseSaveCartForLaterArgs {
3
- onError?: () => void;
4
- onSuccess?: () => void;
3
+ onError?: VoidFunction;
4
+ onSuccess?: VoidFunction;
5
5
  }
6
6
  export declare function useSaveCartForLater({ onError, onSuccess, }?: UseSaveCartForLaterArgs): import("@tanstack/react-query").UseMutationResult<CartModel, Error, {
7
7
  cart: CartModel;
@@ -6,6 +6,6 @@ export declare function usePatchBillToAddress({ skipInvalidation, }?: {
6
6
  isLoading: boolean;
7
7
  isSuccess: boolean;
8
8
  mutate: (args_0: {
9
- billTo: import("../../model/storefront.model").BillToModel;
9
+ billTo: import("../../model/storefront.model").PatchBillToModel;
10
10
  }) => Promise<import("../../model/storefront.model").BillToModel>;
11
11
  };
@@ -1,3 +1,5 @@
1
- export declare function useFetchCountriesWithLanguages({ enabled, }?: {
1
+ import { Country } from '../../model/storefront.model';
2
+ export declare function useFetchCountriesWithLanguages<TReturnType = Country[]>({ enabled, select, }?: {
2
3
  enabled?: boolean;
3
- }): import("@tanstack/react-query").UseQueryResult<import("../../../../..").Country[], Error>;
4
+ select?: (data: Country[]) => TReturnType;
5
+ }): import("@tanstack/react-query").UseQueryResult<TReturnType, Error>;
@@ -2,12 +2,13 @@ import { useQuery } from '@tanstack/react-query';
2
2
  import { TIME } from '../../../../utils/time.js';
3
3
  import { fetchCountriesWithLanguages } from '../../services/website-service.js';
4
4
 
5
- function useFetchCountriesWithLanguages({ enabled = true, } = { enabled: true }) {
5
+ function useFetchCountriesWithLanguages({ enabled = true, select, } = { enabled: true }) {
6
6
  return useQuery({
7
7
  enabled,
8
8
  gcTime: 24 * TIME.HOUR,
9
9
  queryFn: fetchCountriesWithLanguages,
10
- queryKey: ['country-languages'],
10
+ queryKey: ['country-with-languages'],
11
+ select,
11
12
  staleTime: 24 * TIME.HOUR,
12
13
  });
13
14
  }
@@ -1,3 +1,3 @@
1
- export declare function useFetchCountries({ enabled }?: {
1
+ export declare function useFetchCountryModels({ enabled }?: {
2
2
  enabled: boolean;
3
3
  }): import("@tanstack/react-query").UseQueryResult<import("../../model/storefront.model").CountryModel[], Error>;
@@ -0,0 +1,16 @@
1
+ import { useQuery } from '@tanstack/react-query';
2
+ import { TIME } from '../../../../utils/time.js';
3
+ import { fetchCountriesLanguages } from '../../services/website-service.js';
4
+
5
+ function useFetchCountryModels({ enabled = true } = { enabled: true }) {
6
+ return useQuery({
7
+ enabled,
8
+ gcTime: 24 * TIME.HOUR,
9
+ queryFn: fetchCountriesLanguages,
10
+ queryKey: ['countries'],
11
+ select: data => data.countries,
12
+ staleTime: 24 * TIME.HOUR,
13
+ });
14
+ }
15
+
16
+ export { useFetchCountryModels };
@@ -966,8 +966,15 @@ export interface CartModel extends BaseModel {
966
966
  vmiLocationId?: string | null;
967
967
  warehouses: WarehouseDto[] | null;
968
968
  }
969
+ export type PatchBillToModel = Partial<Omit<BillToModel, 'country'> & {
970
+ country?: CountryModel | {
971
+ id: string;
972
+ } | null;
973
+ }> & {
974
+ id: string;
975
+ };
969
976
  export type PatchCartModel = Partial<Omit<CartModel, 'billTo'> & {
970
- billTo?: BillToModel | {
977
+ billTo?: PatchBillToModel | {
971
978
  id: string;
972
979
  } | null;
973
980
  }> & {
@@ -3037,3 +3044,16 @@ export interface AdyenPaymentModel {
3037
3044
  pspReference: string;
3038
3045
  resultCode: AdyenResultCode;
3039
3046
  }
3047
+ export interface Language {
3048
+ cultureCode: string;
3049
+ description: string;
3050
+ id: string;
3051
+ languageCode: string;
3052
+ }
3053
+ export interface Country {
3054
+ abbreviation: string;
3055
+ currencyCode: string;
3056
+ id: string;
3057
+ languages: Language[];
3058
+ name: string;
3059
+ }
@@ -1,10 +1,10 @@
1
- import { BillToCollectionModel, BillToModel, ShipToCollectionModel } from 'shared/api/storefront/model/storefront.model';
1
+ import { BillToCollectionModel, BillToModel, PatchBillToModel, ShipToCollectionModel } from 'shared/api/storefront/model/storefront.model';
2
2
  export declare function fetchBillToAddresses(): Promise<BillToCollectionModel>;
3
3
  export declare function fetchShipToAddresses({ shipToId }: {
4
4
  shipToId: string;
5
5
  }): Promise<ShipToCollectionModel>;
6
- export declare function patchBillToAddress({ billTo }: {
7
- billTo: BillToModel;
6
+ export declare function patchBillToAddress({ billTo, }: {
7
+ billTo: PatchBillToModel;
8
8
  }): Promise<BillToModel>;
9
9
  export declare function fetchFulfillmentMethods({ customerId, }: {
10
10
  customerId: string;
@@ -15,7 +15,7 @@ async function fetchShipToAddresses({ shipToId }) {
15
15
  });
16
16
  return body;
17
17
  }
18
- async function patchBillToAddress({ billTo }) {
18
+ async function patchBillToAddress({ billTo, }) {
19
19
  const { body: updatedBillTo } = await request({
20
20
  body: billTo,
21
21
  credentials: 'include',
@@ -1,6 +1,4 @@
1
- import { Country } from '../../../model/countries-languages';
2
- import { CountryModel, LanguageModel, SessionModel, SettingsCollectionModel } from '../model/storefront.model';
3
- export declare function fetchCountries(): Promise<CountryModel[]>;
1
+ import { Country, CountryModel, LanguageModel, SessionModel, SettingsCollectionModel } from '../model/storefront.model';
4
2
  export declare function fetchCountriesLanguages(): Promise<{
5
3
  countries: CountryModel[];
6
4
  languages: LanguageModel[];
@@ -1,24 +1,6 @@
1
1
  import { config } from '../../../../config.js';
2
- import { isCountryCode, isLanguageCode, isCultureCode } from '../../../../intl/types.js';
3
2
  import { request } from '../../../fetch/request.js';
4
3
 
5
- const countryIsoCodeToLanguageIsoCode = {
6
- '*': ['EN'],
7
- AT: ['DE'],
8
- BE: ['NL', 'FR'],
9
- CH: ['FR', 'DE', 'IT'],
10
- DE: ['DE'],
11
- FR: ['FR'],
12
- IT: ['IT'],
13
- LU: ['FR', 'DE'],
14
- NL: ['EN', 'NL'],
15
- };
16
- async function fetchCountries() {
17
- const { body } = await request({
18
- url: `${config.SHOP_API_URL}/api/v1/websites/current/countries?expand=isActive`,
19
- });
20
- return body.countries || [];
21
- }
22
4
  async function fetchCountriesLanguages() {
23
5
  const { body } = await request({
24
6
  url: `${config.SHOP_API_URL}/api/v1/websites/current?expand=languages%2Ccountries`,
@@ -29,33 +11,10 @@ async function fetchCountriesLanguages() {
29
11
  };
30
12
  }
31
13
  async function fetchCountriesWithLanguages() {
32
- const { countries, languages } = await fetchCountriesLanguages();
33
- return countries.map((country) => {
34
- const abbreviation = country.abbreviation.toUpperCase();
35
- if (!isCountryCode(abbreviation))
36
- throw new Error(`Invalid country code: ${abbreviation}`);
37
- return {
38
- abbreviation,
39
- id: country.id,
40
- languages: languages
41
- .filter(language => countryIsoCodeToLanguageIsoCode[country.abbreviation]?.includes(language.languageCode) ??
42
- countryIsoCodeToLanguageIsoCode['*'].includes(language.languageCode.toUpperCase()))
43
- .map((language) => {
44
- const languageCode = language.languageCode.toUpperCase();
45
- if (!isLanguageCode(languageCode))
46
- throw new Error(`Invalid language code: ${languageCode}`);
47
- if (!isCultureCode(language.cultureCode))
48
- throw new Error(`Invalid culture code: ${language.cultureCode}`);
49
- return {
50
- cultureCode: language.cultureCode,
51
- description: language.description,
52
- id: language.id,
53
- languageCode,
54
- };
55
- }),
56
- name: country.name,
57
- };
14
+ const { body } = await request({
15
+ url: `${config.SHOP_API_URL}/api/v1/custom/countrylanguage`,
58
16
  });
17
+ return body;
59
18
  }
60
19
  async function updateLocale({ countryId, languageId, }) {
61
20
  const { body } = await request({
@@ -80,4 +39,4 @@ async function fetchSettings() {
80
39
  return body.settingsCollection;
81
40
  }
82
41
 
83
- export { fetchCountries, fetchCountriesLanguages, fetchCountriesWithLanguages, fetchSettings, updateLocale };
42
+ export { fetchCountriesLanguages, fetchCountriesWithLanguages, fetchSettings, updateLocale };
@@ -0,0 +1,2 @@
1
+ import { CartModel } from '../api/storefront/model/storefront.model';
2
+ export declare const cart: CartModel;