@4alldigital/foundation-ui--core 3.12.2 → 3.13.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/package.json +2 -2
- package/src/components/AddressForm/AddressForm.tsx +16 -0
- package/src/components/Header/Header.tsx +18 -2
- package/src/components/Menu/Menu.tsx +18 -1
- package/src/features/Search/views/SearchBox/SearchBox.tsx +1 -1
- package/src/features/Search/views/SearchBox/SearchBox.types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4alldigital/foundation-ui--core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.0",
|
|
4
4
|
"description": "Foundation UI Core Component Library (source distribution)",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/he": "^1.2.3"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "2394d061bf5fa814a00ffb74c334a001dbbc9bf4"
|
|
42
42
|
}
|
|
@@ -124,6 +124,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
124
124
|
{/* Full Name */}
|
|
125
125
|
<TextInput
|
|
126
126
|
id="shipping-name"
|
|
127
|
+
name="name"
|
|
128
|
+
autoComplete="shipping name"
|
|
127
129
|
placeholder="Full Name"
|
|
128
130
|
value={address.name || ''}
|
|
129
131
|
onChange={(e) => handleChange('name', e.target.value)}
|
|
@@ -136,6 +138,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
136
138
|
{/* Address Line 1 */}
|
|
137
139
|
<TextInput
|
|
138
140
|
id="shipping-line1"
|
|
141
|
+
name="address-line1"
|
|
142
|
+
autoComplete="shipping address-line1"
|
|
139
143
|
placeholder="Street Address"
|
|
140
144
|
value={address.line1 || ''}
|
|
141
145
|
onChange={(e) => handleChange('line1', e.target.value)}
|
|
@@ -148,6 +152,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
148
152
|
{/* Address Line 2 */}
|
|
149
153
|
<TextInput
|
|
150
154
|
id="shipping-line2"
|
|
155
|
+
name="address-line2"
|
|
156
|
+
autoComplete="shipping address-line2"
|
|
151
157
|
placeholder="Apartment, suite, etc. (optional)"
|
|
152
158
|
value={address.line2 || ''}
|
|
153
159
|
onChange={(e) => handleChange('line2', e.target.value)}
|
|
@@ -158,6 +164,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
158
164
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
159
165
|
<TextInput
|
|
160
166
|
id="shipping-city"
|
|
167
|
+
name="address-level2"
|
|
168
|
+
autoComplete="shipping address-level2"
|
|
161
169
|
placeholder="City"
|
|
162
170
|
value={address.city || ''}
|
|
163
171
|
onChange={(e) => handleChange('city', e.target.value)}
|
|
@@ -169,6 +177,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
169
177
|
|
|
170
178
|
<TextInput
|
|
171
179
|
id="shipping-state"
|
|
180
|
+
name="address-level1"
|
|
181
|
+
autoComplete="shipping address-level1"
|
|
172
182
|
placeholder="State / County / Province"
|
|
173
183
|
value={address.state || ''}
|
|
174
184
|
onChange={(e) => handleChange('state', e.target.value)}
|
|
@@ -183,6 +193,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
183
193
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
184
194
|
<TextInput
|
|
185
195
|
id="shipping-postal-code"
|
|
196
|
+
name="postal-code"
|
|
197
|
+
autoComplete="shipping postal-code"
|
|
186
198
|
placeholder="Postal / ZIP Code"
|
|
187
199
|
value={address.postal_code || ''}
|
|
188
200
|
onChange={(e) => handleChange('postal_code', e.target.value)}
|
|
@@ -194,6 +206,8 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
194
206
|
|
|
195
207
|
<FormSelect
|
|
196
208
|
id="shipping-country"
|
|
209
|
+
name="country"
|
|
210
|
+
autoComplete="shipping country"
|
|
197
211
|
placeholder="Country"
|
|
198
212
|
value={address.country || ''}
|
|
199
213
|
onChange={(e) => handleChange('country', e.target.value)}
|
|
@@ -208,7 +222,9 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
208
222
|
{/* Phone */}
|
|
209
223
|
<TextInput
|
|
210
224
|
id="shipping-phone"
|
|
225
|
+
name="phone"
|
|
211
226
|
type={InputType.TEL}
|
|
227
|
+
autoComplete="shipping tel"
|
|
212
228
|
placeholder="Phone Number (optional)"
|
|
213
229
|
value={address.phone || ''}
|
|
214
230
|
onChange={(e) => handleChange('phone', e.target.value)}
|
|
@@ -4,17 +4,16 @@ import { useCallback, useEffect, useState } from 'react';
|
|
|
4
4
|
import { clsx as cx } from 'clsx';
|
|
5
5
|
import { Props } from './Header.types';
|
|
6
6
|
import { useAppContext } from '../../context/App';
|
|
7
|
+
import { useThemeContext } from '../../context/Theme';
|
|
7
8
|
import Logo from '../Logo';
|
|
8
9
|
import Button from '../Button';
|
|
9
10
|
import Menu from '../Menu';
|
|
10
11
|
import { BTN_VARIANTS } from '../Button/Button.types';
|
|
11
|
-
// import Copy from '../Copy';
|
|
12
12
|
import Link from '../Link';
|
|
13
13
|
import { useLanguage } from '../../hooks';
|
|
14
14
|
import Container from '../Container';
|
|
15
15
|
import { twMerge } from 'tailwind-merge';
|
|
16
16
|
import Cart from '../Cart';
|
|
17
|
-
// import Avatar from '../Avatar';
|
|
18
17
|
|
|
19
18
|
const Header = ({
|
|
20
19
|
testID,
|
|
@@ -28,6 +27,7 @@ const Header = ({
|
|
|
28
27
|
}: Props) => {
|
|
29
28
|
const context = useAppContext();
|
|
30
29
|
const T = useLanguage();
|
|
30
|
+
const theme = useThemeContext();
|
|
31
31
|
|
|
32
32
|
const [mobileMenuClass, mobileMenuIcon] = useState('hidden');
|
|
33
33
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
@@ -94,6 +94,13 @@ const Header = ({
|
|
|
94
94
|
</div>
|
|
95
95
|
{/* <!-- tablet/desktop --> */}
|
|
96
96
|
<div className="hidden md:flex items-center justify-center gap-2">
|
|
97
|
+
{theme?.toggleTheme && (
|
|
98
|
+
<Button
|
|
99
|
+
onClick={theme.toggleTheme}
|
|
100
|
+
icon={theme.isDarkTheme ? 'mdi:weather-sunny' : 'mdi:weather-night'}
|
|
101
|
+
ariaLabel={theme.isDarkTheme ? 'Switch to light mode' : 'Switch to dark mode'}
|
|
102
|
+
/>
|
|
103
|
+
)}
|
|
97
104
|
{!context?.app?.isAuthenticated && context?.app?.loginCallback && (
|
|
98
105
|
<div className="w-32 flex justify-end">
|
|
99
106
|
<Button rounded onClick={context?.app?.loginCallback}>{T.UI.LOGIN}</Button>
|
|
@@ -158,6 +165,15 @@ const Header = ({
|
|
|
158
165
|
<Menu links={context.header.profile} separators />
|
|
159
166
|
)}
|
|
160
167
|
</div>
|
|
168
|
+
{theme?.toggleTheme && (
|
|
169
|
+
<div className="md:hidden flex justify-center">
|
|
170
|
+
<Button
|
|
171
|
+
onClick={theme.toggleTheme}
|
|
172
|
+
icon={theme.isDarkTheme ? 'mdi:weather-sunny' : 'mdi:weather-night'}
|
|
173
|
+
ariaLabel={theme.isDarkTheme ? 'Switch to light mode' : 'Switch to dark mode'}
|
|
174
|
+
/>
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
161
177
|
{context?.app?.isAuthenticated && (
|
|
162
178
|
<div className="md:hidden flex justify-center">
|
|
163
179
|
<Button rounded onClick={context?.app?.logoutCallback}>{T.UI.LOGOUT}</Button>
|
|
@@ -7,7 +7,20 @@ import Heading from '../Heading';
|
|
|
7
7
|
import { HEADING_TAGS } from '../Heading/Heading.types';
|
|
8
8
|
import { twMerge } from 'tailwind-merge';
|
|
9
9
|
|
|
10
|
+
function useCurrentPathname(): string | null {
|
|
11
|
+
try {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
+
const { usePathname } = require('next/navigation');
|
|
14
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
15
|
+
return usePathname();
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
const Menu = ({ testID, title, links, inline = true, separators = false, className }: Props) => {
|
|
22
|
+
const pathname = useCurrentPathname();
|
|
23
|
+
|
|
11
24
|
return (
|
|
12
25
|
<div data-testid={testID || '"Menu"'} className={twMerge(cx('flex flex-col gap-2', className))}>
|
|
13
26
|
{title && (
|
|
@@ -18,13 +31,17 @@ const Menu = ({ testID, title, links, inline = true, separators = false, classNa
|
|
|
18
31
|
<div className={cx('flex gap-0 items-center md:items-start', { 'flex-col md:flex-row ': inline }, { 'flex-col ': !inline })}>
|
|
19
32
|
{links?.map((link, index) => {
|
|
20
33
|
const key = `${link.id}--${index}`;
|
|
34
|
+
const isActive = pathname ? pathname === link.url || (link.url !== '/' && pathname.startsWith(link.url)) : false;
|
|
21
35
|
return (
|
|
22
36
|
<div key={key} className='flex gap-0'>
|
|
23
37
|
<div className="relative py-2">
|
|
24
|
-
<Link href={link.url} className="flex gap-1 transition-opacity hover:opacity-70">
|
|
38
|
+
<Link href={link.url} className={cx("flex gap-1 transition-opacity hover:opacity-70", isActive && "opacity-100 font-bold")}>
|
|
25
39
|
{link.icon && <Icon name={link.icon} />}
|
|
26
40
|
{link.title && <div>{link.title}</div>}
|
|
27
41
|
</Link>
|
|
42
|
+
{isActive && (
|
|
43
|
+
<div className="absolute bottom-0 left-0 right-0 h-0.5 bg-current rounded-full" />
|
|
44
|
+
)}
|
|
28
45
|
</div>
|
|
29
46
|
{separators && index + 1 < links.length && (
|
|
30
47
|
<div className="h-full hidden md:flex self-center px-2">
|
|
@@ -17,7 +17,7 @@ function SearchBox({
|
|
|
17
17
|
resetTrigger = () => {},
|
|
18
18
|
}: Props) {
|
|
19
19
|
return (
|
|
20
|
-
<div className={cx('m-0
|
|
20
|
+
<div className={cx('m-0 w-full', className)}>
|
|
21
21
|
<form onSubmit={e => onSubmit(e)} className="flex items-center">
|
|
22
22
|
<div className="flex-1 bg-body-bg/80 dark:bg-body-bg-dark/80 rounded">
|
|
23
23
|
<TextInput
|