당신에게 코드베이스에 기존 React 컴포넌트를 통합하는 작업이 주어졌습니다 코드베이스는 다음을 지원해야 합니다: - shadcn 프로젝트 구조 - Tailwind CSS - Typescript 그렇지 않은 경우, shadcn CLI를 통해 프로젝트를 설정하고 Tailwind 또는 Typescript를 설치하는 방법에 대한 지침을 제공하세요. 컴포넌트와 스타일의 기본 경로를 확인하세요. 컴포넌트의 기본 경로가 /components/ui가 아닌 경우, 이 폴더를 생성하는 것이 왜 중요한지에 대한 지침을 제공하세요 이 컴포넌트를 /components/ui 폴더에 복사-붙여넣기하세요: ```tsx mac-book-neo-hero.tsx "use client"; import * as React from "react"; import { useEffect, useRef, useState } from "react"; export type FrameSequenceStep = { from: number; to: number; color: string; num: string; total: string; icon?: React.ReactNode; title: string; description: string; label: string; }; export type FrameSequenceHeroProps = { frameCount: number; framePath: (i: number) => string; eagerCount?: number; scrollHeight?: string; brand?: React.ReactNode; navLinks?: { label: string; href: string }[]; ctaLabel?: string; ctaHref?: string; title: React.ReactNode; subtitle?: string; steps: FrameSequenceStep[]; className?: string; }; const cx = (...c: (string | false | null | undefined)[]) => c.filter(Boolean).join(" "); export function FrameSequenceHero({ frameCount, framePath, eagerCount = 140, scrollHeight = "600vh", brand, navLinks = [], ctaLabel, ctaHref = "#", title, subtitle, steps, className, }: FrameSequenceHeroProps) { const spacerRef = useRef(null); const cacheRef = useRef(new Array(frameCount)); const loadedRef = useRef(0); const targetFrameRef = useRef(0); const displayFrameRef = useRef(0); const lastShownRef = useRef(-1); const rafActiveRef = useRef(false); const [loadPct, setLoadPct] = useState(0); const [loaderDone, setLoaderDone] = useState(false); const [navScrolled, setNavScrolled] = useState(false); const [subHidden, setSubHidden] = useState(false); const [activeIdx, setActiveIdx] = useState(-1); const [progress, setProgress] = useState(0); const [stepLocal, setStepLocal] = useState(0); const [currentSrc, setCurrentSrc] = useState(() => framePath(1)); const showFrame = (i: number) => { if (i === lastShownRef.current) return; setCurrentSrc(framePath(i + 1)); lastShownRef.current = i; }; const loop = () => { if (rafActiveRef.current) return; rafActiveRef.current = true; const tick = () => { const diff = targetFrameRef.current - displayFrameRef.current; if (Math.abs(diff) { const eager = Math.min(eagerCount, frameCount); const loadOne = (i: number) => { const img = new Image(); img.decoding = "async"; img.src = framePath(i + 1); const onSettle = () => { loadedRef.current += 1; const pct = Math.round((loadedRef.current / frameCount) * 100); setLoadPct(pct); if (loadedRef.current === eager) { setLoaderDone(true); for (let j = eager; j { const spacer = spacerRef.current; if (!spacer) return; const total = spacer.offsetHeight - window.innerHeight; const p = Math.max(0, Math.min(1, window.scrollY / Math.max(1, total))); targetFrameRef.current = p * (frameCount - 1); loop(); setProgress(p); setNavScrolled(window.scrollY > 4); setSubHidden(window.scrollY > 8); let idx = -1; let local = 0; for (let i = 0; i = s.from && p { window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll); onScroll(); return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [steps, frameCount]); return ( {loadPct {brand} {navLinks.length > 0 && ( {https://t.co/tSkQpsSthN((l) => ( {l.label} ))} )}
이 클립은 OpenAI의 GPT-6 Astra로 생성되었습니다. 페이지의 프롬프트가 생성에 사용된 원문 그대로입니다.
예시는 GPT-6 Astra에서 다음 설정으로 생성되었습니다: 839:540 · 0:13 · Animation · Motion Graphics · 3D Render. 같은 설정을 사용하면 가장 비슷한 결과를 얻을 수 있습니다.
먼저 프롬프트를 그대로 복사한 뒤, 카메라·모션·조명 표현은 유지하고 피사체만 바꿔보세요. 영상 모델은 표현에 민감하므로 몇 차례 시도하는 것이 좋습니다.
물론입니다. 장면을 교체하거나 템포 표현, 화면 비율을 바꿔 프로젝트에 맞게 조정하세요.