create-rue 0.0.11 → 0.0.14
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/bundle.js +2 -2
- package/package.json +2 -2
- package/template/base/app/pages/Home.tsx +14 -7
- package/template/base/app/pages/Report.tsx +10 -6
- package/template/base/app/pages/TodoApp.tsx +37 -23
- package/template/base/app/pages/components/Layout.tsx +7 -5
- package/template/base/package.json +8 -8
- package/template/base/style.css +10 -2
- package/template/base/tsconfig.json +1 -1
package/bundle.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! create-rue v0.0.
|
|
2
|
+
/*! create-rue v0.0.14 | MIT */
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import "node:fs";
|
|
@@ -2052,7 +2052,7 @@ function inferPackageManager() {
|
|
|
2052
2052
|
//#endregion
|
|
2053
2053
|
//#region package.json
|
|
2054
2054
|
var name = "create-rue";
|
|
2055
|
-
var version = "0.0.
|
|
2055
|
+
var version = "0.0.14";
|
|
2056
2056
|
//#endregion
|
|
2057
2057
|
//#region index.ts
|
|
2058
2058
|
const language = await getLanguage(fileURLToPath(new URL("./locales", import.meta.url)));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-rue",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "🛠️ The recommended way to start a Vite-powered Rue project",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/hunzhiwange/create-rue#readme",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"zx": "^8.8.5"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
|
-
"node": "
|
|
43
|
+
"node": ">=22.12.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"format": "vp fmt",
|
|
@@ -35,9 +35,12 @@ const Home: FC = () => (
|
|
|
35
35
|
<div className="hero-content flex-col items-start gap-8 px-6 py-8 lg:flex-row lg:items-end lg:justify-between">
|
|
36
36
|
<div className="max-w-3xl space-y-4">
|
|
37
37
|
<div className="badge badge-primary badge-outline">Rue.js</div>
|
|
38
|
-
<h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">
|
|
38
|
+
<h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">
|
|
39
|
+
The Wasm Framework For Vapor Native DOM
|
|
40
|
+
</h1>
|
|
39
41
|
<p className="max-w-2xl text-base leading-7 text-base-content/70">
|
|
40
|
-
Rue.js 采用原生 JSX / TSX 开发方式,结合细粒度响应式与面向原生 DOM
|
|
42
|
+
Rue.js 采用原生 JSX / TSX 开发方式,结合细粒度响应式与面向原生 DOM
|
|
43
|
+
的渲染模型,适合构建轻量、直接且可维护的前端应用。
|
|
41
44
|
</p>
|
|
42
45
|
<div className="flex flex-wrap gap-3">
|
|
43
46
|
<RouterLink to="/report" className="btn btn-primary">
|
|
@@ -63,7 +66,7 @@ const Home: FC = () => (
|
|
|
63
66
|
</section>
|
|
64
67
|
|
|
65
68
|
<section className="grid gap-4 md:grid-cols-3">
|
|
66
|
-
{highlights.map(item => (
|
|
69
|
+
{highlights.map((item) => (
|
|
67
70
|
<article key={item.title} className="card border border-base-300 bg-base-100 shadow-sm">
|
|
68
71
|
<div className="card-body gap-3">
|
|
69
72
|
<h2 className="text-2xl font-semibold">{item.title}</h2>
|
|
@@ -82,7 +85,7 @@ const Home: FC = () => (
|
|
|
82
85
|
</div>
|
|
83
86
|
|
|
84
87
|
<div className="mockup-code text-sm">
|
|
85
|
-
{quickStartCommands.map(command => (
|
|
88
|
+
{quickStartCommands.map((command) => (
|
|
86
89
|
<pre key={command} data-prefix="$">
|
|
87
90
|
<code>{command}</code>
|
|
88
91
|
</pre>
|
|
@@ -99,7 +102,8 @@ const Home: FC = () => (
|
|
|
99
102
|
</div>
|
|
100
103
|
|
|
101
104
|
<div className="rounded-2xl bg-base-200 p-4 text-sm leading-7 text-base-content/70">
|
|
102
|
-
生成的项目基于 Vite,默认支持 JSX / TSX 组件开发;生产构建使用 npm run build,产物输出到
|
|
105
|
+
生成的项目基于 Vite,默认支持 JSX / TSX 组件开发;生产构建使用 npm run build,产物输出到
|
|
106
|
+
dist 目录。
|
|
103
107
|
</div>
|
|
104
108
|
</div>
|
|
105
109
|
</article>
|
|
@@ -112,8 +116,11 @@ const Home: FC = () => (
|
|
|
112
116
|
</div>
|
|
113
117
|
|
|
114
118
|
<div className="space-y-3">
|
|
115
|
-
{nextSteps.map(step => (
|
|
116
|
-
<div
|
|
119
|
+
{nextSteps.map((step) => (
|
|
120
|
+
<div
|
|
121
|
+
key={step}
|
|
122
|
+
className="rounded-2xl bg-base-200 p-4 text-sm leading-7 text-base-content/75"
|
|
123
|
+
>
|
|
117
124
|
{step}
|
|
118
125
|
</div>
|
|
119
126
|
))}
|
|
@@ -30,7 +30,7 @@ const totalRevenue = rows.reduce((sum, row) => sum + row.revenue, 0)
|
|
|
30
30
|
const totalOrders = rows.reduce((sum, row) => sum + row.orders, 0)
|
|
31
31
|
const avgConversion = rows.reduce((sum, row) => sum + row.conversion, 0) / rows.length
|
|
32
32
|
const peakRow = rows.reduce((max, row) => (row.revenue > max.revenue ? row : max), rows[0])
|
|
33
|
-
const maxRevenue = Math.max(...rows.map(row => row.revenue))
|
|
33
|
+
const maxRevenue = Math.max(...rows.map((row) => row.revenue))
|
|
34
34
|
|
|
35
35
|
const summaryCards = [
|
|
36
36
|
{
|
|
@@ -89,7 +89,7 @@ const Report: FC = () => (
|
|
|
89
89
|
</section>
|
|
90
90
|
|
|
91
91
|
<section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
92
|
-
{summaryCards.map(card => (
|
|
92
|
+
{summaryCards.map((card) => (
|
|
93
93
|
<article key={card.label} className={`card shadow-lg ${card.tone}`}>
|
|
94
94
|
<div className="card-body gap-2">
|
|
95
95
|
<p className="text-sm opacity-80">{card.label}</p>
|
|
@@ -115,13 +115,17 @@ const Report: FC = () => (
|
|
|
115
115
|
</div>
|
|
116
116
|
|
|
117
117
|
<div className="space-y-4">
|
|
118
|
-
{rows.map(row => (
|
|
118
|
+
{rows.map((row) => (
|
|
119
119
|
<div key={row.day} className="grid gap-2">
|
|
120
120
|
<div className="flex items-center justify-between gap-4 text-sm">
|
|
121
121
|
<div className="font-medium">{row.day}</div>
|
|
122
122
|
<div className="text-base-content/60">{moneyFormatter.format(row.revenue)}</div>
|
|
123
123
|
</div>
|
|
124
|
-
<progress
|
|
124
|
+
<progress
|
|
125
|
+
className="progress progress-primary w-full"
|
|
126
|
+
value={row.revenue}
|
|
127
|
+
max={maxRevenue}
|
|
128
|
+
></progress>
|
|
125
129
|
<div className="flex items-center justify-between gap-4 text-xs text-base-content/60">
|
|
126
130
|
<span>{row.orders} 单</span>
|
|
127
131
|
<span>转化率 {row.conversion}%</span>
|
|
@@ -173,7 +177,7 @@ const Report: FC = () => (
|
|
|
173
177
|
</tr>
|
|
174
178
|
</thead>
|
|
175
179
|
<tbody>
|
|
176
|
-
{rows.map(row => (
|
|
180
|
+
{rows.map((row) => (
|
|
177
181
|
<tr key={row.day}>
|
|
178
182
|
<td className="font-medium">{row.day}</td>
|
|
179
183
|
<td>{row.orders}</td>
|
|
@@ -189,4 +193,4 @@ const Report: FC = () => (
|
|
|
189
193
|
</div>
|
|
190
194
|
)
|
|
191
195
|
|
|
192
|
-
export default Report
|
|
196
|
+
export default Report
|
|
@@ -72,7 +72,7 @@ const getStoredTodos = (): TodoItem[] => {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return parsed.filter(
|
|
75
|
-
item =>
|
|
75
|
+
(item) =>
|
|
76
76
|
item &&
|
|
77
77
|
typeof item.id === 'number' &&
|
|
78
78
|
typeof item.title === 'string' &&
|
|
@@ -121,7 +121,7 @@ const EditingTitleInput: FC<{
|
|
|
121
121
|
initialTitle: string
|
|
122
122
|
onSave: (title: string) => void
|
|
123
123
|
onCancel: () => void
|
|
124
|
-
}> = props => {
|
|
124
|
+
}> = (props) => {
|
|
125
125
|
const [title, setTitle] = useState(props.initialTitle)
|
|
126
126
|
|
|
127
127
|
return (
|
|
@@ -170,17 +170,17 @@ const TodoApp: FC = () => {
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
const counts = computed(() => ({
|
|
173
|
-
total: todos.value.filter(item => !item.archived).length,
|
|
174
|
-
todo: todos.value.filter(item => !item.archived && item.status === 'todo').length,
|
|
175
|
-
doing: todos.value.filter(item => !item.archived && item.status === 'doing').length,
|
|
176
|
-
done: todos.value.filter(item => !item.archived && item.status === 'done').length,
|
|
177
|
-
archived: todos.value.filter(item => item.archived).length,
|
|
173
|
+
total: todos.value.filter((item) => !item.archived).length,
|
|
174
|
+
todo: todos.value.filter((item) => !item.archived && item.status === 'todo').length,
|
|
175
|
+
doing: todos.value.filter((item) => !item.archived && item.status === 'doing').length,
|
|
176
|
+
done: todos.value.filter((item) => !item.archived && item.status === 'done').length,
|
|
177
|
+
archived: todos.value.filter((item) => item.archived).length,
|
|
178
178
|
}))
|
|
179
179
|
|
|
180
180
|
const visibleTodos = computed(() => {
|
|
181
181
|
const keyword = search.value.trim().toLowerCase()
|
|
182
182
|
|
|
183
|
-
return todos.value.filter(item => {
|
|
183
|
+
return todos.value.filter((item) => {
|
|
184
184
|
const matchesKeyword = !keyword || item.title.toLowerCase().includes(keyword)
|
|
185
185
|
if (!matchesKeyword) {
|
|
186
186
|
return false
|
|
@@ -222,20 +222,20 @@ const TodoApp: FC = () => {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
const removeTodo = (id: number) => {
|
|
225
|
-
todos.value = todos.value.filter(item => item.id !== id)
|
|
225
|
+
todos.value = todos.value.filter((item) => item.id !== id)
|
|
226
226
|
if (editingId.value === id) {
|
|
227
227
|
editingId.value = null
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
const updateStatus = (id: number, status: TodoStatus) => {
|
|
232
|
-
todos.value = todos.value.map(item =>
|
|
232
|
+
todos.value = todos.value.map((item) =>
|
|
233
233
|
item.id === id ? { ...item, status, archived: false } : item,
|
|
234
234
|
)
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
const toggleArchived = (id: number) => {
|
|
238
|
-
todos.value = todos.value.map(item =>
|
|
238
|
+
todos.value = todos.value.map((item) =>
|
|
239
239
|
item.id === id ? { ...item, archived: !item.archived } : item,
|
|
240
240
|
)
|
|
241
241
|
}
|
|
@@ -253,7 +253,7 @@ const TodoApp: FC = () => {
|
|
|
253
253
|
return
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
todos.value = todos.value.map(item => (item.id === id ? { ...item, title } : item))
|
|
256
|
+
todos.value = todos.value.map((item) => (item.id === id ? { ...item, title } : item))
|
|
257
257
|
cancelEditing()
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -262,7 +262,9 @@ const TodoApp: FC = () => {
|
|
|
262
262
|
<section className="hero border border-base-300 bg-base-100 shadow-xl">
|
|
263
263
|
<div className="hero-content flex-col items-start gap-8 px-6 py-8 lg:flex-row lg:items-end lg:justify-between">
|
|
264
264
|
<div className="max-w-3xl space-y-4">
|
|
265
|
-
<h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">
|
|
265
|
+
<h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">
|
|
266
|
+
Todo App 已作为 base 模板内置页面
|
|
267
|
+
</h1>
|
|
266
268
|
<div className="flex flex-wrap gap-3">
|
|
267
269
|
<RouterLink to="/" className="btn btn-outline">
|
|
268
270
|
返回默认简报
|
|
@@ -330,7 +332,7 @@ const TodoApp: FC = () => {
|
|
|
330
332
|
</div>
|
|
331
333
|
|
|
332
334
|
<div className="flex flex-wrap gap-2">
|
|
333
|
-
{filterOptions.map(filter => (
|
|
335
|
+
{filterOptions.map((filter) => (
|
|
334
336
|
<button
|
|
335
337
|
key={filter.key}
|
|
336
338
|
className={`btn btn-sm ${
|
|
@@ -366,7 +368,7 @@ const TodoApp: FC = () => {
|
|
|
366
368
|
|
|
367
369
|
<section className="grid gap-4">
|
|
368
370
|
{visibleTodos.get().length ? (
|
|
369
|
-
visibleTodos.get().map(item => {
|
|
371
|
+
visibleTodos.get().map((item) => {
|
|
370
372
|
const meta = statusMeta[item.status]
|
|
371
373
|
const isEditing = editingId.value === item.id
|
|
372
374
|
|
|
@@ -381,10 +383,16 @@ const TodoApp: FC = () => {
|
|
|
381
383
|
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
|
382
384
|
<div className="flex-1 space-y-3">
|
|
383
385
|
<div className="flex flex-wrap items-center gap-2">
|
|
384
|
-
<span
|
|
386
|
+
<span
|
|
387
|
+
className={`inline-block h-2.5 w-2.5 rounded-full ${meta.dotClass}`}
|
|
388
|
+
></span>
|
|
385
389
|
<span className={meta.badgeClass}>{meta.label}</span>
|
|
386
|
-
{item.archived &&
|
|
387
|
-
|
|
390
|
+
{item.archived && (
|
|
391
|
+
<span className="badge badge-secondary badge-outline">已归档</span>
|
|
392
|
+
)}
|
|
393
|
+
<span className="text-xs text-base-content/50">
|
|
394
|
+
创建于 {item.createdAt}
|
|
395
|
+
</span>
|
|
388
396
|
</div>
|
|
389
397
|
|
|
390
398
|
{!isEditing && (
|
|
@@ -403,13 +411,13 @@ const TodoApp: FC = () => {
|
|
|
403
411
|
<EditingTitleInput
|
|
404
412
|
key={item.id}
|
|
405
413
|
initialTitle={item.title}
|
|
406
|
-
onSave={title => saveEditing(item.id, title)}
|
|
414
|
+
onSave={(title) => saveEditing(item.id, title)}
|
|
407
415
|
onCancel={cancelEditing}
|
|
408
416
|
/>
|
|
409
417
|
)}
|
|
410
418
|
|
|
411
419
|
<div className="flex flex-wrap gap-2">
|
|
412
|
-
{statusOptions.map(option => (
|
|
420
|
+
{statusOptions.map((option) => (
|
|
413
421
|
<button
|
|
414
422
|
key={option.key}
|
|
415
423
|
className={`btn btn-xs ${
|
|
@@ -427,7 +435,10 @@ const TodoApp: FC = () => {
|
|
|
427
435
|
|
|
428
436
|
<div className="flex flex-wrap gap-2 lg:justify-end">
|
|
429
437
|
{!isEditing && (
|
|
430
|
-
<button
|
|
438
|
+
<button
|
|
439
|
+
className="btn btn-sm btn-outline"
|
|
440
|
+
onClick={() => startEditing(item)}
|
|
441
|
+
>
|
|
431
442
|
改名
|
|
432
443
|
</button>
|
|
433
444
|
)}
|
|
@@ -437,7 +448,10 @@ const TodoApp: FC = () => {
|
|
|
437
448
|
>
|
|
438
449
|
{item.archived ? '恢复' : '归档'}
|
|
439
450
|
</button>
|
|
440
|
-
<button
|
|
451
|
+
<button
|
|
452
|
+
className="btn btn-sm btn-outline btn-error"
|
|
453
|
+
onClick={() => removeTodo(item.id)}
|
|
454
|
+
>
|
|
441
455
|
删除
|
|
442
456
|
</button>
|
|
443
457
|
</div>
|
|
@@ -461,4 +475,4 @@ const TodoApp: FC = () => {
|
|
|
461
475
|
)
|
|
462
476
|
}
|
|
463
477
|
|
|
464
|
-
export default TodoApp
|
|
478
|
+
export default TodoApp
|
|
@@ -111,7 +111,7 @@ const ThemePicker: FC = () => {
|
|
|
111
111
|
theme.value = (event.currentTarget as HTMLSelectElement).value
|
|
112
112
|
}}
|
|
113
113
|
>
|
|
114
|
-
{themes.map(name => (
|
|
114
|
+
{themes.map((name) => (
|
|
115
115
|
<option key={name} value={name} selected={theme.value === name}>
|
|
116
116
|
{themeLabels[name] || name}
|
|
117
117
|
</option>
|
|
@@ -138,7 +138,7 @@ const Header: FC = () => {
|
|
|
138
138
|
</RouterLink>
|
|
139
139
|
</div>
|
|
140
140
|
<nav className="navbar-center hidden flex-1 justify-center gap-2 md:flex">
|
|
141
|
-
{navItems.map(item => (
|
|
141
|
+
{navItems.map((item) => (
|
|
142
142
|
<RouterLink
|
|
143
143
|
key={item.to}
|
|
144
144
|
to={item.to}
|
|
@@ -171,7 +171,7 @@ const Footer: FC = () => (
|
|
|
171
171
|
</footer>
|
|
172
172
|
)
|
|
173
173
|
|
|
174
|
-
const HeaderToggleButton: FC<{ hidden: boolean; onToggle: () => void }> = props => (
|
|
174
|
+
const HeaderToggleButton: FC<{ hidden: boolean; onToggle: () => void }> = (props) => (
|
|
175
175
|
<button
|
|
176
176
|
type="button"
|
|
177
177
|
className="btn btn-circle btn-sm fixed left-3 top-3 z-50 border-base-300 bg-base-100/90 shadow-lg backdrop-blur"
|
|
@@ -183,7 +183,7 @@ const HeaderToggleButton: FC<{ hidden: boolean; onToggle: () => void }> = props
|
|
|
183
183
|
</button>
|
|
184
184
|
)
|
|
185
185
|
|
|
186
|
-
const SiteLayout: FC = props => {
|
|
186
|
+
const SiteLayout: FC = (props) => {
|
|
187
187
|
const route = useRoute()
|
|
188
188
|
const reportHeaderHidden = ref(getStoredHeaderHidden())
|
|
189
189
|
const currentPath = computed(() => route.get()?.path || '/')
|
|
@@ -209,7 +209,9 @@ const SiteLayout: FC = props => {
|
|
|
209
209
|
}}
|
|
210
210
|
/>
|
|
211
211
|
)}
|
|
212
|
-
<main
|
|
212
|
+
<main
|
|
213
|
+
className={`content-width pb-10 ${hideHeader.get() ? 'pt-6 sm:pt-8' : 'pt-6 sm:pt-8'}`}
|
|
214
|
+
>
|
|
213
215
|
{props.children}
|
|
214
216
|
</main>
|
|
215
217
|
<Footer />
|
|
@@ -14,24 +14,24 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@rue-js/jsx-runtime": "^0.0.33",
|
|
17
|
-
"@rue-js/runtime": "^0.0.33",
|
|
18
17
|
"@rue-js/router": "^0.0.33",
|
|
19
18
|
"@rue-js/rue": "^0.0.33",
|
|
19
|
+
"@rue-js/runtime": "^0.0.33",
|
|
20
20
|
"@rue-js/runtime-vapor": "^0.0.33",
|
|
21
|
+
"daisyui": "^5.5.11",
|
|
21
22
|
"oxfmt": "^0.42.0",
|
|
22
|
-
"oxlint": "^1.57.0"
|
|
23
|
-
"daisyui": "^5.5.11"
|
|
23
|
+
"oxlint": "^1.57.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@swc/core": "^1.15.3",
|
|
27
26
|
"@rue-js/jsx-dev-runtime": "^0.0.33",
|
|
28
27
|
"@rue-js/vite-plugin-rue": "^0.0.33",
|
|
29
|
-
"
|
|
30
|
-
"vite": "^8.0.3",
|
|
28
|
+
"@swc/core": "^1.15.3",
|
|
31
29
|
"@tailwindcss/typography": "^0.5.19",
|
|
32
30
|
"@tailwindcss/vite": "^4.1.17",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
31
|
+
"@types/node": "^24.10.1",
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"vite": "^8.0.3",
|
|
34
|
+
"vite-plugin-wasm": "^3.5.0"
|
|
35
35
|
},
|
|
36
36
|
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
|
|
37
37
|
}
|
package/template/base/style.css
CHANGED
|
@@ -16,8 +16,16 @@
|
|
|
16
16
|
body {
|
|
17
17
|
@apply bg-base-200 text-base-content antialiased;
|
|
18
18
|
background-image:
|
|
19
|
-
radial-gradient(
|
|
20
|
-
|
|
19
|
+
radial-gradient(
|
|
20
|
+
circle at top,
|
|
21
|
+
color-mix(in oklch, var(--color-primary) 14%, transparent),
|
|
22
|
+
transparent 28%
|
|
23
|
+
),
|
|
24
|
+
radial-gradient(
|
|
25
|
+
circle at bottom right,
|
|
26
|
+
color-mix(in oklch, var(--color-accent) 10%, transparent),
|
|
27
|
+
transparent 24%
|
|
28
|
+
);
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
* {
|