Initial commit

This commit is contained in:
dk
2025-12-28 15:39:53 +02:00
commit 52d617df97
308 changed files with 62345 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
"use client";
import CardList from "@/components/cardStack/CardList";
import MediaContent from "@/components/shared/MediaContent";
import { cls, shouldUseInvertedText } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
title: string;
subtitle: string;
detail: string;
imageSrc?: string;
imageAlt?: string;
videoSrc?: string;
videoAriaLabel?: string;
};
type TeamGroup = {
id: string;
groupTitle: string;
members: TeamMember[];
};
interface TeamCardElevenProps {
groups: TeamGroup[];
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
cardClassName?: string;
textBoxClassName?: string;
textBoxTitleClassName?: string;
textBoxDescriptionClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
titleImageWrapperClassName?: string;
titleImageClassName?: string;
groupTitleClassName?: string;
memberClassName?: string;
memberImageClassName?: string;
memberTitleClassName?: string;
memberSubtitleClassName?: string;
memberDetailClassName?: string;
}
const TeamCardEleven = ({
groups,
animationType,
title,
titleSegments,
description,
tag,
tagIcon,
buttons,
textboxLayout,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
cardClassName = "",
textBoxClassName = "",
textBoxTitleClassName = "",
textBoxDescriptionClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
titleImageWrapperClassName = "",
titleImageClassName = "",
groupTitleClassName = "",
memberClassName = "",
memberImageClassName = "",
memberTitleClassName = "",
memberSubtitleClassName = "",
memberDetailClassName = "",
}: TeamCardElevenProps) => {
const theme = useTheme();
const shouldUseLightText = shouldUseInvertedText(useInvertedBackground, theme.cardStyle);
const renderMemberRow = (member: TeamMember) => (
<div
key={member.id}
className={cls(
"flex flex-col md:flex-row md:items-center gap-4 py-6",
memberClassName
)}
>
<div className="flex items-center gap-4 flex-1">
<div className={cls(
"relative h-14 w-auto md:h-16 aspect-square rounded-theme overflow-hidden shrink-0",
memberImageClassName
)}>
<MediaContent
imageSrc={member.imageSrc}
imageAlt={member.imageAlt || member.title}
videoSrc={member.videoSrc}
videoAriaLabel={member.videoAriaLabel}
imageClassName="w-full h-full object-cover"
/>
</div>
<div className="flex flex-col">
<p className={cls(
"text-lg md:text-xl font-medium",
shouldUseLightText ? "text-background" : "text-foreground",
memberTitleClassName
)}>
{member.title}
</p>
<p className={cls(
"text-base",
shouldUseLightText ? "text-background/60" : "text-foreground/60",
memberSubtitleClassName
)}>
{member.subtitle}
</p>
</div>
</div>
<p className={cls(
"text-base md:text-lg font-medium",
shouldUseLightText ? "text-background" : "text-foreground",
memberDetailClassName
)}>
{member.detail}
</p>
</div>
);
return (
<CardList
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
animationType={animationType}
useInvertedBackground={useInvertedBackground}
className={className}
containerClassName={containerClassName}
cardClassName={cardClassName}
titleClassName={textBoxTitleClassName}
descriptionClassName={textBoxDescriptionClassName}
textBoxClassName={textBoxClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
titleImageWrapperClassName={titleImageWrapperClassName}
titleImageClassName={titleImageClassName}
ariaLabel={ariaLabel}
>
{groups.map((group) => (
<div key={group.id} className="p-6 md:p-8">
<h3 className={cls(
"text-2xl md:text-3xl font-medium mb-2",
shouldUseLightText ? "text-background" : "text-foreground",
groupTitleClassName
)}>
{group.groupTitle}
</h3>
<div className="flex flex-col divide-y divide-accent/20 border-y border-accent/20">
{group.members.map(renderMemberRow)}
</div>
</div>
))}
</CardList>
);
};
TeamCardEleven.displayName = "TeamCardEleven";
export default TeamCardEleven;

View File

@@ -0,0 +1,142 @@
"use client";
import CardStackTextBox from "@/components/cardStack/CardStackTextBox";
import MediaContent from "@/components/shared/MediaContent";
import { useCardAnimation } from "@/components/cardStack/hooks/useCardAnimation";
import { cls } from "@/lib/utils";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
name: string;
role: string;
imageSrc?: string;
videoSrc?: string;
imageAlt?: string;
videoAriaLabel?: string;
};
interface TeamCardFiveProps {
team: TeamMember[];
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
ariaLabel?: string;
className?: string;
containerClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
textBoxClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
gridClassName?: string;
cardClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
nameClassName?: string;
roleClassName?: string;
}
const TeamCardFive = ({
team,
animationType,
title,
titleSegments,
description,
textboxLayout,
useInvertedBackground,
tag,
tagIcon,
buttons,
ariaLabel = "Team section",
className = "",
containerClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
textBoxClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
gridClassName = "",
cardClassName = "",
mediaWrapperClassName = "",
mediaClassName = "",
nameClassName = "",
roleClassName = "",
}: TeamCardFiveProps) => {
const { itemRefs } = useCardAnimation({ animationType, itemCount: team.length });
return (
<section
aria-label={ariaLabel}
className={cls("relative py-20", useInvertedBackground === "invertCard" ? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground" : "w-full", useInvertedBackground === "invertDefault" && "bg-foreground", className)}
>
<div className={cls("w-content-width mx-auto flex flex-col gap-8", containerClassName)}>
<CardStackTextBox
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
/>
<div className={cls("flex flex-row flex-wrap gap-y-6 md:gap-x-0 justify-center", gridClassName)}>
{team.map((member, index) => (
<div
key={member.id}
ref={(el) => { itemRefs.current[index] = el; }}
className={cls("relative flex flex-col items-center text-center w-[55%] md:w-[28%] -mx-[4%] md:-mx-[2%]", cardClassName)}
>
<div className={cls("relative card w-full aspect-square rounded-theme overflow-hidden p-2 mb-4", mediaWrapperClassName)}>
<MediaContent
imageSrc={member.imageSrc}
videoSrc={member.videoSrc}
imageAlt={member.imageAlt || member.name}
videoAriaLabel={member.videoAriaLabel || member.name}
imageClassName={cls("relative z-1 w-full h-full object-cover rounded-theme!", mediaClassName)}
/>
</div>
<h3 className={cls("relative z-1 w-8/10 text-2xl font-medium leading-tight truncate", (useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard") ? "text-background" : "text-foreground", nameClassName)}>
{member.name}
</h3>
<p className={cls("relative z-1 w-8/10 text-base leading-tight mt-1 truncate", (useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard") ? "text-background/75" : "text-foreground/75", roleClassName)}>
{member.role}
</p>
</div>
))}
</div>
</div>
</section>
);
};
TeamCardFive.displayName = "TeamCardFive";
export default TeamCardFive;

View File

@@ -0,0 +1,186 @@
"use client";
import { memo } from "react";
import AutoCarousel from "@/components/cardStack/layouts/carousels/AutoCarousel";
import MediaContent from "@/components/shared/MediaContent";
import { cls, shouldUseInvertedText } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { LucideIcon } from "lucide-react";
import type { CardAnimationType, ButtonConfig, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
name: string;
role: string;
imageSrc?: string;
videoSrc?: string;
imageAlt?: string;
videoAriaLabel?: string;
};
interface TeamCardFourProps {
team: TeamMember[];
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
speed?: number;
topMarqueeDirection?: "left" | "right";
ariaLabel?: string;
className?: string;
containerClassName?: string;
carouselClassName?: string;
bottomCarouselClassName?: string;
cardClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
nameClassName?: string;
roleClassName?: string;
textBoxClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
}
interface TeamCardProps {
member: TeamMember;
shouldUseLightText: boolean;
cardClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
nameClassName?: string;
roleClassName?: string;
}
const TeamCard = memo(({
member,
shouldUseLightText,
cardClassName = "",
mediaWrapperClassName = "",
mediaClassName = "",
nameClassName = "",
roleClassName = "",
}: TeamCardProps) => {
return (
<div className={cls("relative h-full card rounded-theme overflow-hidden min-h-0 flex items-center gap-8 p-4 pr-10 md:pr-16", cardClassName)}>
<div className={cls("relative h-40 md:h-60 w-auto aspect-square rounded-theme overflow-hidden flex-shrink-0", mediaWrapperClassName)}>
<MediaContent
imageSrc={member.imageSrc}
videoSrc={member.videoSrc}
imageAlt={member.imageAlt || member.name}
videoAriaLabel={member.videoAriaLabel || member.name}
imageClassName={cls("w-full h-full object-cover", mediaClassName)}
/>
</div>
<div className="relative z-1 flex flex-col gap-1 min-w-0 flex-1">
<h3 className={cls("text-3xl font-medium leading-tight", shouldUseLightText ? "text-background" : "text-foreground", nameClassName)}>
{member.name}
</h3>
<p className={cls("text-xl leading-tight", shouldUseLightText ? "text-background/75" : "text-foreground/75", roleClassName)}>
{member.role}
</p>
</div>
</div>
);
});
TeamCard.displayName = "TeamCard";
const TeamCardFour = ({
team,
animationType,
title,
titleSegments,
description,
textboxLayout,
useInvertedBackground,
tag,
tagIcon,
buttons,
speed = 40,
topMarqueeDirection = "left",
ariaLabel = "Team section",
className = "",
containerClassName = "",
carouselClassName = "",
bottomCarouselClassName = "",
cardClassName = "",
mediaWrapperClassName = "",
mediaClassName = "",
nameClassName = "",
roleClassName = "",
textBoxClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
}: TeamCardFourProps) => {
const theme = useTheme();
const shouldUseLightText = shouldUseInvertedText(useInvertedBackground, theme.cardStyle);
return (
<AutoCarousel
speed={speed}
uniformGridCustomHeightClasses="min-h-none"
animationType={animationType}
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
showTextBox={true}
dualMarquee={true}
topMarqueeDirection={topMarqueeDirection}
carouselClassName={carouselClassName}
bottomCarouselClassName={bottomCarouselClassName}
containerClassName={containerClassName}
className={className}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
ariaLabel={ariaLabel}
itemClassName="w-fit!"
>
{team.map((member, index) => (
<TeamCard
key={`${member.id}-${index}`}
member={member}
shouldUseLightText={shouldUseLightText}
cardClassName={cardClassName}
mediaWrapperClassName={mediaWrapperClassName}
mediaClassName={mediaClassName}
nameClassName={nameClassName}
roleClassName={roleClassName}
/>
))}
</AutoCarousel>
);
};
TeamCardFour.displayName = "TeamCardFour";
export default TeamCardFour;

View File

@@ -0,0 +1,185 @@
"use client";
import { memo } from "react";
import Image from "next/image";
import CardStack from "@/components/cardStack/CardStack";
import { cls } from "@/lib/utils";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, GridVariant, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
name: string;
role: string;
imageSrc: string;
imageAlt?: string;
};
interface TeamCardOneProps {
members: TeamMember[];
carouselMode?: "auto" | "buttons";
gridVariant: GridVariant;
uniformGridCustomHeightClasses?: string;
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
cardClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
gridClassName?: string;
carouselClassName?: string;
controlsClassName?: string;
textBoxClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
}
interface TeamMemberCardProps {
member: TeamMember;
cardClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
}
const TeamMemberCard = memo(({
member,
cardClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
}: TeamMemberCardProps) => {
return (
<div className={cls("relative h-full card rounded-theme-capped p-4", cardClassName)}>
<div className="relative z-1 w-full h-full rounded-theme-capped overflow-hidden">
<Image
src={member.imageSrc}
alt={member.imageAlt || member.name}
width={800}
height={800}
className={cls("w-full h-full object-cover ", imageClassName)}
unoptimized={member.imageSrc.startsWith('http') || member.imageSrc.startsWith('//')}
aria-hidden={member.imageAlt === ""}
/>
<div className={cls("!absolute z-1 bottom-4 left-4 right-4 card p-4 rounded-theme-capped flex items-center justify-between gap-3", overlayClassName)}>
<h3 className={cls("relative z-1 text-xl font-medium text-foreground leading-[1.1] truncate", nameClassName)}>
{member.name}
</h3>
<div className="min-w-0 max-w-full w-fit primary-button px-3 py-2 rounded-theme">
<p className={cls("text-sm text-background leading-[1.1] truncate", roleClassName)}>
{member.role}
</p>
</div>
</div>
</div>
</div>
);
});
TeamMemberCard.displayName = "TeamMemberCard";
const TeamCardOne = ({
members,
carouselMode = "buttons",
gridVariant,
uniformGridCustomHeightClasses = "min-h-95 2xl:min-h-105",
animationType,
title,
titleSegments,
description,
tag,
tagIcon,
buttons,
textboxLayout,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
cardClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
gridClassName = "",
carouselClassName = "",
controlsClassName = "",
textBoxClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
}: TeamCardOneProps) => {
return (
<CardStack
mode={carouselMode}
gridVariant={gridVariant}
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
animationType={animationType}
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
className={className}
containerClassName={containerClassName}
gridClassName={gridClassName}
carouselClassName={carouselClassName}
controlsClassName={controlsClassName}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
ariaLabel={ariaLabel}
>
{members.map((member, index) => (
<TeamMemberCard
key={`${member.id}-${index}`}
member={member}
cardClassName={cardClassName}
imageClassName={imageClassName}
overlayClassName={overlayClassName}
nameClassName={nameClassName}
roleClassName={roleClassName}
/>
))}
</CardStack>
);
};
TeamCardOne.displayName = "TeamCardOne";
export default TeamCardOne;

View File

@@ -0,0 +1,151 @@
"use client";
import { useState, useEffect } from "react";
import Image from "next/image";
import TextAnimation from "@/components/text/TextAnimation";
import { cls } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
imageSrc: string;
imageAlt: string;
};
interface TeamCardSevenProps {
team: TeamMember[];
title: string;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
circlesClassName?: string;
imagesContainerClassName?: string;
imageClassName?: string;
titleClassName?: string;
}
const TeamCardSeven = ({
team,
title,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
circlesClassName = "",
imagesContainerClassName = "",
imageClassName = "",
titleClassName = "",
}: TeamCardSevenProps) => {
const theme = useTheme();
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);
const getImageSize = (index: number, total: number): string => {
const isEven = total % 2 === 0;
const centerIndex = Math.floor(total / 2);
let distanceFromCenter: number;
if (isEven) {
const leftCenter = centerIndex - 1;
const rightCenter = centerIndex;
distanceFromCenter = Math.min(
Math.abs(index - leftCenter),
Math.abs(index - rightCenter)
);
} else {
distanceFromCenter = Math.abs(index - centerIndex);
}
if (distanceFromCenter === 0) return "w-35 h-auto md:w-17_5 aspect-square";
if (distanceFromCenter === 1) return "w-25 h-auto md:w-12_5 aspect-square";
if (distanceFromCenter === 2) return "w-10 h-auto md:w-7_5 aspect-square";
return "w-5 h-auto md:h-20 md:w-auto aspect-square";
};
const maxItems = isMobile ? 3 : 7;
const actualTeam = team.slice(0, 7);
const visibleTeam: TeamMember[] = isMobile && actualTeam.length > 3
? actualTeam.slice(
Math.floor((actualTeam.length - 3) / 2),
Math.floor((actualTeam.length - 3) / 2) + 3
)
: actualTeam.slice(0, maxItems);
return (
<section
className={cls(
"relative py-20 overflow-hidden",
useInvertedBackground === "invertCard"
? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground"
: "w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
aria-label={ariaLabel}
>
<div className={cls("w-content-width mx-auto flex flex-col items-center gap-10 h-[37.5rem] md:h-180", containerClassName)}>
<div className="relative w-full h-full flex flex-col items-center justify-center gap-8 md:gap-10" >
<div className="relative w-full flex justify-center items-center">
<div className={cls("absolute inset-0 flex justify-center items-center pointer-events-none", circlesClassName)}>
<div className="absolute! w-150 h-auto md:h-180 md:w-auto aspect-square rounded-theme card opacity-80 mask-fade-bottom" />
<div className="absolute! w-110 h-auto md:h-140 md:w-auto aspect-square rounded-theme card opacity-90 mask-fade-bottom" />
<div className="absolute! w-70 h-auto md:h-100 md:w-auto aspect-square rounded-theme card opacity-100 mask-fade-bottom" />
</div>
<div className={cls("relative flex items-center justify-center gap-3 md:gap-4", imagesContainerClassName)}>
{visibleTeam.map((member, index) => (
<div
key={member.id}
className={cls(
"relative card p-1 rounded-theme overflow-hidden shrink-0",
getImageSize(index, visibleTeam.length),
imageClassName
)}
>
<div className="absolute inset-1 z-1 rounded-theme overflow-hidden" >
<Image
src={member.imageSrc}
alt={member.imageAlt}
width={1000}
height={1000}
className="w-full h-full object-cover"
unoptimized={member.imageSrc.startsWith('http') || member.imageSrc.startsWith('//')}
/>
</div>
</div>
))}
</div>
</div>
<TextAnimation
type={theme.defaultTextAnimation}
text={title}
variant="trigger"
as="h2"
className={cls(
"text-5xl font-medium text-center",
(useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard") && "text-background",
titleClassName
)}
/>
</div>
</div>
</section>
);
};
TeamCardSeven.displayName = "TeamCardSeven";
export default TeamCardSeven;

View File

@@ -0,0 +1,191 @@
"use client";
import { memo } from "react";
import Image from "next/image";
import CardStack from "@/components/cardStack/CardStack";
import { cls } from "@/lib/utils";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, GridVariant, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
const MASK_GRADIENT = "linear-gradient(to bottom, transparent, black 60%)";
type TeamMember = {
id: string;
name: string;
role: string;
imageSrc: string;
imageAlt?: string;
};
interface TeamCardSixProps {
members: TeamMember[];
carouselMode?: "auto" | "buttons";
gridVariant: GridVariant;
uniformGridCustomHeightClasses?: string;
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
cardClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
gridClassName?: string;
carouselClassName?: string;
controlsClassName?: string;
textBoxClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
}
interface TeamMemberCardProps {
member: TeamMember;
cardClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
}
const TeamMemberCard = memo(({
member,
cardClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
}: TeamMemberCardProps) => {
return (
<div className={cls("relative h-full rounded-theme-capped", cardClassName)}>
<div className="relative w-full h-full rounded-theme-capped overflow-hidden">
<Image
src={member.imageSrc}
alt={member.imageAlt || member.name}
width={800}
height={800}
className={cls("w-full h-full object-cover", imageClassName)}
unoptimized={member.imageSrc.startsWith('http') || member.imageSrc.startsWith('//')}
aria-hidden={member.imageAlt === ""}
/>
<div className={cls("absolute z-10 bottom-4 left-4 right-4 p-4 flex flex-col gap-0 text-foreground", overlayClassName)}>
<h3 className={cls("text-2xl font-medium leading-tight truncate", nameClassName)}>
{member.name}
</h3>
<p className={cls("text-base leading-tight truncate", roleClassName)}>
{member.role}
</p>
</div>
<div
className="absolute z-0 backdrop-blur-xl opacity-100 w-full h-1/3 left-0 bottom-0"
style={{ maskImage: MASK_GRADIENT }}
aria-hidden="true"
/>
</div>
</div>
);
});
TeamMemberCard.displayName = "TeamMemberCard";
const TeamCardSix = ({
members,
carouselMode = "buttons",
gridVariant,
uniformGridCustomHeightClasses = "min-h-95 2xl:min-h-105",
animationType,
title,
titleSegments,
description,
tag,
tagIcon,
buttons,
textboxLayout,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
cardClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
gridClassName = "",
carouselClassName = "",
controlsClassName = "",
textBoxClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
}: TeamCardSixProps) => {
return (
<CardStack
mode={carouselMode}
gridVariant={gridVariant}
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
animationType={animationType}
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
className={className}
containerClassName={containerClassName}
gridClassName={gridClassName}
carouselClassName={carouselClassName}
controlsClassName={controlsClassName}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
ariaLabel={ariaLabel}
>
{members.map((member, index) => (
<TeamMemberCard
key={`${member.id}-${index}`}
member={member}
cardClassName={cardClassName}
imageClassName={imageClassName}
overlayClassName={overlayClassName}
nameClassName={nameClassName}
roleClassName={roleClassName}
/>
))}
</CardStack>
);
};
TeamCardSix.displayName = "TeamCardSix";
export default TeamCardSix;

View File

@@ -0,0 +1,138 @@
"use client";
import TextAnimation from "@/components/text/TextAnimation";
import MediaContent from "@/components/shared/MediaContent";
import Tag from "@/components/shared/Tag";
import { cls, shouldUseInvertedText } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { InvertedBackground } from "@/providers/themeProvider/config/constants";
type TeamMember = {
id: string;
name: string;
imageSrc?: string;
imageAlt?: string;
videoSrc?: string;
videoAriaLabel?: string;
};
interface TeamCardTenProps {
title: string;
tag: string;
members: TeamMember[];
memberVariant: "default" | "card";
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
titleClassName?: string;
tagClassName?: string;
membersContainerClassName?: string;
memberClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
nameClassName?: string;
}
const TeamCardTen = ({
title,
tag,
members,
memberVariant,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
titleClassName = "",
tagClassName = "",
membersContainerClassName = "",
memberClassName = "",
mediaWrapperClassName = "",
mediaClassName = "",
nameClassName = "",
}: TeamCardTenProps) => {
const theme = useTheme();
const shouldUseLightText = useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard";
const shouldMemberUseLightText = memberVariant === "card"
? shouldUseInvertedText("invertDefault", theme.cardStyle) || shouldUseInvertedText("invertCard", theme.cardStyle)
: shouldUseLightText;
return (
<section
aria-label={ariaLabel}
className={cls(
"relative py-20",
useInvertedBackground === "invertCard"
? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground"
: "w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
>
<div className={cls("w-content-width mx-auto flex flex-col gap-10", containerClassName)}>
<TextAnimation
type={theme.defaultTextAnimation}
text={title}
variant="words-trigger"
className={cls(
"text-3xl md:text-5xl font-medium leading-tight",
shouldUseLightText ? "text-background" : "text-foreground",
titleClassName
)}
/>
<div className="relative w-full h-px bg-accent/20" />
<div className="flex flex-col md:flex-row md:items-start gap-10 md:gap-8">
<div className="w-fit md:w-15" >
<Tag
text={tag}
useInvertedBackground={useInvertedBackground}
className={cls("min-w-0 max-w-full text-xl px-6", tagClassName)}
textClassName="truncate"
/>
</div>
<div className={cls(
"w-full grid gap-8 flex-1",
members.length === 1 && "grid-cols-1",
members.length >= 2 && "grid-cols-2",
membersContainerClassName
)}>
{members.map((member) => (
<div
key={member.id}
className={cls(
"flex flex-col gap-4",
memberVariant === "card" && "card rounded-theme-capped p-4",
memberClassName
)}
>
<div className={cls("relative aspect-[3/3.5] rounded-theme-capped overflow-hidden", mediaWrapperClassName)}>
<MediaContent
imageSrc={member.imageSrc}
imageAlt={member.imageAlt || member.name}
videoSrc={member.videoSrc}
videoAriaLabel={member.videoAriaLabel}
imageClassName={cls("w-full h-full object-cover", mediaClassName)}
/>
</div>
<p className={cls(
"text-xl md:text-3xl font-medium truncate",
shouldMemberUseLightText ? "text-background" : "text-foreground",
nameClassName
)}>
{member.name}
</p>
</div>
))}
</div>
</div>
</div>
</section>
);
};
TeamCardTen.displayName = "TeamCardTen";
export default TeamCardTen;

View File

@@ -0,0 +1,215 @@
"use client";
import { memo } from "react";
import Image from "next/image";
import CardStack from "@/components/cardStack/CardStack";
import { cls, shouldUseInvertedText } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type SocialLink = {
icon: LucideIcon;
url: string;
};
type TeamMember = {
id: string;
name: string;
role: string;
imageSrc: string;
imageAlt?: string;
socialLinks?: SocialLink[];
};
interface TeamCardThreeProps {
members: TeamMember[];
carouselMode?: "auto" | "buttons";
uniformGridCustomHeightClasses?: string;
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
cardClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
imageClassName?: string;
nameClassName?: string;
roleClassName?: string;
socialLinksClassName?: string;
socialIconClassName?: string;
gridClassName?: string;
carouselClassName?: string;
controlsClassName?: string;
textBoxClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
}
interface TeamMemberCardProps {
member: TeamMember;
shouldUseLightText: boolean;
cardClassName?: string;
imageClassName?: string;
nameClassName?: string;
roleClassName?: string;
socialLinksClassName?: string;
socialIconClassName?: string;
}
const TeamMemberCard = memo(({
member,
shouldUseLightText,
cardClassName = "",
imageClassName = "",
nameClassName = "",
roleClassName = "",
socialLinksClassName = "",
socialIconClassName = "",
}: TeamMemberCardProps) => {
return (
<div className={cls("card text-foreground rounded-theme-capped p-6 flex flex-col items-center text-center gap-4", cardClassName)}>
<div className="relative z-1 w-full aspect-square rounded-theme-capped overflow-hidden">
<Image
src={member.imageSrc}
alt={member.imageAlt || member.name}
width={800}
height={800}
className={cls("w-full h-full object-cover ", imageClassName)}
unoptimized={member.imageSrc.startsWith('http') || member.imageSrc.startsWith('//')}
aria-hidden={member.imageAlt === ""}
/>
</div>
<div className="relative z-1 flex flex-col gap-0">
<h3 className={cls("text-3xl font-medium leading-[1.15]", shouldUseLightText ? "text-background" : "text-foreground", nameClassName)}>
{member.name}
</h3>
<p className={cls("text-base leading-[1.15]", shouldUseLightText ? "text-background" : "text-foreground", roleClassName)}>
{member.role}
</p>
</div>
{member.socialLinks && member.socialLinks.length > 0 && (
<div className={cls("relative z-1 flex gap-3", socialLinksClassName)}>
{member.socialLinks.map((link, index) => (
<a
key={index}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className={cls("primary-button h-9 aspect-square w-auto flex items-center justify-center rounded-theme", socialIconClassName)}
>
<link.icon className="h-4/10 text-background" strokeWidth={1.5} />
</a>
))}
</div>
)}
</div>
);
});
TeamMemberCard.displayName = "TeamMemberCard";
const TeamCardThree = ({
members,
carouselMode = "buttons",
uniformGridCustomHeightClasses = "min-h-95 2xl:min-h-105",
animationType,
title,
titleSegments,
description,
tag,
tagIcon,
buttons,
textboxLayout,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
cardClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
imageClassName = "",
nameClassName = "",
roleClassName = "",
socialLinksClassName = "",
socialIconClassName = "",
gridClassName = "",
carouselClassName = "",
controlsClassName = "",
textBoxClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
}: TeamCardThreeProps) => {
const theme = useTheme();
const shouldUseLightText = shouldUseInvertedText(useInvertedBackground, theme.cardStyle);
return (
<CardStack
mode={carouselMode}
gridVariant="uniform-all-items-equal"
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
animationType={animationType}
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
className={className}
containerClassName={containerClassName}
gridClassName={gridClassName}
carouselClassName={carouselClassName}
controlsClassName={controlsClassName}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
ariaLabel={ariaLabel}
>
{members.map((member, index) => (
<TeamMemberCard
key={`${member.id}-${index}`}
member={member}
shouldUseLightText={shouldUseLightText}
cardClassName={cardClassName}
imageClassName={imageClassName}
nameClassName={nameClassName}
roleClassName={roleClassName}
socialLinksClassName={socialLinksClassName}
socialIconClassName={socialIconClassName}
/>
))}
</CardStack>
);
};
TeamCardThree.displayName = "TeamCardThree";
export default TeamCardThree;

View File

@@ -0,0 +1,227 @@
"use client";
import { memo } from "react";
import Image from "next/image";
import CardStack from "@/components/cardStack/CardStack";
import { cls } from "@/lib/utils";
import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, GridVariant, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
type SocialLink = {
icon: LucideIcon;
url: string;
};
type TeamMember = {
id: string;
name: string;
role: string;
description: string;
imageSrc: string;
imageAlt?: string;
socialLinks?: SocialLink[];
};
interface TeamCardTwoProps {
members: TeamMember[];
carouselMode?: "auto" | "buttons";
gridVariant: GridVariant;
uniformGridCustomHeightClasses?: string;
animationType: CardAnimationType;
title: string;
titleSegments?: TitleSegment[];
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: TextboxLayout;
useInvertedBackground: InvertedBackground;
ariaLabel?: string;
className?: string;
containerClassName?: string;
cardClassName?: string;
textBoxTitleClassName?: string;
textBoxTitleImageWrapperClassName?: string;
textBoxTitleImageClassName?: string;
textBoxDescriptionClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
memberDescriptionClassName?: string;
socialLinksClassName?: string;
socialIconClassName?: string;
gridClassName?: string;
carouselClassName?: string;
controlsClassName?: string;
textBoxClassName?: string;
textBoxTagClassName?: string;
textBoxButtonContainerClassName?: string;
textBoxButtonClassName?: string;
textBoxButtonTextClassName?: string;
}
interface TeamMemberCardProps {
member: TeamMember;
cardClassName?: string;
imageClassName?: string;
overlayClassName?: string;
nameClassName?: string;
roleClassName?: string;
memberDescriptionClassName?: string;
socialLinksClassName?: string;
socialIconClassName?: string;
}
const TeamMemberCard = memo(({
member,
cardClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
memberDescriptionClassName = "",
socialLinksClassName = "",
socialIconClassName = "",
}: TeamMemberCardProps) => {
return (
<div className={cls("relative h-full rounded-theme-capped overflow-hidden group", cardClassName)}>
<Image
src={member.imageSrc}
alt={member.imageAlt || member.name}
width={800}
height={800}
className={cls("relative z-1 w-full h-full object-cover", imageClassName)}
unoptimized={member.imageSrc.startsWith('http') || member.imageSrc.startsWith('//')}
aria-hidden={member.imageAlt === ""}
/>
<div className={cls("!absolute z-10 bottom-6 left-6 right-6 card p-6 flex flex-col gap-2 rounded-theme-capped", overlayClassName)}>
<div className="relative z-1 flex items-start justify-between">
<h3 className={cls("text-2xl font-medium text-foreground leading-[1.1] truncate", nameClassName)}>
{member.name}
</h3>
<div className="relative z-1 secondary-button px-3 py-1 rounded-theme" >
<p className={cls("text-xs text-foreground leading-[1.1] truncate", roleClassName)}>
{member.role}
</p>
</div>
</div>
<p className={cls("relative z-1 text-base text-foreground leading-[1.1]", memberDescriptionClassName)}>
{member.description}
</p>
{member.socialLinks && member.socialLinks.length > 0 && (
<div className={cls("relative z-1 flex gap-3 mt-1", socialLinksClassName)}>
{member.socialLinks.map((link, index) => (
<a
key={index}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className={cls("primary-button h-9 aspect-square w-auto flex items-center justify-center rounded-theme", socialIconClassName)}
>
<link.icon className="h-4/10 text-background" strokeWidth={1.5} />
</a>
))}
</div>
)}
</div>
</div>
);
});
TeamMemberCard.displayName = "TeamMemberCard";
const TeamCardTwo = ({
members,
carouselMode = "buttons",
gridVariant,
uniformGridCustomHeightClasses = "min-h-95 2xl:min-h-105",
animationType,
title,
titleSegments,
description,
tag,
tagIcon,
buttons,
textboxLayout,
useInvertedBackground,
ariaLabel = "Team section",
className = "",
containerClassName = "",
cardClassName = "",
textBoxTitleClassName = "",
textBoxTitleImageWrapperClassName = "",
textBoxTitleImageClassName = "",
textBoxDescriptionClassName = "",
imageClassName = "",
overlayClassName = "",
nameClassName = "",
roleClassName = "",
memberDescriptionClassName = "",
socialLinksClassName = "",
socialIconClassName = "",
gridClassName = "",
carouselClassName = "",
controlsClassName = "",
textBoxClassName = "",
textBoxTagClassName = "",
textBoxButtonContainerClassName = "",
textBoxButtonClassName = "",
textBoxButtonTextClassName = "",
}: TeamCardTwoProps) => {
return (
<CardStack
mode={carouselMode}
gridVariant={gridVariant}
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
animationType={animationType}
title={title}
titleSegments={titleSegments}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
className={className}
containerClassName={containerClassName}
gridClassName={gridClassName}
carouselClassName={carouselClassName}
controlsClassName={controlsClassName}
textBoxClassName={textBoxClassName}
titleClassName={textBoxTitleClassName}
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
titleImageClassName={textBoxTitleImageClassName}
descriptionClassName={textBoxDescriptionClassName}
tagClassName={textBoxTagClassName}
buttonContainerClassName={textBoxButtonContainerClassName}
buttonClassName={textBoxButtonClassName}
buttonTextClassName={textBoxButtonTextClassName}
ariaLabel={ariaLabel}
>
{members.map((member, index) => (
<TeamMemberCard
key={`${member.id}-${index}`}
member={member}
cardClassName={cardClassName}
imageClassName={imageClassName}
overlayClassName={overlayClassName}
nameClassName={nameClassName}
roleClassName={roleClassName}
memberDescriptionClassName={memberDescriptionClassName}
socialLinksClassName={socialLinksClassName}
socialIconClassName={socialIconClassName}
/>
))}
</CardStack>
);
};
TeamCardTwo.displayName = "TeamCardTwo";
export default TeamCardTwo;