create-ng-tailwind 3.1.0 → 4.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.

Potentially problematic release.


This version of create-ng-tailwind might be problematic. Click here for more details.

Files changed (48) hide show
  1. package/CHANGELOG.md +96 -341
  2. package/README.md +111 -157
  3. package/lib/cli/index.js +74 -3
  4. package/lib/cli/interactive.js +26 -1
  5. package/lib/managers/ProjectManager.js +2 -5
  6. package/lib/templates/base/components.js +243 -0
  7. package/lib/templates/base/index.js +207 -0
  8. package/lib/templates/base/infrastructure.js +314 -0
  9. package/lib/templates/base/linting.js +359 -0
  10. package/lib/templates/base/pwa.js +103 -0
  11. package/lib/templates/base/services.js +362 -0
  12. package/lib/templates/blog/app.js +250 -0
  13. package/lib/templates/blog/components.js +360 -0
  14. package/lib/templates/blog/i18n.js +77 -0
  15. package/lib/templates/blog/index.js +126 -0
  16. package/lib/templates/blog/pages.js +554 -0
  17. package/lib/templates/blog/services.js +390 -0
  18. package/lib/templates/dashboard/app.js +320 -0
  19. package/lib/templates/dashboard/charts.js +305 -0
  20. package/lib/templates/dashboard/components.js +410 -0
  21. package/lib/templates/dashboard/i18n.js +340 -0
  22. package/lib/templates/dashboard/index.js +141 -0
  23. package/lib/templates/dashboard/layout.js +310 -0
  24. package/lib/templates/dashboard/pages.js +681 -0
  25. package/lib/templates/ecommerce/app.js +315 -0
  26. package/lib/templates/ecommerce/components.js +496 -0
  27. package/lib/templates/ecommerce/i18n.js +389 -0
  28. package/lib/templates/ecommerce/index.js +152 -0
  29. package/lib/templates/ecommerce/layout.js +270 -0
  30. package/lib/templates/ecommerce/pages.js +969 -0
  31. package/lib/templates/ecommerce/services.js +300 -0
  32. package/lib/templates/index.js +12 -0
  33. package/lib/templates/landing/index.js +1117 -0
  34. package/lib/templates/portfolio/index.js +1160 -0
  35. package/lib/templates/saas/index.js +1371 -0
  36. package/lib/templates/starter/app.js +364 -0
  37. package/lib/templates/starter/i18n.js +856 -0
  38. package/lib/templates/starter/index.js +52 -4060
  39. package/lib/templates/starter/layout.js +852 -0
  40. package/lib/templates/starter/pages.js +1241 -0
  41. package/lib/utils/nodeCompat.js +85 -0
  42. package/package.json +1 -1
  43. package/lib/templates/starter/features.js +0 -867
  44. package/lib/utils/ai-config.js +0 -641
  45. /package/lib/templates/{starter → base}/advanced-features.js +0 -0
  46. /package/lib/templates/{starter → base}/seo-assets.js +0 -0
  47. /package/lib/templates/{starter → base}/seo-features.js +0 -0
  48. /package/lib/templates/{starter → base}/ui-features.js +0 -0
@@ -0,0 +1,315 @@
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
+
4
+ /**
5
+ * Ecommerce App Configuration
6
+ * - Routes
7
+ * - App Config (with i18n)
8
+ * - App Component
9
+ * - Styles (Tailwind v4 with theme)
10
+ */
11
+
12
+ async function createRouting(config) {
13
+ const routesFile = `import { Routes } from '@angular/router';
14
+
15
+ export const routes: Routes = [
16
+ {
17
+ path: '',
18
+ loadComponent: () => import('./features/home/home.component').then(m => m.HomeComponent),
19
+ },
20
+ {
21
+ path: 'products',
22
+ loadComponent: () => import('./features/products/products.component').then(m => m.ProductsComponent),
23
+ },
24
+ {
25
+ path: 'products/:id',
26
+ loadComponent: () => import('./features/product-detail/product-detail.component').then(m => m.ProductDetailComponent),
27
+ },
28
+ {
29
+ path: 'cart',
30
+ loadComponent: () => import('./features/cart/cart.component').then(m => m.CartComponent),
31
+ },
32
+ {
33
+ path: 'checkout',
34
+ loadComponent: () => import('./features/checkout/checkout.component').then(m => m.CheckoutComponent),
35
+ },
36
+ {
37
+ path: 'wishlist',
38
+ loadComponent: () => import('./features/wishlist/wishlist.component').then(m => m.WishlistComponent),
39
+ },
40
+ {
41
+ path: '**',
42
+ redirectTo: '',
43
+ },
44
+ ];`;
45
+
46
+ await fs.writeFile(
47
+ path.join(config.fullPath, "src/app/app.routes.ts"),
48
+ routesFile
49
+ );
50
+ }
51
+
52
+ async function createAppConfig(config) {
53
+ const appConfigFile = `import { ApplicationConfig, provideZoneChangeDetection, importProvidersFrom } from '@angular/core';
54
+ import { provideRouter } from '@angular/router';
55
+ import { provideHttpClient, withInterceptors, HttpClient } from '@angular/common/http';
56
+ import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
57
+ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
58
+
59
+ import { routes } from './app.routes';
60
+ import { authInterceptor } from '@core/interceptors/auth.interceptor';
61
+ import { errorInterceptor } from '@core/interceptors/error.interceptor';
62
+ import { loadingInterceptor } from '@core/interceptors/loading.interceptor';
63
+ import { cachingInterceptor } from '@core/interceptors/caching.interceptor';
64
+
65
+ export function HttpLoaderFactory(http: HttpClient) {
66
+ return new TranslateHttpLoader(http, './assets/i18n/', '.json');
67
+ }
68
+
69
+ export const appConfig: ApplicationConfig = {
70
+ providers: [
71
+ provideZoneChangeDetection({ eventCoalescing: true }),
72
+ provideRouter(routes),
73
+ provideHttpClient(
74
+ withInterceptors([
75
+ authInterceptor,
76
+ cachingInterceptor,
77
+ loadingInterceptor,
78
+ errorInterceptor,
79
+ ])
80
+ ),
81
+ importProvidersFrom(
82
+ TranslateModule.forRoot({
83
+ loader: {
84
+ provide: TranslateLoader,
85
+ useFactory: HttpLoaderFactory,
86
+ deps: [HttpClient]
87
+ }
88
+ })
89
+ ),
90
+ ],
91
+ };`;
92
+
93
+ await fs.writeFile(
94
+ path.join(config.fullPath, "src/app/app.config.ts"),
95
+ appConfigFile
96
+ );
97
+ }
98
+
99
+ async function createAppComponent(config) {
100
+ const appTs = `import { Component, inject } from '@angular/core';
101
+ import { RouterOutlet } from '@angular/router';
102
+ import { HeaderComponent } from './layout/header/header.component';
103
+ import { FooterComponent } from './layout/footer/footer.component';
104
+ import { ToastComponent } from '@shared/components/toast/toast.component';
105
+ import { ModalComponent } from '@shared/components/modal/modal.component';
106
+ import { TranslationService } from '@core/i18n/translation.service';
107
+
108
+ @Component({
109
+ selector: 'app-root',
110
+ imports: [RouterOutlet, HeaderComponent, FooterComponent, ToastComponent, ModalComponent],
111
+ template: \`
112
+ <div class="flex min-h-screen flex-col">
113
+ <app-header />
114
+ <main class="flex-1">
115
+ <router-outlet />
116
+ </main>
117
+ <app-footer />
118
+ </div>
119
+ <app-toast />
120
+ <app-modal />
121
+ \`,
122
+ })
123
+ export class App {
124
+ private translationService = inject(TranslationService);
125
+ title = '${config.projectName}';
126
+ }`;
127
+
128
+ const appHtml = `<!-- Template defined inline in app.ts -->`;
129
+
130
+ await fs.writeFile(path.join(config.fullPath, "src/app/app.ts"), appTs);
131
+ await fs.writeFile(path.join(config.fullPath, "src/app/app.html"), appHtml);
132
+ }
133
+
134
+ async function createStyles(config) {
135
+ const stylesFile = `@import "tailwindcss";
136
+
137
+ @theme {
138
+ --color-primary-50: #eff6ff;
139
+ --color-primary-100: #dbeafe;
140
+ --color-primary-200: #bfdbfe;
141
+ --color-primary-300: #93c5fd;
142
+ --color-primary-400: #60a5fa;
143
+ --color-primary-500: #3b82f6;
144
+ --color-primary-600: #2563eb;
145
+ --color-primary-700: #1d4ed8;
146
+ --color-primary-800: #1e40af;
147
+ --color-primary-900: #1e3a8a;
148
+ --color-primary-950: #172554;
149
+
150
+ --color-secondary-50: #f8fafc;
151
+ --color-secondary-100: #f1f5f9;
152
+ --color-secondary-200: #e2e8f0;
153
+ --color-secondary-300: #cbd5e1;
154
+ --color-secondary-400: #94a3b8;
155
+ --color-secondary-500: #64748b;
156
+ --color-secondary-600: #475569;
157
+ --color-secondary-700: #334155;
158
+ --color-secondary-800: #1e293b;
159
+ --color-secondary-900: #0f172a;
160
+ --color-secondary-950: #020617;
161
+
162
+ --color-accent-50: #fdf4ff;
163
+ --color-accent-100: #fae8ff;
164
+ --color-accent-200: #f5d0fe;
165
+ --color-accent-300: #f0abfc;
166
+ --color-accent-400: #e879f9;
167
+ --color-accent-500: #d946ef;
168
+ --color-accent-600: #c026d3;
169
+ --color-accent-700: #a21caf;
170
+ --color-accent-800: #86198f;
171
+ --color-accent-900: #701a75;
172
+ --color-accent-950: #4a044e;
173
+
174
+ --color-success-50: #f0fdf4;
175
+ --color-success-100: #dcfce7;
176
+ --color-success-200: #bbf7d0;
177
+ --color-success-300: #86efac;
178
+ --color-success-400: #4ade80;
179
+ --color-success-500: #22c55e;
180
+ --color-success-600: #16a34a;
181
+ --color-success-700: #15803d;
182
+ --color-success-800: #166534;
183
+ --color-success-900: #14532d;
184
+ --color-success-950: #052e16;
185
+
186
+ --color-warning-50: #fffbeb;
187
+ --color-warning-100: #fef3c7;
188
+ --color-warning-200: #fde68a;
189
+ --color-warning-300: #fcd34d;
190
+ --color-warning-400: #fbbf24;
191
+ --color-warning-500: #f59e0b;
192
+ --color-warning-600: #d97706;
193
+ --color-warning-700: #b45309;
194
+ --color-warning-800: #92400e;
195
+ --color-warning-900: #78350f;
196
+ --color-warning-950: #451a03;
197
+
198
+ --color-danger-50: #fef2f2;
199
+ --color-danger-100: #fee2e2;
200
+ --color-danger-200: #fecaca;
201
+ --color-danger-300: #fca5a5;
202
+ --color-danger-400: #f87171;
203
+ --color-danger-500: #ef4444;
204
+ --color-danger-600: #dc2626;
205
+ --color-danger-700: #b91c1c;
206
+ --color-danger-800: #991b1b;
207
+ --color-danger-900: #7f1d1d;
208
+ --color-danger-950: #450a0a;
209
+ }
210
+
211
+ /* RTL Support */
212
+ html[dir="rtl"] {
213
+ direction: rtl;
214
+ }
215
+
216
+ html[dir="ltr"] {
217
+ direction: ltr;
218
+ }
219
+
220
+ /* RTL-aware spacing utilities */
221
+ html[dir="rtl"] .space-x-2 > * + * {
222
+ margin-right: 0.5rem;
223
+ margin-left: 0;
224
+ }
225
+
226
+ html[dir="rtl"] .space-x-3 > * + * {
227
+ margin-right: 0.75rem;
228
+ margin-left: 0;
229
+ }
230
+
231
+ html[dir="rtl"] .space-x-4 > * + * {
232
+ margin-right: 1rem;
233
+ margin-left: 0;
234
+ }
235
+
236
+ /* RTL-aware text alignment */
237
+ html[dir="rtl"] .text-left {
238
+ text-align: right;
239
+ }
240
+
241
+ html[dir="rtl"] .text-right {
242
+ text-align: left;
243
+ }
244
+
245
+ /* Smooth scrolling */
246
+ html {
247
+ scroll-behavior: smooth;
248
+ }
249
+
250
+ /* Custom scrollbar */
251
+ ::-webkit-scrollbar {
252
+ width: 8px;
253
+ height: 8px;
254
+ }
255
+
256
+ ::-webkit-scrollbar-track {
257
+ background: #f1f5f9;
258
+ }
259
+
260
+ ::-webkit-scrollbar-thumb {
261
+ background: #cbd5e1;
262
+ border-radius: 4px;
263
+ }
264
+
265
+ ::-webkit-scrollbar-thumb:hover {
266
+ background: #94a3b8;
267
+ }
268
+
269
+ /* Line clamp utility */
270
+ .line-clamp-1 {
271
+ display: -webkit-box;
272
+ -webkit-line-clamp: 1;
273
+ -webkit-box-orient: vertical;
274
+ overflow: hidden;
275
+ }
276
+
277
+ .line-clamp-2 {
278
+ display: -webkit-box;
279
+ -webkit-line-clamp: 2;
280
+ -webkit-box-orient: vertical;
281
+ overflow: hidden;
282
+ }`;
283
+
284
+ await fs.writeFile(path.join(config.fullPath, "src/styles.css"), stylesFile);
285
+ }
286
+
287
+ async function installI18nPackages(config) {
288
+ if (!config.skipInstall) {
289
+ const execa = require("execa");
290
+ await execa.command(
291
+ "npm install @ngx-translate/core@^15.0.0 @ngx-translate/http-loader@^8.0.0 --force",
292
+ {
293
+ cwd: config.fullPath,
294
+ stdio: "pipe",
295
+ }
296
+ );
297
+ } else {
298
+ const packageJsonPath = path.join(config.fullPath, "package.json");
299
+ const packageJson = await fs.readJson(packageJsonPath);
300
+ if (!packageJson.dependencies) {
301
+ packageJson.dependencies = {};
302
+ }
303
+ packageJson.dependencies["@ngx-translate/core"] = "^15.0.0";
304
+ packageJson.dependencies["@ngx-translate/http-loader"] = "^8.0.0";
305
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
306
+ }
307
+ }
308
+
309
+ module.exports = {
310
+ createRouting,
311
+ createAppConfig,
312
+ createAppComponent,
313
+ createStyles,
314
+ installI18nPackages,
315
+ };