@cldemo/ui-kit

Vue 3 + TypeScript 组件库,提供 PC 端和移动端的通用 UI 组件及工具函数。
4,742
Install
npm install @cldemo/ui-kit
Latest Version:1.1.12
Vue:3
License:MIT
Last Updated:Oct 18, 2026
Links: npm
Maintainer: chelei

VueDemo

Vue 3 + TypeScript 组件库,提供 PC 端和移动端的通用 UI 组件及工具函数。

快速开始

npm install       # 安装依赖
npm run lib:build # 构建组件库产物

按需使用与全局注入

组件库支持 按需引入(推荐)与 全量 install 两种方式,需注意以下几点:

  • 按需引入组件(三种路径任选,均自带组件样式与 TS 类型):
    • unplugin-vue-components + clResolver(见 buildLibs/resolver),组件列表自动从 clComponentMap 解析;推荐业务侧首选,也是唯一零维护的接入方式;
    • 小驼峰入口:import ClButton from '@cldemo/ui-kit/button'(./* 通配,类型完备);
    • 精确组件路径:import ClButton from '@cldemo/ui-kit/utils/Element/ClButton'(按端区分 utils/Element|Web|Mobile)。
    • 每个组件入口均已自带其样式(如 import '.../styles/Element/ClButton.css'),无需手动引全量 CSS。
  • 具名导入:根入口 import { ClXxx } from '@cldemo/ui-kit' 与按端入口 @cldemo/ui-kit/web / @cldemo/ui-kit/mobile 导出组件清单中的全部组件(清单见 COMPONENT_CATALOG.md)。
    • 导出名 = 组件自身的 defineOptions({ name }),可用 node scripts/check-manifest.cjs 校验一致性;
    • 根入口会静态引入全部组件(含 ClEcharts/ClCropper/ClSelect/ClPreview),因此全量场景必须装齐全部 peer;按需场景请用 clResolver 或单组件入口。
  • 全量 CSS:如需一次性引入所有样式,用 import '@cldemo/ui-kit/ui-kit.css'(唯一官方样式入口,勿用 buildLibs/... 深层路径——不在 exports 暴露,会被打包器拦截)。按端全量样式也可用 @cldemo/ui-kit/styles 下的组件样式。
  • use* 工厂与 $ClGlobals 是两套入口:
    • 独立 use 工厂:useNotify / useAlert / usePreview / useClipboard / languagePack,随组件按需可用,自身 mount,不依赖 app.use(install),推荐业务侧统一使用;
    • $ClGlobals.*:依赖全量 app.use(install) 的 provide,只在全量安装场景可用,按需模式下拿不到(成员明细见下方 use 工厂与 $ClGlobals);
    • 请二选一使用,勿在同一项目混用,否则同一功能行为可能不一致。
  • 组件名与标签的对应关系:组件 name 同时决定「模板 kebab 标签」「clComponentMap 键」「全局注册名」,三者由 node scripts/generate-components.cjs + node scripts/generate-resolver.cjs 从组件源码统一派生(事实源 = src/libs/*/componentsInstalls.ts)。
    • 标签一律是「组件名按大写边界加连字符并小写」:ClDropdownMenuM → <cl-dropdown-menu-m>、ClColorPicker → <cl-color-picker>;
    • clResolver 额外容忍 PascalCase 直写标签(<ClDropdownMenu>)与全小写(<clbutton>);
    • 新增组件只需在对应 componentsInstalls.ts 加 import,npm run dev / npm run lib:build 会自动重生成清单,npm run gate 会拦住漏导。
  • setGlobalConfig 全局组件配置:单个入口配置所有组件的全局默认,按需加载与全量安装共用同一份配置注册表:
    • 按需加载(推荐直达子路径,只加载配置模块本身):import CommonGlobalConfig from '@cldemo/ui-kit/common/globalConfig',如 CommonGlobalConfig.setGlobalConfig({ calendar: { restDays: [...] } });
    • 亦可从 common 具名引入:import { setGlobalConfig } from '@cldemo/ui-kit/common';
    • 全量安装:等价写法 app.use(ClLibs, { globalsOption: { calendar: { restDays: [...] } } })(install 内部写入同一注册表);
    • 合并优先级:页面 props 显式值 > 全局配置 > 组件默认值;注册表为 reactive,运行中再次调用会自动刷新。
  • 类型提示:install 签名与 $ClGlobals 结构可从 import { ClGlobals, ClGlobalOptions } from '@cldemo/ui-kit' 获取。
  • peer 依赖:vue / vue-router / echarts / cropper-next-vue / vue-virtual-scroller 为 peer,由使用方提供、组件库不内置(避免双实例),且已 external、不强制打包。
    • 按需引入(推荐):只装用到的,如 <cl-echarts> 用时装 echarts、<cl-cropper> 用时装 cropper-next-vue、<cl-select> / <cl-pull-to-refresh> 用时装 vue-virtual-scroller;用不到的无需安装。
    • 全量安装:根入口静态引入含 ClEcharts/ClCropper/ClSelect 在内的 Web 端全部组件,因此必须同时安装全部 peer,否则构建/运行时 resolve 失败。
  • Common 工具:@cldemo/ui-kit/common(含 CommDay 等)不依赖 echarts;echarts 由 <cl-echarts> 内部按需 import('echarts') 懒加载,不因使用工具而触发。
  • 运行环境:本库面向浏览器端渲染(CSR),目标场景为后台管理系统类 SPA,不提供 SSR / Nuxt 支持。组件按 CSR 假设编写(直接使用 window/document,不做服务端环境守卫)——这是有意的范围取舍,不是待补项。如需在服务端渲染环境中使用,请自行把组件包进客户端渲染分支。

主题定制(Design Token)

组件库的视觉值(颜色 / 间距 / 字号 / 圆角 / 层级等)统一由 Design Token 管理,单一事实源为 src/libs/Common/token.css。

  • 自动注入,无需手动引入:Token 随库入口(全量)与各组件 entry(按需)自动加载,模块级去重保证全站只加载一次。
  • 换主题 = 覆盖语义层变量:
:root {
  --cl-primary: #7c3aed;
  --cl-primary-hover: #8b5cf6;
  --cl-primary-active: #6d28d9;
}
  • 全部 token 清单与定制方式:见 docs/tokens/design-token.md。
  • 新增组件/样式时:禁止硬编码色值,一律引用 var(--cl-*, fallback);新增类名须带 cl- 前缀且用 kebab-case。规则见 docs/通用组件规范.md 第 9 节。
  • 门禁:node scripts/check-tokens.cjs 检查新增硬编码色值(存量已列基线,不阻塞)。
  • 响应式:本库不提供响应式能力,尺寸与布局由使用方控制。

暗色模式

Token 只覆盖语义层与遮罩层,基础层与品牌色定制不受影响。

<!-- 1. 跟随系统:无需任何配置,系统深色时自动生效 -->
<!-- 2. 手动切换:html 上加属性 -->
<html data-cl-theme="dark">
<!-- 3. 局部暗色:任意容器加 class -->
<div class="cl-theme-dark">…</div>

被覆盖的语义变量:--cl-primary*、--cl-{success,warning,danger}-{text,bg,border}、 --cl-text-*、--cl-border*、--cl-bg*、--cl-mask*、--cl-overlay、--cl-shadow-*。

语言切换(i18n)

字典与取词能力由 languagePack 提供,语言本身放在全局配置注册表里(响应式),切换后已渲染的文案会立即刷新:

import { setLocale } from '@cldemo/ui-kit/common'

setLocale('en')     // 支持 'zh_cn'(默认)| 'en'
setLocale('zh_cn')
  • 组件内取词:const { optPageLanguage, getPageLanguage } = useLanguage(); getPageLanguage('paginate'),模板用 optPageLanguage.jumpTo;
  • 无障碍名称取词:const { optA11yText } = useA11yLanguage(),模板用 :aria-label="optA11yText.loading";
  • 词条只增不改,新增文案请加进 src/libs/Common/i18n/{zh_CN,en}.ts(跨组件复用的通用词放 Common/i18n/a11y.ts)。

v-model 契约

组件同时支持标准写法与历史写法,二者等效:

<cl-input v-model="value" />          <!-- Vue 3 标准(推荐)-->
<cl-input v-model:value="value" />    <!-- 1.x 历史写法,继续可用 -->
  • 实现方式:组件同时声明并触发 update:value 与 update:modelValue,父组件只响应自己监听的那个;
  • v-model:show 等命名模型(弹层显隐)沿用各自的名字,不受影响;
  • 新增组件请两个事件都声明(src/libsTest/componentManifest.test.ts 会校验二者成对出现)。

日志开关

库内告警统一走 clLog,默认开发构建输出、生产构建静默(error 始终输出):

import CommonGlobalConfig from '@cldemo/ui-kit/common/globalConfig'

CommonGlobalConfig.setGlobalConfig({ debug: true })                         // 全开
CommonGlobalConfig.setGlobalConfig({ debug: { warn: true, error: false } }) // 只开告警
CommonGlobalConfig.setGlobalConfig({ debug: null })                         // 清除,回到默认策略

输出统一带 [ui-kit][组件名] 前缀,便于在控制台区分来源。

可访问性

  • 组件普遍已补 role / aria-* / :focus-visible 焦点样式;
  • ClModal 提供 isEscapeClose(Esc 关闭)与 isFocusTrap(焦点陷阱 + 焦点还原),默认开启;
  • 焦点陷阱可复用:src/libs/Use/focusTrap.ts(useFocusTrap(refEl, isActive, { onEscape }),需在库内引用,未单独对外暴露);
  • 滚动锁全库统一(src/libs/Use/scrollLock.ts):同容器多组件叠加计数,最后一个解锁才还原,不会互相打断;
  • Load 与过渡类动画遵循 prefers-reduced-motion。

目录结构

src/
└── libs/
    ├── Element/          # 通用组件(PC / Mobile 共用)
    ├── Web/              # Web 端专用组件
    ├── Mobile/           # Mobile 端专用组件
    └── Common/           # 公共工具(base、day、echart、axios 等)

组件列表

Element(通用组件)

组件 标签 说明
Badge <cl-badge> 徽章
Breadcrumb <cl-breadcrumb> 面包屑导航
Button <cl-button> 按钮
Callout <cl-callout> 提示条
Card <cl-card> 卡片
CardColor <cl-card-color> 彩色卡片
Checkbox <cl-checkbox> 复选框
Clipboard <cl-clipboard> 复制
Collapse <cl-collapse> 折叠面板
CountDown <cl-count-down> 倒计时
Cropper <cl-cropper> 图片裁剪
Darg <cl-darg> 拖拽排序
Divider <cl-divider> 分割线
Ellipsis <cl-ellipsis> 文本省略
Empty <cl-empty> 空状态
Form <cl-form> 表单
FormGroup <cl-form-group> 表单组布局
IconFont <cl-icon-font> 图标
Image <cl-image> 图片
Input <cl-input> 输入框
InputCaptcha <cl-input-captcha> 验证码输入框
InputNumber <cl-input-number> 数字输入框
InputNumberStepper <cl-input-number-stepper> 数字输入框(加减步进)
InputPassword <cl-input-password> 密码输入框
InputSearch <cl-input-search> 搜索框
InputTextarea <cl-input-textarea> 文本域
Link <cl-link> 链接
Load <cl-load> 加载动画
LoadScreen <cl-load-screen> 全屏加载遮罩
Modal <cl-modal> 弹窗
NumberRoll <cl-number-roll> 数字动画
Overlay <cl-overlay> 遮罩层
Progress <cl-progress> 进度条
Radio <cl-radio> 单选框
Slider <cl-slider> 滑动条
Switchery <cl-switchery> 开关
Tags <cl-tags> 标签
Transition <cl-slide-up-down> 过渡动画
Waterfall <cl-waterfall> 瀑布流

Web(Web 端组件)

组件 标签 说明
Alert useAlert() 警告框(use 工厂,无标签)
AnchorNav <cl-anchor-nav> 锚点导航
Calendar <cl-calendar> 日历
CodeLegend <cl-code-legend> 图例卡片
ColorPicker <cl-color-picker> 颜色选择器
CropperPreview <cl-cropper-preview> 裁剪预览
DateTime <cl-date-time> 日期时间
DropdownMenu <cl-dropdown-menu> 下拉菜单
DropdownPopup <cl-dropdown-popup> 下拉弹出层
ECharts <cl-echarts> 图表
EchartsLineAxisTag <cl-echarts-line-axis-tag> 折线标签图表
FileUpload <cl-file-upload> 文件上传
FramePhone <cl-frame-phone> 手机外壳
InputTag <cl-input-tag> 输入标签
Notify useNotify() 通知(use 工厂,无标签)
Paginate <cl-paginate> 分页
Portlet <cl-portlet> 面板
Preview usePreview() 大图预览(use 工厂,无标签)
PreviewExample <cl-preview-example> 预览示例
ScrollxFence <cl-scroll-xfence> 横向滚动围栏
Select <cl-select> 选择框
SelectCascade <cl-select-cascade> 级联选择
SelectMove <cl-select-move> 穿梭选择
SelectTag <cl-select-tag> 标签选择器
SelectTree <cl-select-tree> 树形选择
SideMenu <cl-side-menu> 侧边菜单
Table <cl-table> 表格
TableEdit <cl-table-edit> 表格编辑
TableSimple <cl-table-simple> 简易表格
Tabs <cl-tabs> 标签页
Tree <cl-tree> 树形
WeekHour <cl-week-hour> 周时间选择器
XEditable <cl-x-editable> 内联编辑

Mobile(移动端组件)

组件 标签 说明
ActionSheet <cl-action-sheet> 动作面板
AreaM <cl-area-m> 省市区三级联动选择器,内置全国数据(含港澳台),areaList 为空时自动按需加载
BackTop <cl-back-top> 回到顶部
Banner <cl-banner> 横幅
CalendarM <cl-calendar-m> 日历
Cell <cl-cell> 单元格
CellSwipe <cl-cell-swipe> 滑动单元格
CodeLegendM <cl-code-legend-m> 图例卡片
DropdownMenuM <cl-dropdown-menu-m> 下拉菜单
FloatingBubble <cl-floating-bubble> 浮动气泡
FloatingPanel <cl-floating-panel> 浮动面板
Grid <cl-grid> 宫格
TextHighlight <cl-text-highlight> 文本高亮
IndexBar <cl-index-bar> 索引栏
InputOtp <cl-input-otp> 验证码输入框
NavBar <cl-nav-bar> 导航栏
NoticeBar <cl-notice-bar> 通知栏
NotifyM <cl-notify-m> 消息通知
NumberKeyboard <cl-number-keyboard> 数字键盘
Picker <cl-picker> 选择器
PickerCascader <cl-picker-cascader> 级联选择
PickerDate <cl-picker-date> 日期选择
PickerTime <cl-picker-time> 时间选择
Popup <cl-popup> 弹出层
PullToRefresh <cl-pull-to-refresh> 下拉刷新
Rate <cl-rate> 评分
ScrollCard <cl-scroll-card> 滚动卡片列表
ShareSheet <cl-share-sheet> 分享面板
Sidebar <cl-sidebar> 侧边导航
SidebarSelect <cl-sidebar-select> 侧栏选择
Signature <cl-signature> 签名
Steps <cl-steps> 步骤条
Swipe <cl-swipe> 轮播
TabM <cl-tab-m> 标签页
Tabbar <cl-tabbar> 标签栏
Toast <cl-toast> 轻提示
Watermark <cl-watermark> 水印

本地联调(符号链接接入)

消费方把 node_modules/@cldemo/ui-kit 指向本仓库根目录(符号链接 / npm link)后,可以边改组件边联调,但编辑器需要额外配置,否则 lib:build 之后会持续报 TS7016(找不到声明文件),或类型提示停留在旧版本。

原因:TypeScript 按 realpath 解析符号链接,最终读到的是本仓库的真实路径(位于消费方工作区之外),而 VS Code 的文件监视器对工作区外路径覆盖不可靠 —— 重建产物的事件传不到 TS 服务,失败状态会一直保留到手动重启。

注意:这与 .gitignore 无关。编辑器的文件监视不读取 .gitignore(只有搜索与源代码管理读),因此调整 buildLibs 的忽略规则解决不了该问题。

消费方两种修法(任选其一):

  1. 把组件库目录纳入监视范围 —— files.watcherInclude 只接受绝对路径,写相对路径会被当作工作区相对路径而落空,改完需重载窗口:
// 消费方 .vscode/settings.json
"files.watcherInclude": ["<组件库根目录的绝对路径>"]
  1. 把组件库根目录加入多根工作区(.code-workspace 的 folders)—— 路径成为工作区内路径后监视天然覆盖,最稳。

未做上述配置时,每次 lib:build 后消费方都要手动执行一次命令面板的 TypeScript: Restart TS Server(本仓库 npm run lib:build 收尾会打印该提示)。

校验与门禁

命令 作用
npm run manifest:generate 从 src/libs/*/componentsInstalls.ts 重生成 components.ts 与 resolver.ts
npm run manifest:check 校验:组件名唯一 · 标签与 name 自洽 · 导出无遗漏 · resolver 覆盖且产物存在
npm run token:check 校验是否新增硬编码色值(基线只减不增)
npm run gate 一次跑完上面两项门禁(CI 建议挂这个)
npm test 运行单元测试(vitest)
npm run lint 代码检查

指令

指令随组件库一起发布,全量 app.use(install) 自动注册;按需模式下 clResolver 只解析组件、不解析指令(Components({ directives: true }) 对此无效),需显式注册后再在模板使用 —— 例如 import * as Tooltip from '@cldemo/ui-kit/core/tooltip' 后 app.use(createInstallCore({ tooltip: Tooltip }, {}))(完整入口清单见 COMPONENT_CATALOG.md 的「按需引入:细粒度入口」)。

指令 说明
v-cl-code-highlight 代码高亮
v-cl-waves 波纹效果
v-cl-tooltip 工具提示
v-cl-lazy-image 图片懒加载

use 工厂与 $ClGlobals

名称 说明
useNotify() 通知
useAlert() 警告框
usePreview() 大图预览
useClipboard() 剪贴板复制
languagePack() 语言包
$ClGlobals 全局注入容器(全量安装时可用,inject('$ClGlobals') 获取),成员明细见下方
setGlobalConfig() 组件全局默认配置(推荐 @cldemo/ui-kit/common/globalConfig,亦可从 @cldemo/ui-kit/common 具名引入)

$ClGlobals 共 8 个成员,其中 5 个与上方 use 工厂对应,另有 loadScreen / validate / toast 三个成员无对应 use 工厂:

成员 说明 对应 use 工厂
clipboard 剪贴板复制 useClipboard()
loadScreen 全屏加载遮罩 —
languagePack 语言包 languagePack()
validate 表单校验规则表 —
notify 通知 useNotify()
alert 警告框 useAlert()
preview 大图/视频预览(懒加载) usePreview()
toast 轻提示 —

具体使用方法见 COMPONENT_CATALOG.md 的「use 工厂(开放 API)」与「$ClGlobals 全局注入」章节。

组件命名规范

  • 文件夹名:PascalCase(如 InputNumberStepper)
  • 组件名:Cl + PascalCase(如 ClInputNumberStepper)
  • 使用标签:cl- + kebab-case(如 <cl-input-number-stepper>)

License

MIT

Related Packages

markdown-to-jsx

A very fast and versatile markdown toolchain. AST, React, React Native, SolidJS,...

200,072,413 2,394
@vue/component-compiler-utils

Lower level utilities for compiling Vue single file components

65,523,325 322
@storybook/vue3

Storybook Vue 3 renderer: Develop, document, and test UI components in isolation

31,443,686 91,389

Version History

Version Released License
1.1.12 MIT
1.1.11 MIT
1.1.10 MIT
1.1.9 MIT
1.1.8 MIT