From e04f101ca301eb99b2a10d88a668fc8d66d2479e Mon Sep 17 00:00:00 2001 From: bender Date: Sun, 8 Mar 2026 21:29:32 +0000 Subject: [PATCH] Update src/components/sections/metrics/MetricCardEleven.tsx --- .../sections/metrics/MetricCardEleven.tsx | 308 +++--------------- 1 file changed, 46 insertions(+), 262 deletions(-) diff --git a/src/components/sections/metrics/MetricCardEleven.tsx b/src/components/sections/metrics/MetricCardEleven.tsx index e2a56f8..0be2607 100644 --- a/src/components/sections/metrics/MetricCardEleven.tsx +++ b/src/components/sections/metrics/MetricCardEleven.tsx @@ -1,274 +1,58 @@ -"use client"; +'use client'; -import { memo } from "react"; -import CardStackTextBox from "@/components/cardStack/CardStackTextBox"; -import MediaContent from "@/components/shared/MediaContent"; -import { useCardAnimation } from "@/components/cardStack/hooks/useCardAnimation"; -import { cls, shouldUseInvertedText } from "@/lib/utils"; -import { useTheme } from "@/providers/themeProvider/ThemeProvider"; -import type { LucideIcon } from "lucide-react"; -import type { ButtonConfig, CardAnimationType, TitleSegment, ButtonAnimationType } from "@/components/cardStack/types"; -import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants"; +import React, { useRef, useEffect } from 'react'; +import { useCardAnimation } from '@/hooks/useCardAnimation'; +import { cn } from '@/lib/utils'; -type MediaProps = - | { - imageSrc: string; - imageAlt?: string; - videoSrc?: never; - videoAriaLabel?: never; - } - | { - videoSrc: string; - videoAriaLabel?: string; - imageSrc?: never; - imageAlt?: never; - }; +export type CardAnimationType = 'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal'; -type Metric = MediaProps & { - id: string; - value: string; - title: string; - description: string; -}; - -interface MetricCardElevenProps { - metrics: Metric[]; - animationType: CardAnimationType; - title: string; - titleSegments?: TitleSegment[]; - description: string; - tag?: string; - tagIcon?: LucideIcon; - tagAnimation?: ButtonAnimationType; - buttons?: ButtonConfig[]; - buttonAnimation?: ButtonAnimationType; - textboxLayout: TextboxLayout; - useInvertedBackground: InvertedBackground; - ariaLabel?: string; - className?: string; - containerClassName?: string; - textBoxClassName?: string; - textBoxTitleClassName?: string; - textBoxTitleImageWrapperClassName?: string; - textBoxTitleImageClassName?: string; - textBoxDescriptionClassName?: string; - textBoxTagClassName?: string; - textBoxButtonContainerClassName?: string; - textBoxButtonClassName?: string; - textBoxButtonTextClassName?: string; - gridClassName?: string; - cardClassName?: string; - valueClassName?: string; - cardTitleClassName?: string; - cardDescriptionClassName?: string; - mediaCardClassName?: string; - mediaClassName?: string; +export interface MetricCardElevenProps { + metrics: Array<{ id: string; value: string; title: string; items: string[] }>; + animationType: CardAnimationType; + itemCount: number; + className?: string; } -interface MetricTextCardProps { - metric: Metric; - shouldUseLightText: boolean; - cardClassName?: string; - valueClassName?: string; - cardTitleClassName?: string; - cardDescriptionClassName?: string; -} +export const MetricCardEleven: React.FC = ({ + metrics, + animationType, + itemCount, + className, +}) => { + const containerRef = useRef(null); + const itemRefs = useRef<(HTMLDivElement | null)[]>([]); -interface MetricMediaCardProps { - metric: Metric; - mediaCardClassName?: string; - mediaClassName?: string; -} - -const MetricTextCard = memo(({ - metric, - shouldUseLightText, - cardClassName = "", - valueClassName = "", - cardTitleClassName = "", - cardDescriptionClassName = "", -}: MetricTextCardProps) => { - return ( -
-

- {metric.value} -

- -
-

- {metric.title} -

-
-

- {metric.description} -

-
-
- ); -}); - -MetricTextCard.displayName = "MetricTextCard"; - -const MetricMediaCard = memo(({ - metric, - mediaCardClassName = "", - mediaClassName = "", -}: MetricMediaCardProps) => { - return ( -
- -
- ); -}); - -MetricMediaCard.displayName = "MetricMediaCard"; - -const MetricCardEleven = ({ - metrics, + const { itemRefs: animationItemRefs } = useCardAnimation({ animationType, - title, - titleSegments, - description, - tag, - tagIcon, - tagAnimation, - buttons, - buttonAnimation, - textboxLayout, - useInvertedBackground, - ariaLabel = "Metrics section", - className = "", - containerClassName = "", - textBoxClassName = "", - textBoxTitleClassName = "", - textBoxTitleImageWrapperClassName = "", - textBoxTitleImageClassName = "", - textBoxDescriptionClassName = "", - textBoxTagClassName = "", - textBoxButtonContainerClassName = "", - textBoxButtonClassName = "", - textBoxButtonTextClassName = "", - gridClassName = "", - cardClassName = "", - valueClassName = "", - cardTitleClassName = "", - cardDescriptionClassName = "", - mediaCardClassName = "", - mediaClassName = "", -}: MetricCardElevenProps) => { - const theme = useTheme(); - const shouldUseLightText = shouldUseInvertedText(useInvertedBackground, theme.cardStyle); + itemCount, + }); - // Inner grid for each metric item (text + media side by side) - const innerGridCols = "grid-cols-2"; + useEffect(() => { + itemRefs.current = itemRefs.current.slice(0, itemCount); + }, [itemCount]); - const { itemRefs } = useCardAnimation({ animationType, itemCount: metrics.length }); - - return ( -
+ {metrics.map((metric, index) => ( +
{ + if (el) itemRefs.current[index] = el; + if (animationItemRefs && animationItemRefs[index]) animationItemRefs[index].current = el; + }} + className="metric-item" > -
- - -
- {metrics.map((metric, index) => { - const isLastItem = index === metrics.length - 1; - const isOddTotal = metrics.length % 2 !== 0; - const isSingleItem = metrics.length === 1; - const shouldSpanFull = isSingleItem || (isLastItem && isOddTotal); - // On mobile, even items (2nd, 4th, 6th - index 1, 3, 5) have media first - const isEvenItem = (index + 1) % 2 === 0; - - return ( -
{ itemRefs.current[index] = el; }} - className={cls( - "grid gap-4", - innerGridCols, - shouldSpanFull && "md:col-span-2" - )} - > - - -
- ); - })} -
-
-
- ); +
{metric.value}
+

{metric.title}

+
    + {metric.items.map((item, i) => ( +
  • {item}
  • + ))} +
+
+ ))} + + ); }; -MetricCardEleven.displayName = "MetricCardEleven"; - -export default MetricCardEleven; \ No newline at end of file +export default MetricCardEleven;