@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.
Files changed (56) hide show
  1. package/README.md +14 -8
  2. package/dist/components/button/index.d.ts +8 -8
  3. package/dist/components/checkbox/index.js +5 -1
  4. package/dist/components/code-block/index.d.ts +776 -0
  5. package/dist/components/code-block/index.js +335 -0
  6. package/dist/components/dialog/index.d.ts +3 -3
  7. package/dist/components/dialog/index.js +5 -5
  8. package/dist/components/filter/index.d.ts +8 -2
  9. package/dist/components/filter/index.js +11 -20
  10. package/dist/components/form/index.d.ts +39 -0
  11. package/dist/components/form/index.js +6 -0
  12. package/dist/components/input/index.d.ts +48 -7
  13. package/dist/components/input/index.js +23 -3
  14. package/dist/components/notice/index.d.ts +1 -1
  15. package/dist/components/notice/index.js +4 -4
  16. package/dist/components/notification/index.d.ts +1 -1
  17. package/dist/components/notification/index.js +5 -5
  18. package/dist/components/radio/index.js +29 -3
  19. package/dist/components/search/index.js +37 -35
  20. package/dist/components/select/index.js +1 -3
  21. package/dist/components/select/select-trigger.d.ts +4 -2
  22. package/dist/components/select/select-trigger.js +9 -4
  23. package/dist/components/table/index.d.ts +19 -8
  24. package/dist/components/table/index.js +3 -3
  25. package/dist/components/tag/index.d.ts +1 -1
  26. package/dist/components/text/index.d.ts +4 -3
  27. package/dist/components/toast/index.d.ts +4 -4
  28. package/dist/components/toast/index.js +16 -1
  29. package/dist/index.d.ts +1 -2
  30. package/dist/index.js +2 -4
  31. package/dist/services/dialog.d.ts +1 -1
  32. package/dist/styles/components/avatar.css +4 -1
  33. package/dist/styles/components/button.css +2 -0
  34. package/dist/styles/components/code-block.css +216 -0
  35. package/dist/styles/components/code-block.tokens.css +40 -0
  36. package/dist/styles/components/dialog.css +3 -3
  37. package/dist/styles/components/filter.css +22 -34
  38. package/dist/styles/components/input.css +24 -0
  39. package/dist/styles/components/select.css +3 -4
  40. package/dist/styles/components/table.css +33 -22
  41. package/dist/styles/components/table.tokens.css +6 -6
  42. package/dist/styles/components/text.css +10 -0
  43. package/dist/styles/components/toast.css +35 -6
  44. package/dist/styles/components/upload.css +1 -0
  45. package/dist/styles/index.css +7 -8
  46. package/dist/styles/reset.css +52 -167
  47. package/package.json +2 -2
  48. package/dist/components/code/index.d.ts +0 -134
  49. package/dist/components/code/index.js +0 -117
  50. package/dist/components/code-editor/index.d.ts +0 -163
  51. package/dist/components/code-editor/index.js +0 -98
  52. package/dist/styles/components/code-editor.css +0 -91
  53. package/dist/styles/components/code-editor.tokens.css +0 -24
  54. package/dist/styles/components/code.css +0 -153
  55. package/dist/styles/components/code.tokens.css +0 -29
  56. package/dist/styles/components/filter.tokens.css +0 -14
@@ -11,8 +11,12 @@
11
11
  [data-manohub-ui] {
12
12
  /* 单件令牌 */
13
13
  --ui-table-font-size: var(--ui-font-caption);
14
- --ui-table-head-height: 34px; /* 设计 1160×34 */
15
- --ui-table-row-height: 30px; /* 设计 919×30,节距 31 */
14
+ /* 尺寸档三档 = 30 / 38 / 46(sm / md / lg),本节是**基础值 = 中档(md)**,
15
+ 与 Button(24 / 32 / 40)、Tree(基础 34、紧凑 28)同一条库内约定:
16
+ 基础令牌承担 md,`.mh-<件>--<档>` 只改写另两档。
17
+ ⚠️ 两个档位改写分别在面文件的 `.mh-table--xs`(sm)与 `.mh-table--lg` 里,别写回本文件。 */
18
+ --ui-table-head-height: 38px; /* 中档(md)表头 = 行高 */
19
+ --ui-table-row-height: 38px; /* 中档(md)行高 */
16
20
  --ui-table-line-height: var(--ui-line-caption); /* 单元格行高 = 正文档的 13px 配对(default 20 / farris 18) */
17
21
  --ui-table-head-bg: var(--ui-base-200); /* 设计 #f1f2f5 */
18
22
  --ui-table-head-text: var(--ui-base-content-muted);
@@ -29,10 +33,6 @@
29
33
  --ui-table-link: var(--ui-primary);
30
34
  --ui-table-padding-x: var(--ui-space-4); /* 单元格左右内距 16 */
31
35
  --ui-table-col-check: 40px;
32
- /* 长文本列的兜底上限 —— **只在 `layout="auto"` 下生效**(`.mh-table:not(.mh-table--fixed)`
33
- 作用域内)。`layout="fixed"` 下列宽由 `<colgroup>` 钉死,本令牌不参与,
34
- 否则「宽列」会被它压回 150px 而自相矛盾。要按列给宽请用 `TableColumn.width`。 */
35
- --ui-table-ellipsis: 150px;
36
36
  --ui-table-drag-line: var(--ui-primary);
37
37
  --ui-table-drag-line-width: 3px;
38
38
  --ui-table-drag-line-height: 40px;
@@ -27,6 +27,16 @@
27
27
  color: var(--mh-text-tone-color, inherit);
28
28
  }
29
29
 
30
+ /* 浏览器给 `h1`-`h6` 的那套字阶(`1.5em` + 粗体)只该是**语义**,视觉由 `size` / `weight` 定:
31
+ 归零搬到了本件(元素级基线不再代管 —— 那条在 Tailwind 的层外,会压住消费方的 `text-*` 工具类)。
32
+ 只点名标题标签:`strong` / `b` 的加粗是它们唯一的表达,不能被归零。
33
+ 档位类在本文件里更靠后、且同特异性,故 `--heading` / `--semibold` 一类照样覆盖它
34
+ (静态页里手写 `<h2 class="mh-text">` 且不给档位时,也仍是「正文字号 + 继承字重」)。 */
35
+ .mh-text:where(h1, h2, h3, h4, h5, h6) {
36
+ font-size: inherit;
37
+ font-weight: inherit;
38
+ }
39
+
30
40
  /* ===== 字号档(每档配一枚行高令牌,两者成对出现才不会出现「字号变了行距没变」) ===== */
31
41
  .mh-text--caption {
32
42
  font-size: var(--ui-font-caption);
@@ -26,7 +26,12 @@
26
26
  display: flex;
27
27
  align-items: center;
28
28
  gap: var(--ui-toast-gap);
29
- width: var(--ui-toast-width);
29
+ /* 宽度:**内容自适应,240 起、最长 560** —— 即规范原文的「宽 240 / 最大 560」。
30
+ 原写法 `width: var(--ui-toast-width)` 是**固定宽**:文本被锁在 240−40=200px 里折行,
31
+ 而 `max-width` 永远轮不到(内容只会折行,撑不宽元素)⇒ 23 字提示被硬折成两行。
32
+ 改 min/max 夹住的 fit-content 后:短文案仍是 240(样张宽不变),长文案按内容展开、到 560 才折行。 */
33
+ width: fit-content;
34
+ min-width: var(--ui-toast-width);
30
35
  max-width: var(--ui-toast-width-max);
31
36
  min-height: var(--ui-toast-min-height);
32
37
  padding: var(--ui-space-3) var(--ui-space-4) var(--ui-space-3) var(--ui-space-6);
@@ -37,9 +42,9 @@
37
42
  }
38
43
 
39
44
  /* loading:**不另设样张高**(高度与其它档一致,见文件头的「有意偏差」)—— 本档只差图标(转圈) */
40
- /* 带动作:更宽的样张宽 */
45
+ /* 带动作:**更宽的样张宽**(360 是下限,长文案仍可展开到 560 上限) */
41
46
  .mh-toast--action {
42
- width: 360px;
47
+ min-width: 360px;
43
48
  }
44
49
 
45
50
  /* ===== 图标:圆形色底 + 白色字形(18×18) ===== */
@@ -91,7 +96,10 @@
91
96
  /* 占满剩余宽度:动作位 / 关闭位都被顶到右端。
92
97
  不写成「每个右侧位各给 margin-left: auto」—— 两个 auto 会平分剩余空间,
93
98
  而本族的常驻提示可能同时带动作与关闭位(那样动作钮会被推到卡片中间)。 */
94
- flex: 1;
99
+ /* ⚠️ 必须是 `flex: 1 1 auto`,不能写成 `flex: 1`(= basis 0%):父级现在是 `width: fit-content`,
100
+ 容器的固有宽按子项的**内容宽**算,basis 为 0 会让文本对容器宽度的贡献退化
101
+ ⇒ 容器停在 min-width(240)、长文案照旧折行(改宽度就白改了)。 */
102
+ flex: 1 1 auto;
95
103
  min-width: 0;
96
104
  margin: 0;
97
105
  font-size: var(--ui-toast-text-size);
@@ -115,19 +123,40 @@
115
123
  outline-offset: 2px;
116
124
  }
117
125
 
118
- /* ===== 堆叠容器(顶部居中、纵向 8) ===== */
126
+ /* ===== 堆叠容器(顶部居中、纵向 8) =====
127
+ ⚠️ `z-index` 只对**普通层**有效:原生 `<dialog>.showModal()` 的模态层与 `::backdrop` 在 top layer,
128
+ 对它 z-index 再大也没用(toast 会被遮罩压暗)。故本容器带 `popover="manual"` 进 top layer
129
+ —— `showPopover()` 由组件层负责(见 `ToastStack` 的说明)。 */
119
130
  .mh-toast-stack {
120
131
  position: fixed;
121
132
  top: var(--ui-space-6);
122
133
  left: 50%;
123
134
  transform: translateX(-50%);
124
- z-index: 1080; /* 高于页面内容、低于模态层(原生 <dialog> 的 top layer 不受影响) */
135
+ z-index: 1080; /* 普通层里仍压过页面内容;popover 不可用的浏览器靠它兜底 */
125
136
  display: flex;
126
137
  flex-direction: column;
127
138
  gap: var(--ui-space-2);
128
139
  align-items: center;
129
140
  pointer-events: none; /* 容器不挡点击;每条自己恢复 */
130
141
  }
142
+
143
+ /* `[popover]` 档:清掉 UA 给 popover 的默认,否则会变成「全屏居中、带边框的方块」
144
+ (UA 给的是 `inset: 0; margin: auto; border: solid; padding: .25em; background: Canvas; overflow: auto`)。
145
+ ⚠️ `inset: auto` 与 `top` / `left` **必须写在同一条规则里**:只写 `inset: auto` 会把上面那条规则里的
146
+ `left: 50%` 一并压成 auto(同层冲突按顺序/特异性决胜,本块更高),元素就跑到视口左边缘去了。 */
147
+ .mh-toast-stack[popover] {
148
+ inset: auto;
149
+ top: var(--ui-space-6);
150
+ left: 50%;
151
+ transform: translateX(-50%);
152
+ margin: 0;
153
+ border: 0;
154
+ padding: 0;
155
+ background: transparent;
156
+ overflow: visible;
157
+ max-width: none;
158
+ max-height: none;
159
+ }
131
160
  .mh-toast-stack > .mh-toast {
132
161
  pointer-events: auto;
133
162
  }
@@ -138,6 +138,7 @@
138
138
  overflow: hidden;
139
139
  }
140
140
  .mh-upload__thumb-img {
141
+ display: block; /* 元素级基线不再把 `img` 转块级(那条会压消费方的 `h-*` / `hidden`),本件自己写 */
141
142
  width: var(--ui-upload-thumb-inner);
142
143
  height: var(--ui-upload-thumb-inner);
143
144
  object-fit: cover;
@@ -43,10 +43,11 @@
43
43
  * (护栏会拦「面里出现不含修饰符类的 `--ui-*` 声明」)。
44
44
  *
45
45
  * 层序:**基线(`./reset.css`,元素级、零特异性)→ 值 → 面**;面内部**操作层在前**(零 JS 原语、规则走 `:where()` 零特异性,
46
- * 永远给皮肤让位),组件面在后。
46
+ * 永远给皮肤让位),组件面在后。基线只有两面(`box-sizing` + 容器基座)—— 其余元素级声明一律归各组件面:
47
+ * 本文件**在 Tailwind 的层外**(未分层 > 分层),多留一条就会压住消费方的工具类(理由见 `reset.css` 文件头)。
47
48
  */
48
49
 
49
- /* ===== 基线:元素级 reset(特异性最低;先于值 → 面,消费方写任何元素选择器都能盖过它) ===== */
50
+ /* ===== 基线:元素级 reset(只有盒模型 + 容器基座;先于值 → 面,消费方写任何元素选择器都能盖过它) ===== */
50
51
  @import './reset.css';
51
52
 
52
53
  /* ===== 值:组件令牌基础值(锚 `[data-manohub-ui]`,与主题令牌同层序) ===== */
@@ -59,8 +60,7 @@
59
60
  @import './components/tag.tokens.css';
60
61
  @import './components/avatar.tokens.css';
61
62
  @import './components/skeleton.tokens.css';
62
- @import './components/code.tokens.css';
63
- @import './components/code-editor.tokens.css';
63
+ @import './components/code-block.tokens.css';
64
64
 
65
65
  /* 表单与选择控件 */
66
66
  @import './components/button.tokens.css';
@@ -71,7 +71,7 @@
71
71
  @import './components/checkbox.tokens.css';
72
72
  @import './components/radio.tokens.css';
73
73
  @import './components/capsule.tokens.css';
74
- @import './components/filter.tokens.css';
74
+ /* 筛选条没有自己的令牌:字段区几何一律继承 Form 的默认档 */
75
75
 
76
76
  /* 反馈与三态 */
77
77
  @import './components/notice.tokens.css';
@@ -116,8 +116,7 @@
116
116
  @import './components/tag.css';
117
117
  @import './components/avatar.css';
118
118
  @import './components/skeleton.css';
119
- @import './components/code.css'; /* 行内 chip / 代码块(复制按钮的面归按钮族,故在其后);面里靠升一档特异性压过按钮族,见其文件头 */
120
- @import './components/code-editor.css'; /* 可编辑代码区(与只读块视觉同源;无按钮,与按钮族无层序关系) */
119
+ @import './components/code-block.css'; /* 代码块族(只读面 / 编辑面 / 角标 / 复制位;复制按钮的面归按钮族,故在其后);面里靠升一档特异性压过按钮族,见其文件头 */
121
120
 
122
121
  /* 表单与选择控件(按钮 → 输入 → 选择 → 开关 → 勾选 → 单选(两形态同面)→ 胶囊) */
123
122
  @import './components/button.css';
@@ -129,7 +128,7 @@
129
128
  @import './components/checkbox.css';
130
129
  @import './components/radio.css'; /* 单选一件两形态(`.Group` / `.Card`)同一个面文件 */
131
130
  @import './components/capsule.css';
132
- @import './components/filter.css'; /* 筛选条:条件字段区 + 查询/重置(控件由消费方自放) */
131
+ @import './components/filter.css'; /* 筛选条:**零规则**(字段排布与几何全部沿用 Form,本文件只留说明;见其文件头) */
133
132
 
134
133
  /* 反馈与三态 */
135
134
  @import './components/notice.css';
@@ -1,70 +1,81 @@
1
1
  /**
2
- * 基础重置(reset)—— 元素级基线,随 `@manohub/ui/styles.css` 一起到达消费方。
2
+ * 元素级基线 —— 随 `@manohub/ui/styles.css` 一起到达消费方(该入口的**首条 import**)。
3
3
  *
4
- * ## 为什么基线归本包
4
+ * ## 它现在只有两面
5
5
  *
6
- * 接入契约(`@manohub/kit/CONTRACT.md` §3)禁应用侧写裸元素选择器与字号字面量,
7
- * 于是「把浏览器默认值归零」在应用侧**没有合规落点**:0.6.0 之前它寄在入口层的
8
- * `reset.css` 里,随入口层零样式化一并删除后就成了缺口(契约 §10 记在案)。
9
- * 本包是样式面(② 面层)的唯一来源,元素基线因此归这里 —— 位于「值」之后、「面」之前。
6
+ * 1. **盒模型**:`box-sizing: border-box` 覆盖容器、全部后代与伪元素
7
+ * —— 本库所有面的几何都按 border-box 写盒高与内距,这条一丢,全库尺寸集体走样。
8
+ * 2. **容器基座**:`[data-manohub-ui]` 上的字族 / 字号 / 行高 / 字色 / 底色 / 整链高度与抗锯齿。
9
+ * 它是令牌的落点(`@manohub/theme` 的全局令牌与各件的 `<件>.tokens.css` 都锚这个属性),
10
+ * 也是本文件唯一一条**描述容器自身、不涉及后代**、因此不带 `:where()` 的规则。
10
11
  *
11
- * ## 参照口径
12
+ * 除这两面之外**一条都不留**(2026-09 瘦身)。理由与去向见下面两节。
12
13
  *
13
- * 主体对齐 **Tailwind Preflight**(消费方 `apps/<app>/src/style.css` 一直在引的那份):
14
- * 覆盖的元素清单一致,**唯一的有意差异是表单控件的底色** —— Preflight 把 `input` / `select` /
15
- * `textarea` 也清成透明,本文件保留浏览器原生底色(裸输入框若连底都没有就完全不可见);
16
- * 挂类的控件(`.mh-input` 等)有自己的面,不受这条影响。本包组件面本来就是按「已清零」的环境写的 ——
17
- * 全部 33 处挂类的 `<button>` 合并后都自带 border / background / padding ——
18
- * 所以本文件**不改变任何组件的外观**;它的作用是:
14
+ * ## 为什么删:未分层 > 分层(不是特异性问题)
19
15
  *
20
- * 1. 让文档站 / 静态页也站到与真实应用同一个起跑线(此前只有真实应用有 preflight);
21
- * 2. 让裸元素(`ul` / `a` / `p` / `button` …)不再带浏览器的默认内外距、列表序号与链接色 ——
22
- * 页面骨架由应用的 tsx 摆放时,不必再为每个原生元素写一次归零。
16
+ * 旧版这份文件是按 **Tailwind Preflight** 逐条复刻的(盒模型 / 块级外边距归零 / 标题字阶 /
17
+ * 列表序号 / 链接下划线 / 控件外观 / 媒体元素转块 …)。问题出在**级联层**上:Tailwind 4 的
18
+ * 产物首行是 `@layer theme, base, components, utilities;`,preflight 与全部工具类都在层里,
19
+ * 而本文件**在层外** —— CSS 里未分层的普通声明一律赢过分层里的普通声明,**这条优先于特异性**。
20
+ * 于是那些复刻规则把消费方的工具类整片压住(实测:`border*` 被 `border-width: 0` 打掉、
21
+ * `img` 上的 `h-*` 被 `height: auto` 打掉,同类还有 `h1`–`h6` 的 `text-*`、`p` 的 `mb-*`、
22
+ * `svg`/`img` 上的 `hidden`),而 `:where()` 把特异性降到 0 也救不了 —— 胜负不在特异性上。
23
23
  *
24
- * 与旧实现(`app-kit` 的 reset)相比,多了按钮外观归零、列表序号归零、链接继承色去下划线、
25
- * 标题字阶归位、媒体元素转块级 —— 那几条正是「应用侧各写各的」在补齐的部分。
24
+ * 两件事要分开:**分层**管优先级(本文件现在不再依赖消费方分层,因为可抢的声明已经没有了),
25
+ * **瘦身**管重复 —— 与 preflight 重合的规则对 Tailwind 消费方本就是零增量,剩下的都归了具体组件。
26
26
  *
27
- * ## 特异性纪律(改本文件前必读)
27
+ * ## 删掉的那些去了哪
28
28
  *
29
- * **作用域一律用 `:where([data-manohub-ui])` 包裹**:`:where()` 特异性为 0,
30
- * 故每条规则等价于纯元素选择器(0,0,1)甚至更低(`:where(X) *` 即 0,0,0)。
29
+ * | 旧规则 | 现在的落点 |
30
+ * |---|---|
31
+ * | `img` / `svg` / `video` / `canvas` / `audio` / `iframe` / `embed` / `object` 转块级、`img`+`video` 不溢出 | 用图的件各自写:Card / ListView / QueryState 本来就有,Avatar / Upload 已补 `display: block` |
32
+ * | `a { color: inherit; text-decoration: inherit }` | `.mh-button` 基块补 `text-decoration: none`(链接形态的按钮就是 `<a>`);正文链接的颜色与下划线交给消费方 |
33
+ * | `textarea { resize: vertical }` | `.mh-input--textarea` |
34
+ * | `button` 的 `cursor: pointer` / 透明底 / 无渐变 / 无缩改 | 各按钮形态的面(本来都自带 `border` / `background` / `padding` / `cursor`) |
35
+ * | `code` / `kbd` / `samp` / `pre` 等宽族 | CodeBlock 面,以及 `.mh-text--mono`(消费方写裸 `<code>` 时用后者) |
36
+ * | `:disabled { cursor: default }` | 各件禁用态(Button / Input / Select / Checkbox / Capsule / Card / Collapse 等都已自带) |
37
+ * | `[type='search'] { outline-offset: -2px }` | 搜索框的面自画焦点环 |
38
+ * | 标题字阶归位 / 块级元素外边距归零 / 列表序号与缩进 / 控件字体与颜色继承 / `b`+`strong` / `small` / `summary` / `label` | **直接删**:全库零组件依赖,且 Tailwind Preflight 全都有 |
39
+ *
40
+ * `border-width: 0; border-style: solid` 也一并删了:库内每个面都写全简写
41
+ * (`border: 1px solid …` / `border: none` / `border-bottom: 1px solid …`),没有一处依赖默认值,
42
+ * 留着只会继续压消费方的 `border*` 工具类。
43
+ *
44
+ * ## 特异性的老纪律(往这里加东西前必读)
45
+ *
46
+ * **作用域一律用 `:where([data-manohub-ui])` 包裹**:`:where()` 特异性为 0,等价于纯元素选择器。
31
47
  * 写成 `.container button` 这类高特异性选择器(0,1,1)会**反压本包组件面**(普遍是单类 0,1,0)——
32
- * 本仓踩过:主按钮文字变成 `color: inherit` 的黑色。**新增任何 reset 级样式都要遵守这条。**
33
- * 也正因为它的特异性最低,消费方在自己的样式里写任何元素选择器都能盖过它。
48
+ * 本仓踩过:主按钮文字变成 `color: inherit` 的黑色。
34
49
  *
35
- * 唯一一条不带 `:where()` 的是**容器基座**(下面的 `[data-manohub-ui]`):它描述容器自身而非其后代,
36
- * 且要能在消费方「同名选择器后写即胜」的规则里被覆盖,故保持 (0,1,0)(与旧实现一致)。
50
+ * 唯一例外是**容器基座**(下面的 `[data-manohub-ui]`):它描述容器自身而非其后代,
51
+ * 且要能在消费方「同名选择器后写即胜」的规则里被覆盖,故保持 (0,1,0)。
37
52
  *
38
- * ## 四条不做
53
+ * **加声明之前先自问**:这条会不会压住消费方的 Tailwind 工具类?会压就落进**具体组件的面**
54
+ * (谁渲染这个元素谁负责),不要放这里。`__tests__/contract-reset.spec.ts` 按这条锁着:
55
+ * 除容器基座外,整份文件只允许 `box-sizing` 一条声明。
56
+ *
57
+ * ## 三条不做
39
58
  *
40
59
  * 1. **不碰 `html` / `body` / `#app`**:micro-app 的 scopecss **不作用域化**它们,
41
- * 写进去会泄漏到宿主应用的全局样式。
42
- * **整链高度由消费方承担,且契约明确它是合法的** —— 写在应用的 `app.css` 或入口 HTML 的 `<style>` 里
43
- * (`@manohub/kit/CONTRACT.md` §1.2「入口基线」,是 L1-6「不得用裸元素选择器」的**唯一例外**);
60
+ * 写进去会泄漏到宿主应用的全局样式。整链高度由消费方承担
61
+ * (`@manohub/kit/CONTRACT.md` §1.2「入口基线」,是 L1-6「不得用裸元素选择器」的唯一例外);
44
62
  * 容器自身在这里给 `height: 100%`,`Page` 的 `height: 100%` 依赖上面那条链存在。
45
63
  * 2. **不定义任何 `--ui-*` 令牌**:值一律归 `@manohub/theme`,本文件只**消费**(两处定义必然漂)。
46
64
  * 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
65
  *
52
- * ## 富文本须知
66
+ * ## 富文本须知(相对旧版是反转)
53
67
  *
54
- * 重置掉 `ul` / `ol` 的序号、`a` 的下划线之后,**富文本(markdown)需要自行复权** ——
55
- * 富文本排版目前没有合规归属(见 `@manohub/kit/CONTRACT.md` §10 的已知缺口),
56
- * 消费方要为自己的富文本容器类补回 `list-style`、链接色与下划线、段落边距。
57
- * 本文件有意**不含** `.mh-markdown` 一类的富文本预设:那是独立的一件事,不混进元素基线。
68
+ * 本文件现在**不归零列表序号、不归零链接下划线、不归位标题字阶**,所以富文本(markdown)与正文
69
+ * 可以直接吃浏览器默认排版 —— 旧版那条「消费方须为自己的富文本容器复权」的告示随之作废
70
+ * (见 `@manohub/kit/CONTRACT.md` §10)。反之,消费方想要一套自己的正文排版,按自己的容器类写即可。
58
71
  */
59
72
 
60
- /* ===== 盒模型与边框:边框属性归零(对齐 Preflight,`border: 1px solid …` 写法不受影响) ===== */
73
+ /* ===== 盒模型:容器、其后代与伪元素一律 border-box(本库全部面的几何前提) ===== */
61
74
  :where([data-manohub-ui]),
62
75
  :where([data-manohub-ui]) *,
63
76
  :where([data-manohub-ui]) *::before,
64
77
  :where([data-manohub-ui]) *::after {
65
78
  box-sizing: border-box;
66
- border-width: 0;
67
- border-style: solid;
68
79
  }
69
80
 
70
81
  /* ===== 容器基座:字族 / 字号 / 行高 / 字色 / 底色 / 整链高度(本文件唯一不带 :where() 的一条) ===== */
@@ -81,129 +92,3 @@
81
92
  -webkit-font-smoothing: antialiased;
82
93
  -moz-osx-font-smoothing: grayscale;
83
94
  }
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
- }
206
-
207
- :where([data-manohub-ui]) label {
208
- margin: 0;
209
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manohub/ui",
3
- "version": "0.8.2",
3
+ "version": "0.10.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.8.2"
49
+ "@manohub/icon": "^0.10.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "^24.0.0",
@@ -1,134 +0,0 @@
1
- import { type PropType, type SlotsType, type VNodeChild } from 'vue';
2
- /**
3
- * 代码(**自绘**;行内 chip / 代码块 / 语言角标 / 复制位)—— **只读展示件**。
4
- *
5
- * 三种形态:`inline`(行内 chip,如版本号、规则 ID)、`inline + plain`(中性档)、
6
- * 缺省(代码块 + 右上角 hover / 聚焦显形的方形图标复制按钮 + 可选语言角标)。
7
- * 代码块**缺省不折行**(横向滚动,缩进与列对齐不被破坏),`wrap` 才软换行。
8
- *
9
- * **编辑态用 `CodeEditor`**(本件只管展示):要「只读看 + 就地改」,把两件组合起来用
10
- * ——只读时用本件渲染(可接已高亮节点),切到编辑时换成 `CodeEditor`。
11
- *
12
- * ## 高亮由消费方声明(本件不做语法高亮)
13
- *
14
- * 本件不认识任何语言:`language` 只画右上角的**角标**,**不做**分词着色。
15
- * 需要高亮时走**默认插槽**传入已高亮过的节点(VNode / 已转义好的 HTML 片段皆可),
16
- * 此时 `code` 仍应给**纯文本**——它是复制进剪贴板的内容(插槽内容是渲染结果,不能拿去复制)。
17
- *
18
- * ## 复制按钮的面归按钮族(`.mh-button--icon`)
19
- *
20
- * 本件只补定位与显隐(见 `styles/components/code.css`);按钮挂在宿主 `.mh-code__wrap` 上
21
- * 而**不是代码块里** —— 代码块是 `overflow-x: auto` 的滚动容器,放进去会被裁掉。
22
- *
23
- * ## 复制动作与降级
24
- *
25
- * 走 `navigator.clipboard.writeText`(**唯一需要 JS 的部分**,按 copied 状态二选一图标)。
26
- * 环境没有该 API(旧浏览器、非安全上下文)或写入被拒时:不谎报成功,`onCopy(false)` 交回结果
27
- * 并 `console.warn` 一次 —— 消费方据此提示「请手动复制」(本件不自己弹提示,避免与页面的提示口径两套)。
28
- *
29
- * @example 行内
30
- * <Code inline>v1.2.0</Code>
31
- * <Code inline plain>RULE-1024</Code>
32
- *
33
- * @example 代码块 + 语言角标 + 复制
34
- * <Code :code="sql" language="sql" copyable @copy="(ok) => ok || showManualTip()" />
35
- *
36
- * @example 高亮交给消费方(`code` 仍是复制用的纯文本)
37
- * <Code :code="sql" language="sql" copyable>
38
- * <span v-html="highlightedSql" />
39
- * </Code>
40
- */
41
- export declare const Code: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
42
- /** 代码文本(也可用默认插槽给复杂内容);**复制进剪贴板的就是它** */
43
- code: {
44
- type: StringConstructor;
45
- default: string;
46
- };
47
- /** 行内 chip(缺省是代码块) */
48
- inline: {
49
- type: BooleanConstructor;
50
- default: boolean;
51
- };
52
- /** 行内中性档(不强调的短标识) */
53
- plain: {
54
- type: BooleanConstructor;
55
- default: boolean;
56
- };
57
- /** 右上角语言角标(如 `sql` / `json` / `vue`);只做标注,**不做语法高亮** */
58
- language: {
59
- type: StringConstructor;
60
- default: string;
61
- };
62
- /** 代码块右上角的复制按钮 */
63
- copyable: {
64
- type: BooleanConstructor;
65
- default: boolean;
66
- };
67
- /** 最大高度(数字按 px):超出后**块内滚动**,用于长日志/长配置 */
68
- maxHeight: {
69
- type: PropType<string | number>;
70
- default: undefined;
71
- };
72
- /** 允许软换行(缺省保持 `pre` 的横向不换行 + 横向滚动) */
73
- wrap: {
74
- type: BooleanConstructor;
75
- default: boolean;
76
- };
77
- /** 复制结果回调:`true` = 真的写进剪贴板了 */
78
- onCopy: {
79
- type: PropType<(ok: boolean) => void>;
80
- default: undefined;
81
- };
82
- }>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
83
- /** 代码文本(也可用默认插槽给复杂内容);**复制进剪贴板的就是它** */
84
- code: {
85
- type: StringConstructor;
86
- default: string;
87
- };
88
- /** 行内 chip(缺省是代码块) */
89
- inline: {
90
- type: BooleanConstructor;
91
- default: boolean;
92
- };
93
- /** 行内中性档(不强调的短标识) */
94
- plain: {
95
- type: BooleanConstructor;
96
- default: boolean;
97
- };
98
- /** 右上角语言角标(如 `sql` / `json` / `vue`);只做标注,**不做语法高亮** */
99
- language: {
100
- type: StringConstructor;
101
- default: string;
102
- };
103
- /** 代码块右上角的复制按钮 */
104
- copyable: {
105
- type: BooleanConstructor;
106
- default: boolean;
107
- };
108
- /** 最大高度(数字按 px):超出后**块内滚动**,用于长日志/长配置 */
109
- maxHeight: {
110
- type: PropType<string | number>;
111
- default: undefined;
112
- };
113
- /** 允许软换行(缺省保持 `pre` 的横向不换行 + 横向滚动) */
114
- wrap: {
115
- type: BooleanConstructor;
116
- default: boolean;
117
- };
118
- /** 复制结果回调:`true` = 真的写进剪贴板了 */
119
- onCopy: {
120
- type: PropType<(ok: boolean) => void>;
121
- default: undefined;
122
- };
123
- }>> & Readonly<{}>, {
124
- inline: boolean;
125
- wrap: boolean;
126
- plain: boolean;
127
- code: string;
128
- onCopy: (ok: boolean) => void;
129
- language: string;
130
- copyable: boolean;
131
- maxHeight: string | number;
132
- }, SlotsType<{
133
- default?: () => VNodeChild;
134
- }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;