包与依赖关系
XiHan.UI 是一个 pnpm workspace。packages/*/* 是对外发布的库包(按角色分 adapters / design / features / engine / tools 五组),tooling/* 是内部工具(不发布)。
全部库包
| 包 | 依赖 | peer 依赖 | 层 |
|---|---|---|---|
@xihan-ui/core | motion | — | 1 |
@xihan-ui/tokens | — | — | 1 |
@xihan-ui/icons | — | — | 1 |
@xihan-ui/motion | — | — | 1 |
@xihan-ui/pointer | — | — | 1 |
@xihan-ui/viz | — | — | 1 |
@xihan-ui/expression | — | — | 1 |
@xihan-ui/xlsx | — | — | 1 |
@xihan-ui/position | core | — | 2 |
@xihan-ui/code-highlight | core | — | 2 |
@xihan-ui/chat-stream | core | — | 2 |
@xihan-ui/markdown | — | — | 2 |
@xihan-ui/sound | core | — | 2 |
@xihan-ui/designer-kit | core pointer expression viz | — | 2 |
@xihan-ui/animations | core motion | — | 2 |
@xihan-ui/headless | core motion pointer viz expression | — | 3 |
@xihan-ui/styles | tokens(只取其 CSS 产物) | — | 3 |
@xihan-ui/backgrounds | core motion | — | 3 |
@xihan-ui/vue | core motion pointer viz expression headless position | vue、backgrounds(可选)、sound(可选)、code-highlight(可选) | 4 |
@xihan-ui/web-components | core motion pointer viz expression headless position | backgrounds(可选)、code-highlight(可选) | 4 |
@xihan-ui/designer-shell | core pointer viz designer-kit web-components | — | 5 |
@xihan-ui/cli | — | — | 5 |
发布走 changesets,所有库包同属一个 fixed 版本组,一起升到同一个版本号。
依赖图
箭头方向 = 依赖方向,只画实际声明的依赖。同层之间只有 core → motion 一条横向依赖。
层 5 ┌──────────────────┐
│ designer-shell │ 只出 Web Components
└────────┬─────────┘
│ core · pointer · viz · designer-kit · web-components
▼
层 4 ┌─────────────┐ ┌──────────────────┐
│ vue │ │ web-components │ peer: backgrounds · code-highlight(可选);vue 另有 peer: sound(可选)、vue
└──────┬──────┘ └────────┬─────────┘
│ core · motion · pointer · viz · expression · headless · position
└───────────┬───────────┘
▼
层 3 ┌──────────────┐ ┌───────────────────┐ ┌────────────────┐
│ headless │ │ backgrounds │ │ styles(纯CSS)│
└──────┬───────┘ └─────────┬─────────┘ └───────┬────────┘
core·motion·pointer·viz· core·motion tokens 的 CSS 产物
expression │ │
▼ ▼
层 2 ┌──────────┐ ┌────────────────┐ ┌─────────────┐ ┌───────┐ ┌────────────┐ ┌──────────────┐ ┌──────────┐
│ position │ │ code-highlight │ │ chat-stream │ │ sound │ │ animations │ │ designer-kit │ │ markdown │
└────┬─────┘ └───────┬────────┘ └──────┬──────┘ └───┬───┘ └─────┬──────┘ └──────┬───────┘ └──────────┘
└───────────────┴─────────────────┴───────────┴───────────┴───────────────┘ 无依赖
▼
层 1 ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────┐ ┌─────────┐ ┌─────┐ ┌────────────┐ ┌──────┐
│ core │─►│ motion │ │ tokens │ │ icons │ │ pointer │ │ viz │ │ expression │ │ xlsx │
└──────────┘ └──────────┘ └──────────┘ └───────┘ └─────────┘ └─────┘ └────────────┘ └──────┘
零运行时依赖 无依赖 无依赖 无依赖 无依赖 无依赖 无依赖五个包完全独立,可以单独使用:
@xihan-ui/tokens:只需要设计令牌与主题运行时,不需要组件;@xihan-ui/markdown:只需要流式 Markdown 渲染内核;@xihan-ui/expression:只需要在模板里写公式与条件;@xihan-ui/xlsx:只需要把表格写成 Excel 文件;@xihan-ui/styles:纯 CSS,它对tokens的依赖只是为了@import令牌产物,不引入任何 JS。
依赖规则
分层拓扑写在 tooling/eslint-config/src/layers.json 中,由 dependency-cruiser 在 pnpm boundaries 时强制。层级越低越基础,只能依赖 canDependOn 列出的包。
除分层外还有四条规则:
| 规则 | 内容 |
|---|---|
no-circular | 禁止循环依赖 |
no-unresolvable | 无法解析的 import:最常见的成因是引用了邻层却未在 package.json 中声明依赖 |
styles-no-js-deps | styles 是纯 CSS,不得依赖任何 JS 包 |
no-external-in-packages | 库包的运行时代码不得引入第三方 |
第三方运行时依赖
没有。登记在案的例外只有适配器的宿主框架:@xihan-ui/vue 的 vue,@xihan-ui/react 的 react 与 react-dom。
以下能力均为自研,不引入第三方:
| 能力 | 包 | 常见的第三方选择 |
|---|---|---|
| 日期运算、时区换算与按地区的周 | core(@xihan-ui/core/date) | date-fns / Day.js / @internationalized/date |
| 浮层定位 | position | Floating UI |
| 代码着色 | code-highlight | Shiki / Prism |
| Web Components 响应式基类 | web-components | Lit |
| Markdown 渲染 | markdown | markdown-it / marked |
| 状态机 | core | XState |
新增第三方运行时依赖必须逐条登记进白名单并写明理由与移除条件,由 check-runtime-deps 门禁保证。
开发期第三方依赖另行处理
@lit/reactive-element 与 commonmark-spec 出现在 workspace catalog 中,但只供测试比对:前者用于差分校验自研响应式基类,后者用于读取 CommonMark 官方用例。两者都不进入任何包的运行时依赖。
版本约定
- 内部运行时依赖一律
workspace:^(发布时展开为当前锁步版本的^区间),内部开发期依赖用workspace:*; - 第三方版本只从 workspace catalog 取,包内写
catalog:,不得内联版本号(check-exact-pins门禁); - 升级只改
pnpm-workspace.yaml的 catalog 一处。
产物契约
| 项 | 值 |
|---|---|
| 模块格式 | ESM only,不提供 CJS |
| Node | >= 18 |
| 类型 | 每个入口一份 .d.ts |
| 副作用 | 全部 sideEffects: false,styles、tokens/tokens.css 与 designer-shell/style.css 除外 |
pnpm gate:publish 逐包运行 publint 与 attw,按 ESM-only 的支持面校验 exports 条件与类型解析(node16-from-ESM 与 bundler 两列)。
子路径导出
主入口之外另有子路径的包:
| 包 | 子路径 |
|---|---|
@xihan-ui/core | ./metadata ./skin-check ./vite ./vanilla ./presence ./json(JSON 值的类型与纯函数,零依赖) ./options(选项与选项树的结构校验,零依赖) ./hotkey(快捷键的平台写法与按键命中,零依赖) ./url(图片与链接地址的安全判定,零依赖) ./clipboard(往系统剪贴板写文本,零依赖) ./template(文本模板,占位只写数据路径) ./rich-text(富文本模型、HTML 白名单解析与检查,零依赖) ./rich-text-dom(按富文本模型生成 DOM) ./svg-export(SVG 克隆成独立文件、序列化与栅格化成 PNG,只在浏览器里用) ./color(颜色换算:十六进制、RGB、HSV、HSL、OKLCH 互转,CSS 颜色写法的解析与写出,零依赖) |
@xihan-ui/designer-kit | ./field-inference(从 JSON 样例与 JSON Schema 推断字段树、合并字段) ./properties(属性描述、显示条件、取值检查与自定义编辑器接口) ./schema(结构校验的问题形状与读取器) |
@xihan-ui/designer-shell | ./locale(零件的中文文案) ./style.css(零件的样式) |
@xihan-ui/tokens | ./runtime ./tokens.css ./tokens.json |
@xihan-ui/icons | ./codegen |
@xihan-ui/viz | ./hierarchy(层级布局:层级节点、组树、矩形树图、分区与圆堆积) ./sankey(桑基布局) |
@xihan-ui/headless | ./locale(内建语言包) |
@xihan-ui/vue | ./backgrounds ./behavior ./locale ./plugin(全量注册与全局组件类型) ./resolver(unplugin-vue-components 的组件解析器) ./sound |
@xihan-ui/react | ./backgrounds ./behavior ./locale ./sound |
@xihan-ui/web-components | ./define ./backgrounds ./locale ./services ./authoring(第三方编写元素用的基类与辅助件) ./custom-elements.json |
@xihan-ui/styles | 每份皮肤一条 CSS,共 155 条(143 份组件皮肤 + 12 份共享层),另有 ./index.css(主入口,生成的扁平有层文件,家族只内联一次)与 ./index.unlayered.css 两个整包入口 |
其余十二个包(motion / pointer / position / code-highlight / animations / backgrounds / chat-stream / markdown / sound / cli / expression / xlsx)只有主入口。
组件没有单独的子路径导出:按需引入依靠 tree-shaking,不依靠手写路径。
