@latte-macchiat-io/latte-vanilla-components 0.0.202 → 0.0.203
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 +1 -1
- package/src/components/Carousel/export.tsx +2 -4
- package/src/components/Carousel/index.tsx +159 -191
- package/src/components/Carousel/theme.ts +102 -0
- package/src/components/Columns/export.tsx +2 -5
- package/src/components/Columns/index.tsx +10 -15
- package/src/components/Columns/styles.css.ts +3 -1
- package/src/components/Columns/theme.ts +24 -0
- package/src/components/ConsentCookie/export.tsx +2 -4
- package/src/components/ConsentCookie/index.tsx +104 -0
- package/src/components/Footer/export.tsx +1 -4
- package/src/components/Footer/index.tsx +1 -8
- package/src/components/Footer/theme.ts +51 -0
- package/src/components/Form/export.tsx +17 -3
- package/src/components/Header/export.tsx +1 -4
- package/src/components/Header/index.tsx +19 -35
- package/src/components/Header/styles.css.ts +2 -2
- package/src/components/Header/theme.ts +51 -0
- package/src/components/Heading/export.tsx +1 -0
- package/src/components/Heading/index.tsx +3 -8
- package/src/components/Icon/export.tsx +1 -4
- package/src/components/Icon/index.tsx +4 -5
- package/src/components/Icon/theme.ts +17 -0
- package/src/components/KeyNumber/export.tsx +2 -4
- package/src/components/KeyNumber/index.tsx +3 -3
- package/src/components/KeyNumber/theme.ts +22 -0
- package/src/components/LanguageSwitcher/export.tsx +2 -4
- package/src/components/LanguageSwitcher/index.tsx +37 -63
- package/src/components/Logo/export.tsx +1 -4
- package/src/components/Logo/index.tsx +2 -5
- package/src/components/Logo/styles.css.ts +2 -2
- package/src/components/Main/export.tsx +1 -4
- package/src/components/Main/index.tsx +1 -9
- package/src/components/Main/theme.ts +19 -0
- package/src/components/Modal/export.tsx +2 -4
- package/src/components/Modal/index.tsx +4 -5
- package/src/components/Modal/theme.ts +31 -0
- package/src/components/Nav/export.tsx +1 -4
- package/src/components/Nav/index.tsx +6 -14
- package/src/components/Nav/styles.css.ts +3 -1
- package/src/components/Nav/theme.ts +24 -0
- package/src/components/NavLegal/export.tsx +1 -4
- package/src/components/NavLegal/index.tsx +1 -7
- package/src/components/NavLegal/theme.ts +24 -0
- package/src/components/NavSocial/export.tsx +2 -5
- package/src/components/NavSocial/index.tsx +14 -18
- package/src/components/NavSocial/theme.ts +34 -0
- package/src/components/Section/export.tsx +2 -6
- package/src/components/Section/index.tsx +4 -8
- package/src/components/Section/theme.ts +40 -0
- package/src/components/Video/export.tsx +2 -2
- package/src/components/Video/index.tsx +78 -83
- package/src/components/Video/theme.ts +104 -0
- package/src/index.ts +19 -49
- package/src/theme/baseThemeValues.ts +40 -712
- package/src/theme/contract.css.ts +0 -16
- package/src/utils/useWindowSize.ts +29 -0
- package/src/components/ConsentCookie/ConsentCookie.tsx +0 -200
- package/src/components/Header/HeaderOverlay/index.tsx +0 -32
- package/src/components/Header/HeaderOverlay/styles.css.ts +0 -33
- package/src/components/Header/ToggleNav/index.tsx +0 -29
- package/src/components/Header/ToggleNav/styles.css.ts +0 -40
- package/src/components/ThemeTest/ThemeTest.css.ts +0 -11
- package/src/components/ThemeTest/ThemeTest.tsx +0 -12
- /package/src/components/ConsentCookie/{ConsentCookie.css.ts → styles.css.ts} +0 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
import { clsx } from 'clsx';
|
2
|
+
import { useEffect, useState } from 'react';
|
3
|
+
|
4
|
+
import { getCookie, setCookie } from './cookie';
|
5
|
+
import { consentActions, consentContent, type ConsentCookieVariants, consentRecipe } from './styles.css';
|
6
|
+
|
7
|
+
import { Button } from '../Button';
|
8
|
+
|
9
|
+
// Declare window object including gtag to avoid TypeScript errors
|
10
|
+
declare const window: Window &
|
11
|
+
typeof globalThis & {
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
13
|
+
gtag: any;
|
14
|
+
};
|
15
|
+
|
16
|
+
export interface ConsentCookieProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>, NonNullable<ConsentCookieVariants> {
|
17
|
+
cookieName?: string;
|
18
|
+
cookieExpirationDays?: number;
|
19
|
+
onAccept?: () => void;
|
20
|
+
onReject?: () => void;
|
21
|
+
translations?: {
|
22
|
+
actions: {
|
23
|
+
accept: string;
|
24
|
+
reject: string;
|
25
|
+
};
|
26
|
+
};
|
27
|
+
enableGoogleAnalytics?: boolean;
|
28
|
+
}
|
29
|
+
|
30
|
+
export const ConsentCookie = ({
|
31
|
+
variant,
|
32
|
+
onAccept,
|
33
|
+
onReject,
|
34
|
+
children,
|
35
|
+
className,
|
36
|
+
translations,
|
37
|
+
cookieName = 'consent',
|
38
|
+
cookieExpirationDays = 365,
|
39
|
+
enableGoogleAnalytics = true,
|
40
|
+
}: ConsentCookieProps) => {
|
41
|
+
const [showConsent, setShowConsent] = useState(false);
|
42
|
+
|
43
|
+
const handleAccept = () => {
|
44
|
+
setShowConsent(false);
|
45
|
+
setCookie(cookieName, 'true', cookieExpirationDays);
|
46
|
+
|
47
|
+
if (enableGoogleAnalytics && typeof window !== 'undefined' && typeof window.gtag !== 'undefined') {
|
48
|
+
window.gtag('consent', 'update', {
|
49
|
+
analytics_storage: 'granted',
|
50
|
+
});
|
51
|
+
}
|
52
|
+
|
53
|
+
onAccept?.();
|
54
|
+
};
|
55
|
+
|
56
|
+
const handleReject = () => {
|
57
|
+
setShowConsent(false);
|
58
|
+
setCookie(cookieName, 'false', cookieExpirationDays);
|
59
|
+
|
60
|
+
if (enableGoogleAnalytics && typeof window !== 'undefined' && typeof window.gtag !== 'undefined') {
|
61
|
+
window.gtag('consent', 'update', {
|
62
|
+
analytics_storage: 'denied',
|
63
|
+
});
|
64
|
+
}
|
65
|
+
|
66
|
+
onReject?.();
|
67
|
+
};
|
68
|
+
|
69
|
+
useEffect(() => {
|
70
|
+
const consentValue = getCookie(cookieName);
|
71
|
+
const shouldShowConsent = consentValue !== 'true' && consentValue !== 'false';
|
72
|
+
const areCookiesAccepted = consentValue === 'true';
|
73
|
+
|
74
|
+
if (shouldShowConsent) {
|
75
|
+
setShowConsent(true);
|
76
|
+
}
|
77
|
+
|
78
|
+
// Set initial Google Analytics consent
|
79
|
+
if (enableGoogleAnalytics && typeof window !== 'undefined' && typeof window.gtag !== 'undefined') {
|
80
|
+
const gAnalyticsConsent = areCookiesAccepted ? 'granted' : 'denied';
|
81
|
+
window.gtag('consent', 'update', {
|
82
|
+
analytics_storage: gAnalyticsConsent,
|
83
|
+
});
|
84
|
+
}
|
85
|
+
}, [cookieName, enableGoogleAnalytics]);
|
86
|
+
|
87
|
+
if (!showConsent) return null;
|
88
|
+
|
89
|
+
return (
|
90
|
+
<div className={clsx(consentRecipe({ variant }), className)} role="dialog" aria-modal="true" aria-labelledby="consent-title">
|
91
|
+
<div className={consentContent}>
|
92
|
+
{children}
|
93
|
+
<div className={consentActions}>
|
94
|
+
<Button size="sm" onClick={handleReject}>
|
95
|
+
{translations?.actions.reject || 'Reject'}
|
96
|
+
</Button>
|
97
|
+
<Button variant="primary" size="sm" onClick={handleAccept}>
|
98
|
+
{translations?.actions.accept || 'Accept'}
|
99
|
+
</Button>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
</div>
|
103
|
+
);
|
104
|
+
};
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { clsx } from 'clsx';
|
2
|
-
import { forwardRef } from 'react';
|
3
2
|
|
4
3
|
import { footerRecipe } from './styles.css';
|
5
4
|
|
@@ -8,10 +7,4 @@ export type FooterProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
8
7
|
children: React.ReactNode;
|
9
8
|
};
|
10
9
|
|
11
|
-
export const Footer =
|
12
|
-
return (
|
13
|
-
<footer ref={ref} className={clsx(footerRecipe, css, className)}>
|
14
|
-
{children}
|
15
|
-
</footer>
|
16
|
-
);
|
17
|
-
});
|
10
|
+
export const Footer = ({ children, css, className }: FooterProps) => <footer className={clsx(footerRecipe, css, className)}>{children}</footer>;
|
@@ -0,0 +1,51 @@
|
|
1
|
+
const themeFooterBase = {
|
2
|
+
footer: {
|
3
|
+
fontSize: '0.8em',
|
4
|
+
height: {
|
5
|
+
mobile: '15px',
|
6
|
+
sm: '15px',
|
7
|
+
md: '30px',
|
8
|
+
lg: '30px',
|
9
|
+
xl: '50px',
|
10
|
+
'2xl': '50px',
|
11
|
+
},
|
12
|
+
gap: {
|
13
|
+
mobile: '15px',
|
14
|
+
sm: '15px',
|
15
|
+
md: '30px',
|
16
|
+
lg: '30px',
|
17
|
+
xl: '50px',
|
18
|
+
'2xl': '50px',
|
19
|
+
},
|
20
|
+
paddingTop: {
|
21
|
+
mobile: '15px',
|
22
|
+
sm: '15px',
|
23
|
+
md: '30px',
|
24
|
+
lg: '30px',
|
25
|
+
xl: '50px',
|
26
|
+
'2xl': '50px',
|
27
|
+
},
|
28
|
+
paddingBottom: {
|
29
|
+
mobile: '15px',
|
30
|
+
sm: '15px',
|
31
|
+
md: '30px',
|
32
|
+
lg: '30px',
|
33
|
+
xl: '50px',
|
34
|
+
'2xl': '50px',
|
35
|
+
},
|
36
|
+
},
|
37
|
+
};
|
38
|
+
|
39
|
+
export const themeFooterLight = {
|
40
|
+
footer: {
|
41
|
+
...themeFooterBase.footer,
|
42
|
+
backgroundColor: '#FF7377',
|
43
|
+
},
|
44
|
+
};
|
45
|
+
|
46
|
+
export const themeFooterDark = {
|
47
|
+
footer: {
|
48
|
+
...themeFooterBase.footer,
|
49
|
+
backgroundColor: '#FF7377',
|
50
|
+
},
|
51
|
+
};
|
@@ -1,4 +1,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
export { Form, type FormProps } from './Form';
|
2
|
+
export { type FormVariants } from './Form.css';
|
3
3
|
|
4
|
-
|
4
|
+
export { Row, type RowProps } from '../Form/Row/Row';
|
5
|
+
export { type RowVariants } from '../Form/Row/Row.css';
|
6
|
+
|
7
|
+
export { TextField, type TextFieldProps, type InputType } from '../Form/TextField/TextField';
|
8
|
+
export { type TextFieldVariants } from '../Form/TextField/TextField.css';
|
9
|
+
|
10
|
+
// Form TextField Subcomponents
|
11
|
+
export { Label, type LabelProps } from '../Form/TextField/Label/Label';
|
12
|
+
export { type LabelVariants } from '../Form/TextField/Label/Label.css';
|
13
|
+
|
14
|
+
export { Input, type InputProps, type InputType as InputFieldType } from '../Form/TextField/Input/Input';
|
15
|
+
export { type InputVariants } from '../Form/TextField/Input/Input.css';
|
16
|
+
|
17
|
+
export { Textarea, type TextareaProps } from '../Form/TextField/Textarea/Textarea';
|
18
|
+
export { type TextareaVariants } from '../Form/TextField/Textarea/Textarea.css';
|
@@ -1,10 +1,9 @@
|
|
1
1
|
import { clsx } from 'clsx';
|
2
|
-
import {
|
2
|
+
import { useState } from 'react';
|
3
3
|
|
4
4
|
import { headerOverlayRecipe, headerPlaceholder, headerRecipe, headerToggleNav } from './styles.css';
|
5
5
|
|
6
6
|
export type HeaderProps = React.HTMLAttributes<HTMLDivElement> & {
|
7
|
-
css?: string;
|
8
7
|
isFixed?: boolean;
|
9
8
|
hideToggleNav?: boolean;
|
10
9
|
children: React.ReactNode;
|
@@ -12,40 +11,25 @@ export type HeaderProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
12
11
|
childrenToggleNav?: React.ReactNode;
|
13
12
|
};
|
14
13
|
|
15
|
-
export const Header =
|
16
|
-
(
|
17
|
-
|
18
|
-
children,
|
19
|
-
childrenOverlay,
|
20
|
-
childrenToggleNav,
|
21
|
-
isFixed = false,
|
22
|
-
hideToggleNav = false,
|
14
|
+
export const Header = ({ children, childrenOverlay, childrenToggleNav, isFixed = false, hideToggleNav = false, className }: HeaderProps) => {
|
15
|
+
const [isNavOpen, setNavOpen] = useState(false);
|
16
|
+
const onToggleNav = () => setNavOpen(!isNavOpen);
|
23
17
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
) => {
|
29
|
-
const [isNavOpen, setNavOpen] = useState(false);
|
18
|
+
return (
|
19
|
+
<>
|
20
|
+
<header className={clsx(headerRecipe({ isFixed }), className)}>
|
21
|
+
{childrenOverlay && <div className={headerOverlayRecipe({ isOpen: isNavOpen })}>{childrenOverlay}</div>}
|
30
22
|
|
31
|
-
|
23
|
+
{children}
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
25
|
+
{!hideToggleNav && (
|
26
|
+
<button onClick={onToggleNav} aria-label="Toggle navigation" className={headerToggleNav}>
|
27
|
+
{childrenToggleNav}
|
28
|
+
</button>
|
29
|
+
)}
|
30
|
+
</header>
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
{childrenToggleNav}
|
43
|
-
</button>
|
44
|
-
)}
|
45
|
-
</header>
|
46
|
-
|
47
|
-
{isFixed && <div className={headerPlaceholder} />}
|
48
|
-
</>
|
49
|
-
);
|
50
|
-
}
|
51
|
-
);
|
32
|
+
{isFixed && <div className={headerPlaceholder} />}
|
33
|
+
</>
|
34
|
+
);
|
35
|
+
};
|
@@ -61,11 +61,11 @@ export const headerToggleNav = style([
|
|
61
61
|
|
62
62
|
export const headerOverlayRecipe = recipe({
|
63
63
|
base: {
|
64
|
-
position: 'fixed',
|
65
64
|
inset: 0,
|
65
|
+
zIndex: 25,
|
66
|
+
position: 'fixed',
|
66
67
|
backgroundColor: 'rgba(0,0,0,0.6)',
|
67
68
|
transition: 'opacity 0.3s ease-in-out, visibility 0.3s ease-in-out',
|
68
|
-
zIndex: 25,
|
69
69
|
},
|
70
70
|
|
71
71
|
variants: {
|
@@ -0,0 +1,51 @@
|
|
1
|
+
const themeHeaderBase = {
|
2
|
+
header: {
|
3
|
+
fontSize: '1.2em',
|
4
|
+
height: {
|
5
|
+
mobile: '15px',
|
6
|
+
sm: '15px',
|
7
|
+
md: '30px',
|
8
|
+
lg: '30px',
|
9
|
+
xl: '50px',
|
10
|
+
'2xl': '50px',
|
11
|
+
},
|
12
|
+
gap: {
|
13
|
+
mobile: '15px',
|
14
|
+
sm: '15px',
|
15
|
+
md: '30px',
|
16
|
+
lg: '30px',
|
17
|
+
xl: '50px',
|
18
|
+
'2xl': '50px',
|
19
|
+
},
|
20
|
+
paddingTop: {
|
21
|
+
mobile: '15px',
|
22
|
+
sm: '15px',
|
23
|
+
md: '30px',
|
24
|
+
lg: '30px',
|
25
|
+
xl: '50px',
|
26
|
+
'2xl': '50px',
|
27
|
+
},
|
28
|
+
paddingBottom: {
|
29
|
+
mobile: '15px',
|
30
|
+
sm: '15px',
|
31
|
+
md: '30px',
|
32
|
+
lg: '30px',
|
33
|
+
xl: '50px',
|
34
|
+
'2xl': '50px',
|
35
|
+
},
|
36
|
+
},
|
37
|
+
};
|
38
|
+
|
39
|
+
export const themeHeaderLight = {
|
40
|
+
header: {
|
41
|
+
...themeHeaderBase.header,
|
42
|
+
backgroundColor: '#FF7377',
|
43
|
+
},
|
44
|
+
};
|
45
|
+
|
46
|
+
export const themeHeaderDark = {
|
47
|
+
header: {
|
48
|
+
...themeHeaderBase.header,
|
49
|
+
backgroundColor: '#FF7377',
|
50
|
+
},
|
51
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export { Heading, type HeadingProps } from './';
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { clsx } from 'clsx';
|
2
|
-
import { forwardRef } from 'react';
|
3
2
|
|
4
3
|
import { headingRecipe, HeadingVariants } from './styles.css';
|
5
4
|
import { AllowedHeading } from './types';
|
@@ -11,12 +10,8 @@ export type HeadingProps = React.HTMLAttributes<HTMLHeadingElement> &
|
|
11
10
|
children: React.ReactNode;
|
12
11
|
};
|
13
12
|
|
14
|
-
export const Heading =
|
13
|
+
export const Heading = ({ as, size, weight, align, css, className, children }: HeadingProps) => {
|
15
14
|
const Component = as as AllowedHeading;
|
16
15
|
|
17
|
-
return (
|
18
|
-
|
19
|
-
{children}
|
20
|
-
</Component>
|
21
|
-
);
|
22
|
-
});
|
16
|
+
return <Component className={clsx(headingRecipe({ size, weight, align }), css, className)}>{children}</Component>;
|
17
|
+
};
|
@@ -1,24 +1,23 @@
|
|
1
|
-
import
|
1
|
+
import clsx from 'clsx';
|
2
2
|
|
3
3
|
import path from './path';
|
4
4
|
|
5
5
|
import { iconRecipe } from './style.css';
|
6
6
|
import { themeContract } from '../../theme/contract.css';
|
7
7
|
|
8
|
-
export type IconProps = {
|
8
|
+
export type IconProps = React.HTMLAttributes<HTMLDivElement> & {
|
9
9
|
icon?: string;
|
10
10
|
size?: number;
|
11
11
|
color?: string;
|
12
12
|
viewBox?: string;
|
13
13
|
iconPath?: string;
|
14
|
-
styles?: CSSProperties;
|
15
14
|
};
|
16
15
|
|
17
|
-
export const Icon = ({ icon = '', size = 24,
|
16
|
+
export const Icon = ({ icon = '', className, size = 24, iconPath = '', viewBox = '0 0 24 24', color = themeContract.icon.color }: IconProps) => {
|
18
17
|
const d = iconPath || path[icon as keyof typeof path];
|
19
18
|
|
20
19
|
return (
|
21
|
-
<svg className={iconRecipe} viewBox={viewBox} width={`${size}px`} height={`${size}px`}
|
20
|
+
<svg className={clsx(iconRecipe, className)} viewBox={viewBox} width={`${size}px`} height={`${size}px`}>
|
22
21
|
<path className={iconPath} d={d} fill={color} />
|
23
22
|
</svg>
|
24
23
|
);
|
@@ -0,0 +1,17 @@
|
|
1
|
+
const themeIconBase = {
|
2
|
+
icon: {},
|
3
|
+
};
|
4
|
+
|
5
|
+
export const themeIconLight = {
|
6
|
+
icon: {
|
7
|
+
...themeIconBase.icon,
|
8
|
+
color: '#FF7377',
|
9
|
+
},
|
10
|
+
};
|
11
|
+
|
12
|
+
export const themeIconDark = {
|
13
|
+
icon: {
|
14
|
+
...themeIconBase.icon,
|
15
|
+
color: '#FF7377',
|
16
|
+
},
|
17
|
+
};
|
@@ -3,6 +3,7 @@
|
|
3
3
|
import { clsx } from 'clsx';
|
4
4
|
import { forwardRef } from 'react';
|
5
5
|
import CountUp from 'react-countup';
|
6
|
+
|
6
7
|
import { useInView } from 'react-intersection-observer';
|
7
8
|
|
8
9
|
import { keyNumberRecipe, keyNumberValueRecipe, KeyNumberValueVariants, type KeyNumberVariants } from './styles.css';
|
@@ -10,7 +11,6 @@ import { keyNumberRecipe, keyNumberValueRecipe, KeyNumberValueVariants, type Key
|
|
10
11
|
export type KeyNumberProps = React.HTMLAttributes<HTMLDivElement> &
|
11
12
|
KeyNumberVariants &
|
12
13
|
KeyNumberValueVariants & {
|
13
|
-
css?: string;
|
14
14
|
value: number;
|
15
15
|
suffix?: string;
|
16
16
|
prefix?: string;
|
@@ -21,7 +21,7 @@ export type KeyNumberProps = React.HTMLAttributes<HTMLDivElement> &
|
|
21
21
|
};
|
22
22
|
|
23
23
|
export const KeyNumber = forwardRef<HTMLDivElement, KeyNumberProps>(
|
24
|
-
({ value, suffix = '', prefix = '', duration = 2, threshold = 0.3, separator = ',', decimals = 0, size, align, vAlign,
|
24
|
+
({ value, suffix = '', prefix = '', duration = 2, threshold = 0.3, separator = ',', decimals = 0, size, align, vAlign, className }, ref) => {
|
25
25
|
const [inViewRef, inView] = useInView({
|
26
26
|
threshold,
|
27
27
|
triggerOnce: true,
|
@@ -39,7 +39,7 @@ export const KeyNumber = forwardRef<HTMLDivElement, KeyNumberProps>(
|
|
39
39
|
}
|
40
40
|
}
|
41
41
|
}}
|
42
|
-
className={clsx(keyNumberRecipe({ align, vAlign }),
|
42
|
+
className={clsx(keyNumberRecipe({ align, vAlign }), className)}>
|
43
43
|
{prefix}
|
44
44
|
<CountUp end={inView ? value : 0} duration={duration} separator={separator} decimals={decimals} className={keyNumberValueRecipe({ size })} />
|
45
45
|
{suffix}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
const themeKeyNumberBase = {
|
2
|
+
keyNumber: {
|
3
|
+
fontSize: {
|
4
|
+
large: '2.5em',
|
5
|
+
xlarge: '4em',
|
6
|
+
},
|
7
|
+
paddingTop: { mobile: '15px', sm: '15px', md: '30px', lg: '30px', xl: '50px', '2xl': '50px' },
|
8
|
+
paddingBottom: { mobile: '15px', sm: '15px', md: '30px', lg: '30px', xl: '50px', '2xl': '50px' },
|
9
|
+
},
|
10
|
+
};
|
11
|
+
|
12
|
+
export const themeKeyNumberLight = {
|
13
|
+
keyNumber: {
|
14
|
+
...themeKeyNumberBase.keyNumber,
|
15
|
+
},
|
16
|
+
};
|
17
|
+
|
18
|
+
export const themeKeyNumberDark = {
|
19
|
+
keyNumber: {
|
20
|
+
...themeKeyNumberBase.keyNumber,
|
21
|
+
},
|
22
|
+
};
|
@@ -1,4 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
// export { styles as LanguageSwitcherStyles } from './styles.css';
|
1
|
+
export { LanguageSwitcher, type LanguageSwitcherProps, type Locale } from './';
|
2
|
+
export { type LanguageSwitcherVariants } from './styles.css';
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { clsx } from 'clsx';
|
2
|
-
import { forwardRef } from 'react';
|
3
2
|
import { languageSwitcherIcon, languageSwitcherRecipe, languageSwitcherSelect, type LanguageSwitcherVariants } from './styles.css';
|
4
3
|
|
5
4
|
import { Icon } from '../Icon';
|
@@ -10,69 +9,44 @@ export interface Locale {
|
|
10
9
|
label?: string;
|
11
10
|
}
|
12
11
|
|
13
|
-
export
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
placeholder?: string;
|
22
|
-
}
|
23
|
-
|
24
|
-
export const LanguageSwitcher = forwardRef<HTMLDivElement, LanguageSwitcherProps>(
|
25
|
-
(
|
26
|
-
{
|
27
|
-
locales,
|
28
|
-
currentLocale,
|
29
|
-
onChange,
|
30
|
-
disabled = false,
|
31
|
-
placeholder,
|
32
|
-
variant,
|
33
|
-
size,
|
34
|
-
css,
|
35
|
-
className,
|
36
|
-
|
37
|
-
...htmlProps
|
38
|
-
},
|
39
|
-
ref
|
40
|
-
) => {
|
41
|
-
const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
42
|
-
onChange(event.target.value);
|
43
|
-
};
|
12
|
+
export type LanguageSwitcherProps = React.HTMLAttributes<HTMLDivElement> &
|
13
|
+
LanguageSwitcherVariants & {
|
14
|
+
locales: Locale[];
|
15
|
+
disabled?: boolean;
|
16
|
+
placeholder?: string;
|
17
|
+
currentLocale: string;
|
18
|
+
onChange: (locale: string) => void;
|
19
|
+
};
|
44
20
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
21
|
+
export const LanguageSwitcher = ({
|
22
|
+
size,
|
23
|
+
locales,
|
24
|
+
variant,
|
25
|
+
onChange,
|
26
|
+
className,
|
27
|
+
placeholder,
|
28
|
+
currentLocale,
|
29
|
+
disabled = false,
|
30
|
+
}: LanguageSwitcherProps) => {
|
31
|
+
const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => onChange(event.target.value);
|
50
32
|
|
51
|
-
|
52
|
-
|
33
|
+
return (
|
34
|
+
<div className={clsx(languageSwitcherRecipe({ variant, size }), className)}>
|
35
|
+
<select className={languageSwitcherSelect} value={currentLocale} onChange={handleSelectChange} disabled={disabled} aria-label="Switch language">
|
36
|
+
{placeholder && (
|
37
|
+
<option value="" disabled>
|
38
|
+
{placeholder}
|
39
|
+
</option>
|
53
40
|
)}
|
54
|
-
{
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
<option value="" disabled>
|
63
|
-
{placeholder}
|
64
|
-
</option>
|
65
|
-
)}
|
66
|
-
{locales.map((locale) => (
|
67
|
-
<option key={locale.code} value={locale.code} disabled={locale.code === currentLocale}>
|
68
|
-
{locale.label || locale.name}
|
69
|
-
</option>
|
70
|
-
))}
|
71
|
-
</select>
|
72
|
-
<div className={languageSwitcherIcon}>
|
73
|
-
<Icon icon="caret" />
|
74
|
-
</div>
|
41
|
+
{locales.map((locale) => (
|
42
|
+
<option key={locale.code} value={locale.code} disabled={locale.code === currentLocale}>
|
43
|
+
{locale.label || locale.name}
|
44
|
+
</option>
|
45
|
+
))}
|
46
|
+
</select>
|
47
|
+
<div className={languageSwitcherIcon}>
|
48
|
+
<Icon icon="caret" />
|
75
49
|
</div>
|
76
|
-
|
77
|
-
|
78
|
-
|
50
|
+
</div>
|
51
|
+
);
|
52
|
+
};
|
@@ -1,13 +1,10 @@
|
|
1
1
|
import { clsx } from 'clsx';
|
2
2
|
import { ReactNode } from 'react';
|
3
3
|
|
4
|
-
import {
|
4
|
+
import { logo } from './styles.css';
|
5
5
|
|
6
6
|
export type LogoProps = React.HTMLAttributes<HTMLDivElement> & {
|
7
|
-
css?: string;
|
8
7
|
children?: ReactNode;
|
9
8
|
};
|
10
9
|
|
11
|
-
export const Logo = ({ children,
|
12
|
-
return <div className={clsx(logoBase, css, className)}>{children}</div>;
|
13
|
-
};
|
10
|
+
export const Logo = ({ children, className }: LogoProps) => <div className={clsx(logo, className)}>{children}</div>;
|
@@ -1,12 +1,12 @@
|
|
1
1
|
import { globalStyle, style } from '@vanilla-extract/css';
|
2
2
|
|
3
|
-
export const
|
3
|
+
export const logo = style({
|
4
4
|
alignItems: 'center',
|
5
5
|
display: 'inline-flex',
|
6
6
|
justifyContent: 'center',
|
7
7
|
});
|
8
8
|
|
9
|
-
globalStyle(`${
|
9
|
+
globalStyle(`${logo} img`, {
|
10
10
|
width: '100%',
|
11
11
|
height: 'auto',
|
12
12
|
maxWidth: '100%',
|