@morya-ui/mcp 0.3.3 → 0.3.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.
- package/LICENSE +21 -21
- package/README.md +151 -151
- package/bin/morya-ui-mcp.js +2 -2
- package/data/catalog.json +62 -51
- package/data/example-coverage.json +6 -4
- package/data/golden-pages/dashboard-page.vue +138 -138
- package/data/golden-pages/detail-page.vue +178 -178
- package/data/golden-pages/empty-state.vue +56 -56
- package/data/golden-pages/form-in-dialog.vue +166 -166
- package/data/golden-pages/form-page.vue +107 -107
- package/data/golden-pages/landing-page.vue +358 -358
- package/data/golden-pages/list-page-dense.vue +168 -0
- package/data/golden-pages/list-page-rail.vue +272 -0
- package/data/golden-pages/list-page.vue +222 -216
- package/data/golden-pages/login-page.vue +231 -231
- package/data/golden-pages/result-page.vue +84 -84
- package/data/golden-pages/settings-page.vue +163 -163
- package/data/golden-pages/wizard-form.vue +182 -182
- package/dist/__tests__/page-snippets.test.js +29 -0
- package/dist/__tests__/tools.test.js +94 -1
- package/dist/decisions.d.ts +2 -0
- package/dist/decisions.js +76 -7
- package/dist/golden-pages.d.ts +18 -0
- package/dist/golden-pages.js +76 -22
- package/dist/index.js +9 -3
- package/dist/page-snippets.js +960 -257
- package/dist/patterns.d.ts +5 -3
- package/dist/patterns.js +53 -13
- package/dist/style-presets.d.ts +33 -0
- package/dist/style-presets.js +131 -0
- package/dist/tools.d.ts +12 -0
- package/dist/tools.js +301 -210
- package/package.json +1 -1
package/dist/patterns.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface PagePattern {
|
|
|
12
12
|
descriptionEn: string;
|
|
13
13
|
keywords: string[];
|
|
14
14
|
goldenPage?: string;
|
|
15
|
+
/** Composition-first: prefer these page-snippet ids over cloning the golden page. */
|
|
16
|
+
suggestedSnippets?: string[];
|
|
15
17
|
components: PatternComponent[];
|
|
16
18
|
structure: string[];
|
|
17
19
|
layout: Record<string, string>;
|
|
@@ -51,8 +53,8 @@ export declare const designRules: {
|
|
|
51
53
|
readonly motion: "--m-motion-fast/normal/enter/exit/distance/ease; intensity via useMotion (data-m-motion); enter/exit via motion.transitions / transition prop (fade, scale-fade, zoom, slide-*, dialog, drawer, …)";
|
|
52
54
|
};
|
|
53
55
|
readonly composition: {
|
|
54
|
-
readonly workflow: readonly ["For full pages: recommend_page → get_golden_page →
|
|
55
|
-
readonly snippets: readonly ["list-filters", "list-toolbar", "list-table", "list-row-actions", "form-header", "form-body", "form-actions", "dashboard-kpi-grid", "dashboard-chart-card", "layout-app-shell", "scrollable-panel"];
|
|
56
|
+
readonly workflow: readonly ["Resolve style first: user reference/description → prompt cues → ask when uncertain (get_style_direction; no preset catalog).", "For full pages: recommend_page({ style? }) → suggestedSnippets / get_page_snippet → optional get_golden_page → apply styleDirection.", "Craft: visual-craft Ops polish or Express design plan; optional frontend-design / impeccable only after contract (companions never replace M*).", "For local edits: get_page_snippet(section) — list filters prefer list-filters-stack; also toolbar/form-actions/KPI/scrollable-panel.", "Use MLayout fillViewport as the app shell; put MPageContent inside MLayoutContent.", "Prefer MPage* components over scoped CSS for filters, toolbars, headers, form surfaces, and KPI cards.", "Use MSpace or MFlex for control groups inside MPageFilters; default filter composition is list-filters-stack.", "Golden pages lock structure/API, not the only aesthetic — do not emit identical quiet chrome every time."];
|
|
57
|
+
readonly snippets: readonly ["list-filters-stack", "list-filters", "list-filters-dense", "list-filter-chips", "list-toolbar", "list-table", "list-row-actions", "form-header", "form-body", "form-actions", "dashboard-kpi-grid", "dashboard-chart-card", "layout-app-shell", "scrollable-panel"];
|
|
56
58
|
readonly pageStack: {
|
|
57
59
|
readonly list: readonly ["MLayout", "MLayoutHeader", "MLayoutContent", "MPageContent", "MPageFilters", "MPageToolbar", "MTable"];
|
|
58
60
|
readonly form: readonly ["MLayout", "MLayoutHeader", "MLayoutContent", "MPageContent", "MPageHeader", "MPageSection", "MForm"];
|
|
@@ -68,7 +70,7 @@ export declare const designRules: {
|
|
|
68
70
|
readonly do: readonly ["MLayoutHeader bordered (default)", "MPageFilters for filter regions", "MPageSection variant=\"form\" for forms", "MTable bordered when table needs grid lines"];
|
|
69
71
|
readonly avoid: readonly ["MCard wrapping MTable that is already bordered", "Nested MCard with bordered=true on both levels", "Hand-written section borders when MPageFilters or MPageSection applies", "Double borders on filter + table wrapper"];
|
|
70
72
|
};
|
|
71
|
-
readonly goldenPages: readonly ["list-page", "form-page", "dashboard-page", "login-page", "landing-page", "empty-state", "detail-page", "form-in-dialog", "result-page", "settings-page", "wizard-form"];
|
|
73
|
+
readonly goldenPages: readonly ["list-page", "list-page-dense", "list-page-rail", "form-page", "dashboard-page", "login-page", "landing-page", "empty-state", "detail-page", "form-in-dialog", "result-page", "settings-page", "wizard-form"];
|
|
72
74
|
};
|
|
73
75
|
readonly actions: {
|
|
74
76
|
readonly primary: {
|
package/dist/patterns.js
CHANGED
|
@@ -6,6 +6,16 @@ export const pagePatterns = [
|
|
|
6
6
|
description: '用于资源管理、设备管理、用户管理等带筛选和行操作的数据列表。',
|
|
7
7
|
descriptionEn: 'A resource-management list with filters, actions, row operations, and pagination.',
|
|
8
8
|
goldenPage: 'list-page',
|
|
9
|
+
suggestedSnippets: [
|
|
10
|
+
'layout-app-shell',
|
|
11
|
+
'page-header-actions',
|
|
12
|
+
'list-filters-stack',
|
|
13
|
+
'list-table',
|
|
14
|
+
'list-status-dot',
|
|
15
|
+
'empty-block',
|
|
16
|
+
'form-in-dialog',
|
|
17
|
+
'confirm-delete',
|
|
18
|
+
],
|
|
9
19
|
keywords: [
|
|
10
20
|
'列表',
|
|
11
21
|
'表格',
|
|
@@ -51,17 +61,17 @@ export const pagePatterns = [
|
|
|
51
61
|
' └── MLayout',
|
|
52
62
|
' ├── MLayoutHeader → MBreadcrumb',
|
|
53
63
|
' └── MLayoutContent',
|
|
54
|
-
' └── MPageContent',
|
|
64
|
+
' └── MPageContent (+ fill when full-viewport main list)',
|
|
55
65
|
' ├── MPageFilters (MSpace + MInput + MSelect + MButton)',
|
|
56
66
|
' ├── MPageToolbar (title + primary action)',
|
|
57
|
-
' ├── MTable (paginator, #cell-* slots, #empty)',
|
|
67
|
+
' ├── MTable (+ fill when height rule applies; paginator, #cell-* slots, #empty)',
|
|
58
68
|
' └── MDialog (create/edit MForm, optional)',
|
|
59
69
|
],
|
|
60
70
|
layout: {
|
|
61
71
|
page: 'MLayout fillViewport + has-sider;MLayoutContent 内用 MPageContent 堆叠区块',
|
|
62
72
|
header: 'MLayoutHeader 放面包屑;标题与主操作用 MPageToolbar',
|
|
63
73
|
filters: 'MPageFilters 包裹筛选控件;内部 MSpace wrap 或 MFlex',
|
|
64
|
-
data: 'MTable 直接放在 MPageContent 内,不要额外 MCard
|
|
74
|
+
data: 'MTable 直接放在 MPageContent 内,不要额外 MCard;全视口主列表且表格是主任务时再 fill(表体滚、分页贴底),嵌入/短页跳过;paginator + #empty',
|
|
65
75
|
form: '列表新建/编辑默认 MDialog + MForm,不要默认拆独立表单路由',
|
|
66
76
|
},
|
|
67
77
|
styleRules: [
|
|
@@ -94,6 +104,7 @@ export const pagePatterns = [
|
|
|
94
104
|
description: '用于创建或编辑业务对象,包含分组字段、校验和提交状态。',
|
|
95
105
|
descriptionEn: 'A create or edit page with grouped fields, validation, and submit states.',
|
|
96
106
|
goldenPage: 'form-page',
|
|
107
|
+
suggestedSnippets: ['page-content-form', 'form-header', 'form-body', 'form-actions'],
|
|
97
108
|
keywords: ['表单', '新增', '编辑', '创建', '配置', '设置', 'form', 'create', 'edit', 'settings'],
|
|
98
109
|
components: [
|
|
99
110
|
{ component: 'ConfigProvider', role: '应用根包裹' },
|
|
@@ -155,6 +166,7 @@ export const pagePatterns = [
|
|
|
155
166
|
description: '从列表触发的短表单 CRUD:留在列表页,用 MDialog 承载 MForm。',
|
|
156
167
|
descriptionEn: 'Short CRUD forms launched from a list: keep the list page and host MForm in MDialog.',
|
|
157
168
|
keywords: ['弹窗表单', '新建弹窗', '编辑弹窗', '列表新建', 'dialog form', 'modal form', 'inline create', 'inline edit'],
|
|
169
|
+
suggestedSnippets: ['form-in-dialog', 'page-header-actions', 'list-table'],
|
|
158
170
|
components: [
|
|
159
171
|
{ component: 'Dialog', role: '承载短表单' },
|
|
160
172
|
{ component: 'Form', role: '声明式校验' },
|
|
@@ -195,6 +207,13 @@ export const pagePatterns = [
|
|
|
195
207
|
description: '用于展示关键指标、趋势、告警和需要优先处理的业务信息。',
|
|
196
208
|
descriptionEn: 'A workspace for KPIs, trends, alerts, and prioritized operational information.',
|
|
197
209
|
keywords: ['仪表盘', '工作台', '监控', '指标', '趋势', '告警', 'dashboard', 'monitoring', 'kpi', 'analytics'],
|
|
210
|
+
suggestedSnippets: [
|
|
211
|
+
'layout-app-shell',
|
|
212
|
+
'page-header-actions',
|
|
213
|
+
'dashboard-kpi-grid',
|
|
214
|
+
'dashboard-chart-card',
|
|
215
|
+
'dashboard-recent-table',
|
|
216
|
+
],
|
|
198
217
|
components: [
|
|
199
218
|
{ component: 'ConfigProvider', role: '应用根包裹' },
|
|
200
219
|
{ component: 'Layout', role: '页面骨架' },
|
|
@@ -262,6 +281,7 @@ export const pagePatterns = [
|
|
|
262
281
|
interactionRules: ['显示未保存修改状态', '保存成功使用 message.success 单行反馈;仅有 summary+detail 时用 toast', '保存失败保留输入并显示字段或页面级错误', '切换 Tab 不应意外丢失未保存输入'],
|
|
263
282
|
avoid: ['不要把所有设置塞进一个超长表单', '不要用 placeholder 代替配置项 label', '不要隐藏影响范围较大的配置说明'],
|
|
264
283
|
goldenPage: 'settings-page',
|
|
284
|
+
suggestedSnippets: ['page-content-form', 'form-header', 'form-body', 'form-actions'],
|
|
265
285
|
},
|
|
266
286
|
{
|
|
267
287
|
id: 'empty-state',
|
|
@@ -270,6 +290,7 @@ export const pagePatterns = [
|
|
|
270
290
|
description: '用于首次使用、搜索无结果、资源已清空或暂时没有内容的场景。',
|
|
271
291
|
descriptionEn: 'For first use, no search results, empty resources, or temporarily unavailable content.',
|
|
272
292
|
goldenPage: 'empty-state',
|
|
293
|
+
suggestedSnippets: ['empty-block'],
|
|
273
294
|
keywords: ['空状态', '无数据', '无结果', '首次使用', 'empty', 'no results', 'no data', 'zero state'],
|
|
274
295
|
components: [
|
|
275
296
|
{ component: 'PageContent', role: '承载空态的内容区', required: false },
|
|
@@ -300,6 +321,7 @@ export const pagePatterns = [
|
|
|
300
321
|
description: '用于登录、注册、找回密码和二次认证流程。',
|
|
301
322
|
descriptionEn: 'For login, registration, password recovery, and second-factor authentication flows.',
|
|
302
323
|
goldenPage: 'login-page',
|
|
324
|
+
suggestedSnippets: ['auth-split-shell'],
|
|
303
325
|
keywords: ['登录', '注册', '认证', '密码', '验证码', 'login', 'register', 'authentication', 'password', 'otp'],
|
|
304
326
|
components: [
|
|
305
327
|
{ component: 'ConfigProvider', role: '应用根包裹' },
|
|
@@ -332,6 +354,7 @@ export const pagePatterns = [
|
|
|
332
354
|
description: '用于产品官网、发布页、定价前导等公开营销表面;首屏单一任务,控件仍用 morya-ui。',
|
|
333
355
|
descriptionEn: 'Public marketing surfaces (product home, launch, pre-pricing). One job in the first viewport; controls still use morya-ui.',
|
|
334
356
|
goldenPage: 'landing-page',
|
|
357
|
+
suggestedSnippets: [],
|
|
335
358
|
keywords: [
|
|
336
359
|
'落地页',
|
|
337
360
|
'营销',
|
|
@@ -365,8 +388,8 @@ export const pagePatterns = [
|
|
|
365
388
|
},
|
|
366
389
|
styleRules: [
|
|
367
390
|
'交互控件使用 MButton / MTag / MAccordion 等',
|
|
368
|
-
'颜色与间距使用 --m
|
|
369
|
-
'
|
|
391
|
+
'颜色与间距使用 --m-*;氛围跟已选 style preset(默认扁平/简洁,勿擅自渐变)',
|
|
392
|
+
'未点名 expressive 预设时:禁止紫蓝 aurora、奶油衬线陶土、报纸风、霓虹、毛玻璃默认脸',
|
|
370
393
|
'首屏不要堆统计条、促销胶囊、日程碎片',
|
|
371
394
|
],
|
|
372
395
|
interactionRules: ['CTA 指向明确下一步', 'FAQ 用 Accordion 降低长页噪声', '尊重 prefers-reduced-motion 若加动画'],
|
|
@@ -394,6 +417,7 @@ export const pagePatterns = [
|
|
|
394
417
|
interactionRules: ['进入下一步前只校验当前步骤', '返回上一步保留输入', '完成前展示摘要或确认', '刷新和离开时处理未完成状态'],
|
|
395
418
|
avoid: ['不要把所有字段一次性隐藏在一个超长页面', '不要允许跳过有前置依赖的步骤', '不要让完成按钮在每一步都使用相同文案'],
|
|
396
419
|
goldenPage: 'wizard-form',
|
|
420
|
+
suggestedSnippets: ['wizard-steps', 'form-body', 'result-block'],
|
|
397
421
|
},
|
|
398
422
|
{
|
|
399
423
|
id: 'detail-page',
|
|
@@ -445,6 +469,7 @@ export const pagePatterns = [
|
|
|
445
469
|
'不要让详情页的操作按钮分散在多个无关区域',
|
|
446
470
|
],
|
|
447
471
|
goldenPage: 'detail-page',
|
|
472
|
+
suggestedSnippets: ['detail-toolbar', 'form-in-dialog', 'confirm-delete', 'list-status-dot'],
|
|
448
473
|
},
|
|
449
474
|
{
|
|
450
475
|
id: 'result-page',
|
|
@@ -502,6 +527,7 @@ export const pagePatterns = [
|
|
|
502
527
|
'不要使用已移除的 #extra 插槽;操作用 #footer',
|
|
503
528
|
],
|
|
504
529
|
goldenPage: 'result-page',
|
|
530
|
+
suggestedSnippets: ['result-block'],
|
|
505
531
|
},
|
|
506
532
|
];
|
|
507
533
|
/** Advisory page-writing standards for MCP and human authors — not enforced blockers. */
|
|
@@ -538,38 +564,44 @@ export const pageStandards = [
|
|
|
538
564
|
titleEn: 'Page section components',
|
|
539
565
|
recommend: [
|
|
540
566
|
'筛选区用 MPageFilters,标题+操作用 MPageToolbar,表单区用 MPageSection',
|
|
541
|
-
'列表页 MTable 直接放在 MPageContent
|
|
567
|
+
'列表页 MTable 直接放在 MPageContent 内,不要额外 MCard',
|
|
568
|
+
'全视口后台主列表(表格是页面主任务)才用 MPageContent fill + MTable fill;嵌入/短页/整页文档滚动跳过 fill',
|
|
542
569
|
'同行控件用 MSpace / MFlex;区块之间依赖 MPageContent 的 gap',
|
|
543
|
-
'局部区块优先 get_page_snippet(filters / toolbar / form-actions 等)',
|
|
570
|
+
'局部区块优先 get_page_snippet(filters / toolbar / form-actions / list-table 等)',
|
|
544
571
|
],
|
|
545
572
|
recommendEn: [
|
|
546
573
|
'Use MPageFilters, MPageToolbar, and MPageSection for filters, headers/actions, and forms',
|
|
547
|
-
'Place MTable directly in MPageContent on list pages',
|
|
574
|
+
'Place MTable directly in MPageContent on list pages (no extra Card)',
|
|
575
|
+
'Use MPageContent fill + MTable fill only for full-viewport admin lists whose main job is one table; skip fill for embedded/short/document-scroll cases',
|
|
548
576
|
'Use MSpace / MFlex for same-row controls; let MPageContent gap separate sections',
|
|
549
|
-
'Prefer get_page_snippet for local blocks such as filters, toolbar, or
|
|
577
|
+
'Prefer get_page_snippet for local blocks such as filters, toolbar, form-actions, or list-table',
|
|
550
578
|
],
|
|
551
579
|
discouraged: [
|
|
552
580
|
'手写 .page-filters / .page-toolbar 类',
|
|
553
581
|
'用 MCard 或带 padding 的容器再包 MPageFilters / MPageSection / MPageToolbar',
|
|
554
582
|
'在已有 MPage* 区块之间再写 margin 叠间距',
|
|
583
|
+
'对嵌入表/短页/整页滚动硬套 fill,或适合 fill 时却手写 min-height/calc',
|
|
555
584
|
],
|
|
556
585
|
discouragedEn: [
|
|
557
586
|
'Hand-written .page-filters / .page-toolbar classes',
|
|
558
587
|
'Wrapping MPageFilters / MPageSection / MPageToolbar with MCard or extra padded containers',
|
|
559
588
|
'Adding margin between MPage* siblings that PageContent gap already spaces',
|
|
589
|
+
'Forcing fill on embedded/short/document-scroll tables, or hand-writing min-height/calc when fill fits',
|
|
560
590
|
],
|
|
561
|
-
mcp: { decision: '
|
|
591
|
+
mcp: { snippet: 'list-table', decision: 'page-scroll-choice' },
|
|
562
592
|
},
|
|
563
593
|
{
|
|
564
594
|
id: 'scroll',
|
|
565
595
|
title: '滚动',
|
|
566
596
|
titleEn: 'Scroll',
|
|
567
597
|
recommend: [
|
|
598
|
+
'全视口主列表可选用表体滚动:MPageContent fill + MTable fill;否则优先整页 Layout 滚动或局部 MScrollbar',
|
|
568
599
|
'组件内置滚动区(Layout 壳、菜单/下拉面板、Table 视口等)使用内置 MScrollbar',
|
|
569
600
|
'Dialog / Drawer / Popover / Splitter 等内容区不强制主题滚动;需要时由业务自行包 MScrollbar',
|
|
570
601
|
'已内置滚动的组件通常无需再外包一层',
|
|
571
602
|
],
|
|
572
603
|
recommendEn: [
|
|
604
|
+
'Full-viewport main lists may use table-body scroll via MPageContent fill + MTable fill; otherwise prefer layout scroll or local MScrollbar',
|
|
573
605
|
'Component-owned scroll chrome (Layout shell, menu/select panels, Table viewport) uses built-in MScrollbar',
|
|
574
606
|
'Do not force themed scroll into Dialog / Drawer / Popover / Splitter content; apps can wrap MScrollbar when needed',
|
|
575
607
|
'Components that already scroll internally usually need no extra wrapper',
|
|
@@ -649,14 +681,20 @@ export const designRules = {
|
|
|
649
681
|
},
|
|
650
682
|
composition: {
|
|
651
683
|
workflow: [
|
|
652
|
-
'
|
|
653
|
-
'For
|
|
684
|
+
'Resolve style first: user reference/description → prompt cues → ask when uncertain (get_style_direction; no preset catalog).',
|
|
685
|
+
'For full pages: recommend_page({ style? }) → suggestedSnippets / get_page_snippet → optional get_golden_page → apply styleDirection.',
|
|
686
|
+
'Craft: visual-craft Ops polish or Express design plan; optional frontend-design / impeccable only after contract (companions never replace M*).',
|
|
687
|
+
'For local edits: get_page_snippet(section) — list filters prefer list-filters-stack; also toolbar/form-actions/KPI/scrollable-panel.',
|
|
654
688
|
'Use MLayout fillViewport as the app shell; put MPageContent inside MLayoutContent.',
|
|
655
689
|
'Prefer MPage* components over scoped CSS for filters, toolbars, headers, form surfaces, and KPI cards.',
|
|
656
|
-
'Use MSpace or MFlex for control groups inside MPageFilters;
|
|
690
|
+
'Use MSpace or MFlex for control groups inside MPageFilters; default filter composition is list-filters-stack.',
|
|
691
|
+
'Golden pages lock structure/API, not the only aesthetic — do not emit identical quiet chrome every time.',
|
|
657
692
|
],
|
|
658
693
|
snippets: [
|
|
694
|
+
'list-filters-stack',
|
|
659
695
|
'list-filters',
|
|
696
|
+
'list-filters-dense',
|
|
697
|
+
'list-filter-chips',
|
|
660
698
|
'list-toolbar',
|
|
661
699
|
'list-table',
|
|
662
700
|
'list-row-actions',
|
|
@@ -690,6 +728,8 @@ export const designRules = {
|
|
|
690
728
|
},
|
|
691
729
|
goldenPages: [
|
|
692
730
|
'list-page',
|
|
731
|
+
'list-page-dense',
|
|
732
|
+
'list-page-rail',
|
|
693
733
|
'form-page',
|
|
694
734
|
'dashboard-page',
|
|
695
735
|
'login-page',
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual style direction for generated pages — no named preset catalog.
|
|
3
|
+
* Structure still comes from golden pages; look follows the user’s reference / words.
|
|
4
|
+
*/
|
|
5
|
+
/** How agents pick a visual direction before coding. */
|
|
6
|
+
export declare const styleResolution: {
|
|
7
|
+
priorityZh: string[];
|
|
8
|
+
priorityEn: string[];
|
|
9
|
+
hardRulesZh: string[];
|
|
10
|
+
hardRulesEn: string[];
|
|
11
|
+
};
|
|
12
|
+
export type StyleResolutionKind = 'explicit' | 'inferred' | 'ask';
|
|
13
|
+
export interface StyleDirectionResult {
|
|
14
|
+
resolution: StyleResolutionKind;
|
|
15
|
+
/** Free-text summary of the direction (user words or inferred reading). */
|
|
16
|
+
summary?: string;
|
|
17
|
+
confidence: number;
|
|
18
|
+
guidanceZh: string;
|
|
19
|
+
guidanceEn: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pick list golden craft variant from free-text style/intent.
|
|
23
|
+
* Returns null to keep the canonical list-page.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveListCraftVariant(text: string | null | undefined): 'list-page-dense' | 'list-page-rail' | null;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve visual direction from an optional free-text style string and/or intent.
|
|
28
|
+
* No preset catalog — explicit user words win; otherwise ask or carefully infer.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveStyleDirection(args: {
|
|
31
|
+
intent?: string;
|
|
32
|
+
style?: string;
|
|
33
|
+
}): StyleDirectionResult;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual style direction for generated pages — no named preset catalog.
|
|
3
|
+
* Structure still comes from golden pages; look follows the user’s reference / words.
|
|
4
|
+
*/
|
|
5
|
+
/** How agents pick a visual direction before coding. */
|
|
6
|
+
export const styleResolution = {
|
|
7
|
+
priorityZh: [
|
|
8
|
+
'【最高优先】用户给了明确参考(截图 / 设计稿 / 现有页 / URL /「像 XX」)或明确描述了风格 → 必须按用户指定执行,映射到 --m-* + M*,不要换组件库、不要改成另一套脸',
|
|
9
|
+
'用户未点名、但提示词有明确气质/行业线索 → 按提示推断并在回复里用一句话点名你理解的风格;装饰性毛玻璃/霓虹/整页渐变等仅当提示明确要求',
|
|
10
|
+
'不确定(无参考、无线索)→ 必须先向用户询问一次,请其说明或贴参考;在用户回答前不要擅自发明完整视觉',
|
|
11
|
+
'用户回答「你看着办 / 直接写」且仍无线索 → 用克制、扁平、token 实色的安静后台脸,并在回复里说明;禁止默认毛玻璃/霓虹/紫渐变/新拟态',
|
|
12
|
+
'已安装 frontend-design / impeccable 时:结构与契约仍用 morya-ui-pages + MCP;companion 只加深已定方向,不得推翻用户指定或未询问就换脸',
|
|
13
|
+
],
|
|
14
|
+
priorityEn: [
|
|
15
|
+
'【Highest】User gave a clear reference (screenshot / mock / page / URL / “like X”) or explicitly described a style → follow it; map to --m-* + M*; never switch kits or substitute another look',
|
|
16
|
+
'No explicit description, but the prompt has clear mood / industry cues → infer and state your reading in one sentence; decorative glass/neon/full-page gradients only when clearly requested',
|
|
17
|
+
'Uncertain (no reference, vague cues) → must ask once for a description or reference before inventing the full look',
|
|
18
|
+
'User says “your call / just ship” with still no cues → use a quiet flat on-token admin face and say so; never default glass/neon/purple-mesh/neumorph',
|
|
19
|
+
'If frontend-design / impeccable are installed: structure + contract still from morya-ui-pages + MCP; companions only deepen the chosen direction — never override an explicit user choice or invent a look without asking',
|
|
20
|
+
],
|
|
21
|
+
hardRulesZh: [
|
|
22
|
+
'用户明确参考 / 明确描述优先于一切 companion 与默认启发式',
|
|
23
|
+
'没有命名风格预设表;不要把页面硬套进固定「风格 id」',
|
|
24
|
+
'黄金样例管区块顺序与 API,不管死审美;结构可镜像,视觉必须跟参考 / 用户描述 / 已说明的推断走',
|
|
25
|
+
'任何方向仍只用 morya-ui 的 M* 与 --m-*(可用 color-mix),禁止第二套 UI kit 与裸 hex 主题色',
|
|
26
|
+
'风格不确定时先问用户,禁止静默套一套 AI 默认脸(紫蓝 aurora、奶油衬线陶土、霓虹、未要求的毛玻璃/渐变)',
|
|
27
|
+
'Frontend Design / Impeccable / UI-UX-Pro-Max 与本 skill 冲突时,以 morya-ui-pages + DESIGN.md + MCP 为准',
|
|
28
|
+
],
|
|
29
|
+
hardRulesEn: [
|
|
30
|
+
'An explicit user reference or style description outranks every companion and every heuristic',
|
|
31
|
+
'There is no named style-preset catalog; do not force pages into fixed style ids',
|
|
32
|
+
'Golden pages lock block order and APIs, not the only aesthetic; mirror structure, follow reference / user words / stated inference for craft',
|
|
33
|
+
'Every look still uses morya-ui M* and --m-* only (color-mix OK); no second UI kit or raw hex theme colors',
|
|
34
|
+
'When style is uncertain, ask first — never silently apply an AI-default face (purple aurora, cream+serif+terracotta, neon, unsolicited glass/gradients)',
|
|
35
|
+
'When Frontend Design / Impeccable / UI-UX-Pro-Max conflict with this skill, morya-ui-pages + DESIGN.md + MCP win',
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
/** List golden craft keywords only (density / sider chrome) — not a style catalog. */
|
|
39
|
+
const denseHints = /dense|compact|高密|紧凑|工具台|监控列表|cms/i;
|
|
40
|
+
const railHints = /rail|侧栏强调|品牌侧栏|colored\s*sider|accent\s*rail/i;
|
|
41
|
+
/**
|
|
42
|
+
* Pick list golden craft variant from free-text style/intent.
|
|
43
|
+
* Returns null to keep the canonical list-page.
|
|
44
|
+
*/
|
|
45
|
+
export function resolveListCraftVariant(text) {
|
|
46
|
+
const raw = (text || '').trim();
|
|
47
|
+
if (!raw)
|
|
48
|
+
return null;
|
|
49
|
+
if (railHints.test(raw))
|
|
50
|
+
return 'list-page-rail';
|
|
51
|
+
if (denseHints.test(raw))
|
|
52
|
+
return 'list-page-dense';
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve visual direction from an optional free-text style string and/or intent.
|
|
57
|
+
* No preset catalog — explicit user words win; otherwise ask or carefully infer.
|
|
58
|
+
*/
|
|
59
|
+
export function resolveStyleDirection(args) {
|
|
60
|
+
const explicit = args.style?.trim();
|
|
61
|
+
if (explicit) {
|
|
62
|
+
return {
|
|
63
|
+
resolution: 'explicit',
|
|
64
|
+
summary: explicit,
|
|
65
|
+
confidence: 100,
|
|
66
|
+
guidanceZh: `用户已指定风格方向:「${explicit}」。在黄金结构上落实到 M* + --m-*,不要换成另一套脸。`,
|
|
67
|
+
guidanceEn: `User specified style direction: “${explicit}”. Implement on the golden structure with M* + --m-*; do not substitute another look.`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const intent = (args.intent || '').trim();
|
|
71
|
+
const cueScore = scoreStyleCues(intent);
|
|
72
|
+
if (intent && cueScore >= 20) {
|
|
73
|
+
const summary = summarizeStyleCues(intent);
|
|
74
|
+
return {
|
|
75
|
+
resolution: 'inferred',
|
|
76
|
+
summary,
|
|
77
|
+
confidence: cueScore,
|
|
78
|
+
guidanceZh: `从提示词推断风格方向:「${summary}」。若不符请用户纠正。不确定时应先问,不要静默发明。`,
|
|
79
|
+
guidanceEn: `Inferred style direction: “${summary}”. Ask the user to correct if wrong. When unsure, ask — do not invent silently.`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
resolution: 'ask',
|
|
84
|
+
confidence: 0,
|
|
85
|
+
guidanceZh: '风格不确定:请先向用户询问(描述气质,或贴参考图/现有页)。有明确参考或明确描述时必须跟用户。禁止在未询问时套 AI 默认渐变/霓虹/毛玻璃。',
|
|
86
|
+
guidanceEn: 'Style uncertain: ask the user for a short description or a reference. When they give a reference or clear words, follow them. Never apply AI-default gradients/neon/glass without asking.',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function scoreStyleCues(query) {
|
|
90
|
+
const q = query.toLowerCase();
|
|
91
|
+
let score = 0;
|
|
92
|
+
const hits = [
|
|
93
|
+
[/毛玻璃|glass|frosted|霓虹|neon|渐变|gradient|新拟态|neumorph|大屏|datav|暗黑|cyber/i, 35],
|
|
94
|
+
[/简洁|克制|扁平|flat|商务|erp|crm|政企|政务|国企|留白|极简|黑白|卡片|看板|仪表盘|cms|内容管理/i, 28],
|
|
95
|
+
[/像.+一样|参考|截图|设计稿|mock|figma/i, 40],
|
|
96
|
+
[/saas|工具后台|运营后台|监控|安全/i, 18],
|
|
97
|
+
];
|
|
98
|
+
for (const [re, pts] of hits) {
|
|
99
|
+
if (re.test(q))
|
|
100
|
+
score += pts;
|
|
101
|
+
}
|
|
102
|
+
return score;
|
|
103
|
+
}
|
|
104
|
+
function summarizeStyleCues(intent) {
|
|
105
|
+
const q = intent.toLowerCase();
|
|
106
|
+
if (/毛玻璃|glass|frosted/.test(q))
|
|
107
|
+
return '半透明毛玻璃气质(仅当用户明确要求)';
|
|
108
|
+
if (/霓虹|neon|暗黑科技|cyber/.test(q))
|
|
109
|
+
return '深色 + 克制科技强调';
|
|
110
|
+
if (/渐变|gradient/.test(q))
|
|
111
|
+
return '有克制的色彩渐变(chrome/品牌条,非 aurora)';
|
|
112
|
+
if (/新拟态|neumorph/.test(q))
|
|
113
|
+
return '新拟态柔和凹凸(展示向)';
|
|
114
|
+
if (/大屏|wallboard|datav/.test(q))
|
|
115
|
+
return '深色数据大屏:大数字、轻动态';
|
|
116
|
+
if (/政企|政务|国企/.test(q))
|
|
117
|
+
return '方正严谨、偏政企正式';
|
|
118
|
+
if (/erp|crm|商务/.test(q))
|
|
119
|
+
return '稳重商务、清晰分区';
|
|
120
|
+
if (/看板|仪表盘|kpi|卡片/.test(q))
|
|
121
|
+
return '模块化卡片/指标看板';
|
|
122
|
+
if (/cms|内容管理/.test(q))
|
|
123
|
+
return '紧凑表格优先的内容管理';
|
|
124
|
+
if (/极简|黑白|排版/.test(q))
|
|
125
|
+
return '黑白灰、排版层级';
|
|
126
|
+
if (/扁平|flat/.test(q))
|
|
127
|
+
return '纯色扁平、少阴影';
|
|
128
|
+
if (/简洁|克制|留白|saas|工具/.test(q))
|
|
129
|
+
return '简洁克制、少装饰';
|
|
130
|
+
return '按提示词气质落地(克制、token 实色优先)';
|
|
131
|
+
}
|
package/dist/tools.d.ts
CHANGED
|
@@ -116,6 +116,7 @@ export declare function createToolHandlers(catalog?: import("./catalog.js").Cata
|
|
|
116
116
|
intent: string;
|
|
117
117
|
pageType?: string;
|
|
118
118
|
features?: string[];
|
|
119
|
+
style?: string;
|
|
119
120
|
mode?: string;
|
|
120
121
|
includeScaffold?: boolean;
|
|
121
122
|
}) => {
|
|
@@ -134,6 +135,17 @@ export declare function createToolHandlers(catalog?: import("./catalog.js").Cata
|
|
|
134
135
|
text: string;
|
|
135
136
|
}[];
|
|
136
137
|
};
|
|
138
|
+
getStyleDirection: (args?: {
|
|
139
|
+
intent?: string;
|
|
140
|
+
style?: string;
|
|
141
|
+
mode?: string;
|
|
142
|
+
}) => {
|
|
143
|
+
structuredContent?: Record<string, unknown> | undefined;
|
|
144
|
+
content: {
|
|
145
|
+
type: "text";
|
|
146
|
+
text: string;
|
|
147
|
+
}[];
|
|
148
|
+
};
|
|
137
149
|
recommendComponent: (args: {
|
|
138
150
|
query?: string;
|
|
139
151
|
decision?: string;
|