@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
@@ -9,18 +9,17 @@ export type CardHeaderIcon = string | (() => VNodeChild);
9
9
  /**
10
10
  * 卡片容器:**卡片外观的唯一实现**(底 / 弱描边 / 圆角 / 内距 / 悬浮与选中反馈)。
11
11
  *
12
- * 消费方(含 `ListView.CardItem`)不得再自绘卡片外观(描边 / 圆角 / 阴影 / 底色),
13
- * 也不得在应用侧写这四类属性 —— 需要不同形态就用本件的维度(`variant` / `interactive` /
14
- * `selected` / `disabled`),或提为骨架层待建件。
12
+ * 消费方(含 `ListView.CardItem`)不得再自绘卡片外观(描边 / 圆角 / 阴影 / 底色),也不得在应用侧写这四类
13
+ * 属性 —— 需要不同形态就用本件的维度(`variant` / `interactive` / `selected` / `disabled`),或提为骨架层待建件。
15
14
  *
16
15
  * ## 几何来源(技能市场卡片实测,逐项落 `--ui-*` 令牌)
17
16
  *
18
- * - 圆角 8(`--ui-radius-md`)、内距 20(`--mh-card-padding`,原型 `p-5`)
19
- * - 底 `--ui-base-100`、弱描边 `--ui-base-300`(原型 `border-border`)
20
- * - 悬浮:描边转 `--ui-primary` + 主色 12% 阴影(`--ui-shadow-card-hover`)
17
+ * 圆角 8(`--ui-radius-md`)、内距 20(`--mh-card-padding`,原型 `p-5`)、底 `--ui-base-100`、弱描边
18
+ * `--ui-base-300`(原型 `border-border`)、悬浮转 `--ui-primary` 描边 + 主色 12% 阴影
19
+ * (`--ui-shadow-card-hover`)。
21
20
  *
22
- * 列表卡片项那套几何(最小高 144、状态胶囊、标签片…)属 `ListView.CardItem`,**不在本件** ——
23
- * 通用卡片不该被一条「只在列表里成立」的最小高绑住(**头部四件两处一致**,见下)。
21
+ * 列表卡片项那套几何(最小高 144、状态胶囊、标签片…)属 `ListView.CardItem`,**不在本件** —— 通用卡片不该被
22
+ * 一条「只在列表里成立」的最小高绑住(**头部四件两处一致**,见下)。
24
23
  *
25
24
  * ## Header 区域(四件;`Card.Header` 是完整入口,`Card` 上的同名 props 是它的简写)
26
25
  *
@@ -1,5 +1,5 @@
1
1
  import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
- export type DialogWidth = 'md' | 'lg';
2
+ export type DialogWidth = 'sm' | 'md' | 'lg';
3
3
  /** 语义档:决定标题左侧图标的图形与颜色(缺省不渲染图标) */
4
4
  export type DialogTone = 'info' | 'success' | 'warning' | 'error';
5
5
  /**
@@ -56,7 +56,7 @@ export declare const Dialog: import("vue").DefineComponent<import("vue").Extract
56
56
  type: PropType<DialogTone>;
57
57
  default: undefined;
58
58
  };
59
- /** 宽度:尺寸档 `md` 520 / `lg` 760,或直接给像素数 */
59
+ /** 宽度:尺寸档 `sm` 400 / `md` 520 / `lg` 760,或直接给像素数 */
60
60
  width: {
61
61
  type: PropType<DialogWidth | number>;
62
62
  default: string;
@@ -163,7 +163,7 @@ export declare const Dialog: import("vue").DefineComponent<import("vue").Extract
163
163
  type: PropType<DialogTone>;
164
164
  default: undefined;
165
165
  };
166
- /** 宽度:尺寸档 `md` 520 / `lg` 760,或直接给像素数 */
166
+ /** 宽度:尺寸档 `sm` 400 / `md` 520 / `lg` 760,或直接给像素数 */
167
167
  width: {
168
168
  type: PropType<DialogWidth | number>;
169
169
  default: string;
@@ -30,7 +30,7 @@ const Dialog = /* @__PURE__ */ defineComponent({
30
30
  type: String,
31
31
  default: void 0
32
32
  },
33
- /** 宽度:尺寸档 `md` 520 / `lg` 760,或直接给像素数 */
33
+ /** 宽度:尺寸档 `sm` 400 / `md` 520 / `lg` 760,或直接给像素数 */
34
34
  width: {
35
35
  type: [String, Number],
36
36
  default: "md"
@@ -169,12 +169,13 @@ const Dialog = /* @__PURE__ */ defineComponent({
169
169
  };
170
170
  return void 0;
171
171
  });
172
+ const widthClass = computed(() => typeof props.width === "string" && props.width !== "md" ? `mh-dialog--${props.width}` : "");
172
173
  const heightStyle = computed(() => props.panelHeight ? {
173
174
  height: props.panelHeight
174
175
  } : void 0);
175
176
  return () => createVNode("dialog", {
176
177
  "ref": dialogRef,
177
- "class": ["mh-popup", "mh-dialog", props.width === "lg" ? "mh-dialog--lg" : "", props.tone ? `mh-dialog--${props.tone}` : "", attrs.class].filter(Boolean).join(" "),
178
+ "class": ["mh-popup", "mh-dialog", widthClass.value, props.tone ? `mh-dialog--${props.tone}` : "", attrs.class].filter(Boolean).join(" "),
178
179
  "style": {
179
180
  ...widthStyle.value,
180
181
  ...heightStyle.value,
@@ -5,30 +5,19 @@ export type FormPadding = Padding;
5
5
  /** label 列的水平对齐:`right`(默认,与 farris / 主流水平表单一致)或 `left` */
6
6
  export type FormLabelAlign = 'left' | 'right';
7
7
  /**
8
- * 字段行的排布档:
8
+ * 字段行的排布档:`1`(默认,逐行);`2 ~ 6`(**列数上限** —— 放得下 N 列就并排,放不下少排一列,不会
9
+ * 把控件压成窄条;5 / 6 是给宽屏展示页的,默认最小宽 320 下要容器 1632 / 1960px);`'auto'`(**列数随容器
10
+ * 宽度动态变化**,每列宽由 `columnMinWidth` 决定)。
9
11
  *
10
- * - `1`(默认):逐行;
11
- * - `2 ~ 6`:**列数上限** —— 容器放得下 N 列就并排,放不下**少排一列**(不会把控件压成窄条)。
12
- * 高列数(5 / 6)在默认最小宽 320 下要容器 1632 / 1960px 才排得出来,普通表单页用不到 ——
13
- * 留着它是给「宽屏展示页 / 大屏看板」这类场景,配 `columnMinWidth` 才好落地;
14
- * - `'auto'`:**列数随容器宽度动态变化** —— 能排几列排几列,每列宽由 `columnMinWidth` 决定。
15
- *
16
- * 两类的差别是**可预期性**(不是能力高低):
17
- *
18
- * - 数字档承诺「最多 N 列」,所以「哪几个字段同排」在够宽的容器里是确定的;
19
- * - 动态档会一路排下去(默认参数下 1320px 就够 4 列),窄了就减 ——
20
- * 同一个表单在不同容器里列数不同 ⇒ **字段的相对位置会变**。要「两个字段必须并肩」就别用它。
12
+ * 两类的差别是**可预期性**(不是能力高低):数字档承诺「最多 N 列」,够宽的容器里「哪几个字段同排」是
13
+ * 确定的;动态档会一路排下去、窄了就减,同一个表单在不同容器里列数不同 ⇒ **字段的相对位置会变**
14
+ * —— 要「两个字段必须并肩」就别用它。
21
15
  */
22
16
  export type FormColumns = 1 | 2 | 3 | 4 | 5 | 6 | 'auto';
23
17
  /**
24
- * 行内**垂直**对齐(label 与控件在控件行内怎么对齐):
25
- *
26
- * - `center`(默认):label 文字与控件**中线**对齐 —— 单行控件(输入框 / 选择器 / 开关)用它;
27
- * - `start`:label 与控件**首行文字**对齐 —— 多行控件(文本域)与整块内容用它,
28
- * 否则 label 会落到整块高度的中间。
29
- *
30
- * 不传即**自动判定**(样式按控件类型切档:文本域行零配置就是顶对齐);
31
- * 显式传入优先于自动判定,用于自绘内容(卡片组 / 表格 / 富文本这类样式认不出来的块)。
18
+ * 行内**垂直**对齐(label 与控件在控件行内怎么对齐):`center`(默认,与控件**中线**对齐,单行控件用);
19
+ * `start`(与控件**首行文字**对齐,多行控件与整块内容用,否则 label 会落到整块高度中间)。
20
+ * 不传即**自动判定**(样式按控件类型切档);显式传入优先,用于自绘内容(卡片组 / 表格 / 富文本)。
32
21
  */
33
22
  export type FormItemAlign = 'center' | 'start';
34
23
  /** 表单值:**字段名 → 值**(键就是 `Form.Item` 的 `name`) */
@@ -54,37 +43,27 @@ export interface FormProps {
54
43
  */
55
44
  labelAlign?: FormLabelAlign;
56
45
  /**
57
- * 表单级控件列宽上限(px);缺省**撑满**剩余宽度。
58
- *
59
- * 宽表单(>600px)里让输入框一路拉到右边缘很难看,两种收法二选一:
60
- * ① 收宽度 —— 传 `controlWidth={360}`,控件列封顶、右侧留白;
61
- * ② 分列 —— 传 `columns`(`2 | 3 | 4` 上限档,或 `'auto'` 动态),把行并排起来(见下)。
46
+ * 表单级控件列宽上限(px);缺省**撑满**剩余宽度。宽表单(>600px)里让输入框一路拉到右边缘很难看,
47
+ * 两种收法二选一:① 收宽度(`controlWidth={360}`,控件列封顶、右侧留白);② 分列(`columns`,见下)。
62
48
  */
63
49
  controlWidth?: number;
64
50
  /**
65
- * 列数:`1`(默认,逐行)/ `2 ~ 6`(**容器够宽才并排**,窄了按列最小宽度自动回落一列)/
66
- * `'auto'`(列数随容器宽度动态变化,取舍见 `FormColumns`)。
67
- *
68
- * 多列下每一行都要能独立成格,所以「整行内容」(说明行、卡片组、表格、文本域)记得
69
- * 在对应 `Form.Item` 上给 `fullWidth`,否则会被压成一格。
51
+ * 列数:`1`(默认,逐行)/ `2 ~ 6`(**容器够宽才并排**,窄了按列最小宽度自动回落一列)/ `'auto'`
52
+ * (列数随容器宽度动态变化,取舍见 `FormColumns`)。多列下「整行内容」(说明行 / 卡片组 / 表格 /
53
+ * 文本域)记得在对应 `Form.Item` 上给 `fullWidth`,否则会被压成一格。
70
54
  */
71
55
  columns?: FormColumns;
72
56
  /**
73
- * 一列的**最小宽度**(px);缺省取令牌 `--ui-form-column-min`(320 = 「label 120 + 一个还能用的
74
- * 输入框」的下限)。
75
- *
76
- * 它同时是**回落阈值**与**动态列数的除数**:数字档下容器窄于
77
- * `N × 最小宽 + (N − 1) × 行距` 就少排一列;动态档下列数 =
78
- * `floor((容器宽 + 行距) / (最小宽 + 行距))`。抽屉 / 弹窗里嫌字段太窄就调小(如 280),
79
- * 宽页面里嫌列太多就调大(如 380)。
57
+ * 一列的**最小宽度**(px);缺省取令牌 `--ui-form-column-min`(320 =「label 120 + 一个还能用的输入框」
58
+ * 的下限)。它同时是**回落阈值**与**动态列数的除数**:数字档下容器窄于
59
+ * `N × 最小宽 + (N − 1) × 行距` 就少排一列;动态档下列数 = `floor((容器宽 + 行距) / (最小宽 + 行距))`。
60
+ * 抽屉 / 弹窗里嫌字段太窄就调小(如 280),宽页面里嫌列太多就调大(如 380)。
80
61
  */
81
62
  columnMinWidth?: number;
82
63
  /**
83
64
  * 表单内距(**px 数字**,与 `Panel` 同一口径):`number` = 四边同值;`{ y, x }` = 上下 / 左右分别给。
84
- *
85
- * **缺省 0**:表单贴容器边,内距由所在容器给(页面里的表单在 `Panel.Body` 里,那块自带内距)。
86
- * 弹窗 / 抽屉里没有别的容器给内距时用它自带 —— 如 `padding={{ y: 16, x: 20 }}`,
87
- * 这样就不必再给表单挂一个「只写 padding」的应用侧类。
65
+ * **缺省 0**(表单贴容器边,内距由所在容器给);弹窗 / 抽屉里没有别的容器给内距时用它自带
66
+ * (如 `padding={{ y: 16, x: 20 }}`),这样就不必再挂一个「只写 padding」的应用侧类。
88
67
  */
89
68
  padding?: FormPadding;
90
69
  /** 行距(px,字段行之间 / 与 `Form.Header` 之间);缺省沿用样式里的 8px 档 */
@@ -180,85 +159,54 @@ export interface FormItemProps {
180
159
  /**
181
160
  * 表单行(**自建**):`label + 控件 + 错误 + 说明` 四件。
182
161
  *
183
- * 为什么不封装 farris 的 `FDynamicFormGroup`:那是动态表单(元数据驱动)体系里的分组件 ——
184
- * 控件要经 `editor` 描述对象交给它渲染,label 宽度 / 控件限宽由 farris 表单类写死
185
- * (inline 6rem 右对齐、字段 max-width 26.625rem),校验信息走**绝对定位的浮层提示条**。
186
- * 与本仓三条口径冲突:① 控件由消费方直接写(不构造底层配置对象);② 数据入参只收朴素业务值;
187
- * ③ 错误与说明按文档流排布(浮层在弹窗里会压住下一行的控件)。故按「缺件处置流程」自建,
188
- * 必填星号固定在 label 文本**之后**(`服务名称*`,有意偏离 farris 的「星号在左」);
189
- * **label 对齐是维度**(`labelAlign`,
190
- * 默认 `right`(与 farris / 主流水平表单一致),`left` 时所有 label 起点一致)。
162
+ * 为什么不封装 farris 的 `FDynamicFormGroup`:那是元数据驱动的动态表单分组件(控件经 `editor` 描述对象
163
+ * 渲染、label 宽度由 farris 表单类写死、校验信息走绝对定位的浮层提示条),与本仓三条口径冲突:控件由
164
+ * 消费方直接写、数据入参只收朴素业务值、错误与说明按文档流排布(浮层在弹窗里会压住下一行的控件)。故按
165
+ * 「缺件处置流程」自建;必填星号固定在 label 文本**之后**(`服务名称*`,有意偏离 farris 的「星号在左」);
166
+ * label 对齐是维度(`labelAlign`,默认 `right` 与主流水平表单一致,`left` 时所有 label 起点一致)。
191
167
  *
192
168
  * ## 宽表单怎么处理(两条杠杆,可叠加)
193
- *
194
169
  * - **限宽**:`controlWidth` 封顶控件列(表单级给默认、逐行可覆盖)—— 单列表单不至于把输入框拉成长条;
195
- * - **分列**:`columns` 让行并排,宽度用得更充分。档位见 `FormColumns`:
196
- * `2 ~ 6` 是**列数上限**(宽够就并排、窄了自动少排一列);`'auto'` 是**列数随宽度动态变化**。
197
- * 回落阈值与动态列数都由 `columnMinWidth`(缺省令牌 `--ui-form-column-min` = 320)决定,
198
- * **不需要消费方写媒体查询**;多列下「整块内容」记得 `fullWidth`。
170
+ * - **分列**:`columns` 让行并排(`2 ~ 6` 是**列数上限**,宽够才并排;`'auto'` 是列数随宽度动态变化)。
171
+ * 回落阈值与动态列数都由 `columnMinWidth`(缺省令牌 `--ui-form-column-min` = 320)决定,**不需要消费方
172
+ * 写媒体查询**;多列下「整块内容」记得 `fullWidth`。
199
173
  *
200
- * `Form.Item` 是唯一入口(`Form` 只承载表单级设置、行间距/列数与容器内距),
201
- * 控件从默认插槽进,因此输入框 / 下拉 / 文本域 / 自绘分组卡片共用同一个容器。
174
+ * `Form.Item` 是唯一入口(`Form` 只承载表单级设置、行间距 / 列数与容器内距),控件从默认插槽进。
202
175
  *
203
176
  * ## 行内垂直对齐(label 与控件怎么对齐)
204
- *
205
- * 对齐参照是**控件那一行**,不是整行:控件列与 label 同处第 1 行,错误 / 说明自然落第 2 行起 ——
206
- * 所以提示文案的有无与长短都不会带动 label 的位置。规则按控件形态自动切档,消费方零配置:
207
- *
208
- * - **单行控件**(输入框 / 选择器 / 开关 / 自绘单行内容):label 与控件**中线**对齐,**与控件高度无关**
209
- * —— 档位切 sm/md/lg、换主题、放自绘控件都自动成立;
210
- * - **多行与整块内容**(文本域这类样式认得出形态的):label 与控件**首行文字**对齐,不会落到整块中间;
211
- * - 样式认不出形态的自绘块(卡片组 / 表格 / 富文本)用 `align="start"` 显式声明;要强制居中用 `align="center"`。
212
- *
213
- * **本件不再依赖任何「控件高度」常量**:从前用一个外部注入的高度变量把 label 撑到控件高,
214
- * 而那个变量在骨架层没有任何出处(回退成 `auto`),于是 label 盒退化成一行文字并贴行顶 ——
215
- * 输入框中线偏高 6px、大号档偏高 10px、文本域偏高 9px,档位越高错得越多。
177
+ * 对齐参照是**控件那一行**,不是整行:控件列与 label 同处第 1 行、错误 / 说明自然落第 2 行起 —— 提示文案
178
+ * 的有无与长短都不会带动 label 的位置。规则按控件形态自动切档、消费方零配置:单行控件 → label 与控件
179
+ * **中线**对齐(**与控件高度无关**,切档 / 换主题 / 放自绘控件都成立);多行与整块内容(文本域这类样式
180
+ * 认得出形态的)→ **首行文字**对齐;样式认不出形态的自绘块(卡片组 / 表格 / 富文本)用 `align="start"`,
181
+ * 要强制居中用 `align="center"`。
182
+ * **本件不再依赖任何「控件高度」常量**:从前那个外部注入的高度变量在骨架层没有出处(回退成 `auto`),
183
+ * label 盒因此退化成一行文字并贴行顶 —— 档位越高错得越多。
216
184
  *
217
185
  * ## 容器内距(`padding`)
218
- *
219
- * 与 `Panel` **同一口径同一实现**(`src/components/part-padding.ts`):`number` 四边同值、
220
- * `{ y, x }` 上下 / 左右分别给,缺省 0(贴容器边)。页面里的表单在 `Panel.Body` 里、内距由那块给;
221
- * **弹窗 / 抽屉里没有别的容器**给内距,就用表单自带的 `padding={{ y: 16, x: 20 }}`。
186
+ * 与 `Panel` **同一口径同一实现**(`src/components/part-padding.ts`):`number` 四边同值、`{ y, x }` 分别
187
+ * 给,缺省 0(贴容器边)。页面里的表单在 `Panel.Body` 里、内距由那块给;**弹窗 / 抽屉里没有别的容器**
188
+ * 给内距,就用表单自带的 `padding={{ y: 16, x: 20 }}`。
222
189
  *
223
190
  * ## label 提示(`tip`)
224
- *
225
- * 字段名(与必填星号)之后挂一枚问号图标,悬停 / 键盘聚焦弹出说明气泡。它是**按需展开**的补充
226
- * 解释,不占版面;常驻说明仍归 `hint`(排在控件下方)。两者分工不同,也**不互相替代**。
227
- *
228
- * - 图标取 `@manohub/icon` 的 `help`(带圈问号),尺寸随主题图标档(`--ui-font-icon`);
229
- * - 图标**排在星号之后**(`服务名称*ⓘ`)—— 与「星号跟着字段名走」同一口径;
230
- * - 只给 `tip`(无 `label`、非必填)时**同样保留 label 列**(与「只给 required」同一判据),
231
- * 否则图标没有列可落、静默消失;
232
- * - 气泡用 `Tooltip` 的 **hover 档**(零 JS):不吃点击、不抢焦点;代价是 hover 档不进浏览器
233
- * 顶层浮层,会被祖先 `overflow` 裁切(弹窗 / 抽屉里贴着裁剪边的字段可能看不全)。
191
+ * 字段名(与必填星号)之后挂一枚问号图标,悬停 / 键盘聚焦弹出说明气泡 —— 按需展开的补充解释、不占版面;
192
+ * 常驻说明仍归 `hint`(排在控件下方),两者不互相替代。图标取 `help`(带圈问号)字形、尺寸随主题图标档、
193
+ * **排在星号之后**(`服务名称*ⓘ`);只给 `tip`(无 `label`、非必填)时**同样保留 label 列**,否则图标
194
+ * 没有列可落、静默消失。气泡用 `Tooltip` 的 **hover 档**(零 JS、不吃点击、不抢焦点),代价是 hover 档
195
+ * 不进浏览器顶层浮层,会被祖先 `overflow` 裁切(弹窗 / 抽屉里贴着裁剪边的字段可能看不全)。
234
196
  *
235
197
  * ## 键盘事件(`onKeydown` 转发到根节点)
236
- *
237
- * `onKeydown` 是本件的**声明式入口**(缺省不绑):传进来的处理器绑在根节点上 ——
238
- * 本件是 `inheritAttrs: false`,根节点只显式绑 `class` / `style`,不声明的监听器会被静默丢掉。
239
- * 根节点即「全部字段行的容器」,因此它是「字段区层面的委托」的落点:本包 `Filter` 的
240
- * 「字段区回车 = 查询」就搭在这里,构造 `Filter` 时**不必**再套一层只为挂事件的壳
241
- * (那会改变 `class` / `style` 的落点)。要不要拦、拦哪些按键由调用方自己判断,本件只转发。
242
- * **有意只开这一条**:其它监听器不转发,扩张要先当一次公开行为变更裁决。
198
+ * `onKeydown` 是本件的**声明式入口**(缺省不绑):本件是 `inheritAttrs: false`,根节点只显式绑
199
+ * `class` / `style`,不声明的监听器会被静默丢掉。根节点即「全部字段行的容器」,故它是「字段区层面的委托」
200
+ * 的落点 —— `Filter` 的「字段区回车 = 查询」就搭在这里,构造 `Filter` 时**不必**再套一层只为挂事件的壳
201
+ * (那会改变 `class` / `style` 的落点)。要不要拦、拦哪些按键由调用方判断,本件只转发;**有意只开这一条**,
202
+ * 其它监听器不转发,扩张要先当一次公开行为变更裁决。
243
203
  *
244
204
  * ## 只读值(摘要 / 详情)
245
- *
246
- * 「向导最后一步的确认摘要」「详情弹窗」不需要另起一套描述列表件 —— 只用表单行本身,
247
- * label 列宽、行距、错误与说明全部复用。控件位放**只读 + 无框**的输入框即可(本件不给
248
- * 「静态文本」形态:那套几何与输入框迟早会漂开 —— 从前它没有高度与内距,值文字既不在
249
- * 输入框那条竖线上、也不在同一条中线上):
250
- *
251
- * ```tsx
252
- * <Form.Item label="创建人" readonly>
253
- * <Input model-value={row.creator || '—'} readonly bordered={false} />
254
- * </Form.Item>
255
- * ```
256
- *
257
- * - **几何与可编辑行完全一致**:值文字与输入框内的值同高、同左缘、同中线,混排时节奏整齐;
258
- * - **没有「可编辑」的线索**:不显悬停底色、不给聚焦边框与主色环,但仍可点进去选中 / 复制;
259
- * - **空值占位归业务**:组件不再替你把 `''` 显示成 `—`,按上面的写法自己拼;
260
- * - **label 弱化**:传 `readonly` 把 label 降一档次要色,字段名与取值一眼分得开;
261
- * - 控件位是徽标 / 链接这类**非文本**只读内容时同样传 `readonly`:内容直接走默认插槽。
205
+ * 「向导最后一步的确认摘要」「详情弹窗」不需要另起一套描述列表件 —— 只用表单行本身(label 列宽 / 行距 /
206
+ * 错误与说明全部复用),控件位放**只读 + 无框**的输入框即可(本件不给「静态文本」形态:那套几何与输入框
207
+ * 迟早会漂开)。几何与可编辑行完全一致;没有「可编辑」的线索(不显悬停底色、不给聚焦框与主色环,仍可点
208
+ * 进去选中 / 复制);**空值占位归业务**(组件不替你把 `''` 显示成 `—`);传 `readonly` 把 label 降一档
209
+ * 次要色;控件位是徽标 / 链接这类**非文本**只读内容时同样传 `readonly`,内容直接走默认插槽。
262
210
  *
263
211
  * @example
264
212
  * <Form labelWidth={120} columns={2}>
@@ -57,11 +57,10 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
57
57
  default: string;
58
58
  };
59
59
  /**
60
- * 占位文案。两种形态都消费它:
61
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
62
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
63
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
64
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
60
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
61
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
62
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
63
+ * 的调用方行为不变。
65
64
  */
66
65
  placeholder: {
67
66
  type: StringConstructor;
@@ -82,11 +81,9 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
82
81
  default: boolean;
83
82
  };
84
83
  /**
85
- * **只读**:值可选中 / 复制,但不能改。
86
- *
87
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
88
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
89
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
84
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
85
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
86
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
90
87
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
91
88
  */
92
89
  readonly: {
@@ -184,11 +181,10 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
184
181
  default: string;
185
182
  };
186
183
  /**
187
- * 占位文案。两种形态都消费它:
188
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
189
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
190
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
191
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
184
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
185
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
186
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
187
+ * 的调用方行为不变。
192
188
  */
193
189
  placeholder: {
194
190
  type: StringConstructor;
@@ -209,11 +205,9 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
209
205
  default: boolean;
210
206
  };
211
207
  /**
212
- * **只读**:值可选中 / 复制,但不能改。
213
- *
214
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
215
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
216
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
208
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
209
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
210
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
217
211
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
218
212
  */
219
213
  readonly: {
@@ -524,11 +518,10 @@ export declare const InputCompound: {
524
518
  default: string;
525
519
  };
526
520
  /**
527
- * 占位文案。两种形态都消费它:
528
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
529
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
530
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
531
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
521
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
522
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
523
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
524
+ * 的调用方行为不变。
532
525
  */
533
526
  placeholder: {
534
527
  type: StringConstructor;
@@ -549,11 +542,9 @@ export declare const InputCompound: {
549
542
  default: boolean;
550
543
  };
551
544
  /**
552
- * **只读**:值可选中 / 复制,但不能改。
553
- *
554
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
555
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
556
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
545
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
546
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
547
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
557
548
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
558
549
  */
559
550
  readonly: {
@@ -685,11 +676,10 @@ export declare const InputCompound: {
685
676
  default: string;
686
677
  };
687
678
  /**
688
- * 占位文案。两种形态都消费它:
689
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
690
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
691
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
692
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
679
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
680
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
681
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
682
+ * 的调用方行为不变。
693
683
  */
694
684
  placeholder: {
695
685
  type: StringConstructor;
@@ -710,11 +700,9 @@ export declare const InputCompound: {
710
700
  default: boolean;
711
701
  };
712
702
  /**
713
- * **只读**:值可选中 / 复制,但不能改。
714
- *
715
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
716
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
717
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
703
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
704
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
705
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
718
706
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
719
707
  */
720
708
  readonly: {
@@ -837,11 +825,10 @@ export declare const InputCompound: {
837
825
  default: string;
838
826
  };
839
827
  /**
840
- * 占位文案。两种形态都消费它:
841
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
842
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
843
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
844
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
828
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
829
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
830
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
831
+ * 的调用方行为不变。
845
832
  */
846
833
  placeholder: {
847
834
  type: StringConstructor;
@@ -862,11 +849,9 @@ export declare const InputCompound: {
862
849
  default: boolean;
863
850
  };
864
851
  /**
865
- * **只读**:值可选中 / 复制,但不能改。
866
- *
867
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
868
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
869
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
852
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
853
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
854
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
870
855
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
871
856
  */
872
857
  readonly: {
@@ -16,11 +16,10 @@ const Input = /* @__PURE__ */ defineComponent({
16
16
  default: ""
17
17
  },
18
18
  /**
19
- * 占位文案。两种形态都消费它:
20
- * - 缺省(`as="input"`)走原生 `::placeholder` 伪元素;
21
- * - 触发器形态(`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载
22
- * (`.mh-input__placeholder`)—— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,
23
- * 并**取代** `default` 插槽(见上面触发器一节)。没传 `hasValue` 的调用方行为不变。
19
+ * 占位文案(两种形态都消费它):缺省(`as="input"`)走原生 `::placeholder` 伪元素;触发器形态
20
+ * (`as="button"`)**没有 `::placeholder` 可用**,改由一个 span 承载(`.mh-input__placeholder`)
21
+ * —— 当且仅当 `hasValue === false` 且本 prop 有值时渲染它,并**取代** `default` 插槽。没传 `hasValue`
22
+ * 的调用方行为不变。
24
23
  */
25
24
  placeholder: {
26
25
  type: String,
@@ -41,11 +40,9 @@ const Input = /* @__PURE__ */ defineComponent({
41
40
  default: false
42
41
  },
43
42
  /**
44
- * **只读**:值可选中 / 复制,但不能改。
45
- *
46
- * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
47
- * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
48
- * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
43
+ * **只读**:值可选中 / 复制,但不能改。与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显
44
+ * 业务值,也是 `Form.Item` 的 `readonly` 行推荐写法):几何与可编辑输入框**完全一致**(同高 / 同内距 /
45
+ * 值文字同左缘),但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
49
46
  * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
50
47
  */
51
48
  readonly: {
@@ -3,40 +3,33 @@ import { type Padding } from '../part-padding';
3
3
  /**
4
4
  * 页面骨架复合件 —— 页面结构与滚动归属的统一契约。
5
5
  *
6
- * 滚动契约写死在 `.mh-page*` 样式:Header / Filter / Footer 不滚;
7
- * Body 只管**页面级**滚动归属,只有两档:`mode="scroll"` 自身滚(长内容页)、
8
- * `mode="plain"`(默认)不滚 —— 滚动下沉到区域内容区或内容件自持的定高容器。
9
- * **表格不靠 Body 的 mode 表达**:外框由 `Table` 的 `framed` 档给,高度与滚动由
10
- * 承载它的内容件承担(`Panel.Body`,或表格件自带的定高容器)。
6
+ * 滚动契约写死在 `.mh-page*` 样式:Header / Filter / Footer 不滚;Body 只管**页面级**滚动归属,只有两档:
7
+ * `mode="scroll"` 自身滚(长内容页)、`mode="plain"`(默认)不滚(滚动下沉到区域内容区或内容件自持的定高
8
+ * 容器)。**表格不靠 Body 的 mode 表达**:外框由 `Table` 的 `framed` 档给,高度与滚动由承载它的内容件承担
9
+ * (`Panel.Body`,或表格件自带的定高容器)。
11
10
  *
12
- * **Split 不滚,栏内滚动由内容承担** —— 双栏内部用 `Panel`
13
- * (Header 固定 + Body `overflow:auto`)承载各自区域的滚动。
11
+ * **Split 不滚,栏内滚动由内容承担** —— 双栏内部用 `Panel`(Header 固定 + Body `overflow:auto`)承载各自
12
+ * 区域的滚动。
14
13
  *
15
- * 与 `Panel` 的分工:本件是**页面级**(唯一),管页头规格、页脚固定、页面级滚动归属;
16
- * `Panel` 是**区域级**(可多个),只管区域内的三件与区域内滚动。分页归属跟承载表格的容器走。
14
+ * 与 `Panel` 的分工:本件是**页面级**(唯一),管页头规格 / 页脚固定 / 页面级滚动归属;`Panel` 是**区域级**
15
+ * (可多个),只管区域内的三件与区域内滚动。分页归属跟承载表格的容器走。
17
16
  *
18
- * **侧栏能力(内建,缺省开启,无需消费方配置)**:
19
- * - 分隔线即拖拽手柄:按住左右拖即改宽,夹在 `minWidth`(缺省 160)与 `maxWidth`(缺省 480)之间;
20
- * - 手柄上悬停显形一个箭头按钮,点击收起侧栏;收起后页面边缘常驻 16px 展开把手,点击展开并恢复收起前的宽度
21
- * —— 展开按钮**占满整条把手**(全高全宽 + 描边 + 底),收起态里它是整块侧栏唯一看得见的东西;
22
- * - `width` 只是**初始宽度**:拖拽结果不持久化(刷新 / 重进回到初始宽度),收起也不清拖出的宽度;
23
- * - **宽度过渡期间内容不重排**:内容按展开时的宽度定宽(组件下发 `--mh-page-split-frozen`),
24
- * 多出的部分由容器裁掉 —— 栏内滚动容器不会因宽度被压缩而闪出滚动条;
25
- * - 左侧栏用 `sidebar`、右侧栏用 `rightSidebar`(互为镜像:分隔线在侧栏左侧、拖拽方向相反),
26
- * 两者可同时存在构成三栏;某侧传 `resizable: false` 时该侧不渲染手柄与把手。
17
+ * **侧栏能力(内建,缺省开启)**:分隔线即拖拽手柄(按住左右拖即改宽,夹在 `minWidth` 缺省 160 与
18
+ * `maxWidth` 缺省 480 之间);手柄悬停显形一个箭头按钮,点击收起侧栏,收起后页面边缘常驻 16px 展开把手
19
+ * (**占满整条把手**:全高全宽 + 描边 + 底),点击展开并恢复收起前的宽度;`width` 只是**初始宽度**(拖拽
20
+ * 结果不持久化,收起也不清拖出的宽度);**宽度过渡期间内容不重排**(内容按展开时的宽度定宽,组件下发
21
+ * `--mh-page-split-frozen`,多出的部分由容器裁掉,栏内滚动容器不会闪出滚动条);左侧栏 `sidebar`、右侧栏
22
+ * `rightSidebar`(互为镜像),两者可同时存在构成三栏,某侧传 `resizable: false` 则不渲染手柄与把手。
27
23
  *
28
- * 两级滚动归属(契约):
29
- * - `Page.Body.mode` 管**页面级**(scroll/plain,全页唯一);
30
- * - `Panel.Body` 管**区域内**(Header 固定 / 内容滚)。
24
+ * 两级滚动归属(契约):`Page.Body.mode` 管**页面级**(scroll / plain,全页唯一);`Panel.Body` 管**区域内**。
31
25
  *
32
- * **成员位置固定(归位)**:成员不按书写顺序渲染 —— 以本件为根,一律归到固定位置,
33
- * 于是「读代码的顺序」不必等于「视觉顺序」(页脚写最前面也仍在底部):
34
- * - **页面级行**:`Filter → Header → Body → Footer`(与 `Panel` 同款归位法);
35
- * - **主体区**:自由内容(含直接写在根下的 `Page.Split`)—— 没写显式 `Page.Body` 时
36
- * 自动包一层 `Page.Body`(缺省 `mode="plain"`),所以双栏可以只写 `Page.Split`。
26
+ * **成员位置固定(归位)**:成员不按书写顺序渲染 —— 以本件为根一律归到固定位置,故「读代码的顺序」不必
27
+ * 等于「视觉顺序」(页脚写最前面也仍在底部):页面级行 = `Filter → Header → Body → Footer`(与 `Panel`
28
+ * 同款归位法);主体区自由内容(含直接写在根下的 `Page.Split`)没写显式 `Page.Body` 时自动包一层
29
+ * (缺省 `mode="plain"`),所以双栏可以只写 `Page.Split`。
37
30
  *
38
- * 页头右侧的自由位(搜索框 / 按钮 / 等)是 `Page.Header` 的 `extra` 位(属性或插槽),
39
- * 没有独立的成员件:那个位置只有页头一个承载者,写成成员等于给它加一层没有意义的转发。
31
+ * 页头右侧的自由位(搜索框 / 按钮 / 等)是 `Page.Header` 的 `extra` 位(属性或插槽),**没有独立的成员件**:
32
+ * 那个位置只有页头一个承载者,写成成员等于给它加一层没有意义的转发。
40
33
  *
41
34
  * @example
42
35
  * // 模板 A:列表页(页头 + 表格 + 页脚分页)
@@ -22,17 +22,15 @@ import { type Padding } from '../part-padding';
22
22
  *
23
23
  * ## 分页归属(**跟承载表格的容器走**)
24
24
  *
25
- * 分页条不按「页面」决定位置,而按**表格所在容器**:
26
- * - 表格在 `Panel` 里(区域级列表)→ 放 `Panel.Footer`(面板内表 + 分页是一个整体,面板体滚动、分页常驻);
27
- * - 表格直接挂在 页面主体 下(页面级列表)→ 放 页面页脚。
28
- * 把区域列表的分页提到 页面页脚(或把页面级分页塞进面板)都属于错位。
25
+ * 分页条不按「页面」决定位置,而按**表格所在容器**:表格在 `Panel` 里(区域级列表)→ 放 `Panel.Footer`
26
+ * (面板内表 + 分页是一个整体,面板体滚动、分页常驻);表格直接挂在页面主体下(页面级列表)→ 放页面页脚。
27
+ * 把区域列表的分页提到页面页脚(或把页面级分页塞进面板)都属于错位。
29
28
  *
30
29
  * ## 无框契约
31
30
  *
32
- * `Panel` 自身**不加描边、不加圆角、不加阴影、不设独立底色、不加单侧边框** ——
33
- * 分区感只由 Header 下方的 1px 分隔线提供(与 `.mh-page__header` 同一手法);
34
- * 两栏之间的竖直分隔线由 `Page` 提供。
35
- * 需要卡片外观时由**内容件**承载(表格用 `表格.framed`),业务侧不得给面板补描边/圆角/阴影。
31
+ * `Panel` 自身**不加描边 / 圆角 / 阴影 / 独立底色 / 单侧边框** —— 分区感只由 Header 下方的 1px 分隔线提供
32
+ * (与 `.mh-page__header` 同一手法);两栏之间的竖直分隔线由 `Page` 提供。需要卡片外观时由**内容件**承载
33
+ * (表格用 `framed`),业务侧不得给面板补描边 / 圆角 / 阴影。
36
34
  *
37
35
  * ## 内距(`padding`)
38
36
  *
@@ -1,22 +1,19 @@
1
1
  import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
2
  import type { ControlSize } from '../control-size';
3
3
  /**
4
- * 单选族(一个文件三成员,对应面 `styles/components/radio.css` 的两段):
4
+ * 单选族(一个文件三成员,对应面 `styles/components/radio.css` 的两段):`Radio`(单个选项 —— 原生路径的
5
+ * 受控叶,`checked` 由使用方算)、`Radio.Group`(普通单选组 —— 一行一项,横排 16 / 纵排 12)、
6
+ * `Radio.Card`(卡片式单选组 —— 一个选项一张卡、整卡可点)。
5
7
  *
6
- * - `Radio`:单个选项(原生路径的受控叶,`checked` 由使用方算)
7
- * - `Radio.Group`:普通单选组 —— 一行一项,横排 16 / 纵排 12
8
- * - `Radio.Card`:卡片式单选组 —— 一个选项一张卡、整卡可点
8
+ * **判据**:选项只有一行文字 → `Radio.Group`;选项要「标题 + 说明」且整卡可点 → `Radio.Card`;要按钮形态的
9
+ * 分组 → `Capsule`(本族不重复造按钮档)。
9
10
  *
10
- * **判据**:选项只有一行文字 → `Radio.Group`;选项要「标题 + 说明」且整卡可点 → `Radio.Card`;
11
- * 要按钮形态的分组 → `Capsule`(本族不重复造按钮档)。
12
- *
13
- * **受控口径(族内统一)**:两个组都是「受控传 `modelValue`,不传即非受控(由 `defaultValue` 起)」,
14
- * 选中上报 `emit('update:modelValue')`(`v-model` 落地)+ `onChange` 双走 —— 与 `Capsule` /
15
- * `Checkbox.Group` 同一份口径,故 `v-model` 是本族的推荐写法。
16
- *
17
- * **单选组必须有值**:`modelValue` 与非受控初值都没给时,落到**第一个可选项**(跳过禁用项)——
18
- * 单选语义就是必选其一,与 `Tabs` 的「缺省第一项」同口径;没有可选项(表为空或全禁用)才是空值。
19
- * 自排插槽(`Radio.Group` 不给 `options`)时组件无从推断有哪些值,缺省值由消费方自定。
11
+ * **受控口径(族内统一)**:两个组都是「受控传 `modelValue`,不传即非受控(由 `defaultValue` 起)」,选中
12
+ * 上报 `emit('update:modelValue')` + `onChange` 双走 —— 与 `Capsule` / `Checkbox.Group` 同一份口径,故
13
+ * `v-model` 是本族的推荐写法。
14
+ * **单选组必须有值**:`modelValue` 与非受控初值都没给时落到**第一个可选项**(跳过禁用项)—— 单选语义就是
15
+ * 必选其一,与 `Tabs` 的「缺省第一项」同口径;没有可选项(表为空或全禁用)才是空值。自排插槽
16
+ * (`Radio.Group` 不给 `options`)时组件无从推断有哪些值,缺省值由消费方自定。
20
17
  *
21
18
  * 状态表达不统一是**有意的**(各自贴着自己的面):`Radio` 走原生 `input:checked + .mh-radio__box`
22
19
  * (故 **input 必须紧邻框体之前**),`Radio.Card` 走卡片上的 `data-state`(卡片就是 label,圆点在卡内)。