@sonic-equipment/ui 162.0.0 → 164.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.
- package/dist/buttons/link/link.d.ts +2 -1
- package/dist/buttons/link/link.js +3 -3
- package/dist/cards/orderline-card/orderline-card.js +1 -1
- package/dist/collapsables/cascading-component/cascading-component-container-context.d.ts +2 -0
- package/dist/collapsables/cascading-component/cascading-component-container-context.js +5 -0
- package/dist/collapsables/cascading-component/cascading-component-container-provider.d.ts +7 -0
- package/dist/collapsables/cascading-component/cascading-component-container-provider.js +28 -0
- package/dist/collapsables/cascading-component/cascading-component-container.d.ts +8 -0
- package/dist/collapsables/cascading-component/cascading-component-container.js +8 -0
- package/dist/collapsables/cascading-component/cascading-component.d.ts +13 -0
- package/dist/collapsables/cascading-component/cascading-component.js +44 -0
- package/dist/collapsables/cascading-component/types.d.ts +11 -0
- package/dist/collapsables/cascading-component/use-cascading-component-container.d.ts +2 -0
- package/dist/collapsables/cascading-component/use-cascading-component-container.js +8 -0
- package/dist/collapsables/cascading-component/use-cascading-component.d.ts +2 -0
- package/dist/collapsables/cascading-component/use-cascading-component.js +14 -0
- package/dist/collapsables/cascading-component/use-has-cascading-component-container.d.ts +1 -0
- package/dist/collapsables/cascading-component/use-has-cascading-component-container.js +7 -0
- package/dist/collapsables/unmounter/unmounter.d.ts +14 -0
- package/dist/collapsables/unmounter/unmounter.js +43 -0
- package/dist/collapsables/unmounter/utils.d.ts +2 -0
- package/dist/collapsables/unmounter/utils.js +18 -0
- package/dist/country-select/country-select.js +1 -1
- package/dist/country-selector/connected-country-selector.js +20 -2
- package/dist/country-selector/country-selector-dialog/country-selector-dialog.js +1 -1
- package/dist/country-selector/use-countries-languages.d.ts +17 -1
- package/dist/country-selector/use-countries-languages.js +58 -29
- package/dist/delivery-time/delivery-time.d.ts +1 -1
- package/dist/delivery-time/delivery-time.js +20 -8
- package/dist/delivery-time/delivery-time.module.css.js +1 -1
- package/dist/exports.d.ts +15 -1
- package/dist/icons/glyph/glyphs-arrow-blackcaps-right-icon.js +7 -0
- package/dist/index.js +15 -2
- package/dist/intl/translation-id.d.ts +1 -1
- package/dist/lists/icon-list/icon-list.d.ts +10 -0
- package/dist/lists/icon-list/icon-list.js +11 -0
- package/dist/lists/icon-list/icon-list.module.css.js +3 -0
- package/dist/lists/menu-list/menu-list-back-button.d.ts +7 -0
- package/dist/lists/menu-list/menu-list-back-button.js +9 -0
- package/dist/lists/menu-list/menu-list-header.d.ts +7 -0
- package/dist/lists/menu-list/menu-list-header.js +10 -0
- package/dist/lists/menu-list/menu-list-item.d.ts +26 -0
- package/dist/lists/menu-list/menu-list-item.js +20 -0
- package/dist/lists/menu-list/menu-list.d.ts +14 -0
- package/dist/lists/menu-list/menu-list.js +13 -0
- package/dist/lists/menu-list/menu-list.module.css.js +3 -0
- package/dist/modals/signin/sign-in-dialog.js +2 -2
- package/dist/pages/checkout/cart-page/cart-page.js +1 -1
- package/dist/pages/checkout/order-confirmation-page/order-confirmation-page-content.js +1 -1
- package/dist/pages/checkout/payment-page/components/adyen-payment.js +1 -1
- package/dist/pages/checkout/payment-page/components/payment.js +9 -9
- package/dist/pages/checkout/payment-page/payment-page-content.js +1 -1
- package/dist/shared/utils/date.d.ts +1 -12
- package/dist/shared/utils/date.js +8 -64
- package/dist/styles.css +333 -6
- package/package.json +1 -1
- package/dist/lists/ul/list.d.ts +0 -10
- package/dist/lists/ul/list.js +0 -11
- package/dist/lists/ul/list.module.css.js +0 -3
- package/dist/shared/utils/date.test.d.ts +0 -1
|
@@ -9,8 +9,9 @@ export interface LinkProps {
|
|
|
9
9
|
isDisabled?: boolean;
|
|
10
10
|
onClick?: MouseEventHandler<HTMLElement>;
|
|
11
11
|
onKeyUp?: (event: KeyboardEvent) => void;
|
|
12
|
+
role?: string;
|
|
12
13
|
tabIndex?: number;
|
|
13
14
|
target?: string;
|
|
14
15
|
title?: string;
|
|
15
16
|
}
|
|
16
|
-
export declare function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, tabIndex, target, title, ...rest }: LinkProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }: LinkProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,17 +3,17 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import styles from './link.module.css.js';
|
|
5
5
|
|
|
6
|
-
function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, tabIndex, target, title, ...rest }) {
|
|
6
|
+
function Link({ children, className, color, hasUnderline, href, id, isDisabled, onClick, onKeyUp, role, tabIndex, target, title, ...rest }) {
|
|
7
7
|
if (href) {
|
|
8
8
|
return (jsx("a", { className: clsx({
|
|
9
9
|
[styles.hover]: Boolean(href || onClick),
|
|
10
10
|
[styles['has-underline']]: hasUnderline,
|
|
11
|
-
}, styles['link'], color && styles[color], className), "data-disabled": isDisabled ? true : undefined, href: href, id: id, onClick: onClick, onKeyUp: onKeyUp, tabIndex: isDisabled ? -1 : tabIndex, target: target, title: title, ...rest, children: children }));
|
|
11
|
+
}, styles['link'], color && styles[color], className), "data-disabled": isDisabled ? true : undefined, href: href, id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, target: target, title: title, ...rest, children: children }));
|
|
12
12
|
}
|
|
13
13
|
return (jsx("button", { className: clsx({
|
|
14
14
|
[styles.hover]: Boolean(href || onClick),
|
|
15
15
|
[styles['has-underline']]: hasUnderline,
|
|
16
|
-
}, styles['link'], color && styles[color], className), "data-disabled": isDisabled ? true : undefined, disabled: isDisabled ? true : undefined, id: id, onClick: onClick, onKeyUp: onKeyUp, tabIndex: isDisabled ? -1 : tabIndex, title: title, type: "button", ...rest, children: children }));
|
|
16
|
+
}, styles['link'], color && styles[color], className), "data-disabled": isDisabled ? true : undefined, disabled: isDisabled ? true : undefined, id: id, onClick: onClick, onKeyUp: onKeyUp, role: role, tabIndex: isDisabled ? -1 : tabIndex, title: title, type: "button", ...rest, children: children }));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export { Link };
|
|
@@ -11,7 +11,7 @@ import styles from './orderline-card.module.css.js';
|
|
|
11
11
|
|
|
12
12
|
function OrderLineCard(props) {
|
|
13
13
|
const { deliveryDate, href, image, isReadonly, price, productId, sku, tags, title, } = props;
|
|
14
|
-
return (jsxs("article", { "aria-labelledby": `title-${productId}`, className: clsx(styles['orderline-card'], isReadonly && styles.readonly), "data-disabled": isReadonly ? true : undefined, "data-product-id": sku, "data-test-selector": "orderLineListItem", id: productId, children: [isReadonly ? (jsx("div", { className: styles.title, "data-test-selector": "orderLineCardTitle", id: `title-${productId}`, children: title })) : (jsx(RouteLink, { className: styles.title, "data-test-selector": "orderLineCardTitle", href: href, id: `title-${productId}`, children: title })), tags && tags.length > 0 && (jsx("div", { className: styles.tags, children: tags.map(tag => (jsx(Tag, { children: jsx(FormattedMessage, { fallbackValue: tag, id: `tag.${tag.toLowerCase()}` }) }, tag))) })), jsx(ProductSku, { className: styles.sku, sku: sku }), jsx(Price, { className: styles.price, currencyCode: price.currencyCode, "data-test-selector": "orderLineCardPrice", originalPrice: price.originalTotalPrice, price: price.totalPrice, pricePerUnit: price.pricePerUnit, variant: "sonic" }), jsx("div", { className: styles['image-container'], role: "presentation", children: jsx(Image, { "data-test-selector": "orderLineCardImage", ...image, fit: "contain" }) }), isReadonly ? (jsx("p", { className: styles.amount, children: jsx(FormattedMessage, { id: "Amount: {0}", replacementValues: { '0': props.quantity.toString() } }) })) : (jsx("div", { className: styles['add-to-cart-button'], children: props.addToCartButton })),
|
|
14
|
+
return (jsxs("article", { "aria-labelledby": `title-${productId}`, className: clsx(styles['orderline-card'], isReadonly && styles.readonly), "data-disabled": isReadonly ? true : undefined, "data-product-id": sku, "data-test-selector": "orderLineListItem", id: productId, children: [isReadonly ? (jsx("div", { className: styles.title, "data-test-selector": "orderLineCardTitle", id: `title-${productId}`, children: title })) : (jsx(RouteLink, { className: styles.title, "data-test-selector": "orderLineCardTitle", href: href, id: `title-${productId}`, children: title })), tags && tags.length > 0 && (jsx("div", { className: styles.tags, children: tags.map(tag => (jsx(Tag, { children: jsx(FormattedMessage, { fallbackValue: tag, id: `tag.${tag.toLowerCase()}` }) }, tag))) })), jsx(ProductSku, { className: styles.sku, sku: sku }), jsx(Price, { className: styles.price, currencyCode: price.currencyCode, "data-test-selector": "orderLineCardPrice", originalPrice: price.originalTotalPrice, price: price.totalPrice, pricePerUnit: price.pricePerUnit, variant: "sonic" }), jsx("div", { className: styles['image-container'], role: "presentation", children: jsx(Image, { "data-test-selector": "orderLineCardImage", ...image, fit: "contain" }) }), isReadonly ? (jsx("p", { className: styles.amount, children: jsx(FormattedMessage, { id: "Amount: {0}", replacementValues: { '0': props.quantity.toString() } }) })) : (jsx("div", { className: styles['add-to-cart-button'], children: props.addToCartButton })), jsx(DeliveryTime, { className: styles.delivery, deliveryDate: deliveryDate }), !isReadonly && (jsx("div", { className: styles.remove, "data-test-selector": "orderLineCardRemove", children: props.removeButton }))] }));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export { OrderLineCard };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface CascadingComponentContainerProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
onClose?: VoidFunction;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function CascadingComponentContainerProvider({ children, onClose, timeout, }: CascadingComponentContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useMemo, useEffect } from 'react';
|
|
3
|
+
import { voidFunction } from '../../shared/model/defaults.js';
|
|
4
|
+
import { CascadingComponentContainerContext } from './cascading-component-container-context.js';
|
|
5
|
+
import { useCascadingComponentContainer } from './use-cascading-component-container.js';
|
|
6
|
+
|
|
7
|
+
function CascadingComponentContainerProvider({ children, onClose, timeout, }) {
|
|
8
|
+
const parentContext = useCascadingComponentContainer();
|
|
9
|
+
const [closeChildrenFns, updateCloseChildrenFns] = useState([]);
|
|
10
|
+
const value = useMemo(() => ({
|
|
11
|
+
close: onClose || voidFunction,
|
|
12
|
+
closeChildCascadingComponents: () => closeChildrenFns.forEach(fn => fn()),
|
|
13
|
+
registerChild: onClose => updateCloseChildrenFns(fns => [...fns, onClose]),
|
|
14
|
+
timeout,
|
|
15
|
+
unregisterChild: onClose => updateCloseChildrenFns(fns => fns.filter(fn => fn !== onClose)),
|
|
16
|
+
}),
|
|
17
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
|
+
[onClose, timeout]);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!parentContext || !onClose)
|
|
21
|
+
return;
|
|
22
|
+
parentContext.registerChild(onClose);
|
|
23
|
+
return () => parentContext.unregisterChild(onClose);
|
|
24
|
+
}, [onClose, parentContext]);
|
|
25
|
+
return (jsx(CascadingComponentContainerContext.Provider, { value: value, children: children }));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { CascadingComponentContainerProvider };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface CascadingComponentProps {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
onClose?: VoidFunction;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function CascadingComponentContainer({ children, onClose, timeout, }: CascadingComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { CascadingComponentContainerProvider } from './cascading-component-container-provider.js';
|
|
3
|
+
|
|
4
|
+
function CascadingComponentContainer({ children, onClose, timeout, }) {
|
|
5
|
+
return (jsx(CascadingComponentContainerProvider, { onClose: onClose, timeout: timeout, children: children }));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { CascadingComponentContainer };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RefHTMLElement } from '../unmounter/utils';
|
|
3
|
+
import { CascadingComponentContainerProps } from './cascading-component-container-provider';
|
|
4
|
+
interface CascadingComponentProps<TElement extends HTMLElement = HTMLElement, RefElement extends RefHTMLElement<TElement> = undefined> {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
isVisible?: boolean;
|
|
7
|
+
nodeRef: React.Ref<RefElement>;
|
|
8
|
+
onUnmounted?: () => void;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function CascadingComponent<TElement extends HTMLElement = HTMLElement, RefElement extends RefHTMLElement<TElement> = undefined>({ children, isVisible, nodeRef, onClose, onUnmounted, timeout, }: CascadingComponentProps<TElement, RefElement> & CascadingComponentContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function InternalCascadingComponent<TElement extends HTMLElement = HTMLElement, RefElement extends RefHTMLElement<TElement> = undefined>({ children, isVisible: _isVisible, nodeRef, onUnmounted, timeout: timeout, }: CascadingComponentProps<TElement, RefElement>): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { CSSTransition } from 'react-transition-group';
|
|
4
|
+
import { Unmounter } from '../unmounter/unmounter.js';
|
|
5
|
+
import { createAddEndListener } from '../unmounter/utils.js';
|
|
6
|
+
import { CascadingComponentContainerProvider } from './cascading-component-container-provider.js';
|
|
7
|
+
import { useCascadingComponentContainer } from './use-cascading-component-container.js';
|
|
8
|
+
|
|
9
|
+
function CascadingComponent({ children, isVisible = false, nodeRef, onClose, onUnmounted, timeout, }) {
|
|
10
|
+
const context = useCascadingComponentContainer();
|
|
11
|
+
if (!context) {
|
|
12
|
+
return (jsx(Fragment, { children: jsx(CascadingComponentContainerProvider, { onClose: onClose, timeout: timeout, children: jsx(InternalCascadingComponent, { isVisible: isVisible, nodeRef: nodeRef, onUnmounted: onUnmounted, timeout: timeout, children: children }) }) }));
|
|
13
|
+
}
|
|
14
|
+
return (jsx(InternalCascadingComponent, { isVisible: isVisible, nodeRef: nodeRef, onUnmounted: onUnmounted, timeout: timeout || context.timeout, children: children }));
|
|
15
|
+
}
|
|
16
|
+
function InternalCascadingComponent({ children, isVisible: _isVisible = false, nodeRef, onUnmounted, timeout: timeout, }) {
|
|
17
|
+
const [isVisible, setIsVisible] = useState(_isVisible);
|
|
18
|
+
const [unmount, setUnmount] = useState(false);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (_isVisible) {
|
|
21
|
+
setIsVisible(_isVisible);
|
|
22
|
+
setUnmount(false);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
setUnmount(true);
|
|
26
|
+
}
|
|
27
|
+
}, [_isVisible]);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (isVisible) {
|
|
30
|
+
setUnmount(false);
|
|
31
|
+
}
|
|
32
|
+
}, [isVisible]);
|
|
33
|
+
const onUnmountReady = useCallback(() => {
|
|
34
|
+
setIsVisible(false);
|
|
35
|
+
}, []);
|
|
36
|
+
const onClose = useCallback(() => {
|
|
37
|
+
setUnmount(true);
|
|
38
|
+
}, []);
|
|
39
|
+
return (jsx(CSSTransition, { mountOnEnter: true, unmountOnExit: true, ...(timeout === undefined
|
|
40
|
+
? { addEndListener: createAddEndListener(nodeRef) }
|
|
41
|
+
: { timeout }), in: isVisible, nodeRef: nodeRef, children: jsx(Unmounter, { onUnmounted: onUnmounted, onUnmountReady: onUnmountReady, unmount: unmount, children: jsx(CascadingComponentContainerProvider, { onClose: onClose, timeout: timeout, children: children }) }) }));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { CascadingComponent, InternalCascadingComponent };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CascadingComponentContainerContextType {
|
|
2
|
+
close: VoidFunction;
|
|
3
|
+
closeChildCascadingComponents: VoidFunction;
|
|
4
|
+
registerChild: (closeFn: VoidFunction) => void;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
unregisterChild: (closeFn: VoidFunction) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface CascadingComponentContextType {
|
|
9
|
+
close: VoidFunction;
|
|
10
|
+
closeChildCascadingComponents: VoidFunction;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { CascadingComponentContainerContext } from './cascading-component-container-context.js';
|
|
3
|
+
|
|
4
|
+
function useCascadingComponentContainer() {
|
|
5
|
+
return useContext(CascadingComponentContainerContext);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { useCascadingComponentContainer };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useCascadingComponentContainer } from './use-cascading-component-container.js';
|
|
2
|
+
|
|
3
|
+
function useCascadingComponent() {
|
|
4
|
+
const context = useCascadingComponentContainer();
|
|
5
|
+
if (!context) {
|
|
6
|
+
throw new Error('useCascadingComponent must be used within a CascadingComponentProvider');
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
close: context.close,
|
|
10
|
+
closeChildCascadingComponents: context.closeChildCascadingComponents,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useCascadingComponent };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useHasCascadingComponentContainer(): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface UnmounterContextType {
|
|
3
|
+
registerChild: () => void;
|
|
4
|
+
unmount: boolean;
|
|
5
|
+
unregisterChild: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const UnmounterContext: React.Context<UnmounterContextType | null>;
|
|
8
|
+
export declare function useUnmount(): UnmounterContextType | null;
|
|
9
|
+
export declare function Unmounter({ children: children, onUnmounted, onUnmountReady, unmount: _unmount, }: {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
onUnmountReady?: () => void;
|
|
12
|
+
onUnmounted?: () => void;
|
|
13
|
+
unmount?: boolean;
|
|
14
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useContext, useState, useEffect, useMemo } from 'react';
|
|
3
|
+
|
|
4
|
+
const UnmounterContext = createContext(null);
|
|
5
|
+
function useUnmount() {
|
|
6
|
+
const context = useContext(UnmounterContext);
|
|
7
|
+
return context;
|
|
8
|
+
}
|
|
9
|
+
function Unmounter({ children: children, onUnmounted, onUnmountReady, unmount: _unmount = false, }) {
|
|
10
|
+
const parentContext = useUnmount();
|
|
11
|
+
const [hadChildren, setHadChildren] = useState(false);
|
|
12
|
+
const [childCount, updateChildCount] = useState(0);
|
|
13
|
+
const unmount = Boolean(_unmount || parentContext?.unmount);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
return () => onUnmounted?.();
|
|
16
|
+
}, [onUnmounted]);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!parentContext)
|
|
19
|
+
return;
|
|
20
|
+
parentContext.registerChild();
|
|
21
|
+
return () => {
|
|
22
|
+
parentContext.unregisterChild();
|
|
23
|
+
};
|
|
24
|
+
}, [parentContext]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!unmount || (hadChildren && childCount > 0))
|
|
27
|
+
return;
|
|
28
|
+
onUnmountReady?.();
|
|
29
|
+
}, [unmount, childCount, hadChildren, onUnmountReady]);
|
|
30
|
+
const value = useMemo(() => {
|
|
31
|
+
return {
|
|
32
|
+
registerChild: () => {
|
|
33
|
+
setHadChildren(true);
|
|
34
|
+
updateChildCount(count => count + 1);
|
|
35
|
+
},
|
|
36
|
+
unmount,
|
|
37
|
+
unregisterChild: () => updateChildCount(count => count - 1),
|
|
38
|
+
};
|
|
39
|
+
}, [unmount]);
|
|
40
|
+
return (jsx(UnmounterContext.Provider, { value: value, children: children }));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { Unmounter, UnmounterContext, useUnmount };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type RefHTMLElement<TElement extends HTMLElement> = TElement | undefined;
|
|
2
|
+
export declare function createAddEndListener<TElement extends HTMLElement, RefElement extends RefHTMLElement<TElement> = undefined>(nodeRef: React.Ref<RefElement>): (doneOrNode: VoidFunction | HTMLElement, done?: VoidFunction) => void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function createAddEndListener(nodeRef) {
|
|
2
|
+
return function addEndListener(doneOrNode, done) {
|
|
3
|
+
if (done === undefined) {
|
|
4
|
+
if (typeof doneOrNode === 'function') {
|
|
5
|
+
if (nodeRef && 'current' in nodeRef && nodeRef.current) {
|
|
6
|
+
return nodeRef.current.addEventListener('transitionend', doneOrNode, false);
|
|
7
|
+
}
|
|
8
|
+
throw new Error('Unsupported CSSTransition addEndListener function call');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
else if (typeof doneOrNode !== 'function') {
|
|
12
|
+
return doneOrNode.addEventListener('transitionend', done, false);
|
|
13
|
+
}
|
|
14
|
+
throw new Error('Unsupported CSSTransition addEndListener function call');
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { createAddEndListener };
|
|
@@ -20,7 +20,7 @@ function CountrySelect({ countries, countryNameInLanguageOfCountry = false, 'dat
|
|
|
20
20
|
}), {}),
|
|
21
21
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22
22
|
[countries]);
|
|
23
|
-
return (jsx(SelectField, { "data-key": selectedCountry?.id, "data-test-selector": dataTestSelector, defaultSelectedOption: defaultSelectedCountry?.id, isDisabled: isDisabled, isLoading: isLoading, isRequired: isRequired, label: t('Country'), name: name, onChange: value => onCountryChange?.(countries.find(country => country.id === value)), options: countryOptions, selectedOption: selectedCountry?.id, showLabel: showLabel,
|
|
23
|
+
return (jsx(SelectField, { "data-key": selectedCountry?.id, "data-test-selector": dataTestSelector, defaultSelectedOption: defaultSelectedCountry?.id, isDisabled: isDisabled, isLoading: isLoading, isRequired: isRequired, label: t('Country'), name: name, onChange: value => onCountryChange?.(countries.find(country => country.id === value)), options: countryOptions, placeholder: t('Select a country'), selectedOption: selectedCountry?.id, showLabel: showLabel, variant: "solid" }));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export { CountrySelect };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useMemo, useEffect } from 'react';
|
|
4
|
+
import { logger } from '../logging/logger.js';
|
|
4
5
|
import { useDisclosure } from '../shared/hooks/use-disclosure.js';
|
|
5
6
|
import { CountrySelectorDialog } from './country-selector-dialog/country-selector-dialog.js';
|
|
6
7
|
import { CountrySelectorTrigger } from './country-selector-trigger/country-selector-trigger.js';
|
|
@@ -8,18 +9,35 @@ import { useCountriesLanguages } from './use-countries-languages.js';
|
|
|
8
9
|
|
|
9
10
|
function ConnectedCountrySelector({ defaultCountryCode, defaultLanguageCode, onChange, showCountry = true, }) {
|
|
10
11
|
const { close, isOpen, open, setIsOpen } = useDisclosure(false);
|
|
11
|
-
const { countries, defaultCountry, defaultLanguage, isFetching, selectedCountry, selectedLanguage, updateCountryLanguage, } = useCountriesLanguages({
|
|
12
|
+
const { countries, defaultCountry, defaultLanguage, error, isFetching, selectedCountry, selectedLanguage, updateCountryLanguage, } = useCountriesLanguages({
|
|
12
13
|
defaultCountryCode,
|
|
13
14
|
defaultLanguageCode,
|
|
14
15
|
});
|
|
15
16
|
const isCountryLanguageSelected = useMemo(() => selectedCountry !== undefined && selectedLanguage !== undefined, [selectedCountry, selectedLanguage]);
|
|
16
17
|
const isDismissable = isCountryLanguageSelected;
|
|
17
18
|
useEffect(() => {
|
|
19
|
+
if (!isFetching) {
|
|
20
|
+
if (selectedCountry === undefined && selectedLanguage === undefined) {
|
|
21
|
+
logger.info('Opening country selector dialog because no country or language is selected');
|
|
22
|
+
}
|
|
23
|
+
else if (selectedCountry === undefined) {
|
|
24
|
+
logger.info('Opening country selector dialog because no country is selected');
|
|
25
|
+
}
|
|
26
|
+
else if (selectedLanguage === undefined) {
|
|
27
|
+
logger.info('Opening country selector dialog because no language is selected');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (isOpen)
|
|
31
|
+
return;
|
|
18
32
|
setIsOpen(!isFetching && !isCountryLanguageSelected);
|
|
19
33
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
-
}, [isFetching, isCountryLanguageSelected]);
|
|
34
|
+
}, [isFetching, isCountryLanguageSelected, isOpen]);
|
|
21
35
|
if (isFetching)
|
|
22
36
|
return null;
|
|
37
|
+
if (error !== undefined) {
|
|
38
|
+
logger.error('Error fetching countries and languages:', error);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
23
41
|
return (jsxs(Fragment, { children: [jsx(CountrySelectorTrigger, { onClick: open, selectedCountry: selectedCountry, selectedLanguage: selectedLanguage, showCountry: showCountry }), jsx(CountrySelectorDialog, { countries: countries, isDismissable: isDismissable, isOpen: isOpen, onOpenChange: open => {
|
|
24
42
|
if (!isDismissable)
|
|
25
43
|
return;
|
|
@@ -32,7 +32,7 @@ function CountrySelectorDialog({ countries, isDismissable, isOpen, onOpenChange,
|
|
|
32
32
|
onSubmit({ country: currentCountry, language: currentLanguage });
|
|
33
33
|
e.preventDefault();
|
|
34
34
|
e.stopPropagation();
|
|
35
|
-
}, shouldCloseOnInteractOutside: isDismissable, title: "Country Selector", children: jsxs("div", { className: styles.content, children: [jsx("svg", { className: styles.logo, height: "32", viewBox: "0 0 134 32", width: "134", xmlns: "http://www.w3.org/2000/svg", children: jsxs("g", { fill: "none", fillRule: "evenodd", children: [jsx("path", { d: "M15.83 11.533c2.42 0 4.382 1.977 4.382 4.415 0 8.794-7.1 15.95-15.83 15.95C1.963 31.897 0 29.92 0 27.481c0-2.354 1.83-4.278 4.134-4.408l.249-.007c3.797 0 6.905-3.036 7.058-6.826l.006-.293c0-2.438 1.963-4.415 4.383-4.415zM15.83 0c2.42 0 4.383 1.977 4.383 4.415 0 2.355-1.83 4.279-4.134 4.409l-.249.007c-3.8 0-6.906 3.035-7.059 6.824l-.006.293c0 2.438-1.962 4.415-4.382 4.415S0 18.386 0 15.948C0 7.154 7.101 0 15.83 0zm8.208 16.022c0 8.794 7.101 15.95 15.83 15.95s15.83-7.156 15.83-15.95S48.597.074 39.868.074s-15.83 7.154-15.83 15.948zm8.765 0c0-3.924 3.169-7.118 7.065-7.118 3.895 0 7.065 3.194 7.065 7.118 0 3.926-3.17 7.119-7.065 7.119-3.896 0-7.065-3.193-7.065-7.12zm76.888-11.276c-6.173 6.217-6.173 16.335-.002 22.553 6.173 6.217 16.215 6.217 22.388 0a4.44 4.44 0 0 0 .001-6.244 4.359 4.359 0 0 0-6.003-.184l-.194.184a7.04 7.04 0 0 1-9.994 0c-2.753-2.775-2.753-7.29.002-10.065a7.036 7.036 0 0 1 9.751-.233l.24.231a4.36 4.36 0 0 0 6.198 0 4.44 4.44 0 0 0-.001-6.245c-6.173-6.217-16.215-6.216-22.386.003zm-17.162-.174v22.863c0 2.439 1.961 4.416 4.381 4.416 2.422 0 4.384-1.977 4.384-4.416V4.572c0-2.439-1.962-4.416-4.384-4.416-2.42 0-4.38 1.977-4.38 4.416zM64.1.1c-2.42 0-4.383 1.977-4.383 4.415v23.07c0 2.438 1.962 4.415 4.382 4.415s4.383-1.977 4.383-4.415V8.93h3.933c3.895 0 7.065 3.192 7.065 7.118v11.537c0 2.438 1.962 4.415 4.382 4.415s4.383-1.977 4.383-4.415V16.048C88.244 7.254 81.143.1 72.414.1h-8.316z", fill: "#000" }), jsx("path", { d: "M47.036 16.022c0 3.99-3.209 7.222-7.168 7.222-3.96 0-7.169-3.233-7.169-7.222 0-3.989 3.21-7.222 7.169-7.222 3.96 0 7.168 3.233 7.168 7.222", fill: "#E30613" })] }) }), jsx("p", { className: styles.intro, children: jsx(FormattedMessage, { id: "Welcome to Sonic Equipment. Please choose your country and language below." }) }), jsxs("div", { className: styles.selects, children: [showCountry && (jsx(CountrySelect, { countries: countries, countryNameInLanguageOfCountry: true, "data-test-selector": "clSelector_country", onCountryChange: onCountryChange, selectedCountry: currentCountry })), jsx(Select, { "data-test-selector": "clSelector_language", label: t('Language'), onChange: value => setCurrentLanguage(currentCountry.languages.find(language => language.id === value) || currentLanguage), options: languageOptions, selectedOption: currentLanguage.id, showPlaceholder: false, variant: "solid" })] })] }) }));
|
|
35
|
+
}, shouldCloseOnInteractOutside: isDismissable, title: "Country Selector", children: jsxs("div", { className: styles.content, children: [jsx("svg", { className: styles.logo, height: "32", viewBox: "0 0 134 32", width: "134", xmlns: "http://www.w3.org/2000/svg", children: jsxs("g", { fill: "none", fillRule: "evenodd", children: [jsx("path", { d: "M15.83 11.533c2.42 0 4.382 1.977 4.382 4.415 0 8.794-7.1 15.95-15.83 15.95C1.963 31.897 0 29.92 0 27.481c0-2.354 1.83-4.278 4.134-4.408l.249-.007c3.797 0 6.905-3.036 7.058-6.826l.006-.293c0-2.438 1.963-4.415 4.383-4.415zM15.83 0c2.42 0 4.383 1.977 4.383 4.415 0 2.355-1.83 4.279-4.134 4.409l-.249.007c-3.8 0-6.906 3.035-7.059 6.824l-.006.293c0 2.438-1.962 4.415-4.382 4.415S0 18.386 0 15.948C0 7.154 7.101 0 15.83 0zm8.208 16.022c0 8.794 7.101 15.95 15.83 15.95s15.83-7.156 15.83-15.95S48.597.074 39.868.074s-15.83 7.154-15.83 15.948zm8.765 0c0-3.924 3.169-7.118 7.065-7.118 3.895 0 7.065 3.194 7.065 7.118 0 3.926-3.17 7.119-7.065 7.119-3.896 0-7.065-3.193-7.065-7.12zm76.888-11.276c-6.173 6.217-6.173 16.335-.002 22.553 6.173 6.217 16.215 6.217 22.388 0a4.44 4.44 0 0 0 .001-6.244 4.359 4.359 0 0 0-6.003-.184l-.194.184a7.04 7.04 0 0 1-9.994 0c-2.753-2.775-2.753-7.29.002-10.065a7.036 7.036 0 0 1 9.751-.233l.24.231a4.36 4.36 0 0 0 6.198 0 4.44 4.44 0 0 0-.001-6.245c-6.173-6.217-16.215-6.216-22.386.003zm-17.162-.174v22.863c0 2.439 1.961 4.416 4.381 4.416 2.422 0 4.384-1.977 4.384-4.416V4.572c0-2.439-1.962-4.416-4.384-4.416-2.42 0-4.38 1.977-4.38 4.416zM64.1.1c-2.42 0-4.383 1.977-4.383 4.415v23.07c0 2.438 1.962 4.415 4.382 4.415s4.383-1.977 4.383-4.415V8.93h3.933c3.895 0 7.065 3.192 7.065 7.118v11.537c0 2.438 1.962 4.415 4.382 4.415s4.383-1.977 4.383-4.415V16.048C88.244 7.254 81.143.1 72.414.1h-8.316z", fill: "#000" }), jsx("path", { d: "M47.036 16.022c0 3.99-3.209 7.222-7.168 7.222-3.96 0-7.169-3.233-7.169-7.222 0-3.989 3.21-7.222 7.169-7.222 3.96 0 7.168 3.233 7.168 7.222", fill: "#E30613" })] }) }), jsx("p", { className: styles.intro, children: jsx(FormattedMessage, { id: "Welcome to Sonic Equipment. Please choose your country and language below." }) }), jsxs("div", { className: styles.selects, children: [showCountry && (jsx(CountrySelect, { isRequired: true, countries: countries, countryNameInLanguageOfCountry: true, "data-test-selector": "clSelector_country", onCountryChange: onCountryChange, selectedCountry: currentCountry })), jsx(Select, { isRequired: true, "data-test-selector": "clSelector_language", label: t('Language'), onChange: value => setCurrentLanguage(currentCountry.languages.find(language => language.id === value) || currentLanguage), options: languageOptions, placeholder: t('Select a language'), selectedOption: currentLanguage.id, showPlaceholder: false, variant: "solid" })] })] }) }));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export { CountrySelectorDialog };
|
|
@@ -4,10 +4,24 @@ interface UseCountriesLanguagesArgs {
|
|
|
4
4
|
defaultCountryCode: CountryCode;
|
|
5
5
|
defaultLanguageCode: LanguageCode;
|
|
6
6
|
}
|
|
7
|
+
interface UseCountriesLanguagesReturnTypeError {
|
|
8
|
+
countries: undefined;
|
|
9
|
+
defaultCountry: undefined;
|
|
10
|
+
defaultLanguage: undefined;
|
|
11
|
+
error: object | Error | string;
|
|
12
|
+
isFetching: false;
|
|
13
|
+
selectedCountry: undefined;
|
|
14
|
+
selectedLanguage: undefined;
|
|
15
|
+
updateCountryLanguage(args: {
|
|
16
|
+
country: Country;
|
|
17
|
+
language: Language;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
}
|
|
7
20
|
interface UseCountriesLanguagesReturnTypeFetching {
|
|
8
21
|
countries: undefined;
|
|
9
22
|
defaultCountry: undefined;
|
|
10
23
|
defaultLanguage: undefined;
|
|
24
|
+
error: undefined;
|
|
11
25
|
isFetching: true;
|
|
12
26
|
selectedCountry: undefined;
|
|
13
27
|
selectedLanguage: undefined;
|
|
@@ -20,6 +34,7 @@ interface UseCountriesLanguagesReturnTypeSelected {
|
|
|
20
34
|
countries: Country[];
|
|
21
35
|
defaultCountry: Country;
|
|
22
36
|
defaultLanguage: Language;
|
|
37
|
+
error: undefined;
|
|
23
38
|
isFetching: false;
|
|
24
39
|
selectedCountry: Country;
|
|
25
40
|
selectedLanguage: Language;
|
|
@@ -32,6 +47,7 @@ interface UseCountriesLanguagesReturnType {
|
|
|
32
47
|
countries: Country[];
|
|
33
48
|
defaultCountry: Country;
|
|
34
49
|
defaultLanguage: Language;
|
|
50
|
+
error: undefined;
|
|
35
51
|
isFetching: false;
|
|
36
52
|
selectedCountry: Country | undefined;
|
|
37
53
|
selectedLanguage: Language | undefined;
|
|
@@ -40,5 +56,5 @@ interface UseCountriesLanguagesReturnType {
|
|
|
40
56
|
language: Language;
|
|
41
57
|
}): Promise<void>;
|
|
42
58
|
}
|
|
43
|
-
export declare function useCountriesLanguages({ defaultCountryCode, defaultLanguageCode, }: UseCountriesLanguagesArgs): UseCountriesLanguagesReturnType | UseCountriesLanguagesReturnTypeFetching | UseCountriesLanguagesReturnTypeSelected;
|
|
59
|
+
export declare function useCountriesLanguages({ defaultCountryCode, defaultLanguageCode, }: UseCountriesLanguagesArgs): UseCountriesLanguagesReturnType | UseCountriesLanguagesReturnTypeError | UseCountriesLanguagesReturnTypeFetching | UseCountriesLanguagesReturnTypeSelected;
|
|
44
60
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { config } from '../config.js';
|
|
4
|
+
import { logger } from '../logging/logger.js';
|
|
4
5
|
import { useFetchCountriesWithLanguages } from '../shared/api/storefront/hooks/website/use-fetch-countries-with-languages.js';
|
|
5
6
|
import { updateLocale } from '../shared/api/storefront/services/website-service.js';
|
|
6
7
|
import { useCookie } from '../shared/hooks/use-cookie.js';
|
|
@@ -17,8 +18,8 @@ const cookieOptions = {
|
|
|
17
18
|
function useCountriesLanguages({ defaultCountryCode, defaultLanguageCode, }) {
|
|
18
19
|
const [sessionCountries, setSessionCountries] = useSessionStorage('countries-v1');
|
|
19
20
|
const [currentCountryId] = useCookie('CurrentCountryId', cookieOptions);
|
|
21
|
+
// const [currentLanguageId] = ['be71b608-4876-420a-b1f5-adfe0093a72a'] // useCookie('CurrentLanguageId', cookieOptions)
|
|
20
22
|
const [currentLanguageId] = useCookie('CurrentLanguageId', cookieOptions);
|
|
21
|
-
const [contextLanguageCode] = useCookie('SetContextLanguageCode', cookieOptions);
|
|
22
23
|
const hasSessionCountries = Boolean(sessionCountries?.length);
|
|
23
24
|
const { data: apiCountries, error, isFetching, } = useFetchCountriesWithLanguages({
|
|
24
25
|
enabled: !hasSessionCountries,
|
|
@@ -32,44 +33,72 @@ function useCountriesLanguages({ defaultCountryCode, defaultLanguageCode, }) {
|
|
|
32
33
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
34
|
}, [apiCountries]);
|
|
34
35
|
async function updateCountryLanguage({ country, language, }) {
|
|
35
|
-
await updateLocale({
|
|
36
|
+
await updateLocale({
|
|
37
|
+
countryId: country.id,
|
|
38
|
+
languageId: language.id,
|
|
39
|
+
});
|
|
36
40
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
logger.info('CountryID from cookie', currentCountryId, countries?.find(country => country.id === currentCountryId)?.name ||
|
|
43
|
+
'Unknown');
|
|
44
|
+
}, [countries, currentCountryId]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
logger.info('LanguageID from cookie', currentLanguageId, countries
|
|
47
|
+
?.find(country => country.id === currentCountryId)
|
|
48
|
+
?.languages.find(language => language.id === currentLanguageId)
|
|
49
|
+
?.description || 'Unknown');
|
|
50
|
+
}, [countries, currentCountryId, currentLanguageId]);
|
|
51
|
+
try {
|
|
52
|
+
if (error)
|
|
53
|
+
throw error;
|
|
54
|
+
if (isFetching) {
|
|
55
|
+
return {
|
|
56
|
+
countries: undefined,
|
|
57
|
+
defaultCountry: undefined,
|
|
58
|
+
defaultLanguage: undefined,
|
|
59
|
+
error: undefined,
|
|
60
|
+
isFetching,
|
|
61
|
+
selectedCountry: undefined,
|
|
62
|
+
selectedLanguage: undefined,
|
|
63
|
+
updateCountryLanguage,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (!countries || countries.length === 0)
|
|
67
|
+
throw new Error('No countries found');
|
|
68
|
+
const defaultCountry = countries.find(country => country.abbreviation.toUpperCase() ===
|
|
69
|
+
defaultCountryCode.toUpperCase()) || countries[0];
|
|
70
|
+
if (!defaultCountry)
|
|
71
|
+
throw new Error(`Unable to find the default country ${defaultCountryCode}`);
|
|
72
|
+
const defaultLanguage = defaultCountry.languages.find(language => language.languageCode.toUpperCase() ===
|
|
73
|
+
defaultLanguageCode.toUpperCase()) || defaultCountry.languages[0];
|
|
74
|
+
if (!defaultLanguage)
|
|
75
|
+
throw new Error(`Unable to find the default language ${defaultLanguageCode} for country ${defaultCountry.name}`);
|
|
76
|
+
const selectedCountry = countries.find(country => country.id === currentCountryId);
|
|
77
|
+
const selectedLanguage = selectedCountry &&
|
|
78
|
+
selectedCountry.languages.find(language => language.id === currentLanguageId);
|
|
79
|
+
return {
|
|
80
|
+
countries,
|
|
81
|
+
defaultCountry,
|
|
82
|
+
defaultLanguage,
|
|
83
|
+
error: undefined,
|
|
84
|
+
isFetching,
|
|
85
|
+
selectedCountry,
|
|
86
|
+
selectedLanguage,
|
|
87
|
+
updateCountryLanguage,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
40
91
|
return {
|
|
41
92
|
countries: undefined,
|
|
42
93
|
defaultCountry: undefined,
|
|
43
94
|
defaultLanguage: undefined,
|
|
44
|
-
|
|
95
|
+
error: error,
|
|
96
|
+
isFetching: false,
|
|
45
97
|
selectedCountry: undefined,
|
|
46
98
|
selectedLanguage: undefined,
|
|
47
99
|
updateCountryLanguage,
|
|
48
100
|
};
|
|
49
101
|
}
|
|
50
|
-
if (!countries || countries.length === 0)
|
|
51
|
-
throw new Error('No countries found');
|
|
52
|
-
const defaultCountry = countries.find(country => country.abbreviation.toUpperCase() === defaultCountryCode.toUpperCase()) || countries[0];
|
|
53
|
-
if (!defaultCountry)
|
|
54
|
-
throw new Error(`Unable to find the default country ${defaultCountryCode}`);
|
|
55
|
-
const defaultLanguage = defaultCountry.languages.find(language => language.languageCode.toUpperCase() ===
|
|
56
|
-
defaultLanguageCode.toUpperCase()) || defaultCountry.languages[0];
|
|
57
|
-
if (!defaultLanguage)
|
|
58
|
-
throw new Error(`Unable to find the default language ${defaultLanguageCode} for country ${defaultCountry.name}`);
|
|
59
|
-
const selectedCountry = countries.find(country => country.id === currentCountryId);
|
|
60
|
-
const selectedLanguage = selectedCountry &&
|
|
61
|
-
(selectedCountry.languages.find(language => language.id === currentLanguageId) ||
|
|
62
|
-
selectedCountry.languages.find(language => language.languageCode.toUpperCase() ===
|
|
63
|
-
contextLanguageCode?.toUpperCase()));
|
|
64
|
-
return {
|
|
65
|
-
countries,
|
|
66
|
-
defaultCountry,
|
|
67
|
-
defaultLanguage,
|
|
68
|
-
isFetching,
|
|
69
|
-
selectedCountry,
|
|
70
|
-
selectedLanguage,
|
|
71
|
-
updateCountryLanguage,
|
|
72
|
-
};
|
|
73
102
|
}
|
|
74
103
|
|
|
75
104
|
export { useCountriesLanguages };
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { FormattedMessage } from '../intl/formatted-message.js';
|
|
5
|
-
import { useFormattedMessage } from '../intl/use-formatted-message.js';
|
|
6
|
-
import { getDateUnitObject } from '../shared/utils/date.js';
|
|
7
5
|
import { InfoIconTooltip } from '../info-icon-tooltip/info-icon-tooltip.js';
|
|
6
|
+
import { useFormattedMessage } from '../intl/use-formatted-message.js';
|
|
7
|
+
import { useIntl } from '../intl/use-intl.js';
|
|
8
|
+
import { formatDateToLocaleString } from '../shared/utils/date.js';
|
|
8
9
|
import styles from './delivery-time.module.css.js';
|
|
9
10
|
|
|
10
11
|
function DeliveryTime({ className, deliveryDate }) {
|
|
12
|
+
const { cultureCode } = useIntl();
|
|
11
13
|
const t = useFormattedMessage();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if (!deliveryDate) {
|
|
15
|
+
return (jsx("div", { className: clsx(styles['delivery-time'], className), children: jsx("p", {
|
|
16
|
+
// eslint-disable-next-line @eslint-react/dom/no-dangerously-set-innerhtml
|
|
17
|
+
dangerouslySetInnerHTML: {
|
|
18
|
+
__html: t('Availability unknown, please contact customer support for lead time or alternatives.'),
|
|
19
|
+
}, "data-test-selector": "deliveryTime_unknown" }) }));
|
|
20
|
+
}
|
|
21
|
+
const localeDate = formatDateToLocaleString(deliveryDate, cultureCode, {
|
|
22
|
+
day: 'numeric',
|
|
23
|
+
month: 'short',
|
|
24
|
+
year: 'numeric',
|
|
25
|
+
});
|
|
26
|
+
return (jsxs("div", { className: clsx(styles['delivery-time'], className), children: [jsx("p", { "data-test-selector": "deliveryTime", children: jsx(FormattedMessage, { id: "Delivery expected on {0}", replacementValues: {
|
|
27
|
+
'0': localeDate,
|
|
28
|
+
} }) }), jsx(InfoIconTooltip, { className: styles['info'], variant: "stroke", children: jsx(FormattedMessage, { id: "The expected delivery is an indication based on the product availability and the shipping location." }) })] }));
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
export { DeliveryTime };
|