@manohub/ui 0.6.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 (169) hide show
  1. package/README.md +141 -0
  2. package/dist/components/avatar/index.d.ts +283 -0
  3. package/dist/components/avatar/index.js +167 -0
  4. package/dist/components/badge/index.d.ts +132 -0
  5. package/dist/components/badge/index.js +99 -0
  6. package/dist/components/button/index.d.ts +578 -0
  7. package/dist/components/button/index.js +191 -0
  8. package/dist/components/capsule/index.d.ts +161 -0
  9. package/dist/components/capsule/index.js +101 -0
  10. package/dist/components/card/index.d.ts +456 -0
  11. package/dist/components/card/index.js +231 -0
  12. package/dist/components/checkbox/index.d.ts +331 -0
  13. package/dist/components/checkbox/index.js +165 -0
  14. package/dist/components/code/index.d.ts +134 -0
  15. package/dist/components/code/index.js +117 -0
  16. package/dist/components/code-editor/index.d.ts +163 -0
  17. package/dist/components/code-editor/index.js +98 -0
  18. package/dist/components/collapse/index.d.ts +125 -0
  19. package/dist/components/collapse/index.js +95 -0
  20. package/dist/components/control-size.d.ts +8 -0
  21. package/dist/components/dialog/index.d.ts +224 -0
  22. package/dist/components/dialog/index.js +194 -0
  23. package/dist/components/divider/index.d.ts +64 -0
  24. package/dist/components/divider/index.js +62 -0
  25. package/dist/components/drawer/index.d.ts +226 -0
  26. package/dist/components/drawer/index.js +190 -0
  27. package/dist/components/filter/index.d.ts +391 -0
  28. package/dist/components/filter/index.js +203 -0
  29. package/dist/components/form/index.d.ts +704 -0
  30. package/dist/components/form/index.js +329 -0
  31. package/dist/components/input/index.d.ts +980 -0
  32. package/dist/components/input/index.js +334 -0
  33. package/dist/components/layout/index.d.ts +162 -0
  34. package/dist/components/layout/index.js +100 -0
  35. package/dist/components/list-view/index.d.ts +563 -0
  36. package/dist/components/list-view/index.js +221 -0
  37. package/dist/components/loading/index.d.ts +77 -0
  38. package/dist/components/loading/index.js +40 -0
  39. package/dist/components/nav/index.d.ts +293 -0
  40. package/dist/components/nav/index.js +164 -0
  41. package/dist/components/notice/index.d.ts +137 -0
  42. package/dist/components/notice/index.js +101 -0
  43. package/dist/components/notification/index.d.ts +118 -0
  44. package/dist/components/notification/index.js +99 -0
  45. package/dist/components/page/index.d.ts +276 -0
  46. package/dist/components/page/index.js +351 -0
  47. package/dist/components/page/split-resize.d.ts +42 -0
  48. package/dist/components/page/split-resize.js +36 -0
  49. package/dist/components/pagination/index.d.ts +171 -0
  50. package/dist/components/pagination/index.js +226 -0
  51. package/dist/components/panel/index.d.ts +401 -0
  52. package/dist/components/panel/index.js +193 -0
  53. package/dist/components/part-padding.d.ts +27 -0
  54. package/dist/components/part-padding.js +23 -0
  55. package/dist/components/query-state/index.d.ts +207 -0
  56. package/dist/components/query-state/index.js +181 -0
  57. package/dist/components/radio/index.d.ts +473 -0
  58. package/dist/components/radio/index.js +250 -0
  59. package/dist/components/search/index.d.ts +167 -0
  60. package/dist/components/search/index.js +105 -0
  61. package/dist/components/select/index.d.ts +252 -0
  62. package/dist/components/select/index.js +281 -0
  63. package/dist/components/skeleton/index.d.ts +88 -0
  64. package/dist/components/skeleton/index.js +56 -0
  65. package/dist/components/steps/index.d.ts +199 -0
  66. package/dist/components/steps/index.js +117 -0
  67. package/dist/components/switch/index.d.ts +150 -0
  68. package/dist/components/switch/index.js +103 -0
  69. package/dist/components/table/index.d.ts +351 -0
  70. package/dist/components/table/index.js +286 -0
  71. package/dist/components/tabs/index.d.ts +179 -0
  72. package/dist/components/tabs/index.js +153 -0
  73. package/dist/components/tabset/index.d.ts +105 -0
  74. package/dist/components/tabset/index.js +68 -0
  75. package/dist/components/tag/index.d.ts +203 -0
  76. package/dist/components/tag/index.js +144 -0
  77. package/dist/components/toast/index.d.ts +271 -0
  78. package/dist/components/toast/index.js +116 -0
  79. package/dist/components/tooltip/index.d.ts +126 -0
  80. package/dist/components/tooltip/index.js +97 -0
  81. package/dist/components/tree/index.d.ts +317 -0
  82. package/dist/components/tree/index.js +251 -0
  83. package/dist/components/upload/index.d.ts +384 -0
  84. package/dist/components/upload/index.js +172 -0
  85. package/dist/index.d.ts +63 -0
  86. package/dist/index.js +102 -0
  87. package/dist/services/base.d.ts +21 -0
  88. package/dist/services/base.js +42 -0
  89. package/dist/services/dialog.d.ts +41 -0
  90. package/dist/services/dialog.js +83 -0
  91. package/dist/services/index.d.ts +12 -0
  92. package/dist/services/loading.d.ts +21 -0
  93. package/dist/services/loading.js +41 -0
  94. package/dist/services/toast.d.ts +40 -0
  95. package/dist/services/toast.js +74 -0
  96. package/dist/styles/components/avatar.css +128 -0
  97. package/dist/styles/components/avatar.tokens.css +24 -0
  98. package/dist/styles/components/badge.css +237 -0
  99. package/dist/styles/components/button.css +454 -0
  100. package/dist/styles/components/button.tokens.css +56 -0
  101. package/dist/styles/components/capsule.css +120 -0
  102. package/dist/styles/components/capsule.tokens.css +27 -0
  103. package/dist/styles/components/card.css +192 -0
  104. package/dist/styles/components/checkbox.css +145 -0
  105. package/dist/styles/components/checkbox.tokens.css +26 -0
  106. package/dist/styles/components/code-editor.css +91 -0
  107. package/dist/styles/components/code-editor.tokens.css +24 -0
  108. package/dist/styles/components/code.css +153 -0
  109. package/dist/styles/components/code.tokens.css +29 -0
  110. package/dist/styles/components/collapse.css +62 -0
  111. package/dist/styles/components/collapse.tokens.css +20 -0
  112. package/dist/styles/components/dialog.css +106 -0
  113. package/dist/styles/components/dialog.tokens.css +24 -0
  114. package/dist/styles/components/divider.css +71 -0
  115. package/dist/styles/components/divider.tokens.css +21 -0
  116. package/dist/styles/components/drawer.css +143 -0
  117. package/dist/styles/components/drawer.tokens.css +22 -0
  118. package/dist/styles/components/filter.css +41 -0
  119. package/dist/styles/components/filter.tokens.css +14 -0
  120. package/dist/styles/components/form.css +220 -0
  121. package/dist/styles/components/form.tokens.css +15 -0
  122. package/dist/styles/components/input.css +445 -0
  123. package/dist/styles/components/input.tokens.css +41 -0
  124. package/dist/styles/components/layout.css +198 -0
  125. package/dist/styles/components/list-view.css +244 -0
  126. package/dist/styles/components/loading.css +76 -0
  127. package/dist/styles/components/loading.tokens.css +23 -0
  128. package/dist/styles/components/nav.css +48 -0
  129. package/dist/styles/components/notice.css +153 -0
  130. package/dist/styles/components/notice.tokens.css +17 -0
  131. package/dist/styles/components/notification.css +159 -0
  132. package/dist/styles/components/notification.tokens.css +37 -0
  133. package/dist/styles/components/page.css +473 -0
  134. package/dist/styles/components/pagination.css +297 -0
  135. package/dist/styles/components/pagination.tokens.css +32 -0
  136. package/dist/styles/components/panel.css +77 -0
  137. package/dist/styles/components/query-state.css +88 -0
  138. package/dist/styles/components/radio.css +271 -0
  139. package/dist/styles/components/radio.tokens.css +26 -0
  140. package/dist/styles/components/search.css +30 -0
  141. package/dist/styles/components/select.css +242 -0
  142. package/dist/styles/components/select.tokens.css +33 -0
  143. package/dist/styles/components/skeleton.css +60 -0
  144. package/dist/styles/components/skeleton.tokens.css +27 -0
  145. package/dist/styles/components/steps.css +157 -0
  146. package/dist/styles/components/steps.tokens.css +42 -0
  147. package/dist/styles/components/switch.css +165 -0
  148. package/dist/styles/components/switch.tokens.css +26 -0
  149. package/dist/styles/components/table.css +439 -0
  150. package/dist/styles/components/table.tokens.css +41 -0
  151. package/dist/styles/components/tabs.css +234 -0
  152. package/dist/styles/components/tabs.tokens.css +30 -0
  153. package/dist/styles/components/tag.css +200 -0
  154. package/dist/styles/components/tag.tokens.css +30 -0
  155. package/dist/styles/components/toast.css +150 -0
  156. package/dist/styles/components/toast.tokens.css +26 -0
  157. package/dist/styles/components/tooltip.css +89 -0
  158. package/dist/styles/components/tooltip.tokens.css +25 -0
  159. package/dist/styles/components/tree.css +139 -0
  160. package/dist/styles/components/tree.tokens.css +20 -0
  161. package/dist/styles/components/upload.css +150 -0
  162. package/dist/styles/components/upload.tokens.css +27 -0
  163. package/dist/styles/index.css +149 -0
  164. package/dist/styles/operations/collapse.css +84 -0
  165. package/dist/styles/operations/popup.css +189 -0
  166. package/dist/styles/operations/tabset.css +57 -0
  167. package/dist/utils/state-illustration.d.ts +31 -0
  168. package/dist/utils/state-illustration.js +156 -0
  169. package/package.json +62 -0
@@ -0,0 +1,456 @@
1
+ import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
+ import type { Padding } from '../part-padding';
3
+ /** 描边档:`outline`(默认,弱描边)/ `plain`(无描边,靠容器底色区分) */
4
+ export type CardVariant = 'outline' | 'plain';
5
+ /** 卡片内距:与 `Panel` / `Form` 共用一套口径(`number` = 四边同值;`{ y, x }` 分别给) */
6
+ export type CardPadding = Padding;
7
+ /** 头部图标:图片地址(渲染 `<img>`、按方框自裁)或返回节点的函数(图标一律来自 `@manohub/icon`) */
8
+ export type CardHeaderIcon = string | (() => VNodeChild);
9
+ /**
10
+ * 卡片容器:**卡片外观的唯一实现**(底 / 弱描边 / 圆角 / 内距 / 悬浮与选中反馈)。
11
+ *
12
+ * 消费方(含 `ListView.CardItem`)不得再自绘卡片外观(描边 / 圆角 / 阴影 / 底色),
13
+ * 也不得在应用侧写这四类属性 —— 需要不同形态就用本件的维度(`variant` / `interactive` /
14
+ * `selected` / `disabled`),或提为骨架层待建件。
15
+ *
16
+ * ## 几何来源(portal 技能市场卡片实测,逐项落 `--ui-*` 令牌)
17
+ *
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`)
21
+ *
22
+ * 列表卡片项那套几何(最小高 144、状态胶囊、标签片…)属 `ListView.CardItem`,**不在本件** ——
23
+ * 通用卡片不该被一条「只在列表里成立」的最小高绑住(**头部四件两处一致**,见下)。
24
+ *
25
+ * ## Header 区域(四件;`Card.Header` 是完整入口,`Card` 上的同名 props 是它的简写)
26
+ *
27
+ * ```
28
+ * ┌───────────────────────────────────────────────┐
29
+ * │ [图标] 标题 extra(右端) │
30
+ * │ 副标题 │
31
+ * └───────────────────────────────────────────────┘
32
+ * ```
33
+ *
34
+ * - **左侧区域**(`__header-main`)= 图标(`icon`)+ 文字块(`title` / `subtitle` 上下两行)
35
+ * + `Card.Header` 默认插槽的自排内容;
36
+ * - **右侧** = `extra` 插槽(状态胶囊 / 行内按钮 / 统计);
37
+ * - 四个位**一个都没给**时退化为**纯自排容器**:默认插槽内容原样进头容器(DOM 与没有这些位时一致)。
38
+ *
39
+ * 四个位两处入口完全等价:
40
+ * `<Card title="…" subtitle="…" icon="…">` ≡ `<Card.Header title="…" subtitle="…" icon="…" />`。
41
+ *
42
+ * 几何:图标 36×36(与 `ListView.CardItem` 同一档)、圆角取控件档 6;标题 16/600 单行省略;
43
+ * 副标题 12 + 弱字色,同样单行省略。
44
+ *
45
+ * ## 内距:**全部由段承载,根件不出内距;相邻两段之间只有一份**
46
+ *
47
+ * 根件只出面(底 / 描边 / 圆角),既不出内距也不出段间距;内距一律吃在**段**上:
48
+ * `Card.Header` / `Body` / `Footer`(分件)与 `Card` 内建头 / 操作行默认各吃 `--mh-card-padding`(20px)。
49
+ *
50
+ * 纵向的分配是「**每段只吃上边**」:一段只负责**与自己上方之间的距离**(下一段的上内距就是段间距),
51
+ * 卡片的**下沿由最后一段补**(面上 `:last-child` 那条规则)——
52
+ * 所以 header + body、body + footer 相邻时都不会叠成两份(20 + 20),卡片首末两端又各有一份完整内距。
53
+ *
54
+ * 要收紧某一段给那一段传 `padding`(px 数字或 `{ y, x }`,**缺哪边不覆盖哪边**:
55
+ * 这里的 `y` 就是该段的段间距,横向照 `x`);要整卡统一就改令牌 `--mh-card-padding`。
56
+ *
57
+ * 直接写内容(`<Card>正文</Card>`)时,**裸子节点会被自动包进一层 `Card.Body`**(与 `Panel` 的简写路径同款),
58
+ * 所以它与显式写 `<Card><Card.Body>正文</Card.Body></Card>` 得到同一份内距。
59
+ *
60
+ * ## 三件(`Card.Header` / `Body` / `Footer`)
61
+ *
62
+ * 分件只有内距这一个维度:**不给就走 CSS 默认值**(不额外产生行内 `style`,DOM 与没有该维度时一致)。
63
+ * 分件的 `padding` 语义同上(纵向只表达段间距;下边由末段补)。
64
+ *
65
+ * ## 底部操作行(`actions` 插槽)
66
+ *
67
+ * `margin-top: auto` 贴卡片底部,卡片被拉伸(网格等高)时才有差别;内距与段同口径。
68
+ *
69
+ * ## 为什么不是 `<button>`
70
+ *
71
+ * 卡片里常驻操作按钮(编辑 / 删除等),整卡换成按钮会产生嵌套可交互元素;键盘可达性由卡内控件承担。
72
+ * 「整卡可点」由 `interactive`(光标 + 悬浮反馈)+ `onClick` 表达,与原型一致。
73
+ *
74
+ * @example 技能卡(图标 + 标题/副标题 + 右端状态 + 正文 + 操作行)
75
+ * <Card>
76
+ * <Card.Header icon={skill.icon} title={skill.name} subtitle={`V${skill.version}`}>
77
+ * <template #extra><Tag shape="status" tone="success">已发布</Tag></template>
78
+ * </Card.Header>
79
+ * <Card.Body>{skill.description}</Card.Body>
80
+ * <template #actions><Button size="sm">编辑</Button></template>
81
+ * </Card>
82
+ */
83
+ export interface CardProps {
84
+ /**
85
+ * 描边档:`outline`(默认)弱描边 `--ui-base-300`;`plain` 无描边。
86
+ * 底 / 圆角 / 阴影不随档位变化 —— 卡片外观在本件只有一处定义。
87
+ */
88
+ variant?: CardVariant;
89
+ /** 悬浮反馈:hover 描边转主色 + 主色 12% 阴影,并显示 `cursor: pointer` */
90
+ interactive?: boolean;
91
+ /** 选中态(主色描边 + 主色弱底);只表达「已选中」,不表达单选逻辑 */
92
+ selected?: boolean;
93
+ /** 禁用态(半透明 + `not-allowed`;不转发 `onClick`) */
94
+ disabled?: boolean;
95
+ /** Header 简写:图标(图片地址,或返回节点的函数 —— 如 `() => <Icon name="skill" />`) */
96
+ icon?: CardHeaderIcon;
97
+ /** Header 简写:标题(单行省略;节点形态走 `title` 插槽) */
98
+ title?: string;
99
+ /** Header 简写:副标题(标题下方第二行,弱字色单行省略) */
100
+ subtitle?: string;
101
+ /** 整卡点击(打开详情 / 抽屉)。卡片是**容器**不是按钮:卡内操作位需自行 `stopPropagation`(见 `ListView.CardItem`) */
102
+ onClick?: (e: MouseEvent) => void;
103
+ }
104
+ /**
105
+ * 卡片头部:**四件**(图标 / 标题 / 副标题 + 右端 `extra`)。
106
+ *
107
+ * 四个位都可由属性给;`icon` / `title` / `subtitle` / `extra` 也都可走同名插槽(**插槽优先**)。
108
+ * 一个位都不给时退化为自排容器:默认插槽内容原样进头容器(`Card.Header` 也仍然是「自己排头」的逃生口)。
109
+ */
110
+ export declare const CardHeader: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
111
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
112
+ padding: {
113
+ type: PropType<CardPadding>;
114
+ default: undefined;
115
+ };
116
+ /** 图标:图片地址或返回节点的函数(图标一律来自 `@manohub/icon`) */
117
+ icon: {
118
+ type: PropType<CardHeaderIcon>;
119
+ default: undefined;
120
+ };
121
+ /** 标题(单行省略);要节点化标题时走 `title` 插槽 */
122
+ title: {
123
+ type: StringConstructor;
124
+ default: undefined;
125
+ };
126
+ /** 副标题(标题下方第二行,弱字色单行省略) */
127
+ subtitle: {
128
+ type: StringConstructor;
129
+ default: undefined;
130
+ };
131
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
132
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
133
+ padding: {
134
+ type: PropType<CardPadding>;
135
+ default: undefined;
136
+ };
137
+ /** 图标:图片地址或返回节点的函数(图标一律来自 `@manohub/icon`) */
138
+ icon: {
139
+ type: PropType<CardHeaderIcon>;
140
+ default: undefined;
141
+ };
142
+ /** 标题(单行省略);要节点化标题时走 `title` 插槽 */
143
+ title: {
144
+ type: StringConstructor;
145
+ default: undefined;
146
+ };
147
+ /** 副标题(标题下方第二行,弱字色单行省略) */
148
+ subtitle: {
149
+ type: StringConstructor;
150
+ default: undefined;
151
+ };
152
+ }>> & Readonly<{}>, {
153
+ padding: Padding;
154
+ icon: CardHeaderIcon;
155
+ title: string;
156
+ subtitle: string;
157
+ }, SlotsType<{
158
+ default?: () => VNodeChild;
159
+ icon?: () => VNodeChild;
160
+ title?: () => VNodeChild;
161
+ subtitle?: () => VNodeChild;
162
+ extra?: () => VNodeChild;
163
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
164
+ /** 卡片内容区:撑满剩余高度(卡片被拉伸时才有差别),本身不滚动 —— 滚动归属由所在容器决定 */
165
+ export declare const CardBody: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
166
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
167
+ padding: {
168
+ type: PropType<CardPadding>;
169
+ default: undefined;
170
+ };
171
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
172
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
173
+ padding: {
174
+ type: PropType<CardPadding>;
175
+ default: undefined;
176
+ };
177
+ }>> & Readonly<{}>, {
178
+ padding: Padding;
179
+ }, SlotsType<{
180
+ default?: () => VNodeChild;
181
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
182
+ /** 卡片尾部:贴卡片底部(`margin-top: auto`),承载标签 / 统计 / 操作位 */
183
+ export declare const CardFooter: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
184
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
185
+ padding: {
186
+ type: PropType<CardPadding>;
187
+ default: undefined;
188
+ };
189
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
190
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
191
+ padding: {
192
+ type: PropType<CardPadding>;
193
+ default: undefined;
194
+ };
195
+ }>> & Readonly<{}>, {
196
+ padding: Padding;
197
+ }, SlotsType<{
198
+ default?: () => VNodeChild;
199
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
200
+ /**
201
+ * 复合件入口:`Card` + `Card.Header` / `Card.Body` / `Card.Footer`
202
+ * (与 `Panel` 同款 `Object.assign` 复合写法;成员不平级导出)
203
+ */
204
+ export declare const Card: {
205
+ new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
206
+ variant: {
207
+ type: PropType<CardVariant>;
208
+ default: string;
209
+ };
210
+ interactive: {
211
+ type: BooleanConstructor;
212
+ default: boolean;
213
+ };
214
+ selected: {
215
+ type: BooleanConstructor;
216
+ default: boolean;
217
+ };
218
+ disabled: {
219
+ type: BooleanConstructor;
220
+ default: boolean;
221
+ };
222
+ icon: {
223
+ type: PropType<CardHeaderIcon>;
224
+ default: undefined;
225
+ };
226
+ title: {
227
+ type: StringConstructor;
228
+ default: undefined;
229
+ };
230
+ subtitle: {
231
+ type: StringConstructor;
232
+ default: undefined;
233
+ };
234
+ onClick: {
235
+ type: PropType<(e: MouseEvent) => void>;
236
+ default: undefined;
237
+ };
238
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
239
+ icon: CardHeaderIcon;
240
+ disabled: boolean;
241
+ title: string;
242
+ onClick: (e: MouseEvent) => void;
243
+ subtitle: string;
244
+ variant: CardVariant;
245
+ interactive: boolean;
246
+ selected: boolean;
247
+ }, true, {}, SlotsType<{
248
+ default?: () => VNodeChild;
249
+ /** 图标的节点形态(替代 `icon` 属性;插槽优先于属性) */
250
+ icon?: () => VNodeChild;
251
+ /** 标题的节点形态(替代 `title` 属性) */
252
+ title?: () => VNodeChild;
253
+ /** 副标题的节点形态(替代 `subtitle` 属性) */
254
+ subtitle?: () => VNodeChild;
255
+ /** 右端(状态胶囊 / 行内按钮 / 统计) */
256
+ extra?: () => VNodeChild;
257
+ /** 底部操作行 */
258
+ actions?: () => VNodeChild;
259
+ }>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
260
+ P: {};
261
+ B: {};
262
+ D: {};
263
+ C: {};
264
+ M: {};
265
+ Defaults: {};
266
+ }, Readonly<import("vue").ExtractPropTypes<{
267
+ variant: {
268
+ type: PropType<CardVariant>;
269
+ default: string;
270
+ };
271
+ interactive: {
272
+ type: BooleanConstructor;
273
+ default: boolean;
274
+ };
275
+ selected: {
276
+ type: BooleanConstructor;
277
+ default: boolean;
278
+ };
279
+ disabled: {
280
+ type: BooleanConstructor;
281
+ default: boolean;
282
+ };
283
+ icon: {
284
+ type: PropType<CardHeaderIcon>;
285
+ default: undefined;
286
+ };
287
+ title: {
288
+ type: StringConstructor;
289
+ default: undefined;
290
+ };
291
+ subtitle: {
292
+ type: StringConstructor;
293
+ default: undefined;
294
+ };
295
+ onClick: {
296
+ type: PropType<(e: MouseEvent) => void>;
297
+ default: undefined;
298
+ };
299
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, {
300
+ icon: CardHeaderIcon;
301
+ disabled: boolean;
302
+ title: string;
303
+ onClick: (e: MouseEvent) => void;
304
+ subtitle: string;
305
+ variant: CardVariant;
306
+ interactive: boolean;
307
+ selected: boolean;
308
+ }>;
309
+ __isFragment?: never;
310
+ __isTeleport?: never;
311
+ __isSuspense?: never;
312
+ } & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
313
+ variant: {
314
+ type: PropType<CardVariant>;
315
+ default: string;
316
+ };
317
+ interactive: {
318
+ type: BooleanConstructor;
319
+ default: boolean;
320
+ };
321
+ selected: {
322
+ type: BooleanConstructor;
323
+ default: boolean;
324
+ };
325
+ disabled: {
326
+ type: BooleanConstructor;
327
+ default: boolean;
328
+ };
329
+ icon: {
330
+ type: PropType<CardHeaderIcon>;
331
+ default: undefined;
332
+ };
333
+ title: {
334
+ type: StringConstructor;
335
+ default: undefined;
336
+ };
337
+ subtitle: {
338
+ type: StringConstructor;
339
+ default: undefined;
340
+ };
341
+ onClick: {
342
+ type: PropType<(e: MouseEvent) => void>;
343
+ default: undefined;
344
+ };
345
+ }>> & Readonly<{}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
346
+ icon: CardHeaderIcon;
347
+ disabled: boolean;
348
+ title: string;
349
+ onClick: (e: MouseEvent) => void;
350
+ subtitle: string;
351
+ variant: CardVariant;
352
+ interactive: boolean;
353
+ selected: boolean;
354
+ }, {}, string, SlotsType<{
355
+ default?: () => VNodeChild;
356
+ /** 图标的节点形态(替代 `icon` 属性;插槽优先于属性) */
357
+ icon?: () => VNodeChild;
358
+ /** 标题的节点形态(替代 `title` 属性) */
359
+ title?: () => VNodeChild;
360
+ /** 副标题的节点形态(替代 `subtitle` 属性) */
361
+ subtitle?: () => VNodeChild;
362
+ /** 右端(状态胶囊 / 行内按钮 / 统计) */
363
+ extra?: () => VNodeChild;
364
+ /** 底部操作行 */
365
+ actions?: () => VNodeChild;
366
+ }>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & {
367
+ Header: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
368
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
369
+ padding: {
370
+ type: PropType<CardPadding>;
371
+ default: undefined;
372
+ };
373
+ /** 图标:图片地址或返回节点的函数(图标一律来自 `@manohub/icon`) */
374
+ icon: {
375
+ type: PropType<CardHeaderIcon>;
376
+ default: undefined;
377
+ };
378
+ /** 标题(单行省略);要节点化标题时走 `title` 插槽 */
379
+ title: {
380
+ type: StringConstructor;
381
+ default: undefined;
382
+ };
383
+ /** 副标题(标题下方第二行,弱字色单行省略) */
384
+ subtitle: {
385
+ type: StringConstructor;
386
+ default: undefined;
387
+ };
388
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
389
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
390
+ padding: {
391
+ type: PropType<CardPadding>;
392
+ default: undefined;
393
+ };
394
+ /** 图标:图片地址或返回节点的函数(图标一律来自 `@manohub/icon`) */
395
+ icon: {
396
+ type: PropType<CardHeaderIcon>;
397
+ default: undefined;
398
+ };
399
+ /** 标题(单行省略);要节点化标题时走 `title` 插槽 */
400
+ title: {
401
+ type: StringConstructor;
402
+ default: undefined;
403
+ };
404
+ /** 副标题(标题下方第二行,弱字色单行省略) */
405
+ subtitle: {
406
+ type: StringConstructor;
407
+ default: undefined;
408
+ };
409
+ }>> & Readonly<{}>, {
410
+ padding: Padding;
411
+ icon: CardHeaderIcon;
412
+ title: string;
413
+ subtitle: string;
414
+ }, SlotsType<{
415
+ default?: () => VNodeChild;
416
+ icon?: () => VNodeChild;
417
+ title?: () => VNodeChild;
418
+ subtitle?: () => VNodeChild;
419
+ extra?: () => VNodeChild;
420
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
421
+ Body: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
422
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
423
+ padding: {
424
+ type: PropType<CardPadding>;
425
+ default: undefined;
426
+ };
427
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
428
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
429
+ padding: {
430
+ type: PropType<CardPadding>;
431
+ default: undefined;
432
+ };
433
+ }>> & Readonly<{}>, {
434
+ padding: Padding;
435
+ }, SlotsType<{
436
+ default?: () => VNodeChild;
437
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
438
+ Footer: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
439
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
440
+ padding: {
441
+ type: PropType<CardPadding>;
442
+ default: undefined;
443
+ };
444
+ }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
445
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
446
+ padding: {
447
+ type: PropType<CardPadding>;
448
+ default: undefined;
449
+ };
450
+ }>> & Readonly<{}>, {
451
+ padding: Padding;
452
+ }, SlotsType<{
453
+ default?: () => VNodeChild;
454
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
455
+ };
456
+ export type CardCompound = typeof Card;
@@ -0,0 +1,231 @@
1
+ import { defineComponent, createVNode, h } from "vue";
2
+ const isBlank = (value) => value === void 0 || value === null || value === false || value === "";
3
+ function resolveSlot(slotFn, propValue, transform) {
4
+ if (slotFn) return slotFn();
5
+ if (propValue === void 0 || propValue === null) return void 0;
6
+ return transform ? transform(propValue) : propValue;
7
+ }
8
+ const renderHeaderIcon = (icon) => typeof icon === "function" ? icon() : createVNode("img", {
9
+ "class": "mh-card__header-icon-img",
10
+ "src": icon,
11
+ "alt": ""
12
+ }, null);
13
+ function renderHeaderParts(parts) {
14
+ const noBuiltin = isBlank(parts.icon) && isBlank(parts.title) && isBlank(parts.subtitle) && isBlank(parts.extra);
15
+ if (noBuiltin) return isBlank(parts.main) ? [] : [parts.main];
16
+ const left = [];
17
+ if (!isBlank(parts.icon)) {
18
+ left.push(createVNode("span", {
19
+ "class": "mh-card__header-icon"
20
+ }, [parts.icon]));
21
+ }
22
+ if (!isBlank(parts.title) || !isBlank(parts.subtitle)) {
23
+ left.push(createVNode("span", {
24
+ "class": "mh-card__header-text"
25
+ }, [isBlank(parts.title) ? null : createVNode("span", {
26
+ "class": "mh-card__header-title"
27
+ }, [parts.title]), isBlank(parts.subtitle) ? null : createVNode("span", {
28
+ "class": "mh-card__header-subtitle"
29
+ }, [parts.subtitle])]));
30
+ }
31
+ if (!isBlank(parts.main)) left.push(parts.main);
32
+ return [left.length > 0 ? createVNode("div", {
33
+ "class": "mh-card__header-main"
34
+ }, [left]) : null, isBlank(parts.extra) ? null : createVNode("span", {
35
+ "class": "mh-card__header-extra"
36
+ }, [parts.extra])];
37
+ }
38
+ const mergeSegmentStyle = (attrsStyle, padding) => {
39
+ if (padding === void 0) return attrsStyle;
40
+ const y = typeof padding === "number" ? padding : padding.y;
41
+ const x = typeof padding === "number" ? padding : padding.x;
42
+ const style = {};
43
+ if (y !== void 0) style.paddingTop = `${y}px`;
44
+ if (x !== void 0) {
45
+ style.paddingLeft = `${x}px`;
46
+ style.paddingRight = `${x}px`;
47
+ }
48
+ if (Object.keys(style).length === 0) return attrsStyle;
49
+ return [attrsStyle, style];
50
+ };
51
+ const CardHeader = /* @__PURE__ */ defineComponent({
52
+ name: "CardHeader",
53
+ inheritAttrs: false,
54
+ props: {
55
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
56
+ padding: {
57
+ type: [Number, Object],
58
+ default: void 0
59
+ },
60
+ /** 图标:图片地址或返回节点的函数(图标一律来自 `@manohub/icon`) */
61
+ icon: {
62
+ type: [String, Function],
63
+ default: void 0
64
+ },
65
+ /** 标题(单行省略);要节点化标题时走 `title` 插槽 */
66
+ title: {
67
+ type: String,
68
+ default: void 0
69
+ },
70
+ /** 副标题(标题下方第二行,弱字色单行省略) */
71
+ subtitle: {
72
+ type: String,
73
+ default: void 0
74
+ }
75
+ },
76
+ slots: Object,
77
+ setup(props, {
78
+ slots,
79
+ attrs
80
+ }) {
81
+ return () => createVNode("div", {
82
+ "class": ["mh-card__header", attrs.class].filter(Boolean).join(" "),
83
+ "style": mergeSegmentStyle(attrs.style, props.padding)
84
+ }, [renderHeaderParts({
85
+ icon: resolveSlot(slots.icon, props.icon, renderHeaderIcon),
86
+ title: resolveSlot(slots.title, props.title),
87
+ subtitle: resolveSlot(slots.subtitle, props.subtitle),
88
+ extra: slots.extra?.(),
89
+ main: slots.default?.()
90
+ })]);
91
+ }
92
+ });
93
+ const CardBody = /* @__PURE__ */ defineComponent({
94
+ name: "CardBody",
95
+ inheritAttrs: false,
96
+ props: {
97
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
98
+ padding: {
99
+ type: [Number, Object],
100
+ default: void 0
101
+ }
102
+ },
103
+ slots: Object,
104
+ setup(props, {
105
+ slots,
106
+ attrs
107
+ }) {
108
+ return () => createVNode("div", {
109
+ "class": ["mh-card__body", attrs.class].filter(Boolean).join(" "),
110
+ "style": mergeSegmentStyle(attrs.style, props.padding)
111
+ }, [slots.default?.()]);
112
+ }
113
+ });
114
+ const CardFooter = /* @__PURE__ */ defineComponent({
115
+ name: "CardFooter",
116
+ inheritAttrs: false,
117
+ props: {
118
+ /** 这一段的内距(横向 + 段间距):缺省吃组件令牌 `--mh-card-padding`(20px);下边由卡片末段统一补 */
119
+ padding: {
120
+ type: [Number, Object],
121
+ default: void 0
122
+ }
123
+ },
124
+ slots: Object,
125
+ setup(props, {
126
+ slots,
127
+ attrs
128
+ }) {
129
+ return () => createVNode("div", {
130
+ "class": ["mh-card__footer", attrs.class].filter(Boolean).join(" "),
131
+ "style": mergeSegmentStyle(attrs.style, props.padding)
132
+ }, [slots.default?.()]);
133
+ }
134
+ });
135
+ const isCardPart = (child) => !!child && typeof child === "object" && (child.type === CardHeader || child.type === CardBody || child.type === CardFooter);
136
+ const flattenChildren = (raw) => (Array.isArray(raw) ? raw : raw == null ? [] : [raw]).flatMap((child) => Array.isArray(child) ? child : [child]).filter((child) => child !== null && child !== void 0 && child !== false && child !== true && child !== "");
137
+ function withImplicitBody(children) {
138
+ const out = [];
139
+ let loose = [];
140
+ const flush = () => {
141
+ if (loose.length === 0) return;
142
+ const group = loose;
143
+ loose = [];
144
+ out.push(h(CardBody, null, {
145
+ default: () => group
146
+ }));
147
+ };
148
+ for (const child of children) {
149
+ if (isCardPart(child)) {
150
+ flush();
151
+ out.push(child);
152
+ } else {
153
+ loose.push(child);
154
+ }
155
+ }
156
+ flush();
157
+ return out;
158
+ }
159
+ const CardRoot = /* @__PURE__ */ defineComponent({
160
+ name: "Card",
161
+ inheritAttrs: false,
162
+ props: {
163
+ variant: {
164
+ type: String,
165
+ default: "outline"
166
+ },
167
+ interactive: {
168
+ type: Boolean,
169
+ default: false
170
+ },
171
+ selected: {
172
+ type: Boolean,
173
+ default: false
174
+ },
175
+ disabled: {
176
+ type: Boolean,
177
+ default: false
178
+ },
179
+ icon: {
180
+ type: [String, Function],
181
+ default: void 0
182
+ },
183
+ title: {
184
+ type: String,
185
+ default: void 0
186
+ },
187
+ subtitle: {
188
+ type: String,
189
+ default: void 0
190
+ },
191
+ onClick: {
192
+ type: Function,
193
+ default: void 0
194
+ }
195
+ },
196
+ slots: Object,
197
+ setup(props, {
198
+ slots,
199
+ attrs
200
+ }) {
201
+ return () => {
202
+ const hasHead = Boolean(props.icon !== void 0 || props.title !== void 0 || props.subtitle !== void 0 || slots.icon || slots.title || slots.subtitle || slots.extra);
203
+ const classes = ["mh-card", `mh-card--${props.variant}`, props.interactive ? "mh-card--interactive" : "", props.selected ? "mh-card--selected" : "", props.disabled ? "mh-card--disabled" : "", attrs.class].filter(Boolean).join(" ");
204
+ return createVNode("div", {
205
+ "class": classes,
206
+ "style": attrs.style,
207
+ "onClick": props.disabled ? void 0 : props.onClick
208
+ }, [hasHead ? createVNode("div", {
209
+ "class": "mh-card__header"
210
+ }, [renderHeaderParts({
211
+ icon: resolveSlot(slots.icon, props.icon, renderHeaderIcon),
212
+ title: resolveSlot(slots.title, props.title),
213
+ subtitle: resolveSlot(slots.subtitle, props.subtitle),
214
+ extra: slots.extra?.()
215
+ })]) : null, withImplicitBody(flattenChildren(slots.default?.())), slots.actions ? createVNode("div", {
216
+ "class": "mh-card__actions"
217
+ }, [slots.actions()]) : null]);
218
+ };
219
+ }
220
+ });
221
+ const Card = Object.assign(CardRoot, {
222
+ Header: CardHeader,
223
+ Body: CardBody,
224
+ Footer: CardFooter
225
+ });
226
+ export {
227
+ Card,
228
+ CardBody,
229
+ CardFooter,
230
+ CardHeader
231
+ };