npm package: @jack-huang/cu-ui
Description: 基于 uni-app 的通用组件库，支持多端兼容（H5、App、各类小程序）
Latest version: 1.0.38

# CU-UI

> 贡献者请先阅读 [AGENTS.md](./AGENTS.md)，了解项目规则与协作指南。

基于 uni-app 的通用组件库，支持多端兼容（H5、App、各类小程序）。

## 特性

- 🚀 支持 Vue 2 和 Vue 3
- 📱 多端兼容：H5、App、微信小程序、支付宝小程序等
- 🎨 现代化设计风格
- 📦 按需引入，减小包体积
- 🔧 TypeScript 支持
- 📖 详细的文档和示例
- 📦 支持 npm 发布和安装

## 安装

```bash
npm install @jack-huang/cu-ui
# 或
yarn add @jack-huang/cu-ui
# 或
pnpm add @jack-huang/cu-ui
```

## 使用方式

### 方式一：easycom 自动按需引入（推荐）

在 `pages.json` 中配置 easycom：

```json
{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^cu-(.*)": "@jack-huang/cu-ui/src/components/cu-$1/cu-$1.vue"
    }
  }
}
```

然后就可以在页面中直接使用组件，无需引入：

```vue
<template>
  <view>
    <cu-button type="primary">主要按钮</cu-button>
  </view>
</template>
```

### 方式二：手动按需引入

支持多种按需引入方式：

#### 2.1 从主入口按需引入
```vue
<template>
  <view>
    <cu-button type="primary">主要按钮</cu-button>
  </view>
</template>

<script>
import { CuButton } from '@jack-huang/cu-ui'

export default {
  components: {
    CuButton
  }
}
</script>
```

#### 2.2 直接引入组件文件
```vue
<template>
  <view>
    <cu-button type="primary">主要按钮</cu-button>
  </view>
</template>

<script>
import CuButton from '@jack-huang/cu-ui/src/components/cu-button'

export default {
  components: {
    CuButton
  }
}
</script>
```

#### 2.3 引入 Vue 文件（uni-app 推荐）
```vue
<template>
  <view>
    <cu-button type="primary">主要按钮</cu-button>
  </view>
</template>

<script>
import CuButton from '@jack-huang/cu-ui/src/components/cu-button/cu-button.vue'

export default {
  components: {
    CuButton
  }
}
</script>
```

### 方式三：全量引入

#### Vue 3 项目
```js
import { createSSRApp } from 'vue'
import App from './App.vue'
import CuUI from '@jack-huang/cu-ui'

export function createApp() {
  const app = createSSRApp(App)
  app.use(CuUI)
  return {
    app
  }
}
```

#### Vue 2 项目
```js
import Vue from 'vue'
import CuUI from '@jack-huang/cu-ui'

Vue.use(CuUI)

// 或者在 uni-app 中
export function createApp() {
  const app = new Vue({
    // ...
  })
  return {
    app
  }
}
```

## 组件用法示例

### CuButton 按钮
```vue
<template>
  <view>
    <!-- 1) 默认 primary，size 默认 normal（会应用 cu-button--normal） -->
    <cu-button>默认按钮</cu-button>

    <!-- 2) 自定义 class：可传 String/Array/Object，在全局或页面样式中定义 .my-btn -->
    <cu-button custom-class="my-btn">自定义 Class</cu-button>

    <!-- 3) 自定义 style：对象写法，覆盖颜色/尺寸等单值样式更方便，优先级更高 -->
    <cu-button :custom-style="{ backgroundColor: '#333', borderColor: '#333' }">
      自定义颜色
    </cu-button>

    <!-- 4) 自定义 style：字符串写法也支持 -->
    <cu-button custom-style="height: 48px; border-radius: 8px;">
      自定义尺寸
    </cu-button>

    <!-- 5) 原生 class/style 依然透传到根节点，可与 customClass/customStyle 混用 -->
    <cu-button class="my-btn-2" style="font-weight: bold;">
      原生透传
    </cu-button>

    <!-- 6) 禁用态：不可点击、无交互反馈；朴素/默认类型禁用态有更明确的视觉 -->
    <cu-button disabled>禁用</cu-button>

    <!-- 7) 加载态：阻止点击，保留主题色；如需 loading 也应用禁用视觉，可将类绑定合并到 disabled -->
    <cu-button :loading="true">加载中</cu-button>
  </view>
</template>
```

提示：
- `customClass` 支持 String/Array/Object，`customStyle` 支持 String/Object。
- 如需更强覆盖，优先选择 `customStyle`（行内样式）。
- 若要为不同主题（primary/success/...）定义专属禁用配色，可在项目样式中进一步定制。

### CuImage 图片
```vue
<template>
  <view>
    <!-- 单图 + 点击预览（默认开启），懒加载默认 true -->
    <cu-image :src="img" :lazy="true" />

    <!-- 多图预览，current 指定初始索引；失败自动重试 3 次 -->
    <cu-image :urls="imgs" :current="1" :retry="3" />
  </view>
</template>

<script>
export default {
  data() {
    return {
      img: 'https://example.com/a.jpg',
      imgs: [
        'https://example.com/a.jpg',
        'https://example.com/b.jpg'
      ]
    }
  }
}
</script>
```

### CuDropdown 下拉菜单
```vue
<template>
  <view>
    <button id="moreBtn" @click="open">更多</button>
    <cu-dropdown
      v-model:visible="visible"
      :items="items"
      placement="bottom"
      toggleOnTriggerClick
      @select="onSelect"
    >
      <cu-button type="success">更多</cu-button>
    </cu-dropdown>
  </view>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      pos: { x: 120, y: 100 },
      items: [
        { label: '加入购物车', value: 'cart' },
        { label: '申请开票', value: 'invoice' }
      ]
    }
  },
  methods: {
    open(e) {
      const t = e?.detail || e?.touches?.[0] || {}
      this.pos = { x: t.x || 120, y: t.y || 100 }
      this.visible = true

      // 或定位到元素下方
      // const q = uni.createSelectorQuery().in(this)
      // q.select('#moreBtn').boundingClientRect(rect => {
      //   this.pos = { x: rect.left, y: rect.bottom }
      //   this.visible = true
      // }).exec()
    },
    onSelect({ item }) {
      console.log('select:', item.value)
    }
  }
}
</script>
```

注意：
- 已在 package.json 的 exports 开放 "./src/*"，配合 pages.json 的 easycom 自定义映射：
  "^cu-(.*)": "@jack-huang/cu-ui/src/components/cu-$1/cu-$1.vue"

## 组件列表

- [x] Button 按钮（cu-button）
- [x] Image 图片（cu-image）
- [x] Dropdown 下拉菜单（cu-dropdown）
- [ ] Input 输入框
- [ ] Card 卡片
- [ ] Modal 弹窗
- [ ] Loading 加载中
- [ ] Toast 提示

## 开发

```bash
# 克隆项目
git clone <repository-url>

# 进入项目目录
cd uniapp-common-components

# 安装依赖
npm install

# 开发模式（监听文件变化）
npm run dev

# 构建
npm run build

# 发布到 npm
npm publish
```

## 项目结构

```
cu-ui/
├── src/                    # 源码目录
│   ├── components/         # 组件目录
│   │   └── cu-button/     # 按钮组件
│   ├── index.js           # 入口文件
│   └── index.d.ts         # TypeScript 声明文件
├── lib/                   # 构建输出目录
├── examples/              # 示例项目
├── package.json           # 包配置文件
├── rollup.config.js       # 构建配置
└── README.md              # 说明文档
```

## 贡献

欢迎提交 Issue 和 Pull Request。

## 许可证

MIT License