@hua-labs/motion-core 2.2.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -39
- package/dist/chunk-47QAGQLN.mjs +1057 -0
- package/dist/chunk-47QAGQLN.mjs.map +1 -0
- package/dist/chunk-LSIP7MB5.cjs +1090 -0
- package/dist/chunk-LSIP7MB5.cjs.map +1 -0
- package/dist/index.cjs +7532 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +834 -642
- package/dist/index.d.ts +834 -642
- package/dist/index.mjs +4393 -1744
- package/dist/index.mjs.map +1 -1
- package/dist/native.cjs +692 -0
- package/dist/native.cjs.map +1 -0
- package/dist/native.d.mts +177 -0
- package/dist/native.d.ts +177 -0
- package/dist/native.mjs +555 -0
- package/dist/native.mjs.map +1 -0
- package/dist/springPhysics-DLyZ4nbx.d.mts +687 -0
- package/dist/springPhysics-DLyZ4nbx.d.ts +687 -0
- package/package.json +31 -11
- package/dist/index.js +0 -4756
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, RefObject } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HUA Motion Core - 의존성 제로 모션 엔진
|
|
6
|
+
*
|
|
7
|
+
* 순수 JavaScript로 구현된 고성능 모션 엔진
|
|
8
|
+
* GPU 가속, 레이어 분리, 성능 최적화 포함
|
|
9
|
+
*/
|
|
10
|
+
interface MotionFrame {
|
|
11
|
+
progress: number;
|
|
12
|
+
properties: {
|
|
13
|
+
opacity?: number;
|
|
14
|
+
transform?: string;
|
|
15
|
+
scale?: number;
|
|
16
|
+
translateX?: number;
|
|
17
|
+
translateY?: number;
|
|
18
|
+
rotate?: number;
|
|
19
|
+
rotateX?: number;
|
|
20
|
+
rotateY?: number;
|
|
21
|
+
rotateZ?: number;
|
|
22
|
+
skewX?: number;
|
|
23
|
+
skewY?: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
interface MotionOptions {
|
|
27
|
+
duration: number;
|
|
28
|
+
easing: (t: number) => number;
|
|
29
|
+
delay?: number;
|
|
30
|
+
direction?: 'forward' | 'reverse' | 'alternate';
|
|
31
|
+
iterations?: number;
|
|
32
|
+
fill?: 'none' | 'forwards' | 'backwards' | 'both';
|
|
33
|
+
onStart?: () => void;
|
|
34
|
+
onUpdate?: (progress: number) => void;
|
|
35
|
+
onComplete?: () => void;
|
|
36
|
+
onCancel?: () => void;
|
|
37
|
+
}
|
|
38
|
+
interface Motion {
|
|
39
|
+
id: string;
|
|
40
|
+
element: HTMLElement;
|
|
41
|
+
isRunning: boolean;
|
|
42
|
+
isPaused: boolean;
|
|
43
|
+
currentProgress: number;
|
|
44
|
+
startTime: number;
|
|
45
|
+
pauseTime: number;
|
|
46
|
+
options: MotionOptions;
|
|
47
|
+
}
|
|
48
|
+
declare class MotionEngine {
|
|
49
|
+
private motions;
|
|
50
|
+
private isRunning;
|
|
51
|
+
private animationFrameId;
|
|
52
|
+
/**
|
|
53
|
+
* 모션 시작
|
|
54
|
+
*/
|
|
55
|
+
motion(element: HTMLElement, motionFrames: MotionFrame[], options: MotionOptions): Promise<string>;
|
|
56
|
+
/**
|
|
57
|
+
* 모션 중지
|
|
58
|
+
*/
|
|
59
|
+
stop(motionId: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* 모션 일시정지
|
|
62
|
+
*/
|
|
63
|
+
pause(motionId: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* 모션 재개
|
|
66
|
+
*/
|
|
67
|
+
resume(motionId: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* 모든 모션 중지
|
|
70
|
+
*/
|
|
71
|
+
stopAll(): void;
|
|
72
|
+
/**
|
|
73
|
+
* 모션 상태 확인
|
|
74
|
+
*/
|
|
75
|
+
getMotion(motionId: string): Motion | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* 실행 중인 모션 수
|
|
78
|
+
*/
|
|
79
|
+
getActiveMotionCount(): number;
|
|
80
|
+
/**
|
|
81
|
+
* 애니메이션 루프 시작
|
|
82
|
+
*/
|
|
83
|
+
private startAnimationLoop;
|
|
84
|
+
/**
|
|
85
|
+
* 애니메이션 루프 중지
|
|
86
|
+
*/
|
|
87
|
+
private stopAnimationLoop;
|
|
88
|
+
/**
|
|
89
|
+
* 메인 애니메이션 루프
|
|
90
|
+
*/
|
|
91
|
+
private animate;
|
|
92
|
+
/**
|
|
93
|
+
* 모션 프레임 적용
|
|
94
|
+
*/
|
|
95
|
+
private applyMotionFrame;
|
|
96
|
+
/**
|
|
97
|
+
* GPU 가속 활성화
|
|
98
|
+
*/
|
|
99
|
+
private enableGPUAcceleration;
|
|
100
|
+
/**
|
|
101
|
+
* 레이어 분리
|
|
102
|
+
*/
|
|
103
|
+
private createLayer;
|
|
104
|
+
/**
|
|
105
|
+
* 고유 모션 ID 생성
|
|
106
|
+
*/
|
|
107
|
+
private generateMotionId;
|
|
108
|
+
/**
|
|
109
|
+
* 정리
|
|
110
|
+
*/
|
|
111
|
+
destroy(): void;
|
|
112
|
+
}
|
|
113
|
+
declare const motionEngine: MotionEngine;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* HUA Motion Core - 전환 효과 시스템
|
|
117
|
+
*
|
|
118
|
+
* CSS Motion API를 활용한 고성능 전환 효과들
|
|
119
|
+
* GPU 가속 및 레이어 분리 최적화 포함
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
type TransitionType = 'fade' | 'slide' | 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right' | 'scale' | 'flip' | 'morph' | 'cube' | 'zoom';
|
|
123
|
+
interface TransitionOptions extends Omit<MotionOptions, 'easing'> {
|
|
124
|
+
type: TransitionType;
|
|
125
|
+
easing?: (t: number) => number;
|
|
126
|
+
distance?: number;
|
|
127
|
+
scale?: number;
|
|
128
|
+
perspective?: number;
|
|
129
|
+
onTransitionStart?: () => void;
|
|
130
|
+
onTransitionComplete?: () => void;
|
|
131
|
+
}
|
|
132
|
+
declare class TransitionEffects {
|
|
133
|
+
private static instance;
|
|
134
|
+
private activeTransitions;
|
|
135
|
+
static getInstance(): TransitionEffects;
|
|
136
|
+
/**
|
|
137
|
+
* 공통 전환 실행 헬퍼
|
|
138
|
+
*/
|
|
139
|
+
private executeTransition;
|
|
140
|
+
/**
|
|
141
|
+
* 페이드 인/아웃 전환
|
|
142
|
+
*/
|
|
143
|
+
fade(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* 슬라이드 전환
|
|
146
|
+
*/
|
|
147
|
+
slide(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* 스케일 전환
|
|
150
|
+
*/
|
|
151
|
+
scale(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* 플립 전환 (3D 회전)
|
|
154
|
+
*/
|
|
155
|
+
flip(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* 큐브 전환 (3D 큐브 회전)
|
|
158
|
+
*/
|
|
159
|
+
cube(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* 모프 전환 (복합 변형)
|
|
162
|
+
*/
|
|
163
|
+
morph(element: HTMLElement, options: Omit<TransitionOptions, 'type'>): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* 전환 중지
|
|
166
|
+
*/
|
|
167
|
+
stopTransition(transitionId: string): void;
|
|
168
|
+
/**
|
|
169
|
+
* 모든 전환 중지
|
|
170
|
+
*/
|
|
171
|
+
stopAllTransitions(): void;
|
|
172
|
+
/**
|
|
173
|
+
* 활성 전환 수 확인
|
|
174
|
+
*/
|
|
175
|
+
getActiveTransitionCount(): number;
|
|
176
|
+
/**
|
|
177
|
+
* GPU 가속 활성화
|
|
178
|
+
*/
|
|
179
|
+
private enableGPUAcceleration;
|
|
180
|
+
/**
|
|
181
|
+
* 기본 이징 함수
|
|
182
|
+
*/
|
|
183
|
+
private getDefaultEasing;
|
|
184
|
+
/**
|
|
185
|
+
* 고유 전환 ID 생성
|
|
186
|
+
*/
|
|
187
|
+
private generateTransitionId;
|
|
188
|
+
/**
|
|
189
|
+
* 정리
|
|
190
|
+
*/
|
|
191
|
+
destroy(): void;
|
|
192
|
+
}
|
|
193
|
+
declare const transitionEffects: TransitionEffects;
|
|
194
|
+
|
|
195
|
+
type MotionElement = HTMLDivElement | HTMLSpanElement | HTMLButtonElement | HTMLHeadingElement | HTMLParagraphElement | HTMLImageElement;
|
|
196
|
+
type MotionStyle = CSSProperties & {
|
|
197
|
+
'--motion-delay'?: string;
|
|
198
|
+
'--motion-duration'?: string;
|
|
199
|
+
'--motion-easing'?: string;
|
|
200
|
+
'--motion-progress'?: string;
|
|
201
|
+
};
|
|
202
|
+
interface BaseMotionOptions {
|
|
203
|
+
/** 모션 시작 지연 시간 (ms) */
|
|
204
|
+
delay?: number;
|
|
205
|
+
/** 모션 지속 시간 (ms) */
|
|
206
|
+
duration?: number;
|
|
207
|
+
/** Intersection Observer 임계값 (0-1) */
|
|
208
|
+
threshold?: number;
|
|
209
|
+
/** 한 번만 트리거할지 여부 */
|
|
210
|
+
triggerOnce?: boolean;
|
|
211
|
+
/** 이징 함수명 */
|
|
212
|
+
easing?: string;
|
|
213
|
+
/** 자동 시작 여부 */
|
|
214
|
+
autoStart?: boolean;
|
|
215
|
+
/** 모션 완료 시 콜백 */
|
|
216
|
+
onComplete?: () => void;
|
|
217
|
+
/** 모션 시작 시 콜백 */
|
|
218
|
+
onStart?: () => void;
|
|
219
|
+
/** 모션 중단 시 콜백 */
|
|
220
|
+
onStop?: () => void;
|
|
221
|
+
/** 모션 리셋 시 콜백 */
|
|
222
|
+
onReset?: () => void;
|
|
223
|
+
}
|
|
224
|
+
interface BaseMotionReturn<T extends MotionElement = HTMLDivElement> {
|
|
225
|
+
/** DOM 요소 참조 (React 19 호환) */
|
|
226
|
+
ref: React.RefObject<T | null>;
|
|
227
|
+
/** 요소가 화면에 보이는지 여부 */
|
|
228
|
+
isVisible: boolean;
|
|
229
|
+
/** 모션이 진행 중인지 여부 */
|
|
230
|
+
isAnimating: boolean;
|
|
231
|
+
/** 적용할 CSS 스타일 (React 19 호환) - useFadeIn 등에서는 항상 반환됨 */
|
|
232
|
+
style: MotionStyle;
|
|
233
|
+
/** 적용할 CSS 클래스명 */
|
|
234
|
+
className?: string;
|
|
235
|
+
/** 모션 진행률 (0-1) - useFadeIn 등에서는 항상 반환됨 */
|
|
236
|
+
progress: number;
|
|
237
|
+
/** 모션 시작 함수 - useFadeIn 등에서는 항상 반환됨 */
|
|
238
|
+
start: () => void;
|
|
239
|
+
/** 모션 리셋 함수 - useFadeIn 등에서는 항상 반환됨 */
|
|
240
|
+
reset: () => void;
|
|
241
|
+
/** 모션 중단 함수 - useFadeIn 등에서는 항상 반환됨 */
|
|
242
|
+
stop: () => void;
|
|
243
|
+
/** 모션 일시정지 함수 - 일부 훅에서만 제공 */
|
|
244
|
+
pause?: () => void;
|
|
245
|
+
/** 모션 재개 함수 - 일부 훅에서만 제공 */
|
|
246
|
+
resume?: () => void;
|
|
247
|
+
}
|
|
248
|
+
interface InteractionReturn<T extends MotionElement = HTMLDivElement> extends BaseMotionReturn<T> {
|
|
249
|
+
/** 가시성 토글 함수 */
|
|
250
|
+
toggle?: () => void;
|
|
251
|
+
/** 표시 함수 */
|
|
252
|
+
show?: () => void;
|
|
253
|
+
/** 숨김 함수 */
|
|
254
|
+
hide?: () => void;
|
|
255
|
+
}
|
|
256
|
+
interface FadeInOptions extends BaseMotionOptions {
|
|
257
|
+
/** 초기 투명도 */
|
|
258
|
+
initialOpacity?: number;
|
|
259
|
+
/** 목표 투명도 */
|
|
260
|
+
targetOpacity?: number;
|
|
261
|
+
}
|
|
262
|
+
interface SlideOptions extends BaseMotionOptions {
|
|
263
|
+
/** 슬라이드 방향 */
|
|
264
|
+
direction?: 'up' | 'down' | 'left' | 'right';
|
|
265
|
+
/** 슬라이드 거리 (px) */
|
|
266
|
+
distance?: number;
|
|
267
|
+
}
|
|
268
|
+
interface ScaleOptions extends BaseMotionOptions {
|
|
269
|
+
/** 초기 스케일 */
|
|
270
|
+
initialScale?: number;
|
|
271
|
+
/** 목표 스케일 */
|
|
272
|
+
targetScale?: number;
|
|
273
|
+
}
|
|
274
|
+
interface BounceOptions extends BaseMotionOptions {
|
|
275
|
+
/** 바운스 강도 */
|
|
276
|
+
intensity?: number;
|
|
277
|
+
/** 바운스 횟수 */
|
|
278
|
+
bounces?: number;
|
|
279
|
+
}
|
|
280
|
+
interface PulseOptions extends BaseMotionOptions {
|
|
281
|
+
/** 펄스 강도 */
|
|
282
|
+
intensity?: number;
|
|
283
|
+
/** 반복 횟수 (-1 = 무한) */
|
|
284
|
+
repeatCount?: number;
|
|
285
|
+
/** 반복 간격 (ms) */
|
|
286
|
+
repeatDelay?: number;
|
|
287
|
+
}
|
|
288
|
+
interface SpringOptions extends BaseMotionOptions {
|
|
289
|
+
/** 스프링 질량 */
|
|
290
|
+
mass?: number;
|
|
291
|
+
/** 스프링 강성 */
|
|
292
|
+
stiffness?: number;
|
|
293
|
+
/** 스프링 감쇠 */
|
|
294
|
+
damping?: number;
|
|
295
|
+
/** 정지 임계값 */
|
|
296
|
+
restDelta?: number;
|
|
297
|
+
/** 정지 속도 */
|
|
298
|
+
restSpeed?: number;
|
|
299
|
+
}
|
|
300
|
+
interface GestureOptions extends BaseMotionOptions {
|
|
301
|
+
/** 호버 제스처 활성화 */
|
|
302
|
+
hover?: boolean;
|
|
303
|
+
/** 드래그 제스처 활성화 */
|
|
304
|
+
drag?: boolean;
|
|
305
|
+
/** 핀치 제스처 활성화 */
|
|
306
|
+
pinch?: boolean;
|
|
307
|
+
/** 스와이프 제스처 활성화 */
|
|
308
|
+
swipe?: boolean;
|
|
309
|
+
/** 틸트 제스처 활성화 */
|
|
310
|
+
tilt?: boolean;
|
|
311
|
+
}
|
|
312
|
+
type MotionDirection = 'up' | 'down' | 'left' | 'right';
|
|
313
|
+
type MotionEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'bounce' | 'elastic';
|
|
314
|
+
type MotionTrigger = 'scroll' | 'click' | 'hover' | 'focus' | 'auto';
|
|
315
|
+
type MotionCallback = () => void;
|
|
316
|
+
type MotionProgressCallback = (progress: number) => void;
|
|
317
|
+
type MotionStateCallback<T extends MotionElement = HTMLDivElement> = (state: BaseMotionReturn<T>) => void;
|
|
318
|
+
interface PerformanceMetrics {
|
|
319
|
+
/** 모션 시작 시간 */
|
|
320
|
+
startTime: number;
|
|
321
|
+
/** 모션 종료 시간 */
|
|
322
|
+
endTime?: number;
|
|
323
|
+
/** 총 지속 시간 */
|
|
324
|
+
duration: number;
|
|
325
|
+
/** FPS */
|
|
326
|
+
fps: number;
|
|
327
|
+
/** 메모리 사용량 */
|
|
328
|
+
memoryUsage?: number;
|
|
329
|
+
}
|
|
330
|
+
interface MotionConfig {
|
|
331
|
+
/** 성능 모니터링 활성화 */
|
|
332
|
+
enablePerformanceMonitoring?: boolean;
|
|
333
|
+
/** 디버그 모드 활성화 */
|
|
334
|
+
debug?: boolean;
|
|
335
|
+
/** 로그 레벨 */
|
|
336
|
+
logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
337
|
+
}
|
|
338
|
+
interface InViewOptions {
|
|
339
|
+
/** Intersection Observer 임계값 */
|
|
340
|
+
threshold?: number | number[];
|
|
341
|
+
/** 루트 마진 */
|
|
342
|
+
rootMargin?: string;
|
|
343
|
+
/** 한 번만 트리거할지 여부 */
|
|
344
|
+
triggerOnce?: boolean;
|
|
345
|
+
/** 초기 가시성 상태 */
|
|
346
|
+
initialInView?: boolean;
|
|
347
|
+
}
|
|
348
|
+
interface InViewReturn<T extends HTMLElement = HTMLDivElement> {
|
|
349
|
+
/** DOM 요소 참조 */
|
|
350
|
+
ref: RefObject<T | null>;
|
|
351
|
+
/** 요소가 화면에 보이는지 여부 */
|
|
352
|
+
inView: boolean;
|
|
353
|
+
/** IntersectionObserver 엔트리 */
|
|
354
|
+
entry: IntersectionObserverEntry | null;
|
|
355
|
+
}
|
|
356
|
+
interface MouseOptions {
|
|
357
|
+
/** 타겟 요소 참조 */
|
|
358
|
+
targetRef?: RefObject<HTMLElement | null>;
|
|
359
|
+
/** 스로틀 시간 (ms) */
|
|
360
|
+
throttle?: number;
|
|
361
|
+
}
|
|
362
|
+
interface MouseReturn {
|
|
363
|
+
/** 마우스 X 좌표 (viewport 기준) */
|
|
364
|
+
x: number;
|
|
365
|
+
/** 마우스 Y 좌표 (viewport 기준) */
|
|
366
|
+
y: number;
|
|
367
|
+
/** 요소 내 상대 X 좌표 (0-1) */
|
|
368
|
+
elementX: number;
|
|
369
|
+
/** 요소 내 상대 Y 좌표 (0-1) */
|
|
370
|
+
elementY: number;
|
|
371
|
+
/** 마우스가 타겟 위에 있는지 여부 */
|
|
372
|
+
isOver: boolean;
|
|
373
|
+
}
|
|
374
|
+
interface ReducedMotionReturn {
|
|
375
|
+
/** 사용자가 모션 감소를 선호하는지 여부 */
|
|
376
|
+
prefersReducedMotion: boolean;
|
|
377
|
+
}
|
|
378
|
+
interface WindowSizeOptions {
|
|
379
|
+
/** 디바운스 시간 (ms) */
|
|
380
|
+
debounce?: number;
|
|
381
|
+
/** 초기 너비 */
|
|
382
|
+
initialWidth?: number;
|
|
383
|
+
/** 초기 높이 */
|
|
384
|
+
initialHeight?: number;
|
|
385
|
+
}
|
|
386
|
+
interface WindowSizeReturn {
|
|
387
|
+
/** 윈도우 너비 */
|
|
388
|
+
width: number;
|
|
389
|
+
/** 윈도우 높이 */
|
|
390
|
+
height: number;
|
|
391
|
+
/** 마운트 여부 (SSR 대응) */
|
|
392
|
+
isMounted: boolean;
|
|
393
|
+
}
|
|
394
|
+
type ScrollRevealMotionType = 'fadeIn' | 'slideUp' | 'slideLeft' | 'slideRight' | 'scaleIn' | 'bounceIn';
|
|
395
|
+
interface ScrollRevealOptions extends BaseMotionOptions {
|
|
396
|
+
/** 루트 마진 */
|
|
397
|
+
rootMargin?: string;
|
|
398
|
+
/** 모션 타입 */
|
|
399
|
+
motionType?: ScrollRevealMotionType;
|
|
400
|
+
}
|
|
401
|
+
interface GradientOptions extends BaseMotionOptions {
|
|
402
|
+
/** 그라디언트 색상 배열 */
|
|
403
|
+
colors?: string[];
|
|
404
|
+
/** 그라디언트 방향 */
|
|
405
|
+
direction?: 'horizontal' | 'vertical' | 'diagonal';
|
|
406
|
+
/** 그라디언트 크기 (%) */
|
|
407
|
+
size?: number;
|
|
408
|
+
}
|
|
409
|
+
interface ToggleMotionOptions extends BaseMotionOptions {
|
|
410
|
+
}
|
|
411
|
+
interface RepeatOptions extends BaseMotionOptions {
|
|
412
|
+
/** 반복 효과 타입 */
|
|
413
|
+
type?: 'pulse' | 'bounce' | 'wave' | 'fade';
|
|
414
|
+
/** 효과 강도 */
|
|
415
|
+
intensity?: number;
|
|
416
|
+
}
|
|
417
|
+
interface HoverMotionOptions extends BaseMotionOptions {
|
|
418
|
+
/** 호버 시 스케일 */
|
|
419
|
+
hoverScale?: number;
|
|
420
|
+
/** 호버 시 Y 오프셋 (px) */
|
|
421
|
+
hoverY?: number;
|
|
422
|
+
/** 호버 시 투명도 */
|
|
423
|
+
hoverOpacity?: number;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
type PageType = 'home' | 'dashboard' | 'product' | 'blog';
|
|
427
|
+
type MotionType = 'hero' | 'title' | 'button' | 'card' | 'text' | 'image';
|
|
428
|
+
type EntranceType = 'fadeIn' | 'slideUp' | 'slideLeft' | 'slideRight' | 'scaleIn' | 'bounceIn';
|
|
429
|
+
interface PageMotionElement {
|
|
430
|
+
type: MotionType;
|
|
431
|
+
entrance?: EntranceType;
|
|
432
|
+
hover?: boolean;
|
|
433
|
+
click?: boolean;
|
|
434
|
+
delay?: number;
|
|
435
|
+
duration?: number;
|
|
436
|
+
threshold?: number;
|
|
437
|
+
}
|
|
438
|
+
interface PageMotionsConfig {
|
|
439
|
+
[elementId: string]: PageMotionElement;
|
|
440
|
+
}
|
|
441
|
+
interface MotionState {
|
|
442
|
+
internalVisibility: boolean;
|
|
443
|
+
triggeredVisibility: boolean;
|
|
444
|
+
finalVisibility: boolean;
|
|
445
|
+
opacity: number;
|
|
446
|
+
translateY: number;
|
|
447
|
+
translateX: number;
|
|
448
|
+
scale: number;
|
|
449
|
+
rotation: number;
|
|
450
|
+
isHovered: boolean;
|
|
451
|
+
isClicked: boolean;
|
|
452
|
+
isAnimating: boolean;
|
|
453
|
+
}
|
|
454
|
+
interface PageMotionRef<T extends HTMLElement = HTMLElement> {
|
|
455
|
+
ref: React.RefObject<T | null>;
|
|
456
|
+
style: React.CSSProperties;
|
|
457
|
+
isVisible: boolean;
|
|
458
|
+
isHovered: boolean;
|
|
459
|
+
isClicked: boolean;
|
|
460
|
+
}
|
|
461
|
+
interface MotionPreset {
|
|
462
|
+
entrance: EntranceType;
|
|
463
|
+
delay: number;
|
|
464
|
+
duration: number;
|
|
465
|
+
hover: boolean;
|
|
466
|
+
click: boolean;
|
|
467
|
+
}
|
|
468
|
+
interface PresetConfig {
|
|
469
|
+
[key: string]: MotionPreset;
|
|
470
|
+
}
|
|
471
|
+
interface SpringConfig$1 {
|
|
472
|
+
mass?: number;
|
|
473
|
+
stiffness?: number;
|
|
474
|
+
damping?: number;
|
|
475
|
+
restDelta?: number;
|
|
476
|
+
restSpeed?: number;
|
|
477
|
+
}
|
|
478
|
+
interface GestureConfig {
|
|
479
|
+
hover?: boolean;
|
|
480
|
+
drag?: boolean;
|
|
481
|
+
pinch?: boolean;
|
|
482
|
+
swipe?: boolean;
|
|
483
|
+
tilt?: boolean;
|
|
484
|
+
}
|
|
485
|
+
interface OrchestrationConfig {
|
|
486
|
+
sequence?: 'sequential' | 'parallel' | 'stagger';
|
|
487
|
+
staggerDelay?: number;
|
|
488
|
+
staggerDuration?: number;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
declare const MOTION_PRESETS: PresetConfig;
|
|
492
|
+
declare const PAGE_MOTIONS: Record<PageType, PageMotionsConfig>;
|
|
493
|
+
/**
|
|
494
|
+
* 프리셋과 커스텀 설정을 병합
|
|
495
|
+
*/
|
|
496
|
+
declare function mergeWithPreset(preset: MotionPreset, custom?: Partial<MotionPreset>): MotionPreset;
|
|
497
|
+
/**
|
|
498
|
+
* 페이지 타입으로 프리셋 가져오기
|
|
499
|
+
*/
|
|
500
|
+
declare function getPagePreset(pageType: PageType): PageMotionsConfig;
|
|
501
|
+
/**
|
|
502
|
+
* 모션 타입으로 기본 프리셋 가져오기
|
|
503
|
+
*/
|
|
504
|
+
declare function getMotionPreset(type: string): MotionPreset;
|
|
505
|
+
|
|
506
|
+
/** 프로필 전체의 기본 모션 디폴트 */
|
|
507
|
+
interface MotionProfileBase {
|
|
508
|
+
/** 기본 duration (ms) */
|
|
509
|
+
duration: number;
|
|
510
|
+
/** 기본 easing (CSS 또는 named preset) */
|
|
511
|
+
easing: string;
|
|
512
|
+
/** IntersectionObserver 임계값 */
|
|
513
|
+
threshold: number;
|
|
514
|
+
/** 한 번만 트리거할지 여부 */
|
|
515
|
+
triggerOnce: boolean;
|
|
516
|
+
}
|
|
517
|
+
/** 입장 애니메이션 디폴트 */
|
|
518
|
+
interface MotionProfileEntrance {
|
|
519
|
+
slide: {
|
|
520
|
+
/** 슬라이드 거리 (px) */
|
|
521
|
+
distance: number;
|
|
522
|
+
/** 슬라이드 전용 이징 */
|
|
523
|
+
easing: string;
|
|
524
|
+
};
|
|
525
|
+
fade: {
|
|
526
|
+
/** 초기 투명도 */
|
|
527
|
+
initialOpacity: number;
|
|
528
|
+
};
|
|
529
|
+
scale: {
|
|
530
|
+
/** 초기 스케일 (useScrollReveal/useStagger용, 0.95 등 미세 변화) */
|
|
531
|
+
from: number;
|
|
532
|
+
};
|
|
533
|
+
bounce: {
|
|
534
|
+
/** 바운스 강도 */
|
|
535
|
+
intensity: number;
|
|
536
|
+
/** 바운스 전용 이징 */
|
|
537
|
+
easing: string;
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
/** 스태거 디폴트 */
|
|
541
|
+
interface MotionProfileStagger {
|
|
542
|
+
/** 아이템 간 딜레이 (ms) */
|
|
543
|
+
perItem: number;
|
|
544
|
+
/** 첫 아이템 전 딜레이 (ms) */
|
|
545
|
+
baseDelay: number;
|
|
546
|
+
}
|
|
547
|
+
/** 인터랙션 디폴트 */
|
|
548
|
+
interface MotionProfileInteraction {
|
|
549
|
+
hover: {
|
|
550
|
+
/** 호버 시 스케일 */
|
|
551
|
+
scale: number;
|
|
552
|
+
/** 호버 시 Y 오프셋 (px) */
|
|
553
|
+
y: number;
|
|
554
|
+
/** 호버 duration (ms) */
|
|
555
|
+
duration: number;
|
|
556
|
+
/** 호버 이징 */
|
|
557
|
+
easing: string;
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
/** 스프링 물리 디폴트 */
|
|
561
|
+
interface MotionProfileSpring {
|
|
562
|
+
/** 질량 */
|
|
563
|
+
mass: number;
|
|
564
|
+
/** 강성 */
|
|
565
|
+
stiffness: number;
|
|
566
|
+
/** 감쇠 */
|
|
567
|
+
damping: number;
|
|
568
|
+
/** 정지 임계값 */
|
|
569
|
+
restDelta: number;
|
|
570
|
+
/** 정지 속도 */
|
|
571
|
+
restSpeed: number;
|
|
572
|
+
}
|
|
573
|
+
/** reduced motion 전략 */
|
|
574
|
+
type ReducedMotionStrategy = 'skip' | 'fade-only' | 'minimal';
|
|
575
|
+
/** 전체 Motion Profile */
|
|
576
|
+
interface MotionProfile {
|
|
577
|
+
/** 프로필 이름 */
|
|
578
|
+
name: string;
|
|
579
|
+
/** 공통 디폴트 */
|
|
580
|
+
base: MotionProfileBase;
|
|
581
|
+
/** 입장 애니메이션 */
|
|
582
|
+
entrance: MotionProfileEntrance;
|
|
583
|
+
/** 스태거 */
|
|
584
|
+
stagger: MotionProfileStagger;
|
|
585
|
+
/** 인터랙션 */
|
|
586
|
+
interaction: MotionProfileInteraction;
|
|
587
|
+
/** 스프링 물리 */
|
|
588
|
+
spring: MotionProfileSpring;
|
|
589
|
+
/** reduced motion 전략 */
|
|
590
|
+
reducedMotion: ReducedMotionStrategy;
|
|
591
|
+
}
|
|
592
|
+
/** 내장 프로필 이름 */
|
|
593
|
+
type BuiltInProfileName = 'neutral' | 'hua';
|
|
594
|
+
/** DeepPartial 유틸리티 */
|
|
595
|
+
type DeepPartial<T> = {
|
|
596
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* neutral 프로필 — 기존 하드코딩 디폴트와 동일.
|
|
601
|
+
* Provider 없을 때 fallback으로 사용되므로 하위 호환 100% 보장.
|
|
602
|
+
*/
|
|
603
|
+
declare const neutral: MotionProfile;
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* HUA 프로필 — 스르륵 쫀뜩한 브랜드 시그니처.
|
|
607
|
+
*
|
|
608
|
+
* 특징:
|
|
609
|
+
* - CSS ease-out 기반이되 끝에 미세한 오버슈트 (1.04~1.06)
|
|
610
|
+
* - 도착점을 살짝 지나쳤다가 돌아오는 탄성
|
|
611
|
+
* - 바운스 없이 쫀뜩 (높은 감쇠 + 높은 강성)
|
|
612
|
+
* - neutral보다 짧은 duration, 좁은 distance → 더 정교한 느낌
|
|
613
|
+
*/
|
|
614
|
+
declare const hua: MotionProfile;
|
|
615
|
+
|
|
616
|
+
interface MotionProfileProviderProps {
|
|
617
|
+
/** 내장 프로필 이름 또는 커스텀 프로필 객체 */
|
|
618
|
+
profile?: BuiltInProfileName | MotionProfile;
|
|
619
|
+
/** 선택한 프로필 위에 부분 오버라이드 */
|
|
620
|
+
overrides?: DeepPartial<MotionProfile>;
|
|
621
|
+
children: React.ReactNode;
|
|
622
|
+
}
|
|
623
|
+
declare function MotionProfileProvider({ profile, overrides, children, }: MotionProfileProviderProps): react.FunctionComponentElement<react.ProviderProps<MotionProfile>>;
|
|
624
|
+
/**
|
|
625
|
+
* 현재 프로필을 가져옴.
|
|
626
|
+
* Provider 밖에서 호출 시 neutral 프로필 반환 (하위 호환).
|
|
627
|
+
*/
|
|
628
|
+
declare function useMotionProfile(): MotionProfile;
|
|
629
|
+
|
|
630
|
+
/** 이름 또는 객체에서 프로필 resolve */
|
|
631
|
+
declare function resolveProfile(profile: BuiltInProfileName | MotionProfile): MotionProfile;
|
|
632
|
+
/** 프로필에 오버라이드를 깊은 병합 */
|
|
633
|
+
declare function mergeProfileOverrides(base: MotionProfile, overrides: DeepPartial<MotionProfile>): MotionProfile;
|
|
634
|
+
|
|
635
|
+
type EasingFunction = (t: number) => number;
|
|
636
|
+
declare const linear: EasingFunction;
|
|
637
|
+
declare const easeIn: EasingFunction;
|
|
638
|
+
declare const easeOut: EasingFunction;
|
|
639
|
+
declare const easeInOut: EasingFunction;
|
|
640
|
+
declare const easeInQuad: EasingFunction;
|
|
641
|
+
declare const easeOutQuad: EasingFunction;
|
|
642
|
+
declare const easeInOutQuad: EasingFunction;
|
|
643
|
+
type EasingType = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' | 'easeOutQuint' | 'easeInOutQuint' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' | 'easeInCirc' | 'easeOutCirc' | 'easeInOutCirc' | 'easeInBounce' | 'easeOutBounce' | 'easeInOutBounce' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeInElastic' | 'easeOutElastic' | 'easeInOutElastic' | 'pulse' | 'pulseSmooth' | 'skeletonWave' | 'blink';
|
|
644
|
+
declare function isValidEasing(easingName: string): boolean;
|
|
645
|
+
declare function getEasing(easingName: unknown): EasingFunction;
|
|
646
|
+
declare function applyEasing(t: number, easingName: string | EasingFunction): number;
|
|
647
|
+
declare function safeApplyEasing(t: number, easingName: unknown): number;
|
|
648
|
+
declare function getAvailableEasings(): string[];
|
|
649
|
+
declare function isEasingFunction(value: any): value is EasingFunction;
|
|
650
|
+
declare const easingPresets: {
|
|
651
|
+
readonly default: "easeOut";
|
|
652
|
+
readonly smooth: "easeInOutCubic";
|
|
653
|
+
readonly fast: "easeOutQuad";
|
|
654
|
+
readonly slow: "easeInOutSine";
|
|
655
|
+
readonly bouncy: "easeOutBounce";
|
|
656
|
+
readonly elastic: "easeOutElastic";
|
|
657
|
+
readonly fade: "easeInOut";
|
|
658
|
+
readonly scale: "easeOutBack";
|
|
659
|
+
};
|
|
660
|
+
declare function getPresetEasing(preset: keyof typeof easingPresets): EasingFunction;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Spring physics calculation (Hooke's Law + damping)
|
|
664
|
+
*
|
|
665
|
+
* Pure function — no side effects, fully testable.
|
|
666
|
+
*/
|
|
667
|
+
interface SpringConfig {
|
|
668
|
+
stiffness: number;
|
|
669
|
+
damping: number;
|
|
670
|
+
mass: number;
|
|
671
|
+
}
|
|
672
|
+
interface SpringResult {
|
|
673
|
+
value: number;
|
|
674
|
+
velocity: number;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Calculate one step of a damped spring simulation.
|
|
678
|
+
*
|
|
679
|
+
* @param currentValue Current position
|
|
680
|
+
* @param currentVelocity Current velocity
|
|
681
|
+
* @param targetValue Equilibrium (target) position
|
|
682
|
+
* @param deltaTime Time step in seconds
|
|
683
|
+
* @param config Spring parameters (stiffness, damping, mass)
|
|
684
|
+
*/
|
|
685
|
+
declare function calculateSpring(currentValue: number, currentVelocity: number, targetValue: number, deltaTime: number, config: SpringConfig): SpringResult;
|
|
686
|
+
|
|
687
|
+
export { type MotionStateCallback as $, type MotionFrame as A, type BaseMotionOptions as B, type Motion as C, type DeepPartial as D, type EntranceType as E, type FadeInOptions as F, type GradientOptions as G, type HoverMotionOptions as H, type InteractionReturn as I, type MotionOptions as J, type MotionPreset as K, type MotionProfile as L, type MotionElement as M, type MotionProfileBase as N, type MotionProfileEntrance as O, type PageType as P, type MotionProfileInteraction as Q, type RepeatOptions as R, type SlideOptions as S, type ToggleMotionOptions as T, MotionProfileProvider as U, type MotionProfileProviderProps as V, type WindowSizeOptions as W, type MotionProfileSpring as X, type MotionProfileStagger as Y, type MotionProgressCallback as Z, type MotionState as _, type PageMotionRef as a, type MotionTrigger as a0, type MotionType as a1, type OrchestrationConfig as a2, PAGE_MOTIONS as a3, type PageMotionElement as a4, type PerformanceMetrics as a5, type PresetConfig as a6, type ReducedMotionStrategy as a7, type SpringConfig$1 as a8, type SpringConfig as a9, resolveProfile as aA, safeApplyEasing as aB, transitionEffects as aC, useMotionProfile as aD, type SpringResult as aa, TransitionEffects as ab, type TransitionOptions as ac, type TransitionType as ad, applyEasing as ae, calculateSpring as af, easeIn as ag, easeInOut as ah, easeInOutQuad as ai, easeInQuad as aj, easeOut as ak, easeOutQuad as al, easingPresets as am, getAvailableEasings as an, getEasing as ao, getMotionPreset as ap, getPagePreset as aq, getPresetEasing as ar, hua as as, isEasingFunction as at, isValidEasing as au, linear as av, mergeProfileOverrides as aw, mergeWithPreset as ax, motionEngine as ay, neutral as az, type PageMotionsConfig as b, type BaseMotionReturn as c, type ScaleOptions as d, type BounceOptions as e, type PulseOptions as f, type SpringOptions as g, type ScrollRevealOptions as h, type InViewOptions as i, type InViewReturn as j, type MouseOptions as k, type MouseReturn as l, type ReducedMotionReturn as m, type WindowSizeReturn as n, type ScrollRevealMotionType as o, type BuiltInProfileName as p, type EasingFunction as q, type EasingType as r, type GestureConfig as s, type GestureOptions as t, MOTION_PRESETS as u, type MotionCallback as v, type MotionConfig as w, type MotionDirection as x, type MotionEasing as y, MotionEngine as z };
|