@sonic-equipment/ui 260.0.9 → 260.1.1
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/cookies/use-cookie.js +4 -1
- package/dist/country-language-selector/connected-country-language-selector.js +2 -1
- package/dist/forms/fields/select-field/select-field.js +9 -11
- package/dist/header/header.js +2 -5
- package/dist/shared/api/bff/model/bff.model.d.ts +2 -0
- package/dist/shared/routing/route-utils.js +6 -1
- package/package.json +1 -1
|
@@ -10,7 +10,10 @@ function useCookie(name, options = defaultCookieOptions) {
|
|
|
10
10
|
const Cookies = context
|
|
11
11
|
? isCookieGetterSetter(context)
|
|
12
12
|
? context
|
|
13
|
-
:
|
|
13
|
+
: {
|
|
14
|
+
get: createReadonlyCookieReader(context).get,
|
|
15
|
+
set: clientCookieContextValue.set,
|
|
16
|
+
}
|
|
14
17
|
: clientCookieContextValue;
|
|
15
18
|
const cookieValue = Cookies.get()?.[name];
|
|
16
19
|
const [stateValue, setStateValue] = useState(cookieValue);
|
|
@@ -82,7 +82,8 @@ function ConnectedCountryLanguageSelector({ className, countries: _countries, is
|
|
|
82
82
|
path = `/${optionKey}`;
|
|
83
83
|
}
|
|
84
84
|
menuOptions[optionKey] =
|
|
85
|
-
environment === 'next-production'
|
|
85
|
+
environment === 'next-production' ||
|
|
86
|
+
environment === 'production' ? (jsx("span", { lang: languageCode, children: `${t(optionCountryLabel)} - ${t(optionLanguageLabel)}` })) : (jsxs("span", { lang: languageCode, children: [`${t(optionCountryLabel)} - ${t(optionLanguageLabel)}`, jsx("code", { style: { fontSize: '12px' }, children: path })] }));
|
|
86
87
|
optionData.push({
|
|
87
88
|
country: countryCode,
|
|
88
89
|
key: optionKey,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { useState
|
|
3
|
+
import { useState } from 'react';
|
|
4
4
|
import { Select, Button, SelectValue, Popover, ListBox, Header, ListBoxSection, ListBoxItem } from 'react-aria-components';
|
|
5
5
|
import clsx from 'clsx';
|
|
6
6
|
import { Icon } from '../../../icon/icon.js';
|
|
@@ -12,15 +12,13 @@ import { Label } from '../../elements/label/label.js';
|
|
|
12
12
|
import { FormFieldLayout } from '../../layout/form/form-field-layout.js';
|
|
13
13
|
import styles from './select-field.module.css.js';
|
|
14
14
|
|
|
15
|
-
/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */
|
|
16
15
|
function SelectField({ className, 'data-test-selector': dataTestSelector, defaultSelectedOption, info, isDisabled, isInvalid, isLoading, isRequired, label, name, onChange, optionGroups, options, placeholder, selectedOption, showLabel = true, showPlaceholder, size = 'lg', variant = 'outline', }) {
|
|
17
16
|
const [selectedKey, setSelectedKey] = useState(defaultSelectedOption);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
setSelectedKey(selectedOption);
|
|
21
|
-
}, [selectedOption]);
|
|
17
|
+
const isControlled = selectedOption !== undefined;
|
|
18
|
+
const currentSelectedKey = isControlled ? selectedOption : selectedKey;
|
|
22
19
|
const handleChange = (key) => {
|
|
23
|
-
|
|
20
|
+
if (!isControlled)
|
|
21
|
+
setSelectedKey(key);
|
|
24
22
|
onChange?.(key);
|
|
25
23
|
};
|
|
26
24
|
const grouplessOptions = Object.keys(options).filter(key => {
|
|
@@ -32,21 +30,21 @@ function SelectField({ className, 'data-test-selector': dataTestSelector, defaul
|
|
|
32
30
|
[styles['loading']]: isLoading,
|
|
33
31
|
}, className), "data-test-selector": dataTestSelector, defaultSelectedKey: defaultSelectedOption === undefined
|
|
34
32
|
? undefined
|
|
35
|
-
: String(defaultSelectedOption), isDisabled: isDisabled, isInvalid: isInvalid, isRequired: isRequired, name: name, onSelectionChange: key => handleChange(key), placeholder: placeholder || label, selectedKey: selectedOption === undefined ? undefined : String(selectedOption), children: jsx(FormFieldLayout, { errorSlot: jsx(FieldError, {}), infoSlot: info && jsx(InfoIconTooltip, { children: info }), labelSlot: showLabel && jsx(Label, { isRequired: isRequired, children: label }), children: jsxs(Fragment, { children: [jsxs(Button, { className: styles.button, children: [jsx(SelectValue, { className: styles.value, "data-test-selector": "value" }), isLoading ? (jsx(ProgressCircle, { "aria-hidden": "true", className: styles.loading, variant: "gray" })) : (jsx(Icon, { className: styles.icon, name: "ArrowDown", size: "xxs" }))] }), jsx(Popover, { className: clsx(styles.popover, styles[variant]), placement: "bottom left", children: jsxs(ListBox, { className: styles.listbox, "data-test-selector": dataTestSelector ? `${dataTestSelector}_options` : undefined, children: [showPlaceholder && (jsx(Header, { className: styles.header, children: placeholder || label })), optionGroups &&
|
|
33
|
+
: String(defaultSelectedOption), isDisabled: isDisabled, isInvalid: isInvalid, isRequired: isRequired, name: name, onSelectionChange: key => handleChange(key), placeholder: placeholder || label, selectedKey: selectedOption === undefined ? undefined : String(selectedOption), children: jsx(FormFieldLayout, { errorSlot: jsx(FieldError, {}), infoSlot: info && jsx(InfoIconTooltip, { children: info }), labelSlot: showLabel && jsx(Label, { isRequired: isRequired, children: label }), children: jsxs(Fragment, { children: [jsxs(Button, { className: styles.button, children: [jsx(SelectValue, { className: styles.value, "data-test-selector": "value" }), isLoading ? (jsx(ProgressCircle, { "aria-hidden": "true", className: styles.loading, variant: "gray" })) : (jsx(Icon, { className: styles.icon, name: "ArrowDown", size: "xxs" }))] }), jsx(Popover, { className: clsx(styles.popover, styles[variant]), maxHeight: 300, placement: "bottom left", children: jsxs(ListBox, { className: styles.listbox, "data-test-selector": dataTestSelector ? `${dataTestSelector}_options` : undefined, children: [showPlaceholder && (jsx(Header, { className: styles.header, children: placeholder || label })), optionGroups &&
|
|
36
34
|
optionGroups.map(({ key: groupKey, options: groupOptions, reactNode }) => {
|
|
37
35
|
return (groupOptions.some(k => k in options) && (jsxs(ListBoxSection, { className: styles.section, children: [jsx(Header, { className: styles.header, children: reactNode || label }), groupOptions.map(optionKey => {
|
|
38
36
|
const value = options[optionKey];
|
|
39
37
|
const textValue = childrenToText(value);
|
|
40
|
-
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [
|
|
38
|
+
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [currentSelectedKey === optionKey && (jsx("span", { className: styles.icon, slot: "description", children: jsx(Icon, { className: styles.check, name: "Checkmark" }) })), jsx("span", { className: styles.label, slot: "label", children: value })] }, optionKey));
|
|
41
39
|
})] }, groupKey)));
|
|
42
40
|
}), optionGroups && grouplessOptions.length > 0 && (jsx(ListBoxSection, { className: styles.section, children: grouplessOptions.map(optionKey => {
|
|
43
41
|
const value = options[optionKey];
|
|
44
42
|
const textValue = childrenToText(value);
|
|
45
|
-
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [
|
|
43
|
+
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [currentSelectedKey === optionKey && (jsx("span", { className: styles.icon, slot: "description", children: jsx(Icon, { className: styles.check, name: "Checkmark" }) })), jsx("span", { className: styles.label, slot: "label", children: value })] }, optionKey));
|
|
46
44
|
}) })), !optionGroups &&
|
|
47
45
|
Object.entries(options).map(([optionKey, value]) => {
|
|
48
46
|
const textValue = childrenToText(value);
|
|
49
|
-
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [
|
|
47
|
+
return (jsxs(ListBoxItem, { "aria-label": textValue, className: styles.item, id: optionKey, textValue: textValue, children: [currentSelectedKey === optionKey && (jsx("span", { className: styles.icon, slot: "description", children: jsx(Icon, { className: styles.check, name: "Checkmark" }) })), jsx("span", { className: styles.label, slot: "label", children: value })] }, optionKey));
|
|
50
48
|
})] }) })] }) }) }));
|
|
51
49
|
}
|
|
52
50
|
|
package/dist/header/header.js
CHANGED
|
@@ -5,7 +5,7 @@ import clsx from 'clsx';
|
|
|
5
5
|
import { useDrawer } from '../drawer/use-drawer.js';
|
|
6
6
|
import { useGlobalSearchDisclosure } from '../global-search/global-search-provider/use-search-disclosure.js';
|
|
7
7
|
import { useFormattedMessage } from '../intl/use-formatted-message.js';
|
|
8
|
-
import {
|
|
8
|
+
import { isNavigationSection, isNavigationLinkItem } from '../shared/api/bff/model/bff.model.js';
|
|
9
9
|
import { useIsBreakpoint } from '../shared/hooks/use-is-breakpoint.js';
|
|
10
10
|
import { useResizeObserver } from '../shared/hooks/use-resize-observer.js';
|
|
11
11
|
import { useOnNavigate } from '../shared/routing/use-on-navigate.js';
|
|
@@ -67,13 +67,10 @@ function Header({ className, headerNavigationSection, sticky, }) {
|
|
|
67
67
|
if (activeLinkGroup)
|
|
68
68
|
setDesktopNavigationOpen(true);
|
|
69
69
|
}, [activeLinkGroup, setDesktopNavigationOpen]);
|
|
70
|
-
const homeLink = headerNavigationSection?.items
|
|
71
|
-
.filter(isNavigationLink)
|
|
72
|
-
.find(item => item.key === 'home');
|
|
73
70
|
const mainNavigationSection = headerNavigationSection?.items
|
|
74
71
|
.filter(isNavigationSection)
|
|
75
72
|
.find(item => item.key === 'main-navigation');
|
|
76
|
-
return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), "data-test-selector": "pageHeader", children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "pageHeaderHamburgerButton", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { "data-test-selector": "pageHeaderLogo", href:
|
|
73
|
+
return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), "data-test-selector": "pageHeader", children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "pageHeaderHamburgerButton", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { "data-test-selector": "pageHeaderLogo", href: "/", title: t('Home') }), mainNavigation: jsx(NavigationLinkList, { activeLink: activeLinkGroup, "data-test-selector": "pageHeaderMainNavigation", navigationSection: mainNavigationSection, onSubmenuToggle: toggleActiveSubmenu }), navigationActions: jsxs(Fragment, { children: [jsx(ConnectedAccountButton, { "data-test-selector": "pageHeaderAccountButton" }), jsx(ConnectedFavoritesButton, { "data-test-selector": "pageHeaderFavoritesButton", href: "abc" }), jsx(ConnectedCartButton, { "data-test-selector": "pageHeaderCartButton", href: paths.CART })] }), search: jsx(SearchButton, { "aria-controls": "global-search", "data-test-selector": "pageHeaderSearchButton", isActive: searchOpen, onActiveChange: toggleSearch }) }) }), jsx(SearchDrawer, { groupId: searchGroupId, instanceId: searchInstanceId }), !isXl && (jsx(MobileNavigationDrawer, { groupId: mobileNavigationDrawer.groupId, instanceId: mobileNavigationDrawer.instanceId, linkItems: mainNavigationSection?.items.filter(isNavigationLinkItem) })), isXl && (jsx(DesktopNavigationDrawer, { groupId: desktopNavigationDrawer.groupId, instanceId: desktopNavigationDrawer.instanceId, linkGroup: activeLinkGroup, onClosed: () => setActiveLinkGroup(undefined) }))] }));
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
export { Header };
|
|
@@ -8,9 +8,11 @@ export interface PageModel {
|
|
|
8
8
|
canonicalPath: string;
|
|
9
9
|
metaDescription: string;
|
|
10
10
|
metaKeywords: string;
|
|
11
|
+
needRedirect: boolean;
|
|
11
12
|
openGraphImage: string;
|
|
12
13
|
openGraphTitle: string;
|
|
13
14
|
openGraphUrl: string;
|
|
15
|
+
redirectUrl: string;
|
|
14
16
|
title: string;
|
|
15
17
|
}
|
|
16
18
|
interface Category {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
const malformedLinkRegex = /\b[a-z]{2}-[a-z]{2}\/[a-z]{2}(?=[#/?]|$)/i;
|
|
1
2
|
function buildHref({ basePathname, href, ignoreLocalePrefix, }) {
|
|
2
3
|
if (!href.startsWith('http') &&
|
|
3
4
|
basePathname &&
|
|
4
5
|
basePathname !== '/' &&
|
|
5
6
|
!ignoreLocalePrefix &&
|
|
6
7
|
!href.startsWith(`/${basePathname}`)) {
|
|
7
|
-
|
|
8
|
+
const urlWithbasePath = `/${basePathname.replace(/^\//, '')}/${href.replace(/^\//, '')}`;
|
|
9
|
+
const isMalformed = new RegExp(malformedLinkRegex).test(urlWithbasePath);
|
|
10
|
+
return isMalformed
|
|
11
|
+
? urlWithbasePath.replace(/([a-z]{2}-[a-z]{2})\/[a-z]{2}(?=[#/?]|$)/i, '$1')
|
|
12
|
+
: urlWithbasePath;
|
|
8
13
|
}
|
|
9
14
|
return href;
|
|
10
15
|
}
|