@manohub/ui 0.7.1 → 0.8.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 +1 -1
- package/dist/components/button/index.d.ts +6 -0
- package/dist/components/card/index.d.ts +1 -1
- package/dist/components/form/index.d.ts +28 -46
- package/dist/components/form/index.js +3 -21
- package/dist/components/input/index.d.ts +74 -6
- package/dist/components/input/index.js +13 -1
- package/dist/components/list-view/index.d.ts +1 -1
- package/dist/components/pagination/index.d.ts +2 -2
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/query-state/index.d.ts +18 -2
- package/dist/components/select/index.d.ts +32 -30
- package/dist/components/select/index.js +46 -82
- package/dist/components/select/select-list.d.ts +125 -0
- package/dist/components/select/select-list.js +95 -0
- package/dist/components/select/select-panel.d.ts +106 -0
- package/dist/components/select/select-panel.js +72 -0
- package/dist/components/select/select-shared.d.ts +64 -0
- package/dist/components/select/select-shared.js +24 -0
- package/dist/components/select/select-tree-filter.d.ts +61 -0
- package/dist/components/select/select-tree-filter.js +63 -0
- package/dist/components/select/select-tree.d.ts +274 -0
- package/dist/components/select/select-tree.js +263 -0
- package/dist/components/select/select-trigger.d.ts +132 -0
- package/dist/components/select/select-trigger.js +101 -0
- package/dist/components/steps/index.d.ts +1 -1
- package/dist/components/table/index.d.ts +25 -4
- package/dist/components/text/index.d.ts +7 -2
- package/dist/components/tree/index.d.ts +28 -2
- package/dist/components/tree/index.js +14 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/styles/components/form.css +0 -21
- package/dist/styles/components/input.css +25 -0
- package/dist/styles/components/select.css +21 -0
- package/dist/styles/components/select.tokens.css +3 -0
- package/package.json +2 -2
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type PropType, type VNodeChild } from 'vue';
|
|
2
|
+
import { type InputStatus } from '../input';
|
|
3
|
+
import type { ControlSize } from '../control-size';
|
|
4
|
+
export declare const SelectTrigger: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
5
|
+
/** 面板 id(`popovertarget` 的目标,由 `createSelectPanelId()` 产出的全页唯一 id) */
|
|
6
|
+
panelId: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
required: true;
|
|
9
|
+
};
|
|
10
|
+
/** 尺寸档(24 / 28 / 32):框高与字号归输入面,本件只透传 */
|
|
11
|
+
size: {
|
|
12
|
+
type: PropType<ControlSize>;
|
|
13
|
+
default: string;
|
|
14
|
+
};
|
|
15
|
+
/** 校验状态(红 / 黄;与输入框同一词表) */
|
|
16
|
+
status: {
|
|
17
|
+
type: PropType<InputStatus>;
|
|
18
|
+
default: undefined;
|
|
19
|
+
};
|
|
20
|
+
disabled: {
|
|
21
|
+
type: BooleanConstructor;
|
|
22
|
+
default: boolean;
|
|
23
|
+
};
|
|
24
|
+
clearable: {
|
|
25
|
+
type: BooleanConstructor;
|
|
26
|
+
default: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** 显式判定清除位显隐(多选的值是数组、单选显示的是 label,都没有「一个字符串模型」可喂) */
|
|
29
|
+
hasValue: {
|
|
30
|
+
type: BooleanConstructor;
|
|
31
|
+
default: boolean;
|
|
32
|
+
};
|
|
33
|
+
/** 多选形态(控件上多一个 `mh-select--multiple`,标签不换行) */
|
|
34
|
+
multiple: {
|
|
35
|
+
type: BooleanConstructor;
|
|
36
|
+
default: boolean;
|
|
37
|
+
};
|
|
38
|
+
placeholder: {
|
|
39
|
+
type: StringConstructor;
|
|
40
|
+
default: string;
|
|
41
|
+
};
|
|
42
|
+
/** 单选显示文本(无值时不渲染它,改渲染 `placeholder`) */
|
|
43
|
+
label: {
|
|
44
|
+
type: StringConstructor;
|
|
45
|
+
default: undefined;
|
|
46
|
+
};
|
|
47
|
+
/** 触发器上的键盘契约(`createTriggerKeydown()` 产出,两件同源) */
|
|
48
|
+
onKeydown: {
|
|
49
|
+
type: PropType<(event: KeyboardEvent) => void>;
|
|
50
|
+
default: undefined;
|
|
51
|
+
};
|
|
52
|
+
/** 清除位被点击(输入面的内建清除位回调;本件只把它转给消费方) */
|
|
53
|
+
onClear: {
|
|
54
|
+
type: PropType<() => void>;
|
|
55
|
+
default: undefined;
|
|
56
|
+
};
|
|
57
|
+
/** 值区自定义渲染(多选标签收纳用;不给则走单选那一行) */
|
|
58
|
+
renderValue: {
|
|
59
|
+
type: PropType<() => VNodeChild>;
|
|
60
|
+
default: undefined;
|
|
61
|
+
};
|
|
62
|
+
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
63
|
+
/** 面板 id(`popovertarget` 的目标,由 `createSelectPanelId()` 产出的全页唯一 id) */
|
|
64
|
+
panelId: {
|
|
65
|
+
type: StringConstructor;
|
|
66
|
+
required: true;
|
|
67
|
+
};
|
|
68
|
+
/** 尺寸档(24 / 28 / 32):框高与字号归输入面,本件只透传 */
|
|
69
|
+
size: {
|
|
70
|
+
type: PropType<ControlSize>;
|
|
71
|
+
default: string;
|
|
72
|
+
};
|
|
73
|
+
/** 校验状态(红 / 黄;与输入框同一词表) */
|
|
74
|
+
status: {
|
|
75
|
+
type: PropType<InputStatus>;
|
|
76
|
+
default: undefined;
|
|
77
|
+
};
|
|
78
|
+
disabled: {
|
|
79
|
+
type: BooleanConstructor;
|
|
80
|
+
default: boolean;
|
|
81
|
+
};
|
|
82
|
+
clearable: {
|
|
83
|
+
type: BooleanConstructor;
|
|
84
|
+
default: boolean;
|
|
85
|
+
};
|
|
86
|
+
/** 显式判定清除位显隐(多选的值是数组、单选显示的是 label,都没有「一个字符串模型」可喂) */
|
|
87
|
+
hasValue: {
|
|
88
|
+
type: BooleanConstructor;
|
|
89
|
+
default: boolean;
|
|
90
|
+
};
|
|
91
|
+
/** 多选形态(控件上多一个 `mh-select--multiple`,标签不换行) */
|
|
92
|
+
multiple: {
|
|
93
|
+
type: BooleanConstructor;
|
|
94
|
+
default: boolean;
|
|
95
|
+
};
|
|
96
|
+
placeholder: {
|
|
97
|
+
type: StringConstructor;
|
|
98
|
+
default: string;
|
|
99
|
+
};
|
|
100
|
+
/** 单选显示文本(无值时不渲染它,改渲染 `placeholder`) */
|
|
101
|
+
label: {
|
|
102
|
+
type: StringConstructor;
|
|
103
|
+
default: undefined;
|
|
104
|
+
};
|
|
105
|
+
/** 触发器上的键盘契约(`createTriggerKeydown()` 产出,两件同源) */
|
|
106
|
+
onKeydown: {
|
|
107
|
+
type: PropType<(event: KeyboardEvent) => void>;
|
|
108
|
+
default: undefined;
|
|
109
|
+
};
|
|
110
|
+
/** 清除位被点击(输入面的内建清除位回调;本件只把它转给消费方) */
|
|
111
|
+
onClear: {
|
|
112
|
+
type: PropType<() => void>;
|
|
113
|
+
default: undefined;
|
|
114
|
+
};
|
|
115
|
+
/** 值区自定义渲染(多选标签收纳用;不给则走单选那一行) */
|
|
116
|
+
renderValue: {
|
|
117
|
+
type: PropType<() => VNodeChild>;
|
|
118
|
+
default: undefined;
|
|
119
|
+
};
|
|
120
|
+
}>> & Readonly<{}>, {
|
|
121
|
+
size: ControlSize;
|
|
122
|
+
multiple: boolean;
|
|
123
|
+
disabled: boolean;
|
|
124
|
+
label: string;
|
|
125
|
+
onKeydown: (event: KeyboardEvent) => void;
|
|
126
|
+
placeholder: string;
|
|
127
|
+
status: InputStatus;
|
|
128
|
+
clearable: boolean;
|
|
129
|
+
hasValue: boolean;
|
|
130
|
+
onClear: () => void;
|
|
131
|
+
renderValue: () => VNodeChild;
|
|
132
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { defineComponent, createVNode } from "vue";
|
|
2
|
+
import { Icon } from "@manohub/icon";
|
|
3
|
+
import { Input } from "../input/index.js";
|
|
4
|
+
const SelectTrigger = /* @__PURE__ */ defineComponent({
|
|
5
|
+
name: "SelectTrigger",
|
|
6
|
+
inheritAttrs: false,
|
|
7
|
+
props: {
|
|
8
|
+
/** 面板 id(`popovertarget` 的目标,由 `createSelectPanelId()` 产出的全页唯一 id) */
|
|
9
|
+
panelId: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: true
|
|
12
|
+
},
|
|
13
|
+
/** 尺寸档(24 / 28 / 32):框高与字号归输入面,本件只透传 */
|
|
14
|
+
size: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: "md"
|
|
17
|
+
},
|
|
18
|
+
/** 校验状态(红 / 黄;与输入框同一词表) */
|
|
19
|
+
status: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: void 0
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false
|
|
26
|
+
},
|
|
27
|
+
clearable: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false
|
|
30
|
+
},
|
|
31
|
+
/** 显式判定清除位显隐(多选的值是数组、单选显示的是 label,都没有「一个字符串模型」可喂) */
|
|
32
|
+
hasValue: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: false
|
|
35
|
+
},
|
|
36
|
+
/** 多选形态(控件上多一个 `mh-select--multiple`,标签不换行) */
|
|
37
|
+
multiple: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
},
|
|
41
|
+
placeholder: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: "请选择"
|
|
44
|
+
},
|
|
45
|
+
/** 单选显示文本(无值时不渲染它,改渲染 `placeholder`) */
|
|
46
|
+
label: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: void 0
|
|
49
|
+
},
|
|
50
|
+
/** 触发器上的键盘契约(`createTriggerKeydown()` 产出,两件同源) */
|
|
51
|
+
onKeydown: {
|
|
52
|
+
type: Function,
|
|
53
|
+
default: void 0
|
|
54
|
+
},
|
|
55
|
+
/** 清除位被点击(输入面的内建清除位回调;本件只把它转给消费方) */
|
|
56
|
+
onClear: {
|
|
57
|
+
type: Function,
|
|
58
|
+
default: void 0
|
|
59
|
+
},
|
|
60
|
+
/** 值区自定义渲染(多选标签收纳用;不给则走单选那一行) */
|
|
61
|
+
renderValue: {
|
|
62
|
+
type: Function,
|
|
63
|
+
default: void 0
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
setup(props) {
|
|
67
|
+
const controlClass = () => ["mh-select", props.multiple ? "mh-select--multiple" : "", props.size === "md" ? "" : `mh-select--${props.size}`].filter(Boolean).join(" ");
|
|
68
|
+
return () => createVNode(Input, {
|
|
69
|
+
"as": "button",
|
|
70
|
+
"size": props.size,
|
|
71
|
+
"status": props.status,
|
|
72
|
+
"disabled": props.disabled,
|
|
73
|
+
"clearable": props.clearable,
|
|
74
|
+
"hasValue": props.hasValue,
|
|
75
|
+
"class": "mh-popup-anchor mh-select-host",
|
|
76
|
+
"controlClass": controlClass(),
|
|
77
|
+
"controlAttrs": {
|
|
78
|
+
popovertarget: props.panelId,
|
|
79
|
+
"aria-haspopup": "listbox",
|
|
80
|
+
/* 开合态由原生 popover 与 popup.css 的箭头转向承担,本件不维护第二份;
|
|
81
|
+
恒定 'false' 是既有口径(输入面的触发器形态不跟踪 popover 的开关状态) */
|
|
82
|
+
"aria-expanded": "false",
|
|
83
|
+
onKeydown: props.onKeydown
|
|
84
|
+
},
|
|
85
|
+
"onChange": () => props.onClear?.()
|
|
86
|
+
}, {
|
|
87
|
+
default: () => props.renderValue ? props.renderValue() : createVNode("span", {
|
|
88
|
+
"class": ["mh-select__value", props.hasValue ? "" : "mh-select__value--placeholder"].filter(Boolean).join(" ")
|
|
89
|
+
}, [props.hasValue ? props.label : props.placeholder]),
|
|
90
|
+
/* 箭头沿用输入框的右侧图标位(槽内尺寸收敛见 `select.css` 的 `.mh-select-host` 一节);
|
|
91
|
+
展开转向由 `popup.css` 的 `.mh-popup-caret` 承担(含触发器进表壳后的兄弟档) */
|
|
92
|
+
suffix: () => createVNode(Icon, {
|
|
93
|
+
"name": "chevron-down",
|
|
94
|
+
"class": "mh-select__caret mh-popup-caret"
|
|
95
|
+
}, null)
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
export {
|
|
100
|
+
SelectTrigger
|
|
101
|
+
};
|
|
@@ -37,7 +37,7 @@ export type CanJump = (index: number, current: number) => boolean;
|
|
|
37
37
|
*
|
|
38
38
|
* ### 「哪几步能跳」由调用方给(`canJump`)
|
|
39
39
|
*
|
|
40
|
-
* 本件**不猜业务规则**:`canJump` 缺省 `true
|
|
40
|
+
* 本件**不猜业务规则**:`canJump` 缺省 `true`(每一步都可跳),要限制就注入一条判定:
|
|
41
41
|
*
|
|
42
42
|
* ```tsx
|
|
43
43
|
* <Steps clickable :can-jump="(index, current) => index <= current" … />
|
|
@@ -72,13 +72,34 @@ export interface TablePagination {
|
|
|
72
72
|
* 组件自己切片会让「服务端分页」与「客户端分页」两套口径藏在同一个 prop 里;
|
|
73
73
|
* - **错误态**:归 `QueryState`(表格只管列数据)。
|
|
74
74
|
*
|
|
75
|
-
* @example
|
|
75
|
+
* @example 基本列表(表默认满宽;列宽给权重 + `fixed` 才严格按比例,长文本列配 `ellipsis`)
|
|
76
76
|
* <Table
|
|
77
|
-
*
|
|
78
|
-
* :
|
|
77
|
+
* layout="fixed" striped row-key="id" :data="rows"
|
|
78
|
+
* :columns="[
|
|
79
|
+
* { key: 'name', title: '名称', width: 3 },
|
|
80
|
+
* { key: 'amount', title: '金额', width: 1, align: 'right' },
|
|
81
|
+
* { key: 'description', title: '描述', width: 4, ellipsis: true },
|
|
82
|
+
* ]"
|
|
79
83
|
* :pagination="{ total: 120, current: page, onChange: (p) => (page = p) }"
|
|
80
|
-
* @sort="({ key, order }) => (sortKey = key, sortOrder = order)"
|
|
81
84
|
* />
|
|
85
|
+
*
|
|
86
|
+
* @example 操作列(用 `actions` 插槽 + 一列 `align:'right'`;行内操作同族,`Button.Group` 收口)
|
|
87
|
+
* <Table :columns="columns" :data="rows" row-key="id">
|
|
88
|
+
* {{
|
|
89
|
+
* actions: ({ row }) => (
|
|
90
|
+
* <Button.Group>
|
|
91
|
+
* <Button variant="text" onClick={() => open(row)}>编辑</Button>
|
|
92
|
+
* <Button variant="text" danger onClick={() => remove(row)}>删除</Button>
|
|
93
|
+
* </Button.Group>
|
|
94
|
+
* ),
|
|
95
|
+
* }}
|
|
96
|
+
* </Table>
|
|
97
|
+
*
|
|
98
|
+
* @example 单元格自定义 + 按行判定可勾选
|
|
99
|
+
* <Table :columns="columns" :data="rows" row-key="id" v-model="selected"
|
|
100
|
+
* :selectable="(row) => row.status === 'draft'">
|
|
101
|
+
* {{ cell: ({ value, column }) => column.key === 'status' ? <Text tone="success">{value}</Text> : value }}
|
|
102
|
+
* </Table>
|
|
82
103
|
*/
|
|
83
104
|
export declare const Table: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
84
105
|
columns: {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
2
2
|
/** 字号档(每档都有一枚配套的行高令牌,故**不开放**只有字号的 micro / display) */
|
|
3
3
|
export type TextSize = 'caption' | 'body' | 'heading' | 'title';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* 语义色档(`success` / `warning` 取 `-strong`,与 `Notice` / `Dialog` 同一张表)。
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ 自绘样式时要字色,一律落 `--ui-<tone>` / `--ui-<tone>-strong`(浅底深字)。
|
|
8
|
+
* `--ui-*-content` 那一族是**实心填充之上的白字**,配浅底(`-weak`)就是白字白底。
|
|
9
|
+
*/
|
|
5
10
|
export type TextTone = 'default' | 'muted' | 'subtle' | 'primary' | 'success' | 'warning' | 'error';
|
|
6
11
|
/** 字重档(缺省**不设**,即继承上下文 —— 这样「在已加粗的区域里放一段普通文字」不必显式写 regular) */
|
|
7
12
|
export type TextWeight = 'regular' | 'medium' | 'semibold';
|
|
@@ -30,7 +35,7 @@ export interface TextProps {
|
|
|
30
35
|
* 但**没有件消费它们**:卡片描述、表单说明、只读值、列表次级信息这些「容器里的文字层级」
|
|
31
36
|
* 于是无处可归 —— `Card` 只管卡片外壳,`Panel` 只管区域,两者都不管内容里的排版;
|
|
32
37
|
* 而契约 L1-5 又禁应用侧写 `font-*` / `color`。**令牌有了、路径没有**,
|
|
33
|
-
*
|
|
38
|
+
* 结果就是每个应用都要为「卡片里的文字」保留一条定版例外登记(首批迁移的登记项里,
|
|
34
39
|
* 绝大多数属于这一类)。本件把这条路径补上。
|
|
35
40
|
*
|
|
36
41
|
* ## 与 `Title` / 平台默认的关系
|
|
@@ -23,8 +23,7 @@ export interface TreeNode {
|
|
|
23
23
|
* ## 为什么自建(对照计划登记的退路)
|
|
24
24
|
*
|
|
25
25
|
* farris `FTreeView` 实测结论:① 是列模板式网格(节点内容可用 `columnTemplate` 承载);
|
|
26
|
-
* ② **只在挂载时填充一次可见行,data
|
|
27
|
-
* `apps/skill/src/features/skill/farris-file-tree.tsx` 正是用 `key` 强制重挂绕行);
|
|
26
|
+
* ② **只在挂载时填充一次可见行,data 变化不刷新**(**唯一**的兜底是 `key` 强制重挂 —— 那会丢展开态);
|
|
28
27
|
* ③ 层级缩进不可控、节点图标走 farris 图标字体类。
|
|
29
28
|
*
|
|
30
29
|
* 而本组件的硬需求是「数据更新时**不丢**用户已展开的节点 / 滚动位置 / 焦点」——
|
|
@@ -80,6 +79,19 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
80
79
|
type: PropType<(node: TreeNode) => void>;
|
|
81
80
|
default: undefined;
|
|
82
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
|
|
84
|
+
*
|
|
85
|
+
* 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
|
|
86
|
+
* 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
|
|
87
|
+
* 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
|
|
88
|
+
*
|
|
89
|
+
* 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
|
|
90
|
+
*/
|
|
91
|
+
renderLabel: {
|
|
92
|
+
type: PropType<(node: TreeNode) => unknown>;
|
|
93
|
+
default: undefined;
|
|
94
|
+
};
|
|
83
95
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
84
96
|
renderNode: {
|
|
85
97
|
type: PropType<(node: TreeNode) => unknown>;
|
|
@@ -200,6 +212,19 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
200
212
|
type: PropType<(node: TreeNode) => void>;
|
|
201
213
|
default: undefined;
|
|
202
214
|
};
|
|
215
|
+
/**
|
|
216
|
+
* 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
|
|
217
|
+
*
|
|
218
|
+
* 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
|
|
219
|
+
* 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
|
|
220
|
+
* 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
|
|
221
|
+
*
|
|
222
|
+
* 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
|
|
223
|
+
*/
|
|
224
|
+
renderLabel: {
|
|
225
|
+
type: PropType<(node: TreeNode) => unknown>;
|
|
226
|
+
default: undefined;
|
|
227
|
+
};
|
|
203
228
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
204
229
|
renderNode: {
|
|
205
230
|
type: PropType<(node: TreeNode) => unknown>;
|
|
@@ -305,6 +330,7 @@ export declare const Tree: import("vue").DefineComponent<import("vue").ExtractPr
|
|
|
305
330
|
onErrorAction: () => void;
|
|
306
331
|
labelKey: string;
|
|
307
332
|
childrenKey: string;
|
|
333
|
+
renderLabel: (node: TreeNode) => unknown;
|
|
308
334
|
renderNode: (node: TreeNode) => unknown;
|
|
309
335
|
renderActions: (node: TreeNode) => unknown;
|
|
310
336
|
expandedKeys: string[];
|
|
@@ -33,6 +33,19 @@ const Tree = /* @__PURE__ */ defineComponent({
|
|
|
33
33
|
type: Function,
|
|
34
34
|
default: void 0
|
|
35
35
|
},
|
|
36
|
+
/**
|
|
37
|
+
* 标签体的自定义渲染(**替掉** `labelKey` 的纯文本)。
|
|
38
|
+
*
|
|
39
|
+
* 与 `renderNode` 的分工:本 prop 渲染的是**标签本体**(占位、省略号、行内对齐都由 `.mh-tree__label`
|
|
40
|
+
* 承担,因此必须留在那个槽里);`renderNode` 渲染的是标签**之后**的常驻附加内容(计数徽标一类)。
|
|
41
|
+
* 典型用途是搜索命中的文本高亮(把标签切成多个片段)。
|
|
42
|
+
*
|
|
43
|
+
* 缺省不传时仍渲染 `labelKey` 的纯文本 —— 这是绝大多数消费方的路径,行为零变化。
|
|
44
|
+
*/
|
|
45
|
+
renderLabel: {
|
|
46
|
+
type: Function,
|
|
47
|
+
default: void 0
|
|
48
|
+
},
|
|
36
49
|
/** 节点附加内容(计数徽标等),渲染在标签之后 */
|
|
37
50
|
renderNode: {
|
|
38
51
|
type: Function,
|
|
@@ -231,7 +244,7 @@ const Tree = /* @__PURE__ */ defineComponent({
|
|
|
231
244
|
"class": "mh-tree__caret mh-tree__caret--empty"
|
|
232
245
|
}, null), createVNode("span", {
|
|
233
246
|
"class": "mh-tree__label"
|
|
234
|
-
}, [String(node[props.labelKey] ?? "")]), props.renderNode ? createVNode("span", {
|
|
247
|
+
}, [props.renderLabel ? props.renderLabel(node) : String(node[props.labelKey] ?? "")]), props.renderNode ? createVNode("span", {
|
|
235
248
|
"class": "mh-tree__extra"
|
|
236
249
|
}, [props.renderNode(node)]) : null, props.renderActions ? createVNode("span", {
|
|
237
250
|
"class": "mh-tree__actions",
|
package/dist/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export { Badge, type BadgeTone, type BadgeShape, type BadgeSize, type BadgeDot,
|
|
|
34
34
|
export { Button, type ButtonVariant, type ButtonCompound, type ButtonCompoundType, } from './components/button';
|
|
35
35
|
export { Input, Textarea, type TextareaProps, type InputCompound, type InputCompoundType, } from './components/input';
|
|
36
36
|
export { Search, type SearchProps } from './components/search';
|
|
37
|
-
export { Select, type SelectOption, type SelectValue } from './components/select';
|
|
37
|
+
export { Select, SelectTree, type SelectOption, type SelectValue } from './components/select';
|
|
38
38
|
export { Switch } from './components/switch';
|
|
39
39
|
export { Capsule, type CapsuleOption, type CapsuleShape } from './components/capsule';
|
|
40
40
|
export { Form, type FormProps, type FormHeaderProps, type FormItemProps, type FormValues, type FormItemSlotScope, type FormItemAlign, type FormLabelAlign, type FormColumns, type FormPadding, type FormCompound, } from './components/form';
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ import { Upload, formatFileSize } from "./components/upload/index.js";
|
|
|
39
39
|
import { QueryState } from "./components/query-state/index.js";
|
|
40
40
|
import { Loading } from "./components/loading/index.js";
|
|
41
41
|
import { mergePartStyle, partPaddingStyle } from "./components/part-padding.js";
|
|
42
|
+
import { SelectTree } from "./components/select/select-tree.js";
|
|
42
43
|
import { alert, closeAllDialogs, confirm } from "./services/dialog.js";
|
|
43
44
|
import { clearToasts, toast } from "./services/toast.js";
|
|
44
45
|
import { configureHost, getHostSelector, resolveHost } from "./services/base.js";
|
|
@@ -74,6 +75,7 @@ export {
|
|
|
74
75
|
Radio,
|
|
75
76
|
Search,
|
|
76
77
|
Select,
|
|
78
|
+
SelectTree,
|
|
77
79
|
Skeleton,
|
|
78
80
|
Steps,
|
|
79
81
|
Switch,
|
|
@@ -227,27 +227,6 @@
|
|
|
227
227
|
align-items: center;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
/* 只读文本行(Form.Item 的 text 形态:摘要 / 详情):正文色与行高,
|
|
231
|
-
长文案(SQL where、列说明)按词折行;`pre-wrap` 保留换行符(多行过滤条件回显)。
|
|
232
|
-
它只占第 1 行、与 label 各自居中即对齐 —— **不给任何高度**(撑到某个「控件高」等于把那个
|
|
233
|
-
外部高度变量换个名字复活;只读行按内容高排版,行与行的间距归 `Form` 的 gap)。 */
|
|
234
|
-
|
|
235
|
-
.mh-form-item__text {
|
|
236
|
-
display: flex;
|
|
237
|
-
align-items: center;
|
|
238
|
-
font-size: var(--ui-font-body);
|
|
239
|
-
line-height: var(--ui-line-body);
|
|
240
|
-
color: var(--ui-base-content);
|
|
241
|
-
white-space: pre-wrap;
|
|
242
|
-
word-break: break-word;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/* 空值占位(组件统一给 `—`):压成次要色,避免它被当成真实取值 */
|
|
246
|
-
|
|
247
|
-
.mh-form-item__text[data-empty='true'] {
|
|
248
|
-
color: var(--ui-base-content-subtle);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
230
|
/* 错误 / 说明:**行的直接子节点**(不在控件列里面),排在控件行之下、与控件列同列。
|
|
252
231
|
只给 `grid-column` 不给行号 —— 自动放置会把它们推进下一个空行:控件占着第 1 行,
|
|
253
232
|
于是它们既不会挤进第 1 行、也不会掉到 label 列下面去。 */
|
|
@@ -169,6 +169,19 @@
|
|
|
169
169
|
background: var(--ui-base-100);
|
|
170
170
|
box-shadow: 0 0 0 2px var(--ui-primary-weak);
|
|
171
171
|
}
|
|
172
|
+
/* **只读值档**(`readonly` + `bordered={false}`):几何照旧(与可编辑输入框同高、同内距),
|
|
173
|
+
但把「可编辑」的线索全退掉 —— 只读值不该在滑过时亮起浅底、被点中时亮出边框与主色环。
|
|
174
|
+
仍然可聚焦、可选中复制(只读 ≠ 禁用:要的就是能选、能复制)。
|
|
175
|
+
它是摘要 / 详情里值回显的推荐写法,也是 `Form.Item` 的 `readonly` 行配的那一档。
|
|
176
|
+
特异性 0-3-0,压过上面两条(0-2-0);带壳时框主是壳,同款规则见文件下半部分。 */
|
|
177
|
+
.mh-input--borderless[readonly]:hover,
|
|
178
|
+
.mh-input--borderless[readonly].is-hover,
|
|
179
|
+
.mh-input--borderless[readonly]:focus,
|
|
180
|
+
.mh-input--borderless[readonly].is-focus {
|
|
181
|
+
border-color: transparent;
|
|
182
|
+
background: transparent;
|
|
183
|
+
box-shadow: none;
|
|
184
|
+
}
|
|
172
185
|
|
|
173
186
|
/* ===== 展示态(下划线,只读值回显) ===== */
|
|
174
187
|
.mh-input--display {
|
|
@@ -310,6 +323,18 @@
|
|
|
310
323
|
background: var(--ui-base-100);
|
|
311
324
|
box-shadow: 0 0 0 2px var(--ui-primary-weak);
|
|
312
325
|
}
|
|
326
|
+
/* **只读值档**同款(带壳时框主是壳):退掉悬停底与聚焦的边框 / 底色 / 主色环。
|
|
327
|
+
特异性 0-4-0,压过上面两条(0-3-0),并且写在它们之后。 */
|
|
328
|
+
.mh-input__wrap:has(> .mh-input--borderless[readonly]):hover,
|
|
329
|
+
.mh-input__wrap:has(> .mh-input--borderless[readonly]).is-hover {
|
|
330
|
+
border-color: transparent;
|
|
331
|
+
background: transparent;
|
|
332
|
+
}
|
|
333
|
+
.mh-input__wrap:has(> .mh-input--borderless[readonly]):focus-within {
|
|
334
|
+
border-color: transparent;
|
|
335
|
+
background: transparent;
|
|
336
|
+
box-shadow: none;
|
|
337
|
+
}
|
|
313
338
|
|
|
314
339
|
/* ===== 前缀 / 后缀插槽(纯装饰:图标、单位、域名;无底色、不进 Tab 序列) ===== */
|
|
315
340
|
.mh-input__prefix,
|
|
@@ -219,6 +219,27 @@
|
|
|
219
219
|
padding: var(--ui-space-2) var(--ui-space-2) var(--ui-space-1);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
/* ===== 树体(树选择 `SelectTree` 的面板内容)=====
|
|
223
|
+
边界要认清楚:**面板皮肤归本文件**(上一节),**树的行态归 tree 面**(`.mh-tree__*` 那一族,
|
|
224
|
+
本文件一行都不碰 —— 跨族类名须先登记跨面豁免,这里不走那条路)。
|
|
225
|
+
故本件只做「把树安放进面板」这一件事:内距 + 限高 + 溢出滚动。
|
|
226
|
+
行高 / 缩进 / 滑过与选中底色全部沿用 tree 面,两处形态不会漂移。 */
|
|
227
|
+
.mh-select__tree {
|
|
228
|
+
/* 行底满宽、只有内容缩进(缩进公式在 tree 面),故左右各留一个最小呼吸位 */
|
|
229
|
+
padding: 0 var(--ui-space-1) var(--ui-space-1);
|
|
230
|
+
max-height: var(--ui-select-tree-max-height);
|
|
231
|
+
overflow-y: auto;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* 命中高亮(搜索命中的那段文字,由组件的 `renderLabel` 落进 `.mh-tree__label` 槽)。
|
|
235
|
+
底色取主色浅底档(与选中 / 滑过同一套语义槽位);字色 `inherit` —— 高亮只负责「标出位置」,
|
|
236
|
+
不引入第二套强调色,否则同一行里会同时出现三种主色深浅。 */
|
|
237
|
+
.mh-select__hit {
|
|
238
|
+
border-radius: var(--ui-radius-xs);
|
|
239
|
+
background: var(--ui-primary-weak);
|
|
240
|
+
color: inherit;
|
|
241
|
+
}
|
|
242
|
+
|
|
222
243
|
/* ===== 日期格(DatePicker 复用本族面板;选中主色实底、区间浅底) ===== */
|
|
223
244
|
.mh-select__date {
|
|
224
245
|
display: inline-flex;
|
|
@@ -30,4 +30,7 @@
|
|
|
30
30
|
--ui-select-option-selected: var(--ui-primary-subtle); /* 见头部「有色差异」 */
|
|
31
31
|
--ui-select-chip-height: 24px; /* 多选标签(规范复用标签族 24 档) */
|
|
32
32
|
--ui-select-icon-size: var(--ui-font-icon); /* 下拉箭头:常规图标档 */
|
|
33
|
+
/* 树形态(SelectTree):面板内树体的限高 —— 约等于 9 行(行高 34 + 行距 6 的节距 40 见 tree.css),
|
|
34
|
+
超过即滚动,长树不把面板撑成整屏 */
|
|
35
|
+
--ui-select-tree-max-height: 320px;
|
|
33
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manohub/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "AIHub 自绘组件层:不依赖 farris 的手写 Vue TSX 组件 + 自带令牌层(Farris 规范视觉 · daisyUI 式语义令牌 · shadcn 式 API 词汇)。",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"vue": "^3.5.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@manohub/icon": "^0.
|
|
49
|
+
"@manohub/icon": "^0.8.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^24.0.0",
|