@manohub/ui 0.8.2 → 0.10.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 +14 -8
- package/dist/components/button/index.d.ts +8 -8
- package/dist/components/checkbox/index.js +5 -1
- package/dist/components/code-block/index.d.ts +776 -0
- package/dist/components/code-block/index.js +335 -0
- package/dist/components/dialog/index.d.ts +3 -3
- package/dist/components/dialog/index.js +5 -5
- package/dist/components/filter/index.d.ts +8 -2
- package/dist/components/filter/index.js +11 -20
- package/dist/components/form/index.d.ts +39 -0
- package/dist/components/form/index.js +6 -0
- package/dist/components/input/index.d.ts +48 -7
- package/dist/components/input/index.js +23 -3
- package/dist/components/notice/index.d.ts +1 -1
- package/dist/components/notice/index.js +4 -4
- package/dist/components/notification/index.d.ts +1 -1
- package/dist/components/notification/index.js +5 -5
- package/dist/components/radio/index.js +29 -3
- package/dist/components/search/index.js +37 -35
- package/dist/components/select/index.js +1 -3
- package/dist/components/select/select-trigger.d.ts +4 -2
- package/dist/components/select/select-trigger.js +9 -4
- package/dist/components/table/index.d.ts +19 -8
- package/dist/components/table/index.js +3 -3
- package/dist/components/tag/index.d.ts +1 -1
- package/dist/components/text/index.d.ts +4 -3
- package/dist/components/toast/index.d.ts +4 -4
- package/dist/components/toast/index.js +16 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -4
- package/dist/services/dialog.d.ts +1 -1
- package/dist/styles/components/avatar.css +4 -1
- package/dist/styles/components/button.css +2 -0
- package/dist/styles/components/code-block.css +216 -0
- package/dist/styles/components/code-block.tokens.css +40 -0
- package/dist/styles/components/dialog.css +3 -3
- package/dist/styles/components/filter.css +22 -34
- package/dist/styles/components/input.css +24 -0
- package/dist/styles/components/select.css +3 -4
- package/dist/styles/components/table.css +33 -22
- package/dist/styles/components/table.tokens.css +6 -6
- package/dist/styles/components/text.css +10 -0
- package/dist/styles/components/toast.css +35 -6
- package/dist/styles/components/upload.css +1 -0
- package/dist/styles/index.css +7 -8
- package/dist/styles/reset.css +52 -167
- package/package.json +2 -2
- package/dist/components/code/index.d.ts +0 -134
- package/dist/components/code/index.js +0 -117
- package/dist/components/code-editor/index.d.ts +0 -163
- package/dist/components/code-editor/index.js +0 -98
- package/dist/styles/components/code-editor.css +0 -91
- package/dist/styles/components/code-editor.tokens.css +0 -24
- package/dist/styles/components/code.css +0 -153
- package/dist/styles/components/code.tokens.css +0 -29
- package/dist/styles/components/filter.tokens.css +0 -14
|
@@ -99,7 +99,7 @@ export declare const Toast: import("vue").DefineComponent<import("vue").ExtractP
|
|
|
99
99
|
onClose?: (() => any) | undefined;
|
|
100
100
|
}>, {
|
|
101
101
|
text: string;
|
|
102
|
-
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";
|
|
102
|
+
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" | "info-circle" | "check-circle" | "alert-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
|
|
103
103
|
closable: boolean;
|
|
104
104
|
tone: ToastTone;
|
|
105
105
|
action: string;
|
|
@@ -151,7 +151,7 @@ export declare const ToastCompound: {
|
|
|
151
151
|
close: () => true;
|
|
152
152
|
}, import("vue").PublicProps, {
|
|
153
153
|
text: string;
|
|
154
|
-
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";
|
|
154
|
+
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" | "info-circle" | "check-circle" | "alert-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
|
|
155
155
|
closable: boolean;
|
|
156
156
|
tone: ToastTone;
|
|
157
157
|
action: string;
|
|
@@ -205,7 +205,7 @@ export declare const ToastCompound: {
|
|
|
205
205
|
onClose?: (() => any) | undefined;
|
|
206
206
|
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, {
|
|
207
207
|
text: string;
|
|
208
|
-
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";
|
|
208
|
+
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" | "info-circle" | "check-circle" | "alert-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
|
|
209
209
|
closable: boolean;
|
|
210
210
|
tone: ToastTone;
|
|
211
211
|
action: string;
|
|
@@ -256,7 +256,7 @@ export declare const ToastCompound: {
|
|
|
256
256
|
close: () => true;
|
|
257
257
|
}, string, {
|
|
258
258
|
text: string;
|
|
259
|
-
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";
|
|
259
|
+
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" | "info-circle" | "check-circle" | "alert-circle" | "list" | "calendar" | "clock" | "lock" | "unlock" | "users" | "archive" | "package" | "plug" | "branch" | "tag" | "ai" | "shield-check" | "shield-alert" | "history";
|
|
260
260
|
closable: boolean;
|
|
261
261
|
tone: ToastTone;
|
|
262
262
|
action: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, onMounted, onBeforeUnmount, createVNode } from "vue";
|
|
1
|
+
import { defineComponent, onMounted, onBeforeUnmount, createVNode, ref, onUpdated } from "vue";
|
|
2
2
|
import { Icon } from "@manohub/icon";
|
|
3
3
|
const TONE_ICON = {
|
|
4
4
|
info: "info",
|
|
@@ -110,7 +110,22 @@ const ToastStack = /* @__PURE__ */ defineComponent({
|
|
|
110
110
|
slots,
|
|
111
111
|
attrs
|
|
112
112
|
}) {
|
|
113
|
+
const rootRef = ref(null);
|
|
114
|
+
const raise = () => {
|
|
115
|
+
const el = rootRef.value;
|
|
116
|
+
if (!el) return;
|
|
117
|
+
if (!el.hasAttribute("popover")) el.setAttribute("popover", "manual");
|
|
118
|
+
if (typeof el.showPopover !== "function") return;
|
|
119
|
+
try {
|
|
120
|
+
if (el.matches(":popover-open")) el.hidePopover();
|
|
121
|
+
el.showPopover();
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
onMounted(raise);
|
|
126
|
+
onUpdated(raise);
|
|
113
127
|
return () => createVNode("div", {
|
|
128
|
+
"ref": rootRef,
|
|
114
129
|
"class": ["mh-toast-stack", attrs.class].filter(Boolean).join(" "),
|
|
115
130
|
"style": attrs.style
|
|
116
131
|
}, [slots.default?.()]);
|
package/dist/index.d.ts
CHANGED
|
@@ -50,8 +50,7 @@ export { Pagination, type PaginationPageItem } from './components/pagination';
|
|
|
50
50
|
export { TabBar, type TabBarOption, type TabBarValue } from './components/tabbar';
|
|
51
51
|
export { Steps, type CanJump, type StepsItem, type StepsVariant, type StepsCompound, type StepsCompoundType, } from './components/steps';
|
|
52
52
|
export { Toast, type ToastTone, type ToastCompound, type ToastCompoundType, } from './components/toast';
|
|
53
|
-
export {
|
|
54
|
-
export { CodeEditor, type CodeEditorProps, type CodeEditorAutoSize, } from './components/code-editor';
|
|
53
|
+
export { CodeBlock, type CodeBlockProps, type CodeEditorAutoSize, type CodeBlockCompound, type CodeBlockCompoundType, } from './components/code-block';
|
|
55
54
|
export { Upload, formatFileSize, type UploadFile, type UploadCompound, type UploadCompoundType, } from './components/upload';
|
|
56
55
|
export { QueryState, type QueryStateKind, type QueryStateProps } from './components/query-state';
|
|
57
56
|
export { Loading, type LoadingOverlay, type LoadingProps } from './components/loading';
|
package/dist/index.js
CHANGED
|
@@ -33,8 +33,7 @@ import { Pagination } from "./components/pagination/index.js";
|
|
|
33
33
|
import { TabBar } from "./components/tabbar/index.js";
|
|
34
34
|
import { Steps } from "./components/steps/index.js";
|
|
35
35
|
import { Toast } from "./components/toast/index.js";
|
|
36
|
-
import {
|
|
37
|
-
import { CodeEditor } from "./components/code-editor/index.js";
|
|
36
|
+
import { CodeBlock } from "./components/code-block/index.js";
|
|
38
37
|
import { Upload, formatFileSize } from "./components/upload/index.js";
|
|
39
38
|
import { QueryState } from "./components/query-state/index.js";
|
|
40
39
|
import { Loading } from "./components/loading/index.js";
|
|
@@ -51,8 +50,7 @@ export {
|
|
|
51
50
|
Capsule,
|
|
52
51
|
Card,
|
|
53
52
|
Checkbox,
|
|
54
|
-
|
|
55
|
-
CodeEditor,
|
|
53
|
+
CodeBlock,
|
|
56
54
|
Collapse,
|
|
57
55
|
Dialog,
|
|
58
56
|
Divider,
|
|
@@ -5,7 +5,7 @@ export interface ConfirmOptions {
|
|
|
5
5
|
/** 正文(纯文本;复杂内容请直接用 `Dialog` 组件) */
|
|
6
6
|
detail?: string;
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* 语义档(决定标题左侧的带圈语义图标与配色):`info` / `success` / `warning` / `error`。
|
|
9
9
|
*
|
|
10
10
|
* 不传则无图标。**危险操作用 `error`** —— 它同时把确定按钮染成危险色
|
|
11
11
|
* (除非显式给了 `okDanger`),这样「删除确认」与「保存成功」不再长得一样。
|
|
@@ -22,8 +22,11 @@
|
|
|
22
22
|
color: var(--ui-base-100); /* 占位前景 */
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/* 图片:撑满 + 跟随形态自裁(否则去掉容器 overflow
|
|
25
|
+
/* 图片:撑满 + 跟随形态自裁(否则去掉容器 overflow 后长宽不符的图会外溢)。
|
|
26
|
+
`display: block` 必须自己写:元素级基线不再把 `img` 转块级(那条会压消费方的 `h-*` / `hidden`),
|
|
27
|
+
否则行内基线间隙会把圆形头像顶偏。 */
|
|
26
28
|
.mh-avatar > img {
|
|
29
|
+
display: block;
|
|
27
30
|
width: 100%;
|
|
28
31
|
height: 100%;
|
|
29
32
|
border-radius: inherit;
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
font-family: inherit;
|
|
41
41
|
font-size: var(--ui-button-font-size);
|
|
42
42
|
line-height: var(--ui-line-body);
|
|
43
|
+
/* 链接形态时本体就是 `<a>`(见组件层),基线不再代管 `a { text-decoration: inherit }`,这里自己摘掉下划线 */
|
|
44
|
+
text-decoration: none;
|
|
43
45
|
cursor: pointer;
|
|
44
46
|
white-space: nowrap;
|
|
45
47
|
/* 三态补间(底 / 边 / 字 / 影) */
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeBlock —— 代码块族(只读面 + 编辑面 + 语言角标 + 复制位)。
|
|
3
|
+
*
|
|
4
|
+
* 一个**族根** `.mh-code-block` 承载两形态共用的部分(底 / 圆角 / 等宽字族 / 字号 / 行高 / 定位上下文),
|
|
5
|
+
* 形态差异只在**槽位**上:只读面是 `__view`(`<pre>`,横向滚动、缺省不折行),
|
|
6
|
+
* 编辑面是 `__editor`(`<textarea>`,软换行)。两形态共用同一个根 ⇒ 互切时块体不跳,
|
|
7
|
+
* 且"同源"是**一处定义**(`code-block.tokens.css`),不是两处巧合。
|
|
8
|
+
*
|
|
9
|
+
* 观感基准:**无边框浅底块 + 方圆角 + 右上角语言角标 + 悬浮/聚焦让位后出现的方形图标复制按钮**。
|
|
10
|
+
*
|
|
11
|
+
* ## 三件结构决定(改前先读)
|
|
12
|
+
*
|
|
13
|
+
* - **复制按钮的面仍归按钮族**(`.mh-button--icon`),本族只补「浮在代码面上需要自己的底与定位」;
|
|
14
|
+
* 故标记是 `class="mh-button mh-button--icon mh-code-block__copy"`。
|
|
15
|
+
* - **复制按钮与语言角标都不能放进代码面里**:只读面是 `overflow-x: auto` 的滚动容器,会裁掉
|
|
16
|
+
* 外挂的绝对定位件 —— 故两者都挂在**族根**上(族根只做 `position: relative`)。
|
|
17
|
+
* - **隐藏用 `opacity` + `pointer-events`**(不是 `visibility` / `display`):键盘仍能 Tab 到它,
|
|
18
|
+
* `:focus-within` 会把它显出来,且隐藏时不残留一块看不见的可点区。
|
|
19
|
+
* - **编辑面画框的是根**(圆角归根、面自身透明无框):原生 `textarea` 的框模型(内距 / 滚动条 /
|
|
20
|
+
* 聚焦轮廓)会把框画歪,收归根才能与只读面对齐(旧实现同此口径)。
|
|
21
|
+
*
|
|
22
|
+
* ## 本族与按钮族的层序
|
|
23
|
+
*
|
|
24
|
+
* `styles/index.css` 里 `code-block.css` 在 `button.css` **之前**导入,故 `background` / `color` /
|
|
25
|
+
* `box-shadow` 这些**同特异性的声明会被按钮族的档位规则压掉**(历史 bug:复制位的白底被
|
|
26
|
+
* `.mh-button--text { background: transparent }` 压成透明,看起来像一段悬空文字)。
|
|
27
|
+
* 修法不是调层序,而是让本族的声明**升一档特异性**(`.mh-code-block > .mh-code-block__copy`,
|
|
28
|
+
* 悬停 / 成功态再各叠一层)—— 按钮族日后换皮肤也压不掉它。
|
|
29
|
+
*
|
|
30
|
+
* 零 JS 可表达:全部皮肤 + 角标让位 + 复制位的显隐。**真正的复制动作归组件层**(要 `navigator.clipboard`)。
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/* ===== 族根:两形态共用的底 / 圆角 / 字族,以及角标与复制位的定位上下文 ===== */
|
|
34
|
+
.mh-code-block {
|
|
35
|
+
position: relative;
|
|
36
|
+
min-width: 0; /* flex / grid 里能被压到容器宽(否则长行的 min-content 会把轨道撑宽、页面横向溢出) */
|
|
37
|
+
border-radius: var(--ui-code-block-radius);
|
|
38
|
+
background: var(--ui-code-block-bg);
|
|
39
|
+
font-family: var(--ui-font-mono);
|
|
40
|
+
font-size: var(--ui-code-block-font-size);
|
|
41
|
+
line-height: var(--ui-code-block-line-height);
|
|
42
|
+
color: var(--ui-base-content);
|
|
43
|
+
}
|
|
44
|
+
/* 聚焦环:与输入框族同一句(主色弱底当环,不新造阴影令牌)。**只在编辑档**给 ——
|
|
45
|
+
只读面本身不可聚焦,给它加环会在「键盘聚焦复制位」时冒出一圈(只读块从前没有这一圈,保持原样)。 */
|
|
46
|
+
.mh-code-block--editable {
|
|
47
|
+
transition: box-shadow 0.15s ease, background-color 0.15s ease, color 0.15s ease;
|
|
48
|
+
}
|
|
49
|
+
.mh-code-block--editable:focus-within {
|
|
50
|
+
box-shadow: 0 0 0 2px var(--ui-primary-weak);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ===== 只读面(`__view`):`<pre>` —— 缺省横向滚动(缩进与列对齐不被破坏),`--wrap` 档才软换行 ===== */
|
|
54
|
+
.mh-code-block__view {
|
|
55
|
+
display: block;
|
|
56
|
+
margin: var(--ui-space-2) 0 0;
|
|
57
|
+
padding: var(--ui-code-block-padding);
|
|
58
|
+
border: 0;
|
|
59
|
+
border-radius: inherit;
|
|
60
|
+
font: inherit;
|
|
61
|
+
color: inherit;
|
|
62
|
+
overflow-x: auto;
|
|
63
|
+
white-space: pre;
|
|
64
|
+
overflow-wrap: normal;
|
|
65
|
+
}
|
|
66
|
+
.mh-code-block--wrap > .mh-code-block__view {
|
|
67
|
+
white-space: pre-wrap;
|
|
68
|
+
overflow-wrap: anywhere;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ===== 编辑面(`__editor`):`<textarea>` 透明底 + 无框 + 无 outline(框与聚焦环都画在族根上) ===== */
|
|
72
|
+
.mh-code-block__editor {
|
|
73
|
+
display: block;
|
|
74
|
+
width: 100%;
|
|
75
|
+
margin: 0;
|
|
76
|
+
padding: var(--ui-code-block-editor-padding-y) var(--ui-code-block-editor-padding-x);
|
|
77
|
+
border: 0;
|
|
78
|
+
border-radius: inherit;
|
|
79
|
+
background: transparent;
|
|
80
|
+
font: inherit;
|
|
81
|
+
line-height: inherit;
|
|
82
|
+
color: inherit;
|
|
83
|
+
outline: none;
|
|
84
|
+
resize: none; /* 高度由 autoSize / maxHeight 决定,不留拖拽把手(同只读面:不被用户拖变形) */
|
|
85
|
+
overflow: auto;
|
|
86
|
+
tab-size: 2;
|
|
87
|
+
}
|
|
88
|
+
.mh-code-block__editor::placeholder {
|
|
89
|
+
color: var(--ui-base-content-subtle);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* 只读档(原生 `readonly`:仍可选中、可滚动、可复制,只是不可改)——**不弱化字色**,
|
|
93
|
+
代码是拿来读的;只是光标不再是文本输入那一支(与只读面观感一致) */
|
|
94
|
+
.mh-code-block--editable:has(> .mh-code-block__editor[readonly]) {
|
|
95
|
+
cursor: default;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* 禁用档:底与字色弱化 + 内描边(本族没有外描边,靠内描边表达"锁住") */
|
|
99
|
+
.mh-code-block--editable:has(> .mh-code-block__editor:disabled) {
|
|
100
|
+
background: var(--ui-base-100);
|
|
101
|
+
color: var(--ui-base-content-subtle);
|
|
102
|
+
box-shadow: inset 0 0 0 1px var(--ui-base-300);
|
|
103
|
+
}
|
|
104
|
+
.mh-code-block--editable:has(> .mh-code-block__editor:disabled) > .mh-code-block__editor {
|
|
105
|
+
cursor: not-allowed;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* ===== 语言角标(可选):两形态的槽位**有意不同** =====
|
|
109
|
+
* 共用部分(绝对定位 + 等宽小字 + 不吃指针)写在基类;
|
|
110
|
+
* 只读面与复制位**同槽位**(等高 32),悬停 / 聚焦时淡出让位(零 JS 互斥);
|
|
111
|
+
* 编辑面**不叠在文字上**(内容会折行,压住就看不见了),而是让首行右端**预留**出它的宽度。 */
|
|
112
|
+
.mh-code-block__lang {
|
|
113
|
+
position: absolute;
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
font-family: var(--ui-font-mono);
|
|
117
|
+
font-size: var(--ui-code-block-font-size);
|
|
118
|
+
line-height: 1;
|
|
119
|
+
color: var(--ui-base-content-subtle);
|
|
120
|
+
user-select: none;
|
|
121
|
+
pointer-events: none; /* 装饰位不吃指针事件,否则会挡住复制位的悬停热区 */
|
|
122
|
+
}
|
|
123
|
+
/* 只读档:与复制位同槽位(让位互换时基线不跳) */
|
|
124
|
+
.mh-code-block:not(.mh-code-block--editable) > .mh-code-block__lang {
|
|
125
|
+
top: var(--ui-code-block-copy-inset);
|
|
126
|
+
right: var(--ui-code-block-copy-inset);
|
|
127
|
+
height: var(--ui-code-block-copy-size);
|
|
128
|
+
transition: opacity 0.15s ease;
|
|
129
|
+
}
|
|
130
|
+
.mh-code-block:not(.mh-code-block--editable):hover > .mh-code-block__lang,
|
|
131
|
+
.mh-code-block:not(.mh-code-block--editable):focus-within > .mh-code-block__lang,
|
|
132
|
+
.mh-code-block.is-hover > .mh-code-block__lang {
|
|
133
|
+
opacity: 0;
|
|
134
|
+
}
|
|
135
|
+
/* 编辑档:贴编辑面的右上角,并给编辑面首行右端预留出它的宽度 */
|
|
136
|
+
.mh-code-block--editable > .mh-code-block__lang {
|
|
137
|
+
top: var(--ui-code-block-editor-padding-y);
|
|
138
|
+
right: var(--ui-code-block-editor-padding-x);
|
|
139
|
+
height: var(--ui-code-block-line-height);
|
|
140
|
+
}
|
|
141
|
+
.mh-code-block--editable:has(> .mh-code-block__lang) > .mh-code-block__editor {
|
|
142
|
+
padding-right: calc(var(--ui-code-block-editor-padding-x) + var(--ui-code-block-lang-reserve));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* ===== 行内 chip(`--inline`,挂在 `<code>` 上即自身为根;`--plain` 是它的中性档) ===== */
|
|
146
|
+
.mh-code-block--inline {
|
|
147
|
+
display: inline-flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
padding: 1px var(--ui-space-3);
|
|
150
|
+
border-radius: var(--ui-radius-full);
|
|
151
|
+
background: var(--ui-code-block-chip-bg);
|
|
152
|
+
color: var(--ui-primary);
|
|
153
|
+
/* 行内 chip 回到「继承外部行高」(改动前它不声明行高,族根那枚等宽行高是给代码面的)——
|
|
154
|
+
同一元素上两条规则,后者胜出,故这里写 inherit 即等价于旧行为 */
|
|
155
|
+
line-height: inherit;
|
|
156
|
+
}
|
|
157
|
+
/* 中性档(规范 `.chip--plain`:规则 ID 这类不强调的短标识) */
|
|
158
|
+
.mh-code-block--plain {
|
|
159
|
+
background: var(--ui-code-block-bg);
|
|
160
|
+
color: var(--ui-base-content);
|
|
161
|
+
border-radius: var(--ui-code-block-radius);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* ===== 复制位(面归按钮族,本族只给定位、浮底、方形几何、显隐) =====
|
|
165
|
+
* 选择器**刻意升一档**(`.mh-code-block >`):同特异性下按钮族的档位规则会压掉这几条(见文件头) */
|
|
166
|
+
.mh-code-block > .mh-code-block__copy {
|
|
167
|
+
position: absolute;
|
|
168
|
+
top: var(--ui-code-block-copy-inset);
|
|
169
|
+
right: var(--ui-code-block-copy-inset);
|
|
170
|
+
width: var(--ui-code-block-copy-size);
|
|
171
|
+
height: var(--ui-code-block-copy-size);
|
|
172
|
+
padding: 0;
|
|
173
|
+
border: 1px solid var(--ui-code-block-line);
|
|
174
|
+
border-radius: var(--ui-radius-sm);
|
|
175
|
+
background: var(--ui-base-100);
|
|
176
|
+
color: var(--ui-base-content);
|
|
177
|
+
box-shadow: none; /* 压掉图标按钮 hover 档的卡片光晕(本件浮在块上,再加影会脏) */
|
|
178
|
+
opacity: 0;
|
|
179
|
+
pointer-events: none;
|
|
180
|
+
transition: opacity 0.15s ease, border-color 0.15s ease, color 0.15s ease;
|
|
181
|
+
}
|
|
182
|
+
/* 显形:族根悬停 / 键盘聚焦进入(`.is-hover` 是**静态档**,供静态页与读图对状态,与全库同款三源等价) */
|
|
183
|
+
.mh-code-block:hover > .mh-code-block__copy,
|
|
184
|
+
.mh-code-block:focus-within > .mh-code-block__copy,
|
|
185
|
+
.mh-code-block.is-hover > .mh-code-block__copy {
|
|
186
|
+
opacity: 1;
|
|
187
|
+
pointer-events: auto;
|
|
188
|
+
}
|
|
189
|
+
/* 悬停 / 键盘聚焦的加深档(再叠一层,压过 `.mh-button--icon:hover` 的字色与光晕) */
|
|
190
|
+
.mh-code-block > .mh-code-block__copy:hover,
|
|
191
|
+
.mh-code-block > .mh-code-block__copy:focus-visible,
|
|
192
|
+
.mh-code-block.is-hover > .mh-code-block__copy {
|
|
193
|
+
border-color: var(--ui-base-content-subtle);
|
|
194
|
+
color: var(--ui-primary);
|
|
195
|
+
box-shadow: none;
|
|
196
|
+
}
|
|
197
|
+
/* 复制成功态(组件下发 `data-state`;原生无此态,静态档 `.is-copied` 供读图) */
|
|
198
|
+
.mh-code-block > .mh-code-block__copy.is-copied,
|
|
199
|
+
.mh-code-block > .mh-code-block__copy[data-state='copied'] {
|
|
200
|
+
border-color: var(--ui-success);
|
|
201
|
+
color: var(--ui-success);
|
|
202
|
+
opacity: 1;
|
|
203
|
+
pointer-events: auto;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* 无悬停能力的设备(触屏):复制位常显;角标让位(`display: none` 而非透明 —— 它只是装饰,
|
|
207
|
+
不占焦点序列,隐藏掉才不会与常显的复制位叠在一起) */
|
|
208
|
+
@media (hover: none) {
|
|
209
|
+
.mh-code-block > .mh-code-block__copy {
|
|
210
|
+
opacity: 1;
|
|
211
|
+
pointer-events: auto;
|
|
212
|
+
}
|
|
213
|
+
.mh-code-block:not(.mh-code-block--editable) > .mh-code-block__lang {
|
|
214
|
+
display: none;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* code-block —— 单件令牌(**基础值**)。
|
|
3
|
+
*
|
|
4
|
+
* 本族自己的几何 / 尺寸 / 色彩槽位;只服务本族,故不随主题进 `@manohub/theme`。
|
|
5
|
+
*
|
|
6
|
+
* ## 两形态共用同一份令牌
|
|
7
|
+
*
|
|
8
|
+
* 只读面(`__view`)与编辑面(`__editor`)**共用**底 / 圆角 / 字族 / 字号 / 行高这几枚 ——
|
|
9
|
+
* 这正是「视觉同源、互切不跳」的落点:一处定义,两形态一起变。
|
|
10
|
+
* 从前是两套单件令牌各写一份同值(`--ui-code-*` 与 `--ui-code-editor-*`),
|
|
11
|
+
* 靠注释互相提醒"要一致";0.9.0 收成一族(见 `docs/guide/migration-0-9.md`)。
|
|
12
|
+
*
|
|
13
|
+
* 两形态**有意不同**的只有内距:只读面上下 12(与左右齐)、编辑面上下 8
|
|
14
|
+
* (`textarea` 的行高自带行距,上下再给 12 会显得空)—— 它们各自保留一枚令牌。
|
|
15
|
+
*
|
|
16
|
+
* ## 抽出说明
|
|
17
|
+
*
|
|
18
|
+
* 这些是**基础值**,锚在 `[data-manohub-ui]` —— 跨包唯一作用域锚,由入口层无条件写在应用容器上,
|
|
19
|
+
* 因此**任何落在容器里的分件都取得到值**(历史症状:跨件消费的 `--ui-*-group-*` 取不到值,组内间距变 0)。
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ `.mh-<件>--<档>` 这类**档位改写**留在面文件的修饰符块里 —— 它们靠「同一元素上两个
|
|
22
|
+
* 选择器改写同一个令牌」生效,搬到本文件会让档位失效。
|
|
23
|
+
* ⚠️ 新增组件要登记两处:本文件 + `src/styles/index.css`(见其文件头「五处齐备」)。
|
|
24
|
+
*/
|
|
25
|
+
[data-manohub-ui] {
|
|
26
|
+
/* 单件令牌(挂在容器上:族根 / 只读面 / 编辑面 / 复制位都在其下) */
|
|
27
|
+
--ui-code-block-bg: var(--ui-base-200); /* 代码面底(只读块与编辑框同底 —— 互切的"不跳"靠它) */
|
|
28
|
+
--ui-code-block-chip-bg: var(--ui-primary-weak); /* 行内 chip 底(规范 Au02) */
|
|
29
|
+
--ui-code-block-line: var(--ui-base-300); /* 描边色:面自身无边框,本令牌现服务复制位按钮 */
|
|
30
|
+
--ui-code-block-radius: var(--ui-radius-control);
|
|
31
|
+
--ui-code-block-font-size: var(--ui-font-caption); /* 规范等宽字号档对位 */
|
|
32
|
+
--ui-code-block-line-height: var(--ui-line-caption); /* 等宽行高:角标与复制位也吃它 */
|
|
33
|
+
--ui-code-block-padding: var(--ui-space-3); /* 12:只读面四边内距 */
|
|
34
|
+
--ui-code-block-editor-padding-x: var(--ui-space-3); /* 12:编辑面左右内距 */
|
|
35
|
+
--ui-code-block-editor-padding-y: var(--ui-space-2); /* 8:编辑面上下内距(比只读面小,见文件头) */
|
|
36
|
+
--ui-code-block-lang-reserve: 56px; /* 编辑面:首行右端给角标预留的宽度(只影响折行位置) */
|
|
37
|
+
--ui-code-block-copy-size: var(--ui-control-height-md); /* 32:复制位方形热区(与按钮族标准档同高) */
|
|
38
|
+
/* 复制位是 `Button`(`mh-button__icon`):字形尺寸归按钮族的图标槽(常规图标档),本族不另设令牌 */
|
|
39
|
+
--ui-code-block-copy-inset: var(--ui-space-2); /* 8:复制位 / 角标距块边 */
|
|
40
|
+
}
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
font-weight: var(--ui-weight-medium);
|
|
59
59
|
color: var(--ui-base-content);
|
|
60
60
|
}
|
|
61
|
-
/* 语义档(`tone
|
|
62
|
-
缺省(不传 tone
|
|
63
|
-
|
|
61
|
+
/* 语义档(`tone`):标题左侧一个**带圈语义图标**(图标位没有底色圆,故取带圈族 —— 见
|
|
62
|
+
`@manohub/icon` 的「两族」口径),颜色按档取语义色 —— 缺省(不传 tone)不渲染,故不影响既有外观。
|
|
63
|
+
取色口径与 `Notice` 同一张表(success / warning 取 -strong 档,否则浅底上对比度不足)。 */
|
|
64
64
|
.mh-dialog__tone-icon {
|
|
65
65
|
flex: none;
|
|
66
66
|
width: var(--ui-font-icon);
|
|
@@ -1,41 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filter
|
|
2
|
+
* Filter(筛选条):**本件无自有面 —— 零规则**。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 它现在是一层**纯壳**:只给 `Form` 传「排布档 + label 列宽(可选)+ 值模型 + 字段区回车」,
|
|
5
|
+
* 字段行的排布与几何**全部沿用 `Form`**:
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 1
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* 1. 字段排布 = `Form` 的多列动态档(本件传 `columns="auto"`)—— 网格轨道**跨行共用**,
|
|
8
|
+
* 因此换行下来的字段与上一行**逐列对齐**。从前本件自建 flex 字段区
|
|
9
|
+
* (`flex: 1 1 240px` + `wrap`),而 flex 的 `grow` 是**按行分配**的:末行只剩一项时
|
|
10
|
+
* 它独占该行剩余宽度,被拉成通栏 —— 那正是本件 2026-09 交出机制的起因;
|
|
11
|
+
* 2. label 列宽 / 行距 / 列距 / 字段最小宽 = `Form` 的默认档(令牌 + `.mh-form` 的 8px 档)。
|
|
12
|
+
* 本件**不设默认值、也不落行内值** —— 写死就是第二份默认值,`Form` 调档时不会跟着变;
|
|
13
|
+
* 消费方要收紧筛选条的几何,在容器上覆盖 `Form` 的那两个令牌即可(继承生效);
|
|
14
|
+
* 3. 表头(`Form.Header`)与字段行(`Form.Item`)一律沿用 `Form`,本件不重画任何一个。
|
|
11
15
|
*
|
|
12
|
-
*
|
|
13
|
-
* 上行高 32(右侧两颗按钮)、下行字段「标签 + 10±2px + 控件(高 32 / 圆角 6 / 边 --ui-base-300)」。
|
|
16
|
+
* ## 为什么还留着这个文件(而不是删掉)
|
|
14
17
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* 由页面承担;本件画了就会与页面的线叠成双线。
|
|
18
|
+
* 「组件与面一一配对」是本包的机械护栏(用例 `contract-class-surface` 要求每个组件目录
|
|
19
|
+
* 都有同名面文件)。本件确实没有自己的类与几何,故这里只留说明文字。它对外的唯一类名是
|
|
20
|
+
* `.mh-filter__form` —— **结构锚点**(消费方与用例靠它定位这个壳,几何沿用 `.mh-form`),
|
|
21
|
+
* 已登记在共用台账「只做结构 / 测试锚点、面上没有样式声明的类」里。
|
|
20
22
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* ## 与设计稿的关系
|
|
24
|
+
*
|
|
25
|
+
* 稿(Figma「MH后台 0911」node 0:3355,页面「01.1 技能权限分配」的筛选区)只用来确定
|
|
26
|
+
* **筛选条由哪些部件组成**(上行两颗按钮 + 下行若干字段);几何**不再照抄**稿里的
|
|
27
|
+
* 68 / 16 / 24 / 240,自 2026-09 起统一走 `Form` 的默认档 —— 取舍见
|
|
28
|
+
* `components/filter/index.tsx` 的文件头。
|
|
24
29
|
*/
|
|
25
|
-
|
|
26
|
-
/* 字段区:列距 24 / 行距 16,窄了整体换行(不压缩控件高度、不截断标签)。
|
|
27
|
-
字段区是 `Form` 的直接子节点(`Form.Header` 归位在最前),以下均为 `Form.Item` 自身。 */
|
|
28
|
-
.mh-filter__fields {
|
|
29
|
-
display: flex;
|
|
30
|
-
flex-wrap: wrap;
|
|
31
|
-
align-items: center;
|
|
32
|
-
column-gap: var(--ui-space-6);
|
|
33
|
-
row-gap: var(--ui-space-4);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/* 字段(`Filter.Item` = 挂了这个类的 `Form.Item`):宽度自适应
|
|
37
|
-
—— 够宽均分铺满,不够则换行;label 列宽与控件列取用全部来自 form.css。 */
|
|
38
|
-
.mh-filter__item {
|
|
39
|
-
flex: 1 1 var(--ui-filter-item-min);
|
|
40
|
-
min-width: 0;
|
|
41
|
-
}
|
|
@@ -127,6 +127,30 @@
|
|
|
127
127
|
cursor: pointer;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/* ===== 触发器形态 · 占位文案 =====
|
|
131
|
+
*
|
|
132
|
+
* `<button>` **没有 `::placeholder` 伪元素**,故触发器形态的占位由组件渲染一个 span 承载
|
|
133
|
+
* (判据见 `components/input/index.tsx` 的 `showPlaceholder`)。这里只给它的排版与色。
|
|
134
|
+
*
|
|
135
|
+
* `display: block` 是**必要的**(实测四种父级 × 长/短文案):span 默认是 inline,而 `overflow`
|
|
136
|
+
* 对行内盒不生效 ⇒ 长占位会直接撑破控件;`block` 之后它撑满控件的内容宽、超长走省略号,
|
|
137
|
+
* 且在**父级是 flex**(如 `Select` 的触发器)时会被 blockify,行为与 inline 一致
|
|
138
|
+
* —— 两种父级下都对,故不要求消费方给控件开 flex。`min-width: 0` 供 flex 父级下允许收缩。
|
|
139
|
+
* `flex: 1` 是给**父级是 flex** 的复合件用的(`Select` 的值区`.mh-select__value` 就是这个配方):
|
|
140
|
+
* 实测同样的「占位 + 右侧箭头」在 flex 父级下,不给 `flex: 1` 时占位只有**内容宽**(48px)、
|
|
141
|
+
* 给了才撑满到箭头前(207 / 可用 220)—— 少了它会让选择器的占位区窄成一截。
|
|
142
|
+
* 父级不是 flex 时 `flex` 属性被忽略,故对单件用法无副作用。
|
|
143
|
+
* 色与原生 `.mh-input::placeholder` 同档(弱文本),选择器值区的 `--placeholder` 也是这一档。 */
|
|
144
|
+
.mh-input__placeholder {
|
|
145
|
+
display: block;
|
|
146
|
+
flex: 1;
|
|
147
|
+
min-width: 0;
|
|
148
|
+
overflow: hidden;
|
|
149
|
+
text-overflow: ellipsis;
|
|
150
|
+
white-space: nowrap;
|
|
151
|
+
color: var(--ui-base-content-subtle);
|
|
152
|
+
}
|
|
153
|
+
|
|
130
154
|
/* ===== 触发器形态 · 整箱热区(命中测试重定向,纯 CSS) =====
|
|
131
155
|
*
|
|
132
156
|
* 目的:让**整件**(值 / 标签 + 右侧图标 + 左右内距)都等同于点那个原生触发按钮。
|
|
@@ -66,7 +66,9 @@
|
|
|
66
66
|
height: calc(var(--ui-select-chip-height) - 4px);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/*
|
|
69
|
+
/* 值区:有值时的单选那一行(占满剩余宽、超出省略)。
|
|
70
|
+
⚠️ **无值态不在这里** —— 占位由输入面渲染(`.mh-input__placeholder`,色与截断同档):
|
|
71
|
+
2026-09-29 收敛,此前本文件还有一个 `--placeholder` 修饰类专门给占位上灰字。 */
|
|
70
72
|
.mh-select__value {
|
|
71
73
|
flex: 1;
|
|
72
74
|
min-width: 0;
|
|
@@ -74,9 +76,6 @@
|
|
|
74
76
|
text-overflow: ellipsis;
|
|
75
77
|
white-space: nowrap;
|
|
76
78
|
}
|
|
77
|
-
.mh-select__value--placeholder {
|
|
78
|
-
color: var(--ui-base-content-subtle);
|
|
79
|
-
}
|
|
80
79
|
/* 下拉箭头:渲染在输入面的**右侧图标位**(`.mh-input__suffix`,表壳的子元素)里 ——
|
|
81
80
|
位置由表壳的 flex 排布给(控件 `flex: 1 1 auto` 自然把附加位挤到右端),故不再需要 `margin-left: auto`。
|
|
82
81
|
字形由 @manohub/icon 给;展开转向由 popup.css 的 `.mh-popup-caret` 承担(含触发器进表壳后的兄弟档);
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
border: none;
|
|
80
80
|
border-radius: 0;
|
|
81
81
|
}
|
|
82
|
-
/*
|
|
82
|
+
/* 紧凑档(`size="sm"`):三档 30 / 38 / 46 里的最小档,嵌在卡片 / 面板里的表格用它 */
|
|
83
83
|
.mh-table--xs {
|
|
84
|
-
--ui-table-head-height:
|
|
85
|
-
--ui-table-row-height:
|
|
84
|
+
--ui-table-head-height: 30px;
|
|
85
|
+
--ui-table-row-height: 30px;
|
|
86
86
|
}
|
|
87
87
|
/* 窄屏下的最小宽(触发横向滚动,而不是把列压扁) */
|
|
88
88
|
.mh-table--wide {
|
|
@@ -94,14 +94,21 @@
|
|
|
94
94
|
* 列宽从此**受声明约束、不再被内容撑破** ⇒ 长文本不会把表格撑得比容器还宽,
|
|
95
95
|
* 于是「百分比 / 数字权重」可以「吃满容器 + 严格按比例」。
|
|
96
96
|
*
|
|
97
|
-
*
|
|
97
|
+
* 调用方要知道的:表体**默认不换行**(nowrap + 省略号,见下条);要换行的列显式标 `wrap: true`。 */
|
|
98
98
|
.mh-table--fixed {
|
|
99
99
|
table-layout: fixed;
|
|
100
100
|
}
|
|
101
|
-
/*
|
|
102
|
-
|
|
101
|
+
/* `fixed` 档表体默认**不换行**(nowrap + 省略号)。两条依据:
|
|
102
|
+
* ① 列宽已被 `<colgroup>` 钉死,换行救不回内容,只会把行高顶高(`td` 的 `height` 只是**下限**);
|
|
103
|
+
* ② 换行必然伴随**从字符间断字** —— 实测序号列窄到装不下两位数时,旧的 `overflow-wrap: anywhere`
|
|
104
|
+
* 把 `10` 拆成 `1` / `0` 两行,行高 30 → **49**。
|
|
105
|
+
* 于是「换行」改成**列级主动选择**:`TableColumn.wrap: true`(见 `.mh-table__cell-wrap`)。
|
|
106
|
+
* ⚠️ **只在本档翻默认**:`auto` 档的列宽由内容计算,td 默认 nowrap 会让长文本列不再靠换行收敛、
|
|
107
|
+
* 表格更容易撑破容器 —— 与本档「表头裁切只加在 fixed」同一条判据(见上一条注释)。 */
|
|
103
108
|
.mh-table--fixed tbody td {
|
|
104
|
-
overflow
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
text-overflow: ellipsis;
|
|
111
|
+
white-space: nowrap;
|
|
105
112
|
}
|
|
106
113
|
/* 前导列(勾选 / 展开)在 auto 下靠内容把 40px 的「建议宽」撑出去;fixed 下是硬宽,
|
|
107
114
|
而 `thead th` / `tbody td` 的标准左右内距各 16px ⇒ 可用内容只有 40 − 32 = 8px,
|
|
@@ -248,8 +255,12 @@
|
|
|
248
255
|
z-index: 2; /* 表头既钉顶又钉左,压住表头其余列 */
|
|
249
256
|
background: var(--ui-table-head-bg);
|
|
250
257
|
}
|
|
251
|
-
/* `--sticky-head
|
|
252
|
-
|
|
258
|
+
/* `--sticky-head`:表头钉顶。
|
|
259
|
+
* ⚠️ 选择器必须带 `tr`(0-1-3):文件后段「拖拽线的定位上下文」那条
|
|
260
|
+
* `.mh-table thead th { position: relative }` 是 **0-1-2**,与不写 `tr` 的写法**同特异性且在后**
|
|
261
|
+
* ⇒ 会把 `position: sticky` 覆盖掉,`stickyHead` 静默失效(0.6.0 起就存在,0.9.0 复核仍在)。
|
|
262
|
+
* `sticky` 同样是定位元素,照样给表头里的拖拽线当包含块,故加 `tr` 不损失原能力。 */
|
|
263
|
+
.mh-table--sticky-head thead tr th {
|
|
253
264
|
position: sticky;
|
|
254
265
|
top: 0;
|
|
255
266
|
z-index: 1;
|
|
@@ -271,16 +282,16 @@
|
|
|
271
282
|
.mh-table__cell-link:hover {
|
|
272
283
|
text-decoration: underline;
|
|
273
284
|
}
|
|
274
|
-
/*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
white-space:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
/* 列级**放开换行**(列定义里 `wrap: true` 时下发,只作用于表体 `td`;表头始终 nowrap)。
|
|
286
|
+
* 缺省不换行在面文件的 `.mh-table--fixed tbody td` 里 —— 本档才翻默认,故这里同时把
|
|
287
|
+
* 「换行三件套」与 `overflow-wrap` 兜底一并给回:换来的是「长文本列自己决定换行」。
|
|
288
|
+
* ⚠️ 选择器必须带 `td`(0-1-3):`.mh-table--fixed tbody td` 是 **0-1-2**,
|
|
289
|
+
* 单个类(0-1-0)压不过它(同 §表头对齐那条的先例)。 */
|
|
290
|
+
.mh-table tbody td.mh-table__cell-wrap {
|
|
291
|
+
white-space: normal;
|
|
292
|
+
overflow: visible;
|
|
293
|
+
text-overflow: clip;
|
|
294
|
+
overflow-wrap: anywhere;
|
|
284
295
|
}
|
|
285
296
|
.mh-table__cell-icon {
|
|
286
297
|
display: inline-flex;
|
|
@@ -399,10 +410,10 @@
|
|
|
399
410
|
color: var(--ui-warning); /* 规范 #ff6c29 */
|
|
400
411
|
}
|
|
401
412
|
|
|
402
|
-
/* ===== 尺寸档:大号(详情页 /
|
|
413
|
+
/* ===== 尺寸档:大号(详情页 / 展示型表格)—— 三档 30 / 38 / 46 里的最大档 ===== */
|
|
403
414
|
.mh-table--lg {
|
|
404
|
-
--ui-table-head-height:
|
|
405
|
-
--ui-table-row-height:
|
|
415
|
+
--ui-table-head-height: 46px;
|
|
416
|
+
--ui-table-row-height: 46px;
|
|
406
417
|
--ui-table-padding-x: var(--ui-space-6);
|
|
407
418
|
}
|
|
408
419
|
|