@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.
@@ -10,7 +10,10 @@ function useCookie(name, options = defaultCookieOptions) {
10
10
  const Cookies = context
11
11
  ? isCookieGetterSetter(context)
12
12
  ? context
13
- : createReadonlyCookieReader(context)
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' ? (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 })] }));
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, useEffect } from 'react';
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
- useEffect(() => {
19
- if (selectedOption)
20
- setSelectedKey(selectedOption);
21
- }, [selectedOption]);
17
+ const isControlled = selectedOption !== undefined;
18
+ const currentSelectedKey = isControlled ? selectedOption : selectedKey;
22
19
  const handleChange = (key) => {
23
- setSelectedKey(key);
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: [selectedKey === 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));
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: [selectedKey === 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));
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: [selectedKey === 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));
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
 
@@ -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 { isNavigationLink, isNavigationSection, isNavigationLinkItem } from '../shared/api/bff/model/bff.model.js';
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: homeLink?.href || undefined, 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) }))] }));
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
- return `/${basePathname.replace(/^\//, '')}/${href.replace(/^\//, '')}`;
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonic-equipment/ui",
3
- "version": "260.0.9",
3
+ "version": "260.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {