@elsapiens/cli 0.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/README.md +283 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +565 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/app/app.ejs +19 -0
- package/dist/templates/app/index-css.ejs +5 -0
- package/dist/templates/app/index-html.ejs +13 -0
- package/dist/templates/app/main.ejs +15 -0
- package/dist/templates/app/package.ejs +31 -0
- package/dist/templates/app/page-dashboard.ejs +108 -0
- package/dist/templates/app/page-settings.ejs +116 -0
- package/dist/templates/app/tsconfig.ejs +21 -0
- package/dist/templates/app/vite-config.ejs +9 -0
- package/dist/templates/components/simple.ejs +16 -0
- package/dist/templates/components/stateful.ejs +30 -0
- package/dist/templates/pages/dashboard.ejs +203 -0
- package/dist/templates/pages/list.ejs +191 -0
- package/dist/templates/pages/settings.ejs +163 -0
- package/package.json +62 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Input,
|
|
4
|
+
Select,
|
|
5
|
+
Card,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
CardContent,
|
|
9
|
+
Table,
|
|
10
|
+
Badge,
|
|
11
|
+
DonutChart,
|
|
12
|
+
} from '@elsapiens/ui';
|
|
13
|
+
import { Search, Filter, Plus, FileText, MoreVertical } from 'lucide-react';
|
|
14
|
+
|
|
15
|
+
// Sample data - replace with your data source
|
|
16
|
+
const items = [
|
|
17
|
+
{ id: '1', name: 'Item One', type: 'Type A', status: 'active', date: '2024-01-15' },
|
|
18
|
+
{ id: '2', name: 'Item Two', type: 'Type B', status: 'pending', date: '2024-01-14' },
|
|
19
|
+
{ id: '3', name: 'Item Three', type: 'Type A', status: 'active', date: '2024-01-13' },
|
|
20
|
+
{ id: '4', name: 'Item Four', type: 'Type C', status: 'inactive', date: '2024-01-12' },
|
|
21
|
+
{ id: '5', name: 'Item Five', type: 'Type B', status: 'active', date: '2024-01-11' },
|
|
22
|
+
{ id: '6', name: 'Item Six', type: 'Type A', status: 'pending', date: '2024-01-10' },
|
|
23
|
+
{ id: '7', name: 'Item Seven', type: 'Type C', status: 'active', date: '2024-01-09' },
|
|
24
|
+
{ id: '8', name: 'Item Eight', type: 'Type B', status: 'inactive', date: '2024-01-08' },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const itemStats = [
|
|
28
|
+
{ name: 'Type A', value: 3, color: 'primary' as const },
|
|
29
|
+
{ name: 'Type B', value: 3, color: 'success' as const },
|
|
30
|
+
{ name: 'Type C', value: 2, color: 'warning' as const },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const getStatusBadgeVariant = (status: string): 'default' | 'success' | 'warning' | 'info' => {
|
|
34
|
+
switch (status) {
|
|
35
|
+
case 'active':
|
|
36
|
+
return 'success';
|
|
37
|
+
case 'pending':
|
|
38
|
+
return 'warning';
|
|
39
|
+
case 'inactive':
|
|
40
|
+
return 'default';
|
|
41
|
+
default:
|
|
42
|
+
return 'default';
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default function <%= pascalName %>() {
|
|
47
|
+
return (
|
|
48
|
+
<div className="p-6">
|
|
49
|
+
{/* Page Header - pl-6 to align with table spacer */}
|
|
50
|
+
<div className="flex items-center justify-between mb-8 pl-6">
|
|
51
|
+
<div>
|
|
52
|
+
<h1 className="text-2xl font-bold text-foreground"><%= title %></h1>
|
|
53
|
+
<p className="text-muted-foreground"><%= description %></p>
|
|
54
|
+
</div>
|
|
55
|
+
<Button>
|
|
56
|
+
<Plus className="w-4 h-4 mr-2" />
|
|
57
|
+
Add New
|
|
58
|
+
</Button>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
{/* Stats Row */}
|
|
62
|
+
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6 mb-8">
|
|
63
|
+
{/* Quick Stats */}
|
|
64
|
+
<Card padding="none">
|
|
65
|
+
<CardContent className="p-6">
|
|
66
|
+
<div className="text-center">
|
|
67
|
+
<p className="text-3xl font-bold text-foreground">{items.length}</p>
|
|
68
|
+
<p className="text-sm text-muted-foreground">Total Items</p>
|
|
69
|
+
</div>
|
|
70
|
+
</CardContent>
|
|
71
|
+
</Card>
|
|
72
|
+
<Card padding="none">
|
|
73
|
+
<CardContent className="p-6">
|
|
74
|
+
<div className="text-center">
|
|
75
|
+
<p className="text-3xl font-bold text-foreground">
|
|
76
|
+
{items.filter(i => i.status === 'active').length}
|
|
77
|
+
</p>
|
|
78
|
+
<p className="text-sm text-muted-foreground">Active</p>
|
|
79
|
+
</div>
|
|
80
|
+
</CardContent>
|
|
81
|
+
</Card>
|
|
82
|
+
<Card padding="none">
|
|
83
|
+
<CardContent className="p-6">
|
|
84
|
+
<div className="text-center">
|
|
85
|
+
<p className="text-3xl font-bold text-foreground">
|
|
86
|
+
{items.filter(i => i.status === 'pending').length}
|
|
87
|
+
</p>
|
|
88
|
+
<p className="text-sm text-muted-foreground">Pending</p>
|
|
89
|
+
</div>
|
|
90
|
+
</CardContent>
|
|
91
|
+
</Card>
|
|
92
|
+
{/* Distribution Chart */}
|
|
93
|
+
<Card padding="none">
|
|
94
|
+
<CardContent className="p-6">
|
|
95
|
+
<DonutChart
|
|
96
|
+
data={itemStats}
|
|
97
|
+
height={100}
|
|
98
|
+
showLegend={false}
|
|
99
|
+
centerValue={String(items.length)}
|
|
100
|
+
centerSubtext="Items"
|
|
101
|
+
/>
|
|
102
|
+
</CardContent>
|
|
103
|
+
</Card>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
{/* Filters - pl-6 to align with table spacer */}
|
|
107
|
+
<div className="flex items-center gap-4 mb-6 pl-6">
|
|
108
|
+
<div className="flex-1 max-w-md">
|
|
109
|
+
<div className="relative">
|
|
110
|
+
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
|
111
|
+
<Input placeholder="Search..." className="pl-10" hideMessage />
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
<Select
|
|
115
|
+
options={[
|
|
116
|
+
{ value: 'all', label: 'All Types' },
|
|
117
|
+
{ value: 'type-a', label: 'Type A' },
|
|
118
|
+
{ value: 'type-b', label: 'Type B' },
|
|
119
|
+
{ value: 'type-c', label: 'Type C' },
|
|
120
|
+
]}
|
|
121
|
+
placeholder="Filter by type"
|
|
122
|
+
hideMessage
|
|
123
|
+
/>
|
|
124
|
+
<Button variant="outline">
|
|
125
|
+
<Filter className="w-4 h-4 mr-2" />
|
|
126
|
+
Filters
|
|
127
|
+
</Button>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{/* Table */}
|
|
131
|
+
<div>
|
|
132
|
+
<Card padding="none">
|
|
133
|
+
<CardHeader className="p-6">
|
|
134
|
+
<CardTitle>All Items</CardTitle>
|
|
135
|
+
</CardHeader>
|
|
136
|
+
<CardContent className="p-6">
|
|
137
|
+
<Table
|
|
138
|
+
data={items}
|
|
139
|
+
columns={[
|
|
140
|
+
{
|
|
141
|
+
key: 'name',
|
|
142
|
+
header: 'Name',
|
|
143
|
+
render: (item) => (
|
|
144
|
+
<div className="flex items-center gap-3">
|
|
145
|
+
<div className="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center">
|
|
146
|
+
<FileText className="w-5 h-5 text-primary" />
|
|
147
|
+
</div>
|
|
148
|
+
<span className="font-medium text-foreground">{item.name}</span>
|
|
149
|
+
</div>
|
|
150
|
+
),
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: 'type',
|
|
154
|
+
header: 'Type',
|
|
155
|
+
render: (item) => (
|
|
156
|
+
<Badge variant="info" size="sm">
|
|
157
|
+
{item.type}
|
|
158
|
+
</Badge>
|
|
159
|
+
),
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
key: 'status',
|
|
163
|
+
header: 'Status',
|
|
164
|
+
render: (item) => (
|
|
165
|
+
<Badge variant={getStatusBadgeVariant(item.status)} size="sm">
|
|
166
|
+
{item.status}
|
|
167
|
+
</Badge>
|
|
168
|
+
),
|
|
169
|
+
},
|
|
170
|
+
{ key: 'date', header: 'Date' },
|
|
171
|
+
{
|
|
172
|
+
key: 'actions',
|
|
173
|
+
header: 'Actions',
|
|
174
|
+
align: 'right',
|
|
175
|
+
render: () => (
|
|
176
|
+
<button className="p-2 rounded-md hover:bg-muted transition-colors">
|
|
177
|
+
<MoreVertical className="w-4 h-4 text-muted-foreground" />
|
|
178
|
+
</button>
|
|
179
|
+
),
|
|
180
|
+
},
|
|
181
|
+
]}
|
|
182
|
+
striped={false}
|
|
183
|
+
inCard="full"
|
|
184
|
+
cardPadding="lg"
|
|
185
|
+
/>
|
|
186
|
+
</CardContent>
|
|
187
|
+
</Card>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Input,
|
|
4
|
+
Toggle,
|
|
5
|
+
Select,
|
|
6
|
+
Card,
|
|
7
|
+
CardHeader,
|
|
8
|
+
CardTitle,
|
|
9
|
+
CardContent,
|
|
10
|
+
} from '@elsapiens/ui';
|
|
11
|
+
import { User, Bell, Shield, Palette } from 'lucide-react';
|
|
12
|
+
import { useState } from 'react';
|
|
13
|
+
|
|
14
|
+
export default function <%= pascalName %>() {
|
|
15
|
+
const [notifications, setNotifications] = useState(true);
|
|
16
|
+
const [emailUpdates, setEmailUpdates] = useState(false);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="p-6 max-w-4xl">
|
|
20
|
+
{/* Page Header - pl-6 to align with card content */}
|
|
21
|
+
<div className="mb-8 pl-6">
|
|
22
|
+
<h1 className="text-2xl font-bold text-foreground"><%= title %></h1>
|
|
23
|
+
<p className="text-muted-foreground"><%= description %></p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div className="space-y-6">
|
|
27
|
+
{/* Profile Section */}
|
|
28
|
+
<Card padding="none">
|
|
29
|
+
<CardHeader className="p-6">
|
|
30
|
+
<CardTitle className="flex items-center gap-3">
|
|
31
|
+
<User className="w-5 h-5 text-muted-foreground" />
|
|
32
|
+
Profile
|
|
33
|
+
</CardTitle>
|
|
34
|
+
</CardHeader>
|
|
35
|
+
<CardContent className="p-6 pt-0 space-y-4">
|
|
36
|
+
<div className="grid grid-cols-2 gap-4">
|
|
37
|
+
<div>
|
|
38
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
39
|
+
First Name
|
|
40
|
+
</label>
|
|
41
|
+
<Input defaultValue="John" hideMessage />
|
|
42
|
+
</div>
|
|
43
|
+
<div>
|
|
44
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
45
|
+
Last Name
|
|
46
|
+
</label>
|
|
47
|
+
<Input defaultValue="Doe" hideMessage />
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<div>
|
|
51
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
52
|
+
Email
|
|
53
|
+
</label>
|
|
54
|
+
<Input type="email" defaultValue="john.doe@example.com" hideMessage />
|
|
55
|
+
</div>
|
|
56
|
+
<div className="pt-2">
|
|
57
|
+
<Button>Save Changes</Button>
|
|
58
|
+
</div>
|
|
59
|
+
</CardContent>
|
|
60
|
+
</Card>
|
|
61
|
+
|
|
62
|
+
{/* Notifications Section */}
|
|
63
|
+
<Card padding="none">
|
|
64
|
+
<CardHeader className="p-6">
|
|
65
|
+
<CardTitle className="flex items-center gap-3">
|
|
66
|
+
<Bell className="w-5 h-5 text-muted-foreground" />
|
|
67
|
+
Notifications
|
|
68
|
+
</CardTitle>
|
|
69
|
+
</CardHeader>
|
|
70
|
+
<CardContent className="p-6 pt-0 space-y-4">
|
|
71
|
+
<div className="flex items-center justify-between">
|
|
72
|
+
<div>
|
|
73
|
+
<p className="font-medium text-foreground">Push Notifications</p>
|
|
74
|
+
<p className="text-sm text-muted-foreground">Receive push notifications for updates</p>
|
|
75
|
+
</div>
|
|
76
|
+
<Toggle checked={notifications} onChange={setNotifications} />
|
|
77
|
+
</div>
|
|
78
|
+
<div className="flex items-center justify-between">
|
|
79
|
+
<div>
|
|
80
|
+
<p className="font-medium text-foreground">Email Updates</p>
|
|
81
|
+
<p className="text-sm text-muted-foreground">Receive weekly email summaries</p>
|
|
82
|
+
</div>
|
|
83
|
+
<Toggle checked={emailUpdates} onChange={setEmailUpdates} />
|
|
84
|
+
</div>
|
|
85
|
+
</CardContent>
|
|
86
|
+
</Card>
|
|
87
|
+
|
|
88
|
+
{/* Appearance Section */}
|
|
89
|
+
<Card padding="none">
|
|
90
|
+
<CardHeader className="p-6">
|
|
91
|
+
<CardTitle className="flex items-center gap-3">
|
|
92
|
+
<Palette className="w-5 h-5 text-muted-foreground" />
|
|
93
|
+
Appearance
|
|
94
|
+
</CardTitle>
|
|
95
|
+
</CardHeader>
|
|
96
|
+
<CardContent className="p-6 pt-0 space-y-4">
|
|
97
|
+
<div>
|
|
98
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
99
|
+
Theme
|
|
100
|
+
</label>
|
|
101
|
+
<Select
|
|
102
|
+
options={[
|
|
103
|
+
{ value: 'light', label: 'Light' },
|
|
104
|
+
{ value: 'dark', label: 'Dark' },
|
|
105
|
+
{ value: 'system', label: 'System' },
|
|
106
|
+
]}
|
|
107
|
+
value="light"
|
|
108
|
+
hideMessage
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
<div>
|
|
112
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
113
|
+
Language
|
|
114
|
+
</label>
|
|
115
|
+
<Select
|
|
116
|
+
options={[
|
|
117
|
+
{ value: 'en', label: 'English' },
|
|
118
|
+
{ value: 'es', label: 'Spanish' },
|
|
119
|
+
{ value: 'fr', label: 'French' },
|
|
120
|
+
]}
|
|
121
|
+
value="en"
|
|
122
|
+
hideMessage
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
</CardContent>
|
|
126
|
+
</Card>
|
|
127
|
+
|
|
128
|
+
{/* Security Section */}
|
|
129
|
+
<Card padding="none">
|
|
130
|
+
<CardHeader className="p-6">
|
|
131
|
+
<CardTitle className="flex items-center gap-3">
|
|
132
|
+
<Shield className="w-5 h-5 text-muted-foreground" />
|
|
133
|
+
Security
|
|
134
|
+
</CardTitle>
|
|
135
|
+
</CardHeader>
|
|
136
|
+
<CardContent className="p-6 pt-0 space-y-4">
|
|
137
|
+
<div>
|
|
138
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
139
|
+
Current Password
|
|
140
|
+
</label>
|
|
141
|
+
<Input type="password" placeholder="Enter current password" hideMessage />
|
|
142
|
+
</div>
|
|
143
|
+
<div>
|
|
144
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
145
|
+
New Password
|
|
146
|
+
</label>
|
|
147
|
+
<Input type="password" placeholder="Enter new password" hideMessage />
|
|
148
|
+
</div>
|
|
149
|
+
<div>
|
|
150
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
151
|
+
Confirm New Password
|
|
152
|
+
</label>
|
|
153
|
+
<Input type="password" placeholder="Confirm new password" hideMessage />
|
|
154
|
+
</div>
|
|
155
|
+
<div className="pt-2">
|
|
156
|
+
<Button>Update Password</Button>
|
|
157
|
+
</div>
|
|
158
|
+
</CardContent>
|
|
159
|
+
</Card>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elsapiens/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI scaffolding tool for elSapiens SDK projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"elsapiens": "./dist/index.js",
|
|
8
|
+
"el": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"commander": "^12.0.0",
|
|
19
|
+
"@clack/prompts": "^0.7.0",
|
|
20
|
+
"ejs": "^3.1.9",
|
|
21
|
+
"fs-extra": "^11.2.0",
|
|
22
|
+
"picocolors": "^1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/ejs": "^3.1.5",
|
|
26
|
+
"@types/fs-extra": "^11.0.4",
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"tsup": "^8.0.1",
|
|
29
|
+
"typescript": "^5.3.3"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"elsapiens",
|
|
33
|
+
"cli",
|
|
34
|
+
"scaffolding",
|
|
35
|
+
"react",
|
|
36
|
+
"vite",
|
|
37
|
+
"typescript"
|
|
38
|
+
],
|
|
39
|
+
"author": "elSapiens",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/elsapiens/sdk.git",
|
|
44
|
+
"directory": "packages/cli"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/elsapiens/sdk#readme",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/elsapiens/sdk/issues"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18.0.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup",
|
|
58
|
+
"dev": "tsup --watch",
|
|
59
|
+
"clean": "rm -rf dist",
|
|
60
|
+
"typecheck": "tsc --noEmit"
|
|
61
|
+
}
|
|
62
|
+
}
|