purvex-ui 0.1.2 → 0.1.6
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/package.json +4 -3
- package/registry/components.json +30 -0
- package/templates/avatar.jsx +70 -0
- package/templates/button.jsx +83 -0
- package/templates/card.jsx +67 -0
- package/templates/utils.js +6 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "purvex-ui",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "React component generator with Tailwind CSS v4 & Purple Elegant theme
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "React component generator with Tailwind CSS v4 & Purple Elegant theme",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"purvex-ui": "src/index.js"
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"src/",
|
|
11
11
|
"templates/",
|
|
12
|
-
"registry/"
|
|
12
|
+
"registry/",
|
|
13
|
+
"README.md"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
15
16
|
"test": "echo \"No tests yet\"",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.1.0",
|
|
3
|
+
"lastUpdated": "2025-12-28",
|
|
4
|
+
"components": [
|
|
5
|
+
{
|
|
6
|
+
"name": "button",
|
|
7
|
+
"displayName": "Button",
|
|
8
|
+
"description": "Tombol dengan berbagai variant dan ukuran",
|
|
9
|
+
"category": "basic",
|
|
10
|
+
"files": ["button.jsx"],
|
|
11
|
+
"dependencies": []
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "card",
|
|
15
|
+
"displayName": "Card",
|
|
16
|
+
"description": "Komponen card untuk konten",
|
|
17
|
+
"category": "layout",
|
|
18
|
+
"files": ["card.jsx"],
|
|
19
|
+
"dependencies": []
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "avatar",
|
|
23
|
+
"displayName": "Avatar",
|
|
24
|
+
"description": "Komponen avatar untuk menampilkan gambar profil",
|
|
25
|
+
"category": "layout",
|
|
26
|
+
"files": ["avatar.jsx"],
|
|
27
|
+
"dependencies": []
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
const Avatar = React.forwardRef(function Avatar({
|
|
5
|
+
src,
|
|
6
|
+
alt = "avatar",
|
|
7
|
+
size = 72,
|
|
8
|
+
border = true,
|
|
9
|
+
variant = "circle", // circle, square, star, heart, triangle, abstract
|
|
10
|
+
className,
|
|
11
|
+
...props
|
|
12
|
+
}, ref) {
|
|
13
|
+
// Variants shapes dengan clip-path yang benar
|
|
14
|
+
const shapeStyles = {
|
|
15
|
+
star: {
|
|
16
|
+
clipPath: 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)'
|
|
17
|
+
},
|
|
18
|
+
heart: {
|
|
19
|
+
clipPath: 'polygon(50% 93%, 5% 40%, 25% 10%, 50% 30%, 75% 10%, 95% 40%)'
|
|
20
|
+
},
|
|
21
|
+
triangle: {
|
|
22
|
+
clipPath: 'polygon(50% 0%, 0% 100%, 100% 100%)'
|
|
23
|
+
},
|
|
24
|
+
abstract: {
|
|
25
|
+
clipPath: 'polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)'
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Kelas Tailwind untuk shape biasa
|
|
30
|
+
const shapeClasses = {
|
|
31
|
+
circle: "rounded-full",
|
|
32
|
+
square: "rounded-md",
|
|
33
|
+
star: "",
|
|
34
|
+
heart: "",
|
|
35
|
+
triangle: "",
|
|
36
|
+
abstract: "",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Apakah perlu inline style untuk clip-path?
|
|
40
|
+
const needsClipPath = ['star', 'heart', 'triangle', 'abstract'].includes(variant);
|
|
41
|
+
const inlineStyle = needsClipPath ? shapeStyles[variant] : {};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn(
|
|
47
|
+
"relative overflow-hidden shrink-0",
|
|
48
|
+
border && "before:absolute before:inset-0 before:border-2 before:border-border/20",
|
|
49
|
+
shapeClasses[variant],
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
style={{
|
|
53
|
+
...inlineStyle,
|
|
54
|
+
width: `${size}px`,
|
|
55
|
+
height: `${size}px`,
|
|
56
|
+
}}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
<img
|
|
60
|
+
src={src}
|
|
61
|
+
alt={alt}
|
|
62
|
+
className="w-full h-full object-cover"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
Avatar.displayName = "Avatar";
|
|
69
|
+
|
|
70
|
+
export { Avatar };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
const Button = React.forwardRef(function Button(
|
|
5
|
+
{ className, variant = "default", size = "default", children, ...props },
|
|
6
|
+
ref
|
|
7
|
+
) {
|
|
8
|
+
const baseClasses = cn(
|
|
9
|
+
// Base styles
|
|
10
|
+
"inline-flex items-center justify-center break-words rounded-md text-sm font-bold",
|
|
11
|
+
"ring-offset-background transition-colors",
|
|
12
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
13
|
+
"disabled:pointer-events-none disabled:opacity-50 hover:cursor-pointer hover:scale-102 transition-all",
|
|
14
|
+
|
|
15
|
+
// Variants flat
|
|
16
|
+
variant === "default" &&
|
|
17
|
+
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
18
|
+
variant === "primary-outline" &&
|
|
19
|
+
"bg-blue-100 text-blue-600 hover:bg-blue-200",
|
|
20
|
+
variant === "destructive" &&
|
|
21
|
+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
22
|
+
variant === "outline" &&
|
|
23
|
+
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
24
|
+
variant === "secondary" &&
|
|
25
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
26
|
+
variant === "ghost" && "hover:bg-accent hover:text-accent-foreground",
|
|
27
|
+
variant === "link" && "text-primary underline-offset-4 hover:underline",
|
|
28
|
+
variant === "success" && "bg-green-600 text-white hover:bg-green-700",
|
|
29
|
+
variant === "warning" && "bg-yellow-500 text-black hover:bg-yellow-600",
|
|
30
|
+
variant === "info" && "bg-blue-500 text-white hover:bg-blue-600",
|
|
31
|
+
variant === "dark" && "bg-gray-800 text-white hover:bg-gray-900",
|
|
32
|
+
|
|
33
|
+
// Gradient variants
|
|
34
|
+
variant === "primary-gradient" &&
|
|
35
|
+
"bg-linear-to-bl from-purple-500 via-purple-600 to-purple-700 text-white hover:from-purple-600 hover:via-purple-700 hover:to-purple-800",
|
|
36
|
+
variant === "destructive-gradient" &&
|
|
37
|
+
"bg-linear-to-bl from-red-500 via-red-600 to-red-700 text-white hover:from-red-600 hover:via-red-700 hover:to-red-800",
|
|
38
|
+
variant === "success-gradient" &&
|
|
39
|
+
"bg-linear-to-br from-green-500 via-green-600 to-green-700 text-white hover:from-green-600 hover:via-green-700 hover:to-green-800",
|
|
40
|
+
variant === "warning-gradient" &&
|
|
41
|
+
"bg-linear-to-br from-yellow-400 via-yellow-500 to-yellow-600 text-black hover:from-yellow-500 hover:via-yellow-600 hover:to-yellow-700",
|
|
42
|
+
variant === "info-gradient" &&
|
|
43
|
+
"bg-linear-to-bl from-blue-400 via-blue-500 to-blue-600 text-white hover:from-blue-500 hover:via-blue-600 hover:to-blue-700",
|
|
44
|
+
variant === "secondary-gradient" &&
|
|
45
|
+
"bg-linear-to-bl from-gray-200 via-gray-300 to-gray-400 text-gray-800 hover:from-gray-300 hover:via-gray-400 hover:to-gray-500",
|
|
46
|
+
variant === "dark-gradient" &&
|
|
47
|
+
"bg-linear-to-bl from-gray-700 via-gray-800 to-gray-900 text-white hover:from-gray-800 hover:via-gray-900 hover:to-black",
|
|
48
|
+
|
|
49
|
+
// Pasangan / light / outline
|
|
50
|
+
variant === "primary-light" &&
|
|
51
|
+
"bg-primary/20 text-primary hover:bg-primary/30",
|
|
52
|
+
variant === "destructive-light" &&
|
|
53
|
+
"bg-destructive/20 text-destructive hover:bg-destructive/30",
|
|
54
|
+
variant === "success-light" &&
|
|
55
|
+
"bg-green-100 text-green-600 hover:bg-green-200",
|
|
56
|
+
variant === "warning-light" &&
|
|
57
|
+
"bg-yellow-100 text-yellow-600 hover:bg-yellow-200",
|
|
58
|
+
variant === "info-light" && "bg-blue-100 text-blue-600 hover:bg-blue-200",
|
|
59
|
+
variant === "secondary-light" &&
|
|
60
|
+
"bg-secondary/20 text-secondary hover:bg-secondary/30",
|
|
61
|
+
variant === "dark-light" &&
|
|
62
|
+
"bg-gray-700/30 text-gray-800 hover:bg-gray-700/50",
|
|
63
|
+
|
|
64
|
+
// Sizes
|
|
65
|
+
size === "default" && "min-h-10 rounded-lg px-5 py-2",
|
|
66
|
+
size === "sm" && "min-h-9 rounded-md px-3",
|
|
67
|
+
size === "lg" && "min-h-11 rounded-md px-8",
|
|
68
|
+
size === "icon" && "h-10 w-10",
|
|
69
|
+
|
|
70
|
+
// Custom classes dari user
|
|
71
|
+
className
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<button className={baseClasses} ref={ref} {...props}>
|
|
76
|
+
{children}
|
|
77
|
+
</button>
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
Button.displayName = "Button";
|
|
82
|
+
|
|
83
|
+
export { Button };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
const Card = React.forwardRef(function Card({ className, hover = false, ...props }, ref) {
|
|
5
|
+
return (
|
|
6
|
+
<div
|
|
7
|
+
ref={ref}
|
|
8
|
+
className={cn(
|
|
9
|
+
"rounded-2xl border bg-card text-card-foreground transition-all",
|
|
10
|
+
hover && "hover:shadow-md hover:scale-[1.02]",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
Card.displayName = "Card";
|
|
19
|
+
|
|
20
|
+
const CardHeader = React.forwardRef(function CardHeader({ className, ...props }, ref) {
|
|
21
|
+
return (
|
|
22
|
+
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
CardHeader.displayName = "CardHeader";
|
|
27
|
+
|
|
28
|
+
const CardTitle = React.forwardRef(function CardTitle({ className, ...props }, ref) {
|
|
29
|
+
return (
|
|
30
|
+
<h3
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={cn("text-2xl font-semibold leading-none tracking-tight", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
CardTitle.displayName = "CardTitle";
|
|
39
|
+
|
|
40
|
+
const CardDescription = React.forwardRef(function CardDescription({ className, ...props }, ref) {
|
|
41
|
+
return (
|
|
42
|
+
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
CardDescription.displayName = "CardDescription";
|
|
47
|
+
|
|
48
|
+
const CardContent = React.forwardRef(function CardContent({ className, ...props }, ref) {
|
|
49
|
+
return <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
CardContent.displayName = "CardContent";
|
|
53
|
+
|
|
54
|
+
const CardFooter = React.forwardRef(function CardFooter({ className, ...props }, ref) {
|
|
55
|
+
return <div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
CardFooter.displayName = "CardFooter";
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
Card,
|
|
62
|
+
CardHeader,
|
|
63
|
+
CardFooter,
|
|
64
|
+
CardTitle,
|
|
65
|
+
CardDescription,
|
|
66
|
+
CardContent,
|
|
67
|
+
};
|