@xnary/pastry-ui

Pastry UI — 基于 Vue 3 的企业级组件库
Install
npm install @xnary/pastry-ui
Latest Version:0.1.0
Vue:3
License:MIT
Last Updated:Sep 16, 2026
Links: npm
Maintainer: shijunfan

Pastry UI

基于 Vue 3 的企业级组件库,从内部项目抽离并发布到公网 npm。

  • 包名:@xnary/pastry-ui
  • 依赖:vue@^3.3(peer)
  • 组件:53 个(表单、表格、弹窗、菜单、日期时间、上传、树形/级联、DAG 画布等)
  • 设计特点:核心包零业务依赖——不引用任何宿主代码、不内置图标库、不内置请求实现,全部通过注册/注入接入。

安装

npm install @xnary/pastry-ui

快速开始

// main.js
import { createApp } from 'vue'
import PastryUI from '@xnary/pastry-ui'
import '@xnary/pastry-ui/style.css'   // 组件样式(必须)
import '@xnary/pastry-ui/global.css'  // 全局滚动条等(可选,会作用于整个页面)
import { useIconParkIcons } from '@xnary/pastry-ui/adapters/iconpark'

const app = createApp(App)

app.use(PastryUI, {
  // 可选:注入默认上传实现,PtUpload 不传 action/httpRequest 时用它
  upload: {
    request: ({ file, onSuccess, onError }) => { /* ... */ }
  }
})

// 图标:注册适配器后 <PtIcon name="search" /> 才会渲染
useIconParkIcons()

按需引入(不注册全局组件):

import { PtButton, PtTable, PtTableColumn } from '@xnary/pastry-ui'
import '@xnary/pastry-ui/style.css'

图标(PtIcon)

PtIcon 是纯包装组件:自身不含任何图标库代码,图标一律通过适配器注册提供。

<PtIcon name="search" />              <!-- 走默认适配器 -->
<PtIcon name="tdesign:home" />        <!-- 冒号前缀显式指定适配器(多个图标库可共存) -->
<PtIcon name="search"><svg/></PtIcon> <!-- 有插槽时插槽优先 -->

适配器契约:

import { registerIconAdapter } from '@xnary/pastry-ui'

registerIconAdapter({
  name: 'my-icons',                            // 适配器名,用于 name="my-icons:home"
  resolve: (iconName) => icons[iconName],      // 返回组件对象或已全局注册的组件名字符串;拿不到返回 null
  props: ({ size, color, strokeWidth }) => ({  // 可选:抹平图标库传参差异
    size, fill: color
  }),
  aliases: { 'arrow-left': 'Left' }            // 可选:本图标库专有的名称别名表
}, { asDefault: true })

用 IconPark

npm install @icon-park/vue-next
import { useIconParkIcons } from '@xnary/pastry-ui/adapters/iconpark'

useIconParkIcons()                     // 注册为默认适配器
useIconParkIcons({ asDefault: false }) // 或只注册,之后写 name="iconpark:home"

该适配器保留了历史别名表(arrow-left、warning、success-filled、document-add、setting、people 等),老项目的 name 写法可直接沿用。

用 TDesign 图标

import { registerIconAdapter } from '@xnary/pastry-ui'
import * as TDesign from 'tdesign-icons-vue-next'

const pascal = (name) => String(name).replace(/(^[a-zA-Z])|(-[a-zA-Z])/g, (c) => c.slice(-1).toUpperCase())

registerIconAdapter({
  name: 'tdesign',
  // TDesign 的组件名带 Icon 后缀:home → HomeIcon
  resolve: (name) => TDesign[`${pascal(name)}Icon`] ?? TDesign[pascal(name)] ?? null,
  props: ({ size, color }) => ({ size, fill: color })
}, { asDefault: true })

图标找不到时不会抛错:优先渲染插槽,无插槽则渲染空占位,并在控制台按图标名提示一次。

上传(PtUpload)

包内不含任何请求实现,上传通过以下三种方式之一提供(优先级从高到低):

  1. 组件 prop::http-request="fn"
const uploader = ({ file, onSuccess, onError }) => {
  const fd = new FormData()
  fd.append('file', file)
  myApi.post('file/upload', fd, { headers: { 'Content-Type': 'multipart/form-data' } })
    .then(onSuccess)
    .catch(onError)
}
  1. 组件 prop:action="/api/file/upload"(配 :headers,内部用 fetch)

  2. 安装时注入默认上传器(适合大量存量调用点):

app.use(PastryUI, {
  upload: {
    request: ({ file, onSuccess, onError }) => { /* 同上 */ }
  }
})

也可以在运行时配置:

import { setPastryUIConfig } from '@xnary/pastry-ui'
setPastryUIConfig({ upload: { request: uploader } })

三者都没有时会给出明确报错提示,不会静默失败。

组件清单

  • 基础:PtButton PtButtonGroup PtIcon PtDivider PtTag PtAlert PtProgress PtEmpty
  • 表单:PtInput PtInputNumber PtSelect PtOption PtOptionGroup PtCheckbox PtCheckboxGroup PtRadio PtRadioGroup PtRadioButton PtSwitch PtSlider PtColorPicker PtCascader PtCitySelect PtUpload PtForm PtFormItem
  • 日期时间:PtDatePicker PtDateTimePicker PtTimePicker
  • 数据:PtTable PtTableColumn PtPagination PtTransfer PtDagCanvas
  • 反馈/浮层:PtDialog PtDrawer PtTooltip PtPopover PtPopup PtDropdown PtDropdownMenu PtDropdownItem PtImagePreview PtCascadingMenu
  • 导航/布局:PtMenu PtMenuItem PtSubMenu PtSidebar PtTabs PtTabPane PtRow PtCol
  • 命令式 API:PtMessage PtMessageBox PtLoading、指令 v-pt-loading

组件文档(Storybook)

组件文档是本仓库里的一个独立子项目 storybook/(自带 package.json、依赖与脚本,不参与组件库构建与发布;根包 files 白名单不含它)。 文档直接引用 src/ 源码,改组件即时生效;覆盖全部 52 个组件 + 命令式 API + 设计令牌。

cd storybook
npm install          # 只装文档工程依赖
npm run storybook    # http://localhost:6006

新增组件后请补 storybook/stories/<分类>/<组件名>.stories.js:npm run build-storybook 与 npm run storybook 都会先跑 npm run check,漏写文档会直接失败并列出缺哪个组件。写故事的约定见 storybook/README.md。

样式与主题

  • @xnary/pastry-ui/style.css:组件样式 + CSS 变量(--pt-*),必须引入。
  • @xnary/pastry-ui/global.css:全局滚动条等会外溢的规则,可选。
  • 主题:覆盖 :root 上的 --pt-accent、--pt-surface、--pt-border-radius-* 等变量即可。
  • 移动端适配断点约定为 768px。

发布

npm run release -- patch      # 递增版本 → 构建 → 校验产物 → npm publish --access public
npm run release -- 0.2.0      # 指定版本
npm run release -- patch --dry-run   # 只构建与校验,不发布

发布前需要拥有 @xnary scope 的公网 npm 权限(npm login,或 CI 中配置 Automation token)。脚本会自动校验产物里没有内网地址、内部接口路径等痕迹。

完整发版与升级流程

  1. 改代码:在 E:/workspaces/pastry-ui 修改组件,本地 npm run dev 起 demo 页面自测。

  2. 构建与校验:npm run build,确认 dist/ 下有 pastry-ui.es.js、pastry-ui.umd.cjs、pastry-ui.css、global.css、cityData.json、adapters/iconpark.js。

  3. 本地验证:npm pack 出 tgz,在任一业务项目里 npm install <tgz 路径> 跑通页面(图标、上传、表格、弹窗)后再发布。

  4. 发布:npm run release -- patch(版本号递增 + 构建 + 校验 + npm publish --access public),随后 git commit、git tag v<版本>、git push --follow-tags。

  5. 各项目升级(6 个项目:basic-framework、ajitai-lesson、stardust-new、falco-shop、shimmer/server、pastrybi):

    # npm 项目
    npm install @xnary/pastry-ui@<版本> && npm run build
    # shimmer/server 用 pnpm
    pnpm add @xnary/pastry-ui@<版本> && npm run build
    

    升级后回归:图标显示、上传、表格(排序/列宽/固定列/分页)、弹窗与提示、日期时间选择器、页面整体样式(滚动条)。

  6. archetype 模板同步(仅 basic-framework):在 basic-framework/archetype 下跑 python3 sync-to-archetype.py,把最新的 frontend/(含新版本依赖与 main.js 接入代码)同步进模板,再 mvn install 更新本地 archetype。

破坏性变更(组件 API、样式引入方式、图标注册方式等)必须同步更新 MIGRATION.md,并在 CHANGELOG.md 里单独标出。

License

MIT

Related Packages

@alanlee97/lee-ui

基于 Vue 3 的轻量级 UI 组件库

909
@yymojo-tec/mojo-ui

Mojo UI 是 YYmojo 旗下维护的 UI 组件库。

9,973
whelk-ui

Vue3 Component Library for NearBeach

5,447
@finmars/ui

Finmars UI library for Vue 3 applications.

2,862

Version History

Version Released Vue License
0.1.0 ^3.3.0 MIT