@salesforce/retail-react-app 2.2.0 → 2.3.0-nightly-20231212080144
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/CHANGELOG.md +7 -0
- package/app/components/_app/index.jsx +4 -11
- package/app/components/field/index.jsx +14 -4
- package/app/components/header/index.jsx +27 -29
- package/app/components/header/index.test.js +16 -18
- package/app/components/list-menu/index.jsx +5 -1
- package/app/components/list-menu/index.test.js +1 -1
- package/app/components/pagination/index.jsx +8 -2
- package/app/components/with-registration/index.jsx +16 -5
- package/app/hooks/use-auth-modal.js +6 -1
- package/app/page-designer/layouts/carousel/index.jsx +12 -4
- package/app/pages/product-list/partials/radio-refinements.jsx +53 -45
- package/app/pages/product-list/partials/refinements.jsx +3 -2
- package/app/static/translations/compiled/en-GB.json +54 -0
- package/app/static/translations/compiled/en-US.json +54 -0
- package/app/static/translations/compiled/en-XA.json +126 -0
- package/package.json +6 -6
- package/translations/en-GB.json +27 -0
- package/translations/en-US.json +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## v2.3.0-dev (Nov 8, 2023)
|
|
2
|
+
### Accessibility improvements
|
|
3
|
+
|
|
4
|
+
- Change radio refinements (for example, filtering by Price) from radio inputs to styled buttons [#1605](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1605)
|
|
5
|
+
|
|
1
6
|
## v2.2.0 (Nov 8, 2023)
|
|
2
7
|
|
|
3
8
|
### Accessibility Improvements
|
|
@@ -14,12 +19,14 @@
|
|
|
14
19
|
- Improve keyboard accessibility of product scroller [#1559](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1559)
|
|
15
20
|
- Fix focus indicator for hero features links on homepage [#1561](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1561)
|
|
16
21
|
- Ensure color is not the sole means of communicating information [#1570](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1570)
|
|
22
|
+
- Improve keyboard accessibility of account menu and nav bar [#1572](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1572)
|
|
17
23
|
|
|
18
24
|
### Other Features
|
|
19
25
|
|
|
20
26
|
- Add [Active Data](https://help.salesforce.com/s/articleView?id=cc.b2c_active_data_attributes.htm&type=5) files, update pages (app index.jsx, product list and product details pages) to trigger events on product category and product detail views [#1555](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1555)
|
|
21
27
|
- Replace max-age with s-maxage to only cache shared caches [#1564](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1564)
|
|
22
28
|
- Implement gift option for basket [#1546](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1546)
|
|
29
|
+
- Added option to specify `isLoginPage` function to the `withRegistration` component. The default behavior is "all pages ending in `/login`". [#1572](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1572)
|
|
23
30
|
- Update `extract-default-messages` script to support multiple locales [#1574](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1574)
|
|
24
31
|
- Update engine compatibility to include npm 10 [#1597](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1597)
|
|
25
32
|
- Add support for localization in icon component [#1609](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1609)
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
useAccessToken,
|
|
19
19
|
useCategory,
|
|
20
20
|
useCommerceApi,
|
|
21
|
-
useCustomerType,
|
|
22
21
|
useCustomerBaskets,
|
|
23
22
|
useShopperBasketsMutation
|
|
24
23
|
} from '@salesforce/commerce-sdk-react'
|
|
@@ -123,7 +122,6 @@ const App = (props) => {
|
|
|
123
122
|
const history = useHistory()
|
|
124
123
|
const location = useLocation()
|
|
125
124
|
const authModal = useAuthModal()
|
|
126
|
-
const {isRegistered} = useCustomerType()
|
|
127
125
|
const {site, locale, buildUrl} = useMultiSite()
|
|
128
126
|
|
|
129
127
|
const [isOnline, setIsOnline] = useState(true)
|
|
@@ -257,18 +255,13 @@ const App = (props) => {
|
|
|
257
255
|
}
|
|
258
256
|
|
|
259
257
|
const onAccountClick = () => {
|
|
260
|
-
// Link to account page
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
history.push(path)
|
|
264
|
-
} else {
|
|
265
|
-
// if they already are at the login page, do not show login modal
|
|
266
|
-
if (new RegExp(`^/login$`).test(location.pathname)) return
|
|
267
|
-
authModal.onOpen()
|
|
268
|
-
}
|
|
258
|
+
// Link to account page if registered; Header component will show auth modal for guest users
|
|
259
|
+
const path = buildUrl('/account')
|
|
260
|
+
history.push(path)
|
|
269
261
|
}
|
|
270
262
|
|
|
271
263
|
const onWishlistClick = () => {
|
|
264
|
+
// Link to wishlist page if registered; Header component will show auth modal for guest users
|
|
272
265
|
const path = buildUrl('/account/wishlist')
|
|
273
266
|
history.push(path)
|
|
274
267
|
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
Checkbox
|
|
20
20
|
} from '@salesforce/retail-react-app/app/components/shared/ui'
|
|
21
21
|
import {VisibilityIcon, VisibilityOffIcon} from '@salesforce/retail-react-app/app/components/icons'
|
|
22
|
+
import {useIntl} from 'react-intl'
|
|
22
23
|
|
|
23
24
|
const Field = ({
|
|
24
25
|
name,
|
|
@@ -35,8 +36,18 @@ const Field = ({
|
|
|
35
36
|
helpText,
|
|
36
37
|
children
|
|
37
38
|
}) => {
|
|
39
|
+
const intl = useIntl()
|
|
38
40
|
const [hidePassword, setHidePassword] = useState(true)
|
|
39
41
|
const PasswordIcon = hidePassword ? VisibilityIcon : VisibilityOffIcon
|
|
42
|
+
const passwordIconLabel = hidePassword
|
|
43
|
+
? intl.formatMessage({
|
|
44
|
+
id: 'field.password.assistive_msg.show_password',
|
|
45
|
+
defaultMessage: 'Show password'
|
|
46
|
+
})
|
|
47
|
+
: intl.formatMessage({
|
|
48
|
+
id: 'field.password.assistive_msg.hide_password',
|
|
49
|
+
defaultMessage: 'Hide password'
|
|
50
|
+
})
|
|
40
51
|
const inputType =
|
|
41
52
|
type === 'password' && hidePassword ? 'password' : type === 'password' ? 'text' : type
|
|
42
53
|
return (
|
|
@@ -51,8 +62,7 @@ const Field = ({
|
|
|
51
62
|
|
|
52
63
|
return (
|
|
53
64
|
<FormControl id={name} isInvalid={error}>
|
|
54
|
-
{!['checkbox', 'radio'].includes(type) &&
|
|
55
|
-
type !== 'hidden' &&
|
|
65
|
+
{!['checkbox', 'radio', 'hidden'].includes(type) &&
|
|
56
66
|
(formLabel || <FormLabel>{label}</FormLabel>)}
|
|
57
67
|
|
|
58
68
|
<InputGroup>
|
|
@@ -83,7 +93,7 @@ const Field = ({
|
|
|
83
93
|
<InputRightElement>
|
|
84
94
|
<IconButton
|
|
85
95
|
variant="ghosted"
|
|
86
|
-
aria-label=
|
|
96
|
+
aria-label={passwordIconLabel}
|
|
87
97
|
icon={<PasswordIcon color="gray.500" boxSize={6} />}
|
|
88
98
|
onClick={() => setHidePassword(!hidePassword)}
|
|
89
99
|
/>
|
|
@@ -120,7 +130,7 @@ const Field = ({
|
|
|
120
130
|
{children}
|
|
121
131
|
</InputGroup>
|
|
122
132
|
|
|
123
|
-
{error &&
|
|
133
|
+
{error && type !== 'hidden' && (
|
|
124
134
|
<FormErrorMessage color="red.600">{error.message}</FormErrorMessage>
|
|
125
135
|
)}
|
|
126
136
|
|
|
@@ -49,8 +49,6 @@ import useNavigation from '@salesforce/retail-react-app/app/hooks/use-navigation
|
|
|
49
49
|
import LoadingSpinner from '@salesforce/retail-react-app/app/components/loading-spinner'
|
|
50
50
|
import {isHydrated, noop} from '@salesforce/retail-react-app/app/utils/utils'
|
|
51
51
|
|
|
52
|
-
const ENTER_KEY = 'Enter'
|
|
53
|
-
|
|
54
52
|
const IconButtonWithRegistration = withRegistration(IconButton)
|
|
55
53
|
/**
|
|
56
54
|
* The header is the main source for accessing
|
|
@@ -86,7 +84,13 @@ const Header = ({
|
|
|
86
84
|
const {isRegistered} = useCustomerType()
|
|
87
85
|
const logout = useAuthHelper(AuthHelpers.Logout)
|
|
88
86
|
const navigate = useNavigation()
|
|
89
|
-
const {
|
|
87
|
+
const {
|
|
88
|
+
getButtonProps: getAccountMenuButtonProps,
|
|
89
|
+
getDisclosureProps: getAccountMenuDisclosureProps,
|
|
90
|
+
isOpen: isAccountMenuOpen,
|
|
91
|
+
onClose: onAccountMenuClose,
|
|
92
|
+
onOpen: onAccountMenuOpen
|
|
93
|
+
} = useDisclosure()
|
|
90
94
|
const [isDesktop] = useMediaQuery('(min-width: 992px)')
|
|
91
95
|
|
|
92
96
|
const [showLoading, setShowLoading] = useState(false)
|
|
@@ -103,15 +107,10 @@ const Header = ({
|
|
|
103
107
|
setShowLoading(false)
|
|
104
108
|
}
|
|
105
109
|
|
|
106
|
-
const keyMap = {
|
|
107
|
-
Escape: () => onClose(),
|
|
108
|
-
Enter: () => onOpen()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
110
|
const handleIconsMouseLeave = () => {
|
|
112
111
|
// don't close the menu if users enter the popover content
|
|
113
112
|
setTimeout(() => {
|
|
114
|
-
if (!hasEnterPopoverContent.current)
|
|
113
|
+
if (!hasEnterPopoverContent.current) onAccountMenuClose()
|
|
115
114
|
}, 100)
|
|
116
115
|
}
|
|
117
116
|
|
|
@@ -154,39 +153,37 @@ const Header = ({
|
|
|
154
153
|
{...styles.search}
|
|
155
154
|
/>
|
|
156
155
|
</Box>
|
|
157
|
-
<
|
|
158
|
-
{...styles.accountIcon}
|
|
159
|
-
tabIndex={0}
|
|
160
|
-
onMouseOver={isDesktop ? onOpen : noop}
|
|
161
|
-
onKeyDown={(e) => {
|
|
162
|
-
e.key === ENTER_KEY ? onMyAccountClick() : noop
|
|
163
|
-
}}
|
|
164
|
-
onClick={onMyAccountClick}
|
|
156
|
+
<IconButtonWithRegistration
|
|
157
|
+
icon={<AccountIcon {...styles.accountIcon} />}
|
|
165
158
|
aria-label={intl.formatMessage({
|
|
166
159
|
id: 'header.button.assistive_msg.my_account',
|
|
167
160
|
defaultMessage: 'My account'
|
|
168
161
|
})}
|
|
162
|
+
variant="unstyled"
|
|
163
|
+
onClick={onMyAccountClick}
|
|
164
|
+
onMouseOver={isDesktop ? onAccountMenuOpen : noop}
|
|
169
165
|
/>
|
|
170
166
|
|
|
171
167
|
{isRegistered && isHydrated() && (
|
|
172
168
|
<Popover
|
|
173
169
|
isLazy
|
|
174
170
|
arrowSize={15}
|
|
175
|
-
isOpen={
|
|
171
|
+
isOpen={isAccountMenuOpen}
|
|
176
172
|
placement="bottom-end"
|
|
177
|
-
onClose={
|
|
178
|
-
onOpen={
|
|
173
|
+
onClose={onAccountMenuClose}
|
|
174
|
+
onOpen={onAccountMenuOpen}
|
|
179
175
|
>
|
|
180
176
|
<PopoverTrigger>
|
|
181
|
-
<
|
|
182
|
-
aria-label=
|
|
177
|
+
<IconButton
|
|
178
|
+
aria-label={intl.formatMessage({
|
|
179
|
+
id: 'header.button.assistive_msg.my_account_menu',
|
|
180
|
+
defaultMessage: 'Open account menu'
|
|
181
|
+
})}
|
|
182
|
+
icon={<ChevronDownIcon {...styles.arrowDown} />}
|
|
183
|
+
variant="unstyled"
|
|
184
|
+
{...getAccountMenuButtonProps()}
|
|
185
|
+
onMouseOver={onAccountMenuOpen}
|
|
183
186
|
onMouseLeave={handleIconsMouseLeave}
|
|
184
|
-
onKeyDown={(e) => {
|
|
185
|
-
keyMap[e.key]?.(e)
|
|
186
|
-
}}
|
|
187
|
-
{...styles.arrowDown}
|
|
188
|
-
onMouseOver={onOpen}
|
|
189
|
-
tabIndex={0}
|
|
190
187
|
/>
|
|
191
188
|
</PopoverTrigger>
|
|
192
189
|
|
|
@@ -194,11 +191,12 @@ const Header = ({
|
|
|
194
191
|
{...styles.popoverContent}
|
|
195
192
|
onMouseLeave={() => {
|
|
196
193
|
hasEnterPopoverContent.current = false
|
|
197
|
-
|
|
194
|
+
onAccountMenuClose()
|
|
198
195
|
}}
|
|
199
196
|
onMouseOver={() => {
|
|
200
197
|
hasEnterPopoverContent.current = true
|
|
201
198
|
}}
|
|
199
|
+
{...getAccountMenuDisclosureProps()}
|
|
202
200
|
>
|
|
203
201
|
<PopoverArrow />
|
|
204
202
|
<PopoverHeader>
|
|
@@ -62,11 +62,11 @@ test('renders Header', async () => {
|
|
|
62
62
|
renderWithProviders(<Header />)
|
|
63
63
|
|
|
64
64
|
await waitFor(() => {
|
|
65
|
-
const menu =
|
|
66
|
-
const logo =
|
|
67
|
-
const account =
|
|
68
|
-
const cart =
|
|
69
|
-
const wishlist =
|
|
65
|
+
const menu = screen.getByLabelText('Menu')
|
|
66
|
+
const logo = screen.getByLabelText('Logo')
|
|
67
|
+
const account = screen.getByLabelText('My account')
|
|
68
|
+
const cart = screen.getByLabelText('My cart, number of items: 0')
|
|
69
|
+
const wishlist = screen.getByLabelText('Wishlist')
|
|
70
70
|
const searchInput = document.querySelector('input[type="search"]')
|
|
71
71
|
expect(menu).toBeInTheDocument()
|
|
72
72
|
expect(logo).toBeInTheDocument()
|
|
@@ -91,10 +91,10 @@ test('renders Header with event handlers', async () => {
|
|
|
91
91
|
/>
|
|
92
92
|
)
|
|
93
93
|
await waitFor(() => {
|
|
94
|
-
const menu =
|
|
95
|
-
const logo =
|
|
96
|
-
const account =
|
|
97
|
-
const cart =
|
|
94
|
+
const menu = screen.getByLabelText('Menu')
|
|
95
|
+
const logo = screen.getByLabelText('Logo')
|
|
96
|
+
const account = screen.getByLabelText('My account')
|
|
97
|
+
const cart = screen.getByLabelText('My cart, number of items: 0')
|
|
98
98
|
expect(menu).toBeInTheDocument()
|
|
99
99
|
fireEvent.click(menu)
|
|
100
100
|
expect(onMenuClick).toHaveBeenCalledTimes(1)
|
|
@@ -124,7 +124,7 @@ test.each(testBaskets)(
|
|
|
124
124
|
renderWithProviders(<Header />)
|
|
125
125
|
|
|
126
126
|
await waitFor(() => {
|
|
127
|
-
const cart =
|
|
127
|
+
const cart = screen.getByLabelText('My cart, number of items: 0')
|
|
128
128
|
const badge = document.querySelector(
|
|
129
129
|
'button[aria-label="My cart, number of items: 0"] .chakra-badge'
|
|
130
130
|
)
|
|
@@ -141,9 +141,7 @@ test('renders cart badge when basket is loaded', async () => {
|
|
|
141
141
|
|
|
142
142
|
await waitFor(() => {
|
|
143
143
|
// Look for badge.
|
|
144
|
-
const badge =
|
|
145
|
-
'button[aria-label="My cart, number of items: 2"] .chakra-badge'
|
|
146
|
-
)
|
|
144
|
+
const badge = screen.getByLabelText('My cart, number of items: 2')
|
|
147
145
|
expect(badge).toBeInTheDocument()
|
|
148
146
|
})
|
|
149
147
|
})
|
|
@@ -156,10 +154,10 @@ test('route to account page when an authenticated users click on account icon',
|
|
|
156
154
|
|
|
157
155
|
await waitFor(() => {
|
|
158
156
|
// Look for account icon
|
|
159
|
-
const accountTrigger =
|
|
157
|
+
const accountTrigger = screen.getByLabelText('Open account menu')
|
|
160
158
|
expect(accountTrigger).toBeInTheDocument()
|
|
161
159
|
})
|
|
162
|
-
const accountIcon =
|
|
160
|
+
const accountIcon = screen.getByLabelText('My account')
|
|
163
161
|
fireEvent.click(accountIcon)
|
|
164
162
|
await waitFor(() => {
|
|
165
163
|
expect(history.push).toHaveBeenCalledWith(createPathWithDefaults('/account'))
|
|
@@ -181,7 +179,7 @@ test('route to wishlist page when an authenticated users click on wishlist icon'
|
|
|
181
179
|
|
|
182
180
|
await waitFor(() => {
|
|
183
181
|
// Look for account icon
|
|
184
|
-
const accountTrigger =
|
|
182
|
+
const accountTrigger = screen.getByLabelText('Open account menu')
|
|
185
183
|
expect(accountTrigger).toBeInTheDocument()
|
|
186
184
|
})
|
|
187
185
|
const wishlistIcon = screen.getByRole('button', {name: /wishlist/i})
|
|
@@ -207,10 +205,10 @@ test('shows dropdown menu when an authenticated users hover on the account icon'
|
|
|
207
205
|
|
|
208
206
|
await waitFor(() => {
|
|
209
207
|
// Look for account icon
|
|
210
|
-
const accountTrigger =
|
|
208
|
+
const accountTrigger = screen.getByLabelText('Open account menu')
|
|
211
209
|
expect(accountTrigger).toBeInTheDocument()
|
|
212
210
|
})
|
|
213
|
-
const accountIcon =
|
|
211
|
+
const accountIcon = screen.getByLabelText('My account')
|
|
214
212
|
fireEvent.click(accountIcon)
|
|
215
213
|
await waitFor(() => {
|
|
216
214
|
expect(history.push).toHaveBeenCalledWith(createPathWithDefaults('/account'))
|
|
@@ -225,6 +225,7 @@ const ListMenu = ({root, maxColumns = MAXIMUM_NUMBER_COLUMNS}) => {
|
|
|
225
225
|
const theme = useTheme()
|
|
226
226
|
const {baseStyle} = theme.components.ListMenu
|
|
227
227
|
const [ariaBusy, setAriaBusy] = useState(true)
|
|
228
|
+
const intl = useIntl()
|
|
228
229
|
|
|
229
230
|
useEffect(() => {
|
|
230
231
|
setAriaBusy(false)
|
|
@@ -233,7 +234,10 @@ const ListMenu = ({root, maxColumns = MAXIMUM_NUMBER_COLUMNS}) => {
|
|
|
233
234
|
return (
|
|
234
235
|
<nav
|
|
235
236
|
id="list-menu"
|
|
236
|
-
aria-label=
|
|
237
|
+
aria-label={intl.formatMessage({
|
|
238
|
+
id: 'list_menu.nav.assistive_msg',
|
|
239
|
+
defaultMessage: 'Main navigation'
|
|
240
|
+
})}
|
|
237
241
|
aria-live="polite"
|
|
238
242
|
aria-busy={ariaBusy}
|
|
239
243
|
aria-atomic="true"
|
|
@@ -19,7 +19,7 @@ describe('ListMenu', () => {
|
|
|
19
19
|
const categoryTrigger = screen.getByText(/Mens/i)
|
|
20
20
|
await user.hover(categoryTrigger)
|
|
21
21
|
expect(categoryTrigger).toBeInTheDocument()
|
|
22
|
-
expect(screen.getByRole('navigation', {name: '
|
|
22
|
+
expect(screen.getByRole('navigation', {name: 'Main navigation'})).toBeInTheDocument()
|
|
23
23
|
const suit = screen.getByText(/suits/i)
|
|
24
24
|
expect(suit).toBeInTheDocument()
|
|
25
25
|
})
|
|
@@ -53,7 +53,10 @@ const Pagination = (props) => {
|
|
|
53
53
|
// as intended, the workaround is to use the current url when its disabled.
|
|
54
54
|
href={prev || currentURL}
|
|
55
55
|
to={prev || currentURL}
|
|
56
|
-
aria-label=
|
|
56
|
+
aria-label={intl.formatMessage({
|
|
57
|
+
id: 'pagination.link.prev.assistive_msg',
|
|
58
|
+
defaultMessage: 'Previous Page'
|
|
59
|
+
})}
|
|
57
60
|
aria-disabled={!prev}
|
|
58
61
|
variant="link"
|
|
59
62
|
>
|
|
@@ -102,7 +105,10 @@ const Pagination = (props) => {
|
|
|
102
105
|
// as intended, the workaround is to use the current url when its disabled.
|
|
103
106
|
href={next || currentURL}
|
|
104
107
|
to={next || currentURL}
|
|
105
|
-
aria-label=
|
|
108
|
+
aria-label={intl.formatMessage({
|
|
109
|
+
id: 'pagination.link.next.assistive_msg',
|
|
110
|
+
defaultMessage: 'Next Page'
|
|
111
|
+
})}
|
|
106
112
|
aria-disabled={!next}
|
|
107
113
|
variant="link"
|
|
108
114
|
>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
5
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
@@ -13,20 +13,31 @@ import {useLocation} from 'react-router-dom'
|
|
|
13
13
|
import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
|
|
14
14
|
import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer'
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Higher-order component that modifies the given component's `onClick` to show the login form if
|
|
18
|
+
* the user is not logged in.
|
|
19
|
+
* @param {React.Component} component Component to wrap.
|
|
20
|
+
* @param {(location: Location, locale: string) => boolean} [options.isLoginPage] Function that
|
|
21
|
+
* determines whether the current page is the "login" page, to avoid showing a duplicate modal.
|
|
22
|
+
* Defaults to all paths ending with "/login".
|
|
23
|
+
* @returns {React.Component} wrapped component
|
|
24
|
+
*/
|
|
25
|
+
const withRegistration = (
|
|
26
|
+
Component,
|
|
27
|
+
{isLoginPage = (loc) => loc.pathname.endsWith('/login')} = {}
|
|
28
|
+
) => {
|
|
17
29
|
const WrappedComponent = ({onClick = noop, ...passThroughProps}) => {
|
|
18
30
|
const {data: customer} = useCurrentCustomer()
|
|
19
31
|
const authModal = useAuthModal()
|
|
32
|
+
const showToast = useToast()
|
|
20
33
|
const location = useLocation()
|
|
21
34
|
const {formatMessage, locale} = useIntl()
|
|
22
|
-
const isLoginPage = new RegExp(`^/${locale}/login$`).test(location.pathname)
|
|
23
|
-
const showToast = useToast()
|
|
24
35
|
|
|
25
36
|
const handleClick = (e) => {
|
|
26
37
|
e.preventDefault()
|
|
27
38
|
if (!customer.isRegistered) {
|
|
28
39
|
// Do not show auth modal if users is already on the login page
|
|
29
|
-
if (isLoginPage) {
|
|
40
|
+
if (isLoginPage(location, locale)) {
|
|
30
41
|
showToast({
|
|
31
42
|
title: formatMessage({
|
|
32
43
|
defaultMessage: 'Please sign in to continue!',
|
|
@@ -278,7 +278,12 @@ export const AuthModal = ({
|
|
|
278
278
|
>
|
|
279
279
|
<ModalOverlay />
|
|
280
280
|
<ModalContent>
|
|
281
|
-
<ModalCloseButton
|
|
281
|
+
<ModalCloseButton
|
|
282
|
+
aria-label={formatMessage({
|
|
283
|
+
id: 'auth_modal.button.close.assistive_msg',
|
|
284
|
+
defaultMessage: 'Close login form'
|
|
285
|
+
})}
|
|
286
|
+
/>
|
|
282
287
|
<ModalBody pb={8} bg="white" paddingBottom={14} marginTop={14}>
|
|
283
288
|
{!form.formState.isSubmitSuccessful && currentView === LOGIN_VIEW && (
|
|
284
289
|
<LoginForm
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import {Component, regionPropType} from '@salesforce/commerce-sdk-react/components'
|
|
19
19
|
import {ChevronLeftIcon, ChevronRightIcon} from '@salesforce/retail-react-app/app/components/icons'
|
|
20
20
|
import {useEffect} from 'react'
|
|
21
|
+
import {useIntl} from 'react-intl'
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Display child components in a carousel slider manner. Configurations include the number of
|
|
@@ -37,6 +38,7 @@ import {useEffect} from 'react'
|
|
|
37
38
|
* @returns {React.ReactElement} - Carousel component.
|
|
38
39
|
*/
|
|
39
40
|
export const Carousel = (props = {}) => {
|
|
41
|
+
const intl = useIntl()
|
|
40
42
|
const scrollRef = useRef()
|
|
41
43
|
const breakpoint = useBreakpoint()
|
|
42
44
|
const [hasOverflow, setHasOverflow] = useState(false)
|
|
@@ -172,11 +174,14 @@ export const Carousel = (props = {}) => {
|
|
|
172
174
|
{/* boxShadow requires !important --> https://github.com/chakra-ui/chakra-ui/issues/3553 */}
|
|
173
175
|
<IconButton
|
|
174
176
|
data-testid="carousel-nav-left"
|
|
175
|
-
aria-label=
|
|
177
|
+
aria-label={intl.formatMessage({
|
|
178
|
+
id: 'carousel.button.scroll_left.assistive_msg',
|
|
179
|
+
defaultMessage: 'Scroll carousel left'
|
|
180
|
+
})}
|
|
176
181
|
icon={<ChevronLeftIcon color="black" />}
|
|
177
182
|
borderRadius="full"
|
|
178
183
|
colorScheme="whiteAlpha"
|
|
179
|
-
boxShadow=
|
|
184
|
+
boxShadow="0 3px 10px rgb(0 0 0 / 20%) !important"
|
|
180
185
|
onClick={() => scroll(-1)}
|
|
181
186
|
/>
|
|
182
187
|
</Box>
|
|
@@ -191,11 +196,14 @@ export const Carousel = (props = {}) => {
|
|
|
191
196
|
{/* boxShadow requires !important --> https://github.com/chakra-ui/chakra-ui/issues/3553 */}
|
|
192
197
|
<IconButton
|
|
193
198
|
data-testid="carousel-nav-right"
|
|
194
|
-
aria-label=
|
|
199
|
+
aria-label={intl.formatMessage({
|
|
200
|
+
id: 'carousel.button.scroll_right.assistive_msg',
|
|
201
|
+
defaultMessage: 'Scroll carousel right'
|
|
202
|
+
})}
|
|
195
203
|
icon={<ChevronRightIcon color="black" />}
|
|
196
204
|
borderRadius="full"
|
|
197
205
|
colorScheme="whiteAlpha"
|
|
198
|
-
boxShadow=
|
|
206
|
+
boxShadow="0 3px 10px rgb(0 0 0 / 20%) !important"
|
|
199
207
|
onClick={() => scroll(1)}
|
|
200
208
|
/>
|
|
201
209
|
</Box>
|
|
@@ -1,66 +1,74 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
5
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React from 'react'
|
|
9
|
-
import {
|
|
10
|
-
Box,
|
|
11
|
-
Text,
|
|
12
|
-
Radio,
|
|
13
|
-
RadioGroup,
|
|
14
|
-
Stack
|
|
15
|
-
} from '@salesforce/retail-react-app/app/components/shared/ui'
|
|
8
|
+
import React, {useRef} from 'react'
|
|
9
|
+
import {Box, Text, Radio, Stack} from '@salesforce/retail-react-app/app/components/shared/ui'
|
|
16
10
|
import PropTypes from 'prop-types'
|
|
17
11
|
|
|
18
|
-
const
|
|
12
|
+
const RadioRefinement = ({filter, value, toggleFilter, selectedFilters}) => {
|
|
13
|
+
const buttonRef = useRef()
|
|
14
|
+
// Because choosing a refinement is equivalent to a form submission, the best semantic choice
|
|
15
|
+
// for the refinement is a button or a link, rather than a radio input. The radio element here
|
|
16
|
+
// is purely for visual purposes, and should probably be replaced with a simple icon.
|
|
19
17
|
return (
|
|
20
18
|
<Box>
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
<Radio
|
|
20
|
+
display="inline-flex"
|
|
21
|
+
height={{base: '44px', lg: '24px'}}
|
|
22
|
+
isChecked={selectedFilters.includes(value.value)}
|
|
23
|
+
// Ideally, this "icon" would be part of the button, but doing so with a radio input
|
|
24
|
+
// triggers `onClick` twice. The radio must be separate, and therefore we must add
|
|
25
|
+
// these workarounds to prevent it from receiving focus.
|
|
26
|
+
inputProps={{'aria-hidden': true, tabIndex: -1}}
|
|
27
|
+
onClick={() => buttonRef.current?.click()}
|
|
28
|
+
/>
|
|
29
|
+
<Text
|
|
30
|
+
ref={buttonRef}
|
|
31
|
+
ml={2}
|
|
32
|
+
as="button"
|
|
33
|
+
fontSize="sm"
|
|
34
|
+
onClick={() => toggleFilter(value, filter.attributeId, false, false)}
|
|
25
35
|
>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
.filter((refinementValue) => refinementValue.hitCount > 0)
|
|
29
|
-
.map((value) => {
|
|
30
|
-
return (
|
|
31
|
-
<Box key={value.value}>
|
|
32
|
-
<Radio
|
|
33
|
-
display="flex"
|
|
34
|
-
alignItems="center"
|
|
35
|
-
height={{base: '44px', lg: '24px'}}
|
|
36
|
-
value={value.value}
|
|
37
|
-
onChange={() =>
|
|
38
|
-
toggleFilter(
|
|
39
|
-
value,
|
|
40
|
-
filter.attributeId,
|
|
41
|
-
selectedFilters.includes(value.value),
|
|
42
|
-
false
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
fontSize="sm"
|
|
46
|
-
>
|
|
47
|
-
<Text marginLeft={-1} fontSize="sm">
|
|
48
|
-
{value.label}
|
|
49
|
-
</Text>
|
|
50
|
-
</Radio>
|
|
51
|
-
</Box>
|
|
52
|
-
)
|
|
53
|
-
})}
|
|
54
|
-
</Stack>
|
|
55
|
-
</RadioGroup>
|
|
36
|
+
{value.label}
|
|
37
|
+
</Text>
|
|
56
38
|
</Box>
|
|
57
39
|
)
|
|
58
40
|
}
|
|
59
41
|
|
|
42
|
+
RadioRefinement.propTypes = {
|
|
43
|
+
filter: PropTypes.object,
|
|
44
|
+
value: PropTypes.object,
|
|
45
|
+
toggleFilter: PropTypes.func,
|
|
46
|
+
selectedFilters: PropTypes.arrayOf(PropTypes.object)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const RadioRefinements = ({filter, toggleFilter, selectedFilters}) => {
|
|
50
|
+
return (
|
|
51
|
+
<Stack spacing={1}>
|
|
52
|
+
{filter.values.map(
|
|
53
|
+
(value) =>
|
|
54
|
+
value.hitCount > 0 && (
|
|
55
|
+
<RadioRefinement
|
|
56
|
+
key={value.value}
|
|
57
|
+
value={value}
|
|
58
|
+
filter={filter}
|
|
59
|
+
toggleFilter={toggleFilter}
|
|
60
|
+
selectedFilters={selectedFilters}
|
|
61
|
+
/>
|
|
62
|
+
)
|
|
63
|
+
)}
|
|
64
|
+
</Stack>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
RadioRefinements.propTypes = {
|
|
61
69
|
filter: PropTypes.object,
|
|
62
70
|
toggleFilter: PropTypes.func,
|
|
63
|
-
selectedFilters: PropTypes.
|
|
71
|
+
selectedFilters: PropTypes.arrayOf(PropTypes.object)
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
export default RadioRefinements
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
5
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
@@ -25,7 +25,8 @@ import LinkRefinements from '@salesforce/retail-react-app/app/pages/product-list
|
|
|
25
25
|
import {isServer} from '@salesforce/retail-react-app/app/utils/utils'
|
|
26
26
|
import {FILTER_ACCORDION_SATE} from '@salesforce/retail-react-app/app/constants'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
/** Map of refinement attribute IDs to the components used to display values as filter options. */
|
|
29
|
+
export const componentMap = {
|
|
29
30
|
cgid: LinkRefinements,
|
|
30
31
|
c_refinementColor: ColorRefinements,
|
|
31
32
|
c_size: SizeRefinements,
|
|
@@ -355,6 +355,12 @@
|
|
|
355
355
|
"value": "You Might Also Like"
|
|
356
356
|
}
|
|
357
357
|
],
|
|
358
|
+
"auth_modal.button.close.assistive_msg": [
|
|
359
|
+
{
|
|
360
|
+
"type": 0,
|
|
361
|
+
"value": "Close login form"
|
|
362
|
+
}
|
|
363
|
+
],
|
|
358
364
|
"auth_modal.description.now_signed_in": [
|
|
359
365
|
{
|
|
360
366
|
"type": 0,
|
|
@@ -413,6 +419,18 @@
|
|
|
413
419
|
"value": "Password Reset"
|
|
414
420
|
}
|
|
415
421
|
],
|
|
422
|
+
"carousel.button.scroll_left.assistive_msg": [
|
|
423
|
+
{
|
|
424
|
+
"type": 0,
|
|
425
|
+
"value": "Scroll carousel left"
|
|
426
|
+
}
|
|
427
|
+
],
|
|
428
|
+
"carousel.button.scroll_right.assistive_msg": [
|
|
429
|
+
{
|
|
430
|
+
"type": 0,
|
|
431
|
+
"value": "Scroll carousel right"
|
|
432
|
+
}
|
|
433
|
+
],
|
|
416
434
|
"cart.info.removed_from_cart": [
|
|
417
435
|
{
|
|
418
436
|
"type": 0,
|
|
@@ -1163,6 +1181,18 @@
|
|
|
1163
1181
|
"value": "Top Sellers"
|
|
1164
1182
|
}
|
|
1165
1183
|
],
|
|
1184
|
+
"field.password.assistive_msg.hide_password": [
|
|
1185
|
+
{
|
|
1186
|
+
"type": 0,
|
|
1187
|
+
"value": "Hide password"
|
|
1188
|
+
}
|
|
1189
|
+
],
|
|
1190
|
+
"field.password.assistive_msg.show_password": [
|
|
1191
|
+
{
|
|
1192
|
+
"type": 0,
|
|
1193
|
+
"value": "Show password"
|
|
1194
|
+
}
|
|
1195
|
+
],
|
|
1166
1196
|
"footer.column.account": [
|
|
1167
1197
|
{
|
|
1168
1198
|
"type": 0,
|
|
@@ -1375,6 +1405,12 @@
|
|
|
1375
1405
|
"value": "My account"
|
|
1376
1406
|
}
|
|
1377
1407
|
],
|
|
1408
|
+
"header.button.assistive_msg.my_account_menu": [
|
|
1409
|
+
{
|
|
1410
|
+
"type": 0,
|
|
1411
|
+
"value": "Open account menu"
|
|
1412
|
+
}
|
|
1413
|
+
],
|
|
1378
1414
|
"header.button.assistive_msg.my_cart_with_num_items": [
|
|
1379
1415
|
{
|
|
1380
1416
|
"type": 0,
|
|
@@ -1613,6 +1649,12 @@
|
|
|
1613
1649
|
"value": "Please select all your options above"
|
|
1614
1650
|
}
|
|
1615
1651
|
],
|
|
1652
|
+
"list_menu.nav.assistive_msg": [
|
|
1653
|
+
{
|
|
1654
|
+
"type": 0,
|
|
1655
|
+
"value": "Main navigation"
|
|
1656
|
+
}
|
|
1657
|
+
],
|
|
1616
1658
|
"locale_text.message.ar-SA": [
|
|
1617
1659
|
{
|
|
1618
1660
|
"type": 0,
|
|
@@ -2123,12 +2165,24 @@
|
|
|
2123
2165
|
"value": "Next"
|
|
2124
2166
|
}
|
|
2125
2167
|
],
|
|
2168
|
+
"pagination.link.next.assistive_msg": [
|
|
2169
|
+
{
|
|
2170
|
+
"type": 0,
|
|
2171
|
+
"value": "Next Page"
|
|
2172
|
+
}
|
|
2173
|
+
],
|
|
2126
2174
|
"pagination.link.prev": [
|
|
2127
2175
|
{
|
|
2128
2176
|
"type": 0,
|
|
2129
2177
|
"value": "Prev"
|
|
2130
2178
|
}
|
|
2131
2179
|
],
|
|
2180
|
+
"pagination.link.prev.assistive_msg": [
|
|
2181
|
+
{
|
|
2182
|
+
"type": 0,
|
|
2183
|
+
"value": "Previous Page"
|
|
2184
|
+
}
|
|
2185
|
+
],
|
|
2132
2186
|
"password_card.info.password_updated": [
|
|
2133
2187
|
{
|
|
2134
2188
|
"type": 0,
|
|
@@ -355,6 +355,12 @@
|
|
|
355
355
|
"value": "You Might Also Like"
|
|
356
356
|
}
|
|
357
357
|
],
|
|
358
|
+
"auth_modal.button.close.assistive_msg": [
|
|
359
|
+
{
|
|
360
|
+
"type": 0,
|
|
361
|
+
"value": "Close login form"
|
|
362
|
+
}
|
|
363
|
+
],
|
|
358
364
|
"auth_modal.description.now_signed_in": [
|
|
359
365
|
{
|
|
360
366
|
"type": 0,
|
|
@@ -413,6 +419,18 @@
|
|
|
413
419
|
"value": "Password Reset"
|
|
414
420
|
}
|
|
415
421
|
],
|
|
422
|
+
"carousel.button.scroll_left.assistive_msg": [
|
|
423
|
+
{
|
|
424
|
+
"type": 0,
|
|
425
|
+
"value": "Scroll carousel left"
|
|
426
|
+
}
|
|
427
|
+
],
|
|
428
|
+
"carousel.button.scroll_right.assistive_msg": [
|
|
429
|
+
{
|
|
430
|
+
"type": 0,
|
|
431
|
+
"value": "Scroll carousel right"
|
|
432
|
+
}
|
|
433
|
+
],
|
|
416
434
|
"cart.info.removed_from_cart": [
|
|
417
435
|
{
|
|
418
436
|
"type": 0,
|
|
@@ -1163,6 +1181,18 @@
|
|
|
1163
1181
|
"value": "Top Sellers"
|
|
1164
1182
|
}
|
|
1165
1183
|
],
|
|
1184
|
+
"field.password.assistive_msg.hide_password": [
|
|
1185
|
+
{
|
|
1186
|
+
"type": 0,
|
|
1187
|
+
"value": "Hide password"
|
|
1188
|
+
}
|
|
1189
|
+
],
|
|
1190
|
+
"field.password.assistive_msg.show_password": [
|
|
1191
|
+
{
|
|
1192
|
+
"type": 0,
|
|
1193
|
+
"value": "Show password"
|
|
1194
|
+
}
|
|
1195
|
+
],
|
|
1166
1196
|
"footer.column.account": [
|
|
1167
1197
|
{
|
|
1168
1198
|
"type": 0,
|
|
@@ -1375,6 +1405,12 @@
|
|
|
1375
1405
|
"value": "My account"
|
|
1376
1406
|
}
|
|
1377
1407
|
],
|
|
1408
|
+
"header.button.assistive_msg.my_account_menu": [
|
|
1409
|
+
{
|
|
1410
|
+
"type": 0,
|
|
1411
|
+
"value": "Open account menu"
|
|
1412
|
+
}
|
|
1413
|
+
],
|
|
1378
1414
|
"header.button.assistive_msg.my_cart_with_num_items": [
|
|
1379
1415
|
{
|
|
1380
1416
|
"type": 0,
|
|
@@ -1613,6 +1649,12 @@
|
|
|
1613
1649
|
"value": "Please select all your options above"
|
|
1614
1650
|
}
|
|
1615
1651
|
],
|
|
1652
|
+
"list_menu.nav.assistive_msg": [
|
|
1653
|
+
{
|
|
1654
|
+
"type": 0,
|
|
1655
|
+
"value": "Main navigation"
|
|
1656
|
+
}
|
|
1657
|
+
],
|
|
1616
1658
|
"locale_text.message.ar-SA": [
|
|
1617
1659
|
{
|
|
1618
1660
|
"type": 0,
|
|
@@ -2123,12 +2165,24 @@
|
|
|
2123
2165
|
"value": "Next"
|
|
2124
2166
|
}
|
|
2125
2167
|
],
|
|
2168
|
+
"pagination.link.next.assistive_msg": [
|
|
2169
|
+
{
|
|
2170
|
+
"type": 0,
|
|
2171
|
+
"value": "Next Page"
|
|
2172
|
+
}
|
|
2173
|
+
],
|
|
2126
2174
|
"pagination.link.prev": [
|
|
2127
2175
|
{
|
|
2128
2176
|
"type": 0,
|
|
2129
2177
|
"value": "Prev"
|
|
2130
2178
|
}
|
|
2131
2179
|
],
|
|
2180
|
+
"pagination.link.prev.assistive_msg": [
|
|
2181
|
+
{
|
|
2182
|
+
"type": 0,
|
|
2183
|
+
"value": "Previous Page"
|
|
2184
|
+
}
|
|
2185
|
+
],
|
|
2132
2186
|
"password_card.info.password_updated": [
|
|
2133
2187
|
{
|
|
2134
2188
|
"type": 0,
|
|
@@ -739,6 +739,20 @@
|
|
|
739
739
|
"value": "]"
|
|
740
740
|
}
|
|
741
741
|
],
|
|
742
|
+
"auth_modal.button.close.assistive_msg": [
|
|
743
|
+
{
|
|
744
|
+
"type": 0,
|
|
745
|
+
"value": "["
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
"type": 0,
|
|
749
|
+
"value": "Ƈŀǿǿşḗḗ ŀǿǿɠīƞ ƒǿǿřḿ"
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
"type": 0,
|
|
753
|
+
"value": "]"
|
|
754
|
+
}
|
|
755
|
+
],
|
|
742
756
|
"auth_modal.description.now_signed_in": [
|
|
743
757
|
{
|
|
744
758
|
"type": 0,
|
|
@@ -845,6 +859,34 @@
|
|
|
845
859
|
"value": "]"
|
|
846
860
|
}
|
|
847
861
|
],
|
|
862
|
+
"carousel.button.scroll_left.assistive_msg": [
|
|
863
|
+
{
|
|
864
|
+
"type": 0,
|
|
865
|
+
"value": "["
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
"type": 0,
|
|
869
|
+
"value": "Şƈřǿǿŀŀ ƈȧȧřǿǿŭŭşḗḗŀ ŀḗḗƒŧ"
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
"type": 0,
|
|
873
|
+
"value": "]"
|
|
874
|
+
}
|
|
875
|
+
],
|
|
876
|
+
"carousel.button.scroll_right.assistive_msg": [
|
|
877
|
+
{
|
|
878
|
+
"type": 0,
|
|
879
|
+
"value": "["
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
"type": 0,
|
|
883
|
+
"value": "Şƈřǿǿŀŀ ƈȧȧřǿǿŭŭşḗḗŀ řīɠħŧ"
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
"type": 0,
|
|
887
|
+
"value": "]"
|
|
888
|
+
}
|
|
889
|
+
],
|
|
848
890
|
"cart.info.removed_from_cart": [
|
|
849
891
|
{
|
|
850
892
|
"type": 0,
|
|
@@ -2411,6 +2453,34 @@
|
|
|
2411
2453
|
"value": "]"
|
|
2412
2454
|
}
|
|
2413
2455
|
],
|
|
2456
|
+
"field.password.assistive_msg.hide_password": [
|
|
2457
|
+
{
|
|
2458
|
+
"type": 0,
|
|
2459
|
+
"value": "["
|
|
2460
|
+
},
|
|
2461
|
+
{
|
|
2462
|
+
"type": 0,
|
|
2463
|
+
"value": "Ħīḓḗḗ ƥȧȧşşẇǿǿřḓ"
|
|
2464
|
+
},
|
|
2465
|
+
{
|
|
2466
|
+
"type": 0,
|
|
2467
|
+
"value": "]"
|
|
2468
|
+
}
|
|
2469
|
+
],
|
|
2470
|
+
"field.password.assistive_msg.show_password": [
|
|
2471
|
+
{
|
|
2472
|
+
"type": 0,
|
|
2473
|
+
"value": "["
|
|
2474
|
+
},
|
|
2475
|
+
{
|
|
2476
|
+
"type": 0,
|
|
2477
|
+
"value": "Şħǿǿẇ ƥȧȧşşẇǿǿřḓ"
|
|
2478
|
+
},
|
|
2479
|
+
{
|
|
2480
|
+
"type": 0,
|
|
2481
|
+
"value": "]"
|
|
2482
|
+
}
|
|
2483
|
+
],
|
|
2414
2484
|
"footer.column.account": [
|
|
2415
2485
|
{
|
|
2416
2486
|
"type": 0,
|
|
@@ -2863,6 +2933,20 @@
|
|
|
2863
2933
|
"value": "]"
|
|
2864
2934
|
}
|
|
2865
2935
|
],
|
|
2936
|
+
"header.button.assistive_msg.my_account_menu": [
|
|
2937
|
+
{
|
|
2938
|
+
"type": 0,
|
|
2939
|
+
"value": "["
|
|
2940
|
+
},
|
|
2941
|
+
{
|
|
2942
|
+
"type": 0,
|
|
2943
|
+
"value": "Ǿƥḗḗƞ ȧȧƈƈǿǿŭŭƞŧ ḿḗḗƞŭŭ"
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
"type": 0,
|
|
2947
|
+
"value": "]"
|
|
2948
|
+
}
|
|
2949
|
+
],
|
|
2866
2950
|
"header.button.assistive_msg.my_cart_with_num_items": [
|
|
2867
2951
|
{
|
|
2868
2952
|
"type": 0,
|
|
@@ -3397,6 +3481,20 @@
|
|
|
3397
3481
|
"value": "]"
|
|
3398
3482
|
}
|
|
3399
3483
|
],
|
|
3484
|
+
"list_menu.nav.assistive_msg": [
|
|
3485
|
+
{
|
|
3486
|
+
"type": 0,
|
|
3487
|
+
"value": "["
|
|
3488
|
+
},
|
|
3489
|
+
{
|
|
3490
|
+
"type": 0,
|
|
3491
|
+
"value": "Ḿȧȧīƞ ƞȧȧṽīɠȧȧŧīǿǿƞ"
|
|
3492
|
+
},
|
|
3493
|
+
{
|
|
3494
|
+
"type": 0,
|
|
3495
|
+
"value": "]"
|
|
3496
|
+
}
|
|
3497
|
+
],
|
|
3400
3498
|
"locale_text.message.ar-SA": [
|
|
3401
3499
|
{
|
|
3402
3500
|
"type": 0,
|
|
@@ -4531,6 +4629,20 @@
|
|
|
4531
4629
|
"value": "]"
|
|
4532
4630
|
}
|
|
4533
4631
|
],
|
|
4632
|
+
"pagination.link.next.assistive_msg": [
|
|
4633
|
+
{
|
|
4634
|
+
"type": 0,
|
|
4635
|
+
"value": "["
|
|
4636
|
+
},
|
|
4637
|
+
{
|
|
4638
|
+
"type": 0,
|
|
4639
|
+
"value": "Ƞḗḗẋŧ Ƥȧȧɠḗḗ"
|
|
4640
|
+
},
|
|
4641
|
+
{
|
|
4642
|
+
"type": 0,
|
|
4643
|
+
"value": "]"
|
|
4644
|
+
}
|
|
4645
|
+
],
|
|
4534
4646
|
"pagination.link.prev": [
|
|
4535
4647
|
{
|
|
4536
4648
|
"type": 0,
|
|
@@ -4545,6 +4657,20 @@
|
|
|
4545
4657
|
"value": "]"
|
|
4546
4658
|
}
|
|
4547
4659
|
],
|
|
4660
|
+
"pagination.link.prev.assistive_msg": [
|
|
4661
|
+
{
|
|
4662
|
+
"type": 0,
|
|
4663
|
+
"value": "["
|
|
4664
|
+
},
|
|
4665
|
+
{
|
|
4666
|
+
"type": 0,
|
|
4667
|
+
"value": "Ƥřḗḗṽīǿǿŭŭş Ƥȧȧɠḗḗ"
|
|
4668
|
+
},
|
|
4669
|
+
{
|
|
4670
|
+
"type": 0,
|
|
4671
|
+
"value": "]"
|
|
4672
|
+
}
|
|
4673
|
+
],
|
|
4548
4674
|
"password_card.info.password_updated": [
|
|
4549
4675
|
{
|
|
4550
4676
|
"type": 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/retail-react-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0-nightly-20231212080144",
|
|
4
4
|
"license": "See license in LICENSE",
|
|
5
5
|
"author": "cc-pwa-kit@salesforce.com",
|
|
6
6
|
"ccExtensibility": {
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"@lhci/cli": "^0.11.0",
|
|
46
46
|
"@loadable/component": "^5.15.3",
|
|
47
47
|
"@peculiar/webcrypto": "^1.4.2",
|
|
48
|
-
"@salesforce/commerce-sdk-react": "1.
|
|
49
|
-
"@salesforce/pwa-kit-dev": "3.
|
|
50
|
-
"@salesforce/pwa-kit-react-sdk": "3.
|
|
51
|
-
"@salesforce/pwa-kit-runtime": "3.
|
|
48
|
+
"@salesforce/commerce-sdk-react": "1.3.0-nightly-20231212080144",
|
|
49
|
+
"@salesforce/pwa-kit-dev": "3.4.0-nightly-20231212080144",
|
|
50
|
+
"@salesforce/pwa-kit-react-sdk": "3.4.0-nightly-20231212080144",
|
|
51
|
+
"@salesforce/pwa-kit-runtime": "3.4.0-nightly-20231212080144",
|
|
52
52
|
"@tanstack/react-query": "^4.28.0",
|
|
53
53
|
"@tanstack/react-query-devtools": "^4.29.1",
|
|
54
54
|
"@testing-library/dom": "^9.0.1",
|
|
@@ -100,5 +100,5 @@
|
|
|
100
100
|
"maxSize": "320 kB"
|
|
101
101
|
}
|
|
102
102
|
],
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "dbf0d4f2e45234cfc395f412a1fa94c364a877c2"
|
|
104
104
|
}
|
package/translations/en-GB.json
CHANGED
|
@@ -144,6 +144,9 @@
|
|
|
144
144
|
"add_to_cart_modal.recommended_products.title.might_also_like": {
|
|
145
145
|
"defaultMessage": "You Might Also Like"
|
|
146
146
|
},
|
|
147
|
+
"auth_modal.button.close.assistive_msg": {
|
|
148
|
+
"defaultMessage": "Close login form"
|
|
149
|
+
},
|
|
147
150
|
"auth_modal.description.now_signed_in": {
|
|
148
151
|
"defaultMessage": "You're now signed in."
|
|
149
152
|
},
|
|
@@ -162,6 +165,12 @@
|
|
|
162
165
|
"auth_modal.password_reset_success.title.password_reset": {
|
|
163
166
|
"defaultMessage": "Password Reset"
|
|
164
167
|
},
|
|
168
|
+
"carousel.button.scroll_left.assistive_msg": {
|
|
169
|
+
"defaultMessage": "Scroll carousel left"
|
|
170
|
+
},
|
|
171
|
+
"carousel.button.scroll_right.assistive_msg": {
|
|
172
|
+
"defaultMessage": "Scroll carousel right"
|
|
173
|
+
},
|
|
165
174
|
"cart.info.removed_from_cart": {
|
|
166
175
|
"defaultMessage": "Item removed from cart"
|
|
167
176
|
},
|
|
@@ -471,6 +480,12 @@
|
|
|
471
480
|
"empty_search_results.recommended_products.title.top_sellers": {
|
|
472
481
|
"defaultMessage": "Top Sellers"
|
|
473
482
|
},
|
|
483
|
+
"field.password.assistive_msg.hide_password": {
|
|
484
|
+
"defaultMessage": "Hide password"
|
|
485
|
+
},
|
|
486
|
+
"field.password.assistive_msg.show_password": {
|
|
487
|
+
"defaultMessage": "Show password"
|
|
488
|
+
},
|
|
474
489
|
"footer.column.account": {
|
|
475
490
|
"defaultMessage": "Account"
|
|
476
491
|
},
|
|
@@ -561,6 +576,9 @@
|
|
|
561
576
|
"header.button.assistive_msg.my_account": {
|
|
562
577
|
"defaultMessage": "My account"
|
|
563
578
|
},
|
|
579
|
+
"header.button.assistive_msg.my_account_menu": {
|
|
580
|
+
"defaultMessage": "Open account menu"
|
|
581
|
+
},
|
|
564
582
|
"header.button.assistive_msg.my_cart_with_num_items": {
|
|
565
583
|
"defaultMessage": "My cart, number of items: {numItems}"
|
|
566
584
|
},
|
|
@@ -674,6 +692,9 @@
|
|
|
674
692
|
"lCPCxk": {
|
|
675
693
|
"defaultMessage": "Please select all your options above"
|
|
676
694
|
},
|
|
695
|
+
"list_menu.nav.assistive_msg": {
|
|
696
|
+
"defaultMessage": "Main navigation"
|
|
697
|
+
},
|
|
677
698
|
"locale_text.message.ar-SA": {
|
|
678
699
|
"defaultMessage": "Arabic (Saudi Arabia)"
|
|
679
700
|
},
|
|
@@ -909,9 +930,15 @@
|
|
|
909
930
|
"pagination.link.next": {
|
|
910
931
|
"defaultMessage": "Next"
|
|
911
932
|
},
|
|
933
|
+
"pagination.link.next.assistive_msg": {
|
|
934
|
+
"defaultMessage": "Next Page"
|
|
935
|
+
},
|
|
912
936
|
"pagination.link.prev": {
|
|
913
937
|
"defaultMessage": "Prev"
|
|
914
938
|
},
|
|
939
|
+
"pagination.link.prev.assistive_msg": {
|
|
940
|
+
"defaultMessage": "Previous Page"
|
|
941
|
+
},
|
|
915
942
|
"password_card.info.password_updated": {
|
|
916
943
|
"defaultMessage": "Password updated"
|
|
917
944
|
},
|
package/translations/en-US.json
CHANGED
|
@@ -144,6 +144,9 @@
|
|
|
144
144
|
"add_to_cart_modal.recommended_products.title.might_also_like": {
|
|
145
145
|
"defaultMessage": "You Might Also Like"
|
|
146
146
|
},
|
|
147
|
+
"auth_modal.button.close.assistive_msg": {
|
|
148
|
+
"defaultMessage": "Close login form"
|
|
149
|
+
},
|
|
147
150
|
"auth_modal.description.now_signed_in": {
|
|
148
151
|
"defaultMessage": "You're now signed in."
|
|
149
152
|
},
|
|
@@ -162,6 +165,12 @@
|
|
|
162
165
|
"auth_modal.password_reset_success.title.password_reset": {
|
|
163
166
|
"defaultMessage": "Password Reset"
|
|
164
167
|
},
|
|
168
|
+
"carousel.button.scroll_left.assistive_msg": {
|
|
169
|
+
"defaultMessage": "Scroll carousel left"
|
|
170
|
+
},
|
|
171
|
+
"carousel.button.scroll_right.assistive_msg": {
|
|
172
|
+
"defaultMessage": "Scroll carousel right"
|
|
173
|
+
},
|
|
165
174
|
"cart.info.removed_from_cart": {
|
|
166
175
|
"defaultMessage": "Item removed from cart"
|
|
167
176
|
},
|
|
@@ -471,6 +480,12 @@
|
|
|
471
480
|
"empty_search_results.recommended_products.title.top_sellers": {
|
|
472
481
|
"defaultMessage": "Top Sellers"
|
|
473
482
|
},
|
|
483
|
+
"field.password.assistive_msg.hide_password": {
|
|
484
|
+
"defaultMessage": "Hide password"
|
|
485
|
+
},
|
|
486
|
+
"field.password.assistive_msg.show_password": {
|
|
487
|
+
"defaultMessage": "Show password"
|
|
488
|
+
},
|
|
474
489
|
"footer.column.account": {
|
|
475
490
|
"defaultMessage": "Account"
|
|
476
491
|
},
|
|
@@ -561,6 +576,9 @@
|
|
|
561
576
|
"header.button.assistive_msg.my_account": {
|
|
562
577
|
"defaultMessage": "My account"
|
|
563
578
|
},
|
|
579
|
+
"header.button.assistive_msg.my_account_menu": {
|
|
580
|
+
"defaultMessage": "Open account menu"
|
|
581
|
+
},
|
|
564
582
|
"header.button.assistive_msg.my_cart_with_num_items": {
|
|
565
583
|
"defaultMessage": "My cart, number of items: {numItems}"
|
|
566
584
|
},
|
|
@@ -674,6 +692,9 @@
|
|
|
674
692
|
"lCPCxk": {
|
|
675
693
|
"defaultMessage": "Please select all your options above"
|
|
676
694
|
},
|
|
695
|
+
"list_menu.nav.assistive_msg": {
|
|
696
|
+
"defaultMessage": "Main navigation"
|
|
697
|
+
},
|
|
677
698
|
"locale_text.message.ar-SA": {
|
|
678
699
|
"defaultMessage": "Arabic (Saudi Arabia)"
|
|
679
700
|
},
|
|
@@ -909,9 +930,15 @@
|
|
|
909
930
|
"pagination.link.next": {
|
|
910
931
|
"defaultMessage": "Next"
|
|
911
932
|
},
|
|
933
|
+
"pagination.link.next.assistive_msg": {
|
|
934
|
+
"defaultMessage": "Next Page"
|
|
935
|
+
},
|
|
912
936
|
"pagination.link.prev": {
|
|
913
937
|
"defaultMessage": "Prev"
|
|
914
938
|
},
|
|
939
|
+
"pagination.link.prev.assistive_msg": {
|
|
940
|
+
"defaultMessage": "Previous Page"
|
|
941
|
+
},
|
|
915
942
|
"password_card.info.password_updated": {
|
|
916
943
|
"defaultMessage": "Password updated"
|
|
917
944
|
},
|