@manohub/ui 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +12 -4
  2. package/dist/components/button/index.d.ts +8 -8
  3. package/dist/components/capsule/index.d.ts +13 -9
  4. package/dist/components/capsule/index.js +1 -1
  5. package/dist/components/card/index.js +7 -4
  6. package/dist/components/checkbox/index.js +1 -0
  7. package/dist/components/dialog/index.d.ts +58 -6
  8. package/dist/components/dialog/index.js +45 -8
  9. package/dist/components/drawer/index.d.ts +18 -6
  10. package/dist/components/drawer/index.js +11 -5
  11. package/dist/components/form/index.d.ts +115 -17
  12. package/dist/components/form/index.js +39 -9
  13. package/dist/components/input/index.d.ts +4 -4
  14. package/dist/components/input/index.js +1 -1
  15. package/dist/components/layout/index.d.ts +43 -1
  16. package/dist/components/layout/index.js +22 -2
  17. package/dist/components/notice/index.d.ts +24 -11
  18. package/dist/components/notice/index.js +11 -5
  19. package/dist/components/notification/index.d.ts +2 -2
  20. package/dist/components/page/index.js +4 -4
  21. package/dist/components/panel/index.js +4 -4
  22. package/dist/components/part-padding.d.ts +9 -6
  23. package/dist/components/part-padding.js +2 -1
  24. package/dist/components/radio/index.d.ts +1 -1
  25. package/dist/components/radio/index.js +1 -0
  26. package/dist/components/search/index.d.ts +26 -6
  27. package/dist/components/search/index.js +22 -4
  28. package/dist/components/steps/index.d.ts +232 -6
  29. package/dist/components/steps/index.js +84 -26
  30. package/dist/components/switch/index.d.ts +29 -5
  31. package/dist/components/switch/index.js +8 -2
  32. package/dist/components/tabbar/index.d.ts +184 -0
  33. package/dist/components/tabbar/index.js +161 -0
  34. package/dist/components/table/index.d.ts +74 -8
  35. package/dist/components/table/index.js +69 -16
  36. package/dist/components/tabs/index.d.ts +145 -125
  37. package/dist/components/tabs/index.js +93 -117
  38. package/dist/components/tag/index.d.ts +2 -2
  39. package/dist/components/text/index.d.ts +120 -0
  40. package/dist/components/text/index.js +55 -0
  41. package/dist/components/toast/index.d.ts +8 -8
  42. package/dist/components/toast/index.js +11 -2
  43. package/dist/components/upload/index.d.ts +30 -0
  44. package/dist/components/upload/index.js +7 -1
  45. package/dist/index.d.ts +6 -5
  46. package/dist/index.js +6 -3
  47. package/dist/services/dialog.d.ts +20 -5
  48. package/dist/services/dialog.js +8 -1
  49. package/dist/styles/components/capsule.css +4 -4
  50. package/dist/styles/components/dialog.css +40 -1
  51. package/dist/styles/components/form.css +206 -26
  52. package/dist/styles/components/input.css +29 -2
  53. package/dist/styles/components/layout.css +2 -0
  54. package/dist/styles/components/select.css +11 -0
  55. package/dist/styles/components/steps.css +48 -0
  56. package/dist/styles/components/{tabs.css → tabbar.css} +66 -65
  57. package/dist/styles/components/tabbar.tokens.css +30 -0
  58. package/dist/styles/components/table.css +50 -1
  59. package/dist/styles/components/table.tokens.css +3 -0
  60. package/dist/styles/components/text.css +101 -0
  61. package/dist/styles/components/toast.css +12 -6
  62. package/dist/styles/index.css +8 -4
  63. package/dist/styles/operations/tabs.css +73 -0
  64. package/dist/styles/reset.css +205 -0
  65. package/package.json +2 -2
  66. package/dist/components/tabset/index.d.ts +0 -105
  67. package/dist/components/tabset/index.js +0 -68
  68. package/dist/styles/components/tabs.tokens.css +0 -30
  69. package/dist/styles/operations/tabset.css +0 -57
@@ -1,153 +1,129 @@
1
- import { defineComponent, ref, computed, createVNode, Fragment, mergeProps } from "vue";
2
- import { Icon } from "@manohub/icon";
1
+ import { defineComponent, ref, createVNode } from "vue";
2
+ import { TabBar } from "../tabbar/index.js";
3
+ const TabPanel = /* @__PURE__ */ defineComponent({
4
+ name: "TabPanel",
5
+ /* 渲染的是插槽内容(片段根),属性无处可继承 —— 壳归 `Tabs`,属性由它在渲染期搬过去 */
6
+ inheritAttrs: false,
7
+ props: {
8
+ name: {
9
+ type: String,
10
+ required: true
11
+ },
12
+ value: {
13
+ type: [String, Number],
14
+ default: void 0
15
+ },
16
+ disabled: {
17
+ type: Boolean,
18
+ default: false
19
+ },
20
+ lazy: {
21
+ type: Boolean,
22
+ default: false
23
+ }
24
+ },
25
+ slots: Object,
26
+ setup(_props, {
27
+ slots
28
+ }) {
29
+ return () => slots.default?.() ?? null;
30
+ }
31
+ });
32
+ const flattenChildren = (raw) => (Array.isArray(raw) ? raw : raw == null ? [] : [raw]).flatMap((child) => Array.isArray(child) ? child : [child]).filter((child) => child !== null && child !== void 0 && child !== false && child !== true && child !== "");
33
+ const isTabPanel = (child) => !!child && typeof child === "object" && child.type === TabPanel;
34
+ const panelPropsOf = (child) => isTabPanel(child) ? child.props ?? {} : null;
3
35
  const Tabs = /* @__PURE__ */ defineComponent({
4
36
  name: "Tabs",
5
37
  inheritAttrs: false,
6
38
  props: {
7
39
  options: {
8
40
  type: Array,
9
- required: true
41
+ default: void 0
10
42
  },
11
- /** 受控选中值;不传即非受控(由 `defaultValue` 起) */
12
43
  value: {
13
44
  type: [String, Number],
14
45
  default: void 0
15
46
  },
16
- /** 非受控初始选中值,缺省第一项 */
17
47
  defaultValue: {
18
48
  type: [String, Number],
19
49
  default: void 0
20
50
  },
21
- /** 选中变化回调(受控与非受控都会调) */
22
51
  onChange: {
23
52
  type: Function,
24
53
  default: void 0
25
54
  },
26
- /** 形态:`line` 下划线 / `card` 选项卡 */
27
- type: {
28
- type: String,
29
- default: "line"
30
- },
31
- /** 整体居中(页签少、要撑满整行时用) */
32
- centered: {
33
- type: Boolean,
34
- default: false
35
- },
36
- /** 尺寸档(24 / 32 / 40,只覆盖令牌) */
37
- size: {
38
- type: String,
39
- default: "md"
40
- },
41
- /** 每项带关闭位(单项可用 `option.closable` 覆写) */
42
- closable: {
43
- type: Boolean,
44
- default: false
45
- },
46
- /** 尾部「新增」按钮 */
47
- addable: {
55
+ lazy: {
48
56
  type: Boolean,
49
57
  default: false
50
- },
51
- /** 「更多」页签的文字 */
52
- moreLabel: {
53
- type: String,
54
- default: "更多"
55
- },
56
- /** 关闭某项(只回调,**不从 `options` 里删** —— 数据归调用方) */
57
- onClose: {
58
- type: Function,
59
- default: void 0
60
- },
61
- /** 点新增(只回调) */
62
- onAdd: {
63
- type: Function,
64
- default: void 0
65
58
  }
66
59
  },
60
+ /* 同 `TabBar`:受控值必须 emit 回 `update:value`,否则 `v-model:value="current"` 静默失效
61
+ (受控时内部状态不更新、外部又收不到 ⇒ 点选项毫无反应)。 */
62
+ emits: {
63
+ "update:value": (value) => true
64
+ },
67
65
  slots: Object,
68
66
  setup(props, {
69
67
  slots,
70
- attrs
68
+ attrs,
69
+ emit
71
70
  }) {
72
- const innerValue = ref(props.value ?? props.defaultValue ?? props.options[0]?.value);
73
- const current = computed(() => props.value ?? innerValue.value);
74
- const moreId = `mh-tabs-${Math.random().toString(36).slice(2, 10)}`;
71
+ const innerValue = ref(props.defaultValue);
72
+ let items = [];
75
73
  const select = (value) => {
76
- const target = props.options.find((option) => option.value === value);
77
- if (target?.disabled) return;
74
+ if (items.find((option) => option.value === value)?.disabled) return;
78
75
  if (props.value === void 0) innerValue.value = value;
76
+ emit("update:value", value);
79
77
  props.onChange?.(value);
80
78
  };
81
- const isClosable = (option) => option.closable ?? props.closable;
82
- return () => createVNode("nav", {
83
- "class": [
84
- "mh-tabs",
85
- /* `mh-popup-host` 是操作层展开转向的**宿主标记**(popup.css 靠它 :has 反推面板开合):
86
- 没有它,「更多」的 caret 展开时不会翻向 —— 与 Select / Tooltip 同一分工。 */
87
- "mh-popup-host",
88
- props.type === "card" ? "mh-tabs--card" : "",
89
- props.centered ? "mh-tabs--centered" : "",
90
- props.size === "md" ? "" : `mh-tabs--${props.size}`,
91
- attrs.class
92
- ].filter(Boolean).join(" "),
93
- "style": attrs.style,
94
- "role": "tablist"
95
- }, [props.options.map((option) => {
96
- const active = option.value === current.value;
97
- return createVNode("button", {
98
- "key": option.value,
99
- "type": "button",
100
- "role": "tab",
101
- "class": ["mh-tabs__tab", active ? "is-selected" : "", option.disabled ? "is-disabled" : ""].filter(Boolean).join(" "),
102
- "data-state": active ? "active" : "inactive",
103
- "aria-selected": active,
104
- "disabled": option.disabled,
105
- "onClick": () => select(option.value)
106
- }, [option.label, isClosable(option) && !option.disabled ? (
107
- /* 关闭位不是 `<button>`:页签自己是按钮,按钮里嵌按钮是非法 HTML。
108
- 用 `role="button"` + `stopPropagation` 表达同样的语义与行为。 */
109
- createVNode("span", {
110
- "class": "mh-tabs__close",
111
- "role": "button",
112
- "tabindex": -1,
113
- "aria-label": `关闭${option.label}`,
114
- "onClick": (event) => {
115
- event.stopPropagation();
116
- event.preventDefault();
117
- props.onClose?.(option.value);
118
- }
119
- }, [createVNode(Icon, {
120
- "name": "close"
121
- }, null)])
122
- ) : null]);
123
- }), props.addable ? createVNode("button", {
124
- "type": "button",
125
- "class": "mh-tabs__add",
126
- "aria-label": "新增页签",
127
- "onClick": () => props.onAdd?.()
128
- }, [createVNode(Icon, {
129
- "name": "plus"
130
- }, null)]) : null, slots.more ? createVNode(Fragment, null, [createVNode("button", mergeProps({
131
- "type": "button",
132
- "class": "mh-tabs__tab mh-tabs__tab--more",
133
- "data-state": "inactive"
134
- }, {
135
- popovertarget: moreId
136
- }), [props.moreLabel, createVNode(Icon, {
137
- "name": "chevron-down",
138
- "class": "mh-popup-caret"
139
- }, null)]), createVNode("div", mergeProps({
140
- "id": moreId,
141
- "class": "mh-popup",
142
- "data-side": "bottom",
143
- "data-align": "end"
144
- }, {
145
- popover: "auto"
146
- }), [slots.more({
147
- options: props.options
148
- })])]) : null]);
79
+ return () => {
80
+ const nodes = flattenChildren(slots.default?.());
81
+ const panelMode = nodes.some(isTabPanel);
82
+ const list = panelMode ? nodes.filter(isTabPanel) : nodes;
83
+ const blockItems = list.map((node, index) => {
84
+ const info = panelPropsOf(node);
85
+ if (info) {
86
+ return {
87
+ label: info.name,
88
+ value: info.value ?? info.name,
89
+ disabled: info.disabled ?? false
90
+ };
91
+ }
92
+ return props.options?.[index] ?? null;
93
+ });
94
+ items = blockItems.filter((item) => item !== null);
95
+ const current = props.value ?? innerValue.value ?? items[0]?.value;
96
+ const panels = list.map((node, index) => {
97
+ const item = blockItems[index];
98
+ const info = panelPropsOf(node);
99
+ const active = item !== null && item.value === current;
100
+ if ((props.lazy || info?.lazy) && !active) return null;
101
+ const raw = info ? node.props ?? {} : {};
102
+ return createVNode("div", {
103
+ "key": String(item?.value ?? index),
104
+ "class": ["mh-tabs-panel", raw.class].filter(Boolean).join(" "),
105
+ "style": raw.style,
106
+ "hidden": !active
107
+ }, [node]);
108
+ });
109
+ return createVNode("div", {
110
+ "class": ["mh-tabs", attrs.class].filter(Boolean).join(" "),
111
+ "style": attrs.style
112
+ }, [slots.selector ? slots.selector({
113
+ value: current,
114
+ options: items,
115
+ select
116
+ }) : createVNode(TabBar, {
117
+ "options": items,
118
+ "value": current,
119
+ "onChange": select
120
+ }, null), createVNode("div", {
121
+ "class": "mh-tabs-panels"
122
+ }, [panels])]);
123
+ };
149
124
  }
150
125
  });
151
126
  export {
127
+ TabPanel,
152
128
  Tabs
153
129
  };
@@ -185,7 +185,7 @@ export declare const Tag: import("vue").DefineComponent<import("vue").ExtractPro
185
185
  }>> & Readonly<{}>, {
186
186
  color: string;
187
187
  size: ControlSize;
188
- icon: "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "wrench" | "plus" | "bell" | "settings" | "logout" | "home" | "workbench" | "grid-dots" | "heart" | "heart-filled" | "edit" | "refresh" | "upload" | "save" | "more" | "eye" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "sparkles" | "shield-check" | "shield-alert" | "history";
188
+ icon: "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
189
189
  disabled: boolean;
190
190
  name: string;
191
191
  value: string | number;
@@ -196,8 +196,8 @@ export declare const Tag: import("vue").DefineComponent<import("vue").ExtractPro
196
196
  selected: boolean;
197
197
  lg: boolean;
198
198
  shape: "add" | "select" | "chip" | "regular" | "status" | undefined;
199
- tone: "error" | "info" | "success" | "warning" | undefined;
200
199
  closable: boolean;
200
+ tone: "error" | "info" | "success" | "warning" | undefined;
201
201
  }, SlotsType<{
202
202
  default?: () => VNodeChild;
203
203
  }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,120 @@
1
+ import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
+ /** 字号档(每档都有一枚配套的行高令牌,故**不开放**只有字号的 micro / display) */
3
+ export type TextSize = 'caption' | 'body' | 'heading' | 'title';
4
+ /** 语义色档(`success` / `warning` 取 `-strong`,与 `Notice` / `Dialog` 同一张表) */
5
+ export type TextTone = 'default' | 'muted' | 'subtle' | 'primary' | 'success' | 'warning' | 'error';
6
+ /** 字重档(缺省**不设**,即继承上下文 —— 这样「在已加粗的区域里放一段普通文字」不必显式写 regular) */
7
+ export type TextWeight = 'regular' | 'medium' | 'semibold';
8
+ /** 承载标签(只开放语义明确的这几个;`as` 决定语义,`size` 决定视觉,两者**有意解耦**) */
9
+ export type TextTag = 'span' | 'p' | 'div' | 'label' | 'small' | 'strong' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
10
+ export interface TextProps {
11
+ /** 字号档(缺省 `body` = 14/20) */
12
+ size?: TextSize;
13
+ /** 语义色档(缺省 `default` = 正文色) */
14
+ tone?: TextTone;
15
+ /** 字重档(缺省不设,继承上下文) */
16
+ weight?: TextWeight;
17
+ /** 等宽族(代码、路径、ID 一类) */
18
+ mono?: boolean;
19
+ /** 截断:`true` 单行省略 / 数字 = 最多 N 行省略 */
20
+ truncate?: boolean | number;
21
+ /** 承载标签(缺省 `span`;语义标签如 `h2` / `p` / `label` 用它,视觉仍由 `size` 定) */
22
+ as?: TextTag;
23
+ }
24
+ /**
25
+ * 文本排版(**最小排版件**:字号 / 行高 / 字重 / 语义色 / 等宽 / 截断六个维度)。
26
+ *
27
+ * ## 为什么需要它
28
+ *
29
+ * `theme` 一直有 `--ui-font-{caption,body,heading,title}` 与 `--ui-font-mono` 这套档位令牌,
30
+ * 但**没有件消费它们**:卡片描述、表单说明、只读值、列表次级信息这些「容器里的文字层级」
31
+ * 于是无处可归 —— `Card` 只管卡片外壳,`Panel` 只管区域,两者都不管内容里的排版;
32
+ * 而契约 L1-5 又禁应用侧写 `font-*` / `color`。**令牌有了、路径没有**,
33
+ * 结果就是每个应用都要为「卡片里的文字」保留一条定版例外登记(本仓 repository 的 31 处里,
34
+ * 绝大多数属于这一类)。本件把这条路径补上。
35
+ *
36
+ * ## 与 `Title` / 平台默认的关系
37
+ *
38
+ * 浏览器给 `h1`-`h6` 的字阶已被 reset 归零(`font-size: inherit` / `font-weight: inherit`),
39
+ * 所以 `as="h2"` 只贡献**语义**,视觉完全由 `size` / `weight` 决定 ——
40
+ * 这与「标题的字阶必须跟设计稿」不冲突:要多大显式给 `size`。
41
+ *
42
+ * ## 不做什么
43
+ *
44
+ * - **不做富文本**:不解析 markdown、不认 `**加粗**`(富文本排版的归属见 `@manohub/kit/CONTRACT.md` §10);
45
+ * - **不做省略的展开**:截断只表示「显示不下就省略」,需要「展开全文」交互的走业务自己实现;
46
+ * - **不承载色底 / 描边 / 内距**:那是 `Tag` / `Badge` / `Card` 的事。
47
+ *
48
+ * @example 卡片里的三行信息(标题 / 描述 / 元信息)
49
+ * <Text as="h3" size="heading" weight="semibold">{repo.name}</Text>
50
+ * <Text tone="muted" truncate>{repo.url}</Text>
51
+ * <Text as="small" size="caption" tone="subtle">{repo.updatedAt}</Text>
52
+ *
53
+ * @example 只读值 + 等宽
54
+ * <Text mono>{task.id}</Text>
55
+ *
56
+ * @example 最多两行,超出省略
57
+ * <Text :truncate="2">{longDescription}</Text>
58
+ */
59
+ export declare const Text: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
60
+ size: {
61
+ type: PropType<TextSize>;
62
+ default: string;
63
+ };
64
+ tone: {
65
+ type: PropType<TextTone>;
66
+ default: string;
67
+ };
68
+ weight: {
69
+ type: PropType<TextWeight>;
70
+ default: undefined;
71
+ };
72
+ mono: {
73
+ type: BooleanConstructor;
74
+ default: boolean;
75
+ };
76
+ truncate: {
77
+ type: PropType<boolean | number>;
78
+ default: boolean;
79
+ };
80
+ as: {
81
+ type: PropType<TextTag>;
82
+ default: string;
83
+ };
84
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
85
+ [key: string]: any;
86
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
87
+ size: {
88
+ type: PropType<TextSize>;
89
+ default: string;
90
+ };
91
+ tone: {
92
+ type: PropType<TextTone>;
93
+ default: string;
94
+ };
95
+ weight: {
96
+ type: PropType<TextWeight>;
97
+ default: undefined;
98
+ };
99
+ mono: {
100
+ type: BooleanConstructor;
101
+ default: boolean;
102
+ };
103
+ truncate: {
104
+ type: PropType<boolean | number>;
105
+ default: boolean;
106
+ };
107
+ as: {
108
+ type: PropType<TextTag>;
109
+ default: string;
110
+ };
111
+ }>> & Readonly<{}>, {
112
+ size: TextSize;
113
+ weight: TextWeight;
114
+ tone: TextTone;
115
+ mono: boolean;
116
+ truncate: number | boolean;
117
+ as: TextTag;
118
+ }, SlotsType<{
119
+ default?: () => VNodeChild;
120
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,55 @@
1
+ import { defineComponent, h } from "vue";
2
+ const Text = /* @__PURE__ */ defineComponent({
3
+ name: "Text",
4
+ inheritAttrs: false,
5
+ props: {
6
+ size: {
7
+ type: String,
8
+ default: "body"
9
+ },
10
+ tone: {
11
+ type: String,
12
+ default: "default"
13
+ },
14
+ weight: {
15
+ type: String,
16
+ default: void 0
17
+ },
18
+ mono: {
19
+ type: Boolean,
20
+ default: false
21
+ },
22
+ truncate: {
23
+ type: [Boolean, Number],
24
+ default: false
25
+ },
26
+ as: {
27
+ type: String,
28
+ default: "span"
29
+ }
30
+ },
31
+ slots: Object,
32
+ setup(props, {
33
+ attrs,
34
+ slots
35
+ }) {
36
+ return () => {
37
+ const lines = props.truncate === true ? 1 : typeof props.truncate === "number" && props.truncate >= 1 ? Math.floor(props.truncate) : 0;
38
+ const classes = ["mh-text", `mh-text--${props.size}`, `mh-text--${props.tone}`, props.weight ? `mh-text--${props.weight}` : "", props.mono ? "mh-text--mono" : "", lines === 1 ? "mh-text--truncate" : "", lines > 1 ? "mh-text--clamp" : "", attrs.class].filter(Boolean).join(" ");
39
+ const style = {
40
+ ...lines > 1 ? {
41
+ "--mh-text-lines": String(lines)
42
+ } : {},
43
+ ...attrs.style
44
+ };
45
+ return h(props.as, {
46
+ ...attrs,
47
+ class: classes,
48
+ style
49
+ }, [slots.default?.()]);
50
+ };
51
+ }
52
+ });
53
+ export {
54
+ Text
55
+ };
@@ -99,9 +99,9 @@ export declare const Toast: import("vue").DefineComponent<import("vue").ExtractP
99
99
  onClose?: (() => any) | undefined;
100
100
  }>, {
101
101
  text: string;
102
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "wrench" | "plus" | "bell" | "settings" | "logout" | "home" | "workbench" | "grid-dots" | "heart" | "heart-filled" | "edit" | "refresh" | "upload" | "save" | "more" | "eye" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "sparkles" | "shield-check" | "shield-alert" | "history";
103
- tone: ToastTone;
102
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
104
103
  closable: boolean;
104
+ tone: ToastTone;
105
105
  action: string;
106
106
  onAction: () => void;
107
107
  duration: number;
@@ -151,9 +151,9 @@ export declare const ToastCompound: {
151
151
  close: () => true;
152
152
  }, import("vue").PublicProps, {
153
153
  text: string;
154
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "wrench" | "plus" | "bell" | "settings" | "logout" | "home" | "workbench" | "grid-dots" | "heart" | "heart-filled" | "edit" | "refresh" | "upload" | "save" | "more" | "eye" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "sparkles" | "shield-check" | "shield-alert" | "history";
155
- tone: ToastTone;
154
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
156
155
  closable: boolean;
156
+ tone: ToastTone;
157
157
  action: string;
158
158
  onAction: () => void;
159
159
  duration: number;
@@ -205,9 +205,9 @@ export declare const ToastCompound: {
205
205
  onClose?: (() => any) | undefined;
206
206
  }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, {
207
207
  text: string;
208
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "wrench" | "plus" | "bell" | "settings" | "logout" | "home" | "workbench" | "grid-dots" | "heart" | "heart-filled" | "edit" | "refresh" | "upload" | "save" | "more" | "eye" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "sparkles" | "shield-check" | "shield-alert" | "history";
209
- tone: ToastTone;
208
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
210
209
  closable: boolean;
210
+ tone: ToastTone;
211
211
  action: string;
212
212
  onAction: () => void;
213
213
  duration: number;
@@ -256,9 +256,9 @@ export declare const ToastCompound: {
256
256
  close: () => true;
257
257
  }, string, {
258
258
  text: string;
259
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "wrench" | "plus" | "bell" | "settings" | "logout" | "home" | "workbench" | "grid-dots" | "heart" | "heart-filled" | "edit" | "refresh" | "upload" | "save" | "more" | "eye" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "sparkles" | "shield-check" | "shield-alert" | "history";
260
- tone: ToastTone;
259
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
261
260
  closable: boolean;
261
+ tone: ToastTone;
262
262
  action: string;
263
263
  onAction: () => void;
264
264
  duration: number;
@@ -67,11 +67,20 @@ const Toast = /* @__PURE__ */ defineComponent({
67
67
  return () => {
68
68
  const hasAction = Boolean(props.action || slots.action);
69
69
  return createVNode("div", {
70
- "class": ["mh-toast", props.tone === "loading" ? "mh-toast--loading" : "", hasAction ? "mh-toast--action" : "", attrs.class].filter(Boolean).join(" "),
70
+ "class": [
71
+ "mh-toast",
72
+ /* 语义档一律落在**根修饰符**:`.mh-<件>--<tone>` 是本包 tone 维度的统一落点
73
+ (`Badge` / `Dialog` / `Notice` / `Notification` / `Tag` / `Text` 同款)。
74
+ 此前本件把 tone 落在 `.mh-toast__icon--<tone>`,是唯一一个落子元素修饰符的 ——
75
+ 消费方按「组件名 → 类名」的直觉拼 `.mh-toast--success` 会落空(缺陷 §3.5)。 */
76
+ `mh-toast--${props.tone}`,
77
+ hasAction ? "mh-toast--action" : "",
78
+ attrs.class
79
+ ].filter(Boolean).join(" "),
71
80
  "style": attrs.style,
72
81
  "role": "status"
73
82
  }, [props.icon === false ? null : createVNode("span", {
74
- "class": ["mh-toast__icon", `mh-toast__icon--${props.tone}`].join(" ")
83
+ "class": "mh-toast__icon"
75
84
  }, [createVNode(Icon, {
76
85
  "name": typeof props.icon === "string" ? props.icon : TONE_ICON[props.tone],
77
86
  "size": props.tone === "loading" ? 16 : 12
@@ -40,6 +40,12 @@ export declare const Upload: import("vue").DefineComponent<import("vue").Extract
40
40
  type: StringConstructor;
41
41
  default: undefined;
42
42
  };
43
+ /**
44
+ * 是否允许多选(**默认关**,与主流一致)。
45
+ *
46
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
47
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
48
+ */
43
49
  multiple: {
44
50
  type: BooleanConstructor;
45
51
  default: boolean;
@@ -94,6 +100,12 @@ export declare const Upload: import("vue").DefineComponent<import("vue").Extract
94
100
  type: StringConstructor;
95
101
  default: undefined;
96
102
  };
103
+ /**
104
+ * 是否允许多选(**默认关**,与主流一致)。
105
+ *
106
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
107
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
108
+ */
97
109
  multiple: {
98
110
  type: BooleanConstructor;
99
111
  default: boolean;
@@ -164,6 +176,12 @@ export declare const UploadCompound: {
164
176
  type: StringConstructor;
165
177
  default: undefined;
166
178
  };
179
+ /**
180
+ * 是否允许多选(**默认关**,与主流一致)。
181
+ *
182
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
183
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
184
+ */
167
185
  multiple: {
168
186
  type: BooleanConstructor;
169
187
  default: boolean;
@@ -239,6 +257,12 @@ export declare const UploadCompound: {
239
257
  type: StringConstructor;
240
258
  default: undefined;
241
259
  };
260
+ /**
261
+ * 是否允许多选(**默认关**,与主流一致)。
262
+ *
263
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
264
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
265
+ */
242
266
  multiple: {
243
267
  type: BooleanConstructor;
244
268
  default: boolean;
@@ -309,6 +333,12 @@ export declare const UploadCompound: {
309
333
  type: StringConstructor;
310
334
  default: undefined;
311
335
  };
336
+ /**
337
+ * 是否允许多选(**默认关**,与主流一致)。
338
+ *
339
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
340
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
341
+ */
312
342
  multiple: {
313
343
  type: BooleanConstructor;
314
344
  default: boolean;
@@ -19,9 +19,15 @@ const Upload = /* @__PURE__ */ defineComponent({
19
19
  type: String,
20
20
  default: void 0
21
21
  },
22
+ /**
23
+ * 是否允许多选(**默认关**,与主流一致)。
24
+ *
25
+ * 0.6.x 默认开 + `maxCount` 默认 0(不限量)⇒ 拖入一堆文件会被**静默全部接收** ——
26
+ * 单文件场景(换头像、传一份合同)因此多收文件且不报错。要多选请显式 `multiple`。
27
+ */
22
28
  multiple: {
23
29
  type: Boolean,
24
- default: true
30
+ default: false
25
31
  },
26
32
  disabled: {
27
33
  type: Boolean,