@manohub/ui 1.0.4 → 1.0.5

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.
Files changed (84) hide show
  1. package/dist/components/card/index.d.ts +7 -8
  2. package/dist/components/dialog/index.d.ts +3 -3
  3. package/dist/components/dialog/index.js +3 -2
  4. package/dist/components/form/index.d.ts +54 -106
  5. package/dist/components/input/index.d.ts +35 -50
  6. package/dist/components/input/index.js +7 -10
  7. package/dist/components/page/index.d.ts +21 -28
  8. package/dist/components/panel/index.d.ts +6 -8
  9. package/dist/components/radio/index.d.ts +11 -14
  10. package/dist/components/select/index.d.ts +23 -35
  11. package/dist/components/table/index.d.ts +9 -9
  12. package/dist/components/tree/index.d.ts +16 -24
  13. package/dist/services/dialog.d.ts +3 -1
  14. package/dist/services/dialog.js +2 -0
  15. package/dist/styles/components/avatar.css +5 -7
  16. package/dist/styles/components/avatar.tokens.css +4 -9
  17. package/dist/styles/components/badge.css +3 -6
  18. package/dist/styles/components/badge.tokens.css +5 -17
  19. package/dist/styles/components/button.css +33 -57
  20. package/dist/styles/components/button.tokens.css +5 -14
  21. package/dist/styles/components/capsule.css +11 -20
  22. package/dist/styles/components/capsule.tokens.css +4 -9
  23. package/dist/styles/components/card.css +13 -24
  24. package/dist/styles/components/checkbox.css +9 -15
  25. package/dist/styles/components/checkbox.tokens.css +4 -9
  26. package/dist/styles/components/code-block.css +30 -40
  27. package/dist/styles/components/code-block.tokens.css +7 -20
  28. package/dist/styles/components/collapse.css +6 -10
  29. package/dist/styles/components/collapse.tokens.css +4 -9
  30. package/dist/styles/components/dialog.css +19 -27
  31. package/dist/styles/components/dialog.tokens.css +9 -9
  32. package/dist/styles/components/divider.css +9 -14
  33. package/dist/styles/components/divider.tokens.css +4 -9
  34. package/dist/styles/components/drawer.css +12 -16
  35. package/dist/styles/components/drawer.tokens.css +7 -9
  36. package/dist/styles/components/filter.css +13 -24
  37. package/dist/styles/components/form.css +76 -143
  38. package/dist/styles/components/form.tokens.css +9 -6
  39. package/dist/styles/components/input.css +80 -166
  40. package/dist/styles/components/input.tokens.css +5 -13
  41. package/dist/styles/components/layout.css +13 -29
  42. package/dist/styles/components/loading.css +6 -10
  43. package/dist/styles/components/loading.tokens.css +4 -9
  44. package/dist/styles/components/notice.css +1 -1
  45. package/dist/styles/components/notice.tokens.css +8 -6
  46. package/dist/styles/components/notification.css +9 -12
  47. package/dist/styles/components/notification.tokens.css +4 -12
  48. package/dist/styles/components/page.css +12 -22
  49. package/dist/styles/components/pagination.css +10 -15
  50. package/dist/styles/components/pagination.tokens.css +4 -9
  51. package/dist/styles/components/query-state.css +1 -1
  52. package/dist/styles/components/query-state.tokens.css +6 -0
  53. package/dist/styles/components/radio.css +10 -25
  54. package/dist/styles/components/radio.tokens.css +4 -9
  55. package/dist/styles/components/search.css +10 -18
  56. package/dist/styles/components/select.css +63 -109
  57. package/dist/styles/components/select.tokens.css +4 -12
  58. package/dist/styles/components/skeleton.css +4 -7
  59. package/dist/styles/components/skeleton.tokens.css +4 -9
  60. package/dist/styles/components/steps.css +9 -12
  61. package/dist/styles/components/steps.tokens.css +4 -12
  62. package/dist/styles/components/switch.css +5 -8
  63. package/dist/styles/components/switch.tokens.css +4 -9
  64. package/dist/styles/components/tabbar.css +10 -11
  65. package/dist/styles/components/tabbar.tokens.css +4 -9
  66. package/dist/styles/components/table.css +52 -86
  67. package/dist/styles/components/table.tokens.css +5 -6
  68. package/dist/styles/components/tag.css +13 -23
  69. package/dist/styles/components/tag.tokens.css +5 -11
  70. package/dist/styles/components/text.css +11 -23
  71. package/dist/styles/components/toast.css +11 -18
  72. package/dist/styles/components/toast.tokens.css +6 -9
  73. package/dist/styles/components/tooltip.css +9 -11
  74. package/dist/styles/components/tooltip.tokens.css +5 -9
  75. package/dist/styles/components/tree.css +14 -27
  76. package/dist/styles/components/tree.tokens.css +5 -6
  77. package/dist/styles/components/upload.css +8 -13
  78. package/dist/styles/components/upload.tokens.css +4 -9
  79. package/dist/styles/index.css +27 -50
  80. package/dist/styles/operations/collapse.css +12 -25
  81. package/dist/styles/operations/popup.css +41 -79
  82. package/dist/styles/operations/tabs.css +14 -32
  83. package/dist/styles/reset.css +0 -61
  84. package/package.json +2 -2
@@ -1,29 +1,19 @@
1
1
  /**
2
2
  * Form + Form.Item(自建表单:label 列 + 控件列 + 错误 / 说明)。
3
3
  *
4
- * 依据:`@aihub/theme` 的 `components/field.css`(标签色与列宽 / 必填星标 / 说明与报错)与
5
- * 设计稿《MH后台-0911》的表单(`02.1` 高级筛选区:标签 13px、必填星号 `#ff1922`、
4
+ * 依据:设计稿《MH后台-0911》的表单(`02.1` 高级筛选区:标签 13px、必填星号 `#ff1922`、
6
5
  * 标签与控件间距 10)。**必填星号取 `--ui-required-mark`(专用色),不复用 `--ui-error`**。
7
6
  */
8
7
 
9
- /* ===== Form(自建表单:label + 控件 + 错误 + 说明)=====
10
- 沿 farris 表单的既有约定:label **右对齐**、必填星号在 label 文本**左侧**。
11
- 与 farris 动态表单的两处有意差异:① 控件撑满剩余宽度(按需用 controlWidth 收敛),
12
- 不受 farris「字段 max-width 26.625rem」约束;② 错误与说明走**文档流**排在控件下方
13
- (farris 用绝对定位的浮层提示条,在弹窗里会压住下一行控件)。
8
+ /* ===== Form =====
9
+ label **右对齐**、必填星号在 label 文本**左侧**;控件撑满剩余宽度(需要时用 `controlWidth` 收敛),
10
+ 错误与说明走**文档流**排在控件下方(不用绝对定位的浮层提示条 —— 那在弹窗里会压住下一行控件)。
11
+ label 列宽只由变量驱动:Form / Form.Item 落 `--mh-form-label-width`,默认取令牌。
12
+ 行几何是**两列 grid**(label 列 + 控件列):label 与控件同处第 1 行、交叉轴居中 ⇒ 两侧文字落在
13
+ 同一条中线上;错误 / 说明是**行的直接子节点**,自然落第 2 行起,不会把 label 带走。
14
+ 对齐**不依赖任何「控件高度」常量**(需要顶对齐的行见下面的「行内垂直对齐档」)。
14
15
 
15
- label 列宽只由变量驱动:Form / Form.Item 落 `--mh-form-label-width`,默认取令牌,
16
- 故换宽窄不需要在消费方写 CSS。
17
-
18
- 行几何是**两列 grid**(label 列 + 控件列):label 与控件同处第 1 行、交叉轴居中 ⇒ 两侧文字
19
- 落在同一条中线上;错误 / 说明是**行的直接子节点**,自然落第 2 行起,不会把 label 带走。
20
- 对齐**不依赖任何「控件高度」常量**(从前那个 `--ui-form-control-height` 在骨架层没有出处,
21
- 回退 `auto` ⇒ label 盒退化成一行文字并贴行顶,档位越高错得越多)。
22
- 需要顶对齐的行(文本域自动判定、或消费方显式 `align`)见下面的「行内垂直对齐档」。 */
23
-
24
- /* 行距取 8px 档:Form.Item 自己已经是一个完整行(label 与控件等高 + 错误/说明按文档流往下排),
25
- 再用 16px 行距会把表单拉得很散 —— 尤其是步骤⑤那种「只读文本行」的摘要,行与行之间会显得发虚。
26
- 要更松的排版属于消费方场景,改这里之前先确认不是想把「行距」当成区块间距在用。 */
16
+ 行距取 8px 档:Form.Item 自己已是一个完整行,用 16px 会把表单拉得很散(只读摘要行间会发虚)。 */
27
17
 
28
18
  .mh-form {
29
19
  display: flex;
@@ -32,29 +22,20 @@
32
22
  /* 多列公式用的三个变量(**都在本件**,不进 theme 令牌文件):
33
23
  - `--mh-form-columns`:数字档的**列数上限**(档位类只覆盖它,不复制几何);
34
24
  - `--mh-form-column-min`:一列的**最小宽度**(`columnMinWidth` 行内覆盖,缺省取令牌 320);
35
- - `--mh-form-gap`:行距 —— 公式里必须用**与实体 gap 同一个值**算轨道下限
36
- (从前这里硬编码 8px,`gap` 调大后列宽会算偏、临界宽度上还会误判是否回落)。 */
25
+ - `--mh-form-gap`:行距 —— 公式里必须用**与实体 gap 同一个值**算轨道下限。 */
37
26
  --mh-form-columns: 2;
38
27
  --mh-form-column-min: var(--ui-form-column-min);
39
28
  --mh-form-gap: var(--ui-space-2);
40
29
  }
41
30
 
42
31
  /* ===== 多列(数字档:`columns` = 2 / 3 / 4)=====
43
- * 轨道下限取「**最小列宽**」与「**按 N 列等分**」的较大者,配 `auto-fit`:
44
- * - 容器放得下 N 列 ⇒ 排 N 列;
45
- * - 放不下 ⇒ 轨道数减少(**自动回落**,不会把控件压成窄条)。
46
- *
47
- * 把「均分值」当轨道下限就是「**上限 N 列**」的实现 —— 没有它,`auto-fit` 会一路排下去
48
- * (实测 1400px 得 4 列,与「最多 N 列」的承诺不符)。
49
- *
50
- * 这条是表单与 `Layout.Row` 的**关键差别**:后者列数恒定、窄了等分收窄(实测 480px 容器里
51
- * Form 回落成一列、控件还有 360px;恒定两列会把控件压到 ~104px)。表单会被放进抽屉 / 弹窗 /
52
- * 分栏,容器宽度不可预知,所以要的是「回落到能用」而不是「列数不变」。
53
- *
32
+ * 轨道下限取「最小列宽」与「按 N 列等分」的**较大者**,配 `auto-fit`:放得下 N 列就排 N 列、放不下就减少
33
+ * 轨道数(回落,不把控件压成窄条)。没有那个「均分值」下限,`auto-fit` 会一路排下去(实测 1400px 得 4 列,
34
+ * 与「最多 N 列」的承诺不符)。这也是表单与 `Layout.Row` 的关键差别:后者列数恒定、窄了等分收窄;表单会被
35
+ * 放进抽屉 / 弹窗 / 分栏,要的是「回落到能用」。
54
36
  * `align-items: start`:同一行的字段各自顶部对齐,不被隔壁那个「错误 + 多行说明」撑高的格子拉扯。
55
- *
56
- * `mh-form--two-column` 是 `columns={2}` 的**历史类名**(已发布过,改名属破坏性变更),
57
- * 与 3~6 档共用下面这份几何声明(`2` 与 `3+` 走两个类名只是历史包袱,样式上完全等价)。 */
37
+ * `mh-form--two-column` 是 `columns={2}` 的**已发布的类名**(改名属破坏性变更),与 3~6 档共用下面这份
38
+ * 几何声明(走两个类名只是历史包袱,样式上完全等价)。 */
58
39
 
59
40
  .mh-form--two-column,
60
41
  .mh-form--columns-3,
@@ -76,7 +57,7 @@
76
57
  }
77
58
 
78
59
  /* 档位只覆盖变量(几何只有一份)。5 / 6 档在默认最小宽 320 下要容器 1632 / 1960px 才排得出来,
79
- 留着它们是给「宽屏展示页 / 大屏看板」用 —— 配合 `columnMinWidth` 调小最小宽才落地得快。 */
60
+ 留着是给「宽屏展示页 / 大屏看板」用 —— 配合 `columnMinWidth` 调小最小宽才落地得快。 */
80
61
  .mh-form--columns-3 {
81
62
  --mh-form-columns: 3;
82
63
  }
@@ -91,14 +72,11 @@
91
72
  }
92
73
 
93
74
  /* ===== 动态列数(`columns="auto"`)=====
94
- * `auto-fill` + `minmax(最小列宽, 1fr)`:**列数随容器宽度变**,列数 =
95
- * `floor((容器宽 + 行距) / (最小宽 + 行距))`。实测(最小宽 320 / 行距 8):
96
- * 640px → 1 列、660px → 2 列、1000px → 3 列、1320px → 4 列;每列宽落在 `[最小宽, 2 × 最小宽)`。
97
- *
98
- * 为什么是 `auto-fill` 而不是 `auto-fit`:两者只差在「子项少于轨道数」时 ——
99
- * `auto-fit` 会**折叠空轨道**,于是宽容器里 2 个字段被拉成两条长条(实测 1400px 下每项 696px);
100
- * `auto-fill` 保留轨道,字段列宽稳定在区间内(1400px 下每项 344px)。表单要的是**列宽稳定**,
101
- * 不是「把剩余宽度填满」。 */
75
+ * `auto-fill` + `minmax(最小列宽, 1fr)`:列数随容器宽度变。实测(最小宽 320 / 行距 8):
76
+ * 640px → 1 列、660px → 2 列、1000px → 3 列、1320px → 4 列。
77
+ * 为什么是 `auto-fill` 而不是 `auto-fit`:两者只差在「子项少于轨道数」时 —— `auto-fit` 会**折叠空轨道**,
78
+ * 宽容器里 2 个字段被拉成两条长条(实测 1400px 下每项 696px);`auto-fill` 保留轨道,列宽稳定在区间内
79
+ * (1400px 下每项 344px)。表单要的是**列宽稳定**,不是「把剩余宽度填满」。 */
102
80
 
103
81
  .mh-form--columns-auto {
104
82
  display: grid;
@@ -119,27 +97,24 @@
119
97
  它必须能被内部长内容压缩,否则长 URL / 自绘表格会撑破列宽。 */
120
98
  display: grid;
121
99
  grid-template-columns: var(--mh-form-label-width) minmax(0, 1fr);
122
- /* **第 1 行内交叉轴居中** = label 文字与控件中线对齐。
123
- 第 1 行的行高由控件(恒高于一行文字)决定 ⇒ 对齐与控件高度**解耦**:
124
- 控件档位换 sm/md/lg、换主题、放自绘控件都自动成立,**不需要任何「控件高度」常量**。 */
100
+ /* **第 1 行内交叉轴居中** = label 文字与控件中线对齐。第 1 行的行高由控件(恒高于一行文字)决定
101
+ ⇒ 对齐与控件高度**解耦**:换档位 / 换主题 / 放自绘控件都自动成立。 */
125
102
  align-items: center;
126
103
  }
127
104
 
128
- /* label 列:固定宽 + **右对齐**(与 farris 的动态表单一致,也是水平表单的通行默认)。
129
- 只占第 1 行(控件那一行),所以错误 / 说明的出现不会把它带走;
130
- 本件**不设任何高度** —— 从前用 min-height 取一个外部注入的控件高度来「假装等高」,
131
- 而那个变量在骨架层没有出处(回退 auto),label 盒退化成一行文字并贴行顶:
132
- 输入框中线偏高 6px、大号档偏高 10px、文本域偏高 9px。 */
105
+ /* label 列:固定宽 + **右对齐**;只占第 1 行,所以错误 / 说明的出现不会把它带走。
106
+ 本件**不设任何高度** —— 用 min-height 取一个外部注入的控件高度来「假装等高」会因变量无出处
107
+ 而退化成一行文字并贴行顶(实测输入框中线偏高 6px、大号档 10px、文本域 9px)。 */
133
108
 
134
109
  .mh-form-item__label {
135
110
  grid-column: 1;
136
111
  grid-row: 1;
137
112
  width: var(--mh-form-label-width);
138
113
  box-sizing: border-box;
139
- padding-right: var(--ui-space-3);
114
+ padding-right: var(--ui-form-label-padding-right);
140
115
  display: flex;
141
116
  align-items: center;
142
- /* 右对齐:label 文本贴着控件列,短标签也不会在列里留下大段空隙(与 farris 动态表单一致) */
117
+ /* 右对齐:label 文本贴着控件列,短标签也不会在列里留下大段空隙 */
143
118
  justify-content: flex-end;
144
119
  gap: 2px;
145
120
  font-size: var(--ui-font-body);
@@ -149,31 +124,25 @@
149
124
 
150
125
  .mh-form-item__required {
151
126
  flex: 0 0 auto;
152
- /* **不是** `--ui-error`:星号表达「这里有个必填要求」,不是「这里出错了」。
153
- 两者放同一枚令牌时,改错误色会顺带改掉全站的必填星号(反之亦然)。
154
- 设计实证:`02.1 > 高级筛选 > 1..4` 的 `*` = `#ff1922`(比错误色 `#f23030` 更艳)。 */
127
+ /* **不是** `--ui-error`:星号表达「这里有个必填要求」,不是「这里出错了」—— 两者放同一枚令牌时
128
+ 改错误色会顺带改掉全站的必填星号。设计实证:`02.1 > 高级筛选 > 1..4` 的 `*` = `#ff1922`。 */
155
129
  color: var(--ui-required-mark);
156
130
  }
157
131
 
158
132
  /* ===== label 提示位(`Form.Item` 的 `tip`)=====
159
- * 图标与气泡都**不新造** —— 图标取 `@manohub/icon` 的 `help`(带圈问号),气泡复用 `Tooltip` 的面
160
- * (`.mh-tooltip`)与操作层 `popup.css` 的 hover 档;本件只声明**提示位在 label 行里怎么排**。
161
- *
162
- * 宿主位(Tooltip 落在 label 里的那个 span)有两件事必做,少一件就有肉眼可见的偏移:
163
- * ① `flex: 0 0 auto` —— label 文本过长时走省略号,图标不被挤压;
164
- * ② 行高归 1 —— 图标比一行文字矮(图标档对 20px 行盒),留在 label 的行盒里会按基线排,
165
- * 中线与 label 文字错开(本仓对这类 1~6px 偏移有实测前科,见 `.mh-form-item__control` 那段)。
166
- * 气泡本身是固定定位(操作层 hover 档),不参与本行排布,故宿主宽度恒等于图标宽度。 */
133
+ * 图标取 `@manohub/icon` 的 `help`,气泡复用 `Tooltip` 的面(`.mh-tooltip`)与操作层 `popup.css` 的
134
+ * hover 档;本件只声明**提示位在 label 行里怎么排**。宿主位两件事必做:① `flex: 0 0 auto`(label
135
+ * 文本过长走省略号时不挤压图标);② 行高归 1(图标比一行文字矮,留在 label 行盒里会按基线排、
136
+ * 中线与文字错开)。气泡是固定定位(操作层 hover 档),不参与本行排布。 */
167
137
 
168
138
  .mh-form-item__tip {
169
139
  display: inline-flex;
170
140
  align-items: center;
171
141
  flex: 0 0 auto;
172
- /* 行盒归零(`font-size: 0` + `line-height: 0`):`Tooltip` 的宿主里还夹着一层 **inline 的锚点
173
- span**(`.mh-popup-anchor`),它会给内含的 `inline-flex` 触发器生成行盒 —— 行盒按基线对齐,
174
- 于是宿主比图标高出一个 descender 间隙(实测 16px 图标 ⇒ 宿主 17px)。宿主再把这 17px 在
175
- label 行里居中,图标中线就比文字中线高 0.5px。归零后宿主高度 === 图标高度,中线才重合。
176
- 图标 svg 不受影响(它自带尺寸,不读字号)。 */
142
+ /* 行盒归零(`font-size: 0` + `line-height: 0`):`Tooltip` 宿主里还夹着一层 **inline 的锚点 span**
143
+ (`.mh-popup-anchor`),它会给内含的 `inline-flex` 触发器生成行盒 —— 宿主因此比图标高出一个
144
+ descender 间隙(实测 16px 图标 ⇒ 宿主 17px),在 label 行里居中后图标中线比文字高 0.5px。
145
+ 归零后宿主高度 === 图标高度。图标 svg 自带尺寸,不读字号。 */
177
146
  font-size: 0;
178
147
  line-height: 0;
179
148
  }
@@ -188,8 +157,7 @@
188
157
  padding: 0;
189
158
  border: none;
190
159
  background: transparent;
191
- /* 静止:**浅灰**(`subtle`,同计数器档);滑过 / 键盘聚焦转**正文色(黑)** ——
192
- 从 muted(#666) 起手的那版与 hover 后的 content(#1a1a1a) 只差一档,视觉上几乎看不出交互。 */
160
+ /* 静止取 subdued 档:从 muted(#666) 起手时与 hover 后的正文色只差一档,看不出交互 */
193
161
  color: var(--ui-base-content-subtle);
194
162
  cursor: help;
195
163
  }
@@ -218,18 +186,16 @@
218
186
 
219
187
 
220
188
 
221
- /* label 对齐:基类默认右对齐(贴控件列,`labelAlign` 缺省档);
222
- `labelAlign="left"` 时挂这个修饰类改成左对齐 —— 只给「非默认值」挂类,避免两段声明争胜出顺序。
189
+ /* label 对齐:基类默认右对齐(贴控件列,`labelAlign` 缺省档);`labelAlign="left"` 时挂这个修饰类
190
+ 改成左对齐 —— 只给「非默认值」挂类,避免两段声明争胜出顺序。
223
191
  位置必须在基类规则之后:`.mh-form-item__label {` 是它的子串,测试取规则体时按首次出现命中。 */
224
192
 
225
193
  .mh-form-item--label-left .mh-form-item__label {
226
194
  justify-content: flex-start;
227
195
  }
228
196
 
229
- /* 只读展示行(`Form.Item` 的 `text` 形态,或显式 `readonly`)的 label 降一档为**次要色**:
230
- 值与字段名同取正文色时,摘要 / 详情读起来是一串并列文本,分不清哪个是字段名
231
- (原型 .sum-group td.k / .field-item .k 用的正是次要色)。值侧不变,仍是正文色。
232
- `muted` 而非 `subtle`:空值占位「—」已经是 subtle,label 再用同色会让空行整行同调。
197
+ /* 只读展示行的 label 降一档为**次要色**:值与字段名同取正文色时,摘要 / 详情读起来是一串并列文本,
198
+ 分不清哪个是字段名。值侧不变。`muted` 而非 `subtle`:空值占位「—」已是 subtle。
233
199
  位置同样必须在基类 `.mh-form-item__label {` 之后(spec 的 ruleBody 按首次出现取规则体)。 */
234
200
 
235
201
  .mh-form-item--readonly .mh-form-item__label {
@@ -255,35 +221,15 @@
255
221
  }
256
222
 
257
223
  /* 矮控件(开关 / 勾选框 / 单选)在控件列里**按盒居中**,而不是按行盒的基线排。
258
- *
259
- * 它们高 14~18px,**比一行文字(20px)还矮**(`Switch` / `Checkbox` / `Radio` 三件即这一族):
260
- * 作为行内元素参与基线对齐时,控件列会被 line box 撑高(实测 22px = 18 + 行内 leading),
261
- * 而控件本身在那一行里偏上 2px —— 开关与标签看着就不在一条中线上(本件第 1 行本来是居中的,
262
- * 偏的是**控件列内部**这一层)。
263
- *
264
- * 单子项时把控件列切成 flex 并 `align-items: center`:控件列高度回到控件自身高度,
265
- * 与 label 同处第 1 行、各自居中 ⇒ 两侧中线重合(实测 switch 18px / checkbox 14px 偏差都为 0,
266
- * 行高也从 22px 回到 20px —— 不再被行盒的 leading 撑高)。
267
- *
268
- * 为什么限定「**唯一**子项」:控件列里放多个内容时(如「输入框 + 获取按钮」)原本是块级上下堆叠,
269
- * 无条件 flex 会把它们排成一行 —— 那是布局变更,不是修对齐。
270
- *
271
- * 判据是**属性协议** `data-inline-control`,不是元素名、也不是别件的类名:
272
- *
273
- * - `Switch` / `Checkbox` / `Radio` 在根节点上声明这个属性(三件正好是这一族,14~18px);
274
- * - **自绘的行内小控件**(根是 `div` / `span` 都行)在根上加同一个属性就自动接入 ——
275
- * 不需要对齐本库的类名,也不必知道这里的实现;
276
- * - 为什么不按元素名判(`label` / `button`):那把判据绑死在「别人怎么写 DOM」上,
277
- * 自绘控件必然漏掉(而控件根是什么元素本就是它的实现自由);
278
- * 按类名判则要求两个面互相引用,本仓既有裁决不允许。
279
- *
280
- * 对齐**不依赖控件列的高度**(别以为 `display: flex` 让控件列从「撑满行高」变成「内容撑高」
281
- * 就把对齐弄丢了):switch 行三种行级配置实测 —— `center` 控件列 18px、`stretch` 控件列 20px,
282
- * switch 中心都落在行中心、与 label 文字同线(Δ 都是 0);三种里唯一会偏的是 `align="start"`
283
- * 顶对齐档(Δ = −10,label 有 9px 上内距而控件贴顶)—— 那一档是给多行 / 整块内容用的,
284
- * 开关不要放进那种行,或显式写 `align="center"`。
285
- * 将来若要让控件列**占满行高**(例如给它画背景 / 分割线),在行上写 `align-items: stretch`
286
- * 或给控件列 `align-self: stretch` 即可 —— 实测那样 switch 依然居中。 */
224
+ * 它们高 14~18px、**比一行文字(20px)还矮**:作为行内元素参与基线对齐时,控件列会被 line box 撑高
225
+ * (实测 22px = 18 + 行内 leading),而控件本身偏上 2px —— 开关与标签看着不在一条中线上。单子项时把控件列
226
+ * 切成 flex 并 `align-items: center`:控件列高度回到控件自身高度、两侧中线重合(实测偏差为 0)。
227
+ * 限定「**唯一**子项」的原因:控件列里放多个内容时(如「输入框 + 获取按钮」)原本是块级堆叠,无条件 flex
228
+ * 会把它们排成一行 —— 那是布局变更,不是修对齐。
229
+ * 判据是**属性协议** `data-inline-control`(不是元素名、也不是别件的类名):`Switch` / `Checkbox` /
230
+ * `Radio` 在根节点上声明它,**自绘的行内小控件**加同一个属性即接入。按元素名判等于把判据绑死在「别人怎么写
231
+ * DOM」上;按类名判要求两个面互相引用(本仓裁决不允许)。
232
+ * ⚠️ 三种行级配置里只有 `align="start"` 顶对齐档会偏 —— 那一档是给多行 / 整块内容用的,开关不要放进那种行。 */
287
233
 
288
234
  .mh-form-item__control:has(> [data-inline-control]:only-child) {
289
235
  display: flex;
@@ -291,8 +237,7 @@
291
237
  }
292
238
 
293
239
  /* 错误 / 说明:**行的直接子节点**(不在控件列里面),排在控件行之下、与控件列同列。
294
- 只给 `grid-column` 不给行号 —— 自动放置会把它们推进下一个空行:控件占着第 1 行,
295
- 于是它们既不会挤进第 1 行、也不会掉到 label 列下面去。 */
240
+ 只给 `grid-column` 不给行号 —— 自动放置会把它们推进下一个空行(控件占着第 1 行)。 */
296
241
 
297
242
  .mh-form-item__error {
298
243
  grid-column: 2;
@@ -322,32 +267,27 @@
322
267
  }
323
268
 
324
269
  /* ===== 行内垂直对齐档 =====
325
- * 默认(基类)`center`:label 与控件**中线**对齐 —— 第 1 行行高 = 控件真实高度,
326
- * 与控件档位 / 主题 / 自绘控件都无关。需要顶对齐的是**多行与整块内容**:label 该与首行文字齐,
327
- * 而不是落到整块高度的中间。
328
- *
270
+ * 默认(基类)`center`:label 与控件**中线**对齐。需要顶对齐的是**多行与整块内容**:label 该与首行
271
+ * 文字齐,而不是落到整块高度的中间。
329
272
  * 自动判定(按控件形态,消费方零配置):认**原生元素** `textarea`,不认别件的类名(面之间不互指,
330
- * 是本仓的既有裁决;认元素还顺带覆盖了代码编辑区这类自绘多行件)。
331
- * 文本域的壳带 8px 上内距 + 1px 边框(控件自身内距被壳归零,见 input.css),
332
- * label 补上同样的偏移才与**首行文字**同线 —— 不补则仍偏高 9px(实测)。
333
- * 整条自动判定包 `:where()`:把选择器特异性压回 0-1-0,显式修饰类(0-2-0)才稳定压过它,
334
- * 不必靠「谁写在后面」争胜出。 */
273
+ * 是本仓的既有裁决;认元素还顺带覆盖了代码编辑区这类自绘多行件)。文本域的壳带 8px 上内距 + 1px 边框
274
+ * (控件自身内距被壳归零,见 input.css),label 补上同样偏移才与**首行文字**同线 —— 不补偏高 9px(实测)。
275
+ * 整条包 `:where()`:把特异性压回 0-1-0,显式修饰类(0-2-0)才稳定压过它,不必靠「谁写在后面」。 */
335
276
  .mh-form-item:where(:has(.mh-form-item__control textarea)) {
336
277
  align-items: start;
337
278
  }
338
279
  .mh-form-item:where(:has(.mh-form-item__control textarea)) > .mh-form-item__label {
339
- padding-top: calc(var(--ui-space-2) + 1px);
280
+ padding-top: var(--ui-form-label-padding-top);
340
281
  }
341
282
 
342
283
  /* 显式档(`Form.Item` 的 `align`):样式认不出形态的自绘内容(卡片组 / 表格 / 富文本)写 start;
343
- 要强制回到默认的中线对齐写 center。两者都会压过上面的自动判定。
344
- `start` 沿用与文本域**同一口径**的上内距(8px 内距 + 1px 边框):自绘块自带更大内距时会有几像素差
345
- (实测块内距 12px 时差 4px)—— 组件无从知道自绘块内部的排版,要求严格同线时在块内自行调整。 */
284
+ 要强制回到默认的中线对齐写 center(两者都压过上面的自动判定)。
285
+ `start` 沿用与文本域同一口径的上内距:自绘块自带更大内距时会有几像素差(实测块内距 12px 时差 4px)。 */
346
286
  .mh-form-item.mh-form-item--align-start {
347
287
  align-items: start;
348
288
  }
349
289
  .mh-form-item.mh-form-item--align-start > .mh-form-item__label {
350
- padding-top: calc(var(--ui-space-2) + 1px);
290
+ padding-top: var(--ui-form-label-padding-top);
351
291
  }
352
292
  .mh-form-item.mh-form-item--align-center {
353
293
  align-items: center;
@@ -358,9 +298,8 @@
358
298
 
359
299
  /* ===== 纵向排布(`layout="vertical"`:label 在控件上方) =====
360
300
  * 窄容器(抽屉 / 移动端)与「字段名很长」的场景用纵向 —— 横向时 label 列宽会把控件压得很窄。
361
- * 单列三行:label / 控件 / 提示依次往下(提示不给行号,自动放置接在控件之后)。
362
- * 选择器带 `>` 且写成 0-3-0:纵向档必须压过上面的顶对齐档与显式档 ——
363
- * 纵向时 label 本来就在上方,那 9px 上内距只会在 label 上多出一截空隙。 */
301
+ * 单列三行:label / 控件 / 提示依次往下。选择器带 `>` 且写成 0-3-0:纵向档必须压过上面的顶对齐档
302
+ * 与显式档 —— 纵向时 label 本来就在上方,那 9px 上内距只会多出一截空隙。 */
364
303
  .mh-form--vertical .mh-form-item {
365
304
  grid-template-columns: minmax(0, 1fr);
366
305
  }
@@ -372,7 +311,7 @@
372
311
  justify-content: flex-start;
373
312
  padding-right: 0;
374
313
  padding-top: 0;
375
- padding-bottom: var(--ui-space-2);
314
+ padding-bottom: var(--ui-form-label-padding-bottom);
376
315
  text-align: left;
377
316
  }
378
317
  .mh-form--vertical .mh-form-item > .mh-form-item__control {
@@ -386,13 +325,11 @@
386
325
 
387
326
  /* ===== 表单头(`Form.Header`:单头,成员归位到最前)=====
388
327
  只做**标题排版**与**右端操作位**,不承担区块分组(那是 `Panel` 的职责)。
389
- 三样(title / extra / description)都没有时组件整块不渲染 —— 空盒子同样占一档
390
- `Form` 的 gap,会凭空多出间距。 */
328
+ 三样(title / extra / description)都没有时组件整块不渲染 —— 空盒子同样占一档 gap,会凭空多出间距。 */
391
329
 
392
- /* `grid-column: 1 / -1`:多列下**表头必须跨满整行** —— 它是 `Form` 的一个 grid 子项,
393
- 不跨行就只占一格(实测 `columns={2}`、容器 800 时表头只有 396px = 半宽;列数越多越窄)。
394
- `1 / -1` 引用的是最后一条**显式**轨道线,不会生成隐式轨道,故动态列数下同样安全;
395
- 单列(flex 形态)时该属性无效、无副作用(与 `.mh-form-item--full` 同款写法)。 */
330
+ /* `grid-column: 1 / -1`:多列下**表头必须跨满整行** —— 它是 `Form` 的一个 grid 子项,不跨行就只占一格
331
+ (实测 `columns={2}`、容器 800 时表头只有 396px)。`1 / -1` 引用最后一条**显式**轨道线,不生成隐式
332
+ 轨道,故动态列数下同样安全;单列(flex 形态)时该属性无效、无副作用(同 `.mh-form-item--full`)。 */
396
333
 
397
334
  .mh-form__header {
398
335
  grid-column: 1 / -1;
@@ -401,8 +338,7 @@
401
338
  gap: var(--ui-space-1);
402
339
  }
403
340
 
404
- /* 标题行:14px/600 —— 与字段 label(14px/400)拉开「这是标题」的字重差;
405
- 有意不打到 16px(`--ui-font-heading` 是弹窗标题那一档)。
341
+ /* 标题行:14px/600 —— 与字段 label(14px/400)拉开字重差;有意不打到 16px(那是弹窗标题那一档)。
406
342
  行高由这一行**最高的孩子**决定:筛选条里是两颗 32px 按钮 ⇒ 这一行就是 32px(与设计稿一致)。 */
407
343
 
408
344
  .mh-form__title {
@@ -416,10 +352,9 @@
416
352
  }
417
353
 
418
354
  /* 标题左端的品牌色竖标(主色胶囊,几何见 `form.tokens.css` 的两枚令牌 —— 库内唯一来源)。
419
- * **只在有标题文本时出现**:这一行也会在「只给 `extra`」时渲染(筛选条那种),
420
- * 那时凭空多一条竖标就成了坏的排版 —— 用 `:has()` 守住真正有标题的那一种。
421
- * `flex: none`:标题换行时竖标不许被挤扁。竖标与文本之间的间距由标题行既有的 `gap` 给,
422
- * 本句不另写间距(两处各写一遍必然漂)。 */
355
+ * **只在有标题文本时出现**:这一行也会在「只给 `extra`」时渲染(筛选条那种),那时凭空多一条竖标
356
+ 就成了坏的排版 —— 用 `:has()` 守住真正有标题的那一种。
357
+ * `flex: none`:标题换行时竖标不许被挤扁;竖标与文本之间的间距由标题行既有的 `gap` 给。 */
423
358
  .mh-form__title:has(> .mh-form__title-text)::before {
424
359
  content: '';
425
360
  flex: none;
@@ -429,8 +364,7 @@
429
364
  background: var(--ui-primary);
430
365
  }
431
366
 
432
- /* 标题文本允许被挤窄(右端操作位不参与收缩);长标题**换行**而不是截断
433
- —— 截断会让这一块读不出是什么。 */
367
+ /* 标题文本允许被挤窄(右端操作位不参与收缩);长标题**换行**而不是截断 —— 截断会让这一块读不出是什么。 */
434
368
 
435
369
  .mh-form__title-text {
436
370
  min-width: 0;
@@ -438,8 +372,7 @@
438
372
  }
439
373
 
440
374
  /* 右端操作位(`extra` 槽):贴右由 `margin-left: auto` 表达,不用 `justify-content: space-between`
441
- (那条依赖「这一行只有两个子节点」,标题换行或将来再加子节点时就不再贴右);
442
- `flex: none` 让操作位自身不被标题挤变形(与卡片便捷头同一手法)。 */
375
+ (那条依赖「这一行只有两个子节点」);`flex: none` 让操作位自身不被标题挤变形。 */
443
376
 
444
377
  .mh-form__title-extra {
445
378
  margin-left: auto;
@@ -3,12 +3,11 @@
3
3
  * 覆盖 —— 组件只下发 --mh-form-label-width)+ 两列表单的列最小宽度(320 = 「label 120 + 一个还能
4
4
  * 用的输入框」的下限,容器放不下两列时自动回落一列)。
5
5
  *
6
- * ## 抽出说明
7
- * 本文件从面文件里抽出:这些是**基础值**,锚在 `[data-manohub-ui]`(跨包唯一作用域锚,
8
- * 由入口层无条件写在应用容器上)—— 任何落在容器里的分件都取得到值,不再依赖
9
- * 「声明在某个组件根类上」这条脆弱假设。
10
- * ⚠️ `.mh-<件>--<档>` 这类**档位改写**留在面文件的修饰符块里(拆开会让档位失效)。
11
- */
6
+ *
7
+ * 令牌锚 `[data-manohub-ui]`(容器是每个分件的祖先 ⇒ 落在容器里的分件都取得到值)。
8
+ * ⚠️ `.mh-<件>--<档>` 这类**档位改写**留在面文件的修饰符块里(搬走会让档位失效);
9
+ * 新增组件要登记两处:本文件 + `src/styles/index.css`(见其文件头「五处齐备」)。
10
+ */
12
11
  [data-manohub-ui] {
13
12
  --ui-form-label-width: 120px;
14
13
  --ui-form-column-min: 320px;
@@ -16,4 +15,8 @@
16
15
  同值的竖标(`.mh-demo__title::before`),现由演示改用本件的 `Form.Header`,那一份已删。 */
17
16
  --ui-form-title-bar-width: 3px;
18
17
  --ui-form-title-bar-height: 14px;
18
+ /* 标签三向内距:右(与控件之间的呼吸位)/ 上(顶对齐时的基线补偿)/ 下(竖排版式的行距) */
19
+ --ui-form-label-padding-right: var(--ui-space-3);
20
+ --ui-form-label-padding-top: calc(var(--ui-space-2) + 1px);
21
+ --ui-form-label-padding-bottom: var(--ui-space-2);
19
22
  }