@manohub/ui 0.7.0 → 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 +4 -4
- package/dist/components/button/index.d.ts +14 -8
- package/dist/components/capsule/index.d.ts +13 -9
- package/dist/components/capsule/index.js +1 -1
- package/dist/components/card/index.d.ts +1 -1
- package/dist/components/card/index.js +7 -4
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/dialog/index.d.ts +1 -1
- package/dist/components/form/index.d.ts +142 -62
- package/dist/components/form/index.js +41 -29
- package/dist/components/input/index.d.ts +74 -6
- package/dist/components/input/index.js +13 -1
- package/dist/components/layout/index.d.ts +43 -1
- package/dist/components/layout/index.js +22 -2
- package/dist/components/list-view/index.d.ts +1 -1
- package/dist/components/notice/index.d.ts +2 -2
- package/dist/components/notification/index.d.ts +2 -2
- package/dist/components/page/index.js +4 -4
- package/dist/components/pagination/index.d.ts +2 -2
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/panel/index.js +4 -4
- package/dist/components/part-padding.d.ts +9 -6
- package/dist/components/part-padding.js +2 -1
- package/dist/components/query-state/index.d.ts +18 -2
- package/dist/components/radio/index.d.ts +1 -1
- package/dist/components/radio/index.js +1 -0
- 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 +232 -6
- package/dist/components/steps/index.js +84 -26
- package/dist/components/switch/index.d.ts +29 -5
- package/dist/components/switch/index.js +8 -2
- package/dist/components/tabbar/index.d.ts +184 -0
- package/dist/components/tabbar/index.js +161 -0
- package/dist/components/table/index.d.ts +99 -12
- package/dist/components/table/index.js +69 -16
- package/dist/components/tabs/index.d.ts +142 -126
- package/dist/components/tabs/index.js +87 -119
- package/dist/components/tag/index.d.ts +2 -2
- package/dist/components/text/index.d.ts +7 -2
- package/dist/components/toast/index.d.ts +8 -8
- package/dist/components/tree/index.d.ts +28 -2
- package/dist/components/tree/index.js +14 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -3
- package/dist/styles/components/capsule.css +4 -4
- package/dist/styles/components/form.css +198 -39
- package/dist/styles/components/input.css +53 -1
- package/dist/styles/components/layout.css +2 -0
- package/dist/styles/components/select.css +21 -0
- package/dist/styles/components/select.tokens.css +3 -0
- package/dist/styles/components/steps.css +48 -0
- package/dist/styles/components/{tabs.css → tabbar.css} +66 -65
- package/dist/styles/components/tabbar.tokens.css +30 -0
- package/dist/styles/components/table.css +50 -1
- package/dist/styles/components/table.tokens.css +3 -0
- package/dist/styles/index.css +3 -3
- package/dist/styles/operations/tabs.css +73 -0
- package/package.json +2 -2
- package/dist/components/tabset/index.d.ts +0 -109
- package/dist/components/tabset/index.js +0 -75
- package/dist/styles/components/tabs.tokens.css +0 -30
- package/dist/styles/operations/tabset.css +0 -57
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
2
|
+
import type { ControlSize } from '../control-size';
|
|
3
|
+
export interface TabBarOption {
|
|
4
|
+
/** 项文字 */
|
|
5
|
+
label: string;
|
|
6
|
+
/** 项值(受控值就是它) */
|
|
7
|
+
value: string | number;
|
|
8
|
+
/** 禁用项:不可选 */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** 单项可关(`closable` 打开时用它例外掉某些项) */
|
|
11
|
+
closable?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type TabBarValue = string | number;
|
|
14
|
+
/** 页签形态:`line` 下划线指示条 / `card` 选项卡(与内容区连成一体) */
|
|
15
|
+
export type TabBarType = 'line' | 'card';
|
|
16
|
+
/**
|
|
17
|
+
* 页签条(**自绘**;下划线或选项卡两种形态 + 三档尺寸 + 居中 + 可关闭 + 可新增 + 「更多」收纳)。
|
|
18
|
+
*
|
|
19
|
+
* ## 与 `Tabs` / `Capsule` 的分工(三者都能"切换",判据在**可见形态**)
|
|
20
|
+
*
|
|
21
|
+
* - 本件:**页签条**(`line` 下划线 / `card` 选项卡,页面级分区切换)—— 就是这一族的皮肤,
|
|
22
|
+
* 也是 `Tabs` **不传 `selector` 插槽时的缺省皮肤**(只给 `options` + 面板就够);
|
|
23
|
+
* - `Capsule`:胶囊/分段按钮(块状选中底),用于筛选项那种"按钮感"切换 —— 同样能塞进 `Tabs` 的 `selector`;
|
|
24
|
+
* - `Tabs`:**骨架**(把某组互斥项与面板显隐接起来),它不含皮肤:缺省借本件,传了 `selector` 就整块换掉。
|
|
25
|
+
*
|
|
26
|
+
* ## 指示条为什么不是一个滑块
|
|
27
|
+
*
|
|
28
|
+
* 每个项的指示条是它自己的伪元素、常驻但未选时 `opacity:0; scale:.75` —— "滑过去"的观感来自这两个属性的
|
|
29
|
+
* 过渡。做成一条共享滑块要 JS 量位置,且首帧会跳。**别在页签区加轨线**(会扣走区高 1px,规范明确警告)。
|
|
30
|
+
* (`card` 档不画指示条:选中由底色与顶边表达。)
|
|
31
|
+
*
|
|
32
|
+
* ## 超过一屏的页签怎么放
|
|
33
|
+
*
|
|
34
|
+
* 给 `more` 插槽即出「更多 ▾」页签 + 操作层浮层(原生 popover,零 JS 开合);哪些页签收进"更多"由调用方
|
|
35
|
+
* 决定 —— 收多久、收哪些是业务判断,不是皮肤能定的。
|
|
36
|
+
*
|
|
37
|
+
* @example 基本
|
|
38
|
+
* <TabBar :options="[{label:'全部',value:'all'},{label:'进行中',value:'doing'}]" v-model:value="current" />
|
|
39
|
+
*
|
|
40
|
+
* @example 选项卡形态 + 可关闭可新增
|
|
41
|
+
* <TabBar type="card" closable addable :options="tabs" v-model:value="current"
|
|
42
|
+
* :on-close="remove" :on-add="add" />
|
|
43
|
+
*/
|
|
44
|
+
export declare const TabBar: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
45
|
+
options: {
|
|
46
|
+
type: PropType<TabBarOption[]>;
|
|
47
|
+
required: true;
|
|
48
|
+
};
|
|
49
|
+
/** 受控选中值;不传即非受控(由 `defaultValue` 起) */
|
|
50
|
+
value: {
|
|
51
|
+
type: PropType<TabBarValue | undefined>;
|
|
52
|
+
default: undefined;
|
|
53
|
+
};
|
|
54
|
+
/** 非受控初始选中值,缺省第一项 */
|
|
55
|
+
defaultValue: {
|
|
56
|
+
type: PropType<TabBarValue | undefined>;
|
|
57
|
+
default: undefined;
|
|
58
|
+
};
|
|
59
|
+
/** 选中变化回调(受控与非受控都会调) */
|
|
60
|
+
onChange: {
|
|
61
|
+
type: PropType<(value: TabBarValue) => void>;
|
|
62
|
+
default: undefined;
|
|
63
|
+
};
|
|
64
|
+
/** 形态:`line` 下划线 / `card` 选项卡 */
|
|
65
|
+
type: {
|
|
66
|
+
type: PropType<TabBarType>;
|
|
67
|
+
default: string;
|
|
68
|
+
};
|
|
69
|
+
/** 整体居中(页签少、要撑满整行时用) */
|
|
70
|
+
centered: {
|
|
71
|
+
type: BooleanConstructor;
|
|
72
|
+
default: boolean;
|
|
73
|
+
};
|
|
74
|
+
/** 尺寸档(24 / 32 / 40,只覆盖令牌) */
|
|
75
|
+
size: {
|
|
76
|
+
type: PropType<ControlSize>;
|
|
77
|
+
default: string;
|
|
78
|
+
};
|
|
79
|
+
/** 每项带关闭位(单项可用 `option.closable` 覆写) */
|
|
80
|
+
closable: {
|
|
81
|
+
type: BooleanConstructor;
|
|
82
|
+
default: boolean;
|
|
83
|
+
};
|
|
84
|
+
/** 尾部「新增」按钮 */
|
|
85
|
+
addable: {
|
|
86
|
+
type: BooleanConstructor;
|
|
87
|
+
default: boolean;
|
|
88
|
+
};
|
|
89
|
+
/** 「更多」页签的文字 */
|
|
90
|
+
moreLabel: {
|
|
91
|
+
type: StringConstructor;
|
|
92
|
+
default: string;
|
|
93
|
+
};
|
|
94
|
+
/** 关闭某项(只回调,**不从 `options` 里删** —— 数据归调用方) */
|
|
95
|
+
onClose: {
|
|
96
|
+
type: PropType<(value: TabBarValue) => void>;
|
|
97
|
+
default: undefined;
|
|
98
|
+
};
|
|
99
|
+
/** 点新增(只回调) */
|
|
100
|
+
onAdd: {
|
|
101
|
+
type: PropType<() => void>;
|
|
102
|
+
default: undefined;
|
|
103
|
+
};
|
|
104
|
+
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
105
|
+
'update:value': (value: TabBarValue) => true;
|
|
106
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
107
|
+
options: {
|
|
108
|
+
type: PropType<TabBarOption[]>;
|
|
109
|
+
required: true;
|
|
110
|
+
};
|
|
111
|
+
/** 受控选中值;不传即非受控(由 `defaultValue` 起) */
|
|
112
|
+
value: {
|
|
113
|
+
type: PropType<TabBarValue | undefined>;
|
|
114
|
+
default: undefined;
|
|
115
|
+
};
|
|
116
|
+
/** 非受控初始选中值,缺省第一项 */
|
|
117
|
+
defaultValue: {
|
|
118
|
+
type: PropType<TabBarValue | undefined>;
|
|
119
|
+
default: undefined;
|
|
120
|
+
};
|
|
121
|
+
/** 选中变化回调(受控与非受控都会调) */
|
|
122
|
+
onChange: {
|
|
123
|
+
type: PropType<(value: TabBarValue) => void>;
|
|
124
|
+
default: undefined;
|
|
125
|
+
};
|
|
126
|
+
/** 形态:`line` 下划线 / `card` 选项卡 */
|
|
127
|
+
type: {
|
|
128
|
+
type: PropType<TabBarType>;
|
|
129
|
+
default: string;
|
|
130
|
+
};
|
|
131
|
+
/** 整体居中(页签少、要撑满整行时用) */
|
|
132
|
+
centered: {
|
|
133
|
+
type: BooleanConstructor;
|
|
134
|
+
default: boolean;
|
|
135
|
+
};
|
|
136
|
+
/** 尺寸档(24 / 32 / 40,只覆盖令牌) */
|
|
137
|
+
size: {
|
|
138
|
+
type: PropType<ControlSize>;
|
|
139
|
+
default: string;
|
|
140
|
+
};
|
|
141
|
+
/** 每项带关闭位(单项可用 `option.closable` 覆写) */
|
|
142
|
+
closable: {
|
|
143
|
+
type: BooleanConstructor;
|
|
144
|
+
default: boolean;
|
|
145
|
+
};
|
|
146
|
+
/** 尾部「新增」按钮 */
|
|
147
|
+
addable: {
|
|
148
|
+
type: BooleanConstructor;
|
|
149
|
+
default: boolean;
|
|
150
|
+
};
|
|
151
|
+
/** 「更多」页签的文字 */
|
|
152
|
+
moreLabel: {
|
|
153
|
+
type: StringConstructor;
|
|
154
|
+
default: string;
|
|
155
|
+
};
|
|
156
|
+
/** 关闭某项(只回调,**不从 `options` 里删** —— 数据归调用方) */
|
|
157
|
+
onClose: {
|
|
158
|
+
type: PropType<(value: TabBarValue) => void>;
|
|
159
|
+
default: undefined;
|
|
160
|
+
};
|
|
161
|
+
/** 点新增(只回调) */
|
|
162
|
+
onAdd: {
|
|
163
|
+
type: PropType<() => void>;
|
|
164
|
+
default: undefined;
|
|
165
|
+
};
|
|
166
|
+
}>> & Readonly<{
|
|
167
|
+
"onUpdate:value"?: ((value: TabBarValue) => any) | undefined;
|
|
168
|
+
}>, {
|
|
169
|
+
size: ControlSize;
|
|
170
|
+
value: TabBarValue | undefined;
|
|
171
|
+
type: TabBarType;
|
|
172
|
+
onChange: (value: TabBarValue) => void;
|
|
173
|
+
onClose: (value: TabBarValue) => void;
|
|
174
|
+
defaultValue: TabBarValue | undefined;
|
|
175
|
+
centered: boolean;
|
|
176
|
+
closable: boolean;
|
|
177
|
+
addable: boolean;
|
|
178
|
+
moreLabel: string;
|
|
179
|
+
onAdd: () => void;
|
|
180
|
+
}, SlotsType<{
|
|
181
|
+
more?: (context: {
|
|
182
|
+
options: TabBarOption[];
|
|
183
|
+
}) => VNodeChild;
|
|
184
|
+
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { defineComponent, ref, computed, createVNode, Fragment, mergeProps } from "vue";
|
|
2
|
+
import { Icon } from "@manohub/icon";
|
|
3
|
+
const TabBar = /* @__PURE__ */ defineComponent({
|
|
4
|
+
name: "TabBar",
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
props: {
|
|
7
|
+
options: {
|
|
8
|
+
type: Array,
|
|
9
|
+
required: true
|
|
10
|
+
},
|
|
11
|
+
/** 受控选中值;不传即非受控(由 `defaultValue` 起) */
|
|
12
|
+
value: {
|
|
13
|
+
type: [String, Number],
|
|
14
|
+
default: void 0
|
|
15
|
+
},
|
|
16
|
+
/** 非受控初始选中值,缺省第一项 */
|
|
17
|
+
defaultValue: {
|
|
18
|
+
type: [String, Number],
|
|
19
|
+
default: void 0
|
|
20
|
+
},
|
|
21
|
+
/** 选中变化回调(受控与非受控都会调) */
|
|
22
|
+
onChange: {
|
|
23
|
+
type: Function,
|
|
24
|
+
default: void 0
|
|
25
|
+
},
|
|
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: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
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
|
+
}
|
|
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
|
+
},
|
|
73
|
+
slots: Object,
|
|
74
|
+
setup(props, {
|
|
75
|
+
slots,
|
|
76
|
+
attrs,
|
|
77
|
+
emit
|
|
78
|
+
}) {
|
|
79
|
+
const innerValue = ref(props.value ?? props.defaultValue ?? props.options[0]?.value);
|
|
80
|
+
const current = computed(() => props.value ?? innerValue.value);
|
|
81
|
+
const moreId = `mh-tabbar-${Math.random().toString(36).slice(2, 10)}`;
|
|
82
|
+
const select = (value) => {
|
|
83
|
+
const target = props.options.find((option) => option.value === value);
|
|
84
|
+
if (target?.disabled) return;
|
|
85
|
+
if (props.value === void 0) innerValue.value = value;
|
|
86
|
+
emit("update:value", value);
|
|
87
|
+
props.onChange?.(value);
|
|
88
|
+
};
|
|
89
|
+
const isClosable = (option) => option.closable ?? props.closable;
|
|
90
|
+
return () => createVNode("nav", {
|
|
91
|
+
"class": [
|
|
92
|
+
"mh-tabbar",
|
|
93
|
+
/* `mh-popup-host` 是操作层展开转向的**宿主标记**(popup.css 靠它 :has 反推面板开合):
|
|
94
|
+
没有它,「更多」的 caret 展开时不会翻向 —— 与 Select / Tooltip 同一分工。 */
|
|
95
|
+
"mh-popup-host",
|
|
96
|
+
props.type === "card" ? "mh-tabbar--card" : "",
|
|
97
|
+
props.centered ? "mh-tabbar--centered" : "",
|
|
98
|
+
props.size === "md" ? "" : `mh-tabbar--${props.size}`,
|
|
99
|
+
attrs.class
|
|
100
|
+
].filter(Boolean).join(" "),
|
|
101
|
+
"style": attrs.style,
|
|
102
|
+
"role": "tablist"
|
|
103
|
+
}, [props.options.map((option) => {
|
|
104
|
+
const active = option.value === current.value;
|
|
105
|
+
return createVNode("button", {
|
|
106
|
+
"key": option.value,
|
|
107
|
+
"type": "button",
|
|
108
|
+
"role": "tab",
|
|
109
|
+
"class": ["mh-tabbar__tab", active ? "is-selected" : "", option.disabled ? "is-disabled" : ""].filter(Boolean).join(" "),
|
|
110
|
+
"data-state": active ? "active" : "inactive",
|
|
111
|
+
"aria-selected": active,
|
|
112
|
+
"disabled": option.disabled,
|
|
113
|
+
"onClick": () => select(option.value)
|
|
114
|
+
}, [option.label, isClosable(option) && !option.disabled ? (
|
|
115
|
+
/* 关闭位不是 `<button>`:页签自己是按钮,按钮里嵌按钮是非法 HTML。
|
|
116
|
+
用 `role="button"` + `stopPropagation` 表达同样的语义与行为。 */
|
|
117
|
+
createVNode("span", {
|
|
118
|
+
"class": "mh-tabbar__close",
|
|
119
|
+
"role": "button",
|
|
120
|
+
"tabindex": -1,
|
|
121
|
+
"aria-label": `关闭${option.label}`,
|
|
122
|
+
"onClick": (event) => {
|
|
123
|
+
event.stopPropagation();
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
props.onClose?.(option.value);
|
|
126
|
+
}
|
|
127
|
+
}, [createVNode(Icon, {
|
|
128
|
+
"name": "close"
|
|
129
|
+
}, null)])
|
|
130
|
+
) : null]);
|
|
131
|
+
}), props.addable ? createVNode("button", {
|
|
132
|
+
"type": "button",
|
|
133
|
+
"class": "mh-tabbar__add",
|
|
134
|
+
"aria-label": "新增页签",
|
|
135
|
+
"onClick": () => props.onAdd?.()
|
|
136
|
+
}, [createVNode(Icon, {
|
|
137
|
+
"name": "plus"
|
|
138
|
+
}, null)]) : null, slots.more ? createVNode(Fragment, null, [createVNode("button", mergeProps({
|
|
139
|
+
"type": "button",
|
|
140
|
+
"class": "mh-tabbar__tab mh-tabbar__tab--more",
|
|
141
|
+
"data-state": "inactive"
|
|
142
|
+
}, {
|
|
143
|
+
popovertarget: moreId
|
|
144
|
+
}), [props.moreLabel, createVNode(Icon, {
|
|
145
|
+
"name": "chevron-down",
|
|
146
|
+
"class": "mh-popup-caret"
|
|
147
|
+
}, null)]), createVNode("div", mergeProps({
|
|
148
|
+
"id": moreId,
|
|
149
|
+
"class": "mh-popup",
|
|
150
|
+
"data-side": "bottom",
|
|
151
|
+
"data-align": "end"
|
|
152
|
+
}, {
|
|
153
|
+
popover: "auto"
|
|
154
|
+
}), [slots.more({
|
|
155
|
+
options: props.options
|
|
156
|
+
})])]) : null]);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
export {
|
|
160
|
+
TabBar
|
|
161
|
+
};
|
|
@@ -5,11 +5,27 @@ export interface TableColumn {
|
|
|
5
5
|
key: string;
|
|
6
6
|
/** 列标题 */
|
|
7
7
|
title: string;
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* 列宽。四种写法,可混用(**`auto` 下是"建议值",长文本可顶破;`fixed` 下是硬约束**):
|
|
10
|
+
*
|
|
11
|
+
* - `number` —— **比例权重**,只在这些权重列之间按 `w_i / Σw` 折算成百分比。
|
|
12
|
+
* 想「按比例分配」就用它,不必手算百分比。
|
|
13
|
+
* - `'120px'` —— 固定宽(`fixed` 下是硬宽,**容器变窄也不收缩**,可能横向滚动)
|
|
14
|
+
* - `'20%'` —— 百分比(**吃满 + 严格按比例 + 任意容器宽不溢出**,响应式首选)
|
|
15
|
+
* - 不传 —— 单用时吃剩余/等分;**与 `px` 混用会被压到 0**,不建议
|
|
16
|
+
*/
|
|
17
|
+
width?: string | number;
|
|
10
18
|
align?: 'left' | 'center' | 'right';
|
|
11
|
-
/**
|
|
19
|
+
/** 长文本省略(表头仍完整)。`fixed` 下建议给所有长文本列都标上,否则会换行(行高变高) */
|
|
12
20
|
ellipsis?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* 列下限(px):防止窄容器把该列压没。**给了才下发 `min-width`** ——
|
|
23
|
+
* ⚠️ 它**不是硬下限**:实测(Chrome)`<col>` 上的 `min-width` 会被当成**分配权重**参与按比例
|
|
24
|
+
* 分摊 —— 800 宽容器下 `width:50% + min-width:500px` 的列实测只有 **444**,不是 500。
|
|
25
|
+
* 想要真下限得换机制(该列直接给 px 硬宽,或把内容包一层带 `min-width` 的盒)。
|
|
26
|
+
* 只在调用方显式要时才下发(`<col>` 上不写时不会出现)。
|
|
27
|
+
*/
|
|
28
|
+
minWidth?: number;
|
|
13
29
|
/** 必填列:表头加星号 */
|
|
14
30
|
required?: boolean;
|
|
15
31
|
/** 可排序:本件只发事件与显示态,**排序算法归调用方** */
|
|
@@ -23,6 +39,11 @@ export interface TableRowProps {
|
|
|
23
39
|
class?: string;
|
|
24
40
|
onClick?: (row: TableRow, index: number, event: MouseEvent) => void;
|
|
25
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* 行级可勾选判定(`selectable` 的函数形态):返回 `false` 的行渲染**禁用态**勾选框,
|
|
44
|
+
* 且不进表头全选的增删范围。签名与 `onRow` / `rowClass` 一致(都给 `index`)。
|
|
45
|
+
*/
|
|
46
|
+
export type TableRowSelectable = (row: TableRow, index: number) => boolean;
|
|
26
47
|
/** 分页档:`false` 不渲染;给对象就渲染分页条(**本件不切片,`data` 是当前页数据**) */
|
|
27
48
|
export interface TablePagination {
|
|
28
49
|
total: number;
|
|
@@ -51,13 +72,34 @@ export interface TablePagination {
|
|
|
51
72
|
* 组件自己切片会让「服务端分页」与「客户端分页」两套口径藏在同一个 prop 里;
|
|
52
73
|
* - **错误态**:归 `QueryState`(表格只管列数据)。
|
|
53
74
|
*
|
|
54
|
-
* @example
|
|
75
|
+
* @example 基本列表(表默认满宽;列宽给权重 + `fixed` 才严格按比例,长文本列配 `ellipsis`)
|
|
55
76
|
* <Table
|
|
56
|
-
*
|
|
57
|
-
* :
|
|
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
|
+
* ]"
|
|
58
83
|
* :pagination="{ total: 120, current: page, onChange: (p) => (page = p) }"
|
|
59
|
-
* @sort="({ key, order }) => (sortKey = key, sortOrder = order)"
|
|
60
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>
|
|
61
103
|
*/
|
|
62
104
|
export declare const Table: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
63
105
|
columns: {
|
|
@@ -78,9 +120,18 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
78
120
|
type: PropType<Array<string | number>>;
|
|
79
121
|
default: undefined;
|
|
80
122
|
};
|
|
81
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* 选择列:`false` = 不出选择列;`true` = 全表可勾选;**函数 = 按行判定可勾选性**。
|
|
125
|
+
*
|
|
126
|
+
* 函数形态下,返回 `false` 的行渲染**禁用态**勾选框(`Checkbox` 自带置灰外观 +
|
|
127
|
+
* `cursor: not-allowed`),且**不进表头全选的增删范围**;整表都不可勾选时,表头勾选框自身禁用。
|
|
128
|
+
*
|
|
129
|
+
* ⚠️ 「有没有选择列」只由 `selectable === false` 决定 —— 函数形态**恒渲染**选择列。
|
|
130
|
+
* ⚠️ 别用「受控回弹」在调用方模拟行级禁用:本件是全受控(`selected = props.modelValue`),
|
|
131
|
+
* 被忽略的上报**不会**让原生 `input.checked` 复位,会留下「整行点亮却不在选中集」的假象。
|
|
132
|
+
*/
|
|
82
133
|
selectable: {
|
|
83
|
-
type:
|
|
134
|
+
type: PropType<boolean | TableRowSelectable>;
|
|
84
135
|
default: boolean;
|
|
85
136
|
};
|
|
86
137
|
/** 斑马纹(**显式类**而非 nth-child:表里可能有分组行) */
|
|
@@ -107,6 +158,19 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
107
158
|
type: BooleanConstructor;
|
|
108
159
|
default: boolean;
|
|
109
160
|
};
|
|
161
|
+
/**
|
|
162
|
+
* 布局档(只决定 `<table>` 的 `table-layout`;**列宽一律由 `<colgroup>` 下发,与档位无关**):
|
|
163
|
+
*
|
|
164
|
+
* - `auto`(缺省)—— 列宽随内容自适应。`column.width` 是**建议值**,
|
|
165
|
+
* 长文本(尤其中文长串 / 无空格串)会顶破列宽把表格撑得比容器还宽 ⇒ 包裹层出横向滚动条。
|
|
166
|
+
* - `fixed` —— `table-layout: fixed`:列宽受声明约束、**不再被内容撑破**,
|
|
167
|
+
* 于是百分比 / 数字权重可以「吃满容器 + 严格按比例」。代价:长文本列要显式 `ellipsis: true`,
|
|
168
|
+
* 否则会**换行**(行高变高)。
|
|
169
|
+
*/
|
|
170
|
+
layout: {
|
|
171
|
+
type: PropType<"auto" | "fixed">;
|
|
172
|
+
default: string;
|
|
173
|
+
};
|
|
110
174
|
stickyHead: {
|
|
111
175
|
type: BooleanConstructor;
|
|
112
176
|
default: boolean;
|
|
@@ -203,9 +267,18 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
203
267
|
type: PropType<Array<string | number>>;
|
|
204
268
|
default: undefined;
|
|
205
269
|
};
|
|
206
|
-
/**
|
|
270
|
+
/**
|
|
271
|
+
* 选择列:`false` = 不出选择列;`true` = 全表可勾选;**函数 = 按行判定可勾选性**。
|
|
272
|
+
*
|
|
273
|
+
* 函数形态下,返回 `false` 的行渲染**禁用态**勾选框(`Checkbox` 自带置灰外观 +
|
|
274
|
+
* `cursor: not-allowed`),且**不进表头全选的增删范围**;整表都不可勾选时,表头勾选框自身禁用。
|
|
275
|
+
*
|
|
276
|
+
* ⚠️ 「有没有选择列」只由 `selectable === false` 决定 —— 函数形态**恒渲染**选择列。
|
|
277
|
+
* ⚠️ 别用「受控回弹」在调用方模拟行级禁用:本件是全受控(`selected = props.modelValue`),
|
|
278
|
+
* 被忽略的上报**不会**让原生 `input.checked` 复位,会留下「整行点亮却不在选中集」的假象。
|
|
279
|
+
*/
|
|
207
280
|
selectable: {
|
|
208
|
-
type:
|
|
281
|
+
type: PropType<boolean | TableRowSelectable>;
|
|
209
282
|
default: boolean;
|
|
210
283
|
};
|
|
211
284
|
/** 斑马纹(**显式类**而非 nth-child:表里可能有分组行) */
|
|
@@ -232,6 +305,19 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
232
305
|
type: BooleanConstructor;
|
|
233
306
|
default: boolean;
|
|
234
307
|
};
|
|
308
|
+
/**
|
|
309
|
+
* 布局档(只决定 `<table>` 的 `table-layout`;**列宽一律由 `<colgroup>` 下发,与档位无关**):
|
|
310
|
+
*
|
|
311
|
+
* - `auto`(缺省)—— 列宽随内容自适应。`column.width` 是**建议值**,
|
|
312
|
+
* 长文本(尤其中文长串 / 无空格串)会顶破列宽把表格撑得比容器还宽 ⇒ 包裹层出横向滚动条。
|
|
313
|
+
* - `fixed` —— `table-layout: fixed`:列宽受声明约束、**不再被内容撑破**,
|
|
314
|
+
* 于是百分比 / 数字权重可以「吃满容器 + 严格按比例」。代价:长文本列要显式 `ellipsis: true`,
|
|
315
|
+
* 否则会**换行**(行高变高)。
|
|
316
|
+
*/
|
|
317
|
+
layout: {
|
|
318
|
+
type: PropType<"auto" | "fixed">;
|
|
319
|
+
default: string;
|
|
320
|
+
};
|
|
235
321
|
stickyHead: {
|
|
236
322
|
type: BooleanConstructor;
|
|
237
323
|
default: boolean;
|
|
@@ -308,6 +394,7 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
308
394
|
"onUpdate:modelValue"?: ((keys: (string | number)[]) => any) | undefined;
|
|
309
395
|
}>, {
|
|
310
396
|
fill: boolean;
|
|
397
|
+
layout: "fixed" | "auto";
|
|
311
398
|
size: ControlSize;
|
|
312
399
|
compact: boolean;
|
|
313
400
|
data: TableRow[];
|
|
@@ -318,7 +405,7 @@ export declare const Table: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
318
405
|
onExpandChange: (keys: Array<string | number>) => void;
|
|
319
406
|
modelValue: (string | number)[];
|
|
320
407
|
emptyText: string;
|
|
321
|
-
selectable: boolean;
|
|
408
|
+
selectable: boolean | TableRowSelectable;
|
|
322
409
|
striped: boolean;
|
|
323
410
|
borderless: boolean;
|
|
324
411
|
stickyHead: boolean;
|