@sonic-equipment/ui 178.0.0 → 180.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 (102) hide show
  1. package/dist/algolia/algolia-active-filters.js +4 -0
  2. package/dist/config.js +4 -7
  3. package/dist/country-select/country-select.d.ts +1 -0
  4. package/dist/exports.d.ts +19 -9
  5. package/dist/forms/input/input.d.ts +1 -0
  6. package/dist/forms/input/input.js +4 -4
  7. package/dist/forms/input/input.module.css.js +1 -1
  8. package/dist/forms/password-field/password-field.d.ts +2 -0
  9. package/dist/forms/password-field/password-field.js +15 -0
  10. package/dist/forms/search-field/search-field.d.ts +5 -0
  11. package/dist/forms/search-field/search-field.js +19 -0
  12. package/dist/forms/text-field/text-field.d.ts +25 -24
  13. package/dist/forms/text-field/text-field.js +7 -14
  14. package/dist/forms/textarea/textarea.d.ts +1 -0
  15. package/dist/forms/textarea/textarea.js +2 -2
  16. package/dist/forms/textarea/textarea.module.css.js +1 -1
  17. package/dist/global-search/search-highlight/highlight.d.ts +1 -0
  18. package/dist/header/buttons/account/connected-account-button.js +1 -1
  19. package/dist/icons/solid/solid-rating-icon.js +7 -0
  20. package/dist/index.js +20 -10
  21. package/dist/intl/translation-id.d.ts +1 -1
  22. package/dist/modals/dialog/dialog.d.ts +5 -1
  23. package/dist/modals/dialog/dialog.js +10 -4
  24. package/dist/navigation/mobile-navigation/mobile-navigation.js +1 -1
  25. package/dist/observers/intersection-observer.d.ts +9 -1
  26. package/dist/observers/intersection-observer.js +6 -3
  27. package/dist/pages/account/components/create-account-form/create-account-form.js +3 -2
  28. package/dist/pages/account/components/sign-in-form/sign-in-form.js +2 -1
  29. package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.d.ts +15 -0
  30. package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.js +23 -0
  31. package/dist/pages/my-sonic/actions/change-customer/change-customer-dialog.module.css.js +3 -0
  32. package/dist/pages/my-sonic/actions/change-customer/change-customer.d.ts +13 -0
  33. package/dist/pages/my-sonic/actions/change-customer/change-customer.js +66 -0
  34. package/dist/pages/my-sonic/actions/change-customer/change-customer.module.css.js +3 -0
  35. package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.d.ts +2 -0
  36. package/dist/pages/my-sonic/actions/change-customer/connected-change-customer-dialog.js +39 -0
  37. package/dist/pages/my-sonic/navigation/connected-my-sonic-navigation.d.ts +1 -0
  38. package/dist/pages/{my-account/navigation/connected-my-account-navigation.js → my-sonic/navigation/connected-my-sonic-navigation.js} +5 -5
  39. package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.d.ts +6 -0
  40. package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.js +19 -0
  41. package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.module.css.js +3 -0
  42. package/dist/pages/{my-account/navigation/my-account-mobile-navigation.d.ts → my-sonic/navigation/my-sonic-mobile-navigation.d.ts} +1 -1
  43. package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.js +22 -0
  44. package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.d.ts +18 -0
  45. package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.js +29 -0
  46. package/dist/pages/my-sonic/widgets/connected-customer-information-widget.d.ts +1 -0
  47. package/dist/pages/my-sonic/widgets/connected-customer-information-widget.js +56 -0
  48. package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.d.ts +2 -2
  49. package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.js +3 -2
  50. package/dist/pages/product/layouts/product-details-page-layout/product-details-page-layout.module.css.js +1 -1
  51. package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.d.ts +1 -0
  52. package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.js +24 -0
  53. package/dist/pages/product/product-details-page/components/product-details-recently-viewed-section/product-details-recently-viewed-section.module.css.js +3 -0
  54. package/dist/pages/product/product-details-page/product-details.d.ts +1 -2
  55. package/dist/pages/product/product-details-page/product-details.js +4 -5
  56. package/dist/shared/api/bff/hooks/use-fetch-product-details-page-data.js +6 -2
  57. package/dist/shared/api/bff/hooks/use-fetch-recently-viewed-products.d.ts +4 -0
  58. package/dist/shared/api/bff/hooks/use-fetch-recently-viewed-products.js +15 -0
  59. package/dist/shared/api/bff/model/bff.model.d.ts +0 -1
  60. package/dist/shared/api/bff/services/bff-service.d.ts +4 -1
  61. package/dist/shared/api/bff/services/bff-service.js +11 -1
  62. package/dist/shared/api/storefront/hooks/authentication/use-patch-session.d.ts +12 -1
  63. package/dist/shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.d.ts +4 -1
  64. package/dist/shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js +5 -6
  65. package/dist/shared/api/storefront/hooks/product/use-mark-product-as-viewed.d.ts +2 -0
  66. package/dist/shared/api/storefront/hooks/product/use-mark-product-as-viewed.js +17 -0
  67. package/dist/shared/api/storefront/model/storefront.model.d.ts +4 -1
  68. package/dist/shared/api/storefront/services/customer-service.d.ts +5 -1
  69. package/dist/shared/api/storefront/services/customer-service.js +3 -3
  70. package/dist/shared/api/storefront/services/product-service.d.ts +4 -0
  71. package/dist/shared/api/storefront/services/product-service.js +10 -0
  72. package/dist/shared/feature-flags/use-feature-flags.d.ts +0 -3
  73. package/dist/shared/feature-flags/use-feature-flags.js +0 -3
  74. package/dist/shared/fetch/request.d.ts +1 -1
  75. package/dist/shared/ga/google-analytics-provider.d.ts +1 -1
  76. package/dist/shared/hooks/use-intersection-observer.d.ts +2 -1
  77. package/dist/shared/hooks/use-intersection-observer.js +3 -2
  78. package/dist/styles.css +228 -101
  79. package/dist/text/highlight-text/highlight-text.d.ts +10 -0
  80. package/dist/text/highlight-text/highlight-text.js +19 -0
  81. package/dist/text/highlight-text/highlight-text.module.css.js +3 -0
  82. package/dist/typography/heading/heading.d.ts +3 -1
  83. package/dist/typography/heading/heading.js +2 -1
  84. package/package.json +2 -1
  85. package/dist/icons/solid/solid-dashboard-icon.js +0 -7
  86. package/dist/pages/my-account/navigation/connected-my-account-navigation.d.ts +0 -1
  87. package/dist/pages/my-account/navigation/my-account-desktop-navigation.d.ts +0 -6
  88. package/dist/pages/my-account/navigation/my-account-desktop-navigation.js +0 -17
  89. package/dist/pages/my-account/navigation/my-account-desktop-navigation.module.css.js +0 -3
  90. package/dist/pages/my-account/navigation/my-account-mobile-navigation.js +0 -25
  91. package/dist/pages/my-account/widgets/connected-company-information-widget.d.ts +0 -1
  92. package/dist/pages/my-account/widgets/connected-company-information-widget.js +0 -43
  93. package/dist/pages/product/product-details-page/components/product-details-recently-viewed/product-details-recently-viewed.d.ts +0 -4
  94. package/dist/pages/product/product-details-page/components/product-details-recently-viewed/product-details-recently-viewed.js +0 -15
  95. /package/dist/pages/{my-account → my-sonic}/widgets/components/address-data-card.d.ts +0 -0
  96. /package/dist/pages/{my-account → my-sonic}/widgets/components/address-data-card.js +0 -0
  97. /package/dist/pages/{my-account → my-sonic}/widgets/connected-bill-to-address-widget.d.ts +0 -0
  98. /package/dist/pages/{my-account → my-sonic}/widgets/connected-bill-to-address-widget.js +0 -0
  99. /package/dist/pages/{my-account → my-sonic}/widgets/connected-ship-to-address-widget.d.ts +0 -0
  100. /package/dist/pages/{my-account → my-sonic}/widgets/connected-ship-to-address-widget.js +0 -0
  101. /package/dist/pages/{my-account → my-sonic}/widgets/connected-user-account-widget.d.ts +0 -0
  102. /package/dist/pages/{my-account → my-sonic}/widgets/connected-user-account-widget.js +0 -0
@@ -1,8 +1,16 @@
1
1
  import { ReactNode } from 'react';
2
2
  interface IntersectionObserverProps {
3
+ /** The content to render when the observer is intersecting */
3
4
  children: ReactNode;
5
+ /** Options for the IntersectionObserver */
6
+ intersectionObserverInit?: IntersectionObserverInit;
7
+ /** Whether the observer is disabled */
4
8
  isDisabled?: boolean;
9
+ /** Whether the observer is a placeholder.
10
+ * Once intersected the observer is replaced by its children */
11
+ isPlaceholder?: boolean;
12
+ /** Callback when the intersection state changes */
5
13
  onIntersectingChange?: (isIntersecting: boolean) => void;
6
14
  }
7
- export declare function IntersectionObserverComponent({ children, isDisabled, onIntersectingChange, }: IntersectionObserverProps): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | null | undefined;
15
+ export declare function IntersectionObserverComponent({ children, intersectionObserverInit, isDisabled, isPlaceholder, onIntersectingChange, }: IntersectionObserverProps): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | null | undefined;
8
16
  export {};
@@ -3,17 +3,20 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { useRef } from 'react';
4
4
  import { useIntersectionObserver } from '../shared/hooks/use-intersection-observer.js';
5
5
 
6
- function IntersectionObserverComponent({ children, isDisabled, onIntersectingChange, }) {
6
+ function IntersectionObserverComponent({ children, intersectionObserverInit, isDisabled, isPlaceholder = false, onIntersectingChange, }) {
7
7
  const topRef = useRef(null);
8
8
  const bottomRef = useRef(null);
9
- useIntersectionObserver({
9
+ const { isIntersecting } = useIntersectionObserver({
10
+ intersectionObserverInit,
10
11
  isDisabled,
11
12
  observables: [{ ref: topRef }, { ref: bottomRef }],
12
13
  onIntersectingChange,
13
14
  });
14
15
  if (isDisabled)
15
16
  return children;
16
- return (jsxs("div", { children: [jsx("div", { ref: topRef }), children, jsx("div", { ref: bottomRef })] }));
17
+ if (isIntersecting && isPlaceholder)
18
+ return children;
19
+ return (jsxs("div", { "data-intersecting": isIntersecting, style: { display: 'contents' }, children: [jsx("div", { ref: topRef, "aria-hidden": true, "data-role": "top of intersection observer" }), isIntersecting && children, jsx("div", { ref: bottomRef, "aria-hidden": true, "data-role": "bottom of intersection observer" })] }));
17
20
  }
18
21
 
19
22
  export { IntersectionObserverComponent };
@@ -7,6 +7,7 @@ import { useCountries } from '../../../../country-select/hooks/use-countries.js'
7
7
  import { Form } from '../../../../forms/form/form.js';
8
8
  import { FormSegment } from '../../../../forms/form/form-segment.js';
9
9
  import { FormSegmentGroup } from '../../../../forms/form/form-segment-group.js';
10
+ import { PasswordField } from '../../../../forms/password-field/password-field.js';
10
11
  import { SwitchField } from '../../../../forms/switch-field/switch-field.js';
11
12
  import { TextField } from '../../../../forms/text-field/text-field.js';
12
13
  import { isCountryCode } from '../../../../intl/types.js';
@@ -78,12 +79,12 @@ function CreateAccountForm({ errorType, isDisabled: _isDisabled = false, isPendi
78
79
  if (!value)
79
80
  return value;
80
81
  return (validateEmail(value) || t('Please enter a valid email address'));
81
- } }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "new-password", "data-test-selector": "createAccount_password", info: "Password must be at least 8 characters long, include at least one number, at least one lowercase character, at least one uppercase character and at least one non-alphanumeric character.", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", onChange: setPassword, type: "password", validate: value => {
82
+ } }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "new-password", "data-test-selector": "createAccount_password", info: "Password must be at least 8 characters long, include at least one number, at least one lowercase character, at least one uppercase character and at least one non-alphanumeric character.", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", onChange: setPassword, validate: value => {
82
83
  if (!value)
83
84
  return;
84
85
  return (validatePassword(value) ||
85
86
  t('Password does not meet requirements'));
86
- } }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "new-password", customErrorMessage: "Passwords do not match", "data-test-selector": "createAccount_passwordConfirm", isDisabled: isDisabled, isInvalid: isMismatchingPasswords(), isRequired: true, label: t('Confirm password'), onChange: setPasswordConfirm, type: "password", value: passwordConfirm }) })] }), jsxs(FormSegmentGroup, { children: [jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, isSelected: isPrivateAccount, name: "isPrivateAccount", onChange: setIsPrivateAccount, children: t('Private account') }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "organization", "data-test-selector": "createAccount_companyName", isDisabled: isDisabled, isRequired: !isPrivateAccount, label: t('Company name'), name: "companyName", onChange: setCompanyName, value: companyName }, `companyName-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "given-name", "data-test-selector": "createAccount_firstName", isDisabled: isDisabled, label: t('First name'), name: "firstName" }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "family-name", "data-test-selector": "createAccount_lastName", isDisabled: isDisabled, isRequired: isPrivateAccount, label: t('Last name'), name: "lastName", onChange: setLastName, value: lastName }, `lastname-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(CountrySelect, { isRequired: true, countries: countries || [], "data-test-selector": "createAccount_countrySelect", defaultSelectedCountry: defaultSelectedCountry, isDisabled: isLoadingCountries || isDisabled, isLoading: isLoadingCountries, name: "countrySelect" }, defaultSelectedCountry?.id) })] }), jsx(FormSegmentGroup, { children: jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, name: "isSubscribed", children: t('Sign me up for newsletters and product updates') }) }) })] }));
87
+ } }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "new-password", customErrorMessage: "Passwords do not match", "data-test-selector": "createAccount_passwordConfirm", isDisabled: isDisabled, isInvalid: isMismatchingPasswords(), isRequired: true, label: t('Confirm password'), onChange: setPasswordConfirm, value: passwordConfirm }) })] }), jsxs(FormSegmentGroup, { children: [jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, isSelected: isPrivateAccount, name: "isPrivateAccount", onChange: setIsPrivateAccount, children: t('Private account') }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "organization", "data-test-selector": "createAccount_companyName", isDisabled: isDisabled, isRequired: !isPrivateAccount, label: t('Company name'), name: "companyName", onChange: setCompanyName, value: companyName }, `companyName-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "given-name", "data-test-selector": "createAccount_firstName", isDisabled: isDisabled, label: t('First name'), name: "firstName" }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "family-name", "data-test-selector": "createAccount_lastName", isDisabled: isDisabled, isRequired: isPrivateAccount, label: t('Last name'), name: "lastName", onChange: setLastName, value: lastName }, `lastname-${Boolean(isPrivateAccount)}`) }), jsx(FormSegment, { children: jsx(CountrySelect, { isRequired: true, countries: countries || [], "data-test-selector": "createAccount_countrySelect", defaultSelectedCountry: defaultSelectedCountry, isDisabled: isLoadingCountries || isDisabled, isLoading: isLoadingCountries, name: "countrySelect" }, defaultSelectedCountry?.id) })] }), jsx(FormSegmentGroup, { children: jsx(FormSegment, { children: jsx(SwitchField, { isDisabled: isDisabled, name: "isSubscribed", children: t('Sign me up for newsletters and product updates') }) }) })] }));
87
88
  }
88
89
 
89
90
  export { CreateAccountForm };
@@ -5,6 +5,7 @@ import { Link } from '../../../../buttons/link/link.js';
5
5
  import { Form } from '../../../../forms/form/form.js';
6
6
  import { FormSegment } from '../../../../forms/form/form-segment.js';
7
7
  import { FormSegmentGroup } from '../../../../forms/form/form-segment-group.js';
8
+ import { PasswordField } from '../../../../forms/password-field/password-field.js';
8
9
  import { SwitchField } from '../../../../forms/switch-field/switch-field.js';
9
10
  import { TextField } from '../../../../forms/text-field/text-field.js';
10
11
  import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
@@ -64,7 +65,7 @@ function SignInForm({ allowGuestSignIn = false, createAccountPath, errorType, in
64
65
  if (!value)
65
66
  return value;
66
67
  return (validateEmail(value) || t('Please enter a valid email address'));
67
- } }) }), jsx(FormSegment, { children: jsx(TextField, { autoComplete: "current-password", "data-test-selector": "signIn_password", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", showLabel: true, type: "password" }) })] }) }));
68
+ } }) }), jsx(FormSegment, { children: jsx(PasswordField, { autoComplete: "current-password", "data-test-selector": "signIn_password", isDisabled: isDisabled, isRequired: true, label: t('Password'), name: "password", showLabel: true }) })] }) }));
68
69
  }
69
70
 
70
71
  export { SignInForm };
@@ -0,0 +1,15 @@
1
+ import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
2
+ export interface ChangeCustomerDialogProps {
3
+ currentlySelectedCustomerId?: string;
4
+ data?: BillToCollectionModel;
5
+ error?: Error | null | unknown;
6
+ filter?: string;
7
+ hasErrorSubmitting?: boolean;
8
+ isLoading?: boolean;
9
+ isOpen: boolean;
10
+ isUpdating?: boolean;
11
+ onClose: () => void;
12
+ onCustomerSelected: (id: string) => void;
13
+ onFilterChanged?: (filter: string) => void;
14
+ }
15
+ export declare function ChangeCustomerDialog({ currentlySelectedCustomerId, data, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating, onClose, onCustomerSelected, onFilterChanged, }: ChangeCustomerDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { FormattedMessage } from '../../../../intl/formatted-message.js';
4
+ import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
5
+ import { Message } from '../../../../message/message.js';
6
+ import { Dialog } from '../../../../modals/dialog/dialog.js';
7
+ import { ChangeCustomer } from './change-customer.js';
8
+ import styles from './change-customer-dialog.module.css.js';
9
+
10
+ function ChangeCustomerDialog({ currentlySelectedCustomerId, data, error, filter, hasErrorSubmitting, isLoading, isOpen, isUpdating = false, onClose, onCustomerSelected, onFilterChanged, }) {
11
+ const t = useFormattedMessage();
12
+ const [hasCustomerSelected, setHasCustomerSelected] = useState(false);
13
+ const [selectedCustomerId, setSelectedCustomerId] = useState();
14
+ return (jsx(Dialog, { allowSubmit: !hasErrorSubmitting && hasCustomerSelected, className: styles['change-customer-dialog'], isOpen: isOpen, isSubmitting: isUpdating || hasErrorSubmitting, onOpenChange: isOpen => !isOpen && onClose(), onSubmit: () => selectedCustomerId && onCustomerSelected(selectedCustomerId), title: t('Change customer'), children: hasErrorSubmitting ? (jsx(Message, { className: styles.error, type: "danger", children: jsx(FormattedMessage, { id: "An error occurred while changing the customer." }) })) : (jsx(ChangeCustomer, { className: styles.content, data: data, error: error, filter: filter, isLoading: isLoading, onCustomerSelected: id => {
15
+ setSelectedCustomerId(id);
16
+ onCustomerSelected(id);
17
+ }, onCustomerSelectionChanged: id => {
18
+ setSelectedCustomerId(id);
19
+ setHasCustomerSelected(true);
20
+ }, onFilterChanged: onFilterChanged, selectedId: currentlySelectedCustomerId })) }));
21
+ }
22
+
23
+ export { ChangeCustomerDialog };
@@ -0,0 +1,3 @@
1
+ var styles = {"change-customer-dialog":"change-customer-dialog-module-O6oOS","content":"change-customer-dialog-module-OP23q"};
2
+
3
+ export { styles as default };
@@ -0,0 +1,13 @@
1
+ import { BillToCollectionModel } from '../../../../shared/api/storefront/model/storefront.model';
2
+ export interface ChangeCustomerProps {
3
+ className?: string;
4
+ data?: BillToCollectionModel;
5
+ error?: Error | null | unknown;
6
+ filter?: string;
7
+ isLoading?: boolean;
8
+ onCustomerSelected?: (id: string) => void;
9
+ onCustomerSelectionChanged?: (id: string) => void;
10
+ onFilterChanged?: (filter: string) => void;
11
+ selectedId?: string;
12
+ }
13
+ export declare function ChangeCustomer({ className, data, error, filter, isLoading, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged, selectedId, }: ChangeCustomerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useRef, useMemo } from 'react';
3
+ import { ListBox, ListBoxItem, Text } from 'react-aria-components';
4
+ import clsx from 'clsx';
5
+ import { SearchField } from '../../../../forms/search-field/search-field.js';
6
+ import { SolidRatingIcon } from '../../../../icons/solid/solid-rating-icon.js';
7
+ import { FormattedMessage } from '../../../../intl/formatted-message.js';
8
+ import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
9
+ import { Message } from '../../../../message/message.js';
10
+ import { UnauthorizedRequestError } from '../../../../shared/fetch/request.js';
11
+ import { HighlightText } from '../../../../text/highlight-text/highlight-text.js';
12
+ import styles from './change-customer.module.css.js';
13
+
14
+ const DEFAULT_PAGE_SIZE = 20;
15
+ function ChangeCustomer({ className, data, error, filter = '', isLoading = false, onCustomerSelected, onCustomerSelectionChanged, onFilterChanged, selectedId, }) {
16
+ const t = useFormattedMessage();
17
+ const listBoxRef = useRef(null);
18
+ const hasMoreResults = !isLoading &&
19
+ data?.pagination &&
20
+ data.pagination.totalItemCount > DEFAULT_PAGE_SIZE;
21
+ const listBoxItems = useMemo(() => {
22
+ const listBoxItems = [...(data?.billTos || [])];
23
+ if (error instanceof UnauthorizedRequestError) {
24
+ listBoxItems.push({
25
+ id: 'message',
26
+ message: t('You are not authorized to view customers. Please log in or contact support.'),
27
+ type: 'danger',
28
+ });
29
+ }
30
+ else if (error) {
31
+ listBoxItems.push({
32
+ id: 'message',
33
+ message: t('An error occurred while fetching customers. Please try again later.'),
34
+ type: 'danger',
35
+ });
36
+ }
37
+ else if (hasMoreResults) {
38
+ listBoxItems.push({
39
+ id: 'message',
40
+ message: t('There are more customers, please refine your search if needed.'),
41
+ type: 'warning',
42
+ });
43
+ }
44
+ return listBoxItems;
45
+ }, [data?.billTos, error, hasMoreResults, t]);
46
+ return (jsxs("div", { className: clsx(styles['change-customer-container'], className), children: [jsx(SearchField, { autoFocus: true, isDebounced: true, "aria-controls": "filtered-customer-results-list", isLoading: isLoading, label: t('Search for a customer'), onChange: onFilterChanged, onKeyUp: ({ key }) => {
47
+ if (key === 'ArrowDown') {
48
+ listBoxRef.current?.focus();
49
+ }
50
+ }, placeholder: t('Search for a customer'), showLabel: false, size: "md", value: filter, variant: "outline" }), jsx(ListBox, { ref: listBoxRef, "aria-label": "List of customers", "aria-live": "polite", className: styles['list-box'], id: "filtered-customer-results-list", items: listBoxItems, onAction: key => onCustomerSelected?.(String(key)), onSelectionChange: keys => onCustomerSelectionChanged?.(String([...keys][0])), renderEmptyState: () => !isLoading && (jsx(Message, { type: "info", children: jsx(FormattedMessage, { id: "No results found. Please refine your search." }) })), selectionBehavior: "replace", selectionMode: "single", children: listBoxItem => 'type' in listBoxItem ? (jsx(ListBoxItem, { isDisabled: true, children: jsx(Message, { type: listBoxItem.type, children: listBoxItem.message }) }, "marker")) : (jsxs(ListBoxItem, { className: styles['list-box-item'], id: listBoxItem.id, children: [jsxs(Text, { slot: "label", children: [jsxs("div", { className: styles['company-name'], children: [jsx(HighlightText, { className: styles['company-name-text'], highlightText: filter, text: `${listBoxItem.companyName}` }), selectedId === listBoxItem.id && (jsx(SolidRatingIcon, { className: styles['selected-icon'] }))] }), jsx(HighlightText, { className: styles['customer-number'], highlightText: filter, text: `${listBoxItem.customerNumber}` })] }), jsxs(Text, { slot: "description", children: [jsx("div", { children: jsx(HighlightText, { highlightText: filter, text: [
51
+ [listBoxItem.firstName, listBoxItem.lastName].join(' '),
52
+ ]
53
+ .filter(Boolean)
54
+ .join(', ') }) }), jsx("div", { children: jsx(HighlightText, { highlightText: filter, text: [
55
+ listBoxItem.address1,
56
+ listBoxItem.address2,
57
+ listBoxItem.address3,
58
+ listBoxItem.address4,
59
+ ]
60
+ .filter(Boolean)
61
+ .join(', ') }) }), jsx(HighlightText, { highlightText: filter, text: [listBoxItem.postalCode, listBoxItem.country?.name]
62
+ .filter(Boolean)
63
+ .join(', ') })] })] }, listBoxItem.id)) })] }));
64
+ }
65
+
66
+ export { ChangeCustomer };
@@ -0,0 +1,3 @@
1
+ var styles = {"change-customer-container":"change-customer-module-2kOw4","list-box":"change-customer-module-StfiY","list-box-item":"change-customer-module-P7ouY","company-name":"change-customer-module-DSVPN","company-name-text":"change-customer-module-4KQoq","customer-number":"change-customer-module-4p6ab"};
2
+
3
+ export { styles as default };
@@ -0,0 +1,2 @@
1
+ import { ChangeCustomerDialogProps } from './change-customer-dialog';
2
+ export declare function ConnectedChangeCustomerDialog({ currentlySelectedCustomerId, isOpen, onClose, onCustomerSelected, }: ChangeCustomerDialogProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,39 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { usePatchSession } from '../../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
4
+ import { useFetchBillToAddresses } from '../../../../shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js';
5
+ import { ChangeCustomerDialog } from './change-customer-dialog.js';
6
+
7
+ function ConnectedChangeCustomerDialog({ currentlySelectedCustomerId, isOpen, onClose, onCustomerSelected, }) {
8
+ const [filter, setFilter] = useState('');
9
+ const { error: errorMutation, isLoading: isMutating, mutate, } = usePatchSession();
10
+ const { data, error, isFetching, isLoading } = useFetchBillToAddresses({
11
+ filter,
12
+ isEnabled: isOpen,
13
+ });
14
+ return (jsx(ChangeCustomerDialog, { currentlySelectedCustomerId: currentlySelectedCustomerId, data: data, error: error, filter: filter, hasErrorSubmitting: Boolean(errorMutation), isLoading: isLoading || isFetching, isOpen: isOpen, isUpdating: isMutating, onClose: onClose, onCustomerSelected: async (id) => {
15
+ id = `${id}`;
16
+ try {
17
+ await mutate({
18
+ session: {
19
+ billTo: {
20
+ id,
21
+ isDefault: false,
22
+ },
23
+ billToId: id,
24
+ customerWasUpdated: false,
25
+ fulfillmentMethod: 'Ship',
26
+ pickUpWarehouse: null,
27
+ shipTo: { id },
28
+ shipToId: id,
29
+ },
30
+ });
31
+ onCustomerSelected(id);
32
+ }
33
+ catch {
34
+ // Handle error if needed
35
+ }
36
+ }, onFilterChanged: setFilter }));
37
+ }
38
+
39
+ export { ConnectedChangeCustomerDialog };
@@ -0,0 +1 @@
1
+ export declare function ConnectedMySonicNavigation(): import("react/jsx-runtime").JSX.Element;
@@ -6,10 +6,10 @@ import { useIsBreakpoint } from '../../../shared/hooks/use-is-breakpoint.js';
6
6
  import { useLocation } from '../../../shared/routing/use-location.js';
7
7
  import { useNavigate } from '../../../shared/routing/use-navigate.js';
8
8
  import { PATHS } from '../../paths.js';
9
- import { MyAccountDesktopNavigation } from './my-account-desktop-navigation.js';
10
- import { MyAccountMobileNavigation } from './my-account-mobile-navigation.js';
9
+ import { MySonicDesktopNavigation } from './my-sonic-desktop-navigation.js';
10
+ import { MySonicMobileNavigation } from './my-sonic-mobile-navigation.js';
11
11
 
12
- function ConnectedMyAccountNavigation() {
12
+ function ConnectedMySonicNavigation() {
13
13
  const isXl = useIsBreakpoint('xl');
14
14
  const { pathname } = useLocation();
15
15
  const { navigate } = useNavigate();
@@ -21,7 +21,7 @@ function ConnectedMyAccountNavigation() {
21
21
  navigate(PATHS.HOME, { reload: true });
22
22
  },
23
23
  });
24
- return (jsx("div", { style: { display: 'grid' }, children: isXl ? (jsx(MyAccountDesktopNavigation, { currentPath: pathname, onLogout: mutate })) : (jsx(MyAccountMobileNavigation, { currentPath: pathname, onLogout: mutate })) }));
24
+ return (jsx("div", { style: { display: 'grid' }, children: isXl ? (jsx(MySonicDesktopNavigation, { currentPath: pathname, onLogout: mutate })) : (jsx(MySonicMobileNavigation, { currentPath: pathname, onLogout: mutate })) }));
25
25
  }
26
26
 
27
- export { ConnectedMyAccountNavigation };
27
+ export { ConnectedMySonicNavigation };
@@ -0,0 +1,6 @@
1
+ interface MySonicDesktopNavigationProps {
2
+ currentPath?: string;
3
+ onLogout?: VoidFunction;
4
+ }
5
+ export declare function MySonicDesktopNavigation({ currentPath, onLogout, }: MySonicDesktopNavigationProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,19 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { FormattedMessage } from '../../../intl/formatted-message.js';
3
+ import { MenuList } from '../../../lists/menu-list/menu-list.js';
4
+ import { MenuListItem } from '../../../lists/menu-list/menu-list-item.js';
5
+ import { mySonicNavigationItems } from './my-sonic-navigation-items.js';
6
+ import styles from './my-sonic-desktop-navigation.module.css.js';
7
+
8
+ function MySonicDesktopNavigation({ currentPath, onLogout, }) {
9
+ return (jsx(MenuList, { children: mySonicNavigationItems.map(item => (jsx(MenuListItem, { hasChildren: true, badge: jsx(item.Icon, {}), ...(item.type === 'action'
10
+ ? item.action === 'logout'
11
+ ? { onClick: onLogout }
12
+ : {}
13
+ : {
14
+ href: item.path,
15
+ isSelected: currentPath?.toLowerCase() === item.path,
16
+ }), children: jsx("span", { className: styles['menu-list-item'], children: jsx(FormattedMessage, { id: item.label }) }) }, item.label))) }));
17
+ }
18
+
19
+ export { MySonicDesktopNavigation };
@@ -0,0 +1,3 @@
1
+ var styles = {"menu-list-item":"my-sonic-desktop-navigation-module-f8Y3F"};
2
+
3
+ export { styles as default };
@@ -1,4 +1,4 @@
1
- export declare function MyAccountMobileNavigation({ currentPath, onLogout, }: {
1
+ export declare function MySonicMobileNavigation({ currentPath, onLogout, }: {
2
2
  currentPath?: string;
3
3
  onLogout: () => void;
4
4
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Select } from '../../../forms/select/select.js';
3
+ import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
4
+ import { useNavigate } from '../../../shared/routing/use-navigate.js';
5
+ import { mySonicNavigationItems } from './my-sonic-navigation-items.js';
6
+
7
+ function MySonicMobileNavigation({ currentPath, onLogout, }) {
8
+ const { navigate } = useNavigate();
9
+ const t = useFormattedMessage();
10
+ return (jsx(Select, { label: t('Navigate to...'), onChange: option => {
11
+ if (option === 'logout')
12
+ return onLogout();
13
+ return navigate(option);
14
+ }, options: mySonicNavigationItems.reduce((options, item) => ({
15
+ ...options,
16
+ ...(item.type === 'link'
17
+ ? { [item.path]: t(item.label) }
18
+ : { [item.action]: t(item.label) }),
19
+ }), {}), selectedOption: currentPath?.toLowerCase() }));
20
+ }
21
+
22
+ export { MySonicMobileNavigation };
@@ -0,0 +1,18 @@
1
+ import { ComponentType } from 'react';
2
+ import { TranslationId } from '../../../intl/translation-id';
3
+ interface MySonicNavigationItemBase {
4
+ Icon: ComponentType;
5
+ label: TranslationId;
6
+ type: 'link' | 'action';
7
+ }
8
+ interface MySonicNavigationLink extends MySonicNavigationItemBase {
9
+ path: Lowercase<string>;
10
+ type: 'link';
11
+ }
12
+ interface MySonicNavigationAction extends MySonicNavigationItemBase {
13
+ action: string;
14
+ type: 'action';
15
+ }
16
+ type MySonicNavigationItem = MySonicNavigationLink | MySonicNavigationAction;
17
+ export declare const mySonicNavigationItems: MySonicNavigationItem[];
18
+ export {};
@@ -0,0 +1,29 @@
1
+ import { SolidCartIcon } from '../../../icons/solid/solid-cart-icon.js';
2
+ import { SolidFavoriteIcon } from '../../../icons/solid/solid-favorite-icon.js';
3
+ import { SolidLoginIcon } from '../../../icons/solid/solid-login-icon.js';
4
+ import { SolidLogOutIcon } from '../../../icons/solid/solid-logout-icon.js';
5
+ import { PATHS } from '../../paths.js';
6
+
7
+ const mySonicNavigationItems = [
8
+ {
9
+ Icon: SolidLoginIcon,
10
+ label: 'Account',
11
+ path: PATHS.ACCOUNT_SETTINGS.toLowerCase(),
12
+ type: 'link',
13
+ },
14
+ {
15
+ Icon: SolidFavoriteIcon,
16
+ label: 'Favorites',
17
+ path: PATHS.ACCOUNT_MY_LISTS.toLowerCase(),
18
+ type: 'link',
19
+ },
20
+ {
21
+ Icon: SolidCartIcon,
22
+ label: 'Orders',
23
+ path: PATHS.ACCOUNT_ORDERS.toLowerCase(),
24
+ type: 'link',
25
+ },
26
+ { Icon: SolidLogOutIcon, action: 'logout', label: 'Log out', type: 'action' },
27
+ ];
28
+
29
+ export { mySonicNavigationItems };
@@ -0,0 +1 @@
1
+ export declare function ConnectedCustomerInformationWidget(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,56 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { Button } from '../../../buttons/button/button.js';
4
+ import { DataCard } from '../../../cards/data-card/data-card.js';
5
+ import { FormattedMessage } from '../../../intl/formatted-message.js';
6
+ import { useFetchBillToAddresses } from '../../../shared/api/storefront/hooks/customer/use-fetch-bill-to-addresses.js';
7
+ import { useFetchCurrentBillToAddress } from '../../../shared/api/storefront/hooks/customer/use-fetch-current-bill-to-address.js';
8
+ import { ConnectedChangeCustomerDialog } from '../actions/change-customer/connected-change-customer-dialog.js';
9
+
10
+ function ConnectedCustomerInformationWidget() {
11
+ const [isOpenChangeCustomerDialog, setIsOpenChangeCustomerDialog] = useState(false);
12
+ const { data: billToAddress, error: fetchBillToAddressError, isLoading: isLoadingFetchCurrentBillToAddress, } = useFetchCurrentBillToAddress();
13
+ const { data: billToAddresses, error: fetchBillToAddressesError, isLoading: isLoadingFetchBillToAddresses, } = useFetchBillToAddresses();
14
+ const hasBillToAddresses = Boolean(billToAddresses?.pagination?.totalItemCount);
15
+ const data = billToAddress
16
+ ? [
17
+ {
18
+ key: 'company-name',
19
+ label: 'Company name',
20
+ value: billToAddress.companyName,
21
+ },
22
+ {
23
+ key: 'coc-number',
24
+ label: 'CoC number',
25
+ value: billToAddress.properties.cocRegistration,
26
+ },
27
+ {
28
+ key: 'billing',
29
+ label: 'Billing',
30
+ value: [
31
+ billToAddress.address1,
32
+ billToAddress.address2,
33
+ billToAddress.address3,
34
+ billToAddress.address4,
35
+ billToAddress.postalCode,
36
+ billToAddress.city,
37
+ billToAddress.country?.abbreviation,
38
+ ]
39
+ .filter(Boolean)
40
+ .join(', ') || null,
41
+ },
42
+ ]
43
+ : [];
44
+ function onChangeCustomer() {
45
+ setIsOpenChangeCustomerDialog(true);
46
+ }
47
+ return (jsxs(Fragment, { children: [jsx(DataCard, { actions: hasBillToAddresses
48
+ ? [
49
+ jsx(Button, { color: "secondary", onClick: onChangeCustomer, size: "sm", variant: "outline", children: jsx(FormattedMessage, { id: "Select other customer" }) }, "edit"),
50
+ ]
51
+ : undefined, data: data, "data-test-selector": "customer-information-widget", isLoading: isLoadingFetchCurrentBillToAddress || isLoadingFetchBillToAddresses, showError: fetchBillToAddressError || fetchBillToAddressesError, title: "Selected customer" }), hasBillToAddresses && (jsx(ConnectedChangeCustomerDialog, { isOpen: isOpenChangeCustomerDialog, onClose: () => setIsOpenChangeCustomerDialog(false), onCustomerSelected: () => {
52
+ window?.location.reload();
53
+ } }, billToAddress?.id))] }));
54
+ }
55
+
56
+ export { ConnectedCustomerInformationWidget };
@@ -2,8 +2,8 @@ interface ProductDetailsPageLayoutProps {
2
2
  imageGallery?: React.ReactNode;
3
3
  included?: React.ReactNode;
4
4
  productInformation?: React.ReactNode;
5
- recentlyViewed?: React.ReactNode;
5
+ recentlyViewedSection?: React.ReactNode;
6
6
  usp?: React.ReactNode;
7
7
  }
8
- export declare function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewed, usp, }: ProductDetailsPageLayoutProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewedSection, usp, }: ProductDetailsPageLayoutProps): import("react/jsx-runtime").JSX.Element;
9
9
  export {};
@@ -1,8 +1,9 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { IntersectionObserverComponent } from '../../../../observers/intersection-observer.js';
2
3
  import styles from './product-details-page-layout.module.css.js';
3
4
 
4
- function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewed, usp, }) {
5
- return (jsxs("div", { className: styles['product-details-page-layout'], children: [jsxs("section", { className: styles.top, children: [jsx("div", { className: styles['image-gallery'], children: imageGallery }), jsx("div", { className: styles['product-information'], "data-test-selector": "productInformation", children: productInformation })] }), jsx("section", { className: styles.usp, "data-test-selector": "usp", children: usp }), jsx("section", { className: styles.included, "data-test-selector": "included", children: included }), jsx("section", { className: styles['recently-viewed'], "data-test-selector": "recentlyViewed", children: recentlyViewed })] }));
5
+ function ProductDetailsPageLayout({ imageGallery, included, productInformation, recentlyViewedSection, usp, }) {
6
+ return (jsxs("div", { className: styles['product-details-page-layout'], children: [jsxs("section", { className: styles.top, children: [jsx("div", { className: styles['image-gallery'], children: imageGallery }), jsx("div", { className: styles['product-information'], "data-test-selector": "productInformation", children: productInformation })] }), usp && (jsx("section", { className: styles.usp, "data-test-selector": "usp", children: usp })), included && (jsx("section", { className: styles.included, "data-test-selector": "included", children: included })), jsx(IntersectionObserverComponent, { isPlaceholder: true, intersectionObserverInit: { rootMargin: '400px' }, children: recentlyViewedSection })] }));
6
7
  }
7
8
 
8
9
  export { ProductDetailsPageLayout };
@@ -1,3 +1,3 @@
1
- var styles = {"product-details-page-layout":"product-details-page-layout-module-pPtZX","top":"product-details-page-layout-module-KCKLZ","image-gallery":"product-details-page-layout-module-0uf92","product-information":"product-details-page-layout-module-3-19O","recently-viewed":"product-details-page-layout-module-Cl9u-","included":"product-details-page-layout-module-lfAgH","usp":"product-details-page-layout-module-e8ZNQ"};
1
+ var styles = {"product-details-page-layout":"product-details-page-layout-module-pPtZX","top":"product-details-page-layout-module-KCKLZ","image-gallery":"product-details-page-layout-module-0uf92","product-information":"product-details-page-layout-module-3-19O","included":"product-details-page-layout-module-lfAgH","usp":"product-details-page-layout-module-e8ZNQ"};
2
2
 
3
3
  export { styles as default };
@@ -0,0 +1 @@
1
+ export declare function ProductDetailsRecentlyViewedSection(): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,24 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { ConnectedProductCard } from '../../../../../cards/product-card/connected-product-card.js';
3
+ import { CardCarousel } from '../../../../../carousel/card-carousel/card-carousel.js';
4
+ import { FormattedMessage } from '../../../../../intl/formatted-message.js';
5
+ import { useCultureCode } from '../../../../../intl/use-culture-code.js';
6
+ import { useFetchRecentlyViewedProducts } from '../../../../../shared/api/bff/hooks/use-fetch-recently-viewed-products.js';
7
+ import { Heading } from '../../../../../typography/heading/heading.js';
8
+ import styles from './product-details-recently-viewed-section.module.css.js';
9
+
10
+ function ProductDetailsRecentlyViewedSection() {
11
+ const cultureCode = useCultureCode();
12
+ const { data: products, isLoading } = useFetchRecentlyViewedProducts({
13
+ cultureCode,
14
+ });
15
+ if (isLoading || !products || products.length === 0)
16
+ return null;
17
+ return (jsxs("section", { className: styles['recently-viewed'], "data-test-selector": "recentlyViewed", children: [jsx(Heading, { size: "s", tag: "h2", children: jsx(FormattedMessage, { id: "Recently viewed" }) }), jsx(CardCarousel, { hasOverflow: true, cards: products.map(product => (jsx(ConnectedProductCard, { href: product.href, id: product.productId, image: {
18
+ fit: 'contain',
19
+ image: product.image,
20
+ title: product.image?.altText || product.title,
21
+ }, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.productId))) })] }));
22
+ }
23
+
24
+ export { ProductDetailsRecentlyViewedSection };
@@ -0,0 +1,3 @@
1
+ var styles = {"recently-viewed":"product-details-recently-viewed-section-module-cGFgH"};
2
+
3
+ export { styles as default };
@@ -1,6 +1,5 @@
1
1
  import { ProductDetailsPageDataResponse } from '../../../shared/api/bff/model/bff.model';
2
- export declare function ProductDetails({ data, priceComponent, recentlyViewedComponent, }: {
2
+ export declare function ProductDetails({ data, priceComponent, }: {
3
3
  data: ProductDetailsPageDataResponse;
4
4
  priceComponent?: React.ReactNode;
5
- recentlyViewedComponent?: React.ReactNode;
6
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -10,10 +10,10 @@ import { Page } from '../../components/page/page.js';
10
10
  import { ProductDetailsPageLayout } from '../layouts/product-details-page-layout/product-details-page-layout.js';
11
11
  import { ProductDetailImages } from './components/product-details-images/product-detail-images.js';
12
12
  import { ProductDetailsPanel } from './components/product-details-panel/product-details-panel.js';
13
- import { ProductDetailsRecentlyViewed } from './components/product-details-recently-viewed/product-details-recently-viewed.js';
13
+ import { ProductDetailsRecentlyViewedSection } from './components/product-details-recently-viewed-section/product-details-recently-viewed-section.js';
14
14
 
15
- function ProductDetails({ data, priceComponent, recentlyViewedComponent, }) {
16
- const { breadCrumb, included, page, product, recentlyViewed, usps } = data;
15
+ function ProductDetails({ data, priceComponent, }) {
16
+ const { breadCrumb, included, page, product, usps } = data;
17
17
  useDataLayer({
18
18
  event: {
19
19
  event: 'view_item',
@@ -31,8 +31,7 @@ function ProductDetails({ data, priceComponent, recentlyViewedComponent, }) {
31
31
  fit: 'contain',
32
32
  image: product.image,
33
33
  title: product.image?.altText || product.title,
34
- }, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.storefrontId))) })] })), productInformation: jsx(ProductDetailsPanel, { priceComponent: priceComponent, product: product }), recentlyViewed: recentlyViewedComponent ||
35
- (recentlyViewed.length > 0 && (jsx(ProductDetailsRecentlyViewed, { recentlyViewed: recentlyViewed }))), usp: usps && jsx(ProductUSPCarousel, { usps: usps }) }) }));
34
+ }, price: product.price, sku: product.sku, tags: product.tags, title: product.title }, product.storefrontId))) })] })), productInformation: jsx(ProductDetailsPanel, { priceComponent: priceComponent, product: product }), recentlyViewedSection: jsx(ProductDetailsRecentlyViewedSection, {}), usp: usps && usps.length > 0 && jsx(ProductUSPCarousel, { usps: usps }) }) }));
36
35
  }
37
36
 
38
37
  export { ProductDetails };
@@ -1,11 +1,15 @@
1
- import { useQuery } from '@tanstack/react-query';
1
+ import { useQueryClient, useQuery } from '@tanstack/react-query';
2
2
  import { TIME } from '../../../utils/time.js';
3
3
  import { fetchProductDetailsPageData } from '../services/bff-service.js';
4
4
 
5
5
  function useFetchProductDetailsPageData(args) {
6
+ const queryClient = useQueryClient();
6
7
  return useQuery({
7
8
  gcTime: 1 * TIME.DAY,
8
- queryFn: () => fetchProductDetailsPageData(args),
9
+ queryFn: () => {
10
+ queryClient.removeQueries({ queryKey: ['products', 'recently-viewed'] });
11
+ return fetchProductDetailsPageData(args);
12
+ },
9
13
  queryKey: ['product-details-page-data', args.pageUrl, args.cultureCode],
10
14
  staleTime: 1 * TIME.DAY,
11
15
  });
@@ -0,0 +1,4 @@
1
+ import { CultureCode } from '../../../../intl/types';
2
+ export declare function useFetchRecentlyViewedProducts({ cultureCode, }: {
3
+ cultureCode: CultureCode;
4
+ }): import("@tanstack/react-query").UseQueryResult<import("../model/bff.model").ProductSummary[], Error>;