@catalystsoftware/ui 1.0.15 → 1.0.17
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 +11 -1
- package/dist/components/catalyst-ui/data/chat-data.tsx +336 -0
- package/dist/components/catalyst-ui/data/code-data.tsx +1 -74
- package/dist/components/catalyst-ui/data/core-data.tsx +679 -7
- package/dist/components/catalyst-ui/data/crm-data.tsx +2 -2
- package/dist/components/catalyst-ui/data/forms-data.tsx +5 -5
- package/dist/components/catalyst-ui/data/media-data.tsx +66 -3
- package/dist/components/catalyst-ui/data/overlay-data.tsx +5 -3
- package/dist/components/catalyst-ui/data/primitive-data.tsx +18 -128
- package/dist/components/catalyst-ui/data/sidebars-data.tsx +38 -38
- package/dist/components/catalyst-ui/data/tools-data.tsx +1 -1
- package/dist/components/catalyst-ui/data/utils-data.tsx +27 -9
- package/dist/components/catalyst-ui/marketing/sections/header.tsx +1 -0
- package/dist/components/catalyst-ui/overlays/sidebar-props.tsx +1 -1
- package/dist/components/catalyst-ui/primitives/alert.tsx +1 -1
- package/dist/components/catalyst-ui/tools/md-badge-builder.tsx +1 -1
- package/dist/components/catalyst-ui/tools/monaco-sidebar.tsx +935 -331
- package/dist/components/catalyst-ui/tools/monaco.tsx +66 -66
- package/dist/components/catalyst-ui/tools/snippets.tsx +844 -0
- package/dist/data/tailwind.config.js +1 -1
- package/dist/data/tailwind.config.ngin.ts +1 -1
- package/dist/index.js +45 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive React component library with 100+ production-ready components for building modern web applications.
|
|
4
4
|
|
|
5
|
+
## UPDATE
|
|
6
|
+
|
|
7
|
+
Adding a new line option 'Configure Import Call'. Configures your package.json and tsconfig.json files to allow the use of '#icons' and '#catalyst' in-place of the traditional '~/components/catalyst-ui' and '@catalystsoftware/icons'
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import { Command, CommandGroup, CommandItem, CommandList, cn } from '#catalyst'
|
|
11
|
+
import { X } from '#icons'
|
|
12
|
+
```
|
|
13
|
+
Selecting the full installation will also configure your project for this use as well.
|
|
14
|
+
|
|
5
15
|
## Installation
|
|
6
16
|
|
|
7
17
|
### Quick Start
|
|
@@ -101,7 +111,7 @@ Catalyst UI automatically detects and uses your package manager:
|
|
|
101
111
|
|
|
102
112
|
### Config File (Optional)
|
|
103
113
|
|
|
104
|
-
Create a `
|
|
114
|
+
Create a `config.catalyst` file in your project root to customize installation behavior:
|
|
105
115
|
|
|
106
116
|
```bash
|
|
107
117
|
bunx @catalystsoftware/ui
|
|
@@ -1,4 +1,340 @@
|
|
|
1
1
|
// @dev app/components/catalyst-ui/data/chat-data.tsx:12
|
|
2
|
+
export interface Character {
|
|
3
|
+
id?: string | number;
|
|
4
|
+
emoji: string;
|
|
5
|
+
name: string;
|
|
6
|
+
online: boolean;
|
|
7
|
+
backgroundColor?: string;
|
|
8
|
+
gradientFrom?: string;
|
|
9
|
+
gradientTo?: string;
|
|
10
|
+
gradientColors?: string;
|
|
11
|
+
avatar?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface MessageDockProps {
|
|
14
|
+
characters?: Character[];
|
|
15
|
+
onMessageSend?: (message: string, character: Character, characterIndex: number) => void;
|
|
16
|
+
onCharacterSelect?: (character: Character, characterIndex: number) => void;
|
|
17
|
+
onDockToggle?: (isExpanded: boolean) => void;
|
|
18
|
+
className?: string;
|
|
19
|
+
expandedWidth?: number;
|
|
20
|
+
position?: "bottom" | "top";
|
|
21
|
+
showSparkleButton?: boolean;
|
|
22
|
+
showMenuButton?: boolean;
|
|
23
|
+
enableAnimations?: boolean;
|
|
24
|
+
animationDuration?: number;
|
|
25
|
+
placeholder?: (characterName: string) => string;
|
|
26
|
+
theme?: "light" | "dark" | "auto";
|
|
27
|
+
autoFocus?: boolean;
|
|
28
|
+
closeOnClickOutside?: boolean;
|
|
29
|
+
closeOnEscape?: boolean;
|
|
30
|
+
closeOnSend?: boolean;
|
|
31
|
+
}
|
|
32
|
+
const defaultCharacters: Character[] = [
|
|
33
|
+
{ emoji: "✨", name: "Sparkle", online: false },
|
|
34
|
+
{
|
|
35
|
+
emoji: "🧙♂️",
|
|
36
|
+
name: "Wizard",
|
|
37
|
+
online: true,
|
|
38
|
+
backgroundColor: "bg-emerald-200 dark:bg-emerald-300",
|
|
39
|
+
gradientFrom: "from-emerald-200",
|
|
40
|
+
gradientTo: "to-emerald-50",
|
|
41
|
+
gradientColors: "#a7f3d0, #ecfdf5"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
emoji: "🦄",
|
|
45
|
+
name: "Unicorn",
|
|
46
|
+
online: true,
|
|
47
|
+
backgroundColor: "bg-violet-200 dark:bg-violet-300",
|
|
48
|
+
gradientFrom: "from-violet-200",
|
|
49
|
+
gradientTo: "to-violet-50",
|
|
50
|
+
gradientColors: "#c4b5fd, #f5f3ff"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
emoji: "🐵",
|
|
54
|
+
name: "Monkey",
|
|
55
|
+
online: true,
|
|
56
|
+
backgroundColor: "bg-amber-200 dark:bg-amber-300",
|
|
57
|
+
gradientFrom: "from-amber-200",
|
|
58
|
+
gradientTo: "to-amber-50",
|
|
59
|
+
gradientColors: "#fde68a, #fffbeb"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
emoji: "🤖",
|
|
63
|
+
name: "Robot",
|
|
64
|
+
online: false,
|
|
65
|
+
backgroundColor: "bg-rose-200 dark:bg-rose-300",
|
|
66
|
+
gradientFrom: "from-rose-200",
|
|
67
|
+
gradientTo: "to-rose-50",
|
|
68
|
+
gradientColors: "#fecaca, #fef2f2"
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
const getGradientColors = (character: Character) => {
|
|
72
|
+
return character.gradientColors || "#86efac, #dcfce7";
|
|
73
|
+
};
|
|
74
|
+
export function MessageDock({ characters = defaultCharacters, onMessageSend, onCharacterSelect, onDockToggle, className, expandedWidth = 448, position = "bottom", showSparkleButton = true, showMenuButton = true, enableAnimations = true, animationDuration = 1, placeholder = (name: string) => `Message ${name}...`, theme = "light", autoFocus = true, closeOnClickOutside = true, closeOnEscape = true, closeOnSend = true, }: MessageDockProps) {
|
|
75
|
+
const shouldReduceMotion = useReducedMotion();
|
|
76
|
+
const [expandedCharacter, setExpandedCharacter] = useState<number | null>(null);
|
|
77
|
+
const [messageInput, setMessageInput] = useState("");
|
|
78
|
+
const dockRef = useRef<HTMLDivElement>(null);
|
|
79
|
+
const [collapsedWidth, setCollapsedWidth] = useState<number>(266);
|
|
80
|
+
const [hasInitialized, setHasInitialized] = useState(false);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (dockRef.current && !hasInitialized) {
|
|
83
|
+
const width = dockRef.current.offsetWidth;
|
|
84
|
+
if (width > 0) {
|
|
85
|
+
setCollapsedWidth(width);
|
|
86
|
+
setHasInitialized(true);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}, [hasInitialized]);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!closeOnClickOutside)
|
|
92
|
+
return;
|
|
93
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
94
|
+
if (dockRef.current && !dockRef.current.contains(event.target as Node)) {
|
|
95
|
+
setExpandedCharacter(null);
|
|
96
|
+
setMessageInput("");
|
|
97
|
+
onDockToggle?.(false);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
101
|
+
return () => {
|
|
102
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
103
|
+
};
|
|
104
|
+
}, [closeOnClickOutside, onDockToggle]);
|
|
105
|
+
const containerVariants = {
|
|
106
|
+
hidden: {
|
|
107
|
+
opacity: 0,
|
|
108
|
+
y: 100,
|
|
109
|
+
scale: 0.8,
|
|
110
|
+
},
|
|
111
|
+
visible: {
|
|
112
|
+
opacity: 1,
|
|
113
|
+
y: 0,
|
|
114
|
+
scale: 1,
|
|
115
|
+
transition: {
|
|
116
|
+
type: "spring" as const,
|
|
117
|
+
stiffness: 300,
|
|
118
|
+
damping: 30,
|
|
119
|
+
mass: 0.8,
|
|
120
|
+
staggerChildren: 0.1,
|
|
121
|
+
delayChildren: 0.2,
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const hoverAnimation = shouldReduceMotion
|
|
126
|
+
? { scale: 1.02 }
|
|
127
|
+
: {
|
|
128
|
+
scale: 1.05,
|
|
129
|
+
y: -8,
|
|
130
|
+
transition: {
|
|
131
|
+
type: "spring",
|
|
132
|
+
stiffness: 400,
|
|
133
|
+
damping: 25,
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const handleCharacterClick = (index: number) => {
|
|
137
|
+
const character = characters[index];
|
|
138
|
+
if (expandedCharacter === index) {
|
|
139
|
+
setExpandedCharacter(null);
|
|
140
|
+
setMessageInput("");
|
|
141
|
+
onDockToggle?.(false);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
setExpandedCharacter(index);
|
|
145
|
+
onCharacterSelect?.(character, index);
|
|
146
|
+
onDockToggle?.(true);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const handleSendMessage = () => {
|
|
150
|
+
if (messageInput.trim() && expandedCharacter !== null) {
|
|
151
|
+
const character = characters[expandedCharacter];
|
|
152
|
+
onMessageSend?.(messageInput, character, expandedCharacter);
|
|
153
|
+
setMessageInput("");
|
|
154
|
+
if (closeOnSend) {
|
|
155
|
+
setExpandedCharacter(null);
|
|
156
|
+
onDockToggle?.(false);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const selectedCharacter = expandedCharacter !== null ? characters[expandedCharacter] : null;
|
|
161
|
+
const isExpanded = expandedCharacter !== null;
|
|
162
|
+
const defaultPositionClasses = position === "top"
|
|
163
|
+
? "fixed top-6 left-1/2 -translate-x-1/2 z-50"
|
|
164
|
+
: "fixed bottom-6 left-1/2 -translate-x-1/2 z-50";
|
|
165
|
+
return (<motion.div ref={dockRef} className={cn(
|
|
166
|
+
// Only apply default positioning if not overridden by className
|
|
167
|
+
!className?.includes('relative') && !className?.includes('absolute') ? defaultPositionClasses : '', className)} initial={enableAnimations ? "hidden" : "visible"} animate="visible" variants={enableAnimations ? containerVariants : {}}>
|
|
168
|
+
<motion.div className="rounded-full px-4 py-2 shadow-2xl border border-border bg-background/95 backdrop-blur-md" animate={{
|
|
169
|
+
width: isExpanded ? expandedWidth : collapsedWidth,
|
|
170
|
+
background: isExpanded && selectedCharacter
|
|
171
|
+
? `linear-gradient(to right, ${getGradientColors(selectedCharacter)})`
|
|
172
|
+
: "hsl(var(--background))"
|
|
173
|
+
}} transition={enableAnimations ? {
|
|
174
|
+
type: "spring",
|
|
175
|
+
stiffness: isExpanded ? 300 : 500,
|
|
176
|
+
damping: isExpanded ? 30 : 35,
|
|
177
|
+
mass: isExpanded ? 0.8 : 0.6,
|
|
178
|
+
background: {
|
|
179
|
+
duration: 0.2 * animationDuration,
|
|
180
|
+
ease: "easeInOut"
|
|
181
|
+
}
|
|
182
|
+
} : { duration: 0 }}>
|
|
183
|
+
<div className="flex items-center gap-2 relative">
|
|
184
|
+
{showSparkleButton && (<motion.div className="flex items-center justify-center" animate={{
|
|
185
|
+
opacity: isExpanded ? 0 : 1,
|
|
186
|
+
x: isExpanded ? -20 : 0,
|
|
187
|
+
scale: isExpanded ? 0.8 : 1
|
|
188
|
+
}} transition={{
|
|
189
|
+
type: "spring",
|
|
190
|
+
stiffness: 400,
|
|
191
|
+
damping: 30,
|
|
192
|
+
delay: isExpanded ? 0 : 0
|
|
193
|
+
}}>
|
|
194
|
+
<motion.button className="w-12 h-12 flex items-center justify-center cursor-pointer" whileHover={!isExpanded
|
|
195
|
+
? {
|
|
196
|
+
scale: 1.02,
|
|
197
|
+
y: -2,
|
|
198
|
+
transition: {
|
|
199
|
+
type: "spring",
|
|
200
|
+
stiffness: 400,
|
|
201
|
+
damping: 25,
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
: undefined} whileTap={{ scale: 0.95 }} aria-label="Sparkle">
|
|
205
|
+
<span className="text-2xl">✨</span>
|
|
206
|
+
</motion.button>
|
|
207
|
+
</motion.div>)}
|
|
208
|
+
<motion.div className="w-px h-6 bg-gray-300 mr-2 -ml-2" animate={{
|
|
209
|
+
opacity: isExpanded ? 0 : 1,
|
|
210
|
+
scaleY: isExpanded ? 0 : 1
|
|
211
|
+
}} transition={{
|
|
212
|
+
type: "spring",
|
|
213
|
+
stiffness: 300,
|
|
214
|
+
damping: 30,
|
|
215
|
+
delay: isExpanded ? 0 : 0.3
|
|
216
|
+
}}/>
|
|
217
|
+
{characters.slice(1, -1).map((character, index) => {
|
|
218
|
+
const actualIndex = index + 1;
|
|
219
|
+
const isSelected = expandedCharacter === actualIndex;
|
|
220
|
+
return (<motion.div key={character.name} className={cn("relative", isSelected && isExpanded && "absolute left-1 top-1 z-20")} style={{
|
|
221
|
+
width: isSelected && isExpanded ? 0 : "auto",
|
|
222
|
+
minWidth: isSelected && isExpanded ? 0 : "auto",
|
|
223
|
+
overflow: "visible"
|
|
224
|
+
}} animate={{
|
|
225
|
+
opacity: isExpanded && !isSelected ? 0 : 1,
|
|
226
|
+
y: isExpanded && !isSelected ? 60 : 0,
|
|
227
|
+
scale: isExpanded && !isSelected ? 0.8 : 1,
|
|
228
|
+
x: isSelected && isExpanded ? 0 : 0
|
|
229
|
+
}} transition={{
|
|
230
|
+
type: "spring",
|
|
231
|
+
stiffness: 400,
|
|
232
|
+
damping: 30,
|
|
233
|
+
delay: isExpanded && !isSelected
|
|
234
|
+
? index * 0.05
|
|
235
|
+
: isExpanded
|
|
236
|
+
? 0.1
|
|
237
|
+
: 0
|
|
238
|
+
}}>
|
|
239
|
+
<motion.button className={cn("relative w-10 h-10 rounded-full flex items-center justify-center text-xl cursor-pointer", isSelected && isExpanded
|
|
240
|
+
? "bg-white/90"
|
|
241
|
+
: character.backgroundColor)} onClick={() => handleCharacterClick(actualIndex)} whileHover={!isExpanded ? hoverAnimation : { scale: 1.05 }} whileTap={{ scale: 0.95 }} aria-label={`Message ${character.name}`}>
|
|
242
|
+
<span className="text-2xl">{character.emoji}</span>
|
|
243
|
+
{character.online && (<motion.div className="absolute bottom-0 right-0 w-3 h-3 bg-green-500 border-2 border-white rounded-full" initial={{ scale: 0 }} animate={{ scale: isExpanded && !isSelected ? 0 : 1 }} transition={{
|
|
244
|
+
delay: isExpanded
|
|
245
|
+
? isSelected
|
|
246
|
+
? 0.3
|
|
247
|
+
: 0
|
|
248
|
+
: (index + 1) * 0.1 + 0.5,
|
|
249
|
+
type: "spring",
|
|
250
|
+
stiffness: 500,
|
|
251
|
+
damping: 30
|
|
252
|
+
}}/>)}
|
|
253
|
+
</motion.button>
|
|
254
|
+
</motion.div>);
|
|
255
|
+
})}
|
|
256
|
+
<AnimatePresence>
|
|
257
|
+
{isExpanded && (<motion.input type="text" value={messageInput} onChange={(e) => setMessageInput(e.target.value)} onKeyDown={(e) => {
|
|
258
|
+
if (e.key === "Enter") {
|
|
259
|
+
handleSendMessage();
|
|
260
|
+
}
|
|
261
|
+
if (e.key === "Escape" && closeOnEscape) {
|
|
262
|
+
setExpandedCharacter(null);
|
|
263
|
+
setMessageInput("");
|
|
264
|
+
onDockToggle?.(false);
|
|
265
|
+
}
|
|
266
|
+
}} placeholder={placeholder(selectedCharacter?.name || "")} className="w-[300px] absolute left-14 right-0 bg-transparent border-none outline-none text-sm font-medium z-50 text-foreground placeholder-muted-foreground" autoFocus={autoFocus} initial={{ opacity: 0, x: 20 }} animate={{
|
|
267
|
+
opacity: 1,
|
|
268
|
+
x: 0,
|
|
269
|
+
transition: {
|
|
270
|
+
delay: 0.2,
|
|
271
|
+
type: "spring",
|
|
272
|
+
stiffness: 400,
|
|
273
|
+
damping: 30,
|
|
274
|
+
}
|
|
275
|
+
}} exit={{
|
|
276
|
+
opacity: 0,
|
|
277
|
+
transition: {
|
|
278
|
+
duration: 0.1,
|
|
279
|
+
ease: "easeOut"
|
|
280
|
+
}
|
|
281
|
+
}}/>)}
|
|
282
|
+
</AnimatePresence>
|
|
283
|
+
<motion.div className="w-px h-6 bg-gray-300 ml-2 -mr-2" animate={{
|
|
284
|
+
opacity: isExpanded ? 0 : 1,
|
|
285
|
+
scaleY: isExpanded ? 0 : 1
|
|
286
|
+
}} transition={{
|
|
287
|
+
type: "spring",
|
|
288
|
+
stiffness: 300,
|
|
289
|
+
damping: 30,
|
|
290
|
+
delay: isExpanded ? 0 : 0
|
|
291
|
+
}}/>
|
|
292
|
+
{showMenuButton && (<motion.div className={cn("flex items-center justify-center z-20", isExpanded && "absolute right-0")} transition={{ type: "spring", stiffness: 400, damping: 30 }}>
|
|
293
|
+
<AnimatePresence mode="wait">
|
|
294
|
+
{!isExpanded ? (<motion.button key="menu" className="w-12 h-12 flex items-center justify-center cursor-pointer" whileHover={{
|
|
295
|
+
scale: 1.02,
|
|
296
|
+
y: -2,
|
|
297
|
+
transition: {
|
|
298
|
+
type: "spring",
|
|
299
|
+
stiffness: 400,
|
|
300
|
+
damping: 25,
|
|
301
|
+
}
|
|
302
|
+
}} whileTap={{ scale: 0.95 }} aria-label="Menu" initial={{ opacity: 0, rotate: -90 }} animate={{ opacity: 1, rotate: 0 }} exit={{ opacity: 0, rotate: 90 }} transition={{ type: "spring", stiffness: 400, damping: 30 }}>
|
|
303
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="text-muted-foreground">
|
|
304
|
+
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
305
|
+
<line x1="3" y1="12" x2="21" y2="12"/>
|
|
306
|
+
<line x1="3" y1="18" x2="21" y2="18"/>
|
|
307
|
+
</svg>
|
|
308
|
+
</motion.button>) : (<motion.button key="send" onClick={handleSendMessage} className="w-10 h-10 flex items-center justify-center rounded-full bg-background/90 hover:bg-background transition-colors disabled:opacity-50 cursor-pointer relative z-30 border border-border/50" whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} disabled={!messageInput.trim()} initial={{ opacity: 0, scale: 0, rotate: -90 }} animate={{
|
|
309
|
+
opacity: 1,
|
|
310
|
+
scale: 1,
|
|
311
|
+
rotate: 0,
|
|
312
|
+
transition: {
|
|
313
|
+
delay: 0.25,
|
|
314
|
+
type: "spring",
|
|
315
|
+
stiffness: 400,
|
|
316
|
+
damping: 30,
|
|
317
|
+
}
|
|
318
|
+
}} exit={{
|
|
319
|
+
opacity: 0,
|
|
320
|
+
scale: 0,
|
|
321
|
+
rotate: 90,
|
|
322
|
+
transition: {
|
|
323
|
+
duration: 0.1,
|
|
324
|
+
ease: "easeIn"
|
|
325
|
+
}
|
|
326
|
+
}}>
|
|
327
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="text-muted-foreground">
|
|
328
|
+
<path d="m22 2-7 20-4-9-9-4z"/>
|
|
329
|
+
<path d="M22 2 11 13"/>
|
|
330
|
+
</svg>
|
|
331
|
+
</motion.button>)}
|
|
332
|
+
</AnimatePresence>
|
|
333
|
+
</motion.div>)}
|
|
334
|
+
</div>
|
|
335
|
+
</motion.div>
|
|
336
|
+
</motion.div>);
|
|
337
|
+
}
|
|
2
338
|
export const chatData = [
|
|
3
339
|
{
|
|
4
340
|
name: "message dock",
|
|
@@ -289,80 +289,7 @@ export function TerminalDemo() {
|
|
|
289
289
|
</AnimatedSpan>
|
|
290
290
|
|
|
291
291
|
<AnimatedSpan className="text-green-500">
|
|
292
|
-
✔ Validating
|
|
293
|
-
</AnimatedSpan>
|
|
294
|
-
|
|
295
|
-
<AnimatedSpan className="text-green-500">
|
|
296
|
-
✔ Writing components.json.
|
|
297
|
-
</AnimatedSpan>
|
|
298
|
-
|
|
299
|
-
<AnimatedSpan className="text-green-500">
|
|
300
|
-
✔ Checking registry.
|
|
301
|
-
</AnimatedSpan>
|
|
302
|
-
|
|
303
|
-
<AnimatedSpan className="text-green-500">
|
|
304
|
-
✔ Updating tailwind.config.ts
|
|
305
|
-
</AnimatedSpan>
|
|
306
|
-
|
|
307
|
-
<AnimatedSpan className="text-green-500">
|
|
308
|
-
✔ Updating app/globals.css
|
|
309
|
-
</AnimatedSpan>
|
|
310
|
-
|
|
311
|
-
<AnimatedSpan className="text-green-500">
|
|
312
|
-
✔ Installing dependencies.
|
|
313
|
-
</AnimatedSpan>
|
|
314
|
-
|
|
315
|
-
<AnimatedSpan className="text-blue-500">
|
|
316
|
-
<span> Updated 1 file:</span>
|
|
317
|
-
<span className="pl-2">- lib/utils.ts</span>
|
|
318
|
-
</AnimatedSpan>
|
|
319
|
-
|
|
320
|
-
<TypingAnimation className="text-muted-foreground">
|
|
321
|
-
Success! Project initialization completed.
|
|
322
|
-
</TypingAnimation>
|
|
323
|
-
|
|
324
|
-
<TypingAnimation className="text-muted-foreground">
|
|
325
|
-
You may now add components.
|
|
326
|
-
</TypingAnimation>
|
|
327
|
-
</Terminal>
|
|
328
|
-
)
|
|
329
|
-
}
|
|
330
|
-
`,
|
|
331
|
-
premium: true,
|
|
332
|
-
category: "Code",
|
|
333
|
-
tags: ["animation", "typing", "terminal", "sequence"],
|
|
334
|
-
features: ["Typing Animation", "Sequenced", "Interactive", "TypeScript"],
|
|
335
|
-
dependencies: ["motion", "react"],
|
|
336
|
-
props: {
|
|
337
|
-
"Terminal": [
|
|
338
|
-
{ name: "className", type: "string", default: "null" },
|
|
339
|
-
{ name: "sequence", type: "boolean", default: "true" },
|
|
340
|
-
{ name: "startOnView", type: "boolean", default: "true" }
|
|
341
|
-
],
|
|
342
|
-
"AnimatedSpan": [
|
|
343
|
-
{ name: "className", type: "string", default: "null" },
|
|
344
|
-
{ name: "delay", type: "number", default: "0" },
|
|
345
|
-
{ name: "startOnView", type: "boolean", default: "false" }
|
|
346
|
-
],
|
|
347
|
-
"TypingAnimation": [
|
|
348
|
-
{ name: "className", type: "string", default: "null" },
|
|
349
|
-
{ name: "duration", type: "number", default: "60" },
|
|
350
|
-
{ name: "delay", type: "number", default: "0" },
|
|
351
|
-
{ name: "as", type: "React.ElementType", default: "span" },
|
|
352
|
-
{ name: "startOnView", type: "boolean", default: "true" }
|
|
353
|
-
]
|
|
354
|
-
},
|
|
355
|
-
desc: null,
|
|
356
|
-
status: null,
|
|
357
|
-
lastUpdated: null
|
|
358
|
-
},
|
|
359
|
-
{
|
|
360
|
-
name: "Sandbox",
|
|
361
|
-
value: "sandbox",
|
|
362
|
-
importPath: "~/components/catalyst-ui/code/sandbox",
|
|
363
|
-
multiImport: "SandboxTabs, SandboxTabsList, SandboxTabsTrigger, SandboxTabsContent, SandboxCodeEditor, SandboxConsole, SandboxFileExplorer, SandboxLayout, SandboxPreview, SandboxProvider",
|
|
364
|
-
basicusage: `
|
|
365
|
-
|
|
292
|
+
✔ Validating
|
|
366
293
|
|
|
367
294
|
|
|
368
295
|
const Example = () => (
|