@manohub/ui 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/components/button/index.d.ts +8 -8
- package/dist/components/dialog/index.d.ts +58 -6
- package/dist/components/dialog/index.js +45 -8
- package/dist/components/drawer/index.d.ts +18 -6
- package/dist/components/drawer/index.js +11 -5
- package/dist/components/input/index.d.ts +4 -4
- package/dist/components/input/index.js +1 -1
- package/dist/components/notice/index.d.ts +23 -10
- package/dist/components/notice/index.js +11 -5
- package/dist/components/notification/index.d.ts +1 -1
- package/dist/components/search/index.d.ts +33 -4
- package/dist/components/search/index.js +24 -8
- package/dist/components/table/index.d.ts +2 -1
- package/dist/components/tabs/index.d.ts +6 -2
- package/dist/components/tabs/index.js +9 -1
- package/dist/components/tabset/index.d.ts +6 -2
- package/dist/components/tabset/index.js +8 -1
- package/dist/components/tag/index.d.ts +1 -1
- package/dist/components/text/index.d.ts +120 -0
- package/dist/components/text/index.js +55 -0
- package/dist/components/toast/index.d.ts +4 -4
- package/dist/components/toast/index.js +11 -2
- package/dist/components/upload/index.d.ts +30 -0
- package/dist/components/upload/index.js +7 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/services/dialog.d.ts +20 -5
- package/dist/services/dialog.js +8 -1
- package/dist/styles/components/dialog.css +40 -1
- package/dist/styles/components/input.css +1 -1
- package/dist/styles/components/search.css +5 -1
- package/dist/styles/components/select.css +11 -0
- package/dist/styles/components/table.css +9 -4
- package/dist/styles/components/text.css +101 -0
- package/dist/styles/components/toast.css +12 -6
- package/dist/styles/index.css +5 -1
- package/dist/styles/reset.css +205 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { Avatar } from "./components/avatar/index.js";
|
|
|
10
10
|
import { Skeleton } from "./components/skeleton/index.js";
|
|
11
11
|
import { Radio } from "./components/radio/index.js";
|
|
12
12
|
import { Tag } from "./components/tag/index.js";
|
|
13
|
+
import { Text } from "./components/text/index.js";
|
|
13
14
|
import { Tree } from "./components/tree/index.js";
|
|
14
15
|
import { ListView } from "./components/list-view/index.js";
|
|
15
16
|
import { Badge } from "./components/badge/index.js";
|
|
@@ -80,6 +81,7 @@ export {
|
|
|
80
81
|
Tabs,
|
|
81
82
|
Tabset,
|
|
82
83
|
Tag,
|
|
84
|
+
Text,
|
|
83
85
|
Textarea,
|
|
84
86
|
Toast,
|
|
85
87
|
Tooltip,
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
+
import { type DialogTone } from '../components/dialog';
|
|
1
2
|
export interface ConfirmOptions {
|
|
2
3
|
/** 标题(缺省不渲染页头,只剩内容与底栏) */
|
|
3
4
|
title?: string;
|
|
4
5
|
/** 正文(纯文本;复杂内容请直接用 `Dialog` 组件) */
|
|
5
6
|
detail?: string;
|
|
7
|
+
/**
|
|
8
|
+
* 语义档(决定标题左侧的裸符号与配色):`info` / `success` / `warning` / `error`。
|
|
9
|
+
*
|
|
10
|
+
* 不传则无图标。**危险操作用 `error`** —— 它同时把确定按钮染成危险色
|
|
11
|
+
* (除非显式给了 `okDanger`),这样「删除确认」与「保存成功」不再长得一样。
|
|
12
|
+
*/
|
|
13
|
+
tone?: DialogTone;
|
|
6
14
|
/** 确定按钮文案 */
|
|
7
15
|
okText?: string;
|
|
8
16
|
/** 取消按钮文案(`alert` 不使用) */
|
|
9
17
|
cancelText?: string;
|
|
10
|
-
/**
|
|
18
|
+
/** 确定按钮的危险色(删除类确认;不传时由 `tone === 'error'` 推出) */
|
|
11
19
|
okDanger?: boolean;
|
|
12
20
|
/** 是否显示关闭位(缺省开:用户总得有第三条退路) */
|
|
13
21
|
closable?: boolean;
|
|
@@ -18,11 +26,15 @@ export interface ConfirmOptions {
|
|
|
18
26
|
* 与 `Dialog` 组件的分工:组件是「受控弹窗」,本函数补齐命令式调用缺的那一层(宿主 + 收场 Promise)。
|
|
19
27
|
* 语义与主流库一致:**任何非确定路径都折成 `false`**,调用方 `if (await confirm(...))` 一处判断即可。
|
|
20
28
|
*
|
|
29
|
+
* **遮罩与 Esc 都归 `false`**:`Dialog` 组件形态的 `closeOnBackdrop` 默认已改为 `true`(跟主流),
|
|
30
|
+
* 但命令式确认框必须**显式关掉它** —— 这里一条误点就丢一次决策,与 Ant Design
|
|
31
|
+
* (`<Modal maskClosable>` 默认 `true`、`Modal.confirm` 默认 `false`)的分工一致。
|
|
32
|
+
*
|
|
21
33
|
* 需要「确定按钮进加载态」的异步确认请直接用 `Dialog` 组件(`onOk` 返回 Promise 时自动进加载态)——
|
|
22
34
|
* 命令式形态刻意不引入跨 tick 的加载态,免得调用方以为弹窗已经关了。
|
|
23
35
|
*
|
|
24
|
-
* @example
|
|
25
|
-
* if (await confirm({ title: '删除确认', detail: '删除后不可恢复,确认继续?', okText: '删除',
|
|
36
|
+
* @example 删除确认(`tone: 'error'` 给标题加提示图标并把确定按钮染危险色)
|
|
37
|
+
* if (await confirm({ title: '删除确认', detail: '删除后不可恢复,确认继续?', okText: '删除', tone: 'error' })) {
|
|
26
38
|
* await remove()
|
|
27
39
|
* }
|
|
28
40
|
*/
|
|
@@ -33,8 +45,11 @@ export declare function confirm(options?: ConfirmOptions): Promise<boolean>;
|
|
|
33
45
|
* 底栏**自绘**而不是用内建底栏:内建底栏固定是「取消 + 确定」两枚,而告知框没有「取消」可言
|
|
34
46
|
* (给两枚按钮会让用户以为还有一条分支)。
|
|
35
47
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
48
|
+
* 与 `confirm()` 同一口径:**遮罩与 Esc 都显式关掉**(告知框同样不该被一次误点打发掉)。
|
|
49
|
+
*
|
|
50
|
+
* @example 危险操作的回执:这一条与「保存成功」在图标与配色上区分开
|
|
51
|
+
* await alert({ tone: 'error', title: '移除失败', detail: '该来源系统仍被 3 个应用引用。' })
|
|
52
|
+
* await alert({ tone: 'success', title: '导入完成', detail: '共 128 条,其中 3 条被跳过。' })
|
|
38
53
|
*/
|
|
39
54
|
export declare function alert(options?: ConfirmOptions): Promise<void>;
|
|
40
55
|
/** 收掉全部在档弹窗(逐个折成 `false`);幂等。换应用 / 卸载时调 */
|
package/dist/services/dialog.js
CHANGED
|
@@ -39,10 +39,14 @@ function confirm(options = {}) {
|
|
|
39
39
|
{
|
|
40
40
|
open: ctx.isOpen(),
|
|
41
41
|
title: options.title,
|
|
42
|
+
tone: options.tone,
|
|
42
43
|
closable: options.closable ?? true,
|
|
44
|
+
// 组件形态默认已开(跟主流);命令式这一层显式关掉,防误点丢决策
|
|
45
|
+
closeOnBackdrop: false,
|
|
46
|
+
maskClosable: false,
|
|
43
47
|
okText: options.okText ?? "确定",
|
|
44
48
|
cancelText: options.cancelText ?? "取消",
|
|
45
|
-
okDanger: options.okDanger ??
|
|
49
|
+
okDanger: options.okDanger ?? options.tone === "error",
|
|
46
50
|
onOk: () => ctx.finish(true),
|
|
47
51
|
onCancel: () => ctx.finish(false),
|
|
48
52
|
onClose: () => ctx.finish(false)
|
|
@@ -58,7 +62,10 @@ function alert(options = {}) {
|
|
|
58
62
|
{
|
|
59
63
|
open: ctx.isOpen(),
|
|
60
64
|
title: options.title,
|
|
65
|
+
tone: options.tone,
|
|
61
66
|
closable: options.closable ?? true,
|
|
67
|
+
closeOnBackdrop: false,
|
|
68
|
+
maskClosable: false,
|
|
62
69
|
// 关闭位与 Esc 都算「看过了」
|
|
63
70
|
onCancel: () => ctx.finish(true),
|
|
64
71
|
onClose: () => ctx.finish(true)
|
|
@@ -16,6 +16,15 @@
|
|
|
16
16
|
* (`class="mh-popup mh-card"` + 按钮),不需要新的面;尺寸 220/r10 那组值也不值得为它单开一族。
|
|
17
17
|
*/
|
|
18
18
|
.mh-dialog {
|
|
19
|
+
/* 三段式列布局:页头 / 底栏由内容定高(`flex: none`),内容区吃掉剩余高度。
|
|
20
|
+
与 `Drawer` 同构(那边一直是这么写的)—— 本件此前漏了这一层,表现为
|
|
21
|
+
**高度受控时底栏不贴底**(body 只有内容高,剩余空间全留在 footer 之后)。
|
|
22
|
+
不设高度时零影响:列容器无高度约束 ⇒ body 高 = 内容高(与改前逐像素一致)。
|
|
23
|
+
⚠️ 加 `display: flex` 会以作者源压过 UA 的 `dialog:not([open]) { display: none }`,
|
|
24
|
+
收起态靠操作层 `operations/popup.css` 的 `:is(… dialog.mh-popup:not([open]))` 兜住
|
|
25
|
+
(特异性 0-3-0,高于本行)—— **那条兜底不能删**。 */
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
19
28
|
width: var(--ui-dialog-width);
|
|
20
29
|
max-width: var(--ui-dialog-width);
|
|
21
30
|
padding: 0; /* UA 给 <dialog> 的内距一律归零:内距由页头 / 内容 / 底栏各自拥有 */
|
|
@@ -42,14 +51,38 @@
|
|
|
42
51
|
align-items: center;
|
|
43
52
|
justify-content: space-between;
|
|
44
53
|
gap: var(--ui-space-2);
|
|
54
|
+
flex: none; /* 高度受控时不被压缩(同 Drawer) */
|
|
45
55
|
padding: var(--ui-space-4) var(--ui-space-6) 0;
|
|
46
56
|
font-size: var(--ui-font-heading); /* 规范 16px */
|
|
47
57
|
line-height: var(--ui-line-heading);
|
|
48
58
|
font-weight: var(--ui-weight-medium);
|
|
49
59
|
color: var(--ui-base-content);
|
|
50
60
|
}
|
|
61
|
+
/* 语义档(`tone`):标题左侧一个**裸符号**,颜色按档取语义色 ——
|
|
62
|
+
缺省(不传 tone)不渲染,故不影响既有外观。取色口径与 `Notice` 同一张表
|
|
63
|
+
(success / warning 取 -strong 档,否则浅底上对比度不足)。 */
|
|
64
|
+
.mh-dialog__tone-icon {
|
|
65
|
+
flex: none;
|
|
66
|
+
width: var(--ui-font-icon);
|
|
67
|
+
height: var(--ui-font-icon);
|
|
68
|
+
color: var(--mh-dialog-tone-color, var(--ui-primary));
|
|
69
|
+
}
|
|
70
|
+
.mh-dialog--info {
|
|
71
|
+
--mh-dialog-tone-color: var(--ui-info);
|
|
72
|
+
}
|
|
73
|
+
.mh-dialog--success {
|
|
74
|
+
--mh-dialog-tone-color: var(--ui-success-strong);
|
|
75
|
+
}
|
|
76
|
+
.mh-dialog--warning {
|
|
77
|
+
--mh-dialog-tone-color: var(--ui-warning-strong);
|
|
78
|
+
}
|
|
79
|
+
.mh-dialog--error {
|
|
80
|
+
--mh-dialog-tone-color: var(--ui-error);
|
|
81
|
+
}
|
|
82
|
+
|
|
51
83
|
/* 标题位(插槽版也走这个类,两路渲染同一份排版) */
|
|
52
84
|
.mh-dialog__title {
|
|
85
|
+
flex: 1 1 auto; /* 撑满中段:语义图标在左、关闭位在右(`space-between` 下三者的正确落位) */
|
|
53
86
|
min-width: 0;
|
|
54
87
|
overflow: hidden;
|
|
55
88
|
text-overflow: ellipsis;
|
|
@@ -82,8 +115,13 @@
|
|
|
82
115
|
outline-offset: 2px;
|
|
83
116
|
}
|
|
84
117
|
|
|
85
|
-
/* 内容区(内距 24;三段之间无分割线,交界间距只由三段内距单一拥有)
|
|
118
|
+
/* 内容区(内距 24;三段之间无分割线,交界间距只由三段内距单一拥有)
|
|
119
|
+
`flex: 1 1 auto` + `min-height: 0`:吃掉页头与底栏之外的全部高度(含 `panelHeight` /
|
|
120
|
+
消费方经 style 给的高度),超出即**本段**滚动 —— 页头与底栏因此永远可见。 */
|
|
86
121
|
.mh-dialog__body {
|
|
122
|
+
flex: 1 1 auto;
|
|
123
|
+
min-height: 0;
|
|
124
|
+
overflow-y: auto;
|
|
87
125
|
padding: var(--ui-space-6);
|
|
88
126
|
font-size: var(--ui-font-body);
|
|
89
127
|
line-height: var(--ui-line-body);
|
|
@@ -102,5 +140,6 @@
|
|
|
102
140
|
display: flex;
|
|
103
141
|
justify-content: flex-end;
|
|
104
142
|
gap: var(--ui-space-2);
|
|
143
|
+
flex: none; /* 高度受控时贴底且不被压缩(同 Drawer) */
|
|
105
144
|
padding: 0 var(--ui-space-6) var(--ui-space-4);
|
|
106
145
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Search —— 搜索框(输入框 +
|
|
2
|
+
* Search —— 搜索框(输入框 + 可选搜索按钮的**组合件面**)。
|
|
3
3
|
*
|
|
4
4
|
* 本面**只声明「一行里怎么摆」**:输入框那一段的面归 `input.css`(框 / 内距 / 清除位 /
|
|
5
5
|
* 聚焦态 / 禁用态全套复用),搜索按钮的面归 `button.css`。本件因此没有自己的几何令牌,
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* 必须允许收缩,否则会把同行的搜索按钮挤出容器(窄栏里尤其明显);
|
|
11
11
|
* - 搜索按钮 `flex: none`:它永远是「那么大」,宽度让给输入框。
|
|
12
12
|
*
|
|
13
|
+
* **按钮是可选的**:不传 `searchText` 时本件只渲染输入框(框内的放大镜已占住「搜索」语义,
|
|
14
|
+
* 再出一个同字形的图标按钮就是同一个意思画两遍)。此时 `__btn` 那条摆法规则无对象,
|
|
15
|
+
* 输入框自然占满整行——摆法不用改,缺了按钮也不留空档。
|
|
16
|
+
*
|
|
13
17
|
* **类名与面文件名同根**:`.mh-search*`,一律 `mh-` 前缀。
|
|
14
18
|
*/
|
|
15
19
|
.mh-search {
|
|
@@ -131,6 +131,17 @@
|
|
|
131
131
|
width: 100%;
|
|
132
132
|
height: var(--ui-select-option-height);
|
|
133
133
|
padding: 0 var(--ui-select-padding-x);
|
|
134
|
+
/* **按钮重置四条,必须自带**:本行是 `<button role="option">`,而按钮自带 UA 外观
|
|
135
|
+
(`border: 2px outset` / `background: ButtonFace` / `font-family: Arial` / `text-align: center`)。
|
|
136
|
+
reset 层(`styles/reset.css`)虽然也清零了前三条,但组件面**不得依赖它** ——
|
|
137
|
+
本仓的 0.6.x 就漏了这四条,表现为选项行呈原生按钮外观(灰底 + 立体边框 + 居中 Arial),
|
|
138
|
+
而同一面板里的 `.mh-select__add` 写齐了 ⇒ 一个面板里两种外观。
|
|
139
|
+
`text-align` 是 reset 层**没有**的一项(它不属于「元素基线」,属于「列表行」语义),故此处必写。
|
|
140
|
+
色彩 / 字族这些**值**仍然归令牌,这四条只是把 UA 的默认值归零。 */
|
|
141
|
+
border: none;
|
|
142
|
+
background: transparent;
|
|
143
|
+
font-family: inherit;
|
|
144
|
+
text-align: left;
|
|
134
145
|
font-size: var(--ui-select-font-size);
|
|
135
146
|
color: var(--ui-base-content);
|
|
136
147
|
cursor: pointer;
|
|
@@ -30,11 +30,15 @@
|
|
|
30
30
|
* "没写的边"顶掉,结果就是与表外框叠成 2px、行交界处叠成 2px、还多出列分隔线。
|
|
31
31
|
* 2. **斑马纹是显式类**(`.is-striped`)而非 `:nth-child(even)`:表里可以插分组行,`nth-child` 会整表错位
|
|
32
32
|
* —— 这是规范里唯一允许"用类代替结构选择器"的豁免。
|
|
33
|
-
* 3. **行选中由行内的选择控件驱动**(`tr:has(input:checked)`):这样零 JS 也能选中;
|
|
33
|
+
* 3. **行选中由行内的选择控件驱动**(`tr:has(.mh-table__col-check input:checked)`):这样零 JS 也能选中;
|
|
34
34
|
* 组件态给 `[data-state='selected']`,静态档给 `.is-selected` —— 三源等价。
|
|
35
35
|
* 勾选列复用 `Checkbox` **组件**(不在表格里手写原生 input):该件内部才是真实 `<input type="checkbox">`,
|
|
36
|
-
* 故 `:has(
|
|
36
|
+
* 故 `:has(...)` 这条路径照旧成立;`Checkbox` 的框体带 `data-state`(checked / indeterminate),
|
|
37
37
|
* 半选与选中都走它自己的样式数据,表格这边不再画方块。
|
|
38
|
+
* **选择器必须限定在勾选列内**(`.mh-table__col-check`,勾选列单元格自带的类):不限列时,
|
|
39
|
+
* 功能列里任何「内部本来就是 checkbox」的件都会命中 —— `Switch` 的内部正是 `<input type="checkbox">`,
|
|
40
|
+
* 于是「启用」这类**功能值**会把整行点亮。功能值与行选择语义不同,视觉必须分开(否则一张表里
|
|
41
|
+
* 开关一开就整行变色,且用户无从判断那到底表示什么)。
|
|
38
42
|
* 4. **固定列必须自带底**(`background: var(--ui-base-100)`):它是 sticky 的,不遮挡就会被滚过的单元格透出。
|
|
39
43
|
*
|
|
40
44
|
* **不做**:排序与列宽拖拽的**算法**(规范只给了 `↕` 字形与 3×40 拖拽线这两处视觉),也不做空态/加载态
|
|
@@ -141,10 +145,11 @@
|
|
|
141
145
|
}
|
|
142
146
|
/* 选中态**只有底色**:规范样张里那条 2px 主色下沿(Au01)已去掉 ——
|
|
143
147
|
行线只由单元格底边提供,选中行不再额外压一条线(`box-shadow: inset 0 -2px` 会盖住底边线,
|
|
144
|
-
看起来像"两行线叠在一起")。要恢复下沿就加回 inset 阴影 + 对应令牌。
|
|
148
|
+
看起来像"两行线叠在一起")。要恢复下沿就加回 inset 阴影 + 对应令牌。
|
|
149
|
+
第三条路径限定在勾选列内(见文件头第 3 条):不限列会被功能列的 Switch 命中。 */
|
|
145
150
|
.mh-table tbody tr.is-selected td,
|
|
146
151
|
.mh-table tbody tr[data-state='selected'] td,
|
|
147
|
-
.mh-table tbody tr:has(input:checked) td {
|
|
152
|
+
.mh-table tbody tr:has(.mh-table__col-check input:checked) td {
|
|
148
153
|
background: var(--ui-table-row-selected);
|
|
149
154
|
}
|
|
150
155
|
.mh-table tbody tr.is-disabled td,
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text —— 文本排版(字号 / 行高 / 字重 / 语义色 / 等宽 / 截断)。
|
|
3
|
+
*
|
|
4
|
+
* 本文件是 `@manohub/theme` 那套 `--ui-font-*` / `--ui-line-*` / `--ui-weight-*` 档位令牌的
|
|
5
|
+
* **第一个消费者**:在此之前它们只有定义、没有件,于是「卡片里的文字层级」在应用侧无合规落点
|
|
6
|
+
* (契约 L1-5 禁 `font-*` / `color`),每个应用都要留一条定版例外登记。
|
|
7
|
+
*
|
|
8
|
+
* ## 取色口径
|
|
9
|
+
*
|
|
10
|
+
* 与 `Notice` / `Dialog` 的语义档同一张表:`success` / `warning` 取 `-strong` 档
|
|
11
|
+
* (直接用 500 档主色在浅底上对比度不足,属可读性缺陷)。
|
|
12
|
+
*
|
|
13
|
+
* ## 为什么 tone 走内部变量
|
|
14
|
+
*
|
|
15
|
+
* `--mh-text-tone-color` 是**内部状态变量**(`--mh-` 命名空间),由修饰符类赋值、由根类消费 ——
|
|
16
|
+
* 这样「一条规则管颜色」而不是七条各写一次 `color`。默认值取 `inherit`,
|
|
17
|
+
* 故**不传 tone 的文字也不会被强行染色**(`tone` 缺省档是 `default`,与正文色一致)。
|
|
18
|
+
*
|
|
19
|
+
* ## 截断
|
|
20
|
+
*
|
|
21
|
+
* `--truncate`(单行)与 `--clamp`(N 行)都要 `min-width: 0` 才能在被 flex 拉伸的子项里生效
|
|
22
|
+
* (flex 子项的 `min-width` 默认是 `auto`,不给就会把容器撑开而不是省略)。
|
|
23
|
+
* N 行的行数经 `--mh-text-lines` 下发(`-webkit-line-clamp` 只吃值,不能由类名表达行数)。
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
.mh-text {
|
|
27
|
+
color: var(--mh-text-tone-color, inherit);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ===== 字号档(每档配一枚行高令牌,两者成对出现才不会出现「字号变了行距没变」) ===== */
|
|
31
|
+
.mh-text--caption {
|
|
32
|
+
font-size: var(--ui-font-caption);
|
|
33
|
+
line-height: var(--ui-line-caption);
|
|
34
|
+
}
|
|
35
|
+
.mh-text--body {
|
|
36
|
+
font-size: var(--ui-font-body);
|
|
37
|
+
line-height: var(--ui-line-body);
|
|
38
|
+
}
|
|
39
|
+
.mh-text--heading {
|
|
40
|
+
font-size: var(--ui-font-heading);
|
|
41
|
+
line-height: var(--ui-line-heading);
|
|
42
|
+
}
|
|
43
|
+
.mh-text--title {
|
|
44
|
+
font-size: var(--ui-font-title);
|
|
45
|
+
line-height: var(--ui-line-title);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ===== 字重档(缺省不给,即继承上下文) ===== */
|
|
49
|
+
.mh-text--regular {
|
|
50
|
+
font-weight: var(--ui-weight-regular);
|
|
51
|
+
}
|
|
52
|
+
.mh-text--medium {
|
|
53
|
+
font-weight: var(--ui-weight-medium);
|
|
54
|
+
}
|
|
55
|
+
.mh-text--semibold {
|
|
56
|
+
font-weight: var(--ui-weight-semibold);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ===== 语义色档 ===== */
|
|
60
|
+
.mh-text--default {
|
|
61
|
+
--mh-text-tone-color: var(--ui-base-content);
|
|
62
|
+
}
|
|
63
|
+
.mh-text--muted {
|
|
64
|
+
--mh-text-tone-color: var(--ui-base-content-muted);
|
|
65
|
+
}
|
|
66
|
+
.mh-text--subtle {
|
|
67
|
+
--mh-text-tone-color: var(--ui-base-content-subtle);
|
|
68
|
+
}
|
|
69
|
+
.mh-text--primary {
|
|
70
|
+
--mh-text-tone-color: var(--ui-primary);
|
|
71
|
+
}
|
|
72
|
+
.mh-text--success {
|
|
73
|
+
--mh-text-tone-color: var(--ui-success-strong);
|
|
74
|
+
}
|
|
75
|
+
.mh-text--warning {
|
|
76
|
+
--mh-text-tone-color: var(--ui-warning-strong);
|
|
77
|
+
}
|
|
78
|
+
.mh-text--error {
|
|
79
|
+
--mh-text-tone-color: var(--ui-error);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ===== 等宽族(代码 / 路径 / ID;字号跟随所在档,不另开一档) ===== */
|
|
83
|
+
.mh-text--mono {
|
|
84
|
+
font-family: var(--ui-font-mono);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* ===== 截断 ===== */
|
|
88
|
+
.mh-text--truncate {
|
|
89
|
+
display: block;
|
|
90
|
+
min-width: 0;
|
|
91
|
+
overflow: hidden;
|
|
92
|
+
text-overflow: ellipsis;
|
|
93
|
+
white-space: nowrap;
|
|
94
|
+
}
|
|
95
|
+
.mh-text--clamp {
|
|
96
|
+
display: -webkit-box;
|
|
97
|
+
-webkit-box-orient: vertical;
|
|
98
|
+
-webkit-line-clamp: var(--mh-text-lines, 2);
|
|
99
|
+
min-width: 0;
|
|
100
|
+
overflow: hidden;
|
|
101
|
+
}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
width: 360px;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/* 图标:圆形色底 + 白色字形(18×18) */
|
|
45
|
+
/* ===== 图标:圆形色底 + 白色字形(18×18) ===== */
|
|
46
46
|
.mh-toast__icon {
|
|
47
47
|
display: flex;
|
|
48
48
|
align-items: center;
|
|
@@ -55,22 +55,28 @@
|
|
|
55
55
|
font-size: var(--ui-font-caption);
|
|
56
56
|
line-height: 1;
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
|
|
59
|
+
/* ===== 语义档:色落在**根修饰符**上,由它再作用到图标 =====
|
|
60
|
+
* 本包 tone 维度的统一落点是 `.mh-<件>--<tone>`(`Badge` / `Dialog` / `Notice` / `Notification`
|
|
61
|
+
* / `Tag` / `Text` 同款)。本件此前写成 `.mh-toast__icon--<tone>`,是唯一一个落子元素修饰符的 ——
|
|
62
|
+
* 消费方按直觉拼 `.mh-toast--success` 会落空。现改为「根挂 tone、面里用后代选择器取到图标」,
|
|
63
|
+
* **视觉一字未变**(圆形色底仍然只在图标上)。 */
|
|
64
|
+
.mh-toast--info .mh-toast__icon {
|
|
59
65
|
background: var(--ui-info);
|
|
60
66
|
}
|
|
61
|
-
.mh-
|
|
67
|
+
.mh-toast--success .mh-toast__icon {
|
|
62
68
|
background: var(--ui-success);
|
|
63
69
|
}
|
|
64
|
-
.mh-
|
|
70
|
+
.mh-toast--warning .mh-toast__icon {
|
|
65
71
|
background: var(--ui-warning);
|
|
66
72
|
}
|
|
67
|
-
.mh-
|
|
73
|
+
.mh-toast--error .mh-toast__icon {
|
|
68
74
|
background: var(--ui-error);
|
|
69
75
|
}
|
|
70
76
|
/* loading 档:透明底 + 主色字形 + 匀速转圈。
|
|
71
77
|
规范此处是「2px 描边 + 上边缺口」的自画法,本仓改用意形(图标包的 `loading`)——
|
|
72
78
|
硬约束是「图标一律来自图标包、不用文字符号或自画形状冒充」,视觉等价(都是转圈环)。 */
|
|
73
|
-
.mh-
|
|
79
|
+
.mh-toast--loading .mh-toast__icon {
|
|
74
80
|
background: transparent;
|
|
75
81
|
color: var(--ui-primary);
|
|
76
82
|
animation: mh-toast-spin 0.8s linear infinite;
|
package/dist/styles/index.css
CHANGED
|
@@ -42,10 +42,13 @@
|
|
|
42
42
|
* 跨件共用的值一律进 `@manohub/theme`;面上的 `--ui-*` 只允许出现在**修饰符块**里
|
|
43
43
|
* (护栏会拦「面里出现不含修饰符类的 `--ui-*` 声明」)。
|
|
44
44
|
*
|
|
45
|
-
*
|
|
45
|
+
* 层序:**基线(`./reset.css`,元素级、零特异性)→ 值 → 面**;面内部**操作层在前**(零 JS 原语、规则走 `:where()` 零特异性,
|
|
46
46
|
* 永远给皮肤让位),组件面在后。
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
+
/* ===== 基线:元素级 reset(特异性最低;先于值 → 面,消费方写任何元素选择器都能盖过它) ===== */
|
|
50
|
+
@import './reset.css';
|
|
51
|
+
|
|
49
52
|
/* ===== 值:组件令牌基础值(锚 `[data-manohub-ui]`,与主题令牌同层序) ===== */
|
|
50
53
|
/* 容器与分区 */
|
|
51
54
|
@import './components/collapse.tokens.css';
|
|
@@ -104,6 +107,7 @@
|
|
|
104
107
|
@import './components/divider.css'; /* 内容之间的分隔线(设计稿内容区 44 处在用;不是各件自己的框线) */
|
|
105
108
|
@import './components/nav.css';
|
|
106
109
|
@import './components/layout.css'; /* 布局原子件族(Layout.Row 排「行」/ Layout.Column 排「列」);与任何件都无层序耦合 */
|
|
110
|
+
@import './components/text.css'; /* 排版原子件:`--ui-font-*` 档位令牌的第一个消费者;叶子件,与任何件都无层序耦合 */
|
|
107
111
|
|
|
108
112
|
/* 数据展示 */
|
|
109
113
|
@import './components/tree.css';
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基础重置(reset)—— 元素级基线,随 `@manohub/ui/styles.css` 一起到达消费方。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么基线归本包
|
|
5
|
+
*
|
|
6
|
+
* 接入契约(`@manohub/kit/CONTRACT.md` §3)禁应用侧写裸元素选择器与字号字面量,
|
|
7
|
+
* 于是「把浏览器默认值归零」在应用侧**没有合规落点**:0.6.0 之前它寄在入口层的
|
|
8
|
+
* `reset.css` 里,随入口层零样式化一并删除后就成了缺口(契约 §10 记在案)。
|
|
9
|
+
* 本包是样式面(② 面层)的唯一来源,元素基线因此归这里 —— 位于「值」之后、「面」之前。
|
|
10
|
+
*
|
|
11
|
+
* ## 参照口径
|
|
12
|
+
*
|
|
13
|
+
* 主体对齐 **Tailwind Preflight**(消费方 `apps/<app>/src/style.css` 一直在引的那份):
|
|
14
|
+
* 覆盖的元素清单一致,**唯一的有意差异是表单控件的底色** —— Preflight 把 `input` / `select` /
|
|
15
|
+
* `textarea` 也清成透明,本文件保留浏览器原生底色(裸输入框若连底都没有就完全不可见);
|
|
16
|
+
* 挂类的控件(`.mh-input` 等)有自己的面,不受这条影响。本包组件面本来就是按「已清零」的环境写的 ——
|
|
17
|
+
* 全部 33 处挂类的 `<button>` 合并后都自带 border / background / padding ——
|
|
18
|
+
* 所以本文件**不改变任何组件的外观**;它的作用是:
|
|
19
|
+
*
|
|
20
|
+
* 1. 让文档站 / 静态页也站到与真实应用同一个起跑线(此前只有真实应用有 preflight);
|
|
21
|
+
* 2. 让裸元素(`ul` / `a` / `p` / `button` …)不再带浏览器的默认内外距、列表序号与链接色 ——
|
|
22
|
+
* 页面骨架由应用的 tsx 摆放时,不必再为每个原生元素写一次归零。
|
|
23
|
+
*
|
|
24
|
+
* 与旧实现(`app-kit` 的 reset)相比,多了按钮外观归零、列表序号归零、链接继承色去下划线、
|
|
25
|
+
* 标题字阶归位、媒体元素转块级 —— 那几条正是「应用侧各写各的」在补齐的部分。
|
|
26
|
+
*
|
|
27
|
+
* ## 特异性纪律(改本文件前必读)
|
|
28
|
+
*
|
|
29
|
+
* **作用域一律用 `:where([data-manohub-ui])` 包裹**:`:where()` 特异性为 0,
|
|
30
|
+
* 故每条规则等价于纯元素选择器(0,0,1)甚至更低(`:where(X) *` 即 0,0,0)。
|
|
31
|
+
* 写成 `.container button` 这类高特异性选择器(0,1,1)会**反压本包组件面**(普遍是单类 0,1,0)——
|
|
32
|
+
* 本仓踩过:主按钮文字变成 `color: inherit` 的黑色。**新增任何 reset 级样式都要遵守这条。**
|
|
33
|
+
* 也正因为它的特异性最低,消费方在自己的样式里写任何元素选择器都能盖过它。
|
|
34
|
+
*
|
|
35
|
+
* 唯一一条不带 `:where()` 的是**容器基座**(下面的 `[data-manohub-ui]`):它描述容器自身而非其后代,
|
|
36
|
+
* 且要能在消费方「同名选择器后写即胜」的规则里被覆盖,故保持 (0,1,0)(与旧实现一致)。
|
|
37
|
+
*
|
|
38
|
+
* ## 四条不做
|
|
39
|
+
*
|
|
40
|
+
* 1. **不碰 `html` / `body` / `#app`**:micro-app 的 scopecss **不作用域化**它们,
|
|
41
|
+
* 写进去会泄漏到宿主应用的全局样式。
|
|
42
|
+
* **整链高度由消费方承担,且契约明确它是合法的** —— 写在应用的 `app.css` 或入口 HTML 的 `<style>` 里
|
|
43
|
+
* (`@manohub/kit/CONTRACT.md` §1.2「入口基线」,是 L1-6「不得用裸元素选择器」的**唯一例外**);
|
|
44
|
+
* 容器自身在这里给 `height: 100%`,`Page` 的 `height: 100%` 依赖上面那条链存在。
|
|
45
|
+
* 2. **不定义任何 `--ui-*` 令牌**:值一律归 `@manohub/theme`,本文件只**消费**(两处定义必然漂)。
|
|
46
|
+
* 3. **不出现任何类选择器**:本层是元素基线,类归各组件面(`styles/components/`)。
|
|
47
|
+
* 4. **不写 `appearance`**:作者一旦声明了 `background` / `border`,浏览器即放弃原生控件绘制。
|
|
48
|
+
* 实测(无头 Chrome,只引 theme + ui/styles.css):裸 `button` 的计算值是透明底 /
|
|
49
|
+
* `border-width: 0` / `border-radius: 0` / 内距 0 / 字色与字族继承容器 —— 已经是清零态。
|
|
50
|
+
* Safari / iOS 是否还需 `appearance: none` 未在真机核对,故不动(补它前请先在真机取证)。
|
|
51
|
+
*
|
|
52
|
+
* ## 富文本须知
|
|
53
|
+
*
|
|
54
|
+
* 重置掉 `ul` / `ol` 的序号、`a` 的下划线之后,**富文本(markdown)需要自行复权** ——
|
|
55
|
+
* 富文本排版目前没有合规归属(见 `@manohub/kit/CONTRACT.md` §10 的已知缺口),
|
|
56
|
+
* 消费方要为自己的富文本容器类补回 `list-style`、链接色与下划线、段落边距。
|
|
57
|
+
* 本文件有意**不含** `.mh-markdown` 一类的富文本预设:那是独立的一件事,不混进元素基线。
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/* ===== 盒模型与边框:边框属性归零(对齐 Preflight,`border: 1px solid …` 写法不受影响) ===== */
|
|
61
|
+
:where([data-manohub-ui]),
|
|
62
|
+
:where([data-manohub-ui]) *,
|
|
63
|
+
:where([data-manohub-ui]) *::before,
|
|
64
|
+
:where([data-manohub-ui]) *::after {
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
border-width: 0;
|
|
67
|
+
border-style: solid;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ===== 容器基座:字族 / 字号 / 行高 / 字色 / 底色 / 整链高度(本文件唯一不带 :where() 的一条) ===== */
|
|
71
|
+
[data-manohub-ui] {
|
|
72
|
+
font-family: var(--ui-font-family);
|
|
73
|
+
font-size: var(--ui-font-body);
|
|
74
|
+
line-height: var(--ui-line-body);
|
|
75
|
+
color: var(--ui-base-content);
|
|
76
|
+
background: var(--ui-base-100);
|
|
77
|
+
height: 100%;
|
|
78
|
+
min-width: 320px;
|
|
79
|
+
font-synthesis: none;
|
|
80
|
+
text-rendering: optimizeLegibility;
|
|
81
|
+
-webkit-font-smoothing: antialiased;
|
|
82
|
+
-moz-osx-font-smoothing: grayscale;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ===== 块级元素的默认外边距归零 ===== */
|
|
86
|
+
:where([data-manohub-ui]) h1,
|
|
87
|
+
:where([data-manohub-ui]) h2,
|
|
88
|
+
:where([data-manohub-ui]) h3,
|
|
89
|
+
:where([data-manohub-ui]) h4,
|
|
90
|
+
:where([data-manohub-ui]) h5,
|
|
91
|
+
:where([data-manohub-ui]) h6,
|
|
92
|
+
:where([data-manohub-ui]) p,
|
|
93
|
+
:where([data-manohub-ui]) figure,
|
|
94
|
+
:where([data-manohub-ui]) blockquote,
|
|
95
|
+
:where([data-manohub-ui]) dl,
|
|
96
|
+
:where([data-manohub-ui]) dd,
|
|
97
|
+
:where([data-manohub-ui]) pre,
|
|
98
|
+
:where([data-manohub-ui]) hr {
|
|
99
|
+
margin: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* 标题回归正文档:字阶一律由使用方(组件面 / 页面样式)决定,浏览器默认的 2em / bold 不再参与 */
|
|
103
|
+
:where([data-manohub-ui]) h1,
|
|
104
|
+
:where([data-manohub-ui]) h2,
|
|
105
|
+
:where([data-manohub-ui]) h3,
|
|
106
|
+
:where([data-manohub-ui]) h4,
|
|
107
|
+
:where([data-manohub-ui]) h5,
|
|
108
|
+
:where([data-manohub-ui]) h6 {
|
|
109
|
+
font-size: inherit;
|
|
110
|
+
font-weight: inherit;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ===== 列表:去序号、去缩进(富文本自行复权,见文件头「富文本须知」) ===== */
|
|
114
|
+
:where([data-manohub-ui]) ul,
|
|
115
|
+
:where([data-manohub-ui]) ol,
|
|
116
|
+
:where([data-manohub-ui]) menu {
|
|
117
|
+
margin: 0;
|
|
118
|
+
padding: 0;
|
|
119
|
+
list-style: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* ===== 链接:继承文字色,下划线交还使用方(链接态由使用方叠加) ===== */
|
|
123
|
+
:where([data-manohub-ui]) a {
|
|
124
|
+
color: inherit;
|
|
125
|
+
text-decoration: inherit;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* ===== 表单控件:清掉浏览器默认外观,字体与颜色继承上下文 ===== */
|
|
129
|
+
:where([data-manohub-ui]) button,
|
|
130
|
+
:where([data-manohub-ui]) input,
|
|
131
|
+
:where([data-manohub-ui]) optgroup,
|
|
132
|
+
:where([data-manohub-ui]) select,
|
|
133
|
+
:where([data-manohub-ui]) textarea {
|
|
134
|
+
margin: 0;
|
|
135
|
+
padding: 0;
|
|
136
|
+
font: inherit;
|
|
137
|
+
color: inherit;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
:where([data-manohub-ui]) button,
|
|
141
|
+
:where([data-manohub-ui]) [type='button'],
|
|
142
|
+
:where([data-manohub-ui]) [type='reset'],
|
|
143
|
+
:where([data-manohub-ui]) [type='submit'] {
|
|
144
|
+
background-color: transparent;
|
|
145
|
+
background-image: none;
|
|
146
|
+
text-transform: none;
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
:where([data-manohub-ui]) select {
|
|
151
|
+
text-transform: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
:where([data-manohub-ui]) textarea {
|
|
155
|
+
resize: vertical;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
:where([data-manohub-ui]) :disabled {
|
|
159
|
+
cursor: default;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
:where([data-manohub-ui]) [type='search'] {
|
|
163
|
+
outline-offset: -2px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* ===== 媒体元素:转块级(消除行内基线间隙),宽度不溢出容器 ===== */
|
|
167
|
+
:where([data-manohub-ui]) img,
|
|
168
|
+
:where([data-manohub-ui]) svg,
|
|
169
|
+
:where([data-manohub-ui]) video,
|
|
170
|
+
:where([data-manohub-ui]) canvas,
|
|
171
|
+
:where([data-manohub-ui]) audio,
|
|
172
|
+
:where([data-manohub-ui]) iframe,
|
|
173
|
+
:where([data-manohub-ui]) embed,
|
|
174
|
+
:where([data-manohub-ui]) object {
|
|
175
|
+
display: block;
|
|
176
|
+
vertical-align: middle;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
:where([data-manohub-ui]) img,
|
|
180
|
+
:where([data-manohub-ui]) video {
|
|
181
|
+
max-width: 100%;
|
|
182
|
+
height: auto;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* ===== 行内语义与文本节点 ===== */
|
|
186
|
+
:where([data-manohub-ui]) b,
|
|
187
|
+
:where([data-manohub-ui]) strong {
|
|
188
|
+
font-weight: bolder;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:where([data-manohub-ui]) code,
|
|
192
|
+
:where([data-manohub-ui]) kbd,
|
|
193
|
+
:where([data-manohub-ui]) samp,
|
|
194
|
+
:where([data-manohub-ui]) pre {
|
|
195
|
+
font-family: var(--ui-font-mono);
|
|
196
|
+
font-size: 1em;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
:where([data-manohub-ui]) small {
|
|
200
|
+
font-size: 80%;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
:where([data-manohub-ui]) summary {
|
|
204
|
+
display: list-item;
|
|
205
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manohub/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "AIHub 自绘组件层:不依赖 farris 的手写 Vue TSX 组件 + 自带令牌层(Farris 规范视觉 · daisyUI 式语义令牌 · shadcn 式 API 词汇)。",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"vue": "^3.5.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@manohub/icon": "^0.
|
|
49
|
+
"@manohub/icon": "^0.7.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^24.0.0",
|