@ptengine/ui
v0.3.1
Published
Ptengine 基础组件内核:Stencil 编写的 Web Components,输出标准 Custom Elements。
Readme
@ptengine/ui
Ptengine 基础组件内核。用 Stencil 编写,产物是标准 Custom Elements, 在原生 HTML、React、Vue、Angular、Svelte、Solid 里都能用。
组件 API 不含任何 Stencil 概念:标签、属性、事件、插槽、CSS 变量都是 Web 标准。
安装
npm i @ptengine/ui框架项目建议直接装对应的包装包(@ptengine/ui-react / -vue / -angular),
它们带类型、带框架习惯的事件名与双向绑定;下面是不经包装层的用法。
原生 HTML / CDN
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@ptengine/ui/dist/ptengine-ui/ptengine-ui.css"
/>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@ptengine/ui/dist/ptengine-ui/ptengine-ui.esm.js"
></script>
<pt-button variant="brand">开始使用</pt-button>懒加载:页面上出现哪个标签才下载哪个组件。那行样式表可以省:组件会自动把设计变量挂到页面上。
但建议留着 —— 有它首屏不闪,页面自己写的 var(--pt-*) 在第一个组件加载之前也有值。
打包器(Vite / webpack / Rollup)
import '@ptengine/ui/components/pt-button.js'; // 按需导入,可 tree-shaking样式表不用引:第一个组件连上页面时会自动把设计变量挂到 document 上。服务端渲染的页面建议在入口手动引一次
@ptengine/ui/dist/ptengine-ui/ptengine-ui.css,首屏才不会闪(引了的话自动注入会跳过)。
components/<tag>.js 是 import 即注册的入口。要自己控制注册时机,改从无副作用的
@ptengine/ui/dist/components/<tag>.js 取 defineCustomElement 手动调用 —— 三个框架包装层就是这么做的,
所以只用到一个组件时,其余组件不会被打进产物(pnpm treeshake:check 守着这一条)。
轻提示(@ptengine/ui/toast)
import { toast } from '@ptengine/ui/toast';
toast.success('保存成功', { description: '改动已同步' });不是组件:它找页面上的 <pt-toaster>(没有就在 <body> 末尾建一个)并调它的 show()。
三个框架包装包都从这里导入;Node 里(SSR)调用是空操作。
主题
变量来自 @ptengine/tokens,声明在 :root。组件内部是 Shadow DOM,
样式隔离,但自定义属性照常继承进来,所以换主题只需在根节点上切一组变量:
<html data-pt-theme="dark"></html>不写 data-pt-theme 时跟随系统。局部主题孤岛也支持:<div class="pt-dark">…</div>。
定制
Shadow DOM 默认开启,定制点是显式开放的,不是「随便怎么覆盖都行」:
- CSS 变量
--pt-*:改颜色、圆角、间距,作用于整个子树 ::part():改内部某个元素的样式,每个组件的 part 列表见各自的 README
pt-button::part(base) {
letter-spacing: 0.02em;
}组件 API 规范
写新组件前先读仓库根目录的 docs/component-api.md。
规范定稿于 1.0 之前,之后再改就是全线 breaking change。
开发
pnpm --filter @ptengine/ui dev # 本地开发服务器
pnpm --filter @ptengine/ui test # spec 测试
pnpm build # 构建并重新生成三个框架的包装层包装层(packages/ui-react 等)的 src/components 是构建产物,不要手改:
改内核后跑一次 pnpm build,把重新生成的文件一起提交,CI 会校验两者一致。
