@shohojdhara/atomix 0.4.4 → 0.4.6
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/dist/atomix.css +50 -11
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +184 -189
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +4 -4
- package/dist/core.js +194 -199
- package/dist/core.js.map +1 -1
- package/dist/forms.js +184 -189
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +189 -194
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +44 -47
- package/dist/index.esm.js +496 -613
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +528 -631
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +60 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -42
- package/src/components/AtomixGlass/glass-utils.ts +27 -14
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
- package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +5 -5
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +2 -2
- package/src/components/Button/Button.tsx +6 -6
- package/src/components/Card/Card.tsx +3 -3
- package/src/components/Dropdown/Dropdown.tsx +5 -3
- package/src/components/Footer/Footer.tsx +124 -166
- package/src/components/Footer/FooterLink.tsx +16 -19
- package/src/components/Footer/FooterSection.tsx +40 -39
- package/src/components/Footer/FooterSocialLink.tsx +59 -58
- package/src/components/Footer/README.md +1 -1
- package/src/components/Hero/Hero.tsx +72 -142
- package/src/components/Navigation/Menu/MegaMenu.tsx +17 -12
- package/src/components/Navigation/Menu/Menu.tsx +49 -24
- package/src/components/Navigation/Nav/NavItem.tsx +5 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -4
- package/src/components/Slider/Slider.tsx +7 -4
- package/src/lib/composables/index.ts +1 -2
- package/src/lib/composables/useAtomixGlass.ts +246 -222
- package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
- package/src/lib/composables/useFooter.ts +117 -20
- package/src/lib/composables/useSlider.ts +3 -1
- package/src/lib/constants/components.ts +3 -1
- package/src/lib/types/components.ts +44 -12
- package/src/styles/06-components/_components.atomix-glass.scss +72 -14
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -222
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
- package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
- package/src/lib/composables/glass-styles.ts +0 -302
- package/src/lib/composables/useGlassContainer.ts +0 -177
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { forwardRef } from 'react';
|
|
1
|
+
import React, { forwardRef, useState } from 'react';
|
|
2
2
|
import { FooterSectionProps } from '../../lib/types/components';
|
|
3
3
|
import { GridCol } from '../../layouts';
|
|
4
|
-
import { useFooter } from '../../lib/composables/useFooter';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* FooterSection component provides a section within the footer for organizing links and content.
|
|
@@ -31,14 +30,16 @@ export const FooterSection = forwardRef<
|
|
|
31
30
|
},
|
|
32
31
|
ref
|
|
33
32
|
) => {
|
|
34
|
-
const [isCollapsed, setIsCollapsed] =
|
|
33
|
+
const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
|
|
35
34
|
|
|
36
35
|
const handleToggle = () => {
|
|
37
|
-
if (collapsible)
|
|
38
|
-
setIsCollapsed(!isCollapsed);
|
|
39
|
-
}
|
|
36
|
+
if (collapsible) setIsCollapsed(prev => !prev);
|
|
40
37
|
};
|
|
41
38
|
|
|
39
|
+
const sectionId = title
|
|
40
|
+
? `footer-section-${title.toString().toLowerCase().replace(/\s+/g, '-')}`
|
|
41
|
+
: undefined;
|
|
42
|
+
|
|
42
43
|
const sectionClass = [
|
|
43
44
|
'c-footer__section',
|
|
44
45
|
collapsible && 'c-footer__section--collapsible',
|
|
@@ -48,42 +49,42 @@ export const FooterSection = forwardRef<
|
|
|
48
49
|
.filter(Boolean)
|
|
49
50
|
.join(' ');
|
|
50
51
|
|
|
52
|
+
const renderHeader = () => {
|
|
53
|
+
if (!title) return null;
|
|
54
|
+
|
|
55
|
+
if (collapsible) {
|
|
56
|
+
return (
|
|
57
|
+
<div className="c-footer__section-header">
|
|
58
|
+
<button
|
|
59
|
+
type="button"
|
|
60
|
+
className="c-footer__section-toggle"
|
|
61
|
+
onClick={handleToggle}
|
|
62
|
+
aria-expanded={!isCollapsed}
|
|
63
|
+
aria-controls={sectionId}
|
|
64
|
+
>
|
|
65
|
+
{icon && <span className="c-footer__section-icon">{icon}</span>}
|
|
66
|
+
<h4 className="c-footer__section-title">{title}</h4>
|
|
67
|
+
<span className="c-footer__section-chevron">{isCollapsed ? '▼' : '▲'}</span>
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className="c-footer__section-header">
|
|
75
|
+
<div className="c-footer__section-header-content">
|
|
76
|
+
{icon && <span className="c-footer__section-icon">{icon}</span>}
|
|
77
|
+
<h4 className="c-footer__section-title">{title}</h4>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
51
83
|
return (
|
|
52
84
|
<GridCol xs={12} md={showNewsletter ? 6 : 3} className="c-footer__section-col">
|
|
53
85
|
<div ref={ref} className={sectionClass} {...props}>
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
{collapsible ? (
|
|
57
|
-
<button
|
|
58
|
-
type="button"
|
|
59
|
-
className="c-footer__section-toggle"
|
|
60
|
-
onClick={handleToggle}
|
|
61
|
-
aria-expanded={!isCollapsed}
|
|
62
|
-
aria-controls={`footer-section-${title.toString().toLowerCase().replace(/\s+/g, '-')}`}
|
|
63
|
-
>
|
|
64
|
-
{icon && <span className="c-footer__section-icon">{icon}</span>}
|
|
65
|
-
<h4 className="c-footer__section-title">{title}</h4>
|
|
66
|
-
<span className="c-footer__section-chevron">{isCollapsed ? '▼' : '▲'}</span>
|
|
67
|
-
</button>
|
|
68
|
-
) : (
|
|
69
|
-
<div className="c-footer__section-header-content">
|
|
70
|
-
{icon && <span className="c-footer__section-icon">{icon}</span>}
|
|
71
|
-
<h4 className="c-footer__section-title">{title}</h4>
|
|
72
|
-
</div>
|
|
73
|
-
)}
|
|
74
|
-
</div>
|
|
75
|
-
)}
|
|
76
|
-
<div
|
|
77
|
-
className="c-footer__section-content"
|
|
78
|
-
id={
|
|
79
|
-
title
|
|
80
|
-
? `footer-section-${title.toString().toLowerCase().replace(/\s+/g, '-')}`
|
|
81
|
-
: undefined
|
|
82
|
-
}
|
|
83
|
-
style={{
|
|
84
|
-
display: collapsible && isCollapsed ? 'none' : 'flex',
|
|
85
|
-
}}
|
|
86
|
-
>
|
|
86
|
+
{renderHeader()}
|
|
87
|
+
<div className="c-footer__section-content" id={sectionId}>
|
|
87
88
|
{children}
|
|
88
89
|
</div>
|
|
89
90
|
</div>
|
|
@@ -2,6 +2,65 @@ import React, { forwardRef } from 'react';
|
|
|
2
2
|
import { Icon } from '../Icon/Icon';
|
|
3
3
|
import { FooterSocialLinkProps } from '../../lib/types/components';
|
|
4
4
|
|
|
5
|
+
// ─── Platform Maps ───────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
const PLATFORM_ICON_MAP: Record<string, string> = {
|
|
8
|
+
facebook: 'FacebookLogo',
|
|
9
|
+
twitter: 'TwitterLogo',
|
|
10
|
+
instagram: 'InstagramLogo',
|
|
11
|
+
linkedin: 'LinkedinLogo',
|
|
12
|
+
youtube: 'YoutubeLogo',
|
|
13
|
+
github: 'GithubLogo',
|
|
14
|
+
discord: 'DiscordLogo',
|
|
15
|
+
tiktok: 'TiktokLogo',
|
|
16
|
+
pinterest: 'PinterestLogo',
|
|
17
|
+
snapchat: 'SnapchatLogo',
|
|
18
|
+
whatsapp: 'WhatsappLogo',
|
|
19
|
+
telegram: 'TelegramLogo',
|
|
20
|
+
reddit: 'RedditLogo',
|
|
21
|
+
twitch: 'TwitchLogo',
|
|
22
|
+
spotify: 'SpotifyLogo',
|
|
23
|
+
dribbble: 'DribbbleLogo',
|
|
24
|
+
behance: 'BehanceLogo',
|
|
25
|
+
medium: 'MediumLogo',
|
|
26
|
+
dev: 'DevToLogo',
|
|
27
|
+
codepen: 'CodepenLogo',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const PLATFORM_LABEL_MAP: Record<string, string> = {
|
|
31
|
+
facebook: 'Facebook',
|
|
32
|
+
twitter: 'Twitter',
|
|
33
|
+
instagram: 'Instagram',
|
|
34
|
+
linkedin: 'LinkedIn',
|
|
35
|
+
youtube: 'YouTube',
|
|
36
|
+
github: 'GitHub',
|
|
37
|
+
discord: 'Discord',
|
|
38
|
+
tiktok: 'TikTok',
|
|
39
|
+
pinterest: 'Pinterest',
|
|
40
|
+
snapchat: 'Snapchat',
|
|
41
|
+
whatsapp: 'WhatsApp',
|
|
42
|
+
telegram: 'Telegram',
|
|
43
|
+
reddit: 'Reddit',
|
|
44
|
+
twitch: 'Twitch',
|
|
45
|
+
spotify: 'Spotify',
|
|
46
|
+
dribbble: 'Dribbble',
|
|
47
|
+
behance: 'Behance',
|
|
48
|
+
medium: 'Medium',
|
|
49
|
+
dev: 'Dev.to',
|
|
50
|
+
codepen: 'CodePen',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// ─── Helpers ─────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
const getPlatformIcon = (platform: string) => {
|
|
56
|
+
const iconName = PLATFORM_ICON_MAP[platform];
|
|
57
|
+
return iconName ? <Icon name={iconName as any} /> : <Icon name="Link" />;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const getPlatformLabel = (platform: string): string => PLATFORM_LABEL_MAP[platform] || platform;
|
|
61
|
+
|
|
62
|
+
// ─── Component ───────────────────────────────────────────────────
|
|
63
|
+
|
|
5
64
|
/**
|
|
6
65
|
* FooterSocialLink component provides styled social media links with platform-specific icons.
|
|
7
66
|
*
|
|
@@ -26,64 +85,6 @@ export const FooterSocialLink = forwardRef<HTMLAnchorElement, FooterSocialLinkPr
|
|
|
26
85
|
},
|
|
27
86
|
ref
|
|
28
87
|
) => {
|
|
29
|
-
const getPlatformIcon = (platform: string) => {
|
|
30
|
-
const iconMap: Record<string, string> = {
|
|
31
|
-
facebook: 'FacebookLogo',
|
|
32
|
-
twitter: 'TwitterLogo',
|
|
33
|
-
instagram: 'InstagramLogo',
|
|
34
|
-
linkedin: 'LinkedinLogo',
|
|
35
|
-
youtube: 'YoutubeLogo',
|
|
36
|
-
github: 'GithubLogo',
|
|
37
|
-
discord: 'DiscordLogo',
|
|
38
|
-
tiktok: 'TiktokLogo',
|
|
39
|
-
pinterest: 'PinterestLogo',
|
|
40
|
-
snapchat: 'SnapchatLogo',
|
|
41
|
-
whatsapp: 'WhatsappLogo',
|
|
42
|
-
telegram: 'TelegramLogo',
|
|
43
|
-
reddit: 'RedditLogo',
|
|
44
|
-
twitch: 'TwitchLogo',
|
|
45
|
-
spotify: 'SpotifyLogo',
|
|
46
|
-
dribbble: 'DribbbleLogo',
|
|
47
|
-
behance: 'BehanceLogo',
|
|
48
|
-
medium: 'MediumLogo',
|
|
49
|
-
dev: 'DevToLogo',
|
|
50
|
-
codepen: 'CodepenLogo',
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const iconName = iconMap[platform];
|
|
54
|
-
if (iconName) {
|
|
55
|
-
return <Icon name={iconName as any} />;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return <Icon name="Link" />;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const getPlatformLabel = (platform: string) => {
|
|
62
|
-
const labels: Record<string, string> = {
|
|
63
|
-
facebook: 'Facebook',
|
|
64
|
-
twitter: 'Twitter',
|
|
65
|
-
instagram: 'Instagram',
|
|
66
|
-
linkedin: 'LinkedIn',
|
|
67
|
-
youtube: 'YouTube',
|
|
68
|
-
github: 'GitHub',
|
|
69
|
-
discord: 'Discord',
|
|
70
|
-
tiktok: 'TikTok',
|
|
71
|
-
pinterest: 'Pinterest',
|
|
72
|
-
snapchat: 'Snapchat',
|
|
73
|
-
whatsapp: 'WhatsApp',
|
|
74
|
-
telegram: 'Telegram',
|
|
75
|
-
reddit: 'Reddit',
|
|
76
|
-
twitch: 'Twitch',
|
|
77
|
-
spotify: 'Spotify',
|
|
78
|
-
dribbble: 'Dribbble',
|
|
79
|
-
behance: 'Behance',
|
|
80
|
-
medium: 'Medium',
|
|
81
|
-
dev: 'Dev.to',
|
|
82
|
-
codepen: 'CodePen',
|
|
83
|
-
};
|
|
84
|
-
return labels[platform] || platform;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
88
|
const linkClass = [
|
|
88
89
|
'c-footer__social-link',
|
|
89
90
|
`c-footer__social-link--${platform}`,
|
|
@@ -110,7 +110,7 @@ import { Footer, FooterSection, FooterLink } from '@shohojdhara/atomix';
|
|
|
110
110
|
| `active` | `boolean` | `false` | Whether link is active |
|
|
111
111
|
| `disabled` | `boolean` | `false` | Whether link is disabled |
|
|
112
112
|
| `onClick` | `(event: MouseEvent) => void` | - | Link click handler |
|
|
113
|
-
| `
|
|
113
|
+
| `linkComponent` | `React.ElementType` | - | Custom link component (e.g., React Router Link) |
|
|
114
114
|
|
|
115
115
|
### Social Link Configuration
|
|
116
116
|
|
|
@@ -12,21 +12,35 @@ export interface HeroTitleProps extends React.HTMLAttributes<HTMLHeadingElement>
|
|
|
12
12
|
const HeroTitle = ({ children, className, level = 'h1', ...props }: HeroTitleProps) => {
|
|
13
13
|
const Tag = level as any;
|
|
14
14
|
return (
|
|
15
|
-
<Tag
|
|
15
|
+
<Tag
|
|
16
|
+
className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${className || ''}`.trim()}
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
16
19
|
{children}
|
|
17
20
|
</Tag>
|
|
18
21
|
);
|
|
19
22
|
};
|
|
20
23
|
|
|
21
|
-
const HeroSubtitle = ({
|
|
24
|
+
const HeroSubtitle = ({
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: React.HTMLAttributes<HTMLParagraphElement>) => {
|
|
22
29
|
return (
|
|
23
|
-
<p
|
|
30
|
+
<p
|
|
31
|
+
className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${className || ''}`.trim()}
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
24
34
|
{children}
|
|
25
35
|
</p>
|
|
26
36
|
);
|
|
27
37
|
};
|
|
28
38
|
|
|
29
|
-
const HeroText = ({
|
|
39
|
+
const HeroText = ({
|
|
40
|
+
children,
|
|
41
|
+
className,
|
|
42
|
+
...props
|
|
43
|
+
}: React.HTMLAttributes<HTMLParagraphElement>) => {
|
|
30
44
|
return (
|
|
31
45
|
<p className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${className || ''}`.trim()} {...props}>
|
|
32
46
|
{children}
|
|
@@ -36,7 +50,10 @@ const HeroText = ({ children, className, ...props }: React.HTMLAttributes<HTMLPa
|
|
|
36
50
|
|
|
37
51
|
const HeroActions = ({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) => {
|
|
38
52
|
return (
|
|
39
|
-
<div
|
|
53
|
+
<div
|
|
54
|
+
className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${className || ''}`.trim()}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
40
57
|
{children}
|
|
41
58
|
</div>
|
|
42
59
|
);
|
|
@@ -46,34 +63,32 @@ export interface HeroContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
46
63
|
glass?: AtomixGlassProps | boolean;
|
|
47
64
|
}
|
|
48
65
|
|
|
66
|
+
const HERO_DEFAULT_GLASS_PROPS = {
|
|
67
|
+
displacementScale: 60,
|
|
68
|
+
blurAmount: 3,
|
|
69
|
+
saturation: 180,
|
|
70
|
+
aberrationIntensity: 0,
|
|
71
|
+
borderRadius: 8,
|
|
72
|
+
overLight: false as const,
|
|
73
|
+
mode: 'standard' as const,
|
|
74
|
+
};
|
|
75
|
+
|
|
49
76
|
const HeroContent = ({ children, className, style, glass, ...props }: HeroContentProps) => {
|
|
50
77
|
const contentClass = `${HERO.SELECTORS.CONTENT.replace('.', '')} ${className || ''}`.trim();
|
|
51
78
|
|
|
52
|
-
|
|
53
|
-
const glassProps = typeof glass === 'boolean' ? {
|
|
54
|
-
displacementScale: 60,
|
|
55
|
-
blurAmount: 3,
|
|
56
|
-
saturation: 180,
|
|
57
|
-
aberrationIntensity: 0,
|
|
58
|
-
borderRadius: 8,
|
|
59
|
-
overLight: false,
|
|
60
|
-
mode: 'standard' as const,
|
|
61
|
-
} : glass;
|
|
79
|
+
const innerContent = glass ? <div className="u-p-4">{children}</div> : children;
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
81
|
+
const wrappedContent = glass
|
|
82
|
+
? (() => {
|
|
83
|
+
const glassProps =
|
|
84
|
+
glass === true ? HERO_DEFAULT_GLASS_PROPS : { ...HERO_DEFAULT_GLASS_PROPS, ...glass };
|
|
85
|
+
return <AtomixGlass {...glassProps}>{innerContent}</AtomixGlass>;
|
|
86
|
+
})()
|
|
87
|
+
: innerContent;
|
|
73
88
|
|
|
74
89
|
return (
|
|
75
90
|
<div className={contentClass} style={style} {...props}>
|
|
76
|
-
{
|
|
91
|
+
{wrappedContent}
|
|
77
92
|
</div>
|
|
78
93
|
);
|
|
79
94
|
};
|
|
@@ -106,7 +121,13 @@ const HeroImage = ({
|
|
|
106
121
|
);
|
|
107
122
|
};
|
|
108
123
|
|
|
109
|
-
const HeroBackground = ({
|
|
124
|
+
const HeroBackground = ({
|
|
125
|
+
className,
|
|
126
|
+
style,
|
|
127
|
+
src,
|
|
128
|
+
children,
|
|
129
|
+
...props
|
|
130
|
+
}: React.HTMLAttributes<HTMLDivElement> & { src?: string }) => {
|
|
110
131
|
return (
|
|
111
132
|
<div
|
|
112
133
|
className={`${HERO.SELECTORS.BG.replace('.', '')} ${className || ''}`.trim()}
|
|
@@ -114,11 +135,7 @@ const HeroBackground = ({ className, style, src, children, ...props }: React.HTM
|
|
|
114
135
|
{...props}
|
|
115
136
|
>
|
|
116
137
|
{src && (
|
|
117
|
-
|
|
118
|
-
src={src}
|
|
119
|
-
alt="Background"
|
|
120
|
-
className={HERO.SELECTORS.BG_IMAGE.replace('.', '')}
|
|
121
|
-
/>
|
|
138
|
+
<img src={src} alt="Background" className={HERO.SELECTORS.BG_IMAGE.replace('.', '')} />
|
|
122
139
|
)}
|
|
123
140
|
{children}
|
|
124
141
|
</div>
|
|
@@ -332,11 +349,9 @@ export const Hero: React.FC<HeroProps> & {
|
|
|
332
349
|
};
|
|
333
350
|
|
|
334
351
|
const renderContent = () => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
style={parts?.content?.style}
|
|
339
|
-
>
|
|
352
|
+
// Build inner content elements ONCE — no duplication
|
|
353
|
+
const innerElements = (
|
|
354
|
+
<>
|
|
340
355
|
{subtitle && (
|
|
341
356
|
<p
|
|
342
357
|
className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
|
|
@@ -367,115 +382,30 @@ export const Hero: React.FC<HeroProps> & {
|
|
|
367
382
|
{actions}
|
|
368
383
|
</div>
|
|
369
384
|
)}
|
|
370
|
-
|
|
385
|
+
</>
|
|
371
386
|
);
|
|
372
387
|
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (glass === true) {
|
|
382
|
-
return (
|
|
383
|
-
<div
|
|
384
|
-
className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
|
|
385
|
-
style={parts?.content?.style}
|
|
386
|
-
>
|
|
387
|
-
<AtomixGlass
|
|
388
|
-
displacementScale={60}
|
|
389
|
-
blurAmount={3}
|
|
390
|
-
saturation={180}
|
|
391
|
-
aberrationIntensity={0}
|
|
392
|
-
borderRadius={8}
|
|
393
|
-
overLight={false}
|
|
394
|
-
mode="standard"
|
|
395
|
-
>
|
|
396
|
-
<div className="u-p-4">
|
|
397
|
-
{subtitle && (
|
|
398
|
-
<p
|
|
399
|
-
className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
|
|
400
|
-
style={parts?.subtitle?.style}
|
|
401
|
-
>
|
|
402
|
-
{subtitle}
|
|
403
|
-
</p>
|
|
404
|
-
)}
|
|
405
|
-
<HeadingTag
|
|
406
|
-
className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${parts?.title?.className || ''}`.trim()}
|
|
407
|
-
style={parts?.title?.style}
|
|
408
|
-
>
|
|
409
|
-
{title}
|
|
410
|
-
</HeadingTag>
|
|
411
|
-
{text && (
|
|
412
|
-
<p
|
|
413
|
-
className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${parts?.text?.className || ''}`.trim()}
|
|
414
|
-
style={parts?.text?.style}
|
|
415
|
-
>
|
|
416
|
-
{text}
|
|
417
|
-
</p>
|
|
418
|
-
)}
|
|
419
|
-
{actions && (
|
|
420
|
-
<div
|
|
421
|
-
className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${parts?.actions?.className || ''}`.trim()}
|
|
422
|
-
style={parts?.actions?.style}
|
|
423
|
-
>
|
|
424
|
-
{actions}
|
|
425
|
-
</div>
|
|
426
|
-
)}
|
|
427
|
-
</div>
|
|
388
|
+
// Conditionally wrap with AtomixGlass using the standard glass prop pattern
|
|
389
|
+
const contentBody = glass
|
|
390
|
+
? (() => {
|
|
391
|
+
const glassProps =
|
|
392
|
+
glass === true ? HERO_DEFAULT_GLASS_PROPS : { ...HERO_DEFAULT_GLASS_PROPS, ...glass };
|
|
393
|
+
return (
|
|
394
|
+
<AtomixGlass {...glassProps}>
|
|
395
|
+
<div className="u-p-4">{innerElements}</div>
|
|
428
396
|
</AtomixGlass>
|
|
429
|
-
|
|
430
|
-
)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
// If glass is an object, use provided glass props
|
|
434
|
-
return (
|
|
435
|
-
<div
|
|
436
|
-
className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
|
|
437
|
-
style={parts?.content?.style}
|
|
438
|
-
>
|
|
439
|
-
<AtomixGlass {...glass}>
|
|
440
|
-
<div className="u-p-4">
|
|
441
|
-
{subtitle && (
|
|
442
|
-
<p
|
|
443
|
-
className={`${HERO.SELECTORS.SUBTITLE.replace('.', '')} ${parts?.subtitle?.className || ''}`.trim()}
|
|
444
|
-
style={parts?.subtitle?.style}
|
|
445
|
-
>
|
|
446
|
-
{subtitle}
|
|
447
|
-
</p>
|
|
448
|
-
)}
|
|
449
|
-
<HeadingTag
|
|
450
|
-
className={`${HERO.SELECTORS.TITLE.replace('.', '')} ${parts?.title?.className || ''}`.trim()}
|
|
451
|
-
style={parts?.title?.style}
|
|
452
|
-
>
|
|
453
|
-
{title}
|
|
454
|
-
</HeadingTag>
|
|
455
|
-
{text && (
|
|
456
|
-
<p
|
|
457
|
-
className={`${HERO.SELECTORS.TEXT.replace('.', '')} ${parts?.text?.className || ''}`.trim()}
|
|
458
|
-
style={parts?.text?.style}
|
|
459
|
-
>
|
|
460
|
-
{text}
|
|
461
|
-
</p>
|
|
462
|
-
)}
|
|
463
|
-
{actions && (
|
|
464
|
-
<div
|
|
465
|
-
className={`${HERO.SELECTORS.ACTIONS.replace('.', '')} ${parts?.actions?.className || ''}`.trim()}
|
|
466
|
-
style={parts?.actions?.style}
|
|
467
|
-
>
|
|
468
|
-
{actions}
|
|
469
|
-
</div>
|
|
470
|
-
)}
|
|
471
|
-
</div>
|
|
472
|
-
</AtomixGlass>
|
|
473
|
-
</div>
|
|
474
|
-
);
|
|
475
|
-
}
|
|
397
|
+
);
|
|
398
|
+
})()
|
|
399
|
+
: innerElements;
|
|
476
400
|
|
|
477
|
-
|
|
478
|
-
|
|
401
|
+
return (
|
|
402
|
+
<div
|
|
403
|
+
className={`${HERO.SELECTORS.CONTENT.replace('.', '')} ${parts?.content?.className || ''}`.trim()}
|
|
404
|
+
style={parts?.content?.style}
|
|
405
|
+
>
|
|
406
|
+
{contentBody}
|
|
407
|
+
</div>
|
|
408
|
+
);
|
|
479
409
|
};
|
|
480
410
|
|
|
481
411
|
const renderForegroundImage = () => {
|
|
@@ -86,7 +86,7 @@ export const MegaMenuColumn = forwardRef<HTMLDivElement, MegaMenuColumnProps>(
|
|
|
86
86
|
MegaMenuColumn.displayName = 'MegaMenuColumn';
|
|
87
87
|
|
|
88
88
|
export const MegaMenuLink = forwardRef<HTMLAnchorElement, MegaMenuLinkProps>(
|
|
89
|
-
({ href, children, className = '', disabled = false, onClick }, ref) => {
|
|
89
|
+
({ href, target, linkComponent, children, className = '', disabled = false, onClick }, ref) => {
|
|
90
90
|
const handleClick = (e: React.MouseEvent) => {
|
|
91
91
|
if (disabled) {
|
|
92
92
|
e.preventDefault();
|
|
@@ -98,17 +98,22 @@ export const MegaMenuLink = forwardRef<HTMLAnchorElement, MegaMenuLinkProps>(
|
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
101
|
+
const linkProps = {
|
|
102
|
+
ref,
|
|
103
|
+
href,
|
|
104
|
+
to: href,
|
|
105
|
+
target,
|
|
106
|
+
className: `c-menu__subitem-link ${disabled ? 'is-disabled' : ''} ${className}`,
|
|
107
|
+
onClick: handleClick,
|
|
108
|
+
'aria-disabled': disabled,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (linkComponent) {
|
|
112
|
+
const Component = linkComponent as React.ComponentType<any>;
|
|
113
|
+
return <Component {...linkProps}>{children}</Component>;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return <a {...linkProps}>{children}</a>;
|
|
112
117
|
}
|
|
113
118
|
);
|
|
114
119
|
|
|
@@ -39,7 +39,17 @@ interface MenuDividerProps {
|
|
|
39
39
|
|
|
40
40
|
export const MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(
|
|
41
41
|
(
|
|
42
|
-
{
|
|
42
|
+
{
|
|
43
|
+
children,
|
|
44
|
+
href = '#',
|
|
45
|
+
target,
|
|
46
|
+
linkComponent,
|
|
47
|
+
icon,
|
|
48
|
+
active = false,
|
|
49
|
+
disabled = false,
|
|
50
|
+
onClick,
|
|
51
|
+
className = '',
|
|
52
|
+
},
|
|
43
53
|
ref
|
|
44
54
|
) => {
|
|
45
55
|
const handleClick = (e: React.MouseEvent) => {
|
|
@@ -55,31 +65,46 @@ export const MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(
|
|
|
55
65
|
|
|
56
66
|
const itemClass = `c-menu__item ${active ? 'is-active' : ''} ${disabled ? 'is-disabled' : ''} ${className}`;
|
|
57
67
|
|
|
68
|
+
const linkProps = {
|
|
69
|
+
href,
|
|
70
|
+
to: href,
|
|
71
|
+
target,
|
|
72
|
+
className: 'c-menu__link',
|
|
73
|
+
onClick: handleClick,
|
|
74
|
+
'aria-disabled': disabled,
|
|
75
|
+
'aria-current': (active ? 'page' : undefined) as React.AriaAttributes['aria-current'],
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const content = (
|
|
79
|
+
<>
|
|
80
|
+
{icon &&
|
|
81
|
+
(typeof icon === 'string' ? (
|
|
82
|
+
icon.startsWith('c-icon-') ? (
|
|
83
|
+
<Icon
|
|
84
|
+
name={mapIconName(icon.replace('c-icon-', ''))}
|
|
85
|
+
size="sm"
|
|
86
|
+
className="c-menu__icon"
|
|
87
|
+
/>
|
|
88
|
+
) : (
|
|
89
|
+
<i className={`c-menu__icon ${icon}`}>{typeof icon !== 'string' && icon}</i>
|
|
90
|
+
)
|
|
91
|
+
) : (
|
|
92
|
+
<span className="c-menu__icon">{icon}</span>
|
|
93
|
+
))}
|
|
94
|
+
{children}
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
|
|
58
98
|
return (
|
|
59
99
|
<li ref={ref} className={itemClass} role="menuitem">
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
(typeof icon === 'string' ? (
|
|
69
|
-
icon.startsWith('c-icon-') ? (
|
|
70
|
-
<Icon
|
|
71
|
-
name={mapIconName(icon.replace('c-icon-', ''))}
|
|
72
|
-
size="sm"
|
|
73
|
-
className="c-menu__icon"
|
|
74
|
-
/>
|
|
75
|
-
) : (
|
|
76
|
-
<i className={`c-menu__icon ${icon}`}>{typeof icon !== 'string' && icon}</i>
|
|
77
|
-
)
|
|
78
|
-
) : (
|
|
79
|
-
<span className="c-menu__icon">{icon}</span>
|
|
80
|
-
))}
|
|
81
|
-
{children}
|
|
82
|
-
</a>
|
|
100
|
+
{linkComponent ? (
|
|
101
|
+
(() => {
|
|
102
|
+
const Component = linkComponent as React.ComponentType<any>;
|
|
103
|
+
return <Component {...linkProps}>{content}</Component>;
|
|
104
|
+
})()
|
|
105
|
+
) : (
|
|
106
|
+
<a {...linkProps}>{content}</a>
|
|
107
|
+
)}
|
|
83
108
|
</li>
|
|
84
109
|
);
|
|
85
110
|
}
|