@manohub/ui 0.10.1 → 0.10.3
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 +1 -1
- package/dist/components/badge/index.d.ts +46 -1
- package/dist/components/badge/index.js +42 -9
- package/dist/components/card/index.d.ts +1 -1
- package/dist/components/drawer/index.d.ts +1 -1
- package/dist/components/form/index.d.ts +50 -1
- package/dist/components/form/index.js +20 -2
- package/dist/components/input/index.js +1 -0
- package/dist/components/nav/index.d.ts +27 -0
- package/dist/components/nav/index.js +12 -0
- package/dist/components/notice/index.d.ts +1 -1
- package/dist/components/notification/index.d.ts +2 -2
- package/dist/components/select/index.d.ts +9 -0
- package/dist/components/select/index.js +57 -12
- package/dist/components/select/select-list.d.ts +42 -8
- package/dist/components/select/select-list.js +36 -11
- package/dist/components/select/select-panel.d.ts +36 -8
- package/dist/components/select/select-panel.js +18 -4
- package/dist/components/select/select-shared.d.ts +51 -10
- package/dist/components/select/select-shared.js +12 -2
- package/dist/components/select/select-tree.d.ts +25 -3
- package/dist/components/select/select-tree.js +17 -6
- package/dist/components/select/select-trigger.d.ts +21 -0
- package/dist/components/select/select-trigger.js +15 -1
- package/dist/components/tag/index.d.ts +32 -153
- package/dist/components/tag/index.js +102 -101
- package/dist/components/text/index.d.ts +1 -1
- package/dist/components/tooltip/index.d.ts +1 -1
- package/dist/components/tree/index.d.ts +65 -0
- package/dist/components/tree/index.js +29 -2
- package/dist/index.d.ts +1 -1
- package/dist/styles/components/avatar.css +2 -2
- package/dist/styles/components/badge.css +31 -4
- package/dist/styles/components/badge.tokens.css +24 -0
- package/dist/styles/components/button.css +7 -6
- package/dist/styles/components/button.tokens.css +5 -2
- package/dist/styles/components/dialog.css +13 -0
- package/dist/styles/components/divider.css +8 -4
- package/dist/styles/components/divider.tokens.css +2 -1
- package/dist/styles/components/form.css +51 -0
- package/dist/styles/components/notification.css +1 -1
- package/dist/styles/components/select.css +62 -39
- package/dist/styles/components/select.tokens.css +16 -9
- package/dist/styles/components/tag.css +77 -154
- package/dist/styles/components/tag.tokens.css +13 -19
- package/dist/styles/components/tree.css +37 -3
- package/dist/styles/components/tree.tokens.css +4 -3
- package/dist/styles/components/upload.tokens.css +1 -1
- package/dist/styles/index.css +2 -1
- package/dist/styles/operations/popup.css +5 -1
- package/package.json +2 -2
|
@@ -1,203 +1,82 @@
|
|
|
1
|
-
import { type IconName } from '@manohub/icon';
|
|
2
1
|
import { type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
3
|
-
import type
|
|
2
|
+
import { type BadgeShape, type BadgeSize, type BadgeTone } from '../badge';
|
|
3
|
+
/** 本件的形态:`Badge` 的三档 + `add`(新增入口,本件扩展档) */
|
|
4
|
+
export type TagShape = BadgeShape | 'add';
|
|
4
5
|
export interface TagProps {
|
|
5
6
|
/**
|
|
6
7
|
* 形态:
|
|
7
|
-
* - `
|
|
8
|
-
* - `
|
|
9
|
-
* - `select` 可选标签(渲染隐身原生 radio,选中态实底主色)
|
|
10
|
-
* - `add` 新增标签(虚线框 + 加号图标,点击回调)
|
|
11
|
-
* - `chip` 轻量筛选片
|
|
8
|
+
* - `soft`(缺省)/ `outline` / `plain` —— 转发给 `Badge` 的同名档;
|
|
9
|
+
* - `add` 新增入口:虚线入口点击后就地变窄输入框,`Enter` 提交回调 `onAdd`。
|
|
12
10
|
*/
|
|
13
|
-
shape?:
|
|
14
|
-
/**
|
|
15
|
-
tone?:
|
|
16
|
-
/**
|
|
17
|
-
size?:
|
|
18
|
-
/**
|
|
19
|
-
lg?: boolean;
|
|
20
|
-
/** 前置图标(图标包的闭合枚举) */
|
|
21
|
-
icon?: IconName;
|
|
22
|
-
/** 描边档:浅主色底 + 浅主色边(设计稿的标签配方,配 `size="sm"` 即「表格内标签」) */
|
|
23
|
-
outline?: boolean;
|
|
24
|
-
/** 可关闭(右端出现关闭位) */
|
|
11
|
+
shape?: TagShape;
|
|
12
|
+
/** 语义色档(转发 `Badge`;缺省 `default` 是中性面) */
|
|
13
|
+
tone?: BadgeTone;
|
|
14
|
+
/** 尺寸档(转发 `Badge`:`sm` 20 / `md` 24);缺省 `md`(与 `Badge` 的缺省 `sm` 不同,见下) */
|
|
15
|
+
size?: BadgeSize;
|
|
16
|
+
/** 可关闭:右端出现关闭位(**受控**:只回调 `onClose`,本件不删自己) */
|
|
25
17
|
closable?: boolean;
|
|
26
|
-
/**
|
|
27
|
-
color?: string;
|
|
28
|
-
/** `shape="select"` 的选中态 */
|
|
29
|
-
selected?: boolean;
|
|
30
|
-
/** 禁用(可选档不可点、转弱) */
|
|
31
|
-
disabled?: boolean;
|
|
32
|
-
/** `shape="select"` 的原生分组名与值(组内同名互斥) */
|
|
33
|
-
name?: string;
|
|
34
|
-
value?: string | number;
|
|
35
|
-
/** `shape="add"` / `chip` 的点击回调(`select` 档用 `onChange`) */
|
|
36
|
-
onClick?: () => void;
|
|
37
|
-
/** `shape="select"` 的选中变化回调 */
|
|
38
|
-
onChange?: (selected: boolean) => void;
|
|
39
|
-
/** 关闭回调(`closable` 的关闭位点击) */
|
|
18
|
+
/** 关闭位回调(`closable`) */
|
|
40
19
|
onClose?: () => void;
|
|
20
|
+
/** 新增档提交回调(`shape="add"`):载荷是用户敲定的标签名(已 trim、非空) */
|
|
21
|
+
onAdd?: (name: string) => void;
|
|
41
22
|
}
|
|
42
|
-
/**
|
|
43
|
-
* 标签(常规 / 状态 / 可选 / 新增 / 轻量筛选片)。
|
|
44
|
-
*
|
|
45
|
-
* **与 `Badge` 的判据**:`Badge` 是状态徽标(固定短、状态色、可带圆点/数字);
|
|
46
|
-
* 本件是内容标签(描述性文字,长度随内容,可能可选/可加/可关闭)。
|
|
47
|
-
*
|
|
48
|
-
* 可选档(`shape="select"`)是**原生 radio**:组内同名互斥、键盘方向键换项都由浏览器接管,
|
|
49
|
-
* 样式层靠 `:has(input:checked)` / `[data-state='selected']` / `.is-selected` 三源等价选态。
|
|
50
|
-
*
|
|
51
|
-
* 关闭是**受控**的:本件只回调 `onClose`,是否移除由业务决定(与 `Notification` 同一口径)——
|
|
52
|
-
* 组件自己删自己会让「关闭后又能从别处恢复」这类需求无解。
|
|
53
|
-
*
|
|
54
|
-
* @example 状态标签
|
|
55
|
-
* <Tag shape="status" tone="success">已通过</Tag>
|
|
56
|
-
*
|
|
57
|
-
* @example 可关闭的筛选条件
|
|
58
|
-
* <Tag closable icon="filter" onClose={() => remove('status')}>状态:已通过</Tag>
|
|
59
|
-
*
|
|
60
|
-
* @example 可选标签(同组互斥)
|
|
61
|
-
* <Tag shape="select" name="scope" value="all" :selected="v === 'all'" @change="select('all')">全部</Tag>
|
|
62
|
-
*/
|
|
63
23
|
export declare const Tag: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
64
24
|
shape: {
|
|
65
|
-
type: PropType<
|
|
25
|
+
type: PropType<TagShape>;
|
|
66
26
|
default: string;
|
|
67
27
|
};
|
|
68
28
|
tone: {
|
|
69
|
-
type: PropType<
|
|
70
|
-
default:
|
|
29
|
+
type: PropType<BadgeTone>;
|
|
30
|
+
default: string;
|
|
71
31
|
};
|
|
72
32
|
size: {
|
|
73
|
-
type: PropType<
|
|
33
|
+
type: PropType<BadgeSize>;
|
|
74
34
|
default: string;
|
|
75
35
|
};
|
|
76
|
-
lg: {
|
|
77
|
-
type: BooleanConstructor;
|
|
78
|
-
default: boolean;
|
|
79
|
-
};
|
|
80
|
-
icon: {
|
|
81
|
-
type: PropType<IconName>;
|
|
82
|
-
default: undefined;
|
|
83
|
-
};
|
|
84
|
-
outline: {
|
|
85
|
-
type: BooleanConstructor;
|
|
86
|
-
default: boolean;
|
|
87
|
-
};
|
|
88
36
|
closable: {
|
|
89
37
|
type: BooleanConstructor;
|
|
90
38
|
default: boolean;
|
|
91
39
|
};
|
|
92
|
-
|
|
93
|
-
type: StringConstructor;
|
|
94
|
-
default: undefined;
|
|
95
|
-
};
|
|
96
|
-
selected: {
|
|
97
|
-
type: BooleanConstructor;
|
|
98
|
-
default: boolean;
|
|
99
|
-
};
|
|
100
|
-
disabled: {
|
|
101
|
-
type: BooleanConstructor;
|
|
102
|
-
default: boolean;
|
|
103
|
-
};
|
|
104
|
-
name: {
|
|
105
|
-
type: StringConstructor;
|
|
106
|
-
default: undefined;
|
|
107
|
-
};
|
|
108
|
-
value: {
|
|
109
|
-
type: PropType<string | number>;
|
|
110
|
-
default: undefined;
|
|
111
|
-
};
|
|
112
|
-
onClick: {
|
|
40
|
+
onClose: {
|
|
113
41
|
type: PropType<() => void>;
|
|
114
42
|
default: undefined;
|
|
115
43
|
};
|
|
116
|
-
|
|
117
|
-
type: PropType<(
|
|
118
|
-
default: undefined;
|
|
119
|
-
};
|
|
120
|
-
onClose: {
|
|
121
|
-
type: PropType<() => void>;
|
|
44
|
+
onAdd: {
|
|
45
|
+
type: PropType<(name: string) => void>;
|
|
122
46
|
default: undefined;
|
|
123
47
|
};
|
|
124
48
|
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
125
49
|
shape: {
|
|
126
|
-
type: PropType<
|
|
50
|
+
type: PropType<TagShape>;
|
|
127
51
|
default: string;
|
|
128
52
|
};
|
|
129
53
|
tone: {
|
|
130
|
-
type: PropType<
|
|
131
|
-
default:
|
|
54
|
+
type: PropType<BadgeTone>;
|
|
55
|
+
default: string;
|
|
132
56
|
};
|
|
133
57
|
size: {
|
|
134
|
-
type: PropType<
|
|
58
|
+
type: PropType<BadgeSize>;
|
|
135
59
|
default: string;
|
|
136
60
|
};
|
|
137
|
-
lg: {
|
|
138
|
-
type: BooleanConstructor;
|
|
139
|
-
default: boolean;
|
|
140
|
-
};
|
|
141
|
-
icon: {
|
|
142
|
-
type: PropType<IconName>;
|
|
143
|
-
default: undefined;
|
|
144
|
-
};
|
|
145
|
-
outline: {
|
|
146
|
-
type: BooleanConstructor;
|
|
147
|
-
default: boolean;
|
|
148
|
-
};
|
|
149
61
|
closable: {
|
|
150
62
|
type: BooleanConstructor;
|
|
151
63
|
default: boolean;
|
|
152
64
|
};
|
|
153
|
-
|
|
154
|
-
type: StringConstructor;
|
|
155
|
-
default: undefined;
|
|
156
|
-
};
|
|
157
|
-
selected: {
|
|
158
|
-
type: BooleanConstructor;
|
|
159
|
-
default: boolean;
|
|
160
|
-
};
|
|
161
|
-
disabled: {
|
|
162
|
-
type: BooleanConstructor;
|
|
163
|
-
default: boolean;
|
|
164
|
-
};
|
|
165
|
-
name: {
|
|
166
|
-
type: StringConstructor;
|
|
167
|
-
default: undefined;
|
|
168
|
-
};
|
|
169
|
-
value: {
|
|
170
|
-
type: PropType<string | number>;
|
|
171
|
-
default: undefined;
|
|
172
|
-
};
|
|
173
|
-
onClick: {
|
|
65
|
+
onClose: {
|
|
174
66
|
type: PropType<() => void>;
|
|
175
67
|
default: undefined;
|
|
176
68
|
};
|
|
177
|
-
|
|
178
|
-
type: PropType<(
|
|
179
|
-
default: undefined;
|
|
180
|
-
};
|
|
181
|
-
onClose: {
|
|
182
|
-
type: PropType<() => void>;
|
|
69
|
+
onAdd: {
|
|
70
|
+
type: PropType<(name: string) => void>;
|
|
183
71
|
default: undefined;
|
|
184
72
|
};
|
|
185
73
|
}>> & Readonly<{}>, {
|
|
186
|
-
|
|
187
|
-
size: ControlSize;
|
|
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" | "info-circle" | "check-circle" | "alert-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
|
|
189
|
-
disabled: boolean;
|
|
190
|
-
name: string;
|
|
191
|
-
value: string | number;
|
|
192
|
-
onChange: (selected: boolean) => void;
|
|
193
|
-
onClick: () => void;
|
|
74
|
+
size: BadgeSize;
|
|
194
75
|
onClose: () => void;
|
|
195
|
-
|
|
196
|
-
selected: boolean;
|
|
197
|
-
lg: boolean;
|
|
198
|
-
shape: "add" | "select" | "chip" | "regular" | "status" | undefined;
|
|
76
|
+
shape: TagShape;
|
|
199
77
|
closable: boolean;
|
|
200
|
-
|
|
78
|
+
onAdd: (name: string) => void;
|
|
79
|
+
tone: BadgeTone;
|
|
201
80
|
}, SlotsType<{
|
|
202
81
|
default?: () => VNodeChild;
|
|
203
82
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,69 +1,34 @@
|
|
|
1
|
-
import { defineComponent, computed, createVNode, mergeProps, Fragment
|
|
1
|
+
import { defineComponent, computed, ref, watch, createVNode, mergeProps, Fragment } from "vue";
|
|
2
2
|
import { Icon } from "@manohub/icon";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
3
|
+
import { Badge } from "../badge/index.js";
|
|
4
|
+
import { Input } from "../input/index.js";
|
|
6
5
|
const Tag = /* @__PURE__ */ defineComponent({
|
|
7
6
|
name: "Tag",
|
|
8
7
|
inheritAttrs: false,
|
|
9
8
|
props: {
|
|
10
9
|
shape: {
|
|
11
10
|
type: String,
|
|
12
|
-
default: "
|
|
11
|
+
default: "soft"
|
|
13
12
|
},
|
|
14
13
|
tone: {
|
|
15
14
|
type: String,
|
|
16
|
-
default:
|
|
15
|
+
default: "default"
|
|
17
16
|
},
|
|
17
|
+
/* 缺省 `md`(24)而不是跟随 `Badge` 的 `sm`(20):标签比徽标常用大一号 —— 它是列表项 / 卡片头
|
|
18
|
+
里承载文字的那一枚,20 档留给「表格内标签」那种密集场景(显式写 `size="sm"`)。 */
|
|
18
19
|
size: {
|
|
19
20
|
type: String,
|
|
20
21
|
default: "md"
|
|
21
22
|
},
|
|
22
|
-
lg: {
|
|
23
|
-
type: Boolean,
|
|
24
|
-
default: false
|
|
25
|
-
},
|
|
26
|
-
icon: {
|
|
27
|
-
type: String,
|
|
28
|
-
default: void 0
|
|
29
|
-
},
|
|
30
|
-
outline: {
|
|
31
|
-
type: Boolean,
|
|
32
|
-
default: false
|
|
33
|
-
},
|
|
34
23
|
closable: {
|
|
35
24
|
type: Boolean,
|
|
36
25
|
default: false
|
|
37
26
|
},
|
|
38
|
-
|
|
39
|
-
type: String,
|
|
40
|
-
default: void 0
|
|
41
|
-
},
|
|
42
|
-
selected: {
|
|
43
|
-
type: Boolean,
|
|
44
|
-
default: false
|
|
45
|
-
},
|
|
46
|
-
disabled: {
|
|
47
|
-
type: Boolean,
|
|
48
|
-
default: false
|
|
49
|
-
},
|
|
50
|
-
name: {
|
|
51
|
-
type: String,
|
|
52
|
-
default: void 0
|
|
53
|
-
},
|
|
54
|
-
value: {
|
|
55
|
-
type: [String, Number],
|
|
56
|
-
default: void 0
|
|
57
|
-
},
|
|
58
|
-
onClick: {
|
|
59
|
-
type: Function,
|
|
60
|
-
default: void 0
|
|
61
|
-
},
|
|
62
|
-
onChange: {
|
|
27
|
+
onClose: {
|
|
63
28
|
type: Function,
|
|
64
29
|
default: void 0
|
|
65
30
|
},
|
|
66
|
-
|
|
31
|
+
onAdd: {
|
|
67
32
|
type: Function,
|
|
68
33
|
default: void 0
|
|
69
34
|
}
|
|
@@ -73,68 +38,104 @@ const Tag = /* @__PURE__ */ defineComponent({
|
|
|
73
38
|
slots,
|
|
74
39
|
attrs
|
|
75
40
|
}) {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
41
|
+
const isAdd = computed(() => props.shape === "add");
|
|
42
|
+
const baseShape = computed(() => props.shape === "add" ? "plain" : props.shape);
|
|
43
|
+
const editing = ref(false);
|
|
44
|
+
const draft = ref("");
|
|
45
|
+
const editorRef = ref(null);
|
|
46
|
+
const startEdit = () => {
|
|
47
|
+
draft.value = "";
|
|
48
|
+
editing.value = true;
|
|
49
|
+
};
|
|
50
|
+
const stopEdit = () => {
|
|
51
|
+
editing.value = false;
|
|
52
|
+
draft.value = "";
|
|
53
|
+
};
|
|
54
|
+
const submit = () => {
|
|
55
|
+
const name = draft.value.trim();
|
|
56
|
+
if (!name) return;
|
|
57
|
+
props.onAdd?.(name);
|
|
58
|
+
stopEdit();
|
|
59
|
+
};
|
|
60
|
+
watch(editing, (on) => {
|
|
61
|
+
if (!on) return;
|
|
62
|
+
editorRef.value?.querySelector("input")?.focus();
|
|
63
|
+
}, {
|
|
64
|
+
flush: "post"
|
|
65
|
+
});
|
|
66
|
+
const onEditorKeydown = (event) => {
|
|
67
|
+
if (event.key !== "Escape") return;
|
|
68
|
+
event.stopPropagation();
|
|
69
|
+
stopEdit();
|
|
70
|
+
};
|
|
71
|
+
const onEditorFocusout = (event) => {
|
|
72
|
+
const next = event.relatedTarget;
|
|
73
|
+
if (next && editorRef.value?.contains(next)) return;
|
|
74
|
+
stopEdit();
|
|
75
|
+
};
|
|
76
|
+
const forwardAttrs = computed(() => {
|
|
77
|
+
const rest = {};
|
|
78
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
79
|
+
if (key !== "class" && key !== "style") rest[key] = value;
|
|
94
80
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
if (isAdd.value) {
|
|
82
|
+
const consumer = rest.onClick;
|
|
83
|
+
rest.onClick = (event) => {
|
|
84
|
+
consumer?.(event);
|
|
85
|
+
startEdit();
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return rest;
|
|
89
|
+
});
|
|
98
90
|
return () => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
91
|
+
if (isAdd.value && editing.value) {
|
|
92
|
+
return createVNode("span", {
|
|
93
|
+
"ref": editorRef,
|
|
94
|
+
"class": "mh-tag mh-tag--editing",
|
|
95
|
+
"onKeydown": onEditorKeydown,
|
|
96
|
+
"onFocusout": onEditorFocusout
|
|
97
|
+
}, [createVNode(Input, {
|
|
98
|
+
"class": "mh-tag__input",
|
|
99
|
+
"size": "sm",
|
|
100
|
+
"modelValue": draft.value,
|
|
101
|
+
"placeholder": "输入标签名",
|
|
102
|
+
"aria-label": "标签名",
|
|
103
|
+
"onChange": (value) => draft.value = value,
|
|
104
|
+
"onEnter": () => submit()
|
|
105
|
+
}, null), createVNode("button", {
|
|
106
106
|
"type": "button",
|
|
107
|
-
"class":
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
107
|
+
"class": "mh-tag__confirm",
|
|
108
|
+
"aria-label": "添加",
|
|
109
|
+
"tabindex": -1,
|
|
110
|
+
"onMousedown": (event) => event.preventDefault(),
|
|
111
|
+
"onClick": () => submit()
|
|
111
112
|
}, [createVNode(Icon, {
|
|
112
|
-
"name": "plus"
|
|
113
|
-
|
|
114
|
-
}, null), slots.default?.()]);
|
|
115
|
-
}
|
|
116
|
-
if (props.shape === "select") {
|
|
117
|
-
return createVNode("label", {
|
|
118
|
-
"class": classes(),
|
|
119
|
-
"style": style
|
|
120
|
-
}, [createVNode("input", {
|
|
121
|
-
"type": "radio",
|
|
122
|
-
"name": props.name,
|
|
123
|
-
"value": props.value,
|
|
124
|
-
"checked": props.selected,
|
|
125
|
-
"disabled": props.disabled,
|
|
126
|
-
"onChange": (event) => props.onChange?.(event.target.checked)
|
|
127
|
-
}, null), content()]);
|
|
113
|
+
"name": "plus"
|
|
114
|
+
}, null)])]);
|
|
128
115
|
}
|
|
129
|
-
const
|
|
130
|
-
return createVNode(
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
116
|
+
const extraClass = attrs.class;
|
|
117
|
+
return createVNode(Badge, mergeProps(forwardAttrs.value, {
|
|
118
|
+
"as": isAdd.value ? "button" : "span",
|
|
119
|
+
"tone": props.tone,
|
|
120
|
+
"shape": baseShape.value,
|
|
121
|
+
"size": props.size,
|
|
122
|
+
"class": ["mh-tag", isAdd.value ? "mh-tag--add" : void 0, extraClass].filter(Boolean).join(" "),
|
|
123
|
+
"style": attrs.style
|
|
124
|
+
}), {
|
|
125
|
+
default: () => createVNode(Fragment, null, [isAdd.value ? createVNode(Icon, {
|
|
126
|
+
"name": "plus"
|
|
127
|
+
}, null) : null, slots.default?.(), props.closable && !isAdd.value ? createVNode("button", {
|
|
128
|
+
"type": "button",
|
|
129
|
+
"class": "mh-tag__close",
|
|
130
|
+
"aria-label": "关闭",
|
|
131
|
+
"tabindex": -1,
|
|
132
|
+
"onClick": (event) => {
|
|
133
|
+
event.stopPropagation();
|
|
134
|
+
props.onClose?.();
|
|
135
|
+
}
|
|
136
|
+
}, [createVNode(Icon, {
|
|
137
|
+
"name": "close"
|
|
138
|
+
}, null)]) : null])
|
|
138
139
|
});
|
|
139
140
|
};
|
|
140
141
|
}
|
|
@@ -118,9 +118,9 @@ export declare const Text: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
118
118
|
size: TextSize;
|
|
119
119
|
weight: TextWeight;
|
|
120
120
|
tone: TextTone;
|
|
121
|
+
as: TextTag;
|
|
121
122
|
mono: boolean;
|
|
122
123
|
truncate: number | boolean;
|
|
123
|
-
as: TextTag;
|
|
124
124
|
}, SlotsType<{
|
|
125
125
|
default?: () => VNodeChild;
|
|
126
126
|
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -115,10 +115,10 @@ export declare const Tooltip: import("vue").DefineComponent<import("vue").Extrac
|
|
|
115
115
|
title: string;
|
|
116
116
|
align: TooltipAlign;
|
|
117
117
|
action: string;
|
|
118
|
-
onAction: () => void;
|
|
119
118
|
side: TooltipSide;
|
|
120
119
|
trigger: TooltipTrigger;
|
|
121
120
|
guide: boolean;
|
|
121
|
+
onAction: () => void;
|
|
122
122
|
}, SlotsType<{
|
|
123
123
|
default?: () => VNodeChild;
|
|
124
124
|
content?: () => VNodeChild;
|
|
@@ -43,12 +43,25 @@ export interface TreeNode {
|
|
|
43
43
|
* 应用侧只给节点;操作容器自己做 `stopPropagation`,所以点「删除」不会顺带把这一行选中。
|
|
44
44
|
* 导航件(`Nav`)因此不必重写一份行渲染,把数据与 `renderActions` 透传进来即可。
|
|
45
45
|
*
|
|
46
|
+
* ## 图标出口(两处,都是「位」而不是「样式」)
|
|
47
|
+
*
|
|
48
|
+
* 行内的图标位只有两处,各自独立,缺省都不改变现有几何:
|
|
49
|
+
* - `renderCaret(node, expanded)` 替掉**箭头字形**(槽位 / 点击 / `data-expanded` 仍归组件);
|
|
50
|
+
* - `renderIcon(node)` 是标签**前**的节点图标槽(文件夹 / 文件一类),父子节点共用一位。
|
|
51
|
+
*
|
|
52
|
+
* 不在其中之列的(标题里的图标 + 文字)走 `renderLabel`:那属于标签**本体**。
|
|
53
|
+
*
|
|
46
54
|
* @example 受控展开 + 计数徽标 + 行尾操作
|
|
47
55
|
* <Tree nodes={treeNodes.value} rowKey="id" labelKey="name"
|
|
48
56
|
* selected={selectedId.value} onSelect={(n) => select(n.id)}
|
|
49
57
|
* expandedKeys={expandedKeys.value} onExpandChange={(k) => (expandedKeys.value = k)}
|
|
50
58
|
* renderNode={(n) => <Badge>{countOfDomain(n.id)}</Badge>}
|
|
51
59
|
* renderActions={(n) => <Button title="删除" onClick={() => removeDomain(n.id)} />} />
|
|
60
|
+
*
|
|
61
|
+
* @example 文件夹 / 文件图标 + 方向字形自表达(不靠旋转)
|
|
62
|
+
* <Tree nodes={tree.value} rowKey="id"
|
|
63
|
+
* renderIcon={(n) => <Icon name={hasChild(n) ? 'folder' : 'file-text'} />}
|
|
64
|
+
* renderCaret={(_n, expanded) => <Icon name={expanded ? 'chevron-down' : 'chevron-right'} />} />
|
|
52
65
|
*/
|
|
53
66
|
export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
54
67
|
nodes: {
|
|
@@ -92,6 +105,31 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
92
105
|
type: PropType<(node: TreeNode) => unknown>;
|
|
93
106
|
default: undefined;
|
|
94
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* 展开 / 收起箭头的自定义渲染(拿到节点与**当前展开态**)。
|
|
110
|
+
*
|
|
111
|
+
* 缺省仍是 `chevron-down` 字形 + 面层收起态转 −90°(默认路径零变化)。
|
|
112
|
+
* 自定义时**朝向由消费方按 `expanded` 自选字形**(`chevron-right` / `chevron-down`)——
|
|
113
|
+
* 与包内「方位一律用字形、不靠旋转别的图标」的口径同源;**不要再给内容加
|
|
114
|
+
* `mh-tree__caret-icon` 类**(那是缺省字形的转向钩子,加上会被转成 −90°)。
|
|
115
|
+
* 尺寸不必自管:槽位与槽内字形都取全局图标档 `--ui-font-icon`。
|
|
116
|
+
*/
|
|
117
|
+
renderCaret: {
|
|
118
|
+
type: PropType<(node: TreeNode, expanded: boolean) => unknown>;
|
|
119
|
+
default: undefined;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* 标签**前**的节点图标槽(文件夹 / 文件一类)。
|
|
123
|
+
*
|
|
124
|
+
* 父节点与叶子节点**都由消费方按 `node` 判定**(组件不替它猜「是不是叶子」:同一个图标槽
|
|
125
|
+
* 在两种节点上都成立,判定依据是数据而不是渲染期形态)。缺省不渲染该槽,几何零变化。
|
|
126
|
+
* 叶子行的箭头占位仍保留,故图标列跨层级对齐。颜色不写死:跟随行色,
|
|
127
|
+
* 选中行的主色字与滑过态自动同步。
|
|
128
|
+
*/
|
|
129
|
+
renderIcon: {
|
|
130
|
+
type: PropType<(node: TreeNode) => unknown>;
|
|
131
|
+
default: undefined;
|
|
132
|
+
};
|
|
95
133
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
96
134
|
renderNode: {
|
|
97
135
|
type: PropType<(node: TreeNode) => unknown>;
|
|
@@ -225,6 +263,31 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
225
263
|
type: PropType<(node: TreeNode) => unknown>;
|
|
226
264
|
default: undefined;
|
|
227
265
|
};
|
|
266
|
+
/**
|
|
267
|
+
* 展开 / 收起箭头的自定义渲染(拿到节点与**当前展开态**)。
|
|
268
|
+
*
|
|
269
|
+
* 缺省仍是 `chevron-down` 字形 + 面层收起态转 −90°(默认路径零变化)。
|
|
270
|
+
* 自定义时**朝向由消费方按 `expanded` 自选字形**(`chevron-right` / `chevron-down`)——
|
|
271
|
+
* 与包内「方位一律用字形、不靠旋转别的图标」的口径同源;**不要再给内容加
|
|
272
|
+
* `mh-tree__caret-icon` 类**(那是缺省字形的转向钩子,加上会被转成 −90°)。
|
|
273
|
+
* 尺寸不必自管:槽位与槽内字形都取全局图标档 `--ui-font-icon`。
|
|
274
|
+
*/
|
|
275
|
+
renderCaret: {
|
|
276
|
+
type: PropType<(node: TreeNode, expanded: boolean) => unknown>;
|
|
277
|
+
default: undefined;
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* 标签**前**的节点图标槽(文件夹 / 文件一类)。
|
|
281
|
+
*
|
|
282
|
+
* 父节点与叶子节点**都由消费方按 `node` 判定**(组件不替它猜「是不是叶子」:同一个图标槽
|
|
283
|
+
* 在两种节点上都成立,判定依据是数据而不是渲染期形态)。缺省不渲染该槽,几何零变化。
|
|
284
|
+
* 叶子行的箭头占位仍保留,故图标列跨层级对齐。颜色不写死:跟随行色,
|
|
285
|
+
* 选中行的主色字与滑过态自动同步。
|
|
286
|
+
*/
|
|
287
|
+
renderIcon: {
|
|
288
|
+
type: PropType<(node: TreeNode) => unknown>;
|
|
289
|
+
default: undefined;
|
|
290
|
+
};
|
|
228
291
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
229
292
|
renderNode: {
|
|
230
293
|
type: PropType<(node: TreeNode) => unknown>;
|
|
@@ -331,6 +394,8 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
331
394
|
labelKey: string;
|
|
332
395
|
childrenKey: string;
|
|
333
396
|
renderLabel: (node: TreeNode) => unknown;
|
|
397
|
+
renderCaret: (node: TreeNode, expanded: boolean) => unknown;
|
|
398
|
+
renderIcon: (node: TreeNode) => unknown;
|
|
334
399
|
renderNode: (node: TreeNode) => unknown;
|
|
335
400
|
renderActions: (node: TreeNode) => unknown;
|
|
336
401
|
expandedKeys: string[];
|
|
@@ -46,6 +46,31 @@ const Tree = /* @__PURE__ */ defineComponent({
|
|
|
46
46
|
type: Function,
|
|
47
47
|
default: void 0
|
|
48
48
|
},
|
|
49
|
+
/**
|
|
50
|
+
* 展开 / 收起箭头的自定义渲染(拿到节点与**当前展开态**)。
|
|
51
|
+
*
|
|
52
|
+
* 缺省仍是 `chevron-down` 字形 + 面层收起态转 −90°(默认路径零变化)。
|
|
53
|
+
* 自定义时**朝向由消费方按 `expanded` 自选字形**(`chevron-right` / `chevron-down`)——
|
|
54
|
+
* 与包内「方位一律用字形、不靠旋转别的图标」的口径同源;**不要再给内容加
|
|
55
|
+
* `mh-tree__caret-icon` 类**(那是缺省字形的转向钩子,加上会被转成 −90°)。
|
|
56
|
+
* 尺寸不必自管:槽位与槽内字形都取全局图标档 `--ui-font-icon`。
|
|
57
|
+
*/
|
|
58
|
+
renderCaret: {
|
|
59
|
+
type: Function,
|
|
60
|
+
default: void 0
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* 标签**前**的节点图标槽(文件夹 / 文件一类)。
|
|
64
|
+
*
|
|
65
|
+
* 父节点与叶子节点**都由消费方按 `node` 判定**(组件不替它猜「是不是叶子」:同一个图标槽
|
|
66
|
+
* 在两种节点上都成立,判定依据是数据而不是渲染期形态)。缺省不渲染该槽,几何零变化。
|
|
67
|
+
* 叶子行的箭头占位仍保留,故图标列跨层级对齐。颜色不写死:跟随行色,
|
|
68
|
+
* 选中行的主色字与滑过态自动同步。
|
|
69
|
+
*/
|
|
70
|
+
renderIcon: {
|
|
71
|
+
type: Function,
|
|
72
|
+
default: void 0
|
|
73
|
+
},
|
|
49
74
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
50
75
|
renderNode: {
|
|
51
76
|
type: Function,
|
|
@@ -237,12 +262,14 @@ const Tree = /* @__PURE__ */ defineComponent({
|
|
|
237
262
|
event.stopPropagation();
|
|
238
263
|
toggleExpand(key);
|
|
239
264
|
}
|
|
240
|
-
}, [createVNode(Icon, {
|
|
265
|
+
}, [props.renderCaret ? props.renderCaret(node, expanded) : createVNode(Icon, {
|
|
241
266
|
"name": "chevron-down",
|
|
242
267
|
"class": "mh-tree__caret-icon"
|
|
243
268
|
}, null)]) : createVNode("span", {
|
|
244
269
|
"class": "mh-tree__caret mh-tree__caret--empty"
|
|
245
|
-
}, null), createVNode("span", {
|
|
270
|
+
}, null), props.renderIcon ? createVNode("span", {
|
|
271
|
+
"class": "mh-tree__icon"
|
|
272
|
+
}, [props.renderIcon(node)]) : null, createVNode("span", {
|
|
246
273
|
"class": "mh-tree__label"
|
|
247
274
|
}, [props.renderLabel ? props.renderLabel(node) : String(node[props.labelKey] ?? "")]), props.renderNode ? createVNode("span", {
|
|
248
275
|
"class": "mh-tree__extra"
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export { Layout, type LayoutGap, type LayoutAlign, type LayoutJustify, type Layo
|
|
|
26
26
|
export { Avatar, type AvatarProps, type AvatarSize, type AvatarCompound } from './components/avatar';
|
|
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
|
-
export { Tag, type TagProps } from './components/tag';
|
|
29
|
+
export { Tag, type TagProps, type TagShape } from './components/tag';
|
|
30
30
|
export { Text, type TextProps, type TextSize, type TextTone, type TextWeight, type TextTag, } from './components/text';
|
|
31
31
|
export { Tree, type TreeNode } from './components/tree';
|
|
32
32
|
export { ListView, type ListViewProps, type ListViewStatus, type ListViewStatusTone, type ListViewCardItemProps, type ListViewCompound, } from './components/list-view';
|