ai-react-animations 1.0.0 → 1.1.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/dist/AiCreating.cjs +1 -0
- package/dist/AiCreating.mjs +146 -0
- package/dist/AiCreating2.cjs +1 -0
- package/dist/AiCreating2.mjs +203 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.js +6 -149
- package/dist/index.mjs +211 -1
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./index.mjs').AiCreating;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AiCreating - AI Assistant Processing Animation
|
|
3
|
+
* Shows AI helping user with their tasks/requests
|
|
4
|
+
* Relatable user scenario: AI reading, processing, delivering results
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
|
+
// CSS: import 'ai-react-animations/styles.css'
|
|
11
|
+
|
|
12
|
+
export interface AiCreatingProps {
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
onComplete?: () => void;
|
|
15
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function AiCreating({
|
|
19
|
+
isLoading,
|
|
20
|
+
onComplete,
|
|
21
|
+
size = 'md'
|
|
22
|
+
}: AiCreatingProps) {
|
|
23
|
+
const [stage, setStage] = useState<'idle' | 'reading' | 'processing' | 'delivering' | 'complete'>('idle');
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (isLoading) {
|
|
27
|
+
setStage('reading');
|
|
28
|
+
const t1 = setTimeout(() => setStage('processing'), 1800);
|
|
29
|
+
const t2 = setTimeout(() => setStage('delivering'), 3600);
|
|
30
|
+
return () => { clearTimeout(t1); clearTimeout(t2); };
|
|
31
|
+
} else if (stage !== 'idle' && stage !== 'reading') {
|
|
32
|
+
setStage('complete');
|
|
33
|
+
const t = setTimeout(() => {
|
|
34
|
+
onComplete?.();
|
|
35
|
+
setStage('idle');
|
|
36
|
+
}, 1200);
|
|
37
|
+
return () => clearTimeout(t);
|
|
38
|
+
}
|
|
39
|
+
}, [isLoading]);
|
|
40
|
+
|
|
41
|
+
const stageText = {
|
|
42
|
+
idle: '',
|
|
43
|
+
reading: 'Reading your request',
|
|
44
|
+
processing: 'Working on it',
|
|
45
|
+
delivering: 'Almost there',
|
|
46
|
+
complete: 'Done!'
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div className={`ai-creating-wrapper size-${size}`}>
|
|
51
|
+
<div className={`ai-creating-container stage-${stage}`}>
|
|
52
|
+
|
|
53
|
+
{/* Animated Background Particles */}
|
|
54
|
+
<div className="particles">
|
|
55
|
+
<span></span><span></span><span></span>
|
|
56
|
+
<span></span><span></span><span></span>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{/* Main Content */}
|
|
60
|
+
<div className="ai-scene">
|
|
61
|
+
|
|
62
|
+
{/* AI Robot Character */}
|
|
63
|
+
<div className={`ai-robot ${stage}`}>
|
|
64
|
+
<div className="robot-head">
|
|
65
|
+
<div className="robot-face">
|
|
66
|
+
<div className="robot-eyes">
|
|
67
|
+
<div className="eye left">
|
|
68
|
+
<div className="pupil"></div>
|
|
69
|
+
</div>
|
|
70
|
+
<div className="eye right">
|
|
71
|
+
<div className="pupil"></div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
<div className="robot-mouth"></div>
|
|
75
|
+
</div>
|
|
76
|
+
<div className="antenna">
|
|
77
|
+
<div className="antenna-ball"></div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
<div className="robot-body">
|
|
81
|
+
<div className="chest-light"></div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{/* User Request Card - Reading Stage */}
|
|
86
|
+
{(stage === 'reading' || stage === 'processing') && (
|
|
87
|
+
<div className={`request-card ${stage}`}>
|
|
88
|
+
<div className="card-icon">📝</div>
|
|
89
|
+
<div className="card-lines">
|
|
90
|
+
<span className="line"></span>
|
|
91
|
+
<span className="line short"></span>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{/* Processing Gears - Processing Stage */}
|
|
97
|
+
{stage === 'processing' && (
|
|
98
|
+
<div className="processing-visual">
|
|
99
|
+
<div className="gear gear-1">⚙️</div>
|
|
100
|
+
<div className="gear gear-2">⚙️</div>
|
|
101
|
+
<div className="sparkles">
|
|
102
|
+
<span>✨</span><span>✨</span><span>✨</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
|
|
107
|
+
{/* Result Card - Delivering Stage */}
|
|
108
|
+
{(stage === 'delivering' || stage === 'complete') && (
|
|
109
|
+
<div className={`result-card ${stage}`}>
|
|
110
|
+
<div className="result-icon">{stage === 'complete' ? '✅' : '📄'}</div>
|
|
111
|
+
<div className="result-lines">
|
|
112
|
+
<span className="line"></span>
|
|
113
|
+
<span className="line"></span>
|
|
114
|
+
<span className="line short"></span>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
)}
|
|
118
|
+
|
|
119
|
+
{/* Status Text */}
|
|
120
|
+
{stage !== 'idle' && (
|
|
121
|
+
<div className="status-area">
|
|
122
|
+
<span className={`status-text ${stage}`}>{stageText[stage]}</span>
|
|
123
|
+
{stage !== 'complete' && (
|
|
124
|
+
<span className="dots">
|
|
125
|
+
<span>.</span><span>.</span><span>.</span>
|
|
126
|
+
</span>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
{/* Progress Indicator */}
|
|
132
|
+
<div className="progress-track">
|
|
133
|
+
<div className={`progress-bar stage-${stage}`}></div>
|
|
134
|
+
<div className="progress-steps">
|
|
135
|
+
<div className={`step ${stage !== 'idle' ? 'active' : ''}`}></div>
|
|
136
|
+
<div className={`step ${stage === 'processing' || stage === 'delivering' || stage === 'complete' ? 'active' : ''}`}></div>
|
|
137
|
+
<div className={`step ${stage === 'delivering' || stage === 'complete' ? 'active' : ''}`}></div>
|
|
138
|
+
<div className={`step ${stage === 'complete' ? 'active' : ''}`}></div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./index.mjs').AiCreating2;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
4
|
+
import { Sparkles, Brain, Zap } from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
export interface AiCreating2Props {
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
onComplete?: () => void;
|
|
9
|
+
message?: string;
|
|
10
|
+
subMessage?: string;
|
|
11
|
+
/** Primary color for animations (hex) */
|
|
12
|
+
primaryColor?: string;
|
|
13
|
+
/** Background color (hex) */
|
|
14
|
+
backgroundColor?: string;
|
|
15
|
+
/** Text color (hex) */
|
|
16
|
+
textColor?: string;
|
|
17
|
+
/** If true, renders in a contained box instead of full-screen overlay */
|
|
18
|
+
contained?: boolean;
|
|
19
|
+
/** Status messages to cycle through */
|
|
20
|
+
statusMessages?: Array<{ icon: 'sparkles' | 'brain' | 'zap'; text: string }>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const iconMap = {
|
|
24
|
+
sparkles: Sparkles,
|
|
25
|
+
brain: Brain,
|
|
26
|
+
zap: Zap,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function AiCreating2({
|
|
30
|
+
isLoading,
|
|
31
|
+
onComplete,
|
|
32
|
+
message = "Creating your plan...",
|
|
33
|
+
subMessage = "AI is analyzing your goals and building a personalized plan",
|
|
34
|
+
primaryColor = "#6366F1",
|
|
35
|
+
backgroundColor = "#0f172a",
|
|
36
|
+
textColor = "#ffffff",
|
|
37
|
+
contained = false,
|
|
38
|
+
statusMessages = [
|
|
39
|
+
{ icon: 'sparkles', text: 'Analyzing your goals' },
|
|
40
|
+
{ icon: 'brain', text: 'Designing daily structure' },
|
|
41
|
+
{ icon: 'zap', text: 'Generating action items' },
|
|
42
|
+
],
|
|
43
|
+
}: AiCreating2Props) {
|
|
44
|
+
|
|
45
|
+
const containerClass = contained
|
|
46
|
+
? "relative w-full h-full min-h-[400px] rounded-xl flex items-center justify-center overflow-hidden"
|
|
47
|
+
: "fixed inset-0 z-[70] flex items-center justify-center";
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<AnimatePresence>
|
|
51
|
+
{isLoading && (
|
|
52
|
+
<motion.div
|
|
53
|
+
initial={{ opacity: 0 }}
|
|
54
|
+
animate={{ opacity: 1 }}
|
|
55
|
+
exit={{ opacity: 0 }}
|
|
56
|
+
className={containerClass}
|
|
57
|
+
style={{ backgroundColor }}
|
|
58
|
+
>
|
|
59
|
+
<div className="text-center max-w-md px-6">
|
|
60
|
+
{/* Animated AI Brain */}
|
|
61
|
+
<div className="relative w-32 h-32 mx-auto mb-8">
|
|
62
|
+
{/* Outer rotating ring */}
|
|
63
|
+
<motion.div
|
|
64
|
+
className="absolute inset-0 rounded-full"
|
|
65
|
+
style={{ border: `2px solid ${primaryColor}30` }}
|
|
66
|
+
animate={{ rotate: 360 }}
|
|
67
|
+
transition={{ duration: 8, repeat: Infinity, ease: "linear" }}
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
{/* Middle pulsing ring */}
|
|
71
|
+
<motion.div
|
|
72
|
+
className="absolute inset-2 rounded-full"
|
|
73
|
+
style={{ border: `2px solid ${primaryColor}80` }}
|
|
74
|
+
animate={{
|
|
75
|
+
scale: [1, 1.1, 1],
|
|
76
|
+
opacity: [0.5, 1, 0.5]
|
|
77
|
+
}}
|
|
78
|
+
transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
{/* Inner ring with gradient */}
|
|
82
|
+
<motion.div
|
|
83
|
+
className="absolute inset-4 rounded-full"
|
|
84
|
+
style={{
|
|
85
|
+
background: `linear-gradient(135deg, ${primaryColor}40, ${primaryColor}10)`
|
|
86
|
+
}}
|
|
87
|
+
animate={{ rotate: -360 }}
|
|
88
|
+
transition={{ duration: 12, repeat: Infinity, ease: "linear" }}
|
|
89
|
+
/>
|
|
90
|
+
|
|
91
|
+
{/* Center icon */}
|
|
92
|
+
<motion.div
|
|
93
|
+
className="absolute inset-0 flex items-center justify-center"
|
|
94
|
+
animate={{
|
|
95
|
+
scale: [1, 1.05, 1],
|
|
96
|
+
}}
|
|
97
|
+
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
|
|
98
|
+
>
|
|
99
|
+
<Brain className="w-12 h-12" style={{ color: primaryColor }} />
|
|
100
|
+
</motion.div>
|
|
101
|
+
|
|
102
|
+
{/* Floating particles */}
|
|
103
|
+
{[...Array(6)].map((_, i) => (
|
|
104
|
+
<motion.div
|
|
105
|
+
key={i}
|
|
106
|
+
className="absolute w-2 h-2 rounded-full"
|
|
107
|
+
style={{
|
|
108
|
+
top: '50%',
|
|
109
|
+
left: '50%',
|
|
110
|
+
backgroundColor: primaryColor,
|
|
111
|
+
}}
|
|
112
|
+
animate={{
|
|
113
|
+
x: [0, Math.cos(i * 60 * Math.PI / 180) * 60],
|
|
114
|
+
y: [0, Math.sin(i * 60 * Math.PI / 180) * 60],
|
|
115
|
+
opacity: [0, 1, 0],
|
|
116
|
+
scale: [0, 1, 0],
|
|
117
|
+
}}
|
|
118
|
+
transition={{
|
|
119
|
+
duration: 2,
|
|
120
|
+
repeat: Infinity,
|
|
121
|
+
delay: i * 0.3,
|
|
122
|
+
ease: "easeOut"
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
{/* Text */}
|
|
129
|
+
<motion.h3
|
|
130
|
+
className="text-2xl font-bold mb-3"
|
|
131
|
+
style={{ color: textColor }}
|
|
132
|
+
animate={{ opacity: [0.7, 1, 0.7] }}
|
|
133
|
+
transition={{ duration: 2, repeat: Infinity }}
|
|
134
|
+
>
|
|
135
|
+
{message}
|
|
136
|
+
</motion.h3>
|
|
137
|
+
|
|
138
|
+
<motion.p
|
|
139
|
+
className="text-sm mb-6"
|
|
140
|
+
style={{ color: `${textColor}99` }}
|
|
141
|
+
initial={{ opacity: 0, y: 10 }}
|
|
142
|
+
animate={{ opacity: 1, y: 0 }}
|
|
143
|
+
transition={{ delay: 0.3 }}
|
|
144
|
+
>
|
|
145
|
+
{subMessage}
|
|
146
|
+
</motion.p>
|
|
147
|
+
|
|
148
|
+
{/* Progress dots */}
|
|
149
|
+
<div className="flex justify-center gap-2">
|
|
150
|
+
{[0, 1, 2, 3, 4].map((i) => (
|
|
151
|
+
<motion.div
|
|
152
|
+
key={i}
|
|
153
|
+
className="w-2 h-2 rounded-full"
|
|
154
|
+
style={{ backgroundColor: primaryColor }}
|
|
155
|
+
animate={{
|
|
156
|
+
opacity: [0.3, 1, 0.3],
|
|
157
|
+
scale: [0.8, 1.2, 0.8],
|
|
158
|
+
}}
|
|
159
|
+
transition={{
|
|
160
|
+
duration: 1,
|
|
161
|
+
repeat: Infinity,
|
|
162
|
+
delay: i * 0.15,
|
|
163
|
+
}}
|
|
164
|
+
/>
|
|
165
|
+
))}
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Status messages */}
|
|
169
|
+
<motion.div
|
|
170
|
+
className="mt-8 space-y-2"
|
|
171
|
+
initial={{ opacity: 0 }}
|
|
172
|
+
animate={{ opacity: 1 }}
|
|
173
|
+
transition={{ delay: 1 }}
|
|
174
|
+
>
|
|
175
|
+
{statusMessages.map((status, index) => {
|
|
176
|
+
const Icon = iconMap[status.icon];
|
|
177
|
+
return (
|
|
178
|
+
<motion.div
|
|
179
|
+
key={index}
|
|
180
|
+
className="flex items-center justify-center gap-2 text-sm"
|
|
181
|
+
initial={{ opacity: 0, x: -20 }}
|
|
182
|
+
animate={{ opacity: [0, 1, 1, 0.5], x: 0 }}
|
|
183
|
+
transition={{
|
|
184
|
+
delay: index * 2,
|
|
185
|
+
duration: 4,
|
|
186
|
+
repeat: Infinity,
|
|
187
|
+
repeatDelay: (statusMessages.length - 1) * 2 + 4
|
|
188
|
+
}}
|
|
189
|
+
>
|
|
190
|
+
<Icon className="w-4 h-4" style={{ color: primaryColor }} />
|
|
191
|
+
<span style={{ color: `${textColor}99` }}>{status.text}</span>
|
|
192
|
+
</motion.div>
|
|
193
|
+
);
|
|
194
|
+
})}
|
|
195
|
+
</motion.div>
|
|
196
|
+
</div>
|
|
197
|
+
</motion.div>
|
|
198
|
+
)}
|
|
199
|
+
</AnimatePresence>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export default AiCreating2;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
1
|
+
import { FC, ComponentType } from 'react';
|
|
2
2
|
|
|
3
|
+
// AiCreating Props
|
|
3
4
|
export interface AiCreatingProps {
|
|
4
5
|
isLoading: boolean;
|
|
5
6
|
onComplete?: () => void;
|
|
6
7
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
// AiCreating2 Props
|
|
11
|
+
export interface AiCreating2Props {
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
onComplete?: () => void;
|
|
14
|
+
message?: string;
|
|
15
|
+
subMessage?: string;
|
|
16
|
+
primaryColor?: string;
|
|
17
|
+
backgroundColor?: string;
|
|
18
|
+
textColor?: string;
|
|
19
|
+
contained?: boolean;
|
|
20
|
+
statusMessages?: Array<{ icon: 'sparkles' | 'brain' | 'zap'; text: string }>;
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
declare const AiCreating: FC<AiCreatingProps>;
|
|
24
|
+
declare const AiCreating2: FC<AiCreating2Props>;
|
|
25
|
+
|
|
26
|
+
export { AiCreating, AiCreating2 };
|
|
10
27
|
export default AiCreating;
|
package/dist/index.js
CHANGED
|
@@ -1,154 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* AiCreating - AI Assistant Processing Animation
|
|
7
|
-
* Shows AI helping user with their tasks/requests
|
|
8
|
-
* Relatable user scenario: AI reading, processing, delivering results
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// CSS must be imported separately: import 'ai-react-animations/styles.css'
|
|
15
|
-
|
|
16
|
-
interface AiCreatingProps {
|
|
17
|
-
isLoading: boolean;
|
|
18
|
-
onComplete?: () => void;
|
|
19
|
-
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function AiCreating({
|
|
23
|
-
isLoading,
|
|
24
|
-
onComplete,
|
|
25
|
-
size = 'md'
|
|
26
|
-
}: AiCreatingProps) {
|
|
27
|
-
const [stage, setStage] = useState<'idle' | 'reading' | 'processing' | 'delivering' | 'complete'>('idle');
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (isLoading) {
|
|
31
|
-
setStage('reading');
|
|
32
|
-
const t1 = setTimeout(() => setStage('processing'), 1800);
|
|
33
|
-
const t2 = setTimeout(() => setStage('delivering'), 3600);
|
|
34
|
-
return () => { clearTimeout(t1); clearTimeout(t2); };
|
|
35
|
-
} else if (stage !== 'idle' && stage !== 'reading') {
|
|
36
|
-
setStage('complete');
|
|
37
|
-
const t = setTimeout(() => {
|
|
38
|
-
onComplete?.();
|
|
39
|
-
setStage('idle');
|
|
40
|
-
}, 1200);
|
|
41
|
-
return () => clearTimeout(t);
|
|
42
|
-
}
|
|
43
|
-
}, [isLoading]);
|
|
44
|
-
|
|
45
|
-
const stageText = {
|
|
46
|
-
idle: '',
|
|
47
|
-
reading: 'Reading your request',
|
|
48
|
-
processing: 'Working on it',
|
|
49
|
-
delivering: 'Almost there',
|
|
50
|
-
complete: 'Done!'
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<div className={`ai-creating-wrapper size-${size}`}>
|
|
55
|
-
<div className={`ai-creating-container stage-${stage}`}>
|
|
56
|
-
|
|
57
|
-
{/* Animated Background Particles */}
|
|
58
|
-
<div className="particles">
|
|
59
|
-
<span></span><span></span><span></span>
|
|
60
|
-
<span></span><span></span><span></span>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
{/* Main Content */}
|
|
64
|
-
<div className="ai-scene">
|
|
65
|
-
|
|
66
|
-
{/* AI Robot Character */}
|
|
67
|
-
<div className={`ai-robot ${stage}`}>
|
|
68
|
-
<div className="robot-head">
|
|
69
|
-
<div className="robot-face">
|
|
70
|
-
<div className="robot-eyes">
|
|
71
|
-
<div className="eye left">
|
|
72
|
-
<div className="pupil"></div>
|
|
73
|
-
</div>
|
|
74
|
-
<div className="eye right">
|
|
75
|
-
<div className="pupil"></div>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
<div className="robot-mouth"></div>
|
|
79
|
-
</div>
|
|
80
|
-
<div className="antenna">
|
|
81
|
-
<div className="antenna-ball"></div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
<div className="robot-body">
|
|
85
|
-
<div className="chest-light"></div>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
{/* User Request Card - Reading Stage */}
|
|
90
|
-
{(stage === 'reading' || stage === 'processing') && (
|
|
91
|
-
<div className={`request-card ${stage}`}>
|
|
92
|
-
<div className="card-icon">📝</div>
|
|
93
|
-
<div className="card-lines">
|
|
94
|
-
<span className="line"></span>
|
|
95
|
-
<span className="line short"></span>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
)}
|
|
99
|
-
|
|
100
|
-
{/* Processing Gears - Processing Stage */}
|
|
101
|
-
{stage === 'processing' && (
|
|
102
|
-
<div className="processing-visual">
|
|
103
|
-
<div className="gear gear-1">⚙️</div>
|
|
104
|
-
<div className="gear gear-2">⚙️</div>
|
|
105
|
-
<div className="sparkles">
|
|
106
|
-
<span>✨</span><span>✨</span><span>✨</span>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
)}
|
|
110
|
-
|
|
111
|
-
{/* Result Card - Delivering Stage */}
|
|
112
|
-
{(stage === 'delivering' || stage === 'complete') && (
|
|
113
|
-
<div className={`result-card ${stage}`}>
|
|
114
|
-
<div className="result-icon">{stage === 'complete' ? '✅' : '📄'}</div>
|
|
115
|
-
<div className="result-lines">
|
|
116
|
-
<span className="line"></span>
|
|
117
|
-
<span className="line"></span>
|
|
118
|
-
<span className="line short"></span>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
)}
|
|
122
|
-
|
|
123
|
-
{/* Status Text */}
|
|
124
|
-
{stage !== 'idle' && (
|
|
125
|
-
<div className="status-area">
|
|
126
|
-
<span className={`status-text ${stage}`}>{stageText[stage]}</span>
|
|
127
|
-
{stage !== 'complete' && (
|
|
128
|
-
<span className="dots">
|
|
129
|
-
<span>.</span><span>.</span><span>.</span>
|
|
130
|
-
</span>
|
|
131
|
-
)}
|
|
132
|
-
</div>
|
|
133
|
-
)}
|
|
134
|
-
|
|
135
|
-
{/* Progress Indicator */}
|
|
136
|
-
<div className="progress-track">
|
|
137
|
-
<div className={`progress-bar stage-${stage}`}></div>
|
|
138
|
-
<div className="progress-steps">
|
|
139
|
-
<div className={`step ${stage !== 'idle' ? 'active' : ''}`}></div>
|
|
140
|
-
<div className={`step ${stage === 'processing' || stage === 'delivering' || stage === 'complete' ? 'active' : ''}`}></div>
|
|
141
|
-
<div className={`step ${stage === 'delivering' || stage === 'complete' ? 'active' : ''}`}></div>
|
|
142
|
-
<div className={`step ${stage === 'complete' ? 'active' : ''}`}></div>
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
);
|
|
150
|
-
}
|
|
2
|
+
// ai-react-animations - CommonJS Build
|
|
3
|
+
// For full functionality, use ESM import
|
|
151
4
|
|
|
5
|
+
const AiCreating = require('./AiCreating.cjs');
|
|
6
|
+
const AiCreating2 = require('./AiCreating2.cjs');
|
|
152
7
|
|
|
153
8
|
module.exports = AiCreating;
|
|
154
9
|
module.exports.default = AiCreating;
|
|
10
|
+
module.exports.AiCreating = AiCreating;
|
|
11
|
+
module.exports.AiCreating2 = AiCreating2;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// ai-react-animations - ESM Build
|
|
2
|
+
// AiCreating Component
|
|
1
3
|
/**
|
|
2
4
|
* AiCreating - AI Assistant Processing Animation
|
|
3
5
|
* Shows AI helping user with their tasks/requests
|
|
@@ -7,7 +9,7 @@
|
|
|
7
9
|
'use client';
|
|
8
10
|
|
|
9
11
|
import { useEffect, useState } from 'react';
|
|
10
|
-
// CSS
|
|
12
|
+
// CSS: import 'ai-react-animations/styles.css'
|
|
11
13
|
|
|
12
14
|
export interface AiCreatingProps {
|
|
13
15
|
isLoading: boolean;
|
|
@@ -145,3 +147,211 @@ export default function AiCreating({
|
|
|
145
147
|
);
|
|
146
148
|
}
|
|
147
149
|
|
|
150
|
+
|
|
151
|
+
// AiCreating2 Component
|
|
152
|
+
'use client';
|
|
153
|
+
|
|
154
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
155
|
+
import { Sparkles, Brain, Zap } from 'lucide-react';
|
|
156
|
+
|
|
157
|
+
export interface AiCreating2Props {
|
|
158
|
+
isLoading: boolean;
|
|
159
|
+
onComplete?: () => void;
|
|
160
|
+
message?: string;
|
|
161
|
+
subMessage?: string;
|
|
162
|
+
/** Primary color for animations (hex) */
|
|
163
|
+
primaryColor?: string;
|
|
164
|
+
/** Background color (hex) */
|
|
165
|
+
backgroundColor?: string;
|
|
166
|
+
/** Text color (hex) */
|
|
167
|
+
textColor?: string;
|
|
168
|
+
/** If true, renders in a contained box instead of full-screen overlay */
|
|
169
|
+
contained?: boolean;
|
|
170
|
+
/** Status messages to cycle through */
|
|
171
|
+
statusMessages?: Array<{ icon: 'sparkles' | 'brain' | 'zap'; text: string }>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const iconMap = {
|
|
175
|
+
sparkles: Sparkles,
|
|
176
|
+
brain: Brain,
|
|
177
|
+
zap: Zap,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
export function AiCreating2({
|
|
181
|
+
isLoading,
|
|
182
|
+
onComplete,
|
|
183
|
+
message = "Creating your plan...",
|
|
184
|
+
subMessage = "AI is analyzing your goals and building a personalized plan",
|
|
185
|
+
primaryColor = "#6366F1",
|
|
186
|
+
backgroundColor = "#0f172a",
|
|
187
|
+
textColor = "#ffffff",
|
|
188
|
+
contained = false,
|
|
189
|
+
statusMessages = [
|
|
190
|
+
{ icon: 'sparkles', text: 'Analyzing your goals' },
|
|
191
|
+
{ icon: 'brain', text: 'Designing daily structure' },
|
|
192
|
+
{ icon: 'zap', text: 'Generating action items' },
|
|
193
|
+
],
|
|
194
|
+
}: AiCreating2Props) {
|
|
195
|
+
|
|
196
|
+
const containerClass = contained
|
|
197
|
+
? "relative w-full h-full min-h-[400px] rounded-xl flex items-center justify-center overflow-hidden"
|
|
198
|
+
: "fixed inset-0 z-[70] flex items-center justify-center";
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<AnimatePresence>
|
|
202
|
+
{isLoading && (
|
|
203
|
+
<motion.div
|
|
204
|
+
initial={{ opacity: 0 }}
|
|
205
|
+
animate={{ opacity: 1 }}
|
|
206
|
+
exit={{ opacity: 0 }}
|
|
207
|
+
className={containerClass}
|
|
208
|
+
style={{ backgroundColor }}
|
|
209
|
+
>
|
|
210
|
+
<div className="text-center max-w-md px-6">
|
|
211
|
+
{/* Animated AI Brain */}
|
|
212
|
+
<div className="relative w-32 h-32 mx-auto mb-8">
|
|
213
|
+
{/* Outer rotating ring */}
|
|
214
|
+
<motion.div
|
|
215
|
+
className="absolute inset-0 rounded-full"
|
|
216
|
+
style={{ border: `2px solid ${primaryColor}30` }}
|
|
217
|
+
animate={{ rotate: 360 }}
|
|
218
|
+
transition={{ duration: 8, repeat: Infinity, ease: "linear" }}
|
|
219
|
+
/>
|
|
220
|
+
|
|
221
|
+
{/* Middle pulsing ring */}
|
|
222
|
+
<motion.div
|
|
223
|
+
className="absolute inset-2 rounded-full"
|
|
224
|
+
style={{ border: `2px solid ${primaryColor}80` }}
|
|
225
|
+
animate={{
|
|
226
|
+
scale: [1, 1.1, 1],
|
|
227
|
+
opacity: [0.5, 1, 0.5]
|
|
228
|
+
}}
|
|
229
|
+
transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
|
|
230
|
+
/>
|
|
231
|
+
|
|
232
|
+
{/* Inner ring with gradient */}
|
|
233
|
+
<motion.div
|
|
234
|
+
className="absolute inset-4 rounded-full"
|
|
235
|
+
style={{
|
|
236
|
+
background: `linear-gradient(135deg, ${primaryColor}40, ${primaryColor}10)`
|
|
237
|
+
}}
|
|
238
|
+
animate={{ rotate: -360 }}
|
|
239
|
+
transition={{ duration: 12, repeat: Infinity, ease: "linear" }}
|
|
240
|
+
/>
|
|
241
|
+
|
|
242
|
+
{/* Center icon */}
|
|
243
|
+
<motion.div
|
|
244
|
+
className="absolute inset-0 flex items-center justify-center"
|
|
245
|
+
animate={{
|
|
246
|
+
scale: [1, 1.05, 1],
|
|
247
|
+
}}
|
|
248
|
+
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
|
|
249
|
+
>
|
|
250
|
+
<Brain className="w-12 h-12" style={{ color: primaryColor }} />
|
|
251
|
+
</motion.div>
|
|
252
|
+
|
|
253
|
+
{/* Floating particles */}
|
|
254
|
+
{[...Array(6)].map((_, i) => (
|
|
255
|
+
<motion.div
|
|
256
|
+
key={i}
|
|
257
|
+
className="absolute w-2 h-2 rounded-full"
|
|
258
|
+
style={{
|
|
259
|
+
top: '50%',
|
|
260
|
+
left: '50%',
|
|
261
|
+
backgroundColor: primaryColor,
|
|
262
|
+
}}
|
|
263
|
+
animate={{
|
|
264
|
+
x: [0, Math.cos(i * 60 * Math.PI / 180) * 60],
|
|
265
|
+
y: [0, Math.sin(i * 60 * Math.PI / 180) * 60],
|
|
266
|
+
opacity: [0, 1, 0],
|
|
267
|
+
scale: [0, 1, 0],
|
|
268
|
+
}}
|
|
269
|
+
transition={{
|
|
270
|
+
duration: 2,
|
|
271
|
+
repeat: Infinity,
|
|
272
|
+
delay: i * 0.3,
|
|
273
|
+
ease: "easeOut"
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
))}
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
{/* Text */}
|
|
280
|
+
<motion.h3
|
|
281
|
+
className="text-2xl font-bold mb-3"
|
|
282
|
+
style={{ color: textColor }}
|
|
283
|
+
animate={{ opacity: [0.7, 1, 0.7] }}
|
|
284
|
+
transition={{ duration: 2, repeat: Infinity }}
|
|
285
|
+
>
|
|
286
|
+
{message}
|
|
287
|
+
</motion.h3>
|
|
288
|
+
|
|
289
|
+
<motion.p
|
|
290
|
+
className="text-sm mb-6"
|
|
291
|
+
style={{ color: `${textColor}99` }}
|
|
292
|
+
initial={{ opacity: 0, y: 10 }}
|
|
293
|
+
animate={{ opacity: 1, y: 0 }}
|
|
294
|
+
transition={{ delay: 0.3 }}
|
|
295
|
+
>
|
|
296
|
+
{subMessage}
|
|
297
|
+
</motion.p>
|
|
298
|
+
|
|
299
|
+
{/* Progress dots */}
|
|
300
|
+
<div className="flex justify-center gap-2">
|
|
301
|
+
{[0, 1, 2, 3, 4].map((i) => (
|
|
302
|
+
<motion.div
|
|
303
|
+
key={i}
|
|
304
|
+
className="w-2 h-2 rounded-full"
|
|
305
|
+
style={{ backgroundColor: primaryColor }}
|
|
306
|
+
animate={{
|
|
307
|
+
opacity: [0.3, 1, 0.3],
|
|
308
|
+
scale: [0.8, 1.2, 0.8],
|
|
309
|
+
}}
|
|
310
|
+
transition={{
|
|
311
|
+
duration: 1,
|
|
312
|
+
repeat: Infinity,
|
|
313
|
+
delay: i * 0.15,
|
|
314
|
+
}}
|
|
315
|
+
/>
|
|
316
|
+
))}
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
{/* Status messages */}
|
|
320
|
+
<motion.div
|
|
321
|
+
className="mt-8 space-y-2"
|
|
322
|
+
initial={{ opacity: 0 }}
|
|
323
|
+
animate={{ opacity: 1 }}
|
|
324
|
+
transition={{ delay: 1 }}
|
|
325
|
+
>
|
|
326
|
+
{statusMessages.map((status, index) => {
|
|
327
|
+
const Icon = iconMap[status.icon];
|
|
328
|
+
return (
|
|
329
|
+
<motion.div
|
|
330
|
+
key={index}
|
|
331
|
+
className="flex items-center justify-center gap-2 text-sm"
|
|
332
|
+
initial={{ opacity: 0, x: -20 }}
|
|
333
|
+
animate={{ opacity: [0, 1, 1, 0.5], x: 0 }}
|
|
334
|
+
transition={{
|
|
335
|
+
delay: index * 2,
|
|
336
|
+
duration: 4,
|
|
337
|
+
repeat: Infinity,
|
|
338
|
+
repeatDelay: (statusMessages.length - 1) * 2 + 4
|
|
339
|
+
}}
|
|
340
|
+
>
|
|
341
|
+
<Icon className="w-4 h-4" style={{ color: primaryColor }} />
|
|
342
|
+
<span style={{ color: `${textColor}99` }}>{status.text}</span>
|
|
343
|
+
</motion.div>
|
|
344
|
+
);
|
|
345
|
+
})}
|
|
346
|
+
</motion.div>
|
|
347
|
+
</div>
|
|
348
|
+
</motion.div>
|
|
349
|
+
)}
|
|
350
|
+
</AnimatePresence>
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export default AiCreating2;
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
export { AiCreating, AiCreating2 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-react-animations",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Beautiful AI loading animation components for React/Next.js. Shows AI processing states with friendly robot character.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"type": "git",
|
|
42
42
|
"url": "https://github.com/johnbekele/ai-react-animations"
|
|
43
43
|
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"framer-motion": "^11.0.0",
|
|
46
|
+
"lucide-react": "^0.344.0"
|
|
47
|
+
},
|
|
44
48
|
"peerDependencies": {
|
|
45
49
|
"react": ">=17.0.0",
|
|
46
50
|
"react-dom": ">=17.0.0"
|