@sonic-equipment/ui 133.0.0 → 134.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 (66) hide show
  1. package/dist/algolia/{algolia-intialization.js → algolia-initialization.js} +7 -0
  2. package/dist/algolia/algolia-insights-provider.js +7 -0
  3. package/dist/algolia/algolia-search-provider.js +19 -0
  4. package/dist/algolia/use-algolia-insights.d.ts +13 -6
  5. package/dist/algolia/use-algolia-insights.js +93 -10
  6. package/dist/buttons/button/button.d.ts +4 -1
  7. package/dist/buttons/button/button.js +2 -2
  8. package/dist/country-selector/country-select/country-select.d.ts +1 -0
  9. package/dist/country-selector/country-select/country-select.js +2 -2
  10. package/dist/delivery-time/delivery-time.js +1 -1
  11. package/dist/exports.d.ts +7 -2
  12. package/dist/forms/checkbox/checkbox.d.ts +2 -1
  13. package/dist/forms/checkbox/checkbox.js +2 -2
  14. package/dist/forms/field-error/field-error.d.ts +2 -1
  15. package/dist/forms/field-error/field-error.js +3 -2
  16. package/dist/forms/input/input.d.ts +1 -0
  17. package/dist/forms/input/input.js +2 -2
  18. package/dist/forms/label/label.d.ts +3 -1
  19. package/dist/forms/label/label.js +3 -2
  20. package/dist/forms/switch/switch.d.ts +2 -1
  21. package/dist/forms/switch/switch.js +2 -2
  22. package/dist/forms/text-field/text-field.d.ts +3 -1
  23. package/dist/forms/text-field/text-field.js +4 -3
  24. package/dist/forms/text-field/text-field.module.css.js +1 -1
  25. package/dist/forms/textarea/textarea.d.ts +1 -0
  26. package/dist/forms/textarea/textarea.js +3 -2
  27. package/dist/global-search/plugins/categories-plugin.js +2 -1
  28. package/dist/global-search/plugins/popular-categories-plugin.js +2 -0
  29. package/dist/global-search/plugins/query-suggestions-plugin.js +1 -0
  30. package/dist/global-search/plugins/quick-access-plugin.js +2 -2
  31. package/dist/global-search/search-result-panel/sections/with-results.js +0 -1
  32. package/dist/index.js +8 -3
  33. package/dist/info-icon-tooltip/info-icon-tooltip.d.ts +7 -0
  34. package/dist/info-icon-tooltip/info-icon-tooltip.js +20 -0
  35. package/dist/info-icon-tooltip/info-icon-tooltip.module.css.js +3 -0
  36. package/dist/intl/translation-id.d.ts +1 -1
  37. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.d.ts +5 -0
  38. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +83 -0
  39. package/dist/pages/checkout/order-confirmation-page/order-confirmation-page.js +3 -77
  40. package/dist/pages/checkout/payment-page/components/payment.js +49 -4
  41. package/dist/pages/checkout/payment-page/payment-page-content.d.ts +15 -0
  42. package/dist/pages/checkout/payment-page/payment-page-content.js +43 -0
  43. package/dist/pages/checkout/payment-page/payment-page.js +3 -37
  44. package/dist/pages/checkout/shipping-page/components/edit-address.js +3 -3
  45. package/dist/pages/checkout/shipping-page/shipping-page-content.d.ts +14 -0
  46. package/dist/pages/checkout/shipping-page/shipping-page-content.js +40 -0
  47. package/dist/pages/checkout/shipping-page/shipping-page.js +45 -54
  48. package/dist/pages/product/product-details-page/components/product-details-panel/product-details-panel.js +11 -1
  49. package/dist/pages/product/product-listing-page/product-listing-product-overview/product-listing-product-overview.js +0 -1
  50. package/dist/pages/product/search-result-page/search-result-product-overview/search-result-product-overview.js +0 -1
  51. package/dist/shared/fetch/request.d.ts +18 -13
  52. package/dist/shared/fetch/request.js +22 -9
  53. package/dist/shared/ga/use-data-layer.d.ts +7 -3
  54. package/dist/shared/ga/use-data-layer.js +6 -1
  55. package/dist/shared/utils/promise.d.ts +2 -0
  56. package/dist/shared/utils/promise.js +9 -0
  57. package/dist/sign-in-form/sign-in-form.d.ts +19 -0
  58. package/dist/sign-in-form/sign-in-form.js +49 -0
  59. package/dist/sign-in-form/sign-in-form.module.css.js +3 -0
  60. package/dist/styles.css +192 -44
  61. package/dist/tooltip/tooltip.d.ts +3 -2
  62. package/dist/tooltip/tooltip.js +5 -4
  63. package/package.json +1 -1
  64. package/dist/shared/utils/wait.d.ts +0 -1
  65. package/dist/shared/utils/wait.js +0 -5
  66. /package/dist/algolia/{algolia-intialization.d.ts → algolia-initialization.d.ts} +0 -0
@@ -1,26 +1,15 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { jsx } from 'react/jsx-runtime';
2
2
  import { useState, useCallback, useEffect } from 'react';
3
- import { Button } from '../../../buttons/button/button.js';
4
- import { OrderLineCard } from '../../../cards/orderline-card/orderline-card.js';
5
- import { CartTotals } from '../../../cart-totals/cart-totals.js';
6
- import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
7
- import { FormattedMessage } from '../../../intl/formatted-message.js';
8
- import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
9
- import { OrderLineList } from '../../../lists/orderline-list/orderline-list.js';
10
3
  import { useIsAuthenticated } from '../../../shared/api/storefront/hooks/authentication/use-is-authenticated.js';
11
4
  import { useFetchCurrentCheckoutAtp } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart-checkout-atp.js';
12
5
  import { useFetchCurrentCartWithAtp } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart-with-atp.js';
13
6
  import { useNavigate } from '../../../shared/routing/route-provider.js';
14
7
  import { hasNo } from '../../../shared/utils/types.js';
15
- import { Page } from '../../components/page/page.js';
16
8
  import { ErrorPage } from '../../error-page/error-page.js';
17
9
  import { LoadingPage } from '../../loading-page/loading-page.js';
18
10
  import { CHECKOUT_PATHS } from '../constants.js';
19
- import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
20
- import { CheckoutPageSection } from '../layouts/checkout-page-layout/components/checkout-page-section.js';
21
- import { CheckoutPageSectionContent } from '../layouts/checkout-page-layout/components/checkout-page-section-content.js';
22
- import { Payment } from './components/payment.js';
23
11
  import { useHasReturnedFromAdyen } from './hooks/use-has-returned-from-adyen.js';
12
+ import { PaymentPageContent } from './payment-page-content.js';
24
13
 
25
14
  const PAYMENT_FORM_ID = 'paymentForm';
26
15
  function PaymentPage() {
@@ -32,7 +21,6 @@ function PaymentPage() {
32
21
  const { data: atp, isLoading: isAtpLoading } = useFetchCurrentCheckoutAtp();
33
22
  const hasAtp = atp && atp.length > 1;
34
23
  const isLoading = isLoadingCart || isAtpLoading;
35
- const t = useFormattedMessage();
36
24
  const [isProcessing, setIsProcessing] = useState(false);
37
25
  const [isValidating, setIsValidating] = useState(false);
38
26
  const { isNavigating, navigate } = useNavigate();
@@ -66,29 +54,7 @@ function PaymentPage() {
66
54
  cart.cartLines.length === 0 ||
67
55
  hasNo(cart.billTo?.address1))
68
56
  return null;
69
- return (jsx(Page, { breadCrumb: [
70
- { href: CHECKOUT_PATHS.HOME, label: t('Home') },
71
- {
72
- href: CHECKOUT_PATHS.REVIEW_AND_SUBMIT,
73
- label: t('Review and payment'),
74
- },
75
- ], title: t('Review and payment'), children: jsxs(CheckoutPageLayout, { actions: {
76
- primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: PAYMENT_FORM_ID, isDisabled: isProcessing, isLoading: isProcessing ? (jsx(FormattedMessage, { id: "Processing" })) : isValidating ? (jsx(FormattedMessage, { id: "Validating" })) : (false), type: "submit", children: jsx(FormattedMessage, { id: "Pay" }) })),
77
- }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { deliveryDate: hasAtp ? undefined : cart.requestedDeliveryDate, fulfillmentMethod: cart.fulfillmentMethod, isPayByInvoice: (cart.paymentOptions?.paymentMethods?.length || 1) <= 1 &&
78
- cart.paymentMethod?.name === 'PBI', shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines[0]?.pricing?.vatRate || 0 }), children: [jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Payment" }), children: jsx(CheckoutPageSectionContent, { children: jsx(Payment, { atp: atp, cart: cart, form: PAYMENT_FORM_ID, onPaymentComplete: onPaymentComplete, onProcessing: setIsProcessing, onValidating: setIsValidating }) }) }), jsx(CheckoutPageSection, { hasBorder: false, title: jsx(FormattedMessage, { id: "Order" }), children: jsx(CheckoutPageSectionContent, { stretch: true, children: jsx(OrderLineList, { children: cart.cartLines.map(cartLine => (jsx(OrderLineCard, { deliveryDate: cartLine.atp?.date, href: cartLine.productUri, image: {
79
- fit: 'contain',
80
- image: {
81
- '1': cartLine.smallImagePath,
82
- '2': cartLine.smallImagePath,
83
- '3': cartLine.smallImagePath,
84
- altText: cartLine.altText,
85
- },
86
- title: cartLine.altText,
87
- }, isReadonly: true, price: {
88
- originalTotalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
89
- pricePerUnit: cartLine.pricing?.unitNetPrice || 0,
90
- totalPrice: cartLine.pricing?.extendedUnitNetPrice || 0,
91
- }, productId: cartLine.productId || '', quantity: cartLine.qtyOrdered || 1, sku: cartLine.erpNumber || '', tags: [], title: cartLine.productName }, cartLine.id))) }) }) })] }) }));
57
+ return (jsx(PaymentPageContent, { atp: atp, cart: cart, formId: PAYMENT_FORM_ID, hasAtp: Boolean(hasAtp), isProcessing: isProcessing, isValidating: isValidating, onPaymentComplete: onPaymentComplete, setIsProcessing: setIsProcessing, setIsValidating: setIsValidating }));
92
58
  }
93
59
 
94
60
  export { PaymentPage };
@@ -4,11 +4,11 @@ import { Form } from 'react-aria-components';
4
4
  import { CountrySelect } from '../../../../country-selector/country-select/country-select.js';
5
5
  import { Checkbox } from '../../../../forms/checkbox/checkbox.js';
6
6
  import { TextField } from '../../../../forms/text-field/text-field.js';
7
+ import { InfoIconTooltip } from '../../../../info-icon-tooltip/info-icon-tooltip.js';
7
8
  import { FormattedMessage } from '../../../../intl/formatted-message.js';
8
9
  import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
9
10
  import { useFetchCurrentCart } from '../../../../shared/api/storefront/hooks/cart/use-fetch-current-cart.js';
10
11
  import { validatePhone, validateEmail } from '../../../../shared/model/address.js';
11
- import { Tooltip } from '../../../../tooltip/tooltip.js';
12
12
  import { CheckoutPageSection } from '../../layouts/checkout-page-layout/components/checkout-page-section.js';
13
13
  import { CheckoutPageSectionContent } from '../../layouts/checkout-page-layout/components/checkout-page-section-content.js';
14
14
  import { SonicAddress } from './sonic-address.js';
@@ -43,7 +43,7 @@ function EditAddresses({ countries, isLoading, isPickup, onSubmit, }) {
43
43
  },
44
44
  notes: formData.get('notes')?.toString() || '',
45
45
  });
46
- }, children: [jsx(TextField, { isDisabled: isLoading, label: t('First name'), name: "firstName", showLabel: true }), jsx(TextField, { isDisabled: isLoading, isRequired: !companyName, label: t('Last name'), minLength: 3, name: "lastName", onChange: setLastName, showLabel: true, value: lastName }, `lastname-${Boolean(companyName)}`), jsx(TextField, { isDisabled: isLoading, label: t('Company name'), name: "companyName", onChange: setCompanyName, showLabel: true, value: companyName }), jsx(TextField, { isDisabled: isLoading, label: t('Attention'), name: "attention", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: `${t('Address')} 1`, maxLength: 30, minLength: 3, name: "address1", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 2`, maxLength: 30, minLength: 3, name: "address2", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 3`, maxLength: 30, minLength: 3, name: "address3", showLabel: true }) }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Postal Code'), maxLength: 10, minLength: 4, name: "postalCode", showLabel: true }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('City'), maxLength: 30, minLength: 3, name: "city", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(CountrySelect, { isRequired: true, countries: countries, "data-test-selector": "countrySelect", name: "countrySelect" }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Phone'), name: "phone", showLabel: true, validate: value => {
46
+ }, children: [jsx(TextField, { isDisabled: isLoading, label: t('First name'), name: "firstName", showLabel: true }), jsx(TextField, { isDisabled: isLoading, isRequired: !companyName, label: t('Last name'), minLength: 3, name: "lastName", onChange: setLastName, showLabel: true, value: lastName }, `lastname-${Boolean(companyName)}`), jsx(TextField, { isDisabled: isLoading, label: t('Company name'), name: "companyName", onChange: setCompanyName, showLabel: true, value: companyName }), jsx(TextField, { isDisabled: isLoading, label: t('Attention'), name: "attention", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: `${t('Address')} 1`, maxLength: 30, minLength: 3, name: "address1", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 2`, maxLength: 30, minLength: 3, name: "address2", showLabel: true }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, label: `${t('Address')} 3`, maxLength: 30, minLength: 3, name: "address3", showLabel: true }) }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Postal Code'), maxLength: 10, minLength: 4, name: "postalCode", showLabel: true }), jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('City'), maxLength: 30, minLength: 3, name: "city", showLabel: true }), jsx("div", { className: styles['span-2'], children: jsx(CountrySelect, { isRequired: true, countries: countries, "data-test-selector": "countrySelect", isDisabled: isLoading, name: "countrySelect" }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isRequired: true, isDisabled: isLoading, label: t('Phone'), name: "phone", showLabel: true, validate: value => {
47
47
  if (!value)
48
48
  return value;
49
49
  return (validatePhone(value) ||
@@ -53,7 +53,7 @@ function EditAddresses({ countries, isLoading, isPickup, onSubmit, }) {
53
53
  return value;
54
54
  return (validateEmail(value) ||
55
55
  t('Please enter a valid e-mail address'));
56
- } }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] }) }) }), jsx(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: jsx(CheckoutPageSectionContent, { children: jsx(Fragment, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs("div", { className: styles['use-invoice-checkbox'], children: [jsx(Checkbox, { "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), jsx(Tooltip, { text: t('Changing your address is currently not possible. Please contact customer support to change your address.') })] })) }) }) })] }));
56
+ } }) }), jsx("div", { className: styles['span-2'], children: jsx(TextField, { isDisabled: isLoading, isMultiline: true, label: t('Add order notes'), name: "notes", rows: 3, showLabel: true }) })] }) }) }), jsx(CheckoutPageSection, { title: jsx(FormattedMessage, { id: isPickup ? 'Pickup address' : 'Shipping address' }), children: jsx(CheckoutPageSectionContent, { children: jsx(Fragment, { children: isPickup ? (jsx(SonicAddress, {})) : (jsxs("div", { className: styles['use-invoice-checkbox'], children: [jsx(Checkbox, { "data-test-selector": "checkboxUseBillingAddress", isDisabled: true, isSelected: true, children: jsx(FormattedMessage, { id: "Use billing address" }) }), jsx(InfoIconTooltip, { variant: "stroke", children: t('Changing your address is currently not possible. Please contact customer support to change your address.') })] })) }) }) })] }));
57
57
  }
58
58
 
59
59
  export { EDIT_ADDRESS_FORM_ID, EditAddresses };
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { CartModel } from '../../../shared/api/storefront/model/storefront.model';
3
+ export interface ShippingPageContentProps {
4
+ cart: CartModel;
5
+ editAddress: ReactNode;
6
+ errorPatchBillingAddress?: unknown;
7
+ fulfillmentMethods: string[] | undefined;
8
+ isLoadingFulfillmentMethods: boolean;
9
+ isPatching: boolean;
10
+ isPatchingSession: boolean;
11
+ onChangeFulfillmentMethod: (value: string) => void;
12
+ readOnlyAddress: ReactNode;
13
+ }
14
+ export declare function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }: ShippingPageContentProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo } from 'react';
3
+ import { Button } from '../../../buttons/button/button.js';
4
+ import { CartTotals } from '../../../cart-totals/cart-totals.js';
5
+ import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
6
+ import { Select } from '../../../forms/select/select.js';
7
+ import { FormattedMessage } from '../../../intl/formatted-message.js';
8
+ import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
9
+ import { Page } from '../../components/page/page.js';
10
+ import { CHECKOUT_PATHS } from '../constants.js';
11
+ import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
12
+ import { CheckoutPageSection } from '../layouts/checkout-page-layout/components/checkout-page-section.js';
13
+ import { CheckoutPageSectionContent } from '../layouts/checkout-page-layout/components/checkout-page-section-content.js';
14
+ import { EDIT_ADDRESS_FORM_ID } from './components/edit-address.js';
15
+ import styles from './shipping-page.module.css.js';
16
+
17
+ function ShippingPageContent({ cart, editAddress, errorPatchBillingAddress, fulfillmentMethods, isLoadingFulfillmentMethods, isPatching, isPatchingSession, onChangeFulfillmentMethod, readOnlyAddress, }) {
18
+ const t = useFormattedMessage();
19
+ const fulfillmentMethodOptions = fulfillmentMethods?.reduce((acc, method) => ({
20
+ ...acc,
21
+ [method]: t(`fulfillmentMethod.${method}`),
22
+ }), {});
23
+ const hasBillToAddress = useMemo(() => {
24
+ return Boolean(cart.billTo?.address1);
25
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
+ }, [Boolean(cart)]);
27
+ return (jsx(Page, { breadCrumb: [
28
+ { href: CHECKOUT_PATHS.HOME, label: t('Home') },
29
+ {
30
+ href: CHECKOUT_PATHS.CHECKOUT_SHIPPING,
31
+ label: t('Shipping details'),
32
+ },
33
+ ], title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
34
+ primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: EDIT_ADDRESS_FORM_ID, isDisabled: isPatching, isLoading: isPatching || isPatchingSession ? (jsx(FormattedMessage, { id: "Updating address" })) : undefined, type: "submit", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
35
+ }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
36
+ ? cart.fulfillmentMethod
37
+ : undefined, shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines?.[0]?.pricing?.vatRate }), children: [jsxs(Fragment, { children: [fulfillmentMethods && fulfillmentMethods.length > 1 && (jsx(CheckoutPageSection, { hasBorder: true, title: t('Fulfillment method'), children: jsx(CheckoutPageSectionContent, { children: jsx("div", { className: styles['fulfillment-select-wrapper'], children: jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "fulfillmentMethodSelect", defaultSelectedOption: cart.fulfillmentMethod, isLoading: isLoadingFulfillmentMethods, label: t('Fulfillment method'), name: "fulfillmentMethod", onChange: onChangeFulfillmentMethod, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress ? readOnlyAddress : editAddress] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
38
+ }
39
+
40
+ export { ShippingPageContent };
@@ -1,33 +1,26 @@
1
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useMemo, useEffect } from 'react';
3
- import { Button } from '../../../buttons/button/button.js';
4
- import { CartTotals } from '../../../cart-totals/cart-totals.js';
5
- import { CartTotalsSummary } from '../../../cart-totals/cart-totals-summary.js';
6
- import { Select } from '../../../forms/select/select.js';
7
- import { FormattedMessage } from '../../../intl/formatted-message.js';
8
- import { useFormattedMessage } from '../../../intl/use-formatted-message.js';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useRef, useEffect } from 'react';
9
3
  import { useFetchSession } from '../../../shared/api/storefront/hooks/authentication/use-fetch-session.js';
10
4
  import { useIsAuthenticated } from '../../../shared/api/storefront/hooks/authentication/use-is-authenticated.js';
11
5
  import { usePatchSession } from '../../../shared/api/storefront/hooks/authentication/use-patch-session.js';
12
6
  import { useFetchCurrentCart } from '../../../shared/api/storefront/hooks/cart/use-fetch-current-cart.js';
13
7
  import { useFetchFulfillmentMethodsForCurrentCart } from '../../../shared/api/storefront/hooks/customer/use-fetch-fulfillment-methods-for-current-cart.js';
14
8
  import { useFetchCountries } from '../../../shared/api/storefront/hooks/website/use-fetch-countries.js';
9
+ import { useDataLayer } from '../../../shared/ga/use-data-layer.js';
15
10
  import { useNavigate } from '../../../shared/routing/route-provider.js';
16
11
  import { hasNo } from '../../../shared/utils/types.js';
17
- import { Page } from '../../components/page/page.js';
18
12
  import { ErrorPage } from '../../error-page/error-page.js';
19
13
  import { LoadingPage } from '../../loading-page/loading-page.js';
20
14
  import { CHECKOUT_PATHS } from '../constants.js';
21
- import { CheckoutPageLayout } from '../layouts/checkout-page-layout/checkout-page-layout.js';
22
- import { CheckoutPageSection } from '../layouts/checkout-page-layout/components/checkout-page-section.js';
23
- import { CheckoutPageSectionContent } from '../layouts/checkout-page-layout/components/checkout-page-section-content.js';
24
- import { EDIT_ADDRESS_FORM_ID, EditAddresses } from './components/edit-address.js';
15
+ import { EditAddresses } from './components/edit-address.js';
25
16
  import { ReadOnlyAddresses } from './components/readonly-address.js';
26
17
  import { usePatchShippingDetails } from './hooks/use-patch-shipping-details.js';
27
- import styles from './shipping-page.module.css.js';
18
+ import { ShippingPageContent } from './shipping-page-content.js';
28
19
 
29
20
  function ShippingPage() {
30
21
  const isAuthenticated = useIsAuthenticated();
22
+ const { createEcommerceEvent, dataLayer } = useDataLayer();
23
+ const gaEventPushed = useRef(false);
31
24
  const { data: cart, error: errorFetchCart, isLoading: isLoadingCart, refetch: refetchCart, } = useFetchCurrentCart();
32
25
  const { data: countries, isLoading: isLoadingCountries } = useFetchCountries({
33
26
  enabled: hasNo(cart?.billTo?.address1),
@@ -37,16 +30,7 @@ function ShippingPage() {
37
30
  const { isLoading: isPatchingSession, mutate: patchSession } = usePatchSession();
38
31
  const { error: errorPatchBillingAddress, isError, isLoading: isPatching, isSuccess, mutate: patchShippingDetails, } = usePatchShippingDetails();
39
32
  const isLoading = isLoadingCart || isLoadingCountries || isLoadingFulfillmentMethods;
40
- const t = useFormattedMessage();
41
33
  const { isNavigating, navigate } = useNavigate();
42
- const hasBillToAddress = useMemo(() => {
43
- return Boolean(cart?.billTo?.address1);
44
- // eslint-disable-next-line react-hooks/exhaustive-deps
45
- }, [Boolean(cart)]);
46
- const fulfillmentMethodOptions = fulfillmentMethods?.reduce((acc, method) => ({
47
- ...acc,
48
- [method]: t(`fulfillmentMethod.${method}`),
49
- }), {});
50
34
  const isPickup = cart?.fulfillmentMethod === 'PickUp';
51
35
  useEffect(() => {
52
36
  /* Initial guards. When these are not met, we should not proceed */
@@ -77,6 +61,15 @@ function ShippingPage() {
77
61
  return;
78
62
  return navigate(CHECKOUT_PATHS.REVIEW_AND_SUBMIT);
79
63
  }, [isSuccess, cart, navigate, isNavigating, isPatching, isError]);
64
+ useEffect(() => {
65
+ if (!cart || gaEventPushed.current)
66
+ return;
67
+ dataLayer.push(createEcommerceEvent({
68
+ cart,
69
+ event: { event: 'begin_checkout' },
70
+ }));
71
+ gaEventPushed.current = true;
72
+ }, [cart, createEcommerceEvent, dataLayer]);
80
73
  if (errorFetchCart)
81
74
  return jsx(ErrorPage, { error: errorFetchCart });
82
75
  if (isLoading || isNavigating || isError || isSuccess)
@@ -88,37 +81,35 @@ function ShippingPage() {
88
81
  hasNo(cart.billTo) ||
89
82
  (hasNo(cart.billTo.address1) && hasNo(countries)))
90
83
  return null;
91
- return (jsx(Page, { breadCrumb: [
92
- { href: CHECKOUT_PATHS.HOME, label: t('Home') },
93
- {
94
- href: CHECKOUT_PATHS.CHECKOUT_SHIPPING,
95
- label: t('Shipping details'),
96
- },
97
- ], title: t('Shipping details'), children: jsxs(CheckoutPageLayout, { actions: {
98
- primary: (jsx(Button, { withArrow: true, "data-test-selector": "checkoutShippingCartTotalContinueButton", form: EDIT_ADDRESS_FORM_ID, isDisabled: isPatching, isLoading: isPatching || isPatchingSession ? (jsx(FormattedMessage, { id: "Updating address" })) : undefined, type: "submit", children: jsx(FormattedMessage, { id: "Continue shopping" }) })),
99
- }, mobileSummary: jsx(CartTotalsSummary, { totalAmount: cart.orderGrandTotalDisplay }), overview: jsx(CartTotals, { fulfillmentMethod: fulfillmentMethods && fulfillmentMethods.length === 1
100
- ? cart.fulfillmentMethod
101
- : undefined, shippingCost: cart.shippingAndHandlingDisplay, subtotal: cart.orderSubTotalDisplay, tax: cart.totalTaxDisplay, total: cart.orderGrandTotalDisplay, vatPercentage: cart.cartLines[0]?.pricing?.vatRate }), children: [jsxs(Fragment, { children: [fulfillmentMethods && fulfillmentMethods.length > 1 && (jsx(CheckoutPageSection, { hasBorder: true, title: t('Fulfillment method'), children: jsx(CheckoutPageSectionContent, { children: jsx("div", { className: styles['fulfillment-select-wrapper'], children: jsx(Select, { isRequired: true, showLabel: true, "data-test-selector": "fulfillmentMethodSelect", defaultSelectedOption: cart.fulfillmentMethod, isLoading: isLoadingFulfillmentMethods, label: t('Fulfillment method'), name: "fulfillmentMethod", onChange: async (value) => {
102
- await patchSession({
103
- session: {
104
- ...session,
105
- fulfillmentMethod: value,
106
- },
107
- });
108
- await refetchCart();
109
- }, options: fulfillmentMethodOptions || {}, variant: "solid" }) }) }) })), hasBillToAddress ? (jsx(ReadOnlyAddresses, { billTo: cart.billTo, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ notes }) => {
110
- if (!cart.billTo)
111
- return;
112
- await patchShippingDetails({ cart, notes });
113
- }, shipTo: cart.shipTo })) : (jsx(EditAddresses, { countries: countries || [], isLoading: isPatching, isPickup: isPickup, onSubmit: async ({ address, notes }) => {
114
- if (!cart.billTo)
115
- return;
116
- await patchShippingDetails({
117
- billTo: { ...cart.billTo, ...address },
118
- cart,
119
- notes,
120
- });
121
- } }))] }), Boolean(errorPatchBillingAddress) && (jsx("div", { className: styles['error-message'], children: jsx(FormattedMessage, { id: "An unexpected error occured" }) }))] }) }));
84
+ return (jsx(ShippingPageContent, { cart: cart, editAddress: jsx(EditAddresses, { 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, isLoadingFulfillmentMethods: isLoadingFulfillmentMethods, isPatching: isPatching, isPatchingSession: isPatchingSession, onChangeFulfillmentMethod: async (value) => {
97
+ await patchSession({
98
+ session: {
99
+ ...session,
100
+ fulfillmentMethod: value,
101
+ },
102
+ });
103
+ await refetchCart();
104
+ }, readOnlyAddress: jsx(ReadOnlyAddresses, { billTo: cart.billTo, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ notes }) => {
105
+ if (!cart.billTo)
106
+ return;
107
+ await patchShippingDetails({ cart, notes });
108
+ dataLayer.push(createEcommerceEvent({
109
+ cart,
110
+ event: { event: 'add_shipping_info' },
111
+ }));
112
+ }, shipTo: cart.shipTo }) }));
122
113
  }
123
114
 
124
115
  export { ShippingPage };
@@ -10,10 +10,20 @@ import { FormattedMessage } from '../../../../../intl/formatted-message.js';
10
10
  import { DownloadDocumentList } from '../../../../../lists/download-document-list/download-document-list.js';
11
11
  import { FeatureList } from '../../../../../lists/feature-list/feature-list.js';
12
12
  import { Heading } from '../../../../../typography/heading/heading.js';
13
+ import { useAlgoliaInsights } from '../../../../../algolia/use-algolia-insights.js';
13
14
  import styles from './product-details-panel.module.css.js';
14
15
 
15
16
  function ProductDetailsPanel({ priceComponent, product, }) {
16
- return (jsxs("div", { className: styles['product-details-panel'], children: [jsxs("div", { className: styles.heading, children: [jsx(Heading, { italic: true, size: "xs", children: product.productTitle }), jsx(ProductSku, { sku: product.productNumber })] }), jsxs("div", { className: styles['price-action-container'], children: [priceComponent || (jsx(ProductPrice, { "data-test": "productPrice_unitNetPrice", isVatIncluded: product.isVatIncluded, originalPrice: product.originalPrice, price: product.price })), jsxs("div", { className: styles['action-container'], children: [product.canAddToCart && (jsx(ConnectedAddToCartButton, { productId: product.storefrontId })), product.canAddToWishlist && (jsx(ConnectedFavoriteButton, { 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: {
17
+ const { sendAddToCartFromProductDetailsPageEvent, sendAddToWishListFromProductDetailsPageEvent, } = useAlgoliaInsights();
18
+ return (jsxs("div", { className: styles['product-details-panel'], children: [jsxs("div", { className: styles.heading, children: [jsx(Heading, { italic: true, size: "xs", children: product.productTitle }), jsx(ProductSku, { sku: product.productNumber })] }), jsxs("div", { className: styles['price-action-container'], children: [priceComponent || (jsx(ProductPrice, { "data-test": "productPrice_unitNetPrice", isVatIncluded: product.isVatIncluded, originalPrice: product.originalPrice, price: product.price })), jsxs("div", { className: styles['action-container'], children: [product.canAddToCart && (jsx(ConnectedAddToCartButton, { onAddToCart: ({ cartLine }) => {
19
+ sendAddToCartFromProductDetailsPageEvent({
20
+ cartLine,
21
+ });
22
+ }, productId: product.storefrontId })), product.canAddToWishlist && (jsx(ConnectedFavoriteButton, { onFavoriting: () => {
23
+ sendAddToWishListFromProductDetailsPageEvent({
24
+ objectId: product.productNumber,
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: {
17
27
  __html: product.content.htmlContent,
18
28
  } }) }))] }), 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 => ({
19
29
  id: `${attribute.id}`,
@@ -15,7 +15,6 @@ function ProductHitCard({ hit }) {
15
15
  title: hit.name,
16
16
  }, onAddToCart: ({ cartLine }) => sendAddToCartFromProductListPageEvent({
17
17
  cartLine,
18
- objectId: hit.objectId,
19
18
  }), onClick: () => sendProductClickFromProductListPageEvent({
20
19
  objectId: hit.objectId,
21
20
  position: hit.position,
@@ -15,7 +15,6 @@ function ProductHitCard({ hit }) {
15
15
  title: hit.name,
16
16
  }, onAddToCart: ({ cartLine }) => sendAddToCartFromSearchResultPageEvent({
17
17
  cartLine,
18
- objectId: hit.objectId,
19
18
  }), onClick: () => {
20
19
  sendProductClickFromSearchResultPageEvent({
21
20
  objectId: hit.objectId,
@@ -49,10 +49,10 @@ export declare class InternalServerErrorRequestError extends RequestError {
49
49
  constructor(responseOrError: Response | unknown, options?: RequestErrorOptions);
50
50
  }
51
51
  export type RequestHeaders = Record<string, string | null | undefined>;
52
- type RequestHeadersWithBody = RequestHeaders & {
52
+ export type RequestHeadersWithBody = RequestHeaders & {
53
53
  'Content-Type': string;
54
54
  };
55
- interface BaseRequestOptions {
55
+ export interface BaseRequestOptions {
56
56
  cache?: RequestCache;
57
57
  credentials?: RequestCredentials;
58
58
  headers?: RequestHeaders;
@@ -65,38 +65,43 @@ interface BaseRequestOptions {
65
65
  timeout?: number;
66
66
  url: string;
67
67
  }
68
- interface RequestOptionsWithFormData extends BaseRequestOptions {
68
+ export interface RequestOptionsWithFormData extends BaseRequestOptions {
69
69
  body: FormData;
70
70
  headers: RequestHeaders;
71
71
  }
72
- interface RequestOptionsWithBody extends BaseRequestOptions {
72
+ export interface RequestOptionsWithBody extends BaseRequestOptions {
73
73
  body: unknown;
74
74
  headers: RequestHeadersWithBody;
75
75
  }
76
- interface RequestOptionsWithoutBody extends BaseRequestOptions {
76
+ export interface RequestOptionsWithoutBody extends BaseRequestOptions {
77
77
  body?: never;
78
78
  headers?: RequestHeaders;
79
79
  }
80
- type RequestOptions = RequestOptionsWithBody | RequestOptionsWithoutBody | RequestOptionsWithFormData;
81
- type AfterRequestHandler<T> = (args: {
80
+ export type RequestOptions = RequestOptionsWithBody | RequestOptionsWithoutBody | RequestOptionsWithFormData;
81
+ type BeforeRequestHandler = (options?: RequestOptions) => RequestOptions | void;
82
+ type BeforeRequestHandlerAsync = (options?: RequestOptions) => Promise<RequestOptions | void>;
83
+ export interface AfterRequestHandlerArgs<T> {
82
84
  body: T | undefined;
83
85
  error?: RequestError;
84
86
  options: RequestOptions;
85
87
  response?: Response;
86
- }) => void;
87
- type BeforeRequestHandler = (options?: RequestOptions) => RequestOptions | void;
88
- type RequestReturnType<T> = Promise<{
88
+ }
89
+ export type AfterRequestHandler<T> = (args: AfterRequestHandlerArgs<T>) => void;
90
+ export type AfterRequestHandlerAsync<T> = (args: AfterRequestHandlerArgs<T>) => Promise<void>;
91
+ export declare const isJsonBody: (options: RequestOptions) => boolean;
92
+ export declare const isFormData: (body: unknown) => body is FormData;
93
+ export type RequestReturnType<T> = Promise<{
89
94
  body: T;
90
95
  headers: Headers;
91
96
  status: number;
92
97
  statusText: string;
93
98
  }>;
94
- interface Request {
99
+ export interface Request {
95
100
  <T>(options: RequestOptions): RequestReturnType<T>;
96
- _afterHandlers: AfterRequestHandler<any>[];
97
- _beforeHandlers: BeforeRequestHandler[];
98
101
  after<T = any>(handler: AfterRequestHandler<T>): void;
102
+ after<T = any>(handler: AfterRequestHandlerAsync<T>): void;
99
103
  before(handler: BeforeRequestHandler): void;
104
+ before(handler: BeforeRequestHandlerAsync): void;
100
105
  headers: Omit<RequestHeaders, 'Content-Type'>;
101
106
  }
102
107
  export declare const request: Request;
@@ -1,4 +1,5 @@
1
1
  import qs from 'query-string';
2
+ import { isPromise } from '../utils/promise.js';
2
3
 
3
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
5
  const isResponse = (response) => Boolean(response?.json);
@@ -181,17 +182,20 @@ const createBody = (options) => {
181
182
  throw new Error(`request: Unknown body type for request ${url}. Unable to send request.`);
182
183
  };
183
184
  const createHeaders = (...headers) => {
184
- const allHeaders = {};
185
+ const allHeaders = new Headers();
185
186
  for (const header of headers) {
186
187
  if (!header)
187
188
  continue;
188
189
  for (const key of Object.keys(header)) {
189
190
  if (header[key])
190
- allHeaders[key] = header[key];
191
+ allHeaders.append(key, String(header[key]));
191
192
  }
192
193
  }
193
194
  return allHeaders;
194
195
  };
196
+ const beforeHandlers = [];
197
+ /* eslint-disable @typescript-eslint/no-explicit-any */
198
+ const afterHandlers = [];
195
199
  /* Because of a bug in the rollup dts package the following code must be put inside of a IIFE.
196
200
  * The bug occurs when assigning properties to the request function at the top level of this file.
197
201
  * request.headers = {}
@@ -204,7 +208,12 @@ const request = (function createRequestFunction() {
204
208
  let error;
205
209
  let isTimeout = false;
206
210
  try {
207
- options = request._beforeHandlers.reduce((options, handler) => handler(options) || options, options);
211
+ for await (const handler of beforeHandlers) {
212
+ const promiseOrOptions = handler(options);
213
+ options = isPromise(promiseOrOptions)
214
+ ? (await promiseOrOptions) || options
215
+ : promiseOrOptions || options;
216
+ }
208
217
  options.timeout = options.timeout || 1000 * 60 * 2;
209
218
  const url = qs.stringifyUrl({ query: options.params, url: options.url });
210
219
  const controller = new AbortController();
@@ -245,19 +254,23 @@ const request = (function createRequestFunction() {
245
254
  throw error;
246
255
  }
247
256
  finally {
248
- request._afterHandlers.forEach(handler => handler({ body, error, options, response }));
257
+ for await (const handler of afterHandlers) {
258
+ const promiseOrVoid = handler({ body, error, options, response });
259
+ if (isPromise(promiseOrVoid))
260
+ await promiseOrVoid;
261
+ }
249
262
  }
250
263
  };
251
264
  request.headers = {};
252
- request._afterHandlers = [];
253
- request._beforeHandlers = [];
254
265
  request.after = (handler) => {
255
- request._afterHandlers.push(handler);
266
+ afterHandlers.push(
267
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
268
+ handler);
256
269
  };
257
270
  request.before = (handler) => {
258
- request._beforeHandlers.push(handler);
271
+ beforeHandlers.push(handler);
259
272
  };
260
273
  return request;
261
274
  })();
262
275
 
263
- export { BadRequestError, ForbiddenRequestError, InternalServerErrorRequestError, NotFoundRequestError, RequestError, TimeoutRequestError, UnauthorizedRequestError, UnprocessableContentRequestError, isRequestError, request };
276
+ export { BadRequestError, ForbiddenRequestError, InternalServerErrorRequestError, NotFoundRequestError, RequestError, TimeoutRequestError, UnauthorizedRequestError, UnprocessableContentRequestError, isFormData, isJsonBody, isRequestError, request };
@@ -8,9 +8,13 @@ interface GAProductModel {
8
8
  unitListPriceDisplay: string;
9
9
  }
10
10
  interface GACartModel {
11
- cartLines: CartModel['cartLines'];
11
+ cartLines?: CartModel['cartLines'];
12
12
  currencySymbol: string;
13
+ orderGrandTotal: number;
13
14
  orderSubTotal: number;
15
+ shippingAndHandling: number;
16
+ totalTax: number;
17
+ trackId: string;
14
18
  }
15
19
  interface GACartLineModel {
16
20
  erpNumber: string;
@@ -26,12 +30,12 @@ interface CreateEcommerceEventArgsWithCartLine {
26
30
  event: GAEcommerceEvent;
27
31
  }
28
32
  interface CreateEcommerceEventArgsWithCart {
33
+ cart: GACartModel;
29
34
  event: GAEcommerceEvent;
30
- product: GAProductModel;
31
35
  }
32
36
  interface CreateEcommerceEventArgsWithProduct {
33
- cart: GACartModel;
34
37
  event: GAEcommerceEvent;
38
+ product: GAProductModel;
35
39
  }
36
40
  interface CreateEcommerceEvent {
37
41
  (args: CreateEcommerceEventArgsWithCart): GAEcommerceEvent;
@@ -12,7 +12,8 @@ function useDataLayer(eventOrArgs) {
12
12
  ...event,
13
13
  ecommerce: {
14
14
  ...event.ecommerce,
15
- currency: event.ecommerce?.currency ?? cart.currencySymbol,
15
+ currency: event.ecommerce?.currency ??
16
+ currencySymbolToISO[cart.currencySymbol],
16
17
  customer: event.ecommerce?.customer ?? customerNumber,
17
18
  items: cart.cartLines?.map(cartLine => ({
18
19
  item_id: cartLine.erpNumber,
@@ -20,6 +21,10 @@ function useDataLayer(eventOrArgs) {
20
21
  price: cartLine.pricing?.unitNetPrice,
21
22
  quantity: cartLine.qtyOrdered ?? 0,
22
23
  })) ?? [],
24
+ shipping: cart.shippingAndHandling,
25
+ tax: cart.totalTax,
26
+ transaction_id: cart.trackId,
27
+ value: cart.orderGrandTotal,
23
28
  },
24
29
  value: event.value ?? cart.orderSubTotal ?? 0,
25
30
  };
@@ -0,0 +1,2 @@
1
+ export declare function wait(ms: number): Promise<unknown>;
2
+ export declare function isPromise<T>(value: any): value is Promise<T>;
@@ -0,0 +1,9 @@
1
+ function wait(ms) {
2
+ return new Promise(resolve => setTimeout(resolve, ms));
3
+ }
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ function isPromise(value) {
6
+ return value && typeof value.then === 'function';
7
+ }
8
+
9
+ export { isPromise, wait };
@@ -0,0 +1,19 @@
1
+ interface LoginData {
2
+ email: string;
3
+ guestSignin: false;
4
+ password: string;
5
+ remember?: boolean;
6
+ }
7
+ interface GuestLoginData {
8
+ guestSignin: true;
9
+ }
10
+ export interface SignInFormProps {
11
+ allowGuestSignIn?: boolean;
12
+ initialEmail?: string;
13
+ initialRemember?: boolean;
14
+ onSubmit?: ({ data }: {
15
+ data: LoginData | GuestLoginData;
16
+ }) => void;
17
+ }
18
+ export declare function SignInForm({ allowGuestSignIn, initialEmail, initialRemember, onSubmit, }: SignInFormProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};