From 0caddce5acc22b68107774bcf792e2a1214190fc Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:40:46 +0000 Subject: [PATCH] Switch to version 1: modified src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx --- .../layouts/timelines/TimelinePhoneView.tsx | 283 ++++++++++++++++-- 1 file changed, 264 insertions(+), 19 deletions(-) diff --git a/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx b/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx index 0b889cb..adb6692 100644 --- a/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx +++ b/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx @@ -1,30 +1,275 @@ -'use client'; +"use client"; -import React from 'react'; -import { - ButtonConfig, - ButtonAnimationType, - TitleSegment, - CardAnimationType, -} from '@/components/cardStack/types'; +import React, { memo } from "react"; +import MediaContent from "@/components/shared/MediaContent"; +import CardStackTextBox from "../../CardStackTextBox"; +import { usePhoneAnimations, type TimelinePhoneViewItem } from "../../hooks/usePhoneAnimations"; +import { useCardAnimation } from "../../hooks/useCardAnimation"; +import { cls } from "@/lib/utils"; +import type { LucideIcon } from "lucide-react"; +import type { ButtonConfig, ButtonAnimationType, TitleSegment, CardAnimationType } from "../../types"; +import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants"; -interface TimelinePhoneViewProps { - items: any[]; +interface PhoneFrameProps { + imageSrc?: string; + videoSrc?: string; + imageAlt?: string; + videoAriaLabel?: string; + phoneRef: (el: HTMLDivElement | null) => void; className?: string; } -const TimelinePhoneView: React.FC = ({ items, className = '' }) => { - const itemRefs = React.useRef<(HTMLElement | null)[]>([]); +const PhoneFrame = memo(({ + imageSrc, + videoSrc, + imageAlt, + videoAriaLabel, + phoneRef, + className = "", +}: PhoneFrameProps) => ( +
+ +
+)); + +PhoneFrame.displayName = "PhoneFrame"; + +interface TimelinePhoneViewProps { + items: TimelinePhoneViewItem[]; + showTextBox?: boolean; + showDivider?: boolean; + title: string; + titleSegments?: TitleSegment[]; + description: string; + tag?: string; + tagIcon?: LucideIcon; + tagAnimation?: ButtonAnimationType; + buttons?: ButtonConfig[]; + buttonAnimation?: ButtonAnimationType; + animationType: CardAnimationType; + textboxLayout: TextboxLayout; + useInvertedBackground?: InvertedBackground; + className?: string; + containerClassName?: string; + textBoxClassName?: string; + titleClassName?: string; + descriptionClassName?: string; + tagClassName?: string; + buttonContainerClassName?: string; + buttonClassName?: string; + buttonTextClassName?: string; + desktopContainerClassName?: string; + mobileContainerClassName?: string; + desktopContentClassName?: string; + desktopWrapperClassName?: string; + mobileWrapperClassName?: string; + phoneFrameClassName?: string; + mobilePhoneFrameClassName?: string; + titleImageWrapperClassName?: string; + titleImageClassName?: string; + ariaLabel?: string; +} + +const TimelinePhoneView = ({ + items, + showTextBox = true, + showDivider = false, + title, + titleSegments, + description, + tag, + tagIcon, + tagAnimation, + buttons, + buttonAnimation, + animationType, + textboxLayout, + useInvertedBackground, + className = "", + containerClassName = "", + textBoxClassName = "", + titleClassName = "", + descriptionClassName = "", + tagClassName = "", + buttonContainerClassName = "", + buttonClassName = "", + buttonTextClassName = "", + desktopContainerClassName = "", + mobileContainerClassName = "", + desktopContentClassName = "", + desktopWrapperClassName = "", + mobileWrapperClassName = "", + phoneFrameClassName = "", + mobilePhoneFrameClassName = "", + titleImageWrapperClassName = "", + titleImageClassName = "", + ariaLabel = "Timeline phone view section", +}: TimelinePhoneViewProps) => { + const { imageRefs, mobileImageRefs } = usePhoneAnimations(items); + const { itemRefs: contentRefs } = useCardAnimation({ + animationType, + itemCount: items.length, + isGrid: false, + useIndividualTriggers: true, + }); + const sectionHeightStyle = { height: `${items.length * 100}vh` }; return ( -
- {items.map((item, index) => ( -
{ if (el) itemRefs.current[index] = el; }} className="timeline-phone-item"> - {item.title} +
+
+ {showTextBox && ( +
+ +
+ )} + {showDivider && ( +
+ )} +
+
+ {items.map((item, index) => ( +
+
{ contentRefs.current[index] = el; }} + className={desktopWrapperClassName} + > + {item.content} +
+
+ ))} +
+
+ {items.map((item, itemIndex) => ( +
+
+ { + if (imageRefs.current) { + imageRefs.current[itemIndex * 2] = el; + } + }} + className={cls("w-20 2xl:w-25 h-[70vh]", phoneFrameClassName)} + /> + { + if (imageRefs.current) { + imageRefs.current[itemIndex * 2 + 1] = el; + } + }} + className={cls("w-20 2xl:w-25 h-[70vh]", phoneFrameClassName)} + /> +
+
+ ))} +
- ))} -
+
+ {items.map((item, itemIndex) => ( +
+
+ {item.content} +
+
+ { + if (mobileImageRefs.current) { + mobileImageRefs.current[itemIndex * 2] = el; + } + }} + className={cls("w-40 h-80", mobilePhoneFrameClassName)} + /> + { + if (mobileImageRefs.current) { + mobileImageRefs.current[itemIndex * 2 + 1] = el; + } + }} + className={cls("w-40 h-80", mobilePhoneFrameClassName)} + /> +
+
+ ))} +
+
+
); }; -export default TimelinePhoneView; +TimelinePhoneView.displayName = "TimelinePhoneView"; + +export default memo(TimelinePhoneView);