diff --git a/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx b/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx
index 7bbd289..adb6692 100644
--- a/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx
+++ b/src/components/cardStack/layouts/timelines/TimelinePhoneView.tsx
@@ -1,26 +1,63 @@
-import React, { useRef } from 'react';
-import { useCardAnimation, UseCardAnimationOptions } from '@/hooks/useCardAnimation';
+"use client";
-export interface TimelinePhoneViewItem {
- [key: string]: any;
+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 PhoneFrameProps {
+ imageSrc?: string;
+ videoSrc?: string;
+ imageAlt?: string;
+ videoAriaLabel?: string;
+ phoneRef: (el: HTMLDivElement | null) => void;
+ className?: string;
}
-export interface TimelinePhoneViewProps {
- children: React.ReactNode;
+const PhoneFrame = memo(({
+ imageSrc,
+ videoSrc,
+ imageAlt,
+ videoAriaLabel,
+ phoneRef,
+ className = "",
+}: PhoneFrameProps) => (
+
+
+
+));
+
+PhoneFrame.displayName = "PhoneFrame";
+
+interface TimelinePhoneViewProps {
+ items: TimelinePhoneViewItem[];
showTextBox?: boolean;
showDivider?: boolean;
- title?: string;
- titleSegments?: Array<{ type: 'text'; content: string } | { type: 'image'; src: string; alt?: string }>;
- description?: string;
+ title: string;
+ titleSegments?: TitleSegment[];
+ description: string;
tag?: string;
- tagIcon?: any;
- tagAnimation?: string;
- buttons?: Array<{ text: string; onClick?: () => void; href?: string }>;
- buttonAnimation?: string;
- textboxLayout?: string;
- animationType?: string;
- useInvertedBackground?: boolean;
- ariaLabel?: string;
+ tagIcon?: LucideIcon;
+ tagAnimation?: ButtonAnimationType;
+ buttons?: ButtonConfig[];
+ buttonAnimation?: ButtonAnimationType;
+ animationType: CardAnimationType;
+ textboxLayout: TextboxLayout;
+ useInvertedBackground?: InvertedBackground;
className?: string;
containerClassName?: string;
textBoxClassName?: string;
@@ -30,28 +67,209 @@ export interface TimelinePhoneViewProps {
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;
}
-export const TimelinePhoneView: React.FC = ({
- children,
- containerClassName = '',
- ...props
-}) => {
- const containerRef = useRef(null);
- const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
-
- const animationOptions: UseCardAnimationOptions = {
- containerRef,
- itemRefs,
- };
-
- const { } = useCardAnimation(animationOptions);
+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 (
-
- {children}
-
+
+
+ {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);