@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* TabBar —— 页签条(下划线指示条 + 禁用 + 「更多」页签)。
|
|
3
3
|
*
|
|
4
|
-
* 出处:`@aihub/theme` 的 `playground/components/
|
|
4
|
+
* 出处:`@aihub/theme` 的 `playground/components/tabbar.css` 与 `src/components/tabbar.css`
|
|
5
5
|
* (区高 26 / 项间距 30 / 字号 14 / 指示条高 3、距文字 3、两端与文字同宽 / 未选字 `#446a9f` /
|
|
6
6
|
* 滑过 `#529dff` / 选中 `#4e94ff` / 禁用 Te07)。
|
|
7
7
|
*
|
|
@@ -17,38 +17,39 @@
|
|
|
17
17
|
* **三源等价**(本仓通例):原生 `:checked +` / 组件下发 `[data-state='active']` / 静态档 `.is-selected`
|
|
18
18
|
* 指向同一份声明 —— 原生态给零 JS 用法(原生 radio 互斥 + ← → 换页签),组件态给受控值。
|
|
19
19
|
*/
|
|
20
|
-
.mh-
|
|
20
|
+
.mh-tabbar {
|
|
21
21
|
display: flex;
|
|
22
22
|
align-items: flex-end;
|
|
23
|
-
gap: var(--ui-
|
|
24
|
-
height: var(--ui-
|
|
23
|
+
gap: var(--ui-tabbar-gap);
|
|
24
|
+
height: var(--ui-tabbar-height);
|
|
25
|
+
flex-shrink: 0;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
.mh-
|
|
28
|
+
.mh-tabbar__tab {
|
|
28
29
|
position: relative;
|
|
29
30
|
display: inline-flex;
|
|
30
31
|
align-items: flex-end;
|
|
31
32
|
height: 100%;
|
|
32
|
-
padding: 0 0 calc(var(--ui-
|
|
33
|
+
padding: 0 0 calc(var(--ui-tabbar-indicator-gap) + var(--ui-tabbar-indicator-height));
|
|
33
34
|
border: none;
|
|
34
35
|
background: transparent;
|
|
35
36
|
font-family: inherit;
|
|
36
|
-
font-size: var(--ui-
|
|
37
|
+
font-size: var(--ui-tabbar-font-size);
|
|
37
38
|
line-height: var(--ui-line-body);
|
|
38
|
-
color: var(--ui-
|
|
39
|
+
color: var(--ui-tabbar-text);
|
|
39
40
|
cursor: pointer;
|
|
40
41
|
white-space: nowrap;
|
|
41
42
|
}
|
|
42
43
|
/* 指示条:常驻、与文字同宽(不内缩),靠 opacity + scale 过渡出"滑动感" */
|
|
43
|
-
.mh-
|
|
44
|
+
.mh-tabbar__tab::after {
|
|
44
45
|
content: '';
|
|
45
46
|
position: absolute;
|
|
46
47
|
right: 0;
|
|
47
48
|
bottom: 0;
|
|
48
49
|
left: 0;
|
|
49
|
-
height: var(--ui-
|
|
50
|
-
border-radius: var(--ui-
|
|
51
|
-
background: var(--ui-
|
|
50
|
+
height: var(--ui-tabbar-indicator-height);
|
|
51
|
+
border-radius: var(--ui-tabbar-indicator-radius);
|
|
52
|
+
background: var(--ui-tabbar-indicator);
|
|
52
53
|
opacity: 0;
|
|
53
54
|
scale: 0.75;
|
|
54
55
|
transition-property: opacity, scale;
|
|
@@ -56,49 +57,49 @@
|
|
|
56
57
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
.mh-
|
|
60
|
-
color: var(--ui-
|
|
60
|
+
.mh-tabbar__tab:hover {
|
|
61
|
+
color: var(--ui-tabbar-text-hover);
|
|
61
62
|
}
|
|
62
|
-
.mh-
|
|
63
|
-
color: var(--ui-
|
|
63
|
+
.mh-tabbar__tab:active {
|
|
64
|
+
color: var(--ui-tabbar-text-active);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/* 选中(三源等价):字转主色 + 中粗,指示条亮起 */
|
|
67
|
-
.mh-
|
|
68
|
-
.mh-
|
|
69
|
-
.mh-
|
|
70
|
-
color: var(--ui-
|
|
68
|
+
.mh-tabbar__tab.is-selected,
|
|
69
|
+
.mh-tabbar__tab[data-state='active'],
|
|
70
|
+
.mh-tabbar > input:checked + .mh-tabbar__tab {
|
|
71
|
+
color: var(--ui-tabbar-text-active);
|
|
71
72
|
font-weight: var(--ui-weight-medium);
|
|
72
73
|
}
|
|
73
|
-
.mh-
|
|
74
|
-
.mh-
|
|
75
|
-
.mh-
|
|
74
|
+
.mh-tabbar__tab.is-selected::after,
|
|
75
|
+
.mh-tabbar__tab[data-state='active']::after,
|
|
76
|
+
.mh-tabbar > input:checked + .mh-tabbar__tab::after {
|
|
76
77
|
opacity: 1;
|
|
77
78
|
scale: 1;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
/* 禁用(三源等价):字转弱、不可点 */
|
|
81
|
-
.mh-
|
|
82
|
-
.mh-
|
|
83
|
-
.mh-
|
|
84
|
-
color: var(--ui-
|
|
82
|
+
.mh-tabbar__tab.is-disabled,
|
|
83
|
+
.mh-tabbar__tab:disabled,
|
|
84
|
+
.mh-tabbar > input:disabled + .mh-tabbar__tab {
|
|
85
|
+
color: var(--ui-tabbar-text-disabled);
|
|
85
86
|
cursor: not-allowed;
|
|
86
87
|
}
|
|
87
|
-
.mh-
|
|
88
|
-
.mh-
|
|
89
|
-
.mh-
|
|
88
|
+
.mh-tabbar__tab.is-disabled::after,
|
|
89
|
+
.mh-tabbar__tab:disabled::after,
|
|
90
|
+
.mh-tabbar > input:disabled + .mh-tabbar__tab::after {
|
|
90
91
|
opacity: 0;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
/* 「更多」页签:文字 + 转向箭头(字形来自 `@manohub/icon`,本层只排布) */
|
|
94
|
-
.mh-
|
|
95
|
+
.mh-tabbar__tab--more {
|
|
95
96
|
display: inline-flex;
|
|
96
97
|
align-items: center;
|
|
97
98
|
gap: var(--ui-space-1);
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
/* 原生路径的隐身开关:可聚焦但不可见(焦点环画在可见的项上) */
|
|
101
|
-
.mh-
|
|
102
|
+
.mh-tabbar > input {
|
|
102
103
|
position: absolute;
|
|
103
104
|
width: 1px;
|
|
104
105
|
height: 1px;
|
|
@@ -113,40 +114,40 @@
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
/* 键盘焦点环(两条路径各一处,不重叠) */
|
|
116
|
-
.mh-
|
|
117
|
-
.mh-
|
|
117
|
+
.mh-tabbar__tab:focus-visible,
|
|
118
|
+
.mh-tabbar > input:focus-visible + .mh-tabbar__tab {
|
|
118
119
|
outline: 2px solid var(--ui-primary);
|
|
119
120
|
outline-offset: -2px;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
/* ===== 居中档:页签少、要撑满整行时用 ===== */
|
|
123
|
-
.mh-
|
|
124
|
+
.mh-tabbar--centered {
|
|
124
125
|
justify-content: center;
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
/* ===== 尺寸档(只覆盖令牌) ===== */
|
|
128
|
-
.mh-
|
|
129
|
-
--ui-
|
|
130
|
-
--ui-
|
|
131
|
-
--ui-
|
|
129
|
+
.mh-tabbar--sm {
|
|
130
|
+
--ui-tabbar-height: var(--ui-control-height-sm);
|
|
131
|
+
--ui-tabbar-font-size: var(--ui-font-caption);
|
|
132
|
+
--ui-tabbar-gap: var(--ui-space-6);
|
|
132
133
|
}
|
|
133
|
-
.mh-
|
|
134
|
-
--ui-
|
|
135
|
-
--ui-
|
|
134
|
+
.mh-tabbar--lg {
|
|
135
|
+
--ui-tabbar-height: var(--ui-control-height-lg);
|
|
136
|
+
--ui-tabbar-font-size: var(--ui-font-heading);
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
/* ===== 选项卡形态(type="card") =====
|
|
139
140
|
* 与内容区连成一体:页签有边框与浅底,选中项转白底 + 顶部主色条;
|
|
140
141
|
* 底边刻意不画 —— 让内容区自己的上边框接上(面板的 bordered 档就是为此)。 */
|
|
141
|
-
.mh-
|
|
142
|
+
.mh-tabbar--card {
|
|
142
143
|
align-items: flex-end;
|
|
143
144
|
gap: var(--ui-space-1);
|
|
144
145
|
height: auto;
|
|
145
146
|
}
|
|
146
|
-
.mh-
|
|
147
|
+
.mh-tabbar--card .mh-tabbar__tab {
|
|
147
148
|
align-items: center;
|
|
148
|
-
height: var(--ui-
|
|
149
|
-
padding: 0 var(--ui-
|
|
149
|
+
height: var(--ui-tabbar-height);
|
|
150
|
+
padding: 0 var(--ui-tabbar-card-padding-x);
|
|
150
151
|
border: 1px solid var(--ui-base-300);
|
|
151
152
|
border-bottom: none;
|
|
152
153
|
border-radius: var(--ui-radius-control) var(--ui-radius-control) 0 0;
|
|
@@ -154,28 +155,28 @@
|
|
|
154
155
|
color: var(--ui-base-content-muted);
|
|
155
156
|
}
|
|
156
157
|
/* 卡片档不画指示条:选中由底色与顶边表达(两套选中语汇叠在一起会互相打架) */
|
|
157
|
-
.mh-
|
|
158
|
+
.mh-tabbar--card .mh-tabbar__tab::after {
|
|
158
159
|
content: none;
|
|
159
160
|
}
|
|
160
|
-
.mh-
|
|
161
|
+
.mh-tabbar--card .mh-tabbar__tab:hover {
|
|
161
162
|
color: var(--ui-primary);
|
|
162
163
|
}
|
|
163
|
-
.mh-
|
|
164
|
-
.mh-
|
|
165
|
-
.mh-
|
|
164
|
+
.mh-tabbar--card .mh-tabbar__tab.is-selected,
|
|
165
|
+
.mh-tabbar--card .mh-tabbar__tab[data-state='active'],
|
|
166
|
+
.mh-tabbar--card > input:checked + .mh-tabbar__tab {
|
|
166
167
|
background: var(--ui-base-100);
|
|
167
168
|
color: var(--ui-primary);
|
|
168
169
|
box-shadow: inset 0 2px 0 var(--ui-primary);
|
|
169
170
|
}
|
|
170
|
-
.mh-
|
|
171
|
+
.mh-tabbar--card .mh-tabbar__tab.is-disabled {
|
|
171
172
|
background: var(--ui-base-200);
|
|
172
|
-
color: var(--ui-
|
|
173
|
+
color: var(--ui-tabbar-text-disabled);
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
/* ===== 关闭位 =====
|
|
176
177
|
* 页签自己是 `<button>`,所以关闭位用 `<span role="button">`(按钮里嵌按钮是非法 HTML);
|
|
177
178
|
* 线上档的文字是「贴底」的,故关闭位要自己把底部内距补回来才与文字同一水平线。 */
|
|
178
|
-
.mh-
|
|
179
|
+
.mh-tabbar__close {
|
|
179
180
|
display: inline-flex;
|
|
180
181
|
align-items: center;
|
|
181
182
|
justify-content: center;
|
|
@@ -183,7 +184,7 @@
|
|
|
183
184
|
flex: none;
|
|
184
185
|
width: 16px;
|
|
185
186
|
height: 16px;
|
|
186
|
-
margin-bottom: calc(var(--ui-
|
|
187
|
+
margin-bottom: calc(var(--ui-tabbar-indicator-gap) + var(--ui-tabbar-indicator-height));
|
|
187
188
|
margin-left: var(--ui-space-1);
|
|
188
189
|
border-radius: var(--ui-radius-full);
|
|
189
190
|
color: inherit;
|
|
@@ -191,26 +192,26 @@
|
|
|
191
192
|
opacity: 0.5;
|
|
192
193
|
transition: opacity 0.15s ease, background-color 0.15s ease;
|
|
193
194
|
}
|
|
194
|
-
.mh-
|
|
195
|
+
.mh-tabbar--card .mh-tabbar__close {
|
|
195
196
|
margin-bottom: 0;
|
|
196
197
|
}
|
|
197
|
-
.mh-
|
|
198
|
+
.mh-tabbar__close > svg {
|
|
198
199
|
width: 12px;
|
|
199
200
|
height: 12px;
|
|
200
201
|
}
|
|
201
|
-
.mh-
|
|
202
|
+
.mh-tabbar__close:hover {
|
|
202
203
|
opacity: 1;
|
|
203
204
|
background: rgb(0 0 0 / 0.08);
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
/* ===== 新增位 ===== */
|
|
207
|
-
.mh-
|
|
208
|
+
.mh-tabbar__add {
|
|
208
209
|
display: inline-flex;
|
|
209
210
|
align-items: center;
|
|
210
211
|
justify-content: center;
|
|
211
212
|
flex: none;
|
|
212
|
-
width: var(--ui-
|
|
213
|
-
height: var(--ui-
|
|
213
|
+
width: var(--ui-tabbar-height);
|
|
214
|
+
height: var(--ui-tabbar-height);
|
|
214
215
|
padding: 0;
|
|
215
216
|
border: none;
|
|
216
217
|
border-radius: var(--ui-radius-control);
|
|
@@ -219,16 +220,16 @@
|
|
|
219
220
|
cursor: pointer;
|
|
220
221
|
transition: background-color 0.15s ease, color 0.15s ease;
|
|
221
222
|
}
|
|
222
|
-
.mh-
|
|
223
|
+
.mh-tabbar__add > svg {
|
|
223
224
|
width: var(--ui-font-icon); /* 常规图标档 */
|
|
224
225
|
height: var(--ui-font-icon);
|
|
225
226
|
}
|
|
226
227
|
/* 「更多」的折叠箭头:改前无声明、掉到 `<svg>` 默认 16 —— 与新增位同取常规图标档 */
|
|
227
|
-
.mh-
|
|
228
|
+
.mh-tabbar__tab--more > svg {
|
|
228
229
|
width: var(--ui-font-icon);
|
|
229
230
|
height: var(--ui-font-icon);
|
|
230
231
|
}
|
|
231
|
-
.mh-
|
|
232
|
+
.mh-tabbar__add:hover {
|
|
232
233
|
background: var(--ui-base-200);
|
|
233
234
|
color: var(--ui-primary);
|
|
234
235
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tabs —— 单件令牌(**基础值**)。
|
|
3
|
+
*
|
|
4
|
+
* 本件自己的几何 / 尺寸 / 色彩槽位;只服务本件,故不随主题进 `@manohub/theme`。
|
|
5
|
+
*
|
|
6
|
+
* ## 抽出说明
|
|
7
|
+
* 本文件从面文件里抽出(原先混写在 `tabbar.css` 顶部):这些是**基础值**,锚在
|
|
8
|
+
* `[data-manohub-ui]` —— 跨包唯一作用域锚,由入口层无条件写在应用容器上,因此**任何落在
|
|
9
|
+
* 容器里的分件都取得到值**,不再依赖「声明在某个组件根类上」这条脆弱假设
|
|
10
|
+
* (历史症状:跨件消费的 `--ui-*-group-*` 取不到值,组内间距变 0)。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ `.mh-<件>--<档>` 这类**档位改写**留在面文件的修饰符块里 —— 它们靠「同一元素上两个
|
|
13
|
+
* 选择器改写同一个令牌」生效,搬到本文件会让档位失效。
|
|
14
|
+
* ⚠️ 新增组件要登记两处:本文件 + `src/styles/index.css`(见其文件头「五处齐备」)。
|
|
15
|
+
*/
|
|
16
|
+
[data-manohub-ui] {
|
|
17
|
+
/* 单件令牌 */
|
|
18
|
+
--ui-tabbar-height: var(--ui-control-height-md); /* 标准控件高 32 */
|
|
19
|
+
--ui-tabbar-gap: 30px; /* 项间距(规范实测) */
|
|
20
|
+
--ui-tabbar-font-size: var(--ui-font-body);
|
|
21
|
+
--ui-tabbar-text: var(--ui-base-content); /* 规范未选档 #446a9f(偏蓝的正文色),本仓取正文色 */
|
|
22
|
+
--ui-tabbar-text-hover: var(--ui-primary-hover); /* 规范 #529dff */
|
|
23
|
+
--ui-tabbar-text-active: var(--ui-primary); /* 规范 #4e94ff */
|
|
24
|
+
--ui-tabbar-text-disabled: var(--ui-base-content-subtle); /* 规范 Te07 */
|
|
25
|
+
--ui-tabbar-indicator: var(--ui-primary);
|
|
26
|
+
--ui-tabbar-indicator-gap: 3px; /* 指示条与文字的留白 */
|
|
27
|
+
--ui-tabbar-indicator-height: 3px;
|
|
28
|
+
--ui-tabbar-indicator-radius: var(--ui-radius-full);
|
|
29
|
+
--ui-tabbar-card-padding-x: var(--ui-space-4);
|
|
30
|
+
}
|
|
@@ -89,6 +89,29 @@
|
|
|
89
89
|
min-width: 620px;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/* ===== 固定布局档(`layout="fixed"`)=====
|
|
93
|
+
* 列宽由 `<colgroup>` 下发(与档位无关),本档只把布局算法换成 `fixed`:
|
|
94
|
+
* 列宽从此**受声明约束、不再被内容撑破** ⇒ 长文本不会把表格撑得比容器还宽,
|
|
95
|
+
* 于是「百分比 / 数字权重」可以「吃满容器 + 严格按比例」。
|
|
96
|
+
*
|
|
97
|
+
* 代价(调用方要知道):长文本列必须显式 `ellipsis: true`,否则会**换行**(行高变高,见下条)。 */
|
|
98
|
+
.mh-table--fixed {
|
|
99
|
+
table-layout: fixed;
|
|
100
|
+
}
|
|
101
|
+
/* 换行兜底:fixed 已保证「不撑破容器」,这条只防**无空格长串**(如 500 字符的 token)
|
|
102
|
+
溢出单元格、视觉上压到相邻列。`anywhere` 而不是 `break-word`:后者不参与最小内容宽计算。 */
|
|
103
|
+
.mh-table--fixed tbody td {
|
|
104
|
+
overflow-wrap: anywhere;
|
|
105
|
+
}
|
|
106
|
+
/* 前导列(勾选 / 展开)在 auto 下靠内容把 40px 的「建议宽」撑出去;fixed 下是硬宽,
|
|
107
|
+
而 `thead th` / `tbody td` 的标准左右内距各 16px ⇒ 可用内容只有 40 − 32 = 8px,
|
|
108
|
+
装不下 16px 的勾选框(实测该列溢出 19px,还会被上面的 `overflow: hidden` 裁掉)。
|
|
109
|
+
故本档把前导列的内距清零,靠既有的 `text-align: center` 居中。 */
|
|
110
|
+
.mh-table--fixed .mh-table__col-check,
|
|
111
|
+
.mh-table--fixed .mh-table__col-expand {
|
|
112
|
+
padding: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
92
115
|
/* ===== 表头 =====
|
|
93
116
|
* `border: 0` **不是冗余**:本件只画「表外框 + 表头分割线 + 每行底线」三条,其余边必须显式清零。
|
|
94
117
|
* 特异性和平局只发生在**同一个属性**上 —— 本件只声明 `border-bottom` 时,宿主给单元格下的整圈边框
|
|
@@ -110,6 +133,13 @@
|
|
|
110
133
|
.mh-table thead th.is-hover {
|
|
111
134
|
background: var(--ui-table-head-bg-hover);
|
|
112
135
|
}
|
|
136
|
+
/* 固定档下表头也要裁切:列宽已被 colgroup 钉死,长表头文字会**溢出到相邻列**
|
|
137
|
+
(实测溢出 97px),必须靠这两条收住。`white-space: nowrap` 上面已有。
|
|
138
|
+
⚠️ 只在本档加 —— auto 档下表头参与列宽计算,加裁切会改动老页面的列宽分配。 */
|
|
139
|
+
.mh-table--fixed thead th {
|
|
140
|
+
overflow: hidden;
|
|
141
|
+
text-overflow: ellipsis;
|
|
142
|
+
}
|
|
113
143
|
/* 多级表头的组头:下边线不加(组头跨列,加线会切断视觉分组) */
|
|
114
144
|
.mh-table thead th.mh-table__th-group {
|
|
115
145
|
border-bottom: 1px solid var(--ui-table-head-divider);
|
|
@@ -192,6 +222,20 @@
|
|
|
192
222
|
.mh-table__col-actions {
|
|
193
223
|
text-align: right;
|
|
194
224
|
}
|
|
225
|
+
|
|
226
|
+
/* ⚠️ **表头要把对齐重声明一遍**:上面这几条与 `.mh-table__cell-center` / `.mh-table__cell-amount`
|
|
227
|
+
* 都只有 **0-1-0**,而 `.mh-table thead th { text-align: left }` 是 **0-1-1** ⇒ 表头被强拉成左对齐、
|
|
228
|
+
* 与表体不齐:勾选框应居中却贴左(实测表头左留白 0 / 右留白 26,与表体错位 13px)、
|
|
229
|
+
* 右对齐列的标题应靠右却被拉到左边。
|
|
230
|
+
* 只用补 `text-align` —— `thead th` 没声明过其它会被这些类覆盖的属性(宽度/内距不冲突)。
|
|
231
|
+
* 写法沿用 `th.mh-table__th-group`(组头居中)那条既有先例。 */
|
|
232
|
+
.mh-table thead th.mh-table__col-check,
|
|
233
|
+
.mh-table thead th.mh-table__cell-center {
|
|
234
|
+
text-align: center;
|
|
235
|
+
}
|
|
236
|
+
.mh-table thead th.mh-table__col-actions {
|
|
237
|
+
text-align: right;
|
|
238
|
+
}
|
|
195
239
|
/* `--sticky-col`:首列钉住(必须自带底,见文件头第 4 条) */
|
|
196
240
|
.mh-table--sticky-col thead th:first-child,
|
|
197
241
|
.mh-table--sticky-col tbody td:first-child {
|
|
@@ -227,12 +271,17 @@
|
|
|
227
271
|
.mh-table__cell-link:hover {
|
|
228
272
|
text-decoration: underline;
|
|
229
273
|
}
|
|
274
|
+
/* 长文本省略(列定义里 `ellipsis: true` 时下发)。
|
|
275
|
+
* 基础三件套与档位无关;`max-width` **只在 auto 档兜底**:
|
|
276
|
+
* fixed 档的列宽已由 `<colgroup>` 钉死,再来一条 150px 的 max-width 会把宽列又压回 150(自相矛盾)。 */
|
|
230
277
|
.mh-table__cell-ellipsis {
|
|
231
|
-
max-width: var(--ui-table-ellipsis);
|
|
232
278
|
overflow: hidden;
|
|
233
279
|
text-overflow: ellipsis;
|
|
234
280
|
white-space: nowrap;
|
|
235
281
|
}
|
|
282
|
+
.mh-table:not(.mh-table--fixed) .mh-table__cell-ellipsis {
|
|
283
|
+
max-width: var(--ui-table-ellipsis);
|
|
284
|
+
}
|
|
236
285
|
.mh-table__cell-icon {
|
|
237
286
|
display: inline-flex;
|
|
238
287
|
align-items: center;
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
--ui-table-link: var(--ui-primary);
|
|
30
30
|
--ui-table-padding-x: var(--ui-space-4); /* 单元格左右内距 16 */
|
|
31
31
|
--ui-table-col-check: 40px;
|
|
32
|
+
/* 长文本列的兜底上限 —— **只在 `layout="auto"` 下生效**(`.mh-table:not(.mh-table--fixed)`
|
|
33
|
+
作用域内)。`layout="fixed"` 下列宽由 `<colgroup>` 钉死,本令牌不参与,
|
|
34
|
+
否则「宽列」会被它压回 150px 而自相矛盾。要按列给宽请用 `TableColumn.width`。 */
|
|
32
35
|
--ui-table-ellipsis: 150px;
|
|
33
36
|
--ui-table-drag-line: var(--ui-primary);
|
|
34
37
|
--ui-table-drag-line-width: 3px;
|
package/dist/styles/index.css
CHANGED
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
/* 数据与反馈 */
|
|
87
87
|
@import './components/table.tokens.css';
|
|
88
88
|
@import './components/pagination.tokens.css';
|
|
89
|
-
@import './components/
|
|
89
|
+
@import './components/tabbar.tokens.css';
|
|
90
90
|
@import './components/steps.tokens.css';
|
|
91
91
|
@import './components/toast.tokens.css';
|
|
92
92
|
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
/* 操作层(零 JS 原语,自身不带面;面由下面的皮肤族并列组合提供) */
|
|
98
98
|
@import './operations/collapse.css';
|
|
99
99
|
@import './operations/popup.css';
|
|
100
|
-
@import './operations/
|
|
100
|
+
@import './operations/tabs.css';
|
|
101
101
|
|
|
102
102
|
/* 容器与分区 */
|
|
103
103
|
@import './components/page.css'; /* 页面级骨架(唯一;区域级是 Panel) */
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
/* 数据与反馈(表格 / 分页条 / 页签条 / 步骤条 / 消息提示) */
|
|
146
146
|
@import './components/table.css';
|
|
147
147
|
@import './components/pagination.css';
|
|
148
|
-
@import './components/
|
|
148
|
+
@import './components/tabbar.css';
|
|
149
149
|
@import './components/steps.css';
|
|
150
150
|
@import './components/toast.css';
|
|
151
151
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 操作层 · 面板切换骨架(把「一组互斥选项 + 按顺序排列的面板」接起来;只给骨架、不给面)。
|
|
3
|
+
*
|
|
4
|
+
* 出处:`@aihub/theme` 的 `playground/components/tabset.css`(本件当时叫 `Tabset`,0.7.1 起改名 `Tabs`)。
|
|
5
|
+
* 映射:`--mh-*` → `--ui-*`;类名加 `.mh-` 前缀。
|
|
6
|
+
*
|
|
7
|
+
* 本层只做三件事 ——
|
|
8
|
+
* ① 操作根(轨道 → 面板组 的呼吸位);
|
|
9
|
+
* ② 面板组与面板的**弹性链**(供抽屉 / 区域容器里的「填满」用法);
|
|
10
|
+
* ③ 面板的**收起态**(`hidden`)。
|
|
11
|
+
*
|
|
12
|
+
* **显隐只有一条路径:组件路径。** `Tabs` 按受控值给非选中面板下发 `hidden`,
|
|
13
|
+
* 与选择控件形态无关(页签条 / 胶囊 / 分段按钮 / 单选卡片都一样)。本层因此:
|
|
14
|
+
* · 收起态写在 `.mh-tabs-panel[hidden]` 上(UA 的 `[hidden]` 是**元素级**规则,
|
|
15
|
+
* 作者源里任何自带 `display` 的类都能压过它,故这里显式落下一次);
|
|
16
|
+
* · **显形态一条规则都不写** —— 面板显形就是它自己的 `display`(块 / 弹性 / 网格归消费方与皮肤)。
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ 历史缺陷一(0.7.0 及以前):当时只有「零 JS 档位表」、没有上面那条收起规则 ⇒ 面板被基线按住,
|
|
19
|
+
* 而档位表在 `TabBar` 下恒不命中 ⇒ 三块面板全不显示(`apps/mcp` 配置抽屉实测踩到)。
|
|
20
|
+
* ⚠️ 历史缺陷二(0.7.1 一度这么修、已改回):组件路径的显形**不能**写成
|
|
21
|
+
* `.mh-tabs-panel:not([hidden]) { display: block }` —— 它把面板的 `display` 钉死成 `block`,
|
|
22
|
+
* 连带顶掉消费方/皮肤给面板的布局(面板里是弹性列时整条高度链当场断掉)。
|
|
23
|
+
* ⚠️ 已退役(2026-09-24 拍板删除):**零 JS 路径(原生 radio ↔ 档位表)整段移除**。原写法
|
|
24
|
+
* `.mh-tabs:has(input:nth-of-type(n):checked) .mh-tabs-panels > :nth-child(n)` 逐档一条写不出通式,
|
|
25
|
+
* 且同时受三条硬限制:① 上限 8 档;② 开关必须与面板**同序**,且按「同一父级里第 n 个 input」计数;
|
|
26
|
+
* ③ 面板必须是 `.mh-tabs-panels` 的**直接子级**。局限远大于它省下的那点 JS —— 取消。
|
|
27
|
+
* (`TabBar` / `Capsule` 各自面向**静态页**的原生 `:checked` 选中态与本文件无关,仍然有效。)
|
|
28
|
+
*
|
|
29
|
+
* **与皮肤零互指**:本层不认任何皮肤类名(退役后也不再认识 `input`)。
|
|
30
|
+
*
|
|
31
|
+
* 结构契约(轨道项与面板组顺序**一一对应**;面板壳由 `Tabs` 出,消费方不必手写):
|
|
32
|
+
* <div class="mh-tabs">
|
|
33
|
+
* <div class="[皮肤:轨道 / 选择控件]">…</div>
|
|
34
|
+
* <div class="mh-tabs-panels">
|
|
35
|
+
* <section class="mh-tabs-panel [皮肤类]" hidden>…</section>
|
|
36
|
+
* </div>
|
|
37
|
+
* </div>
|
|
38
|
+
*
|
|
39
|
+
* 禁写(与折叠 / 浮层同款):底 / 边 / 圆角 / 内距 / 宽高 / 字号 / 阴影 —— 写了就顶掉皮肤族属性面。
|
|
40
|
+
* 面板的面与几何由皮肤族给(卡片一类);本层只写「收起态」「弹性链」与根上的呼吸位。
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/* ===== 一、操作根:选择控件在上、面板在下 ===== */
|
|
44
|
+
.mh-tabs {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
gap: var(--ui-space-4); /* 控件 → 面板的呼吸位 12px */
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ===== 二、弹性链:面板组 → 面板 =====
|
|
51
|
+
只声明「吃满面板组的剩余高度」,**不动面板的 `display`**。
|
|
52
|
+
用途:抽屉 / 面板级容器里要「页签条固定 + 面板填满 + 面板内部自己滚」时,消费方在自己加到
|
|
53
|
+
根上的类里写 `height: 100%` 即启用 —— 本层不设任何绝对高度,高度归属始终在消费方容器手里。
|
|
54
|
+
根高 auto(桌面普通用法)时这些声明不产生高度变化(无剩余空间可分),与块级布局等价。 */
|
|
55
|
+
.mh-tabs-panels {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
flex: 1 1 auto;
|
|
59
|
+
min-height: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.mh-tabs-panel {
|
|
63
|
+
flex: 1 1 auto;
|
|
64
|
+
min-height: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ===== 三、收起态:本层唯一一条显隐规则 =====
|
|
68
|
+
非选中面板一律带 `hidden`(由 `Tabs` 下发,与控件形态无关)。显式落一次「收起 = 不显示」——
|
|
69
|
+
不依赖 UA 那条 `[hidden]`(它是元素级规则,消费方/皮肤里任何自带 `display` 的类都能压过它)。
|
|
70
|
+
**不写显形规则**:面板显形就是它自己的 `display`(见文件头「历史缺陷二」)。 */
|
|
71
|
+
.mh-tabs-panel[hidden] {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
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",
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { type PropType, type SlotsType, type VNodeChild } from 'vue';
|
|
2
|
-
export interface TabsetOption {
|
|
3
|
-
/** 项文字 */
|
|
4
|
-
label: string;
|
|
5
|
-
/** 项值(受控值就是它) */
|
|
6
|
-
value: string | number;
|
|
7
|
-
/** 禁用项:不可选(原生 radio 路径下方向键会跳过) */
|
|
8
|
-
disabled?: boolean;
|
|
9
|
-
}
|
|
10
|
-
export interface TabsetProps {
|
|
11
|
-
/** 轨道项(顺序即「第 n 项 ↔ 第 n 块面板」的档位表) */
|
|
12
|
-
options: TabsetOption[];
|
|
13
|
-
/** 受控选中值;不传即非受控(由 `defaultValue` 起) */
|
|
14
|
-
value?: string | number;
|
|
15
|
-
/** 非受控初始选中值,缺省第一项 */
|
|
16
|
-
defaultValue?: string | number;
|
|
17
|
-
/** 选中变化回调(受控与非受控都会调) */
|
|
18
|
-
onChange?: (value: string | number) => void;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* 面板切换(**操作层骨架 + 组件路径显隐**)。
|
|
22
|
-
*
|
|
23
|
-
* ## 它是什么
|
|
24
|
-
* 把「一组互斥选项」与「按顺序排列的面板」接起来:第 n 个选项对应第 n 块面板。
|
|
25
|
-
* 骨架(根、面板组、档位表)在操作层 `styles/operations/tabset.css`,本件负责:
|
|
26
|
-
* 受控值、面板包装与显隐、把 `select` 交给选择控件。
|
|
27
|
-
*
|
|
28
|
-
* ## 两条显隐路径(结论一致,不冲突)
|
|
29
|
-
* - **原生路径**(推荐):选择控件用**原生 radio**(如 `Capsule`)→ 操作层的档位表
|
|
30
|
-
* `:has(input:nth-of-type(n):checked)` 直接显隐,**零 JS**;
|
|
31
|
-
* - **组件路径**:控件不是 radio 时,本件按受控值给非选中面板下发 `hidden`。
|
|
32
|
-
* 两条路径都由同一个值驱动,故同时成立不会互相打架。
|
|
33
|
-
*
|
|
34
|
-
* ## 与皮肤零互指
|
|
35
|
-
* 本件不认识任何选择控件的类名 —— 轨道由 `selector` 插槽提供(作用域参数 `{ value, options, select }`),
|
|
36
|
-
* 放胶囊、分段按钮、单选卡片都行;面板内容由默认插槽按 `options` 顺序给出。
|
|
37
|
-
*
|
|
38
|
-
* @example 胶囊 + 面板(`Capsule` 提供原生 radio,故走零 JS 路径)
|
|
39
|
-
* <Tabset :options="tabs" v-model:value="current">
|
|
40
|
-
* {{
|
|
41
|
-
* selector: ({ value, select }) => <Capsule :options="tabs" modelValue={value} onChange={select} />,
|
|
42
|
-
* default: () => [
|
|
43
|
-
* <Card key="all">全部:15 条</Card>,
|
|
44
|
-
* <Card key="doing">进行中:3 条</Card>,
|
|
45
|
-
* ],
|
|
46
|
-
* }}
|
|
47
|
-
* </Tabset>
|
|
48
|
-
*/
|
|
49
|
-
export declare const Tabset: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
50
|
-
options: {
|
|
51
|
-
type: PropType<TabsetOption[]>;
|
|
52
|
-
required: true;
|
|
53
|
-
};
|
|
54
|
-
value: {
|
|
55
|
-
type: PropType<string | number | undefined>;
|
|
56
|
-
default: undefined;
|
|
57
|
-
};
|
|
58
|
-
defaultValue: {
|
|
59
|
-
type: PropType<string | number | undefined>;
|
|
60
|
-
default: undefined;
|
|
61
|
-
};
|
|
62
|
-
onChange: {
|
|
63
|
-
type: PropType<(value: string | number) => void>;
|
|
64
|
-
default: undefined;
|
|
65
|
-
};
|
|
66
|
-
/** 惰性档:只有激活的面板才渲染(切走即卸载),用于面板很重(图表 / 大表格)的场景 */
|
|
67
|
-
lazy: {
|
|
68
|
-
type: BooleanConstructor;
|
|
69
|
-
default: boolean;
|
|
70
|
-
};
|
|
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<{
|
|
74
|
-
options: {
|
|
75
|
-
type: PropType<TabsetOption[]>;
|
|
76
|
-
required: true;
|
|
77
|
-
};
|
|
78
|
-
value: {
|
|
79
|
-
type: PropType<string | number | undefined>;
|
|
80
|
-
default: undefined;
|
|
81
|
-
};
|
|
82
|
-
defaultValue: {
|
|
83
|
-
type: PropType<string | number | undefined>;
|
|
84
|
-
default: undefined;
|
|
85
|
-
};
|
|
86
|
-
onChange: {
|
|
87
|
-
type: PropType<(value: string | number) => void>;
|
|
88
|
-
default: undefined;
|
|
89
|
-
};
|
|
90
|
-
/** 惰性档:只有激活的面板才渲染(切走即卸载),用于面板很重(图表 / 大表格)的场景 */
|
|
91
|
-
lazy: {
|
|
92
|
-
type: BooleanConstructor;
|
|
93
|
-
default: boolean;
|
|
94
|
-
};
|
|
95
|
-
}>> & Readonly<{
|
|
96
|
-
"onUpdate:value"?: ((value: string | number) => any) | undefined;
|
|
97
|
-
}>, {
|
|
98
|
-
value: string | number | undefined;
|
|
99
|
-
onChange: (value: string | number) => void;
|
|
100
|
-
defaultValue: string | number | undefined;
|
|
101
|
-
lazy: boolean;
|
|
102
|
-
}, SlotsType<{
|
|
103
|
-
default?: () => VNodeChild;
|
|
104
|
-
selector?: (context: {
|
|
105
|
-
value: string | number | undefined;
|
|
106
|
-
options: TabsetOption[];
|
|
107
|
-
select: (value: string | number) => void;
|
|
108
|
-
}) => VNodeChild;
|
|
109
|
-
}>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|