@hua-labs/motion-core 2.0.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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +245 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/hooks/useBounceIn.d.ts +3 -0
  5. package/dist/hooks/useBounceIn.d.ts.map +1 -0
  6. package/dist/hooks/useBounceIn.js +141 -0
  7. package/dist/hooks/useBounceIn.js.map +1 -0
  8. package/dist/hooks/useButtonEffect.d.ts +48 -0
  9. package/dist/hooks/useButtonEffect.d.ts.map +1 -0
  10. package/dist/hooks/useButtonEffect.js +311 -0
  11. package/dist/hooks/useButtonEffect.js.map +1 -0
  12. package/dist/hooks/useCardList.d.ts +23 -0
  13. package/dist/hooks/useCardList.d.ts.map +1 -0
  14. package/dist/hooks/useCardList.js +119 -0
  15. package/dist/hooks/useCardList.js.map +1 -0
  16. package/dist/hooks/useClickToggle.d.ts +15 -0
  17. package/dist/hooks/useClickToggle.d.ts.map +1 -0
  18. package/dist/hooks/useClickToggle.js +102 -0
  19. package/dist/hooks/useClickToggle.js.map +1 -0
  20. package/dist/hooks/useFadeIn.d.ts +17 -0
  21. package/dist/hooks/useFadeIn.d.ts.map +1 -0
  22. package/dist/hooks/useFadeIn.js +133 -0
  23. package/dist/hooks/useFadeIn.js.map +1 -0
  24. package/dist/hooks/useFocusToggle.d.ts +15 -0
  25. package/dist/hooks/useFocusToggle.d.ts.map +1 -0
  26. package/dist/hooks/useFocusToggle.js +99 -0
  27. package/dist/hooks/useFocusToggle.js.map +1 -0
  28. package/dist/hooks/useGradient.d.ts +25 -0
  29. package/dist/hooks/useGradient.d.ts.map +1 -0
  30. package/dist/hooks/useGradient.js +144 -0
  31. package/dist/hooks/useGradient.js.map +1 -0
  32. package/dist/hooks/useHoverMotion.d.ts +15 -0
  33. package/dist/hooks/useHoverMotion.d.ts.map +1 -0
  34. package/dist/hooks/useHoverMotion.js +99 -0
  35. package/dist/hooks/useHoverMotion.js.map +1 -0
  36. package/dist/hooks/useLoadingSpinner.d.ts +30 -0
  37. package/dist/hooks/useLoadingSpinner.d.ts.map +1 -0
  38. package/dist/hooks/useLoadingSpinner.js +283 -0
  39. package/dist/hooks/useLoadingSpinner.js.map +1 -0
  40. package/dist/hooks/useMotion.d.ts +103 -0
  41. package/dist/hooks/useMotion.d.ts.map +1 -0
  42. package/dist/hooks/useMotion.js +266 -0
  43. package/dist/hooks/useMotion.js.map +1 -0
  44. package/dist/hooks/useMotionState.d.ts +26 -0
  45. package/dist/hooks/useMotionState.d.ts.map +1 -0
  46. package/dist/hooks/useMotionState.js +119 -0
  47. package/dist/hooks/useMotionState.js.map +1 -0
  48. package/dist/hooks/useNavigation.d.ts +40 -0
  49. package/dist/hooks/useNavigation.d.ts.map +1 -0
  50. package/dist/hooks/useNavigation.js +212 -0
  51. package/dist/hooks/useNavigation.js.map +1 -0
  52. package/dist/hooks/usePulse.d.ts +3 -0
  53. package/dist/hooks/usePulse.d.ts.map +1 -0
  54. package/dist/hooks/usePulse.js +134 -0
  55. package/dist/hooks/usePulse.js.map +1 -0
  56. package/dist/hooks/useRepeat.d.ts +26 -0
  57. package/dist/hooks/useRepeat.d.ts.map +1 -0
  58. package/dist/hooks/useRepeat.js +179 -0
  59. package/dist/hooks/useRepeat.js.map +1 -0
  60. package/dist/hooks/useScaleIn.d.ts +3 -0
  61. package/dist/hooks/useScaleIn.d.ts.map +1 -0
  62. package/dist/hooks/useScaleIn.js +111 -0
  63. package/dist/hooks/useScaleIn.js.map +1 -0
  64. package/dist/hooks/useScrollProgress.d.ts +21 -0
  65. package/dist/hooks/useScrollProgress.d.ts.map +1 -0
  66. package/dist/hooks/useScrollProgress.js +139 -0
  67. package/dist/hooks/useScrollProgress.js.map +1 -0
  68. package/dist/hooks/useScrollReveal.d.ts +17 -0
  69. package/dist/hooks/useScrollReveal.d.ts.map +1 -0
  70. package/dist/hooks/useScrollReveal.js +95 -0
  71. package/dist/hooks/useScrollReveal.js.map +1 -0
  72. package/dist/hooks/useScrollToggle.d.ts +17 -0
  73. package/dist/hooks/useScrollToggle.d.ts.map +1 -0
  74. package/dist/hooks/useScrollToggle.js +119 -0
  75. package/dist/hooks/useScrollToggle.js.map +1 -0
  76. package/dist/hooks/useSkeleton.d.ts +21 -0
  77. package/dist/hooks/useSkeleton.d.ts.map +1 -0
  78. package/dist/hooks/useSkeleton.js +139 -0
  79. package/dist/hooks/useSkeleton.js.map +1 -0
  80. package/dist/hooks/useSlideDown.d.ts +25 -0
  81. package/dist/hooks/useSlideDown.d.ts.map +1 -0
  82. package/dist/hooks/useSlideDown.js +263 -0
  83. package/dist/hooks/useSlideDown.js.map +1 -0
  84. package/dist/hooks/useSlideLeft.d.ts +3 -0
  85. package/dist/hooks/useSlideLeft.d.ts.map +1 -0
  86. package/dist/hooks/useSlideLeft.js +111 -0
  87. package/dist/hooks/useSlideLeft.js.map +1 -0
  88. package/dist/hooks/useSlideRight.d.ts +3 -0
  89. package/dist/hooks/useSlideRight.d.ts.map +1 -0
  90. package/dist/hooks/useSlideRight.js +111 -0
  91. package/dist/hooks/useSlideRight.js.map +1 -0
  92. package/dist/hooks/useSlideUp.d.ts +3 -0
  93. package/dist/hooks/useSlideUp.d.ts.map +1 -0
  94. package/dist/hooks/useSlideUp.js +111 -0
  95. package/dist/hooks/useSlideUp.js.map +1 -0
  96. package/dist/hooks/useSpringMotion.d.ts +32 -0
  97. package/dist/hooks/useSpringMotion.d.ts.map +1 -0
  98. package/dist/hooks/useSpringMotion.js +185 -0
  99. package/dist/hooks/useSpringMotion.js.map +1 -0
  100. package/dist/hooks/useVisibilityToggle.d.ts +15 -0
  101. package/dist/hooks/useVisibilityToggle.d.ts.map +1 -0
  102. package/dist/hooks/useVisibilityToggle.js +106 -0
  103. package/dist/hooks/useVisibilityToggle.js.map +1 -0
  104. package/dist/index.d.ts +29 -0
  105. package/dist/index.d.ts.map +1 -0
  106. package/dist/index.js +43 -0
  107. package/dist/index.js.map +1 -0
  108. package/dist/types/index.d.ts +109 -0
  109. package/dist/types/index.d.ts.map +1 -0
  110. package/dist/types/index.js +5 -0
  111. package/dist/types/index.js.map +1 -0
  112. package/dist/utils/easing.d.ts +44 -0
  113. package/dist/utils/easing.d.ts.map +1 -0
  114. package/dist/utils/easing.js +98 -0
  115. package/dist/utils/easing.js.map +1 -0
  116. package/package.json +69 -0
@@ -0,0 +1,283 @@
1
+ import { useRef, useState, useEffect, useCallback } from 'react';
2
+ export function useLoadingSpinner(options = {}) {
3
+ const { duration = 1000, easing = 'linear', type = 'rotate', rotationSpeed = 1, pulseSpeed = 1, bounceHeight = 20, waveCount = 3, dotCount = 3, barCount = 4, color = '#3b82f6', backgroundColor = 'transparent', size = 40, thickness = 4, autoStart = true, infinite = true, onComplete, onStart, onStop, onReset } = options;
4
+ const ref = useRef(null);
5
+ const [isVisible, setIsVisible] = useState(false);
6
+ const [isAnimating, setIsAnimating] = useState(false);
7
+ const [progress, setProgress] = useState(0);
8
+ const [isLoading, setIsLoading] = useState(false);
9
+ const [rotationAngle, setRotationAngle] = useState(0);
10
+ const [pulseScale, setPulseScale] = useState(1);
11
+ const [bounceOffset, setBounceOffset] = useState(0);
12
+ const [waveProgress, setWaveProgress] = useState(0);
13
+ const [dotProgress, setDotProgress] = useState(0);
14
+ const [barProgress, setBarProgress] = useState(0);
15
+ const animationRef = useRef(null);
16
+ const startTimeRef = useRef(0);
17
+ // 애니메이션 루프 함수
18
+ const runAnimation = useCallback(() => {
19
+ if (!isAnimating)
20
+ return;
21
+ const animate = (currentTime) => {
22
+ if (!isAnimating)
23
+ return;
24
+ if (!startTimeRef.current) {
25
+ startTimeRef.current = currentTime;
26
+ }
27
+ const elapsed = currentTime - startTimeRef.current;
28
+ const currentProgress = (elapsed / duration) % 1;
29
+ setProgress(currentProgress);
30
+ // 타입별 애니메이션 업데이트
31
+ switch (type) {
32
+ case 'rotate':
33
+ setRotationAngle(currentProgress * 360 * rotationSpeed);
34
+ break;
35
+ case 'pulse':
36
+ setPulseScale(0.8 + 0.4 * Math.sin(currentProgress * Math.PI * 2 * pulseSpeed));
37
+ break;
38
+ case 'bounce':
39
+ setBounceOffset(bounceHeight * Math.sin(currentProgress * Math.PI * 2));
40
+ break;
41
+ case 'wave':
42
+ setWaveProgress(currentProgress);
43
+ break;
44
+ case 'dots':
45
+ setDotProgress(currentProgress);
46
+ break;
47
+ case 'bars':
48
+ setBarProgress(currentProgress);
49
+ break;
50
+ }
51
+ if (infinite || currentProgress < 1) {
52
+ animationRef.current = requestAnimationFrame(animate);
53
+ }
54
+ else {
55
+ setIsAnimating(false);
56
+ onComplete?.();
57
+ }
58
+ };
59
+ animationRef.current = requestAnimationFrame(animate);
60
+ }, [isAnimating, duration, type, rotationSpeed, pulseSpeed, bounceHeight, infinite, onComplete]);
61
+ // 로딩 시작 함수
62
+ const startLoading = useCallback(() => {
63
+ if (isLoading)
64
+ return;
65
+ setIsLoading(true);
66
+ setIsAnimating(true);
67
+ setProgress(0);
68
+ startTimeRef.current = 0;
69
+ onStart?.();
70
+ runAnimation();
71
+ }, [isLoading, onStart, runAnimation]);
72
+ // 로딩 중단 함수
73
+ const stopLoading = useCallback(() => {
74
+ setIsLoading(false);
75
+ setIsAnimating(false);
76
+ if (animationRef.current) {
77
+ cancelAnimationFrame(animationRef.current);
78
+ animationRef.current = null;
79
+ }
80
+ onStop?.();
81
+ }, [onStop]);
82
+ // 로딩 상태 설정 함수
83
+ const setLoadingState = useCallback((loading) => {
84
+ if (loading) {
85
+ startLoading();
86
+ }
87
+ else {
88
+ stopLoading();
89
+ }
90
+ }, [startLoading, stopLoading]);
91
+ // 모션 시작 함수
92
+ const start = useCallback(() => {
93
+ if (!isVisible) {
94
+ setIsVisible(true);
95
+ startLoading();
96
+ }
97
+ }, [isVisible, startLoading]);
98
+ // 모션 중단 함수
99
+ const stop = useCallback(() => {
100
+ stopLoading();
101
+ }, [stopLoading]);
102
+ // 모션 리셋 함수
103
+ const reset = useCallback(() => {
104
+ setIsVisible(false);
105
+ setIsAnimating(false);
106
+ setProgress(0);
107
+ setIsLoading(false);
108
+ setRotationAngle(0);
109
+ setPulseScale(1);
110
+ setBounceOffset(0);
111
+ setWaveProgress(0);
112
+ setDotProgress(0);
113
+ setBarProgress(0);
114
+ startTimeRef.current = 0;
115
+ if (animationRef.current) {
116
+ cancelAnimationFrame(animationRef.current);
117
+ animationRef.current = null;
118
+ }
119
+ onReset?.();
120
+ }, [onReset]);
121
+ // 모션 일시정지 함수
122
+ const pause = useCallback(() => {
123
+ setIsAnimating(false);
124
+ if (animationRef.current) {
125
+ cancelAnimationFrame(animationRef.current);
126
+ animationRef.current = null;
127
+ }
128
+ }, []);
129
+ // 모션 재개 함수
130
+ const resume = useCallback(() => {
131
+ if (isVisible && !isAnimating) {
132
+ setIsAnimating(true);
133
+ runAnimation();
134
+ }
135
+ }, [isVisible, isAnimating, runAnimation]);
136
+ // 자동 시작
137
+ useEffect(() => {
138
+ if (autoStart) {
139
+ startLoading();
140
+ }
141
+ }, [autoStart, startLoading]);
142
+ // 컴포넌트 언마운트 시 정리
143
+ useEffect(() => {
144
+ return () => {
145
+ if (animationRef.current) {
146
+ cancelAnimationFrame(animationRef.current);
147
+ }
148
+ };
149
+ }, []);
150
+ // 스피너 스타일 계산
151
+ const getSpinnerStyle = () => {
152
+ const baseStyle = {
153
+ width: size,
154
+ height: size,
155
+ backgroundColor: 'transparent',
156
+ position: 'relative',
157
+ display: 'inline-block'
158
+ };
159
+ switch (type) {
160
+ case 'rotate':
161
+ return {
162
+ ...baseStyle,
163
+ border: `${thickness}px solid ${backgroundColor}`,
164
+ borderTop: `${thickness}px solid ${color}`,
165
+ borderRadius: '50%',
166
+ transform: `rotate(${rotationAngle}deg)`,
167
+ transition: `transform ${duration}ms ${easing}`
168
+ };
169
+ case 'pulse':
170
+ return {
171
+ ...baseStyle,
172
+ backgroundColor: color,
173
+ borderRadius: '50%',
174
+ transform: `scale(${pulseScale})`,
175
+ transition: `transform ${duration}ms ${easing}`
176
+ };
177
+ case 'bounce':
178
+ return {
179
+ ...baseStyle,
180
+ backgroundColor: color,
181
+ borderRadius: '50%',
182
+ transform: `translateY(${bounceOffset}px)`,
183
+ transition: `transform ${duration}ms ${easing}`
184
+ };
185
+ case 'wave':
186
+ return {
187
+ ...baseStyle,
188
+ display: 'flex',
189
+ alignItems: 'center',
190
+ justifyContent: 'space-between'
191
+ };
192
+ case 'dots':
193
+ return {
194
+ ...baseStyle,
195
+ display: 'flex',
196
+ alignItems: 'center',
197
+ justifyContent: 'space-between'
198
+ };
199
+ case 'bars':
200
+ return {
201
+ ...baseStyle,
202
+ display: 'flex',
203
+ alignItems: 'center',
204
+ justifyContent: 'space-between'
205
+ };
206
+ default:
207
+ return baseStyle;
208
+ }
209
+ };
210
+ // 웨이브 바 스타일 생성
211
+ const getWaveBars = () => {
212
+ return Array.from({ length: waveCount }, (_, index) => {
213
+ const delay = index * (duration / waveCount);
214
+ const height = size * (0.3 + 0.7 * Math.sin((waveProgress + index / waveCount) * Math.PI * 2));
215
+ return {
216
+ width: thickness,
217
+ height: `${height}px`,
218
+ backgroundColor: color,
219
+ borderRadius: thickness / 2,
220
+ animationDelay: `${delay}ms`,
221
+ transition: `height ${duration}ms ${easing}`
222
+ };
223
+ });
224
+ };
225
+ // 점 스타일 생성
226
+ const getDots = () => {
227
+ return Array.from({ length: dotCount }, (_, index) => {
228
+ const delay = index * (duration / dotCount);
229
+ const opacity = 0.3 + 0.7 * Math.sin((dotProgress + index / dotCount) * Math.PI * 2);
230
+ const scale = 0.8 + 0.4 * Math.sin((dotProgress + index / dotCount) * Math.PI * 2);
231
+ return {
232
+ width: thickness * 2,
233
+ height: thickness * 2,
234
+ backgroundColor: color,
235
+ borderRadius: '50%',
236
+ opacity,
237
+ transform: `scale(${scale})`,
238
+ animationDelay: `${delay}ms`,
239
+ transition: `all ${duration}ms ${easing}`
240
+ };
241
+ });
242
+ };
243
+ // 바 스타일 생성
244
+ const getBars = () => {
245
+ return Array.from({ length: barCount }, (_, index) => {
246
+ const delay = index * (duration / barCount);
247
+ const height = size * (0.2 + 0.8 * Math.sin((barProgress + index / barCount) * Math.PI * 2));
248
+ return {
249
+ width: thickness,
250
+ height: `${height}px`,
251
+ backgroundColor: color,
252
+ borderRadius: thickness / 2,
253
+ animationDelay: `${delay}ms`,
254
+ transition: `height ${duration}ms ${easing}`
255
+ };
256
+ });
257
+ };
258
+ const style = getSpinnerStyle();
259
+ return {
260
+ ref,
261
+ isVisible,
262
+ isAnimating,
263
+ style,
264
+ progress,
265
+ start,
266
+ stop,
267
+ reset,
268
+ pause,
269
+ resume,
270
+ isLoading,
271
+ spinnerType: type,
272
+ rotationAngle,
273
+ pulseScale,
274
+ bounceOffset,
275
+ waveProgress,
276
+ dotProgress,
277
+ barProgress,
278
+ startLoading,
279
+ stopLoading,
280
+ setLoadingState
281
+ };
282
+ }
283
+ //# sourceMappingURL=useLoadingSpinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadingSpinner.js","sourceRoot":"","sources":["../../src/hooks/useLoadingSpinner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import { BaseMotionOptions, BaseMotionReturn, MotionElement } from '../types';
2
+ export interface MotionOptions extends BaseMotionOptions {
3
+ scale?: number | {
4
+ from: number;
5
+ to: number;
6
+ };
7
+ opacity?: number | {
8
+ from: number;
9
+ to: number;
10
+ };
11
+ rotate?: number | {
12
+ from: number;
13
+ to: number;
14
+ };
15
+ translateX?: number | {
16
+ from: number;
17
+ to: number;
18
+ };
19
+ translateY?: number | {
20
+ from: number;
21
+ to: number;
22
+ };
23
+ skewX?: number | {
24
+ from: number;
25
+ to: number;
26
+ };
27
+ skewY?: number | {
28
+ from: number;
29
+ to: number;
30
+ };
31
+ backgroundColor?: string | {
32
+ from: string;
33
+ to: string;
34
+ };
35
+ color?: string | {
36
+ from: string;
37
+ to: string;
38
+ };
39
+ borderColor?: string | {
40
+ from: string;
41
+ to: string;
42
+ };
43
+ width?: number | string | {
44
+ from: number | string;
45
+ to: number | string;
46
+ };
47
+ height?: number | string | {
48
+ from: number | string;
49
+ to: number | string;
50
+ };
51
+ borderRadius?: number | string | {
52
+ from: number | string;
53
+ to: number | string;
54
+ };
55
+ borderWidth?: number | {
56
+ from: number;
57
+ to: number;
58
+ };
59
+ boxShadow?: string | {
60
+ from: string;
61
+ to: string;
62
+ };
63
+ blur?: number | {
64
+ from: number;
65
+ to: number;
66
+ };
67
+ brightness?: number | {
68
+ from: number;
69
+ to: number;
70
+ };
71
+ contrast?: number | {
72
+ from: number;
73
+ to: number;
74
+ };
75
+ grayscale?: number | {
76
+ from: number;
77
+ to: number;
78
+ };
79
+ hueRotate?: number | {
80
+ from: number;
81
+ to: number;
82
+ };
83
+ saturate?: number | {
84
+ from: number;
85
+ to: number;
86
+ };
87
+ sepia?: number | {
88
+ from: number;
89
+ to: number;
90
+ };
91
+ playOnMount?: boolean;
92
+ loop?: boolean;
93
+ yoyo?: boolean;
94
+ stagger?: number;
95
+ onUpdate?: (progress: number) => void;
96
+ }
97
+ export declare function useMotion<T extends MotionElement = HTMLDivElement>(options?: MotionOptions): BaseMotionReturn<T> & {
98
+ play: () => void;
99
+ reverse: () => void;
100
+ seek: (progress: number) => void;
101
+ getValue: (property: string) => any;
102
+ };
103
+ //# sourceMappingURL=useMotion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMotion.d.ts","sourceRoot":"","sources":["../../src/hooks/useMotion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ import { useRef, useState, useEffect, useCallback } from 'react';
2
+ export function useMotion(options = {}) {
3
+ const { duration = 1000, easing = 'ease-out', delay = 0, threshold = 0.1, triggerOnce = true, autoStart = false, playOnMount = false, loop = false, yoyo = false, stagger = 0, scale = { from: 1, to: 1 }, opacity = { from: 1, to: 1 }, rotate = { from: 0, to: 0 }, translateX = { from: 0, to: 0 }, translateY = { from: 0, to: 0 }, skewX = { from: 0, to: 0 }, skewY = { from: 0, to: 0 }, backgroundColor, color, borderColor, width, height, borderRadius, borderWidth, boxShadow, blur = { from: 0, to: 0 }, brightness = { from: 100, to: 100 }, contrast = { from: 100, to: 100 }, grayscale = { from: 0, to: 0 }, hueRotate = { from: 0, to: 0 }, saturate = { from: 100, to: 100 }, sepia = { from: 0, to: 0 }, onComplete, onStart, onStop, onReset, onUpdate } = options;
4
+ const ref = useRef(null);
5
+ const [isVisible, setIsVisible] = useState(false);
6
+ const [isAnimating, setIsAnimating] = useState(false);
7
+ const [progress, setProgress] = useState(0);
8
+ const [isReversed, setIsReversed] = useState(false);
9
+ const observerRef = useRef(null);
10
+ const animationRef = useRef(null);
11
+ // 값 정규화 함수
12
+ const normalizeValue = (value) => {
13
+ if (typeof value === 'object' && 'from' in value && 'to' in value) {
14
+ return value;
15
+ }
16
+ return { from: value, to: value };
17
+ };
18
+ // 정규화된 값들
19
+ const normalizedScale = normalizeValue(scale);
20
+ const normalizedOpacity = normalizeValue(opacity);
21
+ const normalizedRotate = normalizeValue(rotate);
22
+ const normalizedTranslateX = normalizeValue(translateX);
23
+ const normalizedTranslateY = normalizeValue(translateY);
24
+ const normalizedSkewX = normalizeValue(skewX);
25
+ const normalizedSkewY = normalizeValue(skewY);
26
+ const normalizedBlur = normalizeValue(blur);
27
+ const normalizedBrightness = normalizeValue(brightness);
28
+ const normalizedContrast = normalizeValue(contrast);
29
+ const normalizedGrayscale = normalizeValue(grayscale);
30
+ const normalizedHueRotate = normalizeValue(hueRotate);
31
+ const normalizedSaturate = normalizeValue(saturate);
32
+ const normalizedSepia = normalizeValue(sepia);
33
+ // 보간 함수
34
+ const interpolate = (from, to, progress) => {
35
+ return from + (to - from) * progress;
36
+ };
37
+ // 애니메이션 실행 함수
38
+ const runAnimation = useCallback((startTime, isReverse = false) => {
39
+ if (!isAnimating)
40
+ return;
41
+ const animate = (currentTime) => {
42
+ if (!isAnimating)
43
+ return;
44
+ const elapsed = currentTime - startTime;
45
+ const currentProgress = Math.min(elapsed / duration, 1);
46
+ // 진행률 계산 (정방향/역방향)
47
+ let finalProgress = isReverse ? 1 - currentProgress : currentProgress;
48
+ // 이징 적용
49
+ const easedProgress = finalProgress;
50
+ setProgress(easedProgress);
51
+ // 업데이트 콜백 호출
52
+ onUpdate?.(easedProgress);
53
+ if (currentProgress < 1) {
54
+ animationRef.current = requestAnimationFrame(animate);
55
+ }
56
+ else {
57
+ // 애니메이션 완료
58
+ setIsAnimating(false);
59
+ // 루프 또는 요요 처리
60
+ if (loop || yoyo) {
61
+ if (yoyo) {
62
+ setIsReversed(!isReversed);
63
+ setTimeout(() => {
64
+ if (isAnimating)
65
+ return;
66
+ setIsAnimating(true);
67
+ runAnimation(Date.now(), !isReversed);
68
+ }, stagger);
69
+ }
70
+ else {
71
+ setTimeout(() => {
72
+ if (isAnimating)
73
+ return;
74
+ setIsAnimating(true);
75
+ runAnimation(Date.now(), isReverse);
76
+ }, stagger);
77
+ }
78
+ }
79
+ else {
80
+ onComplete?.();
81
+ }
82
+ }
83
+ };
84
+ animationRef.current = requestAnimationFrame(animate);
85
+ }, [isAnimating, duration, loop, yoyo, stagger, onComplete, onUpdate]);
86
+ // 모션 시작 함수
87
+ const start = useCallback(() => {
88
+ if (!isVisible) {
89
+ setIsVisible(true);
90
+ setIsAnimating(true);
91
+ setProgress(0);
92
+ onStart?.();
93
+ runAnimation(Date.now(), isReversed);
94
+ }
95
+ }, [isVisible, onStart, runAnimation, isReversed]);
96
+ // 재생 함수
97
+ const play = useCallback(() => {
98
+ if (!isAnimating) {
99
+ setIsAnimating(true);
100
+ onStart?.();
101
+ runAnimation(Date.now(), isReversed);
102
+ }
103
+ }, [isAnimating, onStart, runAnimation, isReversed]);
104
+ // 역방향 재생 함수
105
+ const reverse = useCallback(() => {
106
+ setIsReversed(!isReversed);
107
+ if (!isAnimating) {
108
+ setIsAnimating(true);
109
+ onStart?.();
110
+ runAnimation(Date.now(), !isReversed);
111
+ }
112
+ }, [isReversed, isAnimating, onStart, runAnimation]);
113
+ // 진행률 이동 함수
114
+ const seek = useCallback((targetProgress) => {
115
+ const clampedProgress = Math.max(0, Math.min(1, targetProgress));
116
+ setProgress(clampedProgress);
117
+ onUpdate?.(clampedProgress);
118
+ }, [onUpdate]);
119
+ // 특정 속성의 현재 값 가져오기
120
+ const getValue = useCallback((property) => {
121
+ const currentProgress = progress;
122
+ switch (property) {
123
+ case 'scale':
124
+ return interpolate(normalizedScale.from, normalizedScale.to, currentProgress);
125
+ case 'opacity':
126
+ return interpolate(normalizedOpacity.from, normalizedOpacity.to, currentProgress);
127
+ case 'rotate':
128
+ return interpolate(normalizedRotate.from, normalizedRotate.to, currentProgress);
129
+ case 'translateX':
130
+ return interpolate(normalizedTranslateX.from, normalizedTranslateX.to, currentProgress);
131
+ case 'translateY':
132
+ return interpolate(normalizedTranslateY.from, normalizedTranslateY.to, currentProgress);
133
+ case 'skewX':
134
+ return interpolate(normalizedSkewX.from, normalizedSkewX.to, currentProgress);
135
+ case 'skewY':
136
+ return interpolate(normalizedSkewY.from, normalizedSkewY.to, currentProgress);
137
+ case 'blur':
138
+ return interpolate(normalizedBlur.from, normalizedBlur.to, currentProgress);
139
+ case 'brightness':
140
+ return interpolate(normalizedBrightness.from, normalizedBrightness.to, currentProgress);
141
+ case 'contrast':
142
+ return interpolate(normalizedContrast.from, normalizedContrast.to, currentProgress);
143
+ case 'grayscale':
144
+ return interpolate(normalizedGrayscale.from, normalizedGrayscale.to, currentProgress);
145
+ case 'hueRotate':
146
+ return interpolate(normalizedHueRotate.from, normalizedHueRotate.to, currentProgress);
147
+ case 'saturate':
148
+ return interpolate(normalizedSaturate.from, normalizedSaturate.to, currentProgress);
149
+ case 'sepia':
150
+ return interpolate(normalizedSepia.from, normalizedSepia.to, currentProgress);
151
+ default:
152
+ return null;
153
+ }
154
+ }, [progress, normalizedScale, normalizedOpacity, normalizedRotate, normalizedTranslateX,
155
+ normalizedTranslateY, normalizedSkewX, normalizedSkewY, normalizedBlur, normalizedBrightness,
156
+ normalizedContrast, normalizedGrayscale, normalizedHueRotate, normalizedSaturate, normalizedSepia]);
157
+ // 모션 중단 함수
158
+ const stop = useCallback(() => {
159
+ setIsAnimating(false);
160
+ if (animationRef.current) {
161
+ cancelAnimationFrame(animationRef.current);
162
+ animationRef.current = null;
163
+ }
164
+ onStop?.();
165
+ }, [onStop]);
166
+ // 모션 리셋 함수
167
+ const reset = useCallback(() => {
168
+ setIsVisible(false);
169
+ setIsAnimating(false);
170
+ setProgress(0);
171
+ setIsReversed(false);
172
+ if (animationRef.current) {
173
+ cancelAnimationFrame(animationRef.current);
174
+ animationRef.current = null;
175
+ }
176
+ onReset?.();
177
+ }, [onReset]);
178
+ // 모션 일시정지 함수
179
+ const pause = useCallback(() => {
180
+ setIsAnimating(false);
181
+ if (animationRef.current) {
182
+ cancelAnimationFrame(animationRef.current);
183
+ animationRef.current = null;
184
+ }
185
+ }, []);
186
+ // 모션 재개 함수
187
+ const resume = useCallback(() => {
188
+ if (isVisible && !isAnimating) {
189
+ setIsAnimating(true);
190
+ runAnimation(Date.now(), isReversed);
191
+ }
192
+ }, [isVisible, isAnimating, runAnimation, isReversed]);
193
+ // Intersection Observer 설정
194
+ useEffect(() => {
195
+ if (!ref.current || !autoStart)
196
+ return;
197
+ observerRef.current = new IntersectionObserver((entries) => {
198
+ entries.forEach((entry) => {
199
+ if (entry.isIntersecting) {
200
+ start();
201
+ if (triggerOnce) {
202
+ observerRef.current?.disconnect();
203
+ }
204
+ }
205
+ });
206
+ }, { threshold });
207
+ observerRef.current.observe(ref.current);
208
+ return () => {
209
+ if (observerRef.current) {
210
+ observerRef.current.disconnect();
211
+ }
212
+ };
213
+ }, [autoStart, threshold, triggerOnce, start]);
214
+ // 마운트 시 자동 시작
215
+ useEffect(() => {
216
+ if (playOnMount) {
217
+ start();
218
+ }
219
+ }, [playOnMount, start]);
220
+ // 컴포넌트 언마운트 시 정리
221
+ useEffect(() => {
222
+ return () => {
223
+ if (animationRef.current) {
224
+ cancelAnimationFrame(animationRef.current);
225
+ }
226
+ };
227
+ }, []);
228
+ // 현재 진행률에 따른 스타일 계산
229
+ const style = {
230
+ transform: `
231
+ scale(${getValue('scale')})
232
+ rotate(${getValue('rotate')}deg)
233
+ translate(${getValue('translateX')}px, ${getValue('translateY')}px)
234
+ skew(${getValue('skewX')}deg, ${getValue('skewY')}deg)
235
+ `,
236
+ opacity: getValue('opacity'),
237
+ filter: `
238
+ blur(${getValue('blur')}px)
239
+ brightness(${getValue('brightness')}%)
240
+ contrast(${getValue('contrast')}%)
241
+ grayscale(${getValue('grayscale')}%)
242
+ hue-rotate(${getValue('hueRotate')}deg)
243
+ saturate(${getValue('saturate')}%)
244
+ sepia(${getValue('sepia')}%)
245
+ `,
246
+ transition: `all ${duration}ms ${easing}`,
247
+ willChange: 'transform, opacity, filter'
248
+ };
249
+ return {
250
+ ref,
251
+ isVisible,
252
+ isAnimating,
253
+ style,
254
+ progress,
255
+ start,
256
+ stop,
257
+ reset,
258
+ pause,
259
+ resume,
260
+ play,
261
+ reverse,
262
+ seek,
263
+ getValue
264
+ };
265
+ }
266
+ //# sourceMappingURL=useMotion.js.map