1+ import React from 'react' ;
2+
3+ // 🎨 임시 플레이스홀더 컴포넌트 (파일이 없을 경우 대비)
4+ const FallbackPlaceholder = ( { type = 'unknown' , data = null , currentStep = 0 , totalSteps = 0 } ) => (
5+ < div style = { {
6+ width : '100%' ,
7+ height : '100%' ,
8+ display : 'flex' ,
9+ flexDirection : 'column' ,
10+ alignItems : 'center' ,
11+ justifyContent : 'center' ,
12+ padding : '40px' ,
13+ backgroundColor : '#ffffff' ,
14+ border : '2px dashed #e2e8f0' ,
15+ borderRadius : '12px' ,
16+ textAlign : 'center' ,
17+ minHeight : '400px'
18+ } } >
19+ < div style = { { fontSize : '48px' , marginBottom : '20px' } } > 🚧</ div >
20+ < h3 style = { { margin : '0 0 12px 0' , color : '#1e293b' } } >
21+ { type } 애니메이션 개발 중
22+ </ h3 >
23+ < p style = { { margin : '0 0 20px 0' , color : '#64748b' } } >
24+ 곧 완성될 예정입니다!
25+ </ p >
26+ < div style = { {
27+ display : 'grid' ,
28+ gridTemplateColumns : 'repeat(auto-fit, minmax(120px, 1fr))' ,
29+ gap : '12px' ,
30+ width : '100%' ,
31+ maxWidth : '400px' ,
32+ marginTop : '20px'
33+ } } >
34+ < div style = { {
35+ padding : '12px' ,
36+ backgroundColor : '#f8fafc' ,
37+ borderRadius : '8px' ,
38+ border : '1px solid #e2e8f0'
39+ } } >
40+ < div style = { { fontSize : '11px' , color : '#64748b' , marginBottom : '4px' } } > 현재 단계</ div >
41+ < div style = { { fontSize : '14px' , color : '#8b5cf6' , fontWeight : 'bold' } } >
42+ { currentStep + 1 } / { totalSteps }
43+ </ div >
44+ </ div >
45+ < div style = { {
46+ padding : '12px' ,
47+ backgroundColor : '#f8fafc' ,
48+ borderRadius : '8px' ,
49+ border : '1px solid #e2e8f0'
50+ } } >
51+ < div style = { { fontSize : '11px' , color : '#64748b' , marginBottom : '4px' } } > 애니메이션</ div >
52+ < div style = { { fontSize : '14px' , color : '#8b5cf6' , fontWeight : 'bold' } } > { type } </ div >
53+ </ div >
54+ </ div >
55+ </ div >
56+ ) ;
57+
58+ // PlaceholderAnimation import 시도 (실패시 FallbackPlaceholder 사용)
59+ let PlaceholderAnimation ;
60+ try {
61+ PlaceholderAnimation = require ( './animations/PlaceholderAnimation' ) . default ;
62+ } catch ( error ) {
63+ console . warn ( 'PlaceholderAnimation 컴포넌트를 불러올 수 없습니다. Fallback을 사용합니다.' , error ) ;
64+ PlaceholderAnimation = FallbackPlaceholder ;
65+ }
66+
67+ /**
68+ * 🏭 AnimationFactory 클래스 (임시 개발 버전)
69+ * 실제 애니메이션 컴포넌트가 준비되면 교체될 예정
70+ */
71+ export class AnimationFactory {
72+ // 📋 애니메이션 타입 → 컴포넌트 매핑 테이블 (모두 플레이스홀더)
73+ static animations = {
74+ // 🔄 재귀 애니메이션들
75+ 'fibonacci-recursion' : PlaceholderAnimation ,
76+ 'factorial-recursion' : PlaceholderAnimation ,
77+ 'hanoi-tower' : PlaceholderAnimation ,
78+ 'recursion-tree' : PlaceholderAnimation ,
79+
80+ // 🔢 정렬 애니메이션들
81+ 'bubble-sort' : PlaceholderAnimation ,
82+ 'quick-sort' : PlaceholderAnimation ,
83+ 'merge-sort' : PlaceholderAnimation ,
84+ 'insertion-sort' : PlaceholderAnimation ,
85+ 'selection-sort' : PlaceholderAnimation ,
86+ 'heap-sort' : PlaceholderAnimation ,
87+
88+ // 📊 자료구조 애니메이션들
89+ 'array' : PlaceholderAnimation ,
90+ 'array-manipulation' : PlaceholderAnimation ,
91+ 'linked-list' : PlaceholderAnimation ,
92+ 'stack' : PlaceholderAnimation ,
93+ 'queue' : PlaceholderAnimation ,
94+ 'tree' : PlaceholderAnimation ,
95+ 'binary-tree' : PlaceholderAnimation ,
96+ 'bst' : PlaceholderAnimation ,
97+
98+ // 🔍 탐색 애니메이션들
99+ 'binary-search' : PlaceholderAnimation ,
100+ 'linear-search' : PlaceholderAnimation ,
101+ 'breadth-first-search' : PlaceholderAnimation ,
102+ 'depth-first-search' : PlaceholderAnimation ,
103+ 'bfs' : PlaceholderAnimation ,
104+ 'dfs' : PlaceholderAnimation ,
105+
106+ // 📝 변수 추적 애니메이션들
107+ 'variables' : PlaceholderAnimation ,
108+ 'variable-tracking' : PlaceholderAnimation ,
109+ 'basic-algorithm' : PlaceholderAnimation ,
110+
111+ // 🎯 기본 애니메이션 (fallback)
112+ 'default' : PlaceholderAnimation ,
113+ 'unknown' : PlaceholderAnimation
114+ } ;
115+
116+ // 📚 애니메이션 카테고리별 분류
117+ static categories = {
118+ recursion : [
119+ 'fibonacci-recursion' , 'factorial-recursion' ,
120+ 'hanoi-tower' , 'recursion-tree'
121+ ] ,
122+ sorting : [
123+ 'bubble-sort' , 'quick-sort' , 'merge-sort' ,
124+ 'insertion-sort' , 'selection-sort' , 'heap-sort'
125+ ] ,
126+ dataStructures : [
127+ 'array' , 'array-manipulation' , 'linked-list' ,
128+ 'stack' , 'queue' , 'tree' , 'binary-tree' , 'bst'
129+ ] ,
130+ searching : [
131+ 'binary-search' , 'linear-search' , 'breadth-first-search' ,
132+ 'depth-first-search' , 'bfs' , 'dfs'
133+ ] ,
134+ variables : [
135+ 'variables' , 'variable-tracking' , 'basic-algorithm'
136+ ]
137+ } ;
138+
139+ /**
140+ * 🎨 애니메이션 컴포넌트 생성
141+ * @param {string } type - 애니메이션 타입
142+ * @param {Object } props - 컴포넌트에 전달할 props
143+ * @returns {React.Component } 생성된 애니메이션 컴포넌트
144+ */
145+ static createAnimation ( type , props = { } ) {
146+ console . log ( `🏭 Creating animation: ${ type } (개발 중 버전)` ) ;
147+ console . log ( 'Props:' , props ) ;
148+
149+ // 1. 애니메이션 타입 정규화
150+ const normalizedType = this . normalizeType ( type ) ;
151+ console . log ( 'Normalized type:' , normalizedType ) ;
152+
153+ // 2. 컴포넌트 찾기 (현재는 모두 플레이스홀더)
154+ const AnimationComponent = this . animations [ normalizedType ] || PlaceholderAnimation ;
155+ console . log ( 'Selected component:' , AnimationComponent ) ;
156+
157+ // 3. 컴포넌트 생성 및 반환
158+ const element = React . createElement ( AnimationComponent , {
159+ key : `animation-${ normalizedType } -${ Date . now ( ) } ` ,
160+ type : normalizedType ,
161+ animationType : normalizedType ,
162+ ...props
163+ } ) ;
164+
165+ console . log ( 'Created element:' , element ) ;
166+ return element ;
167+ }
168+
169+ /**
170+ * 🔧 애니메이션 타입 정규화
171+ * @param {string } type - 원본 타입
172+ * @returns {string } 정규화된 타입
173+ */
174+ static normalizeType ( type ) {
175+ if ( ! type ) return 'unknown' ;
176+
177+ // 소문자로 변환하고 공백/언더스코어를 하이픈으로 변환
178+ return type . toLowerCase ( )
179+ . replace ( / [ \s _ ] + / g, '-' )
180+ . replace ( / [ ^ a - z 0 - 9 - ] / g, '' ) ;
181+ }
182+
183+ /**
184+ * 📋 사용 가능한 애니메이션 타입 목록
185+ * @returns {Array } 애니메이션 타입 배열
186+ */
187+ static getAvailableTypes ( ) {
188+ return Object . keys ( this . animations ) . filter ( type =>
189+ type !== 'unknown' && type !== 'default'
190+ ) ;
191+ }
192+
193+ /**
194+ * 🏷️ 애니메이션 타입이 유효한지 확인
195+ * @param {string } type - 확인할 타입
196+ * @returns {boolean } 유효성 여부
197+ */
198+ static isValidType ( type ) {
199+ const normalizedType = this . normalizeType ( type ) ;
200+ return normalizedType in this . animations ;
201+ }
202+
203+ /**
204+ * 📂 카테고리별 애니메이션 타입 조회
205+ * @param {string } category - 카테고리명
206+ * @returns {Array } 해당 카테고리의 애니메이션 타입들
207+ */
208+ static getTypesByCategory ( category ) {
209+ return this . categories [ category ] || [ ] ;
210+ }
211+
212+ /**
213+ * 🔍 애니메이션 타입의 카테고리 찾기
214+ * @param {string } type - 애니메이션 타입
215+ * @returns {string|null } 카테고리명
216+ */
217+ static getCategoryByType ( type ) {
218+ const normalizedType = this . normalizeType ( type ) ;
219+
220+ for ( const [ category , types ] of Object . entries ( this . categories ) ) {
221+ if ( types . includes ( normalizedType ) ) {
222+ return category ;
223+ }
224+ }
225+ return null ;
226+ }
227+
228+ /**
229+ * 🎯 새로운 애니메이션 타입 등록 (실제 컴포넌트 완성 후 사용)
230+ * @param {string } type - 애니메이션 타입
231+ * @param {React.Component } component - 컴포넌트
232+ * @param {string } category - 카테고리 (선택사항)
233+ */
234+ static registerAnimation ( type , component , category = null ) {
235+ const normalizedType = this . normalizeType ( type ) ;
236+
237+ // 애니메이션 등록
238+ this . animations [ normalizedType ] = component ;
239+
240+ // 카테고리에 추가 (지정된 경우)
241+ if ( category && this . categories [ category ] ) {
242+ if ( ! this . categories [ category ] . includes ( normalizedType ) ) {
243+ this . categories [ category ] . push ( normalizedType ) ;
244+ }
245+ }
246+
247+ console . log ( `✅ Registered animation: ${ normalizedType } ` ) ;
248+ }
249+
250+ /**
251+ * 📊 팩토리 상태 정보
252+ * @returns {Object } 팩토리 상태
253+ */
254+ static getFactoryInfo ( ) {
255+ return {
256+ version : 'development' ,
257+ mode : 'placeholder-only' ,
258+ totalAnimations : Object . keys ( this . animations ) . length ,
259+ categories : Object . keys ( this . categories ) ,
260+ availableTypes : this . getAvailableTypes ( ) ,
261+ categoriesInfo : Object . entries ( this . categories ) . map ( ( [ name , types ] ) => ( {
262+ name,
263+ count : types . length ,
264+ types
265+ } ) ) ,
266+ note : '모든 애니메이션이 개발 중입니다. 실제 컴포넌트는 곧 추가될 예정입니다.'
267+ } ;
268+ }
269+ }
270+
271+ // 🎨 편의 함수들
272+ export const createAnimation = ( type , props ) =>
273+ AnimationFactory . createAnimation ( type , props ) ;
274+
275+ export const isValidAnimationType = ( type ) =>
276+ AnimationFactory . isValidType ( type ) ;
277+
278+ export const getAnimationTypes = ( ) =>
279+ AnimationFactory . getAvailableTypes ( ) ;
280+
281+ export const registerAnimation = ( type , component , category ) =>
282+ AnimationFactory . registerAnimation ( type , component , category ) ;
283+
284+ // 기본 export
285+ export default AnimationFactory ;
286+
287+ // 개발 상태 로그
288+ console . log ( '🏭 AnimationFactory (개발 중) 로드됨:' , AnimationFactory . getFactoryInfo ( ) ) ;
0 commit comments