@manohub/ui 0.6.0 → 0.7.0
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/README.md +9 -1
- package/dist/components/button/index.d.ts +8 -8
- package/dist/components/dialog/index.d.ts +58 -6
- package/dist/components/dialog/index.js +45 -8
- package/dist/components/drawer/index.d.ts +18 -6
- package/dist/components/drawer/index.js +11 -5
- package/dist/components/input/index.d.ts +4 -4
- package/dist/components/input/index.js +1 -1
- package/dist/components/notice/index.d.ts +23 -10
- package/dist/components/notice/index.js +11 -5
- package/dist/components/notification/index.d.ts +1 -1
- package/dist/components/search/index.d.ts +33 -4
- package/dist/components/search/index.js +24 -8
- package/dist/components/table/index.d.ts +2 -1
- package/dist/components/tabs/index.d.ts +6 -2
- package/dist/components/tabs/index.js +9 -1
- package/dist/components/tabset/index.d.ts +6 -2
- package/dist/components/tabset/index.js +8 -1
- package/dist/components/tag/index.d.ts +1 -1
- package/dist/components/text/index.d.ts +120 -0
- package/dist/components/text/index.js +55 -0
- package/dist/components/toast/index.d.ts +4 -4
- package/dist/components/toast/index.js +11 -2
- package/dist/components/upload/index.d.ts +30 -0
- package/dist/components/upload/index.js +7 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/services/dialog.d.ts +20 -5
- package/dist/services/dialog.js +8 -1
- package/dist/styles/components/dialog.css +40 -1
- package/dist/styles/components/input.css +1 -1
- package/dist/styles/components/search.css +5 -1
- package/dist/styles/components/select.css +11 -0
- package/dist/styles/components/table.css +9 -4
- package/dist/styles/components/text.css +101 -0
- package/dist/styles/components/toast.css +12 -6
- package/dist/styles/index.css +5 -1
- package/dist/styles/reset.css +205 -0
- package/package.json +2 -2
|
@@ -102,7 +102,7 @@ export declare const Notification: import("vue").DefineComponent<import("vue").E
|
|
|
102
102
|
default: undefined;
|
|
103
103
|
};
|
|
104
104
|
}>> & Readonly<{}>, {
|
|
105
|
-
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" | "
|
|
105
|
+
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" | "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";
|
|
106
106
|
title: string;
|
|
107
107
|
onClose: () => void;
|
|
108
108
|
tone: NotificationTone;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type PropType } from 'vue';
|
|
2
2
|
import type { ControlSize } from '../control-size';
|
|
3
|
+
/** 搜索触发位的形态:`text` 主色文案按钮 / `icon` 纯图标按钮 */
|
|
4
|
+
export type SearchAction = 'text' | 'icon';
|
|
3
5
|
export interface SearchProps {
|
|
4
6
|
/** 受控值 */
|
|
5
7
|
modelValue?: string;
|
|
@@ -14,8 +16,10 @@ export interface SearchProps {
|
|
|
14
16
|
clearable?: boolean;
|
|
15
17
|
/** 搜索中:按钮进加载态并吞掉重复点击 */
|
|
16
18
|
loading?: boolean;
|
|
17
|
-
/**
|
|
19
|
+
/** 搜索按钮文案;**不传即不渲染按钮**(只留框内放大镜,提交走回车) */
|
|
18
20
|
searchText?: string;
|
|
21
|
+
/** 触发位形态(配合 `searchText` 或单独给):`text` 文案按钮 / `icon` 纯图标按钮 */
|
|
22
|
+
action?: SearchAction;
|
|
19
23
|
/** 值变更回调(每次输入都调,含清空) */
|
|
20
24
|
onChange?: (value: string) => void;
|
|
21
25
|
/** 搜索触发(点搜索按钮 / 输入框内回车) */
|
|
@@ -24,7 +28,20 @@ export interface SearchProps {
|
|
|
24
28
|
onClear?: () => void;
|
|
25
29
|
}
|
|
26
30
|
/**
|
|
27
|
-
* 搜索框(**自绘**;输入框 +
|
|
31
|
+
* 搜索框(**自绘**;输入框 + 可选搜索触发位的组合件)。
|
|
32
|
+
*
|
|
33
|
+
* ## 三种形态(**同屏只会出现一个「搜索」字形**)
|
|
34
|
+
*
|
|
35
|
+
* | 形态 | 怎么给 | 框内放大镜 | 右侧触发位 |
|
|
36
|
+
* | --- | --- | --- | --- |
|
|
37
|
+
* | 只有回车(缺省) | 什么都不给 | ✅ | 无 |
|
|
38
|
+
* | 图标按钮 | `action="icon"` | ❌(让给按钮) | 主色图标按钮 |
|
|
39
|
+
* | 文案按钮 | `searchText="搜索"` | ✅ | 主色文案按钮 |
|
|
40
|
+
*
|
|
41
|
+
* **框内放大镜与图标按钮不会同时出现** —— 两者是同一个语义的两种画法,
|
|
42
|
+
* 摆在一起就是「一行里两个放大镜,分不出哪个能点」(0.6.0 的缺陷,0.6.1 靠「不给按钮」绕开,
|
|
43
|
+
* 0.7.0 起由 `action="icon"` 把「图标按钮」这一档补上,取图标按钮时框内自动不再画装饰)。
|
|
44
|
+
* 缺省形态的提交走**回车**(`Input` 的 `onEnter` 与 `onSearch` 是同一次语义)。
|
|
28
45
|
*
|
|
29
46
|
* ## 为什么不是 `Input` 的一个档,而是单独一件
|
|
30
47
|
*
|
|
@@ -38,14 +55,14 @@ export interface SearchProps {
|
|
|
38
55
|
* ## 复用而不是重画
|
|
39
56
|
*
|
|
40
57
|
* 输入框那一段**就是本包的 `Input`**(框、内距、清除位、聚焦态、禁用态、`aria-invalid`
|
|
41
|
-
*
|
|
58
|
+
* 全部沿用输入框面),本件只加「一行里怎么摆」与(可选的)搜索按钮 —— 不另写一份输入框几何
|
|
42
59
|
* (两份几何必然在改令牌时漂开)。
|
|
43
60
|
*
|
|
44
61
|
* ## 受控口径(与全库同款)
|
|
45
62
|
*
|
|
46
63
|
* 传 `modelValue` 即受控(`update:modelValue` 与 `onChange` 双走),不传即非受控(由 `defaultValue` 起)。
|
|
47
64
|
*
|
|
48
|
-
* @example
|
|
65
|
+
* @example 最简(框内放大镜 + 回车触发)
|
|
49
66
|
* <Search modelValue={kw} onChange={setKw} onSearch={apply} />
|
|
50
67
|
*
|
|
51
68
|
* @example 带文案的搜索按钮 + 清空动作
|
|
@@ -57,6 +74,9 @@ export interface SearchProps {
|
|
|
57
74
|
* onSearch={apply}
|
|
58
75
|
* onClear={() => apply('')}
|
|
59
76
|
* />
|
|
77
|
+
*
|
|
78
|
+
* @example 纯图标按钮(框内不再画装饰放大镜;`searchText` 退化为无障碍名)
|
|
79
|
+
* <Search modelValue={kw} action="icon" search-text="搜索" onChange={setKw} onSearch={apply} />
|
|
60
80
|
*/
|
|
61
81
|
export declare const Search: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
62
82
|
modelValue: {
|
|
@@ -91,6 +111,10 @@ export declare const Search: import("vue").DefineComponent<import("vue").Extract
|
|
|
91
111
|
type: StringConstructor;
|
|
92
112
|
default: undefined;
|
|
93
113
|
};
|
|
114
|
+
action: {
|
|
115
|
+
type: PropType<SearchAction>;
|
|
116
|
+
default: undefined;
|
|
117
|
+
};
|
|
94
118
|
onChange: {
|
|
95
119
|
type: PropType<(value: string) => void>;
|
|
96
120
|
default: undefined;
|
|
@@ -138,6 +162,10 @@ export declare const Search: import("vue").DefineComponent<import("vue").Extract
|
|
|
138
162
|
type: StringConstructor;
|
|
139
163
|
default: undefined;
|
|
140
164
|
};
|
|
165
|
+
action: {
|
|
166
|
+
type: PropType<SearchAction>;
|
|
167
|
+
default: undefined;
|
|
168
|
+
};
|
|
141
169
|
onChange: {
|
|
142
170
|
type: PropType<(value: string) => void>;
|
|
143
171
|
default: undefined;
|
|
@@ -162,6 +190,7 @@ export declare const Search: import("vue").DefineComponent<import("vue").Extract
|
|
|
162
190
|
modelValue: string;
|
|
163
191
|
clearable: boolean;
|
|
164
192
|
searchText: string;
|
|
193
|
+
action: SearchAction;
|
|
165
194
|
onSearch: (value: string) => void;
|
|
166
195
|
onClear: () => void;
|
|
167
196
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -38,6 +38,10 @@ const Search = /* @__PURE__ */ defineComponent({
|
|
|
38
38
|
type: String,
|
|
39
39
|
default: void 0
|
|
40
40
|
},
|
|
41
|
+
action: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: void 0
|
|
44
|
+
},
|
|
41
45
|
onChange: {
|
|
42
46
|
type: Function,
|
|
43
47
|
default: void 0
|
|
@@ -69,6 +73,9 @@ const Search = /* @__PURE__ */ defineComponent({
|
|
|
69
73
|
if (cleared) props.onClear?.();
|
|
70
74
|
};
|
|
71
75
|
const search = () => props.onSearch?.(current.value ?? "");
|
|
76
|
+
const iconAction = computed(() => props.action === "icon");
|
|
77
|
+
const showAction = computed(() => iconAction.value || props.searchText !== void 0);
|
|
78
|
+
const actionLabel = computed(() => props.searchText ?? "搜索");
|
|
72
79
|
return () => createVNode("div", {
|
|
73
80
|
"class": ["mh-search", attrs.class].filter(Boolean).join(" "),
|
|
74
81
|
"style": attrs.style
|
|
@@ -82,22 +89,31 @@ const Search = /* @__PURE__ */ defineComponent({
|
|
|
82
89
|
"onChange": commit,
|
|
83
90
|
"onEnter": search
|
|
84
91
|
}, {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
default: () => [iconAction.value ? {} : {
|
|
93
|
+
prefix: () => createVNode(Icon, {
|
|
94
|
+
"name": "search"
|
|
95
|
+
}, null)
|
|
96
|
+
}]
|
|
97
|
+
}), showAction.value ? iconAction.value ? createVNode(Button, {
|
|
98
|
+
"class": "mh-search__btn",
|
|
99
|
+
"variant": "primary",
|
|
100
|
+
"size": props.size,
|
|
101
|
+
"icon": "search",
|
|
102
|
+
"title": actionLabel.value,
|
|
103
|
+
"disabled": props.disabled,
|
|
104
|
+
"loading": props.loading,
|
|
105
|
+
"onClick": search
|
|
106
|
+
}, null) : createVNode(Button, {
|
|
89
107
|
"class": "mh-search__btn",
|
|
90
|
-
"variant":
|
|
108
|
+
"variant": "primary",
|
|
91
109
|
"size": props.size,
|
|
92
110
|
"icon": "search",
|
|
93
111
|
"disabled": props.disabled,
|
|
94
112
|
"loading": props.loading,
|
|
95
|
-
"title": props.searchText ? void 0 : "搜索",
|
|
96
|
-
"aria-label": props.searchText ? void 0 : "搜索",
|
|
97
113
|
"onClick": search
|
|
98
114
|
}, {
|
|
99
115
|
default: () => props.searchText
|
|
100
|
-
})]);
|
|
116
|
+
}) : null]);
|
|
101
117
|
}
|
|
102
118
|
});
|
|
103
119
|
export {
|
|
@@ -37,7 +37,8 @@ export interface TablePagination {
|
|
|
37
37
|
* ## 这个组件负责什么、不负责什么(都是刻意的)
|
|
38
38
|
*
|
|
39
39
|
* **负责**:把 `columns` × `data` 渲成表格;列对齐/宽度/省略/必填;行选中(勾选列复用本包的 `Checkbox`
|
|
40
|
-
* 组件 —— 它内部才是真实 `<input type="checkbox">`,故面上的 `tr:has(input:checked)`
|
|
40
|
+
* 组件 —— 它内部才是真实 `<input type="checkbox">`,故面上的 `tr:has(.mh-table__col-check input:checked)`
|
|
41
|
+
* 零 JS 路径仍成立;选择器**限定在勾选列内**,否则功能列的 `Switch` 也会把整行点亮);
|
|
41
42
|
* 展开行;排序按钮的**状态与事件**;加载态与空态;分页条的排布与事件透传;
|
|
42
43
|
* `rowClass` / `onRow` 让调用方标分组行、禁用行与挂行级点击。
|
|
43
44
|
*
|
|
@@ -100,7 +100,9 @@ export declare const Tabs: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
100
100
|
type: PropType<() => void>;
|
|
101
101
|
default: undefined;
|
|
102
102
|
};
|
|
103
|
-
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
103
|
+
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
104
|
+
'update:value': (value: TabsValue) => true;
|
|
105
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
104
106
|
options: {
|
|
105
107
|
type: PropType<TabsOption[]>;
|
|
106
108
|
required: true;
|
|
@@ -160,7 +162,9 @@ export declare const Tabs: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
160
162
|
type: PropType<() => void>;
|
|
161
163
|
default: undefined;
|
|
162
164
|
};
|
|
163
|
-
}>> & Readonly<{
|
|
165
|
+
}>> & Readonly<{
|
|
166
|
+
"onUpdate:value"?: ((value: TabsValue) => any) | undefined;
|
|
167
|
+
}>, {
|
|
164
168
|
size: ControlSize;
|
|
165
169
|
value: TabsValue | undefined;
|
|
166
170
|
type: TabsType;
|
|
@@ -64,10 +64,17 @@ const Tabs = /* @__PURE__ */ defineComponent({
|
|
|
64
64
|
default: void 0
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
|
+
/* 受控值必须 emit 回 `update:value`,否则 `v-model:value="x"` 是**静默失效**的:
|
|
68
|
+
受控时 `props.value !== undefined` ⇒ 内部状态不更新,而外部又收不到新值 ⇒ 点 tab 毫无反应
|
|
69
|
+
(不报错、不警告)。本件 0.6.x 就漏了这条 —— 文档示例教 `v-model:value` 却点了不动。 */
|
|
70
|
+
emits: {
|
|
71
|
+
"update:value": (value) => true
|
|
72
|
+
},
|
|
67
73
|
slots: Object,
|
|
68
74
|
setup(props, {
|
|
69
75
|
slots,
|
|
70
|
-
attrs
|
|
76
|
+
attrs,
|
|
77
|
+
emit
|
|
71
78
|
}) {
|
|
72
79
|
const innerValue = ref(props.value ?? props.defaultValue ?? props.options[0]?.value);
|
|
73
80
|
const current = computed(() => props.value ?? innerValue.value);
|
|
@@ -76,6 +83,7 @@ const Tabs = /* @__PURE__ */ defineComponent({
|
|
|
76
83
|
const target = props.options.find((option) => option.value === value);
|
|
77
84
|
if (target?.disabled) return;
|
|
78
85
|
if (props.value === void 0) innerValue.value = value;
|
|
86
|
+
emit("update:value", value);
|
|
79
87
|
props.onChange?.(value);
|
|
80
88
|
};
|
|
81
89
|
const isClosable = (option) => option.closable ?? props.closable;
|
|
@@ -68,7 +68,9 @@ export declare const Tabset: import("vue").DefineComponent<import("vue").Extract
|
|
|
68
68
|
type: BooleanConstructor;
|
|
69
69
|
default: boolean;
|
|
70
70
|
};
|
|
71
|
-
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
71
|
+
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
72
|
+
'update:value': (value: string | number) => true;
|
|
73
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
72
74
|
options: {
|
|
73
75
|
type: PropType<TabsetOption[]>;
|
|
74
76
|
required: true;
|
|
@@ -90,7 +92,9 @@ export declare const Tabset: import("vue").DefineComponent<import("vue").Extract
|
|
|
90
92
|
type: BooleanConstructor;
|
|
91
93
|
default: boolean;
|
|
92
94
|
};
|
|
93
|
-
}>> & Readonly<{
|
|
95
|
+
}>> & Readonly<{
|
|
96
|
+
"onUpdate:value"?: ((value: string | number) => any) | undefined;
|
|
97
|
+
}>, {
|
|
94
98
|
value: string | number | undefined;
|
|
95
99
|
onChange: (value: string | number) => void;
|
|
96
100
|
defaultValue: string | number | undefined;
|
|
@@ -25,10 +25,16 @@ const Tabset = /* @__PURE__ */ defineComponent({
|
|
|
25
25
|
default: false
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
+
/* 同 `Tabs`:受控值必须 emit 回 `update:value`,否则 `v-model:value="current"` 静默失效
|
|
29
|
+
(受控时内部状态不更新、外部又收不到 ⇒ 点选项毫无反应)。 */
|
|
30
|
+
emits: {
|
|
31
|
+
"update:value": (value) => true
|
|
32
|
+
},
|
|
28
33
|
slots: Object,
|
|
29
34
|
setup(props, {
|
|
30
35
|
slots,
|
|
31
|
-
attrs
|
|
36
|
+
attrs,
|
|
37
|
+
emit
|
|
32
38
|
}) {
|
|
33
39
|
const innerValue = ref(props.value ?? props.defaultValue ?? props.options[0]?.value);
|
|
34
40
|
const current = computed(() => props.value ?? innerValue.value);
|
|
@@ -36,6 +42,7 @@ const Tabset = /* @__PURE__ */ defineComponent({
|
|
|
36
42
|
const target = props.options.find((option) => option.value === value);
|
|
37
43
|
if (target?.disabled) return;
|
|
38
44
|
if (props.value === void 0) innerValue.value = value;
|
|
45
|
+
emit("update:value", value);
|
|
39
46
|
props.onChange?.(value);
|
|
40
47
|
};
|
|
41
48
|
const panels = () => {
|
|
@@ -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" | "
|
|
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" | "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;
|
|
@@ -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,7 +99,7 @@ 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" | "
|
|
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" | "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";
|
|
103
103
|
tone: ToastTone;
|
|
104
104
|
closable: boolean;
|
|
105
105
|
action: string;
|
|
@@ -151,7 +151,7 @@ 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" | "
|
|
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" | "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";
|
|
155
155
|
tone: ToastTone;
|
|
156
156
|
closable: boolean;
|
|
157
157
|
action: string;
|
|
@@ -205,7 +205,7 @@ 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" | "
|
|
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" | "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";
|
|
209
209
|
tone: ToastTone;
|
|
210
210
|
closable: boolean;
|
|
211
211
|
action: string;
|
|
@@ -256,7 +256,7 @@ 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" | "
|
|
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" | "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";
|
|
260
260
|
tone: ToastTone;
|
|
261
261
|
closable: boolean;
|
|
262
262
|
action: string;
|
|
@@ -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": [
|
|
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":
|
|
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:
|
|
30
|
+
default: false
|
|
25
31
|
},
|
|
26
32
|
disabled: {
|
|
27
33
|
type: Boolean,
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export { Avatar, type AvatarProps, type AvatarSize, type AvatarCompound } from '
|
|
|
27
27
|
export { Skeleton, type SkeletonProps } from './components/skeleton';
|
|
28
28
|
export { Radio, type RadioProps, type RadioCompound, type RadioCompoundType, type RadioCardItem, type RadioCardValue, } from './components/radio';
|
|
29
29
|
export { Tag, type TagProps } from './components/tag';
|
|
30
|
+
export { Text, type TextProps, type TextSize, type TextTone, type TextWeight, type TextTag, } from './components/text';
|
|
30
31
|
export { Tree, type TreeNode } from './components/tree';
|
|
31
32
|
export { ListView, type ListViewProps, type ListViewStatus, type ListViewStatusTone, type ListViewCardItemProps, type ListViewCompound, } from './components/list-view';
|
|
32
33
|
export { Badge, type BadgeTone, type BadgeShape, type BadgeSize, type BadgeDot, type BadgeStatus, } from './components/badge';
|