npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

crystalplus-ui

v1.0.5

Published

A beautiful Element Plus component library

Downloads

393

Readme

Crystal UI

A beautiful Element Plus component library for Vue 3, designed to provide a consistent and elegant user interface experience.

🚀 Features

  • 基于 Element Plus:在 Element Plus 基础上进行封装和增强
  • Vue 3 Composition API:采用最新的 Vue 3 组合式 API
  • TypeScript 支持:完整的 TypeScript 类型定义
  • 丰富的组件:包含按钮、输入框、选择器、表格、对话框等常用组件
  • 现代化设计:美观的默认样式,易于定制
  • 响应式布局:适配不同屏幕尺寸

📦 Installation

NPM / Yarn

# 使用 npm
npm install crystalplus-ui

# 使用 yarn
yarn add crystalplus-ui

# 使用 pnpm
pnpm add crystalplus-ui

依赖项

Crystal UI 依赖以下库:

  • Vue 3.x
  • Element Plus 2.x
  • @element-plus/icons-vue

🛠️ Usage

全局注册

main.ts 中:

import { createApp } from "vue";
import App from "./App.vue";
import CrystalUI from "crystalplus-ui";
import "element-plus/dist/index.css";
import "crystalplus-ui/dist/index.css";

const app = createApp(App);
app.use(CrystalUI);
app.mount("#app");

按需导入

import { createApp } from "vue";
import App from "./App.vue";
import { CrystalButton, CrystalInput, CrystalTable } from "crystalplus-ui";
import "element-plus/dist/index.css";
import "crystalplus-ui/dist/index.css";

const app = createApp(App);
app.use(CrystalButton);
app.use(CrystalInput);
app.use(CrystalTable);
app.mount("#app");

单个组件导入

<script setup lang="ts">
import { CrystalButton, CrystalInput } from "crystalplus-ui";
</script>

<template>
  <CrystalButton type="primary">Click Me</CrystalButton>
  <CrystalInput placeholder="请输入内容" />
</template>

📁 Components

基础组件

  • CrystalButton:按钮组件
  • CrystalInput:输入框组件
  • CrystalInputNumber:数字输入框
  • CrystalInputTag:标签输入框
  • CrystalSelect:选择器
  • CrystalDatePickerPane:日期选择面板
  • CrystalTimeSelect:时间选择器
  • CrystalTimePicker:时间选择器
  • CrystalCascader:级联选择器
  • CrystalCheckbox:复选框
  • CrystalCheckboxGroup:复选框组
  • CrystalRadio:单选框
  • CrystalRadioGroup:单选框组
  • CrystalSwitch:开关
  • CrystalIcon:图标组件
  • CrystalImage:图片组件
  • CrystalImages:多图片组件
  • CrystalText:文本组件

表单组件

  • ElFormWrapper:Element Plus 表单封装
  • ClFormWrapper:自定义表单封装
  • ElSearchForm:Element Plus 搜索表单
  • ClSearchForm:自定义搜索表单

弹窗组件

  • CrystalDialog:对话框组件
  • CrystalDrawer:抽屉组件

表格组件

  • ElBasicTable:基础表格组件
  • CrystalTable:增强表格组件(使用 ClSearchForm)

🎯 Component Documentation

CrystalTable

基础用法

<script setup lang="ts">
import { ref } from "vue";
import { CrystalTable } from "crystalplus-ui";

const tableData = ref([
  { id: 1, name: "张三", age: 28, email: "[email protected]" },
  { id: 2, name: "李四", age: 32, email: "[email protected]" },
  { id: 3, name: "王五", age: 25, email: "[email protected]" },
]);

const columns = ref([
  { prop: "id", label: "ID", width: 80 },
  { prop: "name", label: "姓名" },
  { prop: "age", label: "年龄", width: 80 },
  { prop: "email", label: "邮箱" },
]);
</script>

<template>
  <CrystalTable :data="tableData" :columns="columns" />
</template>

带搜索功能

<script setup lang="ts">
import { ref } from "vue";
import { CrystalTable } from "crystalplus-ui";

const tableData = ref([
  { id: 1, name: "张三", age: 28, email: "[email protected]" },
  { id: 2, name: "李四", age: 32, email: "[email protected]" },
  { id: 3, name: "王五", age: 25, email: "[email protected]" },
]);

const columns = ref([
  { prop: "id", label: "ID", width: 80 },
  { prop: "name", label: "姓名" },
  { prop: "age", label: "年龄", width: 80 },
  { prop: "email", label: "邮箱" },
]);

const queryConfig = ref([
  {
    type: "input",
    prop: "name",
    label: "姓名",
    props: {
      placeholder: "请输入姓名",
      clearable: true,
    },
  },
  {
    type: "input",
    prop: "age",
    label: "年龄",
    props: {
      placeholder: "请输入年龄",
      clearable: true,
    },
  },
]);

const handleSearch = (params: any) => {
  console.log("搜索参数:", params);
  // 这里可以根据搜索参数过滤数据
};
</script>

<template>
  <CrystalTable
    :data="tableData"
    :columns="columns"
    :query-config="queryConfig"
    @search="handleSearch"
  />
</template>

带选择功能

<script setup lang="ts">
import { ref } from "vue";
import { CrystalTable } from "crystalplus-ui";

const tableData = ref([
  { id: 1, name: "张三", age: 28, email: "[email protected]" },
  { id: 2, name: "李四", age: 32, email: "[email protected]" },
  { id: 3, name: "王五", age: 25, email: "[email protected]" },
]);

const columns = ref([
  { prop: "id", label: "ID", width: 80 },
  { prop: "name", label: "姓名" },
  { prop: "age", label: "年龄", width: 80 },
  { prop: "email", label: "邮箱" },
]);

const selectedRows = ref<any[]>([]);

const handleSelectionChange = (rows: any[]) => {
  selectedRows.value = rows;
  console.log("选中的行:", rows);
};
</script>

<template>
  <CrystalTable
    :data="tableData"
    :columns="columns"
    :selection="true"
    @selection-change="handleSelectionChange"
  />
</template>

带操作列

<script setup lang="ts">
import { ref } from "vue";
import { CrystalTable } from "crystalplus-ui";

const tableData = ref([
  { id: 1, name: "张三", age: 28, email: "[email protected]" },
  { id: 2, name: "李四", age: 32, email: "[email protected]" },
  { id: 3, name: "王五", age: 25, email: "[email protected]" },
]);

const columns = ref([
  { prop: "id", label: "ID", width: 80 },
  { prop: "name", label: "姓名" },
  { prop: "age", label: "年龄", width: 80 },
  { prop: "email", label: "邮箱" },
]);

const actions = ref([
  {
    label: "编辑",
    type: "primary",
    size: "small",
    icon: "Edit",
    handle: (row: any) => {
      console.log("编辑:", row);
    },
  },
  {
    label: "删除",
    type: "danger",
    size: "small",
    icon: "Delete",
    handle: (row: any) => {
      console.log("删除:", row);
    },
  },
]);
</script>

<template>
  <CrystalTable :data="tableData" :columns="columns" :actions="actions" />
</template>

CrystalDialog

<script setup lang="ts">
import { ref } from "vue";
import { CrystalDialog } from "crystalplus-ui";

const dialogVisible = ref(false);

const openDialog = () => {
  dialogVisible.value = true;
};

const closeDialog = () => {
  dialogVisible.value = false;
};
</script>

<template>
  <div>
    <el-button @click="openDialog">打开对话框</el-button>
    <CrystalDialog v-model="dialogVisible" title="提示" width="500px">
      <span>这是一段内容</span>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="closeDialog">确定</el-button>
        </span>
      </template>
    </CrystalDialog>
  </div>
</template>

CrystalDrawer

<script setup lang="ts">
import { ref } from "vue";
import { CrystalDrawer } from "crystalplus-ui";

const drawerVisible = ref(false);

const openDrawer = () => {
  drawerVisible.value = true;
};

const closeDrawer = () => {
  drawerVisible.value = false;
};
</script>

<template>
  <div>
    <el-button @click="openDrawer">打开抽屉</el-button>
    <CrystalDrawer
      v-model="drawerVisible"
      title="抽屉标题"
      direction="rtl"
      size="50%"
    >
      <span>这是抽屉内容</span>
    </CrystalDrawer>
  </div>
</template>

🎨 Customization

主题定制

Crystal UI 基于 Element Plus,因此可以使用 Element Plus 的主题定制功能:

  1. 使用主题编辑器:访问 Element Plus 主题编辑器 生成自定义主题
  2. SCSS 变量覆盖:在项目中创建自定义的 SCSS 文件,覆盖默认变量

组件样式定制

每个组件都可以通过 classstyle 属性进行定制,也可以通过 CSS 变量进行全局定制。

🔧 API Reference

CrystalTable Props

| 参数 | 类型 | 默认值 | 说明 | | ------------ | -------------- | --------- | -------------- | | data | Array | [] | 表格数据 | | columns | Array | [] | 列配置 | | selection | Boolean | false | 是否显示选择框 | | actions | Array | [] | 操作按钮配置 | | query-config | Array | [] | 搜索表单配置 | | pagination | Object/Boolean | true | 分页配置 | | loading | Boolean | false | 加载状态 | | border | Boolean | false | 是否显示边框 | | stripe | Boolean | false | 是否显示斑马纹 | | size | String | 'default' | 表格尺寸 | | height | String/Number | - | 表格高度 | | max-height | String/Number | - | 表格最大高度 |

CrystalTable Events

| 事件名 | 说明 | 回调参数 | | ---------------- | ---------------- | ------------------ | | search | 搜索时触发 | 搜索参数对象 | | selection-change | 选择项变化时触发 | 选中的行数组 | | page-change | 页码变化时触发 | 当前页码和每页条数 | | sort-change | 排序变化时触发 | 排序信息对象 |

CrystalDialog Props

| 参数 | 类型 | 默认值 | 说明 | | --------------------- | ------- | ------ | ------------------------ | | model-value/v-model | Boolean | false | 对话框可见性 | | title | String | '' | 对话框标题 | | width | String | '50%' | 对话框宽度 | | top | String | '15vh' | 对话框距离顶部的位置 | | modal | Boolean | true | 是否显示遮罩层 | | close-on-click-modal | Boolean | true | 是否点击遮罩层关闭对话框 | | close-on-press-escape | Boolean | true | 是否按 ESC 键关闭对话框 | | show-close | Boolean | true | 是否显示关闭按钮 |

CrystalDrawer Props

| 参数 | 类型 | 默认值 | 说明 | | -------------------- | ------------- | ------ | ----------------------------- | | model-value/v-model | Boolean | false | 抽屉可见性 | | title | String | '' | 抽屉标题 | | direction | String | 'rtl' | 抽屉方向 (rtl, ltr, ttb, btt) | | size | String/Number | '30%' | 抽屉大小 | | show-close | Boolean | true | 是否显示关闭按钮 | | modal | Boolean | true | 是否显示遮罩层 | | close-on-click-modal | Boolean | true | 是否点击遮罩层关闭抽屉 |

📖 Examples

Crystal UI 提供了丰富的示例代码,您可以在以下目录中找到:

  • packages/crystal-ui/src/components/CrystalTable/ - 表格组件示例
  • packages/crystal-ui/src/components/CrystalDialog/ - 对话框组件示例
  • packages/crystal-ui/src/components/CrystalDrawer/ - 抽屉组件示例

🔄 Version History

v1.0.0

  • ✨ 初始版本发布
  • 🎉 包含基础组件:按钮、输入框、选择器等
  • 📊 包含表格、对话框、抽屉等复杂组件
  • 📝 完整的 TypeScript 类型定义

🤝 Contributing

欢迎贡献代码!请遵循以下步骤:

  1. Fork 仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 打开 Pull Request

📄 License

Crystal UI is MIT licensed.

📞 Support

如果您有任何问题或建议,欢迎:


Enjoy using Crystal UI! 🎉