@manohub/kit 1.0.3 → 1.0.4

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/CONTRACT.md CHANGED
@@ -70,20 +70,29 @@ pnpm add vue vue-router pinia vue-i18n @tanstack/vue-query # peer,由应用
70
70
  ```
71
71
 
72
72
  四个包**并列安装**,模块级互不依赖:kit 提供入口编排与本文,ui 提供组件与命令式服务,
73
- theme 提供令牌(值),icon 提供图形。**本包不发布任何样式**(见 §1.2),
73
+ theme 提供令牌(值),icon 提供图形。**本包只出一条样式出口**(`./reset.css`,宿主兜底;见 §1.2),
74
74
  所以 `kit` 的 `peerDependencies` 里没有另外三个。
75
75
 
76
76
  四者之间**唯一的跨包约定**是容器上的属性锚 `data-manohub-ui`(见 §1.3)。
77
77
 
78
- ### 1.2 样式链:两行 + 应用自己一行(顺序即契约)
78
+ ### 1.2 样式链:三行 + 应用自己一行(顺序即契约)
79
79
 
80
80
  ```css
81
81
  @import "@manohub/theme/default.css"; /* ① 令牌(值)—— 换主题只换这一行 */
82
- @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
83
- @import "./app.css"; /* ③ 应用自身(只写布局,见 §3) */
82
+ @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
83
+ @import "@manohub/kit/reset.css"; /* ③ 宿主兜底(元素级复位) */
84
+ @import "./app.css"; /* ④ 应用自身(只写布局,见 §3) */
84
85
  ```
85
86
 
86
- - **顺序不可换**:先值(令牌)后面(组件面)。反过来的话组件面里的 `var(--ui-*)` 全是空值。
87
+ - **顺序不可换**:先值(令牌)、后面(组件面)、兜底在库的最后一位。反过来的话组件面里的
88
+ `var(--ui-*)` 全是空值。
89
+ - **③ 是宿主兜底,不是第二份 reset**:子应用被注入宿主页面,平台门户全局加载的样式会按文档作用域
90
+ 落到子应用 DOM;其中「元素级、无类名」那几条(现状两条:门户的 `@farris/ui-vue` 带裸
91
+ `label { margin-bottom: .3125rem }` 与裸 `button:focus { outline: -webkit-focus-ring-color auto 5px }`)
92
+ 子应用按 L1-6 既不能写裸元素选择器、也不能用 `!important`,
93
+ 只能由库兜住。它与 ② 的分工:元素级基线的两面(盒模型 / 容器基座)归 ②,**兜底归 ③**;
94
+ 该文件**只收兜底、不收设计**,加规则前先读它头部的四条纪律(未分层会压住消费方工具类 /
95
+ 作用域一律 `:where()` / 有意不写 `!important` / 每条写明出处)。
87
96
  - 用非兜底主题时把 ① 换成对应入口(如 `@manohub/theme/farris.css`),
88
97
  并在入口给 `createSubApp({ theme: 'farris' })`(写到容器的 `data-theme` 上)。
89
98
  - **`reset`(元素级基线)自 0.7.0 起已内置在 ② 里**,不需要第三行:`@manohub/ui/styles.css` 的**首条** import
@@ -154,7 +163,7 @@ src/
154
163
 
155
164
  | 条款 | 要什么(闭集) | 为什么 |
156
165
  | --- | --- | --- |
157
- | **L0-1 样式链** | CSS 入口前两条 `@import` **逐字**为 `@manohub/theme/<主题>.css`、`@manohub/ui/styles.css`,且都在自有样式之前;全仓各出现一次 | 值在前、面在后;反了就全是空值 |
166
+ | **L0-1 样式链** | CSS 入口前三条 `@import` **逐字**为 `@manohub/theme/<主题>.css`、`@manohub/ui/styles.css`、`@manohub/kit/reset.css`,且都在自有样式之前;全仓各出现一次 | 值在前、面在后、兜底收尾;反了就全是空值 |
158
167
  | **L0-2 容器与锚** | 应用根恰好一次 `createSubApp(...)`;**不得自己写 `data-manohub-ui`**;**不得依赖 `.app-container`** | 锚是令牌与宿主解析的共同前提;`.app-container` 是本包内部名,不是跨包约定 |
159
168
  | **L0-3 单入口与 i18n** | 全仓 `createSubApp(` 恰好 1 次、`createI18n(` **0 次**(i18n 实例由本包创建) | 双实例会让文案全丢且不报错(见 §9) |
160
169
 
@@ -432,7 +441,7 @@ import { MY_GLYPHS } from './icons'
432
441
  | --- | --- | --- |
433
442
  | **L3-1 件白名单** | 只用导出表里的件;复合成员**只走点号**;**先查 `.d.ts` 再写** | README 与文档会漂移(`Page.Toolbar` / `Input.Group` / `Input.Chip` 都曾出现在文档里,实际不存在) |
434
443
  | **L3-2 外观只走语义 prop** | 改外观**只能**用件自己的 prop(语义词表共 **26 个维度**,逐个列在 §0 指的那份 `.d.ts` 里)或**换件**;**不得写 CSS 改外观** | 「不写 CSS 也能改外观」是这套库的全部答案 |
435
- | **L3-3 外观来源白名单** | **外观**只能来自这几处:`@manohub/ui`(子路径只认 `styles.css`)· `@manohub/icon`(或 `/glyphs`)· `@manohub/theme`(只认 `default.css` / `farris.css`)· `@manohub/kit/entry`(编排,零外观)。**不得从别处取外观**:不引第三方组件库 / CSS 框架 / 图标库,不直连底层组件库,不自绘(含手写 `<svg>` 与文字符号)。**不在本条款管辖内的**(它们不产生外观):① 框架与运行时(`vue` / `vue-router` / `pinia` / `@tanstack/vue-query` / `vue-i18n` / 微前端运行时);② 本仓**业务域自有包**(`@manohub/*` 里不在上列者,如 `@manohub/api-client`);③ **不产生外观的行为库**(拖拽 / 虚拟滚动 / 图表计算一类,只给行为与数据结构)。判据是「**它是不是外观来源**」,不是「它是不是依赖」 | 白名单管的是外观的**来源**。写成「import 清单」会把业务包与行为库一起圈进来 ⇒ 每个已迁移应用都命中一条「不可登记」的违规,而那条违规与「不引第三方组件库」的立法本意毫无关系 |
444
+ | **L3-3 外观来源白名单** | **外观**只能来自这几处:`@manohub/ui`(子路径只认 `styles.css`)· `@manohub/icon`(或 `/glyphs`)· `@manohub/theme`(只认 `default.css` / `farris.css`)· `@manohub/kit/entry`(编排,零外观)· `@manohub/kit/reset.css`(库级宿主兜底,唯一允许的样式来源)。**不得从别处取外观**:不引第三方组件库 / CSS 框架 / 图标库,不直连底层组件库,不自绘(含手写 `<svg>` 与文字符号)。**不在本条款管辖内的**(它们不产生外观):① 框架与运行时(`vue` / `vue-router` / `pinia` / `@tanstack/vue-query` / `vue-i18n` / 微前端运行时);② 本仓**业务域自有包**(`@manohub/*` 里不在上列者,如 `@manohub/api-client`);③ **不产生外观的行为库**(拖拽 / 虚拟滚动 / 图表计算一类,只给行为与数据结构)。判据是「**它是不是外观来源**」,不是「它是不是依赖」 | 白名单管的是外观的**来源**。写成「import 清单」会把业务包与行为库一起圈进来 ⇒ 每个已迁移应用都命中一条「不可登记」的违规,而那条违规与「不引第三方组件库」的立法本意毫无关系 |
436
445
  | **L3-4 交互不走原生控件** | 按钮 / 输入 / 下拉 / 文本域一律用组件;`<button>` `<input>` `<select>` `<textarea>` **带 `class` 承载外观**违规;**无 `href` 的 `<a class>`** 违规(「按钮的伪装」) | 原生控件拿不到令牌、键盘与语义也不对 |
437
446
  | **L3-5 浮层归组件与服务层** | 模态 → `Dialog`;贴边 → `Drawer`;轻提示 → `toast()`;确认 / 告知 → `confirm()` / `alert()`;忙等 → `showLoading()`。**不自己写 `position: fixed` + `z-index` 的遮罩** | 自建遮罩拿不到令牌,也逃不过微前端的 `scopecss` |
438
447
 
@@ -485,7 +494,7 @@ import Sortable from 'sortablejs' // 行为库:不产
485
494
 
486
495
  **L0**
487
496
 
488
- 1. 我的样式链前两条 `@import` 逐字对吗?顺序对吗(theme 在前)?**入口基线**(`html` / `body` / `#app` 的高度链)给了吗(在 ③ 里或入口 HTML 里)?
497
+ 1. 我的样式链前三条 `@import` 逐字对吗?顺序对吗(theme → ui/styles.css → kit/reset.css)?**入口基线**(`html` / `body` / `#app` 的高度链)给了吗(在 ③ 里或入口 HTML 里)?
489
498
  2. 有没有自己写 `data-manohub-ui`?有没有依赖 `.app-container`?
490
499
  3. `createSubApp` 还是只有一处?`createI18n` 是 0 次吗?
491
500
 
@@ -571,7 +580,7 @@ import Sortable from 'sortablejs' // 行为库:不产
571
580
  | 命令式服务不提供异步 `confirm` | 需要「确定按钮进加载态」时直接用 `Dialog` 的 `onOk`(返回 Promise 自动进加载态) |
572
581
  | 命令式 `confirm()` / `alert()` **显式关掉**「点遮罩关闭」 | 组件形态默认**开**(与主流一致,见 §12.2);命令式一条误点就丢一次决策,故显式关掉 —— 与 AntD 的 `<Modal maskClosable>`(开)/ `Modal.confirm`(关)同一分工 |
573
582
  | `Text` 只做六个维度(字号 / 行高 / 字重 / 语义色 / 等宽 / 截断) | 它补的是「容器里的文字层级」这条一直缺的路径;富文本解析、省略的展开交互都不归它 |
574
- | 本包零样式(无 reset、无富文本预设) | 样式只有两个来源:theme(值)与 ui(面)。本包夹在中间转发样式,只会让「值的来源」说不清 |
583
+ | 本包只有一条样式出口(`./reset.css`,宿主兜底;无组件样式、无富文本预设) | 组件样式只有两个来源:theme(值)与 ui(面),本包夹在中间转发只会让「值的来源」说不清。**只有宿主兜底**这一口是例外(2026-10-09 重开):平台门户全局注入的元素级规则(如 `@farris/ui-vue` 那条裸 `label { margin-bottom: .3125rem }`)子应用按 L1-6 既不能写裸元素选择器、也不能用 `!important`,只能由库复位 |
575
584
  | `theme` **有意不建 icons / motion 两片** | 图标不承载颜色(随文案色,见 L1.5-3);动效目前没有跨组件统一的语义。这两片是**有意未建**,不是遗漏 |
576
585
  | **已知缺口:富文本排版暂无归属** | 此前由本包的 `.app-markdown` 预设承担,已随样式删除;`@manohub/ui` 的 `reset` 也**不再代管**(2026-09 起它只有盒模型 + 容器基座两面,不再归零 `ul` / `ol` 的序号与 `a` 的下划线)。默认排版可以直接用,但要一套自己的正文排版(序号 / 间距 / 链接态)仍缺合规落点:需要富文本排版的页面只能整段进 §11 登记,或在 ui 提一个 `Markdown` 件 |
577
586
 
@@ -767,7 +776,7 @@ import Sortable from 'sortablejs' // 行为库:不产
767
776
 
768
777
  按**层**推进,每步单独可跑通(这也是最优顺序):
769
778
 
770
- 1. **L0 自查**(不可豁免,最先看):样式链两行 + 一个入口 + 锚。
779
+ 1. **L0 自查**(不可豁免,最先看):样式链三行(theme → ui → kit/reset.css)+ 一个入口 + 锚。
771
780
  2. **L2 换骨架**:先按 §5 的三种模板把页面骨架摆对——这一步收益最大、风险最低。
772
781
  3. **L3 逐件换**:按 §6 换件与 prop。旧 `App*` 名与底层风格 prop 的对照见
773
782
  `skills/manohub-kit-migrate/references/migration-map.md`。**重点坑**:分页 `page`(0 基) →
@@ -778,3 +787,22 @@ import Sortable from 'sortablejs' // 行为库:不产
778
787
  5. **L1.5 收图形**:全量搜 `<svg` / 文字符号 / `size=` / `rotate(`。
779
788
 
780
789
  逐文件的操作口径与验收清单见 `skills/manohub-kit-migrate/references/migration-playbook.md`。
790
+
791
+ ### 12.4 样式链补第三行(1.0.3 → 1.0.4)变了什么
792
+
793
+ **只有一件事**:`@manohub/kit` 重开**一条**样式出口 `./reset.css`,样式链从两行变三行。
794
+
795
+ | 变化 | 说明 |
796
+ | --- | --- |
797
+ | **`./reset.css` 出口恢复** | 0.6.0 删掉的三条出口(`./styles.css` / `./reset.css` / `./markdown.css`)里**只**恢复 `reset.css`,且是**新口径**:只收「宿主兜底」(平台门户全局注入的元素级规则),**不收设计、不做 Preflight 复刻** —— 加规则前的四条纪律见 `packages/kit/reset.css` 头部 |
798
+ | **L0-1 变为前三条** | 样式链:`theme/<主题>.css` → `ui/styles.css` → **`kit/reset.css`** → 自有样式;顺序不可换 |
799
+ | **为什么需要它** | 子应用被注入宿主页面,门户全局加载的第三方样式会作用到子应用 DOM。实测两例(`@farris/ui-vue` 的裸规则):`label { margin-bottom: .3125rem }`(label 多 5px 底边距)与 `button:focus { outline: -webkit-focus-ring-color auto 5px }`(点一下按钮留一圈深色焦点环);子应用按 L1-6 既不能写裸元素选择器、也不能用 `!important`,只能由库兜住 |
800
+ | **兜底规则怎么写** | 作用域一律 `:where([data-manohub-ui])`;能更精确就不一把梭 —— 如 button 那条写成 `button:focus:not(:focus-visible)`,只压**指针触发**的环,键盘焦点仍由组件面自画(`.mh-button:focus-visible`),特异性 (0,2,1) 硬胜宿主、不依赖注入顺序 |
801
+ | **升级动作** | 每个消费方**多一行** `@import "@manohub/kit/reset.css";`(放 ② 之后、自有样式之前);应用里为顶宿主而写的 `label { margin: 0 !important }` 一类违规可以删掉 |
802
+ | **有意不写 `!important`** | 与宿主那条同为未分层、(0,0,1) ⇒ 平手、靠样式注入顺序决胜(子应用样式在宿主之后注入;micro-app 的 scopecss 还会加 `micro-app[name=…]` 前缀,那更是硬胜) |
803
+
804
+ > 同版**收紧** 0.6.0 那条闸门(而不是撤掉它):`kit` **仍留在** `verify-pack` 的
805
+ > `CSS_FREE_PACKAGES` 名单里,「零样式」改由 `CSS_FREE_EXEMPT_PREFIXES` **按路径精确豁免**
806
+ > `package/reset.css` + `REQUIRED_TARBALL_ENTRIES.kit` 把它列为必需项 —— 除这一条外,发布物里
807
+ > 再出现任何 `.css` 仍会失败。同时 `packages/kit/AGENTS.md` 的「别再往本包加样式」改写为
808
+ > 「只许这一条出口,加规则前先读那份文件的纪律」。
package/README.md CHANGED
@@ -5,7 +5,7 @@ AIHub 子应用**入口编排层**:`createSubApp` 统一挂载、i18n 单实
5
5
 
6
6
  **组件与命令式服务不在本包** —— 它们来自 [`@manohub/ui`](https://www.npmjs.com/package/@manohub/ui);
7
7
  **全局令牌(值)不在本包** —— 它来自 [`@manohub/theme`](https://www.npmjs.com/package/@manohub/theme);
8
- **本包也不发布任何样式** —— 上面两行由消费方直接引。几个包并列安装。
8
+ **本包只出一条样式**(`@manohub/kit/reset.css`,宿主兜底)—— 上面两行由消费方直接引。几个包并列安装。
9
9
 
10
10
  > **0.6.0 是破坏性变更**(上一个已发布版本是 `@manohub/app-kit@0.4.3`):本包不再提供任何组件
11
11
  > (`App*` 前缀名与 `.ak-*` 类名全部退场、farris 依赖移除)、**主题层独立为 `@manohub/theme`**
@@ -31,18 +31,21 @@ pnpm add vue vue-router pinia vue-i18n @tanstack/vue-query
31
31
 
32
32
  `@manohub/ui` 自带图标包依赖(`@manohub/icon`),不必单独声明。
33
33
 
34
- ### 2. 样式:两行 + 应用自己一行(顺序即契约)
34
+ ### 2. 样式:三行 + 应用自己一行(顺序即契约)
35
35
 
36
- **本包不发布任何样式**:设计令牌(值)在 `@manohub/theme`、组件面(类 + 组件令牌基础值)在
37
- `@manohub/ui`,两行由消费方直接引;本包不再提供 reset、富文本预设与样式汇总入口。
36
+ **本包只出「宿主兜底」这一条样式**:设计令牌(值)在 `@manohub/theme`、组件面(类 + 组件令牌基础值)
37
+ 在 `@manohub/ui`;本包历史上那份 reset / 富文本预设 / 样式汇总入口不再提供,只留 `./reset.css`
38
+ —— 它把**平台门户全局注入**的元素级规则复位(子应用按 L1-6 改不掉,故上收到库)。
38
39
 
39
40
  ```css
40
41
  @import "@manohub/theme/default.css"; /* ① 令牌(值)—— 换主题只换这一行 */
41
- @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
42
- @import "./app.css"; /* ③ 应用自身(只写布局) */
42
+ @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
43
+ @import "@manohub/kit/reset.css"; /* ③ 宿主兜底(元素级复位,见该文件头部) */
44
+ @import "./app.css"; /* ④ 应用自身(只写布局) */
43
45
  ```
44
46
 
45
- **顺序不可换**:先值(令牌)后面(组件面)—— 反过来的话组件面里的 `var(--ui-*)` 全是空值。
47
+ **顺序不可换**:先值(令牌)、后面(组件面)、兜底在库的最后一位 —— 反过来的话组件面里的
48
+ `var(--ui-*)` 全是空值。
46
49
 
47
50
  改用非兜底主题:把 ① 换成对应主题入口 + 给容器属性 ——
48
51
 
@@ -142,10 +145,11 @@ pnpm exec kit install --dry-run # 先看会写什么
142
145
  | --- | --- |
143
146
  | `@manohub/kit` | `useClientPagination`、`resolveAppContainer` / `resolveAppContainerSelector` |
144
147
  | `@manohub/kit/entry` | `createSubApp`、`installInitialGuard`、`createQueryClient`、`applyLocale` / `getLocale` / `i18n` / `setupI18n` |
148
+ | `@manohub/kit/reset.css` | **唯一一条样式出口**:宿主兜底(元素级复位,见 §2 的 ③) |
145
149
  | `@manohub/kit/CONTRACT.md` | 接入契约(权威规范:五层闭集条款 + §7 自检清单) |
146
150
 
147
- **本包没有任何样式出口**(0.6.0 起):`./styles.css`、`./reset.css`、`./markdown.css` 都已删除。
148
- 样式请引 `@manohub/theme` 与 `@manohub/ui` 的公开入口(见上面 §2)。
151
+ **本包只有上面那一条样式出口**:`./styles.css` / `./markdown.css` 与富文本预设仍不提供。
152
+ 令牌与组件面请引 `@manohub/theme` / `@manohub/ui` 的公开入口(见上面 §2)。
149
153
 
150
154
  ## 技能包(AI 代理用,随包分发)
151
155
 
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@manohub/kit",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "private": false,
5
5
  "type": "module",
6
- "description": "子应用入口编排层:createSubApp(作用域容器与宿主锚点、pinia/路由/vue-query 装配、宿主挂载协议)、i18n 单实例与语言探测,外加随包分发的接入契约(CONTRACT.md,五层闭集条款 + 自检清单)与三个 AI 技能包。本包**零样式产物**:设计令牌(值)在 @manohub/theme,组件(类与行为)在 @manohub/ui,两者由消费方直接引入。",
6
+ "description": "子应用入口编排层:createSubApp(作用域容器与宿主锚点、pinia/路由/vue-query 装配、宿主挂载协议)、i18n 单实例与语言探测,外加随包分发的接入契约(CONTRACT.md,五层闭集条款 + 自检清单)与三个 AI 技能包。样式方面本包只有**一条出口** `./reset.css`(宿主兜底:把平台门户全局注入的元素级规则复位;设计令牌(值)在 @manohub/theme,组件(类与行为)在 @manohub/ui,两者由消费方直接引入)。",
7
7
  "license": "UNLICENSED",
8
8
  "repository": {
9
9
  "type": "git",
@@ -18,6 +18,7 @@
18
18
  "dist",
19
19
  "skills",
20
20
  "bin",
21
+ "reset.css",
21
22
  "CONTRACT.md",
22
23
  "README.md"
23
24
  ],
@@ -34,6 +35,7 @@
34
35
  "types": "./dist/entry/index.d.ts",
35
36
  "import": "./dist/entry/index.js"
36
37
  },
38
+ "./reset.css": "./reset.css",
37
39
  "./CONTRACT.md": "./CONTRACT.md"
38
40
  },
39
41
  "main": "./dist/index.js",
package/reset.css ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * 宿主兜底 reset —— `@manohub/kit` **唯一**一条样式出口(`@import "@manohub/kit/reset.css"`)。
3
+ *
4
+ * ## 为什么这条得由 kit 出
5
+ *
6
+ * 子应用是被**注入宿主页面**的:宿主(平台门户)全局加载的样式会按文档作用域作用到子应用 DOM。
7
+ * 实测两例,都出自门户全局引的 `@farris/ui-vue/index.css`(都是**裸元素**规则、未分层、无 `!important`):
8
+ *
9
+ * label { margin-bottom: .3125rem } ← 特异性 0,0,1
10
+ * button:focus { outline: -webkit-focus-ring-color auto 5px } ← 特异性 0,1,1
11
+ *
12
+ * ⇒ 子应用里每个 `label` 凭空多出 5px 底边距;每个 `button`一**点击**就多留一圈 5px 深色焦点环
13
+ * (写的是 `:focus` 而非 `:focus-visible` ⇒ 鼠标点击也命中)。子应用自己修不掉:契约 L1-6 既不许它写
14
+ * 裸元素选择器、也不许用 `!important`(§11 红线,登记也不放行)—— 兜底只能由库提供,故有本文件。
15
+ *
16
+ * 出处(两例都由 `aip-web/apps/aip-connection-manage` 的实测上收,2026-10-09):
17
+ * - `label`:应用侧当时写了一条违规补丁 `label { margin: 0 !important }` 顶它,已随本文件删除;
18
+ * - `button`:应用侧从未落过补丁,只在库内**零散清过** —— `packages/ui/src/styles/components/page.css`
19
+ * 的自绘按钮注释原话:「上游 `button:focus` 的 5px 深色环特异性高于基础态,必须显式清掉」。
20
+ *
21
+ * ## 它与 `@manohub/ui/styles.css` 的关系:分工,不是重复
22
+ *
23
+ * 元素级基线的两面(盒模型 / 容器基座)在 `@manohub/ui/styles.css` 的**首条** import,组件面归
24
+ * `@manohub/ui` —— **本文件不是第二个 ui reset**:它只收「宿主/第三方注入进来、子应用按契约又改不掉」
25
+ * 的那几条,每条都要在下面写清**出处**(被谁污染、症状是什么)。往这里加东西前先读下一节。
26
+ *
27
+ * ## 加规则前必读(与 ui reset 同一条纪律)
28
+ *
29
+ * 1. **未分层赢过分层**:本文件在 `@layer` 外,里面的声明会压住消费方的 Tailwind 工具类
30
+ * (`border*` / `img` 上的 `h-*` / `hidden` 一类实测过),而且这条**优先于特异性** ——
31
+ * 先自问「这条会不会压住消费方的工具类」,会压就别加(该归**渲染它的组件面**)。
32
+ * 2. **作用域一律 `:where([data-manohub-ui])` 包裹**:`:where()` 特异性为 0,等价于纯元素选择器,
33
+ * 不会反压 ui 的组件面(普遍单类 0,1,0)。
34
+ * 3. **有意不写 `!important`**:库内零先例;且它会连带压掉库与消费方将来给同名元素设的外边距。
35
+ * 与宿主那条同为未分层、同为 (0,0,1) ⇒ **平手,靠样式注入顺序决胜** —— 子应用的样式在宿主
36
+ * 样式之后注入,故本文件胜出;micro-app 的 scopecss 还会给子应用选择器加 `micro-app[name=…]`
37
+ * 前缀,那更是硬胜。真遇到宿主用 `!important` 或更高特异性时,回来改这里的**锚点**,别改纪律。
38
+ * 4. **只收兜底,不收设计**:视觉值一律归 `@manohub/theme` 的令牌,本文件只做「归零 / 复位」。
39
+ */
40
+
41
+ /* ===== `label` 外边距归零 =====
42
+
43
+ 出处:平台门户全局引 `@farris/ui-vue/index.css` 的裸 `label { margin-bottom: .3125rem }`。
44
+ 症状:卡片 / 表单里的 label 全部多 5px 底边距(子应用里各表单首屏、卡片信息行都受影响)。
45
+ 为什么归零四面而不是只归 `margin-bottom`:契约不许子应用写元素选择器,故库内不设的边距
46
+ 谁都补不回来;而**任何带类的规则都盖得过它**(本文件特异性 0,0,1),不会挡住正常排版。 */
47
+ :where([data-manohub-ui]) label {
48
+ margin: 0;
49
+ }
50
+
51
+ /* ===== `button` 焦点环:只压宿主那一圈,不碰键盘焦点 =====
52
+
53
+ 出处:平台门户全局引 `@farris/ui-vue/index.css` 的裸 `button:focus`(Bootstrap reboot 同款写法):
54
+ `outline: dotted 1px; outline: -webkit-focus-ring-color auto 5px`(另有一处 `4px auto -webkit-focus-ring-color`
55
+ 同源)。写成 `:focus` 而非 `:focus-visible` ⇒ **鼠标点击**也命中,症状是「点一下按钮就留一圈深色环」。
56
+ 为什么是 `:focus:not(:focus-visible)` 而不是一把 `outline: none`:
57
+ - **只压指针触发的那一圈**:键盘 Tab 到按钮时 `:focus-visible` 命中、本条不参与,焦点反馈仍由渲染
58
+ 该按钮的组件面自画(如 `.mh-button:focus-visible` 的 2px 主色环)—— 不把无障碍一起删掉;
59
+ 库外的原生按钮也仍留着宿主那圈作键盘反馈。
60
+ - `:not(:focus-visible)` 把特异性抬到 (0,2,1),**硬胜**宿主那条 (0,1,1):不依赖样式注入顺序,
61
+ 也不需要用 `!important`。
62
+ 库内已有的零散同类补丁(如 `page.css` 的自绘按钮 `…-btn:focus { outline: none }`)**保留不动**:
63
+ 组件不该假定消费方一定引了本文件 —— 这里是「宿主兜底」,不是「组件面的替代品」。 */
64
+ :where([data-manohub-ui]) button:focus:not(:focus-visible) {
65
+ outline: none;
66
+ }
package/skills/lint.mjs CHANGED
@@ -104,7 +104,7 @@ const ALLOWED_SOURCES = [
104
104
  { name: '@manohub/ui', subpaths: ['/styles.css'] },
105
105
  { name: '@manohub/icon', subpaths: ['/glyphs'] },
106
106
  { name: '@manohub/theme', subpaths: ['/default.css', '/farris.css'] },
107
- { name: '@manohub/kit', subpaths: ['/entry', '/CONTRACT.md'] },
107
+ { name: '@manohub/kit', subpaths: ['/entry', '/reset.css', '/CONTRACT.md'] },
108
108
  ]
109
109
 
110
110
  /**
@@ -36,21 +36,26 @@ done
36
36
 
37
37
  ## 2. 样式:两行 + 应用自己一行(顺序即契约)
38
38
 
39
- **`@manohub/kit` 不发布任何样式** —— 样式两行直接引主题包与组件库的公开入口。
39
+ **`@manohub/kit` 只出一条样式(宿主兜底)** —— 令牌与组件面直接引主题包与组件库的公开入口。
40
40
 
41
41
  应用入口 CSS(如 `src/style.css`):
42
42
 
43
43
  ```css
44
44
  @import "@manohub/theme/default.css"; /* ① 令牌(值)—— 换主题只换这一行 */
45
- @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
46
- @import "./app.css"; /* ③ 应用自身(只写布局) */
45
+ @import "@manohub/ui/styles.css"; /* ② 组件面(类 + 组件令牌基础值) */
46
+ @import "@manohub/kit/reset.css"; /* ③ 宿主兜底(元素级复位) */
47
+ @import "./app.css"; /* ④ 应用自身(只写布局) */
47
48
  ```
48
49
 
49
- - **顺序不可换**:先值(令牌)后面(组件面)—— 反过来的话组件面里的 `var(--ui-*)` 全是空值。
50
+ - **顺序不可换**:先值(令牌)、后面(组件面)、兜底收尾 —— 反过来的话组件面里的 `var(--ui-*)` 全是空值。
50
51
  - 换非兜底主题时把 ① 换成对应主题入口(如 `@import "@manohub/theme/farris.css";`),
51
52
  并在入口给 `createSubApp({ theme: 'farris' })`。
52
- - **reset 与富文本排版归应用自己**:本包不再提供 `reset.css` 与 `.app-markdown` 预设
53
- (0.6.0 起 `src/styles/` 整体删除)。应用侧要写时注意仍受样式纪律约束(契约 §3 L1)。
53
+ - **③ 是宿主兜底**:子应用被注入宿主页面,平台门户全局加载的样式会按文档作用域落到子应用 DOM
54
+ (实测一条:门户的 `@farris/ui-vue` 带裸 `label { margin-bottom: .3125rem }`,让每个 `label`
55
+ 多 5px 底边距);这类「元素级、无类名」的规则子应用按 L1-6 改不掉(不许裸元素选择器、不许
56
+ `!important`),故由 ③ 复位。它**只收兜底、不收设计**,别往里加视觉。
57
+ - **富文本排版仍归应用自己**:`.app-markdown` 预设不提供(0.6.0 起删除,契约 §10 记着这个缺口);
58
+ 应用侧要写时注意仍受样式纪律约束(契约 §3 L1)。
54
59
 
55
60
  ## 3. 入口:走 createSubApp
56
61
 
@@ -11,14 +11,14 @@ farris(底层组件库)也不再是依赖。
11
11
 
12
12
  ---
13
13
 
14
- ## 零、0.6.0 增量(主题独立成包 + 容器锚改名 + kit 零样式)
14
+ ## 零、0.6.0 增量(主题独立成包 + 容器锚改名 + kit 只剩一条样式出口)
15
15
 
16
16
  只在**已按 0.6.0 迁完**的仓上做,四步:
17
17
 
18
18
  | 旧 | 新 | 说明 |
19
19
  |---|---|---|
20
- | `@import "@manohub/kit/styles.css"` | **删掉**,改引 `@manohub/theme/default.css` + `@manohub/ui/styles.css` | kit **不再发布任何样式**(`src/styles/` 整体删除):样式汇总入口、reset、富文本预设全没了 |
21
- | `@import "@manohub/kit/reset.css"` | **删掉**(或应用自己补一份 reset) | 同上;reset 的归属随样式一并退场 |
20
+ | `@import "@manohub/kit/styles.css"` | **删掉**,改引 `@manohub/theme/default.css` + `@manohub/ui/styles.css` + `@manohub/kit/reset.css` | kit 的样式汇总入口已退场(`src/styles/` 整体删除):令牌归 theme、组件面归 ui,kit 只留 `reset.css` 一条出口 |
21
+ | `@import "@manohub/kit/reset.css"` | **保留,但换成新版那一份** | 2026-10-09 起它是「只收宿主兜底」的元素级复位(旧版是 Tailwind Preflight 复刻,那批规则会把消费方工具类整片压住);元素级基线的两面已并入 `@manohub/ui/styles.css` 的**首条** import |
22
22
  | `@import "@manohub/ui/theme/default.css"` | `@import "@manohub/theme/default.css"` | 全局令牌已独立成 **`@manohub/theme`**;ui 的 `theme/*` 出口**已删**(无兼容指针) |
23
23
  | `@import "@manohub/ui/theme/farris.css"` | `@import "@manohub/theme/farris.css"` | 同上;用非兜底主题时把它替换掉上面那条 ① |
24
24
  | 容器上的 `data-app-container` | **`data-manohub-ui`** | 跨包唯一作用域锚,由入口层**无条件**写;旧属性不再被任何一方识别(无兼容别名) |