@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.
Files changed (65) hide show
  1. package/package.json +1 -1
  2. package/src/components/Carousel/export.tsx +2 -4
  3. package/src/components/Carousel/index.tsx +159 -191
  4. package/src/components/Carousel/theme.ts +102 -0
  5. package/src/components/Columns/export.tsx +2 -5
  6. package/src/components/Columns/index.tsx +10 -15
  7. package/src/components/Columns/styles.css.ts +3 -1
  8. package/src/components/Columns/theme.ts +24 -0
  9. package/src/components/ConsentCookie/export.tsx +2 -4
  10. package/src/components/ConsentCookie/index.tsx +104 -0
  11. package/src/components/Footer/export.tsx +1 -4
  12. package/src/components/Footer/index.tsx +1 -8
  13. package/src/components/Footer/theme.ts +51 -0
  14. package/src/components/Form/export.tsx +17 -3
  15. package/src/components/Header/export.tsx +1 -4
  16. package/src/components/Header/index.tsx +19 -35
  17. package/src/components/Header/styles.css.ts +2 -2
  18. package/src/components/Header/theme.ts +51 -0
  19. package/src/components/Heading/export.tsx +1 -0
  20. package/src/components/Heading/index.tsx +3 -8
  21. package/src/components/Icon/export.tsx +1 -4
  22. package/src/components/Icon/index.tsx +4 -5
  23. package/src/components/Icon/theme.ts +17 -0
  24. package/src/components/KeyNumber/export.tsx +2 -4
  25. package/src/components/KeyNumber/index.tsx +3 -3
  26. package/src/components/KeyNumber/theme.ts +22 -0
  27. package/src/components/LanguageSwitcher/export.tsx +2 -4
  28. package/src/components/LanguageSwitcher/index.tsx +37 -63
  29. package/src/components/Logo/export.tsx +1 -4
  30. package/src/components/Logo/index.tsx +2 -5
  31. package/src/components/Logo/styles.css.ts +2 -2
  32. package/src/components/Main/export.tsx +1 -4
  33. package/src/components/Main/index.tsx +1 -9
  34. package/src/components/Main/theme.ts +19 -0
  35. package/src/components/Modal/export.tsx +2 -4
  36. package/src/components/Modal/index.tsx +4 -5
  37. package/src/components/Modal/theme.ts +31 -0
  38. package/src/components/Nav/export.tsx +1 -4
  39. package/src/components/Nav/index.tsx +6 -14
  40. package/src/components/Nav/styles.css.ts +3 -1
  41. package/src/components/Nav/theme.ts +24 -0
  42. package/src/components/NavLegal/export.tsx +1 -4
  43. package/src/components/NavLegal/index.tsx +1 -7
  44. package/src/components/NavLegal/theme.ts +24 -0
  45. package/src/components/NavSocial/export.tsx +2 -5
  46. package/src/components/NavSocial/index.tsx +14 -18
  47. package/src/components/NavSocial/theme.ts +34 -0
  48. package/src/components/Section/export.tsx +2 -6
  49. package/src/components/Section/index.tsx +4 -8
  50. package/src/components/Section/theme.ts +40 -0
  51. package/src/components/Video/export.tsx +2 -2
  52. package/src/components/Video/index.tsx +78 -83
  53. package/src/components/Video/theme.ts +104 -0
  54. package/src/index.ts +19 -49
  55. package/src/theme/baseThemeValues.ts +40 -712
  56. package/src/theme/contract.css.ts +0 -16
  57. package/src/utils/useWindowSize.ts +29 -0
  58. package/src/components/ConsentCookie/ConsentCookie.tsx +0 -200
  59. package/src/components/Header/HeaderOverlay/index.tsx +0 -32
  60. package/src/components/Header/HeaderOverlay/styles.css.ts +0 -33
  61. package/src/components/Header/ToggleNav/index.tsx +0 -29
  62. package/src/components/Header/ToggleNav/styles.css.ts +0 -40
  63. package/src/components/ThemeTest/ThemeTest.css.ts +0 -11
  64. package/src/components/ThemeTest/ThemeTest.tsx +0 -12
  65. /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,4 +1 @@
1
- // export { Footer } from '.';
2
- // export type { FooterProps } from '.';
3
-
4
- // export { styles as FooterStyles } from './styles.css';
1
+ export { Footer, type FooterProps } from './';
@@ -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 = forwardRef<HTMLDivElement, FooterProps>(({ children, css, className }, ref) => {
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
- // export { Form } from '.';
2
- // export type { FormProps } from '.';
1
+ export { Form, type FormProps } from './Form';
2
+ export { type FormVariants } from './Form.css';
3
3
 
4
- // export { styles as FormStyles } from './styles.css';
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,4 +1 @@
1
- // export { Header } from '.';
2
- // export type { HeaderProps } from '.';
3
-
4
- // export { styles as HeaderStyles } from './styles.css';
1
+ export { Header, type HeaderProps } from './';
@@ -1,10 +1,9 @@
1
1
  import { clsx } from 'clsx';
2
- import { forwardRef, useState } from 'react';
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 = forwardRef<HTMLDivElement, HeaderProps>(
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
- css,
25
- className,
26
- },
27
- ref
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
- const onToggleNav = () => setNavOpen(!isNavOpen);
23
+ {children}
32
24
 
33
- return (
34
- <>
35
- <header ref={ref} className={clsx(headerRecipe({ isFixed }), css, className)}>
36
- {childrenOverlay && <div className={headerOverlayRecipe({ isOpen: isNavOpen })}>{childrenOverlay}</div>}
25
+ {!hideToggleNav && (
26
+ <button onClick={onToggleNav} aria-label="Toggle navigation" className={headerToggleNav}>
27
+ {childrenToggleNav}
28
+ </button>
29
+ )}
30
+ </header>
37
31
 
38
- {children}
39
-
40
- {!hideToggleNav && (
41
- <button onClick={onToggleNav} aria-label="Toggle navigation" className={headerToggleNav}>
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 = forwardRef<HTMLHeadingElement, HeadingProps>(({ as, size, weight, align, css, className, children }, ref) => {
13
+ export const Heading = ({ as, size, weight, align, css, className, children }: HeadingProps) => {
15
14
  const Component = as as AllowedHeading;
16
15
 
17
- return (
18
- <Component ref={ref} className={clsx(headingRecipe({ size, weight, align }), css, className)}>
19
- {children}
20
- </Component>
21
- );
22
- });
16
+ return <Component className={clsx(headingRecipe({ size, weight, align }), css, className)}>{children}</Component>;
17
+ };
@@ -1,4 +1 @@
1
- // export { Icon } from '.';
2
- // export type { IconProps } from '.';
3
-
4
- // export { styles as IconStyles } from './styles.css';
1
+ export { Icon, type IconProps } from './';
@@ -1,24 +1,23 @@
1
- import { CSSProperties } from 'react';
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, styles = {}, iconPath = '', color = themeContract.icon.color, viewBox = '0 0 24 24' }: IconProps) => {
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`} style={styles}>
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
+ };
@@ -1,4 +1,2 @@
1
- // export { KeyNumber } from '.';
2
- // export type { KeyNumberProps } from '.';
3
-
4
- // export { styles as KeyNumberStyles } from './styles.css';
1
+ export { KeyNumber, type KeyNumberProps } from './';
2
+ export { type KeyNumberVariants } from './styles.css';
@@ -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, css, className }, ref) => {
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 }), css, className)}>
42
+ className={clsx(keyNumberRecipe({ align, vAlign }), className)}>
43
43
  {prefix}&nbsp;
44
44
  <CountUp end={inView ? value : 0} duration={duration} separator={separator} decimals={decimals} className={keyNumberValueRecipe({ size })} />
45
45
  &nbsp;{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
- // export { LanguageSwitcher } from '.';
2
- // export type { LanguageSwitcherProps } from '.';
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 interface LanguageSwitcherProps
14
- extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'onChange'>,
15
- NonNullable<LanguageSwitcherVariants> {
16
- css?: string;
17
- locales: Locale[];
18
- currentLocale: string;
19
- onChange: (locale: string) => void;
20
- disabled?: boolean;
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
- return (
46
- <div
47
- ref={ref}
48
- className={clsx(
49
- languageSwitcherRecipe({ variant, size }),
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
- css,
52
- className
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
- {...htmlProps}>
55
- <select
56
- className={languageSwitcherSelect}
57
- value={currentLocale}
58
- onChange={handleSelectChange}
59
- disabled={disabled}
60
- aria-label="Switch language">
61
- {placeholder && (
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,4 +1 @@
1
- // export { Logo } from '.';
2
- // export type { LogoProps } from '.';
3
-
4
- // export { styles as LogoStyles } from './styles.css';
1
+ export { Logo, type LogoProps } from './';
@@ -1,13 +1,10 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { ReactNode } from 'react';
3
3
 
4
- import { logoBase } from './styles.css';
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, css, className }: LogoProps) => {
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 logoBase = style({
3
+ export const logo = style({
4
4
  alignItems: 'center',
5
5
  display: 'inline-flex',
6
6
  justifyContent: 'center',
7
7
  });
8
8
 
9
- globalStyle(`${logoBase} img`, {
9
+ globalStyle(`${logo} img`, {
10
10
  width: '100%',
11
11
  height: 'auto',
12
12
  maxWidth: '100%',
@@ -1,4 +1 @@
1
- // export { Main } from '.';
2
- // export type { MainProps } from '.';
3
-
4
- // export { styles as MainStyles } from './styles.css';
1
+ export { Main, type MainProps } from './';