@rajdeep0510/scaffold-cli 1.0.2 → 1.3.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.
@@ -1,92 +1,85 @@
1
- import React, { useState } from 'react';
2
- import PropTypes from 'prop-types';
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import clsx from "clsx";
3
4
 
4
- /**
5
- * A customizable button component with multiple variants and sizes + click animation
6
- */
7
5
  const Button = ({
8
- children,
9
- variant = 'primary',
10
- size = 'md',
11
- disabled = false,
12
- loading = false,
13
- className = '',
14
- onClick,
15
- type = 'button',
16
- ...rest
17
- }) => {
18
- const [isActive, setIsActive] = useState(false);
6
+ children,
7
+ size = "sm",
8
+ disabled = false,
9
+ loading = false,
10
+ className = "",
11
+ onClick,
12
+ type = "button",
13
+ borderColor = "white", // "white" or "black"
14
+ borderWidth = 1,
15
+ borderStyle = "solid",
16
+ borderRadius = "md", // sm, md, lg, xl, full
17
+ ...rest
18
+ }) => {
19
+ const sizeClasses = {
20
+ sm: "h-8 px-3 text-sm",
21
+ md: "h-10 px-4 text-sm",
22
+ lg: "h-12 px-5 text-base",
23
+ xl: "h-14 px-6 text-lg",
24
+ };
19
25
 
20
- const baseStyles = {
21
- display: 'inline-flex',
22
- alignItems: 'center',
23
- justifyContent: 'center',
24
- border: 'none',
25
- borderRadius: '6px',
26
- fontFamily: 'inherit',
27
- fontWeight: '500',
28
- cursor: disabled || loading ? 'not-allowed' : 'pointer',
29
- transition: 'all 0.15s ease-in-out',
30
- opacity: disabled || loading ? 0.6 : 1,
31
- transform: isActive ? 'scale(0.95)' : 'scale(1)', // 👈 shrink effect
32
- };
26
+ const radiusClasses = {
27
+ sm: "rounded-sm",
28
+ md: "rounded-md",
29
+ lg: "rounded-lg",
30
+ xl: "rounded-xl",
31
+ full: "rounded-full",
32
+ };
33
33
 
34
- const variantStyles = {
35
- primary: { backgroundColor: '#3b82f6', color: 'white' },
36
- secondary: { backgroundColor: '#f8fafc', color: '#374151', border: '1px solid #d1d5db' },
37
- destructive: { backgroundColor: '#dc2626', color: 'white' },
38
- outline: { backgroundColor: 'transparent', border: '1px solid #d1d5db', color: '#374151' },
39
- ghost: { backgroundColor: 'transparent', color: '#374151' },
40
- };
34
+ const borderClasses = clsx(
35
+ `border-${borderWidth}`,
36
+ borderStyle !== "solid" && `border-${borderStyle}`,
37
+ borderColor === "white" ? "border-white" : "border-black"
38
+ );
41
39
 
42
- const sizeStyles = {
43
- sm: { height: '32px', padding: '0 12px', fontSize: '14px' },
44
- md: { height: '40px', padding: '0 16px', fontSize: '14px' },
45
- lg: { height: '44px', padding: '0 24px', fontSize: '16px' },
46
- xl: { height: '52px', padding: '0 32px', fontSize: '16px' },
47
- };
40
+ const buttonClasses = clsx(
41
+ "inline-flex items-center justify-center font-medium",
42
+ "transition-transform duration-150 ease-in-out", // smooth animation
43
+ "active:scale-95", // 👈 shrink when clicked
44
+ borderClasses,
45
+ radiusClasses[borderRadius],
46
+ sizeClasses[size],
47
+ disabled || loading ? "opacity-60 cursor-not-allowed" : "cursor-pointer",
48
+ className
49
+ );
48
50
 
49
- const buttonStyles = {
50
- ...baseStyles,
51
- ...variantStyles[variant],
52
- ...sizeStyles[size],
53
- };
54
-
55
- const handleClick = (e) => {
56
- if (disabled || loading) {
57
- e.preventDefault();
58
- return;
59
- }
60
- setIsActive(true);
61
- setTimeout(() => setIsActive(false), 150); // reset after animation
62
- if (onClick) onClick(e);
63
- };
64
-
65
- return (
66
- <button
67
- type={type}
68
- disabled={disabled || loading}
69
- onClick={handleClick}
70
- className={className}
71
- style={buttonStyles}
72
- aria-disabled={disabled || loading}
73
- aria-busy={loading}
74
- {...rest}
75
- >
76
- {loading ? 'Loading...' : children}
77
- </button>
78
- );
51
+ return (
52
+ <button
53
+ type={type}
54
+ disabled={disabled || loading}
55
+ onClick={onClick}
56
+ className={buttonClasses}
57
+ {...rest}
58
+ >
59
+ {loading ? (
60
+ <span className="flex items-center gap-2">
61
+ <span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
62
+ Loading...
63
+ </span>
64
+ ) : (
65
+ children
66
+ )}
67
+ </button>
68
+ );
79
69
  };
80
70
 
81
71
  Button.propTypes = {
82
- children: PropTypes.node,
83
- variant: PropTypes.oneOf(['primary', 'secondary', 'destructive', 'outline', 'ghost']),
84
- size: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
85
- disabled: PropTypes.bool,
86
- loading: PropTypes.bool,
87
- className: PropTypes.string,
88
- onClick: PropTypes.func,
89
- type: PropTypes.oneOf(['button', 'submit', 'reset']),
72
+ children: PropTypes.node,
73
+ size: PropTypes.oneOf(["sm", "md", "lg", "xl"]),
74
+ disabled: PropTypes.bool,
75
+ loading: PropTypes.bool,
76
+ className: PropTypes.string,
77
+ onClick: PropTypes.func,
78
+ type: PropTypes.oneOf(["button", "submit", "reset"]),
79
+ borderColor: PropTypes.oneOf(["black", "white"]),
80
+ borderWidth: PropTypes.number,
81
+ borderStyle: PropTypes.oneOf(["solid", "dashed", "dotted", "double"]),
82
+ borderRadius: PropTypes.oneOf(["sm", "md", "lg", "xl", "full"]),
90
83
  };
91
84
 
92
85
  export default Button;
@@ -1,2 +1,6 @@
1
- export { default } from './component';
2
- export { default as Button } from './component';
1
+ /**
2
+ * Button component barrel export
3
+ * This file allows importing the Button component cleanly
4
+ */
5
+ export { default } from "./component";
6
+ export { default as Button } from "./component";
@@ -1,28 +1,152 @@
1
1
  {
2
2
  "name": "Button",
3
- "description": "A customizable button component with multiple variants, sizes, and states.",
3
+ "description": "A customizable button component with size, border, radius, and click animation. Fully compatible with Tailwind CSS for background and text colors.",
4
4
  "category": "form",
5
- "tags": ["button", "interactive", "form", "cta"],
5
+ "tags": [
6
+ "button",
7
+ "interactive",
8
+ "form",
9
+ "cta",
10
+ "action",
11
+ "tailwind"
12
+ ],
6
13
  "version": "1.0.0",
14
+ "author": "@rajdeep",
15
+ "created": "2025-08-28",
7
16
  "dependencies": {
8
- "npm": [],
9
- "peer": ["react", "prop-types"]
17
+ "npm": [
18
+ "clsx"
19
+ ],
20
+ "peer": [
21
+ "react",
22
+ "prop-types"
23
+ ]
10
24
  },
11
25
  "props": [
12
- { "name": "children", "type": "React.ReactNode", "description": "Content inside the button" },
13
- { "name": "variant", "type": "string", "default": "primary", "options": ["primary","secondary","destructive","outline","ghost"] },
14
- { "name": "size", "type": "string", "default": "md", "options": ["sm","md","lg","xl"] },
15
- { "name": "disabled", "type": "boolean", "default": false, "description": "Disable button" },
16
- { "name": "loading", "type": "boolean", "default": false, "description": "Loading state" },
17
- { "name": "className", "type": "string", "description": "Extra CSS classes" },
18
- { "name": "onClick", "type": "function", "description": "Click handler" },
19
- { "name": "type", "type": "string", "default": "button", "options": ["button","submit","reset"] }
26
+ {
27
+ "name": "children",
28
+ "type": "React.ReactNode",
29
+ "required": false,
30
+ "default": "undefined",
31
+ "description": "The content to display inside the button"
32
+ },
33
+ {
34
+ "name": "size",
35
+ "type": "string",
36
+ "required": false,
37
+ "default": "sm",
38
+ "description": "The size of the button",
39
+ "options": [
40
+ "sm",
41
+ "md",
42
+ "lg",
43
+ "xl"
44
+ ]
45
+ },
46
+ {
47
+ "name": "disabled",
48
+ "type": "boolean",
49
+ "required": false,
50
+ "default": "false",
51
+ "description": "Whether the button is disabled and non-interactive"
52
+ },
53
+ {
54
+ "name": "loading",
55
+ "type": "boolean",
56
+ "required": false,
57
+ "default": "false",
58
+ "description": "Whether the button is in a loading state with spinner"
59
+ },
60
+ {
61
+ "name": "className",
62
+ "type": "string",
63
+ "required": false,
64
+ "default": "''",
65
+ "description": "Tailwind or custom classes to style background, text, hover, etc."
66
+ },
67
+ {
68
+ "name": "onClick",
69
+ "type": "function",
70
+ "required": false,
71
+ "default": "undefined",
72
+ "description": "Function to call when the button is clicked"
73
+ },
74
+ {
75
+ "name": "type",
76
+ "type": "string",
77
+ "required": false,
78
+ "default": "button",
79
+ "description": "The HTML button type attribute",
80
+ "options": [
81
+ "button",
82
+ "submit",
83
+ "reset"
84
+ ]
85
+ },
86
+ {
87
+ "name": "borderColor",
88
+ "type": "string",
89
+ "required": false,
90
+ "default": "white",
91
+ "description": "Border color of the button",
92
+ "options": [
93
+ "black",
94
+ "white"
95
+ ]
96
+ },
97
+ {
98
+ "name": "borderWidth",
99
+ "type": "number",
100
+ "required": false,
101
+ "default": "1",
102
+ "description": "Border thickness of the button"
103
+ },
104
+ {
105
+ "name": "borderStyle",
106
+ "type": "string",
107
+ "required": false,
108
+ "default": "solid",
109
+ "description": "Border style of the button",
110
+ "options": [
111
+ "solid",
112
+ "dashed",
113
+ "dotted",
114
+ "double"
115
+ ]
116
+ },
117
+ {
118
+ "name": "borderRadius",
119
+ "type": "string",
120
+ "required": false,
121
+ "default": "md",
122
+ "description": "Border radius for rounded corners",
123
+ "options": [
124
+ "sm",
125
+ "md",
126
+ "lg",
127
+ "xl",
128
+ "full"
129
+ ]
130
+ }
20
131
  ],
21
- "examples": [
22
- { "name": "Basic", "code": "<Button>Click Me</Button>" },
23
- { "name": "Variants", "code": "<><Button variant='primary'>Primary</Button><Button variant='secondary'>Secondary</Button></>" },
24
- { "name": "Sizes", "code": "<><Button size='sm'>Small</Button><Button size='lg'>Large</Button></>" },
25
- { "name": "Loading", "code": "<Button loading>Loading...</Button>" }
132
+ "files": [
133
+ "component.jsx",
134
+ "index.js",
135
+ "meta.json"
26
136
  ],
27
- "files": ["component.jsx", "index.js"]
137
+ "customization": {
138
+ "css_variables": [
139
+ "--button-border-radius",
140
+ "--button-transition"
141
+ ],
142
+ "styling_notes": "Background and text colors are meant to be customized using Tailwind classes via className. Borders and radius are controlled via props."
143
+ },
144
+ "accessibility": {
145
+ "features": [
146
+ "Keyboard navigation support",
147
+ "Screen reader friendly with aria-disabled and aria-busy",
148
+ "Focus visible outline",
149
+ "Semantic <button> element"
150
+ ]
151
+ }
28
152
  }