Commit
·
e9c0734
1
Parent(s):
390e277
add categories
Browse files- app/page.tsx +10 -4
- components/CategoryCard.tsx +41 -0
- components/CategoryRow.tsx +24 -0
- lib/categories.tsx +39 -0
- lib/icons/EmbeddingIcon.tsx +38 -0
- lib/icons/SegmentationIcon.tsx +29 -0
- lib/icons/SentimentAnalysisIcon.tsx +36 -0
- lib/icons/TranscriptionIcon.tsx +32 -0
- lib/utils.ts +43 -0
- package-lock.json +26 -0
- package.json +1 -0
- types/categories.ts +10 -0
app/page.tsx
CHANGED
@@ -1,15 +1,21 @@
|
|
|
|
1 |
import PillLink from '@/components/PillLink';
|
|
|
|
|
2 |
|
3 |
export default function Home() {
|
4 |
return (
|
5 |
-
<div className="mx-auto
|
6 |
<PillLink text="Transformers.js" link="https://www.npmjs.com/package/@xenova/transformers" newText='Powered by' />
|
7 |
-
<h1 className="text-
|
8 |
Playground
|
9 |
</h1>
|
10 |
-
<p className="font-bold text-slate-700
|
11 |
The fastest way to get started with Transformers.js.
|
12 |
</p>
|
|
|
|
|
|
|
13 |
</div>
|
14 |
);
|
15 |
-
}
|
|
|
1 |
+
"use client"
|
2 |
import PillLink from '@/components/PillLink';
|
3 |
+
import CategoryRow from '@/components/CategoryRow';
|
4 |
+
import { categories } from "@/lib/categories";
|
5 |
|
6 |
export default function Home() {
|
7 |
return (
|
8 |
+
<div className="container mx-auto px-4 py-8 text-center">
|
9 |
<PillLink text="Transformers.js" link="https://www.npmjs.com/package/@xenova/transformers" newText='Powered by' />
|
10 |
+
<h1 className="text-4xl sm:text-5xl md:text-6xl font-extrabold tracking-tighter mb-4">
|
11 |
Playground
|
12 |
</h1>
|
13 |
+
<p className="font-bold text-slate-700 font-mono italic text-lg mb-10">
|
14 |
The fastest way to get started with Transformers.js.
|
15 |
</p>
|
16 |
+
<div className="mt-24">
|
17 |
+
<CategoryRow categories={categories} />
|
18 |
+
</div>
|
19 |
</div>
|
20 |
);
|
21 |
+
}
|
components/CategoryCard.tsx
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import type { Category } from '../types/categories';
|
3 |
+
import { getColorConfig } from '@/lib/utils';
|
4 |
+
|
5 |
+
type CategoryCardProps = Category;
|
6 |
+
|
7 |
+
const CategoryCard: React.FC<CategoryCardProps> = ({
|
8 |
+
title,
|
9 |
+
icon: Icon,
|
10 |
+
colorName,
|
11 |
+
description,
|
12 |
+
isNew,
|
13 |
+
graphic: Graphic
|
14 |
+
}) => {
|
15 |
+
const { text, gradient, iconBg } = getColorConfig(colorName);
|
16 |
+
|
17 |
+
return (
|
18 |
+
<div className={`bg-gradient-to-br ${gradient} rounded-xl p-4 text-white w-92 h-[380px] flex flex-col relative shadow-lg transition-transform duration-300 ease-in-out hover:scale-105`}>
|
19 |
+
{isNew && (
|
20 |
+
<div className={`absolute top-2 right-2 ${iconBg} ${text} text-xs font-bold py-1 px-2 rounded-full`}>
|
21 |
+
New
|
22 |
+
</div>
|
23 |
+
)}
|
24 |
+
<div className="flex items-center mb-3">
|
25 |
+
<div className={`${iconBg} ${text} p-1.5 rounded-full mr-2`}>
|
26 |
+
<Icon size={20} />
|
27 |
+
</div>
|
28 |
+
<h2 className="text-xl font-bold">{title}</h2>
|
29 |
+
</div>
|
30 |
+
<div className="mb-3 flex-grow">
|
31 |
+
<Graphic />
|
32 |
+
</div>
|
33 |
+
<p className="text-xs mb-3 leading-tight">{description}</p>
|
34 |
+
<button className={`w-full bg-white ${text} py-2 px-3 rounded-lg text-sm font-semibold hover:bg-opacity-90 transition-colors mt-auto`}>
|
35 |
+
View Tools
|
36 |
+
</button>
|
37 |
+
</div>
|
38 |
+
);
|
39 |
+
};
|
40 |
+
|
41 |
+
export default CategoryCard;
|
components/CategoryRow.tsx
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { motion } from 'framer-motion';
|
2 |
+
import CategoryCard from '@/components/CategoryCard';
|
3 |
+
import { Category } from '@/types/categories';
|
4 |
+
|
5 |
+
interface CategoryRowProps {
|
6 |
+
categories: Category[];
|
7 |
+
}
|
8 |
+
|
9 |
+
export default function CategoryRow({ categories }: CategoryRowProps) {
|
10 |
+
return (
|
11 |
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 sm:gap-12 max-w-5xl mx-auto">
|
12 |
+
{categories.map((category, index) => (
|
13 |
+
<motion.div
|
14 |
+
key={category.title}
|
15 |
+
initial={{ opacity: 0, y: 20 }}
|
16 |
+
animate={{ opacity: 1, y: 0 }}
|
17 |
+
transition={{ duration: 0.5, delay: index * 0.1 }}
|
18 |
+
>
|
19 |
+
<CategoryCard {...category} />
|
20 |
+
</motion.div>
|
21 |
+
))}
|
22 |
+
</div>
|
23 |
+
);
|
24 |
+
}
|
lib/categories.tsx
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use client"
|
2 |
+
import { Scissors, Sparkles, Mic, Smile } from 'lucide-react';
|
3 |
+
import type { Category } from '../types/categories';
|
4 |
+
import SegmentationIcon from './icons/SegmentationIcon';
|
5 |
+
import TranscriptionIcon from './icons/TranscriptionIcon';
|
6 |
+
import SentimentAnalysisIcon from './icons/SentimentAnalysisIcon';
|
7 |
+
import EmbeddingIcon from './icons/EmbeddingIcon';
|
8 |
+
|
9 |
+
export const categories: Category[] = [
|
10 |
+
{
|
11 |
+
title: "Segment",
|
12 |
+
icon: Scissors,
|
13 |
+
description: "Break down images into distinct segments based on the object or background.",
|
14 |
+
isNew: true,
|
15 |
+
colorName: "indigo",
|
16 |
+
graphic: SegmentationIcon
|
17 |
+
},
|
18 |
+
{
|
19 |
+
title: "Embed",
|
20 |
+
icon: Sparkles,
|
21 |
+
description: "Create vector embeddings for text and images.",
|
22 |
+
colorName: "teal",
|
23 |
+
graphic: EmbeddingIcon
|
24 |
+
},
|
25 |
+
{
|
26 |
+
title: "Transcribe",
|
27 |
+
icon: Mic,
|
28 |
+
description: "Convert speech to text with high accuracy using advanced AI-powered transcription (Whisper).",
|
29 |
+
colorName: "rose",
|
30 |
+
graphic: TranscriptionIcon
|
31 |
+
},
|
32 |
+
{
|
33 |
+
title: "Sentiment",
|
34 |
+
icon: Smile,
|
35 |
+
description: "Analyze text to determine the emotional tone and attitude, classifying it as positive, negative, or neutral.",
|
36 |
+
colorName: "amber",
|
37 |
+
graphic: SentimentAnalysisIcon
|
38 |
+
}
|
39 |
+
];
|
lib/icons/EmbeddingIcon.tsx
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
interface IconProps {
|
4 |
+
className?: string;
|
5 |
+
}
|
6 |
+
|
7 |
+
const EmbeddingIcon: React.FC<IconProps> = ({ className = '' }) => {
|
8 |
+
return (
|
9 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" className={`w-full h-auto max-h-28 ${className}`}>
|
10 |
+
<rect x="0" y="0" width="200" height="100" fill="#5eead4" rx="10" ry="10" />
|
11 |
+
|
12 |
+
{/* Text representation */}
|
13 |
+
<rect x="10" y="10" width="80" height="80" fill="#f0fdfa" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
14 |
+
<text x="20" y="40" fill="#f472b6" fontSize="14" fontWeight="bold">Hello</text>
|
15 |
+
<text x="20" y="70" fill="#60a5fa" fontSize="14" fontWeight="bold">World</text>
|
16 |
+
|
17 |
+
{/* Arrow */}
|
18 |
+
<line x1="95" y1="50" x2="105" y2="50" stroke="#fff" strokeWidth="2" />
|
19 |
+
<polygon points="105,46 113,50 105,54" fill="#fff" />
|
20 |
+
|
21 |
+
{/* 3D space representation */}
|
22 |
+
<rect x="110" y="10" width="80" height="80" fill="#f0fdfa" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
23 |
+
|
24 |
+
{/* 3D axes */}
|
25 |
+
<line x1="115" y1="85" x2="185" y2="85" stroke="#0f766e" strokeWidth="1" opacity="0.5" />
|
26 |
+
<line x1="115" y1="85" x2="115" y2="15" stroke="#0f766e" strokeWidth="1" opacity="0.5" />
|
27 |
+
<line x1="115" y1="85" x2="145" y2="65" stroke="#0f766e" strokeWidth="1" opacity="0.5" />
|
28 |
+
|
29 |
+
{/* 3D points */}
|
30 |
+
<circle cx="150" cy="40" r="4" fill="#f472b6" />
|
31 |
+
<text x="157" y="44" fill="#f472b6" fontSize="10" fontWeight="bold">Hello</text>
|
32 |
+
<circle cx="155" cy="70" r="4" fill="#60a5fa" />
|
33 |
+
<text x="120" y="74" fill="#60a5fa" fontSize="10" fontWeight="bold">World</text>
|
34 |
+
</svg>
|
35 |
+
);
|
36 |
+
};
|
37 |
+
|
38 |
+
export default EmbeddingIcon;
|
lib/icons/SegmentationIcon.tsx
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
interface IconProps {
|
4 |
+
className?: string;
|
5 |
+
}
|
6 |
+
|
7 |
+
const SegmentationIcon: React.FC<IconProps> = ({ className = '' }) => {
|
8 |
+
return (
|
9 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" className={`w-full h-auto max-h-28 ${className}`}>
|
10 |
+
<rect x="0" y="0" width="200" height="100" fill="#818cf8" rx="10" ry="10" />
|
11 |
+
|
12 |
+
{/* Original Image */}
|
13 |
+
<rect x="10" y="10" width="80" height="80" fill="#e0e0e0" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
14 |
+
<circle cx="35" cy="35" r="15" fill="#fbbf24" />
|
15 |
+
<rect x="55" y="45" width="25" height="35" fill="#34d399" />
|
16 |
+
|
17 |
+
{/* Arrow */}
|
18 |
+
<line x1="95" y1="50" x2="105" y2="50" stroke="#fff" strokeWidth="2" />
|
19 |
+
<polygon points="105,46 113,50 105,54" fill="#fff" />
|
20 |
+
|
21 |
+
{/* Segmented Image */}
|
22 |
+
<rect x="110" y="10" width="80" height="80" fill="#e0e0e0" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
23 |
+
<circle cx="135" cy="35" r="15" fill="#fbbf24" stroke="#e11d48" strokeWidth="2" strokeDasharray="4 2" />
|
24 |
+
<rect x="155" y="45" width="25" height="35" fill="#34d399" stroke="#e11d48" strokeWidth="2" strokeDasharray="4 2" />
|
25 |
+
</svg>
|
26 |
+
);
|
27 |
+
};
|
28 |
+
|
29 |
+
export default SegmentationIcon;
|
lib/icons/SentimentAnalysisIcon.tsx
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
interface IconProps {
|
4 |
+
className?: string;
|
5 |
+
}
|
6 |
+
|
7 |
+
const SentimentAnalysisIcon: React.FC<IconProps> = ({ className = '' }) => {
|
8 |
+
return (
|
9 |
+
<svg
|
10 |
+
xmlns="http://www.w3.org/2000/svg"
|
11 |
+
viewBox="0 0 200 100"
|
12 |
+
className={`w-full h-auto max-h-28 ${className}`}
|
13 |
+
>
|
14 |
+
<rect x="0" y="0" width="200" height="100" fill="#fbbf24" rx="10" ry="10" />
|
15 |
+
|
16 |
+
{/* Input text */}
|
17 |
+
<rect x="10" y="10" width="80" height="80" fill="#fffbeb" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
18 |
+
<text x="15" y="35" fill="#92400e" fontSize="8" fontWeight="bold">Great product!</text>
|
19 |
+
<text x="15" y="50" fill="#92400e" fontSize="8" fontWeight="bold">Highly</text>
|
20 |
+
<text x="15" y="65" fill="#92400e" fontSize="8" fontWeight="bold">recommended.</text>
|
21 |
+
|
22 |
+
{/* Arrow */}
|
23 |
+
<line x1="95" y1="50" x2="105" y2="50" stroke="#fff" strokeWidth="2" />
|
24 |
+
<polygon points="105,46 113,50 105,54" fill="#fff" />
|
25 |
+
|
26 |
+
{/* Sentiment analysis result */}
|
27 |
+
<rect x="110" y="10" width="80" height="80" fill="#fffbeb" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
28 |
+
<circle cx="150" cy="50" r="22" fill="#4ade80" />
|
29 |
+
<path d="M140 50 Q 150 60, 160 50" fill="none" stroke="#fffbeb" strokeWidth="2" />
|
30 |
+
<circle cx="143" cy="43" r="2" fill="#fffbeb" />
|
31 |
+
<circle cx="157" cy="43" r="2" fill="#fffbeb" />
|
32 |
+
</svg>
|
33 |
+
);
|
34 |
+
};
|
35 |
+
|
36 |
+
export default SentimentAnalysisIcon;
|
lib/icons/TranscriptionIcon.tsx
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
interface TranscriptionIconProps {
|
4 |
+
className?: string;
|
5 |
+
}
|
6 |
+
|
7 |
+
const TranscriptionIcon: React.FC<TranscriptionIconProps> = ({ className = '' }) => {
|
8 |
+
return (
|
9 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" className={`w-full h-auto max-h-28 ${className}`}>
|
10 |
+
<rect x="0" y="0" width="200" height="100" fill="#fb7185" rx="10" ry="10" />
|
11 |
+
|
12 |
+
{/* Audio waveform */}
|
13 |
+
<rect x="10" y="10" width="80" height="80" fill="#fff1f2" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
14 |
+
<path d="M15 50 Q 25 20, 35 50 Q 45 80, 55 50 Q 65 20, 75 50 Q 85 80, 95 50"
|
15 |
+
fill="none" stroke="#e11d48" strokeWidth="2" />
|
16 |
+
|
17 |
+
{/* Arrow */}
|
18 |
+
<line x1="95" y1="50" x2="105" y2="50" stroke="#fff" strokeWidth="2" />
|
19 |
+
<polygon points="105,46 113,50 105,54" fill="#fff" />
|
20 |
+
|
21 |
+
{/* Transcribed text */}
|
22 |
+
<rect x="110" y="10" width="80" height="80" fill="#fff1f2" stroke="#fff" strokeWidth="1" rx="5" ry="5" />
|
23 |
+
<text x="120" y="30" fill="#be123c" fontSize="10" fontWeight="bold">Hello, how</text>
|
24 |
+
<text x="120" y="45" fill="#be123c" fontSize="10" fontWeight="bold">are you</text>
|
25 |
+
<text x="120" y="60" fill="#be123c" fontSize="10" fontWeight="bold">today?</text>
|
26 |
+
<line x1="120" y1="70" x2="180" y2="70" stroke="#fda4af" strokeWidth="1" />
|
27 |
+
<line x1="120" y1="80" x2="170" y2="80" stroke="#fda4af" strokeWidth="1" />
|
28 |
+
</svg>
|
29 |
+
);
|
30 |
+
};
|
31 |
+
|
32 |
+
export default TranscriptionIcon;
|
lib/utils.ts
CHANGED
@@ -4,3 +4,46 @@ import { twMerge } from "tailwind-merge"
|
|
4 |
export function cn(...inputs: ClassValue[]) {
|
5 |
return twMerge(clsx(inputs))
|
6 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
export function cn(...inputs: ClassValue[]) {
|
5 |
return twMerge(clsx(inputs))
|
6 |
}
|
7 |
+
|
8 |
+
export type ColorConfig = {
|
9 |
+
bg: string;
|
10 |
+
text: string;
|
11 |
+
gradient: string;
|
12 |
+
iconBg: string;
|
13 |
+
};
|
14 |
+
|
15 |
+
export const colorConfigs: Record<string, ColorConfig> = {
|
16 |
+
indigo: {
|
17 |
+
bg: 'bg-indigo-200',
|
18 |
+
text: 'text-indigo-800',
|
19 |
+
gradient: 'from-indigo-500 to-indigo-700',
|
20 |
+
iconBg: 'bg-indigo-200',
|
21 |
+
},
|
22 |
+
teal: {
|
23 |
+
bg: 'bg-teal-200',
|
24 |
+
text: 'text-teal-800',
|
25 |
+
gradient: 'from-teal-500 to-teal-700',
|
26 |
+
iconBg: 'bg-teal-200',
|
27 |
+
},
|
28 |
+
rose: {
|
29 |
+
bg: 'bg-rose-200',
|
30 |
+
text: 'text-rose-800',
|
31 |
+
gradient: 'from-rose-500 to-rose-700',
|
32 |
+
iconBg: 'bg-rose-200',
|
33 |
+
},
|
34 |
+
amber: {
|
35 |
+
bg: 'bg-amber-200',
|
36 |
+
text: 'text-amber-800',
|
37 |
+
gradient: 'from-amber-500 to-amber-700',
|
38 |
+
iconBg: 'bg-amber-200',
|
39 |
+
},
|
40 |
+
};
|
41 |
+
|
42 |
+
export const getColorConfig = (colorName: string): ColorConfig => {
|
43 |
+
return colorConfigs[colorName] || {
|
44 |
+
bg: 'bg-gray-200',
|
45 |
+
text: 'text-gray-800',
|
46 |
+
gradient: 'from-gray-500 to-gray-700',
|
47 |
+
iconBg: 'bg-gray-200',
|
48 |
+
};
|
49 |
+
};
|
package-lock.json
CHANGED
@@ -14,6 +14,7 @@
|
|
14 |
"class-variance-authority": "^0.7.0",
|
15 |
"clsx": "^2.1.1",
|
16 |
"cmdk": "^1.0.0",
|
|
|
17 |
"lucide-react": "^0.451.0",
|
18 |
"next": "14.2.15",
|
19 |
"react": "^18",
|
@@ -3054,6 +3055,31 @@
|
|
3054 |
"url": "https://github.com/sponsors/isaacs"
|
3055 |
}
|
3056 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3057 |
"node_modules/fs.realpath": {
|
3058 |
"version": "1.0.0",
|
3059 |
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
|
|
14 |
"class-variance-authority": "^0.7.0",
|
15 |
"clsx": "^2.1.1",
|
16 |
"cmdk": "^1.0.0",
|
17 |
+
"framer-motion": "^11.11.7",
|
18 |
"lucide-react": "^0.451.0",
|
19 |
"next": "14.2.15",
|
20 |
"react": "^18",
|
|
|
3055 |
"url": "https://github.com/sponsors/isaacs"
|
3056 |
}
|
3057 |
},
|
3058 |
+
"node_modules/framer-motion": {
|
3059 |
+
"version": "11.11.7",
|
3060 |
+
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.7.tgz",
|
3061 |
+
"integrity": "sha512-89CgILOXPeG3L7ymOTGrLmf8IiKubYLUN/QkYgQuLvehAHfqgwJbLfCnhuyRI4WTds1TXkUp67A7IJrgRY/j1w==",
|
3062 |
+
"license": "MIT",
|
3063 |
+
"dependencies": {
|
3064 |
+
"tslib": "^2.4.0"
|
3065 |
+
},
|
3066 |
+
"peerDependencies": {
|
3067 |
+
"@emotion/is-prop-valid": "*",
|
3068 |
+
"react": "^18.0.0",
|
3069 |
+
"react-dom": "^18.0.0"
|
3070 |
+
},
|
3071 |
+
"peerDependenciesMeta": {
|
3072 |
+
"@emotion/is-prop-valid": {
|
3073 |
+
"optional": true
|
3074 |
+
},
|
3075 |
+
"react": {
|
3076 |
+
"optional": true
|
3077 |
+
},
|
3078 |
+
"react-dom": {
|
3079 |
+
"optional": true
|
3080 |
+
}
|
3081 |
+
}
|
3082 |
+
},
|
3083 |
"node_modules/fs.realpath": {
|
3084 |
"version": "1.0.0",
|
3085 |
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
package.json
CHANGED
@@ -15,6 +15,7 @@
|
|
15 |
"class-variance-authority": "^0.7.0",
|
16 |
"clsx": "^2.1.1",
|
17 |
"cmdk": "^1.0.0",
|
|
|
18 |
"lucide-react": "^0.451.0",
|
19 |
"next": "14.2.15",
|
20 |
"react": "^18",
|
|
|
15 |
"class-variance-authority": "^0.7.0",
|
16 |
"clsx": "^2.1.1",
|
17 |
"cmdk": "^1.0.0",
|
18 |
+
"framer-motion": "^11.11.7",
|
19 |
"lucide-react": "^0.451.0",
|
20 |
"next": "14.2.15",
|
21 |
"react": "^18",
|
types/categories.ts
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { LucideIcon } from 'lucide-react';
|
2 |
+
|
3 |
+
export interface Category {
|
4 |
+
title: string;
|
5 |
+
icon: LucideIcon;
|
6 |
+
description: string;
|
7 |
+
isNew?: boolean;
|
8 |
+
colorName: string;
|
9 |
+
graphic: React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
10 |
+
};
|