@morya-ui/mcp 0.2.5 → 0.2.6
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/data/catalog.json +12 -12
- package/data/example-coverage.json +2 -2
- package/data/golden-pages/list-page.vue +13 -2
- package/dist/__tests__/tools.test.js +21 -0
- package/dist/decisions.js +59 -4
- package/dist/page-snippets.js +42 -14
- package/dist/patterns.js +52 -8
- package/dist/tools.js +23 -0
- package/package.json +1 -1
package/data/catalog.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"generatedAt": "2026-09-16T08:53:15.402Z",
|
|
3
3
|
"library": {
|
|
4
4
|
"name": "morya-ui",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.6"
|
|
6
6
|
},
|
|
7
7
|
"mcp": {
|
|
8
8
|
"name": "@morya-ui/mcp",
|
|
9
|
-
"version": "0.2.
|
|
9
|
+
"version": "0.2.6"
|
|
10
10
|
},
|
|
11
11
|
"components": [
|
|
12
12
|
{
|
|
@@ -11961,7 +11961,7 @@
|
|
|
11961
11961
|
{
|
|
11962
11962
|
"id": "overview",
|
|
11963
11963
|
"title": "",
|
|
11964
|
-
"body": "# Layout\n\n页面级布局容器。侧栏场景需在对应 `MLayout` 上设置 `has-sider
|
|
11964
|
+
"body": "# Layout\n\n页面级布局容器。侧栏场景需在对应 `MLayout` 上设置 `has-sider`。根布局使用 `fill-viewport`(`height: 100dvh`)或显式 `height` 后,`MLayoutContent` / `MLayoutSider` 会撑满剩余空间。"
|
|
11965
11965
|
},
|
|
11966
11966
|
{
|
|
11967
11967
|
"id": "引入",
|
|
@@ -12006,7 +12006,7 @@
|
|
|
12006
12006
|
{
|
|
12007
12007
|
"id": "layout-props",
|
|
12008
12008
|
"title": "Layout Props",
|
|
12009
|
-
"body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `hasSider` | `boolean` | `false` | 横向容纳 `MLayoutSider`。 |\n| `siderPlacement` | `'left' \\| 'right'` | `'left'` | 侧栏位置。 |\n| `embedded` | `boolean` | `false` | 柔和背景(嵌套内容区)。 |\n| `position` | `'static' \\| 'absolute'` | `'static'` | 定位模式。 |\n| `contentClass` / `contentStyle` | — | — | 滚动容器 class / style。 |\n| `height` | `number \\| string` | — | — |\n| `padding` | `number \\| string` | — | — |\n| `radius` | `number \\| string` | — | — |"
|
|
12009
|
+
"body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `hasSider` | `boolean` | `false` | 横向容纳 `MLayoutSider`。 |\n| `siderPlacement` | `'left' \\| 'right'` | `'left'` | 侧栏位置。 |\n| `fillViewport` | `boolean` | `false` | 根布局撑满视口(`100dvh`),侧栏/内容才能按剩余高度拉伸。 |\n| `embedded` | `boolean` | `false` | 柔和背景(嵌套内容区)。 |\n| `position` | `'static' \\| 'absolute'` | `'static'` | 定位模式。 |\n| `contentClass` / `contentStyle` | — | — | 滚动容器 class / style。 |\n| `height` | `number \\| string` | — | — |\n| `padding` | `number \\| string` | — | — |\n| `radius` | `number \\| string` | — | — |"
|
|
12010
12010
|
},
|
|
12011
12011
|
{
|
|
12012
12012
|
"id": "layoutsider-props",
|
|
@@ -12034,7 +12034,7 @@
|
|
|
12034
12034
|
"body": "| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 布局区域。 |"
|
|
12035
12035
|
}
|
|
12036
12036
|
],
|
|
12037
|
-
"markdown": "---\ntitle: Layout\ncategory: 06 / LAYOUT\ndescription: 页面级布局骨架,含 Header / Sider / Content / Footer。\n---\n\n# Layout\n\n页面级布局容器。侧栏场景需在对应 `MLayout` 上设置 `has-sider
|
|
12037
|
+
"markdown": "---\ntitle: Layout\ncategory: 06 / LAYOUT\ndescription: 页面级布局骨架,含 Header / Sider / Content / Footer。\n---\n\n# Layout\n\n页面级布局容器。侧栏场景需在对应 `MLayout` 上设置 `has-sider`。根布局使用 `fill-viewport`(`height: 100dvh`)或显式 `height` 后,`MLayoutContent` / `MLayoutSider` 会撑满剩余空间。\n\n## 引入\n\n```ts\nimport {\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n```\n\n## 基础用法\n\nHeader / Content / Footer。Content 会占满中间剩余高度。\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## With Sider\n\n顶栏 + 左侧栏 + 主内容。内层 `has-sider` 的 Layout 会吃掉 Header 以下的全部高度。\n\n```vue preview src=\"./demos/WithSider.zh.vue\"\n```\n\n## Right Sider\n\n```vue preview src=\"./demos/RightSider.zh.vue\"\n```\n\n## Full Shell\n\n完整后台骨架:顶栏 + 侧栏 + 内容 + 底栏。\n\n```vue preview src=\"./demos/FullShell.zh.vue\"\n```\n\n## Embedded Content\n\n`embedded` 给内容区柔和背景,便于和顶栏/侧栏区分。\n\n```vue preview src=\"./demos/EmbeddedContent.zh.vue\"\n```\n\n## Scrollable Content\n\n内容超出时仅 Content 区域滚动,Header / Sider 保持固定。`MLayout` / `MLayoutContent` / `MLayoutSider` 通过内置 `MScrollbar` 提供统一滚动条。\n\n```vue preview src=\"./demos/ScrollableContent.zh.vue\"\n```\n\n## Absolute Shell\n\n根布局 `position=\"absolute\"` 铺满父级(父级需 `position: relative` + 明确高度)。\n\n```vue preview src=\"./demos/AbsoluteShell.zh.vue\"\n```\n\n## Layout Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `hasSider` | `boolean` | `false` | 横向容纳 `MLayoutSider`。 |\n| `siderPlacement` | `'left' \\| 'right'` | `'left'` | 侧栏位置。 |\n| `fillViewport` | `boolean` | `false` | 根布局撑满视口(`100dvh`),侧栏/内容才能按剩余高度拉伸。 |\n| `embedded` | `boolean` | `false` | 柔和背景(嵌套内容区)。 |\n| `position` | `'static' \\| 'absolute'` | `'static'` | 定位模式。 |\n| `contentClass` / `contentStyle` | — | — | 滚动容器 class / style。 |\n| `height` | `number \\| string` | — | — |\n| `padding` | `number \\| string` | — | — |\n| `radius` | `number \\| string` | — | — |\n\n## LayoutSider Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `width` | `number \\| string` | `272` | 展开宽度(始终写在 `width` 上)。 |\n| `collapsedWidth` | `number` | `48` | 折叠时的 `max-width`。 |\n| `collapsed` | `boolean` | — | 折叠状态,支持 `v-model:collapsed`。 |\n| `defaultCollapsed` | `boolean` | `false` | 非受控初始折叠。 |\n| `showTrigger` | `boolean \\| 'bar' \\| 'arrow-circle' \\| 'arrow'` | `false` | 折叠触发器;`arrow` 等同 `arrow-circle`。 |\n| `collapseMode` | `'width' \\| 'transform'` | `'transform'` | `transform` 裁切内容;`width` 随侧栏收缩。 |\n| `showCollapsedContent` | `boolean` | `true` | 折叠后是否仍显示侧栏内容。 |\n| `bordered` / `inverted` | `boolean` | `false` | 边框 / 反色。 |\n| `triggerClass` / `triggerStyle` | — | — | 展开态触发器样式。 |\n| `collapsedTriggerClass` / `collapsedTriggerStyle` | — | — | 折叠态触发器样式。 |\n| `contentClass` / `contentStyle` | — | — | 滚动容器 class / style。 |\n\n## Events\n\n| 事件 | 说明 |\n| --- | --- |\n| `scroll` | 滚动容器滚动时触发。 |\n| `after-enter` | 侧栏展开动画结束。 |\n| `after-leave` | 侧栏收起动画结束。 |\n| `collapse` | 侧栏开始收起。 |\n| `expand` | 侧栏开始展开。 |\n| `update:collapsed` | 折叠状态 v-model。 |\n\n## Expose\n\n`MLayout` / `MLayoutContent` / `MLayoutSider` 均暴露 `scrollTo(...)`。\n\n## Components\n\n| 组件 | 说明 |\n| --- | --- |\n| `MLayout` | 根布局。 |\n| `MLayoutHeader` | 顶栏。 |\n| `MLayoutContent` | 主内容区(默认撑满剩余空间)。 |\n| `MLayoutFooter` | 底栏。 |\n| `MLayoutSider` | 侧栏。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 布局区域。 |\n"
|
|
12038
12038
|
},
|
|
12039
12039
|
"en-US": {
|
|
12040
12040
|
"title": "Layout",
|
|
@@ -12924,7 +12924,7 @@
|
|
|
12924
12924
|
{
|
|
12925
12925
|
"id": "折叠与飞出层",
|
|
12926
12926
|
"title": "折叠与飞出层",
|
|
12927
|
-
"body": "`collapsed`
|
|
12927
|
+
"body": "`collapsed` 隐藏文案,仅保留图标;**每个可折叠展示的菜单项必须提供 `icon`**(否则折叠后几乎空白)。悬停时在右侧显示 `MTooltip` 标签,带子项的节点还会弹出飞出层(`.m-menu--flyout`)。飞出层经 `MPopover` Teleport 到 `body`,不会被侧栏或 `MLayoutSider` 滚动区域裁剪。`collapsed-width` 应与侧栏折叠宽度一致,用于居中图标。\n\n使用 `item.to` 时菜单项会渲染为 `RouterLink` / `<a>`;组件已重置链接的默认蓝色下划线,视觉与普通菜单项一致。\n\n```vue preview src=\"./demos/CollapsedAndFlyout.zh.vue\"\n```"
|
|
12928
12928
|
},
|
|
12929
12929
|
{
|
|
12930
12930
|
"id": "嵌入-layout-侧栏",
|
|
@@ -12972,7 +12972,7 @@
|
|
|
12972
12972
|
"body": "<h4 id=\"MenuItem\">MenuItem</h4>\n\n`model` 数组项,支持嵌套:\n\n```ts\ninterface MenuItem {\n key?: string\n label?: string\n icon?: string\n to?: string | RouteLocationRaw // 有 vue-router 时用 RouterLink\n command?: () => void\n disabled?: boolean\n separator?: boolean\n items?: MenuItem[]\n}\n```\n\n`key` 未传时用 `label` 作为标识。`separator: true` 时渲染分隔线。更多见 [API 类型](/docs/types)。"
|
|
12973
12973
|
}
|
|
12974
12974
|
],
|
|
12975
|
-
"markdown": "---\ntitle: Menu\ncategory: 04 / NAVIGATION\ndescription: 垂直/水平导航菜单,支持多级嵌套、受控选中、手风琴展开与折叠侧栏飞出层。\n---\n\n# Menu\n\n基于 `model` 渲染的**导航菜单**,适合后台侧栏、顶栏导航等场景。支持:\n\n- 多级嵌套 `items` 与受控 `selectedKey`\n- 展开路径自动跟随选中项;`accordion` 手风琴\n- `collapsed` 图标模式 + 右侧飞出子菜单(Popover)\n- 非 popup 时默认 `embedded`,无边框铺满 `MLayoutSider`\n\n> 单层悬停子菜单见 [TieredMenu](/components/TieredMenu);顶栏菜单见 [Menubar](/components/Menubar);操作列表见 [Dropdown](/components/Dropdown)。\n\n## 引入\n\n```ts\nimport type {MenuItem} from 'morya-ui';\nimport { MMenu } from 'morya-ui'\n```\n\n## 导航选中\n\n为叶子项设置稳定的 `key`,用 `v-model:selected-key` 与路由同步;点击时触发 `select`。\n\n```vue preview src=\"./demos/Selection.zh.vue\"\n```\n\n未提供 `key` 时会回退到 `label`;生产环境建议始终显式设置 `key`。\n\n## 嵌套子菜单\n\n点击带子项的节点可展开/收起;选中子项时父级会显示 `child-active` 高亮。\n\n```vue preview src=\"./demos/NestedSubmenus.zh.vue\"\n```\n\n## 手风琴与展开控制\n\n`accordion` 同时只保留一个一级子菜单展开。`defaultExpandedKeys` / `v-model:expanded-keys` 可受控展开项;变更 `selectedKey` 时会自动展开其祖先路径。\n\n```vue preview src=\"./demos/AccordionAndExpandedKeys.zh.vue\"\n```\n\n## 折叠与飞出层\n\n`collapsed`
|
|
12975
|
+
"markdown": "---\ntitle: Menu\ncategory: 04 / NAVIGATION\ndescription: 垂直/水平导航菜单,支持多级嵌套、受控选中、手风琴展开与折叠侧栏飞出层。\n---\n\n# Menu\n\n基于 `model` 渲染的**导航菜单**,适合后台侧栏、顶栏导航等场景。支持:\n\n- 多级嵌套 `items` 与受控 `selectedKey`\n- 展开路径自动跟随选中项;`accordion` 手风琴\n- `collapsed` 图标模式 + 右侧飞出子菜单(Popover)\n- 非 popup 时默认 `embedded`,无边框铺满 `MLayoutSider`\n\n> 单层悬停子菜单见 [TieredMenu](/components/TieredMenu);顶栏菜单见 [Menubar](/components/Menubar);操作列表见 [Dropdown](/components/Dropdown)。\n\n## 引入\n\n```ts\nimport type {MenuItem} from 'morya-ui';\nimport { MMenu } from 'morya-ui'\n```\n\n## 导航选中\n\n为叶子项设置稳定的 `key`,用 `v-model:selected-key` 与路由同步;点击时触发 `select`。\n\n```vue preview src=\"./demos/Selection.zh.vue\"\n```\n\n未提供 `key` 时会回退到 `label`;生产环境建议始终显式设置 `key`。\n\n## 嵌套子菜单\n\n点击带子项的节点可展开/收起;选中子项时父级会显示 `child-active` 高亮。\n\n```vue preview src=\"./demos/NestedSubmenus.zh.vue\"\n```\n\n## 手风琴与展开控制\n\n`accordion` 同时只保留一个一级子菜单展开。`defaultExpandedKeys` / `v-model:expanded-keys` 可受控展开项;变更 `selectedKey` 时会自动展开其祖先路径。\n\n```vue preview src=\"./demos/AccordionAndExpandedKeys.zh.vue\"\n```\n\n## 折叠与飞出层\n\n`collapsed` 隐藏文案,仅保留图标;**每个可折叠展示的菜单项必须提供 `icon`**(否则折叠后几乎空白)。悬停时在右侧显示 `MTooltip` 标签,带子项的节点还会弹出飞出层(`.m-menu--flyout`)。飞出层经 `MPopover` Teleport 到 `body`,不会被侧栏或 `MLayoutSider` 滚动区域裁剪。`collapsed-width` 应与侧栏折叠宽度一致,用于居中图标。\n\n使用 `item.to` 时菜单项会渲染为 `RouterLink` / `<a>`;组件已重置链接的默认蓝色下划线,视觉与普通菜单项一致。\n\n```vue preview src=\"./demos/CollapsedAndFlyout.zh.vue\"\n```\n\n## 嵌入 Layout 侧栏\n\n推荐结构:**全局 Header + 下方 `has-sider` Layout**。菜单放在 `MLayoutSider` 内,与 `v-model:collapsed` 联动。\n\n```vue preview src=\"./demos/EmbedInLayoutSider.zh.vue\"\n```\n\n## 水平菜单\n\n`mode=\"horizontal\"` 用于顶栏一级导航;子菜单经 `MPopover` 以下拉飞出层展示(Teleport + 主题滚动条),选中后自动关闭。`popup` 模式的主菜单列表同样内置 `MScrollbar`。\n\n```vue preview src=\"./demos/HorizontalMode.zh.vue\"\n```\n\n## 反色(深色侧栏)\n\n`inverted` 配合 `MLayoutSider` 的 `inverted`,用于深色背景侧栏。\n\n```vue preview src=\"./demos/InvertedDarkSider.zh.vue\"\n```\n\n## 弹出模式\n\n`popup` + `v-model` 将菜单作为浮层,默认 Teleport 到 `body` 并相对**默认插槽触发器**定位(无插槽时回退到最后一次指针位置)。点击外部或选中叶子项后关闭。\n\n```vue preview src=\"./demos/PopupMode.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `model` | `MenuItem[]` | — | 菜单项,可嵌套 `items`。 |\n| `popup` | `boolean` | `false` | 浮层模式;配合 `v-model` 控制显隐。 |\n| `modelValue` | `boolean` | `false` | popup 可见性(`v-model`)。 |\n| `placement` | `'bottom-start' \\| 'bottom-end' \\| 'top-start' \\| 'top-end'` | `'bottom-start'` | popup 相对触发器的位置。 |\n| `selectedKey` | `string \\| null` | `null` | 当前选中项 key(`v-model:selected-key`)。 |\n| `collapsed` | `boolean` | `false` | 图标模式;子菜单以右侧飞出层展示。 |\n| `collapsedWidth` | `number` | `80` | 折叠宽度(px),用于居中图标。 |\n| `indent` | `number` | `12` | 每层额外左内边距(px)。 |\n| `rootIndent` | `number` | `16` | 根级左内边距(px)。 |\n| `accordion` | `boolean` | `false` | 手风琴:同时只展开一个一级子菜单。 |\n| `defaultExpandedKeys` | `string[]` | `[]` | 默认展开的 submenu keys。 |\n| `expandedKeys` | `string[]` | — | 受控展开 keys(`v-model:expanded-keys`)。 |\n| `defaultExpandAll` | `boolean` | `false` | 初始展开全部子菜单。 |\n| `mode` | `'vertical' \\| 'horizontal'` | `'vertical'` | 布局方向。 |\n| `inverted` | `boolean` | `false` | 反色样式,适合深色侧栏。 |\n| `embedded` | `boolean` | `!popup` | 嵌入布局:去边框与最小宽度。 |\n| `teleport` | `boolean` | `true` | popup 时 Teleport 到 `appendTo`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Teleport 目标;未传时使用 ConfigProvider。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | popup 可见性变化。 |\n| `update:selectedKey` | `string \\| null` | 选中项变化。 |\n| `update:expandedKeys` | `string[]` | 展开项变化。 |\n| `select` | `MenuItem` | 点击叶子项(非 disabled / separator)。 |\n\n## Slots\n\n| 插槽 | 说明 |\n| --- | --- |\n| `default` | popup 模式的触发器锚点(如按钮);菜单相对其定位。 |\n\n## MenuItem\n\n| 字段 | 类型 | 说明 |\n| --- | --- | --- |\n| `key` | `string` | 唯一标识;未传时使用 `label`。 |\n| `label` | `string` | 展示文本。 |\n| `icon` | `string` | [Tabler 图标名](/components/Icon) 或字符。 |\n| `command` | `() => void` | 点击回调(与 `select` 事件同时触发)。 |\n| `disabled` | `boolean` | 禁用。 |\n| `separator` | `boolean` | 分隔线(忽略其他字段)。 |\n| `items` | `MenuItem[]` | 子菜单。 |\n\n## 类型\n\n<h4 id=\"MenuItem\">MenuItem</h4>\n\n`model` 数组项,支持嵌套:\n\n```ts\ninterface MenuItem {\n key?: string\n label?: string\n icon?: string\n to?: string | RouteLocationRaw // 有 vue-router 时用 RouterLink\n command?: () => void\n disabled?: boolean\n separator?: boolean\n items?: MenuItem[]\n}\n```\n\n`key` 未传时用 `label` 作为标识。`separator: true` 时渲染分隔线。更多见 [API 类型](/docs/types)。\n"
|
|
12976
12976
|
},
|
|
12977
12977
|
"en-US": {
|
|
12978
12978
|
"title": "Menu",
|
|
@@ -24485,7 +24485,7 @@
|
|
|
24485
24485
|
"zh-CN": {
|
|
24486
24486
|
"title": "介绍",
|
|
24487
24487
|
"description": "Morya UI 是什么、适合谁用、如何开始。",
|
|
24488
|
-
"markdown": "---\ntitle: 介绍\norder: 1\ndescription: Morya UI 是什么、适合谁用、如何开始。\n---\n\n# 介绍\n\n**Morya UI**(`morya-ui`)是一套**开源**的 Vue 3 组件库,内置设计令牌、亮暗主题、国际化与交互式文档。\n\n- **文档站**:[morya-space.github.io/morya-ui](https://morya-space.github.io/morya-ui/)\n- **源码**:[GitHub](https://github.com/morya-space/morya-ui)\n- **npm**:[`morya-ui`](https://www.npmjs.com/package/morya-ui)\n\n## 为什么选择 Morya UI\n\n| | |\n| --- | --- |\n| **
|
|
24488
|
+
"markdown": "---\ntitle: 介绍\norder: 1\ndescription: Morya UI 是什么、适合谁用、如何开始。\n---\n\n# 介绍\n\n**Morya UI**(`morya-ui`)是一套**开源**的 Vue 3 组件库,内置设计令牌、亮暗主题、国际化与交互式文档。\n\n- **文档站**:[morya-space.github.io/morya-ui](https://morya-space.github.io/morya-ui/)\n- **源码**:[GitHub](https://github.com/morya-space/morya-ui)\n- **npm**:[`morya-ui`](https://www.npmjs.com/package/morya-ui)\n\n## 为什么选择 Morya UI\n\n| | |\n| --- | --- |\n| **90+ 个组件** | 基础、表单、导航、数据展示、布局、反馈一应俱全 |\n| **主题系统** | `--m-*` 设计令牌,亮/暗色、`useTheme` / `useDensity` / `useMotion` 同包导出 |\n| **TypeScript** | Composition API 编写,Props / Emits / locale 完整类型 |\n| **按需加载** | ESM 子路径 + `MoryaUIResolver`,支持 tree-shaking |\n| **文档即预览** | 每个组件自带 Markdown + 可交互 `vue preview` |\n\n## 适用场景\n\n- 管理后台、运营平台、SaaS 控制台\n- 需要统一视觉语言的中大型 Vue 3 应用\n- 希望开箱即用主题、浮层与表单能力的团队\n\n## 包结构\n\n| 包 | 说明 |\n| --- | --- |\n| `morya-ui` | 组件、样式、主题 API、文档站源码 |\n| `@morya-ui/setup` | (可选)业务项目一键接入:库 + AI Skill / rules + MCP |\n| `@morya-ui/mcp` | (可选)MCP 服务,供支持该协议的 AI 客户端检索文档 |\n\n## 安装\n\n```bash\npnpm add morya-ui\n```\n\n需要 Vue 3(推荐 3.5 及以上)。支持 [Nuxt / Astro / Vite SSR 等](/docs/ssr)。详见 [快速上手](/docs/quick-start)。\n\n## 下一步\n\n- [快速上手](/docs/quick-start):安装与最小示例\n- [设计令牌](/docs/design-tokens):全部 `--m-*` 变量与用途\n- [主题](/docs/theme):亮暗色与动效\n- [样式与 attrs](/docs/attrs):fallthrough、`pt`、事件在各组件上的落点\n- [API 类型](/docs/types):Props 里 `FieldPassThrough`、`SelectOption` 等类型的结构\n- [全局配置](/docs/config):`ConfigProvider` / `createMoryaUI`\n- [SSR](/docs/ssr):Nuxt / Astro 等集成\n- [无障碍](/docs/accessibility):键盘、表单与浮层约定\n- [AI 接入](/docs/ai-setup):`npx @morya-ui/setup` 与 Agent 配置\n- [Agent Skill](/docs/agent-skill):`morya-ui-pages` 页面生成约定\n- [Agent MCP](/docs/mcp):AI 客户端文档检索\n- [组件](/components):浏览全部组件与 API\n- [参与贡献](https://github.com/morya-space/morya-ui/blob/main/CONTRIBUTING.zh-CN.md)\n",
|
|
24489
24489
|
"sections": [
|
|
24490
24490
|
{
|
|
24491
24491
|
"title": "",
|
|
@@ -24495,7 +24495,7 @@
|
|
|
24495
24495
|
{
|
|
24496
24496
|
"title": "为什么选择 Morya UI",
|
|
24497
24497
|
"id": "为什么选择-morya-ui",
|
|
24498
|
-
"body": "| | |\n| --- | --- |\n| **
|
|
24498
|
+
"body": "| | |\n| --- | --- |\n| **90+ 个组件** | 基础、表单、导航、数据展示、布局、反馈一应俱全 |\n| **主题系统** | `--m-*` 设计令牌,亮/暗色、`useTheme` / `useDensity` / `useMotion` 同包导出 |\n| **TypeScript** | Composition API 编写,Props / Emits / locale 完整类型 |\n| **按需加载** | ESM 子路径 + `MoryaUIResolver`,支持 tree-shaking |\n| **文档即预览** | 每个组件自带 Markdown + 可交互 `vue preview` |"
|
|
24499
24499
|
},
|
|
24500
24500
|
{
|
|
24501
24501
|
"title": "适用场景",
|
|
@@ -24522,7 +24522,7 @@
|
|
|
24522
24522
|
"en-US": {
|
|
24523
24523
|
"title": "Introduction",
|
|
24524
24524
|
"description": "What Morya UI is, who it is for, and how to get started.",
|
|
24525
|
-
"markdown": "---\ntitle: Introduction\norder: 1\ndescription: What Morya UI is, who it is for, and how to get started.\n---\n\n# Introduction\n\n**Morya UI** (`morya-ui`) is an **open-source** Vue 3 component library with design tokens, light/dark themes, i18n, and interactive documentation.\n\n- **Docs**: [morya-space.github.io/morya-ui](https://morya-space.github.io/morya-ui/)\n- **Source**: [GitHub](https://github.com/morya-space/morya-ui)\n- **npm**: [`morya-ui`](https://www.npmjs.com/package/morya-ui)\n\n## Why Morya UI\n\n| | |\n| --- | --- |\n| **
|
|
24525
|
+
"markdown": "---\ntitle: Introduction\norder: 1\ndescription: What Morya UI is, who it is for, and how to get started.\n---\n\n# Introduction\n\n**Morya UI** (`morya-ui`) is an **open-source** Vue 3 component library with design tokens, light/dark themes, i18n, and interactive documentation.\n\n- **Docs**: [morya-space.github.io/morya-ui](https://morya-space.github.io/morya-ui/)\n- **Source**: [GitHub](https://github.com/morya-space/morya-ui)\n- **npm**: [`morya-ui`](https://www.npmjs.com/package/morya-ui)\n\n## Why Morya UI\n\n| | |\n| --- | --- |\n| **90+ components** | Basics, forms, navigation, data display, layout, and feedback |\n| **Theme system** | `--m-*` design tokens; `useTheme` / `useDensity` / `useMotion` in the same package |\n| **TypeScript** | Built with Composition API; fully typed props, emits, and locale |\n| **On-demand** | ESM subpaths + `MoryaUIResolver` with tree-shaking |\n| **Docs as preview** | Markdown + interactive `vue preview` for every component |\n\n## Use cases\n\n- Admin dashboards, ops consoles, SaaS back offices\n- Medium-to-large Vue 3 apps that need a shared visual language\n- Teams that want themes, overlays, and forms without reinventing primitives\n\n## Packages\n\n| Package | Role |\n| --- | --- |\n| `morya-ui` | Components, styles, theme APIs, docs site source |\n| `@morya-ui/setup` | (Optional) One-shot app onboarding: library + AI skill / rules + MCP |\n| `@morya-ui/mcp` | (Optional) MCP server for AI clients that support the protocol |\n\n## Install\n\n```bash\npnpm add morya-ui\n```\n\nRequires Vue 3 (3.5+ recommended). Works with [Nuxt, Astro, Vite SSR, and more](/docs/ssr). See [Quick start](/docs/quick-start).\n\n## Next steps\n\n- [Quick start](/docs/quick-start): install and a minimal example\n- [Design tokens](/docs/design-tokens): full `--m-*` reference\n- [Theme](/docs/theme): light/dark and motion\n- [Styling & attrs](/docs/attrs): fallthrough, `pt`, and event placement\n- [API types](/docs/types): shapes behind names like `FieldPassThrough`, `SelectOption`\n- [Configuration](/docs/config): `ConfigProvider` / `createMoryaUI`\n- [SSR](/docs/ssr): Nuxt, Astro, and similar setups\n- [Accessibility](/docs/accessibility): forms, keyboard, overlays\n- [AI setup](/docs/ai-setup): `npx @morya-ui/setup` and Agent config\n- [Agent Skill](/docs/agent-skill): `morya-ui-pages` page-generation contract\n- [Agent MCP](/docs/mcp): doc lookup for AI clients\n- [Components](/components): browse all components and APIs\n- [Contributing](https://github.com/morya-space/morya-ui/blob/main/CONTRIBUTING.md)\n",
|
|
24526
24526
|
"sections": [
|
|
24527
24527
|
{
|
|
24528
24528
|
"title": "",
|
|
@@ -24532,7 +24532,7 @@
|
|
|
24532
24532
|
{
|
|
24533
24533
|
"title": "Why Morya UI",
|
|
24534
24534
|
"id": "why-morya-ui",
|
|
24535
|
-
"body": "| | |\n| --- | --- |\n| **
|
|
24535
|
+
"body": "| | |\n| --- | --- |\n| **90+ components** | Basics, forms, navigation, data display, layout, and feedback |\n| **Theme system** | `--m-*` design tokens; `useTheme` / `useDensity` / `useMotion` in the same package |\n| **TypeScript** | Built with Composition API; fully typed props, emits, and locale |\n| **On-demand** | ESM subpaths + `MoryaUIResolver` with tree-shaking |\n| **Docs as preview** | Markdown + interactive `vue preview` for every component |"
|
|
24536
24536
|
},
|
|
24537
24537
|
{
|
|
24538
24538
|
"title": "Use cases",
|
|
@@ -26,6 +26,12 @@ import { ref } from 'vue'
|
|
|
26
26
|
|
|
27
27
|
const keyword = ref('')
|
|
28
28
|
const status = ref<string | undefined>()
|
|
29
|
+
const siderCollapsed = ref(false)
|
|
30
|
+
|
|
31
|
+
const menuModel = [
|
|
32
|
+
{ key: 'users', label: '用户管理', icon: 'user', to: '/users' },
|
|
33
|
+
{ key: 'roles', label: '角色管理', icon: 'shield', to: '/roles' },
|
|
34
|
+
]
|
|
29
35
|
|
|
30
36
|
const statusOptions = [
|
|
31
37
|
{ label: '全部', value: '' },
|
|
@@ -52,8 +58,13 @@ const rows = [
|
|
|
52
58
|
<template>
|
|
53
59
|
<MConfigProvider :locale="zhCN">
|
|
54
60
|
<MLayout has-sider fill-viewport>
|
|
55
|
-
<MLayoutSider bordered>
|
|
56
|
-
<MMenu
|
|
61
|
+
<MLayoutSider v-model:collapsed="siderCollapsed" bordered :collapsed-width="72">
|
|
62
|
+
<MMenu
|
|
63
|
+
:model="menuModel"
|
|
64
|
+
:collapsed="siderCollapsed"
|
|
65
|
+
:collapsed-width="72"
|
|
66
|
+
selected-key="users"
|
|
67
|
+
/>
|
|
57
68
|
</MLayoutSider>
|
|
58
69
|
|
|
59
70
|
<MLayout>
|
|
@@ -167,6 +167,27 @@ describe('@morya-ui/mcp handlers', () => {
|
|
|
167
167
|
expect(result.ok).toBe(true);
|
|
168
168
|
expect(result.suggestions.some((item) => item.type === 'redundant-wrapper' && item.standardId === 'page-sections')).toBe(true);
|
|
169
169
|
});
|
|
170
|
+
it('suggests height-chain when MLayout is used without shell CSS', () => {
|
|
171
|
+
const result = read(handlers.validatePage({
|
|
172
|
+
code: '<MLayout fill-viewport has-sider><MLayoutContent /></MLayout>',
|
|
173
|
+
}));
|
|
174
|
+
expect(result.ok).toBe(true);
|
|
175
|
+
expect(result.suggestions.some((item) => item.type === 'height-chain')).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
it('suggests menu icons when MMenu model has no icon fields', () => {
|
|
178
|
+
const result = read(handlers.validatePage({
|
|
179
|
+
code: `<MMenu :model="[{ key: 'users', label: 'Users', to: '/users' }]" />`,
|
|
180
|
+
}));
|
|
181
|
+
expect(result.ok).toBe(true);
|
|
182
|
+
expect(result.suggestions.some((item) => item.type === 'menu-missing-icons')).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
it('does not suggest menu icons when model items include icon', () => {
|
|
185
|
+
const result = read(handlers.validatePage({
|
|
186
|
+
code: `<MMenu :model="[{ key: 'users', label: 'Users', icon: 'user', to: '/users' }]" />`,
|
|
187
|
+
}));
|
|
188
|
+
expect(result.ok).toBe(true);
|
|
189
|
+
expect(result.suggestions.some((item) => item.type === 'menu-missing-icons')).toBe(false);
|
|
190
|
+
});
|
|
170
191
|
it('lists component decision guides when query is omitted', () => {
|
|
171
192
|
const result = read(handlers.recommendComponent({ limit: 5 }));
|
|
172
193
|
expect(result.kind).toBe('decisions');
|
package/dist/decisions.js
CHANGED
|
@@ -1,4 +1,46 @@
|
|
|
1
1
|
export const componentDecisions = [
|
|
2
|
+
{
|
|
3
|
+
id: 'form-surface-choice',
|
|
4
|
+
title: '新建/编辑用弹窗还是独立表单页',
|
|
5
|
+
titleEn: 'Dialog vs dedicated form page for create/edit',
|
|
6
|
+
question: '表单是从列表触发的短录入,还是多分组/长流程的独立配置?',
|
|
7
|
+
questionEn: 'Is this a short create/edit from a list, or a multi-section dedicated form flow?',
|
|
8
|
+
keywords: ['新建', '编辑', '表单', '弹窗', '路由', 'create', 'edit', 'form', 'dialog', 'page'],
|
|
9
|
+
options: [
|
|
10
|
+
{
|
|
11
|
+
component: 'Dialog',
|
|
12
|
+
when: [
|
|
13
|
+
'从列表/工具栏打开新建或编辑',
|
|
14
|
+
'字段大约 ≤8 个、单段表单',
|
|
15
|
+
'希望保存后仍停留在列表上下文',
|
|
16
|
+
],
|
|
17
|
+
whenEn: [
|
|
18
|
+
'Create/edit is launched from a list or toolbar',
|
|
19
|
+
'About ≤8 fields in a single section',
|
|
20
|
+
'User should stay in the list context after save',
|
|
21
|
+
],
|
|
22
|
+
avoidWhen: ['多步骤向导', '多分组长配置页'],
|
|
23
|
+
avoidWhenEn: ['Multi-step wizards', 'Long multi-section configuration pages'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
component: 'Drawer',
|
|
27
|
+
when: ['表单比 Dialog 更长但仍需对照列表', '详情+编辑侧滑'],
|
|
28
|
+
whenEn: ['Form is longer than a dialog but list context matters', 'Detail plus edit in a side panel'],
|
|
29
|
+
avoidWhen: ['字段极少的确认式录入'],
|
|
30
|
+
avoidWhenEn: ['Tiny confirmation-style forms'],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
component: 'Form',
|
|
34
|
+
when: ['用户明确要求独立表单页', '多分组、长校验、离开需确认的配置流'],
|
|
35
|
+
whenEn: [
|
|
36
|
+
'The user explicitly asked for a dedicated form page',
|
|
37
|
+
'Multi-section, heavy validation, or leave-confirm configuration flows',
|
|
38
|
+
],
|
|
39
|
+
avoidWhen: ['列表上的常规短 CRUD'],
|
|
40
|
+
avoidWhenEn: ['Routine short CRUD from a list'],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
2
44
|
{
|
|
3
45
|
id: 'overlay-choice',
|
|
4
46
|
title: '如何选择浮层组件',
|
|
@@ -9,10 +51,23 @@ export const componentDecisions = [
|
|
|
9
51
|
options: [
|
|
10
52
|
{
|
|
11
53
|
component: 'Dialog',
|
|
12
|
-
when: [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
54
|
+
when: [
|
|
55
|
+
'需要用户聚焦完成一项短到中等任务',
|
|
56
|
+
'列表页上的新建/编辑短表单(约 ≤8 个字段)',
|
|
57
|
+
'需要确认危险操作',
|
|
58
|
+
'内容不适合直接放在页面流中',
|
|
59
|
+
],
|
|
60
|
+
whenEn: [
|
|
61
|
+
'The user should focus on a short or medium-sized task',
|
|
62
|
+
'Create/edit short forms launched from a list (~≤8 fields)',
|
|
63
|
+
'A destructive action needs confirmation',
|
|
64
|
+
'Content should not interrupt the page flow',
|
|
65
|
+
],
|
|
66
|
+
avoidWhen: ['内容接近完整多分组页面', '用户需要持续查看底层页面上下文且表单很长'],
|
|
67
|
+
avoidWhenEn: [
|
|
68
|
+
'The content is effectively a multi-section full page',
|
|
69
|
+
'The user must continuously reference the underlying page and the form is long',
|
|
70
|
+
],
|
|
16
71
|
},
|
|
17
72
|
{
|
|
18
73
|
component: 'Drawer',
|
package/dist/page-snippets.js
CHANGED
|
@@ -394,23 +394,51 @@ const recentRows = ref<Record<string, unknown>[]>([])`,
|
|
|
394
394
|
descriptionEn: 'Minimal MLayout fillViewport shell with header and content.',
|
|
395
395
|
pageTypes: ['common'],
|
|
396
396
|
keywords: ['layout', 'shell', 'breadcrumb', 'sider', 'app'],
|
|
397
|
-
imports: [
|
|
397
|
+
imports: [
|
|
398
|
+
'MLayout',
|
|
399
|
+
'MLayoutHeader',
|
|
400
|
+
'MLayoutContent',
|
|
401
|
+
'MLayoutSider',
|
|
402
|
+
'MMenu',
|
|
403
|
+
'MBreadcrumb',
|
|
404
|
+
'MPageContent',
|
|
405
|
+
'MConfigProvider',
|
|
406
|
+
'zhCN',
|
|
407
|
+
],
|
|
398
408
|
template: `<MConfigProvider :locale="zhCN">
|
|
399
|
-
<MLayout fill-viewport>
|
|
400
|
-
<
|
|
401
|
-
<
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
409
|
+
<MLayout fill-viewport has-sider>
|
|
410
|
+
<MLayoutSider v-model:collapsed="siderCollapsed" bordered :collapsed-width="72">
|
|
411
|
+
<MMenu
|
|
412
|
+
:model="[
|
|
413
|
+
{ key: 'users', label: '用户管理', icon: 'user', to: '/users' },
|
|
414
|
+
{ key: 'roles', label: '角色管理', icon: 'shield', to: '/roles' },
|
|
415
|
+
]"
|
|
416
|
+
:collapsed="siderCollapsed"
|
|
417
|
+
:collapsed-width="72"
|
|
418
|
+
/>
|
|
419
|
+
</MLayoutSider>
|
|
420
|
+
<MLayout>
|
|
421
|
+
<MLayoutHeader :padding="'var(--m-space-4) var(--m-space-6)'">
|
|
422
|
+
<MBreadcrumb :model="[{ label: '首页', to: '/' }, { label: '当前页' }]" />
|
|
423
|
+
</MLayoutHeader>
|
|
424
|
+
<MLayoutContent>
|
|
425
|
+
<MPageContent>
|
|
426
|
+
<!-- page sections -->
|
|
427
|
+
</MPageContent>
|
|
428
|
+
</MLayoutContent>
|
|
429
|
+
</MLayout>
|
|
408
430
|
</MLayout>
|
|
409
431
|
</MConfigProvider>`,
|
|
410
|
-
rules: [
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
432
|
+
rules: [
|
|
433
|
+
'根布局用 fillViewport',
|
|
434
|
+
'面包屑放 MLayoutHeader',
|
|
435
|
+
],
|
|
436
|
+
rulesEn: [
|
|
437
|
+
'Use fillViewport on the root layout',
|
|
438
|
+
'Place breadcrumb in MLayoutHeader',
|
|
439
|
+
],
|
|
440
|
+
avoid: ['不要在 MLayoutContent 上写 padding'],
|
|
441
|
+
avoidEn: ['Do not put padding on MLayoutContent'],
|
|
414
442
|
},
|
|
415
443
|
{
|
|
416
444
|
id: 'scrollable-panel',
|
package/dist/patterns.js
CHANGED
|
@@ -42,30 +42,32 @@ export const pagePatterns = [
|
|
|
42
42
|
{ component: 'Table', role: '数据展示', reason: 'paginator 启用内置分页' },
|
|
43
43
|
{ component: 'Tag', role: '业务状态展示(分类/可关闭)', required: false },
|
|
44
44
|
{ component: 'Status', role: '行内状态圆点+文案', required: false },
|
|
45
|
-
{ component: 'Dialog', role: '
|
|
45
|
+
{ component: 'Dialog', role: '新建/编辑短表单(首选)或删除确认', required: false },
|
|
46
46
|
],
|
|
47
47
|
structure: [
|
|
48
48
|
'MConfigProvider',
|
|
49
|
-
'└── MLayout (has-sider)',
|
|
50
|
-
' ├── MLayoutSider → MMenu
|
|
49
|
+
'└── MLayout (has-sider fill-viewport)',
|
|
50
|
+
' ├── MLayoutSider → MMenu',
|
|
51
51
|
' └── MLayout',
|
|
52
52
|
' ├── MLayoutHeader → MBreadcrumb',
|
|
53
53
|
' └── MLayoutContent',
|
|
54
54
|
' └── MPageContent',
|
|
55
55
|
' ├── MPageFilters (MSpace + MInput + MSelect + MButton)',
|
|
56
56
|
' ├── MPageToolbar (title + primary action)',
|
|
57
|
-
'
|
|
57
|
+
' ├── MTable (paginator, #cell-* slots, #empty)',
|
|
58
|
+
' └── MDialog (create/edit MForm, optional)',
|
|
58
59
|
],
|
|
59
60
|
layout: {
|
|
60
61
|
page: 'MLayout fillViewport + has-sider;MLayoutContent 内用 MPageContent 堆叠区块',
|
|
61
62
|
header: 'MLayoutHeader 放面包屑;标题与主操作用 MPageToolbar',
|
|
62
63
|
filters: 'MPageFilters 包裹筛选控件;内部 MSpace wrap 或 MFlex',
|
|
63
64
|
data: 'MTable 直接放在 MPageContent 内,不要额外 MCard;paginator + #empty',
|
|
65
|
+
form: '列表新建/编辑默认 MDialog + MForm,不要默认拆独立表单路由',
|
|
64
66
|
},
|
|
65
67
|
styleRules: [
|
|
66
68
|
'新增、保存等主操作使用 primary MButton',
|
|
67
69
|
'查询等次要操作使用 secondary 或 outlined MButton',
|
|
68
|
-
'删除使用 danger MButton,并配合
|
|
70
|
+
'删除使用 danger MButton,并配合 MConfirmDialog',
|
|
69
71
|
'业务状态优先使用 MStatus(圆点+文案)或 MTag(分类标签),不使用 Button severity 表达状态',
|
|
70
72
|
'间距、颜色、圆角优先使用 --m-* 设计令牌,不直接硬编码色板',
|
|
71
73
|
],
|
|
@@ -74,10 +76,12 @@ export const pagePatterns = [
|
|
|
74
76
|
'加载中禁用重复提交并显示 loading 状态',
|
|
75
77
|
'空数据使用 MTable #empty 插槽或 DataView 空态,不渲染空白表格',
|
|
76
78
|
'行级危险操作必须有确认反馈',
|
|
79
|
+
'新建/编辑短表单用 MDialog,保存成功 message.success 并关闭弹窗',
|
|
77
80
|
'CRUD 成功/删除等单行回执使用 message API,不要默认 Toast',
|
|
78
81
|
],
|
|
79
82
|
avoid: [
|
|
80
83
|
'不要用 MDialog 承载完整列表页',
|
|
84
|
+
'不要为列表短 CRUD 默认生成 /entities/new 独立表单路由',
|
|
81
85
|
'不要用 MButton 代替业务状态标签',
|
|
82
86
|
'不要为每个筛选字段手写一套不一致的 label 和间距',
|
|
83
87
|
'不要用 toast.add({ summary }) 代替 message.success 表达单行操作结果',
|
|
@@ -139,10 +143,50 @@ export const pagePatterns = [
|
|
|
139
143
|
],
|
|
140
144
|
avoid: [
|
|
141
145
|
'不要绕过 MForm 直接手写不一致的字段校验状态',
|
|
142
|
-
'
|
|
146
|
+
'列表上的短新建/编辑优先 MDialog,不要默认拆成独立路由表单页',
|
|
147
|
+
'不要把完整多分组编辑流程塞进过窄的 Dialog;字段很多时用独立表单页或 MDrawer',
|
|
143
148
|
'不要使用 placeholder 代替 label',
|
|
144
149
|
],
|
|
145
150
|
},
|
|
151
|
+
{
|
|
152
|
+
id: 'form-in-dialog',
|
|
153
|
+
title: '列表内新建 / 编辑弹窗',
|
|
154
|
+
titleEn: 'Create or edit in a dialog from a list',
|
|
155
|
+
description: '从列表触发的短表单 CRUD:留在列表页,用 MDialog 承载 MForm。',
|
|
156
|
+
descriptionEn: 'Short CRUD forms launched from a list: keep the list page and host MForm in MDialog.',
|
|
157
|
+
keywords: ['弹窗表单', '新建弹窗', '编辑弹窗', '列表新建', 'dialog form', 'modal form', 'inline create', 'inline edit'],
|
|
158
|
+
components: [
|
|
159
|
+
{ component: 'Dialog', role: '承载短表单' },
|
|
160
|
+
{ component: 'Form', role: '声明式校验' },
|
|
161
|
+
{ component: 'FormItem', role: '字段标签与校验', required: false },
|
|
162
|
+
{ component: 'Input', role: '文本字段' },
|
|
163
|
+
{ component: 'Select', role: '枚举字段', required: false },
|
|
164
|
+
{ component: 'Button', role: '页脚保存/取消' },
|
|
165
|
+
],
|
|
166
|
+
structure: [
|
|
167
|
+
'列表页(list-page)',
|
|
168
|
+
'└── MDialog',
|
|
169
|
+
' ├── MForm + 字段',
|
|
170
|
+
' └── #footer → 取消 / 保存',
|
|
171
|
+
],
|
|
172
|
+
layout: {
|
|
173
|
+
host: '留在列表页,不另开路由',
|
|
174
|
+
dialog: 'MDialog 承载短表单;宽度约 28–36rem',
|
|
175
|
+
form: 'MForm + 字段;页脚用 Dialog #footer',
|
|
176
|
+
},
|
|
177
|
+
styleRules: [
|
|
178
|
+
'Dialog 宽度约 28–36rem;树/长内容区可限高滚动',
|
|
179
|
+
'页脚用 Dialog #footer,不要把主按钮只放在表单流末尾却看不见',
|
|
180
|
+
],
|
|
181
|
+
interactionRules: [
|
|
182
|
+
'保存成功后关闭 Dialog 并 message.success',
|
|
183
|
+
'取消或关闭丢弃未保存草稿(或按产品要求提示)',
|
|
184
|
+
],
|
|
185
|
+
avoid: [
|
|
186
|
+
'不要为 ≤8 字段的列表 CRUD 再开 /entities/new 路由',
|
|
187
|
+
'不要用 Toast 代替单行 message 回执',
|
|
188
|
+
],
|
|
189
|
+
},
|
|
146
190
|
{
|
|
147
191
|
id: 'dashboard',
|
|
148
192
|
title: '仪表盘 / 监控工作台',
|
|
@@ -471,12 +515,12 @@ export const pageStandards = [
|
|
|
471
515
|
'Call get_golden_page before writing a full page and copy the matching structure',
|
|
472
516
|
],
|
|
473
517
|
discouraged: [
|
|
474
|
-
'手写 min-height:100vh',
|
|
518
|
+
'手写 min-height:100vh 代替 Layout',
|
|
475
519
|
'在 MLayoutContent 上写 padding/gap',
|
|
476
520
|
'嵌套多层 MPageContent',
|
|
477
521
|
],
|
|
478
522
|
discouragedEn: [
|
|
479
|
-
'Hand-written min-height:100vh',
|
|
523
|
+
'Hand-written min-height:100vh instead of Layout',
|
|
480
524
|
'Padding/gap on MLayoutContent instead of MPageContent',
|
|
481
525
|
'Nesting multiple MPageContent shells',
|
|
482
526
|
],
|
package/dist/tools.js
CHANGED
|
@@ -927,6 +927,29 @@ export function createToolHandlers(catalog = loadCatalog()) {
|
|
|
927
927
|
: '标准建议:整页高度优先 MLayout fillViewport,少写 min-height:100vh。',
|
|
928
928
|
});
|
|
929
929
|
}
|
|
930
|
+
if ((/fill-viewport|fillViewport/i.test(code) || /<MLayout\b/i.test(code))
|
|
931
|
+
&& !/html\s*,\s*body\s*,\s*#app[\s\S]{0,80}height\s*:\s*100%/i.test(code)) {
|
|
932
|
+
suggestions.push({
|
|
933
|
+
standardId: 'layout-shell',
|
|
934
|
+
type: 'height-chain',
|
|
935
|
+
message: locale === 'en-US'
|
|
936
|
+
? 'Prefer layout-app-shell / golden pages: include html, body, #app { height: 100% } (morya-app-shell.css) with MLayout.'
|
|
937
|
+
: '对齐 layout-app-shell / 黄金样例:配合 MLayout 使用 html, body, #app { height: 100% }(morya-app-shell.css)。',
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
if (/<MMenu\b/i.test(code)) {
|
|
941
|
+
const iconCount = (code.match(/\bicon\s*:/g) || []).length;
|
|
942
|
+
const looksLikeMenuModel = /MMenu[\s\S]{0,1200}\b(label|model)\s*[:=]/i.test(code) || /:model=/i.test(code);
|
|
943
|
+
if (looksLikeMenuModel && iconCount === 0) {
|
|
944
|
+
suggestions.push({
|
|
945
|
+
standardId: 'layout-shell',
|
|
946
|
+
type: 'menu-missing-icons',
|
|
947
|
+
message: locale === 'en-US'
|
|
948
|
+
? 'Prefer golden / layout-app-shell menu items that include icon (e.g. user, shield, home).'
|
|
949
|
+
: '对齐黄金样例 / layout-app-shell:侧栏菜单项带上 icon(如 user、shield、home)。',
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
}
|
|
930
953
|
return textResult({
|
|
931
954
|
ok: true,
|
|
932
955
|
advisory: true,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morya-ui/mcp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.6",
|
|
5
5
|
"description": "MCP server for morya-ui — component docs, examples, and usage guidance for AI coding agents.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp#readme",
|