@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.
Files changed (75) hide show
  1. package/README.md +4 -4
  2. package/dist/components/button/index.d.ts +14 -8
  3. package/dist/components/capsule/index.d.ts +13 -9
  4. package/dist/components/capsule/index.js +1 -1
  5. package/dist/components/card/index.d.ts +1 -1
  6. package/dist/components/card/index.js +7 -4
  7. package/dist/components/checkbox/index.js +1 -0
  8. package/dist/components/dialog/index.d.ts +1 -1
  9. package/dist/components/form/index.d.ts +142 -62
  10. package/dist/components/form/index.js +41 -29
  11. package/dist/components/input/index.d.ts +74 -6
  12. package/dist/components/input/index.js +13 -1
  13. package/dist/components/layout/index.d.ts +43 -1
  14. package/dist/components/layout/index.js +22 -2
  15. package/dist/components/list-view/index.d.ts +1 -1
  16. package/dist/components/notice/index.d.ts +2 -2
  17. package/dist/components/notification/index.d.ts +2 -2
  18. package/dist/components/page/index.js +4 -4
  19. package/dist/components/pagination/index.d.ts +2 -2
  20. package/dist/components/pagination/index.js +1 -1
  21. package/dist/components/panel/index.js +4 -4
  22. package/dist/components/part-padding.d.ts +9 -6
  23. package/dist/components/part-padding.js +2 -1
  24. package/dist/components/query-state/index.d.ts +18 -2
  25. package/dist/components/radio/index.d.ts +1 -1
  26. package/dist/components/radio/index.js +1 -0
  27. package/dist/components/select/index.d.ts +32 -30
  28. package/dist/components/select/index.js +46 -82
  29. package/dist/components/select/select-list.d.ts +125 -0
  30. package/dist/components/select/select-list.js +95 -0
  31. package/dist/components/select/select-panel.d.ts +106 -0
  32. package/dist/components/select/select-panel.js +72 -0
  33. package/dist/components/select/select-shared.d.ts +64 -0
  34. package/dist/components/select/select-shared.js +24 -0
  35. package/dist/components/select/select-tree-filter.d.ts +61 -0
  36. package/dist/components/select/select-tree-filter.js +63 -0
  37. package/dist/components/select/select-tree.d.ts +274 -0
  38. package/dist/components/select/select-tree.js +263 -0
  39. package/dist/components/select/select-trigger.d.ts +132 -0
  40. package/dist/components/select/select-trigger.js +101 -0
  41. package/dist/components/steps/index.d.ts +232 -6
  42. package/dist/components/steps/index.js +84 -26
  43. package/dist/components/switch/index.d.ts +29 -5
  44. package/dist/components/switch/index.js +8 -2
  45. package/dist/components/tabbar/index.d.ts +184 -0
  46. package/dist/components/tabbar/index.js +161 -0
  47. package/dist/components/table/index.d.ts +99 -12
  48. package/dist/components/table/index.js +69 -16
  49. package/dist/components/tabs/index.d.ts +142 -126
  50. package/dist/components/tabs/index.js +87 -119
  51. package/dist/components/tag/index.d.ts +2 -2
  52. package/dist/components/text/index.d.ts +7 -2
  53. package/dist/components/toast/index.d.ts +8 -8
  54. package/dist/components/tree/index.d.ts +28 -2
  55. package/dist/components/tree/index.js +14 -1
  56. package/dist/index.d.ts +6 -6
  57. package/dist/index.js +6 -3
  58. package/dist/styles/components/capsule.css +4 -4
  59. package/dist/styles/components/form.css +198 -39
  60. package/dist/styles/components/input.css +53 -1
  61. package/dist/styles/components/layout.css +2 -0
  62. package/dist/styles/components/select.css +21 -0
  63. package/dist/styles/components/select.tokens.css +3 -0
  64. package/dist/styles/components/steps.css +48 -0
  65. package/dist/styles/components/{tabs.css → tabbar.css} +66 -65
  66. package/dist/styles/components/tabbar.tokens.css +30 -0
  67. package/dist/styles/components/table.css +50 -1
  68. package/dist/styles/components/table.tokens.css +3 -0
  69. package/dist/styles/index.css +3 -3
  70. package/dist/styles/operations/tabs.css +73 -0
  71. package/package.json +2 -2
  72. package/dist/components/tabset/index.d.ts +0 -109
  73. package/dist/components/tabset/index.js +0 -75
  74. package/dist/styles/components/tabs.tokens.css +0 -30
  75. package/dist/styles/operations/tabset.css +0 -57
@@ -68,6 +68,14 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
68
68
  type: BooleanConstructor;
69
69
  default: boolean;
70
70
  };
71
+ /**
72
+ * **只读**:值可选中 / 复制,但不能改。
73
+ *
74
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
75
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
76
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
77
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
78
+ */
71
79
  readonly: {
72
80
  type: BooleanConstructor;
73
81
  default: boolean;
@@ -87,7 +95,10 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
87
95
  type: BooleanConstructor;
88
96
  default: boolean;
89
97
  };
90
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
98
+ /**
99
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
100
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
101
+ */
91
102
  bordered: {
92
103
  type: BooleanConstructor;
93
104
  default: boolean;
@@ -167,6 +178,14 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
167
178
  type: BooleanConstructor;
168
179
  default: boolean;
169
180
  };
181
+ /**
182
+ * **只读**:值可选中 / 复制,但不能改。
183
+ *
184
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
185
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
186
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
187
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
188
+ */
170
189
  readonly: {
171
190
  type: BooleanConstructor;
172
191
  default: boolean;
@@ -186,7 +205,10 @@ export declare const Input: import("vue").DefineComponent<import("vue").ExtractP
186
205
  type: BooleanConstructor;
187
206
  default: boolean;
188
207
  };
189
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
208
+ /**
209
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
210
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
211
+ */
190
212
  bordered: {
191
213
  type: BooleanConstructor;
192
214
  default: boolean;
@@ -276,6 +298,7 @@ export interface TextareaProps {
276
298
  /** 尺寸档 */
277
299
  size?: ControlSize;
278
300
  disabled?: boolean;
301
+ /** 只读(配 `bordered={false}` 即只读值档,口径见 `Input` 的同名 prop) */
279
302
  readonly?: boolean;
280
303
  /** 校验态(下发 `aria-invalid`) */
281
304
  invalid?: boolean;
@@ -289,7 +312,15 @@ export interface TextareaProps {
289
312
  autofocus?: boolean;
290
313
  onChange?: (v: string) => void;
291
314
  }
292
- /** 多行输入(同一份面;结构与单行不同,故单列一个件) */
315
+ /**
316
+ * 多行输入(同一份面;结构与单行不同,故单列一个件)。
317
+ *
318
+ * ⚠️ 本件**没有** `mono` 档(`Input` 有)。要等宽的输入框别拿 `Text mono` 去包 —— 那会丢掉输入能力;
319
+ * 该写法目前只能保留一条带 `font-family: var(--ui-font-mono)` 的应用侧样式登记(缺口见包内 `docs/kit-gaps.md`)。
320
+ *
321
+ * @example 备注框:自适应 2~6 行 + 限长计数
322
+ * <Textarea modelValue={note} autoSize={{ minRows: 2, maxRows: 6 }} maxlength={500} showCount onChange={setNote} />
323
+ */
293
324
  export declare const Textarea: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
294
325
  modelValue: {
295
326
  type: StringConstructor;
@@ -319,6 +350,7 @@ export declare const Textarea: import("vue").DefineComponent<import("vue").Extra
319
350
  type: BooleanConstructor;
320
351
  default: boolean;
321
352
  };
353
+ /** 只读:值可选中 / 复制;配 `bordered={false}` 即只读值档(口径见 `Input` 的同名 prop) */
322
354
  readonly: {
323
355
  type: BooleanConstructor;
324
356
  default: boolean;
@@ -382,6 +414,7 @@ export declare const Textarea: import("vue").DefineComponent<import("vue").Extra
382
414
  type: BooleanConstructor;
383
415
  default: boolean;
384
416
  };
417
+ /** 只读:值可选中 / 复制;配 `bordered={false}` 即只读值档(口径见 `Input` 的同名 prop) */
385
418
  readonly: {
386
419
  type: BooleanConstructor;
387
420
  default: boolean;
@@ -463,6 +496,14 @@ export declare const InputCompound: {
463
496
  type: BooleanConstructor;
464
497
  default: boolean;
465
498
  };
499
+ /**
500
+ * **只读**:值可选中 / 复制,但不能改。
501
+ *
502
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
503
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
504
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
505
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
506
+ */
466
507
  readonly: {
467
508
  type: BooleanConstructor;
468
509
  default: boolean;
@@ -482,7 +523,10 @@ export declare const InputCompound: {
482
523
  type: BooleanConstructor;
483
524
  default: boolean;
484
525
  };
485
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
526
+ /**
527
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
528
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
529
+ */
486
530
  bordered: {
487
531
  type: BooleanConstructor;
488
532
  default: boolean;
@@ -596,6 +640,14 @@ export declare const InputCompound: {
596
640
  type: BooleanConstructor;
597
641
  default: boolean;
598
642
  };
643
+ /**
644
+ * **只读**:值可选中 / 复制,但不能改。
645
+ *
646
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
647
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
648
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
649
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
650
+ */
599
651
  readonly: {
600
652
  type: BooleanConstructor;
601
653
  default: boolean;
@@ -615,7 +667,10 @@ export declare const InputCompound: {
615
667
  type: BooleanConstructor;
616
668
  default: boolean;
617
669
  };
618
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
670
+ /**
671
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
672
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
673
+ */
619
674
  bordered: {
620
675
  type: BooleanConstructor;
621
676
  default: boolean;
@@ -720,6 +775,14 @@ export declare const InputCompound: {
720
775
  type: BooleanConstructor;
721
776
  default: boolean;
722
777
  };
778
+ /**
779
+ * **只读**:值可选中 / 复制,但不能改。
780
+ *
781
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
782
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
783
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
784
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
785
+ */
723
786
  readonly: {
724
787
  type: BooleanConstructor;
725
788
  default: boolean;
@@ -739,7 +802,10 @@ export declare const InputCompound: {
739
802
  type: BooleanConstructor;
740
803
  default: boolean;
741
804
  };
742
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
805
+ /**
806
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
807
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
808
+ */
743
809
  bordered: {
744
810
  type: BooleanConstructor;
745
811
  default: boolean;
@@ -847,6 +913,7 @@ export declare const InputCompound: {
847
913
  type: BooleanConstructor;
848
914
  default: boolean;
849
915
  };
916
+ /** 只读:值可选中 / 复制;配 `bordered={false}` 即只读值档(口径见 `Input` 的同名 prop) */
850
917
  readonly: {
851
918
  type: BooleanConstructor;
852
919
  default: boolean;
@@ -910,6 +977,7 @@ export declare const InputCompound: {
910
977
  type: BooleanConstructor;
911
978
  default: boolean;
912
979
  };
980
+ /** 只读:值可选中 / 复制;配 `bordered={false}` 即只读值档(口径见 `Input` 的同名 prop) */
913
981
  readonly: {
914
982
  type: BooleanConstructor;
915
983
  default: boolean;
@@ -32,6 +32,14 @@ const Input = /* @__PURE__ */ defineComponent({
32
32
  type: Boolean,
33
33
  default: false
34
34
  },
35
+ /**
36
+ * **只读**:值可选中 / 复制,但不能改。
37
+ *
38
+ * 与 `bordered={false}` 组合即**只读值档**(摘要 / 详情里回显业务值,也是 `Form.Item`
39
+ * 的 `readonly` 行推荐的写法):几何与可编辑输入框**完全一致**(同高、同内距、值文字同左缘),
40
+ * 但滑过不亮浅底、聚焦不给边框与主色环 —— 一眼看去是「值」而不是「输入位」。
41
+ * 只读 ≠ 禁用:它照旧可聚焦、可选中复制,也不变灰。
42
+ */
35
43
  readonly: {
36
44
  type: Boolean,
37
45
  default: false
@@ -51,7 +59,10 @@ const Input = /* @__PURE__ */ defineComponent({
51
59
  type: Boolean,
52
60
  default: false
53
61
  },
54
- /** 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底) */
62
+ /**
63
+ * 是否带边框;`false` 用于表格内编辑 / 行内编辑(无框、无底,靠悬停与聚焦给反馈)。
64
+ * 配 `readonly` 即**只读值档**:连悬停底与聚焦框环都退掉(见 `readonly`)。
65
+ */
55
66
  bordered: {
56
67
  type: Boolean,
57
68
  default: true
@@ -225,6 +236,7 @@ const Textarea = /* @__PURE__ */ defineComponent({
225
236
  type: Boolean,
226
237
  default: false
227
238
  },
239
+ /** 只读:值可选中 / 复制;配 `bordered={false}` 即只读值档(口径见 `Input` 的同名 prop) */
228
240
  readonly: {
229
241
  type: Boolean,
230
242
  default: false
@@ -1,4 +1,5 @@
1
1
  import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
+ import { type Padding } from '../part-padding';
2
3
  /**
3
4
  * 布局间距档:**只开放令牌档位,不开放任意 px**(`none/sm/md/lg/xl` → `0 / --ui-space-1/2/3/4`)。
4
5
  *
@@ -32,7 +33,8 @@ export type LayoutSpan = 1 | 2 | 3 | 4;
32
33
  *
33
34
  * ## 与其它件的边界
34
35
  *
35
- * - 表单里并排字段用 `Form columns={2}`(它管 label 列与行距),不要用本族拼表单;
36
+ * - 表单里并排字段用 `Form` 的 `columns`(它管 label 列、行距与**回落**),不要用本族拼表单
37
+ * —— 本族的列数是**恒定**的,窄了只等分收窄,表单会被压出不可用的窄控件;
36
38
  * - 页面级两栏(各自滚动)用 `Page.Split`;
37
39
  * - 只有「块与块怎么摆」这一件事归本族,滚动 / 工具位 / 卡片外观都不归它。
38
40
  */
@@ -63,6 +65,20 @@ export declare const Layout: {
63
65
  type: NumberConstructor;
64
66
  default: undefined;
65
67
  };
68
+ /**
69
+ * 内距:**走骨架件共享口径**(`Padding`,同 `Card` / `Form` / `Page` / `Panel`)——
70
+ * `number` 四边同值、`{ y, x }` 分上下 / 左右、`string` 原样下发(CSS 简写,**逃生舱**)。
71
+ * 口径与理由见 `part-padding.ts`。
72
+ *
73
+ * ⚠️ 与 `gap` 不同口径:`gap` 只开放令牌档(防间距分叉),`padding` 接具体值 ——
74
+ * 内距在设计稿里常是**确定坐标**,令牌梯度(最大 24px)表达不了。
75
+ * ⚠️ 用它之前先想一次:这个数真是「内距」吗?若是「与某个内容列对齐」这类**布局坐标**,
76
+ * 优先改由结构表达(同轴容器 / `columns` / `minColumnWidth`)。
77
+ */
78
+ padding: {
79
+ type: PropType<Padding>;
80
+ default: undefined;
81
+ };
66
82
  }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
67
83
  /** 行间距档(默认 `md` 8px;要贴紧写 `none`) */
68
84
  gap: {
@@ -89,7 +105,22 @@ export declare const Layout: {
89
105
  type: NumberConstructor;
90
106
  default: undefined;
91
107
  };
108
+ /**
109
+ * 内距:**走骨架件共享口径**(`Padding`,同 `Card` / `Form` / `Page` / `Panel`)——
110
+ * `number` 四边同值、`{ y, x }` 分上下 / 左右、`string` 原样下发(CSS 简写,**逃生舱**)。
111
+ * 口径与理由见 `part-padding.ts`。
112
+ *
113
+ * ⚠️ 与 `gap` 不同口径:`gap` 只开放令牌档(防间距分叉),`padding` 接具体值 ——
114
+ * 内距在设计稿里常是**确定坐标**,令牌梯度(最大 24px)表达不了。
115
+ * ⚠️ 用它之前先想一次:这个数真是「内距」吗?若是「与某个内容列对齐」这类**布局坐标**,
116
+ * 优先改由结构表达(同轴容器 / `columns` / `minColumnWidth`)。
117
+ */
118
+ padding: {
119
+ type: PropType<Padding>;
120
+ default: undefined;
121
+ };
92
122
  }>> & Readonly<{}>, {
123
+ padding: Padding;
93
124
  justify: LayoutJustify;
94
125
  gap: LayoutGap;
95
126
  align: LayoutAlign;
@@ -124,6 +155,11 @@ export declare const Layout: {
124
155
  type: PropType<LayoutSpan>;
125
156
  default: number;
126
157
  };
158
+ /** 内距:口径同 `Layout.Row`(共享 `Padding`,复用 `mergePartStyle`) */
159
+ padding: {
160
+ type: PropType<Padding>;
161
+ default: undefined;
162
+ };
127
163
  }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
128
164
  /** 单元内间距档(默认 `md` 8px;要贴紧写 `none`) */
129
165
  gap: {
@@ -150,7 +186,13 @@ export declare const Layout: {
150
186
  type: PropType<LayoutSpan>;
151
187
  default: number;
152
188
  };
189
+ /** 内距:口径同 `Layout.Row`(共享 `Padding`,复用 `mergePartStyle`) */
190
+ padding: {
191
+ type: PropType<Padding>;
192
+ default: undefined;
193
+ };
153
194
  }>> & Readonly<{}>, {
195
+ padding: Padding;
154
196
  wrap: boolean;
155
197
  justify: LayoutJustify;
156
198
  span: LayoutSpan;
@@ -1,4 +1,5 @@
1
1
  import { defineComponent, createVNode } from "vue";
2
+ import { mergePartStyle } from "../part-padding.js";
2
3
  function modifier(base, name, value) {
3
4
  return value === void 0 || value === "" ? "" : `${base}--${name}-${value}`;
4
5
  }
@@ -30,6 +31,11 @@ const LayoutColumn = /* @__PURE__ */ defineComponent({
30
31
  span: {
31
32
  type: Number,
32
33
  default: 1
34
+ },
35
+ /** 内距:口径同 `Layout.Row`(共享 `Padding`,复用 `mergePartStyle`) */
36
+ padding: {
37
+ type: [Number, Object, String],
38
+ default: void 0
33
39
  }
34
40
  },
35
41
  slots: Object,
@@ -39,7 +45,7 @@ const LayoutColumn = /* @__PURE__ */ defineComponent({
39
45
  }) {
40
46
  return () => createVNode("div", {
41
47
  "class": ["mh-layout-column", modifier("mh-layout-column", "gap", props.gap), modifier("mh-layout-column", "align", props.align), props.justify && props.justify !== "start" ? modifier("mh-layout-column", "justify", props.justify) : "", props.wrap ? "mh-layout-column--wrap" : "", props.span > 1 ? `mh-layout-column--span-${props.span}` : "", attrs.class].filter(Boolean).join(" "),
42
- "style": attrs.style
48
+ "style": mergePartStyle(attrs.style, props.padding)
43
49
  }, [slots.default?.()]);
44
50
  }
45
51
  });
@@ -71,6 +77,20 @@ const LayoutRow = /* @__PURE__ */ defineComponent({
71
77
  minColumnWidth: {
72
78
  type: Number,
73
79
  default: void 0
80
+ },
81
+ /**
82
+ * 内距:**走骨架件共享口径**(`Padding`,同 `Card` / `Form` / `Page` / `Panel`)——
83
+ * `number` 四边同值、`{ y, x }` 分上下 / 左右、`string` 原样下发(CSS 简写,**逃生舱**)。
84
+ * 口径与理由见 `part-padding.ts`。
85
+ *
86
+ * ⚠️ 与 `gap` 不同口径:`gap` 只开放令牌档(防间距分叉),`padding` 接具体值 ——
87
+ * 内距在设计稿里常是**确定坐标**,令牌梯度(最大 24px)表达不了。
88
+ * ⚠️ 用它之前先想一次:这个数真是「内距」吗?若是「与某个内容列对齐」这类**布局坐标**,
89
+ * 优先改由结构表达(同轴容器 / `columns` / `minColumnWidth`)。
90
+ */
91
+ padding: {
92
+ type: [Number, Object, String],
93
+ default: void 0
74
94
  }
75
95
  },
76
96
  slots: Object,
@@ -86,7 +106,7 @@ const LayoutRow = /* @__PURE__ */ defineComponent({
86
106
  if (props.minColumnWidth) style["--mh-layout-row-min"] = `${props.minColumnWidth}px`;
87
107
  return createVNode("div", {
88
108
  "class": ["mh-layout-row", modifier("mh-layout-row", "gap", props.gap), modifier("mh-layout-row", "align", props.align), props.justify && props.justify !== "start" ? modifier("mh-layout-row", "justify", props.justify) : "", isGrid ? "mh-layout-row--grid" : "", isGrid ? modifier("mh-layout-row", "columns", props.columns) : "", attrs.class].filter(Boolean).join(" "),
89
- "style": style
109
+ "style": mergePartStyle(style, props.padding)
90
110
  }, [slots.default?.()]);
91
111
  };
92
112
  }
@@ -84,7 +84,7 @@ export interface ListViewProps {
84
84
  *
85
85
  * 以 `Card interactive` 为壳,卡片外观与悬浮反馈都来自它;本件只管卡片**内部**的排版与几何
86
86
  * (最小高 144、图标 36、标题 16/600、描述两行截断、尾部贴底、胶囊与标签片),
87
- * 几何来源同 `Card`(portal 技能市场卡片实测)。
87
+ * 几何来源同 `Card`(技能市场卡片实测)。
88
88
  *
89
89
  * 三处「有意为之」:
90
90
  * 1. **操作位默认隐藏**(`opacity: 0`),卡片悬浮或卡内获得焦点时显形;触屏(无 hover 能力)恒显形 ——
@@ -136,11 +136,11 @@ export declare const Notice: import("vue").DefineComponent<import("vue").Extract
136
136
  default: undefined;
137
137
  };
138
138
  }>> & Readonly<{}>, {
139
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
139
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
140
140
  onClose: () => void;
141
141
  message: string;
142
- tone: NoticeTone;
143
142
  closable: boolean;
143
+ tone: NoticeTone;
144
144
  description: string;
145
145
  action: string;
146
146
  closeText: string;
@@ -102,11 +102,11 @@ export declare const Notification: import("vue").DefineComponent<import("vue").E
102
102
  default: undefined;
103
103
  };
104
104
  }>> & Readonly<{}>, {
105
- icon: boolean | "filter" | "copy" | "help" | "table" | "menu" | "search" | "link" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
105
+ icon: boolean | "search" | "link" | "filter" | "copy" | "help" | "table" | "menu" | "delete" | "image" | "close" | "key" | "page-title" | "loading" | "info" | "alert" | "chevron-left" | "chevron-right" | "chevron-down" | "chevron-up" | "check" | "user" | "download" | "back" | "folder" | "folder-open" | "file" | "file-code" | "file-json" | "file-text" | "terminal" | "shield" | "tool" | "plus" | "notification" | "settings" | "logout" | "home" | "workbench" | "apps" | "favorite" | "favorite-filled" | "drag-handle" | "edit" | "refresh" | "upload" | "save" | "more" | "preview" | "external-link" | "minus" | "plus-circle" | "close-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
106
106
  title: string;
107
107
  onClose: () => void;
108
- tone: NotificationTone;
109
108
  closable: boolean;
109
+ tone: NotificationTone;
110
110
  avatar: string;
111
111
  duration: number;
112
112
  }, SlotsType<{
@@ -12,7 +12,7 @@ const PageFilter = /* @__PURE__ */ defineComponent({
12
12
  props: {
13
13
  /** 内距(px 数字 = 四边同值;`{ y, x }` 分别给);缺省不落行内样式,沿用 CSS 默认(`14px 20px 0`) */
14
14
  padding: {
15
- type: [Number, Object],
15
+ type: [Number, Object, String],
16
16
  default: void 0
17
17
  }
18
18
  },
@@ -49,7 +49,7 @@ const PageHeader = /* @__PURE__ */ defineComponent({
49
49
  },
50
50
  /** 内距(px 数字 = 四边同值;`{ y, x }` 分别给);缺省不落行内样式,沿用 CSS 默认(`14px 20px 13px`) */
51
51
  padding: {
52
- type: [Number, Object],
52
+ type: [Number, Object, String],
53
53
  default: void 0
54
54
  }
55
55
  },
@@ -107,7 +107,7 @@ const PageBody = /* @__PURE__ */ defineComponent({
107
107
  default: "plain"
108
108
  },
109
109
  padding: {
110
- type: [Number, Object],
110
+ type: [Number, Object, String],
111
111
  default: void 0
112
112
  }
113
113
  },
@@ -128,7 +128,7 @@ const PageFooter = /* @__PURE__ */ defineComponent({
128
128
  props: {
129
129
  /** 内距(px 数字 = 四边同值;`{ y, x }` 分别给);缺省不落行内样式,沿用 CSS 默认(`12px 20px`) */
130
130
  padding: {
131
- type: [Number, Object],
131
+ type: [Number, Object, String],
132
132
  default: void 0
133
133
  }
134
134
  },
@@ -34,7 +34,7 @@ export declare const Pagination: import("vue").DefineComponent<import("vue").Ext
34
34
  type: NumberConstructor;
35
35
  default: number;
36
36
  };
37
- /** 当前页(**1 起**) */
37
+ /** 当前页(**1 起**;接口用 0 基的话在调用方 ±1 换算,别把 0 基值直接接进来) */
38
38
  modelValue: {
39
39
  type: NumberConstructor;
40
40
  default: number;
@@ -96,7 +96,7 @@ export declare const Pagination: import("vue").DefineComponent<import("vue").Ext
96
96
  type: NumberConstructor;
97
97
  default: number;
98
98
  };
99
- /** 当前页(**1 起**) */
99
+ /** 当前页(**1 起**;接口用 0 基的话在调用方 ±1 换算,别把 0 基值直接接进来) */
100
100
  modelValue: {
101
101
  type: NumberConstructor;
102
102
  default: number;
@@ -9,7 +9,7 @@ const Pagination = /* @__PURE__ */ defineComponent({
9
9
  type: Number,
10
10
  default: 0
11
11
  },
12
- /** 当前页(**1 起**) */
12
+ /** 当前页(**1 起**;接口用 0 基的话在调用方 ±1 换算,别把 0 基值直接接进来) */
13
13
  modelValue: {
14
14
  type: Number,
15
15
  default: 1
@@ -24,7 +24,7 @@ const PanelHeader = /* @__PURE__ */ defineComponent({
24
24
  },
25
25
  /** 头这一行的内距(与根件同一口径);内建头自带 `0 8px` 的内距,本项按需覆盖 */
26
26
  padding: {
27
- type: [Number, Object],
27
+ type: [Number, Object, String],
28
28
  default: void 0
29
29
  }
30
30
  },
@@ -70,7 +70,7 @@ const PanelBody = /* @__PURE__ */ defineComponent({
70
70
  props: {
71
71
  /** 内容区内距(与根件同一口径);缺省 0 = 内容贴面板边(页面里的区域通常如此) */
72
72
  padding: {
73
- type: [Number, Object],
73
+ type: [Number, Object, String],
74
74
  default: void 0
75
75
  }
76
76
  },
@@ -91,7 +91,7 @@ const PanelFooter = /* @__PURE__ */ defineComponent({
91
91
  props: {
92
92
  /** 页脚内距(与根件同一口径);缺省 0 = 贴面板边 */
93
93
  padding: {
94
- type: [Number, Object],
94
+ type: [Number, Object, String],
95
95
  default: void 0
96
96
  }
97
97
  },
@@ -145,7 +145,7 @@ const PanelRoot = /* @__PURE__ */ defineComponent({
145
145
  },
146
146
  /** 面板内距(px 数字,或 `{ y, x }`);缺省 0 = 贴容器边 */
147
147
  padding: {
148
- type: [Number, Object],
148
+ type: [Number, Object, String],
149
149
  default: void 0
150
150
  }
151
151
  },
@@ -1,20 +1,23 @@
1
1
  import type { StyleValue } from 'vue';
2
2
  /**
3
- * 骨架件的**内距**口径(`Panel` 及其三件、`Form` 共用同一套)。
3
+ * 骨架件的**内距**口径(`Card` / `Form` / `Page` / `Panel` / `Layout` 共用同一套)。
4
4
  *
5
5
  * - `number` → 四边同值(`padding={16}`);
6
6
  * - `{ y, x }` → 上下 / 左右分别给(`{ y: 12, x: 20 }`,弹窗里的容器常用 —— 与 `Page` 的页面左右内距同档),
7
- * **缺哪边就不落哪边的声明**(只给 `y` 时不覆盖消费方在 `style` 里写的左右内距)。
7
+ * **缺哪边就不落哪边的声明**(只给 `y` 时不覆盖消费方在 `style` 里写的左右内距);
8
+ * - `string` → **原样下发**(CSS 简写,可非对称,如 `'40px 0 0 140px'`)—— **逃生舱**。
8
9
  *
9
- * 为什么是 px 数字而不是 CSS 字符串:几何值在本仓是**设计基准**,不跟根字号
10
- * (与 `Form.labelWidth` / `表格.rowHeight` 同口径);要写自适应内距的场合请走 `class`。
10
+ * 常规用 `number` / `{ y, x }`:几何值在本仓是**设计基准**,不跟根字号
11
+ * (与 `Form.labelWidth` / `表格.rowHeight` 同口径)。
12
+ * `string` 只为「令牌梯度与 `{ y, x }` 都表达不了的设计要求」留口(典型:**只给一侧**的非对称坐标)——
13
+ * 写它等于自己写 CSS,所以**优先级最低**,能不用就不用。
11
14
  */
12
15
  export type Padding = number | {
13
16
  y?: number;
14
17
  x?: number;
15
- };
18
+ } | string;
16
19
  /**
17
- * 内距 → 行内样式。缺省(`undefined`)时返回 `undefined`:**不额外产生 style 属性**,
20
+ * 内距 → 行内样式。缺省(`undefined` / 空串)时返回 `undefined`:**不额外产生 style 属性**,
18
21
  * DOM 与「没有这个维度」时完全一致。
19
22
  */
20
23
  export declare function partPaddingStyle(padding: Padding | undefined): StyleValue | undefined;
@@ -1,6 +1,7 @@
1
1
  function partPaddingStyle(padding) {
2
- if (padding === void 0) return void 0;
2
+ if (padding === void 0 || padding === "") return void 0;
3
3
  if (typeof padding === "number") return { padding: `${padding}px` };
4
+ if (typeof padding === "string") return { padding };
4
5
  const style = {};
5
6
  if (padding.y !== void 0) {
6
7
  style.paddingTop = `${padding.y}px`;
@@ -45,13 +45,29 @@ export interface QueryStateProps {
45
45
  *
46
46
  * 文案 props 可覆盖(i18n 由消费方传 t() 结果;本包不内置文案)。
47
47
  *
48
- * @example 空态带 CTA、错误态带重试
48
+ * ## 两个容易拿不准的点
49
+ *
50
+ * - `empty` 是**触发位**,不是「文案 prop」:`true` 触发并用默认文案;给字符串则**既触发、
51
+ * 又当空态标题**(副文案仍走 `emptyDescription`);
52
+ * - **本件不自带数据源**:`loading` / `error` / `empty` 都由调用方按自己的请求结果给。
53
+ * `Table` 自带加载与空两态却**没有错误态** —— 要么只把 error 交给本件,要么整块三态由本件在外层表达:
54
+ *
55
+ * @example 列表页:三态在外层,表格只管数据(经典写法)
56
+ * <QueryState
57
+ * loading={isLoading}
58
+ * error={loadError}
59
+ * :empty="rows.length === 0"
60
+ * :error-action-text="t('common.retry')"
61
+ * onErrorAction={() => refetch()}>
62
+ * <Table :columns="columns" :data="rows" row-key="id" />
63
+ * </QueryState>
64
+ *
65
+ * @example 三态齐备(空态带 CTA、错误态带重试)
49
66
  * <QueryState
50
67
  * loading={isLoading}
51
68
  * error={loadError.value}
52
69
  * errorActionText={t('common.retry')}
53
70
  * onErrorAction={() => reload()}
54
- * empty={topics.length === 0}
55
71
  * empty={t('topic.empty')}
56
72
  * emptyDescription={t('topic.emptyDescription')}
57
73
  * emptyActionText={t('topic.create')}
@@ -15,7 +15,7 @@ import type { ControlSize } from '../control-size';
15
15
  * `Checkbox.Group` 同一份口径,故 `v-model` 是本族的推荐写法。
16
16
  *
17
17
  * **单选组必须有值**:`modelValue` 与非受控初值都没给时,落到**第一个可选项**(跳过禁用项)——
18
- * 单选语义就是必选其一,与 `Tabset` 的「缺省第一项」同口径;没有可选项(表为空或全禁用)才是空值。
18
+ * 单选语义就是必选其一,与 `Tabs` 的「缺省第一项」同口径;没有可选项(表为空或全禁用)才是空值。
19
19
  * 自排插槽(`Radio.Group` 不给 `options`)时组件无从推断有哪些值,缺省值由消费方自定。
20
20
  *
21
21
  * 状态表达不统一是**有意的**(各自贴着自己的面):`Radio` 走原生 `input:checked + .mh-radio__box`
@@ -44,6 +44,7 @@ const Radio = /* @__PURE__ */ defineComponent({
44
44
  }) {
45
45
  return () => createVNode("label", {
46
46
  "class": ["mh-radio", props.size === "md" ? "" : `mh-radio--${props.size}`, props.disabled ? "is-disabled" : void 0, attrs.class].filter(Boolean).join(" "),
47
+ "data-inline-control": "true",
47
48
  "style": attrs.style
48
49
  }, [createVNode("input", {
49
50
  "class": "mh-radio__input",