@morya-ui/mcp 0.4.1 → 0.4.2

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-10-08T08:29:10.652Z",
2
+ "generatedAt": "2026-10-09T09:31:59.453Z",
3
3
  "library": {
4
4
  "name": "morya-ui",
5
- "version": "0.4.1"
5
+ "version": "0.4.2"
6
6
  },
7
7
  "mcp": {
8
8
  "name": "@morya-ui/mcp",
9
- "version": "0.4.1"
9
+ "version": "0.4.2"
10
10
  },
11
11
  "components": [
12
12
  {
@@ -101,7 +101,7 @@
101
101
  "sectionId": "extra",
102
102
  "lang": "vue",
103
103
  "preview": true,
104
- "code": "<script setup lang=\"ts\">\nimport { MAccordion, MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = [\n { value: 'a', header: 'Section A' },\n]\n</script>\n\n<template>\n <MAccordion v-model=\"active\" :tabs=\"tabs\">\n <template #extra=\"{ tab }\">\n <MButton :label=\"tab.header\" size=\"small\" text />\n </template>\n <template #a>\n <p style=\"margin:0\">\n Content.\n </p>\n </template>\n </MAccordion>\n</template>",
104
+ "code": "<script setup lang=\"ts\">\nimport { MAccordion, MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = [\n { value: 'a', header: 'Section A' },\n]\n</script>\n\n<template>\n <MAccordion v-model=\"active\" :tabs=\"tabs\">\n <template #extra=\"{ tab }\">\n <MButton :label=\"tab.header\" size=\"small\" type=\"text\"/>\n </template>\n <template #a>\n <p style=\"margin:0\">\n Content.\n </p>\n </template>\n </MAccordion>\n</template>",
105
105
  "locale": "zh-CN"
106
106
  },
107
107
  {
@@ -137,7 +137,7 @@
137
137
  "sectionId": "extra",
138
138
  "lang": "vue",
139
139
  "preview": true,
140
- "code": "<script setup lang=\"ts\">\nimport { MAccordion, MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = [\n { value: 'a', header: 'Section A' },\n]\n</script>\n\n<template>\n <MAccordion v-model=\"active\" :tabs=\"tabs\">\n <template #extra=\"{ tab }\">\n <MButton :label=\"tab.header\" size=\"small\" text />\n </template>\n <template #a>\n <p style=\"margin:0\">\n Content.\n </p>\n </template>\n </MAccordion>\n</template>",
140
+ "code": "<script setup lang=\"ts\">\nimport { MAccordion, MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = [\n { value: 'a', header: 'Section A' },\n]\n</script>\n\n<template>\n <MAccordion v-model=\"active\" :tabs=\"tabs\">\n <template #extra=\"{ tab }\">\n <MButton :label=\"tab.header\" size=\"small\" type=\"text\"/>\n </template>\n <template #a>\n <p style=\"margin:0\">\n Content.\n </p>\n </template>\n </MAccordion>\n</template>",
141
141
  "locale": "en-US"
142
142
  }
143
143
  ],
@@ -302,7 +302,7 @@
302
302
  "sectionId": "基础用法",
303
303
  "lang": "vue",
304
304
  "preview": true,
305
- "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MAffix, MButton } from 'morya-ui'\n\nconst top = ref(80)\n</script>\n\n<template>\n <div style=\"height: 320px; overflow: auto; border: 1px solid var(--m-color-border); padding: var(--m-space-4);\">\n <p>向下滚动,按钮在距顶部 {{ top }}px 时固定。</p>\n <div style=\"height: 120px\" />\n <MAffix :offset-top=\"top\">\n <MButton severity=\"primary\">\n Affix at {{ top }}px\n </MButton>\n </MAffix>\n <div style=\"height: 480px\" />\n </div>\n</template>",
305
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MAffix, MButton } from 'morya-ui'\n\nconst top = ref(80)\n</script>\n\n<template>\n <div style=\"height: 320px; overflow: auto; border: 1px solid var(--m-color-border); padding: var(--m-space-4);\">\n <p>向下滚动,按钮在距顶部 {{ top }}px 时固定。</p>\n <div style=\"height: 120px\" />\n <MAffix :offset-top=\"top\">\n <MButton type=\"primary\">\n Affix at {{ top }}px\n </MButton>\n </MAffix>\n <div style=\"height: 480px\" />\n </div>\n</template>",
306
306
  "locale": "zh-CN"
307
307
  },
308
308
  {
@@ -320,7 +320,7 @@
320
320
  "sectionId": "basic",
321
321
  "lang": "vue",
322
322
  "preview": true,
323
- "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MAffix, MButton } from 'morya-ui'\n\nconst top = ref(80)\n</script>\n\n<template>\n <div style=\"height: 320px; overflow: auto; border: 1px solid var(--m-color-border); padding: var(--m-space-4);\">\n <p>向下滚动,按钮在距顶部 {{ top }}px 时固定。</p>\n <div style=\"height: 120px\" />\n <MAffix :offset-top=\"top\">\n <MButton severity=\"primary\">\n Affix at {{ top }}px\n </MButton>\n </MAffix>\n <div style=\"height: 480px\" />\n </div>\n</template>",
323
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MAffix, MButton } from 'morya-ui'\n\nconst top = ref(80)\n</script>\n\n<template>\n <div style=\"height: 320px; overflow: auto; border: 1px solid var(--m-color-border); padding: var(--m-space-4);\">\n <p>向下滚动,按钮在距顶部 {{ top }}px 时固定。</p>\n <div style=\"height: 120px\" />\n <MAffix :offset-top=\"top\">\n <MButton type=\"primary\">\n Affix at {{ top }}px\n </MButton>\n </MAffix>\n <div style=\"height: 480px\" />\n </div>\n</template>",
324
324
  "locale": "en-US"
325
325
  }
326
326
  ],
@@ -510,7 +510,7 @@
510
510
  "sectionId": "操作区",
511
511
  "lang": "vue",
512
512
  "preview": true,
513
- "code": "<script setup lang=\"ts\">\nimport { MAlert, MButton, message } from 'morya-ui'\n\nfunction onUndo() {\n message.info('已撤销')\n}\n</script>\n\n<template>\n <MAlert severity=\"info\">\n <template #title>\n 已归档\n </template>\n 该记录已移入归档。你可以撤销此次操作。\n <template #action>\n <MButton\n size=\"small\"\n text\n @click=\"onUndo\"\n >\n 撤销\n </MButton>\n </template>\n </MAlert>\n</template>",
513
+ "code": "<script setup lang=\"ts\">\nimport { MAlert, MButton, message } from 'morya-ui'\n\nfunction onUndo() {\n message.info('已撤销')\n}\n</script>\n\n<template>\n <MAlert severity=\"info\">\n <template #title>\n 已归档\n </template>\n 该记录已移入归档。你可以撤销此次操作。\n <template #action>\n <MButton size=\"small\" @click=\"onUndo\" type=\"text\">\n 撤销\n </MButton>\n </template>\n </MAlert>\n</template>",
514
514
  "locale": "zh-CN"
515
515
  },
516
516
  {
@@ -564,7 +564,7 @@
564
564
  "sectionId": "action",
565
565
  "lang": "vue",
566
566
  "preview": true,
567
- "code": "<script setup lang=\"ts\">\nimport { MAlert, MButton, message } from 'morya-ui'\n\nfunction onUndo() {\n message.info('已撤销')\n}\n</script>\n\n<template>\n <MAlert severity=\"info\">\n <template #title>\n 已归档\n </template>\n 该记录已移入归档。你可以撤销此次操作。\n <template #action>\n <MButton\n size=\"small\"\n text\n @click=\"onUndo\"\n >\n 撤销\n </MButton>\n </template>\n </MAlert>\n</template>",
567
+ "code": "<script setup lang=\"ts\">\nimport { MAlert, MButton, message } from 'morya-ui'\n\nfunction onUndo() {\n message.info('已撤销')\n}\n</script>\n\n<template>\n <MAlert severity=\"info\">\n <template #title>\n 已归档\n </template>\n 该记录已移入归档。你可以撤销此次操作。\n <template #action>\n <MButton size=\"small\" @click=\"onUndo\" type=\"text\">\n 撤销\n </MButton>\n </template>\n </MAlert>\n</template>",
568
568
  "locale": "en-US"
569
569
  },
570
570
  {
@@ -1554,7 +1554,7 @@
1554
1554
  "sectionId": "overlay",
1555
1555
  "lang": "vue",
1556
1556
  "preview": true,
1557
- "code": "<script setup lang=\"ts\">\nimport { MBadge, MButton } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:flex;flex-wrap:wrap;gap:1.5rem;align-items:center\">\n <MBadge :value=\"120\" :max=\"99\">\n <MButton label=\"Inbox\" severity=\"secondary\" />\n </MBadge>\n <MBadge processing>\n <MButton label=\"Live\" icon=\"check\" />\n </MBadge>\n </div>\n</template>",
1557
+ "code": "<script setup lang=\"ts\">\nimport { MBadge, MButton } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:flex;flex-wrap:wrap;gap:1.5rem;align-items:center\">\n <MBadge :value=\"120\" :max=\"99\">\n <MButton label=\"Inbox\"/>\n </MBadge>\n <MBadge processing>\n <MButton label=\"Live\" icon=\"check\" />\n </MBadge>\n </div>\n</template>",
1558
1558
  "locale": "zh-CN"
1559
1559
  },
1560
1560
  {
@@ -1599,7 +1599,7 @@
1599
1599
  "sectionId": "overlay",
1600
1600
  "lang": "vue",
1601
1601
  "preview": true,
1602
- "code": "<script setup lang=\"ts\">\nimport { MBadge, MButton } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:flex;flex-wrap:wrap;gap:1.5rem;align-items:center\">\n <MBadge :value=\"120\" :max=\"99\">\n <MButton label=\"Inbox\" severity=\"secondary\" />\n </MBadge>\n <MBadge processing>\n <MButton label=\"Live\" icon=\"check\" />\n </MBadge>\n </div>\n</template>",
1602
+ "code": "<script setup lang=\"ts\">\nimport { MBadge, MButton } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:flex;flex-wrap:wrap;gap:1.5rem;align-items:center\">\n <MBadge :value=\"120\" :max=\"99\">\n <MButton label=\"Inbox\"/>\n </MBadge>\n <MBadge processing>\n <MButton label=\"Live\" icon=\"check\" />\n </MBadge>\n </div>\n</template>",
1603
1603
  "locale": "en-US"
1604
1604
  }
1605
1605
  ],
@@ -2065,171 +2065,129 @@
2065
2065
  "name": "Button",
2066
2066
  "exportName": "MButton",
2067
2067
  "category": "01 / BASIC",
2068
- "description": "按钮用于触发即时动作。",
2069
- "descriptionEn": "Button triggers an immediate action.",
2068
+ "description": "触发即时操作的按钮。",
2069
+ "descriptionEn": "A button that triggers an immediate action.",
2070
2070
  "import": "import { MButton } from 'morya-ui'",
2071
2071
  "props": [
2072
2072
  {
2073
- "name": "label",
2074
- "type": "string",
2075
- "default": "—",
2076
- "description": "按钮文案。存在默认插槽内容时以插槽为准。"
2077
- },
2078
- {
2079
- "name": "icon",
2080
- "type": "IconName | Component",
2081
- "default": "—",
2082
- "description": "图标名称或自定义组件。"
2083
- },
2084
- {
2085
- "name": "iconPos",
2086
- "type": "'left' | 'right' | 'top' | 'bottom'",
2087
- "default": "'left'",
2088
- "description": "图标相对标签的位置。"
2089
- },
2090
- {
2091
- "name": "iconOnly",
2092
- "type": "boolean",
2093
- "default": "false",
2094
- "description": "强制方形纯图标按钮。"
2095
- },
2096
- {
2097
- "name": "badge",
2098
- "type": "string",
2099
- "default": "—",
2100
- "description": "徽标文本。"
2101
- },
2102
- {
2103
- "name": "badgeSeverity",
2104
- "type": "'secondary' | 'info' | 'success' | 'warn' | 'danger' | 'contrast' | null",
2105
- "default": "null",
2106
- "description": "徽标语义色。"
2107
- },
2108
- {
2109
- "name": "severity",
2110
- "type": "'secondary' | 'success' | 'info' | 'warn' | 'help' | 'danger' | 'contrast'",
2111
- "default": "—",
2112
- "description": "语义色。省略时为 primary。"
2073
+ "name": "type",
2074
+ "type": "'default' | 'primary' | 'dashed' | 'link' | 'text'",
2075
+ "default": "'default'",
2076
+ "description": "语法糖。同时设置 `color` 与 `variant` 时以后者为准。"
2113
2077
  },
2114
2078
  {
2115
2079
  "name": "color",
2116
- "type": "string",
2117
- "default": "—",
2118
- "description": "自定义颜色,覆盖 `severity`。"
2119
- },
2120
- {
2121
- "name": "size",
2122
- "type": "'small' | 'large' | 'sm' | 'md' | 'lg'",
2080
+ "type": "'default' | 'primary' | 'danger' | 'success' | 'info' | 'warning' | 'help' | 'contrast'",
2123
2081
  "default": "—",
2124
- "description": "尺寸。默认中等;兼容 `sm` / `lg`。"
2082
+ "description": "颜色轴。"
2125
2083
  },
2126
2084
  {
2127
2085
  "name": "variant",
2128
- "type": "'outlined' | 'dashed' | 'text' | 'link' | 'ghost' | 'quaternary'",
2086
+ "type": "'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link'",
2129
2087
  "default": "—",
2130
- "description": "样式变体快捷方式,等价于对应布尔 prop。"
2088
+ "description": "变体轴。"
2131
2089
  },
2132
2090
  {
2133
- "name": "outlined",
2091
+ "name": "danger",
2134
2092
  "type": "boolean",
2135
2093
  "default": "false",
2136
- "description": "描边按钮。"
2094
+ "description": "危险色语法糖。设置了 `color` 时以 `color` 为准。"
2137
2095
  },
2138
2096
  {
2139
- "name": "dashed",
2097
+ "name": "ghost",
2140
2098
  "type": "boolean",
2141
2099
  "default": "false",
2142
- "description": "虚线边框。"
2100
+ "description": "透明背景。对 `text` / `link` 无效。"
2143
2101
  },
2144
2102
  {
2145
- "name": "text",
2146
- "type": "boolean",
2147
- "default": "false",
2148
- "description": "文字按钮。"
2103
+ "name": "shape",
2104
+ "type": "'default' | 'circle' | 'round' | 'square'",
2105
+ "default": "'default'",
2106
+ "description": "形状。"
2149
2107
  },
2150
2108
  {
2151
- "name": "link",
2152
- "type": "boolean",
2153
- "default": "false",
2154
- "description": "链接按钮。"
2109
+ "name": "size",
2110
+ "type": "'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'",
2111
+ "default": "—",
2112
+ "description": "尺寸;可继承 ConfigProvider。"
2155
2113
  },
2156
2114
  {
2157
- "name": "underline",
2115
+ "name": "block",
2158
2116
  "type": "boolean",
2159
- "default": "true",
2160
- "description": "`link` 悬浮下划线。设为 `false` 可关闭。"
2117
+ "default": "false",
2118
+ "description": "宽度撑满父容器。"
2161
2119
  },
2162
2120
  {
2163
- "name": "ghost",
2164
- "type": "boolean",
2121
+ "name": "loading",
2122
+ "type": "boolean | { delay?: number; icon?: IconName | Component }",
2165
2123
  "default": "false",
2166
- "description": "浅色填充,等同于 `text` 的悬浮态。"
2124
+ "description": "加载中;可延迟出现并自定义图标。"
2167
2125
  },
2168
2126
  {
2169
- "name": "quaternary",
2127
+ "name": "disabled",
2170
2128
  "type": "boolean",
2171
2129
  "default": "false",
2172
- "description": "极轻量文字按钮。"
2130
+ "description": "禁用;可继承 ConfigProvider。"
2173
2131
  },
2174
2132
  {
2175
- "name": "plain",
2176
- "type": "boolean",
2177
- "default": "false",
2178
- "description": "浅色填充,等同于 `outlined` 的悬浮态;也可与 `text` / `outlined` 组合弱化。"
2133
+ "name": "htmlType",
2134
+ "type": "'button' | 'submit' | 'reset'",
2135
+ "default": "'button'",
2136
+ "description": "原生 `button` 的 `type`。"
2179
2137
  },
2180
2138
  {
2181
- "name": "raised",
2182
- "type": "boolean",
2183
- "default": "false",
2184
- "description": "浮起阴影。"
2139
+ "name": "href",
2140
+ "type": "string",
2141
+ "default": "—",
2142
+ "description": "设置后渲染为 `<a>`。"
2185
2143
  },
2186
2144
  {
2187
- "name": "rounded",
2188
- "type": "boolean",
2189
- "default": "false",
2190
- "description": "全圆角(兼容;推荐 `shape=\"round\"`)。"
2145
+ "name": "target",
2146
+ "type": "string",
2147
+ "default": "—",
2148
+ "description": "链接 `target`,需配合 `href`。"
2191
2149
  },
2192
2150
  {
2193
- "name": "shape",
2194
- "type": "'default' | 'circle' | 'round' | 'square'",
2195
- "default": "'default'",
2196
- "description": "形状。"
2151
+ "name": "label",
2152
+ "type": "string",
2153
+ "default": "—",
2154
+ "description": "文案;默认插槽优先。"
2197
2155
  },
2198
2156
  {
2199
- "name": "fluid",
2200
- "type": "boolean",
2201
- "default": "false",
2202
- "description": "宽度撑满容器。"
2157
+ "name": "icon",
2158
+ "type": "IconName | Component",
2159
+ "default": "—",
2160
+ "description": "图标名称或组件。"
2203
2161
  },
2204
2162
  {
2205
- "name": "loading",
2163
+ "name": "iconPlacement",
2164
+ "type": "'start' | 'end'",
2165
+ "default": "'start'",
2166
+ "description": "图标位置。"
2167
+ },
2168
+ {
2169
+ "name": "iconOnly",
2206
2170
  "type": "boolean",
2207
2171
  "default": "false",
2208
- "description": "加载中,禁用点击并显示 spinner。"
2172
+ "description": "强制纯图标方形按钮。"
2209
2173
  },
2210
2174
  {
2211
- "name": "disabled",
2175
+ "name": "autoInsertSpace",
2212
2176
  "type": "boolean",
2213
- "default": "false",
2214
- "description": "禁用。"
2177
+ "default": "true",
2178
+ "description": "两个汉字之间插入空格。"
2215
2179
  },
2216
2180
  {
2217
2181
  "name": "ripple",
2218
2182
  "type": "boolean",
2219
2183
  "default": "false",
2220
- "description": "点击水波纹。设为 `true` 可开启。"
2184
+ "description": "点击水波纹。"
2221
2185
  },
2222
2186
  {
2223
2187
  "name": "press",
2224
2188
  "type": "boolean",
2225
2189
  "default": "false",
2226
- "description": "按下时轻微缩放。设为 `true` 可开启。"
2227
- },
2228
- {
2229
- "name": "nativeType",
2230
- "type": "'button' | 'submit' | 'reset'",
2231
- "default": "'button'",
2232
- "description": "原生 button type。"
2190
+ "description": "按下缩放。"
2233
2191
  },
2234
2192
  {
2235
2193
  "name": "autofocus",
@@ -2241,11 +2199,11 @@
2241
2199
  "name": "ariaLabel",
2242
2200
  "type": "string",
2243
2201
  "default": "—",
2244
- "description": "组合的可访问名称。"
2202
+ "description": "组的可访问名称。"
2245
2203
  },
2246
2204
  {
2247
2205
  "name": "pt",
2248
- "type": "[RootPassThrough](/docs/types#RootPassThrough) `{ root? }",
2206
+ "type": "{ root? }",
2249
2207
  "default": "—",
2250
2208
  "description": "组容器透传。"
2251
2209
  }
@@ -2254,7 +2212,7 @@
2254
2212
  {
2255
2213
  "name": "click",
2256
2214
  "payload": "MouseEvent",
2257
- "description": "启用状态下点击触发。"
2215
+ "description": "点击时触发;`loading` / `disabled` 时不触发。"
2258
2216
  }
2259
2217
  ],
2260
2218
  "slots": [
@@ -2274,11 +2232,11 @@
2274
2232
  "methods": [
2275
2233
  {
2276
2234
  "name": "focus",
2277
- "description": "聚焦底层 button。"
2235
+ "description": "聚焦根元素。"
2278
2236
  },
2279
2237
  {
2280
2238
  "name": "ref",
2281
- "description": "底层 `HTMLButtonElement`。"
2239
+ "description": "根 `HTMLButtonElement` 或 `HTMLAnchorElement`。"
2282
2240
  }
2283
2241
  ],
2284
2242
  "examples": [
@@ -2288,7 +2246,7 @@
2288
2246
  "sectionId": "引入",
2289
2247
  "lang": "ts",
2290
2248
  "preview": false,
2291
- "code": "import { MButton } from \"morya-ui\";",
2249
+ "code": "import { MButton, MButtonGroup } from 'morya-ui'",
2292
2250
  "locale": "zh-CN"
2293
2251
  },
2294
2252
  {
@@ -2297,7 +2255,7 @@
2297
2255
  "sectionId": "代码演示",
2298
2256
  "lang": "vue",
2299
2257
  "preview": true,
2300
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton>Submit</MButton>\n <MButton label=\"Label Prop\" />\n <MButton severity=\"secondary\" label=\"Secondary\" />\n </div>\n</template>",
2258
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Primary\" />\n <MButton label=\"Default\" />\n <MButton type=\"dashed\" label=\"Dashed\" />\n <MButton type=\"text\" label=\"Text\" />\n <MButton type=\"link\" label=\"Link\" />\n </MFlex>\n</template>",
2301
2259
  "locale": "zh-CN"
2302
2260
  },
2303
2261
  {
@@ -2306,7 +2264,7 @@
2306
2264
  "sectionId": "代码演示",
2307
2265
  "lang": "vue",
2308
2266
  "preview": true,
2309
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace wrap>\n <MButton label=\"Primary\" />\n <MButton\n severity=\"secondary\"\n label=\"Default\"\n />\n <MButton\n variant=\"dashed\"\n label=\"Dashed\"\n />\n <MButton\n text\n label=\"Text\"\n />\n <MButton\n link\n label=\"Link\"\n />\n <MButton\n severity=\"danger\"\n label=\"Danger\"\n />\n </MSpace>\n</template>",
2267
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"medium\">\n <MFlex gap=\"small\" wrap>\n <MButton color=\"primary\" variant=\"solid\" label=\"Solid\" />\n <MButton color=\"primary\" variant=\"outlined\" label=\"Outlined\" />\n <MButton color=\"primary\" variant=\"dashed\" label=\"Dashed\" />\n <MButton color=\"primary\" variant=\"filled\" label=\"Filled\" />\n <MButton color=\"primary\" variant=\"text\" label=\"Text\" />\n <MButton color=\"primary\" variant=\"link\" label=\"Link\" />\n </MFlex>\n <MFlex gap=\"small\" wrap>\n <MButton color=\"danger\" variant=\"solid\" label=\"Danger\" />\n <MButton color=\"success\" variant=\"solid\" label=\"Success\" />\n <MButton color=\"info\" variant=\"filled\" label=\"Info\" />\n <MButton color=\"warning\" variant=\"outlined\" label=\"Warning\" />\n <MButton color=\"contrast\" variant=\"solid\" label=\"Contrast\" />\n </MFlex>\n </MFlex>\n</template>",
2310
2268
  "locale": "zh-CN"
2311
2269
  },
2312
2270
  {
@@ -2315,7 +2273,7 @@
2315
2273
  "sectionId": "代码演示",
2316
2274
  "lang": "vue",
2317
2275
  "preview": true,
2318
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace wrap>\n <MButton label=\"Default\" />\n <MButton\n shape=\"round\"\n label=\"Round\"\n />\n <MButton\n shape=\"circle\"\n icon=\"search\"\n icon-only\n aria-label=\"Search\"\n />\n <MButton\n shape=\"square\"\n icon=\"edit\"\n icon-only\n aria-label=\"Edit\"\n />\n </MSpace>\n</template>",
2276
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" icon=\"search\" label=\"Search\" />\n <MButton icon=\"search\" icon-placement=\"end\" label=\"Search\" />\n <MButton type=\"primary\" icon=\"plus\" icon-only aria-label=\"Add\" />\n <MButton shape=\"circle\" icon=\"edit\" aria-label=\"Edit\" />\n </MFlex>\n</template>",
2319
2277
  "locale": "zh-CN"
2320
2278
  },
2321
2279
  {
@@ -2324,7 +2282,7 @@
2324
2282
  "sectionId": "代码演示",
2325
2283
  "lang": "vue",
2326
2284
  "preview": true,
2327
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Primary\" />\n <MButton label=\"Secondary\" severity=\"secondary\" />\n <MButton label=\"Success\" severity=\"success\" />\n <MButton label=\"Info\" severity=\"info\" />\n <MButton label=\"Warn\" severity=\"warn\" />\n <MButton label=\"Help\" severity=\"help\" />\n <MButton label=\"Danger\" severity=\"danger\" />\n <MButton label=\"Contrast\" severity=\"contrast\" />\n </div>\n</template>",
2285
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" size=\"small\" label=\"Small\" />\n <MButton type=\"primary\" size=\"medium\" label=\"Medium\" />\n <MButton type=\"primary\" size=\"large\" label=\"Large\" />\n <MButton type=\"primary\" size=\"small\" icon=\"search\" icon-only aria-label=\"Search small\" />\n <MButton type=\"primary\" size=\"large\" icon=\"search\" icon-only aria-label=\"Search large\" />\n </MFlex>\n</template>",
2328
2286
  "locale": "zh-CN"
2329
2287
  },
2330
2288
  {
@@ -2333,7 +2291,7 @@
2333
2291
  "sectionId": "代码演示",
2334
2292
  "lang": "vue",
2335
2293
  "preview": true,
2336
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4 w-full\">\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Outlined\" outlined />\n <MButton label=\"Success\" severity=\"success\" outlined />\n <MButton label=\"Danger\" severity=\"danger\" outlined />\n </div>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Raised\" raised />\n <MButton label=\"Rounded\" rounded />\n <MButton label=\"Plain\" plain />\n <MButton label=\"Plain Text\" text plain />\n </div>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Small\" size=\"small\" />\n <MButton label=\"Large\" size=\"large\" />\n <MButton label=\"Fluid\" fluid />\n </div>\n </div>\n</template>",
2294
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" label=\"Default\" />\n <MButton type=\"primary\" shape=\"round\" label=\"Round\" />\n <MButton type=\"primary\" shape=\"circle\" icon=\"search\" aria-label=\"Search\" />\n <MButton type=\"primary\" shape=\"square\" icon=\"plus\" aria-label=\"Add\" />\n </MFlex>\n</template>",
2337
2295
  "locale": "zh-CN"
2338
2296
  },
2339
2297
  {
@@ -2342,7 +2300,7 @@
2342
2300
  "sectionId": "代码演示",
2343
2301
  "lang": "vue",
2344
2302
  "preview": true,
2345
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Text\" text />\n <MButton label=\"Text Danger\" text severity=\"danger\" />\n <MButton label=\"Link\" link />\n <MButton label=\"Link No Underline\" link :underline=\"false\" />\n <MButton label=\"Link Secondary\" link severity=\"secondary\" />\n </div>\n</template>",
2303
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" danger label=\"Primary\" />\n <MButton danger label=\"Default\" />\n <MButton type=\"dashed\" danger label=\"Dashed\" />\n <MButton type=\"text\" danger label=\"Text\" />\n <MButton type=\"link\" danger label=\"Link\" />\n </MFlex>\n</template>",
2346
2304
  "locale": "zh-CN"
2347
2305
  },
2348
2306
  {
@@ -2351,7 +2309,7 @@
2351
2309
  "sectionId": "代码演示",
2352
2310
  "lang": "vue",
2353
2311
  "preview": true,
2354
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Ghost\" ghost />\n <MButton label=\"Ghost Danger\" ghost severity=\"danger\" />\n <MButton label=\"Quaternary\" quaternary />\n <MButton label=\"Custom\" color=\"#e11d48\" />\n </div>\n</template>",
2312
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <div\n class=\"rounded-md p-4\"\n style=\"background: linear-gradient(135deg, #0f172a, #1d4ed8)\"\n >\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" ghost label=\"Primary Ghost\" />\n <MButton ghost label=\"Default Ghost\" />\n <MButton type=\"dashed\" ghost label=\"Dashed Ghost\" />\n <MButton type=\"primary\" danger ghost label=\"Danger Ghost\" />\n </MFlex>\n </div>\n</template>",
2355
2313
  "locale": "zh-CN"
2356
2314
  },
2357
2315
  {
@@ -2360,7 +2318,7 @@
2360
2318
  "sectionId": "代码演示",
2361
2319
  "lang": "vue",
2362
2320
  "preview": true,
2363
- "code": "<script setup lang=\"ts\">\nimport { MButton, MButtonGroup } from 'morya-ui'\n</script>\n\n<template>\n <MButtonGroup aria-label=\"对齐\">\n <MButton label=\"左\" />\n <MButton label=\"中\" severity=\"secondary\" />\n <MButton label=\"右\" severity=\"secondary\" />\n </MButtonGroup>\n</template>",
2321
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MButton, MFlex } from 'morya-ui'\n\nconst loading = ref(false)\n\nfunction toggle() {\n loading.value = true\n window.setTimeout(() => {\n loading.value = false\n }, 2000)\n}\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Always\" loading />\n <MButton label=\"Delayed\" :loading=\"{ delay: 400 }\" />\n <MButton type=\"primary\" :loading=\"loading\" label=\"Click me\" @click=\"toggle\" />\n </MFlex>\n</template>",
2364
2322
  "locale": "zh-CN"
2365
2323
  },
2366
2324
  {
@@ -2369,7 +2327,7 @@
2369
2327
  "sectionId": "代码演示",
2370
2328
  "lang": "vue",
2371
2329
  "preview": true,
2372
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton icon=\"check\" label=\"Save\" />\n <MButton icon=\"search\" label=\"Search\" icon-pos=\"right\" severity=\"secondary\" />\n <MButton icon=\"plus\" icon-only rounded aria-label=\"Add\" />\n <MButton icon=\"trash\" icon-only rounded outlined severity=\"danger\" aria-label=\"Delete\" />\n <MButton label=\"Messages\" badge=\"2\" badge-severity=\"danger\" severity=\"secondary\" />\n </div>\n</template>",
2330
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Primary\" disabled />\n <MButton label=\"Default\" disabled />\n <MButton type=\"dashed\" label=\"Dashed\" disabled />\n <MButton type=\"text\" label=\"Text\" disabled />\n <MButton type=\"link\" label=\"Link\" disabled />\n <MButton type=\"primary\" danger label=\"Danger\" disabled />\n </MFlex>\n</template>",
2373
2331
  "locale": "zh-CN"
2374
2332
  },
2375
2333
  {
@@ -2378,7 +2336,7 @@
2378
2336
  "sectionId": "代码演示",
2379
2337
  "lang": "vue",
2380
2338
  "preview": true,
2381
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst loading = ref(false)\n\nfunction toggleLoading() {\n loading.value = true\n window.setTimeout(() => {\n loading.value = false\n }, 900)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Search\" icon=\"search\" :loading=\"loading\" @click=\"toggleLoading\" />\n <MButton label=\"Always Loading\" loading severity=\"secondary\" />\n </div>\n</template>",
2339
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"small\" class=\"w-full\">\n <MButton type=\"primary\" block label=\"Primary Block\" />\n <MButton block label=\"Default Block\" />\n <MButton type=\"dashed\" block label=\"Dashed Block\" />\n </MFlex>\n</template>",
2382
2340
  "locale": "zh-CN"
2383
2341
  },
2384
2342
  {
@@ -2387,7 +2345,34 @@
2387
2345
  "sectionId": "代码演示",
2388
2346
  "lang": "vue",
2389
2347
  "preview": true,
2390
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Disabled\" disabled />\n <MButton label=\"Disabled Outlined\" outlined disabled />\n <MButton label=\"Disabled Text\" text disabled />\n </div>\n</template>",
2348
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MButtonGroup, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"medium\">\n <MButtonGroup aria-label=\"行内操作\">\n <MButton label=\"编辑\" />\n <MButton label=\"分享\" />\n <MButton danger label=\"删除\" />\n </MButtonGroup>\n <MButtonGroup block aria-label=\"表单操作\">\n <MButton label=\"取消\" />\n <MButton type=\"primary\" label=\"确认\" />\n </MButtonGroup>\n </MFlex>\n</template>",
2349
+ "locale": "zh-CN"
2350
+ },
2351
+ {
2352
+ "id": "代码演示-12",
2353
+ "section": "代码演示",
2354
+ "sectionId": "代码演示",
2355
+ "lang": "vue",
2356
+ "preview": true,
2357
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" ripple label=\"Ripple\" />\n <MButton type=\"primary\" press label=\"Press\" />\n <MButton type=\"primary\" ripple press label=\"Both\" />\n </MFlex>\n</template>",
2358
+ "locale": "zh-CN"
2359
+ },
2360
+ {
2361
+ "id": "faq-1",
2362
+ "section": "FAQ",
2363
+ "sectionId": "faq",
2364
+ "lang": "vue",
2365
+ "preview": false,
2366
+ "code": "<MButton type=\"primary\">保存</MButton>",
2367
+ "locale": "zh-CN"
2368
+ },
2369
+ {
2370
+ "id": "faq-2",
2371
+ "section": "FAQ",
2372
+ "sectionId": "faq",
2373
+ "lang": "vue",
2374
+ "preview": false,
2375
+ "code": "<MButton color=\"primary\" variant=\"solid\">保存</MButton>",
2391
2376
  "locale": "zh-CN"
2392
2377
  },
2393
2378
  {
@@ -2396,7 +2381,7 @@
2396
2381
  "sectionId": "import",
2397
2382
  "lang": "ts",
2398
2383
  "preview": false,
2399
- "code": "import { MButton } from \"morya-ui\";",
2384
+ "code": "import { MButton, MButtonGroup } from 'morya-ui'",
2400
2385
  "locale": "en-US"
2401
2386
  },
2402
2387
  {
@@ -2405,7 +2390,7 @@
2405
2390
  "sectionId": "examples",
2406
2391
  "lang": "vue",
2407
2392
  "preview": true,
2408
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton>Submit</MButton>\n <MButton label=\"Label Prop\" />\n <MButton severity=\"secondary\" label=\"Secondary\" />\n </div>\n</template>",
2393
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Primary\" />\n <MButton label=\"Default\" />\n <MButton type=\"dashed\" label=\"Dashed\" />\n <MButton type=\"text\" label=\"Text\" />\n <MButton type=\"link\" label=\"Link\" />\n </MFlex>\n</template>",
2409
2394
  "locale": "en-US"
2410
2395
  },
2411
2396
  {
@@ -2414,7 +2399,7 @@
2414
2399
  "sectionId": "examples",
2415
2400
  "lang": "vue",
2416
2401
  "preview": true,
2417
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace wrap>\n <MButton label=\"Primary\" />\n <MButton\n severity=\"secondary\"\n label=\"Default\"\n />\n <MButton\n variant=\"dashed\"\n label=\"Dashed\"\n />\n <MButton\n text\n label=\"Text\"\n />\n <MButton\n link\n label=\"Link\"\n />\n <MButton\n severity=\"danger\"\n label=\"Danger\"\n />\n </MSpace>\n</template>",
2402
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"medium\">\n <MFlex gap=\"small\" wrap>\n <MButton color=\"primary\" variant=\"solid\" label=\"Solid\" />\n <MButton color=\"primary\" variant=\"outlined\" label=\"Outlined\" />\n <MButton color=\"primary\" variant=\"dashed\" label=\"Dashed\" />\n <MButton color=\"primary\" variant=\"filled\" label=\"Filled\" />\n <MButton color=\"primary\" variant=\"text\" label=\"Text\" />\n <MButton color=\"primary\" variant=\"link\" label=\"Link\" />\n </MFlex>\n <MFlex gap=\"small\" wrap>\n <MButton color=\"danger\" variant=\"solid\" label=\"Danger\" />\n <MButton color=\"success\" variant=\"solid\" label=\"Success\" />\n <MButton color=\"info\" variant=\"filled\" label=\"Info\" />\n <MButton color=\"warning\" variant=\"outlined\" label=\"Warning\" />\n <MButton color=\"contrast\" variant=\"solid\" label=\"Contrast\" />\n </MFlex>\n </MFlex>\n</template>",
2418
2403
  "locale": "en-US"
2419
2404
  },
2420
2405
  {
@@ -2423,7 +2408,7 @@
2423
2408
  "sectionId": "examples",
2424
2409
  "lang": "vue",
2425
2410
  "preview": true,
2426
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace wrap>\n <MButton label=\"Default\" />\n <MButton\n shape=\"round\"\n label=\"Round\"\n />\n <MButton\n shape=\"circle\"\n icon=\"search\"\n icon-only\n aria-label=\"Search\"\n />\n <MButton\n shape=\"square\"\n icon=\"edit\"\n icon-only\n aria-label=\"Edit\"\n />\n </MSpace>\n</template>",
2411
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" icon=\"search\" label=\"Search\" />\n <MButton icon=\"search\" icon-placement=\"end\" label=\"Search\" />\n <MButton type=\"primary\" icon=\"plus\" icon-only aria-label=\"Add\" />\n <MButton shape=\"circle\" icon=\"edit\" aria-label=\"Edit\" />\n </MFlex>\n</template>",
2427
2412
  "locale": "en-US"
2428
2413
  },
2429
2414
  {
@@ -2432,7 +2417,7 @@
2432
2417
  "sectionId": "examples",
2433
2418
  "lang": "vue",
2434
2419
  "preview": true,
2435
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Primary\" />\n <MButton label=\"Secondary\" severity=\"secondary\" />\n <MButton label=\"Success\" severity=\"success\" />\n <MButton label=\"Info\" severity=\"info\" />\n <MButton label=\"Warn\" severity=\"warn\" />\n <MButton label=\"Help\" severity=\"help\" />\n <MButton label=\"Danger\" severity=\"danger\" />\n <MButton label=\"Contrast\" severity=\"contrast\" />\n </div>\n</template>",
2420
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" size=\"small\" label=\"Small\" />\n <MButton type=\"primary\" size=\"medium\" label=\"Medium\" />\n <MButton type=\"primary\" size=\"large\" label=\"Large\" />\n <MButton type=\"primary\" size=\"small\" icon=\"search\" icon-only aria-label=\"Search small\" />\n <MButton type=\"primary\" size=\"large\" icon=\"search\" icon-only aria-label=\"Search large\" />\n </MFlex>\n</template>",
2436
2421
  "locale": "en-US"
2437
2422
  },
2438
2423
  {
@@ -2441,7 +2426,7 @@
2441
2426
  "sectionId": "examples",
2442
2427
  "lang": "vue",
2443
2428
  "preview": true,
2444
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4 w-full\">\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Outlined\" outlined />\n <MButton label=\"Success\" severity=\"success\" outlined />\n <MButton label=\"Danger\" severity=\"danger\" outlined />\n </div>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Raised\" raised />\n <MButton label=\"Rounded\" rounded />\n <MButton label=\"Plain\" plain />\n <MButton label=\"Plain Text\" text plain />\n </div>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Small\" size=\"small\" />\n <MButton label=\"Large\" size=\"large\" />\n <MButton label=\"Fluid\" fluid />\n </div>\n </div>\n</template>",
2429
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap align=\"center\">\n <MButton type=\"primary\" label=\"Default\" />\n <MButton type=\"primary\" shape=\"round\" label=\"Round\" />\n <MButton type=\"primary\" shape=\"circle\" icon=\"search\" aria-label=\"Search\" />\n <MButton type=\"primary\" shape=\"square\" icon=\"plus\" aria-label=\"Add\" />\n </MFlex>\n</template>",
2445
2430
  "locale": "en-US"
2446
2431
  },
2447
2432
  {
@@ -2450,7 +2435,7 @@
2450
2435
  "sectionId": "examples",
2451
2436
  "lang": "vue",
2452
2437
  "preview": true,
2453
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Text\" text />\n <MButton label=\"Text Danger\" text severity=\"danger\" />\n <MButton label=\"Link\" link />\n <MButton label=\"Link No Underline\" link :underline=\"false\" />\n <MButton label=\"Link Secondary\" link severity=\"secondary\" />\n </div>\n</template>",
2438
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" danger label=\"Primary\" />\n <MButton danger label=\"Default\" />\n <MButton type=\"dashed\" danger label=\"Dashed\" />\n <MButton type=\"text\" danger label=\"Text\" />\n <MButton type=\"link\" danger label=\"Link\" />\n </MFlex>\n</template>",
2454
2439
  "locale": "en-US"
2455
2440
  },
2456
2441
  {
@@ -2459,7 +2444,7 @@
2459
2444
  "sectionId": "examples",
2460
2445
  "lang": "vue",
2461
2446
  "preview": true,
2462
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Ghost\" ghost />\n <MButton label=\"Ghost Danger\" ghost severity=\"danger\" />\n <MButton label=\"Quaternary\" quaternary />\n <MButton label=\"Custom\" color=\"#e11d48\" />\n </div>\n</template>",
2447
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <div\n class=\"rounded-md p-4\"\n style=\"background: linear-gradient(135deg, #0f172a, #1d4ed8)\"\n >\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" ghost label=\"Primary Ghost\" />\n <MButton ghost label=\"Default Ghost\" />\n <MButton type=\"dashed\" ghost label=\"Dashed Ghost\" />\n <MButton type=\"primary\" danger ghost label=\"Danger Ghost\" />\n </MFlex>\n </div>\n</template>",
2463
2448
  "locale": "en-US"
2464
2449
  },
2465
2450
  {
@@ -2468,7 +2453,7 @@
2468
2453
  "sectionId": "examples",
2469
2454
  "lang": "vue",
2470
2455
  "preview": true,
2471
- "code": "<script setup lang=\"ts\">\nimport { MButton, MButtonGroup } from 'morya-ui'\n</script>\n\n<template>\n <MButtonGroup aria-label=\"Align\">\n <MButton label=\"Left\" />\n <MButton label=\"Center\" severity=\"secondary\" />\n <MButton label=\"Right\" severity=\"secondary\" />\n </MButtonGroup>\n</template>",
2456
+ "code": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { MButton, MFlex } from 'morya-ui'\n\nconst loading = ref(false)\n\nfunction toggle() {\n loading.value = true\n window.setTimeout(() => {\n loading.value = false\n }, 2000)\n}\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Always\" loading />\n <MButton label=\"Delayed\" :loading=\"{ delay: 400 }\" />\n <MButton type=\"primary\" :loading=\"loading\" label=\"Click me\" @click=\"toggle\" />\n </MFlex>\n</template>",
2472
2457
  "locale": "en-US"
2473
2458
  },
2474
2459
  {
@@ -2477,7 +2462,7 @@
2477
2462
  "sectionId": "examples",
2478
2463
  "lang": "vue",
2479
2464
  "preview": true,
2480
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton icon=\"check\" label=\"Save\" />\n <MButton icon=\"search\" label=\"Search\" icon-pos=\"right\" severity=\"secondary\" />\n <MButton icon=\"plus\" icon-only rounded aria-label=\"Add\" />\n <MButton icon=\"trash\" icon-only rounded outlined severity=\"danger\" aria-label=\"Delete\" />\n <MButton label=\"Messages\" badge=\"2\" badge-severity=\"danger\" severity=\"secondary\" />\n </div>\n</template>",
2465
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" label=\"Primary\" disabled />\n <MButton label=\"Default\" disabled />\n <MButton type=\"dashed\" label=\"Dashed\" disabled />\n <MButton type=\"text\" label=\"Text\" disabled />\n <MButton type=\"link\" label=\"Link\" disabled />\n <MButton type=\"primary\" danger label=\"Danger\" disabled />\n </MFlex>\n</template>",
2481
2466
  "locale": "en-US"
2482
2467
  },
2483
2468
  {
@@ -2486,7 +2471,7 @@
2486
2471
  "sectionId": "examples",
2487
2472
  "lang": "vue",
2488
2473
  "preview": true,
2489
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst loading = ref(false)\n\nfunction toggleLoading() {\n loading.value = true\n window.setTimeout(() => {\n loading.value = false\n }, 900)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Search\" icon=\"search\" :loading=\"loading\" @click=\"toggleLoading\" />\n <MButton label=\"Always Loading\" loading severity=\"secondary\" />\n </div>\n</template>",
2474
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"small\" class=\"w-full\">\n <MButton type=\"primary\" block label=\"Primary Block\" />\n <MButton block label=\"Default Block\" />\n <MButton type=\"dashed\" block label=\"Dashed Block\" />\n </MFlex>\n</template>",
2490
2475
  "locale": "en-US"
2491
2476
  },
2492
2477
  {
@@ -2495,114 +2480,141 @@
2495
2480
  "sectionId": "examples",
2496
2481
  "lang": "vue",
2497
2482
  "preview": true,
2498
- "code": "<script setup lang=\"ts\">\nimport { MButton } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Disabled\" disabled />\n <MButton label=\"Disabled Outlined\" outlined disabled />\n <MButton label=\"Disabled Text\" text disabled />\n </div>\n</template>",
2483
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MButtonGroup, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical gap=\"medium\">\n <MButtonGroup aria-label=\"Row actions\">\n <MButton label=\"Edit\" />\n <MButton label=\"Share\" />\n <MButton danger label=\"Delete\" />\n </MButtonGroup>\n <MButtonGroup block aria-label=\"Form actions\">\n <MButton label=\"Cancel\" />\n <MButton type=\"primary\" label=\"Confirm\" />\n </MButtonGroup>\n </MFlex>\n</template>",
2484
+ "locale": "en-US"
2485
+ },
2486
+ {
2487
+ "id": "examples-12",
2488
+ "section": "Examples",
2489
+ "sectionId": "examples",
2490
+ "lang": "vue",
2491
+ "preview": true,
2492
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex gap=\"small\" wrap>\n <MButton type=\"primary\" ripple label=\"Ripple\" />\n <MButton type=\"primary\" press label=\"Press\" />\n <MButton type=\"primary\" ripple press label=\"Both\" />\n </MFlex>\n</template>",
2493
+ "locale": "en-US"
2494
+ },
2495
+ {
2496
+ "id": "faq-1",
2497
+ "section": "FAQ",
2498
+ "sectionId": "faq",
2499
+ "lang": "vue",
2500
+ "preview": false,
2501
+ "code": "<MButton type=\"primary\">Save</MButton>",
2502
+ "locale": "en-US"
2503
+ },
2504
+ {
2505
+ "id": "faq-2",
2506
+ "section": "FAQ",
2507
+ "sectionId": "faq",
2508
+ "lang": "vue",
2509
+ "preview": false,
2510
+ "code": "<MButton color=\"primary\" variant=\"solid\">Save</MButton>",
2499
2511
  "locale": "en-US"
2500
2512
  }
2501
2513
  ],
2502
2514
  "locales": {
2503
2515
  "zh-CN": {
2504
2516
  "title": "Button",
2505
- "description": "按钮用于触发即时动作。",
2517
+ "description": "触发即时操作的按钮。",
2506
2518
  "sections": [
2507
2519
  {
2508
2520
  "id": "overview",
2509
2521
  "title": "",
2510
- "body": "# Button\n\n按钮用于触发即时动作。"
2522
+ "body": "# Button\n\n触发提交、确认、导航等即时操作。"
2511
2523
  },
2512
2524
  {
2513
2525
  "id": "何时使用",
2514
2526
  "title": "何时使用",
2515
- "body": "- 需要触发表单提交、确认、导航或其它即时操作时。\n- 页面主操作使用默认(primary)按钮;次要操作用 `severity=\"secondary\"` 或 `outlined` / `text`。\n- 危险、破坏性操作用 `severity=\"danger\"`;轻量内联操作用 `text` 或 `link`。\n- 相邻一组互斥或相关操作用 `MButtonGroup`。"
2527
+ "body": "- 主操作:`type=\"primary\"`,同一操作区通常只放一个。\n- 次操作:默认按钮,或 `type=\"dashed\"` / `type=\"text\"`。\n- 内联导航或弱操作:`type=\"link\"` / `type=\"text\"`。\n- 破坏性操作:加 `danger`,并配合确认。\n- 相邻操作需要拼成一组时:用 `MButtonGroup`(仅视觉拼组)。"
2516
2528
  },
2517
2529
  {
2518
2530
  "id": "引入",
2519
2531
  "title": "引入",
2520
- "body": "```ts\nimport { MButton } from \"morya-ui\";\n```"
2532
+ "body": "```ts\nimport { MButton, MButtonGroup } from 'morya-ui'\n```"
2521
2533
  },
2522
2534
  {
2523
2535
  "id": "代码演示",
2524
2536
  "title": "代码演示",
2525
- "body": "### 基础用法\n\n通过默认插槽或 `label` 展示按钮文案。\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### 类型\n\n常用组合:`severity=\"secondary\"` 默认样式、`variant=\"dashed\"` 虚线、`text` / `link` 文字链、`severity=\"danger\"` 危险、`fluid` 通栏。\n\n```vue preview src=\"./demos/VariantTypes.vue\"\n\n```\n\n### Shape\n\n`shape`:`default` / `round` / `circle` / `square`。旧 `rounded` 等价于 `shape=\"round\"`。\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Severity\n\n使用 `severity` 定义按钮语义色;省略时为 primary。\n\n```vue preview src=\"./demos/Severity.vue\"\n\n```\n\n### Styles\n\n`outlined`、`text`、`link`、`raised`、`rounded`、`plain` 可自由组合。\n\n```vue preview src=\"./demos/Styles.vue\"\n\n```\n\n### Text & Link\n\n`text` 为轻量文字按钮;`link` 呈现为无背景的内联链接样式,默认悬浮下划线,设 `:underline=\"false\"` 可关闭。二者均可与 `severity` 组合。\n\n```vue preview src=\"./demos/TextAndLink.vue\"\n\n```\n\n### Ghost & Quaternary\n\n`ghost` 为浅色填充,等同于 `text` 的悬浮态;`quaternary` 更克制,适合工具栏次要操作。也可通过 `variant` 指定。\n\n```vue preview src=\"./demos/GhostAndQuaternary.vue\"\n\n```\n\n### Button Group\n\n`MButtonGroup` 将相邻按钮拼成一组。\n\n```vue preview src=\"./demos/ButtonGroup.zh.vue\"\n\n```\n\n### Icons & Badge\n\n支持 `icon`、`iconPos`、`iconOnly`,以及 `badge` 徽标。\n\n```vue preview src=\"./demos/IconsAndBadge.vue\"\n\n```\n\n### Loading\n\n`loading` 状态下显示 spinner 并阻止点击。\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```"
2537
+ "body": "### 基础用法\n\n`type` 是 `color` + `variant` 的语法糖。省略时为默认描边按钮。\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### 颜色与变体\n\n需要更细控制时直接设 `color` 与 `variant`;二者同时存在时优先于 `type`。\n\n```vue preview src=\"./demos/ColorVariant.vue\"\n\n```\n\n### 图标\n\n`icon` 可配名称或组件;`iconPlacement` 控制位置;纯图标请提供 `ariaLabel`。\n\n```vue preview src=\"./demos/Icon.vue\"\n\n```\n\n### 尺寸\n\n```vue preview src=\"./demos/Size.vue\"\n\n```\n\n### 形状\n\n`shape`:`default` / `round` / `circle` / `square`。\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### 危险按钮\n\n`danger` 将颜色切到危险色,并保留当前 `type` / `variant` 形态。\n\n```vue preview src=\"./demos/Danger.vue\"\n\n```\n\n### 幽灵按钮\n\n`ghost` 让背景透明,适合深色或复杂底图。对 `text` / `link` 无效。\n\n```vue preview src=\"./demos/Ghost.vue\"\n\n```\n\n### 加载中\n\n`loading` 可为布尔值,或 `{ delay, icon }`。加载中会禁用点击。\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### 不可用\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n### Block\n\n`block` 让按钮宽度撑满父容器。\n\n```vue preview src=\"./demos/Block.vue\"\n\n```\n\n### 按钮组\n\n`MButtonGroup` 只做视觉拼组(圆角与边框衔接),没有选中态。需要互斥切换时用 [`SelectButton`](/components/SelectButton)。\n\n```vue preview src=\"./demos/ButtonGroup.zh.vue\"\n\n```\n\n### 水波纹与按压\n\n`ripple` / `press` 默认关闭,需要时显式开启。\n\n```vue preview src=\"./demos/RipplePress.vue\"\n\n```"
2526
2538
  },
2527
2539
  {
2528
2540
  "id": "api",
2529
2541
  "title": "API",
2530
- "body": "### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --------------- | ---------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- |\n| `label` | `string` | — | 按钮文案。存在默认插槽内容时以插槽为准。 |\n| `icon` | `IconName \\| Component` | — | 图标名称或自定义组件。 |\n| `iconPos` | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'left'` | 图标相对标签的位置。 |\n| `iconOnly` | `boolean` | `false` | 强制方形纯图标按钮。 |\n| `badge` | `string` | — | 徽标文本。 |\n| `badgeSeverity` | `'secondary' \\| 'info' \\| 'success' \\| 'warn' \\| 'danger' \\| 'contrast' \\| null` | `null` | 徽标语义色。 |\n| `severity` | `'secondary' \\| 'success' \\| 'info' \\| 'warn' \\| 'help' \\| 'danger' \\| 'contrast'` | — | 语义色。省略时为 primary。 |\n| `color` | `string` | — | 自定义颜色,覆盖 `severity`。 |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | 尺寸。默认中等;兼容 `sm` / `lg`。 |\n| `variant` | `'outlined' \\| 'dashed' \\| 'text' \\| 'link' \\| 'ghost' \\| 'quaternary'` | — | 样式变体快捷方式,等价于对应布尔 prop。 |\n| `outlined` | `boolean` | `false` | 描边按钮。 |\n| `dashed` | `boolean` | `false` | 虚线边框。 |\n| `text` | `boolean` | `false` | 文字按钮。 |\n| `link` | `boolean` | `false` | 链接按钮。 |\n| `underline` | `boolean` | `true` | `link` 悬浮下划线。设为 `false` 可关闭。 |\n| `ghost` | `boolean` | `false` | 浅色填充,等同于 `text` 的悬浮态。 |\n| `quaternary` | `boolean` | `false` | 极轻量文字按钮。 |\n| `plain` | `boolean` | `false` | 浅色填充,等同于 `outlined` 的悬浮态;也可与 `text` / `outlined` 组合弱化。 |\n| `raised` | `boolean` | `false` | 浮起阴影。 |\n| `rounded` | `boolean` | `false` | 全圆角(兼容;推荐 `shape=\"round\"`)。 |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | 形状。 |\n| `fluid` | `boolean` | `false` | 宽度撑满容器。 |\n| `loading` | `boolean` | `false` | 加载中,禁用点击并显示 spinner。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `ripple` | `boolean` | `false` | 点击水波纹。设为 `true` 可开启。 |\n| `press` | `boolean` | `false` | 按下时轻微缩放。设为 `true` 可开启。 |\n| `nativeType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | 原生 button type。 |\n| `autofocus` | `boolean` | `false` | 原生 autofocus。 |\n| `ariaLabel` | `string` | — | 可访问名称;图标按钮建议提供。 |\n\n### Events\n\n| 事件名 | 参数 | 说明 |\n| ------- | ------------ | -------------------- |\n| `click` | `MouseEvent` | 启用状态下点击触发。 |\n\n### Slots\n\n| 插槽名 | 说明 |\n| ------------- | -------------------------- |\n| `default` | 按钮内容,优先于 `label`。 |\n| `icon` | 自定义图标。 |\n| `loadingicon` | 自定义加载图标。 |\n\n### Instance\n\n| 方法 / 属性 | 说明 |\n| ----------- | -------------------------- |\n| `focus()` | 聚焦底层 button。 |\n| `ref` | 底层 `HTMLButtonElement`。 |\n\n### Props — ButtonGroup\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `fluid` | `boolean` | `false` | 宽度撑满容器。 |\n| `ariaLabel` | `string` | — | 组合的可访问名称。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 组容器透传。 |"
2542
+ "body": "推荐组合顺序:`type` → `shape` → `size` → `loading` → `disabled`。\n\n### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `type` | `'default' \\| 'primary' \\| 'dashed' \\| 'link' \\| 'text'` | `'default'` | 语法糖。同时设置 `color` 与 `variant` 时以后者为准。 |\n| `color` | `'default' \\| 'primary' \\| 'danger' \\| 'success' \\| 'info' \\| 'warning' \\| 'help' \\| 'contrast'` | — | 颜色轴。 |\n| `variant` | `'solid' \\| 'outlined' \\| 'dashed' \\| 'filled' \\| 'text' \\| 'link'` | — | 变体轴。 |\n| `danger` | `boolean` | `false` | 危险色语法糖。设置了 `color` 时以 `color` 为准。 |\n| `ghost` | `boolean` | `false` | 透明背景。对 `text` / `link` 无效。 |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | 形状。 |\n| `size` | `'small' \\| 'medium' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | 尺寸;可继承 ConfigProvider。 |\n| `block` | `boolean` | `false` | 宽度撑满父容器。 |\n| `loading` | `boolean \\| { delay?: number; icon?: IconName \\| Component }` | `false` | 加载中;可延迟出现并自定义图标。 |\n| `disabled` | `boolean` | `false` | 禁用;可继承 ConfigProvider。 |\n| `htmlType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | 原生 `button` 的 `type`。 |\n| `href` | `string` | — | 设置后渲染为 `<a>`。 |\n| `target` | `string` | — | 链接 `target`,需配合 `href`。 |\n| `label` | `string` | — | 文案;默认插槽优先。 |\n| `icon` | `IconName \\| Component` | — | 图标名称或组件。 |\n| `iconPlacement` | `'start' \\| 'end'` | `'start'` | 图标位置。 |\n| `iconOnly` | `boolean` | `false` | 强制纯图标方形按钮。 |\n| `autoInsertSpace` | `boolean` | `true` | 两个汉字之间插入空格。 |\n| `ripple` | `boolean` | `false` | 点击水波纹。 |\n| `press` | `boolean` | `false` | 按下缩放。 |\n| `autofocus` | `boolean` | `false` | 原生 autofocus。 |\n| `ariaLabel` | `string` | — | 可访问名称;纯图标按钮建议提供。 |\n| `pt` | `{ root?, icon?, content? }` | — | 语义结构透传。 |\n\n### Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `click` | `MouseEvent` | 点击时触发;`loading` / `disabled` 时不触发。 |\n\n### Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 按钮内容,优先于 `label`。 |\n| `icon` | 自定义图标。 |\n| `loadingicon` | 自定义加载图标。 |\n\n### Instance\n\n| 方法 / 属性 | 说明 |\n| --- | --- |\n| `focus()` | 聚焦根元素。 |\n| `ref` | 根 `HTMLButtonElement` 或 `HTMLAnchorElement`。 |\n\n### MButtonGroup Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `block` | `boolean` | `false` | 宽度撑满父容器。 |\n| `ariaLabel` | `string` | — | 组的可访问名称。 |\n| `pt` | `{ root? }` | — | 组容器透传。 |"
2531
2543
  },
2532
2544
  {
2533
2545
  "id": "design-token",
2534
2546
  "title": "Design Token",
2535
- "body": "复用全局 `--m-*` 令牌,见[设计令牌](/docs/design-tokens)。组件级 `--m-button-*` 表将在后续补充。"
2547
+ "body": "复用全局 `--m-*` 令牌,见[设计令牌](/docs/design-tokens)。按钮在根节点暴露 `--m-button-*`(尺寸、圆角、色阶、填充透明度、动效等),主题切换时跟随 `--m-color-*` / `--m-control-*` / `--m-motion-*`。"
2536
2548
  },
2537
2549
  {
2538
2550
  "id": "semantic-dom",
2539
2551
  "title": "Semantic DOM",
2540
- "body": "`MButton` 是叶子组件:根节点即原生 `<button class=\"m-button\">`,`class` / `style` / 事件直接落在该元素上(见[样式与 attrs](/docs/attrs)、[Common Props](/docs/common-props))。\n\n```text\nbutton.m-button ← 根(交互元素)\n span.m-button__ripple ← 可选:ripple 层\n span.m-button__icon ← 图标 / loading spinner(aria-hidden)\n span.m-button__spinner ← loading 时\n span.m-button__label ← 文案(插槽或 label)\n span.m-button__badge* ← 可选徽标\n```\n\n`MButton` 本身不暴露 `pt`;拼组用 `MButtonGroup` 的 `pt.root` 修改组容器。绑定样式时优先针对 `.m-button`,再按需覆盖 `__icon` / `__label` / `__badge`。"
2552
+ "body": "根节点即交互元素:有 `href` 时为 `<a class=\"m-button\">`,否则为 `<button class=\"m-button\">`。\n\n```text\nbutton.m-button / a.m-button\n span.m-button__ripple* ← ripple 开启时\n span.m-button__icon* ← 图标 / loading\n span.m-button__label* ← 文案\n```\n\n可用 `pt.root` / `pt.icon` / `pt.content` 覆盖各节点。更多约定见[样式与 attrs](/docs/attrs)、[Common Props](/docs/common-props)。"
2541
2553
  },
2542
2554
  {
2543
2555
  "id": "faq",
2544
2556
  "title": "FAQ",
2545
- "body": "### `severity` 和 `variant` 有什么区别?\n\n`severity` 控制语义色(如 `danger`、`success`);省略时为 primary。`variant`(或对应布尔 prop)控制样式形态,如 `outlined`、`text`、`link`、`ghost`。二者可组合,例如 `severity=\"danger\"` + `variant=\"outlined\"`。\n\n### `text` 和 `link` 该怎么选?`rounded` 和 `shape` 呢?\n\n`text` 是轻量文字按钮;`link` 更接近内联链接(默认悬浮下划线)。形状优先用 `shape`(`round` / `circle` / `square`);旧的 `rounded` 仍可用,等价于 `shape=\"round\"`。"
2557
+ "body": "### `type` 和 `color` / `variant` 怎么选?\n\n日常优先用 `type`。需要跨色系细调时再用 `color` + `variant`;二者齐全时覆盖 `type`。\n\n| `type` | 等价于 |\n| --- | --- |\n| `primary` | `color=\"primary\"` + `variant=\"solid\"` |\n| `default` | `color=\"default\"` + `variant=\"outlined\"` |\n| `dashed` | `color=\"default\"` + `variant=\"dashed\"` |\n| `text` | `color=\"default\"` + `variant=\"text\"` |\n| `link` | `color=\"link\"` + `variant=\"link\"` |\n\n```vue\n<MButton type=\"primary\">保存</MButton>\n```\n\n等同于\n\n```vue\n<MButton color=\"primary\" variant=\"solid\">保存</MButton>\n```\n\n### Button 的 `color` 和其它组件的 `severity`?\n\nButton 使用 `color` / `variant`。Badge、Tag、Alert、Message、Toast 等反馈组件仍使用 `severity`。\n\n### `text` 和 `link` 怎么区分?\n\n`type=\"text\"`(或 `variant=\"text\"`)保留按钮热区与高度;`type=\"link\"` 更接近内联链接。"
2546
2558
  },
2547
2559
  {
2548
2560
  "id": "无障碍",
2549
2561
  "title": "无障碍",
2550
- "body": "- 渲染原生 `<button>`。\n- 纯图标按钮请设置 `ariaLabel`(或可访问的文本标签)。\n- `loading` 时设置 `aria-busy`,并禁用交互。"
2562
+ "body": "- 默认渲染原生 `<button>`;设置 `href` 时渲染 `<a>`。\n- 纯图标按钮请设置 `ariaLabel`(或可见文本)。\n- `loading` 时设置 `aria-busy`,并阻止点击。\n- 禁用的链接按钮会去掉 `href`,并设置 `aria-disabled` 与 `tabindex=\"-1\"`。"
2551
2563
  }
2552
2564
  ],
2553
- "markdown": "---\ntitle: Button\ncategory: 01 / BASIC\ndescription: 按钮用于触发即时动作。\n---\n\n# Button\n\n按钮用于触发即时动作。\n\n## 何时使用\n\n- 需要触发表单提交、确认、导航或其它即时操作时。\n- 页面主操作使用默认(primary)按钮;次要操作用 `severity=\"secondary\"` 或 `outlined` / `text`。\n- 危险、破坏性操作用 `severity=\"danger\"`;轻量内联操作用 `text` 或 `link`。\n- 相邻一组互斥或相关操作用 `MButtonGroup`。\n\n## 引入\n\n```ts\nimport { MButton } from \"morya-ui\";\n```\n\n## 代码演示\n\n### 基础用法\n\n通过默认插槽或 `label` 展示按钮文案。\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### 类型\n\n常用组合:`severity=\"secondary\"` 默认样式、`variant=\"dashed\"` 虚线、`text` / `link` 文字链、`severity=\"danger\"` 危险、`fluid` 通栏。\n\n```vue preview src=\"./demos/VariantTypes.vue\"\n\n```\n\n### Shape\n\n`shape`:`default` / `round` / `circle` / `square`。旧 `rounded` 等价于 `shape=\"round\"`。\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Severity\n\n使用 `severity` 定义按钮语义色;省略时为 primary。\n\n```vue preview src=\"./demos/Severity.vue\"\n\n```\n\n### Styles\n\n`outlined`、`text`、`link`、`raised`、`rounded`、`plain` 可自由组合。\n\n```vue preview src=\"./demos/Styles.vue\"\n\n```\n\n### Text & Link\n\n`text` 为轻量文字按钮;`link` 呈现为无背景的内联链接样式,默认悬浮下划线,设 `:underline=\"false\"` 可关闭。二者均可与 `severity` 组合。\n\n```vue preview src=\"./demos/TextAndLink.vue\"\n\n```\n\n### Ghost & Quaternary\n\n`ghost` 为浅色填充,等同于 `text` 的悬浮态;`quaternary` 更克制,适合工具栏次要操作。也可通过 `variant` 指定。\n\n```vue preview src=\"./demos/GhostAndQuaternary.vue\"\n\n```\n\n### Button Group\n\n`MButtonGroup` 将相邻按钮拼成一组。\n\n```vue preview src=\"./demos/ButtonGroup.zh.vue\"\n\n```\n\n### Icons & Badge\n\n支持 `icon`、`iconPos`、`iconOnly`,以及 `badge` 徽标。\n\n```vue preview src=\"./demos/IconsAndBadge.vue\"\n\n```\n\n### Loading\n\n`loading` 状态下显示 spinner 并阻止点击。\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n## API\n\n### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --------------- | ---------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- |\n| `label` | `string` | — | 按钮文案。存在默认插槽内容时以插槽为准。 |\n| `icon` | `IconName \\| Component` | — | 图标名称或自定义组件。 |\n| `iconPos` | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'left'` | 图标相对标签的位置。 |\n| `iconOnly` | `boolean` | `false` | 强制方形纯图标按钮。 |\n| `badge` | `string` | — | 徽标文本。 |\n| `badgeSeverity` | `'secondary' \\| 'info' \\| 'success' \\| 'warn' \\| 'danger' \\| 'contrast' \\| null` | `null` | 徽标语义色。 |\n| `severity` | `'secondary' \\| 'success' \\| 'info' \\| 'warn' \\| 'help' \\| 'danger' \\| 'contrast'` | — | 语义色。省略时为 primary。 |\n| `color` | `string` | — | 自定义颜色,覆盖 `severity`。 |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | 尺寸。默认中等;兼容 `sm` / `lg`。 |\n| `variant` | `'outlined' \\| 'dashed' \\| 'text' \\| 'link' \\| 'ghost' \\| 'quaternary'` | — | 样式变体快捷方式,等价于对应布尔 prop。 |\n| `outlined` | `boolean` | `false` | 描边按钮。 |\n| `dashed` | `boolean` | `false` | 虚线边框。 |\n| `text` | `boolean` | `false` | 文字按钮。 |\n| `link` | `boolean` | `false` | 链接按钮。 |\n| `underline` | `boolean` | `true` | `link` 悬浮下划线。设为 `false` 可关闭。 |\n| `ghost` | `boolean` | `false` | 浅色填充,等同于 `text` 的悬浮态。 |\n| `quaternary` | `boolean` | `false` | 极轻量文字按钮。 |\n| `plain` | `boolean` | `false` | 浅色填充,等同于 `outlined` 的悬浮态;也可与 `text` / `outlined` 组合弱化。 |\n| `raised` | `boolean` | `false` | 浮起阴影。 |\n| `rounded` | `boolean` | `false` | 全圆角(兼容;推荐 `shape=\"round\"`)。 |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | 形状。 |\n| `fluid` | `boolean` | `false` | 宽度撑满容器。 |\n| `loading` | `boolean` | `false` | 加载中,禁用点击并显示 spinner。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `ripple` | `boolean` | `false` | 点击水波纹。设为 `true` 可开启。 |\n| `press` | `boolean` | `false` | 按下时轻微缩放。设为 `true` 可开启。 |\n| `nativeType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | 原生 button type。 |\n| `autofocus` | `boolean` | `false` | 原生 autofocus。 |\n| `ariaLabel` | `string` | — | 可访问名称;图标按钮建议提供。 |\n\n### Events\n\n| 事件名 | 参数 | 说明 |\n| ------- | ------------ | -------------------- |\n| `click` | `MouseEvent` | 启用状态下点击触发。 |\n\n### Slots\n\n| 插槽名 | 说明 |\n| ------------- | -------------------------- |\n| `default` | 按钮内容,优先于 `label`。 |\n| `icon` | 自定义图标。 |\n| `loadingicon` | 自定义加载图标。 |\n\n### Instance\n\n| 方法 / 属性 | 说明 |\n| ----------- | -------------------------- |\n| `focus()` | 聚焦底层 button。 |\n| `ref` | 底层 `HTMLButtonElement`。 |\n\n### Props — ButtonGroup\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `fluid` | `boolean` | `false` | 宽度撑满容器。 |\n| `ariaLabel` | `string` | — | 组合的可访问名称。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 组容器透传。 |\n\n## Design Token\n\n复用全局 `--m-*` 令牌,见[设计令牌](/docs/design-tokens)。组件级 `--m-button-*` 表将在后续补充。\n\n## Semantic DOM\n\n`MButton` 是叶子组件:根节点即原生 `<button class=\"m-button\">`,`class` / `style` / 事件直接落在该元素上(见[样式与 attrs](/docs/attrs)、[Common Props](/docs/common-props))。\n\n```text\nbutton.m-button ← 根(交互元素)\n span.m-button__ripple ← 可选:ripple 层\n span.m-button__icon ← 图标 / loading spinner(aria-hidden)\n span.m-button__spinner ← loading 时\n span.m-button__label ← 文案(插槽或 label)\n span.m-button__badge* ← 可选徽标\n```\n\n`MButton` 本身不暴露 `pt`;拼组用 `MButtonGroup` 的 `pt.root` 修改组容器。绑定样式时优先针对 `.m-button`,再按需覆盖 `__icon` / `__label` / `__badge`。\n\n## FAQ\n\n### `severity` 和 `variant` 有什么区别?\n\n`severity` 控制语义色(如 `danger`、`success`);省略时为 primary。`variant`(或对应布尔 prop)控制样式形态,如 `outlined`、`text`、`link`、`ghost`。二者可组合,例如 `severity=\"danger\"` + `variant=\"outlined\"`。\n\n### `text` 和 `link` 该怎么选?`rounded` 和 `shape` 呢?\n\n`text` 是轻量文字按钮;`link` 更接近内联链接(默认悬浮下划线)。形状优先用 `shape`(`round` / `circle` / `square`);旧的 `rounded` 仍可用,等价于 `shape=\"round\"`。\n\n## 无障碍\n\n- 渲染原生 `<button>`。\n- 纯图标按钮请设置 `ariaLabel`(或可访问的文本标签)。\n- `loading` 时设置 `aria-busy`,并禁用交互。\n"
2565
+ "markdown": "---\ntitle: Button\ncategory: 01 / BASIC\ndescription: 触发即时操作的按钮。\n---\n\n# Button\n\n触发提交、确认、导航等即时操作。\n\n## 何时使用\n\n- 主操作:`type=\"primary\"`,同一操作区通常只放一个。\n- 次操作:默认按钮,或 `type=\"dashed\"` / `type=\"text\"`。\n- 内联导航或弱操作:`type=\"link\"` / `type=\"text\"`。\n- 破坏性操作:加 `danger`,并配合确认。\n- 相邻操作需要拼成一组时:用 `MButtonGroup`(仅视觉拼组)。\n\n## 引入\n\n```ts\nimport { MButton, MButtonGroup } from 'morya-ui'\n```\n\n## 代码演示\n\n### 基础用法\n\n`type` 是 `color` + `variant` 的语法糖。省略时为默认描边按钮。\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### 颜色与变体\n\n需要更细控制时直接设 `color` 与 `variant`;二者同时存在时优先于 `type`。\n\n```vue preview src=\"./demos/ColorVariant.vue\"\n\n```\n\n### 图标\n\n`icon` 可配名称或组件;`iconPlacement` 控制位置;纯图标请提供 `ariaLabel`。\n\n```vue preview src=\"./demos/Icon.vue\"\n\n```\n\n### 尺寸\n\n```vue preview src=\"./demos/Size.vue\"\n\n```\n\n### 形状\n\n`shape`:`default` / `round` / `circle` / `square`。\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### 危险按钮\n\n`danger` 将颜色切到危险色,并保留当前 `type` / `variant` 形态。\n\n```vue preview src=\"./demos/Danger.vue\"\n\n```\n\n### 幽灵按钮\n\n`ghost` 让背景透明,适合深色或复杂底图。对 `text` / `link` 无效。\n\n```vue preview src=\"./demos/Ghost.vue\"\n\n```\n\n### 加载中\n\n`loading` 可为布尔值,或 `{ delay, icon }`。加载中会禁用点击。\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### 不可用\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n### Block\n\n`block` 让按钮宽度撑满父容器。\n\n```vue preview src=\"./demos/Block.vue\"\n\n```\n\n### 按钮组\n\n`MButtonGroup` 只做视觉拼组(圆角与边框衔接),没有选中态。需要互斥切换时用 [`SelectButton`](/components/SelectButton)。\n\n```vue preview src=\"./demos/ButtonGroup.zh.vue\"\n\n```\n\n### 水波纹与按压\n\n`ripple` / `press` 默认关闭,需要时显式开启。\n\n```vue preview src=\"./demos/RipplePress.vue\"\n\n```\n\n## API\n\n推荐组合顺序:`type` → `shape` → `size` → `loading` → `disabled`。\n\n### Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `type` | `'default' \\| 'primary' \\| 'dashed' \\| 'link' \\| 'text'` | `'default'` | 语法糖。同时设置 `color` 与 `variant` 时以后者为准。 |\n| `color` | `'default' \\| 'primary' \\| 'danger' \\| 'success' \\| 'info' \\| 'warning' \\| 'help' \\| 'contrast'` | — | 颜色轴。 |\n| `variant` | `'solid' \\| 'outlined' \\| 'dashed' \\| 'filled' \\| 'text' \\| 'link'` | — | 变体轴。 |\n| `danger` | `boolean` | `false` | 危险色语法糖。设置了 `color` 时以 `color` 为准。 |\n| `ghost` | `boolean` | `false` | 透明背景。对 `text` / `link` 无效。 |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | 形状。 |\n| `size` | `'small' \\| 'medium' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | 尺寸;可继承 ConfigProvider。 |\n| `block` | `boolean` | `false` | 宽度撑满父容器。 |\n| `loading` | `boolean \\| { delay?: number; icon?: IconName \\| Component }` | `false` | 加载中;可延迟出现并自定义图标。 |\n| `disabled` | `boolean` | `false` | 禁用;可继承 ConfigProvider。 |\n| `htmlType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | 原生 `button` 的 `type`。 |\n| `href` | `string` | — | 设置后渲染为 `<a>`。 |\n| `target` | `string` | — | 链接 `target`,需配合 `href`。 |\n| `label` | `string` | — | 文案;默认插槽优先。 |\n| `icon` | `IconName \\| Component` | — | 图标名称或组件。 |\n| `iconPlacement` | `'start' \\| 'end'` | `'start'` | 图标位置。 |\n| `iconOnly` | `boolean` | `false` | 强制纯图标方形按钮。 |\n| `autoInsertSpace` | `boolean` | `true` | 两个汉字之间插入空格。 |\n| `ripple` | `boolean` | `false` | 点击水波纹。 |\n| `press` | `boolean` | `false` | 按下缩放。 |\n| `autofocus` | `boolean` | `false` | 原生 autofocus。 |\n| `ariaLabel` | `string` | — | 可访问名称;纯图标按钮建议提供。 |\n| `pt` | `{ root?, icon?, content? }` | — | 语义结构透传。 |\n\n### Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `click` | `MouseEvent` | 点击时触发;`loading` / `disabled` 时不触发。 |\n\n### Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 按钮内容,优先于 `label`。 |\n| `icon` | 自定义图标。 |\n| `loadingicon` | 自定义加载图标。 |\n\n### Instance\n\n| 方法 / 属性 | 说明 |\n| --- | --- |\n| `focus()` | 聚焦根元素。 |\n| `ref` | 根 `HTMLButtonElement` 或 `HTMLAnchorElement`。 |\n\n### MButtonGroup Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `block` | `boolean` | `false` | 宽度撑满父容器。 |\n| `ariaLabel` | `string` | — | 组的可访问名称。 |\n| `pt` | `{ root? }` | — | 组容器透传。 |\n\n## Design Token\n\n复用全局 `--m-*` 令牌,见[设计令牌](/docs/design-tokens)。按钮在根节点暴露 `--m-button-*`(尺寸、圆角、色阶、填充透明度、动效等),主题切换时跟随 `--m-color-*` / `--m-control-*` / `--m-motion-*`。\n\n## Semantic DOM\n\n根节点即交互元素:有 `href` 时为 `<a class=\"m-button\">`,否则为 `<button class=\"m-button\">`。\n\n```text\nbutton.m-button / a.m-button\n span.m-button__ripple* ← ripple 开启时\n span.m-button__icon* ← 图标 / loading\n span.m-button__label* ← 文案\n```\n\n可用 `pt.root` / `pt.icon` / `pt.content` 覆盖各节点。更多约定见[样式与 attrs](/docs/attrs)、[Common Props](/docs/common-props)。\n\n## FAQ\n\n### `type` 和 `color` / `variant` 怎么选?\n\n日常优先用 `type`。需要跨色系细调时再用 `color` + `variant`;二者齐全时覆盖 `type`。\n\n| `type` | 等价于 |\n| --- | --- |\n| `primary` | `color=\"primary\"` + `variant=\"solid\"` |\n| `default` | `color=\"default\"` + `variant=\"outlined\"` |\n| `dashed` | `color=\"default\"` + `variant=\"dashed\"` |\n| `text` | `color=\"default\"` + `variant=\"text\"` |\n| `link` | `color=\"link\"` + `variant=\"link\"` |\n\n```vue\n<MButton type=\"primary\">保存</MButton>\n```\n\n等同于\n\n```vue\n<MButton color=\"primary\" variant=\"solid\">保存</MButton>\n```\n\n### Button 的 `color` 和其它组件的 `severity`?\n\nButton 使用 `color` / `variant`。Badge、Tag、Alert、Message、Toast 等反馈组件仍使用 `severity`。\n\n### `text` 和 `link` 怎么区分?\n\n`type=\"text\"`(或 `variant=\"text\"`)保留按钮热区与高度;`type=\"link\"` 更接近内联链接。\n\n## 无障碍\n\n- 默认渲染原生 `<button>`;设置 `href` 时渲染 `<a>`。\n- 纯图标按钮请设置 `ariaLabel`(或可见文本)。\n- `loading` 时设置 `aria-busy`,并阻止点击。\n- 禁用的链接按钮会去掉 `href`,并设置 `aria-disabled` 与 `tabindex=\"-1\"`。\n"
2554
2566
  },
2555
2567
  "en-US": {
2556
2568
  "title": "Button",
2557
- "description": "Button triggers an immediate action.",
2569
+ "description": "A button that triggers an immediate action.",
2558
2570
  "sections": [
2559
2571
  {
2560
2572
  "id": "overview",
2561
2573
  "title": "",
2562
- "body": "# Button\n\nButton triggers an immediate action."
2574
+ "body": "# Button\n\nUse Button for submit, confirm, navigate, and other immediate actions."
2563
2575
  },
2564
2576
  {
2565
2577
  "id": "when-to-use",
2566
2578
  "title": "When to use",
2567
- "body": "- Use when the user needs to trigger a submit, confirm, navigate, or other immediate action.\n- Prefer the default (primary) button for the main action; use `severity=\"secondary\"` or `outlined` / `text` for secondary actions.\n- Use `severity=\"danger\"` for destructive actions; use `text` or `link` for lightweight inline actions.\n- Use `MButtonGroup` when adjacent buttons belong together."
2579
+ "body": "- Primary action: `type=\"primary\"`. Keep one primary action in a region.\n- Secondary action: the default button, or `type=\"dashed\"` / `type=\"text\"`.\n- Inline or low-emphasis action: `type=\"link\"` / `type=\"text\"`.\n- Destructive action: add `danger`, and confirm when needed.\n- Adjacent actions that should look joined: wrap them in `MButtonGroup` (visual only)."
2568
2580
  },
2569
2581
  {
2570
2582
  "id": "import",
2571
2583
  "title": "Import",
2572
- "body": "```ts\nimport { MButton } from \"morya-ui\";\n```"
2584
+ "body": "```ts\nimport { MButton, MButtonGroup } from 'morya-ui'\n```"
2573
2585
  },
2574
2586
  {
2575
2587
  "id": "examples",
2576
2588
  "title": "Examples",
2577
- "body": "### Basic\n\nShow button text via the default slot or the `label` prop.\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### Types\n\nCommon combinations: default primary, `severity=\"secondary\"`, `variant=\"dashed\"`, `text` / `link`, `severity=\"danger\"`, and `fluid` for full width.\n\n```vue preview src=\"./demos/VariantTypes.vue\"\n\n```\n\n### Shape\n\n`shape`: `default` / `round` / `circle` / `square`. Legacy `rounded` maps to `shape=\"round\"`.\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Severity\n\nUse `severity` for semantic color; defaults to primary when omitted.\n\n```vue preview src=\"./demos/Severity.vue\"\n\n```\n\n### Styles\n\n`outlined`, `text`, `link`, `raised`, `rounded`, and `plain` can be combined freely.\n\n```vue preview src=\"./demos/Styles.vue\"\n\n```\n\n### Text & Link\n\n`text` is a lightweight text button; `link` renders as a backgroundless inline link style with underline on hover by default. Set `:underline=\"false\"` to disable. Both can be combined with `severity`.\n\n```vue preview src=\"./demos/TextAndLink.vue\"\n\n```\n\n### Ghost & Quaternary\n\n`ghost` is a soft fill matching text hover; `quaternary` is quieter for secondary toolbar actions. Both can be set via `variant`.\n\n```vue preview src=\"./demos/GhostAndQuaternary.vue\"\n\n```\n\n### Button Group\n\n`MButtonGroup` joins adjacent buttons.\n\n```vue preview src=\"./demos/ButtonGroup.en.vue\"\n\n```\n\n### Icons & Badge\n\nSupports `icon`, `iconPos`, `iconOnly`, and a `badge`.\n\n```vue preview src=\"./demos/IconsAndBadge.vue\"\n\n```\n\n### Loading\n\nIn the `loading` state, a spinner is shown and clicks are blocked.\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```"
2589
+ "body": "### Basic\n\n`type` is sugar for a `color` + `variant` pair. Omit it for the default outlined button.\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### Color & variant\n\nSet `color` and `variant` for finer control. When both are set, they win over `type`.\n\n```vue preview src=\"./demos/ColorVariant.vue\"\n\n```\n\n### Icon\n\n`icon` accepts a name or component. Use `iconPlacement` for position. Icon-only buttons need `ariaLabel`.\n\n```vue preview src=\"./demos/Icon.vue\"\n\n```\n\n### Size\n\n```vue preview src=\"./demos/Size.vue\"\n\n```\n\n### Shape\n\n`shape`: `default` / `round` / `circle` / `square`.\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Danger\n\n`danger` switches the color to danger while keeping the current `type` / `variant` look.\n\n```vue preview src=\"./demos/Danger.vue\"\n\n```\n\n### Ghost\n\n`ghost` makes the background transparent for dark or busy surfaces. It is ignored for `text` / `link`.\n\n```vue preview src=\"./demos/Ghost.vue\"\n\n```\n\n### Loading\n\n`loading` accepts a boolean or `{ delay, icon }`. Clicks are blocked while loading.\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n### Block\n\n`block` stretches the button to the parent width.\n\n```vue preview src=\"./demos/Block.vue\"\n\n```\n\n### Button group\n\n`MButtonGroup` only joins adjacent buttons visually. It has no selected state. For mutually exclusive switching, use [`SelectButton`](/components/SelectButton).\n\n```vue preview src=\"./demos/ButtonGroup.en.vue\"\n\n```\n\n### Ripple & press\n\n`ripple` and `press` are off by default. Turn them on when you want the motion.\n\n```vue preview src=\"./demos/RipplePress.vue\"\n\n```"
2578
2590
  },
2579
2591
  {
2580
2592
  "id": "api",
2581
2593
  "title": "API",
2582
- "body": "### Props\n\n| Prop | Type | Default | Description |\n| --------------- | ---------------------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------- |\n| `label` | `string` | — | Button text. Default slot content takes precedence when present. |\n| `icon` | `IconName \\| Component` | — | Icon name or custom component. |\n| `iconPos` | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'left'` | Icon position relative to the label. |\n| `iconOnly` | `boolean` | `false` | Force a square icon-only button. |\n| `badge` | `string` | — | Badge text. |\n| `badgeSeverity` | `'secondary' \\| 'info' \\| 'success' \\| 'warn' \\| 'danger' \\| 'contrast' \\| null` | `null` | Badge semantic color. |\n| `severity` | `'secondary' \\| 'success' \\| 'info' \\| 'warn' \\| 'help' \\| 'danger' \\| 'contrast'` | — | Semantic color. Defaults to primary when omitted. |\n| `color` | `string` | — | Custom color; overrides `severity`. |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | Size. Medium by default; `sm` / `lg` aliases supported. |\n| `variant` | `'outlined' \\| 'text' \\| 'link' \\| 'ghost' \\| 'quaternary'` | — | Style variant shortcut, equivalent to the matching boolean prop. |\n| `outlined` | `boolean` | `false` | Outlined button. |\n| `text` | `boolean` | `false` | Text button. |\n| `link` | `boolean` | `false` | Link button. |\n| `underline` | `boolean` | `true` | Underline on hover for `link`. Set `false` to disable. |\n| `ghost` | `boolean` | `false` | Soft fill matching text hover. |\n| `quaternary` | `boolean` | `false` | Extra-quiet text button. |\n| `plain` | `boolean` | `false` | Soft fill matching outlined hover; can also mute `text` / `outlined`. |\n| `raised` | `boolean` | `false` | Raised shadow. |\n| `rounded` | `boolean` | `false` | Fully rounded. |\n| `fluid` | `boolean` | `false` | Stretch to full container width. |\n| `loading` | `boolean` | `false` | Loading state; disables clicks and shows a spinner. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `ripple` | `boolean` | `false` | Click ripple ink. Set `true` to enable. |\n| `press` | `boolean` | `false` | Slight scale while pressed. Set `true` to enable. |\n| `nativeType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Native button type. |\n| `autofocus` | `boolean` | `false` | Native autofocus. |\n| `ariaLabel` | `string` | — | Accessible name; recommended for icon-only buttons. |\n\n### Events\n\n| Event | Prop | Description |\n| ------- | ------------ | ---------------------------- |\n| `click` | `MouseEvent` | Fired on click when enabled. |\n\n### Slots\n\n| Slot | Description |\n| ------------- | ---------------------------------------------- |\n| `default` | Button content; takes precedence over `label`. |\n| `icon` | Custom icon. |\n| `loadingicon` | Custom loading icon. |\n\n### Instance\n\n| Method / Property | Description |\n| ----------------- | ------------------------------- |\n| `focus()` | Focus the underlying button. |\n| `ref` | Underlying `HTMLButtonElement`. |\n\n### Props — ButtonGroup\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `fluid` | `boolean` | `false` | Stretch to full container width. |\n| `ariaLabel` | `string` | — | Accessible name for the group. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Group wrapper pass-through. |"
2594
+ "body": "Suggested composition order: `type` → `shape` → `size` → `loading` → `disabled`.\n\n### Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `type` | `'default' \\| 'primary' \\| 'dashed' \\| 'link' \\| 'text'` | `'default'` | Sugar. When both `color` and `variant` are set, they win. |\n| `color` | `'default' \\| 'primary' \\| 'danger' \\| 'success' \\| 'info' \\| 'warning' \\| 'help' \\| 'contrast'` | — | Color axis. |\n| `variant` | `'solid' \\| 'outlined' \\| 'dashed' \\| 'filled' \\| 'text' \\| 'link'` | — | Variant axis. |\n| `danger` | `boolean` | `false` | Danger-color sugar. `color` wins when set. |\n| `ghost` | `boolean` | `false` | Transparent background. Ignored for `text` / `link`. |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | Corner shape. |\n| `size` | `'small' \\| 'medium' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | Size; can inherit from ConfigProvider. |\n| `block` | `boolean` | `false` | Stretch to the parent width. |\n| `loading` | `boolean \\| { delay?: number; icon?: IconName \\| Component }` | `false` | Loading state with optional delay and icon. |\n| `disabled` | `boolean` | `false` | Disabled; can inherit from ConfigProvider. |\n| `htmlType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Native button `type`. |\n| `href` | `string` | — | Renders as `<a>` when set. |\n| `target` | `string` | — | Anchor `target`; requires `href`. |\n| `label` | `string` | — | Label text; the default slot wins when present. |\n| `icon` | `IconName \\| Component` | — | Icon name or component. |\n| `iconPlacement` | `'start' \\| 'end'` | `'start'` | Icon placement. |\n| `iconOnly` | `boolean` | `false` | Force a square icon-only button. |\n| `autoInsertSpace` | `boolean` | `true` | Insert a space between two Chinese characters. |\n| `ripple` | `boolean` | `false` | Click ripple. |\n| `press` | `boolean` | `false` | Press scale. |\n| `autofocus` | `boolean` | `false` | Native autofocus. |\n| `ariaLabel` | `string` | — | Accessible name; recommended for icon-only buttons. |\n| `pt` | `{ root?, icon?, content? }` | — | Semantic DOM pass-through. |\n\n### Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `click` | `MouseEvent` | Fired on click; suppressed while `loading` / `disabled`. |\n\n### Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Button content; wins over `label`. |\n| `icon` | Custom icon. |\n| `loadingicon` | Custom loading icon. |\n\n### Instance\n\n| Member | Description |\n| --- | --- |\n| `focus()` | Focus the root element. |\n| `ref` | Root `HTMLButtonElement` or `HTMLAnchorElement`. |\n\n### MButtonGroup Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `block` | `boolean` | `false` | Stretch to the parent width. |\n| `ariaLabel` | `string` | — | Accessible name for the group. |\n| `pt` | `{ root? }` | — | Group wrapper pass-through. |"
2583
2595
  },
2584
2596
  {
2585
2597
  "id": "design-token",
2586
2598
  "title": "Design Token",
2587
- "body": "Reuses global `--m-*` tokens; see [Design Tokens](/docs/design-tokens). A component-level `--m-button-*` table will follow later."
2599
+ "body": "Reuses global `--m-*` tokens; see [Design Tokens](/docs/design-tokens). Button exposes `--m-button-*` on the root (size, radius, tones, fill opacity, motion). Theme switches follow `--m-color-*` / `--m-control-*` / `--m-motion-*`."
2588
2600
  },
2589
2601
  {
2590
2602
  "id": "semantic-dom",
2591
2603
  "title": "Semantic DOM",
2592
- "body": "`MButton` is a leaf control: the root is the native `<button class=\"m-button\">`. `class` / `style` / events land on that element (see [Attrs](/docs/attrs) and [Common Props](/docs/common-props)).\n\n```text\nbutton.m-button ← root (interactive element)\n span.m-button__ripple ← optional ripple layer\n span.m-button__icon ← icon / loading spinner (aria-hidden)\n span.m-button__spinner ← while loading\n span.m-button__label ← label (slot or `label` prop)\n span.m-button__badge* ← optional badge\n```\n\n`MButton` itself does not expose `pt`; use `MButtonGroup` `pt.root` for the group wrapper. Target `.m-button` first when styling, then `__icon` / `__label` / `__badge` as needed."
2604
+ "body": "The root is the interactive element: `<a class=\"m-button\">` when `href` is set, otherwise `<button class=\"m-button\">`.\n\n```text\nbutton.m-button / a.m-button\n span.m-button__ripple* ← when ripple is on\n span.m-button__icon* ← icon / loading\n span.m-button__label* ← label\n```\n\nOverride parts with `pt.root` / `pt.icon` / `pt.content`. See also [Attrs](/docs/attrs) and [Common Props](/docs/common-props)."
2593
2605
  },
2594
2606
  {
2595
2607
  "id": "faq",
2596
2608
  "title": "FAQ",
2597
- "body": "### What is the difference between `severity` and `variant`?\n\n`severity` sets the semantic color (e.g. `danger`, `success`); primary is used when omitted. `variant` (or the matching boolean prop) sets the visual style such as `outlined`, `text`, `link`, or `ghost`. They compose, e.g. `severity=\"danger\"` + `variant=\"outlined\"`.\n\n### When should I use `text` vs `link`, or `rounded` vs `shape`?\n\n`text` is a lightweight text button; `link` behaves more like an inline link (underline on hover by default). Prefer `shape` (`round` / `circle` / `square`) for geometry; legacy `rounded` still works and maps to `shape=\"round\"`."
2609
+ "body": "### How do I choose between `type` and `color` / `variant`?\n\nPrefer `type` for everyday use. Reach for `color` + `variant` when you need finer cross-tone control. When both axes are set, they override `type`.\n\n| `type` | Equals |\n| --- | --- |\n| `primary` | `color=\"primary\"` + `variant=\"solid\"` |\n| `default` | `color=\"default\"` + `variant=\"outlined\"` |\n| `dashed` | `color=\"default\"` + `variant=\"dashed\"` |\n| `text` | `color=\"default\"` + `variant=\"text\"` |\n| `link` | `color=\"link\"` + `variant=\"link\"` |\n\n```vue\n<MButton type=\"primary\">Save</MButton>\n```\n\nequals\n\n```vue\n<MButton color=\"primary\" variant=\"solid\">Save</MButton>\n```\n\n### Button `color` vs other components' `severity`?\n\nButton uses `color` / `variant`. Feedback components such as Badge, Tag, Alert, Message, and Toast still use `severity`.\n\n### `text` vs `link`?\n\n`type=\"text\"` (or `variant=\"text\"`) keeps button height and hit area. `type=\"link\"` is closer to an inline link."
2598
2610
  },
2599
2611
  {
2600
2612
  "id": "accessibility",
2601
2613
  "title": "Accessibility",
2602
- "body": "- Renders a native `<button>`.\n- For icon-only buttons, set `ariaLabel` (or provide an accessible text label).\n- Sets `aria-busy` while `loading` and disables interaction."
2614
+ "body": "- Renders a native `<button>` by default; renders `<a>` when `href` is set.\n- Provide `ariaLabel` (or visible text) for icon-only buttons.\n- Sets `aria-busy` while `loading` and blocks interaction.\n- A disabled link button drops `href` and sets `aria-disabled` with `tabindex=\"-1\"`."
2603
2615
  }
2604
2616
  ],
2605
- "markdown": "---\ntitle: Button\ncategory: 01 / BASIC\ndescription: Button triggers an immediate action.\n---\n\n# Button\n\nButton triggers an immediate action.\n\n## When to use\n\n- Use when the user needs to trigger a submit, confirm, navigate, or other immediate action.\n- Prefer the default (primary) button for the main action; use `severity=\"secondary\"` or `outlined` / `text` for secondary actions.\n- Use `severity=\"danger\"` for destructive actions; use `text` or `link` for lightweight inline actions.\n- Use `MButtonGroup` when adjacent buttons belong together.\n\n## Import\n\n```ts\nimport { MButton } from \"morya-ui\";\n```\n\n## Examples\n\n### Basic\n\nShow button text via the default slot or the `label` prop.\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### Types\n\nCommon combinations: default primary, `severity=\"secondary\"`, `variant=\"dashed\"`, `text` / `link`, `severity=\"danger\"`, and `fluid` for full width.\n\n```vue preview src=\"./demos/VariantTypes.vue\"\n\n```\n\n### Shape\n\n`shape`: `default` / `round` / `circle` / `square`. Legacy `rounded` maps to `shape=\"round\"`.\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Severity\n\nUse `severity` for semantic color; defaults to primary when omitted.\n\n```vue preview src=\"./demos/Severity.vue\"\n\n```\n\n### Styles\n\n`outlined`, `text`, `link`, `raised`, `rounded`, and `plain` can be combined freely.\n\n```vue preview src=\"./demos/Styles.vue\"\n\n```\n\n### Text & Link\n\n`text` is a lightweight text button; `link` renders as a backgroundless inline link style with underline on hover by default. Set `:underline=\"false\"` to disable. Both can be combined with `severity`.\n\n```vue preview src=\"./demos/TextAndLink.vue\"\n\n```\n\n### Ghost & Quaternary\n\n`ghost` is a soft fill matching text hover; `quaternary` is quieter for secondary toolbar actions. Both can be set via `variant`.\n\n```vue preview src=\"./demos/GhostAndQuaternary.vue\"\n\n```\n\n### Button Group\n\n`MButtonGroup` joins adjacent buttons.\n\n```vue preview src=\"./demos/ButtonGroup.en.vue\"\n\n```\n\n### Icons & Badge\n\nSupports `icon`, `iconPos`, `iconOnly`, and a `badge`.\n\n```vue preview src=\"./demos/IconsAndBadge.vue\"\n\n```\n\n### Loading\n\nIn the `loading` state, a spinner is shown and clicks are blocked.\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n## API\n\n### Props\n\n| Prop | Type | Default | Description |\n| --------------- | ---------------------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------- |\n| `label` | `string` | — | Button text. Default slot content takes precedence when present. |\n| `icon` | `IconName \\| Component` | — | Icon name or custom component. |\n| `iconPos` | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'left'` | Icon position relative to the label. |\n| `iconOnly` | `boolean` | `false` | Force a square icon-only button. |\n| `badge` | `string` | — | Badge text. |\n| `badgeSeverity` | `'secondary' \\| 'info' \\| 'success' \\| 'warn' \\| 'danger' \\| 'contrast' \\| null` | `null` | Badge semantic color. |\n| `severity` | `'secondary' \\| 'success' \\| 'info' \\| 'warn' \\| 'help' \\| 'danger' \\| 'contrast'` | — | Semantic color. Defaults to primary when omitted. |\n| `color` | `string` | — | Custom color; overrides `severity`. |\n| `size` | `'small' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | Size. Medium by default; `sm` / `lg` aliases supported. |\n| `variant` | `'outlined' \\| 'text' \\| 'link' \\| 'ghost' \\| 'quaternary'` | — | Style variant shortcut, equivalent to the matching boolean prop. |\n| `outlined` | `boolean` | `false` | Outlined button. |\n| `text` | `boolean` | `false` | Text button. |\n| `link` | `boolean` | `false` | Link button. |\n| `underline` | `boolean` | `true` | Underline on hover for `link`. Set `false` to disable. |\n| `ghost` | `boolean` | `false` | Soft fill matching text hover. |\n| `quaternary` | `boolean` | `false` | Extra-quiet text button. |\n| `plain` | `boolean` | `false` | Soft fill matching outlined hover; can also mute `text` / `outlined`. |\n| `raised` | `boolean` | `false` | Raised shadow. |\n| `rounded` | `boolean` | `false` | Fully rounded. |\n| `fluid` | `boolean` | `false` | Stretch to full container width. |\n| `loading` | `boolean` | `false` | Loading state; disables clicks and shows a spinner. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `ripple` | `boolean` | `false` | Click ripple ink. Set `true` to enable. |\n| `press` | `boolean` | `false` | Slight scale while pressed. Set `true` to enable. |\n| `nativeType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Native button type. |\n| `autofocus` | `boolean` | `false` | Native autofocus. |\n| `ariaLabel` | `string` | — | Accessible name; recommended for icon-only buttons. |\n\n### Events\n\n| Event | Prop | Description |\n| ------- | ------------ | ---------------------------- |\n| `click` | `MouseEvent` | Fired on click when enabled. |\n\n### Slots\n\n| Slot | Description |\n| ------------- | ---------------------------------------------- |\n| `default` | Button content; takes precedence over `label`. |\n| `icon` | Custom icon. |\n| `loadingicon` | Custom loading icon. |\n\n### Instance\n\n| Method / Property | Description |\n| ----------------- | ------------------------------- |\n| `focus()` | Focus the underlying button. |\n| `ref` | Underlying `HTMLButtonElement`. |\n\n### Props — ButtonGroup\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `fluid` | `boolean` | `false` | Stretch to full container width. |\n| `ariaLabel` | `string` | — | Accessible name for the group. |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Group wrapper pass-through. |\n\n## Design Token\n\nReuses global `--m-*` tokens; see [Design Tokens](/docs/design-tokens). A component-level `--m-button-*` table will follow later.\n\n## Semantic DOM\n\n`MButton` is a leaf control: the root is the native `<button class=\"m-button\">`. `class` / `style` / events land on that element (see [Attrs](/docs/attrs) and [Common Props](/docs/common-props)).\n\n```text\nbutton.m-button ← root (interactive element)\n span.m-button__ripple ← optional ripple layer\n span.m-button__icon ← icon / loading spinner (aria-hidden)\n span.m-button__spinner ← while loading\n span.m-button__label ← label (slot or `label` prop)\n span.m-button__badge* ← optional badge\n```\n\n`MButton` itself does not expose `pt`; use `MButtonGroup` `pt.root` for the group wrapper. Target `.m-button` first when styling, then `__icon` / `__label` / `__badge` as needed.\n\n## FAQ\n\n### What is the difference between `severity` and `variant`?\n\n`severity` sets the semantic color (e.g. `danger`, `success`); primary is used when omitted. `variant` (or the matching boolean prop) sets the visual style such as `outlined`, `text`, `link`, or `ghost`. They compose, e.g. `severity=\"danger\"` + `variant=\"outlined\"`.\n\n### When should I use `text` vs `link`, or `rounded` vs `shape`?\n\n`text` is a lightweight text button; `link` behaves more like an inline link (underline on hover by default). Prefer `shape` (`round` / `circle` / `square`) for geometry; legacy `rounded` still works and maps to `shape=\"round\"`.\n\n## Accessibility\n\n- Renders a native `<button>`.\n- For icon-only buttons, set `ariaLabel` (or provide an accessible text label).\n- Sets `aria-busy` while `loading` and disables interaction.\n"
2617
+ "markdown": "---\ntitle: Button\ncategory: 01 / BASIC\ndescription: A button that triggers an immediate action.\n---\n\n# Button\n\nUse Button for submit, confirm, navigate, and other immediate actions.\n\n## When to use\n\n- Primary action: `type=\"primary\"`. Keep one primary action in a region.\n- Secondary action: the default button, or `type=\"dashed\"` / `type=\"text\"`.\n- Inline or low-emphasis action: `type=\"link\"` / `type=\"text\"`.\n- Destructive action: add `danger`, and confirm when needed.\n- Adjacent actions that should look joined: wrap them in `MButtonGroup` (visual only).\n\n## Import\n\n```ts\nimport { MButton, MButtonGroup } from 'morya-ui'\n```\n\n## Examples\n\n### Basic\n\n`type` is sugar for a `color` + `variant` pair. Omit it for the default outlined button.\n\n```vue preview src=\"./demos/Basic.vue\"\n\n```\n\n### Color & variant\n\nSet `color` and `variant` for finer control. When both are set, they win over `type`.\n\n```vue preview src=\"./demos/ColorVariant.vue\"\n\n```\n\n### Icon\n\n`icon` accepts a name or component. Use `iconPlacement` for position. Icon-only buttons need `ariaLabel`.\n\n```vue preview src=\"./demos/Icon.vue\"\n\n```\n\n### Size\n\n```vue preview src=\"./demos/Size.vue\"\n\n```\n\n### Shape\n\n`shape`: `default` / `round` / `circle` / `square`.\n\n```vue preview src=\"./demos/Shape.vue\"\n\n```\n\n### Danger\n\n`danger` switches the color to danger while keeping the current `type` / `variant` look.\n\n```vue preview src=\"./demos/Danger.vue\"\n\n```\n\n### Ghost\n\n`ghost` makes the background transparent for dark or busy surfaces. It is ignored for `text` / `link`.\n\n```vue preview src=\"./demos/Ghost.vue\"\n\n```\n\n### Loading\n\n`loading` accepts a boolean or `{ delay, icon }`. Clicks are blocked while loading.\n\n```vue preview src=\"./demos/Loading.vue\"\n\n```\n\n### Disabled\n\n```vue preview src=\"./demos/Disabled.vue\"\n\n```\n\n### Block\n\n`block` stretches the button to the parent width.\n\n```vue preview src=\"./demos/Block.vue\"\n\n```\n\n### Button group\n\n`MButtonGroup` only joins adjacent buttons visually. It has no selected state. For mutually exclusive switching, use [`SelectButton`](/components/SelectButton).\n\n```vue preview src=\"./demos/ButtonGroup.en.vue\"\n\n```\n\n### Ripple & press\n\n`ripple` and `press` are off by default. Turn them on when you want the motion.\n\n```vue preview src=\"./demos/RipplePress.vue\"\n\n```\n\n## API\n\nSuggested composition order: `type` → `shape` → `size` → `loading` → `disabled`.\n\n### Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `type` | `'default' \\| 'primary' \\| 'dashed' \\| 'link' \\| 'text'` | `'default'` | Sugar. When both `color` and `variant` are set, they win. |\n| `color` | `'default' \\| 'primary' \\| 'danger' \\| 'success' \\| 'info' \\| 'warning' \\| 'help' \\| 'contrast'` | — | Color axis. |\n| `variant` | `'solid' \\| 'outlined' \\| 'dashed' \\| 'filled' \\| 'text' \\| 'link'` | — | Variant axis. |\n| `danger` | `boolean` | `false` | Danger-color sugar. `color` wins when set. |\n| `ghost` | `boolean` | `false` | Transparent background. Ignored for `text` / `link`. |\n| `shape` | `'default' \\| 'circle' \\| 'round' \\| 'square'` | `'default'` | Corner shape. |\n| `size` | `'small' \\| 'medium' \\| 'large' \\| 'sm' \\| 'md' \\| 'lg'` | — | Size; can inherit from ConfigProvider. |\n| `block` | `boolean` | `false` | Stretch to the parent width. |\n| `loading` | `boolean \\| { delay?: number; icon?: IconName \\| Component }` | `false` | Loading state with optional delay and icon. |\n| `disabled` | `boolean` | `false` | Disabled; can inherit from ConfigProvider. |\n| `htmlType` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Native button `type`. |\n| `href` | `string` | — | Renders as `<a>` when set. |\n| `target` | `string` | — | Anchor `target`; requires `href`. |\n| `label` | `string` | — | Label text; the default slot wins when present. |\n| `icon` | `IconName \\| Component` | — | Icon name or component. |\n| `iconPlacement` | `'start' \\| 'end'` | `'start'` | Icon placement. |\n| `iconOnly` | `boolean` | `false` | Force a square icon-only button. |\n| `autoInsertSpace` | `boolean` | `true` | Insert a space between two Chinese characters. |\n| `ripple` | `boolean` | `false` | Click ripple. |\n| `press` | `boolean` | `false` | Press scale. |\n| `autofocus` | `boolean` | `false` | Native autofocus. |\n| `ariaLabel` | `string` | — | Accessible name; recommended for icon-only buttons. |\n| `pt` | `{ root?, icon?, content? }` | — | Semantic DOM pass-through. |\n\n### Events\n\n| Event | Payload | Description |\n| --- | --- | --- |\n| `click` | `MouseEvent` | Fired on click; suppressed while `loading` / `disabled`. |\n\n### Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Button content; wins over `label`. |\n| `icon` | Custom icon. |\n| `loadingicon` | Custom loading icon. |\n\n### Instance\n\n| Member | Description |\n| --- | --- |\n| `focus()` | Focus the root element. |\n| `ref` | Root `HTMLButtonElement` or `HTMLAnchorElement`. |\n\n### MButtonGroup Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `block` | `boolean` | `false` | Stretch to the parent width. |\n| `ariaLabel` | `string` | — | Accessible name for the group. |\n| `pt` | `{ root? }` | — | Group wrapper pass-through. |\n\n## Design Token\n\nReuses global `--m-*` tokens; see [Design Tokens](/docs/design-tokens). Button exposes `--m-button-*` on the root (size, radius, tones, fill opacity, motion). Theme switches follow `--m-color-*` / `--m-control-*` / `--m-motion-*`.\n\n## Semantic DOM\n\nThe root is the interactive element: `<a class=\"m-button\">` when `href` is set, otherwise `<button class=\"m-button\">`.\n\n```text\nbutton.m-button / a.m-button\n span.m-button__ripple* ← when ripple is on\n span.m-button__icon* ← icon / loading\n span.m-button__label* ← label\n```\n\nOverride parts with `pt.root` / `pt.icon` / `pt.content`. See also [Attrs](/docs/attrs) and [Common Props](/docs/common-props).\n\n## FAQ\n\n### How do I choose between `type` and `color` / `variant`?\n\nPrefer `type` for everyday use. Reach for `color` + `variant` when you need finer cross-tone control. When both axes are set, they override `type`.\n\n| `type` | Equals |\n| --- | --- |\n| `primary` | `color=\"primary\"` + `variant=\"solid\"` |\n| `default` | `color=\"default\"` + `variant=\"outlined\"` |\n| `dashed` | `color=\"default\"` + `variant=\"dashed\"` |\n| `text` | `color=\"default\"` + `variant=\"text\"` |\n| `link` | `color=\"link\"` + `variant=\"link\"` |\n\n```vue\n<MButton type=\"primary\">Save</MButton>\n```\n\nequals\n\n```vue\n<MButton color=\"primary\" variant=\"solid\">Save</MButton>\n```\n\n### Button `color` vs other components' `severity`?\n\nButton uses `color` / `variant`. Feedback components such as Badge, Tag, Alert, Message, and Toast still use `severity`.\n\n### `text` vs `link`?\n\n`type=\"text\"` (or `variant=\"text\"`) keeps button height and hit area. `type=\"link\"` is closer to an inline link.\n\n## Accessibility\n\n- Renders a native `<button>` by default; renders `<a>` when `href` is set.\n- Provide `ariaLabel` (or visible text) for icon-only buttons.\n- Sets `aria-busy` while `loading` and blocks interaction.\n- A disabled link button drops `href` and sets `aria-disabled` with `tabindex=\"-1\"`.\n"
2606
2618
  }
2607
2619
  }
2608
2620
  },
@@ -2935,7 +2947,7 @@
2935
2947
  "sectionId": "基础用法",
2936
2948
  "lang": "vue",
2937
2949
  "preview": true,
2938
- "code": "<script setup lang=\"ts\">\nimport { MButton, MCard } from 'morya-ui'\n</script>\n\n<template>\n <MCard title=\"Project overview\" subtitle=\"Updated 2 hours ago\">\n <p style=\"margin:0;color:var(--m-color-text-muted)\">\n Title and subtitle align in the header. Body content stays in the default slot.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Dismiss\" severity=\"secondary\" text />\n <MButton label=\"Continue\" />\n </div>\n </template>\n </MCard>\n</template>",
2950
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MCard } from 'morya-ui'\n</script>\n\n<template>\n <MCard title=\"Project overview\" subtitle=\"Updated 2 hours ago\">\n <p style=\"margin:0;color:var(--m-color-text-muted)\">\n Title and subtitle align in the header. Body content stays in the default slot.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Dismiss\" type=\"text\"/>\n <MButton label=\"Continue\" />\n </div>\n </template>\n </MCard>\n</template>",
2939
2951
  "locale": "zh-CN"
2940
2952
  },
2941
2953
  {
@@ -2962,7 +2974,7 @@
2962
2974
  "sectionId": "shadow",
2963
2975
  "lang": "vue",
2964
2976
  "preview": true,
2965
- "code": "<script setup lang=\"ts\">\nimport { MCard } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:grid;gap:var(--m-space-4);max-width:28rem;padding:var(--m-space-2)\">\n <MCard title=\"Flat (default)\" shadow=\"never\">\n Flat surface; use `shadow=\"hover\"` when you want elevation on interaction only.\n </MCard>\n <MCard title=\"Hover shadow\" shadow=\"hover\">\n Same elevation as `always`, shown only on hover (`--m-card-shadow-rest`).\n </MCard>\n <MCard title=\"Always elevated\" shadow=\"always\">\n Resting shadow (`--m-card-shadow-rest` → `--m-shadow-raised`); use for dashboard modules.\n </MCard>\n </div>\n</template>",
2977
+ "code": "<script setup lang=\"ts\">\nimport { MCard, MInput } from 'morya-ui'\nimport { ref } from 'vue';\n\nconst inputValue = ref('')\n</script>\n\n<template>\n <div style=\"display:grid;gap:var(--m-space-4);max-width:28rem;padding:var(--m-space-2)\">\n <MCard title=\"Flat (default)\" shadow=\"never\">\n Flat surface; use `shadow=\"hover\"` when you want elevation on interaction only.\n </MCard>\n <MCard title=\"Hover shadow\" shadow=\"hover\">\n Same elevation as `always`, shown only on hover (`--m-card-shadow-rest`).\n\n <MInput v-model=\"inputValue\" placeholder=\"Hover me\" />\n </MCard>\n <MCard title=\"Always elevated\" shadow=\"always\">\n Resting shadow (`--m-card-shadow-rest` → `--m-shadow-raised`); use for dashboard modules.\n </MCard>\n </div>\n</template>",
2966
2978
  "locale": "zh-CN"
2967
2979
  },
2968
2980
  {
@@ -2980,7 +2992,7 @@
2980
2992
  "sectionId": "basic",
2981
2993
  "lang": "vue",
2982
2994
  "preview": true,
2983
- "code": "<script setup lang=\"ts\">\nimport { MButton, MCard } from 'morya-ui'\n</script>\n\n<template>\n <MCard title=\"Project overview\" subtitle=\"Updated 2 hours ago\">\n <p style=\"margin:0;color:var(--m-color-text-muted)\">\n Title and subtitle align in the header. Body content stays in the default slot.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Dismiss\" severity=\"secondary\" text />\n <MButton label=\"Continue\" />\n </div>\n </template>\n </MCard>\n</template>",
2995
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MCard } from 'morya-ui'\n</script>\n\n<template>\n <MCard title=\"Project overview\" subtitle=\"Updated 2 hours ago\">\n <p style=\"margin:0;color:var(--m-color-text-muted)\">\n Title and subtitle align in the header. Body content stays in the default slot.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Dismiss\" type=\"text\"/>\n <MButton label=\"Continue\" />\n </div>\n </template>\n </MCard>\n</template>",
2984
2996
  "locale": "en-US"
2985
2997
  },
2986
2998
  {
@@ -3007,7 +3019,7 @@
3007
3019
  "sectionId": "shadow",
3008
3020
  "lang": "vue",
3009
3021
  "preview": true,
3010
- "code": "<script setup lang=\"ts\">\nimport { MCard } from 'morya-ui'\n</script>\n\n<template>\n <div style=\"display:grid;gap:var(--m-space-4);max-width:28rem;padding:var(--m-space-2)\">\n <MCard title=\"Flat (default)\" shadow=\"never\">\n Flat surface; use `shadow=\"hover\"` when you want elevation on interaction only.\n </MCard>\n <MCard title=\"Hover shadow\" shadow=\"hover\">\n Same elevation as `always`, shown only on hover (`--m-card-shadow-rest`).\n </MCard>\n <MCard title=\"Always elevated\" shadow=\"always\">\n Resting shadow (`--m-card-shadow-rest` → `--m-shadow-raised`); use for dashboard modules.\n </MCard>\n </div>\n</template>",
3022
+ "code": "<script setup lang=\"ts\">\nimport { MCard, MInput } from 'morya-ui'\nimport { ref } from 'vue';\n\nconst inputValue = ref('')\n</script>\n\n<template>\n <div style=\"display:grid;gap:var(--m-space-4);max-width:28rem;padding:var(--m-space-2)\">\n <MCard title=\"Flat (default)\" shadow=\"never\">\n Flat surface; use `shadow=\"hover\"` when you want elevation on interaction only.\n </MCard>\n <MCard title=\"Hover shadow\" shadow=\"hover\">\n Same elevation as `always`, shown only on hover (`--m-card-shadow-rest`).\n\n <MInput v-model=\"inputValue\" placeholder=\"Hover me\" />\n </MCard>\n <MCard title=\"Always elevated\" shadow=\"always\">\n Resting shadow (`--m-card-shadow-rest` → `--m-shadow-raised`); use for dashboard modules.\n </MCard>\n </div>\n</template>",
3011
3023
  "locale": "en-US"
3012
3024
  }
3013
3025
  ],
@@ -5055,10 +5067,10 @@
5055
5067
  "description": "取消按钮文案。"
5056
5068
  },
5057
5069
  {
5058
- "name": "acceptSeverity",
5059
- "type": "[ButtonSeverity](/docs/types#ButtonSeverity)",
5070
+ "name": "acceptColor",
5071
+ "type": "[ButtonColor](/docs/types#ButtonColor)",
5060
5072
  "default": "—",
5061
- "description": "确认按钮语义色。"
5073
+ "description": "确认按钮颜色。"
5062
5074
  },
5063
5075
  {
5064
5076
  "name": "type",
@@ -5175,7 +5187,7 @@
5175
5187
  "sectionId": "基础用法",
5176
5188
  "lang": "vue",
5177
5189
  "preview": true,
5178
- "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst visible = ref(false)\n</script>\n\n<template>\n <MButton label=\"删除\" severity=\"danger\" @click=\"visible = true\" />\n <MConfirmDialog\n v-model=\"visible\"\n header=\"删除确认\"\n message=\"确定要删除该项吗?此操作不可撤销。\"\n accept-label=\"删除\"\n reject-label=\"取消\"\n accept-severity=\"danger\"\n />\n</template>",
5190
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst visible = ref(false)\n</script>\n\n<template>\n <MButton label=\"删除\" @click=\"visible = true\" danger type=\"primary\"/>\n <MConfirmDialog\n v-model=\"visible\"\n header=\"删除确认\"\n message=\"确定要删除该项吗?此操作不可撤销。\"\n accept-label=\"删除\"\n reject-label=\"取消\"\n accept-color=\"danger\"\n />\n</template>",
5179
5191
  "locale": "zh-CN"
5180
5192
  },
5181
5193
  {
@@ -5193,7 +5205,7 @@
5193
5205
  "sectionId": "basic",
5194
5206
  "lang": "vue",
5195
5207
  "preview": true,
5196
- "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst visible = ref(false)\n</script>\n\n<template>\n <MButton label=\"Delete\" severity=\"danger\" @click=\"visible = true\" />\n <MConfirmDialog\n v-model=\"visible\"\n header=\"Confirm delete\"\n message=\"Are you sure you want to delete this item? This action cannot be undone.\"\n accept-label=\"Delete\"\n reject-label=\"Cancel\"\n accept-severity=\"danger\"\n />\n</template>",
5208
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst visible = ref(false)\n</script>\n\n<template>\n <MButton label=\"Delete\" @click=\"visible = true\" danger type=\"primary\"/>\n <MConfirmDialog\n v-model=\"visible\"\n header=\"Confirm delete\"\n message=\"Are you sure you want to delete this item? This action cannot be undone.\"\n accept-label=\"Delete\"\n reject-label=\"Cancel\"\n accept-color=\"danger\"\n />\n</template>",
5197
5209
  "locale": "en-US"
5198
5210
  }
5199
5211
  ],
@@ -5220,7 +5232,7 @@
5220
5232
  {
5221
5233
  "id": "props",
5222
5234
  "title": "Props",
5223
- "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否可见。 |\n| `header` | `string` | `'确认'` | 标题。 |\n| `message` | `string` | — | 正文。 |\n| `acceptLabel` | `string` | `'确认'` | 确认按钮文案。 |\n| `rejectLabel` | `string` | `'取消'` | 取消按钮文案。 |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | 确认按钮语义色。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 正文状态图标;确认流程用本组件,Dialog `type` 只做标题图标。 |\n| `loading` | `boolean` | `false` | 确认按钮加载中。 |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `accept`。 |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `reject`。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `blockScroll` | `boolean` | — | — |\n| `closeOnEsc` | `boolean` | — | — |\n| `closeOnOutsideClick` | `boolean` | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
5235
+ "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否可见。 |\n| `header` | `string` | `'确认'` | 标题。 |\n| `message` | `string` | — | 正文。 |\n| `acceptLabel` | `string` | `'确认'` | 确认按钮文案。 |\n| `rejectLabel` | `string` | `'取消'` | 取消按钮文案。 |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | 确认按钮颜色。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 正文状态图标;确认流程用本组件,Dialog `type` 只做标题图标。 |\n| `loading` | `boolean` | `false` | 确认按钮加载中。 |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `accept`。 |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `reject`。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `blockScroll` | `boolean` | — | — |\n| `closeOnEsc` | `boolean` | — | — |\n| `closeOnOutsideClick` | `boolean` | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
5224
5236
  },
5225
5237
  {
5226
5238
  "id": "events",
@@ -5233,7 +5245,7 @@
5233
5245
  "body": "| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 对话框正文。 |\n| `footer` | 自定义 `footer` 内容。 |\n| `header` | 自定义 `header` 内容。 |"
5234
5246
  }
5235
5247
  ],
5236
- "markdown": "---\ntitle: ConfirmDialog\ncategory: 05 / FEEDBACK\ndescription: 确认 / 取消对话框,复用 Dialog 浮层样式。\n---\n\n# ConfirmDialog\n\n需要用户明确确认时使用的模态对话框。\n\n## 引入\n\n```ts\nimport { MButton, MConfirmDialog } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否可见。 |\n| `header` | `string` | `'确认'` | 标题。 |\n| `message` | `string` | — | 正文。 |\n| `acceptLabel` | `string` | `'确认'` | 确认按钮文案。 |\n| `rejectLabel` | `string` | `'取消'` | 取消按钮文案。 |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | 确认按钮语义色。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 正文状态图标;确认流程用本组件,Dialog `type` 只做标题图标。 |\n| `loading` | `boolean` | `false` | 确认按钮加载中。 |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `accept`。 |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `reject`。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `blockScroll` | `boolean` | — | — |\n| `closeOnEsc` | `boolean` | — | — |\n| `closeOnOutsideClick` | `boolean` | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 可见性变化。 |\n| `accept` | — | 点击确认。 |\n| `reject` | — | 点击取消或关闭。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 对话框正文。 |\n| `footer` | 自定义 `footer` 内容。 |\n| `header` | 自定义 `header` 内容。 |\n"
5248
+ "markdown": "---\ntitle: ConfirmDialog\ncategory: 05 / FEEDBACK\ndescription: 确认 / 取消对话框,复用 Dialog 浮层样式。\n---\n\n# ConfirmDialog\n\n需要用户明确确认时使用的模态对话框。\n\n## 引入\n\n```ts\nimport { MButton, MConfirmDialog } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否可见。 |\n| `header` | `string` | `'确认'` | 标题。 |\n| `message` | `string` | — | 正文。 |\n| `acceptLabel` | `string` | `'确认'` | 确认按钮文案。 |\n| `rejectLabel` | `string` | `'取消'` | 取消按钮文案。 |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | 确认按钮颜色。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 正文状态图标;确认流程用本组件,Dialog `type` 只做标题图标。 |\n| `loading` | `boolean` | `false` | 确认按钮加载中。 |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `accept`。 |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭、不触发 `reject`。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `blockScroll` | `boolean` | — | — |\n| `closeOnEsc` | `boolean` | — | — |\n| `closeOnOutsideClick` | `boolean` | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 可见性变化。 |\n| `accept` | — | 点击确认。 |\n| `reject` | — | 点击取消或关闭。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 对话框正文。 |\n| `footer` | 自定义 `footer` 内容。 |\n| `header` | 自定义 `header` 内容。 |\n"
5237
5249
  },
5238
5250
  "en-US": {
5239
5251
  "title": "ConfirmDialog",
@@ -5257,7 +5269,7 @@
5257
5269
  {
5258
5270
  "id": "props",
5259
5271
  "title": "Props",
5260
- "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. |\n| `header` | `string` | locale `confirm` | Title. |\n| `message` | `string` | — | Body text. |\n| `acceptLabel` | `string` | locale `accept` | Accept button label. |\n| `rejectLabel` | `string` | locale `reject` | Reject button label. |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | Accept button semantic color. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon beside the message. |\n| `loading` | `boolean` | `false` | Loading state on the accept button. |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `accept`. |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `reject`. |\n| `teleport` | `boolean` | `true` | Overlay Teleport; defaults to `body`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target; `'self'` / `false` renders in place. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |"
5272
+ "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. |\n| `header` | `string` | locale `confirm` | Title. |\n| `message` | `string` | — | Body text. |\n| `acceptLabel` | `string` | locale `accept` | Accept button label. |\n| `rejectLabel` | `string` | locale `reject` | Reject button label. |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | Accept button color. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon beside the message. |\n| `loading` | `boolean` | `false` | Loading state on the accept button. |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `accept`. |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `reject`. |\n| `teleport` | `boolean` | `true` | Overlay Teleport; defaults to `body`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target; `'self'` / `false` renders in place. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |"
5261
5273
  },
5262
5274
  {
5263
5275
  "id": "events",
@@ -5270,7 +5282,7 @@
5270
5282
  "body": "| Slot | Description |\n| --- | --- |\n| `default` | Dialog body. |"
5271
5283
  }
5272
5284
  ],
5273
- "markdown": "---\ntitle: ConfirmDialog\ncategory: 05 / FEEDBACK\ndescription: Confirm / cancel dialog that reuses Dialog overlay styling.\n---\n\n# ConfirmDialog\n\nModal dialog used when the user must explicitly confirm an action.\n\n## Import\n\n```ts\nimport { MButton, MConfirmDialog } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. |\n| `header` | `string` | locale `confirm` | Title. |\n| `message` | `string` | — | Body text. |\n| `acceptLabel` | `string` | locale `accept` | Accept button label. |\n| `rejectLabel` | `string` | locale `reject` | Reject button label. |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | Accept button semantic color. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon beside the message. |\n| `loading` | `boolean` | `false` | Loading state on the accept button. |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `accept`. |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `reject`. |\n| `teleport` | `boolean` | `true` | Overlay Teleport; defaults to `body`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target; `'self'` / `false` renders in place. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Visibility change. |\n| `accept` | — | Accept clicked. |\n| `reject` | — | Reject clicked or dialog closed. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Dialog body. |\n"
5285
+ "markdown": "---\ntitle: ConfirmDialog\ncategory: 05 / FEEDBACK\ndescription: Confirm / cancel dialog that reuses Dialog overlay styling.\n---\n\n# ConfirmDialog\n\nModal dialog used when the user must explicitly confirm an action.\n\n## Import\n\n```ts\nimport { MButton, MConfirmDialog } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. |\n| `header` | `string` | locale `confirm` | Title. |\n| `message` | `string` | — | Body text. |\n| `acceptLabel` | `string` | locale `accept` | Accept button label. |\n| `rejectLabel` | `string` | locale `reject` | Reject button label. |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | Accept button color. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon beside the message. |\n| `loading` | `boolean` | `false` | Loading state on the accept button. |\n| `beforeAccept` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `accept`. |\n| `beforeReject` | `() => unknown \\| Promise<unknown>` | — | Return `false` to keep open and skip `reject`. |\n| `teleport` | `boolean` | `true` | Overlay Teleport; defaults to `body`. |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | Mount target; `'self'` / `false` renders in place. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Visibility change. |\n| `accept` | — | Accept clicked. |\n| `reject` | — | Reject clicked or dialog closed. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Dialog body. |\n"
5274
5286
  }
5275
5287
  }
5276
5288
  },
@@ -5356,8 +5368,8 @@
5356
5368
  "description": "进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。"
5357
5369
  },
5358
5370
  {
5359
- "name": "acceptSeverity",
5360
- "type": "[ButtonSeverity](/docs/types#ButtonSeverity)",
5371
+ "name": "acceptColor",
5372
+ "type": "[ButtonColor](/docs/types#ButtonColor)",
5361
5373
  "default": "—",
5362
5374
  "description": "—"
5363
5375
  },
@@ -5408,7 +5420,7 @@
5408
5420
  "sectionId": "基础用法",
5409
5421
  "lang": "vue",
5410
5422
  "preview": true,
5411
- "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmPopup } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst target = ref<HTMLElement | null>(null)\n\nfunction ask(event: MouseEvent) {\n target.value = event.currentTarget as HTMLElement\n open.value = true\n}\n</script>\n\n<template>\n <MButton label=\"删除\" severity=\"danger\" @click=\"ask\" />\n <MConfirmPopup v-model=\"open\" :target=\"target\" message=\"确认删除?\" icon=\"info\" placement=\"top\" />\n</template>",
5423
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmPopup } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst target = ref<HTMLElement | null>(null)\n\nfunction ask(event: MouseEvent) {\n target.value = event.currentTarget as HTMLElement\n open.value = true\n}\n</script>\n\n<template>\n <MButton label=\"删除\" @click=\"ask\" danger type=\"primary\"/>\n <MConfirmPopup v-model=\"open\" :target=\"target\" message=\"确认删除?\" icon=\"info\" placement=\"top\" />\n</template>",
5412
5424
  "locale": "zh-CN"
5413
5425
  },
5414
5426
  {
@@ -5435,7 +5447,7 @@
5435
5447
  "sectionId": "basic",
5436
5448
  "lang": "vue",
5437
5449
  "preview": true,
5438
- "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmPopup } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst target = ref<HTMLElement | null>(null)\n\nfunction ask(event: MouseEvent) {\n target.value = event.currentTarget as HTMLElement\n open.value = true\n}\n</script>\n\n<template>\n <MButton label=\"Delete\" severity=\"danger\" @click=\"ask\" />\n <MConfirmPopup v-model=\"open\" :target=\"target\" message=\"Delete this item?\" icon=\"info\" placement=\"top\" />\n</template>",
5450
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MConfirmPopup } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst target = ref<HTMLElement | null>(null)\n\nfunction ask(event: MouseEvent) {\n target.value = event.currentTarget as HTMLElement\n open.value = true\n}\n</script>\n\n<template>\n <MButton label=\"Delete\" @click=\"ask\" danger type=\"primary\"/>\n <MConfirmPopup v-model=\"open\" :target=\"target\" message=\"Delete this item?\" icon=\"info\" placement=\"top\" />\n</template>",
5439
5451
  "locale": "en-US"
5440
5452
  },
5441
5453
  {
@@ -5476,7 +5488,7 @@
5476
5488
  {
5477
5489
  "id": "props",
5478
5490
  "title": "Props",
5479
- "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否显示。 |\n| `message` | `string` | — | 提示文案。 |\n| `acceptLabel` / `rejectLabel` | `string` | `确认` / `取消` | 按钮。 |\n| `icon` | [IconName](/docs/types#IconName) | — | 文案旁图标。 |\n| `beforeAccept` | `() => boolean \\| Promise<boolean>` | — | 返回 `false` 时保持打开。 |\n| `placement` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | 相对 `target` 的位置。 |\n| `target` | `HTMLElement \\| null` | — | 锚点。 |\n| `position` | `{ top, left } \\| null` | — | 无锚点时的坐标。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
5491
+ "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否显示。 |\n| `message` | `string` | — | 提示文案。 |\n| `acceptLabel` / `rejectLabel` | `string` | `确认` / `取消` | 按钮。 |\n| `icon` | [IconName](/docs/types#IconName) | — | 文案旁图标。 |\n| `beforeAccept` | `() => boolean \\| Promise<boolean>` | — | 返回 `false` 时保持打开。 |\n| `placement` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | 相对 `target` 的位置。 |\n| `target` | `HTMLElement \\| null` | — | 锚点。 |\n| `position` | `{ top, left } \\| null` | — | 无锚点时的坐标。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
5480
5492
  },
5481
5493
  {
5482
5494
  "id": "events",
@@ -5489,7 +5501,7 @@
5489
5501
  "body": "| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 弹出层正文。 |"
5490
5502
  }
5491
5503
  ],
5492
- "markdown": "---\ntitle: ConfirmPopup\ncategory: 05 / FEEDBACK\ndescription: 锚定在目标旁的确认气泡。\n---\n\n# ConfirmPopup\n\n轻量确认浮层,支持 `target` 或坐标定位。\n\n## 引入\n\n```ts\nimport { MConfirmPopup } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Before accept\n\n`beforeAccept` 返回 `false` 时保持打开且不触发 `accept`。\n\n```vue preview src=\"./demos/BeforeAccept.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否显示。 |\n| `message` | `string` | — | 提示文案。 |\n| `acceptLabel` / `rejectLabel` | `string` | `确认` / `取消` | 按钮。 |\n| `icon` | [IconName](/docs/types#IconName) | — | 文案旁图标。 |\n| `beforeAccept` | `() => boolean \\| Promise<boolean>` | — | 返回 `false` 时保持打开。 |\n| `placement` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | 相对 `target` 的位置。 |\n| `target` | `HTMLElement \\| null` | — | 锚点。 |\n| `position` | `{ top, left } \\| null` | — | 无锚点时的坐标。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `acceptSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 显隐。 |\n| `accept` / `reject` | — | 确认 / 取消。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 弹出层正文。 |\n"
5504
+ "markdown": "---\ntitle: ConfirmPopup\ncategory: 05 / FEEDBACK\ndescription: 锚定在目标旁的确认气泡。\n---\n\n# ConfirmPopup\n\n轻量确认浮层,支持 `target` 或坐标定位。\n\n## 引入\n\n```ts\nimport { MConfirmPopup } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Before accept\n\n`beforeAccept` 返回 `false` 时保持打开且不触发 `accept`。\n\n```vue preview src=\"./demos/BeforeAccept.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 是否显示。 |\n| `message` | `string` | — | 提示文案。 |\n| `acceptLabel` / `rejectLabel` | `string` | `确认` / `取消` | 按钮。 |\n| `icon` | [IconName](/docs/types#IconName) | — | 文案旁图标。 |\n| `beforeAccept` | `() => boolean \\| Promise<boolean>` | — | 返回 `false` 时保持打开。 |\n| `placement` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | 相对 `target` 的位置。 |\n| `target` | `HTMLElement \\| null` | — | 锚点。 |\n| `position` | `{ top, left } \\| null` | — | 无锚点时的坐标。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self' \\| false` | `'body'` | 挂载目标;`'self'` / `false` 就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `acceptColor` | [ButtonColor](/docs/types#ButtonColor) | — | — |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 显隐。 |\n| `accept` / `reject` | — | 确认 / 取消。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 弹出层正文。 |\n"
5493
5505
  },
5494
5506
  "en-US": {
5495
5507
  "title": "ConfirmPopup",
@@ -6954,10 +6966,10 @@
6954
6966
  "description": "预设页脚按钮;有 `footer` 插槽时忽略"
6955
6967
  },
6956
6968
  {
6957
- "name": "positiveSeverity",
6958
- "type": "[ButtonSeverity](/docs/types#ButtonSeverity)",
6969
+ "name": "positiveColor",
6970
+ "type": "[ButtonColor](/docs/types#ButtonColor)",
6959
6971
  "default": "—",
6960
- "description": "确认按钮语义色"
6972
+ "description": "确认按钮颜色"
6961
6973
  },
6962
6974
  {
6963
6975
  "name": "onPositiveClick",
@@ -7105,7 +7117,7 @@
7105
7117
  "sectionId": "positions",
7106
7118
  "lang": "vue",
7107
7119
  "preview": true,
7108
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'center' | 'top' | 'topright' | 'bottomleft'>('center')\n\nfunction openAt(next: 'center' | 'top' | 'topright' | 'bottomleft') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Center\" size=\"small\" @click=\"openAt('center')\" />\n <MButton label=\"Top\" size=\"small\" severity=\"secondary\" @click=\"openAt('top')\" />\n <MButton label=\"Top Right\" size=\"small\" @click=\"openAt('topright')\" />\n <MButton label=\"Bottom Left\" size=\"small\" severity=\"secondary\" @click=\"openAt('bottomleft')\" />\n <MDialog v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Dialog can dock to edges and corners.\n </p>\n </MDialog>\n </div>\n</template>",
7120
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'center' | 'top' | 'topright' | 'bottomleft'>('center')\n\nfunction openAt(next: 'center' | 'top' | 'topright' | 'bottomleft') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Center\" size=\"small\" @click=\"openAt('center')\" />\n <MButton label=\"Top\" size=\"small\" @click=\"openAt('top')\"/>\n <MButton label=\"Top Right\" size=\"small\" @click=\"openAt('topright')\" />\n <MButton label=\"Bottom Left\" size=\"small\" @click=\"openAt('bottomleft')\"/>\n <MDialog v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Dialog can dock to edges and corners.\n </p>\n </MDialog>\n </div>\n</template>",
7109
7121
  "locale": "zh-CN"
7110
7122
  },
7111
7123
  {
@@ -7114,7 +7126,7 @@
7114
7126
  "sectionId": "footer-actions",
7115
7127
  "lang": "vue",
7116
7128
  "preview": true,
7117
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Save changes\" width=\"28rem\">\n <p style=\"margin:0\">\n Footer slot is for primary and secondary actions.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Cancel\" severity=\"secondary\" text @click=\"open = false\" />\n <MButton label=\"Confirm\" @click=\"open = false\" />\n </div>\n </template>\n </MDialog>\n </div>\n</template>",
7129
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Save changes\" width=\"28rem\">\n <p style=\"margin:0\">\n Footer slot is for primary and secondary actions.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Cancel\" @click=\"open = false\" type=\"text\"/>\n <MButton label=\"Confirm\" @click=\"open = false\" />\n </div>\n </template>\n </MDialog>\n </div>\n</template>",
7118
7130
  "locale": "zh-CN"
7119
7131
  },
7120
7132
  {
@@ -7123,7 +7135,7 @@
7123
7135
  "sectionId": "no-dismiss-mask",
7124
7136
  "lang": "vue",
7125
7137
  "preview": true,
7126
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"No Mask Dismiss\" severity=\"secondary\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Stay open\" :dismissable-mask=\"false\">\n <p style=\"margin:0\">\n Click the mask — the dialog stays open. Use the close button or Esc.\n </p>\n </MDialog>\n </div>\n</template>",
7138
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"No Mask Dismiss\" @click=\"open = true\"/>\n <MDialog v-model=\"open\" header=\"Stay open\" :dismissable-mask=\"false\">\n <p style=\"margin:0\">\n Click the mask — the dialog stays open. Use the close button or Esc.\n </p>\n </MDialog>\n </div>\n</template>",
7127
7139
  "locale": "zh-CN"
7128
7140
  },
7129
7141
  {
@@ -7177,7 +7189,7 @@
7177
7189
  "sectionId": "positions",
7178
7190
  "lang": "vue",
7179
7191
  "preview": true,
7180
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'center' | 'top' | 'topright' | 'bottomleft'>('center')\n\nfunction openAt(next: 'center' | 'top' | 'topright' | 'bottomleft') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Center\" size=\"small\" @click=\"openAt('center')\" />\n <MButton label=\"Top\" size=\"small\" severity=\"secondary\" @click=\"openAt('top')\" />\n <MButton label=\"Top Right\" size=\"small\" @click=\"openAt('topright')\" />\n <MButton label=\"Bottom Left\" size=\"small\" severity=\"secondary\" @click=\"openAt('bottomleft')\" />\n <MDialog v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Dialog can dock to edges and corners.\n </p>\n </MDialog>\n </div>\n</template>",
7192
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'center' | 'top' | 'topright' | 'bottomleft'>('center')\n\nfunction openAt(next: 'center' | 'top' | 'topright' | 'bottomleft') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Center\" size=\"small\" @click=\"openAt('center')\" />\n <MButton label=\"Top\" size=\"small\" @click=\"openAt('top')\"/>\n <MButton label=\"Top Right\" size=\"small\" @click=\"openAt('topright')\" />\n <MButton label=\"Bottom Left\" size=\"small\" @click=\"openAt('bottomleft')\"/>\n <MDialog v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Dialog can dock to edges and corners.\n </p>\n </MDialog>\n </div>\n</template>",
7181
7193
  "locale": "en-US"
7182
7194
  },
7183
7195
  {
@@ -7186,7 +7198,7 @@
7186
7198
  "sectionId": "footer-actions",
7187
7199
  "lang": "vue",
7188
7200
  "preview": true,
7189
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Save changes\" width=\"28rem\">\n <p style=\"margin:0\">\n Footer slot is for primary and secondary actions.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Cancel\" severity=\"secondary\" text @click=\"open = false\" />\n <MButton label=\"Confirm\" @click=\"open = false\" />\n </div>\n </template>\n </MDialog>\n </div>\n</template>",
7201
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Save changes\" width=\"28rem\">\n <p style=\"margin:0\">\n Footer slot is for primary and secondary actions.\n </p>\n <template #footer>\n <div style=\"display:flex;gap:0.75rem;justify-content:flex-end;width:100%\">\n <MButton label=\"Cancel\" @click=\"open = false\" type=\"text\"/>\n <MButton label=\"Confirm\" @click=\"open = false\" />\n </div>\n </template>\n </MDialog>\n </div>\n</template>",
7190
7202
  "locale": "en-US"
7191
7203
  },
7192
7204
  {
@@ -7195,7 +7207,7 @@
7195
7207
  "sectionId": "no-dismiss-mask",
7196
7208
  "lang": "vue",
7197
7209
  "preview": true,
7198
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"No Mask Dismiss\" severity=\"secondary\" @click=\"open = true\" />\n <MDialog v-model=\"open\" header=\"Stay open\" :dismissable-mask=\"false\">\n <p style=\"margin:0\">\n Click the mask — the dialog stays open. Use the close button or Esc.\n </p>\n </MDialog>\n </div>\n</template>",
7210
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDialog } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"No Mask Dismiss\" @click=\"open = true\"/>\n <MDialog v-model=\"open\" header=\"Stay open\" :dismissable-mask=\"false\">\n <p style=\"margin:0\">\n Click the mask — the dialog stays open. Use the close button or Esc.\n </p>\n </MDialog>\n </div>\n</template>",
7199
7211
  "locale": "en-US"
7200
7212
  },
7201
7213
  {
@@ -7274,7 +7286,7 @@
7274
7286
  {
7275
7287
  "id": "props",
7276
7288
  "title": "Props",
7277
- "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 可见性。配合 `v-model` 使用。 |\n| `title` | `string` | — | 标题文案。 |\n| `header` | `string` | — | `title` 的别名。 |\n| `closeOnEsc` | `boolean` | `true` | 按 Esc 关闭。 |\n| `blockScroll` | `boolean` | `true` | 打开时锁定页面滚动(`modal` 时生效)。 |\n| `closeOnOutsideClick` | `boolean` | `true` | 点击遮罩关闭。 |\n| `dismissableMask` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `maskClosable` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `closable` | `boolean` | `true` | 显示关闭按钮。 |\n| `maximizable` | `boolean` | `false` | 显示最大化 / 还原按钮。 |\n| `modal` | `boolean` | `true` | 遮罩层。 |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | 对话框位置。 |\n| `centered` | `boolean` | — | 垂直居中:`true` → `center`,`false` → `top`;省略时用 `position`。 |\n| `width` | `string` | — | 对话框宽度(最大化时忽略)。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 就地渲染。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 标题状态图标;`warning` 与 `warn` 同义 |\n| `positiveText` / `negativeText` | `string` | — | 预设页脚按钮;有 `footer` 插槽时忽略 |\n| `positiveSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | 确认按钮语义色 |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭 |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | X / Esc / 遮罩关闭前;返回 `false` 则保持打开 |\n| `ariaLabel` | `string` | — | 对话框可访问名称。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 遮罩层(backdrop)透传,键名 `root`。 |"
7289
+ "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 可见性。配合 `v-model` 使用。 |\n| `title` | `string` | — | 标题文案。 |\n| `header` | `string` | — | `title` 的别名。 |\n| `closeOnEsc` | `boolean` | `true` | 按 Esc 关闭。 |\n| `blockScroll` | `boolean` | `true` | 打开时锁定页面滚动(`modal` 时生效)。 |\n| `closeOnOutsideClick` | `boolean` | `true` | 点击遮罩关闭。 |\n| `dismissableMask` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `maskClosable` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `closable` | `boolean` | `true` | 显示关闭按钮。 |\n| `maximizable` | `boolean` | `false` | 显示最大化 / 还原按钮。 |\n| `modal` | `boolean` | `true` | 遮罩层。 |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | 对话框位置。 |\n| `centered` | `boolean` | — | 垂直居中:`true` → `center`,`false` → `top`;省略时用 `position`。 |\n| `width` | `string` | — | 对话框宽度(最大化时忽略)。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 就地渲染。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 标题状态图标;`warning` 与 `warn` 同义 |\n| `positiveText` / `negativeText` | `string` | — | 预设页脚按钮;有 `footer` 插槽时忽略 |\n| `positiveColor` | [ButtonColor](/docs/types#ButtonColor) | — | 确认按钮颜色 |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭 |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | X / Esc / 遮罩关闭前;返回 `false` 则保持打开 |\n| `ariaLabel` | `string` | — | 对话框可访问名称。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 遮罩层(backdrop)透传,键名 `root`。 |"
7278
7290
  },
7279
7291
  {
7280
7292
  "id": "样式与-attrs",
@@ -7299,10 +7311,10 @@
7299
7311
  {
7300
7312
  "id": "命令式调用-usemodal-modal",
7301
7313
  "title": "命令式调用(useModal / modal)",
7302
- "body": "不写模板也能弹出对话框:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// 模块级单例\nmodal.confirm({\n title: '确认删除?',\n content: '删除后不可恢复',\n onOk: async () => { await remove() },\n})\n\n// 或组件内作用域实例\nconst dialog = useModal()\ndialog.success({ title: '已保存' })\n```\n\n每个调用返回 `{ destroy, update }`:`update` 可在打开时改标题/内容,`destroy` 立即关闭并卸载。`modal.destroyAll()` 关闭全部由该 API 创建的对话框。\n\n| 方法 | 说明 |\n| --- | --- |\n| `info(options)` | 信息弹窗(默认无取消按钮) |\n| `success(options)` | 成功弹窗 |\n| `warning(options)` | 警告弹窗 |\n| `error(options)` | 错误弹窗 |\n| `confirm(options)` | 确认弹窗(默认显示取消按钮) |\n| `destroyAll()` | 关闭全部 |\n\n`options` 传字符串等价于 `{ content: '...' }`。\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `title` | `string` | — | 标题 |\n| `content` | `string \\| VNode` | — | 内容 |\n| `type` | `DialogType` | — | 头部状态图标 |\n| `okText` / `cancelText` | `string` | locale | 按钮文案 |\n| `showCancel` | `boolean` | 状态弹窗 `false`,`confirm` `true` | 是否显示取消按钮 |\n| `okSeverity` | `ButtonSeverity` | `'primary'` | 确认按钮语义色 |\n| `width` / `position` / `centered` | 同 Dialog | — | 布局 |\n| `maskClosable` | `boolean` | `false` | 点击遮罩关闭 |\n| `onOk` | `() => void \\| Promise<void>` | — | 确认回调;返回 Promise 时按钮进入 loading |\n| `onCancel` | `() => void` | — | 取消 / 关闭回调 |\n| `afterClose` | `() => void` | — | 关闭动画结束后回调 |\n\n> 命令式弹窗就地渲染在挂载容器内(不 Teleport),便于精确销毁。\n| `footer` | 底部操作区。 |"
7314
+ "body": "不写模板也能弹出对话框:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// 模块级单例\nmodal.confirm({\n title: '确认删除?',\n content: '删除后不可恢复',\n onOk: async () => { await remove() },\n})\n\n// 或组件内作用域实例\nconst dialog = useModal()\ndialog.success({ title: '已保存' })\n```\n\n每个调用返回 `{ destroy, update }`:`update` 可在打开时改标题/内容,`destroy` 立即关闭并卸载。`modal.destroyAll()` 关闭全部由该 API 创建的对话框。\n\n| 方法 | 说明 |\n| --- | --- |\n| `info(options)` | 信息弹窗(默认无取消按钮) |\n| `success(options)` | 成功弹窗 |\n| `warning(options)` | 警告弹窗 |\n| `error(options)` | 错误弹窗 |\n| `confirm(options)` | 确认弹窗(默认显示取消按钮) |\n| `destroyAll()` | 关闭全部 |\n\n`options` 传字符串等价于 `{ content: '...' }`。\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `title` | `string` | — | 标题 |\n| `content` | `string \\| VNode` | — | 内容 |\n| `type` | `DialogType` | — | 头部状态图标 |\n| `okText` / `cancelText` | `string` | locale | 按钮文案 |\n| `showCancel` | `boolean` | 状态弹窗 `false`,`confirm` `true` | 是否显示取消按钮 |\n| `okColor` | `ButtonColor` | `'primary'` | 确认按钮颜色 |\n| `width` / `position` / `centered` | 同 Dialog | — | 布局 |\n| `maskClosable` | `boolean` | `false` | 点击遮罩关闭 |\n| `onOk` | `() => void \\| Promise<void>` | — | 确认回调;返回 Promise 时按钮进入 loading |\n| `onCancel` | `() => void` | — | 取消 / 关闭回调 |\n| `afterClose` | `() => void` | — | 关闭动画结束后回调 |\n\n> 命令式弹窗就地渲染在挂载容器内(不 Teleport),便于精确销毁。\n| `footer` | 底部操作区。 |"
7303
7315
  }
7304
7316
  ],
7305
- "markdown": "---\ntitle: Dialog\ncategory: 05 / FEEDBACK\ndescription: 模态对话框。支持预设页脚、异步关闭拦截、状态 type。\n---\n\n# Dialog\n\n模态对话框。可见性使用 `v-model`(`modelValue`),对应 的 `visible`。\n\n## 引入\n\n```ts\nimport { MButton, MDialog } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Positions\n\n支持 `center` / `top` / `bottom` / `left` / `right` 以及四角位置。\n\n```vue preview src=\"./demos/Positions.vue\"\n```\n\n## Footer actions\n\n```vue preview src=\"./demos/FooterActions.vue\"\n```\n\n## No dismiss mask\n\n`dismissableMask={false}`(或 `closeOnOutsideClick={false}` / `maskClosable={false}`)时点击遮罩不关闭。\n\n```vue preview src=\"./demos/NoDismissMask.vue\"\n```\n\n## Maximizable\n\n`maximizable` 在标题栏提供最大化 / 还原切换。\n\n```vue preview src=\"./demos/Maximizable.vue\"\n```\n\n## 预设页脚与异步关闭\n\n`positiveText` / `negativeText` 生成确认 / 取消按钮(`footer` 插槽优先)。处理函数返回 `false`(含 Promise)则保持打开。确认型流程请用 [ConfirmDialog](/components/ConfirmDialog);`type` 只负责 Dialog 标题图标。\n\n```vue preview src=\"./demos/PresetFooterAndAsyncClose.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 可见性。配合 `v-model` 使用。 |\n| `title` | `string` | — | 标题文案。 |\n| `header` | `string` | — | `title` 的别名。 |\n| `closeOnEsc` | `boolean` | `true` | 按 Esc 关闭。 |\n| `blockScroll` | `boolean` | `true` | 打开时锁定页面滚动(`modal` 时生效)。 |\n| `closeOnOutsideClick` | `boolean` | `true` | 点击遮罩关闭。 |\n| `dismissableMask` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `maskClosable` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `closable` | `boolean` | `true` | 显示关闭按钮。 |\n| `maximizable` | `boolean` | `false` | 显示最大化 / 还原按钮。 |\n| `modal` | `boolean` | `true` | 遮罩层。 |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | 对话框位置。 |\n| `centered` | `boolean` | — | 垂直居中:`true` → `center`,`false` → `top`;省略时用 `position`。 |\n| `width` | `string` | — | 对话框宽度(最大化时忽略)。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 就地渲染。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 标题状态图标;`warning` 与 `warn` 同义 |\n| `positiveText` / `negativeText` | `string` | — | 预设页脚按钮;有 `footer` 插槽时忽略 |\n| `positiveSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | 确认按钮语义色 |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭 |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | X / Esc / 遮罩关闭前;返回 `false` 则保持打开 |\n| `ariaLabel` | `string` | — | 对话框可访问名称。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 遮罩层(backdrop)透传,键名 `root`。 |\n\n## 样式与 attrs\n\nDialog Teleport 到 `body` 后,你在组件上写的 fallthrough attrs(`class`、`style`、`data-*`、`title` 等)落在**遮罩层**(`.m-dialog-backdrop`),不是内层 `.m-dialog` 面板。面板宽度用 `width` prop;内层 DOM 用 `pt`。详见 [样式与 attrs](/docs/attrs)。\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 可见性变化。 |\n| `close` | — | 关闭时触发。 |\n| `show` | — | 打开时触发。 |\n| `hide` | — | 关闭后触发。 |\n| `maximize` | — | 进入最大化。 |\n| `unmaximize` | — | 退出最大化。 |\n\n## Methods\n\n| 方法 | 说明 |\n| --- | --- |\n| `close()` | 关闭对话框(等同取消/关闭动作)。 |\n| `maximize()` | 最大化;已最大化时无操作。 |\n| `unmaximize()` | 退出最大化。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 对话框内容。 |\n| `header` | 自定义标题区。 |\n| `footer` | 底部操作区。 |\n\n## 命令式调用(useModal / modal)\n\n不写模板也能弹出对话框:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// 模块级单例\nmodal.confirm({\n title: '确认删除?',\n content: '删除后不可恢复',\n onOk: async () => { await remove() },\n})\n\n// 或组件内作用域实例\nconst dialog = useModal()\ndialog.success({ title: '已保存' })\n```\n\n每个调用返回 `{ destroy, update }`:`update` 可在打开时改标题/内容,`destroy` 立即关闭并卸载。`modal.destroyAll()` 关闭全部由该 API 创建的对话框。\n\n| 方法 | 说明 |\n| --- | --- |\n| `info(options)` | 信息弹窗(默认无取消按钮) |\n| `success(options)` | 成功弹窗 |\n| `warning(options)` | 警告弹窗 |\n| `error(options)` | 错误弹窗 |\n| `confirm(options)` | 确认弹窗(默认显示取消按钮) |\n| `destroyAll()` | 关闭全部 |\n\n`options` 传字符串等价于 `{ content: '...' }`。\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `title` | `string` | — | 标题 |\n| `content` | `string \\| VNode` | — | 内容 |\n| `type` | `DialogType` | — | 头部状态图标 |\n| `okText` / `cancelText` | `string` | locale | 按钮文案 |\n| `showCancel` | `boolean` | 状态弹窗 `false`,`confirm` `true` | 是否显示取消按钮 |\n| `okSeverity` | `ButtonSeverity` | `'primary'` | 确认按钮语义色 |\n| `width` / `position` / `centered` | 同 Dialog | — | 布局 |\n| `maskClosable` | `boolean` | `false` | 点击遮罩关闭 |\n| `onOk` | `() => void \\| Promise<void>` | — | 确认回调;返回 Promise 时按钮进入 loading |\n| `onCancel` | `() => void` | — | 取消 / 关闭回调 |\n| `afterClose` | `() => void` | — | 关闭动画结束后回调 |\n\n> 命令式弹窗就地渲染在挂载容器内(不 Teleport),便于精确销毁。\n| `footer` | 底部操作区。 |\n"
7317
+ "markdown": "---\ntitle: Dialog\ncategory: 05 / FEEDBACK\ndescription: 模态对话框。支持预设页脚、异步关闭拦截、状态 type。\n---\n\n# Dialog\n\n模态对话框。可见性使用 `v-model`(`modelValue`),对应 的 `visible`。\n\n## 引入\n\n```ts\nimport { MButton, MDialog } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Positions\n\n支持 `center` / `top` / `bottom` / `left` / `right` 以及四角位置。\n\n```vue preview src=\"./demos/Positions.vue\"\n```\n\n## Footer actions\n\n```vue preview src=\"./demos/FooterActions.vue\"\n```\n\n## No dismiss mask\n\n`dismissableMask={false}`(或 `closeOnOutsideClick={false}` / `maskClosable={false}`)时点击遮罩不关闭。\n\n```vue preview src=\"./demos/NoDismissMask.vue\"\n```\n\n## Maximizable\n\n`maximizable` 在标题栏提供最大化 / 还原切换。\n\n```vue preview src=\"./demos/Maximizable.vue\"\n```\n\n## 预设页脚与异步关闭\n\n`positiveText` / `negativeText` 生成确认 / 取消按钮(`footer` 插槽优先)。处理函数返回 `false`(含 Promise)则保持打开。确认型流程请用 [ConfirmDialog](/components/ConfirmDialog);`type` 只负责 Dialog 标题图标。\n\n```vue preview src=\"./demos/PresetFooterAndAsyncClose.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | 可见性。配合 `v-model` 使用。 |\n| `title` | `string` | — | 标题文案。 |\n| `header` | `string` | — | `title` 的别名。 |\n| `closeOnEsc` | `boolean` | `true` | 按 Esc 关闭。 |\n| `blockScroll` | `boolean` | `true` | 打开时锁定页面滚动(`modal` 时生效)。 |\n| `closeOnOutsideClick` | `boolean` | `true` | 点击遮罩关闭。 |\n| `dismissableMask` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `maskClosable` | `boolean` | — | `closeOnOutsideClick` 的别名。 |\n| `closable` | `boolean` | `true` | 显示关闭按钮。 |\n| `maximizable` | `boolean` | `false` | 显示最大化 / 还原按钮。 |\n| `modal` | `boolean` | `true` | 遮罩层。 |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | 对话框位置。 |\n| `centered` | `boolean` | — | 垂直居中:`true` → `center`,`false` → `top`;省略时用 `position`。 |\n| `width` | `string` | — | 对话框宽度(最大化时忽略)。 |\n| `teleport` | `boolean` | `true` | 浮层 Teleport;默认挂到 `body`。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 就地渲染。 |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | 标题状态图标;`warning` 与 `warn` 同义 |\n| `positiveText` / `negativeText` | `string` | — | 预设页脚按钮;有 `footer` 插槽时忽略 |\n| `positiveColor` | [ButtonColor](/docs/types#ButtonColor) | — | 确认按钮颜色 |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | 返回 `false` 则不关闭 |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | X / Esc / 遮罩关闭前;返回 `false` 则保持打开 |\n| `ariaLabel` | `string` | — | 对话框可访问名称。 |\n| `transition` | `string \\| false` | `'zoom'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | 遮罩层(backdrop)透传,键名 `root`。 |\n\n## 样式与 attrs\n\nDialog Teleport 到 `body` 后,你在组件上写的 fallthrough attrs(`class`、`style`、`data-*`、`title` 等)落在**遮罩层**(`.m-dialog-backdrop`),不是内层 `.m-dialog` 面板。面板宽度用 `width` prop;内层 DOM 用 `pt`。详见 [样式与 attrs](/docs/attrs)。\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | 可见性变化。 |\n| `close` | — | 关闭时触发。 |\n| `show` | — | 打开时触发。 |\n| `hide` | — | 关闭后触发。 |\n| `maximize` | — | 进入最大化。 |\n| `unmaximize` | — | 退出最大化。 |\n\n## Methods\n\n| 方法 | 说明 |\n| --- | --- |\n| `close()` | 关闭对话框(等同取消/关闭动作)。 |\n| `maximize()` | 最大化;已最大化时无操作。 |\n| `unmaximize()` | 退出最大化。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 对话框内容。 |\n| `header` | 自定义标题区。 |\n| `footer` | 底部操作区。 |\n\n## 命令式调用(useModal / modal)\n\n不写模板也能弹出对话框:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// 模块级单例\nmodal.confirm({\n title: '确认删除?',\n content: '删除后不可恢复',\n onOk: async () => { await remove() },\n})\n\n// 或组件内作用域实例\nconst dialog = useModal()\ndialog.success({ title: '已保存' })\n```\n\n每个调用返回 `{ destroy, update }`:`update` 可在打开时改标题/内容,`destroy` 立即关闭并卸载。`modal.destroyAll()` 关闭全部由该 API 创建的对话框。\n\n| 方法 | 说明 |\n| --- | --- |\n| `info(options)` | 信息弹窗(默认无取消按钮) |\n| `success(options)` | 成功弹窗 |\n| `warning(options)` | 警告弹窗 |\n| `error(options)` | 错误弹窗 |\n| `confirm(options)` | 确认弹窗(默认显示取消按钮) |\n| `destroyAll()` | 关闭全部 |\n\n`options` 传字符串等价于 `{ content: '...' }`。\n\n| 字段 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `title` | `string` | — | 标题 |\n| `content` | `string \\| VNode` | — | 内容 |\n| `type` | `DialogType` | — | 头部状态图标 |\n| `okText` / `cancelText` | `string` | locale | 按钮文案 |\n| `showCancel` | `boolean` | 状态弹窗 `false`,`confirm` `true` | 是否显示取消按钮 |\n| `okColor` | `ButtonColor` | `'primary'` | 确认按钮颜色 |\n| `width` / `position` / `centered` | 同 Dialog | — | 布局 |\n| `maskClosable` | `boolean` | `false` | 点击遮罩关闭 |\n| `onOk` | `() => void \\| Promise<void>` | — | 确认回调;返回 Promise 时按钮进入 loading |\n| `onCancel` | `() => void` | — | 取消 / 关闭回调 |\n| `afterClose` | `() => void` | — | 关闭动画结束后回调 |\n\n> 命令式弹窗就地渲染在挂载容器内(不 Teleport),便于精确销毁。\n| `footer` | 底部操作区。 |\n"
7306
7318
  },
7307
7319
  "en-US": {
7308
7320
  "title": "Dialog",
@@ -7351,7 +7363,7 @@
7351
7363
  {
7352
7364
  "id": "props",
7353
7365
  "title": "Props",
7354
- "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. Use with `v-model`. |\n| `title` | `string` | — | Title text. |\n| `header` | `string` | — | Alias of `title`. |\n| `closeOnEsc` | `boolean` | `true` | Close on Esc. |\n| `blockScroll` | `boolean` | `true` | Lock page scroll while open (when `modal` is true). |\n| `closeOnOutsideClick` | `boolean` | `true` | Close when clicking the mask. |\n| `dismissableMask` | `boolean` | — | Alias of `closeOnOutsideClick`. |\n| `maskClosable` | `boolean` | — | Alias of `closeOnOutsideClick` . |\n| `closable` | `boolean` | `true` | Show the close button. |\n| `maximizable` | `boolean` | `false` | Show the maximize / restore button. |\n| `modal` | `boolean` | `true` | Overlay mask. |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | Dialog position. |\n| `centered` | `boolean` | — | Vertical centering: `true` → `center`, `false` → `top`; omit to use `position`. |\n| `width` | `string` | — | Dialog width (ignored when maximized). |\n| `teleport` | `boolean` | `true` | Overlay Teleport; mounts to `body` by default. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` renders in place. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon in the header; `warning` is an alias of `warn` |\n| `positiveText` / `negativeText` | `string` | — | Preset footer buttons; ignored when the `footer` slot is used |\n| `positiveSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | Confirm button severity |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | Return `false` to keep the dialog open |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | Runs before X / Esc / mask dismiss; return `false` to keep open |\n| `ariaLabel` | `string` | — | Accessible dialog name. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Backdrop pass-through; key `root`. |"
7366
+ "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. Use with `v-model`. |\n| `title` | `string` | — | Title text. |\n| `header` | `string` | — | Alias of `title`. |\n| `closeOnEsc` | `boolean` | `true` | Close on Esc. |\n| `blockScroll` | `boolean` | `true` | Lock page scroll while open (when `modal` is true). |\n| `closeOnOutsideClick` | `boolean` | `true` | Close when clicking the mask. |\n| `dismissableMask` | `boolean` | — | Alias of `closeOnOutsideClick`. |\n| `maskClosable` | `boolean` | — | Alias of `closeOnOutsideClick` . |\n| `closable` | `boolean` | `true` | Show the close button. |\n| `maximizable` | `boolean` | `false` | Show the maximize / restore button. |\n| `modal` | `boolean` | `true` | Overlay mask. |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | Dialog position. |\n| `centered` | `boolean` | — | Vertical centering: `true` → `center`, `false` → `top`; omit to use `position`. |\n| `width` | `string` | — | Dialog width (ignored when maximized). |\n| `teleport` | `boolean` | `true` | Overlay Teleport; mounts to `body` by default. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` renders in place. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon in the header; `warning` is an alias of `warn` |\n| `positiveText` / `negativeText` | `string` | — | Preset footer buttons; ignored when the `footer` slot is used |\n| `positiveColor` | [ButtonColor](/docs/types#ButtonColor) | — | Confirm button color |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | Return `false` to keep the dialog open |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | Runs before X / Esc / mask dismiss; return `false` to keep open |\n| `ariaLabel` | `string` | — | Accessible dialog name. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Backdrop pass-through; key `root`. |"
7355
7367
  },
7356
7368
  {
7357
7369
  "id": "styling-attrs",
@@ -7376,10 +7388,10 @@
7376
7388
  {
7377
7389
  "id": "imperative-api-usemodal-modal",
7378
7390
  "title": "Imperative API (useModal / modal)",
7379
- "body": "Open dialogs without writing a template:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// Module-level singleton\nmodal.confirm({\n title: 'Delete this item?',\n content: 'This cannot be undone',\n onOk: async () => { await remove() },\n})\n\n// Or a component-scoped instance\nconst dialog = useModal()\ndialog.success({ title: 'Saved' })\n```\n\nEvery call returns `{ destroy, update }`: `update` patches the title / content while open, `destroy` closes and unmounts immediately. `modal.destroyAll()` closes every dialog created through the API.\n\n| Method | Description |\n| --- | --- |\n| `info(options)` | Message dialog (no cancel button by default) |\n| `success(options)` | Success dialog |\n| `warning(options)` | Warning dialog |\n| `error(options)` | Error dialog |\n| `confirm(options)` | Confirmation dialog (cancel button shown by default) |\n| `destroyAll()` | Close all |\n\nPassing a string as `options` is shorthand for `{ content: '...' }`.\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `title` | `string` | — | Title |\n| `content` | `string \\| VNode` | — | Body |\n| `type` | `DialogType` | — | Header status icon |\n| `okText` / `cancelText` | `string` | locale | Button labels |\n| `showCancel` | `boolean` | `false` for status helpers, `true` for `confirm` | Show the cancel button |\n| `okSeverity` | `ButtonSeverity` | `'primary'` | Confirm button tone |\n| `width` / `position` / `centered` | as Dialog | — | Layout |\n| `maskClosable` | `boolean` | `false` | Dismiss by clicking the mask |\n| `onOk` | `() => void \\| Promise<void>` | — | Confirm handler; a returned Promise puts the button in a loading state |\n| `onCancel` | `() => void` | — | Cancel / dismiss handler |\n| `afterClose` | `() => void` | — | Called after the close transition |\n\n> Imperative dialogs render in place inside their mount container (no Teleport) so they can be destroyed precisely."
7391
+ "body": "Open dialogs without writing a template:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// Module-level singleton\nmodal.confirm({\n title: 'Delete this item?',\n content: 'This cannot be undone',\n onOk: async () => { await remove() },\n})\n\n// Or a component-scoped instance\nconst dialog = useModal()\ndialog.success({ title: 'Saved' })\n```\n\nEvery call returns `{ destroy, update }`: `update` patches the title / content while open, `destroy` closes and unmounts immediately. `modal.destroyAll()` closes every dialog created through the API.\n\n| Method | Description |\n| --- | --- |\n| `info(options)` | Message dialog (no cancel button by default) |\n| `success(options)` | Success dialog |\n| `warning(options)` | Warning dialog |\n| `error(options)` | Error dialog |\n| `confirm(options)` | Confirmation dialog (cancel button shown by default) |\n| `destroyAll()` | Close all |\n\nPassing a string as `options` is shorthand for `{ content: '...' }`.\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `title` | `string` | — | Title |\n| `content` | `string \\| VNode` | — | Body |\n| `type` | `DialogType` | — | Header status icon |\n| `okText` / `cancelText` | `string` | locale | Button labels |\n| `showCancel` | `boolean` | `false` for status helpers, `true` for `confirm` | Show the cancel button |\n| `okColor` | `ButtonColor` | `'primary'` | Confirm button color |\n| `width` / `position` / `centered` | as Dialog | — | Layout |\n| `maskClosable` | `boolean` | `false` | Dismiss by clicking the mask |\n| `onOk` | `() => void \\| Promise<void>` | — | Confirm handler; a returned Promise puts the button in a loading state |\n| `onCancel` | `() => void` | — | Cancel / dismiss handler |\n| `afterClose` | `() => void` | — | Called after the close transition |\n\n> Imperative dialogs render in place inside their mount container (no Teleport) so they can be destroyed precisely."
7380
7392
  }
7381
7393
  ],
7382
- "markdown": "---\ntitle: Dialog\ncategory: 05 / FEEDBACK\ndescription: Modal dialog with preset footer actions, async close guards, and status type.\n---\n\n# Dialog\n\nModal dialog. Visibility uses `v-model` (`modelValue`), corresponding to `visible`.\n\n## Import\n\n```ts\nimport { MButton, MDialog } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Positions\n\nSupports `center` / `top` / `bottom` / `left` / `right` and the four corner positions.\n\n```vue preview src=\"./demos/Positions.vue\"\n```\n\n## Footer actions\n\n```vue preview src=\"./demos/FooterActions.vue\"\n```\n\n## No dismiss mask\n\nWith `dismissableMask={false}` (or `closeOnOutsideClick={false}` / `maskClosable={false}`), clicking the mask does not close the dialog.\n\n```vue preview src=\"./demos/NoDismissMask.vue\"\n```\n\n## Maximizable\n\n`maximizable` adds a maximize / restore toggle in the title bar.\n\n```vue preview src=\"./demos/Maximizable.vue\"\n```\n\n## Preset footer and async close\n\n`positiveText` / `negativeText` render confirm / cancel buttons (`footer` slot wins). Return `false` (including from a Promise) to keep the dialog open. Use [ConfirmDialog](/components/ConfirmDialog) for accept/reject flows; Dialog `type` is a header icon only.\n\n```vue preview src=\"./demos/PresetFooterAndAsyncClose.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. Use with `v-model`. |\n| `title` | `string` | — | Title text. |\n| `header` | `string` | — | Alias of `title`. |\n| `closeOnEsc` | `boolean` | `true` | Close on Esc. |\n| `blockScroll` | `boolean` | `true` | Lock page scroll while open (when `modal` is true). |\n| `closeOnOutsideClick` | `boolean` | `true` | Close when clicking the mask. |\n| `dismissableMask` | `boolean` | — | Alias of `closeOnOutsideClick`. |\n| `maskClosable` | `boolean` | — | Alias of `closeOnOutsideClick` . |\n| `closable` | `boolean` | `true` | Show the close button. |\n| `maximizable` | `boolean` | `false` | Show the maximize / restore button. |\n| `modal` | `boolean` | `true` | Overlay mask. |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | Dialog position. |\n| `centered` | `boolean` | — | Vertical centering: `true` → `center`, `false` → `top`; omit to use `position`. |\n| `width` | `string` | — | Dialog width (ignored when maximized). |\n| `teleport` | `boolean` | `true` | Overlay Teleport; mounts to `body` by default. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` renders in place. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon in the header; `warning` is an alias of `warn` |\n| `positiveText` / `negativeText` | `string` | — | Preset footer buttons; ignored when the `footer` slot is used |\n| `positiveSeverity` | [ButtonSeverity](/docs/types#ButtonSeverity) | — | Confirm button severity |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | Return `false` to keep the dialog open |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | Runs before X / Esc / mask dismiss; return `false` to keep open |\n| `ariaLabel` | `string` | — | Accessible dialog name. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Backdrop pass-through; key `root`. |\n\n## Styling & attrs\n\nAfter Teleport, fallthrough attrs on `<MDialog>` (`class`, `style`, `data-*`, `title`, …) land on the **backdrop** (`.m-dialog-backdrop`), not the inner `.m-dialog` panel. Use the `width` prop for panel width; use `pt` for inner DOM. See [Styling & attrs](/docs/attrs).\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Visibility change. |\n| `close` | — | Emitted when closing. |\n| `show` | — | Emitted when opening. |\n| `hide` | — | Emitted after closing. |\n| `maximize` | — | Enter maximize. |\n| `unmaximize` | — | Exit maximize. |\n\n## Methods\n\n| Method | Description |\n| --- | --- |\n| `close()` | Close the dialog (same as the cancel/close action). |\n| `maximize()` | Maximize; no-op when already maximized. |\n| `unmaximize()` | Leave the maximized state. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Dialog content. |\n| `header` | Custom header area. |\n| `footer` | Footer actions. |\n\n## Imperative API (useModal / modal)\n\nOpen dialogs without writing a template:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// Module-level singleton\nmodal.confirm({\n title: 'Delete this item?',\n content: 'This cannot be undone',\n onOk: async () => { await remove() },\n})\n\n// Or a component-scoped instance\nconst dialog = useModal()\ndialog.success({ title: 'Saved' })\n```\n\nEvery call returns `{ destroy, update }`: `update` patches the title / content while open, `destroy` closes and unmounts immediately. `modal.destroyAll()` closes every dialog created through the API.\n\n| Method | Description |\n| --- | --- |\n| `info(options)` | Message dialog (no cancel button by default) |\n| `success(options)` | Success dialog |\n| `warning(options)` | Warning dialog |\n| `error(options)` | Error dialog |\n| `confirm(options)` | Confirmation dialog (cancel button shown by default) |\n| `destroyAll()` | Close all |\n\nPassing a string as `options` is shorthand for `{ content: '...' }`.\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `title` | `string` | — | Title |\n| `content` | `string \\| VNode` | — | Body |\n| `type` | `DialogType` | — | Header status icon |\n| `okText` / `cancelText` | `string` | locale | Button labels |\n| `showCancel` | `boolean` | `false` for status helpers, `true` for `confirm` | Show the cancel button |\n| `okSeverity` | `ButtonSeverity` | `'primary'` | Confirm button tone |\n| `width` / `position` / `centered` | as Dialog | — | Layout |\n| `maskClosable` | `boolean` | `false` | Dismiss by clicking the mask |\n| `onOk` | `() => void \\| Promise<void>` | — | Confirm handler; a returned Promise puts the button in a loading state |\n| `onCancel` | `() => void` | — | Cancel / dismiss handler |\n| `afterClose` | `() => void` | — | Called after the close transition |\n\n> Imperative dialogs render in place inside their mount container (no Teleport) so they can be destroyed precisely.\n"
7394
+ "markdown": "---\ntitle: Dialog\ncategory: 05 / FEEDBACK\ndescription: Modal dialog with preset footer actions, async close guards, and status type.\n---\n\n# Dialog\n\nModal dialog. Visibility uses `v-model` (`modelValue`), corresponding to `visible`.\n\n## Import\n\n```ts\nimport { MButton, MDialog } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.vue\"\n```\n\n## Positions\n\nSupports `center` / `top` / `bottom` / `left` / `right` and the four corner positions.\n\n```vue preview src=\"./demos/Positions.vue\"\n```\n\n## Footer actions\n\n```vue preview src=\"./demos/FooterActions.vue\"\n```\n\n## No dismiss mask\n\nWith `dismissableMask={false}` (or `closeOnOutsideClick={false}` / `maskClosable={false}`), clicking the mask does not close the dialog.\n\n```vue preview src=\"./demos/NoDismissMask.vue\"\n```\n\n## Maximizable\n\n`maximizable` adds a maximize / restore toggle in the title bar.\n\n```vue preview src=\"./demos/Maximizable.vue\"\n```\n\n## Preset footer and async close\n\n`positiveText` / `negativeText` render confirm / cancel buttons (`footer` slot wins). Return `false` (including from a Promise) to keep the dialog open. Use [ConfirmDialog](/components/ConfirmDialog) for accept/reject flows; Dialog `type` is a header icon only.\n\n```vue preview src=\"./demos/PresetFooterAndAsyncClose.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `modelValue` | `boolean` | `false` | Visibility. Use with `v-model`. |\n| `title` | `string` | — | Title text. |\n| `header` | `string` | — | Alias of `title`. |\n| `closeOnEsc` | `boolean` | `true` | Close on Esc. |\n| `blockScroll` | `boolean` | `true` | Lock page scroll while open (when `modal` is true). |\n| `closeOnOutsideClick` | `boolean` | `true` | Close when clicking the mask. |\n| `dismissableMask` | `boolean` | — | Alias of `closeOnOutsideClick`. |\n| `maskClosable` | `boolean` | — | Alias of `closeOnOutsideClick` . |\n| `closable` | `boolean` | `true` | Show the close button. |\n| `maximizable` | `boolean` | `false` | Show the maximize / restore button. |\n| `modal` | `boolean` | `true` | Overlay mask. |\n| `position` | `'center' \\| 'top' \\| 'bottom' \\| 'left' \\| 'right' \\| 'topleft' \\| 'topright' \\| 'bottomleft' \\| 'bottomright'` | `'center'` | Dialog position. |\n| `centered` | `boolean` | — | Vertical centering: `true` → `center`, `false` → `top`; omit to use `position`. |\n| `width` | `string` | — | Dialog width (ignored when maximized). |\n| `teleport` | `boolean` | `true` | Overlay Teleport; mounts to `body` by default. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` renders in place. |\n| `type` | `'info' \\| 'success' \\| 'warning' \\| 'error'` | — | Status icon in the header; `warning` is an alias of `warn` |\n| `positiveText` / `negativeText` | `string` | — | Preset footer buttons; ignored when the `footer` slot is used |\n| `positiveColor` | [ButtonColor](/docs/types#ButtonColor) | — | Confirm button color |\n| `onPositiveClick` / `onNegativeClick` | `(e) => unknown \\| Promise<unknown>` | — | Return `false` to keep the dialog open |\n| `beforeClose` | `() => unknown \\| Promise<unknown>` | — | Runs before X / Esc / mask dismiss; return `false` to keep open |\n| `ariaLabel` | `string` | — | Accessible dialog name. |\n| `transition` | `string \\| false` | `'zoom'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Backdrop pass-through; key `root`. |\n\n## Styling & attrs\n\nAfter Teleport, fallthrough attrs on `<MDialog>` (`class`, `style`, `data-*`, `title`, …) land on the **backdrop** (`.m-dialog-backdrop`), not the inner `.m-dialog` panel. Use the `width` prop for panel width; use `pt` for inner DOM. See [Styling & attrs](/docs/attrs).\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `update:modelValue` | `boolean` | Visibility change. |\n| `close` | — | Emitted when closing. |\n| `show` | — | Emitted when opening. |\n| `hide` | — | Emitted after closing. |\n| `maximize` | — | Enter maximize. |\n| `unmaximize` | — | Exit maximize. |\n\n## Methods\n\n| Method | Description |\n| --- | --- |\n| `close()` | Close the dialog (same as the cancel/close action). |\n| `maximize()` | Maximize; no-op when already maximized. |\n| `unmaximize()` | Leave the maximized state. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Dialog content. |\n| `header` | Custom header area. |\n| `footer` | Footer actions. |\n\n## Imperative API (useModal / modal)\n\nOpen dialogs without writing a template:\n\n```ts\nimport { modal, useModal } from 'morya-ui'\n\n// Module-level singleton\nmodal.confirm({\n title: 'Delete this item?',\n content: 'This cannot be undone',\n onOk: async () => { await remove() },\n})\n\n// Or a component-scoped instance\nconst dialog = useModal()\ndialog.success({ title: 'Saved' })\n```\n\nEvery call returns `{ destroy, update }`: `update` patches the title / content while open, `destroy` closes and unmounts immediately. `modal.destroyAll()` closes every dialog created through the API.\n\n| Method | Description |\n| --- | --- |\n| `info(options)` | Message dialog (no cancel button by default) |\n| `success(options)` | Success dialog |\n| `warning(options)` | Warning dialog |\n| `error(options)` | Error dialog |\n| `confirm(options)` | Confirmation dialog (cancel button shown by default) |\n| `destroyAll()` | Close all |\n\nPassing a string as `options` is shorthand for `{ content: '...' }`.\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `title` | `string` | — | Title |\n| `content` | `string \\| VNode` | — | Body |\n| `type` | `DialogType` | — | Header status icon |\n| `okText` / `cancelText` | `string` | locale | Button labels |\n| `showCancel` | `boolean` | `false` for status helpers, `true` for `confirm` | Show the cancel button |\n| `okColor` | `ButtonColor` | `'primary'` | Confirm button color |\n| `width` / `position` / `centered` | as Dialog | — | Layout |\n| `maskClosable` | `boolean` | `false` | Dismiss by clicking the mask |\n| `onOk` | `() => void \\| Promise<void>` | — | Confirm handler; a returned Promise puts the button in a loading state |\n| `onCancel` | `() => void` | — | Cancel / dismiss handler |\n| `afterClose` | `() => void` | — | Called after the close transition |\n\n> Imperative dialogs render in place inside their mount container (no Teleport) so they can be destroyed precisely.\n"
7383
7395
  }
7384
7396
  }
7385
7397
  },
@@ -8082,7 +8094,7 @@
8082
8094
  "sectionId": "position",
8083
8095
  "lang": "vue",
8084
8096
  "preview": true,
8085
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'left' | 'right' | 'top' | 'bottom'>('right')\n\nfunction openAt(next: 'left' | 'right' | 'top' | 'bottom') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Left\" size=\"small\" @click=\"openAt('left')\" />\n <MButton label=\"Right\" size=\"small\" severity=\"secondary\" @click=\"openAt('right')\" />\n <MButton label=\"Top\" size=\"small\" severity=\"secondary\" @click=\"openAt('top')\" />\n <MButton label=\"Bottom\" size=\"small\" severity=\"secondary\" @click=\"openAt('bottom')\" />\n <MDrawer v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Use <code>dismissable</code> to control mask dismiss.\n </p>\n </MDrawer>\n </div>\n</template>",
8097
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'left' | 'right' | 'top' | 'bottom'>('right')\n\nfunction openAt(next: 'left' | 'right' | 'top' | 'bottom') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Left\" size=\"small\" @click=\"openAt('left')\" />\n <MButton label=\"Right\" size=\"small\" @click=\"openAt('right')\"/>\n <MButton label=\"Top\" size=\"small\" @click=\"openAt('top')\"/>\n <MButton label=\"Bottom\" size=\"small\" @click=\"openAt('bottom')\"/>\n <MDrawer v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Use <code>dismissable</code> to control mask dismiss.\n </p>\n </MDrawer>\n </div>\n</template>",
8086
8098
  "locale": "zh-CN"
8087
8099
  },
8088
8100
  {
@@ -8091,7 +8103,7 @@
8091
8103
  "sectionId": "footer",
8092
8104
  "lang": "vue",
8093
8105
  "preview": true,
8094
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer, MSpace } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDrawer v-model=\"open\" header=\"Edit details\" position=\"right\" :width=\"360\">\n <p style=\"margin:0\">\n Put primary and secondary actions in the footer slot so the body can scroll independently.\n </p>\n <template #footer>\n <MSpace style=\"justify-content: flex-end; width: 100%\">\n <MButton label=\"Cancel\" severity=\"secondary\" text @click=\"open = false\" />\n <MButton label=\"Save\" @click=\"open = false\" />\n </MSpace>\n </template>\n </MDrawer>\n </div>\n</template>",
8106
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer, MSpace } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDrawer v-model=\"open\" header=\"Edit details\" position=\"right\" :width=\"360\">\n <p style=\"margin:0\">\n Put primary and secondary actions in the footer slot so the body can scroll independently.\n </p>\n <template #footer>\n <MSpace style=\"justify-content: flex-end; width: 100%\">\n <MButton label=\"Cancel\" @click=\"open = false\" type=\"text\"/>\n <MButton label=\"Save\" @click=\"open = false\" />\n </MSpace>\n </template>\n </MDrawer>\n </div>\n</template>",
8095
8107
  "locale": "zh-CN"
8096
8108
  },
8097
8109
  {
@@ -8118,7 +8130,7 @@
8118
8130
  "sectionId": "position",
8119
8131
  "lang": "vue",
8120
8132
  "preview": true,
8121
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'left' | 'right' | 'top' | 'bottom'>('right')\n\nfunction openAt(next: 'left' | 'right' | 'top' | 'bottom') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Left\" size=\"small\" @click=\"openAt('left')\" />\n <MButton label=\"Right\" size=\"small\" severity=\"secondary\" @click=\"openAt('right')\" />\n <MButton label=\"Top\" size=\"small\" severity=\"secondary\" @click=\"openAt('top')\" />\n <MButton label=\"Bottom\" size=\"small\" severity=\"secondary\" @click=\"openAt('bottom')\" />\n <MDrawer v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Use <code>dismissable</code> to control mask dismiss.\n </p>\n </MDrawer>\n </div>\n</template>",
8133
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst position = ref<'left' | 'right' | 'top' | 'bottom'>('right')\n\nfunction openAt(next: 'left' | 'right' | 'top' | 'bottom') {\n position.value = next\n open.value = true\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Left\" size=\"small\" @click=\"openAt('left')\" />\n <MButton label=\"Right\" size=\"small\" @click=\"openAt('right')\"/>\n <MButton label=\"Top\" size=\"small\" @click=\"openAt('top')\"/>\n <MButton label=\"Bottom\" size=\"small\" @click=\"openAt('bottom')\"/>\n <MDrawer v-model=\"open\" :header=\"`Position: ${position}`\" :position=\"position\">\n <p style=\"margin:0\">\n Use <code>dismissable</code> to control mask dismiss.\n </p>\n </MDrawer>\n </div>\n</template>",
8122
8134
  "locale": "en-US"
8123
8135
  },
8124
8136
  {
@@ -8127,7 +8139,7 @@
8127
8139
  "sectionId": "footer",
8128
8140
  "lang": "vue",
8129
8141
  "preview": true,
8130
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer, MSpace } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDrawer v-model=\"open\" header=\"Edit details\" position=\"right\" :width=\"360\">\n <p style=\"margin:0\">\n Put primary and secondary actions in the footer slot so the body can scroll independently.\n </p>\n <template #footer>\n <MSpace style=\"justify-content: flex-end; width: 100%\">\n <MButton label=\"Cancel\" severity=\"secondary\" text @click=\"open = false\" />\n <MButton label=\"Save\" @click=\"open = false\" />\n </MSpace>\n </template>\n </MDrawer>\n </div>\n</template>",
8142
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDrawer, MSpace } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div>\n <MButton label=\"With Footer\" @click=\"open = true\" />\n <MDrawer v-model=\"open\" header=\"Edit details\" position=\"right\" :width=\"360\">\n <p style=\"margin:0\">\n Put primary and secondary actions in the footer slot so the body can scroll independently.\n </p>\n <template #footer>\n <MSpace style=\"justify-content: flex-end; width: 100%\">\n <MButton label=\"Cancel\" @click=\"open = false\" type=\"text\"/>\n <MButton label=\"Save\" @click=\"open = false\" />\n </MSpace>\n </template>\n </MDrawer>\n </div>\n</template>",
8131
8143
  "locale": "en-US"
8132
8144
  }
8133
8145
  ],
@@ -8349,7 +8361,7 @@
8349
8361
  "sectionId": "基础用法",
8350
8362
  "lang": "vue",
8351
8363
  "preview": true,
8352
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { value: 'edit', label: 'Edit' },\n { value: 'duplicate', label: 'Duplicate' },\n { value: 'delete', label: 'Delete', disabled: true },\n]\n\nfunction onSelect(item: { value?: string; label?: string }) {\n open.value = false\n console.log(item.value)\n}\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" @select=\"onSelect\">\n <template #trigger>\n <MButton label=\"Actions\" icon=\"chevron-down\" icon-pos=\"right\" severity=\"secondary\" />\n </template>\n </MDropdown>\n</template>",
8364
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { value: 'edit', label: 'Edit' },\n { value: 'duplicate', label: 'Duplicate' },\n { value: 'delete', label: 'Delete', disabled: true },\n]\n\nfunction onSelect(item: { value?: string; label?: string }) {\n open.value = false\n console.log(item.value)\n}\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" @select=\"onSelect\">\n <template #trigger>\n <MButton label=\"Actions\" icon=\"chevron-down\" icon-placement=\"end\"/>\n </template>\n </MDropdown>\n</template>",
8353
8365
  "locale": "zh-CN"
8354
8366
  },
8355
8367
  {
@@ -8358,7 +8370,7 @@
8358
8370
  "sectionId": "nested-group-hover",
8359
8371
  "lang": "vue",
8360
8372
  "preview": true,
8361
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { type: 'group' as const, label: '编辑', items: [{ value: 'cut', label: '剪切' }, { value: 'copy', label: '复制' }] },\n { separator: true },\n { value: 'more', label: '更多', items: [{ value: 'deep', label: '深层操作' }] },\n]\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" trigger=\"hover\" :show-delay=\"0\" :hide-delay=\"200\">\n <template #trigger>\n <MButton label=\"悬停打开\" severity=\"secondary\" />\n </template>\n </MDropdown>\n</template>",
8373
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { type: 'group' as const, label: '编辑', items: [{ value: 'cut', label: '剪切' }, { value: 'copy', label: '复制' }] },\n { separator: true },\n { value: 'more', label: '更多', items: [{ value: 'deep', label: '深层操作' }] },\n]\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" trigger=\"hover\" :show-delay=\"0\" :hide-delay=\"200\">\n <template #trigger>\n <MButton label=\"悬停打开\"/>\n </template>\n </MDropdown>\n</template>",
8362
8374
  "locale": "zh-CN"
8363
8375
  },
8364
8376
  {
@@ -8385,7 +8397,7 @@
8385
8397
  "sectionId": "basic",
8386
8398
  "lang": "vue",
8387
8399
  "preview": true,
8388
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { value: 'edit', label: 'Edit' },\n { value: 'duplicate', label: 'Duplicate' },\n { value: 'delete', label: 'Delete', disabled: true },\n]\n\nfunction onSelect(item: { value?: string; label?: string }) {\n open.value = false\n console.log(item.value)\n}\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" @select=\"onSelect\">\n <template #trigger>\n <MButton label=\"Actions\" icon=\"chevron-down\" icon-pos=\"right\" severity=\"secondary\" />\n </template>\n </MDropdown>\n</template>",
8400
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { value: 'edit', label: 'Edit' },\n { value: 'duplicate', label: 'Duplicate' },\n { value: 'delete', label: 'Delete', disabled: true },\n]\n\nfunction onSelect(item: { value?: string; label?: string }) {\n open.value = false\n console.log(item.value)\n}\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" @select=\"onSelect\">\n <template #trigger>\n <MButton label=\"Actions\" icon=\"chevron-down\" icon-placement=\"end\"/>\n </template>\n </MDropdown>\n</template>",
8389
8401
  "locale": "en-US"
8390
8402
  },
8391
8403
  {
@@ -8394,7 +8406,7 @@
8394
8406
  "sectionId": "nested-group-hover",
8395
8407
  "lang": "vue",
8396
8408
  "preview": true,
8397
- "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { type: 'group' as const, label: 'Edit', items: [{ value: 'cut', label: 'Cut' }, { value: 'copy', label: 'Copy' }] },\n { separator: true },\n { value: 'more', label: 'More', items: [{ value: 'deep', label: 'Deep action' }] },\n]\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" trigger=\"hover\" :show-delay=\"0\" :hide-delay=\"200\">\n <template #trigger>\n <MButton label=\"Hover to open\" severity=\"secondary\" />\n </template>\n </MDropdown>\n</template>",
8409
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MDropdown } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\nconst items = [\n { type: 'group' as const, label: 'Edit', items: [{ value: 'cut', label: 'Cut' }, { value: 'copy', label: 'Copy' }] },\n { separator: true },\n { value: 'more', label: 'More', items: [{ value: 'deep', label: 'Deep action' }] },\n]\n</script>\n\n<template>\n <MDropdown v-model=\"open\" :items=\"items\" trigger=\"hover\" :show-delay=\"0\" :hide-delay=\"200\">\n <template #trigger>\n <MButton label=\"Hover to open\"/>\n </template>\n </MDropdown>\n</template>",
8398
8410
  "locale": "en-US"
8399
8411
  },
8400
8412
  {
@@ -8633,7 +8645,7 @@
8633
8645
  "sectionId": "操作区",
8634
8646
  "lang": "vue",
8635
8647
  "preview": true,
8636
- "code": "<script setup lang=\"ts\">\nimport { MButton, MEmpty } from 'morya-ui'\n</script>\n\n<template>\n <MEmpty\n title=\"还没有课程\"\n description=\"创建第一门课程后,学员就能在目录里看到它。也可以稍后从模板导入。\"\n icon=\"book\"\n >\n <template #extra>\n <MButton label=\"创建第一门课程\" />\n <MButton label=\"从模板导入\" severity=\"secondary\" text />\n </template>\n </MEmpty>\n</template>",
8648
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MEmpty } from 'morya-ui'\n</script>\n\n<template>\n <MEmpty\n title=\"还没有课程\"\n description=\"创建第一门课程后,学员就能在目录里看到它。也可以稍后从模板导入。\"\n icon=\"book\"\n >\n <template #extra>\n <MButton label=\"创建第一门课程\" />\n <MButton label=\"从模板导入\" type=\"text\"/>\n </template>\n </MEmpty>\n</template>",
8637
8649
  "locale": "zh-CN"
8638
8650
  },
8639
8651
  {
@@ -8687,7 +8699,7 @@
8687
8699
  "sectionId": "actions",
8688
8700
  "lang": "vue",
8689
8701
  "preview": true,
8690
- "code": "<script setup lang=\"ts\">\nimport { MButton, MEmpty } from 'morya-ui'\n</script>\n\n<template>\n <MEmpty\n title=\"No courses yet\"\n description=\"Create your first course so learners can find it in the catalog. You can also import from a template later.\"\n icon=\"book\"\n >\n <template #extra>\n <MButton label=\"Create first course\" />\n <MButton label=\"Import from template\" severity=\"secondary\" text />\n </template>\n </MEmpty>\n</template>",
8702
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MEmpty } from 'morya-ui'\n</script>\n\n<template>\n <MEmpty\n title=\"No courses yet\"\n description=\"Create your first course so learners can find it in the catalog. You can also import from a template later.\"\n icon=\"book\"\n >\n <template #extra>\n <MButton label=\"Create first course\" />\n <MButton label=\"Import from template\" type=\"text\"/>\n </template>\n </MEmpty>\n</template>",
8691
8703
  "locale": "en-US"
8692
8704
  },
8693
8705
  {
@@ -9672,7 +9684,7 @@
9672
9684
  "sectionId": "基础用法",
9673
9685
  "lang": "vue",
9674
9686
  "preview": true,
9675
- "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex>\n <MButton label=\"一\" size=\"small\" />\n <MButton label=\"二\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"三\" size=\"small\" severity=\"secondary\" />\n </MFlex>\n</template>",
9687
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex>\n <MButton label=\"一\" size=\"small\" />\n <MButton label=\"二\" size=\"small\"/>\n <MButton label=\"三\" size=\"small\"/>\n </MFlex>\n</template>",
9676
9688
  "locale": "zh-CN"
9677
9689
  },
9678
9690
  {
@@ -9681,7 +9693,7 @@
9681
9693
  "sectionId": "vertical",
9682
9694
  "lang": "vue",
9683
9695
  "preview": true,
9684
- "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical>\n <MButton label=\"上\" size=\"small\" />\n <MButton label=\"中\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"下\" size=\"small\" severity=\"secondary\" />\n </MFlex>\n</template>",
9696
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical>\n <MButton label=\"上\" size=\"small\" />\n <MButton label=\"中\" size=\"small\"/>\n <MButton label=\"下\" size=\"small\"/>\n </MFlex>\n</template>",
9685
9697
  "locale": "zh-CN"
9686
9698
  },
9687
9699
  {
@@ -9708,7 +9720,7 @@
9708
9720
  "sectionId": "basic",
9709
9721
  "lang": "vue",
9710
9722
  "preview": true,
9711
- "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex>\n <MButton label=\"One\" size=\"small\" />\n <MButton label=\"Two\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"Three\" size=\"small\" severity=\"secondary\" />\n </MFlex>\n</template>",
9723
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex>\n <MButton label=\"One\" size=\"small\" />\n <MButton label=\"Two\" size=\"small\"/>\n <MButton label=\"Three\" size=\"small\"/>\n </MFlex>\n</template>",
9712
9724
  "locale": "en-US"
9713
9725
  },
9714
9726
  {
@@ -9717,7 +9729,7 @@
9717
9729
  "sectionId": "vertical",
9718
9730
  "lang": "vue",
9719
9731
  "preview": true,
9720
- "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical>\n <MButton label=\"Top\" size=\"small\" />\n <MButton label=\"Middle\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"Bottom\" size=\"small\" severity=\"secondary\" />\n </MFlex>\n</template>",
9732
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MFlex } from 'morya-ui'\n</script>\n\n<template>\n <MFlex vertical>\n <MButton label=\"Top\" size=\"small\" />\n <MButton label=\"Middle\" size=\"small\"/>\n <MButton label=\"Bottom\" size=\"small\"/>\n </MFlex>\n</template>",
9721
9733
  "locale": "en-US"
9722
9734
  },
9723
9735
  {
@@ -10385,7 +10397,7 @@
10385
10397
  "sectionId": "声明式-rules",
10386
10398
  "lang": "vue",
10387
10399
  "preview": true,
10388
- "code": "<script setup lang=\"ts\">\nimport type { FormInstance, FormRules } from 'morya-ui'\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInstance | null>(null)\nconst model = reactive({ name: '', email: '' })\nconst rules: FormRules = {\n name: { required: true, message: '请输入名称', trigger: ['blur', 'input'] },\n email: [\n { required: true, message: '请输入邮箱', trigger: 'blur' },\n { pattern: /.[^\\n\\r@\\u2028\\u2029]*@.+\\..+/, message: '邮箱格式不正确', trigger: 'blur' },\n ],\n}\n\nasync function onSubmit() {\n const { valid } = await formRef.value!.validate()\n if (!valid) return\n}\n</script>\n\n<template>\n <MForm\n ref=\"formRef\"\n :model=\"model\"\n :rules=\"rules\"\n label-position=\"top\"\n validate-on=\"submit\"\n style=\"max-width: 22rem\"\n @submit=\"onSubmit\"\n >\n <MFormItem label=\"名称\" name=\"name\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MFormItem label=\"邮箱\" name=\"email\" help=\"用于接收通知\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.email\" type=\"email\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton native-type=\"submit\" label=\"提交\" />\n </MForm>\n</template>",
10400
+ "code": "<script setup lang=\"ts\">\nimport type { FormInstance, FormRules } from 'morya-ui'\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInstance | null>(null)\nconst model = reactive({ name: '', email: '' })\nconst rules: FormRules = {\n name: { required: true, message: '请输入名称', trigger: ['blur', 'input'] },\n email: [\n { required: true, message: '请输入邮箱', trigger: 'blur' },\n { pattern: /.[^\\n\\r@\\u2028\\u2029]*@.+\\..+/, message: '邮箱格式不正确', trigger: 'blur' },\n ],\n}\n\nasync function onSubmit() {\n const { valid } = await formRef.value!.validate()\n if (!valid) return\n}\n</script>\n\n<template>\n <MForm\n ref=\"formRef\"\n :model=\"model\"\n :rules=\"rules\"\n label-position=\"top\"\n validate-on=\"submit\"\n style=\"max-width: 22rem\"\n @submit=\"onSubmit\"\n >\n <MFormItem label=\"名称\" name=\"name\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MFormItem label=\"邮箱\" name=\"email\" help=\"用于接收通知\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.email\" type=\"email\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton html-type=\"submit\" label=\"提交\"/>\n </MForm>\n</template>",
10389
10401
  "locale": "zh-CN"
10390
10402
  },
10391
10403
  {
@@ -10412,7 +10424,7 @@
10412
10424
  "sectionId": "回调校验-兼容",
10413
10425
  "lang": "vue",
10414
10426
  "preview": true,
10415
- "code": "<script setup lang=\"ts\">\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive } from 'vue'\n\nconst form = reactive({ name: '' })\n</script>\n\n<template>\n <MForm validate-on=\"submit\" style=\"max-width: 22rem\">\n <MFormItem\n label=\"名称\"\n name=\"name\"\n required\n :validate=\"() => (form.name.trim() ? undefined : '请输入名称')\"\n >\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"form.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton native-type=\"submit\" label=\"提交\" />\n </MForm>\n</template>",
10427
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive } from 'vue'\n\nconst form = reactive({ name: '' })\n</script>\n\n<template>\n <MForm validate-on=\"submit\" style=\"max-width: 22rem\">\n <MFormItem\n label=\"名称\"\n name=\"name\"\n required\n :validate=\"() => (form.name.trim() ? undefined : '请输入名称')\"\n >\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"form.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton html-type=\"submit\" label=\"提交\"/>\n </MForm>\n</template>",
10416
10428
  "locale": "zh-CN"
10417
10429
  },
10418
10430
  {
@@ -10448,7 +10460,7 @@
10448
10460
  "sectionId": "declarative-rules",
10449
10461
  "lang": "vue",
10450
10462
  "preview": true,
10451
- "code": "<script setup lang=\"ts\">\nimport type { FormInstance, FormRules } from 'morya-ui'\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInstance | null>(null)\nconst model = reactive({ name: '', email: '' })\nconst rules: FormRules = {\n name: { required: true, message: 'Enter a name', trigger: ['blur', 'input'] },\n email: [\n { required: true, message: 'Enter an email', trigger: 'blur' },\n { pattern: /.[^\\n\\r@\\u2028\\u2029]*@.+\\..+/, message: 'Enter a valid email', trigger: 'blur' },\n ],\n}\n\nasync function onSubmit() {\n const { valid } = await formRef.value!.validate()\n if (!valid) return\n}\n</script>\n\n<template>\n <MForm\n ref=\"formRef\"\n :model=\"model\"\n :rules=\"rules\"\n label-position=\"top\"\n validate-on=\"submit\"\n style=\"max-width: 22rem\"\n @submit=\"onSubmit\"\n >\n <MFormItem label=\"Name\" name=\"name\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MFormItem label=\"Email\" name=\"email\" help=\"Used for notifications\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.email\" type=\"email\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton native-type=\"submit\" label=\"Submit\" />\n </MForm>\n</template>",
10463
+ "code": "<script setup lang=\"ts\">\nimport type { FormInstance, FormRules } from 'morya-ui'\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInstance | null>(null)\nconst model = reactive({ name: '', email: '' })\nconst rules: FormRules = {\n name: { required: true, message: 'Enter a name', trigger: ['blur', 'input'] },\n email: [\n { required: true, message: 'Enter an email', trigger: 'blur' },\n { pattern: /.[^\\n\\r@\\u2028\\u2029]*@.+\\..+/, message: 'Enter a valid email', trigger: 'blur' },\n ],\n}\n\nasync function onSubmit() {\n const { valid } = await formRef.value!.validate()\n if (!valid) return\n}\n</script>\n\n<template>\n <MForm\n ref=\"formRef\"\n :model=\"model\"\n :rules=\"rules\"\n label-position=\"top\"\n validate-on=\"submit\"\n style=\"max-width: 22rem\"\n @submit=\"onSubmit\"\n >\n <MFormItem label=\"Name\" name=\"name\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MFormItem label=\"Email\" name=\"email\" help=\"Used for notifications\">\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"model.email\" type=\"email\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton html-type=\"submit\" label=\"Submit\"/>\n </MForm>\n</template>",
10452
10464
  "locale": "en-US"
10453
10465
  },
10454
10466
  {
@@ -10475,7 +10487,7 @@
10475
10487
  "sectionId": "callback-validation-compatible",
10476
10488
  "lang": "vue",
10477
10489
  "preview": true,
10478
- "code": "<script setup lang=\"ts\">\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive } from 'vue'\n\nconst form = reactive({ name: '' })\n</script>\n\n<template>\n <MForm validate-on=\"submit\" style=\"max-width: 22rem\">\n <MFormItem\n label=\"Name\"\n name=\"name\"\n required\n :validate=\"() => (form.name.trim() ? undefined : 'Enter a name')\"\n >\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"form.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton native-type=\"submit\" label=\"Submit\" />\n </MForm>\n</template>",
10490
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MForm, MFormItem, MInput } from 'morya-ui'\nimport { reactive } from 'vue'\n\nconst form = reactive({ name: '' })\n</script>\n\n<template>\n <MForm validate-on=\"submit\" style=\"max-width: 22rem\">\n <MFormItem\n label=\"Name\"\n name=\"name\"\n required\n :validate=\"() => (form.name.trim() ? undefined : 'Enter a name')\"\n >\n <template #default=\"{ id, invalid }\">\n <MInput :id=\"id\" v-model=\"form.name\" fluid :invalid=\"invalid\" />\n </template>\n </MFormItem>\n <MButton html-type=\"submit\" label=\"Submit\"/>\n </MForm>\n</template>",
10479
10491
  "locale": "en-US"
10480
10492
  },
10481
10493
  {
@@ -15804,7 +15816,7 @@
15804
15816
  "sectionId": "服务式调用",
15805
15817
  "lang": "vue",
15806
15818
  "preview": true,
15807
- "code": "<script setup lang=\"ts\">\nimport { MButton, useLoading } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst panel = ref<HTMLElement>()\nconst { open } = useLoading()\n\nfunction openRegion() {\n const instance = open({\n target: panel.value,\n text: '加载中',\n effect: 'wave',\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n\nfunction openFullscreen() {\n const instance = open({\n text: '正在提交',\n effect: 'aurora',\n lock: true,\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <div\n ref=\"panel\"\n class=\"min-h-32 rounded-md border border-solid border-[var(--m-color-border)] p-4\"\n >\n 可被服务盖住的区域\n </div>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"区域加载\" severity=\"secondary\" @click=\"openRegion\" />\n <MButton label=\"全屏加载\" @click=\"openFullscreen\" />\n </div>\n </div>\n</template>",
15819
+ "code": "<script setup lang=\"ts\">\nimport { MButton, useLoading } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst panel = ref<HTMLElement>()\nconst { open } = useLoading()\n\nfunction openRegion() {\n const instance = open({\n target: panel.value,\n text: '加载中',\n effect: 'wave',\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n\nfunction openFullscreen() {\n const instance = open({\n text: '正在提交',\n effect: 'aurora',\n lock: true,\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <div\n ref=\"panel\"\n class=\"min-h-32 rounded-md border border-solid border-[var(--m-color-border)] p-4\"\n >\n 可被服务盖住的区域\n </div>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"区域加载\" @click=\"openRegion\"/>\n <MButton label=\"全屏加载\" @click=\"openFullscreen\" />\n </div>\n </div>\n</template>",
15808
15820
  "locale": "zh-CN"
15809
15821
  },
15810
15822
  {
@@ -15867,7 +15879,7 @@
15867
15879
  "sectionId": "service",
15868
15880
  "lang": "vue",
15869
15881
  "preview": true,
15870
- "code": "<script setup lang=\"ts\">\nimport { MButton, useLoading } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst panel = ref<HTMLElement>()\nconst { open } = useLoading()\n\nfunction openRegion() {\n const instance = open({\n target: panel.value,\n text: 'Loading',\n effect: 'wave',\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n\nfunction openFullscreen() {\n const instance = open({\n text: 'Submitting',\n effect: 'aurora',\n lock: true,\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <div\n ref=\"panel\"\n class=\"min-h-32 rounded-md border border-solid border-[var(--m-color-border)] p-4\"\n >\n Region covered by the service\n </div>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Cover region\" severity=\"secondary\" @click=\"openRegion\" />\n <MButton label=\"Fullscreen\" @click=\"openFullscreen\" />\n </div>\n </div>\n</template>",
15882
+ "code": "<script setup lang=\"ts\">\nimport { MButton, useLoading } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst panel = ref<HTMLElement>()\nconst { open } = useLoading()\n\nfunction openRegion() {\n const instance = open({\n target: panel.value,\n text: 'Loading',\n effect: 'wave',\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n\nfunction openFullscreen() {\n const instance = open({\n text: 'Submitting',\n effect: 'aurora',\n lock: true,\n })\n window.setTimeout(() => instance.close(), 1600)\n}\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <div\n ref=\"panel\"\n class=\"min-h-32 rounded-md border border-solid border-[var(--m-color-border)] p-4\"\n >\n Region covered by the service\n </div>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Cover region\" @click=\"openRegion\"/>\n <MButton label=\"Fullscreen\" @click=\"openFullscreen\" />\n </div>\n </div>\n</template>",
15871
15883
  "locale": "en-US"
15872
15884
  },
15873
15885
  {
@@ -17407,7 +17419,7 @@
17407
17419
  "sectionId": "api",
17408
17420
  "lang": "vue",
17409
17421
  "preview": true,
17410
- "code": "<script setup lang=\"ts\">\nimport { MButton, message } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Success\" severity=\"success\" @click=\"message.success('保存成功')\" />\n <MButton label=\"Info\" severity=\"info\" @click=\"message.info('这是一条提示')\" />\n <MButton label=\"Warn\" severity=\"warn\" @click=\"message.warn('请核对后再提交')\" />\n <MButton label=\"Error\" severity=\"danger\" @click=\"message.error('请求失败,请重试')\" />\n <MButton\n label=\"Closable\"\n @click=\"message.info({ content: '可手动关闭', closable: true, life: 0 })\"\n />\n </div>\n</template>",
17422
+ "code": "<script setup lang=\"ts\">\nimport { MButton, message } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Success\" @click=\"message.success('保存成功')\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"message.info('这是一条提示')\" color=\"info\" variant=\"solid\"/>\n <MButton label=\"Warn\" @click=\"message.warn('请核对后再提交')\" color=\"warning\" variant=\"solid\"/>\n <MButton label=\"Error\" @click=\"message.error('请求失败,请重试')\" danger type=\"primary\"/>\n <MButton\n label=\"Closable\"\n @click=\"message.info({ content: '可手动关闭', closable: true, life: 0 })\"\n />\n </div>\n</template>",
17411
17423
  "locale": "zh-CN"
17412
17424
  },
17413
17425
  {
@@ -17452,7 +17464,7 @@
17452
17464
  "sectionId": "api",
17453
17465
  "lang": "vue",
17454
17466
  "preview": true,
17455
- "code": "<script setup lang=\"ts\">\nimport { MButton, message } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Success\" severity=\"success\" @click=\"message.success('Saved')\" />\n <MButton label=\"Info\" severity=\"info\" @click=\"message.info('A short tip')\" />\n <MButton label=\"Warn\" severity=\"warn\" @click=\"message.warn('Please double-check')\" />\n <MButton label=\"Error\" severity=\"danger\" @click=\"message.error('Request failed')\" />\n <MButton\n label=\"Closable\"\n @click=\"message.info({ content: 'Dismiss manually', closable: true, life: 0 })\"\n />\n </div>\n</template>",
17467
+ "code": "<script setup lang=\"ts\">\nimport { MButton, message } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3\">\n <MButton label=\"Success\" @click=\"message.success('Saved')\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"message.info('A short tip')\" color=\"info\" variant=\"solid\"/>\n <MButton label=\"Warn\" @click=\"message.warn('Please double-check')\" color=\"warning\" variant=\"solid\"/>\n <MButton label=\"Error\" @click=\"message.error('Request failed')\" danger type=\"primary\"/>\n <MButton\n label=\"Closable\"\n @click=\"message.info({ content: 'Dismiss manually', closable: true, life: 0 })\"\n />\n </div>\n</template>",
17456
17468
  "locale": "en-US"
17457
17469
  },
17458
17470
  {
@@ -18149,7 +18161,7 @@
18149
18161
  "sectionId": "列表页组合",
18150
18162
  "lang": "vue",
18151
18163
  "preview": true,
18152
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilters,\n MPageHeader,\n MPageToolbar,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst keyword = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"用户管理\" description=\"维护账号与角色。\">\n <template #actions>\n <MButton severity=\"primary\">\n 新建\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters aria-label=\"筛选\" variant=\"filled\">\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"搜索\" clearable class=\"w-48\" />\n </MSpace>\n <template #actions>\n <MButton severity=\"secondary\">\n 查询\n </MButton>\n </template>\n </MPageFilters>\n <MPageToolbar>\n <span style=\"color:var(--m-color-text-muted);font-size:var(--m-font-size-sm)\">已选 0 项</span>\n <template #actions>\n <MButton severity=\"secondary\" text>\n 导出\n </MButton>\n <MButton severity=\"danger\" text>\n 删除\n </MButton>\n </template>\n </MPageToolbar>\n </MPageContent>\n </div>\n</template>",
18164
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilters,\n MPageHeader,\n MPageToolbar,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst keyword = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"用户管理\" description=\"维护账号与角色。\">\n <template #actions>\n <MButton type=\"primary\">\n 新建\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters aria-label=\"筛选\" variant=\"filled\">\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"搜索\" clearable class=\"w-48\" />\n </MSpace>\n <template #actions>\n <MButton>\n 查询\n </MButton>\n </template>\n </MPageFilters>\n <MPageToolbar>\n <span style=\"color:var(--m-color-text-muted);font-size:var(--m-font-size-sm)\">已选 0 项</span>\n <template #actions>\n <MButton type=\"text\">\n 导出\n </MButton>\n <MButton type=\"text\" danger>\n 删除\n </MButton>\n </template>\n </MPageToolbar>\n </MPageContent>\n </div>\n</template>",
18153
18165
  "locale": "zh-CN"
18154
18166
  },
18155
18167
  {
@@ -18158,7 +18170,7 @@
18158
18170
  "sectionId": "列表页组合",
18159
18171
  "lang": "vue",
18160
18172
  "preview": true,
18161
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilterChips,\n MPageFilters,\n MPageHeader,\n MSelect,\n MSpace,\n MTag,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst keyword = ref('')\nconst status = ref<string | null>('active')\nconst filtersExpanded = ref(false)\nconst department = ref<string | null>(null)\n\nconst activeFilters = computed(() => {\n const items: Array<{ key: string; label: string }> = []\n if (keyword.value.trim()) {\n items.push({ key: 'keyword', label: `关键词:${keyword.value.trim()}` })\n }\n if (status.value && status.value !== 'all') {\n items.push({ key: 'status', label: `状态:${status.value === 'active' ? '启用' : '停用'}` })\n }\n if (department.value) {\n items.push({ key: 'department', label: `部门:${department.value}` })\n }\n return items\n})\n\nfunction clearFilter(key: string) {\n if (key === 'keyword') keyword.value = ''\n if (key === 'status') status.value = 'all'\n if (key === 'department') department.value = null\n}\n\nfunction resetAll() {\n keyword.value = ''\n status.value = 'all'\n department.value = null\n}\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"用户管理\" description=\"折叠高级筛选(chevron + 收起),查询/重置放 #actions。\">\n <template #actions>\n <MButton severity=\"primary\">\n 新建\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters\n v-model:expanded=\"filtersExpanded\"\n aria-label=\"筛选\"\n variant=\"filled\"\n collapsible\n >\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"搜索名称\" clearable style=\"width: 14rem\" />\n <MSelect\n v-model=\"status\"\n :options=\"[\n { label: '全部', value: 'all' },\n { label: '启用', value: 'active' },\n { label: '停用', value: 'inactive' },\n ]\"\n placeholder=\"状态\"\n style=\"width: 10rem\"\n />\n </MSpace>\n <template #actions>\n <MButton severity=\"secondary\">\n 查询\n </MButton>\n <MButton severity=\"secondary\" text @click=\"resetAll\">\n 重置\n </MButton>\n </template>\n <template #advanced>\n <MSpace wrap>\n <MSelect\n v-model=\"department\"\n :options=\"[\n { label: '研发', value: '研发' },\n { label: '运营', value: '运营' },\n ]\"\n placeholder=\"部门\"\n clearable\n style=\"width: 10rem\"\n />\n </MSpace>\n </template>\n </MPageFilters>\n <MPageFilterChips v-if=\"activeFilters.length\" label=\"已选\" aria-label=\"已选筛选\">\n <MTag\n v-for=\"item in activeFilters\"\n :key=\"item.key\"\n :value=\"item.label\"\n size=\"small\"\n bordered\n closable\n @close=\"clearFilter(item.key)\"\n />\n </MPageFilterChips>\n </MPageContent>\n </div>\n</template>",
18173
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilterChips,\n MPageFilters,\n MPageHeader,\n MSelect,\n MSpace,\n MTag,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst keyword = ref('')\nconst status = ref<string | null>('active')\nconst filtersExpanded = ref(false)\nconst department = ref<string | null>(null)\n\nconst activeFilters = computed(() => {\n const items: Array<{ key: string; label: string }> = []\n if (keyword.value.trim()) {\n items.push({ key: 'keyword', label: `关键词:${keyword.value.trim()}` })\n }\n if (status.value && status.value !== 'all') {\n items.push({ key: 'status', label: `状态:${status.value === 'active' ? '启用' : '停用'}` })\n }\n if (department.value) {\n items.push({ key: 'department', label: `部门:${department.value}` })\n }\n return items\n})\n\nfunction clearFilter(key: string) {\n if (key === 'keyword') keyword.value = ''\n if (key === 'status') status.value = 'all'\n if (key === 'department') department.value = null\n}\n\nfunction resetAll() {\n keyword.value = ''\n status.value = 'all'\n department.value = null\n}\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"用户管理\" description=\"折叠高级筛选(chevron + 收起),查询/重置放 #actions。\">\n <template #actions>\n <MButton type=\"primary\">\n 新建\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters\n v-model:expanded=\"filtersExpanded\"\n aria-label=\"筛选\"\n variant=\"filled\"\n collapsible\n >\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"搜索名称\" clearable style=\"width: 14rem\" />\n <MSelect\n v-model=\"status\"\n :options=\"[\n { label: '全部', value: 'all' },\n { label: '启用', value: 'active' },\n { label: '停用', value: 'inactive' },\n ]\"\n placeholder=\"状态\"\n style=\"width: 10rem\"\n />\n </MSpace>\n <template #actions>\n <MButton>\n 查询\n </MButton>\n <MButton @click=\"resetAll\" type=\"text\">\n 重置\n </MButton>\n </template>\n <template #advanced>\n <MSpace wrap>\n <MSelect\n v-model=\"department\"\n :options=\"[\n { label: '研发', value: '研发' },\n { label: '运营', value: '运营' },\n ]\"\n placeholder=\"部门\"\n clearable\n style=\"width: 10rem\"\n />\n </MSpace>\n </template>\n </MPageFilters>\n <MPageFilterChips v-if=\"activeFilters.length\" label=\"已选\" aria-label=\"已选筛选\">\n <MTag\n v-for=\"item in activeFilters\"\n :key=\"item.key\"\n :value=\"item.label\"\n size=\"small\"\n bordered\n closable\n @close=\"clearFilter(item.key)\"\n />\n </MPageFilterChips>\n </MPageContent>\n </div>\n</template>",
18162
18174
  "locale": "zh-CN"
18163
18175
  },
18164
18176
  {
@@ -18167,7 +18179,7 @@
18167
18179
  "sectionId": "表单页组合",
18168
18180
  "lang": "vue",
18169
18181
  "preview": true,
18170
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MForm,\n MFormItem,\n MInput,\n MPageContent,\n MPageHeader,\n MPageSection,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst name = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden;background:var(--m-color-surface)\"\n >\n <MPageContent width=\"narrow\">\n <MPageHeader title=\"新建用户\" description=\"填写基本信息。\" />\n <MPageSection variant=\"form\">\n <MForm @submit.prevent>\n <MFormItem label=\"姓名\" name=\"name\">\n <MInput v-model=\"name\" fluid />\n </MFormItem>\n <MPageSection variant=\"actions\">\n <MSpace>\n <MButton native-type=\"submit\" severity=\"primary\">\n 保存\n </MButton>\n <MButton severity=\"secondary\">\n 取消\n </MButton>\n </MSpace>\n </MPageSection>\n </MForm>\n </MPageSection>\n </MPageContent>\n </div>\n</template>",
18182
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MForm,\n MFormItem,\n MInput,\n MPageContent,\n MPageHeader,\n MPageSection,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst name = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:hidden;background:var(--m-color-surface)\"\n >\n <MPageContent width=\"narrow\">\n <MPageHeader title=\"新建用户\" description=\"填写基本信息。\" />\n <MPageSection variant=\"form\">\n <MForm @submit.prevent>\n <MFormItem label=\"姓名\" name=\"name\">\n <MInput v-model=\"name\" fluid />\n </MFormItem>\n <MPageSection variant=\"actions\">\n <MSpace>\n <MButton html-type=\"submit\">\n 保存\n </MButton>\n <MButton>\n 取消\n </MButton>\n </MSpace>\n </MPageSection>\n </MForm>\n </MPageSection>\n </MPageContent>\n </div>\n</template>",
18171
18183
  "locale": "zh-CN"
18172
18184
  },
18173
18185
  {
@@ -18203,7 +18215,7 @@
18203
18215
  "sectionId": "list-page-stack",
18204
18216
  "lang": "vue",
18205
18217
  "preview": true,
18206
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilters,\n MPageHeader,\n MPageToolbar,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst keyword = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"Users\" description=\"Manage accounts and roles.\">\n <template #actions>\n <MButton severity=\"primary\">\n Create\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters aria-label=\"Filters\" variant=\"filled\">\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"Search\" clearable class=\"w-48\" />\n </MSpace>\n <template #actions>\n <MButton severity=\"secondary\">\n Search\n </MButton>\n </template>\n </MPageFilters>\n <MPageToolbar>\n <span style=\"color:var(--m-color-text-muted);font-size:var(--m-font-size-sm)\">0 selected</span>\n <template #actions>\n <MButton severity=\"secondary\" text>\n Export\n </MButton>\n <MButton severity=\"danger\" text>\n Delete\n </MButton>\n </template>\n </MPageToolbar>\n </MPageContent>\n </div>\n</template>",
18218
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilters,\n MPageHeader,\n MPageToolbar,\n MSpace,\n} from 'morya-ui'\nimport { ref } from 'vue'\n\nconst keyword = ref('')\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"Users\" description=\"Manage accounts and roles.\">\n <template #actions>\n <MButton type=\"primary\">\n Create\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters aria-label=\"Filters\" variant=\"filled\">\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"Search\" clearable class=\"w-48\" />\n </MSpace>\n <template #actions>\n <MButton>\n Search\n </MButton>\n </template>\n </MPageFilters>\n <MPageToolbar>\n <span style=\"color:var(--m-color-text-muted);font-size:var(--m-font-size-sm)\">0 selected</span>\n <template #actions>\n <MButton type=\"text\">\n Export\n </MButton>\n <MButton type=\"text\" danger>\n Delete\n </MButton>\n </template>\n </MPageToolbar>\n </MPageContent>\n </div>\n</template>",
18207
18219
  "locale": "en-US"
18208
18220
  },
18209
18221
  {
@@ -18212,7 +18224,7 @@
18212
18224
  "sectionId": "list-page-stack",
18213
18225
  "lang": "vue",
18214
18226
  "preview": true,
18215
- "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilterChips,\n MPageFilters,\n MPageHeader,\n MSelect,\n MSpace,\n MTag,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst keyword = ref('')\nconst status = ref<string | null>('active')\nconst filtersExpanded = ref(false)\nconst department = ref<string | null>(null)\n\nconst activeFilters = computed(() => {\n const items: Array<{ key: string; label: string }> = []\n if (keyword.value.trim()) {\n items.push({ key: 'keyword', label: `Keyword: ${keyword.value.trim()}` })\n }\n if (status.value && status.value !== 'all') {\n items.push({\n key: 'status',\n label: `Status: ${status.value === 'active' ? 'Active' : 'Inactive'}`,\n })\n }\n if (department.value) {\n items.push({ key: 'department', label: `Department: ${department.value}` })\n }\n return items\n})\n\nfunction clearFilter(key: string) {\n if (key === 'keyword') keyword.value = ''\n if (key === 'status') status.value = 'all'\n if (key === 'department') department.value = null\n}\n\nfunction resetAll() {\n keyword.value = ''\n status.value = 'all'\n department.value = null\n}\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"Users\" description=\"Collapsible advanced filters (chevron + Collapse); query/reset in #actions.\">\n <template #actions>\n <MButton severity=\"primary\">\n Create\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters\n v-model:expanded=\"filtersExpanded\"\n aria-label=\"Filters\"\n variant=\"filled\"\n collapsible\n >\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"Search name\" clearable style=\"width: 14rem\" />\n <MSelect\n v-model=\"status\"\n :options=\"[\n { label: 'All', value: 'all' },\n { label: 'Active', value: 'active' },\n { label: 'Inactive', value: 'inactive' },\n ]\"\n placeholder=\"Status\"\n style=\"width: 10rem\"\n />\n </MSpace>\n <template #actions>\n <MButton severity=\"secondary\">\n Search\n </MButton>\n <MButton severity=\"secondary\" text @click=\"resetAll\">\n Reset\n </MButton>\n </template>\n <template #advanced>\n <MSpace wrap>\n <MSelect\n v-model=\"department\"\n :options=\"[\n { label: 'Engineering', value: 'Engineering' },\n { label: 'Operations', value: 'Operations' },\n ]\"\n placeholder=\"Department\"\n clearable\n style=\"width: 10rem\"\n />\n </MSpace>\n </template>\n </MPageFilters>\n <MPageFilterChips v-if=\"activeFilters.length\" label=\"Active\" aria-label=\"Active filters\">\n <MTag\n v-for=\"item in activeFilters\"\n :key=\"item.key\"\n :value=\"item.label\"\n size=\"small\"\n bordered\n closable\n @close=\"clearFilter(item.key)\"\n />\n </MPageFilterChips>\n </MPageContent>\n </div>\n</template>",
18227
+ "code": "<script setup lang=\"ts\">\nimport {\n MButton,\n MInput,\n MPageContent,\n MPageFilterChips,\n MPageFilters,\n MPageHeader,\n MSelect,\n MSpace,\n MTag,\n} from 'morya-ui'\nimport { computed, ref } from 'vue'\n\nconst keyword = ref('')\nconst status = ref<string | null>('active')\nconst filtersExpanded = ref(false)\nconst department = ref<string | null>(null)\n\nconst activeFilters = computed(() => {\n const items: Array<{ key: string; label: string }> = []\n if (keyword.value.trim()) {\n items.push({ key: 'keyword', label: `Keyword: ${keyword.value.trim()}` })\n }\n if (status.value && status.value !== 'all') {\n items.push({\n key: 'status',\n label: `Status: ${status.value === 'active' ? 'Active' : 'Inactive'}`,\n })\n }\n if (department.value) {\n items.push({ key: 'department', label: `Department: ${department.value}` })\n }\n return items\n})\n\nfunction clearFilter(key: string) {\n if (key === 'keyword') keyword.value = ''\n if (key === 'status') status.value = 'all'\n if (key === 'department') department.value = null\n}\n\nfunction resetAll() {\n keyword.value = ''\n status.value = 'all'\n department.value = null\n}\n</script>\n\n<template>\n <div\n class=\"doc-demo-frame\"\n style=\"border:1px solid var(--m-color-border);border-radius:var(--m-radius-md);overflow:visible;background:var(--m-color-surface)\"\n >\n <MPageContent>\n <MPageHeader title=\"Users\" description=\"Collapsible advanced filters (chevron + Collapse); query/reset in #actions.\">\n <template #actions>\n <MButton type=\"primary\">\n Create\n </MButton>\n </template>\n </MPageHeader>\n <MPageFilters\n v-model:expanded=\"filtersExpanded\"\n aria-label=\"Filters\"\n variant=\"filled\"\n collapsible\n >\n <MSpace wrap>\n <MInput v-model=\"keyword\" placeholder=\"Search name\" clearable style=\"width: 14rem\" />\n <MSelect\n v-model=\"status\"\n :options=\"[\n { label: 'All', value: 'all' },\n { label: 'Active', value: 'active' },\n { label: 'Inactive', value: 'inactive' },\n ]\"\n placeholder=\"Status\"\n style=\"width: 10rem\"\n />\n </MSpace>\n <template #actions>\n <MButton>\n Search\n </MButton>\n <MButton @click=\"resetAll\" type=\"text\">\n Reset\n </MButton>\n </template>\n <template #advanced>\n <MSpace wrap>\n <MSelect\n v-model=\"department\"\n :options=\"[\n { label: 'Engineering', value: 'Engineering' },\n { label: 'Operations', value: 'Operations' },\n ]\"\n placeholder=\"Department\"\n clearable\n style=\"width: 10rem\"\n />\n </MSpace>\n </template>\n </MPageFilters>\n <MPageFilterChips v-if=\"activeFilters.length\" label=\"Active\" aria-label=\"Active filters\">\n <MTag\n v-for=\"item in activeFilters\"\n :key=\"item.key\"\n :value=\"item.label\"\n size=\"small\"\n bordered\n closable\n @close=\"clearFilter(item.key)\"\n />\n </MPageFilterChips>\n </MPageContent>\n </div>\n</template>",
18216
18228
  "locale": "en-US"
18217
18229
  },
18218
18230
  {
@@ -19182,7 +19194,7 @@
19182
19194
  "sectionId": "placement",
19183
19195
  "lang": "vue",
19184
19196
  "preview": true,
19185
- "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div style=\"display:flex;justify-content:center;padding:2rem\">\n <MPopover v-model=\"open\" placement=\"bottom-start\">\n <MButton label=\"bottom-start\" severity=\"secondary\" @click=\"open = !open\" />\n <template #content>\n <p style=\"margin:0\">\n Aligned to the start of the trigger.\n </p>\n </template>\n </MPopover>\n </div>\n</template>",
19197
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div style=\"display:flex;justify-content:center;padding:2rem\">\n <MPopover v-model=\"open\" placement=\"bottom-start\">\n <MButton label=\"bottom-start\" @click=\"open = !open\"/>\n <template #content>\n <p style=\"margin:0\">\n Aligned to the start of the trigger.\n </p>\n </template>\n </MPopover>\n </div>\n</template>",
19186
19198
  "locale": "zh-CN"
19187
19199
  },
19188
19200
  {
@@ -19191,7 +19203,7 @@
19191
19203
  "sectionId": "hover",
19192
19204
  "lang": "vue",
19193
19205
  "preview": true,
19194
- "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <MPopover v-model=\"open\" trigger=\"hover\" :show-delay=\"80\" :hide-delay=\"120\">\n <MButton label=\"Hover me\" severity=\"secondary\" />\n <template #content>\n <p style=\"margin:0\">\n Opens on hover.\n </p>\n </template>\n </MPopover>\n</template>",
19206
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <MPopover v-model=\"open\" trigger=\"hover\" :show-delay=\"80\" :hide-delay=\"120\">\n <MButton label=\"Hover me\"/>\n <template #content>\n <p style=\"margin:0\">\n Opens on hover.\n </p>\n </template>\n </MPopover>\n</template>",
19195
19207
  "locale": "zh-CN"
19196
19208
  },
19197
19209
  {
@@ -19218,7 +19230,7 @@
19218
19230
  "sectionId": "placement",
19219
19231
  "lang": "vue",
19220
19232
  "preview": true,
19221
- "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div style=\"display:flex;justify-content:center;padding:2rem\">\n <MPopover v-model=\"open\" placement=\"bottom-start\">\n <MButton label=\"bottom-start\" severity=\"secondary\" @click=\"open = !open\" />\n <template #content>\n <p style=\"margin:0\">\n Aligned to the start of the trigger.\n </p>\n </template>\n </MPopover>\n </div>\n</template>",
19233
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <div style=\"display:flex;justify-content:center;padding:2rem\">\n <MPopover v-model=\"open\" placement=\"bottom-start\">\n <MButton label=\"bottom-start\" @click=\"open = !open\"/>\n <template #content>\n <p style=\"margin:0\">\n Aligned to the start of the trigger.\n </p>\n </template>\n </MPopover>\n </div>\n</template>",
19222
19234
  "locale": "en-US"
19223
19235
  },
19224
19236
  {
@@ -19227,7 +19239,7 @@
19227
19239
  "sectionId": "hover",
19228
19240
  "lang": "vue",
19229
19241
  "preview": true,
19230
- "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <MPopover v-model=\"open\" trigger=\"hover\" :show-delay=\"80\" :hide-delay=\"120\">\n <MButton label=\"Hover me\" severity=\"secondary\" />\n <template #content>\n <p style=\"margin:0\">\n Opens on hover.\n </p>\n </template>\n </MPopover>\n</template>",
19242
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MPopover } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst open = ref(false)\n</script>\n\n<template>\n <MPopover v-model=\"open\" trigger=\"hover\" :show-delay=\"80\" :hide-delay=\"120\">\n <MButton label=\"Hover me\"/>\n <template #content>\n <p style=\"margin:0\">\n Opens on hover.\n </p>\n </template>\n </MPopover>\n</template>",
19231
19243
  "locale": "en-US"
19232
19244
  }
19233
19245
  ],
@@ -20619,7 +20631,7 @@
20619
20631
  "sectionId": "操作区",
20620
20632
  "lang": "vue",
20621
20633
  "preview": true,
20622
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"success\" description=\"订单已创建,可在列表中查看详情。\">\n <template #footer>\n <MButton label=\"查看订单\" />\n <MButton label=\"返回首页\" severity=\"secondary\" text />\n </template>\n </MResult>\n <MResult status=\"error\" description=\"请检查网络后重试,或联系管理员。\">\n <template #footer>\n <MButton label=\"重试\" />\n </template>\n </MResult>\n </div>\n</template>",
20634
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"success\" description=\"订单已创建,可在列表中查看详情。\">\n <template #footer>\n <MButton label=\"查看订单\" />\n <MButton label=\"返回首页\" type=\"text\"/>\n </template>\n </MResult>\n <MResult status=\"error\" description=\"请检查网络后重试,或联系管理员。\">\n <template #footer>\n <MButton label=\"重试\" />\n </template>\n </MResult>\n </div>\n</template>",
20623
20635
  "locale": "zh-CN"
20624
20636
  },
20625
20637
  {
@@ -20628,7 +20640,7 @@
20628
20640
  "sectionId": "http-类状态",
20629
20641
  "lang": "vue",
20630
20642
  "preview": true,
20631
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"403\" description=\"你没有访问该资源的权限。\">\n <template #footer>\n <MButton label=\"返回\" severity=\"secondary\" />\n </template>\n </MResult>\n <MResult status=\"404\" description=\"页面不存在或已被移除。\" />\n <MResult status=\"500\" description=\"服务暂时不可用,请稍后再试。\" />\n <MResult :status=\"('418' as any)\" description=\"服务器拒绝泡茶请求。\" />\n </div>\n</template>",
20643
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"403\" description=\"你没有访问该资源的权限。\">\n <template #footer>\n <MButton label=\"返回\"/>\n </template>\n </MResult>\n <MResult status=\"404\" description=\"页面不存在或已被移除。\" />\n <MResult status=\"500\" description=\"服务暂时不可用,请稍后再试。\" />\n <MResult :status=\"('418' as any)\" description=\"服务器拒绝泡茶请求。\" />\n </div>\n</template>",
20632
20644
  "locale": "zh-CN"
20633
20645
  },
20634
20646
  {
@@ -20637,7 +20649,7 @@
20637
20649
  "sectionId": "尺寸",
20638
20650
  "lang": "vue",
20639
20651
  "preview": true,
20640
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-6\" style=\"grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\">\n <MResult\n size=\"small\"\n status=\"success\"\n title=\"保存成功\"\n >\n <template #footer>\n <MButton\n label=\"知道了\"\n size=\"small\"\n severity=\"secondary\"\n />\n </template>\n </MResult>\n <MResult\n size=\"small\"\n status=\"error\"\n title=\"上传失败\"\n >\n <template #footer>\n <MButton\n label=\"重试\"\n size=\"small\"\n />\n </template>\n </MResult>\n </div>\n</template>",
20652
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-6\" style=\"grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\">\n <MResult\n size=\"small\"\n status=\"success\"\n title=\"保存成功\"\n >\n <template #footer>\n <MButton label=\"知道了\" size=\"small\"/>\n </template>\n </MResult>\n <MResult\n size=\"small\"\n status=\"error\"\n title=\"上传失败\"\n >\n <template #footer>\n <MButton\n label=\"重试\"\n size=\"small\"\n />\n </template>\n </MResult>\n </div>\n</template>",
20641
20653
  "locale": "zh-CN"
20642
20654
  },
20643
20655
  {
@@ -20664,7 +20676,7 @@
20664
20676
  "sectionId": "actions",
20665
20677
  "lang": "vue",
20666
20678
  "preview": true,
20667
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"success\" description=\"Your order was created. You can review it in the list.\">\n <template #footer>\n <MButton label=\"View order\" />\n <MButton label=\"Back home\" severity=\"secondary\" text />\n </template>\n </MResult>\n <MResult status=\"error\" description=\"Check your network and try again, or contact an admin.\">\n <template #footer>\n <MButton label=\"Retry\" />\n </template>\n </MResult>\n </div>\n</template>",
20679
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"success\" description=\"Your order was created. You can review it in the list.\">\n <template #footer>\n <MButton label=\"View order\" />\n <MButton label=\"Back home\" type=\"text\"/>\n </template>\n </MResult>\n <MResult status=\"error\" description=\"Check your network and try again, or contact an admin.\">\n <template #footer>\n <MButton label=\"Retry\" />\n </template>\n </MResult>\n </div>\n</template>",
20668
20680
  "locale": "en-US"
20669
20681
  },
20670
20682
  {
@@ -20673,7 +20685,7 @@
20673
20685
  "sectionId": "http-statuses",
20674
20686
  "lang": "vue",
20675
20687
  "preview": true,
20676
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"403\" description=\"You do not have permission to access this resource.\">\n <template #footer>\n <MButton label=\"Go back\" severity=\"secondary\" />\n </template>\n </MResult>\n <MResult status=\"404\" description=\"This page does not exist or was removed.\" />\n <MResult status=\"500\" description=\"The service is temporarily unavailable. Try again later.\" />\n <MResult :status=\"('418' as any)\" description=\"The server refuses to brew coffee.\" />\n </div>\n</template>",
20688
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-8\">\n <MResult status=\"403\" description=\"You do not have permission to access this resource.\">\n <template #footer>\n <MButton label=\"Go back\"/>\n </template>\n </MResult>\n <MResult status=\"404\" description=\"This page does not exist or was removed.\" />\n <MResult status=\"500\" description=\"The service is temporarily unavailable. Try again later.\" />\n <MResult :status=\"('418' as any)\" description=\"The server refuses to brew coffee.\" />\n </div>\n</template>",
20677
20689
  "locale": "en-US"
20678
20690
  },
20679
20691
  {
@@ -20682,7 +20694,7 @@
20682
20694
  "sectionId": "size",
20683
20695
  "lang": "vue",
20684
20696
  "preview": true,
20685
- "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-6\" style=\"grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\">\n <MResult\n size=\"small\"\n status=\"success\"\n title=\"Saved\"\n >\n <template #footer>\n <MButton\n label=\"OK\"\n size=\"small\"\n severity=\"secondary\"\n />\n </template>\n </MResult>\n <MResult\n size=\"small\"\n status=\"error\"\n title=\"Upload failed\"\n >\n <template #footer>\n <MButton\n label=\"Retry\"\n size=\"small\"\n />\n </template>\n </MResult>\n </div>\n</template>",
20697
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MResult } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-6\" style=\"grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\">\n <MResult\n size=\"small\"\n status=\"success\"\n title=\"Saved\"\n >\n <template #footer>\n <MButton label=\"OK\" size=\"small\"/>\n </template>\n </MResult>\n <MResult\n size=\"small\"\n status=\"error\"\n title=\"Upload failed\"\n >\n <template #footer>\n <MButton\n label=\"Retry\"\n size=\"small\"\n />\n </template>\n </MResult>\n </div>\n</template>",
20686
20698
  "locale": "en-US"
20687
20699
  }
20688
20700
  ],
@@ -21030,7 +21042,7 @@
21030
21042
  "sectionId": "max-height",
21031
21043
  "lang": "vue",
21032
21044
  "preview": true,
21033
- "code": "<script setup lang=\"ts\">\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst count = ref(3)\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;gap:0.5rem\">\n <MButton label=\"Add\" size=\"small\" @click=\"count++\" />\n <MButton label=\"Remove\" severity=\"secondary\" size=\"small\" @click=\"count = Math.max(0, count - 1)\" />\n </div>\n <MScrollbar max-height=\"220px\" always class=\"w-full\">\n <p\n v-for=\"item in count\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-info) 12%, transparent);\n color:var(--m-color-info);\n \"\n >\n Item {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21045
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst count = ref(3)\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;gap:0.5rem\">\n <MButton label=\"Add\" size=\"small\" @click=\"count++\" />\n <MButton label=\"Remove\" size=\"small\" @click=\"count = Math.max(0, count - 1)\"/>\n </div>\n <MScrollbar max-height=\"220px\" always class=\"w-full\">\n <p\n v-for=\"item in count\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-info) 12%, transparent);\n color:var(--m-color-info);\n \"\n >\n Item {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21034
21046
  "locale": "zh-CN"
21035
21047
  },
21036
21048
  {
@@ -21057,7 +21069,7 @@
21057
21069
  "sectionId": "manual-scroll",
21058
21070
  "lang": "vue",
21059
21071
  "preview": true,
21060
- "code": "<script setup lang=\"ts\">\nimport type { ScrollbarInstance } from 'morya-ui'\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst scrollbarRef = ref<ScrollbarInstance>()\nconst scrollTop = ref(0)\n\nfunction jump(top: number) {\n scrollbarRef.value?.setScrollTop(top)\n}\n\nfunction onScroll(payload: { scrollTop: number }) {\n scrollTop.value = Math.round(payload.scrollTop)\n}\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center\">\n <MButton label=\"Top\" size=\"small\" @click=\"jump(0)\" />\n <MButton label=\"Mid\" size=\"small\" severity=\"secondary\" @click=\"jump(200)\" />\n <MButton label=\"Bottom\" size=\"small\" severity=\"secondary\" @click=\"jump(9999)\" />\n <span style=\"color:var(--m-color-text-muted);font-size:0.875rem\">scrollTop: {{ scrollTop }}</span>\n </div>\n <MScrollbar ref=\"scrollbarRef\" height=\"200px\" style=\"width: 200px\" always @scroll=\"onScroll\">\n <p\n v-for=\"item in 24\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-success) 12%, transparent);\n color:var(--m-color-success);\n \"\n >\n {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21072
+ "code": "<script setup lang=\"ts\">\nimport type { ScrollbarInstance } from 'morya-ui'\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst scrollbarRef = ref<ScrollbarInstance>()\nconst scrollTop = ref(0)\n\nfunction jump(top: number) {\n scrollbarRef.value?.setScrollTop(top)\n}\n\nfunction onScroll(payload: { scrollTop: number }) {\n scrollTop.value = Math.round(payload.scrollTop)\n}\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center\">\n <MButton label=\"Top\" size=\"small\" @click=\"jump(0)\" />\n <MButton label=\"Mid\" size=\"small\" @click=\"jump(200)\"/>\n <MButton label=\"Bottom\" size=\"small\" @click=\"jump(9999)\"/>\n <span style=\"color:var(--m-color-text-muted);font-size:0.875rem\">scrollTop: {{ scrollTop }}</span>\n </div>\n <MScrollbar ref=\"scrollbarRef\" height=\"200px\" style=\"width: 200px\" always @scroll=\"onScroll\">\n <p\n v-for=\"item in 24\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-success) 12%, transparent);\n color:var(--m-color-success);\n \"\n >\n {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21061
21073
  "locale": "zh-CN"
21062
21074
  },
21063
21075
  {
@@ -21111,7 +21123,7 @@
21111
21123
  "sectionId": "max-height",
21112
21124
  "lang": "vue",
21113
21125
  "preview": true,
21114
- "code": "<script setup lang=\"ts\">\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst count = ref(3)\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;gap:0.5rem\">\n <MButton label=\"Add\" size=\"small\" @click=\"count++\" />\n <MButton label=\"Remove\" severity=\"secondary\" size=\"small\" @click=\"count = Math.max(0, count - 1)\" />\n </div>\n <MScrollbar max-height=\"220px\" always class=\"w-full\">\n <p\n v-for=\"item in count\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-info) 12%, transparent);\n color:var(--m-color-info);\n \"\n >\n Item {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21126
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst count = ref(3)\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;gap:0.5rem\">\n <MButton label=\"Add\" size=\"small\" @click=\"count++\" />\n <MButton label=\"Remove\" size=\"small\" @click=\"count = Math.max(0, count - 1)\"/>\n </div>\n <MScrollbar max-height=\"220px\" always class=\"w-full\">\n <p\n v-for=\"item in count\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-info) 12%, transparent);\n color:var(--m-color-info);\n \"\n >\n Item {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21115
21127
  "locale": "en-US"
21116
21128
  },
21117
21129
  {
@@ -21138,7 +21150,7 @@
21138
21150
  "sectionId": "manual-scroll",
21139
21151
  "lang": "vue",
21140
21152
  "preview": true,
21141
- "code": "<script setup lang=\"ts\">\nimport type { ScrollbarInstance } from 'morya-ui'\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst scrollbarRef = ref<ScrollbarInstance>()\nconst scrollTop = ref(0)\n\nfunction jump(top: number) {\n scrollbarRef.value?.setScrollTop(top)\n}\n\nfunction onScroll(payload: { scrollTop: number }) {\n scrollTop.value = Math.round(payload.scrollTop)\n}\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center\">\n <MButton label=\"Top\" size=\"small\" @click=\"jump(0)\" />\n <MButton label=\"Mid\" size=\"small\" severity=\"secondary\" @click=\"jump(200)\" />\n <MButton label=\"Bottom\" size=\"small\" severity=\"secondary\" @click=\"jump(9999)\" />\n <span style=\"color:var(--m-color-text-muted);font-size:0.875rem\">scrollTop: {{ scrollTop }}</span>\n </div>\n <MScrollbar ref=\"scrollbarRef\" height=\"200px\" always style=\"width: 200px\" @scroll=\"onScroll\">\n <p\n v-for=\"item in 24\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-success) 12%, transparent);\n color:var(--m-color-success);\n \"\n >\n {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21153
+ "code": "<script setup lang=\"ts\">\nimport type { ScrollbarInstance } from 'morya-ui'\nimport { MButton, MScrollbar } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst scrollbarRef = ref<ScrollbarInstance>()\nconst scrollTop = ref(0)\n\nfunction jump(top: number) {\n scrollbarRef.value?.setScrollTop(top)\n}\n\nfunction onScroll(payload: { scrollTop: number }) {\n scrollTop.value = Math.round(payload.scrollTop)\n}\n</script>\n\n<template>\n <div class=\"grid gap-3\">\n <div style=\"display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center\">\n <MButton label=\"Top\" size=\"small\" @click=\"jump(0)\" />\n <MButton label=\"Mid\" size=\"small\" @click=\"jump(200)\"/>\n <MButton label=\"Bottom\" size=\"small\" @click=\"jump(9999)\"/>\n <span style=\"color:var(--m-color-text-muted);font-size:0.875rem\">scrollTop: {{ scrollTop }}</span>\n </div>\n <MScrollbar ref=\"scrollbarRef\" height=\"200px\" always style=\"width: 200px\" @scroll=\"onScroll\">\n <p\n v-for=\"item in 24\"\n :key=\"item\"\n style=\"\n display:flex;align-items:center;justify-content:center;\n height:48px;margin:8px;border-radius:6px;\n background:color-mix(in srgb, var(--m-color-success) 12%, transparent);\n color:var(--m-color-success);\n \"\n >\n {{ item }}\n </p>\n </MScrollbar>\n </div>\n</template>",
21142
21154
  "locale": "en-US"
21143
21155
  },
21144
21156
  {
@@ -22117,7 +22129,7 @@
22117
22129
  "sectionId": "自定义选项渲染",
22118
22130
  "lang": "vue",
22119
22131
  "preview": true,
22120
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSelect } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst value = ref<string | number | undefined>()\nconst options = [\n { label: 'Design', value: 'design' },\n { label: 'Development', value: 'dev' },\n { label: 'Marketing', value: 'mkt' },\n]\n</script>\n\n<template>\n <MSelect v-model=\"value\" label=\"Team\" :options=\"options\" placeholder=\"Choose a team\">\n <template #header>\n <span style=\"color: var(--m-color-text-muted); font-size: var(--m-font-size-xs)\">\n Teams you belong to\n </span>\n </template>\n <template #footer>\n <MButton label=\"Manage teams\" variant=\"text\" size=\"sm\" />\n </template>\n </MSelect>\n</template>",
22132
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSelect } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst value = ref<string | number | undefined>()\nconst options = [\n { label: 'Design', value: 'design' },\n { label: 'Development', value: 'dev' },\n { label: 'Marketing', value: 'mkt' },\n]\n</script>\n\n<template>\n <MSelect v-model=\"value\" label=\"Team\" :options=\"options\" placeholder=\"Choose a team\">\n <template #header>\n <span style=\"color: var(--m-color-text-muted); font-size: var(--m-font-size-xs)\">\n Teams you belong to\n </span>\n </template>\n <template #footer>\n <MButton label=\"Manage teams\" variant=\"text\" size=\"sm\"/>\n </template>\n </MSelect>\n</template>",
22121
22133
  "locale": "zh-CN"
22122
22134
  },
22123
22135
  {
@@ -22279,7 +22291,7 @@
22279
22291
  "sectionId": "custom-option-rendering",
22280
22292
  "lang": "vue",
22281
22293
  "preview": true,
22282
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSelect } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst value = ref<string | number | undefined>()\nconst options = [\n { label: 'Design', value: 'design' },\n { label: 'Development', value: 'dev' },\n { label: 'Marketing', value: 'mkt' },\n]\n</script>\n\n<template>\n <MSelect v-model=\"value\" label=\"Team\" :options=\"options\" placeholder=\"Choose a team\">\n <template #header>\n <span style=\"color: var(--m-color-text-muted); font-size: var(--m-font-size-xs)\">\n Teams you belong to\n </span>\n </template>\n <template #footer>\n <MButton label=\"Manage teams\" variant=\"text\" size=\"sm\" />\n </template>\n </MSelect>\n</template>",
22294
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSelect } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst value = ref<string | number | undefined>()\nconst options = [\n { label: 'Design', value: 'design' },\n { label: 'Development', value: 'dev' },\n { label: 'Marketing', value: 'mkt' },\n]\n</script>\n\n<template>\n <MSelect v-model=\"value\" label=\"Team\" :options=\"options\" placeholder=\"Choose a team\">\n <template #header>\n <span style=\"color: var(--m-color-text-muted); font-size: var(--m-font-size-xs)\">\n Teams you belong to\n </span>\n </template>\n <template #footer>\n <MButton label=\"Manage teams\" variant=\"text\" size=\"sm\"/>\n </template>\n </MSelect>\n</template>",
22283
22295
  "locale": "en-US"
22284
22296
  },
22285
22297
  {
@@ -23581,7 +23593,7 @@
23581
23593
  "sectionId": "基础用法",
23582
23594
  "lang": "vue",
23583
23595
  "preview": true,
23584
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace>\n <MButton label=\"保存\" size=\"small\" />\n <MButton label=\"取消\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"重置\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n</template>",
23596
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace>\n <MButton label=\"保存\" size=\"small\" />\n <MButton label=\"取消\" size=\"small\"/>\n <MButton label=\"重置\" size=\"small\"/>\n </MSpace>\n</template>",
23585
23597
  "locale": "zh-CN"
23586
23598
  },
23587
23599
  {
@@ -23599,7 +23611,7 @@
23599
23611
  "sectionId": "size",
23600
23612
  "lang": "vue",
23601
23613
  "preview": true,
23602
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <MSpace size=\"small\">\n <MButton label=\"small\" size=\"small\" />\n <MButton label=\"small\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace size=\"medium\">\n <MButton label=\"medium\" size=\"small\" />\n <MButton label=\"medium\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace size=\"large\">\n <MButton label=\"large\" size=\"small\" />\n <MButton label=\"large\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace :size=\"20\">\n <MButton label=\"20px\" size=\"small\" />\n <MButton label=\"20px\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n </div>\n</template>",
23614
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <MSpace size=\"small\">\n <MButton label=\"small\" size=\"small\" />\n <MButton label=\"small\" size=\"small\"/>\n </MSpace>\n <MSpace size=\"medium\">\n <MButton label=\"medium\" size=\"small\" />\n <MButton label=\"medium\" size=\"small\"/>\n </MSpace>\n <MSpace size=\"large\">\n <MButton label=\"large\" size=\"small\" />\n <MButton label=\"large\" size=\"small\"/>\n </MSpace>\n <MSpace :size=\"20\">\n <MButton label=\"20px\" size=\"small\" />\n <MButton label=\"20px\" size=\"small\"/>\n </MSpace>\n </div>\n</template>",
23603
23615
  "locale": "zh-CN"
23604
23616
  },
23605
23617
  {
@@ -23626,7 +23638,7 @@
23626
23638
  "sectionId": "basic",
23627
23639
  "lang": "vue",
23628
23640
  "preview": true,
23629
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace>\n <MButton label=\"Save\" size=\"small\" />\n <MButton label=\"Cancel\" size=\"small\" severity=\"secondary\" />\n <MButton label=\"Reset\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n</template>",
23641
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <MSpace>\n <MButton label=\"Save\" size=\"small\" />\n <MButton label=\"Cancel\" size=\"small\"/>\n <MButton label=\"Reset\" size=\"small\"/>\n </MSpace>\n</template>",
23630
23642
  "locale": "en-US"
23631
23643
  },
23632
23644
  {
@@ -23644,7 +23656,7 @@
23644
23656
  "sectionId": "size",
23645
23657
  "lang": "vue",
23646
23658
  "preview": true,
23647
- "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <MSpace size=\"small\">\n <MButton label=\"small\" size=\"small\" />\n <MButton label=\"small\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace size=\"medium\">\n <MButton label=\"medium\" size=\"small\" />\n <MButton label=\"medium\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace size=\"large\">\n <MButton label=\"large\" size=\"small\" />\n <MButton label=\"large\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n <MSpace :size=\"20\">\n <MButton label=\"20px\" size=\"small\" />\n <MButton label=\"20px\" size=\"small\" severity=\"secondary\" />\n </MSpace>\n </div>\n</template>",
23659
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MSpace } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"grid gap-4\">\n <MSpace size=\"small\">\n <MButton label=\"small\" size=\"small\" />\n <MButton label=\"small\" size=\"small\"/>\n </MSpace>\n <MSpace size=\"medium\">\n <MButton label=\"medium\" size=\"small\" />\n <MButton label=\"medium\" size=\"small\"/>\n </MSpace>\n <MSpace size=\"large\">\n <MButton label=\"large\" size=\"small\" />\n <MButton label=\"large\" size=\"small\"/>\n </MSpace>\n <MSpace :size=\"20\">\n <MButton label=\"20px\" size=\"small\" />\n <MButton label=\"20px\" size=\"small\"/>\n </MSpace>\n </div>\n</template>",
23648
23660
  "locale": "en-US"
23649
23661
  },
23650
23662
  {
@@ -24068,13 +24080,13 @@
24068
24080
  "description": "菜单项。"
24069
24081
  },
24070
24082
  {
24071
- "name": "severity",
24083
+ "name": "color",
24072
24084
  "type": "—",
24073
24085
  "default": "—",
24074
24086
  "description": "视觉变体。"
24075
24087
  },
24076
24088
  {
24077
- "name": "outlined",
24089
+ "name": "variant",
24078
24090
  "type": "—",
24079
24091
  "default": "—",
24080
24092
  "description": "视觉变体。"
@@ -24196,7 +24208,7 @@
24196
24208
  {
24197
24209
  "id": "props",
24198
24210
  "title": "Props",
24199
- "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `label` | `string` | — | 主按钮文案。 |\n| `icon` | `string` | — | 可选图标字符。 |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | 菜单项。 |\n| `severity` / `outlined` / `size` | — | — | 视觉变体。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `teleport` | `boolean` | `true` | 是否将菜单 Teleport 出去。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 表示就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
24211
+ "body": "| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `label` | `string` | — | 主按钮文案。 |\n| `icon` | `string` | — | 可选图标字符。 |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | 菜单项。 |\n| `color` / `variant` / `size` | — | — | 视觉变体。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `teleport` | `boolean` | `true` | 是否将菜单 Teleport 出去。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 表示就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |"
24200
24212
  },
24201
24213
  {
24202
24214
  "id": "events",
@@ -24209,7 +24221,7 @@
24209
24221
  "body": "| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 主按钮内容。 |"
24210
24222
  }
24211
24223
  ],
24212
- "markdown": "---\ntitle: SplitButton\ncategory: 01 / BASIC\ndescription: 主操作按钮附带下拉菜单项。\n---\n\n# SplitButton\n\n左侧主按钮触发 `click`,右侧展开菜单项触发 `command`。\n\n## 引入\n\n```ts\nimport { MSplitButton } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `label` | `string` | — | 主按钮文案。 |\n| `icon` | `string` | — | 可选图标字符。 |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | 菜单项。 |\n| `severity` / `outlined` / `size` | — | — | 视觉变体。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `teleport` | `boolean` | `true` | 是否将菜单 Teleport 出去。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 表示就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `click` | `MouseEvent` | 主按钮点击。 |\n| `command` | `item` | 菜单项激活。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 主按钮内容。 |\n"
24224
+ "markdown": "---\ntitle: SplitButton\ncategory: 01 / BASIC\ndescription: 主操作按钮附带下拉菜单项。\n---\n\n# SplitButton\n\n左侧主按钮触发 `click`,右侧展开菜单项触发 `command`。\n\n## 引入\n\n```ts\nimport { MSplitButton } from 'morya-ui'\n```\n\n## 基础用法\n\n```vue preview src=\"./demos/Basic.zh.vue\"\n```\n\n## Props\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `label` | `string` | — | 主按钮文案。 |\n| `icon` | `string` | — | 可选图标字符。 |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | 菜单项。 |\n| `color` / `variant` / `size` | — | — | 视觉变体。 |\n| `disabled` | `boolean` | `false` | 禁用。 |\n| `teleport` | `boolean` | `true` | 是否将菜单 Teleport 出去。 |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | 挂载目标;`'self'` 表示就地渲染。 |\n| `transition` | `string \\| false` | `'scale-fade'` | 进出场动效预设;`false` / `'none'` 关闭。见[动效](/docs/motion)。 |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | DOM 透传,见 [样式与 attrs](/docs/attrs). |\n\n\n## Events\n\n| 事件名 | 参数 | 说明 |\n| --- | --- | --- |\n| `click` | `MouseEvent` | 主按钮点击。 |\n| `command` | `item` | 菜单项激活。 |\n\n## Slots\n\n| 插槽名 | 说明 |\n| --- | --- |\n| `default` | 主按钮内容。 |\n"
24213
24225
  },
24214
24226
  "en-US": {
24215
24227
  "title": "SplitButton",
@@ -24233,7 +24245,7 @@
24233
24245
  {
24234
24246
  "id": "props",
24235
24247
  "title": "Props",
24236
- "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `label` | `string` | — | Primary button label. |\n| `icon` | `string` | — | Optional icon character. |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | Menu items. |\n| `severity` / `outlined` / `size` | — | — | Visual variants. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `teleport` | `boolean` | `true` | Whether to Teleport the menu. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` keeps it in place. |\n| `transition` | `string \\| false` | `'scale-fade'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |"
24248
+ "body": "| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `label` | `string` | — | Primary button label. |\n| `icon` | `string` | — | Optional icon character. |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | Menu items. |\n| `color` / `variant` / `size` | — | — | Visual variants. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `teleport` | `boolean` | `true` | Whether to Teleport the menu. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` keeps it in place. |\n| `transition` | `string \\| false` | `'scale-fade'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |"
24237
24249
  },
24238
24250
  {
24239
24251
  "id": "events",
@@ -24246,7 +24258,7 @@
24246
24258
  "body": "| Slot | Description |\n| --- | --- |\n| `default` | Main button content. |"
24247
24259
  }
24248
24260
  ],
24249
- "markdown": "---\ntitle: SplitButton\ncategory: 01 / BASIC\ndescription: A primary action button with extra dropdown items.\n---\n\n# SplitButton\n\nThe left primary button emits `click`; items in the right-side menu emit `command`.\n\n## Import\n\n```ts\nimport { MSplitButton } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `label` | `string` | — | Primary button label. |\n| `icon` | `string` | — | Optional icon character. |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | Menu items. |\n| `severity` / `outlined` / `size` | — | — | Visual variants. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `teleport` | `boolean` | `true` | Whether to Teleport the menu. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` keeps it in place. |\n| `transition` | `string \\| false` | `'scale-fade'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `click` | `MouseEvent` | Primary button click. |\n| `command` | `item` | Menu item activated. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Main button content. |\n"
24261
+ "markdown": "---\ntitle: SplitButton\ncategory: 01 / BASIC\ndescription: A primary action button with extra dropdown items.\n---\n\n# SplitButton\n\nThe left primary button emits `click`; items in the right-side menu emit `command`.\n\n## Import\n\n```ts\nimport { MSplitButton } from 'morya-ui'\n```\n\n## Basic\n\n```vue preview src=\"./demos/Basic.en.vue\"\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n| --- | --- | --- | --- |\n| `label` | `string` | — | Primary button label. |\n| `icon` | `string` | — | Optional icon character. |\n| `model` | `{ label, command?, disabled? }[]` | `[]` | Menu items. |\n| `color` / `variant` / `size` | — | — | Visual variants. |\n| `disabled` | `boolean` | `false` | Disabled. |\n| `teleport` | `boolean` | `true` | Whether to Teleport the menu. |\n| `appendTo` | `string \\| HTMLElement \\| 'self'` | `'body'` | Mount target; `'self'` keeps it in place. |\n| `transition` | `string \\| false` | `'scale-fade'` | Enter/exit motion preset; `false` / `'none'` disables. See [Motion](/docs/motion). |\n| `pt` | [RootPassThrough](/docs/types#RootPassThrough) `{ root? }` | — | Pass-through; see [Styling & attrs](/docs/attrs). |\n\n\n## Events\n\n| Event | Prop | Description |\n| --- | --- | --- |\n| `click` | `MouseEvent` | Primary button click. |\n| `command` | `item` | Menu item activated. |\n\n## Slots\n\n| Slot | Description |\n| --- | --- |\n| `default` | Main button content. |\n"
24250
24262
  }
24251
24263
  }
24252
24264
  },
@@ -27141,7 +27153,7 @@
27141
27153
  "sectionId": "card-closable-extra",
27142
27154
  "lang": "vue",
27143
27155
  "preview": true,
27144
- "code": "<script setup lang=\"ts\">\nimport { MButton, MTabs } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = ref([\n { label: '设计', value: 'a' },\n { label: '数据', value: 'b' },\n { label: '发布', value: 'c' },\n])\n\nfunction onClose(value: string) {\n tabs.value = tabs.value.filter((tab) => tab.value !== value)\n}\n\nfunction onAdd() {\n const value = `tab-${tabs.value.length + 1}`\n tabs.value = [...tabs.value, { label: `Tab ${tabs.value.length + 1}`, value }]\n active.value = value\n}\n</script>\n\n<template>\n <MTabs\n v-model=\"active\"\n type=\"card\"\n closable\n addable\n :tabs=\"tabs\"\n @close=\"onClose\"\n @add=\"onAdd\"\n >\n <template #extra>\n <MButton label=\"操作\" size=\"small\" severity=\"secondary\" />\n </template>\n <template #default=\"{ activeValue }\">\n <p style=\"margin:0\">\n {{ activeValue }}\n </p>\n </template>\n </MTabs>\n</template>",
27156
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MTabs } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = ref([\n { label: '设计', value: 'a' },\n { label: '数据', value: 'b' },\n { label: '发布', value: 'c' },\n])\n\nfunction onClose(value: string) {\n tabs.value = tabs.value.filter((tab) => tab.value !== value)\n}\n\nfunction onAdd() {\n const value = `tab-${tabs.value.length + 1}`\n tabs.value = [...tabs.value, { label: `Tab ${tabs.value.length + 1}`, value }]\n active.value = value\n}\n</script>\n\n<template>\n <MTabs\n v-model=\"active\"\n type=\"card\"\n closable\n addable\n :tabs=\"tabs\"\n @close=\"onClose\"\n @add=\"onAdd\"\n >\n <template #extra>\n <MButton label=\"操作\" size=\"small\"/>\n </template>\n <template #default=\"{ activeValue }\">\n <p style=\"margin:0\">\n {{ activeValue }}\n </p>\n </template>\n </MTabs>\n</template>",
27145
27157
  "locale": "zh-CN"
27146
27158
  },
27147
27159
  {
@@ -27177,7 +27189,7 @@
27177
27189
  "sectionId": "card-closable-extra",
27178
27190
  "lang": "vue",
27179
27191
  "preview": true,
27180
- "code": "<script setup lang=\"ts\">\nimport { MButton, MTabs } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = ref([\n { label: 'Design', value: 'a' },\n { label: 'Data', value: 'b' },\n { label: 'Ship', value: 'c' },\n])\n\nfunction onClose(value: string) {\n tabs.value = tabs.value.filter((tab) => tab.value !== value)\n}\n\nfunction onAdd() {\n const value = `tab-${tabs.value.length + 1}`\n tabs.value = [...tabs.value, { label: `Tab ${tabs.value.length + 1}`, value }]\n active.value = value\n}\n</script>\n\n<template>\n <MTabs\n v-model=\"active\"\n type=\"card\"\n closable\n addable\n :tabs=\"tabs\"\n @close=\"onClose\"\n @add=\"onAdd\"\n >\n <template #extra>\n <MButton label=\"Action\" size=\"small\" severity=\"secondary\" />\n </template>\n <template #default=\"{ activeValue }\">\n <p style=\"margin:0\">\n {{ activeValue }}\n </p>\n </template>\n </MTabs>\n</template>",
27192
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MTabs } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst active = ref('a')\nconst tabs = ref([\n { label: 'Design', value: 'a' },\n { label: 'Data', value: 'b' },\n { label: 'Ship', value: 'c' },\n])\n\nfunction onClose(value: string) {\n tabs.value = tabs.value.filter((tab) => tab.value !== value)\n}\n\nfunction onAdd() {\n const value = `tab-${tabs.value.length + 1}`\n tabs.value = [...tabs.value, { label: `Tab ${tabs.value.length + 1}`, value }]\n active.value = value\n}\n</script>\n\n<template>\n <MTabs\n v-model=\"active\"\n type=\"card\"\n closable\n addable\n :tabs=\"tabs\"\n @close=\"onClose\"\n @add=\"onAdd\"\n >\n <template #extra>\n <MButton label=\"Action\" size=\"small\"/>\n </template>\n <template #default=\"{ activeValue }\">\n <p style=\"margin:0\">\n {{ activeValue }}\n </p>\n </template>\n </MTabs>\n</template>",
27181
27193
  "locale": "en-US"
27182
27194
  },
27183
27195
  {
@@ -29153,7 +29165,7 @@
29153
29165
  "sectionId": "api",
29154
29166
  "lang": "vue",
29155
29167
  "preview": true,
29156
- "code": "<script setup lang=\"ts\">\nimport { MButton, toast } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton\n label=\"Success\"\n severity=\"success\"\n @click=\"toast.success({ summary: '已保存', detail: '变更已生效。' })\"\n />\n <MButton\n label=\"Info\"\n severity=\"info\"\n @click=\"toast.info({ summary: '提示', detail: '可以继续操作。' })\"\n />\n <MButton\n label=\"Warn\"\n severity=\"warn\"\n @click=\"toast.warn({ summary: '注意', detail: '请再核对一次。' })\"\n />\n <MButton\n label=\"Error\"\n severity=\"danger\"\n @click=\"toast.error({ summary: '失败', detail: '请稍后重试。' })\"\n />\n </div>\n</template>",
29168
+ "code": "<script setup lang=\"ts\">\nimport { MButton, toast } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" @click=\"toast.success({ summary: '已保存', detail: '变更已生效。' })\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"toast.info({ summary: '提示', detail: '可以继续操作。' })\" color=\"info\" variant=\"solid\"/>\n <MButton label=\"Warn\" @click=\"toast.warn({ summary: '注意', detail: '请再核对一次。' })\" color=\"warning\" variant=\"solid\"/>\n <MButton label=\"Error\" @click=\"toast.error({ summary: '失败', detail: '请稍后重试。' })\" danger type=\"primary\"/>\n </div>\n</template>",
29157
29169
  "locale": "zh-CN"
29158
29170
  },
29159
29171
  {
@@ -29171,7 +29183,7 @@
29171
29183
  "sectionId": "controlled",
29172
29184
  "lang": "vue",
29173
29185
  "preview": true,
29174
- "code": "<script setup lang=\"ts\">\nimport type { ToastMessage } from 'morya-ui'\nimport { MButton, MToast } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst messages = ref<ToastMessage[]>([])\nlet seq = 0\n\nfunction push(severity: ToastMessage['severity'], summary: string, detail?: string) {\n messages.value = [\n ...messages.value,\n { id: `toast-${++seq}`, summary, detail, severity, life: 0 },\n ]\n}\n\nfunction onClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" severity=\"success\" @click=\"push('success', 'Saved', 'Your changes are live.')\" />\n <MButton label=\"Info\" severity=\"info\" @click=\"push('info', 'Tip', 'Something to know.')\" />\n </div>\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onClose\" />\n</template>",
29186
+ "code": "<script setup lang=\"ts\">\nimport type { ToastMessage } from 'morya-ui'\nimport { MButton, MToast } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst messages = ref<ToastMessage[]>([])\nlet seq = 0\n\nfunction push(severity: ToastMessage['severity'], summary: string, detail?: string) {\n messages.value = [\n ...messages.value,\n { id: `toast-${++seq}`, summary, detail, severity, life: 0 },\n ]\n}\n\nfunction onClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" @click=\"push('success', 'Saved', 'Your changes are live.')\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"push('info', 'Tip', 'Something to know.')\" color=\"info\" variant=\"solid\"/>\n </div>\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onClose\" />\n</template>",
29175
29187
  "locale": "zh-CN"
29176
29188
  },
29177
29189
  {
@@ -29207,7 +29219,7 @@
29207
29219
  "sectionId": "api",
29208
29220
  "lang": "vue",
29209
29221
  "preview": true,
29210
- "code": "<script setup lang=\"ts\">\nimport { MButton, toast } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton\n label=\"Success\"\n severity=\"success\"\n @click=\"toast.success({ summary: 'Saved', detail: 'Your changes are live.' })\"\n />\n <MButton\n label=\"Info\"\n severity=\"info\"\n @click=\"toast.info({ summary: 'Tip', detail: 'You can continue.' })\"\n />\n <MButton\n label=\"Warn\"\n severity=\"warn\"\n @click=\"toast.warn({ summary: 'Caution', detail: 'Please double-check.' })\"\n />\n <MButton\n label=\"Error\"\n severity=\"danger\"\n @click=\"toast.error({ summary: 'Failed', detail: 'Try again later.' })\"\n />\n </div>\n</template>",
29222
+ "code": "<script setup lang=\"ts\">\nimport { MButton, toast } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" @click=\"toast.success({ summary: 'Saved', detail: 'Your changes are live.' })\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"toast.info({ summary: 'Tip', detail: 'You can continue.' })\" color=\"info\" variant=\"solid\"/>\n <MButton label=\"Warn\" @click=\"toast.warn({ summary: 'Caution', detail: 'Please double-check.' })\" color=\"warning\" variant=\"solid\"/>\n <MButton label=\"Error\" @click=\"toast.error({ summary: 'Failed', detail: 'Try again later.' })\" danger type=\"primary\"/>\n </div>\n</template>",
29211
29223
  "locale": "en-US"
29212
29224
  },
29213
29225
  {
@@ -29225,7 +29237,7 @@
29225
29237
  "sectionId": "controlled",
29226
29238
  "lang": "vue",
29227
29239
  "preview": true,
29228
- "code": "<script setup lang=\"ts\">\nimport type { ToastMessage } from 'morya-ui'\nimport { MButton, MToast } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst messages = ref<ToastMessage[]>([])\nlet seq = 0\n\nfunction push(severity: ToastMessage['severity'], summary: string, detail?: string) {\n messages.value = [\n ...messages.value,\n { id: `toast-${++seq}`, summary, detail, severity, life: 0 },\n ]\n}\n\nfunction onClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" severity=\"success\" @click=\"push('success', 'Saved', 'Your changes are live.')\" />\n <MButton label=\"Info\" severity=\"info\" @click=\"push('info', 'Tip', 'Something to know.')\" />\n </div>\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onClose\" />\n</template>",
29240
+ "code": "<script setup lang=\"ts\">\nimport type { ToastMessage } from 'morya-ui'\nimport { MButton, MToast } from 'morya-ui'\nimport { ref } from 'vue'\n\nconst messages = ref<ToastMessage[]>([])\nlet seq = 0\n\nfunction push(severity: ToastMessage['severity'], summary: string, detail?: string) {\n messages.value = [\n ...messages.value,\n { id: `toast-${++seq}`, summary, detail, severity, life: 0 },\n ]\n}\n\nfunction onClose(message: ToastMessage) {\n messages.value = messages.value.filter((item) => item.id !== message.id)\n}\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-3 items-center\">\n <MButton label=\"Success\" @click=\"push('success', 'Saved', 'Your changes are live.')\" color=\"success\" variant=\"solid\"/>\n <MButton label=\"Info\" @click=\"push('info', 'Tip', 'Something to know.')\" color=\"info\" variant=\"solid\"/>\n </div>\n <MToast :messages=\"messages\" position=\"top-right\" @close=\"onClose\" />\n</template>",
29229
29241
  "locale": "en-US"
29230
29242
  },
29231
29243
  {
@@ -29637,7 +29649,7 @@
29637
29649
  "sectionId": "基础用法",
29638
29650
  "lang": "vue",
29639
29651
  "preview": true,
29640
- "code": "<script setup lang=\"ts\">\nimport { MButton, MToolbar } from 'morya-ui'\n</script>\n\n<template>\n <MToolbar>\n <template #start>\n <MButton label=\"新建\" size=\"small\" />\n </template>\n <template #center>\n <span>工具栏</span>\n </template>\n <template #end>\n <MButton label=\"导出\" severity=\"secondary\" size=\"small\" />\n </template>\n </MToolbar>\n</template>",
29652
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MToolbar } from 'morya-ui'\n</script>\n\n<template>\n <MToolbar>\n <template #start>\n <MButton label=\"新建\" size=\"small\" />\n </template>\n <template #center>\n <span>工具栏</span>\n </template>\n <template #end>\n <MButton label=\"导出\" size=\"small\"/>\n </template>\n </MToolbar>\n</template>",
29641
29653
  "locale": "zh-CN"
29642
29654
  },
29643
29655
  {
@@ -29655,7 +29667,7 @@
29655
29667
  "sectionId": "basic",
29656
29668
  "lang": "vue",
29657
29669
  "preview": true,
29658
- "code": "<script setup lang=\"ts\">\nimport { MButton, MToolbar } from 'morya-ui'\n</script>\n\n<template>\n <MToolbar>\n <template #start>\n <MButton label=\"New\" size=\"small\" />\n </template>\n <template #center>\n <span>Toolbar</span>\n </template>\n <template #end>\n <MButton label=\"Export\" severity=\"secondary\" size=\"small\" />\n </template>\n </MToolbar>\n</template>",
29670
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MToolbar } from 'morya-ui'\n</script>\n\n<template>\n <MToolbar>\n <template #start>\n <MButton label=\"New\" size=\"small\" />\n </template>\n <template #center>\n <span>Toolbar</span>\n </template>\n <template #end>\n <MButton label=\"Export\" size=\"small\"/>\n </template>\n </MToolbar>\n</template>",
29659
29671
  "locale": "en-US"
29660
29672
  }
29661
29673
  ],
@@ -29824,7 +29836,7 @@
29824
29836
  "sectionId": "基础用法",
29825
29837
  "lang": "vue",
29826
29838
  "preview": true,
29827
- "code": "<script setup lang=\"ts\">\nimport { MButton, MTooltip } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-4 items-center\">\n <MTooltip content=\"Save changes\" placement=\"top\">\n <MButton icon=\"check\" icon-only aria-label=\"Save\" />\n </MTooltip>\n <MTooltip content=\"Delete item\" placement=\"bottom\" :show-delay=\"200\" :hide-delay=\"120\" :max-width=\"160\">\n <MButton icon=\"trash\" icon-only severity=\"danger\" outlined aria-label=\"Delete\" />\n </MTooltip>\n </div>\n</template>",
29839
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MTooltip } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-4 items-center\">\n <MTooltip content=\"Save changes\" placement=\"top\">\n <MButton icon=\"check\" icon-only aria-label=\"Save\" />\n </MTooltip>\n <MTooltip content=\"Delete item\" placement=\"bottom\" :show-delay=\"200\" :hide-delay=\"120\" :max-width=\"160\">\n <MButton icon=\"trash\" icon-only aria-label=\"Delete\" danger/>\n </MTooltip>\n </div>\n</template>",
29828
29840
  "locale": "zh-CN"
29829
29841
  },
29830
29842
  {
@@ -29842,7 +29854,7 @@
29842
29854
  "sectionId": "basic",
29843
29855
  "lang": "vue",
29844
29856
  "preview": true,
29845
- "code": "<script setup lang=\"ts\">\nimport { MButton, MTooltip } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-4 items-center\">\n <MTooltip content=\"Save changes\" placement=\"top\">\n <MButton icon=\"check\" icon-only aria-label=\"Save\" />\n </MTooltip>\n <MTooltip content=\"Delete item\" placement=\"bottom\" :show-delay=\"200\" :hide-delay=\"120\" :max-width=\"160\">\n <MButton icon=\"trash\" icon-only severity=\"danger\" outlined aria-label=\"Delete\" />\n </MTooltip>\n </div>\n</template>",
29857
+ "code": "<script setup lang=\"ts\">\nimport { MButton, MTooltip } from 'morya-ui'\n</script>\n\n<template>\n <div class=\"flex flex-wrap gap-4 items-center\">\n <MTooltip content=\"Save changes\" placement=\"top\">\n <MButton icon=\"check\" icon-only aria-label=\"Save\" />\n </MTooltip>\n <MTooltip content=\"Delete item\" placement=\"bottom\" :show-delay=\"200\" :hide-delay=\"120\" :max-width=\"160\">\n <MButton icon=\"trash\" icon-only aria-label=\"Delete\" danger/>\n </MTooltip>\n </div>\n</template>",
29846
29858
  "locale": "en-US"
29847
29859
  }
29848
29860
  ],
@@ -30042,7 +30054,7 @@
30042
30054
  "sectionId": "基础用法",
30043
30055
  "lang": "vue",
30044
30056
  "preview": true,
30045
- "code": "<script setup lang=\"ts\">\nimport type { TourStep } from '../../types'\nimport { computed, ref } from 'vue'\nimport { MButton, MSpace, MTour } from 'morya-ui'\n\nconst open = ref(false)\nconst current = ref(0)\nconst firstEl = ref<HTMLElement | null>(null)\nconst secondEl = ref<HTMLElement | null>(null)\n\nfunction resolveEl(el: HTMLElement | { $el?: HTMLElement } | null) {\n if (!el) return null\n if (el instanceof HTMLElement) return el\n return el.$el ?? null\n}\n\nconst steps = computed((): TourStep[] => [\n {\n title: 'Primary action',\n description: 'This button starts the guided tour.',\n target: () => resolveEl(firstEl.value),\n },\n {\n title: 'Secondary',\n description: 'You can attach steps to any element.',\n target: () => resolveEl(secondEl.value),\n placement: 'bottom-start',\n },\n])\n</script>\n\n<template>\n <MSpace vertical>\n <MSpace>\n <span ref=\"firstEl\">\n <MButton\n severity=\"primary\"\n @click=\"open = true\"\n >\n Start tour\n </MButton>\n </span>\n <span ref=\"secondEl\">\n <MButton>\n Another control\n </MButton>\n </span>\n </MSpace>\n\n <MTour\n v-model:open=\"open\"\n v-model:current=\"current\"\n :steps=\"steps\"\n />\n </MSpace>\n</template>",
30057
+ "code": "<script setup lang=\"ts\">\nimport type { TourStep } from '../../types'\nimport { computed, ref } from 'vue'\nimport { MButton, MSpace, MTour } from 'morya-ui'\n\nconst open = ref(false)\nconst current = ref(0)\nconst firstEl = ref<HTMLElement | null>(null)\nconst secondEl = ref<HTMLElement | null>(null)\n\nfunction resolveEl(el: HTMLElement | { $el?: HTMLElement } | null) {\n if (!el) return null\n if (el instanceof HTMLElement) return el\n return el.$el ?? null\n}\n\nconst steps = computed((): TourStep[] => [\n {\n title: 'Primary action',\n description: 'This button starts the guided tour.',\n target: () => resolveEl(firstEl.value),\n },\n {\n title: 'Secondary',\n description: 'You can attach steps to any element.',\n target: () => resolveEl(secondEl.value),\n placement: 'bottom-start',\n },\n])\n</script>\n\n<template>\n <MSpace vertical>\n <MSpace>\n <span ref=\"firstEl\">\n <MButton @click=\"open = true\" type=\"primary\">\n Start tour\n </MButton>\n </span>\n <span ref=\"secondEl\">\n <MButton>\n Another control\n </MButton>\n </span>\n </MSpace>\n\n <MTour\n v-model:open=\"open\"\n v-model:current=\"current\"\n :steps=\"steps\"\n />\n </MSpace>\n</template>",
30046
30058
  "locale": "zh-CN"
30047
30059
  },
30048
30060
  {
@@ -30060,7 +30072,7 @@
30060
30072
  "sectionId": "basic",
30061
30073
  "lang": "vue",
30062
30074
  "preview": true,
30063
- "code": "<script setup lang=\"ts\">\nimport type { TourStep } from '../../types'\nimport { computed, ref } from 'vue'\nimport { MButton, MSpace, MTour } from 'morya-ui'\n\nconst open = ref(false)\nconst current = ref(0)\nconst firstEl = ref<HTMLElement | null>(null)\nconst secondEl = ref<HTMLElement | null>(null)\n\nfunction resolveEl(el: HTMLElement | { $el?: HTMLElement } | null) {\n if (!el) return null\n if (el instanceof HTMLElement) return el\n return el.$el ?? null\n}\n\nconst steps = computed((): TourStep[] => [\n {\n title: 'Primary action',\n description: 'This button starts the guided tour.',\n target: () => resolveEl(firstEl.value),\n },\n {\n title: 'Secondary',\n description: 'You can attach steps to any element.',\n target: () => resolveEl(secondEl.value),\n placement: 'bottom-start',\n },\n])\n</script>\n\n<template>\n <MSpace vertical>\n <MSpace>\n <span ref=\"firstEl\">\n <MButton\n severity=\"primary\"\n @click=\"open = true\"\n >\n Start tour\n </MButton>\n </span>\n <span ref=\"secondEl\">\n <MButton>\n Another control\n </MButton>\n </span>\n </MSpace>\n\n <MTour\n v-model:open=\"open\"\n v-model:current=\"current\"\n :steps=\"steps\"\n />\n </MSpace>\n</template>",
30075
+ "code": "<script setup lang=\"ts\">\nimport type { TourStep } from '../../types'\nimport { computed, ref } from 'vue'\nimport { MButton, MSpace, MTour } from 'morya-ui'\n\nconst open = ref(false)\nconst current = ref(0)\nconst firstEl = ref<HTMLElement | null>(null)\nconst secondEl = ref<HTMLElement | null>(null)\n\nfunction resolveEl(el: HTMLElement | { $el?: HTMLElement } | null) {\n if (!el) return null\n if (el instanceof HTMLElement) return el\n return el.$el ?? null\n}\n\nconst steps = computed((): TourStep[] => [\n {\n title: 'Primary action',\n description: 'This button starts the guided tour.',\n target: () => resolveEl(firstEl.value),\n },\n {\n title: 'Secondary',\n description: 'You can attach steps to any element.',\n target: () => resolveEl(secondEl.value),\n placement: 'bottom-start',\n },\n])\n</script>\n\n<template>\n <MSpace vertical>\n <MSpace>\n <span ref=\"firstEl\">\n <MButton @click=\"open = true\" type=\"primary\">\n Start tour\n </MButton>\n </span>\n <span ref=\"secondEl\">\n <MButton>\n Another control\n </MButton>\n </span>\n </MSpace>\n\n <MTour\n v-model:open=\"open\"\n v-model:current=\"current\"\n :steps=\"steps\"\n />\n </MSpace>\n</template>",
30064
30076
  "locale": "en-US"
30065
30077
  }
30066
30078
  ],
@@ -32095,7 +32107,7 @@
32095
32107
  "zh-CN": {
32096
32108
  "title": "设计语言",
32097
32109
  "description": "Morya 设计原则与 Design Spec 章节入口。",
32098
- "markdown": "---\ntitle: 设计语言\norder: 4.5\ndescription: Morya 设计原则与 Design Spec 章节入口。\n---\n\n# 设计语言\n\nMorya UI 是一套**令牌驱动**的 Vue 3 组件库:颜色、间距、圆角、字号与动效统一走 `--m-*`,交互词表用 `severity` / `variant` / `size`,全局行为由 `MConfigProvider`、`useTheme`、`useDensity`、`useMotion` 协同。\n\n本文是 Design Spec 总览。原则摘要来自仓库 [`design-kit/DESIGN.md`](https://github.com/morya-space/morya-ui/blob/main/design-kit/DESIGN.md);完整变量目录见 [设计令牌](/docs/design-tokens)。\n\n## 原则\n\n1. **组件优先**:交互与布局优先用库内 `M*`,避免手写等价 DOM。\n2. **令牌优先**:页面与业务样式只消费 `--m-*`;禁止在业务代码写裸 `#hex` / `rgb()`(换品牌改主题入口)。\n3. **语义一致**:主操作为默认 primary;破坏性操作用 `severity=\"danger\"` 或确认流。\n4. **可访问**:控件有可访问名称;纯图标按钮提供 `aria-label`;浮层可键盘关闭。\n5. **单一事实源**:API 以组件文档 / MCP 为准,勿臆造 prop。\n\n## 章节\n\n| 章节 | 内容 |\n| ------------------------------------- | ------------------------------------------ |\n| [色彩](/docs/design-color) | 品牌色、语义色、中性面、对比与覆盖 |\n| [字体与排版](/docs/design-typography) | 字号阶梯、字重、控件字号 |\n| [间距](/docs/design-spacing) | `--m-space-*` 节奏与密度缩放 |\n| [布局](/docs/design-layout) | `MLayout` / `MPage*` / `MSpace` 与页面框架 |\n| [动效](/docs/motion) | 设计原则、时长、缓动、减弱与 API |\n| [反馈](/docs/design-feedback) | Message / Toast / Dialog / Alert 层级 |\n\n工程接入另见 [主题](/docs/theme)、[全局配置](/docs/config)、[约定](/docs/conventions)、[Common Props](/docs/common-props)。\n\n## 主题编辑器\n\n在线调色、密度与动效预览:[主题编辑器](/theme-editor)(独立交互路由)。编程侧用 `createTheme` / `useTheme`,见 [主题](/docs/theme)。\n",
32110
+ "markdown": "---\ntitle: 设计语言\norder: 4.5\ndescription: Morya 设计原则与 Design Spec 章节入口。\n---\n\n# 设计语言\n\nMorya UI 是一套**令牌驱动**的 Vue 3 组件库:颜色、间距、圆角、字号与动效统一走 `--m-*`,交互词表用 `severity` / `variant` / `size`,全局行为由 `MConfigProvider`、`useTheme`、`useDensity`、`useMotion` 协同。\n\n本文是 Design Spec 总览。原则摘要来自仓库 [`design-kit/DESIGN.md`](https://github.com/morya-space/morya-ui/blob/main/design-kit/DESIGN.md);完整变量目录见 [设计令牌](/docs/design-tokens)。\n\n## 原则\n\n1. **组件优先**:交互与布局优先用库内 `M*`,避免手写等价 DOM。\n2. **令牌优先**:页面与业务样式只消费 `--m-*`;禁止在业务代码写裸 `#hex` / `rgb()`(换品牌改主题入口)。\n3. **语义一致**:主操作用 `type=\"primary\"`;破坏性操作用 `danger` / `color=\"danger\"` 或确认流。\n4. **可访问**:控件有可访问名称;纯图标按钮提供 `aria-label`;浮层可键盘关闭。\n5. **单一事实源**:API 以组件文档 / MCP 为准,勿臆造 prop。\n\n## 章节\n\n| 章节 | 内容 |\n| ------------------------------------- | ------------------------------------------ |\n| [色彩](/docs/design-color) | 品牌色、语义色、中性面、对比与覆盖 |\n| [字体与排版](/docs/design-typography) | 字号阶梯、字重、控件字号 |\n| [间距](/docs/design-spacing) | `--m-space-*` 节奏与密度缩放 |\n| [布局](/docs/design-layout) | `MLayout` / `MPage*` / `MSpace` 与页面框架 |\n| [动效](/docs/motion) | 设计原则、时长、缓动、减弱与 API |\n| [反馈](/docs/design-feedback) | Message / Toast / Dialog / Alert 层级 |\n\n工程接入另见 [主题](/docs/theme)、[全局配置](/docs/config)、[约定](/docs/conventions)、[Common Props](/docs/common-props)。\n\n## 主题编辑器\n\n在线调色、密度与动效预览:[主题编辑器](/theme-editor)(独立交互路由)。编程侧用 `createTheme` / `useTheme`,见 [主题](/docs/theme)。\n",
32099
32111
  "sections": [
32100
32112
  {
32101
32113
  "title": "",
@@ -32105,7 +32117,7 @@
32105
32117
  {
32106
32118
  "title": "原则",
32107
32119
  "id": "原则",
32108
- "body": "1. **组件优先**:交互与布局优先用库内 `M*`,避免手写等价 DOM。\n2. **令牌优先**:页面与业务样式只消费 `--m-*`;禁止在业务代码写裸 `#hex` / `rgb()`(换品牌改主题入口)。\n3. **语义一致**:主操作为默认 primary;破坏性操作用 `severity=\"danger\"` 或确认流。\n4. **可访问**:控件有可访问名称;纯图标按钮提供 `aria-label`;浮层可键盘关闭。\n5. **单一事实源**:API 以组件文档 / MCP 为准,勿臆造 prop。"
32120
+ "body": "1. **组件优先**:交互与布局优先用库内 `M*`,避免手写等价 DOM。\n2. **令牌优先**:页面与业务样式只消费 `--m-*`;禁止在业务代码写裸 `#hex` / `rgb()`(换品牌改主题入口)。\n3. **语义一致**:主操作用 `type=\"primary\"`;破坏性操作用 `danger` / `color=\"danger\"` 或确认流。\n4. **可访问**:控件有可访问名称;纯图标按钮提供 `aria-label`;浮层可键盘关闭。\n5. **单一事实源**:API 以组件文档 / MCP 为准,勿臆造 prop。"
32109
32121
  },
32110
32122
  {
32111
32123
  "title": "章节",
@@ -32122,7 +32134,7 @@
32122
32134
  "en-US": {
32123
32135
  "title": "Design language",
32124
32136
  "description": "Entry to Morya design principles and Design Spec chapters.",
32125
- "markdown": "---\ntitle: Design language\norder: 4.5\ndescription: Entry to Morya design principles and Design Spec chapters.\n---\n\n# Design language\n\nMorya UI is a **token-driven** Vue 3 library: color, spacing, radius, type, and motion share `--m-*` variables; interaction vocabulary uses `severity` / `variant` / `size`; global behavior is coordinated by `MConfigProvider`, `useTheme`, `useDensity`, and `useMotion`.\n\nThis page is the Design Spec hub. Principles come from [`design-kit/DESIGN.md`](https://github.com/morya-space/morya-ui/blob/main/design-kit/DESIGN.md); the full variable catalog is in [Design tokens](/docs/design-tokens).\n\n## Principles\n\n1. **Components first**: Prefer library `M*` controls over hand-rolled DOM equivalents.\n2. **Tokens first**: App styles consume `--m-*` only; no raw `#hex` / `rgb()` in product CSS (change brand at the theme entry).\n3. **Semantic consistency**: Primary actions default to primary; destructive work uses `severity=\"danger\"` or a confirm flow.\n4. **Accessibility**: Controls need accessible names; icon-only buttons need `aria-label`; overlays dismiss via keyboard.\n5. **Single source of truth**: Trust component docs / MCP for APIs; do not invent props.\n\n## Chapters\n\n| Chapter | Focus |\n| ------------------------------------- | ------------------------------------------------------------- |\n| [Color](/docs/design-color) | Brand, severity, neutrals, contrast, overrides |\n| [Typography](/docs/design-typography) | Type ramp, weights, control fonts |\n| [Spacing](/docs/design-spacing) | `--m-space-*` rhythm and density scaling |\n| [Layout](/docs/design-layout) | `MLayout` / `MPage*` / `MSpace` and app chrome |\n| [Motion](/docs/motion) | Design principles, duration, easing, reduced motion, and APIs |\n| [Feedback](/docs/design-feedback) | Message / Toast / Dialog / Alert hierarchy |\n\nEngineering guides: [Theme](/docs/theme), [Configuration](/docs/config), [Conventions](/docs/conventions), [Common Props](/docs/common-props).\n\n## Theme editor\n\nLive accent, density, and motion preview: [Theme editor](/theme-editor) (interactive route). Programmatic APIs: `createTheme` / `useTheme` — see [Theme](/docs/theme).\n",
32137
+ "markdown": "---\ntitle: Design language\norder: 4.5\ndescription: Entry to Morya design principles and Design Spec chapters.\n---\n\n# Design language\n\nMorya UI is a **token-driven** Vue 3 library: color, spacing, radius, type, and motion share `--m-*` variables; interaction vocabulary uses `severity` / `variant` / `size`; global behavior is coordinated by `MConfigProvider`, `useTheme`, `useDensity`, and `useMotion`.\n\nThis page is the Design Spec hub. Principles come from [`design-kit/DESIGN.md`](https://github.com/morya-space/morya-ui/blob/main/design-kit/DESIGN.md); the full variable catalog is in [Design tokens](/docs/design-tokens).\n\n## Principles\n\n1. **Components first**: Prefer library `M*` controls over hand-rolled DOM equivalents.\n2. **Tokens first**: App styles consume `--m-*` only; no raw `#hex` / `rgb()` in product CSS (change brand at the theme entry).\n3. **Semantic consistency**: Primary actions use `type=\"primary\"`; destructive work uses `danger` / `color=\"danger\"` or a confirm flow.\n4. **Accessibility**: Controls need accessible names; icon-only buttons need `aria-label`; overlays dismiss via keyboard.\n5. **Single source of truth**: Trust component docs / MCP for APIs; do not invent props.\n\n## Chapters\n\n| Chapter | Focus |\n| ------------------------------------- | ------------------------------------------------------------- |\n| [Color](/docs/design-color) | Brand, severity, neutrals, contrast, overrides |\n| [Typography](/docs/design-typography) | Type ramp, weights, control fonts |\n| [Spacing](/docs/design-spacing) | `--m-space-*` rhythm and density scaling |\n| [Layout](/docs/design-layout) | `MLayout` / `MPage*` / `MSpace` and app chrome |\n| [Motion](/docs/motion) | Design principles, duration, easing, reduced motion, and APIs |\n| [Feedback](/docs/design-feedback) | Message / Toast / Dialog / Alert hierarchy |\n\nEngineering guides: [Theme](/docs/theme), [Configuration](/docs/config), [Conventions](/docs/conventions), [Common Props](/docs/common-props).\n\n## Theme editor\n\nLive accent, density, and motion preview: [Theme editor](/theme-editor) (interactive route). Programmatic APIs: `createTheme` / `useTheme` — see [Theme](/docs/theme).\n",
32126
32138
  "sections": [
32127
32139
  {
32128
32140
  "title": "",
@@ -32132,7 +32144,7 @@
32132
32144
  {
32133
32145
  "title": "Principles",
32134
32146
  "id": "principles",
32135
- "body": "1. **Components first**: Prefer library `M*` controls over hand-rolled DOM equivalents.\n2. **Tokens first**: App styles consume `--m-*` only; no raw `#hex` / `rgb()` in product CSS (change brand at the theme entry).\n3. **Semantic consistency**: Primary actions default to primary; destructive work uses `severity=\"danger\"` or a confirm flow.\n4. **Accessibility**: Controls need accessible names; icon-only buttons need `aria-label`; overlays dismiss via keyboard.\n5. **Single source of truth**: Trust component docs / MCP for APIs; do not invent props."
32147
+ "body": "1. **Components first**: Prefer library `M*` controls over hand-rolled DOM equivalents.\n2. **Tokens first**: App styles consume `--m-*` only; no raw `#hex` / `rgb()` in product CSS (change brand at the theme entry).\n3. **Semantic consistency**: Primary actions use `type=\"primary\"`; destructive work uses `danger` / `color=\"danger\"` or a confirm flow.\n4. **Accessibility**: Controls need accessible names; icon-only buttons need `aria-label`; overlays dismiss via keyboard.\n5. **Single source of truth**: Trust component docs / MCP for APIs; do not invent props."
32136
32148
  },
32137
32149
  {
32138
32150
  "title": "Chapters",
@@ -32159,7 +32171,7 @@
32159
32171
  "zh-CN": {
32160
32172
  "title": "色彩",
32161
32173
  "description": "品牌色、语义色、中性色与对比度约定。",
32162
- "markdown": "---\ntitle: 色彩\norder: 4.51\ndescription: 品牌色、语义色、中性色与对比度约定。\n---\n\n# 色彩\n\n组件只消费语义化 `--m-*` 颜色变量,不维护第二套业务色板。亮 / 暗色由 `document.documentElement` 的 `data-theme` 切换(`useTheme`)。\n\n## 原则\n\n- **换品牌改令牌**:在主题入口覆盖 `--m-color-primary`(及派生 hover / active / bg),页面仍写 `var(--m-*)`。\n- **语义先于色相**:按钮、Tag、Alert 用 `severity`,不要用裸色冒充状态。\n- **暗色必须可跟随**:业务 CSS 勿写死浅色专用 hex;依赖 `[data-theme=\"dark\"]` 覆盖。\n- **不只靠颜色传达**:错误 / 成功同时给文案或图标(见 [无障碍](/docs/accessibility))。\n\n## 核心令牌\n\n| Token | 默认(亮色) | 用途 |\n| --- | --- | --- |\n| `--m-color-primary` | `#1677ff` | 品牌主色、链接、默认主按钮 |\n| `--m-color-primary-hover` | `#4096ff` | 主色悬浮 |\n| `--m-color-surface` | `#ffffff` | 容器 / 卡片底 |\n| `--m-color-text` | `rgba(0,0,0,0.88)` | 正文 |\n| `--m-color-text-muted` | `rgba(0,0,0,0.45)` | 次要说明 |\n| `--m-color-border` | `#d9d9d9` | 描边 |\n| `--m-color-split` | `#f0f0f0` | 弱分割(弱于 border) |\n| `--m-color-success` | `#52c41a` | 成功 |\n| `--m-color-info` | `#1677ff` | 信息 |\n| `--m-color-warning` / `--m-color-warn` | `#faad14` | 警告(`warn` 为别名) |\n| `--m-color-danger` | `#ff4d4f` | 危险 / 错误 |\n| `--m-color-help` | `#9333ea` | 帮助提示 |\n| `--m-color-on-emphasis` | `#ffffff` | 实心强调面上的前景 |\n| `--m-color-focus-ring` | 跟主色 | 聚焦相关 |\n| `--m-opacity-disabled` | `0.55` | 禁用透明度 |\n\n暗色示例:`--m-color-surface: #141414`,正文 `rgba(255,255,255,0.85)`。完整表见 [设计令牌](/docs/design-tokens)。\n\n## severity 映射\n\n| `severity` | 对应色 |\n| --- | --- |\n| (省略 / primary) | `--m-color-primary` |\n| `secondary` | 中性次要外观 |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` 系 |\n\n破坏性操作:按钮 / 确认用 `severity=\"danger\"`,不要用主色冒充删除。\n\n## 覆盖方式\n\n```css\n:root {\n --m-color-primary: #0b6e4f;\n}\n[data-theme=\"dark\"] {\n --m-color-primary: #3ecf8e;\n}\n```\n\n也可用 `createTheme({ seed: { colorPrimary: '…' } })` 派生 hover / bg 等(见 [主题](/docs/theme))。在线预览:[主题编辑器](/theme-editor)。\n\n## 建议与避免\n\n| 建议 | 避免 |\n| --- | --- |\n| 主操作默认 primary,次要用 `secondary` / `outlined` | 一屏多个同等实心主按钮 |\n| 错误态用 `danger` + 文案 | 只用红色边框表达错误 |\n| 弱分隔用 `--m-color-split` | 到处加粗边框抢层级 |\n| 聚焦用 `--m-focus-shadow` | 手写外扩 outline 与主题脱节 |\n\n下一章:[字体与排版](/docs/design-typography)。\n",
32174
+ "markdown": "---\ntitle: 色彩\norder: 4.51\ndescription: 品牌色、语义色、中性色与对比度约定。\n---\n\n# 色彩\n\n组件只消费语义化 `--m-*` 颜色变量,不维护第二套业务色板。亮 / 暗色由 `document.documentElement` 的 `data-theme` 切换(`useTheme`)。\n\n## 原则\n\n- **换品牌改令牌**:在主题入口覆盖 `--m-color-primary`(及派生 hover / active / bg),页面仍写 `var(--m-*)`。\n- **语义先于色相**:按钮、Tag、Alert 用 `severity`,不要用裸色冒充状态。\n- **暗色必须可跟随**:业务 CSS 勿写死浅色专用 hex;依赖 `[data-theme=\"dark\"]` 覆盖。\n- **不只靠颜色传达**:错误 / 成功同时给文案或图标(见 [无障碍](/docs/accessibility))。\n\n## 核心令牌\n\n| Token | 默认(亮色) | 用途 |\n| --- | --- | --- |\n| `--m-color-primary` | `#1677ff` | 品牌主色、链接、默认主按钮 |\n| `--m-color-primary-hover` | `#4096ff` | 主色悬浮 |\n| `--m-color-surface` | `#ffffff` | 容器 / 卡片底 |\n| `--m-color-text` | `rgba(0,0,0,0.88)` | 正文 |\n| `--m-color-text-muted` | `rgba(0,0,0,0.45)` | 次要说明 |\n| `--m-color-border` | `#d9d9d9` | 描边 |\n| `--m-color-split` | `#f0f0f0` | 弱分割(弱于 border) |\n| `--m-color-success` | `#52c41a` | 成功 |\n| `--m-color-info` | `#1677ff` | 信息 |\n| `--m-color-warning` / `--m-color-warn` | `#faad14` | 警告(`warn` 为别名) |\n| `--m-color-danger` | `#ff4d4f` | 危险 / 错误 |\n| `--m-color-help` | `#9333ea` | 帮助提示 |\n| `--m-color-on-emphasis` | `#ffffff` | 实心强调面上的前景 |\n| `--m-color-focus-ring` | 跟主色 | 聚焦相关 |\n| `--m-opacity-disabled` | `0.55` | 禁用透明度 |\n\n暗色示例:`--m-color-surface: #141414`,正文 `rgba(255,255,255,0.85)`。完整表见 [设计令牌](/docs/design-tokens)。\n\n## severity 映射\n\n| `severity` | 对应色 |\n| --- | --- |\n| (省略 / primary) | `--m-color-primary` |\n| `secondary` | 中性次要外观 |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` 系 |\n\n破坏性操作:按钮 / 确认用 `danger` 或 `color=\"danger\"`,不要用主色冒充删除。\n\n## 覆盖方式\n\n```css\n:root {\n --m-color-primary: #0b6e4f;\n}\n[data-theme=\"dark\"] {\n --m-color-primary: #3ecf8e;\n}\n```\n\n也可用 `createTheme({ seed: { colorPrimary: '…' } })` 派生 hover / bg 等(见 [主题](/docs/theme))。在线预览:[主题编辑器](/theme-editor)。\n\n## 建议与避免\n\n| 建议 | 避免 |\n| --- | --- |\n| 主操作默认 primary,次要用 `secondary` / `outlined` | 一屏多个同等实心主按钮 |\n| 错误态用 `danger` + 文案 | 只用红色边框表达错误 |\n| 弱分隔用 `--m-color-split` | 到处加粗边框抢层级 |\n| 聚焦用 `--m-focus-shadow` | 手写外扩 outline 与主题脱节 |\n\n下一章:[字体与排版](/docs/design-typography)。\n",
32163
32175
  "sections": [
32164
32176
  {
32165
32177
  "title": "",
@@ -32179,7 +32191,7 @@
32179
32191
  {
32180
32192
  "title": "severity 映射",
32181
32193
  "id": "severity-映射",
32182
- "body": "| `severity` | 对应色 |\n| --- | --- |\n| (省略 / primary) | `--m-color-primary` |\n| `secondary` | 中性次要外观 |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` 系 |\n\n破坏性操作:按钮 / 确认用 `severity=\"danger\"`,不要用主色冒充删除。"
32194
+ "body": "| `severity` | 对应色 |\n| --- | --- |\n| (省略 / primary) | `--m-color-primary` |\n| `secondary` | 中性次要外观 |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` 系 |\n\n破坏性操作:按钮 / 确认用 `danger` 或 `color=\"danger\"`,不要用主色冒充删除。"
32183
32195
  },
32184
32196
  {
32185
32197
  "title": "覆盖方式",
@@ -32196,7 +32208,7 @@
32196
32208
  "en-US": {
32197
32209
  "title": "Color",
32198
32210
  "description": "Brand, severity, neutrals, and contrast conventions.",
32199
- "markdown": "---\ntitle: Color\norder: 4.51\ndescription: Brand, severity, neutrals, and contrast conventions.\n---\n\n# Color\n\nComponents consume semantic `--m-*` color variables only—there is no second product palette. Light / dark follows `data-theme` on `document.documentElement` via `useTheme`.\n\n## Principles\n\n- **Brand at the theme entry**: Override `--m-color-primary` (and derived hover / active / bg); pages keep `var(--m-*)`.\n- **Semantics over hue**: Buttons, tags, and alerts use `severity`—do not fake status with raw colors.\n- **Dark must follow**: Avoid light-only hex in app CSS; rely on `[data-theme=\"dark\"]` overrides.\n- **Never color alone**: Pair error / success with copy or icons (see [Accessibility](/docs/accessibility)).\n\n## Core tokens\n\n| Token | Default (light) | Role |\n| --- | --- | --- |\n| `--m-color-primary` | `#1677ff` | Brand, links, default primary button |\n| `--m-color-primary-hover` | `#4096ff` | Primary hover |\n| `--m-color-surface` | `#ffffff` | Container / card surface |\n| `--m-color-text` | `rgba(0,0,0,0.88)` | Body text |\n| `--m-color-text-muted` | `rgba(0,0,0,0.45)` | Secondary copy |\n| `--m-color-border` | `#d9d9d9` | Borders |\n| `--m-color-split` | `#f0f0f0` | Weaker dividers |\n| `--m-color-success` | `#52c41a` | Success |\n| `--m-color-info` | `#1677ff` | Info |\n| `--m-color-warning` / `--m-color-warn` | `#faad14` | Warning (`warn` alias) |\n| `--m-color-danger` | `#ff4d4f` | Danger / error |\n| `--m-color-help` | `#9333ea` | Help accent |\n| `--m-color-on-emphasis` | `#ffffff` | Foreground on solid emphasis |\n| `--m-color-focus-ring` | Tracks primary | Focus-related |\n| `--m-opacity-disabled` | `0.55` | Disabled opacity |\n\nDark example: `--m-color-surface: #141414`, body `rgba(255,255,255,0.85)`. Full catalog: [Design tokens](/docs/design-tokens).\n\n## Severity mapping\n\n| `severity` | Maps to |\n| --- | --- |\n| (omit / primary) | `--m-color-primary` |\n| `secondary` | Neutral secondary treatment |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` family |\n\nDestructive actions: use `severity=\"danger\"` on buttons / confirms—do not paint delete as primary.\n\n## Overrides\n\n```css\n:root {\n --m-color-primary: #0b6e4f;\n}\n[data-theme=\"dark\"] {\n --m-color-primary: #3ecf8e;\n}\n```\n\nOr derive with `createTheme({ seed: { colorPrimary: '…' } })` (see [Theme](/docs/theme)). Live preview: [Theme editor](/theme-editor).\n\n## Do / Don't\n\n| Do | Don't |\n| --- | --- |\n| One clear primary action; secondary via `secondary` / `outlined` | Several equally solid primary buttons |\n| Errors: `danger` + message | Red border alone for validation |\n| Weak rules with `--m-color-split` | Heavy borders everywhere |\n| Focus with `--m-focus-shadow` | Ad-hoc outline rings that ignore theme |\n\nNext: [Typography](/docs/design-typography).\n",
32211
+ "markdown": "---\ntitle: Color\norder: 4.51\ndescription: Brand, severity, neutrals, and contrast conventions.\n---\n\n# Color\n\nComponents consume semantic `--m-*` color variables only—there is no second product palette. Light / dark follows `data-theme` on `document.documentElement` via `useTheme`.\n\n## Principles\n\n- **Brand at the theme entry**: Override `--m-color-primary` (and derived hover / active / bg); pages keep `var(--m-*)`.\n- **Semantics over hue**: Buttons, tags, and alerts use `severity`—do not fake status with raw colors.\n- **Dark must follow**: Avoid light-only hex in app CSS; rely on `[data-theme=\"dark\"]` overrides.\n- **Never color alone**: Pair error / success with copy or icons (see [Accessibility](/docs/accessibility)).\n\n## Core tokens\n\n| Token | Default (light) | Role |\n| --- | --- | --- |\n| `--m-color-primary` | `#1677ff` | Brand, links, default primary button |\n| `--m-color-primary-hover` | `#4096ff` | Primary hover |\n| `--m-color-surface` | `#ffffff` | Container / card surface |\n| `--m-color-text` | `rgba(0,0,0,0.88)` | Body text |\n| `--m-color-text-muted` | `rgba(0,0,0,0.45)` | Secondary copy |\n| `--m-color-border` | `#d9d9d9` | Borders |\n| `--m-color-split` | `#f0f0f0` | Weaker dividers |\n| `--m-color-success` | `#52c41a` | Success |\n| `--m-color-info` | `#1677ff` | Info |\n| `--m-color-warning` / `--m-color-warn` | `#faad14` | Warning (`warn` alias) |\n| `--m-color-danger` | `#ff4d4f` | Danger / error |\n| `--m-color-help` | `#9333ea` | Help accent |\n| `--m-color-on-emphasis` | `#ffffff` | Foreground on solid emphasis |\n| `--m-color-focus-ring` | Tracks primary | Focus-related |\n| `--m-opacity-disabled` | `0.55` | Disabled opacity |\n\nDark example: `--m-color-surface: #141414`, body `rgba(255,255,255,0.85)`. Full catalog: [Design tokens](/docs/design-tokens).\n\n## Severity mapping\n\n| `severity` | Maps to |\n| --- | --- |\n| (omit / primary) | `--m-color-primary` |\n| `secondary` | Neutral secondary treatment |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` family |\n\nDestructive actions: use `danger` or `color=\"danger\"` on buttons / confirms—do not paint delete as primary.\n\n## Overrides\n\n```css\n:root {\n --m-color-primary: #0b6e4f;\n}\n[data-theme=\"dark\"] {\n --m-color-primary: #3ecf8e;\n}\n```\n\nOr derive with `createTheme({ seed: { colorPrimary: '…' } })` (see [Theme](/docs/theme)). Live preview: [Theme editor](/theme-editor).\n\n## Do / Don't\n\n| Do | Don't |\n| --- | --- |\n| One clear primary action; secondary via `secondary` / `outlined` | Several equally solid primary buttons |\n| Errors: `danger` + message | Red border alone for validation |\n| Weak rules with `--m-color-split` | Heavy borders everywhere |\n| Focus with `--m-focus-shadow` | Ad-hoc outline rings that ignore theme |\n\nNext: [Typography](/docs/design-typography).\n",
32200
32212
  "sections": [
32201
32213
  {
32202
32214
  "title": "",
@@ -32216,7 +32228,7 @@
32216
32228
  {
32217
32229
  "title": "Severity mapping",
32218
32230
  "id": "severity-mapping",
32219
- "body": "| `severity` | Maps to |\n| --- | --- |\n| (omit / primary) | `--m-color-primary` |\n| `secondary` | Neutral secondary treatment |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` family |\n\nDestructive actions: use `severity=\"danger\"` on buttons / confirms—do not paint delete as primary."
32231
+ "body": "| `severity` | Maps to |\n| --- | --- |\n| (omit / primary) | `--m-color-primary` |\n| `secondary` | Neutral secondary treatment |\n| `success` | `--m-color-success` |\n| `info` | `--m-color-info` |\n| `warning` / `warn` | `--m-color-warning` |\n| `help` | `--m-color-help` |\n| `danger` | `--m-color-danger` |\n| `contrast` | `--m-color-contrast` family |\n\nDestructive actions: use `danger` or `color=\"danger\"` on buttons / confirms—do not paint delete as primary."
32220
32232
  },
32221
32233
  {
32222
32234
  "title": "Overrides",
@@ -32861,7 +32873,7 @@
32861
32873
  "zh-CN": {
32862
32874
  "title": "Common Props",
32863
32875
  "description": "跨组件公共 props、Semantic DOM 与 pt 约定。",
32864
- "markdown": "---\ntitle: Common Props\norder: 7.5\ndescription: 跨组件公共 props、Semantic DOM 与 pt 约定。\n---\n\n# Common Props\n\n多数 Morya 组件共享同一套交互词表与样式落点,本页说明 morya 自己的命名与语义。细节交叉阅读:[约定](/docs/conventions)、[样式与 attrs](/docs/attrs)、[API 类型](/docs/types)、[设计令牌](/docs/design-tokens)。\n\n## 语义与外观\n\n| Prop | 含义 | 常见取值 |\n| -------------------- | ------------ | ------------------------------------------------------------------------------------------------------------- |\n| `severity` | 语义色 | `primary`(常可省略)/ `secondary` / `success` / `info` / `warning`(`warn`)/ `help` / `danger` / `contrast` |\n| `variant` | 外观快捷方式 | 随组件:`outlined` / `dashed` / `text` / `link` / `ghost` / `quaternary` / 输入框 `filled` 等 |\n| `size` | 控件尺寸 | `small` / `medium` / `large`(兼容 `sm` / `md` / `lg`);未传常继承 Config |\n| `disabled` | 禁用 | 交互与点击关闭;视觉用 `--m-opacity-disabled` 等 |\n| `loading` | 加载中 | 常见于 Button;阻止重复提交 |\n| `fluid` | 通栏 | 宽度撑满父级 |\n| `status` / `invalid` | 表单校验态 | 如 `error` / `warning`;配合 `error-message` |\n\n布尔形态(`outlined`、`text`、`link`…)与 `variant` 等价时可择一;**severity 管色,variant 管形**,可组合(如 `severity=\"danger\"` + `outlined`)。\n\n## 样式落点:class / style / 事件\n\n复合组件不是「根 = 原生控件」。attrs 三类落点:\n\n| 类型 | 例子 | `class` / `style` / 多数 attrs | 事件 `@xxx` |\n| ---------- | ---------------- | -------------------------------- | ----------------- |\n| 字段 | Input、Select | 外层 field 根 | 内层 input / 控件 |\n| Label 控件 | Checkbox、Switch | 可见 `<label>` | hidden `<input>` |\n| 容器 | Card、Tabs | 对外根(Dialog 的 class 在遮罩) | 同层 |\n| 叶子 | Button、Tag | 交互元素本身 | 同元素 |\n\n完整规则与演示:[样式与 attrs](/docs/attrs)。\n\n## Semantic DOM 与 `pt`\n\n**Semantic DOM**:文档里用稳定的结构名描述可定制节点(如 Button 的 root / icon / label),方便主题与测试定位。\n\n**`pt`(pass-through)**:按分段把 `class` / `style` / 原生属性合并到内层 DOM,键名即分段名。\n\n```vue\n<MInput\n label=\"API Key\"\n :pt=\"{\n root: { class: 'col-span-2' },\n input: { class: 'font-mono', autocomplete: 'off' },\n }\"\n/>\n```\n\n常见键:\n\n| 形态 | `pt` 键 |\n| ----------- | ------------------------------------------------------------------------- |\n| 字段 | `root`、`label`、`input` / `control`,部分有 `prefix` / `suffix` / `help` |\n| Checkbox 等 | `root`、`input` |\n| 单根容器 | `root` |\n| 复杂组件 | 额外键见该组件文档(如 Splitter 的 `gutter`) |\n\n类型:`PassThroughPart`、`FieldPassThrough`、`RootPassThrough` 等见 [API 类型](/docs/types)。同名 `class` / `style` 与已有绑定**合并**,非整段覆盖。\n\n叶子组件(如 `MButton`)通常直接把 `class` 绑在 `<button>` 上;`MButtonGroup` 等仍可用 `pt.root`。结构说明写在各组件 **Semantic DOM** 小节(示范:[Button](/components/Button))。\n\n## 全局默认\n\n`MConfigProvider` / `createMoryaUI` 可下发默认 `size`、`density`、`inputVariant`、`appendTo`、`zIndex`、`locale`、`componentDefaults`、`motion` 等——见 [全局配置](/docs/config)。视觉层仍用 [主题](/docs/theme) 的 `useTheme` / 令牌覆盖。\n\n## 建议与避免\n\n| 建议 | 避免 |\n| ----------------------------------------------------- | ------------------------------------- |\n| 跨组件统一 `severity` 词表 | 同一产品里混用 `type=\"danger\"` 等异名 |\n| 布局 class 加在字段根 | 指望 `class` 自动落到内层 input |\n| 用 `pt` 改前缀 / 控件细节 | 为改一处 class 去 fork 组件 |\n| Semantic DOM 名称与 BEM(`.m-button__label`)对齐记忆 | 臆造未文档化的 `pt` 键 |\n",
32876
+ "markdown": "---\ntitle: Common Props\norder: 7.5\ndescription: 跨组件公共 props、Semantic DOM 与 pt 约定。\n---\n\n# Common Props\n\n多数 Morya 组件共享同一套交互词表与样式落点,本页说明 morya 自己的命名与语义。细节交叉阅读:[约定](/docs/conventions)、[样式与 attrs](/docs/attrs)、[API 类型](/docs/types)、[设计令牌](/docs/design-tokens)。\n\n## 语义与外观\n\n| Prop | 含义 | 常见取值 |\n| -------------------- | ------------ | ------------------------------------------------------------------------------------------------------------- |\n| `severity` | 语义色 | Badge / Tag / Alert / Message 等:`primary` / `secondary` / `success` / `info` / `warning`(`warn`)/ `danger` / `contrast` |\n| `type` / `color` / `variant` | Button 外观 | Button 用 `type`(糖)+ `color` + `variant`(`solid` / `outlined` / `dashed` / `filled` / `text` / `link`);默认 `color=default` + `variant=outlined`;主实心用 `type=\"primary\"` |\n| `size` | 控件尺寸 | `small` / `medium` / `large`(兼容 `sm` / `md` / `lg`);未传常继承 Config |\n| `disabled` | 禁用 | 交互与点击关闭;视觉用 `--m-opacity-disabled` 等 |\n| `loading` | 加载中 | 常见于 Button;阻止重复提交 |\n| `fluid` / `block` | 通栏 | 多数字段用 `fluid`;Button / ButtonGroup 用 `block` |\n| `status` / `invalid` | 表单校验态 | 如 `error` / `warning`;配合 `error-message` |\n\n**Badge / Tag / Alert 等**:`severity` 管色。**Button**:`type` / `color` / `variant` 管色与形(如 `type=\"primary\"`,或 `color=\"danger\"` + `variant=\"outlined\"`);危险实心可用 `type=\"primary\" danger`。\n\n## 样式落点:class / style / 事件\n\n复合组件不是「根 = 原生控件」。attrs 三类落点:\n\n| 类型 | 例子 | `class` / `style` / 多数 attrs | 事件 `@xxx` |\n| ---------- | ---------------- | -------------------------------- | ----------------- |\n| 字段 | Input、Select | 外层 field 根 | 内层 input / 控件 |\n| Label 控件 | Checkbox、Switch | 可见 `<label>` | hidden `<input>` |\n| 容器 | Card、Tabs | 对外根(Dialog 的 class 在遮罩) | 同层 |\n| 叶子 | Button、Tag | 交互元素本身 | 同元素 |\n\n完整规则与演示:[样式与 attrs](/docs/attrs)。\n\n## Semantic DOM 与 `pt`\n\n**Semantic DOM**:文档里用稳定的结构名描述可定制节点(如 Button 的 root / icon / label),方便主题与测试定位。\n\n**`pt`(pass-through)**:按分段把 `class` / `style` / 原生属性合并到内层 DOM,键名即分段名。\n\n```vue\n<MInput\n label=\"API Key\"\n :pt=\"{\n root: { class: 'col-span-2' },\n input: { class: 'font-mono', autocomplete: 'off' },\n }\"\n/>\n```\n\n常见键:\n\n| 形态 | `pt` 键 |\n| ----------- | ------------------------------------------------------------------------- |\n| 字段 | `root`、`label`、`input` / `control`,部分有 `prefix` / `suffix` / `help` |\n| Checkbox 等 | `root`、`input` |\n| 单根容器 | `root` |\n| 复杂组件 | 额外键见该组件文档(如 Splitter 的 `gutter`) |\n\n类型:`PassThroughPart`、`FieldPassThrough`、`RootPassThrough` 等见 [API 类型](/docs/types)。同名 `class` / `style` 与已有绑定**合并**,非整段覆盖。\n\n叶子组件(如 `MButton`)通常直接把 `class` 绑在 `<button>` 上;`MButtonGroup` 等仍可用 `pt.root`。结构说明写在各组件 **Semantic DOM** 小节(示范:[Button](/components/Button))。\n\n## 全局默认\n\n`MConfigProvider` / `createMoryaUI` 可下发默认 `size`、`density`、`inputVariant`、`appendTo`、`zIndex`、`locale`、`componentDefaults`、`motion` 等——见 [全局配置](/docs/config)。视觉层仍用 [主题](/docs/theme) 的 `useTheme` / 令牌覆盖。\n\n## 建议与避免\n\n| 建议 | 避免 |\n| ----------------------------------------------------- | ------------------------------------- |\n| Badge / Tag / Alert 用 `severity`;Button 用 `type` / `color` / `variant` | 在 Button 上继续写已移除的 `severity` / `fluid` / `outlined` 布尔 |\n| 布局 class 加在字段根 | 指望 `class` 自动落到内层 input |\n| 用 `pt` 改前缀 / 控件细节 | 为改一处 class 去 fork 组件 |\n| Semantic DOM 名称与 BEM(`.m-button__label`)对齐记忆 | 臆造未文档化的 `pt` 键 |\n",
32865
32877
  "sections": [
32866
32878
  {
32867
32879
  "title": "",
@@ -32871,7 +32883,7 @@
32871
32883
  {
32872
32884
  "title": "语义与外观",
32873
32885
  "id": "语义与外观",
32874
- "body": "| Prop | 含义 | 常见取值 |\n| -------------------- | ------------ | ------------------------------------------------------------------------------------------------------------- |\n| `severity` | 语义色 | `primary`(常可省略)/ `secondary` / `success` / `info` / `warning`(`warn`)/ `help` / `danger` / `contrast` |\n| `variant` | 外观快捷方式 | 随组件:`outlined` / `dashed` / `text` / `link` / `ghost` / `quaternary` / 输入框 `filled` 等 |\n| `size` | 控件尺寸 | `small` / `medium` / `large`(兼容 `sm` / `md` / `lg`);未传常继承 Config |\n| `disabled` | 禁用 | 交互与点击关闭;视觉用 `--m-opacity-disabled` 等 |\n| `loading` | 加载中 | 常见于 Button;阻止重复提交 |\n| `fluid` | 通栏 | 宽度撑满父级 |\n| `status` / `invalid` | 表单校验态 | 如 `error` / `warning`;配合 `error-message` |\n\n布尔形态(`outlined`、`text`、`link`…)与 `variant` 等价时可择一;**severity 管色,variant 管形**,可组合(如 `severity=\"danger\"` + `outlined`)。"
32886
+ "body": "| Prop | 含义 | 常见取值 |\n| -------------------- | ------------ | ------------------------------------------------------------------------------------------------------------- |\n| `severity` | 语义色 | Badge / Tag / Alert / Message 等:`primary` / `secondary` / `success` / `info` / `warning`(`warn`)/ `danger` / `contrast` |\n| `type` / `color` / `variant` | Button 外观 | Button 用 `type`(糖)+ `color` + `variant`(`solid` / `outlined` / `dashed` / `filled` / `text` / `link`);默认 `color=default` + `variant=outlined`;主实心用 `type=\"primary\"` |\n| `size` | 控件尺寸 | `small` / `medium` / `large`(兼容 `sm` / `md` / `lg`);未传常继承 Config |\n| `disabled` | 禁用 | 交互与点击关闭;视觉用 `--m-opacity-disabled` 等 |\n| `loading` | 加载中 | 常见于 Button;阻止重复提交 |\n| `fluid` / `block` | 通栏 | 多数字段用 `fluid`;Button / ButtonGroup 用 `block` |\n| `status` / `invalid` | 表单校验态 | 如 `error` / `warning`;配合 `error-message` |\n\n**Badge / Tag / Alert 等**:`severity` 管色。**Button**:`type` / `color` / `variant` 管色与形(如 `type=\"primary\"`,或 `color=\"danger\"` + `variant=\"outlined\"`);危险实心可用 `type=\"primary\" danger`。"
32875
32887
  },
32876
32888
  {
32877
32889
  "title": "样式落点:class / style / 事件",
@@ -32891,14 +32903,14 @@
32891
32903
  {
32892
32904
  "title": "建议与避免",
32893
32905
  "id": "建议与避免",
32894
- "body": "| 建议 | 避免 |\n| ----------------------------------------------------- | ------------------------------------- |\n| 跨组件统一 `severity` 词表 | 同一产品里混用 `type=\"danger\"` 等异名 |\n| 布局 class 加在字段根 | 指望 `class` 自动落到内层 input |\n| 用 `pt` 改前缀 / 控件细节 | 为改一处 class 去 fork 组件 |\n| Semantic DOM 名称与 BEM(`.m-button__label`)对齐记忆 | 臆造未文档化的 `pt` 键 |"
32906
+ "body": "| 建议 | 避免 |\n| ----------------------------------------------------- | ------------------------------------- |\n| Badge / Tag / Alert 用 `severity`;Button 用 `type` / `color` / `variant` | 在 Button 上继续写已移除的 `severity` / `fluid` / `outlined` 布尔 |\n| 布局 class 加在字段根 | 指望 `class` 自动落到内层 input |\n| 用 `pt` 改前缀 / 控件细节 | 为改一处 class 去 fork 组件 |\n| Semantic DOM 名称与 BEM(`.m-button__label`)对齐记忆 | 臆造未文档化的 `pt` 键 |"
32895
32907
  }
32896
32908
  ]
32897
32909
  },
32898
32910
  "en-US": {
32899
32911
  "title": "Common Props",
32900
32912
  "description": "Shared props, Semantic DOM, and pt conventions across components.",
32901
- "markdown": "---\ntitle: Common Props\norder: 7.5\ndescription: Shared props, Semantic DOM, and pt conventions across components.\n---\n\n# Common Props\n\nMost Morya components share one interaction vocabulary and style targeting model. This page documents morya's own names and semantics. Cross-links: [Conventions](/docs/conventions), [Attrs](/docs/attrs), [API types](/docs/types), [Design tokens](/docs/design-tokens).\n\n## Semantics and appearance\n\n| Prop | Meaning | Common values |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `severity` | Semantic color | `primary` (often omitted) / `secondary` / `success` / `info` / `warning` (`warn`) / `help` / `danger` / `contrast` |\n| `variant` | Appearance shortcut | Per component: `outlined` / `dashed` / `text` / `link` / `ghost` / `quaternary` / input `filled`, etc. |\n| `size` | Control size | `small` / `medium` / `large` (`sm` / `md` / `lg` aliases); often inherits Config when omitted |\n| `disabled` | Disabled | Blocks interaction; visuals use `--m-opacity-disabled` and related tokens |\n| `loading` | Busy | Common on Button; prevents double submit |\n| `fluid` | Full width | Stretch to parent width |\n| `status` / `invalid` | Form validation | e.g. `error` / `warning`; pair with `error-message` |\n\nBoolean mirrors (`outlined`, `text`, `link`, …) may equal `variant`—pick one. **`severity` colors; `variant` shapes**; they compose (e.g. `severity=\"danger\"` + `outlined`).\n\n## Where class / style / events land\n\nComposite components are not “root = native control”. Three targeting patterns:\n\n| Kind | Examples | `class` / `style` / most attrs | Events `@xxx` |\n| ------------- | ---------------- | ------------------------------------- | --------------------- |\n| Field | Input, Select | Outer field root | Inner input / control |\n| Label control | Checkbox, Switch | Visible `<label>` | Hidden `<input>` |\n| Container | Card, Tabs | Public root (Dialog `class` on scrim) | Same layer |\n| Leaf | Button, Tag | Interactive element itself | Same element |\n\nFull rules and demos: [Attrs](/docs/attrs).\n\n## Semantic DOM and `pt`\n\n**Semantic DOM**: stable structural names in docs for customizable nodes (e.g. Button root / icon / label)—handy for theming and tests.\n\n**`pt` (pass-through)**: merge `class` / `style` / native attrs onto inner DOM by segment key.\n\n```vue\n<MInput\n label=\"API Key\"\n :pt=\"{\n root: { class: 'col-span-2' },\n input: { class: 'font-mono', autocomplete: 'off' },\n }\"\n/>\n```\n\nCommon keys:\n\n| Shape | `pt` keys |\n| --------------------- | ---------------------------------------------------------------------------- |\n| Field | `root`, `label`, `input` / `control`; sometimes `prefix` / `suffix` / `help` |\n| Checkbox-like | `root`, `input` |\n| Single-root container | `root` |\n| Complex | Extra keys in that component’s docs (e.g. Splitter `gutter`) |\n\nTypes: `PassThroughPart`, `FieldPassThrough`, `RootPassThrough`, … in [API types](/docs/types). Same-named `class` / `style` **merge** with existing bindings rather than replace wholesale.\n\nLeaf components such as `MButton` bind `class` on the `<button>` directly; groups like `MButtonGroup` still accept `pt.root`. Structure notes live under each component’s **Semantic DOM** section (example: [Button](/components/Button)).\n\n## Global defaults\n\n`MConfigProvider` / `createMoryaUI` can supply default `size`, `density`, `inputVariant`, `appendTo`, `zIndex`, `locale`, `componentDefaults`, `motion`, and more — see [Configuration](/docs/config). Visual layer remains [Theme](/docs/theme) via `useTheme` / token overrides.\n\n## Do / Don't\n\n| Do | Don't |\n| ------------------------------------------------------ | ---------------------------------------------------------- |\n| Keep one `severity` vocabulary across components | Mix foreign names like `type=\"danger\"` in the same product |\n| Put layout `class` on the field root | Expect `class` to fall through onto the inner input |\n| Use `pt` for prefix / inner tweaks | Fork a component to change one class |\n| Align Semantic DOM names with BEM (`.m-button__label`) | Invent undocumented `pt` keys |\n",
32913
+ "markdown": "---\ntitle: Common Props\norder: 7.5\ndescription: Shared props, Semantic DOM, and pt conventions across components.\n---\n\n# Common Props\n\nMost Morya components share one interaction vocabulary and style targeting model. This page documents morya's own names and semantics. Cross-links: [Conventions](/docs/conventions), [Attrs](/docs/attrs), [API types](/docs/types), [Design tokens](/docs/design-tokens).\n\n## Semantics and appearance\n\n| Prop | Meaning | Common values |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `severity` | Semantic color | Badge / Tag / Alert / Message: `primary` / `secondary` / `success` / `info` / `warning` (`warn`) / `danger` / `contrast` |\n| `type` / `color` / `variant` | Button appearance | Button uses `type` (sugar) + `color` + `variant` (`solid` / `outlined` / `dashed` / `filled` / `text` / `link`); default is `color=default` + `variant=outlined`; solid primary needs `type=\"primary\"` |\n| `size` | Control size | `small` / `medium` / `large` (`sm` / `md` / `lg` aliases); often inherits Config when omitted |\n| `disabled` | Disabled | Blocks interaction; visuals use `--m-opacity-disabled` and related tokens |\n| `loading` | Busy | Common on Button; prevents double submit |\n| `fluid` / `block` | Full width | Most fields use `fluid`; Button / ButtonGroup use `block` |\n| `status` / `invalid` | Form validation | e.g. `error` / `warning`; pair with `error-message` |\n\n**Badge / Tag / Alert**: `severity` sets tone. **Button**: `type` / `color` / `variant` set tone and shape (e.g. `type=\"primary\"`, or `color=\"danger\"` + `variant=\"outlined\"`); solid danger can be `type=\"primary\" danger`.\n\n## Where class / style / events land\n\nComposite components are not “root = native control”. Three targeting patterns:\n\n| Kind | Examples | `class` / `style` / most attrs | Events `@xxx` |\n| ------------- | ---------------- | ------------------------------------- | --------------------- |\n| Field | Input, Select | Outer field root | Inner input / control |\n| Label control | Checkbox, Switch | Visible `<label>` | Hidden `<input>` |\n| Container | Card, Tabs | Public root (Dialog `class` on scrim) | Same layer |\n| Leaf | Button, Tag | Interactive element itself | Same element |\n\nFull rules and demos: [Attrs](/docs/attrs).\n\n## Semantic DOM and `pt`\n\n**Semantic DOM**: stable structural names in docs for customizable nodes (e.g. Button root / icon / label)—handy for theming and tests.\n\n**`pt` (pass-through)**: merge `class` / `style` / native attrs onto inner DOM by segment key.\n\n```vue\n<MInput\n label=\"API Key\"\n :pt=\"{\n root: { class: 'col-span-2' },\n input: { class: 'font-mono', autocomplete: 'off' },\n }\"\n/>\n```\n\nCommon keys:\n\n| Shape | `pt` keys |\n| --------------------- | ---------------------------------------------------------------------------- |\n| Field | `root`, `label`, `input` / `control`; sometimes `prefix` / `suffix` / `help` |\n| Checkbox-like | `root`, `input` |\n| Single-root container | `root` |\n| Complex | Extra keys in that component’s docs (e.g. Splitter `gutter`) |\n\nTypes: `PassThroughPart`, `FieldPassThrough`, `RootPassThrough`, … in [API types](/docs/types). Same-named `class` / `style` **merge** with existing bindings rather than replace wholesale.\n\nLeaf components such as `MButton` bind `class` on the `<button>` directly; groups like `MButtonGroup` still accept `pt.root`. Structure notes live under each component’s **Semantic DOM** section (example: [Button](/components/Button)).\n\n## Global defaults\n\n`MConfigProvider` / `createMoryaUI` can supply default `size`, `density`, `inputVariant`, `appendTo`, `zIndex`, `locale`, `componentDefaults`, `motion`, and more — see [Configuration](/docs/config). Visual layer remains [Theme](/docs/theme) via `useTheme` / token overrides.\n\n## Do / Don't\n\n| Do | Don't |\n| ------------------------------------------------------ | ---------------------------------------------------------- |\n| Use `severity` on Badge / Tag / Alert; `type` / `color` / `variant` on Button | Keep removed Button props (`severity` / `fluid` / boolean `outlined`) |\n| Put layout `class` on the field root | Expect `class` to fall through onto the inner input |\n| Use `pt` for prefix / inner tweaks | Fork a component to change one class |\n| Align Semantic DOM names with BEM (`.m-button__label`) | Invent undocumented `pt` keys |\n",
32902
32914
  "sections": [
32903
32915
  {
32904
32916
  "title": "",
@@ -32908,7 +32920,7 @@
32908
32920
  {
32909
32921
  "title": "Semantics and appearance",
32910
32922
  "id": "semantics-and-appearance",
32911
- "body": "| Prop | Meaning | Common values |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `severity` | Semantic color | `primary` (often omitted) / `secondary` / `success` / `info` / `warning` (`warn`) / `help` / `danger` / `contrast` |\n| `variant` | Appearance shortcut | Per component: `outlined` / `dashed` / `text` / `link` / `ghost` / `quaternary` / input `filled`, etc. |\n| `size` | Control size | `small` / `medium` / `large` (`sm` / `md` / `lg` aliases); often inherits Config when omitted |\n| `disabled` | Disabled | Blocks interaction; visuals use `--m-opacity-disabled` and related tokens |\n| `loading` | Busy | Common on Button; prevents double submit |\n| `fluid` | Full width | Stretch to parent width |\n| `status` / `invalid` | Form validation | e.g. `error` / `warning`; pair with `error-message` |\n\nBoolean mirrors (`outlined`, `text`, `link`, …) may equal `variant`—pick one. **`severity` colors; `variant` shapes**; they compose (e.g. `severity=\"danger\"` + `outlined`)."
32923
+ "body": "| Prop | Meaning | Common values |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `severity` | Semantic color | Badge / Tag / Alert / Message: `primary` / `secondary` / `success` / `info` / `warning` (`warn`) / `danger` / `contrast` |\n| `type` / `color` / `variant` | Button appearance | Button uses `type` (sugar) + `color` + `variant` (`solid` / `outlined` / `dashed` / `filled` / `text` / `link`); default is `color=default` + `variant=outlined`; solid primary needs `type=\"primary\"` |\n| `size` | Control size | `small` / `medium` / `large` (`sm` / `md` / `lg` aliases); often inherits Config when omitted |\n| `disabled` | Disabled | Blocks interaction; visuals use `--m-opacity-disabled` and related tokens |\n| `loading` | Busy | Common on Button; prevents double submit |\n| `fluid` / `block` | Full width | Most fields use `fluid`; Button / ButtonGroup use `block` |\n| `status` / `invalid` | Form validation | e.g. `error` / `warning`; pair with `error-message` |\n\n**Badge / Tag / Alert**: `severity` sets tone. **Button**: `type` / `color` / `variant` set tone and shape (e.g. `type=\"primary\"`, or `color=\"danger\"` + `variant=\"outlined\"`); solid danger can be `type=\"primary\" danger`."
32912
32924
  },
32913
32925
  {
32914
32926
  "title": "Where class / style / events land",
@@ -32928,7 +32940,7 @@
32928
32940
  {
32929
32941
  "title": "Do / Don't",
32930
32942
  "id": "do-don-t",
32931
- "body": "| Do | Don't |\n| ------------------------------------------------------ | ---------------------------------------------------------- |\n| Keep one `severity` vocabulary across components | Mix foreign names like `type=\"danger\"` in the same product |\n| Put layout `class` on the field root | Expect `class` to fall through onto the inner input |\n| Use `pt` for prefix / inner tweaks | Fork a component to change one class |\n| Align Semantic DOM names with BEM (`.m-button__label`) | Invent undocumented `pt` keys |"
32943
+ "body": "| Do | Don't |\n| ------------------------------------------------------ | ---------------------------------------------------------- |\n| Use `severity` on Badge / Tag / Alert; `type` / `color` / `variant` on Button | Keep removed Button props (`severity` / `fluid` / boolean `outlined`) |\n| Put layout `class` on the field root | Expect `class` to fall through onto the inner input |\n| Use `pt` for prefix / inner tweaks | Fork a component to change one class |\n| Align Semantic DOM names with BEM (`.m-button__label`) | Invent undocumented `pt` keys |"
32932
32944
  }
32933
32945
  ]
32934
32946
  }
@@ -32945,24 +32957,24 @@
32945
32957
  "zh-CN": {
32946
32958
  "title": "API 类型",
32947
32959
  "description": "文档 Props 里常见类型名的结构与含义。",
32948
- "markdown": "---\ntitle: API 类型\norder: 8\ndescription: 文档 Props 里常见类型名的结构与含义。\n---\n\n# API 类型\n\n组件文档 Props 表里出现的类型名,在这里查具体结构。包入口也导出同名类型,可在业务代码里 `import type { … } from 'morya-ui'`(以各组件 `types.ts` 为准)。\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\n单个 DOM 节点上要合并的属性 bag。`pt.<part>` 的值就是这个类型。\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\n常用键:`class`、`style`、`data-*`、`onClick` / `onKeydown`(Vue 事件监听写法)、以及该节点合法的原生 HTML 属性。\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\n单根容器(Card、Dialog 遮罩、Tabs 等):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch(可见根是 `<label>`,hidden input 单独一段):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // 一般是 label\n input?: PassThroughPart // 原生 input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\n表单字段(Input、Select、DatePicker 等):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // 外层 .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // 触发器 / 组合控件(Select 等)\n input?: PassThroughPart // 原生 input / textarea\n}\n```\n\n具体组件支持哪些键,见该组件文档的 **类型** 或 **pt** 小节。\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) 在 `FieldPassThrough` 基础上多了前后缀等:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) 在 `RootPassThrough` 上增加分隔条与面板:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\n分隔条外观也可用 `resizeTriggerClass` / `resizeTriggerStyle`,内容用 `#resize-trigger`(别名 `#gutter`)。\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\n控件尺寸,多数表单 / 按钮组件的 `size` prop:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` 为兼容别名;未传时通常继承 [ConfigProvider](/docs/config) 的 `size`。\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n输入框视觉变体:\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonSeverity\">ButtonSeverity</h3>\n\n按钮语义色([`Button`](/components/Button)、Dialog 页脚等):\n\n```ts\ntype ButtonSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning' // 'warn' 为别名\n | 'help'\n | 'danger'\n | 'contrast'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\n浮层 Teleport 挂载目标(Dialog、Select 菜单、Toast 等):\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'`(默认):挂到 document.body \n- `'self'`:不 Teleport,就地渲染 \n- 也常见 `appendTo: false`(运行时兼容,同 `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\n关闭 / 确认前的拦截函数。返回 `false`(含 Promise 解析为 `false`)则**不继续**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\n用于 Dialog `beforeClose`、`onPositiveClick`,ConfirmDialog / ConfirmPopup 的 `beforeAccept` 等。\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) 选项项:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) 选项分组(混入 `options` 渲染分组标题行):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\n单选为标量;`multiple` 时为数组。\n\n<h3 id=\"IconName\">IconName</h3>\n\n[`MIcon`](/components/Icon) / [`Button`](/components/Button) 的 `icon` / `name` 使用的注册名,例如 `'search'`、`'chevron-down'`。完整列表见 Icon 文档注册表。\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nMenu / Dropdown / ContextMenu 等导航项的公共字段:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nMessage、Tag 等的状态色:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\n更细的组件专属类型(如 `TableServerOptions`、`MenuItem`)写在对应组件页 **类型** 小节;这里只列跨组件复用的名字。\n",
32960
+ "markdown": "---\ntitle: API 类型\norder: 8\ndescription: 文档 Props 里常见类型名的结构与含义。\n---\n\n# API 类型\n\n组件文档 Props 表里出现的类型名,在这里查具体结构。包入口也导出同名类型,可在业务代码里 `import type { … } from 'morya-ui'`(以各组件 `types.ts` 为准)。\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\n单个 DOM 节点上要合并的属性 bag。`pt.<part>` 的值就是这个类型。\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\n常用键:`class`、`style`、`data-*`、`onClick` / `onKeydown`(Vue 事件监听写法)、以及该节点合法的原生 HTML 属性。\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\n单根容器(Card、Dialog 遮罩、Tabs 等):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch(可见根是 `<label>`,hidden input 单独一段):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // 一般是 label\n input?: PassThroughPart // 原生 input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\n表单字段(Input、Select、DatePicker 等):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // 外层 .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // 触发器 / 组合控件(Select 等)\n input?: PassThroughPart // 原生 input / textarea\n}\n```\n\n具体组件支持哪些键,见该组件文档的 **类型** 或 **pt** 小节。\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) 在 `FieldPassThrough` 基础上多了前后缀等:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) 在 `RootPassThrough` 上增加分隔条与面板:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\n分隔条外观也可用 `resizeTriggerClass` / `resizeTriggerStyle`,内容用 `#resize-trigger`(别名 `#gutter`)。\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\n控件尺寸,多数表单 / 按钮组件的 `size` prop:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` 为兼容别名;未传时通常继承 [ConfigProvider](/docs/config) 的 `size`。\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n输入框视觉变体:\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonType\">ButtonType</h3>\n\n按钮类型糖([`Button`](/components/Button)):\n\n```ts\ntype ButtonType = 'default' | 'primary' | 'dashed' | 'link' | 'text'\n```\n\n<h3 id=\"ButtonColor\">ButtonColor</h3>\n\n按钮颜色轴(Button、ConfirmDialog `acceptColor`、Dialog `positiveColor` 等):\n\n```ts\ntype ButtonColor =\n | 'default'\n | 'primary'\n | 'danger'\n | 'success'\n | 'info'\n | 'warning'\n | 'help'\n | 'contrast'\n | 'link'\n```\n\n<h3 id=\"ButtonVariant\">ButtonVariant</h3>\n\n按钮变体轴:\n\n```ts\ntype ButtonVariant = 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\n浮层 Teleport 挂载目标(Dialog、Select 菜单、Toast 等):\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'`(默认):挂到 document.body \n- `'self'`:不 Teleport,就地渲染 \n- 也常见 `appendTo: false`(运行时兼容,同 `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\n关闭 / 确认前的拦截函数。返回 `false`(含 Promise 解析为 `false`)则**不继续**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\n用于 Dialog `beforeClose`、`onPositiveClick`,ConfirmDialog / ConfirmPopup 的 `beforeAccept` 等。\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) 选项项:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) 选项分组(混入 `options` 渲染分组标题行):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\n单选为标量;`multiple` 时为数组。\n\n<h3 id=\"IconName\">IconName</h3>\n\n[`MIcon`](/components/Icon) / [`Button`](/components/Button) 的 `icon` / `name` 使用的注册名,例如 `'search'`、`'chevron-down'`。完整列表见 Icon 文档注册表。\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nMenu / Dropdown / ContextMenu 等导航项的公共字段:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nMessage、Tag 等的状态色:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\n更细的组件专属类型(如 `TableServerOptions`、`MenuItem`)写在对应组件页 **类型** 小节;这里只列跨组件复用的名字。\n",
32949
32961
  "sections": [
32950
32962
  {
32951
32963
  "title": "",
32952
32964
  "id": "overview",
32953
- "body": "# API 类型\n\n组件文档 Props 表里出现的类型名,在这里查具体结构。包入口也导出同名类型,可在业务代码里 `import type { … } from 'morya-ui'`(以各组件 `types.ts` 为准)。\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\n单个 DOM 节点上要合并的属性 bag。`pt.<part>` 的值就是这个类型。\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\n常用键:`class`、`style`、`data-*`、`onClick` / `onKeydown`(Vue 事件监听写法)、以及该节点合法的原生 HTML 属性。\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\n单根容器(Card、Dialog 遮罩、Tabs 等):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch(可见根是 `<label>`,hidden input 单独一段):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // 一般是 label\n input?: PassThroughPart // 原生 input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\n表单字段(Input、Select、DatePicker 等):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // 外层 .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // 触发器 / 组合控件(Select 等)\n input?: PassThroughPart // 原生 input / textarea\n}\n```\n\n具体组件支持哪些键,见该组件文档的 **类型** 或 **pt** 小节。\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) 在 `FieldPassThrough` 基础上多了前后缀等:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) 在 `RootPassThrough` 上增加分隔条与面板:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\n分隔条外观也可用 `resizeTriggerClass` / `resizeTriggerStyle`,内容用 `#resize-trigger`(别名 `#gutter`)。\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\n控件尺寸,多数表单 / 按钮组件的 `size` prop:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` 为兼容别名;未传时通常继承 [ConfigProvider](/docs/config) 的 `size`。\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n输入框视觉变体:\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonSeverity\">ButtonSeverity</h3>\n\n按钮语义色([`Button`](/components/Button)、Dialog 页脚等):\n\n```ts\ntype ButtonSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning' // 'warn' 为别名\n | 'help'\n | 'danger'\n | 'contrast'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\n浮层 Teleport 挂载目标(Dialog、Select 菜单、Toast 等):\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'`(默认):挂到 document.body \n- `'self'`:不 Teleport,就地渲染 \n- 也常见 `appendTo: false`(运行时兼容,同 `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\n关闭 / 确认前的拦截函数。返回 `false`(含 Promise 解析为 `false`)则**不继续**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\n用于 Dialog `beforeClose`、`onPositiveClick`,ConfirmDialog / ConfirmPopup 的 `beforeAccept` 等。\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) 选项项:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) 选项分组(混入 `options` 渲染分组标题行):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\n单选为标量;`multiple` 时为数组。\n\n<h3 id=\"IconName\">IconName</h3>\n\n[`MIcon`](/components/Icon) / [`Button`](/components/Button) 的 `icon` / `name` 使用的注册名,例如 `'search'`、`'chevron-down'`。完整列表见 Icon 文档注册表。\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nMenu / Dropdown / ContextMenu 等导航项的公共字段:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nMessage、Tag 等的状态色:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\n更细的组件专属类型(如 `TableServerOptions`、`MenuItem`)写在对应组件页 **类型** 小节;这里只列跨组件复用的名字。"
32965
+ "body": "# API 类型\n\n组件文档 Props 表里出现的类型名,在这里查具体结构。包入口也导出同名类型,可在业务代码里 `import type { … } from 'morya-ui'`(以各组件 `types.ts` 为准)。\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\n单个 DOM 节点上要合并的属性 bag。`pt.<part>` 的值就是这个类型。\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\n常用键:`class`、`style`、`data-*`、`onClick` / `onKeydown`(Vue 事件监听写法)、以及该节点合法的原生 HTML 属性。\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\n单根容器(Card、Dialog 遮罩、Tabs 等):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch(可见根是 `<label>`,hidden input 单独一段):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // 一般是 label\n input?: PassThroughPart // 原生 input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\n表单字段(Input、Select、DatePicker 等):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // 外层 .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // 触发器 / 组合控件(Select 等)\n input?: PassThroughPart // 原生 input / textarea\n}\n```\n\n具体组件支持哪些键,见该组件文档的 **类型** 或 **pt** 小节。\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) 在 `FieldPassThrough` 基础上多了前后缀等:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) 在 `RootPassThrough` 上增加分隔条与面板:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\n分隔条外观也可用 `resizeTriggerClass` / `resizeTriggerStyle`,内容用 `#resize-trigger`(别名 `#gutter`)。\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\n控件尺寸,多数表单 / 按钮组件的 `size` prop:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` 为兼容别名;未传时通常继承 [ConfigProvider](/docs/config) 的 `size`。\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n输入框视觉变体:\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonType\">ButtonType</h3>\n\n按钮类型糖([`Button`](/components/Button)):\n\n```ts\ntype ButtonType = 'default' | 'primary' | 'dashed' | 'link' | 'text'\n```\n\n<h3 id=\"ButtonColor\">ButtonColor</h3>\n\n按钮颜色轴(Button、ConfirmDialog `acceptColor`、Dialog `positiveColor` 等):\n\n```ts\ntype ButtonColor =\n | 'default'\n | 'primary'\n | 'danger'\n | 'success'\n | 'info'\n | 'warning'\n | 'help'\n | 'contrast'\n | 'link'\n```\n\n<h3 id=\"ButtonVariant\">ButtonVariant</h3>\n\n按钮变体轴:\n\n```ts\ntype ButtonVariant = 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\n浮层 Teleport 挂载目标(Dialog、Select 菜单、Toast 等):\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'`(默认):挂到 document.body \n- `'self'`:不 Teleport,就地渲染 \n- 也常见 `appendTo: false`(运行时兼容,同 `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\n关闭 / 确认前的拦截函数。返回 `false`(含 Promise 解析为 `false`)则**不继续**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\n用于 Dialog `beforeClose`、`onPositiveClick`,ConfirmDialog / ConfirmPopup 的 `beforeAccept` 等。\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) 选项项:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) 选项分组(混入 `options` 渲染分组标题行):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\n单选为标量;`multiple` 时为数组。\n\n<h3 id=\"IconName\">IconName</h3>\n\n[`MIcon`](/components/Icon) / [`Button`](/components/Button) 的 `icon` / `name` 使用的注册名,例如 `'search'`、`'chevron-down'`。完整列表见 Icon 文档注册表。\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nMenu / Dropdown / ContextMenu 等导航项的公共字段:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nMessage、Tag 等的状态色:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\n更细的组件专属类型(如 `TableServerOptions`、`MenuItem`)写在对应组件页 **类型** 小节;这里只列跨组件复用的名字。"
32954
32966
  }
32955
32967
  ]
32956
32968
  },
32957
32969
  "en-US": {
32958
32970
  "title": "API types",
32959
32971
  "description": "Shapes behind type names in component Props tables.",
32960
- "markdown": "---\ntitle: API types\norder: 8\ndescription: Shapes behind type names in component Props tables.\n---\n\n# API types\n\nLook up structures for names that appear in Props tables. The package re-exports the same names as TypeScript types (`import type { … } from 'morya-ui'`), per component `types.ts`.\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\nAttribute bag merged onto one DOM node—the value of `pt.<part>`.\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\nCommon keys: `class`, `style`, `data-*`, `onClick` / `onKeydown`, and valid native attributes for that element.\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\nSingle-root containers (Card, Dialog backdrop, Tabs, …):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch (visible `<label>` root + hidden input):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // usually the label\n input?: PassThroughPart // native input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\nForm fields (Input, Select, DatePicker, …):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // outer .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // trigger / composite control\n input?: PassThroughPart // native input / textarea\n}\n```\n\nWhich keys a component accepts is listed on that component’s **Types** or **pt** section.\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) extends `FieldPassThrough` with affixes:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) extends `RootPassThrough` with gutter and panes:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\nGutter look can also use `resizeTriggerClass` / `resizeTriggerStyle`; content goes in `#resize-trigger` (alias `#gutter`).\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\nControl size for many form / button props:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` are legacy aliases. Omitted `size` usually inherits [ConfigProvider](/docs/config).\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonSeverity\">ButtonSeverity</h3>\n\nButton / dialog footer tones:\n\n```ts\ntype ButtonSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning' // alias: 'warn'\n | 'help'\n | 'danger'\n | 'contrast'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\nOverlay Teleport target:\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'` (default) \n- `'self'` — render in place (no Teleport) \n- `false` is accepted at runtime (same idea as `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\nGuard before close / confirm. Return `false` (including from a Promise) to **abort**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\nUsed by Dialog `beforeClose`, ConfirmDialog `beforeAccept`, and similar.\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) option row:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) option group (mix into `options` to render a group header row):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\nScalar when single-select; array when `multiple`.\n\n<h3 id=\"IconName\">IconName</h3>\n\nRegistered icon id for [`MIcon`](/components/Icon) / [`Button`](/components/Button), e.g. `'search'`. See the Icon registry.\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nShared fields for Menu / Dropdown / ContextMenu items:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nStatus tone for Message, Tag, etc.:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\nComponent-only types (`TableServerOptions`, `MenuItem`, …) live under each component’s **Types** section; this page is for shared names only.\n",
32972
+ "markdown": "---\ntitle: API types\norder: 8\ndescription: Shapes behind type names in component Props tables.\n---\n\n# API types\n\nLook up structures for names that appear in Props tables. The package re-exports the same names as TypeScript types (`import type { … } from 'morya-ui'`), per component `types.ts`.\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\nAttribute bag merged onto one DOM node—the value of `pt.<part>`.\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\nCommon keys: `class`, `style`, `data-*`, `onClick` / `onKeydown`, and valid native attributes for that element.\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\nSingle-root containers (Card, Dialog backdrop, Tabs, …):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch (visible `<label>` root + hidden input):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // usually the label\n input?: PassThroughPart // native input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\nForm fields (Input, Select, DatePicker, …):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // outer .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // trigger / composite control\n input?: PassThroughPart // native input / textarea\n}\n```\n\nWhich keys a component accepts is listed on that component’s **Types** or **pt** section.\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) extends `FieldPassThrough` with affixes:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) extends `RootPassThrough` with gutter and panes:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\nGutter look can also use `resizeTriggerClass` / `resizeTriggerStyle`; content goes in `#resize-trigger` (alias `#gutter`).\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\nControl size for many form / button props:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` are legacy aliases. Omitted `size` usually inherits [ConfigProvider](/docs/config).\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonType\">ButtonType</h3>\n\nButton type sugar ([`Button`](/components/Button)):\n\n```ts\ntype ButtonType = 'default' | 'primary' | 'dashed' | 'link' | 'text'\n```\n\n<h3 id=\"ButtonColor\">ButtonColor</h3>\n\nButton color axis (Button, ConfirmDialog `acceptColor`, Dialog `positiveColor`, …):\n\n```ts\ntype ButtonColor =\n | 'default'\n | 'primary'\n | 'danger'\n | 'success'\n | 'info'\n | 'warning'\n | 'help'\n | 'contrast'\n | 'link'\n```\n\n<h3 id=\"ButtonVariant\">ButtonVariant</h3>\n\nButton variant axis:\n\n```ts\ntype ButtonVariant = 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\nOverlay Teleport target:\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'` (default) \n- `'self'` — render in place (no Teleport) \n- `false` is accepted at runtime (same idea as `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\nGuard before close / confirm. Return `false` (including from a Promise) to **abort**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\nUsed by Dialog `beforeClose`, ConfirmDialog `beforeAccept`, and similar.\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) option row:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) option group (mix into `options` to render a group header row):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\nScalar when single-select; array when `multiple`.\n\n<h3 id=\"IconName\">IconName</h3>\n\nRegistered icon id for [`MIcon`](/components/Icon) / [`Button`](/components/Button), e.g. `'search'`. See the Icon registry.\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nShared fields for Menu / Dropdown / ContextMenu items:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nStatus tone for Message, Tag, etc.:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\nComponent-only types (`TableServerOptions`, `MenuItem`, …) live under each component’s **Types** section; this page is for shared names only.\n",
32961
32973
  "sections": [
32962
32974
  {
32963
32975
  "title": "",
32964
32976
  "id": "overview",
32965
- "body": "# API types\n\nLook up structures for names that appear in Props tables. The package re-exports the same names as TypeScript types (`import type { … } from 'morya-ui'`), per component `types.ts`.\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\nAttribute bag merged onto one DOM node—the value of `pt.<part>`.\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\nCommon keys: `class`, `style`, `data-*`, `onClick` / `onKeydown`, and valid native attributes for that element.\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\nSingle-root containers (Card, Dialog backdrop, Tabs, …):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch (visible `<label>` root + hidden input):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // usually the label\n input?: PassThroughPart // native input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\nForm fields (Input, Select, DatePicker, …):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // outer .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // trigger / composite control\n input?: PassThroughPart // native input / textarea\n}\n```\n\nWhich keys a component accepts is listed on that component’s **Types** or **pt** section.\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) extends `FieldPassThrough` with affixes:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) extends `RootPassThrough` with gutter and panes:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\nGutter look can also use `resizeTriggerClass` / `resizeTriggerStyle`; content goes in `#resize-trigger` (alias `#gutter`).\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\nControl size for many form / button props:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` are legacy aliases. Omitted `size` usually inherits [ConfigProvider](/docs/config).\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonSeverity\">ButtonSeverity</h3>\n\nButton / dialog footer tones:\n\n```ts\ntype ButtonSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning' // alias: 'warn'\n | 'help'\n | 'danger'\n | 'contrast'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\nOverlay Teleport target:\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'` (default) \n- `'self'` — render in place (no Teleport) \n- `false` is accepted at runtime (same idea as `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\nGuard before close / confirm. Return `false` (including from a Promise) to **abort**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\nUsed by Dialog `beforeClose`, ConfirmDialog `beforeAccept`, and similar.\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) option row:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) option group (mix into `options` to render a group header row):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\nScalar when single-select; array when `multiple`.\n\n<h3 id=\"IconName\">IconName</h3>\n\nRegistered icon id for [`MIcon`](/components/Icon) / [`Button`](/components/Button), e.g. `'search'`. See the Icon registry.\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nShared fields for Menu / Dropdown / ContextMenu items:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nStatus tone for Message, Tag, etc.:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\nComponent-only types (`TableServerOptions`, `MenuItem`, …) live under each component’s **Types** section; this page is for shared names only."
32977
+ "body": "# API types\n\nLook up structures for names that appear in Props tables. The package re-exports the same names as TypeScript types (`import type { … } from 'morya-ui'`), per component `types.ts`.\n\n<h3 id=\"PassThroughPart\">PassThroughPart</h3>\n\nAttribute bag merged onto one DOM node—the value of `pt.<part>`.\n\n```ts\ntype PassThroughPart = Record<string, unknown>\n```\n\nCommon keys: `class`, `style`, `data-*`, `onClick` / `onKeydown`, and valid native attributes for that element.\n\n<h3 id=\"RootPassThrough\">RootPassThrough</h3>\n\nSingle-root containers (Card, Dialog backdrop, Tabs, …):\n\n```ts\ninterface RootPassThrough {\n root?: PassThroughPart\n}\n```\n\n<h3 id=\"ControlPassThrough\">ControlPassThrough</h3>\n\nCheckbox / Radio / Switch (visible `<label>` root + hidden input):\n\n```ts\ninterface ControlPassThrough {\n root?: PassThroughPart // usually the label\n input?: PassThroughPart // native input\n}\n```\n\n<h3 id=\"FieldPassThrough\">FieldPassThrough</h3>\n\nForm fields (Input, Select, DatePicker, …):\n\n```ts\ninterface FieldPassThrough {\n root?: PassThroughPart // outer .m-*-field\n label?: PassThroughPart\n control?: PassThroughPart // trigger / composite control\n input?: PassThroughPart // native input / textarea\n}\n```\n\nWhich keys a component accepts is listed on that component’s **Types** or **pt** section.\n\n<h3 id=\"InputPassThrough\">InputPassThrough</h3>\n\n[`Input`](/components/Input) extends `FieldPassThrough` with affixes:\n\n```ts\ntype InputPassThrough = FieldPassThrough & {\n prefix?: PassThroughPart\n suffix?: PassThroughPart\n help?: PassThroughPart\n count?: PassThroughPart\n}\n```\n\n<h3 id=\"SplitterPassThrough\">SplitterPassThrough</h3>\n\n[`Splitter`](/components/Splitter) extends `RootPassThrough` with gutter and panes:\n\n```ts\ntype SplitterPassThrough = RootPassThrough & {\n gutter?: PassThroughPart\n panel1?: PassThroughPart\n panel2?: PassThroughPart\n}\n```\n\nGutter look can also use `resizeTriggerClass` / `resizeTriggerStyle`; content goes in `#resize-trigger` (alias `#gutter`).\n\n<h3 id=\"MSizeInput\">MSizeInput</h3>\n\nControl size for many form / button props:\n\n```ts\ntype MSizeInput = 'small' | 'medium' | 'large' | 'sm' | 'md' | 'lg'\n```\n\n`sm` / `md` / `lg` are legacy aliases. Omitted `size` usually inherits [ConfigProvider](/docs/config).\n\n<h3 id=\"MInputVariant\">MInputVariant</h3>\n\n```ts\ntype MInputVariant = 'outlined' | 'filled'\n```\n\n<h3 id=\"ButtonType\">ButtonType</h3>\n\nButton type sugar ([`Button`](/components/Button)):\n\n```ts\ntype ButtonType = 'default' | 'primary' | 'dashed' | 'link' | 'text'\n```\n\n<h3 id=\"ButtonColor\">ButtonColor</h3>\n\nButton color axis (Button, ConfirmDialog `acceptColor`, Dialog `positiveColor`, …):\n\n```ts\ntype ButtonColor =\n | 'default'\n | 'primary'\n | 'danger'\n | 'success'\n | 'info'\n | 'warning'\n | 'help'\n | 'contrast'\n | 'link'\n```\n\n<h3 id=\"ButtonVariant\">ButtonVariant</h3>\n\nButton variant axis:\n\n```ts\ntype ButtonVariant = 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link'\n```\n\n<h3 id=\"MAppendTo\">MAppendTo</h3>\n\nOverlay Teleport target:\n\n```ts\ntype MAppendTo = string | HTMLElement | 'self'\n```\n\n- `'body'` (default) \n- `'self'` — render in place (no Teleport) \n- `false` is accepted at runtime (same idea as `'self'`)\n\n<h3 id=\"AsyncGuard\">AsyncGuard</h3>\n\nGuard before close / confirm. Return `false` (including from a Promise) to **abort**:\n\n```ts\ntype AsyncGuard<T extends unknown[] = []> = (\n ...args: T\n) => unknown | Promise<unknown>\n```\n\nUsed by Dialog `beforeClose`, ConfirmDialog `beforeAccept`, and similar.\n\n<h3 id=\"SelectOption\">SelectOption</h3>\n\n[`Select`](/components/Select) option row:\n\n```ts\ninterface SelectOption {\n label: string\n value: string | number\n disabled?: boolean\n}\n```\n\n<h3 id=\"SelectOptionGroup\">SelectOptionGroup</h3>\n\n[`Select`](/components/Select) option group (mix into `options` to render a group header row):\n\n```ts\ninterface SelectOptionGroup {\n label: string\n items: SelectOption[]\n}\n```\n\n<h3 id=\"SelectModelValue\">SelectModelValue</h3>\n\n```ts\ntype SelectValue = string | number\ntype SelectModelValue = SelectValue | SelectValue[] | undefined\n```\n\nScalar when single-select; array when `multiple`.\n\n<h3 id=\"IconName\">IconName</h3>\n\nRegistered icon id for [`MIcon`](/components/Icon) / [`Button`](/components/Button), e.g. `'search'`. See the Icon registry.\n\n<h3 id=\"MenuNodeBase\">MenuNodeBase</h3>\n\nShared fields for Menu / Dropdown / ContextMenu items:\n\n```ts\ninterface MenuNodeBase {\n key?: string\n label?: string\n value?: string\n icon?: string\n disabled?: boolean\n separator?: boolean\n shortcut?: string\n command?: () => void\n items?: MenuNodeBase[]\n}\n```\n\n<h3 id=\"MSeverity\">MSeverity</h3>\n\nStatus tone for Message, Tag, etc.:\n\n```ts\ntype MSeverity =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'info'\n | 'warning'\n | 'danger'\n | 'contrast'\n```\n\n---\n\nComponent-only types (`TableServerOptions`, `MenuItem`, …) live under each component’s **Types** section; this page is for shared names only."
32966
32978
  }
32967
32979
  ]
32968
32980
  }
@@ -33563,7 +33575,7 @@
33563
33575
  "zh-CN": {
33564
33576
  "title": "Agent MCP",
33565
33577
  "description": "可选的 MCP 服务,供支持 Model Context Protocol 的 AI 客户端检索本库文档。",
33566
- "markdown": "---\ntitle: Agent MCP\norder: 14\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、规则与多编辑器 MCP 一起装好,见 [一键接入](/docs/setup)(默认写入 Cursor / VS Code / Zed 与 `.mcp.json`);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 配置;setup 会写入):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**VS Code**(工作区 `.vscode/mcp.json`;setup 会写入):\n\n```json\n{\n \"servers\": {\n \"morya-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**便携**(项目根 `.mcp.json`;setup 会写入,供 Agent Host / 跨工具发现):\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` 等;需手写,setup 不自动写):\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**(项目 `.zed/settings.json` → `context_servers`;setup 会合并写入):\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 源码(含 settings / wizard / result / detail / form-in-dialog 等;`includeScaffold` 有样例时返回样例源码) |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距、双边框,以及 rows / message / MStatus 等契约 |\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_usage`** → `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 与多编辑器 MCP\n- [Agent Skill](/docs/agent-skill):`morya-ui-pages` 何时用、表面地图\n- [快速上手](/docs/quick-start):在应用中安装并使用组件\n- [组件](/components):浏览全部组件与交互示例\n",
33578
+ "markdown": "---\ntitle: Agent MCP\norder: 14\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、规则与多编辑器 MCP 一起装好,见 [一键接入](/docs/setup)(默认写入 Cursor / VS Code / Zed 与 `.mcp.json`);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 配置;setup 会写入):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**VS Code**(工作区 `.vscode/mcp.json`;setup 会写入):\n\n```json\n{\n \"servers\": {\n \"morya-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**便携**(项目根 `.mcp.json`;setup 会写入,供 Agent Host / 跨工具发现):\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` 等;需手写,setup 不自动写):\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**(项目 `.zed/settings.json` → `context_servers`;setup 会合并写入):\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 源码(含 settings / wizard / result / detail / form-in-dialog 等;`includeScaffold` 有样例时返回样例源码) |\n| `list_page_snippets` | 列出可复用的页面区块 snippet |\n| `get_page_snippet` | 读取局部区块 snippet(筛选区、工具栏等) |\n| `validate_page` | 校验页面组合、间距、双边框,以及 rows / message / MStatus 等契约 |\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_usage`** → `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 的文档,写一个 `type=\"primary\" 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=\"删除\" danger type=\"primary\"/>\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 与多编辑器 MCP\n- [Agent Skill](/docs/agent-skill):`morya-ui-pages` 何时用、表面地图\n- [快速上手](/docs/quick-start):在应用中安装并使用组件\n- [组件](/components):浏览全部组件与交互示例\n",
33567
33579
  "sections": [
33568
33580
  {
33569
33581
  "title": "",
@@ -33583,7 +33595,7 @@
33583
33595
  {
33584
33596
  "title": "对话示例",
33585
33597
  "id": "对话示例",
33586
- "body": "接入后,可直接让助手调用本服务,例如:\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```"
33598
+ "body": "接入后,可直接让助手调用本服务,例如:\n\n> 用 morya-ui 的 MCP 查一下 Dialog 的 props,并给一个带确认 / 取消按钮的示例。\n\n> 搜索和「日期」相关的组件,选一个适合表单的,按文档写出最小用法。\n\n> 根据 MCP 里 Button 的文档,写一个 `type=\"primary\" 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=\"删除\" danger type=\"primary\"/>\n</template>\n```"
33587
33599
  },
33588
33600
  {
33589
33601
  "title": "与文档站的关系",
@@ -33600,7 +33612,7 @@
33600
33612
  "en-US": {
33601
33613
  "title": "Agent MCP",
33602
33614
  "description": "Optional MCP server for AI clients that support the Model Context Protocol.",
33603
- "markdown": "---\ntitle: Agent MCP\norder: 14\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, rules, and multi-editor MCP in one step, see [One-shot setup](/docs/setup) (writes Cursor / VS Code / Zed plus `.mcp.json` by default). 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; written by setup):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**VS Code** (workspace `.vscode/mcp.json`; written by setup):\n\n```json\n{\n \"servers\": {\n \"morya-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Portable** (project-root `.mcp.json`; written by setup for Agent Host / cross-tool discovery):\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.; configure manually — setup does not write these):\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** (project `.zed/settings.json` → `context_servers`; merged by setup):\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` … `settings-page`, `wizard-form`, …) |\n| `list_page_snippets` | List reusable page section snippets |\n| `get_page_snippet` | Read a local section snippet (filters, toolbar, …) |\n| `validate_page` | Check page composition, spacing, double-border, and contract hints (`rows`, message, MStatus) |\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_usage`** → `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 (returns the golden page source when one exists):\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",
33615
+ "markdown": "---\ntitle: Agent MCP\norder: 14\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, rules, and multi-editor MCP in one step, see [One-shot setup](/docs/setup) (writes Cursor / VS Code / Zed plus `.mcp.json` by default). 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; written by setup):\n\n```json\n{\n \"mcpServers\": {\n \"morya-ui\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**VS Code** (workspace `.vscode/mcp.json`; written by setup):\n\n```json\n{\n \"servers\": {\n \"morya-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@morya-ui/mcp\"]\n }\n }\n}\n```\n\n**Portable** (project-root `.mcp.json`; written by setup for Agent Host / cross-tool discovery):\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.; configure manually — setup does not write these):\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** (project `.zed/settings.json` → `context_servers`; merged by setup):\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` … `settings-page`, `wizard-form`, …) |\n| `list_page_snippets` | List reusable page section snippets |\n| `get_page_snippet` | Read a local section snippet (filters, toolbar, …) |\n| `validate_page` | Check page composition, spacing, double-border, and contract hints (`rows`, message, MStatus) |\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_usage`** → `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 (returns the golden page source when one exists):\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 `type=\"primary\" 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\" danger type=\"primary\"/>\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",
33604
33616
  "sections": [
33605
33617
  {
33606
33618
  "title": "",
@@ -33620,7 +33632,7 @@
33620
33632
  {
33621
33633
  "title": "Prompt examples",
33622
33634
  "id": "prompt-examples",
33623
- "body": "After 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```"
33635
+ "body": "After 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 `type=\"primary\" 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\" danger type=\"primary\"/>\n</template>\n```"
33624
33636
  },
33625
33637
  {
33626
33638
  "title": "Relation to this site",
@@ -33647,7 +33659,7 @@
33647
33659
  "zh-CN": {
33648
33660
  "title": "登录表单",
33649
33661
  "description": "用 MForm + FormRules 做邮箱/密码登录校验。",
33650
- "markdown": "---\ntitle: 登录表单\norder: 20\ndescription: 用 MForm + FormRules 做邮箱/密码登录校验。\n---\n\n# 登录表单\n\n把邮箱、密码和提交按钮组合成可直接复制的登录表单:声明式 `rules` 校验,提交时统一跑一遍。\n\n## 目标\n\n- 邮箱必填 + 格式校验\n- 密码必填 + 最短长度\n- 提交时 `validate()`,失败只展示字段错误,成功再继续业务逻辑\n\n## 何时使用\n\n- 登录 / 注册页、账号切换弹窗等短表单\n- 需要字段级错误文案,而不是一次弹全局 Toast\n\n## 步骤\n\n1. 安装并引入样式:`pnpm add morya-ui`,入口加 `import 'morya-ui/styles.css'`(按需导入可跳过全量样式)。\n2. 用 `reactive` 建 `model`,用 `FormRules` 按字段名写规则。\n3. `MForm` 绑定 `model` / `rules`,`validate-on=\"submit\"`;字段放在 `MFormItem` 里,并通过默认插槽拿到 `id` / `invalid`。\n4. 密码用 `MInputPassword`;邮箱用 `MInput type=\"email\"`。\n5. 在 `@submit` 里 `await formRef.validate()`,检查 `valid` 后再请求接口。\n\n`validate()` **始终 resolve**,不会 reject;失败时看 `{ valid, errors }`。\n\n## 预览\n\n```vue preview src=\"./demos/recipes/FormLogin.zh.vue\"\n```\n\n## 检查清单\n\n- [ ] `name` 与 `rules` 键一致(`email` / `password`)\n- [ ] 控件收到 `id` 与 `invalid`,错误能关联到 label\n- [ ] 密码使用 `MInputPassword`(不要用明文 `type=\"password\"` 凑合,除非刻意简化)\n- [ ] 提交按钮 `native-type=\"submit\"`,避免只绑 `@click` 漏掉原生提交\n- [ ] 已引入 `morya-ui` 与样式\n\n## 相关\n\n- [Form](/components/Form):声明式 rules、`useForm`\n- [Input](/components/Input) / [InputPassword](/components/InputPassword)\n- [Button](/components/Button)\n- [快速上手](/docs/quick-start)\n",
33662
+ "markdown": "---\ntitle: 登录表单\norder: 20\ndescription: 用 MForm + FormRules 做邮箱/密码登录校验。\n---\n\n# 登录表单\n\n把邮箱、密码和提交按钮组合成可直接复制的登录表单:声明式 `rules` 校验,提交时统一跑一遍。\n\n## 目标\n\n- 邮箱必填 + 格式校验\n- 密码必填 + 最短长度\n- 提交时 `validate()`,失败只展示字段错误,成功再继续业务逻辑\n\n## 何时使用\n\n- 登录 / 注册页、账号切换弹窗等短表单\n- 需要字段级错误文案,而不是一次弹全局 Toast\n\n## 步骤\n\n1. 安装并引入样式:`pnpm add morya-ui`,入口加 `import 'morya-ui/styles.css'`(按需导入可跳过全量样式)。\n2. 用 `reactive` 建 `model`,用 `FormRules` 按字段名写规则。\n3. `MForm` 绑定 `model` / `rules`,`validate-on=\"submit\"`;字段放在 `MFormItem` 里,并通过默认插槽拿到 `id` / `invalid`。\n4. 密码用 `MInputPassword`;邮箱用 `MInput type=\"email\"`。\n5. 在 `@submit` 里 `await formRef.validate()`,检查 `valid` 后再请求接口。\n\n`validate()` **始终 resolve**,不会 reject;失败时看 `{ valid, errors }`。\n\n## 预览\n\n```vue preview src=\"./demos/recipes/FormLogin.zh.vue\"\n```\n\n## 检查清单\n\n- [ ] `name` 与 `rules` 键一致(`email` / `password`)\n- [ ] 控件收到 `id` 与 `invalid`,错误能关联到 label\n- [ ] 密码使用 `MInputPassword`(不要用明文 `type=\"password\"` 凑合,除非刻意简化)\n- [ ] 提交按钮 `html-type=\"submit\"`,避免只绑 `@click` 漏掉原生提交\n- [ ] 已引入 `morya-ui` 与样式\n\n## 相关\n\n- [Form](/components/Form):声明式 rules、`useForm`\n- [Input](/components/Input) / [InputPassword](/components/InputPassword)\n- [Button](/components/Button)\n- [快速上手](/docs/quick-start)\n",
33651
33663
  "sections": [
33652
33664
  {
33653
33665
  "title": "",
@@ -33677,7 +33689,7 @@
33677
33689
  {
33678
33690
  "title": "检查清单",
33679
33691
  "id": "检查清单",
33680
- "body": "- [ ] `name` 与 `rules` 键一致(`email` / `password`)\n- [ ] 控件收到 `id` 与 `invalid`,错误能关联到 label\n- [ ] 密码使用 `MInputPassword`(不要用明文 `type=\"password\"` 凑合,除非刻意简化)\n- [ ] 提交按钮 `native-type=\"submit\"`,避免只绑 `@click` 漏掉原生提交\n- [ ] 已引入 `morya-ui` 与样式"
33692
+ "body": "- [ ] `name` 与 `rules` 键一致(`email` / `password`)\n- [ ] 控件收到 `id` 与 `invalid`,错误能关联到 label\n- [ ] 密码使用 `MInputPassword`(不要用明文 `type=\"password\"` 凑合,除非刻意简化)\n- [ ] 提交按钮 `html-type=\"submit\"`,避免只绑 `@click` 漏掉原生提交\n- [ ] 已引入 `morya-ui` 与样式"
33681
33693
  },
33682
33694
  {
33683
33695
  "title": "相关",
@@ -33689,7 +33701,7 @@
33689
33701
  "en-US": {
33690
33702
  "title": "Login form",
33691
33703
  "description": "Build an email/password login form with MForm and FormRules.",
33692
- "markdown": "---\ntitle: Login form\norder: 20\ndescription: Build an email/password login form with MForm and FormRules.\n---\n\n# Login form\n\nA copy-paste login form with declarative `rules`: email + password, validate on submit.\n\n## Goal\n\n- Required email with format check\n- Required password with a minimum length\n- Call `validate()` on submit; show field errors first, then run your business logic\n\n## When to use\n\n- Sign-in / sign-up pages and short account dialogs\n- Field-level error copy instead of a single global toast\n\n## Steps\n\n1. Install and load styles: `pnpm add morya-ui`, then `import 'morya-ui/styles.css'` at the app entry (skip full CSS when using subpath imports).\n2. Keep values in a `reactive` `model` and declare `FormRules` keyed by field name.\n3. Bind `model` / `rules` on `MForm` with `validate-on=\"submit\"`. Wrap fields in `MFormItem` and pass `id` / `invalid` from the default slot.\n4. Use `MInputPassword` for the password and `MInput type=\"email\"` for the email.\n5. In `@submit`, `await formRef.validate()` and check `valid` before calling your API.\n\n`validate()` **always resolves** — it does not reject. On failure, inspect `{ valid, errors }`.\n\n## Preview\n\n```vue preview src=\"./demos/recipes/FormLogin.en.vue\"\n```\n\n## Checklist\n\n- [ ] `name` matches the `rules` keys (`email` / `password`)\n- [ ] Controls receive `id` and `invalid` so errors link to labels\n- [ ] Password uses `MInputPassword` (avoid a plain `type=\"password\"` unless you intentionally simplify)\n- [ ] Submit button uses `native-type=\"submit\"` so native form submit is not skipped\n- [ ] `morya-ui` and styles are imported\n\n## Related\n\n- [Form](/components/Form): declarative rules, `useForm`\n- [Input](/components/Input) / [InputPassword](/components/InputPassword)\n- [Button](/components/Button)\n- [Quick start](/docs/quick-start)\n",
33704
+ "markdown": "---\ntitle: Login form\norder: 20\ndescription: Build an email/password login form with MForm and FormRules.\n---\n\n# Login form\n\nA copy-paste login form with declarative `rules`: email + password, validate on submit.\n\n## Goal\n\n- Required email with format check\n- Required password with a minimum length\n- Call `validate()` on submit; show field errors first, then run your business logic\n\n## When to use\n\n- Sign-in / sign-up pages and short account dialogs\n- Field-level error copy instead of a single global toast\n\n## Steps\n\n1. Install and load styles: `pnpm add morya-ui`, then `import 'morya-ui/styles.css'` at the app entry (skip full CSS when using subpath imports).\n2. Keep values in a `reactive` `model` and declare `FormRules` keyed by field name.\n3. Bind `model` / `rules` on `MForm` with `validate-on=\"submit\"`. Wrap fields in `MFormItem` and pass `id` / `invalid` from the default slot.\n4. Use `MInputPassword` for the password and `MInput type=\"email\"` for the email.\n5. In `@submit`, `await formRef.validate()` and check `valid` before calling your API.\n\n`validate()` **always resolves** — it does not reject. On failure, inspect `{ valid, errors }`.\n\n## Preview\n\n```vue preview src=\"./demos/recipes/FormLogin.en.vue\"\n```\n\n## Checklist\n\n- [ ] `name` matches the `rules` keys (`email` / `password`)\n- [ ] Controls receive `id` and `invalid` so errors link to labels\n- [ ] Password uses `MInputPassword` (avoid a plain `type=\"password\"` unless you intentionally simplify)\n- [ ] Submit button uses `html-type=\"submit\"` so native form submit is not skipped\n- [ ] `morya-ui` and styles are imported\n\n## Related\n\n- [Form](/components/Form): declarative rules, `useForm`\n- [Input](/components/Input) / [InputPassword](/components/InputPassword)\n- [Button](/components/Button)\n- [Quick start](/docs/quick-start)\n",
33693
33705
  "sections": [
33694
33706
  {
33695
33707
  "title": "",
@@ -33719,7 +33731,7 @@
33719
33731
  {
33720
33732
  "title": "Checklist",
33721
33733
  "id": "checklist",
33722
- "body": "- [ ] `name` matches the `rules` keys (`email` / `password`)\n- [ ] Controls receive `id` and `invalid` so errors link to labels\n- [ ] Password uses `MInputPassword` (avoid a plain `type=\"password\"` unless you intentionally simplify)\n- [ ] Submit button uses `native-type=\"submit\"` so native form submit is not skipped\n- [ ] `morya-ui` and styles are imported"
33734
+ "body": "- [ ] `name` matches the `rules` keys (`email` / `password`)\n- [ ] Controls receive `id` and `invalid` so errors link to labels\n- [ ] Password uses `MInputPassword` (avoid a plain `type=\"password\"` unless you intentionally simplify)\n- [ ] Submit button uses `html-type=\"submit\"` so native form submit is not skipped\n- [ ] `morya-ui` and styles are imported"
33723
33735
  },
33724
33736
  {
33725
33737
  "title": "Related",
@@ -33835,7 +33847,7 @@
33835
33847
  "zh-CN": {
33836
33848
  "title": "确认流程",
33837
33849
  "description": "声明式 MConfirmDialog 与命令式 useConfirm 两种确认交互。",
33838
- "markdown": "---\ntitle: 确认流程\norder: 22\ndescription: 声明式 MConfirmDialog 与命令式 useConfirm 两种确认交互。\n---\n\n# 确认流程\n\n删除、停用、覆盖写入等不可轻易撤销的操作,先让用户点一次确认。Morya 提供模板声明式与 `useConfirm().require()` 命令式两条路。\n\n## 目标\n\n- 模板里用 `MConfirmDialog` + `v-model` 控制显隐\n- 脚本里用 `useConfirm().require(...)`,得到 `Promise<boolean>`\n- 危险操作用 `accept-severity=\"danger\"`(可选 `type=\"warning\"`)\n\n## 何时使用\n\n| 方式 | 适合 |\n| --- | --- |\n| 声明式 `MConfirmDialog` | 文案/插槽固定、需要和页面状态绑定、要自定义 footer |\n| 命令式 `useConfirm` | 工具函数、表格行操作、不想为每个入口挂一个 Dialog |\n| Dialog `modal.confirm` | 需要完整 Dialog 能力(异步 `onOk`、自定义内容)。见 [Dialog](/components/Dialog) |\n\n## 步骤\n\n1. **声明式**:`visible` 驱动 `v-model`;按钮打开对话框;监听 `@accept` / `@reject`。\n2. **命令式**:`const confirm = useConfirm()`,`await confirm.require({ header, message, ... })`;`true` 表示确认,`false` 表示取消或关闭。\n3. 确认按钮语义色用 `acceptSeverity: 'danger'`;需要状态图标时加 `type: 'warning'`。\n4. 真正删数据放在确认之后;若删除是异步的,可在声明式路径用 `beforeAccept`,或命令式路径里先 `await` 再反馈结果。\n\n## 预览\n\n```vue preview src=\"./demos/recipes/ConfirmFlow.zh.vue\"\n```\n\n## 检查清单\n\n- [ ] 危险操作文案写清楚不可撤销后果\n- [ ] 声明式路径绑定了 `@accept` / `@reject`(或等价业务回调)\n- [ ] 命令式路径处理了 `false`(取消 / Esc / 点遮罩)\n- [ ] 不要把确认框当成普通通知(短反馈用 `message` / `toast`)\n- [ ] 已引入 `morya-ui` 与样式\n\n## 相关\n\n- [ConfirmDialog](/components/ConfirmDialog):`MConfirmDialog`、`useConfirm`\n- [Dialog](/components/Dialog):`useModal` / `modal.confirm`\n- [约定](/docs/conventions):反馈选型\n- [快速上手](/docs/quick-start)\n",
33850
+ "markdown": "---\ntitle: 确认流程\norder: 22\ndescription: 声明式 MConfirmDialog 与命令式 useConfirm 两种确认交互。\n---\n\n# 确认流程\n\n删除、停用、覆盖写入等不可轻易撤销的操作,先让用户点一次确认。Morya 提供模板声明式与 `useConfirm().require()` 命令式两条路。\n\n## 目标\n\n- 模板里用 `MConfirmDialog` + `v-model` 控制显隐\n- 脚本里用 `useConfirm().require(...)`,得到 `Promise<boolean>`\n- 危险操作用 `accept-color=\"danger\"`(可选 `type=\"warning\"`)\n\n## 何时使用\n\n| 方式 | 适合 |\n| --- | --- |\n| 声明式 `MConfirmDialog` | 文案/插槽固定、需要和页面状态绑定、要自定义 footer |\n| 命令式 `useConfirm` | 工具函数、表格行操作、不想为每个入口挂一个 Dialog |\n| Dialog `modal.confirm` | 需要完整 Dialog 能力(异步 `onOk`、自定义内容)。见 [Dialog](/components/Dialog) |\n\n## 步骤\n\n1. **声明式**:`visible` 驱动 `v-model`;按钮打开对话框;监听 `@accept` / `@reject`。\n2. **命令式**:`const confirm = useConfirm()`,`await confirm.require({ header, message, ... })`;`true` 表示确认,`false` 表示取消或关闭。\n3. 确认按钮颜色用 `acceptColor: 'danger'`;需要状态图标时加 `type: 'warning'`。\n4. 真正删数据放在确认之后;若删除是异步的,可在声明式路径用 `beforeAccept`,或命令式路径里先 `await` 再反馈结果。\n\n## 预览\n\n```vue preview src=\"./demos/recipes/ConfirmFlow.zh.vue\"\n```\n\n## 检查清单\n\n- [ ] 危险操作文案写清楚不可撤销后果\n- [ ] 声明式路径绑定了 `@accept` / `@reject`(或等价业务回调)\n- [ ] 命令式路径处理了 `false`(取消 / Esc / 点遮罩)\n- [ ] 不要把确认框当成普通通知(短反馈用 `message` / `toast`)\n- [ ] 已引入 `morya-ui` 与样式\n\n## 相关\n\n- [ConfirmDialog](/components/ConfirmDialog):`MConfirmDialog`、`useConfirm`\n- [Dialog](/components/Dialog):`useModal` / `modal.confirm`\n- [约定](/docs/conventions):反馈选型\n- [快速上手](/docs/quick-start)\n",
33839
33851
  "sections": [
33840
33852
  {
33841
33853
  "title": "",
@@ -33845,7 +33857,7 @@
33845
33857
  {
33846
33858
  "title": "目标",
33847
33859
  "id": "目标",
33848
- "body": "- 模板里用 `MConfirmDialog` + `v-model` 控制显隐\n- 脚本里用 `useConfirm().require(...)`,得到 `Promise<boolean>`\n- 危险操作用 `accept-severity=\"danger\"`(可选 `type=\"warning\"`)"
33860
+ "body": "- 模板里用 `MConfirmDialog` + `v-model` 控制显隐\n- 脚本里用 `useConfirm().require(...)`,得到 `Promise<boolean>`\n- 危险操作用 `accept-color=\"danger\"`(可选 `type=\"warning\"`)"
33849
33861
  },
33850
33862
  {
33851
33863
  "title": "何时使用",
@@ -33855,7 +33867,7 @@
33855
33867
  {
33856
33868
  "title": "步骤",
33857
33869
  "id": "步骤",
33858
- "body": "1. **声明式**:`visible` 驱动 `v-model`;按钮打开对话框;监听 `@accept` / `@reject`。\n2. **命令式**:`const confirm = useConfirm()`,`await confirm.require({ header, message, ... })`;`true` 表示确认,`false` 表示取消或关闭。\n3. 确认按钮语义色用 `acceptSeverity: 'danger'`;需要状态图标时加 `type: 'warning'`。\n4. 真正删数据放在确认之后;若删除是异步的,可在声明式路径用 `beforeAccept`,或命令式路径里先 `await` 再反馈结果。"
33870
+ "body": "1. **声明式**:`visible` 驱动 `v-model`;按钮打开对话框;监听 `@accept` / `@reject`。\n2. **命令式**:`const confirm = useConfirm()`,`await confirm.require({ header, message, ... })`;`true` 表示确认,`false` 表示取消或关闭。\n3. 确认按钮颜色用 `acceptColor: 'danger'`;需要状态图标时加 `type: 'warning'`。\n4. 真正删数据放在确认之后;若删除是异步的,可在声明式路径用 `beforeAccept`,或命令式路径里先 `await` 再反馈结果。"
33859
33871
  },
33860
33872
  {
33861
33873
  "title": "预览",
@@ -33877,7 +33889,7 @@
33877
33889
  "en-US": {
33878
33890
  "title": "Confirm flow",
33879
33891
  "description": "Declarative MConfirmDialog and imperative useConfirm for destructive actions.",
33880
- "markdown": "---\ntitle: Confirm flow\norder: 22\ndescription: Declarative MConfirmDialog and imperative useConfirm for destructive actions.\n---\n\n# Confirm flow\n\nFor deletes, disables, and other hard-to-undo actions, ask once before running them. Morya covers both a template-driven dialog and `useConfirm().require()`.\n\n## Goal\n\n- Control `MConfirmDialog` with `v-model` in the template\n- Call `useConfirm().require(...)` from script and await a `Promise<boolean>`\n- Mark destructive accepts with `accept-severity=\"danger\"` (optional `type=\"warning\"`)\n\n## When to use\n\n| Approach | Best for |\n| --- | --- |\n| Declarative `MConfirmDialog` | Fixed copy/slots, state bound to the page, custom footer |\n| Imperative `useConfirm` | Helpers, per-row table actions, avoiding one Dialog per entry |\n| Dialog `modal.confirm` | Full Dialog features (async `onOk`, custom content). See [Dialog](/components/Dialog) |\n\n## Steps\n\n1. **Declarative**: drive visibility with `v-model`; open from a button; handle `@accept` / `@reject`.\n2. **Imperative**: `const confirm = useConfirm()`, then `await confirm.require({ header, message, ... })`. `true` means accepted; `false` means cancelled or dismissed.\n3. Set `acceptSeverity: 'danger'` for destructive confirms; add `type: 'warning'` when you want a status icon.\n4. Run the real side effect after confirm. For async deletes, use `beforeAccept` on the declarative path, or `await` your API after `require()` resolves `true`.\n\n## Preview\n\n```vue preview src=\"./demos/recipes/ConfirmFlow.en.vue\"\n```\n\n## Checklist\n\n- [ ] Copy spells out the irreversible consequence\n- [ ] Declarative path wires `@accept` / `@reject` (or equivalent handlers)\n- [ ] Imperative path handles `false` (cancel / Esc / outside click)\n- [ ] Do not misuse confirms as toasts (short feedback belongs to `message` / `toast`)\n- [ ] `morya-ui` and styles are imported\n\n## Related\n\n- [ConfirmDialog](/components/ConfirmDialog): `MConfirmDialog`, `useConfirm`\n- [Dialog](/components/Dialog): `useModal` / `modal.confirm`\n- [Conventions](/docs/conventions): feedback selection\n- [Quick start](/docs/quick-start)\n",
33892
+ "markdown": "---\ntitle: Confirm flow\norder: 22\ndescription: Declarative MConfirmDialog and imperative useConfirm for destructive actions.\n---\n\n# Confirm flow\n\nFor deletes, disables, and other hard-to-undo actions, ask once before running them. Morya covers both a template-driven dialog and `useConfirm().require()`.\n\n## Goal\n\n- Control `MConfirmDialog` with `v-model` in the template\n- Call `useConfirm().require(...)` from script and await a `Promise<boolean>`\n- Mark destructive accepts with `accept-color=\"danger\"` (optional `type=\"warning\"`)\n\n## When to use\n\n| Approach | Best for |\n| --- | --- |\n| Declarative `MConfirmDialog` | Fixed copy/slots, state bound to the page, custom footer |\n| Imperative `useConfirm` | Helpers, per-row table actions, avoiding one Dialog per entry |\n| Dialog `modal.confirm` | Full Dialog features (async `onOk`, custom content). See [Dialog](/components/Dialog) |\n\n## Steps\n\n1. **Declarative**: drive visibility with `v-model`; open from a button; handle `@accept` / `@reject`.\n2. **Imperative**: `const confirm = useConfirm()`, then `await confirm.require({ header, message, ... })`. `true` means accepted; `false` means cancelled or dismissed.\n3. Set `acceptColor: 'danger'` for destructive confirms; add `type: 'warning'` when you want a status icon.\n4. Run the real side effect after confirm. For async deletes, use `beforeAccept` on the declarative path, or `await` your API after `require()` resolves `true`.\n\n## Preview\n\n```vue preview src=\"./demos/recipes/ConfirmFlow.en.vue\"\n```\n\n## Checklist\n\n- [ ] Copy spells out the irreversible consequence\n- [ ] Declarative path wires `@accept` / `@reject` (or equivalent handlers)\n- [ ] Imperative path handles `false` (cancel / Esc / outside click)\n- [ ] Do not misuse confirms as toasts (short feedback belongs to `message` / `toast`)\n- [ ] `morya-ui` and styles are imported\n\n## Related\n\n- [ConfirmDialog](/components/ConfirmDialog): `MConfirmDialog`, `useConfirm`\n- [Dialog](/components/Dialog): `useModal` / `modal.confirm`\n- [Conventions](/docs/conventions): feedback selection\n- [Quick start](/docs/quick-start)\n",
33881
33893
  "sections": [
33882
33894
  {
33883
33895
  "title": "",
@@ -33887,7 +33899,7 @@
33887
33899
  {
33888
33900
  "title": "Goal",
33889
33901
  "id": "goal",
33890
- "body": "- Control `MConfirmDialog` with `v-model` in the template\n- Call `useConfirm().require(...)` from script and await a `Promise<boolean>`\n- Mark destructive accepts with `accept-severity=\"danger\"` (optional `type=\"warning\"`)"
33902
+ "body": "- Control `MConfirmDialog` with `v-model` in the template\n- Call `useConfirm().require(...)` from script and await a `Promise<boolean>`\n- Mark destructive accepts with `accept-color=\"danger\"` (optional `type=\"warning\"`)"
33891
33903
  },
33892
33904
  {
33893
33905
  "title": "When to use",
@@ -33897,7 +33909,7 @@
33897
33909
  {
33898
33910
  "title": "Steps",
33899
33911
  "id": "steps",
33900
- "body": "1. **Declarative**: drive visibility with `v-model`; open from a button; handle `@accept` / `@reject`.\n2. **Imperative**: `const confirm = useConfirm()`, then `await confirm.require({ header, message, ... })`. `true` means accepted; `false` means cancelled or dismissed.\n3. Set `acceptSeverity: 'danger'` for destructive confirms; add `type: 'warning'` when you want a status icon.\n4. Run the real side effect after confirm. For async deletes, use `beforeAccept` on the declarative path, or `await` your API after `require()` resolves `true`."
33912
+ "body": "1. **Declarative**: drive visibility with `v-model`; open from a button; handle `@accept` / `@reject`.\n2. **Imperative**: `const confirm = useConfirm()`, then `await confirm.require({ header, message, ... })`. `true` means accepted; `false` means cancelled or dismissed.\n3. Set `acceptColor: 'danger'` for destructive confirms; add `type: 'warning'` when you want a status icon.\n4. Run the real side effect after confirm. For async deletes, use `beforeAccept` on the declarative path, or `await` your API after `require()` resolves `true`."
33901
33913
  },
33902
33914
  {
33903
33915
  "title": "Preview",
@@ -34201,12 +34213,12 @@
34201
34213
  "zh-CN": {
34202
34214
  "title": "约定",
34203
34215
  "description": "morya-ui 的命名、语义色、尺寸与主题约定。",
34204
- "markdown": "---\ntitle: 约定\norder: 35\ndescription: morya-ui 的命名、语义色、尺寸与主题约定。\n---\n\n# 约定\n\nMorya UI 用自己的词表描述界面:组件前缀 `M*`、语义色 `severity`、外观 `variant`、设计令牌 `--m-*`。写业务页时直接跟这套约定走。\n\n## 组件与令牌\n\n| 约定 | 说明 |\n| --- | --- |\n| 组件名 | 一律 `M` 前缀:`MButton`、`MDialog`、`MTable` |\n| 主题 | `MConfigProvider` + `useTheme` / `useDensity` / `useMotion` |\n| 颜色与几何 | 只用 `--m-*`,品牌色改 `--m-color-primary` |\n| 控件高度 | 默认 medium `32px`,圆角 `--m-control-radius` |\n| 字重 | 控件文案默认 400 |\n\n完整变量见 [设计令牌](/docs/design-tokens),覆盖方式见 [主题](/docs/theme)。\n\n## 语义与外观\n\n| 词 | 用在 |\n| --- | --- |\n| `severity` | 语义色:`primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `variant` | 外观:`outlined` / `dashed` / `text` / `link` / `ghost` 等 |\n| `fluid` | 通栏(占满父级宽度) |\n| `size` | `small` / `medium` / `large`(部分控件仍接受 `sm` / `md` / `lg`) |\n| `status` | 表单控件校验态:`error` / `warning` |\n\n按钮默认就是主色实心;次要操作用 `severity=\"secondary\"`,危险操作用 `severity=\"danger\"`。\n\n## 反馈\n\n| 场景 | 用法 |\n| --- | --- |\n| 短操作结果 | `message` / `MMessage` |\n| 摘要 + 详情、异步过程 | `toast` / `MToast` |\n| 需要确认 | `MConfirmDialog` / `MConfirmPopup` / `useConfirm` |\n| 页面内常驻说明 | `MAlert` |\n| 阻塞等待 | `MLoading`(细环可用 `MProgressSpinner`) |\n| 进度 | `MProgressBar` |\n| 空态 / 结果页 | `MEmpty` / `MResult` |\n\n## 布局与页面\n\n后台骨架用 `MLayout` 系列;列表/筛选/统计块用 `MPage*`。间距容器是 `MSpace` / `MFlex` / `MGrid`,相邻按钮拼组用 `MButtonGroup`。\n\n## 本库特有的能力\n\nDock、Terminal、Knob、Page 套件、以及 MCP / Agent Skill 是同一套令牌上的产品面。选型看 [组件文档](/components/Button) 和仓库 `DESIGN.md`。\n",
34216
+ "markdown": "---\ntitle: 约定\norder: 35\ndescription: morya-ui 的命名、语义色、尺寸与主题约定。\n---\n\n# 约定\n\nMorya UI 用自己的词表描述界面:组件前缀 `M*`、语义色 `severity`(Badge / Tag / Alert 等)、Button 的 `type` / `color` / `variant`、设计令牌 `--m-*`。写业务页时直接跟这套约定走。\n\n## 组件与令牌\n\n| 约定 | 说明 |\n| --- | --- |\n| 组件名 | 一律 `M` 前缀:`MButton`、`MDialog`、`MTable` |\n| 主题 | `MConfigProvider` + `useTheme` / `useDensity` / `useMotion` |\n| 颜色与几何 | 只用 `--m-*`,品牌色改 `--m-color-primary` |\n| 控件高度 | 默认 medium `32px`,圆角 `--m-control-radius` |\n| 字重 | 控件文案默认 400 |\n\n完整变量见 [设计令牌](/docs/design-tokens),覆盖方式见 [主题](/docs/theme)。\n\n## 语义与外观\n\n| 词 | 用在 |\n| --- | --- |\n| `severity` | Badge / Tag / Alert 等语义色:`primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `type` / `color` / `variant` | Button:`type` 糖(`primary` / `dashed` / `text` / `link`…)+ `color` + `variant`(`solid` / `outlined` / `filled`…) |\n| `fluid` / `block` | 通栏;字段多用 `fluid`,Button / ButtonGroup 用 `block` |\n| `size` | `small` / `medium` / `large`(部分控件仍接受 `sm` / `md` / `lg`) |\n| `status` | 表单控件校验态:`error` / `warning` |\n\n按钮默认是灰色描边(`default` + `outlined`);主实心用 `type=\"primary\"`,次要动作保持默认或 `type=\"text\"`,危险操作用 `danger` / `color=\"danger\"`。\n\n## 反馈\n\n| 场景 | 用法 |\n| --- | --- |\n| 短操作结果 | `message` / `MMessage` |\n| 摘要 + 详情、异步过程 | `toast` / `MToast` |\n| 需要确认 | `MConfirmDialog` / `MConfirmPopup` / `useConfirm` |\n| 页面内常驻说明 | `MAlert` |\n| 阻塞等待 | `MLoading`(细环可用 `MProgressSpinner`) |\n| 进度 | `MProgressBar` |\n| 空态 / 结果页 | `MEmpty` / `MResult` |\n\n## 布局与页面\n\n后台骨架用 `MLayout` 系列;列表/筛选/统计块用 `MPage*`。间距容器是 `MSpace` / `MFlex` / `MGrid`,相邻按钮拼组用 `MButtonGroup`。\n\n## 本库特有的能力\n\nDock、Terminal、Knob、Page 套件、以及 MCP / Agent Skill 是同一套令牌上的产品面。选型看 [组件文档](/components/Button) 和仓库 `DESIGN.md`。\n",
34205
34217
  "sections": [
34206
34218
  {
34207
34219
  "title": "",
34208
34220
  "id": "overview",
34209
- "body": "# 约定\n\nMorya UI 用自己的词表描述界面:组件前缀 `M*`、语义色 `severity`、外观 `variant`、设计令牌 `--m-*`。写业务页时直接跟这套约定走。"
34221
+ "body": "# 约定\n\nMorya UI 用自己的词表描述界面:组件前缀 `M*`、语义色 `severity`(Badge / Tag / Alert 等)、Button 的 `type` / `color` / `variant`、设计令牌 `--m-*`。写业务页时直接跟这套约定走。"
34210
34222
  },
34211
34223
  {
34212
34224
  "title": "组件与令牌",
@@ -34216,7 +34228,7 @@
34216
34228
  {
34217
34229
  "title": "语义与外观",
34218
34230
  "id": "语义与外观",
34219
- "body": "| 词 | 用在 |\n| --- | --- |\n| `severity` | 语义色:`primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `variant` | 外观:`outlined` / `dashed` / `text` / `link` / `ghost` 等 |\n| `fluid` | 通栏(占满父级宽度) |\n| `size` | `small` / `medium` / `large`(部分控件仍接受 `sm` / `md` / `lg`) |\n| `status` | 表单控件校验态:`error` / `warning` |\n\n按钮默认就是主色实心;次要操作用 `severity=\"secondary\"`,危险操作用 `severity=\"danger\"`。"
34231
+ "body": "| 词 | 用在 |\n| --- | --- |\n| `severity` | Badge / Tag / Alert 等语义色:`primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `type` / `color` / `variant` | Button:`type` 糖(`primary` / `dashed` / `text` / `link`…)+ `color` + `variant`(`solid` / `outlined` / `filled`…) |\n| `fluid` / `block` | 通栏;字段多用 `fluid`,Button / ButtonGroup 用 `block` |\n| `size` | `small` / `medium` / `large`(部分控件仍接受 `sm` / `md` / `lg`) |\n| `status` | 表单控件校验态:`error` / `warning` |\n\n按钮默认是灰色描边(`default` + `outlined`);主实心用 `type=\"primary\"`,次要动作保持默认或 `type=\"text\"`,危险操作用 `danger` / `color=\"danger\"`。"
34220
34232
  },
34221
34233
  {
34222
34234
  "title": "反馈",
@@ -34238,12 +34250,12 @@
34238
34250
  "en-US": {
34239
34251
  "title": "Conventions",
34240
34252
  "description": "Naming, severity, size, and theme conventions in morya-ui.",
34241
- "markdown": "---\ntitle: Conventions\norder: 35\ndescription: Naming, severity, size, and theme conventions in morya-ui.\n---\n\n# Conventions\n\nMorya UI has its own vocabulary: `M*` components, `severity` for tone, `variant` for appearance, and `--m-*` design tokens. Follow these conventions when you assemble product UI.\n\n## Components and tokens\n\n| Convention | Meaning |\n| --- | --- |\n| Names | Always `M` prefix: `MButton`, `MDialog`, `MTable` |\n| Theme | `MConfigProvider` plus `useTheme` / `useDensity` / `useMotion` |\n| Color and geometry | `--m-*` only; brand via `--m-color-primary` |\n| Control height | Medium default `32px`; radius `--m-control-radius` |\n| Type weight | Control copy defaults to 400 |\n\nSee [Design tokens](/docs/design-tokens) and [Theme](/docs/theme).\n\n## Tone and appearance\n\n| Word | Use |\n| --- | --- |\n| `severity` | Semantic color: `primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `variant` | Appearance: `outlined` / `dashed` / `text` / `link` / `ghost`, etc. |\n| `fluid` | Full width of the parent |\n| `size` | `small` / `medium` / `large` (some controls still accept `sm` / `md` / `lg`) |\n| `status` | Field validation: `error` / `warning` |\n\nThe default button is a solid primary action. Use `severity=\"secondary\"` for quiet actions and `severity=\"danger\"` for destructive ones.\n\n## Feedback\n\n| Situation | Use |\n| --- | --- |\n| Short result | `message` / `MMessage` |\n| Summary + detail, or async work | `toast` / `MToast` |\n| Confirm | `MConfirmDialog` / `MConfirmPopup` / `useConfirm` |\n| Persistent in-page notice | `MAlert` |\n| Blocking wait | `MLoading` (`MProgressSpinner` for a thin ring) |\n| Progress | `MProgressBar` |\n| Empty / outcome | `MEmpty` / `MResult` |\n\n## Layout and pages\n\nAdmin chrome uses the `MLayout` family; list/filter/stat blocks use `MPage*`. Spacing containers are `MSpace` / `MFlex` / `MGrid`. Join adjacent buttons with `MButtonGroup`.\n\n## Distinctive surfaces\n\nDock, Terminal, Knob, the Page kit, and MCP / Agent Skill sit on the same token system. Prefer the [component docs](/components/Button) and repository `DESIGN.md` when choosing APIs.\n",
34253
+ "markdown": "---\ntitle: Conventions\norder: 35\ndescription: Naming, severity, size, and theme conventions in morya-ui.\n---\n\n# Conventions\n\nMorya UI has its own vocabulary: `M*` components, `severity` for tone on Badge / Tag / Alert, Button `type` / `color` / `variant`, and `--m-*` design tokens. Follow these conventions when you assemble product UI.\n\n## Components and tokens\n\n| Convention | Meaning |\n| --- | --- |\n| Names | Always `M` prefix: `MButton`, `MDialog`, `MTable` |\n| Theme | `MConfigProvider` plus `useTheme` / `useDensity` / `useMotion` |\n| Color and geometry | `--m-*` only; brand via `--m-color-primary` |\n| Control height | Medium default `32px`; radius `--m-control-radius` |\n| Type weight | Control copy defaults to 400 |\n\nSee [Design tokens](/docs/design-tokens) and [Theme](/docs/theme).\n\n## Tone and appearance\n\n| Word | Use |\n| --- | --- |\n| `severity` | Semantic color on Badge / Tag / Alert: `primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `type` / `color` / `variant` | Button: `type` sugar (`primary` / `dashed` / `text` / `link`…) + `color` + `variant` (`solid` / `outlined` / `filled`…) |\n| `fluid` / `block` | Full width; fields mostly use `fluid`, Button / ButtonGroup use `block` |\n| `size` | `small` / `medium` / `large` (some controls still accept `sm` / `md` / `lg`) |\n| `status` | Field validation: `error` / `warning` |\n\nButtons default to gray outlined (`default` + `outlined`). Use `type=\"primary\"` for solid primary, keep the default or `type=\"text\"` for quiet actions, and `danger` / `color=\"danger\"` for destructive ones.\n\n## Feedback\n\n| Situation | Use |\n| --- | --- |\n| Short result | `message` / `MMessage` |\n| Summary + detail, or async work | `toast` / `MToast` |\n| Confirm | `MConfirmDialog` / `MConfirmPopup` / `useConfirm` |\n| Persistent in-page notice | `MAlert` |\n| Blocking wait | `MLoading` (`MProgressSpinner` for a thin ring) |\n| Progress | `MProgressBar` |\n| Empty / outcome | `MEmpty` / `MResult` |\n\n## Layout and pages\n\nAdmin chrome uses the `MLayout` family; list/filter/stat blocks use `MPage*`. Spacing containers are `MSpace` / `MFlex` / `MGrid`. Join adjacent buttons with `MButtonGroup`.\n\n## Distinctive surfaces\n\nDock, Terminal, Knob, the Page kit, and MCP / Agent Skill sit on the same token system. Prefer the [component docs](/components/Button) and repository `DESIGN.md` when choosing APIs.\n",
34242
34254
  "sections": [
34243
34255
  {
34244
34256
  "title": "",
34245
34257
  "id": "overview",
34246
- "body": "# Conventions\n\nMorya UI has its own vocabulary: `M*` components, `severity` for tone, `variant` for appearance, and `--m-*` design tokens. Follow these conventions when you assemble product UI."
34258
+ "body": "# Conventions\n\nMorya UI has its own vocabulary: `M*` components, `severity` for tone on Badge / Tag / Alert, Button `type` / `color` / `variant`, and `--m-*` design tokens. Follow these conventions when you assemble product UI."
34247
34259
  },
34248
34260
  {
34249
34261
  "title": "Components and tokens",
@@ -34253,7 +34265,7 @@
34253
34265
  {
34254
34266
  "title": "Tone and appearance",
34255
34267
  "id": "tone-and-appearance",
34256
- "body": "| Word | Use |\n| --- | --- |\n| `severity` | Semantic color: `primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `variant` | Appearance: `outlined` / `dashed` / `text` / `link` / `ghost`, etc. |\n| `fluid` | Full width of the parent |\n| `size` | `small` / `medium` / `large` (some controls still accept `sm` / `md` / `lg`) |\n| `status` | Field validation: `error` / `warning` |\n\nThe default button is a solid primary action. Use `severity=\"secondary\"` for quiet actions and `severity=\"danger\"` for destructive ones."
34268
+ "body": "| Word | Use |\n| --- | --- |\n| `severity` | Semantic color on Badge / Tag / Alert: `primary` / `secondary` / `success` / `info` / `warning` / `danger` |\n| `type` / `color` / `variant` | Button: `type` sugar (`primary` / `dashed` / `text` / `link`…) + `color` + `variant` (`solid` / `outlined` / `filled`…) |\n| `fluid` / `block` | Full width; fields mostly use `fluid`, Button / ButtonGroup use `block` |\n| `size` | `small` / `medium` / `large` (some controls still accept `sm` / `md` / `lg`) |\n| `status` | Field validation: `error` / `warning` |\n\nButtons default to gray outlined (`default` + `outlined`). Use `type=\"primary\"` for solid primary, keep the default or `type=\"text\"` for quiet actions, and `danger` / `color=\"danger\"` for destructive ones."
34257
34269
  },
34258
34270
  {
34259
34271
  "title": "Feedback",