@emberkit/cli 0.3.0 → 0.4.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/dist/commands/create.js +121 -411
- package/dist/utils/filesystem.js +19 -0
- package/package.json +1 -1
package/dist/commands/create.js
CHANGED
|
@@ -65,9 +65,7 @@ const starterFiles = {
|
|
|
65
65
|
"scripts": {
|
|
66
66
|
"dev": "emberkit dev",
|
|
67
67
|
"build": "emberkit build",
|
|
68
|
-
"preview": "emberkit preview"
|
|
69
|
-
"lint": "eslint src --ext .ts,.tsx",
|
|
70
|
-
"format": "prettier --write \\"src/**/*.{ts,tsx}\\""
|
|
68
|
+
"preview": "emberkit preview"
|
|
71
69
|
},
|
|
72
70
|
"dependencies": {
|
|
73
71
|
"@emberkit/core": "^0.2.4"
|
|
@@ -75,7 +73,9 @@ const starterFiles = {
|
|
|
75
73
|
"devDependencies": {
|
|
76
74
|
"@emberkit/cli": "^0.2.4",
|
|
77
75
|
"typescript": "^5.7.0",
|
|
78
|
-
"vite": "^6.0.0"
|
|
76
|
+
"vite": "^6.0.0",
|
|
77
|
+
"tailwindcss": "^4.0.0",
|
|
78
|
+
"@tailwindcss/vite": "^4.0.0"
|
|
79
79
|
}
|
|
80
80
|
}`,
|
|
81
81
|
"tsconfig.json": `{
|
|
@@ -100,27 +100,16 @@ const starterFiles = {
|
|
|
100
100
|
"include": ["src"],
|
|
101
101
|
"exclude": ["node_modules", "dist"]
|
|
102
102
|
}`,
|
|
103
|
-
"emberkit.config.ts": `import { defineConfig } from '@emberkit/core';
|
|
104
|
-
|
|
105
|
-
export default defineConfig({
|
|
106
|
-
mode: 'spa',
|
|
107
|
-
build: {
|
|
108
|
-
outDir: 'dist',
|
|
109
|
-
target: 'esnext',
|
|
110
|
-
},
|
|
111
|
-
});`,
|
|
112
103
|
"vite.config.ts": `import { defineConfig } from 'vite';
|
|
113
104
|
import { emberkitVitePlugin } from '@emberkit/core/vite-plugin';
|
|
105
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
114
106
|
|
|
115
107
|
export default defineConfig({
|
|
116
|
-
plugins: [emberkitVitePlugin()],
|
|
108
|
+
plugins: [emberkitVitePlugin(), tailwindcss()],
|
|
117
109
|
server: {
|
|
118
110
|
port: 3000,
|
|
119
111
|
host: 'localhost',
|
|
120
112
|
},
|
|
121
|
-
esbuild: {
|
|
122
|
-
jsxImportSource: '@emberkit/core',
|
|
123
|
-
},
|
|
124
113
|
});`,
|
|
125
114
|
"index.html": `<!DOCTYPE html>
|
|
126
115
|
<html lang="en">
|
|
@@ -131,11 +120,6 @@ export default defineConfig({
|
|
|
131
120
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
132
121
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
133
122
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
134
|
-
<style>
|
|
135
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
136
|
-
body { font-family: 'Inter', sans-serif; background: #0f172a; color: #e2e8f0; }
|
|
137
|
-
a { color: inherit; text-decoration: none; }
|
|
138
|
-
</style>
|
|
139
123
|
</head>
|
|
140
124
|
<body>
|
|
141
125
|
<div id="app"></div>
|
|
@@ -149,6 +133,29 @@ const root = document.getElementById('app');
|
|
|
149
133
|
|
|
150
134
|
if (root) {
|
|
151
135
|
render(App, root);
|
|
136
|
+
}`,
|
|
137
|
+
"src/styles.css": `@import "tailwindcss";
|
|
138
|
+
|
|
139
|
+
@theme {
|
|
140
|
+
--color-ember-50: #fff7ed;
|
|
141
|
+
--color-ember-100: #ffedd5;
|
|
142
|
+
--color-ember-200: #fed7aa;
|
|
143
|
+
--color-ember-300: #fdba74;
|
|
144
|
+
--color-ember-400: #fb923c;
|
|
145
|
+
--color-ember-500: #f97316;
|
|
146
|
+
--color-ember-600: #ea580c;
|
|
147
|
+
--color-ember-700: #c2410c;
|
|
148
|
+
--color-ember-800: #9a3412;
|
|
149
|
+
--color-ember-900: #7c2d12;
|
|
150
|
+
--font-sans: 'Inter', system-ui, sans-serif;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
body {
|
|
154
|
+
@apply bg-slate-900 text-slate-200 font-sans min-h-screen;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
a {
|
|
158
|
+
@apply text-inherit no-underline transition-colors;
|
|
152
159
|
}`,
|
|
153
160
|
"src/routes/_layout.tsx": `import type { RouteComponent } from '@emberkit/core';
|
|
154
161
|
import { Head } from '@emberkit/core';
|
|
@@ -160,21 +167,27 @@ const Layout: RouteComponent = ({ children }) => {
|
|
|
160
167
|
<title>{{name}}</title>
|
|
161
168
|
<meta name="description" content="Built with EmberKit" />
|
|
162
169
|
</Head>
|
|
163
|
-
<div className="
|
|
164
|
-
<header className="
|
|
165
|
-
<div className="
|
|
166
|
-
<
|
|
167
|
-
|
|
170
|
+
<div className="flex flex-col min-h-screen">
|
|
171
|
+
<header className="border-b border-slate-800 bg-slate-900/50 backdrop-blur sticky top-0 z-50">
|
|
172
|
+
<div className="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
173
|
+
<a href="/" className="flex items-center gap-2 group">
|
|
174
|
+
<span className="text-2xl">🔥</span>
|
|
175
|
+
<span className="text-xl font-bold bg-gradient-to-r from-ember-400 to-ember-500 bg-clip-text text-transparent">
|
|
176
|
+
{{name}}
|
|
177
|
+
</span>
|
|
178
|
+
</a>
|
|
179
|
+
<nav className="flex items-center gap-6">
|
|
180
|
+
<a href="/" className="text-slate-400 hover:text-ember-500 font-medium">Home</a>
|
|
181
|
+
<a href="/about" className="text-slate-400 hover:text-ember-500 font-medium">About</a>
|
|
182
|
+
<a href="https://emberkit.dev/docs" target="_blank" className="text-slate-400 hover:text-ember-500 font-medium">
|
|
183
|
+
Docs <span className="text-xs">↗</span>
|
|
184
|
+
</a>
|
|
185
|
+
</nav>
|
|
168
186
|
</div>
|
|
169
|
-
<nav className="nav">
|
|
170
|
-
<a href="/" className="nav-link">Home</a>
|
|
171
|
-
<a href="/about" className="nav-link">About</a>
|
|
172
|
-
<a href="https://emberkit.dev/docs" className="nav-link" target="_blank">Docs →</a>
|
|
173
|
-
</nav>
|
|
174
187
|
</header>
|
|
175
|
-
<main className="
|
|
176
|
-
<footer className="
|
|
177
|
-
<p>Built with <a href="https://emberkit.dev" className="
|
|
188
|
+
<main className="flex-1">{children}</main>
|
|
189
|
+
<footer className="border-t border-slate-800 py-8 text-center text-slate-500">
|
|
190
|
+
<p>Built with <a href="https://emberkit.dev" className="text-ember-500 hover:underline">EmberKit</a></p>
|
|
178
191
|
</footer>
|
|
179
192
|
</div>
|
|
180
193
|
</>
|
|
@@ -189,60 +202,68 @@ const HomePage: RouteComponent = () => {
|
|
|
189
202
|
const count = signal(0);
|
|
190
203
|
|
|
191
204
|
return (
|
|
192
|
-
<div className="
|
|
193
|
-
<section className="
|
|
194
|
-
<h1 className="
|
|
195
|
-
Welcome to <span className="gradient-text">{{name}}</span>
|
|
205
|
+
<div className="max-w-6xl mx-auto px-6 py-16 space-y-20">
|
|
206
|
+
<section className="text-center space-y-6">
|
|
207
|
+
<h1 className="text-5xl md:text-6xl font-extrabold tracking-tight">
|
|
208
|
+
Welcome to <span className="bg-gradient-to-r from-ember-400 via-ember-500 to-ember-600 bg-clip-text text-transparent">{{name}}</span>
|
|
196
209
|
</h1>
|
|
197
|
-
<p className="
|
|
210
|
+
<p className="text-xl text-slate-400 max-w-2xl mx-auto">
|
|
198
211
|
A minimalist TypeScript-first JSX framework built for speed and simplicity.
|
|
199
212
|
Get started in seconds with hot module replacement and zero-config routing.
|
|
200
213
|
</p>
|
|
201
|
-
<div className="
|
|
202
|
-
<a href="/about" className="
|
|
214
|
+
<div className="flex gap-4 justify-center pt-4">
|
|
215
|
+
<a href="/about" className="px-6 py-3 bg-ember-500 hover:bg-ember-600 text-white font-semibold rounded-lg transition-all hover:scale-105">
|
|
203
216
|
Learn More
|
|
204
217
|
</a>
|
|
205
|
-
<a href="https://emberkit.dev/docs" target="_blank" className="
|
|
218
|
+
<a href="https://emberkit.dev/docs" target="_blank" className="px-6 py-3 border border-slate-700 hover:border-ember-500 text-slate-300 hover:text-ember-500 font-semibold rounded-lg transition-all">
|
|
206
219
|
Read Docs →
|
|
207
220
|
</a>
|
|
208
221
|
</div>
|
|
209
222
|
</section>
|
|
210
223
|
|
|
211
|
-
<section className="
|
|
212
|
-
<div className="
|
|
213
|
-
<div className="
|
|
214
|
-
<h3>Lightning Fast</h3>
|
|
215
|
-
<p>Sub-10KB runtime with tree-shakeable architecture</p>
|
|
224
|
+
<section className="grid md:grid-cols-3 gap-6">
|
|
225
|
+
<div className="p-6 rounded-xl border border-slate-800 bg-slate-800/30 hover:border-ember-500/50 transition-colors group">
|
|
226
|
+
<div className="text-3xl mb-4">⚡</div>
|
|
227
|
+
<h3 className="text-lg font-semibold mb-2">Lightning Fast</h3>
|
|
228
|
+
<p className="text-slate-400">Sub-10KB runtime with tree-shakeable architecture</p>
|
|
216
229
|
</div>
|
|
217
|
-
<div className="
|
|
218
|
-
<div className="
|
|
219
|
-
<h3>TypeScript First</h3>
|
|
220
|
-
<p>Full type safety with intelligent autocomplete</p>
|
|
230
|
+
<div className="p-6 rounded-xl border border-slate-800 bg-slate-800/30 hover:border-ember-500/50 transition-colors group">
|
|
231
|
+
<div className="text-3xl mb-4">🔷</div>
|
|
232
|
+
<h3 className="text-lg font-semibold mb-2">TypeScript First</h3>
|
|
233
|
+
<p className="text-slate-400">Full type safety with intelligent autocomplete</p>
|
|
221
234
|
</div>
|
|
222
|
-
<div className="
|
|
223
|
-
<div className="
|
|
224
|
-
<h3>File-Based Routing</h3>
|
|
225
|
-
<p>Routes automatically created from your file structure</p>
|
|
235
|
+
<div className="p-6 rounded-xl border border-slate-800 bg-slate-800/30 hover:border-ember-500/50 transition-colors group">
|
|
236
|
+
<div className="text-3xl mb-4">🛤️</div>
|
|
237
|
+
<h3 className="text-lg font-semibold mb-2">File-Based Routing</h3>
|
|
238
|
+
<p className="text-slate-400">Routes automatically created from your file structure</p>
|
|
226
239
|
</div>
|
|
227
240
|
</section>
|
|
228
241
|
|
|
229
|
-
<section className="
|
|
230
|
-
<h2>
|
|
231
|
-
<div className="
|
|
242
|
+
<section className="p-8 rounded-2xl bg-gradient-to-br from-slate-800/50 to-slate-900/50 border border-slate-700 text-center">
|
|
243
|
+
<h2 className="text-2xl font-bold mb-6">Interactive Counter Demo</h2>
|
|
244
|
+
<div className="flex items-center justify-center gap-6">
|
|
232
245
|
<button
|
|
233
|
-
className="
|
|
246
|
+
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all"
|
|
234
247
|
onClick={() => count.value--}
|
|
235
248
|
>
|
|
236
249
|
−
|
|
237
250
|
</button>
|
|
238
|
-
<span className="
|
|
251
|
+
<span className="text-5xl font-bold tabular-nums min-w-[80px]">{count}</span>
|
|
239
252
|
<button
|
|
240
|
-
className="
|
|
253
|
+
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all"
|
|
241
254
|
onClick={() => count.value++}
|
|
242
255
|
>
|
|
243
256
|
+
|
|
244
257
|
</button>
|
|
245
258
|
</div>
|
|
259
|
+
<p className="text-slate-500 mt-4 text-sm">Try clicking the buttons!</p>
|
|
260
|
+
</section>
|
|
261
|
+
|
|
262
|
+
<section className="text-center py-8">
|
|
263
|
+
<div className="inline-flex items-center gap-3 px-4 py-2 rounded-full bg-ember-500/10 border border-ember-500/20 text-ember-400">
|
|
264
|
+
<span className="w-2 h-2 rounded-full bg-ember-500 animate-pulse"></span>
|
|
265
|
+
<span className="text-sm font-medium">Ready to build something amazing?</span>
|
|
266
|
+
</div>
|
|
246
267
|
</section>
|
|
247
268
|
</div>
|
|
248
269
|
);
|
|
@@ -254,303 +275,37 @@ import { Head } from '@emberkit/core';
|
|
|
254
275
|
|
|
255
276
|
const AboutPage: RouteComponent = () => {
|
|
256
277
|
return (
|
|
257
|
-
<div className="
|
|
278
|
+
<div className="max-w-3xl mx-auto px-6 py-16">
|
|
258
279
|
<Head>
|
|
259
280
|
<title>About - {{name}}</title>
|
|
260
281
|
</Head>
|
|
261
|
-
<
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
<div className="
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
<
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
<
|
|
277
|
-
|
|
278
|
-
<span>Hot module replacement</span>
|
|
279
|
-
</div>
|
|
282
|
+
<h1 className="text-4xl font-bold mb-6">About {{name}}</h1>
|
|
283
|
+
<p className="text-slate-400 text-lg leading-relaxed mb-8">
|
|
284
|
+
EmberKit is a minimalist TypeScript-first JSX framework built for speed and simplicity.
|
|
285
|
+
It combines the best of modern frontend development with a lightweight runtime.
|
|
286
|
+
</p>
|
|
287
|
+
<div className="grid sm:grid-cols-3 gap-4 mb-8">
|
|
288
|
+
<div className="p-4 rounded-lg bg-slate-800/50 border border-slate-700">
|
|
289
|
+
<span className="text-ember-500 text-sm font-semibold">SPA & SSR</span>
|
|
290
|
+
<p className="text-slate-500 text-sm mt-1">Works in both modes</p>
|
|
291
|
+
</div>
|
|
292
|
+
<div className="p-4 rounded-lg bg-slate-800/50 border border-slate-700">
|
|
293
|
+
<span className="text-ember-500 text-sm font-semibold">Zero Config</span>
|
|
294
|
+
<p className="text-slate-500 text-sm mt-1">Sensible defaults</p>
|
|
295
|
+
</div>
|
|
296
|
+
<div className="p-4 rounded-lg bg-slate-800/50 border border-slate-700">
|
|
297
|
+
<span className="text-ember-500 text-sm font-semibold">HMR</span>
|
|
298
|
+
<p className="text-slate-500 text-sm mt-1">Hot module replacement</p>
|
|
280
299
|
</div>
|
|
281
|
-
<a href="/" className="back-link">← Back to Home</a>
|
|
282
300
|
</div>
|
|
301
|
+
<a href="/" className="inline-flex items-center gap-2 text-ember-500 hover:text-ember-400 font-medium">
|
|
302
|
+
← Back to Home
|
|
303
|
+
</a>
|
|
283
304
|
</div>
|
|
284
305
|
);
|
|
285
306
|
};
|
|
286
307
|
|
|
287
308
|
export default AboutPage;`,
|
|
288
|
-
"src/styles.css": `.app {
|
|
289
|
-
min-height: 100vh;
|
|
290
|
-
display: flex;
|
|
291
|
-
flex-direction: column;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.header {
|
|
295
|
-
display: flex;
|
|
296
|
-
justify-content: space-between;
|
|
297
|
-
align-items: center;
|
|
298
|
-
padding: 1.5rem 2rem;
|
|
299
|
-
border-bottom: 1px solid #1e293b;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.logo {
|
|
303
|
-
display: flex;
|
|
304
|
-
align-items: center;
|
|
305
|
-
gap: 0.5rem;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
.logo-icon {
|
|
309
|
-
font-size: 1.5rem;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
.logo-text {
|
|
313
|
-
font-weight: 700;
|
|
314
|
-
font-size: 1.25rem;
|
|
315
|
-
background: linear-gradient(135deg, #f97316, #fb923c);
|
|
316
|
-
-webkit-background-clip: text;
|
|
317
|
-
-webkit-text-fill-color: transparent;
|
|
318
|
-
background-clip: text;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
.nav {
|
|
322
|
-
display: flex;
|
|
323
|
-
gap: 1.5rem;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.nav-link {
|
|
327
|
-
color: #94a3b8;
|
|
328
|
-
font-weight: 500;
|
|
329
|
-
transition: color 0.2s;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.nav-link:hover {
|
|
333
|
-
color: #f97316;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.main {
|
|
337
|
-
flex: 1;
|
|
338
|
-
max-width: 1200px;
|
|
339
|
-
width: 100%;
|
|
340
|
-
margin: 0 auto;
|
|
341
|
-
padding: 3rem 2rem;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.footer {
|
|
345
|
-
padding: 2rem;
|
|
346
|
-
text-align: center;
|
|
347
|
-
border-top: 1px solid #1e293b;
|
|
348
|
-
color: #64748b;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.footer-link {
|
|
352
|
-
color: #f97316;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
.home {
|
|
356
|
-
display: flex;
|
|
357
|
-
flex-direction: column;
|
|
358
|
-
gap: 4rem;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
.hero {
|
|
362
|
-
text-align: center;
|
|
363
|
-
padding: 2rem 0;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.hero-title {
|
|
367
|
-
font-size: 3rem;
|
|
368
|
-
font-weight: 800;
|
|
369
|
-
margin-bottom: 1.5rem;
|
|
370
|
-
line-height: 1.1;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.gradient-text {
|
|
374
|
-
background: linear-gradient(135deg, #f97316, #fb923c, #fdba74);
|
|
375
|
-
-webkit-background-clip: text;
|
|
376
|
-
-webkit-text-fill-color: transparent;
|
|
377
|
-
background-clip: text;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
.hero-desc {
|
|
381
|
-
font-size: 1.25rem;
|
|
382
|
-
color: #94a3b8;
|
|
383
|
-
max-width: 600px;
|
|
384
|
-
margin: 0 auto 2rem;
|
|
385
|
-
line-height: 1.6;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.hero-actions {
|
|
389
|
-
display: flex;
|
|
390
|
-
gap: 1rem;
|
|
391
|
-
justify-content: center;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
.btn {
|
|
395
|
-
display: inline-block;
|
|
396
|
-
padding: 0.875rem 1.75rem;
|
|
397
|
-
border-radius: 0.5rem;
|
|
398
|
-
font-weight: 600;
|
|
399
|
-
transition: all 0.2s;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
.btn-primary {
|
|
403
|
-
background: #f97316;
|
|
404
|
-
color: white;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
.btn-primary:hover {
|
|
408
|
-
background: #ea580c;
|
|
409
|
-
transform: translateY(-1px);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.btn-secondary {
|
|
413
|
-
background: #1e293b;
|
|
414
|
-
color: #e2e8f0;
|
|
415
|
-
border: 1px solid #334155;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.btn-secondary:hover {
|
|
419
|
-
background: #334155;
|
|
420
|
-
border-color: #475569;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
.features {
|
|
424
|
-
display: grid;
|
|
425
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
426
|
-
gap: 1.5rem;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
.feature-card {
|
|
430
|
-
background: #1e293b;
|
|
431
|
-
border: 1px solid #334155;
|
|
432
|
-
border-radius: 0.75rem;
|
|
433
|
-
padding: 1.5rem;
|
|
434
|
-
transition: all 0.2s;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.feature-card:hover {
|
|
438
|
-
border-color: #f97316;
|
|
439
|
-
transform: translateY(-2px);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.feature-icon {
|
|
443
|
-
font-size: 2rem;
|
|
444
|
-
margin-bottom: 1rem;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.feature-card h3 {
|
|
448
|
-
font-size: 1.125rem;
|
|
449
|
-
font-weight: 600;
|
|
450
|
-
margin-bottom: 0.5rem;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
.feature-card p {
|
|
454
|
-
color: #64748b;
|
|
455
|
-
font-size: 0.875rem;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
.counter {
|
|
459
|
-
text-align: center;
|
|
460
|
-
padding: 2rem;
|
|
461
|
-
background: #1e293b;
|
|
462
|
-
border-radius: 1rem;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.counter h2 {
|
|
466
|
-
margin-bottom: 1.5rem;
|
|
467
|
-
font-size: 1.5rem;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
.counter-display {
|
|
471
|
-
display: flex;
|
|
472
|
-
align-items: center;
|
|
473
|
-
justify-content: center;
|
|
474
|
-
gap: 1.5rem;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
.counter-btn {
|
|
478
|
-
width: 48px;
|
|
479
|
-
height: 48px;
|
|
480
|
-
border-radius: 0.5rem;
|
|
481
|
-
border: 1px solid #334155;
|
|
482
|
-
background: #0f172a;
|
|
483
|
-
color: #f97316;
|
|
484
|
-
font-size: 1.5rem;
|
|
485
|
-
cursor: pointer;
|
|
486
|
-
transition: all 0.2s;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.counter-btn:hover {
|
|
490
|
-
background: #f97316;
|
|
491
|
-
color: white;
|
|
492
|
-
border-color: #f97316;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
.counter-value {
|
|
496
|
-
font-size: 2.5rem;
|
|
497
|
-
font-weight: 700;
|
|
498
|
-
min-width: 60px;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
.about {
|
|
502
|
-
max-width: 700px;
|
|
503
|
-
margin: 0 auto;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
.about h1 {
|
|
507
|
-
font-size: 2rem;
|
|
508
|
-
font-weight: 700;
|
|
509
|
-
margin-bottom: 1.5rem;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
.about > div > p {
|
|
513
|
-
color: #94a3b8;
|
|
514
|
-
font-size: 1.125rem;
|
|
515
|
-
line-height: 1.7;
|
|
516
|
-
margin-bottom: 2rem;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
.about-features {
|
|
520
|
-
display: flex;
|
|
521
|
-
gap: 1rem;
|
|
522
|
-
flex-wrap: wrap;
|
|
523
|
-
margin-bottom: 2rem;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
.about-feature {
|
|
527
|
-
display: flex;
|
|
528
|
-
align-items: center;
|
|
529
|
-
gap: 0.5rem;
|
|
530
|
-
background: #1e293b;
|
|
531
|
-
padding: 0.75rem 1rem;
|
|
532
|
-
border-radius: 0.5rem;
|
|
533
|
-
font-size: 0.875rem;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
.feature-badge {
|
|
537
|
-
background: #f97316;
|
|
538
|
-
color: white;
|
|
539
|
-
padding: 0.125rem 0.5rem;
|
|
540
|
-
border-radius: 0.25rem;
|
|
541
|
-
font-size: 0.75rem;
|
|
542
|
-
font-weight: 600;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
.back-link {
|
|
546
|
-
display: inline-block;
|
|
547
|
-
color: #f97316;
|
|
548
|
-
font-weight: 500;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
.back-link:hover {
|
|
552
|
-
text-decoration: underline;
|
|
553
|
-
}`,
|
|
554
309
|
};
|
|
555
310
|
export async function create(options) {
|
|
556
311
|
printHeader();
|
|
@@ -624,8 +379,7 @@ const withUiTemplate = {
|
|
|
624
379
|
"build": "emberkit build",
|
|
625
380
|
"preview": "emberkit preview",
|
|
626
381
|
"lint": "eslint src --ext .ts,.tsx",
|
|
627
|
-
"format": "prettier --write \\"src/**/*.{ts,tsx}\\""
|
|
628
|
-
"build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css"
|
|
382
|
+
"format": "prettier --write \\"src/**/*.{ts,tsx}\\""
|
|
629
383
|
},
|
|
630
384
|
"dependencies": {
|
|
631
385
|
"@emberkit/core": "^0.2.4",
|
|
@@ -635,9 +389,8 @@ const withUiTemplate = {
|
|
|
635
389
|
"@emberkit/cli": "^0.2.4",
|
|
636
390
|
"typescript": "^5.7.0",
|
|
637
391
|
"vite": "^6.0.0",
|
|
638
|
-
"tailwindcss": "^
|
|
639
|
-
"
|
|
640
|
-
"autoprefixer": "^10.4.0"
|
|
392
|
+
"tailwindcss": "^4.0.0",
|
|
393
|
+
"@tailwindcss/vite": "^4.0.0"
|
|
641
394
|
}
|
|
642
395
|
}`,
|
|
643
396
|
"tsconfig.json": `{
|
|
@@ -662,47 +415,6 @@ const withUiTemplate = {
|
|
|
662
415
|
"include": ["src"],
|
|
663
416
|
"exclude": ["node_modules", "dist"]
|
|
664
417
|
}`,
|
|
665
|
-
"tailwind.config.js": `/** @type {import('tailwindcss').Config} */
|
|
666
|
-
export default {
|
|
667
|
-
content: ['./src/**/*.{js,ts,jsx,tsx}', './index.html'],
|
|
668
|
-
theme: {
|
|
669
|
-
extend: {
|
|
670
|
-
colors: {
|
|
671
|
-
ember: {
|
|
672
|
-
50: '#fff7ed',
|
|
673
|
-
100: '#ffedd5',
|
|
674
|
-
200: '#fed7aa',
|
|
675
|
-
300: '#fdba74',
|
|
676
|
-
400: '#fb923c',
|
|
677
|
-
500: '#f97316',
|
|
678
|
-
600: '#ea580c',
|
|
679
|
-
700: '#c2410c',
|
|
680
|
-
800: '#9a3412',
|
|
681
|
-
900: '#7c2d12',
|
|
682
|
-
},
|
|
683
|
-
},
|
|
684
|
-
fontFamily: {
|
|
685
|
-
sans: ['Inter', 'system-ui', 'sans-serif'],
|
|
686
|
-
},
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
plugins: [],
|
|
690
|
-
};`,
|
|
691
|
-
"postcss.config.js": `export default {
|
|
692
|
-
plugins: {
|
|
693
|
-
tailwindcss: {},
|
|
694
|
-
autoprefixer: {},
|
|
695
|
-
},
|
|
696
|
-
};`,
|
|
697
|
-
"emberkit.config.ts": `import { defineConfig } from '@emberkit/core';
|
|
698
|
-
|
|
699
|
-
export default defineConfig({
|
|
700
|
-
mode: 'spa',
|
|
701
|
-
build: {
|
|
702
|
-
outDir: 'dist',
|
|
703
|
-
target: 'esnext',
|
|
704
|
-
},
|
|
705
|
-
});`,
|
|
706
418
|
"vite.config.ts": `import { defineConfig } from 'vite';
|
|
707
419
|
import { emberkitVitePlugin } from '@emberkit/core/vite-plugin';
|
|
708
420
|
import tailwindcss from '@tailwindcss/vite';
|
|
@@ -713,9 +425,6 @@ export default defineConfig({
|
|
|
713
425
|
port: 3000,
|
|
714
426
|
host: 'localhost',
|
|
715
427
|
},
|
|
716
|
-
esbuild: {
|
|
717
|
-
jsxImportSource: '@emberkit/core',
|
|
718
|
-
},
|
|
719
428
|
});`,
|
|
720
429
|
"index.html": `<!DOCTYPE html>
|
|
721
430
|
<html lang="en">
|
|
@@ -743,25 +452,26 @@ if (root) {
|
|
|
743
452
|
}`,
|
|
744
453
|
"src/styles.css": `@import "tailwindcss";
|
|
745
454
|
|
|
746
|
-
|
|
747
|
-
--color-
|
|
748
|
-
--color-
|
|
749
|
-
--color-
|
|
750
|
-
--color-
|
|
751
|
-
--color-
|
|
752
|
-
--color-
|
|
753
|
-
--color-
|
|
455
|
+
@theme {
|
|
456
|
+
--color-ember-50: #fff7ed;
|
|
457
|
+
--color-ember-100: #ffedd5;
|
|
458
|
+
--color-ember-200: #fed7aa;
|
|
459
|
+
--color-ember-300: #fdba74;
|
|
460
|
+
--color-ember-400: #fb923c;
|
|
461
|
+
--color-ember-500: #f97316;
|
|
462
|
+
--color-ember-600: #ea580c;
|
|
463
|
+
--color-ember-700: #c2410c;
|
|
464
|
+
--color-ember-800: #9a3412;
|
|
465
|
+
--color-ember-900: #7c2d12;
|
|
466
|
+
--font-family-sans: 'Inter', system-ui, sans-serif;
|
|
754
467
|
}
|
|
755
468
|
|
|
756
469
|
body {
|
|
757
|
-
|
|
758
|
-
color: var(--color-text);
|
|
759
|
-
font-family: 'Inter', system-ui, sans-serif;
|
|
470
|
+
@apply bg-slate-900 text-slate-200 font-sans;
|
|
760
471
|
}
|
|
761
472
|
|
|
762
473
|
a {
|
|
763
|
-
|
|
764
|
-
text-decoration: none;
|
|
474
|
+
@apply text-inherit no-underline;
|
|
765
475
|
}`,
|
|
766
476
|
"src/routes/_layout.tsx": `import type { RouteComponent } from '@emberkit/core';
|
|
767
477
|
import { Head } from '@emberkit/core';
|
package/dist/utils/filesystem.js
CHANGED
|
@@ -28,6 +28,25 @@ export function getPackageManager() {
|
|
|
28
28
|
return "pnpm";
|
|
29
29
|
if (userAgent.startsWith("yarn"))
|
|
30
30
|
return "yarn";
|
|
31
|
+
if (userAgent.startsWith("npm"))
|
|
32
|
+
return "npm";
|
|
33
|
+
const { existsSync } = require("fs");
|
|
34
|
+
const { platform } = require("os");
|
|
35
|
+
try {
|
|
36
|
+
if (platform() === "win32") {
|
|
37
|
+
if (existsSync("C:\\Program Files\\pnpm\\pnpm.exe") || existsSync(process.env.LOCALAPPDATA + "\\pnpm\\pnpm.exe")) {
|
|
38
|
+
return "pnpm";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const { execSync } = require("child_process");
|
|
43
|
+
execSync("pnpm --version", { stdio: "ignore" });
|
|
44
|
+
return "pnpm";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return "npm";
|
|
49
|
+
}
|
|
31
50
|
return "npm";
|
|
32
51
|
}
|
|
33
52
|
export function getInstallCommand() {
|