@morya-ui/setup 0.2.5

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/bin/morya-ui-setup.js +14 -0
  4. package/package.json +35 -0
  5. package/src/cli.mjs +200 -0
  6. package/src/copy-template.mjs +62 -0
  7. package/src/fs-utils.mjs +23 -0
  8. package/src/install.mjs +63 -0
  9. package/src/mcp.mjs +50 -0
  10. package/src/package-json.mjs +30 -0
  11. package/src/styles.mjs +109 -0
  12. package/template/.agents/skills/morya-ui-pages/SKILL.md +150 -0
  13. package/template/.agents/skills/morya-ui-pages/evals/evals.json +53 -0
  14. package/template/.agents/skills/morya-ui-pages/references/component-index.md +72 -0
  15. package/template/.agents/skills/morya-ui-pages/references/design-system.md +90 -0
  16. package/template/.agents/skills/morya-ui-pages/references/feedback.md +66 -0
  17. package/template/.agents/skills/morya-ui-pages/references/optional-companions.md +29 -0
  18. package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +76 -0
  19. package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +49 -0
  20. package/template/.agents/skills/morya-ui-pages/references/surfaces.md +89 -0
  21. package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +83 -0
  22. package/template/.cursor/rules/coding-style.mdc +41 -0
  23. package/template/.cursor/rules/component-usage.mdc +41 -0
  24. package/template/.cursor/rules/design-system.mdc +17 -0
  25. package/template/.cursor/rules/page-layout.mdc +67 -0
  26. package/template/DESIGN.md +121 -0
  27. package/template/design-tokens/tokens.css +55 -0
  28. package/template/design-tokens/tokens.json +77 -0
  29. package/template/docs/components.md +144 -0
  30. package/template/docs/feedback-message-vs-toast.md +103 -0
  31. package/template/docs/golden-pages/dashboard-page.vue +103 -0
  32. package/template/docs/golden-pages/empty-state.vue +66 -0
  33. package/template/docs/golden-pages/form-page.vue +107 -0
  34. package/template/docs/golden-pages/landing-page.vue +328 -0
  35. package/template/docs/golden-pages/list-page.vue +127 -0
  36. package/template/docs/golden-pages/login-page.vue +191 -0
  37. package/template/scripts/check-raw-colors.mjs +74 -0
  38. package/template/src/examples/DashboardPageExample.vue +103 -0
  39. package/template/src/examples/EmptyStateExample.vue +66 -0
  40. package/template/src/examples/FormPageExample.vue +107 -0
  41. package/template/src/examples/LandingPageExample.vue +328 -0
  42. package/template/src/examples/ListPageExample.vue +127 -0
  43. package/template/src/examples/LoginPageExample.vue +191 -0
@@ -0,0 +1,127 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 黄金样例:列表页
4
+ * @see DESIGN.md §3
5
+ */
6
+ import {
7
+ MBreadcrumb,
8
+ MButton,
9
+ MConfigProvider,
10
+ MInput,
11
+ MLayout,
12
+ MLayoutContent,
13
+ MLayoutHeader,
14
+ MLayoutSider,
15
+ MMenu,
16
+ MPageContent,
17
+ MPageFilters,
18
+ MPageToolbar,
19
+ MSelect,
20
+ MSpace,
21
+ MTable,
22
+ MTag,
23
+ zhCN,
24
+ } from 'morya-ui'
25
+ import { ref } from 'vue'
26
+
27
+ const keyword = ref('')
28
+ const status = ref<string | undefined>()
29
+
30
+ const statusOptions = [
31
+ { label: '全部', value: '' },
32
+ { label: '启用', value: 'active' },
33
+ { label: '停用', value: 'inactive' },
34
+ ]
35
+
36
+ const columns = [
37
+ { key: 'name', label: '名称' },
38
+ { key: 'status', label: '状态' },
39
+ { key: 'updatedAt', label: '更新时间' },
40
+ { key: 'actions', label: '操作', width: 128 },
41
+ ]
42
+
43
+ const rows = [
44
+ { id: '1', name: '示例项目 A', status: 'active', updatedAt: '2026-09-01' },
45
+ { id: '2', name: '示例项目 B', status: 'inactive', updatedAt: '2026-08-28' },
46
+ { id: '3', name: '示例项目 C', status: 'active', updatedAt: '2026-08-25' },
47
+ { id: '4', name: '示例项目 D', status: 'active', updatedAt: '2026-08-20' },
48
+ { id: '5', name: '示例项目 E', status: 'inactive', updatedAt: '2026-08-15' },
49
+ ]
50
+ </script>
51
+
52
+ <template>
53
+ <MConfigProvider :locale="zhCN">
54
+ <MLayout has-sider fill-viewport>
55
+ <MLayoutSider bordered>
56
+ <MMenu :model="[{ label: '用户管理', key: 'users' }, { label: '角色管理', key: 'roles' }]" />
57
+ </MLayoutSider>
58
+
59
+ <MLayout>
60
+ <MLayoutHeader padding="var(--m-space-4) var(--m-space-6)">
61
+ <MBreadcrumb :model="[{ label: '首页', to: '/' }, { label: '用户管理' }]" />
62
+ </MLayoutHeader>
63
+
64
+ <MLayoutContent>
65
+ <MPageContent>
66
+ <MPageFilters aria-label="筛选">
67
+ <MSpace wrap>
68
+ <MInput v-model="keyword" placeholder="搜索名称" clearable style="width: 14rem" />
69
+ <MSelect
70
+ v-model="status"
71
+ :options="statusOptions"
72
+ placeholder="状态"
73
+ clearable
74
+ style="width: 10rem"
75
+ />
76
+ <MButton severity="primary">
77
+ 查询
78
+ </MButton>
79
+ <MButton severity="secondary">
80
+ 重置
81
+ </MButton>
82
+ </MSpace>
83
+ </MPageFilters>
84
+
85
+ <MPageToolbar title="用户管理">
86
+ <template #actions>
87
+ <MButton severity="primary">
88
+ 新建用户
89
+ </MButton>
90
+ </template>
91
+ </MPageToolbar>
92
+
93
+ <MTable
94
+ :columns="columns"
95
+ :rows="rows"
96
+ :rows-per-page="3"
97
+ paginator
98
+ striped
99
+ bordered
100
+ row-key="id"
101
+ aria-label="用户列表"
102
+ >
103
+ <template #cell-status="{ value }">
104
+ <MTag :value="value === 'active' ? '启用' : '停用'" :severity="value === 'active' ? 'success' : 'secondary'" />
105
+ </template>
106
+ <template #cell-actions>
107
+ <MSpace>
108
+ <MButton severity="secondary" size="small">
109
+ 编辑
110
+ </MButton>
111
+ <MButton severity="danger" size="small">
112
+ 删除
113
+ </MButton>
114
+ </MSpace>
115
+ </template>
116
+ <template #empty>
117
+ <p style="margin: 0; padding: var(--m-space-8); text-align: center; color: var(--m-color-text-muted)">
118
+ 暂无用户数据
119
+ </p>
120
+ </template>
121
+ </MTable>
122
+ </MPageContent>
123
+ </MLayoutContent>
124
+ </MLayout>
125
+ </MLayout>
126
+ </MConfigProvider>
127
+ </template>
@@ -0,0 +1,191 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 黄金样例:登录页(Account + 轻量品牌)
4
+ * @see DESIGN.md §3 · morya-ui-pages surfaces § Account
5
+ */
6
+ import {
7
+ MButton,
8
+ MConfigProvider,
9
+ MForm,
10
+ MFormItem,
11
+ MInput,
12
+ MInputPassword,
13
+ MSpace,
14
+ zhCN,
15
+ } from 'morya-ui'
16
+ import { reactive, ref } from 'vue'
17
+
18
+ const submitting = ref(false)
19
+ const formError = ref('')
20
+
21
+ const model = reactive({
22
+ email: '',
23
+ password: '',
24
+ })
25
+
26
+ async function onSubmit() {
27
+ formError.value = ''
28
+ submitting.value = true
29
+ try {
30
+ // await api.login(model)
31
+ if (!model.email || !model.password) {
32
+ formError.value = '请输入邮箱和密码后再试。'
33
+ return
34
+ }
35
+ } finally {
36
+ submitting.value = false
37
+ }
38
+ }
39
+ </script>
40
+
41
+ <template>
42
+ <MConfigProvider :locale="zhCN">
43
+ <div class="login-shell">
44
+ <aside class="login-brand" aria-label="品牌">
45
+ <p class="login-brand__mark">青禾书房</p>
46
+ <h1 class="login-brand__title">把好书留在手边</h1>
47
+ <p class="login-brand__lead">
48
+ 店员与会员共用同一套账户。登录后继续进货、上架与会员服务。
49
+ </p>
50
+ </aside>
51
+
52
+ <main class="login-main">
53
+ <div class="login-panel">
54
+ <header class="login-panel__header">
55
+ <h2>登录</h2>
56
+ <p>使用工作邮箱进入后台。</p>
57
+ </header>
58
+
59
+ <!-- 表单级常驻错误:token 样式告警条(字段错误优先用 errorMessage) -->
60
+ <p v-if="formError" class="login-alert" role="alert">
61
+ {{ formError }}
62
+ </p>
63
+
64
+ <MForm @submit="onSubmit">
65
+ <MFormItem label="邮箱" name="email" required>
66
+ <MInput
67
+ v-model="model.email"
68
+ type="email"
69
+ placeholder="name@qinghe.example"
70
+ autocomplete="username"
71
+ fluid
72
+ />
73
+ </MFormItem>
74
+
75
+ <MFormItem label="密码" name="password" required>
76
+ <MInputPassword
77
+ v-model="model.password"
78
+ placeholder="请输入密码"
79
+ autocomplete="current-password"
80
+ fluid
81
+ />
82
+ </MFormItem>
83
+
84
+ <MSpace style="margin-top: var(--m-space-2)" alignment="center">
85
+ <MButton type="submit" label="登录" :loading="submitting" />
86
+ <MButton type="button" label="忘记密码" severity="secondary" text />
87
+ </MSpace>
88
+ </MForm>
89
+ </div>
90
+ </main>
91
+ </div>
92
+ </MConfigProvider>
93
+ </template>
94
+
95
+ <style scoped>
96
+ .login-shell {
97
+ display: grid;
98
+ grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
99
+ min-height: 100vh;
100
+ background: var(--m-color-surface);
101
+ color: var(--m-color-text);
102
+ }
103
+
104
+ .login-brand {
105
+ display: flex;
106
+ flex-direction: column;
107
+ justify-content: flex-end;
108
+ gap: var(--m-space-4);
109
+ padding: clamp(2rem, 6vw, 4.5rem);
110
+ background:
111
+ linear-gradient(
112
+ 165deg,
113
+ color-mix(in srgb, var(--m-color-primary) 18%, var(--m-color-surface)) 0%,
114
+ var(--m-color-surface) 55%,
115
+ color-mix(in srgb, var(--m-color-border) 35%, var(--m-color-surface)) 100%
116
+ );
117
+ border-right: 1px solid var(--m-color-border);
118
+ }
119
+
120
+ .login-brand__mark {
121
+ margin: 0;
122
+ font-size: 0.8125rem;
123
+ letter-spacing: 0.14em;
124
+ text-transform: uppercase;
125
+ color: var(--m-color-text-muted);
126
+ }
127
+
128
+ .login-brand__title {
129
+ margin: 0;
130
+ max-width: 12em;
131
+ font-size: clamp(2rem, 4vw, 3rem);
132
+ font-weight: 650;
133
+ line-height: 1.15;
134
+ letter-spacing: -0.03em;
135
+ }
136
+
137
+ .login-brand__lead {
138
+ margin: 0;
139
+ max-width: 28rem;
140
+ color: var(--m-color-text-muted);
141
+ line-height: 1.6;
142
+ }
143
+
144
+ .login-main {
145
+ display: grid;
146
+ place-items: center;
147
+ padding: var(--m-space-6);
148
+ }
149
+
150
+ .login-panel {
151
+ width: min(100%, 22rem);
152
+ }
153
+
154
+ .login-panel__header {
155
+ margin-bottom: var(--m-space-5);
156
+ }
157
+
158
+ .login-panel__header h2 {
159
+ margin: 0 0 var(--m-space-2);
160
+ font-size: 1.5rem;
161
+ font-weight: 650;
162
+ }
163
+
164
+ .login-panel__header p {
165
+ margin: 0;
166
+ color: var(--m-color-text-muted);
167
+ }
168
+
169
+ .login-alert {
170
+ margin: 0 0 var(--m-space-4);
171
+ padding: var(--m-space-3) var(--m-space-4);
172
+ border: 1px solid color-mix(in srgb, var(--m-color-danger) 40%, var(--m-color-border));
173
+ border-radius: var(--m-radius-md);
174
+ background: color-mix(in srgb, var(--m-color-danger) 10%, var(--m-color-surface));
175
+ color: var(--m-color-danger);
176
+ font-size: 0.875rem;
177
+ line-height: 1.45;
178
+ }
179
+
180
+ @media (max-width: 768px) {
181
+ .login-shell {
182
+ grid-template-columns: 1fr;
183
+ }
184
+
185
+ .login-brand {
186
+ border-right: 0;
187
+ border-bottom: 1px solid var(--m-color-border);
188
+ min-height: 12rem;
189
+ }
190
+ }
191
+ </style>