@morya-ui/mcp 0.2.8 → 0.2.9

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 CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "generatedAt": "2026-09-21T01:38:25.787Z",
2
+ "generatedAt": "2026-09-21T09:58:15.212Z",
3
3
  "library": {
4
4
  "name": "morya-ui",
5
- "version": "0.2.8"
5
+ "version": "0.2.9"
6
6
  },
7
7
  "mcp": {
8
8
  "name": "@morya-ui/mcp",
9
- "version": "0.2.8"
9
+ "version": "0.2.9"
10
10
  },
11
11
  "components": [
12
12
  {
@@ -8947,7 +8947,7 @@
8947
8947
  "sectionId": "全部系统图标",
8948
8948
  "lang": "vue",
8949
8949
  "preview": true,
8950
- "code": "<script setup lang=\"ts\">\nimport type {ToastMessage} from 'morya-ui';\nimport { iconNames, MIcon, MInput, MToast } from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst query = ref('')\nconst copied = ref<string | null>(null)\nconst messages = ref<ToastMessage[]>([])\nlet toastSeq = 0\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\n\nconst filtered = computed(() => {\n const q = query.value.trim().toLowerCase()\n if (!q) return [...iconNames]\n return iconNames.filter((name) => name.toLowerCase().includes(q))\n})\n\nfunction itemStyle(name: string) {\n const active = copied.value === name\n return [\n 'align-items:center',\n 'background:var(--m-color-surface)',\n `border:1px solid ${active ? 'var(--m-color-primary)' : 'var(--m-color-border)'}`,\n 'border-radius:var(--m-radius-control, 3px)',\n `color:${active ? 'var(--m-color-primary)' : 'var(--m-color-text)'}`,\n 'cursor:pointer',\n 'display:flex',\n 'flex-direction:column',\n 'font:inherit',\n 'gap:0.65rem',\n 'justify-content:center',\n 'min-height:6.5rem',\n 'padding:0.85rem 0.5rem',\n 'width:100%',\n ].join(';')\n}\n\nasync function copyName(name: string) {\n try {\n await navigator.clipboard.writeText(name)\n } catch {\n const area = document.createElement('textarea')\n area.value = name\n document.body.appendChild(area)\n area.select()\n document.execCommand('copy')\n area.remove()\n }\n copied.value = name\n if (copiedTimer) clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => {\n if (copied.value === name) copied.value = null\n }, 1200)\n\n const id = `icon-copy-${++toastSeq}`\n messages.value = [\n ...messages.value,\n {\n id,\n severity: 'success',\n summary: '已复制',\n detail: name,\n closable: true,\n },\n ]\n window.setTimeout(() => {\n messages.value = messages.value.filter((item) => item.id !== id)\n }, 1600)\n}\n\nfunction onToastClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"w-full\">\n <MInput\n v-model=\"query\"\n clearable\n fluid\n placeholder=\"搜索图标名称…\"\n class=\"max-w-xs mb-4\"\n >\n <template #prefix>\n <MIcon name=\"search\" size=\"sm\" />\n </template>\n </MInput>\n\n <p\n v-if=\"!filtered.length\"\n style=\"color: var(--m-color-text-muted); font-size: 0.875rem; margin: 0.5rem 0 0\"\n >\n 没有匹配的图标\n </p>\n\n <div\n v-else\n style=\"display:grid;grid-template-columns:repeat(auto-fill,minmax(7.25rem,1fr));gap:0.75rem;width:100%\"\n >\n <button\n v-for=\"name in filtered\"\n :key=\"name\"\n type=\"button\"\n :style=\"itemStyle(name)\"\n :title=\"`点击复制 ${name}`\"\n @click=\"copyName(name)\"\n >\n <MIcon :name=\"name\" size=\"large\" />\n <span\n style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.72rem;line-height:1.3;max-width:100%;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap\"\n >\n {{ copied === name ? '已复制' : name }}\n </span>\n </button>\n </div>\n\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onToastClose\" />\n </div>\n</template>",
8950
+ "code": "<script setup lang=\"ts\">\nimport type { IconCategoryId, ToastMessage } from 'morya-ui'\nimport {\n getIconCategory,\n getIconCategoryGroups,\n iconCategoryMeta,\n iconNames,\n MIcon,\n MInput,\n MToast,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst query = ref('')\nconst category = ref<IconCategoryId | 'all'>('all')\nconst copied = ref<string | null>(null)\nconst messages = ref<ToastMessage[]>([])\nlet toastSeq = 0\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\n\nconst categoryOptions = computed(() => [\n { id: 'all' as const, label: '全部' },\n ...iconCategoryMeta.map((item) => ({ id: item.id, label: item.labelZh })),\n])\n\nconst filteredNames = computed(() => {\n const q = query.value.trim().toLowerCase()\n return iconNames.filter((name) => {\n if (q && !name.toLowerCase().includes(q)) return false\n if (category.value !== 'all') return getIconCategory(name) === category.value\n return true\n })\n})\n\nconst grouped = computed(() => getIconCategoryGroups(filteredNames.value))\n\nfunction chipStyle(id: IconCategoryId | 'all') {\n const active = category.value === id\n return [\n 'background:' + (active ? 'var(--m-color-primary-soft, color-mix(in srgb, var(--m-color-primary) 14%, transparent))' : 'var(--m-color-surface)'),\n 'border:1px solid ' + (active ? 'var(--m-color-primary)' : 'var(--m-color-border)'),\n 'border-radius:var(--m-radius-full, 999px)',\n 'color:' + (active ? 'var(--m-color-primary)' : 'var(--m-color-text)'),\n 'cursor:pointer',\n 'font:inherit',\n 'font-size:0.8125rem',\n 'line-height:1.2',\n 'padding:0.35rem 0.75rem',\n ].join(';')\n}\n\nfunction itemStyle(name: string) {\n const active = copied.value === name\n return [\n 'align-items:center',\n 'background:var(--m-color-surface)',\n `border:1px solid ${active ? 'var(--m-color-primary)' : 'var(--m-color-border)'}`,\n 'border-radius:var(--m-radius-control, 3px)',\n `color:${active ? 'var(--m-color-primary)' : 'var(--m-color-text)'}`,\n 'cursor:pointer',\n 'display:flex',\n 'flex-direction:column',\n 'font:inherit',\n 'gap:0.65rem',\n 'justify-content:center',\n 'min-height:6.5rem',\n 'padding:0.85rem 0.5rem',\n 'width:100%',\n ].join(';')\n}\n\nasync function copyName(name: string) {\n try {\n await navigator.clipboard.writeText(name)\n } catch {\n const area = document.createElement('textarea')\n area.value = name\n document.body.appendChild(area)\n area.select()\n document.execCommand('copy')\n area.remove()\n }\n copied.value = name\n if (copiedTimer) clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => {\n if (copied.value === name) copied.value = null\n }, 1200)\n\n const id = `icon-copy-${++toastSeq}`\n messages.value = [\n ...messages.value,\n {\n id,\n severity: 'success',\n summary: '已复制',\n detail: name,\n closable: true,\n },\n ]\n window.setTimeout(() => {\n messages.value = messages.value.filter((item) => item.id !== id)\n }, 1600)\n}\n\nfunction onToastClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"w-full\">\n <MInput\n v-model=\"query\"\n clearable\n fluid\n placeholder=\"搜索图标名称…\"\n class=\"max-w-xs mb-3\"\n >\n <template #prefix>\n <MIcon name=\"search\" size=\"sm\" />\n </template>\n </MInput>\n\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;margin-bottom:1rem\">\n <button\n v-for=\"opt in categoryOptions\"\n :key=\"opt.id\"\n type=\"button\"\n :style=\"chipStyle(opt.id)\"\n @click=\"category = opt.id\"\n >\n {{ opt.label }}\n </button>\n </div>\n\n <p\n v-if=\"!grouped.length\"\n style=\"color: var(--m-color-text-muted); font-size: 0.875rem; margin: 0.5rem 0 0\"\n >\n 没有匹配的图标\n </p>\n\n <div v-else style=\"display:grid;gap:1.25rem;width:100%\">\n <section v-for=\"group in grouped\" :key=\"group.id\">\n <h4\n style=\"align-items:baseline;color:var(--m-color-text);display:flex;font-size:0.875rem;font-weight:600;gap:0.5rem;margin:0 0 0.65rem\"\n >\n <span>{{ group.labelZh }}</span>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem;font-weight:500\">\n {{ group.icons.length }}\n </span>\n </h4>\n <div\n style=\"display:grid;grid-template-columns:repeat(auto-fill,minmax(7.25rem,1fr));gap:0.75rem;width:100%\"\n >\n <button\n v-for=\"name in group.icons\"\n :key=\"name\"\n type=\"button\"\n :style=\"itemStyle(name)\"\n :title=\"`点击复制 ${name}`\"\n @click=\"copyName(name)\"\n >\n <MIcon :name=\"name\" size=\"large\" />\n <span\n style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.72rem;line-height:1.3;max-width:100%;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap\"\n >\n {{ copied === name ? '已复制' : name }}\n </span>\n </button>\n </div>\n </section>\n </div>\n\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onToastClose\" />\n </div>\n</template>",
8951
8951
  "locale": "zh-CN"
8952
8952
  },
8953
8953
  {
@@ -8983,7 +8983,7 @@
8983
8983
  "sectionId": "all-system-icons",
8984
8984
  "lang": "vue",
8985
8985
  "preview": true,
8986
- "code": "<script setup lang=\"ts\">\nimport type {ToastMessage} from 'morya-ui';\nimport { iconNames, MIcon, MInput, MToast } from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst query = ref('')\nconst copied = ref<string | null>(null)\nconst messages = ref<ToastMessage[]>([])\nlet toastSeq = 0\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\n\nconst filtered = computed(() => {\n const q = query.value.trim().toLowerCase()\n if (!q) return [...iconNames]\n return iconNames.filter((name) => name.toLowerCase().includes(q))\n})\n\nfunction itemStyle(name: string) {\n const active = copied.value === name\n return [\n 'align-items:center',\n 'background:var(--m-color-surface)',\n `border:1px solid ${active ? 'var(--m-color-primary)' : 'var(--m-color-border)'}`,\n 'border-radius:var(--m-radius-control, 3px)',\n `color:${active ? 'var(--m-color-primary)' : 'var(--m-color-text)'}`,\n 'cursor:pointer',\n 'display:flex',\n 'flex-direction:column',\n 'font:inherit',\n 'gap:0.65rem',\n 'justify-content:center',\n 'min-height:6.5rem',\n 'padding:0.85rem 0.5rem',\n 'width:100%',\n ].join(';')\n}\n\nasync function copyName(name: string) {\n try {\n await navigator.clipboard.writeText(name)\n } catch {\n const area = document.createElement('textarea')\n area.value = name\n document.body.appendChild(area)\n area.select()\n document.execCommand('copy')\n area.remove()\n }\n copied.value = name\n if (copiedTimer) clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => {\n if (copied.value === name) copied.value = null\n }, 1200)\n\n const id = `icon-copy-${++toastSeq}`\n messages.value = [\n ...messages.value,\n {\n id,\n severity: 'success',\n summary: 'Copied',\n detail: name,\n closable: true,\n },\n ]\n window.setTimeout(() => {\n messages.value = messages.value.filter((item) => item.id !== id)\n }, 1600)\n}\n\nfunction onToastClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"w-full\">\n <MInput\n v-model=\"query\"\n clearable\n fluid\n placeholder=\"Search icon names…\"\n class=\"max-w-xs mb-4\"\n >\n <template #prefix>\n <MIcon name=\"search\" size=\"sm\" />\n </template>\n </MInput>\n\n <p\n v-if=\"!filtered.length\"\n style=\"color: var(--m-color-text-muted); font-size: 0.875rem; margin: 0.5rem 0 0\"\n >\n No matching icons\n </p>\n\n <div\n v-else\n style=\"display:grid;grid-template-columns:repeat(auto-fill,minmax(7.25rem,1fr));gap:0.75rem;width:100%\"\n >\n <button\n v-for=\"name in filtered\"\n :key=\"name\"\n type=\"button\"\n :style=\"itemStyle(name)\"\n :title=\"`Click to copy ${name}`\"\n @click=\"copyName(name)\"\n >\n <MIcon :name=\"name\" size=\"large\" />\n <span\n style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.72rem;line-height:1.3;max-width:100%;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap\"\n >\n {{ copied === name ? 'Copied' : name }}\n </span>\n </button>\n </div>\n\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onToastClose\" />\n </div>\n</template>",
8986
+ "code": "<script setup lang=\"ts\">\nimport type { IconCategoryId, ToastMessage } from 'morya-ui'\nimport {\n getIconCategory,\n getIconCategoryGroups,\n iconCategoryMeta,\n iconNames,\n MIcon,\n MInput,\n MToast,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst query = ref('')\nconst category = ref<IconCategoryId | 'all'>('all')\nconst copied = ref<string | null>(null)\nconst messages = ref<ToastMessage[]>([])\nlet toastSeq = 0\nlet copiedTimer: ReturnType<typeof setTimeout> | undefined\n\nconst categoryOptions = computed(() => [\n { id: 'all' as const, label: 'All' },\n ...iconCategoryMeta.map((item) => ({ id: item.id, label: item.labelEn })),\n])\n\nconst filteredNames = computed(() => {\n const q = query.value.trim().toLowerCase()\n return iconNames.filter((name) => {\n if (q && !name.toLowerCase().includes(q)) return false\n if (category.value !== 'all') return getIconCategory(name) === category.value\n return true\n })\n})\n\nconst grouped = computed(() => getIconCategoryGroups(filteredNames.value))\n\nfunction chipStyle(id: IconCategoryId | 'all') {\n const active = category.value === id\n return [\n 'background:' + (active ? 'var(--m-color-primary-soft, color-mix(in srgb, var(--m-color-primary) 14%, transparent))' : 'var(--m-color-surface)'),\n 'border:1px solid ' + (active ? 'var(--m-color-primary)' : 'var(--m-color-border)'),\n 'border-radius:var(--m-radius-full, 999px)',\n 'color:' + (active ? 'var(--m-color-primary)' : 'var(--m-color-text)'),\n 'cursor:pointer',\n 'font:inherit',\n 'font-size:0.8125rem',\n 'line-height:1.2',\n 'padding:0.35rem 0.75rem',\n ].join(';')\n}\n\nfunction itemStyle(name: string) {\n const active = copied.value === name\n return [\n 'align-items:center',\n 'background:var(--m-color-surface)',\n `border:1px solid ${active ? 'var(--m-color-primary)' : 'var(--m-color-border)'}`,\n 'border-radius:var(--m-radius-control, 3px)',\n `color:${active ? 'var(--m-color-primary)' : 'var(--m-color-text)'}`,\n 'cursor:pointer',\n 'display:flex',\n 'flex-direction:column',\n 'font:inherit',\n 'gap:0.65rem',\n 'justify-content:center',\n 'min-height:6.5rem',\n 'padding:0.85rem 0.5rem',\n 'width:100%',\n ].join(';')\n}\n\nasync function copyName(name: string) {\n try {\n await navigator.clipboard.writeText(name)\n } catch {\n const area = document.createElement('textarea')\n area.value = name\n document.body.appendChild(area)\n area.select()\n document.execCommand('copy')\n area.remove()\n }\n copied.value = name\n if (copiedTimer) clearTimeout(copiedTimer)\n copiedTimer = setTimeout(() => {\n if (copied.value === name) copied.value = null\n }, 1200)\n\n const id = `icon-copy-${++toastSeq}`\n messages.value = [\n ...messages.value,\n {\n id,\n severity: 'success',\n summary: 'Copied',\n detail: name,\n closable: true,\n },\n ]\n window.setTimeout(() => {\n messages.value = messages.value.filter((item) => item.id !== id)\n }, 1600)\n}\n\nfunction onToastClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"w-full\">\n <MInput\n v-model=\"query\"\n clearable\n fluid\n placeholder=\"Search icon names…\"\n class=\"max-w-xs mb-3\"\n >\n <template #prefix>\n <MIcon name=\"search\" size=\"sm\" />\n </template>\n </MInput>\n\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;margin-bottom:1rem\">\n <button\n v-for=\"opt in categoryOptions\"\n :key=\"opt.id\"\n type=\"button\"\n :style=\"chipStyle(opt.id)\"\n @click=\"category = opt.id\"\n >\n {{ opt.label }}\n </button>\n </div>\n\n <p\n v-if=\"!grouped.length\"\n style=\"color: var(--m-color-text-muted); font-size: 0.875rem; margin: 0.5rem 0 0\"\n >\n No matching icons\n </p>\n\n <div v-else style=\"display:grid;gap:1.25rem;width:100%\">\n <section v-for=\"group in grouped\" :key=\"group.id\">\n <h4\n style=\"align-items:baseline;color:var(--m-color-text);display:flex;font-size:0.875rem;font-weight:600;gap:0.5rem;margin:0 0 0.65rem\"\n >\n <span>{{ group.labelEn }}</span>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem;font-weight:500\">\n {{ group.icons.length }}\n </span>\n </h4>\n <div\n style=\"display:grid;grid-template-columns:repeat(auto-fill,minmax(7.25rem,1fr));gap:0.75rem;width:100%\"\n >\n <button\n v-for=\"name in group.icons\"\n :key=\"name\"\n type=\"button\"\n :style=\"itemStyle(name)\"\n :title=\"`Click to copy ${name}`\"\n @click=\"copyName(name)\"\n >\n <MIcon :name=\"name\" size=\"large\" />\n <span\n style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.72rem;line-height:1.3;max-width:100%;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap\"\n >\n {{ copied === name ? 'Copied' : name }}\n </span>\n </button>\n </div>\n </section>\n </div>\n\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onToastClose\" />\n </div>\n</template>",
8987
8987
  "locale": "en-US"
8988
8988
  },
8989
8989
  {
@@ -9004,7 +9004,7 @@
9004
9004
  {
9005
9005
  "id": "overview",
9006
9006
  "title": "",
9007
- "body": "# Icon\n\n`MIcon` 只维护**组件库系统图标**(关闭、箭头、状态、操作等)。完整业务图标请用默认插槽接入 [Lucide](https://lucide.dev) 等库,避免把数百个 SVG 打进 `morya-ui`。"
9007
+ "body": "# Icon\n\n`MIcon` 维护**组件库系统图标**(关闭、箭头、状态、导航、业务常用等,含 Tabler outline)。完整海量图标请用默认插槽接入 [Lucide](https://lucide.dev) 等库。"
9008
9008
  },
9009
9009
  {
9010
9010
  "id": "引入",
@@ -9019,7 +9019,7 @@
9019
9019
  {
9020
9020
  "id": "全部系统图标",
9021
9021
  "title": "全部系统图标",
9022
- "body": "点击图标即可复制名称(如 `search`),用法:`<MIcon name=\"search\" />`。\n\n```vue preview src=\"./demos/AllSystemIcons.zh.vue\"\n```"
9022
+ "body": "点击图标即可复制名称(如 `search`),用法:`<MIcon name=\"search\" />`。可按分类筛选,或搜索名称。\n\n```vue preview src=\"./demos/AllSystemIcons.zh.vue\"\n```"
9023
9023
  },
9024
9024
  {
9025
9025
  "id": "自定义-lucide-推荐业务侧",
@@ -9039,7 +9039,7 @@
9039
9039
  {
9040
9040
  "id": "工具导出",
9041
9041
  "title": "工具导出",
9042
- "body": "| 导出 | 说明 |\n| --- | --- |\n| `iconNames` | 全部系统图标名数组。 |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | 注册表与类型守卫。 |"
9042
+ "body": "| 导出 | 说明 |\n| --- | --- |\n| `iconNames` | 全部系统图标名数组。 |\n| `iconCategoryMeta` / `getIconCategory` / `getIconCategoryGroups` | 图标分类元数据与分组。 |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | 注册表与类型守卫。 |"
9043
9043
  },
9044
9044
  {
9045
9045
  "id": "events",
@@ -9047,7 +9047,7 @@
9047
9047
  "body": "无自定义事件。"
9048
9048
  }
9049
9049
  ],
9050
- "markdown": "---\ntitle: Icon\ncategory: 01 / BASIC\ndescription: 系统线框图标注册表。业务图标用默认插槽接入 Lucide 等库。\n---\n\n# Icon\n\n`MIcon` 只维护**组件库系统图标**(关闭、箭头、状态、操作等)。完整业务图标请用默认插槽接入 [Lucide](https://lucide.dev) 等库,避免把数百个 SVG 打进 `morya-ui`。\n\n## 引入\n\n```ts\nimport { iconNames, MIcon } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## 全部系统图标\n\n点击图标即可复制名称(如 `search`),用法:`<MIcon name=\"search\" />`。\n\n```vue preview src=\"./demos/AllSystemIcons.zh.vue\"\n```\n\n## 自定义 / Lucide(推荐业务侧)\n\n系统图标不够时,不要往组件库堆 SVG,用默认插槽挂任意图标组件:\n\n```vue\n<script setup lang=\"ts\">\nimport { User } from 'lucide-vue-next'\nimport { MButton, MIcon, MIconField, MInput } from 'morya-ui'\n</script>\n\n<template>\n <MIcon label=\"用户\" size=\"md\">\n <User :size=\"16\" :stroke-width=\"1.8\" />\n </MIcon>\n\n <MIconField>\n <template #icon>\n <MIcon size=\"sm\">\n <User :size=\"14\" :stroke-width=\"1.8\" />\n </MIcon>\n </template>\n <MInput placeholder=\"搜索用户\" />\n </MIconField>\n\n <!-- Button 也可直接传组件,不必包 MIcon -->\n <MButton :icon=\"User\" label=\"资料\" />\n</template>\n```\n\n安装示例:`pnpm add lucide-vue-next`。线宽建议 `1.75`–`2`,与系统图标 `1.8` 接近。\n\n有默认插槽时**优先渲染插槽**,忽略 `name`。\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `name` | [IconName](/docs/types#IconName) | — | 系统图标名;插槽存在时可省略。 |\n| `label` | `string` | — | 可访问名称;省略时 `aria-hidden`。 |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | `'md'` | 尺寸;`sm`/`lg` 映射到 small/large。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Slots\n\n| 插槽 | 说明 |\n| --- | --- |\n| `default` | 自定义 SVG / 第三方图标组件。 |\n\n## 工具导出\n\n| 导出 | 说明 |\n| --- | --- |\n| `iconNames` | 全部系统图标名数组。 |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | 注册表与类型守卫。 |\n\n## Events\n\n无自定义事件。\n"
9050
+ "markdown": "---\ntitle: Icon\ncategory: 01 / BASIC\ndescription: 系统线框图标注册表。业务图标用默认插槽接入 Lucide 等库。\n---\n\n# Icon\n\n`MIcon` 维护**组件库系统图标**(关闭、箭头、状态、导航、业务常用等,含 Tabler outline)。完整海量图标请用默认插槽接入 [Lucide](https://lucide.dev) 等库。\n\n## 引入\n\n```ts\nimport { iconNames, MIcon } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## 全部系统图标\n\n点击图标即可复制名称(如 `search`),用法:`<MIcon name=\"search\" />`。可按分类筛选,或搜索名称。\n\n```vue preview src=\"./demos/AllSystemIcons.zh.vue\"\n```\n\n## 自定义 / Lucide(推荐业务侧)\n\n系统图标不够时,不要往组件库堆 SVG,用默认插槽挂任意图标组件:\n\n```vue\n<script setup lang=\"ts\">\nimport { User } from 'lucide-vue-next'\nimport { MButton, MIcon, MIconField, MInput } from 'morya-ui'\n</script>\n\n<template>\n <MIcon label=\"用户\" size=\"md\">\n <User :size=\"16\" :stroke-width=\"1.8\" />\n </MIcon>\n\n <MIconField>\n <template #icon>\n <MIcon size=\"sm\">\n <User :size=\"14\" :stroke-width=\"1.8\" />\n </MIcon>\n </template>\n <MInput placeholder=\"搜索用户\" />\n </MIconField>\n\n <!-- Button 也可直接传组件,不必包 MIcon -->\n <MButton :icon=\"User\" label=\"资料\" />\n</template>\n```\n\n安装示例:`pnpm add lucide-vue-next`。线宽建议 `1.75`–`2`,与系统图标 `1.8` 接近。\n\n有默认插槽时**优先渲染插槽**,忽略 `name`。\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `name` | [IconName](/docs/types#IconName) | — | 系统图标名;插槽存在时可省略。 |\n| `label` | `string` | — | 可访问名称;省略时 `aria-hidden`。 |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | `'md'` | 尺寸;`sm`/`lg` 映射到 small/large。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Slots\n\n| 插槽 | 说明 |\n| --- | --- |\n| `default` | 自定义 SVG / 第三方图标组件。 |\n\n## 工具导出\n\n| 导出 | 说明 |\n| --- | --- |\n| `iconNames` | 全部系统图标名数组。 |\n| `iconCategoryMeta` / `getIconCategory` / `getIconCategoryGroups` | 图标分类元数据与分组。 |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | 注册表与类型守卫。 |\n\n## Events\n\n无自定义事件。\n"
9051
9051
  },
9052
9052
  "en-US": {
9053
9053
  "title": "Icon",
@@ -9056,7 +9056,7 @@
9056
9056
  {
9057
9057
  "id": "overview",
9058
9058
  "title": "",
9059
- "body": "# Icon\n\n`MIcon` only maintains **component-library system icons** (close, arrows, status, actions, and so on). For full business icon sets, use the default slot with [Lucide](https://lucide.dev) or another library so hundreds of SVGs are not bundled into `morya-ui`."
9059
+ "body": "# Icon\n\n`MIcon` maintains **component-library system icons** (close, arrows, status, navigation, common business icons from Tabler outline). For large business icon sets, use the default slot with [Lucide](https://lucide.dev) or another library."
9060
9060
  },
9061
9061
  {
9062
9062
  "id": "import",
@@ -9071,7 +9071,7 @@
9071
9071
  {
9072
9072
  "id": "all-system-icons",
9073
9073
  "title": "All system icons",
9074
- "body": "Click an icon to copy its name (for example `search`). Usage: `<MIcon name=\"search\" />`.\n\n```vue preview src=\"./demos/AllSystemIcons.en.vue\"\n```"
9074
+ "body": "Click an icon to copy its name (for example `search`). Usage: `<MIcon name=\"search\" />`. Filter by category or search by name.\n\n```vue preview src=\"./demos/AllSystemIcons.en.vue\"\n```"
9075
9075
  },
9076
9076
  {
9077
9077
  "id": "custom-lucide-recommended-on-the-app-side",
@@ -9091,7 +9091,7 @@
9091
9091
  {
9092
9092
  "id": "utility-exports",
9093
9093
  "title": "Utility exports",
9094
- "body": "| Export | Description |\n| --- | --- |\n| `iconNames` | Array of all system icon names. |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | Registry and type guards. |"
9094
+ "body": "| Export | Description |\n| --- | --- |\n| `iconNames` | Array of all system icon names. |\n| `iconCategoryMeta` / `getIconCategory` / `getIconCategoryGroups` | Category metadata and grouping helpers. |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | Registry and type guards. |"
9095
9095
  },
9096
9096
  {
9097
9097
  "id": "events",
@@ -9099,7 +9099,7 @@
9099
9099
  "body": "No custom events."
9100
9100
  }
9101
9101
  ],
9102
- "markdown": "---\ntitle: Icon\ncategory: 01 / BASIC\ndescription: System outline icon registry. Use the default slot for business icons from Lucide and similar libraries.\n---\n\n# Icon\n\n`MIcon` only maintains **component-library system icons** (close, arrows, status, actions, and so on). For full business icon sets, use the default slot with [Lucide](https://lucide.dev) or another library so hundreds of SVGs are not bundled into `morya-ui`.\n\n## Import\n\n```ts\nimport { iconNames, MIcon } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## All system icons\n\nClick an icon to copy its name (for example `search`). Usage: `<MIcon name=\"search\" />`.\n\n```vue preview src=\"./demos/AllSystemIcons.en.vue\"\n```\n\n## Custom / Lucide (recommended on the app side)\n\nWhen system icons are not enough, do not pile SVGs into the component library. Mount any icon component through the default slot:\n\n```vue\n<script setup lang=\"ts\">\nimport { User } from 'lucide-vue-next'\nimport { MButton, MIcon, MIconField, MInput } from 'morya-ui'\n</script>\n\n<template>\n <MIcon label=\"User\" size=\"md\">\n <User :size=\"16\" :stroke-width=\"1.8\" />\n </MIcon>\n\n <MIconField>\n <template #icon>\n <MIcon size=\"sm\">\n <User :size=\"14\" :stroke-width=\"1.8\" />\n </MIcon>\n </template>\n <MInput placeholder=\"Search users\" />\n </MIconField>\n\n <!-- Button can also take a component directly without wrapping MIcon -->\n <MButton :icon=\"User\" label=\"Profile\" />\n</template>\n```\n\nInstall example: `pnpm add lucide-vue-next`. Prefer stroke width `1.75`–`2`, close to the system icon width of `1.8`.\n\nWhen the default slot is present, it is **rendered first** and `name` is ignored.\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `name` | [IconName](/docs/types#IconName) | — | System icon name; optional when a slot is provided. |\n| `label` | `string` | — | Accessible name; omitted icons use `aria-hidden`. |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | `'md'` | Size; `sm`/`lg` map to small/large. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Custom SVG / third-party icon component. |\n\n## Utility exports\n\n| Export | Description |\n| --- | --- |\n| `iconNames` | Array of all system icon names. |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | Registry and type guards. |\n\n## Events\n\nNo custom events.\n"
9102
+ "markdown": "---\ntitle: Icon\ncategory: 01 / BASIC\ndescription: System outline icon registry. Use the default slot for business icons from Lucide and similar libraries.\n---\n\n# Icon\n\n`MIcon` maintains **component-library system icons** (close, arrows, status, navigation, common business icons from Tabler outline). For large business icon sets, use the default slot with [Lucide](https://lucide.dev) or another library.\n\n## Import\n\n```ts\nimport { iconNames, MIcon } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## All system icons\n\nClick an icon to copy its name (for example `search`). Usage: `<MIcon name=\"search\" />`. Filter by category or search by name.\n\n```vue preview src=\"./demos/AllSystemIcons.en.vue\"\n```\n\n## Custom / Lucide (recommended on the app side)\n\nWhen system icons are not enough, do not pile SVGs into the component library. Mount any icon component through the default slot:\n\n```vue\n<script setup lang=\"ts\">\nimport { User } from 'lucide-vue-next'\nimport { MButton, MIcon, MIconField, MInput } from 'morya-ui'\n</script>\n\n<template>\n <MIcon label=\"User\" size=\"md\">\n <User :size=\"16\" :stroke-width=\"1.8\" />\n </MIcon>\n\n <MIconField>\n <template #icon>\n <MIcon size=\"sm\">\n <User :size=\"14\" :stroke-width=\"1.8\" />\n </MIcon>\n </template>\n <MInput placeholder=\"Search users\" />\n </MIconField>\n\n <!-- Button can also take a component directly without wrapping MIcon -->\n <MButton :icon=\"User\" label=\"Profile\" />\n</template>\n```\n\nInstall example: `pnpm add lucide-vue-next`. Prefer stroke width `1.75`–`2`, close to the system icon width of `1.8`.\n\nWhen the default slot is present, it is **rendered first** and `name` is ignored.\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `name` | [IconName](/docs/types#IconName) | — | System icon name; optional when a slot is provided. |\n| `label` | `string` | — | Accessible name; omitted icons use `aria-hidden`. |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | `'md'` | Size; `sm`/`lg` map to small/large. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Custom SVG / third-party icon component. |\n\n## Utility exports\n\n| Export | Description |\n| --- | --- |\n| `iconNames` | Array of all system icon names. |\n| `iconCategoryMeta` / `getIconCategory` / `getIconCategoryGroups` | Category metadata and grouping helpers. |\n| `iconRegistry` / `getIconDefinition` / `isIconName` | Registry and type guards. |\n\n## Events\n\nNo custom events.\n"
9103
9103
  }
9104
9104
  }
9105
9105
  },
@@ -11905,7 +11905,7 @@
11905
11905
  "sectionId": "基础用法",
11906
11906
  "lang": "vue",
11907
11907
  "preview": true,
11908
- "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutFooter, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Header\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem;display:flex;align-items:center;justify-content:center\">\n Content(自动撑开)\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.75rem 1rem\">\n Footer\n </MLayoutFooter>\n </MLayout>\n</template>",
11908
+ "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutFooter, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Header\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem;display:flex;align-items:center;justify-content:center\">\n Content(自动撑开)\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.75rem 1rem\">\n Footer\n </MLayoutFooter>\n </MLayout>\n</template>",
11909
11909
  "locale": "zh-CN"
11910
11910
  },
11911
11911
  {
@@ -11914,7 +11914,7 @@
11914
11914
  "sectionId": "with-sider",
11915
11915
  "lang": "vue",
11916
11916
  "preview": true,
11917
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem;display:flex;align-items:center;justify-content:space-between\">\n <strong>App</strong>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem\">{{ collapsed ? '已折叠' : '已展开' }}</span>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n :width=\"160\"\n content-style=\"padding:0.75rem\"\n >\n <div style=\"display:grid;gap:0.5rem\">\n <div>概览</div>\n <div>项目</div>\n <div>设置</div>\n </div>\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n 主内容区会横向、纵向同时撑满。\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11917
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('overview')\nconst model = [\n { key: 'overview', label: '概览', icon: 'layout-dashboard' },\n { key: 'projects', label: '项目', icon: 'folder' },\n { key: 'settings', label: '设置', icon: 'settings' },\n]\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem;display:flex;align-items:center;justify-content:space-between\">\n <strong>App</strong>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem\">{{ collapsed ? '已折叠' : '已展开' }}</span>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :width=\"168\"\n :collapsed-width=\"64\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n />\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem\">\n 当前选中:{{ selectedKey }}\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11918
11918
  "locale": "zh-CN"
11919
11919
  },
11920
11920
  {
@@ -11923,7 +11923,7 @@
11923
11923
  "sectionId": "right-sider",
11924
11924
  "lang": "vue",
11925
11925
  "preview": true,
11926
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Inspector\n </MLayoutHeader>\n <MLayout has-sider sider-placement=\"right\">\n <MLayoutSider bordered :width=\"140\" content-style=\"padding:0.75rem\">\n 属性面板\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n 画布 / 主区域\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11926
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Inspector\n </MLayoutHeader>\n <MLayout has-sider sider-placement=\"right\">\n <MLayoutSider bordered :width=\"140\" style=\"padding:0.75rem\">\n 属性面板\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem\">\n 画布 / 主区域\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11927
11927
  "locale": "zh-CN"
11928
11928
  },
11929
11929
  {
@@ -11932,7 +11932,7 @@
11932
11932
  "sectionId": "full-shell",
11933
11933
  "lang": "vue",
11934
11934
  "preview": true,
11935
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n MTag,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\n</script>\n\n<template>\n <MLayout style=\"height:18rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader\n bordered\n inverted\n style=\"padding:0.65rem 1rem;display:flex;align-items:center;gap:0.75rem\"\n >\n <strong>Morya UI</strong>\n <MTag value=\"Studio\" />\n <span style=\"flex:1\" />\n <MButton size=\"small\" label=\"发布\" />\n </MLayoutHeader>\n\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n inverted\n show-trigger=\"bar\"\n :width=\"168\"\n :collapsed-width=\"56\"\n content-style=\"padding:0.75rem\"\n >\n <div style=\"display:grid;gap:0.65rem;font-size:0.875rem\">\n <div>仪表盘</div>\n <div>数据源</div>\n <div>组件</div>\n <div>主题</div>\n </div>\n </MLayoutSider>\n\n <MLayout>\n <MLayoutContent embedded content-style=\"padding:1rem;display:grid;gap:0.75rem;align-content:start\">\n <strong>工作区</strong>\n <p style=\"margin:0;color:var(--m-color-text-muted);font-size:0.875rem\">\n Content 已撑满 Header 与 Footer 之间的空间;侧栏折叠不影响主区高度。\n </p>\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.5rem 1rem;color:var(--m-color-text-muted);font-size:0.75rem\">\n Ready · local\n </MLayoutFooter>\n </MLayout>\n </MLayout>\n </MLayout>\n</template>",
11935
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n MTag,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: '仪表盘', icon: 'layout-dashboard' },\n { key: 'datasources', label: '数据源', icon: 'database' },\n { key: 'widgets', label: '组件', icon: 'components' },\n { key: 'theme', label: '主题', icon: 'palette' },\n]\n</script>\n\n<template>\n <MLayout style=\"height:18rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader\n bordered\n inverted\n style=\"padding:0.65rem 1rem;display:flex;align-items:center;gap:0.75rem\"\n >\n <strong>Morya UI</strong>\n <MTag value=\"Studio\" />\n <span style=\"flex:1\" />\n <MButton size=\"small\" label=\"发布\" />\n </MLayoutHeader>\n\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n inverted\n show-trigger=\"bar\"\n collapse-mode=\"width\"\n :width=\"168\"\n :collapsed-width=\"56\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"56\"\n inverted\n />\n </MLayoutSider>\n\n <MLayout>\n <MLayoutContent embedded style=\"padding:1rem;display:grid;gap:0.75rem;align-content:start\">\n <strong>工作区</strong>\n <p style=\"margin:0;color:var(--m-color-text-muted);font-size:0.875rem\">\n 当前选中:{{ selectedKey }}。Content 已撑满 Header 与 Footer 之间的空间;侧栏折叠不影响主区高度。\n </p>\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.5rem 1rem;color:var(--m-color-text-muted);font-size:0.75rem\">\n Ready · local\n </MLayoutFooter>\n </MLayout>\n </MLayout>\n </MLayout>\n</template>",
11936
11936
  "locale": "zh-CN"
11937
11937
  },
11938
11938
  {
@@ -11941,7 +11941,7 @@
11941
11941
  "sectionId": "embedded-content",
11942
11942
  "lang": "vue",
11943
11943
  "preview": true,
11944
- "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:12rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Settings\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n 嵌套表单 / 列表放在这里。\n </MLayoutContent>\n </MLayout>\n</template>",
11944
+ "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:12rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Settings\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem\">\n 嵌套表单 / 列表放在这里。\n </MLayoutContent>\n </MLayout>\n</template>",
11945
11945
  "locale": "zh-CN"
11946
11946
  },
11947
11947
  {
@@ -11950,7 +11950,7 @@
11950
11950
  "sectionId": "scrollable-content",
11951
11951
  "lang": "vue",
11952
11952
  "preview": true,
11953
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Scroll demo\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider bordered :width=\"120\" content-style=\"padding:0.75rem\">\n 固定侧栏\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n <div style=\"display:grid;gap:0.5rem\">\n <div v-for=\"n in 20\" :key=\"n\">\n 行 {{ n }} — 向下滚动\n </div>\n </div>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11953
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Scroll demo\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider bordered :width=\"120\" style=\"padding:0.75rem\">\n 固定侧栏\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem;overflow:auto;min-height:0\">\n <div style=\"display:grid;gap:0.5rem\">\n <div v-for=\"n in 20\" :key=\"n\">\n 行 {{ n }} — 向下滚动\n </div>\n </div>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11954
11954
  "locale": "zh-CN"
11955
11955
  },
11956
11956
  {
@@ -11959,7 +11959,7 @@
11959
11959
  "sectionId": "absolute-shell",
11960
11960
  "lang": "vue",
11961
11961
  "preview": true,
11962
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <div style=\"position:relative;height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayout position=\"absolute\" has-sider>\n <MLayoutSider bordered :width=\"120\" content-style=\"padding:0.75rem\">\n Nav\n </MLayoutSider>\n <MLayout>\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Absolute layout\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n 填满相对定位容器\n </MLayoutContent>\n </MLayout>\n </MLayout>\n </div>\n</template>",
11962
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <div style=\"position:relative;height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayout position=\"absolute\" has-sider>\n <MLayoutSider bordered :width=\"120\" style=\"padding:0.75rem\">\n Nav\n </MLayoutSider>\n <MLayout>\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Absolute layout\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem\">\n 填满相对定位容器\n </MLayoutContent>\n </MLayout>\n </MLayout>\n </div>\n</template>",
11963
11963
  "locale": "zh-CN"
11964
11964
  },
11965
11965
  {
@@ -11977,7 +11977,7 @@
11977
11977
  "sectionId": "basic",
11978
11978
  "lang": "vue",
11979
11979
  "preview": true,
11980
- "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutFooter, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Header\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem;display:flex;align-items:center;justify-content:center\">\n Content (fills remaining space)\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.75rem 1rem\">\n Footer\n </MLayoutFooter>\n </MLayout>\n</template>",
11980
+ "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutFooter, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Header\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem;display:flex;align-items:center;justify-content:center\">\n Content (fills remaining space)\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.75rem 1rem\">\n Footer\n </MLayoutFooter>\n </MLayout>\n</template>",
11981
11981
  "locale": "en-US"
11982
11982
  },
11983
11983
  {
@@ -11986,7 +11986,7 @@
11986
11986
  "sectionId": "with-sider",
11987
11987
  "lang": "vue",
11988
11988
  "preview": true,
11989
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem;display:flex;align-items:center;justify-content:space-between\">\n <strong>App</strong>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem\">{{ collapsed ? 'Collapsed' : 'Expanded' }}</span>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n :width=\"160\"\n content-style=\"padding:0.75rem\"\n >\n <div style=\"display:grid;gap:0.5rem\">\n <div>Overview</div>\n <div>Projects</div>\n <div>Settings</div>\n </div>\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n Main area stretches both horizontally and vertically.\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11989
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('overview')\nconst model = [\n { key: 'overview', label: 'Overview', icon: 'layout-dashboard' },\n { key: 'projects', label: 'Projects', icon: 'folder' },\n { key: 'settings', label: 'Settings', icon: 'settings' },\n]\n</script>\n\n<template>\n <MLayout style=\"height:16rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem;display:flex;align-items:center;justify-content:space-between\">\n <strong>App</strong>\n <span style=\"color:var(--m-color-text-muted);font-size:0.75rem\">{{ collapsed ? 'Collapsed' : 'Expanded' }}</span>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :width=\"168\"\n :collapsed-width=\"64\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n />\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem\">\n Selected: {{ selectedKey }}\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11990
11990
  "locale": "en-US"
11991
11991
  },
11992
11992
  {
@@ -11995,7 +11995,7 @@
11995
11995
  "sectionId": "right-sider",
11996
11996
  "lang": "vue",
11997
11997
  "preview": true,
11998
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Inspector\n </MLayoutHeader>\n <MLayout has-sider sider-placement=\"right\">\n <MLayoutSider bordered :width=\"140\" content-style=\"padding:0.75rem\">\n Props panel\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n Canvas / main\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11998
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Inspector\n </MLayoutHeader>\n <MLayout has-sider sider-placement=\"right\">\n <MLayoutSider bordered :width=\"140\" style=\"padding:0.75rem\">\n Props panel\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem\">\n Canvas / main\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
11999
11999
  "locale": "en-US"
12000
12000
  },
12001
12001
  {
@@ -12004,7 +12004,7 @@
12004
12004
  "sectionId": "full-shell",
12005
12005
  "lang": "vue",
12006
12006
  "preview": true,
12007
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n MTag,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\n</script>\n\n<template>\n <MLayout style=\"height:18rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader\n bordered\n inverted\n style=\"padding:0.65rem 1rem;display:flex;align-items:center;gap:0.75rem\"\n >\n <strong>Morya UI</strong>\n <MTag value=\"Studio\" />\n <span style=\"flex:1\" />\n <MButton size=\"small\" label=\"Publish\" />\n </MLayoutHeader>\n\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n inverted\n show-trigger=\"bar\"\n :width=\"168\"\n :collapsed-width=\"56\"\n content-style=\"padding:0.75rem\"\n >\n <div style=\"display:grid;gap:0.65rem;font-size:0.875rem\">\n <div>Dashboard</div>\n <div>Datasources</div>\n <div>Widgets</div>\n <div>Theme</div>\n </div>\n </MLayoutSider>\n\n <MLayout>\n <MLayoutContent embedded content-style=\"padding:1rem;display:grid;gap:0.75rem;align-content:start\">\n <strong>Workspace</strong>\n <p style=\"margin:0;color:var(--m-color-text-muted);font-size:0.875rem\">\n Content fills the space between Header and Footer; collapsing the sider keeps the height.\n </p>\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.5rem 1rem;color:var(--m-color-text-muted);font-size:0.75rem\">\n Ready · local\n </MLayoutFooter>\n </MLayout>\n </MLayout>\n </MLayout>\n</template>",
12007
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n MTag,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: 'Dashboard', icon: 'layout-dashboard' },\n { key: 'datasources', label: 'Datasources', icon: 'database' },\n { key: 'widgets', label: 'Widgets', icon: 'components' },\n { key: 'theme', label: 'Theme', icon: 'palette' },\n]\n</script>\n\n<template>\n <MLayout style=\"height:18rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader\n bordered\n inverted\n style=\"padding:0.65rem 1rem;display:flex;align-items:center;gap:0.75rem\"\n >\n <strong>Morya UI</strong>\n <MTag value=\"Studio\" />\n <span style=\"flex:1\" />\n <MButton size=\"small\" label=\"Publish\" />\n </MLayoutHeader>\n\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n inverted\n show-trigger=\"bar\"\n collapse-mode=\"width\"\n :width=\"168\"\n :collapsed-width=\"56\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"56\"\n inverted\n />\n </MLayoutSider>\n\n <MLayout>\n <MLayoutContent embedded style=\"padding:1rem;display:grid;gap:0.75rem;align-content:start\">\n <strong>Workspace</strong>\n <p style=\"margin:0;color:var(--m-color-text-muted);font-size:0.875rem\">\n Selected: {{ selectedKey }}. Content fills the space between Header and Footer; collapsing the sider keeps the height.\n </p>\n </MLayoutContent>\n <MLayoutFooter bordered style=\"padding:0.5rem 1rem;color:var(--m-color-text-muted);font-size:0.75rem\">\n Ready · local\n </MLayoutFooter>\n </MLayout>\n </MLayout>\n </MLayout>\n</template>",
12008
12008
  "locale": "en-US"
12009
12009
  },
12010
12010
  {
@@ -12013,7 +12013,7 @@
12013
12013
  "sectionId": "embedded-content",
12014
12014
  "lang": "vue",
12015
12015
  "preview": true,
12016
- "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:12rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Settings\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n Nested forms / lists go here.\n </MLayoutContent>\n </MLayout>\n</template>",
12016
+ "code": "<script setup lang=\"ts\">\nimport { MLayout, MLayoutContent, MLayoutHeader } from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:12rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Settings\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem\">\n Nested forms / lists go here.\n </MLayoutContent>\n </MLayout>\n</template>",
12017
12017
  "locale": "en-US"
12018
12018
  },
12019
12019
  {
@@ -12022,7 +12022,7 @@
12022
12022
  "sectionId": "scrollable-content",
12023
12023
  "lang": "vue",
12024
12024
  "preview": true,
12025
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Scroll demo\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider bordered :width=\"120\" content-style=\"padding:0.75rem\">\n Fixed sider\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n <div style=\"display:grid;gap:0.5rem\">\n <div v-for=\"n in 20\" :key=\"n\">\n Row {{ n }} — scroll down\n </div>\n </div>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
12025
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <MLayout style=\"height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Scroll demo\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider bordered :width=\"120\" style=\"padding:0.75rem\">\n Fixed sider\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding:1rem;overflow:auto;min-height:0\">\n <div style=\"display:grid;gap:0.5rem\">\n <div v-for=\"n in 20\" :key=\"n\">\n Row {{ n }} — scroll down\n </div>\n </div>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
12026
12026
  "locale": "en-US"
12027
12027
  },
12028
12028
  {
@@ -12031,7 +12031,7 @@
12031
12031
  "sectionId": "absolute-shell",
12032
12032
  "lang": "vue",
12033
12033
  "preview": true,
12034
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <div style=\"position:relative;height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayout position=\"absolute\" has-sider>\n <MLayoutSider bordered :width=\"120\" content-style=\"padding:0.75rem\">\n Nav\n </MLayoutSider>\n <MLayout>\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Absolute layout\n </MLayoutHeader>\n <MLayoutContent embedded content-style=\"padding:1rem\">\n Fills the relative container\n </MLayoutContent>\n </MLayout>\n </MLayout>\n </div>\n</template>",
12034
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n</script>\n\n<template>\n <div style=\"position:relative;height:14rem;border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden\">\n <MLayout position=\"absolute\" has-sider>\n <MLayoutSider bordered :width=\"120\" style=\"padding:0.75rem\">\n Nav\n </MLayoutSider>\n <MLayout>\n <MLayoutHeader bordered style=\"padding:0.75rem 1rem\">\n Absolute layout\n </MLayoutHeader>\n <MLayoutContent embedded style=\"padding:1rem\">\n Fills the relative container\n </MLayoutContent>\n </MLayout>\n </MLayout>\n </div>\n</template>",
12035
12035
  "locale": "en-US"
12036
12036
  }
12037
12037
  ],
@@ -12058,7 +12058,7 @@
12058
12058
  {
12059
12059
  "id": "with-sider",
12060
12060
  "title": "With Sider",
12061
- "body": "顶栏 + 左侧栏 + 主内容。内层 `has-sider` 的 Layout 会吃掉 Header 以下的全部高度。\n\n```vue preview src=\"./demos/WithSider.zh.vue\"\n```"
12061
+ "body": "顶栏 + 左侧栏 + 主内容。侧栏内嵌 `MMenu`,并通过 `v-model:collapsed` 与菜单折叠联动。内层 `has-sider` 的 Layout 会吃掉 Header 以下的全部高度。\n\n```vue preview src=\"./demos/WithSider.zh.vue\"\n```"
12062
12062
  },
12063
12063
  {
12064
12064
  "id": "right-sider",
@@ -12068,7 +12068,7 @@
12068
12068
  {
12069
12069
  "id": "full-shell",
12070
12070
  "title": "Full Shell",
12071
- "body": "完整后台骨架:顶栏 + 侧栏 + 内容 + 底栏。\n\n```vue preview src=\"./demos/FullShell.zh.vue\"\n```"
12071
+ "body": "完整后台骨架:顶栏 + 反色侧栏(`MMenu` `inverted`)+ 内容 + 底栏。\n\n```vue preview src=\"./demos/FullShell.zh.vue\"\n```"
12072
12072
  },
12073
12073
  {
12074
12074
  "id": "embedded-content",
@@ -12078,7 +12078,7 @@
12078
12078
  {
12079
12079
  "id": "scrollable-content",
12080
12080
  "title": "Scrollable Content",
12081
- "body": "内容超出时仅 Content 区域滚动,Header / Sider 保持固定。`MLayout` / `MLayoutContent` / `MLayoutSider` 通过内置 `MScrollbar` 提供统一滚动条。\n\n```vue preview src=\"./demos/ScrollableContent.zh.vue\"\n```"
12081
+ "body": "内容超出时,可在 `MLayoutContent` 上自行设置 `overflow: auto`(或包一层 `MScrollbar`);Header / Sider 保持固定。`MLayout` 根容器仍内置 `MScrollbar`;`MLayoutContent` / `MLayoutSider` 为单层壳。\n\n```vue preview src=\"./demos/ScrollableContent.zh.vue\"\n```"
12082
12082
  },
12083
12083
  {
12084
12084
  "id": "absolute-shell",
@@ -12093,17 +12093,17 @@
12093
12093
  {
12094
12094
  "id": "layoutsider-props",
12095
12095
  "title": "LayoutSider Props",
12096
- "body": "| 参数 | 类型 | 默认值 | 说明 |\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。 |"
12096
+ "body": "| 参数 | 类型 | 默认值 | 说明 |\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| `padding` | `number \\| string` | — | 可选内边距;无默认值。 |\n| `radius` | `number \\| string` | — | 圆角。 |"
12097
12097
  },
12098
12098
  {
12099
12099
  "id": "events",
12100
12100
  "title": "Events",
12101
- "body": "| 事件 | 说明 |\n| --- | --- |\n| `scroll` | 滚动容器滚动时触发。 |\n| `after-enter` | 侧栏展开动画结束。 |\n| `after-leave` | 侧栏收起动画结束。 |\n| `collapse` | 侧栏开始收起。 |\n| `expand` | 侧栏开始展开。 |\n| `update:collapsed` | 折叠状态 v-model。 |"
12101
+ "body": "| 事件 | 说明 |\n| --- | --- |\n| `scroll` | `MLayout` 滚动容器滚动时触发。 |\n| `after-enter` | 侧栏展开动画结束。 |\n| `after-leave` | 侧栏收起动画结束。 |\n| `collapse` | 侧栏开始收起。 |\n| `expand` | 侧栏开始展开。 |\n| `update:collapsed` | 折叠状态 v-model。 |"
12102
12102
  },
12103
12103
  {
12104
12104
  "id": "expose",
12105
12105
  "title": "Expose",
12106
- "body": "`MLayout` / `MLayoutContent` / `MLayoutSider` 均暴露 `scrollTo(...)`。"
12106
+ "body": "`MLayout` 暴露 `scrollTo(...)`。"
12107
12107
  },
12108
12108
  {
12109
12109
  "id": "components",
@@ -12116,7 +12116,7 @@
12116
12116
  "body": "| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 布局区域。 |"
12117
12117
  }
12118
12118
  ],
12119
- "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"
12119
+ "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顶栏 + 左侧栏 + 主内容。侧栏内嵌 `MMenu`,并通过 `v-model:collapsed` 与菜单折叠联动。内层 `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完整后台骨架:顶栏 + 反色侧栏(`MMenu` `inverted`)+ 内容 + 底栏。\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内容超出时,可在 `MLayoutContent` 上自行设置 `overflow: auto`(或包一层 `MScrollbar`);Header / Sider 保持固定。`MLayout` 根容器仍内置 `MScrollbar`;`MLayoutContent` / `MLayoutSider` 为单层壳。\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| `padding` | `number \\| string` | — | 可选内边距;无默认值。 |\n| `radius` | `number \\| string` | — | 圆角。 |\n\n## Events\n\n| 事件 | 说明 |\n| --- | --- |\n| `scroll` | `MLayout` 滚动容器滚动时触发。 |\n| `after-enter` | 侧栏展开动画结束。 |\n| `after-leave` | 侧栏收起动画结束。 |\n| `collapse` | 侧栏开始收起。 |\n| `expand` | 侧栏开始展开。 |\n| `update:collapsed` | 折叠状态 v-model。 |\n\n## Expose\n\n`MLayout` 暴露 `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"
12120
12120
  },
12121
12121
  "en-US": {
12122
12122
  "title": "Layout",
@@ -12140,7 +12140,7 @@
12140
12140
  {
12141
12141
  "id": "with-sider",
12142
12142
  "title": "With Sider",
12143
- "body": "Header + left sider + main. The inner `has-sider` layout consumes all height below the header.\n\n```vue preview src=\"./demos/WithSider.en.vue\"\n```"
12143
+ "body": "Header + left sider + main. The sider hosts `MMenu`, bound to `v-model:collapsed`. The inner `has-sider` layout consumes all height below the header.\n\n```vue preview src=\"./demos/WithSider.en.vue\"\n```"
12144
12144
  },
12145
12145
  {
12146
12146
  "id": "right-sider",
@@ -12150,7 +12150,7 @@
12150
12150
  {
12151
12151
  "id": "full-shell",
12152
12152
  "title": "Full Shell",
12153
- "body": "Admin-style shell: header + sider + content + footer.\n\n```vue preview src=\"./demos/FullShell.en.vue\"\n```"
12153
+ "body": "Admin-style shell: header + inverted sider (`MMenu` `inverted`) + content + footer.\n\n```vue preview src=\"./demos/FullShell.en.vue\"\n```"
12154
12154
  },
12155
12155
  {
12156
12156
  "id": "embedded-content",
@@ -12160,7 +12160,7 @@
12160
12160
  {
12161
12161
  "id": "scrollable-content",
12162
12162
  "title": "Scrollable Content",
12163
- "body": "Only the content pane scrolls; header and sider stay fixed. `MLayout`, `MLayoutContent`, and `MLayoutSider` use built-in `MScrollbar`.\n\n```vue preview src=\"./demos/ScrollableContent.en.vue\"\n```"
12163
+ "body": "When content overflows, set `overflow: auto` on `MLayoutContent` (or wrap with `MScrollbar`); header and sider stay fixed. Root `MLayout` still has built-in `MScrollbar`; `MLayoutContent` / `MLayoutSider` are single-element shells.\n\n```vue preview src=\"./demos/ScrollableContent.en.vue\"\n```"
12164
12164
  },
12165
12165
  {
12166
12166
  "id": "absolute-shell",
@@ -12175,17 +12175,17 @@
12175
12175
  {
12176
12176
  "id": "layoutsider-props",
12177
12177
  "title": "LayoutSider Props",
12178
- "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `width` | `number \\| string` | `272` | Expanded width (always set as `width`). |\n| `collapsedWidth` | `number` | `48` | Collapsed `max-width`. |\n| `collapsed` | `boolean` | — | Collapsed state (`v-model:collapsed`). |\n| `defaultCollapsed` | `boolean` | `false` | Uncontrolled initial collapsed state. |\n| `showTrigger` | `boolean \\| 'bar' \\| 'arrow-circle' \\| 'arrow'` | `false` | Collapse trigger; `arrow` aliases `arrow-circle`. |\n| `collapseMode` | `'width' \\| 'transform'` | `'transform'` | `transform` clips content; `width` shrinks with sider. |\n| `showCollapsedContent` | `boolean` | `true` | Keep sider content visible while collapsed. |\n| `bordered` / `inverted` | `boolean` | `false` | Border / inverted colors. |\n| `triggerClass` / `triggerStyle` | — | — | Expanded trigger styles. |\n| `collapsedTriggerClass` / `collapsedTriggerStyle` | — | — | Collapsed trigger styles. |\n| `contentClass` / `contentStyle` | — | | Scroll container class / style. |"
12178
+ "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `width` | `number \\| string` | `272` | Expanded width (always set as `width`). |\n| `collapsedWidth` | `number` | `48` | Collapsed `max-width`. |\n| `collapsed` | `boolean` | — | Collapsed state (`v-model:collapsed`). |\n| `defaultCollapsed` | `boolean` | `false` | Uncontrolled initial collapsed state. |\n| `showTrigger` | `boolean \\| 'bar' \\| 'arrow-circle' \\| 'arrow'` | `false` | Collapse trigger; `arrow` aliases `arrow-circle`. |\n| `collapseMode` | `'width' \\| 'transform'` | `'transform'` | `transform` clips content; `width` shrinks with sider. |\n| `showCollapsedContent` | `boolean` | `true` | Keep sider content visible while collapsed. |\n| `bordered` / `inverted` | `boolean` | `false` | Border / inverted colors. |\n| `triggerClass` / `triggerStyle` | — | — | Expanded trigger styles. |\n| `collapsedTriggerClass` / `collapsedTriggerStyle` | — | — | Collapsed trigger styles. |\n| `padding` | `number \\| string` | — | Optional padding; no default. |\n| `radius` | `number \\| string` | — | Border radius. |"
12179
12179
  },
12180
12180
  {
12181
12181
  "id": "events",
12182
12182
  "title": "Events",
12183
- "body": "| Event | Description |\n| --- | --- |\n| `scroll` | Fired when the scroll container scrolls. |"
12183
+ "body": "| Event | Description |\n| --- | --- |\n| `scroll` | Fired when the `MLayout` scroll container scrolls. |\n| `after-enter` | Fired when the sider expand transition ends. |\n| `after-leave` | Fired when the sider collapse transition ends. |\n| `collapse` | Fired when the sider starts collapsing. |\n| `expand` | Fired when the sider starts expanding. |\n| `update:collapsed` | Collapsed state v-model. |"
12184
12184
  },
12185
12185
  {
12186
12186
  "id": "expose",
12187
12187
  "title": "Expose",
12188
- "body": "`MLayout` / `MLayoutContent` / `MLayoutSider` expose `scrollTo(...)`."
12188
+ "body": "`MLayout` exposes `scrollTo(...)`."
12189
12189
  },
12190
12190
  {
12191
12191
  "id": "components",
@@ -12198,7 +12198,7 @@
12198
12198
  "body": "| Slot | Description |\n| --- | --- |\n| `default` | Layout regions. |"
12199
12199
  }
12200
12200
  ],
12201
- "markdown": "---\ntitle: Layout\ncategory: 06 / LAYOUT\ndescription: Page layout shell with Header / Sider / Content / Footer.\n---\n\n# Layout\n\nPage-level layout shell. Set `has-sider` on the `MLayout` that hosts a sider. Give the root layout a fixed `height` (or `min-height`) so `MLayoutContent` can fill the remaining space.\n\n## Import\n\n```ts\nimport {\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n```\n\n## Basic\n\nHeader / Content / Footer. Content fills the leftover height.\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## With Sider\n\nHeader + left sider + main. The inner `has-sider` layout consumes all height below the header.\n\n```vue preview src=\"./demos/WithSider.en.vue\"\n```\n\n## Right Sider\n\n```vue preview src=\"./demos/RightSider.en.vue\"\n```\n\n## Full Shell\n\nAdmin-style shell: header + sider + content + footer.\n\n```vue preview src=\"./demos/FullShell.en.vue\"\n```\n\n## Embedded Content\n\n`embedded` softens the content background so it separates from header / sider.\n\n```vue preview src=\"./demos/EmbeddedContent.en.vue\"\n```\n\n## Scrollable Content\n\nOnly the content pane scrolls; header and sider stay fixed. `MLayout`, `MLayoutContent`, and `MLayoutSider` use built-in `MScrollbar`.\n\n```vue preview src=\"./demos/ScrollableContent.en.vue\"\n```\n\n## Absolute Shell\n\nRoot `position=\"absolute\"` fills a relatively positioned parent with an explicit height.\n\n```vue preview src=\"./demos/AbsoluteShell.en.vue\"\n```\n\n## Layout Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `hasSider` | `boolean` | `false` | Horizontal layout for `MLayoutSider`. |\n| `siderPlacement` | `'left' \\| 'right'` | `'left'` | Sider side. |\n| `embedded` | `boolean` | `false` | Soft background for nested content. |\n| `position` | `'static' \\| 'absolute'` | `'static'` | Positioning mode. |\n| `contentClass` / `contentStyle` | — | — | Scroll container class / style. |\n\n## LayoutSider Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `width` | `number \\| string` | `272` | Expanded width (always set as `width`). |\n| `collapsedWidth` | `number` | `48` | Collapsed `max-width`. |\n| `collapsed` | `boolean` | — | Collapsed state (`v-model:collapsed`). |\n| `defaultCollapsed` | `boolean` | `false` | Uncontrolled initial collapsed state. |\n| `showTrigger` | `boolean \\| 'bar' \\| 'arrow-circle' \\| 'arrow'` | `false` | Collapse trigger; `arrow` aliases `arrow-circle`. |\n| `collapseMode` | `'width' \\| 'transform'` | `'transform'` | `transform` clips content; `width` shrinks with sider. |\n| `showCollapsedContent` | `boolean` | `true` | Keep sider content visible while collapsed. |\n| `bordered` / `inverted` | `boolean` | `false` | Border / inverted colors. |\n| `triggerClass` / `triggerStyle` | — | — | Expanded trigger styles. |\n| `collapsedTriggerClass` / `collapsedTriggerStyle` | — | — | Collapsed trigger styles. |\n| `contentClass` / `contentStyle` | — | | Scroll container class / style. |\n\n## Events\n\n| Event | Description |\n| --- | --- |\n| `scroll` | Fired when the scroll container scrolls. |\n\n## Expose\n\n`MLayout` / `MLayoutContent` / `MLayoutSider` expose `scrollTo(...)`.\n\n## Components\n\n| Component | Description |\n| --- | --- |\n| `MLayout` | Root layout. |\n| `MLayoutHeader` | Header bar. |\n| `MLayoutContent` | Main content (fills leftover space by default). |\n| `MLayoutFooter` | Footer bar. |\n| `MLayoutSider` | Side panel. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Layout regions. |\n"
12201
+ "markdown": "---\ntitle: Layout\ncategory: 06 / LAYOUT\ndescription: Page layout shell with Header / Sider / Content / Footer.\n---\n\n# Layout\n\nPage-level layout shell. Set `has-sider` on the `MLayout` that hosts a sider. Give the root layout a fixed `height` (or `min-height`) so `MLayoutContent` can fill the remaining space.\n\n## Import\n\n```ts\nimport {\n MLayout,\n MLayoutContent,\n MLayoutFooter,\n MLayoutHeader,\n MLayoutSider,\n} from 'morya-ui'\n```\n\n## Basic\n\nHeader / Content / Footer. Content fills the leftover height.\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## With Sider\n\nHeader + left sider + main. The sider hosts `MMenu`, bound to `v-model:collapsed`. The inner `has-sider` layout consumes all height below the header.\n\n```vue preview src=\"./demos/WithSider.en.vue\"\n```\n\n## Right Sider\n\n```vue preview src=\"./demos/RightSider.en.vue\"\n```\n\n## Full Shell\n\nAdmin-style shell: header + inverted sider (`MMenu` `inverted`) + content + footer.\n\n```vue preview src=\"./demos/FullShell.en.vue\"\n```\n\n## Embedded Content\n\n`embedded` softens the content background so it separates from header / sider.\n\n```vue preview src=\"./demos/EmbeddedContent.en.vue\"\n```\n\n## Scrollable Content\n\nWhen content overflows, set `overflow: auto` on `MLayoutContent` (or wrap with `MScrollbar`); header and sider stay fixed. Root `MLayout` still has built-in `MScrollbar`; `MLayoutContent` / `MLayoutSider` are single-element shells.\n\n```vue preview src=\"./demos/ScrollableContent.en.vue\"\n```\n\n## Absolute Shell\n\nRoot `position=\"absolute\"` fills a relatively positioned parent with an explicit height.\n\n```vue preview src=\"./demos/AbsoluteShell.en.vue\"\n```\n\n## Layout Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `hasSider` | `boolean` | `false` | Horizontal layout for `MLayoutSider`. |\n| `siderPlacement` | `'left' \\| 'right'` | `'left'` | Sider side. |\n| `embedded` | `boolean` | `false` | Soft background for nested content. |\n| `position` | `'static' \\| 'absolute'` | `'static'` | Positioning mode. |\n| `contentClass` / `contentStyle` | — | — | Scroll container class / style. |\n\n## LayoutSider Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `width` | `number \\| string` | `272` | Expanded width (always set as `width`). |\n| `collapsedWidth` | `number` | `48` | Collapsed `max-width`. |\n| `collapsed` | `boolean` | — | Collapsed state (`v-model:collapsed`). |\n| `defaultCollapsed` | `boolean` | `false` | Uncontrolled initial collapsed state. |\n| `showTrigger` | `boolean \\| 'bar' \\| 'arrow-circle' \\| 'arrow'` | `false` | Collapse trigger; `arrow` aliases `arrow-circle`. |\n| `collapseMode` | `'width' \\| 'transform'` | `'transform'` | `transform` clips content; `width` shrinks with sider. |\n| `showCollapsedContent` | `boolean` | `true` | Keep sider content visible while collapsed. |\n| `bordered` / `inverted` | `boolean` | `false` | Border / inverted colors. |\n| `triggerClass` / `triggerStyle` | — | — | Expanded trigger styles. |\n| `collapsedTriggerClass` / `collapsedTriggerStyle` | — | — | Collapsed trigger styles. |\n| `padding` | `number \\| string` | — | Optional padding; no default. |\n| `radius` | `number \\| string` | — | Border radius. |\n\n## Events\n\n| Event | Description |\n| --- | --- |\n| `scroll` | Fired when the `MLayout` scroll container scrolls. |\n| `after-enter` | Fired when the sider expand transition ends. |\n| `after-leave` | Fired when the sider collapse transition ends. |\n| `collapse` | Fired when the sider starts collapsing. |\n| `expand` | Fired when the sider starts expanding. |\n| `update:collapsed` | Collapsed state v-model. |\n\n## Expose\n\n`MLayout` exposes `scrollTo(...)`.\n\n## Components\n\n| Component | Description |\n| --- | --- |\n| `MLayout` | Root layout. |\n| `MLayoutHeader` | Header bar. |\n| `MLayoutContent` | Main content (fills leftover space by default). |\n| `MLayoutFooter` | Footer bar. |\n| `MLayoutSider` | Side panel. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Layout regions. |\n"
12202
12202
  }
12203
12203
  }
12204
12204
  },
@@ -13159,7 +13159,7 @@
13159
13159
  "sectionId": "导航选中",
13160
13160
  "lang": "vue",
13161
13161
  "preview": true,
13162
- "code": "<script setup lang=\"ts\">\nimport { MMenu } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: '仪表盘', icon: 'layout-dashboard' },\n { key: 'users', label: '用户', icon: 'users' },\n { key: 'settings', label: '设置', icon: 'settings', disabled: true },\n]\n</script>\n\n<template>\n <div>\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n embedded\n @select=\"(item) => console.log('select', item.key)\"\n />\n </div>\n</template>",
13162
+ "code": "<script setup lang=\"ts\">\nimport { MMenu } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: '仪表盘', icon: 'layout-dashboard' },\n { key: 'users', label: '用户', icon: 'users' },\n { key: 'settings', label: '设置', icon: 'settings', disabled: true },\n]\n</script>\n\n<template>\n <div class=\"w-[15rem]\">\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n embedded\n @select=\"(item) => console.log('select', item.key)\"\n />\n </div>\n</template>",
13163
13163
  "locale": "zh-CN"
13164
13164
  },
13165
13165
  {
@@ -13195,7 +13195,7 @@
13195
13195
  "sectionId": "嵌入-layout-侧栏",
13196
13196
  "lang": "vue",
13197
13197
  "preview": true,
13198
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: '仪表盘', icon: 'layout-dashboard' },\n {\n key: 'system',\n label: '系统',\n icon: 'settings',\n items: [\n { key: 'users', label: '用户', icon: 'users' },\n { key: 'roles', label: '角色', icon: 'shield' },\n ],\n },\n]\n</script>\n\n<template>\n <MLayout\n style=\"\n height: 14rem;\n border: 1px solid var(--m-color-border);\n border-radius: var(--m-radius-lg);\n box-shadow: var(--m-shadow-sm);\n overflow: hidden;\n \"\n >\n <MLayoutHeader\n bordered\n style=\"\n padding: 0 var(--m-space-4);\n display: flex;\n align-items: center;\n min-height: var(--m-layout-header-height);\n \"\n >\n <strong style=\"color: var(--m-color-primary); font-size: var(--m-font-size-md)\">头部菜单</strong>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :collapsed-width=\"120\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n />\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding: var(--m-space-4)\">\n <p style=\"margin: 0; color: var(--m-color-text-muted); font-size: var(--m-font-size-sm)\">\n 当前选中:<strong style=\"color: var(--m-color-text)\">{{ selectedKey }}</strong>\n </p>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
13198
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: '仪表盘', icon: 'layout-dashboard' },\n {\n key: 'system',\n label: '系统',\n icon: 'settings',\n items: [\n { key: 'users', label: '用户', icon: 'users' },\n { key: 'roles', label: '角色', icon: 'shield' },\n ],\n },\n]\n</script>\n\n<template>\n <MLayout\n style=\"\n height: 14rem;\n border: 1px solid var(--m-color-border);\n border-radius: var(--m-radius-lg);\n box-shadow: var(--m-shadow-sm);\n overflow: hidden;\n \"\n >\n <MLayoutHeader\n bordered\n style=\"\n padding: 0 var(--m-space-4);\n display: flex;\n align-items: center;\n min-height: var(--m-layout-header-height);\n \"\n >\n <strong style=\"color: var(--m-color-primary); font-size: var(--m-font-size-md)\">头部菜单</strong>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :collapsed-width=\"120\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n />\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding: var(--m-space-4)\">\n <p style=\"margin: 0; color: var(--m-color-text-muted); font-size: var(--m-font-size-sm)\">\n 当前选中:<strong style=\"color: var(--m-color-text)\">{{ selectedKey }}</strong>\n </p>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
13199
13199
  "locale": "zh-CN"
13200
13200
  },
13201
13201
  {
@@ -13285,7 +13285,7 @@
13285
13285
  "sectionId": "embed-in-layout-sider",
13286
13286
  "lang": "vue",
13287
13287
  "preview": true,
13288
- "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: 'Dashboard', icon: 'layout-dashboard' },\n {\n key: 'system',\n label: 'System',\n icon: 'settings',\n items: [\n { key: 'users', label: 'Users', icon: 'users' },\n { key: 'roles', label: 'Roles', icon: 'shield' },\n ],\n },\n]\n</script>\n\n<template>\n <MLayout\n style=\"\n height: 14rem;\n border: 1px solid var(--m-color-border);\n border-radius: var(--m-radius-lg);\n box-shadow: var(--m-shadow-sm);\n overflow: hidden;\n \"\n >\n <MLayoutHeader\n bordered\n style=\"\n padding: 0 var(--m-space-4);\n display: flex;\n align-items: center;\n min-height: var(--m-layout-header-height);\n \"\n >\n <strong style=\"color: var(--m-color-primary); font-size: var(--m-font-size-md)\">Morya UI</strong>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :collapsed-width=\"64\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n accordion\n />\n </MLayoutSider>\n <MLayoutContent embedded content-style=\"padding: var(--m-space-4)\">\n <p style=\"margin: 0; color: var(--m-color-text-muted); font-size: var(--m-font-size-sm)\">\n Selected: <strong style=\"color: var(--m-color-text)\">{{ selectedKey }}</strong>\n </p>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
13288
+ "code": "<script setup lang=\"ts\">\nimport {\n MLayout,\n MLayoutContent,\n MLayoutHeader,\n MLayoutSider,\n MMenu,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst collapsed = ref(false)\nconst selectedKey = ref('dashboard')\nconst model = [\n { key: 'dashboard', label: 'Dashboard', icon: 'layout-dashboard' },\n {\n key: 'system',\n label: 'System',\n icon: 'settings',\n items: [\n { key: 'users', label: 'Users', icon: 'users' },\n { key: 'roles', label: 'Roles', icon: 'shield' },\n ],\n },\n]\n</script>\n\n<template>\n <MLayout\n style=\"\n height: 14rem;\n border: 1px solid var(--m-color-border);\n border-radius: var(--m-radius-lg);\n box-shadow: var(--m-shadow-sm);\n overflow: hidden;\n \"\n >\n <MLayoutHeader\n bordered\n style=\"\n padding: 0 var(--m-space-4);\n display: flex;\n align-items: center;\n min-height: var(--m-layout-header-height);\n \"\n >\n <strong style=\"color: var(--m-color-primary); font-size: var(--m-font-size-md)\">Morya UI</strong>\n </MLayoutHeader>\n <MLayout has-sider>\n <MLayoutSider\n v-model:collapsed=\"collapsed\"\n bordered\n show-trigger=\"arrow-circle\"\n collapse-mode=\"width\"\n :collapsed-width=\"64\"\n >\n <MMenu\n v-model:selected-key=\"selectedKey\"\n :model=\"model\"\n :collapsed=\"collapsed\"\n :collapsed-width=\"64\"\n accordion\n />\n </MLayoutSider>\n <MLayoutContent embedded style=\"padding: var(--m-space-4)\">\n <p style=\"margin: 0; color: var(--m-color-text-muted); font-size: var(--m-font-size-sm)\">\n Selected: <strong style=\"color: var(--m-color-text)\">{{ selectedKey }}</strong>\n </p>\n </MLayoutContent>\n </MLayout>\n </MLayout>\n</template>",
13289
13289
  "locale": "en-US"
13290
13290
  },
13291
13291
  {
@@ -13358,7 +13358,7 @@
13358
13358
  {
13359
13359
  "id": "折叠与飞出层",
13360
13360
  "title": "折叠与飞出层",
13361
- "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```"
13361
+ "body": "`collapsed` 隐藏文案,仅保留图标;**每个可折叠展示的菜单项必须提供 `icon`**(否则折叠后几乎空白)。悬停时在右侧显示 `MTooltip` 标签,带子项的节点还会弹出飞出层(`.m-menu--flyout`)。飞出层经 `MPopover` Teleport 到 `body`,不会被侧栏裁剪。`collapsed-width` 应与侧栏折叠宽度一致,用于居中图标。\n\n使用 `item.to` 时菜单项会渲染为 `RouterLink` / `<a>`;组件已重置链接的默认蓝色下划线,视觉与普通菜单项一致。\n\n```vue preview src=\"./demos/CollapsedAndFlyout.zh.vue\"\n```"
13362
13362
  },
13363
13363
  {
13364
13364
  "id": "嵌入-layout-侧栏",
@@ -13406,7 +13406,7 @@
13406
13406
  "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)。"
13407
13407
  }
13408
13408
  ],
13409
- "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"
13409
+ "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`,不会被侧栏裁剪。`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"
13410
13410
  },
13411
13411
  "en-US": {
13412
13412
  "title": "Menu",
@@ -13440,7 +13440,7 @@
13440
13440
  {
13441
13441
  "id": "collapsed-flyout",
13442
13442
  "title": "Collapsed & flyout",
13443
- "body": "`collapsed` hides labels and keeps icons. Hover shows an `MTooltip` with the label; groups also open a right flyout (`.m-menu--flyout`) via `MPopover` teleported to `body`, so it is not clipped by sider scroll regions. Set `collapsed-width` to match the sider width for centered icons.\n\n```vue preview src=\"./demos/CollapsedAndFlyout.en.vue\"\n```"
13443
+ "body": "`collapsed` hides labels and keeps icons. Hover shows an `MTooltip` with the label; groups also open a right flyout (`.m-menu--flyout`) via `MPopover` teleported to `body`, so it is not clipped by the sider. Set `collapsed-width` to match the sider width for centered icons.\n\n```vue preview src=\"./demos/CollapsedAndFlyout.en.vue\"\n```"
13444
13444
  },
13445
13445
  {
13446
13446
  "id": "embed-in-layout-sider",
@@ -13488,7 +13488,7 @@
13488
13488
  "body": "<h4 id=\"MenuItem\">MenuItem</h4>\n\nEach entry in `model`; supports nesting:\n\n```ts\ninterface MenuItem {\n key?: string\n label?: string\n icon?: string\n to?: string | RouteLocationRaw // RouterLink when vue-router is installed\n command?: () => void\n disabled?: boolean\n separator?: boolean\n items?: MenuItem[]\n}\n```\n\nWhen `key` is omitted, `label` is used as the identifier. `separator: true` renders a divider. See also [API types](/docs/types)."
13489
13489
  }
13490
13490
  ],
13491
- "markdown": "---\ntitle: Menu\ncategory: 04 / NAVIGATION\ndescription: Vertical/horizontal navigation menu with nested items, controlled selection, accordion, and collapsed flyout submenus.\n---\n\n# Menu\n\nNavigation menu rendered from a `model`. Typical uses: admin sidebar, top navigation.\n\n- Nested `items` with controlled `selectedKey`\n- Auto-expand ancestor path when selection changes; optional `accordion`\n- `collapsed` icon rail with right-side flyout submenus (Popover)\n- Non-popup menus default to `embedded` (borderless, full-width in `MLayoutSider`)\n\n> One-level hover submenus: [TieredMenu](/components/TieredMenu). Top bar: [Menubar](/components/Menubar). Action lists: [Dropdown](/components/Dropdown).\n\n## Import\n\n```ts\nimport type {MenuItem} from 'morya-ui';\nimport { MMenu } from 'morya-ui'\n```\n\n## Selection\n\nGive leaf items stable `key` values; sync with routing via `v-model:selected-key`. Emits `select` on click.\n\n```vue preview src=\"./demos/Selection.en.vue\"\n```\n\nIf `key` is omitted, `label` is used as fallback. Prefer explicit keys in production.\n\n## Nested submenus\n\nClick a group to expand/collapse. When a child is selected, the parent shows `child-active` styling.\n\n```vue preview src=\"./demos/NestedSubmenus.en.vue\"\n```\n\n## Accordion & expanded keys\n\n`accordion` keeps at most one top-level group open. Use `defaultExpandedKeys` or `v-model:expanded-keys` for controlled expansion. Changing `selectedKey` auto-expands its ancestor path.\n\n```vue preview src=\"./demos/AccordionAndExpandedKeys.en.vue\"\n```\n\n## Collapsed & flyout\n\n`collapsed` hides labels and keeps icons. Hover shows an `MTooltip` with the label; groups also open a right flyout (`.m-menu--flyout`) via `MPopover` teleported to `body`, so it is not clipped by sider scroll regions. Set `collapsed-width` to match the sider width for centered icons.\n\n```vue preview src=\"./demos/CollapsedAndFlyout.en.vue\"\n```\n\n## Embed in Layout sider\n\nRecommended shell: **global Header + inner `has-sider` Layout**. Bind menu `collapsed` to `MLayoutSider`.\n\n```vue preview src=\"./demos/EmbedInLayoutSider.en.vue\"\n```\n\n## Horizontal mode\n\n`mode=\"horizontal\"` for top nav bars. Submenus open in a `MPopover` dropdown flyout (teleported, themed scrollbar) and close after selection. Popup mode root menus also use built-in `MScrollbar`.\n\n```vue preview src=\"./demos/HorizontalMode.en.vue\"\n```\n\n## Inverted (dark sider)\n\nUse `inverted` with `MLayoutSider`'s `inverted` on dark backgrounds.\n\n```vue preview src=\"./demos/InvertedDarkSider.en.vue\"\n```\n\n## Popup mode\n\n`popup` + `v-model` renders a floating menu, teleported to `body` by default and positioned against the **default-slot trigger** (falls back to the last pointer position when no slot). Closes on outside click or leaf selection.\n\n```vue preview src=\"./demos/PopupMode.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `model` | `MenuItem[]` | — | Menu items; may nest `items`. |\n| `popup` | `boolean` | `false` | Overlay mode; use with `v-model`. |\n| `modelValue` | `boolean` | `false` | Popup visibility (`v-model`). |\n| `placement` | `'bottom-start' \\| 'bottom-end' \\| 'top-start' \\| 'top-end'` | `'bottom-start'` | Popup position relative to the trigger. |\n| `selectedKey` | `string \\| null` | `null` | Selected item key (`v-model:selected-key`). |\n| `collapsed` | `boolean` | `false` | Icon-only; submenus in right flyout. |\n| `collapsedWidth` | `number` | `80` | Collapsed width (px) for icon centering. |\n| `indent` | `number` | `12` | Extra padding-left per level (px). |\n| `rootIndent` | `number` | `16` | Root item padding-left (px). |\n| `accordion` | `boolean` | `false` | Only one top-level submenu open at a time. |\n| `defaultExpandedKeys` | `string[]` | `[]` | Initially expanded submenu keys. |\n| `expandedKeys` | `string[]` | — | Controlled expanded keys (`v-model:expanded-keys`). |\n| `defaultExpandAll` | `boolean` | `false` | Expand all submenus initially. |\n| `mode` | `'vertical' \\| 'horizontal'` | `'vertical'` | Layout direction. |\n| `inverted` | `boolean` | `false` | Inverted colors for dark sider. |\n| `embedded` | `boolean` | `!popup` | Embed in layout (no border/min-width). |\n| `teleport` | `boolean` | `true` | Teleport popup to `appendTo`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Teleport target; falls back to ConfigProvider. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Popup visibility changed. |\n| `update:selectedKey` | `string \\| null` | Selected item changed. |\n| `update:expandedKeys` | `string[]` | Expanded keys changed. |\n| `select` | `MenuItem` | Leaf clicked (not disabled / separator). |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Popup trigger anchor (e.g. a button); menu positions against it. |\n\n## MenuItem\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `key` | `string` | Unique id; falls back to `label`. |\n| `label` | `string` | Display text. |\n| `icon` | `string` | [Tabler icon name](/components/Icon) or character. |\n| `command` | `() => void` | Click handler (also emits `select`). |\n| `disabled` | `boolean` | Disabled state. |\n| `separator` | `boolean` | Separator line (ignores other fields). |\n| `items` | `MenuItem[]` | Child menu items. |\n\n## Types\n\n<h4 id=\"MenuItem\">MenuItem</h4>\n\nEach entry in `model`; supports nesting:\n\n```ts\ninterface MenuItem {\n key?: string\n label?: string\n icon?: string\n to?: string | RouteLocationRaw // RouterLink when vue-router is installed\n command?: () => void\n disabled?: boolean\n separator?: boolean\n items?: MenuItem[]\n}\n```\n\nWhen `key` is omitted, `label` is used as the identifier. `separator: true` renders a divider. See also [API types](/docs/types).\n"
13491
+ "markdown": "---\ntitle: Menu\ncategory: 04 / NAVIGATION\ndescription: Vertical/horizontal navigation menu with nested items, controlled selection, accordion, and collapsed flyout submenus.\n---\n\n# Menu\n\nNavigation menu rendered from a `model`. Typical uses: admin sidebar, top navigation.\n\n- Nested `items` with controlled `selectedKey`\n- Auto-expand ancestor path when selection changes; optional `accordion`\n- `collapsed` icon rail with right-side flyout submenus (Popover)\n- Non-popup menus default to `embedded` (borderless, full-width in `MLayoutSider`)\n\n> One-level hover submenus: [TieredMenu](/components/TieredMenu). Top bar: [Menubar](/components/Menubar). Action lists: [Dropdown](/components/Dropdown).\n\n## Import\n\n```ts\nimport type {MenuItem} from 'morya-ui';\nimport { MMenu } from 'morya-ui'\n```\n\n## Selection\n\nGive leaf items stable `key` values; sync with routing via `v-model:selected-key`. Emits `select` on click.\n\n```vue preview src=\"./demos/Selection.en.vue\"\n```\n\nIf `key` is omitted, `label` is used as fallback. Prefer explicit keys in production.\n\n## Nested submenus\n\nClick a group to expand/collapse. When a child is selected, the parent shows `child-active` styling.\n\n```vue preview src=\"./demos/NestedSubmenus.en.vue\"\n```\n\n## Accordion & expanded keys\n\n`accordion` keeps at most one top-level group open. Use `defaultExpandedKeys` or `v-model:expanded-keys` for controlled expansion. Changing `selectedKey` auto-expands its ancestor path.\n\n```vue preview src=\"./demos/AccordionAndExpandedKeys.en.vue\"\n```\n\n## Collapsed & flyout\n\n`collapsed` hides labels and keeps icons. Hover shows an `MTooltip` with the label; groups also open a right flyout (`.m-menu--flyout`) via `MPopover` teleported to `body`, so it is not clipped by the sider. Set `collapsed-width` to match the sider width for centered icons.\n\n```vue preview src=\"./demos/CollapsedAndFlyout.en.vue\"\n```\n\n## Embed in Layout sider\n\nRecommended shell: **global Header + inner `has-sider` Layout**. Bind menu `collapsed` to `MLayoutSider`.\n\n```vue preview src=\"./demos/EmbedInLayoutSider.en.vue\"\n```\n\n## Horizontal mode\n\n`mode=\"horizontal\"` for top nav bars. Submenus open in a `MPopover` dropdown flyout (teleported, themed scrollbar) and close after selection. Popup mode root menus also use built-in `MScrollbar`.\n\n```vue preview src=\"./demos/HorizontalMode.en.vue\"\n```\n\n## Inverted (dark sider)\n\nUse `inverted` with `MLayoutSider`'s `inverted` on dark backgrounds.\n\n```vue preview src=\"./demos/InvertedDarkSider.en.vue\"\n```\n\n## Popup mode\n\n`popup` + `v-model` renders a floating menu, teleported to `body` by default and positioned against the **default-slot trigger** (falls back to the last pointer position when no slot). Closes on outside click or leaf selection.\n\n```vue preview src=\"./demos/PopupMode.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `model` | `MenuItem[]` | — | Menu items; may nest `items`. |\n| `popup` | `boolean` | `false` | Overlay mode; use with `v-model`. |\n| `modelValue` | `boolean` | `false` | Popup visibility (`v-model`). |\n| `placement` | `'bottom-start' \\| 'bottom-end' \\| 'top-start' \\| 'top-end'` | `'bottom-start'` | Popup position relative to the trigger. |\n| `selectedKey` | `string \\| null` | `null` | Selected item key (`v-model:selected-key`). |\n| `collapsed` | `boolean` | `false` | Icon-only; submenus in right flyout. |\n| `collapsedWidth` | `number` | `80` | Collapsed width (px) for icon centering. |\n| `indent` | `number` | `12` | Extra padding-left per level (px). |\n| `rootIndent` | `number` | `16` | Root item padding-left (px). |\n| `accordion` | `boolean` | `false` | Only one top-level submenu open at a time. |\n| `defaultExpandedKeys` | `string[]` | `[]` | Initially expanded submenu keys. |\n| `expandedKeys` | `string[]` | — | Controlled expanded keys (`v-model:expanded-keys`). |\n| `defaultExpandAll` | `boolean` | `false` | Expand all submenus initially. |\n| `mode` | `'vertical' \\| 'horizontal'` | `'vertical'` | Layout direction. |\n| `inverted` | `boolean` | `false` | Inverted colors for dark sider. |\n| `embedded` | `boolean` | `!popup` | Embed in layout (no border/min-width). |\n| `teleport` | `boolean` | `true` | Teleport popup to `appendTo`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Teleport target; falls back to ConfigProvider. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Popup visibility changed. |\n| `update:selectedKey` | `string \\| null` | Selected item changed. |\n| `update:expandedKeys` | `string[]` | Expanded keys changed. |\n| `select` | `MenuItem` | Leaf clicked (not disabled / separator). |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Popup trigger anchor (e.g. a button); menu positions against it. |\n\n## MenuItem\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `key` | `string` | Unique id; falls back to `label`. |\n| `label` | `string` | Display text. |\n| `icon` | `string` | [Tabler icon name](/components/Icon) or character. |\n| `command` | `() => void` | Click handler (also emits `select`). |\n| `disabled` | `boolean` | Disabled state. |\n| `separator` | `boolean` | Separator line (ignores other fields). |\n| `items` | `MenuItem[]` | Child menu items. |\n\n## Types\n\n<h4 id=\"MenuItem\">MenuItem</h4>\n\nEach entry in `model`; supports nesting:\n\n```ts\ninterface MenuItem {\n key?: string\n label?: string\n icon?: string\n to?: string | RouteLocationRaw // RouterLink when vue-router is installed\n command?: () => void\n disabled?: boolean\n separator?: boolean\n items?: MenuItem[]\n}\n```\n\nWhen `key` is omitted, `label` is used as the identifier. `separator: true` renders a divider. See also [API types](/docs/types).\n"
13492
13492
  }
13493
13493
  }
13494
13494
  },
@@ -13799,7 +13799,7 @@
13799
13799
  {
13800
13800
  "id": "overview",
13801
13801
  "title": "",
13802
- "body": "# Message\n\n从窗口顶部正中滑入的轻量提示(可通过 `placement` 改到六向位置),适合简短操作反馈。推荐用 `message` API;也可挂载 `<MMessage />` 作为自定义挂载点。\n\n与 [Toast](/components/Toast) 的分工:\n\n- **Message(默认)**:轻量单行反馈,默认顶部居中,无标题/详情。**大多数 CRUD / 保存 / 删除回执应使用此项。**\n- **Toast**:四角通知,带 `summary` / `detail`;仅在有补充说明或异步通知感时使用。\n- **`<MMessage>` 组件**:页面内嵌条,用于表单区常驻错误(见下方「内嵌 Message」)。\n\n> AI / 业务代码选型细则见 [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md)。\n\n**快速判断**:只有一句话 → `message.success('已保存')`;有标题 + 详情 → `toast.success({ summary, detail })`。"
13802
+ "body": "# Message\n\n从窗口顶部正中滑入的轻量提示(可通过 `placement` 改到六向位置),适合简短操作反馈。推荐用 `message` API;也可挂载 `<MMessage />` 作为自定义挂载点。\n\n与 [Toast](/components/Toast) 的分工:\n\n- **Message(默认)**:轻量单行反馈,默认顶部居中,无标题/详情。**大多数 CRUD / 保存 / 删除回执应使用此项。**\n- **Toast**:四角通知,带 `summary` / `detail`;仅在有补充说明或异步通知感时使用。\n- **`<MMessage>` 组件**:可选的 message 服务宿主(自定义 `appendTo` / `placement`)。它不是页面内嵌 Alert;表单常驻错误用字段 `errorMessage`,或 token 样式的 `role=\"alert\"`。\n\n> AI / 业务代码选型细则见 [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md)。\n\n**快速判断**:只有一句话 → `message.success('已保存')`;有标题 + 详情 → `toast.success({ summary, detail })`。"
13803
13803
  },
13804
13804
  {
13805
13805
  "id": "引入",
@@ -13847,7 +13847,7 @@
13847
13847
  "body": "<h4 id=\"MessageItem\">MessageItem</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ninterface MessageItem {\n id: string | number\n content: MRenderable\n severity?: MessageSeverity\n closable?: boolean\n /** Auto-close delay in ms. `0` keeps it open. Default `3000` for API calls. */\n life?: number\n icon?: boolean\n}\n```"
13848
13848
  }
13849
13849
  ],
13850
- "markdown": "---\ntitle: Message\ncategory: 05 / FEEDBACK\ndescription: 顶部居中浮层提示,支持 API 调用。\n---\n\n# Message\n\n从窗口顶部正中滑入的轻量提示(可通过 `placement` 改到六向位置),适合简短操作反馈。推荐用 `message` API;也可挂载 `<MMessage />` 作为自定义挂载点。\n\n与 [Toast](/components/Toast) 的分工:\n\n- **Message(默认)**:轻量单行反馈,默认顶部居中,无标题/详情。**大多数 CRUD / 保存 / 删除回执应使用此项。**\n- **Toast**:四角通知,带 `summary` / `detail`;仅在有补充说明或异步通知感时使用。\n- **`<MMessage>` 组件**:页面内嵌条,用于表单区常驻错误(见下方「内嵌 Message」)。\n\n> AI / 业务代码选型细则见 [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md)。\n\n**快速判断**:只有一句话 → `message.success('已保存')`;有标题 + 详情 → `toast.success({ summary, detail })`。\n\n## 引入\n\n```ts\nimport { message, MMessage, useMessage } from 'morya-ui'\n```\n\n## API\n\n首次调用时会自动挂载浮层容器,无需在模板里放置组件。\n\n```vue preview src=\"./demos/Api.zh.vue\"\n```\n\n## 自定义内容\n\n`content`(以及 Toast 的 `summary` / `detail`)支持字符串、`h()` 返回的 VNode、组件,或 `() => VNode` 工厂函数。\n\n```vue preview src=\"./demos/CustomContent.zh.vue\"\n```\n\n## Methods\n\n| 方法 | 说明 |\n| --- | --- |\n| `message.success(content \\| options)` | 成功提示 |\n| `message.info(content \\| options)` | 信息提示 |\n| `message.warn(content \\| options)` | 警告提示(`warning` 同义) |\n| `message.error(content \\| options)` | 错误提示 |\n| `message.open(content \\| options)` | 自定义打开 |\n| `message.close(id?)` | 关闭指定 / 全部 |\n| `message.closeAll()` / `message.destroyAll()` | 关闭全部(二者等价) |\n| `message.config({ placement, max })` | 宿主位置与并发上限 |\n\n返回值:`{ id, close }`。\n\n### MessageOptions\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `content` | `string \\| number \\| VNode \\| Component \\| (() => VNodeChild)` | — | 正文;也可把可渲染值直接当作入参 |\n| `severity` | `'success' \\| 'info' \\| 'warn' \\| 'error' \\| 'secondary' \\| 'contrast'` | `'info'` | 语义色 |\n| `closable` | `boolean` | `false` | 显示关闭按钮 |\n| `life` | `number` | `3000` | 自动关闭毫秒;`0` 不自动关闭 |\n| `icon` | `boolean` | `true` | 显示语义图标 |\n| `id` | `string \\| number` | 自动生成 | 唯一键 |\n\n## 可选宿主\n\n需要自定义 `appendTo` 时,可在应用根部放置:\n\n```vue\n<MMessage append-to=\"body\" />\n```\n\n存在手动宿主时,API 不会再自动挂载第二份。\n\n## Props(`MMessage`)\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `teleport` | `boolean` | `true` | 是否 Teleport |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标 |\n| `placement` | `'top' \\| 'top-left' \\| 'top-right' \\| 'bottom' \\| 'bottom-left' \\| 'bottom-right'` | `'top'` | 宿主位置 |\n| `max` | `number` | — | 同时可见条数;超出丢掉最旧一条 |\n| `auto` | `boolean` | — | — |\n| `messages` | `MessageItem[]` | — | — |\n\n## Events\n\n`<MMessage />` 宿主本身无 Vue 事件;请通过 `message.*` API 的返回值 `{ id, close }` 管理生命周期。\n\n## Slots\n\n无插槽;通过 `message.*` API 注入内容。\n\n## 类型\n\n<h4 id=\"MessageItem\">MessageItem</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ninterface MessageItem {\n id: string | number\n content: MRenderable\n severity?: MessageSeverity\n closable?: boolean\n /** Auto-close delay in ms. `0` keeps it open. Default `3000` for API calls. */\n life?: number\n icon?: boolean\n}\n```\n"
13850
+ "markdown": "---\ntitle: Message\ncategory: 05 / FEEDBACK\ndescription: 顶部居中浮层提示,支持 API 调用。\n---\n\n# Message\n\n从窗口顶部正中滑入的轻量提示(可通过 `placement` 改到六向位置),适合简短操作反馈。推荐用 `message` API;也可挂载 `<MMessage />` 作为自定义挂载点。\n\n与 [Toast](/components/Toast) 的分工:\n\n- **Message(默认)**:轻量单行反馈,默认顶部居中,无标题/详情。**大多数 CRUD / 保存 / 删除回执应使用此项。**\n- **Toast**:四角通知,带 `summary` / `detail`;仅在有补充说明或异步通知感时使用。\n- **`<MMessage>` 组件**:可选的 message 服务宿主(自定义 `appendTo` / `placement`)。它不是页面内嵌 Alert;表单常驻错误用字段 `errorMessage`,或 token 样式的 `role=\"alert\"`。\n\n> AI / 业务代码选型细则见 [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md)。\n\n**快速判断**:只有一句话 → `message.success('已保存')`;有标题 + 详情 → `toast.success({ summary, detail })`。\n\n## 引入\n\n```ts\nimport { message, MMessage, useMessage } from 'morya-ui'\n```\n\n## API\n\n首次调用时会自动挂载浮层容器,无需在模板里放置组件。\n\n```vue preview src=\"./demos/Api.zh.vue\"\n```\n\n## 自定义内容\n\n`content`(以及 Toast 的 `summary` / `detail`)支持字符串、`h()` 返回的 VNode、组件,或 `() => VNode` 工厂函数。\n\n```vue preview src=\"./demos/CustomContent.zh.vue\"\n```\n\n## Methods\n\n| 方法 | 说明 |\n| --- | --- |\n| `message.success(content \\| options)` | 成功提示 |\n| `message.info(content \\| options)` | 信息提示 |\n| `message.warn(content \\| options)` | 警告提示(`warning` 同义) |\n| `message.error(content \\| options)` | 错误提示 |\n| `message.open(content \\| options)` | 自定义打开 |\n| `message.close(id?)` | 关闭指定 / 全部 |\n| `message.closeAll()` / `message.destroyAll()` | 关闭全部(二者等价) |\n| `message.config({ placement, max })` | 宿主位置与并发上限 |\n\n返回值:`{ id, close }`。\n\n### MessageOptions\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `content` | `string \\| number \\| VNode \\| Component \\| (() => VNodeChild)` | — | 正文;也可把可渲染值直接当作入参 |\n| `severity` | `'success' \\| 'info' \\| 'warn' \\| 'error' \\| 'secondary' \\| 'contrast'` | `'info'` | 语义色 |\n| `closable` | `boolean` | `false` | 显示关闭按钮 |\n| `life` | `number` | `3000` | 自动关闭毫秒;`0` 不自动关闭 |\n| `icon` | `boolean` | `true` | 显示语义图标 |\n| `id` | `string \\| number` | 自动生成 | 唯一键 |\n\n## 可选宿主\n\n需要自定义 `appendTo` 时,可在应用根部放置:\n\n```vue\n<MMessage append-to=\"body\" />\n```\n\n存在手动宿主时,API 不会再自动挂载第二份。\n\n## Props(`MMessage`)\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `teleport` | `boolean` | `true` | 是否 Teleport |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标 |\n| `placement` | `'top' \\| 'top-left' \\| 'top-right' \\| 'bottom' \\| 'bottom-left' \\| 'bottom-right'` | `'top'` | 宿主位置 |\n| `max` | `number` | — | 同时可见条数;超出丢掉最旧一条 |\n| `auto` | `boolean` | — | — |\n| `messages` | `MessageItem[]` | — | — |\n\n## Events\n\n`<MMessage />` 宿主本身无 Vue 事件;请通过 `message.*` API 的返回值 `{ id, close }` 管理生命周期。\n\n## Slots\n\n无插槽;通过 `message.*` API 注入内容。\n\n## 类型\n\n<h4 id=\"MessageItem\">MessageItem</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ninterface MessageItem {\n id: string | number\n content: MRenderable\n severity?: MessageSeverity\n closable?: boolean\n /** Auto-close delay in ms. `0` keeps it open. Default `3000` for API calls. */\n life?: number\n icon?: boolean\n}\n```\n"
13851
13851
  },
13852
13852
  "en-US": {
13853
13853
  "title": "Message",
@@ -13856,7 +13856,7 @@
13856
13856
  {
13857
13857
  "id": "overview",
13858
13858
  "title": "",
13859
- "body": "# Message\n\nA lightweight notice that slides in from the top center by default (`placement` can move it). Prefer the `message` API; you can also mount `<MMessage />` as a custom host.\n\nVs [Toast](/components/Toast):\n\n- **Message (default)**: short single-line feedback; no title/detail. Use for most CRUD / save / delete confirmations.\n- **Toast**: corner notifications with `summary` / `detail`; use only when supplementary detail is needed.\n- **`<MMessage>` component**: inline banner for persistent form/auth errors.\n\n> Selection guide: [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md).\n\n**Rule of thumb**: one short sentence → `message.success('Saved')`; title + detail → `toast.success({ summary, detail })`."
13859
+ "body": "# Message\n\nA lightweight notice that slides in from the top center by default (`placement` can move it). Prefer the `message` API; you can also mount `<MMessage />` as a custom host.\n\nVs [Toast](/components/Toast):\n\n- **Message (default)**: short single-line feedback; no title/detail. Use for most CRUD / save / delete confirmations.\n- **Toast**: corner notifications with `summary` / `detail`; use only when supplementary detail is needed.\n- **`<MMessage>` component**: optional host for the `message` service (custom `appendTo` / `placement`). It is not an inline alert; persistent form errors use field `errorMessage` or a token-styled `role=\"alert\"`.\n\n> Selection guide: [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md).\n\n**Rule of thumb**: one short sentence → `message.success('Saved')`; title + detail → `toast.success({ summary, detail })`."
13860
13860
  },
13861
13861
  {
13862
13862
  "id": "import",
@@ -13899,7 +13899,7 @@
13899
13899
  "body": "No slots; content is injected through the `message.*` API."
13900
13900
  }
13901
13901
  ],
13902
- "markdown": "---\ntitle: Message\ncategory: 05 / FEEDBACK\ndescription: Top-center floating notice with an imperative API.\n---\n\n# Message\n\nA lightweight notice that slides in from the top center by default (`placement` can move it). Prefer the `message` API; you can also mount `<MMessage />` as a custom host.\n\nVs [Toast](/components/Toast):\n\n- **Message (default)**: short single-line feedback; no title/detail. Use for most CRUD / save / delete confirmations.\n- **Toast**: corner notifications with `summary` / `detail`; use only when supplementary detail is needed.\n- **`<MMessage>` component**: inline banner for persistent form/auth errors.\n\n> Selection guide: [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md).\n\n**Rule of thumb**: one short sentence → `message.success('Saved')`; title + detail → `toast.success({ summary, detail })`.\n\n## Import\n\n```ts\nimport { message, MMessage, useMessage } from 'morya-ui'\n```\n\n## API\n\nThe first call auto-mounts a floating host; no template component is required.\n\n```vue preview src=\"./demos/Api.en.vue\"\n```\n\n## Custom content\n\n`content` (and Toast `summary` / `detail`) accepts a string, a VNode from `h()`, a component, or a `() => VNode` factory.\n\n```vue preview src=\"./demos/CustomContent.en.vue\"\n```\n\n## Methods\n\n| Method | Description |\n| --- | --- |\n| `message.success(content \\| options)` | Success |\n| `message.info(content \\| options)` | Info |\n| `message.warn(content \\| options)` | Warn (`warning` alias) |\n| `message.error(content \\| options)` | Error |\n| `message.open(content \\| options)` | Open with options |\n| `message.close(id?)` | Close one / all |\n| `message.closeAll()` / `message.destroyAll()` | Close all (aliases of each other) |\n| `message.config({ placement, max })` | Host placement and concurrency cap |\n\nReturns `{ id, close }`.\n\n### MessageOptions\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `content` | `string \\| number \\| VNode \\| Component \\| (() => VNodeChild)` | — | Body; a renderable value may also be passed directly |\n| `severity` | `'success' \\| 'info' \\| 'warn' \\| 'error' \\| 'secondary' \\| 'contrast'` | `'info'` | Tone |\n| `closable` | `boolean` | `false` | Show close button |\n| `life` | `number` | `3000` | Auto-close ms; `0` keeps open |\n| `icon` | `boolean` | `true` | Show severity icon |\n| `id` | `string \\| number` | auto | Unique key |\n\n## Optional host\n\nFor a custom `appendTo`, place this at the app root:\n\n```vue\n<MMessage append-to=\"body\" />\n```\n\nWhen a manual host exists, the API will not mount a second one.\n\n## Props (`MMessage`)\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `teleport` | `boolean` | `true` | Whether to Teleport |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target |\n| `placement` | `'top' \\| 'top-left' \\| 'top-right' \\| 'bottom' \\| 'bottom-left' \\| 'bottom-right'` | `'top'` | Host placement |\n| `max` | `number` | — | Max visible items; oldest is dropped |\n\n## Events\n\nThe `<MMessage />` host emits no Vue events. Use the `{ id, close }` return value from `message.*` APIs to control lifetime.\n\n## Slots\n\nNo slots; content is injected through the `message.*` API.\n"
13902
+ "markdown": "---\ntitle: Message\ncategory: 05 / FEEDBACK\ndescription: Top-center floating notice with an imperative API.\n---\n\n# Message\n\nA lightweight notice that slides in from the top center by default (`placement` can move it). Prefer the `message` API; you can also mount `<MMessage />` as a custom host.\n\nVs [Toast](/components/Toast):\n\n- **Message (default)**: short single-line feedback; no title/detail. Use for most CRUD / save / delete confirmations.\n- **Toast**: corner notifications with `summary` / `detail`; use only when supplementary detail is needed.\n- **`<MMessage>` component**: optional host for the `message` service (custom `appendTo` / `placement`). It is not an inline alert; persistent form errors use field `errorMessage` or a token-styled `role=\"alert\"`.\n\n> Selection guide: [`feedback.md`](../../../../design-kit/.agents/skills/morya-ui-pages/references/feedback.md).\n\n**Rule of thumb**: one short sentence → `message.success('Saved')`; title + detail → `toast.success({ summary, detail })`.\n\n## Import\n\n```ts\nimport { message, MMessage, useMessage } from 'morya-ui'\n```\n\n## API\n\nThe first call auto-mounts a floating host; no template component is required.\n\n```vue preview src=\"./demos/Api.en.vue\"\n```\n\n## Custom content\n\n`content` (and Toast `summary` / `detail`) accepts a string, a VNode from `h()`, a component, or a `() => VNode` factory.\n\n```vue preview src=\"./demos/CustomContent.en.vue\"\n```\n\n## Methods\n\n| Method | Description |\n| --- | --- |\n| `message.success(content \\| options)` | Success |\n| `message.info(content \\| options)` | Info |\n| `message.warn(content \\| options)` | Warn (`warning` alias) |\n| `message.error(content \\| options)` | Error |\n| `message.open(content \\| options)` | Open with options |\n| `message.close(id?)` | Close one / all |\n| `message.closeAll()` / `message.destroyAll()` | Close all (aliases of each other) |\n| `message.config({ placement, max })` | Host placement and concurrency cap |\n\nReturns `{ id, close }`.\n\n### MessageOptions\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `content` | `string \\| number \\| VNode \\| Component \\| (() => VNodeChild)` | — | Body; a renderable value may also be passed directly |\n| `severity` | `'success' \\| 'info' \\| 'warn' \\| 'error' \\| 'secondary' \\| 'contrast'` | `'info'` | Tone |\n| `closable` | `boolean` | `false` | Show close button |\n| `life` | `number` | `3000` | Auto-close ms; `0` keeps open |\n| `icon` | `boolean` | `true` | Show severity icon |\n| `id` | `string \\| number` | auto | Unique key |\n\n## Optional host\n\nFor a custom `appendTo`, place this at the app root:\n\n```vue\n<MMessage append-to=\"body\" />\n```\n\nWhen a manual host exists, the API will not mount a second one.\n\n## Props (`MMessage`)\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `teleport` | `boolean` | `true` | Whether to Teleport |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target |\n| `placement` | `'top' \\| 'top-left' \\| 'top-right' \\| 'bottom' \\| 'bottom-left' \\| 'bottom-right'` | `'top'` | Host placement |\n| `max` | `number` | — | Max visible items; oldest is dropped |\n\n## Events\n\nThe `<MMessage />` host emits no Vue events. Use the `{ id, close }` return value from `message.*` APIs to control lifetime.\n\n## Slots\n\nNo slots; content is injected through the `message.*` API.\n"
13903
13903
  }
13904
13904
  }
13905
13905
  },
@@ -16796,7 +16796,7 @@
16796
16796
  {
16797
16797
  "id": "horizontal",
16798
16798
  "title": "Horizontal",
16799
- "body": "内容宽度超出容器时显示横向滚动条。`trigger=\"none\"` 与 `always` 都会常显滑块;默认 `trigger=\"hover\"` 在悬停时显示。\n\n`MLayout` / `MLayoutContent` / `MLayoutSider`、`MDialog`、`MConfirmDialog`、`MDrawer`、`MSplitter`、`MTable`、`MSelect`、`MTreeSelect`、`MDropdown`、`MContextMenu`、`MPopover`、`MConfirmPopup`、`MMenu`(popup)、`MMenubar`、`MTieredMenu`、`MTabs`、`MGallery`、`MTimeline`(horizontal)、`MTextarea`(autosize `maxRows`)、`MTerminal`、`MOrderList`、`MPickList`、`MTreeTable`、`MVirtualScroller` 等组件已内置本组件。\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```"
16799
+ "body": "内容宽度超出容器时显示横向滚动条。`trigger=\"none\"` 与 `always` 都会常显滑块;默认 `trigger=\"hover\"` 在悬停时显示。\n\n`MLayout`、`MDialog`、`MConfirmDialog`、`MDrawer`、`MSplitter`、`MTable`、`MSelect`、`MTreeSelect`、`MDropdown`、`MContextMenu`、`MPopover`、`MConfirmPopup`、`MMenu`(popup)、`MMenubar`、`MTieredMenu`、`MTabs`、`MGallery`、`MTimeline`(horizontal)、`MTextarea`(autosize `maxRows`)、`MTerminal`、`MOrderList`、`MPickList`、`MTreeTable`、`MVirtualScroller` 等组件已内置本组件。\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```"
16800
16800
  },
16801
16801
  {
16802
16802
  "id": "always-native",
@@ -16834,7 +16834,7 @@
16834
16834
  "body": "<h4 id=\"ScrollbarAriaOrientation\">ScrollbarAriaOrientation</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarAriaOrientation = 'horizontal' | 'vertical'\n```\n\n<h4 id=\"ScrollbarClassValue\">ScrollbarClassValue</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarClassValue = | string\n | string[]\n | Record<string, boolean>\n | Array<string | Record<string, boolean> | null | undefined | false>\n```"
16835
16835
  }
16836
16836
  ],
16837
- "markdown": "---\ntitle: Scrollbar\ncategory: 01 / BASIC\ndescription: 可换肤自定义滚动条,提供一致的滚动体验。\n---\n\n# Scrollbar\n\n用于替换浏览器原生滚动条,提供跨浏览器一致的可换肤滚动体验。\n\n## 引入\n\n```ts\nimport { MScrollbar } from 'morya-ui'\n```\n\n## 基础用法\n\n用 `height` 固定可视区域高度;不设时跟随父容器高度。\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Max height\n\n仅当内容超出 `max-height` 时出现滚动条。\n\n```vue preview src=\"./demos/MaxHeight.vue\"\n```\n\n## Horizontal\n\n内容宽度超出容器时显示横向滚动条。`trigger=\"none\"` 与 `always` 都会常显滑块;默认 `trigger=\"hover\"` 在悬停时显示。\n\n`MLayout` / `MLayoutContent` / `MLayoutSider`、`MDialog`、`MConfirmDialog`、`MDrawer`、`MSplitter`、`MTable`、`MSelect`、`MTreeSelect`、`MDropdown`、`MContextMenu`、`MPopover`、`MConfirmPopup`、`MMenu`(popup)、`MMenubar`、`MTieredMenu`、`MTabs`、`MGallery`、`MTimeline`(horizontal)、`MTextarea`(autosize `maxRows`)、`MTerminal`、`MOrderList`、`MPickList`、`MTreeTable`、`MVirtualScroller` 等组件已内置本组件。\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```\n\n## Always / Native\n\n`always` 常显自定义滑块;`native` 使用浏览器原生滚动条。\n\n```vue preview src=\"./demos/AlwaysNative.vue\"\n```\n\n## Manual scroll\n\n通过实例方法 `setScrollTop` / `setScrollLeft` / `scrollTo` / `update` 控制滚动。\n\n```vue preview src=\"./demos/ManualScroll.zh.vue\"\n```\n\n## Infinite scroll\n\n滚动到边缘时触发 `end-reached`,可用于无限加载。\n\n```vue preview src=\"./demos/InfiniteScroll.zh.vue\"\n```\n\n## API\n\n### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `always` | `boolean` | — | — |\n| `ariaLabel` | `string` | — | — |\n| `ariaOrientation` | `ScrollbarAriaOrientation` | — | — |\n| `distance` | `number` | — | — |\n| `height` | `string \\| number` | — | — |\n| `id` | `string` | — | — |\n| `maxHeight` | `string \\| number` | — | — |\n| `minSize` | `number` | — | — |\n| `native` | `boolean` | — | — |\n| `noresize` | `boolean` | — | — |\n| `role` | `string` | — | — |\n| `tabindex` | `number \\| string` | — | — |\n| `tag` | `string` | — | — |\n| `trigger` | `'hover' \\| 'none'` | — | — |\n| `viewClass` | `ScrollbarClassValue` | — | — |\n| `viewStyle` | `StyleValue` | — | — |\n| `wrapClass` | `ScrollbarClassValue` | — | — |\n| `wrapStyle` | `StyleValue` | — | — |\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| height | `string \\| number` | — | 可视区域高度 |\n| maxHeight | `string \\| number` | — | 最大高度 |\n| fitContent | `boolean` | `false` | 随内容增高,配合根节点 CSS `max-height` 使用(下拉面板) |\n| native | `boolean` | `false` | 使用原生滚动条 |\n| wrapStyle / wrapClass | style / class | — | wrap 容器样式 |\n| viewStyle / viewClass | style / class | — | 内容区样式 |\n| noresize | `boolean` | `false` | 不监听尺寸变化 |\n| tag | `string` | `div` | 内容区标签 |\n| always | `boolean` | `false` | 始终显示滑块 |\n| trigger | `'hover' \\| 'none'` | `'hover'` | `none` 常显滑块;`always` 为 true 时仍常显 |\n| minSize | `number` | `20` | 滑块最小尺寸 |\n| id / role / ariaLabel / ariaOrientation | a11y | — | 内容区无障碍属性 |\n| tabindex | `number \\| string` | — | wrap 的 tabindex |\n| distance | `number` | `0` | 触发 `end-reached` 的边缘距离 |\n\n### Events\n\n| Name | Payload |\n| --- | --- |\n| scroll | `{ scrollTop, scrollLeft }` |\n| end-reached | `'top' \\| 'bottom' \\| 'left' \\| 'right'` |\n\n### Expose\n\n`wrapRef`、`update`、`scrollTo`、`setScrollTop`、`setScrollLeft`、`handleScroll`\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `scroll` | `{ scrollTop, scrollLeft }` | 滚动位置变化。 |\n| `end-reached` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | 滚动到边缘。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 可滚动内容。 |\n\n## 类型\n\n<h4 id=\"ScrollbarAriaOrientation\">ScrollbarAriaOrientation</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarAriaOrientation = 'horizontal' | 'vertical'\n```\n\n<h4 id=\"ScrollbarClassValue\">ScrollbarClassValue</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarClassValue = | string\n | string[]\n | Record<string, boolean>\n | Array<string | Record<string, boolean> | null | undefined | false>\n```\n"
16837
+ "markdown": "---\ntitle: Scrollbar\ncategory: 01 / BASIC\ndescription: 可换肤自定义滚动条,提供一致的滚动体验。\n---\n\n# Scrollbar\n\n用于替换浏览器原生滚动条,提供跨浏览器一致的可换肤滚动体验。\n\n## 引入\n\n```ts\nimport { MScrollbar } from 'morya-ui'\n```\n\n## 基础用法\n\n用 `height` 固定可视区域高度;不设时跟随父容器高度。\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Max height\n\n仅当内容超出 `max-height` 时出现滚动条。\n\n```vue preview src=\"./demos/MaxHeight.vue\"\n```\n\n## Horizontal\n\n内容宽度超出容器时显示横向滚动条。`trigger=\"none\"` 与 `always` 都会常显滑块;默认 `trigger=\"hover\"` 在悬停时显示。\n\n`MLayout`、`MDialog`、`MConfirmDialog`、`MDrawer`、`MSplitter`、`MTable`、`MSelect`、`MTreeSelect`、`MDropdown`、`MContextMenu`、`MPopover`、`MConfirmPopup`、`MMenu`(popup)、`MMenubar`、`MTieredMenu`、`MTabs`、`MGallery`、`MTimeline`(horizontal)、`MTextarea`(autosize `maxRows`)、`MTerminal`、`MOrderList`、`MPickList`、`MTreeTable`、`MVirtualScroller` 等组件已内置本组件。\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```\n\n## Always / Native\n\n`always` 常显自定义滑块;`native` 使用浏览器原生滚动条。\n\n```vue preview src=\"./demos/AlwaysNative.vue\"\n```\n\n## Manual scroll\n\n通过实例方法 `setScrollTop` / `setScrollLeft` / `scrollTo` / `update` 控制滚动。\n\n```vue preview src=\"./demos/ManualScroll.zh.vue\"\n```\n\n## Infinite scroll\n\n滚动到边缘时触发 `end-reached`,可用于无限加载。\n\n```vue preview src=\"./demos/InfiniteScroll.zh.vue\"\n```\n\n## API\n\n### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `always` | `boolean` | — | — |\n| `ariaLabel` | `string` | — | — |\n| `ariaOrientation` | `ScrollbarAriaOrientation` | — | — |\n| `distance` | `number` | — | — |\n| `height` | `string \\| number` | — | — |\n| `id` | `string` | — | — |\n| `maxHeight` | `string \\| number` | — | — |\n| `minSize` | `number` | — | — |\n| `native` | `boolean` | — | — |\n| `noresize` | `boolean` | — | — |\n| `role` | `string` | — | — |\n| `tabindex` | `number \\| string` | — | — |\n| `tag` | `string` | — | — |\n| `trigger` | `'hover' \\| 'none'` | — | — |\n| `viewClass` | `ScrollbarClassValue` | — | — |\n| `viewStyle` | `StyleValue` | — | — |\n| `wrapClass` | `ScrollbarClassValue` | — | — |\n| `wrapStyle` | `StyleValue` | — | — |\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| height | `string \\| number` | — | 可视区域高度 |\n| maxHeight | `string \\| number` | — | 最大高度 |\n| fitContent | `boolean` | `false` | 随内容增高,配合根节点 CSS `max-height` 使用(下拉面板) |\n| native | `boolean` | `false` | 使用原生滚动条 |\n| wrapStyle / wrapClass | style / class | — | wrap 容器样式 |\n| viewStyle / viewClass | style / class | — | 内容区样式 |\n| noresize | `boolean` | `false` | 不监听尺寸变化 |\n| tag | `string` | `div` | 内容区标签 |\n| always | `boolean` | `false` | 始终显示滑块 |\n| trigger | `'hover' \\| 'none'` | `'hover'` | `none` 常显滑块;`always` 为 true 时仍常显 |\n| minSize | `number` | `20` | 滑块最小尺寸 |\n| id / role / ariaLabel / ariaOrientation | a11y | — | 内容区无障碍属性 |\n| tabindex | `number \\| string` | — | wrap 的 tabindex |\n| distance | `number` | `0` | 触发 `end-reached` 的边缘距离 |\n\n### Events\n\n| Name | Payload |\n| --- | --- |\n| scroll | `{ scrollTop, scrollLeft }` |\n| end-reached | `'top' \\| 'bottom' \\| 'left' \\| 'right'` |\n\n### Expose\n\n`wrapRef`、`update`、`scrollTo`、`setScrollTop`、`setScrollLeft`、`handleScroll`\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `scroll` | `{ scrollTop, scrollLeft }` | 滚动位置变化。 |\n| `end-reached` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | 滚动到边缘。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 可滚动内容。 |\n\n## 类型\n\n<h4 id=\"ScrollbarAriaOrientation\">ScrollbarAriaOrientation</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarAriaOrientation = 'horizontal' | 'vertical'\n```\n\n<h4 id=\"ScrollbarClassValue\">ScrollbarClassValue</h4>\n\n完整定义见源码 `types.ts`。\n\n```ts\ntype ScrollbarClassValue = | string\n | string[]\n | Record<string, boolean>\n | Array<string | Record<string, boolean> | null | undefined | false>\n```\n"
16838
16838
  },
16839
16839
  "en-US": {
16840
16840
  "title": "Scrollbar",
@@ -16863,7 +16863,7 @@
16863
16863
  {
16864
16864
  "id": "horizontal",
16865
16865
  "title": "Horizontal",
16866
- "body": "A horizontal scrollbar appears when content is wider than the container. `trigger=\"none\"` and `always` keep the thumb visible; the default `trigger=\"hover\"` shows it on hover.\n\n`MLayout`, `MLayoutContent`, `MLayoutSider`, `MDialog`, `MConfirmDialog`, `MDrawer`, `MSplitter`, `MTable`, `MSelect`, `MTreeSelect`, `MDropdown`, `MContextMenu`, `MPopover`, `MConfirmPopup`, `MMenu` (popup), `MMenubar`, `MTieredMenu`, `MTabs`, `MGallery`, `MTimeline` (horizontal), `MTextarea` (autosize `maxRows`), `MTerminal`, `MOrderList`, `MPickList`, `MTreeTable`, and `MVirtualScroller` integrate this component internally.\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```"
16866
+ "body": "A horizontal scrollbar appears when content is wider than the container. `trigger=\"none\"` and `always` keep the thumb visible; the default `trigger=\"hover\"` shows it on hover.\n\n`MLayout`, `MDialog`, `MConfirmDialog`, `MDrawer`, `MSplitter`, `MTable`, `MSelect`, `MTreeSelect`, `MDropdown`, `MContextMenu`, `MPopover`, `MConfirmPopup`, `MMenu` (popup), `MMenubar`, `MTieredMenu`, `MTabs`, `MGallery`, `MTimeline` (horizontal), `MTextarea` (autosize `maxRows`), `MTerminal`, `MOrderList`, `MPickList`, `MTreeTable`, and `MVirtualScroller` integrate this component internally.\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```"
16867
16867
  },
16868
16868
  {
16869
16869
  "id": "always-native",
@@ -16896,7 +16896,7 @@
16896
16896
  "body": "| Slot | Description |\n| --- | --- |\n| `default` | Scrollable content. |"
16897
16897
  }
16898
16898
  ],
16899
- "markdown": "---\ntitle: Scrollbar\ncategory: 01 / BASIC\ndescription: Themeable custom scrollbar for a consistent scrolling experience.\n---\n\n# Scrollbar\n\nReplaces the native browser scrollbar with a themeable, cross-browser scrolling experience.\n\n## Import\n\n```ts\nimport { MScrollbar } from 'morya-ui'\n```\n\n## Basic\n\nUse `height` to fix the viewport height. If omitted, it follows the parent height.\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Max height\n\nThe scrollbar appears only when content exceeds `max-height`.\n\n```vue preview src=\"./demos/MaxHeight.vue\"\n```\n\n## Horizontal\n\nA horizontal scrollbar appears when content is wider than the container. `trigger=\"none\"` and `always` keep the thumb visible; the default `trigger=\"hover\"` shows it on hover.\n\n`MLayout`, `MLayoutContent`, `MLayoutSider`, `MDialog`, `MConfirmDialog`, `MDrawer`, `MSplitter`, `MTable`, `MSelect`, `MTreeSelect`, `MDropdown`, `MContextMenu`, `MPopover`, `MConfirmPopup`, `MMenu` (popup), `MMenubar`, `MTieredMenu`, `MTabs`, `MGallery`, `MTimeline` (horizontal), `MTextarea` (autosize `maxRows`), `MTerminal`, `MOrderList`, `MPickList`, `MTreeTable`, and `MVirtualScroller` integrate this component internally.\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```\n\n## Always / Native\n\n`always` keeps the custom thumb visible. `native` uses the browser scrollbar.\n\n```vue preview src=\"./demos/AlwaysNative.vue\"\n```\n\n## Manual scroll\n\nControl scrolling with instance methods `setScrollTop` / `setScrollLeft` / `scrollTo` / `update`.\n\n```vue preview src=\"./demos/ManualScroll.en.vue\"\n```\n\n## Infinite scroll\n\nEmits `end-reached` at the edge. Use it for infinite loading.\n\n```vue preview src=\"./demos/InfiniteScroll.en.vue\"\n```\n\n## API\n\n### Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| height | `string \\| number` | — | Viewport height |\n| maxHeight | `string \\| number` | — | Maximum height |\n| fitContent | `boolean` | `false` | Grow with content; pair with CSS `max-height` on the root (dropdown panels) |\n| native | `boolean` | `false` | Use the native scrollbar |\n| wrapStyle / wrapClass | style / class | — | Wrap container styles |\n| viewStyle / viewClass | style / class | — | Content area styles |\n| noresize | `boolean` | `false` | Do not listen for size changes |\n| tag | `string` | `div` | Content area tag |\n| always | `boolean` | `false` | Always show the thumb |\n| trigger | `'hover' \\| 'none'` | `'hover'` | `none` keeps thumbs visible; `always` still wins |\n| minSize | `number` | `20` | Minimum thumb size |\n| id / role / ariaLabel / ariaOrientation | a11y | — | Accessible attributes for the content area |\n| tabindex | `number \\| string` | — | tabindex on the wrap |\n| distance | `number` | `0` | Edge distance that triggers `end-reached` |\n\n### Events\n\n| Name | Payload |\n| --- | --- |\n| scroll | `{ scrollTop, scrollLeft }` |\n| end-reached | `'top' \\| 'bottom' \\| 'left' \\| 'right'` |\n\n### Expose\n\n`wrapRef`, `update`, `scrollTo`, `setScrollTop`, `setScrollLeft`, `handleScroll`\n\n## Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `scroll` | `{ scrollTop, scrollLeft }` | Scroll position change. |\n| `end-reached` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | Scroll boundary reached. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Scrollable content. |\n"
16899
+ "markdown": "---\ntitle: Scrollbar\ncategory: 01 / BASIC\ndescription: Themeable custom scrollbar for a consistent scrolling experience.\n---\n\n# Scrollbar\n\nReplaces the native browser scrollbar with a themeable, cross-browser scrolling experience.\n\n## Import\n\n```ts\nimport { MScrollbar } from 'morya-ui'\n```\n\n## Basic\n\nUse `height` to fix the viewport height. If omitted, it follows the parent height.\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Max height\n\nThe scrollbar appears only when content exceeds `max-height`.\n\n```vue preview src=\"./demos/MaxHeight.vue\"\n```\n\n## Horizontal\n\nA horizontal scrollbar appears when content is wider than the container. `trigger=\"none\"` and `always` keep the thumb visible; the default `trigger=\"hover\"` shows it on hover.\n\n`MLayout`, `MDialog`, `MConfirmDialog`, `MDrawer`, `MSplitter`, `MTable`, `MSelect`, `MTreeSelect`, `MDropdown`, `MContextMenu`, `MPopover`, `MConfirmPopup`, `MMenu` (popup), `MMenubar`, `MTieredMenu`, `MTabs`, `MGallery`, `MTimeline` (horizontal), `MTextarea` (autosize `maxRows`), `MTerminal`, `MOrderList`, `MPickList`, `MTreeTable`, and `MVirtualScroller` integrate this component internally.\n\n```vue preview src=\"./demos/Horizontal.vue\"\n```\n\n## Always / Native\n\n`always` keeps the custom thumb visible. `native` uses the browser scrollbar.\n\n```vue preview src=\"./demos/AlwaysNative.vue\"\n```\n\n## Manual scroll\n\nControl scrolling with instance methods `setScrollTop` / `setScrollLeft` / `scrollTo` / `update`.\n\n```vue preview src=\"./demos/ManualScroll.en.vue\"\n```\n\n## Infinite scroll\n\nEmits `end-reached` at the edge. Use it for infinite loading.\n\n```vue preview src=\"./demos/InfiniteScroll.en.vue\"\n```\n\n## API\n\n### Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| height | `string \\| number` | — | Viewport height |\n| maxHeight | `string \\| number` | — | Maximum height |\n| fitContent | `boolean` | `false` | Grow with content; pair with CSS `max-height` on the root (dropdown panels) |\n| native | `boolean` | `false` | Use the native scrollbar |\n| wrapStyle / wrapClass | style / class | — | Wrap container styles |\n| viewStyle / viewClass | style / class | — | Content area styles |\n| noresize | `boolean` | `false` | Do not listen for size changes |\n| tag | `string` | `div` | Content area tag |\n| always | `boolean` | `false` | Always show the thumb |\n| trigger | `'hover' \\| 'none'` | `'hover'` | `none` keeps thumbs visible; `always` still wins |\n| minSize | `number` | `20` | Minimum thumb size |\n| id / role / ariaLabel / ariaOrientation | a11y | — | Accessible attributes for the content area |\n| tabindex | `number \\| string` | — | tabindex on the wrap |\n| distance | `number` | `0` | Edge distance that triggers `end-reached` |\n\n### Events\n\n| Name | Payload |\n| --- | --- |\n| scroll | `{ scrollTop, scrollLeft }` |\n| end-reached | `'top' \\| 'bottom' \\| 'left' \\| 'right'` |\n\n### Expose\n\n`wrapRef`, `update`, `scrollTo`, `setScrollTop`, `setScrollLeft`, `handleScroll`\n\n## Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `scroll` | `{ scrollTop, scrollLeft }` | Scroll position change. |\n| `end-reached` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | Scroll boundary reached. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Scrollable content. |\n"
16900
16900
  }
16901
16901
  }
16902
16902
  },
@@ -25201,7 +25201,7 @@
25201
25201
  "zh-CN": {
25202
25202
  "title": "一键接入",
25203
25203
  "description": "用 @morya-ui/setup 安装组件库,并按需写入样式、Agent 配置与 MCP。",
25204
- "markdown": "---\ntitle: 一键接入\norder: 3\ndescription: 用 @morya-ui/setup 安装组件库,并按需写入样式、Agent 配置与 MCP。\n---\n\n# 一键接入\n\n[`@morya-ui/setup`](https://www.npmjs.com/package/@morya-ui/setup) 用于在业务 Vue 项目中接入 `morya-ui`:安装依赖、注入样式,并可一并写入 Agent Skill、Cursor 规则与 MCP。手写安装见 [快速上手](/docs/quick-start);AI 生成页面的约定见 [AI 接入](/docs/ai-setup)。\n\n## 命令\n\n在业务项目根目录执行:\n\n```bash\nnpx @morya-ui/setup\n```\n\n默认会:\n\n1. 安装 `morya-ui`(按锁文件选用 pnpm / yarn / npm)\n2. 复制 `DESIGN.md`、Agent Skill、Cursor rules 与检查脚本\n3. 合并 `.cursor/mcp.json`,接入 [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. 尝试在入口注入 `import 'morya-ui/styles.css'`\n5. 若缺失则追加 `check:colors` 脚本\n\n也可以按场景选用:\n\n```bash\n# 只安装组件库并注入样式\nnpx @morya-ui/setup app\n\n# 已装库时,只写入 AI 配置与 MCP\nnpx @morya-ui/setup ai\n```\n\n完成后若写入了 MCP,请 **重启 Cursor**(或重载 MCP)。生成页面前让 Agent 先读 `DESIGN.md`。\n\n## 选项\n\n| Flag | 说明 |\n| --- | --- |\n| `--cwd <dir>` | 目标项目根(默认当前目录) |\n| `--pm pnpm\\|yarn\\|npm` | 指定包管理器 |\n| `--force` | 覆盖已有模板文件与 `morya-ui` MCP 条目 |\n| `--dry-run` | 只打印将要执行的操作 |\n| `--skip-install` | 不安装依赖 |\n| `--skip-template` | 不复制 skill / rules / docs |\n| `--skip-mcp` | 不写 MCP 配置 |\n| `--skip-styles` | 不注入样式 import |\n| `--skip-scripts` | 不改 `package.json` scripts |\n\n默认 **不覆盖** 已有文件;只有 `--force` 才会覆盖模板与 MCP 条目。\n\n示例:只补 MCP:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```\n\n## 会落到项目里的内容\n\n| 路径 | 作用 |\n| --- | --- |\n| `DESIGN.md` | AI 设计第一信源 |\n| `.agents/skills/morya-ui-pages/` | 页面生成 Agent Skill(见 [Agent Skill](/docs/agent-skill)) |\n| `.cursor/rules/` | Cursor 常驻规则 |\n| `scripts/check-raw-colors.mjs` | 裸色值扫描 |\n| `.cursor/mcp.json` | Cursor MCP(`npx -y @morya-ui/mcp`) |\n\n模板源在仓库 [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit)。CLI 不调用 `app.use(MoryaUI)`,也不改 `App.vue`。\n\n## 冲突策略\n\n- 模板文件与 `.cursor/rules/*`:目标已存在则跳过(除非 `--force`)\n- `.cursor/mcp.json`:合并其它 server;已有 `morya-ui` 条目则跳过(除非 `--force`)\n- `check:colors`:仅在缺失时追加(除非 `--force`)\n- 样式:找到入口且尚未引入时才注入\n\n## 下一步\n\n- [快速上手](/docs/quick-start):组件用法与最小示例 \n- [AI 接入](/docs/ai-setup):用 AI 生成业务页面时如何配合 Skill / MCP \n- [Agent Skill](/docs/agent-skill) · [Agent MCP](/docs/mcp) \n- [组件](/components):浏览 API 与预览\n",
25204
+ "markdown": "---\ntitle: 一键接入\norder: 3\ndescription: 用 @morya-ui/setup 安装组件库,并按需写入样式、Agent 配置与 MCP。\n---\n\n# 一键接入\n\n[`@morya-ui/setup`](https://www.npmjs.com/package/@morya-ui/setup) 用于在业务 Vue 项目中接入 `morya-ui`:安装依赖、注入样式,并可一并写入 Agent Skill、Cursor 规则与 MCP。手写安装见 [快速上手](/docs/quick-start);AI 生成页面的约定见 [AI 接入](/docs/ai-setup)。\n\n## 命令\n\n在业务项目根目录执行:\n\n```bash\nnpx @morya-ui/setup\n```\n\n默认会:\n\n1. 安装 `morya-ui`(按锁文件选用 pnpm / yarn / npm)\n2. 复制 `DESIGN.md`、Agent Skill、Cursor rules 与检查脚本\n3. 合并 `.cursor/mcp.json`,接入 [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. 尝试在入口注入 `import 'morya-ui/styles.css'`\n5. 若缺失则追加 `check:colors` 脚本\n\n也可以按场景选用:\n\n```bash\n# 只安装组件库并注入样式\nnpx @morya-ui/setup app\n\n# 已装库时,只写入 AI 配置与 MCP\nnpx @morya-ui/setup ai\n\n# 非交互:默认 skill / 指定 / 全部\nnpx @morya-ui/setup ai --yes\nnpx @morya-ui/setup ai --skills=morya-ui-pages,frontend-design\nnpx @morya-ui/setup ai --skills=all\n```\n\n TTY 下,`full` / `ai` 会提示勾选可选 Agent Skill(必选 `morya-ui-pages` 始终写入)。完成后若写入了 MCP,请 **重启 Cursor**(或重载 MCP)。生成页面前让 Agent 先读 `DESIGN.md`。\n\n## 选项\n\n| Flag | 说明 |\n| --- | --- |\n| `--cwd <dir>` | 目标项目根(默认当前目录) |\n| `--pm pnpm\\|yarn\\|npm` | 指定包管理器 |\n| `--skills <list>` | 逗号分隔的 skill id,或 `all`(跳过交互提示) |\n| `--yes` / `-y` | 使用默认 skill,不提示 |\n| `--force` | 覆盖已有模板文件与 `morya-ui` MCP 条目 |\n| `--dry-run` | 只打印将要执行的操作 |\n| `--skip-install` | 不安装依赖 |\n| `--skip-template` | 不复制 skill / rules / docs |\n| `--skip-mcp` | 不写 MCP 配置 |\n| `--skip-styles` | 不注入样式 import |\n| `--skip-scripts` | 不改 `package.json` scripts |\n\n默认 **不覆盖** 已有文件;只有 `--force` 才会覆盖模板与 MCP 条目。\n\n### Skills\n\n| Id | 默认 | 作用 |\n| --- | --- | --- |\n| `morya-ui-pages` | 必选 | 用 `M*` + 黄金布局生成页面 |\n| `frontend-design` | 可选 | Express / 品牌向视觉味觉 |\n| `fixing-accessibility` | 可选 | 无障碍审计与定向修复 |\n\n目录:[`packages/setup/catalog/skills.json`](https://github.com/morya-space/morya-ui/blob/main/packages/setup/catalog/skills.json)。\n\n示例:只补 MCP:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```\n\n## 会落到项目里的内容\n\n| 路径 | 作用 |\n| --- | --- |\n| `DESIGN.md` | AI 设计第一信源(原则、应用根、令牌摘要、禁止项) |\n| `.agents/skills/morya-ui-pages/` | 页面生成 Agent Skill(见 [Agent Skill](/docs/agent-skill)) |\n| `.agents/skills/<optional>/` | 勾选时写入的 companion skill |\n| `.cursor/rules/` | Cursor 常驻规则 |\n| `scripts/check-raw-colors.mjs` | 裸色值扫描 |\n| `.cursor/mcp.json` | Cursor MCP(`npx -y @morya-ui/mcp`) |\n\n模板源在仓库 [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit)。CLI 不调用 `app.use(MoryaUI)`,也不改 `App.vue`。\n\n## 冲突策略\n\n- 模板文件与 `.cursor/rules/*`:目标已存在则跳过(除非 `--force`)\n- `.cursor/mcp.json`:合并其它 server;已有 `morya-ui` 条目则跳过(除非 `--force`)\n- `check:colors`:仅在缺失时追加(除非 `--force`)\n- 样式:找到入口且尚未引入时才注入\n\n## 下一步\n\n- [快速上手](/docs/quick-start):组件用法与最小示例 \n- [AI 接入](/docs/ai-setup):用 AI 生成业务页面时如何配合 Skill / MCP \n- [Agent Skill](/docs/agent-skill) · [Agent MCP](/docs/mcp) \n- [组件](/components):浏览 API 与预览\n",
25205
25205
  "sections": [
25206
25206
  {
25207
25207
  "title": "",
@@ -25211,17 +25211,17 @@
25211
25211
  {
25212
25212
  "title": "命令",
25213
25213
  "id": "命令",
25214
- "body": "在业务项目根目录执行:\n\n```bash\nnpx @morya-ui/setup\n```\n\n默认会:\n\n1. 安装 `morya-ui`(按锁文件选用 pnpm / yarn / npm)\n2. 复制 `DESIGN.md`、Agent Skill、Cursor rules 与检查脚本\n3. 合并 `.cursor/mcp.json`,接入 [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. 尝试在入口注入 `import 'morya-ui/styles.css'`\n5. 若缺失则追加 `check:colors` 脚本\n\n也可以按场景选用:\n\n```bash\n# 只安装组件库并注入样式\nnpx @morya-ui/setup app\n\n# 已装库时,只写入 AI 配置与 MCP\nnpx @morya-ui/setup ai\n```\n\n完成后若写入了 MCP,请 **重启 Cursor**(或重载 MCP)。生成页面前让 Agent 先读 `DESIGN.md`。"
25214
+ "body": "在业务项目根目录执行:\n\n```bash\nnpx @morya-ui/setup\n```\n\n默认会:\n\n1. 安装 `morya-ui`(按锁文件选用 pnpm / yarn / npm)\n2. 复制 `DESIGN.md`、Agent Skill、Cursor rules 与检查脚本\n3. 合并 `.cursor/mcp.json`,接入 [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. 尝试在入口注入 `import 'morya-ui/styles.css'`\n5. 若缺失则追加 `check:colors` 脚本\n\n也可以按场景选用:\n\n```bash\n# 只安装组件库并注入样式\nnpx @morya-ui/setup app\n\n# 已装库时,只写入 AI 配置与 MCP\nnpx @morya-ui/setup ai\n\n# 非交互:默认 skill / 指定 / 全部\nnpx @morya-ui/setup ai --yes\nnpx @morya-ui/setup ai --skills=morya-ui-pages,frontend-design\nnpx @morya-ui/setup ai --skills=all\n```\n\n TTY 下,`full` / `ai` 会提示勾选可选 Agent Skill(必选 `morya-ui-pages` 始终写入)。完成后若写入了 MCP,请 **重启 Cursor**(或重载 MCP)。生成页面前让 Agent 先读 `DESIGN.md`。"
25215
25215
  },
25216
25216
  {
25217
25217
  "title": "选项",
25218
25218
  "id": "选项",
25219
- "body": "| Flag | 说明 |\n| --- | --- |\n| `--cwd <dir>` | 目标项目根(默认当前目录) |\n| `--pm pnpm\\|yarn\\|npm` | 指定包管理器 |\n| `--force` | 覆盖已有模板文件与 `morya-ui` MCP 条目 |\n| `--dry-run` | 只打印将要执行的操作 |\n| `--skip-install` | 不安装依赖 |\n| `--skip-template` | 不复制 skill / rules / docs |\n| `--skip-mcp` | 不写 MCP 配置 |\n| `--skip-styles` | 不注入样式 import |\n| `--skip-scripts` | 不改 `package.json` scripts |\n\n默认 **不覆盖** 已有文件;只有 `--force` 才会覆盖模板与 MCP 条目。\n\n示例:只补 MCP:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```"
25219
+ "body": "| Flag | 说明 |\n| --- | --- |\n| `--cwd <dir>` | 目标项目根(默认当前目录) |\n| `--pm pnpm\\|yarn\\|npm` | 指定包管理器 |\n| `--skills <list>` | 逗号分隔的 skill id,或 `all`(跳过交互提示) |\n| `--yes` / `-y` | 使用默认 skill,不提示 |\n| `--force` | 覆盖已有模板文件与 `morya-ui` MCP 条目 |\n| `--dry-run` | 只打印将要执行的操作 |\n| `--skip-install` | 不安装依赖 |\n| `--skip-template` | 不复制 skill / rules / docs |\n| `--skip-mcp` | 不写 MCP 配置 |\n| `--skip-styles` | 不注入样式 import |\n| `--skip-scripts` | 不改 `package.json` scripts |\n\n默认 **不覆盖** 已有文件;只有 `--force` 才会覆盖模板与 MCP 条目。\n\n### Skills\n\n| Id | 默认 | 作用 |\n| --- | --- | --- |\n| `morya-ui-pages` | 必选 | 用 `M*` + 黄金布局生成页面 |\n| `frontend-design` | 可选 | Express / 品牌向视觉味觉 |\n| `fixing-accessibility` | 可选 | 无障碍审计与定向修复 |\n\n目录:[`packages/setup/catalog/skills.json`](https://github.com/morya-space/morya-ui/blob/main/packages/setup/catalog/skills.json)。\n\n示例:只补 MCP:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```"
25220
25220
  },
25221
25221
  {
25222
25222
  "title": "会落到项目里的内容",
25223
25223
  "id": "会落到项目里的内容",
25224
- "body": "| 路径 | 作用 |\n| --- | --- |\n| `DESIGN.md` | AI 设计第一信源 |\n| `.agents/skills/morya-ui-pages/` | 页面生成 Agent Skill(见 [Agent Skill](/docs/agent-skill)) |\n| `.cursor/rules/` | Cursor 常驻规则 |\n| `scripts/check-raw-colors.mjs` | 裸色值扫描 |\n| `.cursor/mcp.json` | Cursor MCP(`npx -y @morya-ui/mcp`) |\n\n模板源在仓库 [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit)。CLI 不调用 `app.use(MoryaUI)`,也不改 `App.vue`。"
25224
+ "body": "| 路径 | 作用 |\n| --- | --- |\n| `DESIGN.md` | AI 设计第一信源(原则、应用根、令牌摘要、禁止项) |\n| `.agents/skills/morya-ui-pages/` | 页面生成 Agent Skill(见 [Agent Skill](/docs/agent-skill)) |\n| `.agents/skills/<optional>/` | 勾选时写入的 companion skill |\n| `.cursor/rules/` | Cursor 常驻规则 |\n| `scripts/check-raw-colors.mjs` | 裸色值扫描 |\n| `.cursor/mcp.json` | Cursor MCP(`npx -y @morya-ui/mcp`) |\n\n模板源在仓库 [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit)。CLI 不调用 `app.use(MoryaUI)`,也不改 `App.vue`。"
25225
25225
  },
25226
25226
  {
25227
25227
  "title": "冲突策略",
@@ -25238,7 +25238,7 @@
25238
25238
  "en-US": {
25239
25239
  "title": "One-shot setup",
25240
25240
  "description": "Use @morya-ui/setup to install the library and optionally write styles, Agent config, and MCP.",
25241
- "markdown": "---\ntitle: One-shot setup\norder: 3\ndescription: Use @morya-ui/setup to install the library and optionally write styles, Agent config, and MCP.\n---\n\n# One-shot setup\n\n[`@morya-ui/setup`](https://www.npmjs.com/package/@morya-ui/setup) onboards a consumer Vue app to `morya-ui`: install the dependency, inject styles, and optionally write the Agent skill, Cursor rules, and MCP. For manual install see [Quick start](/docs/quick-start). For AI page-generation workflow see [AI setup](/docs/ai-setup).\n\n## Commands\n\nFrom the app project root:\n\n```bash\nnpx @morya-ui/setup\n```\n\nBy default this will:\n\n1. Install `morya-ui` (pnpm / yarn / npm from the lockfile)\n2. Copy `DESIGN.md`, Agent skill, Cursor rules, and check scripts\n3. Merge `.cursor/mcp.json` for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. Try to inject `import 'morya-ui/styles.css'`\n5. Add a `check:colors` script when missing\n\nOther common commands:\n\n```bash\n# Library + styles only\nnpx @morya-ui/setup app\n\n# AI config + MCP only (library already installed)\nnpx @morya-ui/setup ai\n```\n\nIf MCP was written, **restart Cursor** (or reload MCP). Have the agent read `DESIGN.md` before generating pages.\n\n## Options\n\n| Flag | Meaning |\n| --- | --- |\n| `--cwd <dir>` | Target project root (default: cwd) |\n| `--pm pnpm\\|yarn\\|npm` | Package manager |\n| `--force` | Overwrite existing template files and the `morya-ui` MCP entry |\n| `--dry-run` | Print actions only |\n| `--skip-install` | Skip dependency install |\n| `--skip-template` | Skip copying skill / rules / docs |\n| `--skip-mcp` | Skip writing MCP config |\n| `--skip-styles` | Skip styles import injection |\n| `--skip-scripts` | Skip `package.json` scripts |\n\nBy default **existing files are not overwritten**; use `--force` to overwrite templates and the MCP entry.\n\nExample: MCP only:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```\n\n## What lands in the project\n\n| Path | Role |\n| --- | --- |\n| `DESIGN.md` | Primary design brief for AI |\n| `.agents/skills/morya-ui-pages/` | Page-generation Agent skill (see [Agent Skill](/docs/agent-skill)) |\n| `.cursor/rules/` | Cursor always-on rules |\n| `scripts/check-raw-colors.mjs` | Raw color scan |\n| `.cursor/mcp.json` | Cursor MCP (`npx -y @morya-ui/mcp`) |\n\nTemplate source: [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit). The CLI does not call `app.use(MoryaUI)` or edit `App.vue`.\n\n## Conflict policy\n\n- Template files and `.cursor/rules/*`: skip if the destination exists (unless `--force`)\n- `.cursor/mcp.json`: merge other servers; skip an existing `morya-ui` entry unless `--force`\n- `check:colors`: add only if missing (unless `--force`)\n- Styles: inject only when an entry is found and the import is not already present\n\n## Next steps\n\n- [Quick start](/docs/quick-start): component usage and a minimal example \n- [AI setup](/docs/ai-setup): how setup relates to Skill / MCP for AI page generation \n- [Agent Skill](/docs/agent-skill) · [Agent MCP](/docs/mcp) \n- [Components](/components): browse APIs and previews\n",
25241
+ "markdown": "---\ntitle: One-shot setup\norder: 3\ndescription: Use @morya-ui/setup to install the library and optionally write styles, Agent config, and MCP.\n---\n\n# One-shot setup\n\n[`@morya-ui/setup`](https://www.npmjs.com/package/@morya-ui/setup) onboards a consumer Vue app to `morya-ui`: install the dependency, inject styles, and optionally write the Agent skill, Cursor rules, and MCP. For manual install see [Quick start](/docs/quick-start). For AI page-generation workflow see [AI setup](/docs/ai-setup).\n\n## Commands\n\nFrom the app project root:\n\n```bash\nnpx @morya-ui/setup\n```\n\nBy default this will:\n\n1. Install `morya-ui` (pnpm / yarn / npm from the lockfile)\n2. Copy `DESIGN.md`, Agent skill, Cursor rules, and check scripts\n3. Merge `.cursor/mcp.json` for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. Try to inject `import 'morya-ui/styles.css'`\n5. Add a `check:colors` script when missing\n\nOther common commands:\n\n```bash\n# Library + styles only\nnpx @morya-ui/setup app\n\n# AI config + MCP only (library already installed)\nnpx @morya-ui/setup ai\n\n# Non-interactive skill selection\nnpx @morya-ui/setup ai --yes\nnpx @morya-ui/setup ai --skills=morya-ui-pages,frontend-design\nnpx @morya-ui/setup ai --skills=all\n```\n\nOn a TTY, `full` / `ai` prompts for optional Agent skills (required `morya-ui-pages` is always included). If MCP was written, **restart Cursor** (or reload MCP). Have the agent read `DESIGN.md` before generating pages.\n\n## Options\n\n| Flag | Meaning |\n| --- | --- |\n| `--cwd <dir>` | Target project root (default: cwd) |\n| `--pm pnpm\\|yarn\\|npm` | Package manager |\n| `--skills <list>` | Comma-separated skill ids, or `all` (skips the prompt) |\n| `--yes` / `-y` | Use default skills without prompting |\n| `--force` | Overwrite existing template files and the `morya-ui` MCP entry |\n| `--dry-run` | Print actions only |\n| `--skip-install` | Skip dependency install |\n| `--skip-template` | Skip copying skill / rules / docs |\n| `--skip-mcp` | Skip writing MCP config |\n| `--skip-styles` | Skip styles import injection |\n| `--skip-scripts` | Skip `package.json` scripts |\n\nBy default **existing files are not overwritten**; use `--force` to overwrite templates and the MCP entry.\n\n### Skills\n\n| Id | Default | Role |\n| --- | --- | --- |\n| `morya-ui-pages` | required | Page generation with `M*` + golden layouts |\n| `frontend-design` | optional | Express / brand visual taste |\n| `fixing-accessibility` | optional | A11y audit and targeted fixes |\n\nCatalog: [`packages/setup/catalog/skills.json`](https://github.com/morya-space/morya-ui/blob/main/packages/setup/catalog/skills.json).\n\nExample: MCP only:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```\n\n## What lands in the project\n\n| Path | Role |\n| --- | --- |\n| `DESIGN.md` | Primary design brief (principles, app root, token summary, bans) |\n| `.agents/skills/morya-ui-pages/` | Page-generation Agent skill (see [Agent Skill](/docs/agent-skill)) |\n| `.agents/skills/<optional>/` | Companion skills when selected |\n| `.cursor/rules/` | Cursor always-on rules |\n| `scripts/check-raw-colors.mjs` | Raw color scan |\n| `.cursor/mcp.json` | Cursor MCP (`npx -y @morya-ui/mcp`) |\n\nTemplate source: [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit). The CLI does not call `app.use(MoryaUI)` or edit `App.vue`.\n\n## Conflict policy\n\n- Template files and `.cursor/rules/*`: skip if the destination exists (unless `--force`)\n- `.cursor/mcp.json`: merge other servers; skip an existing `morya-ui` entry unless `--force`\n- `check:colors`: add only if missing (unless `--force`)\n- Styles: inject only when an entry is found and the import is not already present\n\n## Next steps\n\n- [Quick start](/docs/quick-start): component usage and a minimal example \n- [AI setup](/docs/ai-setup): how setup relates to Skill / MCP for AI page generation \n- [Agent Skill](/docs/agent-skill) · [Agent MCP](/docs/mcp) \n- [Components](/components): browse APIs and previews\n",
25242
25242
  "sections": [
25243
25243
  {
25244
25244
  "title": "",
@@ -25248,17 +25248,17 @@
25248
25248
  {
25249
25249
  "title": "Commands",
25250
25250
  "id": "commands",
25251
- "body": "From the app project root:\n\n```bash\nnpx @morya-ui/setup\n```\n\nBy default this will:\n\n1. Install `morya-ui` (pnpm / yarn / npm from the lockfile)\n2. Copy `DESIGN.md`, Agent skill, Cursor rules, and check scripts\n3. Merge `.cursor/mcp.json` for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. Try to inject `import 'morya-ui/styles.css'`\n5. Add a `check:colors` script when missing\n\nOther common commands:\n\n```bash\n# Library + styles only\nnpx @morya-ui/setup app\n\n# AI config + MCP only (library already installed)\nnpx @morya-ui/setup ai\n```\n\nIf MCP was written, **restart Cursor** (or reload MCP). Have the agent read `DESIGN.md` before generating pages."
25251
+ "body": "From the app project root:\n\n```bash\nnpx @morya-ui/setup\n```\n\nBy default this will:\n\n1. Install `morya-ui` (pnpm / yarn / npm from the lockfile)\n2. Copy `DESIGN.md`, Agent skill, Cursor rules, and check scripts\n3. Merge `.cursor/mcp.json` for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp)\n4. Try to inject `import 'morya-ui/styles.css'`\n5. Add a `check:colors` script when missing\n\nOther common commands:\n\n```bash\n# Library + styles only\nnpx @morya-ui/setup app\n\n# AI config + MCP only (library already installed)\nnpx @morya-ui/setup ai\n\n# Non-interactive skill selection\nnpx @morya-ui/setup ai --yes\nnpx @morya-ui/setup ai --skills=morya-ui-pages,frontend-design\nnpx @morya-ui/setup ai --skills=all\n```\n\nOn a TTY, `full` / `ai` prompts for optional Agent skills (required `morya-ui-pages` is always included). If MCP was written, **restart Cursor** (or reload MCP). Have the agent read `DESIGN.md` before generating pages."
25252
25252
  },
25253
25253
  {
25254
25254
  "title": "Options",
25255
25255
  "id": "options",
25256
- "body": "| Flag | Meaning |\n| --- | --- |\n| `--cwd <dir>` | Target project root (default: cwd) |\n| `--pm pnpm\\|yarn\\|npm` | Package manager |\n| `--force` | Overwrite existing template files and the `morya-ui` MCP entry |\n| `--dry-run` | Print actions only |\n| `--skip-install` | Skip dependency install |\n| `--skip-template` | Skip copying skill / rules / docs |\n| `--skip-mcp` | Skip writing MCP config |\n| `--skip-styles` | Skip styles import injection |\n| `--skip-scripts` | Skip `package.json` scripts |\n\nBy default **existing files are not overwritten**; use `--force` to overwrite templates and the MCP entry.\n\nExample: MCP only:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```"
25256
+ "body": "| Flag | Meaning |\n| --- | --- |\n| `--cwd <dir>` | Target project root (default: cwd) |\n| `--pm pnpm\\|yarn\\|npm` | Package manager |\n| `--skills <list>` | Comma-separated skill ids, or `all` (skips the prompt) |\n| `--yes` / `-y` | Use default skills without prompting |\n| `--force` | Overwrite existing template files and the `morya-ui` MCP entry |\n| `--dry-run` | Print actions only |\n| `--skip-install` | Skip dependency install |\n| `--skip-template` | Skip copying skill / rules / docs |\n| `--skip-mcp` | Skip writing MCP config |\n| `--skip-styles` | Skip styles import injection |\n| `--skip-scripts` | Skip `package.json` scripts |\n\nBy default **existing files are not overwritten**; use `--force` to overwrite templates and the MCP entry.\n\n### Skills\n\n| Id | Default | Role |\n| --- | --- | --- |\n| `morya-ui-pages` | required | Page generation with `M*` + golden layouts |\n| `frontend-design` | optional | Express / brand visual taste |\n| `fixing-accessibility` | optional | A11y audit and targeted fixes |\n\nCatalog: [`packages/setup/catalog/skills.json`](https://github.com/morya-space/morya-ui/blob/main/packages/setup/catalog/skills.json).\n\nExample: MCP only:\n\n```bash\nnpx @morya-ui/setup ai --skip-template --skip-scripts\n```"
25257
25257
  },
25258
25258
  {
25259
25259
  "title": "What lands in the project",
25260
25260
  "id": "what-lands-in-the-project",
25261
- "body": "| Path | Role |\n| --- | --- |\n| `DESIGN.md` | Primary design brief for AI |\n| `.agents/skills/morya-ui-pages/` | Page-generation Agent skill (see [Agent Skill](/docs/agent-skill)) |\n| `.cursor/rules/` | Cursor always-on rules |\n| `scripts/check-raw-colors.mjs` | Raw color scan |\n| `.cursor/mcp.json` | Cursor MCP (`npx -y @morya-ui/mcp`) |\n\nTemplate source: [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit). The CLI does not call `app.use(MoryaUI)` or edit `App.vue`."
25261
+ "body": "| Path | Role |\n| --- | --- |\n| `DESIGN.md` | Primary design brief (principles, app root, token summary, bans) |\n| `.agents/skills/morya-ui-pages/` | Page-generation Agent skill (see [Agent Skill](/docs/agent-skill)) |\n| `.agents/skills/<optional>/` | Companion skills when selected |\n| `.cursor/rules/` | Cursor always-on rules |\n| `scripts/check-raw-colors.mjs` | Raw color scan |\n| `.cursor/mcp.json` | Cursor MCP (`npx -y @morya-ui/mcp`) |\n\nTemplate source: [`design-kit/`](https://github.com/morya-space/morya-ui/tree/main/design-kit). The CLI does not call `app.use(MoryaUI)` or edit `App.vue`."
25262
25262
  },
25263
25263
  {
25264
25264
  "title": "Conflict policy",
@@ -25997,7 +25997,7 @@
25997
25997
  "zh-CN": {
25998
25998
  "title": "Agent Skill",
25999
25999
  "description": "消费方 morya-ui-pages skill:何时触发、与 rules/MCP 分工、页面类型地图。",
26000
- "markdown": "---\ntitle: Agent Skill\norder: 12\ndescription: 消费方 morya-ui-pages skill:何时触发、与 rules/MCP 分工、页面类型地图。\n---\n\n# Agent Skill\n\n消费方用 AI 生成 **基于 `morya-ui` 的业务页面** 时,应加载 **`morya-ui-pages`** skill。它规定组件契约、页面类型与工作流;**不是**组件库源码里写新组件用的 skill。\n\n安装方式见 [一键接入](/docs/setup)(`npx @morya-ui/setup` 会复制到项目);AI 侧流程见 [AI 接入](/docs/ai-setup)。本文说明 skill **是什么、何时用、和其它配置怎么分工**。\n\n## 装到哪里\n\n```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # 布局、表面、令牌、反馈、检查清单等\n```\n\n支持 Agent Skills 自动发现的客户端(如 Cursor)会从 `.agents/skills` 读取。生成列表 / 表单 / 登录 / 落地等页面前,应优先匹配本 skill。\n\n源文件在仓库 [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages),随 `@morya-ui/setup` 的 template 同步。\n\n## 何时触发\n\n典型话术或主题:\n\n- `morya-ui`、`M*` 组件、`--m-*` 令牌、黄金样例\n- 后台 / 列表 / 表单 / 仪表盘 / 详情 / 设置\n- 登录 / 注册 / 空状态 / 向导 / 落地页 / 官网\n\n**优先于**通用 `frontend-design`、Impeccable、UI-UX-Pro-Max 等:那些只能当审美参考;栈是 morya-ui 时以本 skill 为准。\n\n**不要**用于:纯后端、或在本仓库 `src/components` 里新增组件库组件。\n\n## 与其它配置的分工\n\n| 层 | 角色 |\n| --- | --- |\n| [一键接入](/docs/setup) / `@morya-ui/setup` | 一次性把库 + skill + rules + MCP 装进项目 |\n| [AI 接入](/docs/ai-setup) | 装好后如何配合 Agent 生成页面 |\n| **`morya-ui-pages` skill** | 按需工作流:选表面、读黄金样例、组 `M*`、自检 |\n| `.cursor/rules/` | 编辑器常驻短规则(设计系统、组件用法、布局) |\n| `DESIGN.md` | 项目设计第一信源;与 skill 冲突时以项目 `DESIGN.md` 为准 |\n| [Agent MCP](/docs/mcp) | 运行时查真实 Props / Events / 示例,禁止臆造 API |\n\n两层始终生效:\n\n1. **契约** — 只用 `M*` 与 `--m-*`,API 以 MCP / 文档为准 \n2. **工艺** — 先定表面类型,再做视觉;后台偏克制,落地 / 品牌向可有意表达,但仍上令牌、上组件\n\n## 页面类型(Surface)地图\n\n| 车道 | 典型表面 | 优先参考 |\n| --- | --- | --- |\n| **Ops** | 列表、表单、仪表盘、详情、设置、筛选抽屉 | 黄金样例 + skill `page-layouts` |\n| **Account** | 登录、注册、邀请、重置密码、个人资料 | skill `surfaces` § Account |\n| **Flow** | 引导、空状态、向导、成功页 | skill `surfaces` § Flow |\n| **System** | 404、无权限、维护中 | skill `surfaces` § System |\n| **Express** | 营销落地、定价、功能展示 | skill `surfaces` + `visual-craft` |\n| **Overlay** | 以 Dialog / Drawer / CommandMenu 为主界面 | skill `surfaces` § Overlay |\n\n不确定时:后台默认 Ops → 最近黄金样例;对外营销 → Express。\n\n## Agent 推荐工作流(摘要)\n\n1. 钉死主体、受众、表面、第一屏单一任务 \n2. 优先 MCP:`recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. 无 MCP 时读 skill `references/`(布局、表面、反馈) \n4. 反馈默认 `message`;`toast` 仅 summary+detail / 异步感(见 skill `references/feedback.md`) \n5. 交付前对照 skill 检查清单;有 MCP 时跑 `validate_page`\n\n细节与硬边界以项目内 `SKILL.md` 为准,本文不重复全文。\n\n## 下一步\n\n- [一键接入](/docs/setup):安装 skill 与其它配置 \n- [AI 接入](/docs/ai-setup):用 AI 生成页面时的流程 \n- [Agent MCP](/docs/mcp):工具与客户端配置 \n- [快速上手](/docs/quick-start):手写安装组件库 \n- [组件](/components):浏览 API\n",
26000
+ "markdown": "---\ntitle: Agent Skill\norder: 12\ndescription: 消费方 morya-ui-pages skill:何时触发、与 rules/MCP 分工、页面类型地图。\n---\n\n# Agent Skill\n\n消费方用 AI 生成 **基于 `morya-ui` 的业务页面** 时,应加载 **`morya-ui-pages`** skill。它规定组件契约、页面类型与工作流;**不是**组件库源码里写新组件用的 skill。\n\n安装方式见 [一键接入](/docs/setup)(`npx @morya-ui/setup` 会复制到项目);AI 侧流程见 [AI 接入](/docs/ai-setup)。本文说明 skill **是什么、何时用、和其它配置怎么分工**。\n\n## 装到哪里\n\n```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # 布局、表面、令牌、反馈、检查清单等\n```\n\n支持 Agent Skills 自动发现的客户端(如 Cursor)会从 `.agents/skills` 读取。生成列表 / 表单 / 登录 / 落地等页面前,应优先匹配本 skill。\n\n源文件在仓库 [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages),随 `@morya-ui/setup` 的 template 同步。可选 companion(`frontend-design`、`fixing-accessibility`)可用 `npx @morya-ui/setup ai --skills=…` 一并写入,见 [一键接入](/docs/setup)。\n\n## 何时触发\n\n典型话术或主题:\n\n- `morya-ui`、`M*` 组件、`--m-*` 令牌、黄金样例\n- 后台 / 列表 / 表单 / 仪表盘 / 详情 / 设置\n- 登录 / 注册 / 空状态 / 向导 / 落地页 / 官网\n\n**优先于**通用 `frontend-design`、Impeccable、UI-UX-Pro-Max 等:那些只能当审美参考;栈是 morya-ui 时以本 skill 为准。\n\n**不要**用于:纯后端、或在本仓库 `src/components` 里新增组件库组件。\n\n## 与其它配置的分工\n\n| 层 | 角色 |\n| --- | --- |\n| [一键接入](/docs/setup) / `@morya-ui/setup` | 一次性把库 + skill + rules + MCP 装进项目 |\n| [AI 接入](/docs/ai-setup) | 装好后如何配合 Agent 生成页面 |\n| **`morya-ui-pages` skill** | 按需工作流:选表面、读黄金样例、组 `M*`、自检 |\n| `.cursor/rules/` | 编辑器常驻短规则(设计系统、组件用法、布局) |\n| `DESIGN.md` | 项目设计第一信源;与 skill 冲突时以项目 `DESIGN.md` 为准 |\n| [Agent MCP](/docs/mcp) | 运行时查真实 Props / Events / 示例,禁止臆造 API |\n\n两层始终生效:\n\n1. **契约** — 只用 `M*` 与 `--m-*`,API 以 MCP / 文档为准 \n2. **工艺** — 先定表面类型,再做视觉;后台偏克制,落地 / 品牌向可有意表达,但仍上令牌、上组件\n\n## 页面类型(Surface)地图\n\n| 车道 | 典型表面 | 优先参考 |\n| --- | --- | --- |\n| **Ops** | 列表、表单、仪表盘、详情、设置、筛选抽屉 | 黄金样例 + skill `page-layouts` |\n| **Account** | 登录、注册、邀请、重置密码、个人资料 | skill `surfaces` § Account |\n| **Flow** | 引导、空状态、向导、成功页 | skill `surfaces` § Flow |\n| **System** | 404、无权限、维护中 | skill `surfaces` § System |\n| **Express** | 营销落地、定价、功能展示 | skill `surfaces` + `visual-craft` |\n| **Overlay** | 以 Dialog / Drawer / CommandMenu 为主界面 | skill `surfaces` § Overlay |\n\n不确定时:后台默认 Ops → 最近黄金样例;对外营销 → Express。\n\n## Agent 推荐工作流(摘要)\n\n1. 钉死主体、受众、表面、第一屏单一任务 \n2. 优先 MCP:`recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. 无 MCP 时读 skill `references/`(布局、表面、反馈) \n4. 反馈默认 `message`;`toast` 仅 summary+detail / 异步感。表单常驻错误用字段 `errorMessage` 或 token 样式的 `role=\"alert\"`,不要把 `<MMessage>` 当成内嵌 Alert。表格行数据用 `rows`。交付前默认做一轮 craft(Ops polish / 氛围配方,见 skill `visual-craft`)。 \n5. 交付前对照 skill 检查清单;有 MCP 时跑 `validate_page`\n\n细节与硬边界以项目内 `SKILL.md` 为准,本文不重复全文。\n\n## 下一步\n\n- [一键接入](/docs/setup):安装 skill 与其它配置 \n- [AI 接入](/docs/ai-setup):用 AI 生成页面时的流程 \n- [Agent MCP](/docs/mcp):工具与客户端配置 \n- [快速上手](/docs/quick-start):手写安装组件库 \n- [组件](/components):浏览 API\n",
26001
26001
  "sections": [
26002
26002
  {
26003
26003
  "title": "",
@@ -26007,7 +26007,7 @@
26007
26007
  {
26008
26008
  "title": "装到哪里",
26009
26009
  "id": "装到哪里",
26010
- "body": "```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # 布局、表面、令牌、反馈、检查清单等\n```\n\n支持 Agent Skills 自动发现的客户端(如 Cursor)会从 `.agents/skills` 读取。生成列表 / 表单 / 登录 / 落地等页面前,应优先匹配本 skill。\n\n源文件在仓库 [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages),随 `@morya-ui/setup` 的 template 同步。"
26010
+ "body": "```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # 布局、表面、令牌、反馈、检查清单等\n```\n\n支持 Agent Skills 自动发现的客户端(如 Cursor)会从 `.agents/skills` 读取。生成列表 / 表单 / 登录 / 落地等页面前,应优先匹配本 skill。\n\n源文件在仓库 [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages),随 `@morya-ui/setup` 的 template 同步。可选 companion(`frontend-design`、`fixing-accessibility`)可用 `npx @morya-ui/setup ai --skills=…` 一并写入,见 [一键接入](/docs/setup)。"
26011
26011
  },
26012
26012
  {
26013
26013
  "title": "何时触发",
@@ -26027,7 +26027,7 @@
26027
26027
  {
26028
26028
  "title": "Agent 推荐工作流(摘要)",
26029
26029
  "id": "agent-推荐工作流-摘要",
26030
- "body": "1. 钉死主体、受众、表面、第一屏单一任务 \n2. 优先 MCP:`recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. 无 MCP 时读 skill `references/`(布局、表面、反馈) \n4. 反馈默认 `message`;`toast` 仅 summary+detail / 异步感(见 skill `references/feedback.md`) \n5. 交付前对照 skill 检查清单;有 MCP 时跑 `validate_page`\n\n细节与硬边界以项目内 `SKILL.md` 为准,本文不重复全文。"
26030
+ "body": "1. 钉死主体、受众、表面、第一屏单一任务 \n2. 优先 MCP:`recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. 无 MCP 时读 skill `references/`(布局、表面、反馈) \n4. 反馈默认 `message`;`toast` 仅 summary+detail / 异步感。表单常驻错误用字段 `errorMessage` 或 token 样式的 `role=\"alert\"`,不要把 `<MMessage>` 当成内嵌 Alert。表格行数据用 `rows`。交付前默认做一轮 craft(Ops polish / 氛围配方,见 skill `visual-craft`)。 \n5. 交付前对照 skill 检查清单;有 MCP 时跑 `validate_page`\n\n细节与硬边界以项目内 `SKILL.md` 为准,本文不重复全文。"
26031
26031
  },
26032
26032
  {
26033
26033
  "title": "下一步",
@@ -26039,7 +26039,7 @@
26039
26039
  "en-US": {
26040
26040
  "title": "Agent Skill",
26041
26041
  "description": "Consumer morya-ui-pages skill — when it triggers, vs rules/MCP, and the surface map.",
26042
- "markdown": "---\ntitle: Agent Skill\norder: 12\ndescription: Consumer morya-ui-pages skill — when it triggers, vs rules/MCP, and the surface map.\n---\n\n# Agent Skill\n\nWhen AI generates **morya-ui consumer pages**, load the **`morya-ui-pages`** skill. It defines the component contract, surface types, and workflow. It is **not** for authoring new components inside the library source.\n\nInstall via [One-shot setup](/docs/setup) (`npx @morya-ui/setup` copies it into the project); AI workflow: [AI setup](/docs/ai-setup). This page explains **what it is, when to use it, and how it relates to other config**.\n\n## Where it lives\n\n```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # layouts, surfaces, tokens, feedback, checklist, …\n```\n\nClients that auto-discover Agent Skills (e.g. Cursor) read `.agents/skills`. Prefer this skill before generating list / form / login / landing pages.\n\nSource: [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages), synced into the `@morya-ui/setup` template.\n\n## When it triggers\n\nTypical topics:\n\n- `morya-ui`, `M*` components, `--m-*` tokens, golden pages\n- Admin list / form / dashboard / detail / settings\n- Login / register / empty state / wizard / landing / marketing site\n\n**Prefer over** generic `frontend-design`, Impeccable, or UI-UX-Pro-Max when the stack is morya-ui — those may inform taste only.\n\n**Do not** use for backend-only work or for adding components under this repo’s `src/components`.\n\n## How it relates to other config\n\n| Layer | Role |\n| --- | --- |\n| [One-shot setup](/docs/setup) / `@morya-ui/setup` | One-shot install of library + skill + rules + MCP |\n| [AI setup](/docs/ai-setup) | How to use the Agent after install |\n| **`morya-ui-pages` skill** | On-demand workflow: pick surface, golden pages, compose `M*`, review |\n| `.cursor/rules/` | Always-on short editor rules |\n| `DESIGN.md` | Project design source of truth; wins over skill on conflict |\n| [Agent MCP](/docs/mcp) | Runtime lookup of real props / events / examples |\n\nTwo layers always apply:\n\n1. **Contract** — only `M*` and `--m-*`; APIs from MCP / docs \n2. **Craft** — pick the surface first; Ops stays restrained; Express may take intentional aesthetic risk on-token and on-component\n\n## Surface map\n\n| Lane | Surfaces | Prefer |\n| --- | --- | --- |\n| **Ops** | list, form, dashboard, detail, settings, filter drawer | Golden pages + skill `page-layouts` |\n| **Account** | login, register, invite, reset password, profile | skill `surfaces` § Account |\n| **Flow** | onboarding, empty, wizard, success | skill `surfaces` § Flow |\n| **System** | 404, permission denied, maintenance | skill `surfaces` § System |\n| **Express** | marketing landing, pricing, feature showcase | skill `surfaces` + `visual-craft` |\n| **Overlay** | Dialog / Drawer / CommandMenu as the main UI | skill `surfaces` § Overlay |\n\nUnclear brief → Ops → nearest golden page; public marketing → Express.\n\n## Recommended agent workflow (summary)\n\n1. Pin subject, audience, surface, and the first viewport’s single job \n2. Prefer MCP: `recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. Without MCP, read skill `references/` (layouts, surfaces, feedback) \n4. Feedback defaults to `message`; `toast` only for summary+detail / async feel \n5. Review with the skill checklist; run MCP `validate_page` when available \n\nFull rules and hard boundaries live in the project’s `SKILL.md` — this page does not duplicate it.\n\n## Next steps\n\n- [One-shot setup](/docs/setup): install the skill and related config \n- [AI setup](/docs/ai-setup): AI page-generation workflow \n- [Agent MCP](/docs/mcp): tools and client config \n- [Quick start](/docs/quick-start): manual library install \n- [Components](/components): browse APIs\n",
26042
+ "markdown": "---\ntitle: Agent Skill\norder: 12\ndescription: Consumer morya-ui-pages skill — when it triggers, vs rules/MCP, and the surface map.\n---\n\n# Agent Skill\n\nWhen AI generates **morya-ui consumer pages**, load the **`morya-ui-pages`** skill. It defines the component contract, surface types, and workflow. It is **not** for authoring new components inside the library source.\n\nInstall via [One-shot setup](/docs/setup) (`npx @morya-ui/setup` copies it into the project); AI workflow: [AI setup](/docs/ai-setup). This page explains **what it is, when to use it, and how it relates to other config**.\n\n## Where it lives\n\n```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # layouts, surfaces, tokens, feedback, checklist, …\n```\n\nClients that auto-discover Agent Skills (e.g. Cursor) read `.agents/skills`. Prefer this skill before generating list / form / login / landing pages.\n\nSource: [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages), synced into the `@morya-ui/setup` template. Optional companions (`frontend-design`, `fixing-accessibility`) can be installed with `npx @morya-ui/setup ai --skills=…` — see [One-shot setup](/docs/setup).\n\n## When it triggers\n\nTypical topics:\n\n- `morya-ui`, `M*` components, `--m-*` tokens, golden pages\n- Admin list / form / dashboard / detail / settings\n- Login / register / empty state / wizard / landing / marketing site\n\n**Prefer over** generic `frontend-design`, Impeccable, or UI-UX-Pro-Max when the stack is morya-ui — those may inform taste only.\n\n**Do not** use for backend-only work or for adding components under this repo’s `src/components`.\n\n## How it relates to other config\n\n| Layer | Role |\n| --- | --- |\n| [One-shot setup](/docs/setup) / `@morya-ui/setup` | One-shot install of library + skill + rules + MCP |\n| [AI setup](/docs/ai-setup) | How to use the Agent after install |\n| **`morya-ui-pages` skill** | On-demand workflow: pick surface, golden pages, compose `M*`, review |\n| `.cursor/rules/` | Always-on short editor rules |\n| `DESIGN.md` | Project design source of truth; wins over skill on conflict |\n| [Agent MCP](/docs/mcp) | Runtime lookup of real props / events / examples |\n\nTwo layers always apply:\n\n1. **Contract** — only `M*` and `--m-*`; APIs from MCP / docs \n2. **Craft** — pick the surface first; Ops stays restrained; Express may take intentional aesthetic risk on-token and on-component\n\n## Surface map\n\n| Lane | Surfaces | Prefer |\n| --- | --- | --- |\n| **Ops** | list, form, dashboard, detail, settings, filter drawer | Golden pages + skill `page-layouts` |\n| **Account** | login, register, invite, reset password, profile | skill `surfaces` § Account |\n| **Flow** | onboarding, empty, wizard, success | skill `surfaces` § Flow |\n| **System** | 404, permission denied, maintenance | skill `surfaces` § System |\n| **Express** | marketing landing, pricing, feature showcase | skill `surfaces` + `visual-craft` |\n| **Overlay** | Dialog / Drawer / CommandMenu as the main UI | skill `surfaces` § Overlay |\n\nUnclear brief → Ops → nearest golden page; public marketing → Express.\n\n## Recommended agent workflow (summary)\n\n1. Pin subject, audience, surface, and the first viewport’s single job \n2. Prefer MCP: `recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. Without MCP, read skill `references/` (layouts, surfaces, feedback) \n4. Feedback defaults to `message`; `toast` only for summary+detail / async feel. Persistent form errors use field `errorMessage` or a token-styled `role=\"alert\"` — `<MMessage>` is not an inline alert. Table rows use `rows`. Always run a light craft pass before delivery (Ops polish / atmosphere — see skill `visual-craft`). \n5. Review with the skill checklist; run MCP `validate_page` when available \n\nFull rules and hard boundaries live in the project’s `SKILL.md` — this page does not duplicate it.\n\n## Next steps\n\n- [One-shot setup](/docs/setup): install the skill and related config \n- [AI setup](/docs/ai-setup): AI page-generation workflow \n- [Agent MCP](/docs/mcp): tools and client config \n- [Quick start](/docs/quick-start): manual library install \n- [Components](/components): browse APIs\n",
26043
26043
  "sections": [
26044
26044
  {
26045
26045
  "title": "",
@@ -26049,7 +26049,7 @@
26049
26049
  {
26050
26050
  "title": "Where it lives",
26051
26051
  "id": "where-it-lives",
26052
- "body": "```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # layouts, surfaces, tokens, feedback, checklist, …\n```\n\nClients that auto-discover Agent Skills (e.g. Cursor) read `.agents/skills`. Prefer this skill before generating list / form / login / landing pages.\n\nSource: [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages), synced into the `@morya-ui/setup` template."
26052
+ "body": "```text\n.agents/skills/morya-ui-pages/\n├── SKILL.md\n└── references/ # layouts, surfaces, tokens, feedback, checklist, …\n```\n\nClients that auto-discover Agent Skills (e.g. Cursor) read `.agents/skills`. Prefer this skill before generating list / form / login / landing pages.\n\nSource: [`design-kit/.agents/skills/morya-ui-pages/`](https://github.com/morya-space/morya-ui/tree/main/design-kit/.agents/skills/morya-ui-pages), synced into the `@morya-ui/setup` template. Optional companions (`frontend-design`, `fixing-accessibility`) can be installed with `npx @morya-ui/setup ai --skills=…` — see [One-shot setup](/docs/setup)."
26053
26053
  },
26054
26054
  {
26055
26055
  "title": "When it triggers",
@@ -26069,7 +26069,7 @@
26069
26069
  {
26070
26070
  "title": "Recommended agent workflow (summary)",
26071
26071
  "id": "recommended-agent-workflow-summary",
26072
- "body": "1. Pin subject, audience, surface, and the first viewport’s single job \n2. Prefer MCP: `recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. Without MCP, read skill `references/` (layouts, surfaces, feedback) \n4. Feedback defaults to `message`; `toast` only for summary+detail / async feel \n5. Review with the skill checklist; run MCP `validate_page` when available \n\nFull rules and hard boundaries live in the project’s `SKILL.md` — this page does not duplicate it."
26072
+ "body": "1. Pin subject, audience, surface, and the first viewport’s single job \n2. Prefer MCP: `recommend_page` → `get_golden_page` → `get_component` / `get_example` \n3. Without MCP, read skill `references/` (layouts, surfaces, feedback) \n4. Feedback defaults to `message`; `toast` only for summary+detail / async feel. Persistent form errors use field `errorMessage` or a token-styled `role=\"alert\"` — `<MMessage>` is not an inline alert. Table rows use `rows`. Always run a light craft pass before delivery (Ops polish / atmosphere — see skill `visual-craft`). \n5. Review with the skill checklist; run MCP `validate_page` when available \n\nFull rules and hard boundaries live in the project’s `SKILL.md` — this page does not duplicate it."
26073
26073
  },
26074
26074
  {
26075
26075
  "title": "Next steps",
@@ -26091,7 +26091,7 @@
26091
26091
  "zh-CN": {
26092
26092
  "title": "Agent MCP",
26093
26093
  "description": "可选的 MCP 服务,供支持 Model Context Protocol 的 AI 客户端检索本库文档。",
26094
- "markdown": "---\ntitle: Agent MCP\norder: 13\ndescription: 可选的 MCP 服务,供支持 Model Context Protocol 的 AI 客户端检索本库文档。\n---\n\n# Agent MCP\n\n[`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp) 是可选的 [Model Context Protocol](https://modelcontextprotocol.io/)(stdio)服务。它把本站组件文档、示例与指南做成可检索工具,方便 **支持 MCP 的 AI 客户端** 按真实 API 生成代码。\n\n日常使用组件库 **不需要** 安装或配置 MCP。应用里仍然只依赖:\n\n```bash\npnpm add morya-ui\n```\n\n```ts\nimport 'morya-ui/styles.css'\n```\n\n若要连同 Agent Skill、Cursor 规则一起装好,见 [一键接入](/docs/setup);AI 流程见 [AI 接入](/docs/ai-setup);Skill 本身说明见 [Agent Skill](/docs/agent-skill)。\n\n## 接入方式\n\nMCP 客户端通过 stdio 启动本包即可:\n\n```bash\nnpx -y @morya-ui/mcp\n```\n\n通用写法:\n\n```json\n{\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n}\n```\n\n字段名因客户端而异,只要支持 MCP stdio 即可接入。\n\n### 常见客户端配置示例\n\n以下为常见产品的配置片段,键名可能随版本变化,以各产品官方文档为准。\n\n**Cursor**(`.cursor/mcp.json` 或用户级 MCP 配置):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Claude Desktop / Claude Code**(`claude_desktop_config.json` 等):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Windsurf**(MCP 设置中的 servers 配置):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Cline**(VS Code 扩展设置中的 MCP servers):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Zed**(`settings.json` → `context_servers`):\n\n```json\n{\n \"context_servers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Continue**(`config.json` / YAML 中的 MCP servers,字段名以当前版本为准):\n\n```json\n{\n \"mcpServers\": [\n {\n \"name\": \"morya-ui\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n ]\n}\n```\n\n## 可用工具\n\n### 基础 — 查组件文档\n\n| 工具 | 作用 |\n| --- | --- |\n| `list` | 列出组件 / 指南 / 示例 / 分类 / 页面模式 |\n| `search` | 搜索文档、示例、页面模式与组件选型指南 |\n| `get_component` | 读取组件说明与 API |\n| `get_example` | 获取源码示例 |\n| `get_guide` | 读取指南 |\n| `get_setup` | 安装与初始化说明 |\n| `validate_usage` | 对照文档粗检 props / events 用法 |\n| `version` | 版本与目录状态 |\n\n### 高级 — 页面组合(可选)\n\n| 工具 | 作用 |\n| --- | --- |\n| `list_patterns` | 列出可复用的页面组合模式 |\n| `get_pattern` | 读取模式的结构、布局与交互规则 |\n| `recommend_page` | 根据页面意图推荐模式;可附带 starter 脚手架 |\n| `get_design_rules` | 设计令牌与 MPage* 组合配方 |\n| `recommend_component` | 列出、阅读或推荐组件选型指南 |\n| `list_golden_pages` | 列出黄金样例页面 |\n| `get_golden_page` | 读取黄金样例 Vue 源码 |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距与双边框问题 |\n\n多数工具支持 `mode`:`zh`(默认)或 `en`。\n\n### 推荐工作流\n\n**查单个组件:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**规划整页:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`\n\n**改局部区块:** `get_page_snippet(section)` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\n需要 starter 代码时,给 `recommend_page` 传 `includeScaffold: true`:\n\n```json\n{\n \"intent\": \"油井管理列表\",\n \"pageType\": \"list\",\n \"features\": [\"筛选\", \"新增\", \"分页\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` 用法:\n\n- 不传 `query` 和 `decision` → 列出全部选型指南\n- 只传 `decision`(如 `overlay-choice`)→ 阅读某一指南\n- 传 `query` → 根据问题推荐组件\n\n## 对话示例\n\n接入后,可直接让助手调用本服务,例如:\n\n> 用 morya-ui 的 MCP 查一下 Dialog 的 props,并给一个带确认 / 取消按钮的示例。\n\n> 搜索和「日期」相关的组件,选一个适合表单的,按文档写出最小用法。\n\n> 根据 MCP 里 Button 的文档,写一个 `severity=\"danger\"` 的删除按钮,并校验 props 是否合法。\n\n助手应先调用工具,再基于返回内容生成类似:\n\n```vue\n<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <MButton label=\"删除\" severity=\"danger\" />\n</template>\n```\n\n## 与文档站的关系\n\n目录与本站同源(组件 `docs/` + 指南 Markdown)。官网文档更新后,维护者重新发布 `@morya-ui/mcp`,客户端通过 `npx -y` 即可拿到新版本。\n\n更多实现细节见仓库内 [packages/ui-mcp/README.md](https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp)。\n\n## 下一步\n\n- [AI 接入](/docs/ai-setup):`npx @morya-ui/setup`、skill 与 Cursor MCP\n- [Agent Skill](/docs/agent-skill):`morya-ui-pages` 何时用、表面地图\n- [快速上手](/docs/quick-start):在应用中安装并使用组件\n- [组件](/components):浏览全部组件与交互示例\n",
26094
+ "markdown": "---\ntitle: Agent MCP\norder: 13\ndescription: 可选的 MCP 服务,供支持 Model Context Protocol 的 AI 客户端检索本库文档。\n---\n\n# Agent MCP\n\n[`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp) 是可选的 [Model Context Protocol](https://modelcontextprotocol.io/)(stdio)服务。它把本站组件文档、示例与指南做成可检索工具,方便 **支持 MCP 的 AI 客户端** 按真实 API 生成代码。\n\n日常使用组件库 **不需要** 安装或配置 MCP。应用里仍然只依赖:\n\n```bash\npnpm add morya-ui\n```\n\n```ts\nimport 'morya-ui/styles.css'\n```\n\n若要连同 Agent Skill、Cursor 规则一起装好,见 [一键接入](/docs/setup);AI 流程见 [AI 接入](/docs/ai-setup);Skill 本身说明见 [Agent Skill](/docs/agent-skill)。\n\n## 接入方式\n\nMCP 客户端通过 stdio 启动本包即可:\n\n```bash\nnpx -y @morya-ui/mcp\n```\n\n通用写法:\n\n```json\n{\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n}\n```\n\n字段名因客户端而异,只要支持 MCP stdio 即可接入。\n\n### 常见客户端配置示例\n\n以下为常见产品的配置片段,键名可能随版本变化,以各产品官方文档为准。\n\n**Cursor**(`.cursor/mcp.json` 或用户级 MCP 配置):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Claude Desktop / Claude Code**(`claude_desktop_config.json` 等):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Windsurf**(MCP 设置中的 servers 配置):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Cline**(VS Code 扩展设置中的 MCP servers):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Zed**(`settings.json` → `context_servers`):\n\n```json\n{\n \"context_servers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Continue**(`config.json` / YAML 中的 MCP servers,字段名以当前版本为准):\n\n```json\n{\n \"mcpServers\": [\n {\n \"name\": \"morya-ui\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n ]\n}\n```\n\n## 可用工具\n\n### 基础 — 查组件文档\n\n| 工具 | 作用 |\n| --- | --- |\n| `list` | 列出组件 / 指南 / 示例 / 分类 / 页面模式 |\n| `search` | 搜索文档、示例、页面模式与组件选型指南 |\n| `get_component` | 读取组件说明与 API |\n| `get_example` | 获取源码示例 |\n| `get_guide` | 读取指南 |\n| `get_setup` | 安装与初始化说明 |\n| `validate_usage` | 对照文档粗检 props / events 用法 |\n| `version` | 版本与目录状态 |\n\n### 高级 — 页面组合(可选)\n\n| 工具 | 作用 |\n| --- | --- |\n| `list_patterns` | 列出可复用的页面组合模式 |\n| `get_pattern` | 读取模式的结构、布局与交互规则 |\n| `recommend_page` | 根据页面意图推荐模式;可附带 starter 脚手架 |\n| `get_design_rules` | 设计令牌与 MPage* 组合配方 |\n| `recommend_component` | 列出、阅读或推荐组件选型指南 |\n| `list_golden_pages` | 列出黄金样例页面 |\n| `get_golden_page` | 读取黄金样例 Vue 源码 |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距与双边框问题 |\n\n多数工具支持 `mode`:`zh`(默认)或 `en`。\n\n### 推荐工作流\n\n**查单个组件:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**规划整页:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`\n\n**改局部区块:** `get_page_snippet(section)` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\n需要 starter 代码时,给 `recommend_page` 传 `includeScaffold: true`:\n\n```json\n{\n \"intent\": \"油井管理列表\",\n \"pageType\": \"list\",\n \"features\": [\"筛选\", \"新增\", \"分页\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` 用法:\n\n- 不传 `query` 和 `decision` → 列出全部选型指南\n- 只传 `decision` 阅读某一指南\n- 传 `query` → 根据问题推荐组件\n\n当前指南包括:`form-surface-choice`、`overlay-choice`、`data-display-choice`、`selection-choice`(含 Select / TreeSelect / CascadeSelect / Listbox / SelectButton / Radio / AutoComplete)、`status-label-choice`、`empty-result-choice`、`action-menu-choice`、`loading-choice`、`page-scroll-choice`、`surface-choice`、`page-section-choice`、`layout-spacing-choice`、`surface-nesting-choice`。\n\n## 对话示例\n\n接入后,可直接让助手调用本服务,例如:\n\n> 用 morya-ui 的 MCP 查一下 Dialog 的 props,并给一个带确认 / 取消按钮的示例。\n\n> 搜索和「日期」相关的组件,选一个适合表单的,按文档写出最小用法。\n\n> 根据 MCP 里 Button 的文档,写一个 `severity=\"danger\"` 的删除按钮,并校验 props 是否合法。\n\n助手应先调用工具,再基于返回内容生成类似:\n\n```vue\n<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <MButton label=\"删除\" severity=\"danger\" />\n</template>\n```\n\n## 与文档站的关系\n\n目录与本站同源(组件 `docs/` + 指南 Markdown)。官网文档更新后,维护者重新发布 `@morya-ui/mcp`,客户端通过 `npx -y` 即可拿到新版本。\n\n更多实现细节见仓库内 [packages/ui-mcp/README.md](https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp)。\n\n## 下一步\n\n- [AI 接入](/docs/ai-setup):`npx @morya-ui/setup`、skill 与 Cursor MCP\n- [Agent Skill](/docs/agent-skill):`morya-ui-pages` 何时用、表面地图\n- [快速上手](/docs/quick-start):在应用中安装并使用组件\n- [组件](/components):浏览全部组件与交互示例\n",
26095
26095
  "sections": [
26096
26096
  {
26097
26097
  "title": "",
@@ -26106,7 +26106,7 @@
26106
26106
  {
26107
26107
  "title": "可用工具",
26108
26108
  "id": "可用工具",
26109
- "body": "### 基础 — 查组件文档\n\n| 工具 | 作用 |\n| --- | --- |\n| `list` | 列出组件 / 指南 / 示例 / 分类 / 页面模式 |\n| `search` | 搜索文档、示例、页面模式与组件选型指南 |\n| `get_component` | 读取组件说明与 API |\n| `get_example` | 获取源码示例 |\n| `get_guide` | 读取指南 |\n| `get_setup` | 安装与初始化说明 |\n| `validate_usage` | 对照文档粗检 props / events 用法 |\n| `version` | 版本与目录状态 |\n\n### 高级 — 页面组合(可选)\n\n| 工具 | 作用 |\n| --- | --- |\n| `list_patterns` | 列出可复用的页面组合模式 |\n| `get_pattern` | 读取模式的结构、布局与交互规则 |\n| `recommend_page` | 根据页面意图推荐模式;可附带 starter 脚手架 |\n| `get_design_rules` | 设计令牌与 MPage* 组合配方 |\n| `recommend_component` | 列出、阅读或推荐组件选型指南 |\n| `list_golden_pages` | 列出黄金样例页面 |\n| `get_golden_page` | 读取黄金样例 Vue 源码 |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距与双边框问题 |\n\n多数工具支持 `mode`:`zh`(默认)或 `en`。\n\n### 推荐工作流\n\n**查单个组件:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**规划整页:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`\n\n**改局部区块:** `get_page_snippet(section)` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\n需要 starter 代码时,给 `recommend_page` 传 `includeScaffold: true`:\n\n```json\n{\n \"intent\": \"油井管理列表\",\n \"pageType\": \"list\",\n \"features\": [\"筛选\", \"新增\", \"分页\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` 用法:\n\n- 不传 `query` 和 `decision` → 列出全部选型指南\n- 只传 `decision`(如 `overlay-choice`)→ 阅读某一指南\n- 传 `query` → 根据问题推荐组件"
26109
+ "body": "### 基础 — 查组件文档\n\n| 工具 | 作用 |\n| --- | --- |\n| `list` | 列出组件 / 指南 / 示例 / 分类 / 页面模式 |\n| `search` | 搜索文档、示例、页面模式与组件选型指南 |\n| `get_component` | 读取组件说明与 API |\n| `get_example` | 获取源码示例 |\n| `get_guide` | 读取指南 |\n| `get_setup` | 安装与初始化说明 |\n| `validate_usage` | 对照文档粗检 props / events 用法 |\n| `version` | 版本与目录状态 |\n\n### 高级 — 页面组合(可选)\n\n| 工具 | 作用 |\n| --- | --- |\n| `list_patterns` | 列出可复用的页面组合模式 |\n| `get_pattern` | 读取模式的结构、布局与交互规则 |\n| `recommend_page` | 根据页面意图推荐模式;可附带 starter 脚手架 |\n| `get_design_rules` | 设计令牌与 MPage* 组合配方 |\n| `recommend_component` | 列出、阅读或推荐组件选型指南 |\n| `list_golden_pages` | 列出黄金样例页面 |\n| `get_golden_page` | 读取黄金样例 Vue 源码 |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距与双边框问题 |\n\n多数工具支持 `mode`:`zh`(默认)或 `en`。\n\n### 推荐工作流\n\n**查单个组件:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**规划整页:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`\n\n**改局部区块:** `get_page_snippet(section)` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\n需要 starter 代码时,给 `recommend_page` 传 `includeScaffold: true`:\n\n```json\n{\n \"intent\": \"油井管理列表\",\n \"pageType\": \"list\",\n \"features\": [\"筛选\", \"新增\", \"分页\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` 用法:\n\n- 不传 `query` 和 `decision` → 列出全部选型指南\n- 只传 `decision` 阅读某一指南\n- 传 `query` → 根据问题推荐组件\n\n当前指南包括:`form-surface-choice`、`overlay-choice`、`data-display-choice`、`selection-choice`(含 Select / TreeSelect / CascadeSelect / Listbox / SelectButton / Radio / AutoComplete)、`status-label-choice`、`empty-result-choice`、`action-menu-choice`、`loading-choice`、`page-scroll-choice`、`surface-choice`、`page-section-choice`、`layout-spacing-choice`、`surface-nesting-choice`。"
26110
26110
  },
26111
26111
  {
26112
26112
  "title": "对话示例",
@@ -26128,7 +26128,7 @@
26128
26128
  "en-US": {
26129
26129
  "title": "Agent MCP",
26130
26130
  "description": "Optional MCP server for AI clients that support the Model Context Protocol.",
26131
- "markdown": "---\ntitle: Agent MCP\norder: 13\ndescription: Optional MCP server for AI clients that support the Model Context Protocol.\n---\n\n# Agent MCP\n\n[`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp) is an optional [Model Context Protocol](https://modelcontextprotocol.io/) (stdio) server. It indexes this site’s component docs, examples, and guides so **any MCP-capable AI client** can look up the real API.\n\nYou do **not** need MCP to use the component library. Apps still only depend on:\n\n```bash\npnpm add morya-ui\n```\n\n```ts\nimport 'morya-ui/styles.css'\n```\n\nFor Agent skill, Cursor rules, and writing MCP in one step, see [One-shot setup](/docs/setup). AI workflow: [AI setup](/docs/ai-setup). Skill behavior: [Agent Skill](/docs/agent-skill).\n\n## How to connect\n\nMCP clients start the package over stdio:\n\n```bash\nnpx -y @morya-ui/mcp\n```\n\nGeneric shape:\n\n```json\n{\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n}\n```\n\nField names differ by client. Any client that supports MCP stdio can connect.\n\n### Common client config examples\n\nSnippets for popular products. Key names may change across versions — check each product’s docs.\n\n**Cursor** (`.cursor/mcp.json` or user-level MCP settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Claude Desktop / Claude Code** (`claude_desktop_config.json`, etc.):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Windsurf** (MCP servers in settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Cline** (MCP servers in the VS Code extension settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Zed** (`settings.json` → `context_servers`):\n\n```json\n{\n \"context_servers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Continue** (`config.json` / YAML MCP servers — follow the current schema):\n\n```json\n{\n \"mcpServers\": [\n {\n \"name\": \"morya-ui\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n ]\n}\n```\n\n## Tools\n\n### Core — component docs\n\n| Tool | Purpose |\n| --- | --- |\n| `list` | List components / guides / examples / categories / patterns |\n| `search` | Search docs, examples, patterns, and decision guides |\n| `get_component` | Read component docs and API |\n| `get_example` | Return a source example |\n| `get_guide` | Read a guide |\n| `get_setup` | Install and setup guidance |\n| `validate_usage` | Soft-check usage against documented props/events |\n| `version` | Version and catalog status |\n\n### Advanced — page composition (optional)\n\n| Tool | Purpose |\n| --- | --- |\n| `list_patterns` | List reusable page composition patterns |\n| `get_pattern` | Read a pattern's structure, layout, and rules |\n| `recommend_page` | Recommend a pattern from page intent; optional starter scaffold |\n| `get_design_rules` | Design-token and composition rules |\n| `recommend_component` | List, read, or recommend component selection guides |\n\nMost tools accept `mode`: `zh` (default) or `en`.\n\n### Recommended workflow\n\n**Look up a component:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**Plan a page:** `recommend_page` → `get_pattern` → `get_component` / `get_example` → `get_design_rules`; use `recommend_component` when choosing between similar components\n\nPass `includeScaffold: true` to `recommend_page` for starter Vue code:\n\n```json\n{\n \"intent\": \"Oil well management list\",\n \"pageType\": \"list\",\n \"features\": [\"filters\", \"create\", \"pagination\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` modes:\n\n- omit `query` and `decision` → list decision guides\n- `decision` only (e.g. `overlay-choice`) → read one guide\n- `query` → recommend a component for a UI question\n\n## Prompt examples\n\nAfter connecting, you can ask the assistant to use this server, for example:\n\n> Use the morya-ui MCP to look up Dialog props and give an example with confirm / cancel actions.\n\n> Search for date-related components, pick one suitable for forms, and write a minimal usage from the docs.\n\n> Following the Button docs from MCP, write a delete button with `severity=\"danger\"` and validate the props.\n\nThe assistant should call tools first, then produce something like:\n\n```vue\n<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <MButton label=\"Delete\" severity=\"danger\" />\n</template>\n```\n\n## Relation to this site\n\nThe catalog is generated from the same sources as this site (component `docs/` + guide Markdown). After docs change, maintainers republish `@morya-ui/mcp`; clients using `npx -y` pick up the new release.\n\nImplementation notes live in [packages/ui-mcp/README.md](https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp).\n\n## Next steps\n\n- [One-shot setup](/docs/setup): `npx @morya-ui/setup`\n- [AI setup](/docs/ai-setup): Agent skill and MCP workflow\n- [Agent Skill](/docs/agent-skill): when to use `morya-ui-pages`\n- [Quick start](/docs/quick-start): install and use components in an app\n- [Components](/components): browse live examples and APIs\n",
26131
+ "markdown": "---\ntitle: Agent MCP\norder: 13\ndescription: Optional MCP server for AI clients that support the Model Context Protocol.\n---\n\n# Agent MCP\n\n[`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp) is an optional [Model Context Protocol](https://modelcontextprotocol.io/) (stdio) server. It indexes this site’s component docs, examples, and guides so **any MCP-capable AI client** can look up the real API.\n\nYou do **not** need MCP to use the component library. Apps still only depend on:\n\n```bash\npnpm add morya-ui\n```\n\n```ts\nimport 'morya-ui/styles.css'\n```\n\nFor Agent skill, Cursor rules, and writing MCP in one step, see [One-shot setup](/docs/setup). AI workflow: [AI setup](/docs/ai-setup). Skill behavior: [Agent Skill](/docs/agent-skill).\n\n## How to connect\n\nMCP clients start the package over stdio:\n\n```bash\nnpx -y @morya-ui/mcp\n```\n\nGeneric shape:\n\n```json\n{\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n}\n```\n\nField names differ by client. Any client that supports MCP stdio can connect.\n\n### Common client config examples\n\nSnippets for popular products. Key names may change across versions — check each product’s docs.\n\n**Cursor** (`.cursor/mcp.json` or user-level MCP settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Claude Desktop / Claude Code** (`claude_desktop_config.json`, etc.):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Windsurf** (MCP servers in settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Cline** (MCP servers in the VS Code extension settings):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Zed** (`settings.json` → `context_servers`):\n\n```json\n{\n \"context_servers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Continue** (`config.json` / YAML MCP servers — follow the current schema):\n\n```json\n{\n \"mcpServers\": [\n {\n \"name\": \"morya-ui\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n ]\n}\n```\n\n## Tools\n\n### Core — component docs\n\n| Tool | Purpose |\n| --- | --- |\n| `list` | List components / guides / examples / categories / patterns |\n| `search` | Search docs, examples, patterns, and decision guides |\n| `get_component` | Read component docs and API |\n| `get_example` | Return a source example |\n| `get_guide` | Read a guide |\n| `get_setup` | Install and setup guidance |\n| `validate_usage` | Soft-check usage against documented props/events |\n| `version` | Version and catalog status |\n\n### Advanced — page composition (optional)\n\n| Tool | Purpose |\n| --- | --- |\n| `list_patterns` | List reusable page composition patterns |\n| `get_pattern` | Read a pattern's structure, layout, and rules |\n| `recommend_page` | Recommend a pattern from page intent; optional starter scaffold |\n| `get_design_rules` | Design-token and MPage* composition rules |\n| `recommend_component` | List, read, or recommend component selection guides |\n| `list_golden_pages` | List golden page samples |\n| `get_golden_page` | Read a golden page Vue source (`list-page`, `form-page`, `dashboard-page`, `login-page`, `landing-page`, `empty-state`) |\n| `list_page_snippets` | List reusable page-section snippets |\n| `get_page_snippet` | Read one snippet (filters, toolbar, form actions, …) |\n| `validate_page` | Check page composition, spacing, and double-border issues |\n\nMost tools accept `mode`: `zh` (default) or `en`.\n\nComponent lookup accepts common aliases such as `DataTable`, `数据表格`, `Pager`, and `确认弹窗`.\n\n### Recommended workflow\n\n**Look up a component:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**Plan a page:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`. Use `recommend_component` when choosing between similar components.\n\n**Edit one section:** `list_page_snippets` → `get_page_snippet` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\nPass `includeScaffold: true` to `recommend_page` for starter Vue code:\n\n```json\n{\n \"intent\": \"Oil well management list\",\n \"pageType\": \"list\",\n \"features\": [\"filters\", \"create\", \"pagination\"],\n \"mode\": \"en\",\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` modes:\n\n- omit `query` and `decision` → list decision guides\n- `decision` only → read one guide\n- `query` → recommend a component for a UI question\n\nCurrent guides include `form-surface-choice`, `overlay-choice`, `data-display-choice`, `selection-choice` (Select / TreeSelect / CascadeSelect / Listbox / SelectButton / Radio / AutoComplete), `status-label-choice`, `empty-result-choice`, `action-menu-choice`, `loading-choice`, `page-scroll-choice`, `surface-choice`, `page-section-choice`, `layout-spacing-choice`, and `surface-nesting-choice`.\n\n## Prompt examples\n\nAfter connecting, you can ask the assistant to use this server, for example:\n\n> Use the morya-ui MCP to look up Dialog props and give an example with confirm / cancel actions.\n\n> Search for date-related components, pick one suitable for forms, and write a minimal usage from the docs.\n\n> Following the Button docs from MCP, write a delete button with `severity=\"danger\"` and validate the props.\n\nThe assistant should call tools first, then produce something like:\n\n```vue\n<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <MButton label=\"Delete\" severity=\"danger\" />\n</template>\n```\n\n## Relation to this site\n\nThe catalog is generated from the same sources as this site (component `docs/` + guide Markdown). After docs change, maintainers republish `@morya-ui/mcp`; clients using `npx -y` pick up the new release.\n\nImplementation notes live in [packages/ui-mcp/README.md](https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp).\n\n## Next steps\n\n- [One-shot setup](/docs/setup): `npx @morya-ui/setup`\n- [AI setup](/docs/ai-setup): Agent skill and MCP workflow\n- [Agent Skill](/docs/agent-skill): when to use `morya-ui-pages`\n- [Quick start](/docs/quick-start): install and use components in an app\n- [Components](/components): browse live examples and APIs\n",
26132
26132
  "sections": [
26133
26133
  {
26134
26134
  "title": "",
@@ -26143,7 +26143,7 @@
26143
26143
  {
26144
26144
  "title": "Tools",
26145
26145
  "id": "tools",
26146
- "body": "### Core — component docs\n\n| Tool | Purpose |\n| --- | --- |\n| `list` | List components / guides / examples / categories / patterns |\n| `search` | Search docs, examples, patterns, and decision guides |\n| `get_component` | Read component docs and API |\n| `get_example` | Return a source example |\n| `get_guide` | Read a guide |\n| `get_setup` | Install and setup guidance |\n| `validate_usage` | Soft-check usage against documented props/events |\n| `version` | Version and catalog status |\n\n### Advanced — page composition (optional)\n\n| Tool | Purpose |\n| --- | --- |\n| `list_patterns` | List reusable page composition patterns |\n| `get_pattern` | Read a pattern's structure, layout, and rules |\n| `recommend_page` | Recommend a pattern from page intent; optional starter scaffold |\n| `get_design_rules` | Design-token and composition rules |\n| `recommend_component` | List, read, or recommend component selection guides |\n\nMost tools accept `mode`: `zh` (default) or `en`.\n\n### Recommended workflow\n\n**Look up a component:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**Plan a page:** `recommend_page` → `get_pattern` → `get_component` / `get_example` → `get_design_rules`; use `recommend_component` when choosing between similar components\n\nPass `includeScaffold: true` to `recommend_page` for starter Vue code:\n\n```json\n{\n \"intent\": \"Oil well management list\",\n \"pageType\": \"list\",\n \"features\": [\"filters\", \"create\", \"pagination\"],\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` modes:\n\n- omit `query` and `decision` → list decision guides\n- `decision` only (e.g. `overlay-choice`) → read one guide\n- `query` → recommend a component for a UI question"
26146
+ "body": "### Core — component docs\n\n| Tool | Purpose |\n| --- | --- |\n| `list` | List components / guides / examples / categories / patterns |\n| `search` | Search docs, examples, patterns, and decision guides |\n| `get_component` | Read component docs and API |\n| `get_example` | Return a source example |\n| `get_guide` | Read a guide |\n| `get_setup` | Install and setup guidance |\n| `validate_usage` | Soft-check usage against documented props/events |\n| `version` | Version and catalog status |\n\n### Advanced — page composition (optional)\n\n| Tool | Purpose |\n| --- | --- |\n| `list_patterns` | List reusable page composition patterns |\n| `get_pattern` | Read a pattern's structure, layout, and rules |\n| `recommend_page` | Recommend a pattern from page intent; optional starter scaffold |\n| `get_design_rules` | Design-token and MPage* composition rules |\n| `recommend_component` | List, read, or recommend component selection guides |\n| `list_golden_pages` | List golden page samples |\n| `get_golden_page` | Read a golden page Vue source (`list-page`, `form-page`, `dashboard-page`, `login-page`, `landing-page`, `empty-state`) |\n| `list_page_snippets` | List reusable page-section snippets |\n| `get_page_snippet` | Read one snippet (filters, toolbar, form actions, …) |\n| `validate_page` | Check page composition, spacing, and double-border issues |\n\nMost tools accept `mode`: `zh` (default) or `en`.\n\nComponent lookup accepts common aliases such as `DataTable`, `数据表格`, `Pager`, and `确认弹窗`.\n\n### Recommended workflow\n\n**Look up a component:** `search` / `get_component` → `get_example` → `validate_usage`\n\n**Plan a page:** `recommend_page` → `get_golden_page` → `get_pattern` → `get_design_rules` → `get_component` / `get_example` → `validate_page`. Use `recommend_component` when choosing between similar components.\n\n**Edit one section:** `list_page_snippets` → `get_page_snippet` → `get_component` / `get_example` → `validate_usage` → `validate_page`\n\nPass `includeScaffold: true` to `recommend_page` for starter Vue code:\n\n```json\n{\n \"intent\": \"Oil well management list\",\n \"pageType\": \"list\",\n \"features\": [\"filters\", \"create\", \"pagination\"],\n \"mode\": \"en\",\n \"includeScaffold\": true\n}\n```\n\n`recommend_component` modes:\n\n- omit `query` and `decision` → list decision guides\n- `decision` only → read one guide\n- `query` → recommend a component for a UI question\n\nCurrent guides include `form-surface-choice`, `overlay-choice`, `data-display-choice`, `selection-choice` (Select / TreeSelect / CascadeSelect / Listbox / SelectButton / Radio / AutoComplete), `status-label-choice`, `empty-result-choice`, `action-menu-choice`, `loading-choice`, `page-scroll-choice`, `surface-choice`, `page-section-choice`, `layout-spacing-choice`, and `surface-nesting-choice`."
26147
26147
  },
26148
26148
  {
26149
26149
  "title": "Prompt examples",