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

zpd-ui

v1.1.0

Published

A React component library with AI-friendly configuration guide

Readme

ZPD UI

一个基于 React + TypeScript 的组件库。

📦 安装

npm install zpd-ui
# 或者
pnpm add zpd-ui
# 或者
yarn add zpd-ui

🚀 快速开始

💡 提示:如果你在使用 Cursor 或 GitHub Copilot,可以查看 AI Skills 配置指南,通过简单的提示词即可生成完整的组件配置代码!

1️⃣ 在应用入口引入样式(推荐)

// main.tsx 或 index.tsx
import 'zpd-ui/styles';  // 👈 只需引入一次

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(<App />);

💡 提示:样式文件已包含移动端优化(iOS 回弹禁用、滚动条隐藏、表单元素重置等),专为 H5 场景设计。

2️⃣ 在组件中使用

// App.tsx 或任何组件
import { Button, MusicPlayer, AudioEffect } from 'zpd-ui';
import { useAudio, audioManager } from 'zpd-ui';

function App() {
  const { play } = useAudio();
  
  return (
    <div>
      <Button variant="primary" size="medium" onClick={() => play('/click.mp3')}>
        点击我
      </Button>
      <MusicPlayer 
        musicUrl="/music.mp3" 
        playIconClass="icon-play" 
        pauseIconClass="icon-pause" 
      />
    </div>
  );
}

💡 提示: 样式只需在入口文件引入一次,其他地方直接使用组件即可。详见 样式引入指南

📚 组件列表

Barrage 弹幕

弹幕组件,支持自动播放和手动控制。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | list | BarrageBullet[] | - | 弹幕列表 | | intervalTime | number | 1300 | 弹幕间隔时间(毫秒) | | className | string | '' | 容器类名 | | tabClassName | string | '' | 弹幕项类名 | | renderItem | (item: BarrageBullet) => React.ReactNode | - | 渲染函数 |

示例

<Barrage
  list={barrageList}
  intervalTime={1300}
  renderItem={(item) => <span>{item.text}</span>}
/>

CountDown 倒计时

倒计时组件,支持自定义格式和服务器时间同步。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | targetTime | number \| string \| null \| undefined | - | 目标时间戳(毫秒) | | serverTime | number | - | 服务器时间戳(毫秒) | | format | string | 'HH:mm:ss' | 格式化字符串(dd/HH/mm/ss) | | className | string | - | 容器类名 | | refreshData | () => void | - | 倒计时结束回调 | | backgroundClassName | string | '' | 背景类名 | | partClassName | string | '' | 部分类名 |

示例

<CountDown
  className={Images.time_bg_png}
  targetTime={newer_end_ts ? newer_end_ts * 1000 : 0}
  format="dd'D'HH:mm:ss"
  refreshData={() => countDownEnd()}
/>

List 列表

列表组件,支持分页加载、无限滚动、游标分页、简单渲染和数据填充等功能。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | url | string | - | 请求地址 | | params | Record<string, unknown> | {} | 请求参数 | | method | 'GET' \| 'POST' | 'get' | 请求方法 | | pageSize | number | 10 | 每页数量 | | dataKey | string | 'items' | 数据字段名 | | className | string | - | 容器类名 | | renderItem | (item: T, index: number) => React.ReactNode | - | 渲染函数 | | onDataLoaded | (data: unknown, list: T[], myRank: T) => void | - | 数据加载回调 | | finishRender | () => React.ReactNode | - | 加载完成后的渲染函数 | | noDataRender | () => React.ReactNode | - | 无数据时的渲染函数 | | cursorKey | string | - | 游标分页参数名(如 'last_id') | | hasNextKey | string | 'has_next' | 是否有下一页的字段名 | | myRankKey | string | 'my_rank' | 我的排名的字段名 | | children | React.ReactNode | - | 子元素 | | request | (options: any) => Promise<ApiResponse> | - | 自定义请求函数(优先使用,否则使用 window.ZPD_REQUEST.request) | | useSimpleRender | boolean | false | 使用简单渲染模式(不使用滚动容器),适用于一次性加载全部数据 | | enablePadding | boolean | false | 启用数据填充,仅在没有下一页且当前数据不足时填充占位数据 | | paddingThreshold | number | pageSize | 填充阈值,当数据量 < 此值时才填充 | | paddingPlaceholder | T | {} | 填充的占位数据 |

渲染模式

容器滚动模式(默认)

  • 列表在固定高度容器内滚动
  • 支持自动无限加载更多
  • 适用于大部分列表场景

简单渲染模式(useSimpleRender={true}

  • 列表直接渲染,自然撑开页面
  • 基于页面滚动
  • 适用于一次性加载全部数据或手动控制加载的场景

示例

// 基础用法 - 容器内无限滚动
<List
  ref={listRef}
  url="/api/users"
  params={{ status: 'active' }}
  request={request}
  renderItem={(item: User) => <UserCard data={item} />}
  onDataLoaded={(data, list) => {
    console.log('加载完成', list.length)
  }}
/>

// 简单渲染模式 - 一次性加载全部数据
<List
  url="/api/all-ranks"
  useSimpleRender={true}
  request={request}
  renderItem={(item: Rank) => <RankCard data={item} />}
/>

// 数据填充 - 最后一页数据不足时自动填充
<List
  url="/api/top10"
  pageSize={10}
  enablePadding={true}
  paddingThreshold={10}
  paddingPlaceholder={{ name: '虚位以待', score: 0 }}
  request={request}
  renderItem={(item: Rank, index) => (
    <div>#{index + 1} {item.name}</div>
  )}
/>

// 简单渲染 + 数据填充 - 固定展示数量
<List
  url="/api/featured"
  useSimpleRender={true}
  enablePadding={true}
  paddingThreshold={5}
  paddingPlaceholder={{ name: '暂无' }}
  request={request}
  renderItem={(item) => <Card data={item} />}
/>

// 游标分页 - 高性能场景
<List
  url="/api/messages"
  cursorKey="last_id"
  dataKey="messages"
  request={request}
  renderItem={(item) => <MessageItem data={item} />}
/>

MusicPlayer 音乐播放器

音乐播放器组件,支持自动播放、循环播放和动态切换音频源。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | musicUrl | string | - | 音乐文件 URL | | playIconClass | string | - | 播放状态图标类名 | | pauseIconClass | string | - | 暂停状态图标类名 | | className | string | - | 额外容器类名 | | loop | boolean | true | 是否循环播放 | | autoPlay | boolean | true | 是否自动播放 |

特性

  • ✅ 三层自动播放策略(直接播放 → 静音播放 → 等待用户交互)
  • ✅ 支持动态切换音频源
  • ✅ 适合背景音乐场景

示例

// 基础用法
<MusicPlayer
  musicUrl="/music.mp3"
  playIconClass="icon-play"
  pauseIconClass="icon-pause"
/>

// 根据状态切换音乐
<MusicPlayer
  musicUrl={status === 'active' ? '/music1.mp3' : '/music2.mp3'}
  playIconClass="icon-play"
  pauseIconClass="icon-pause"
  loop={true}
/>

AudioEffect 音效组件

无 UI 的音效播放组件,适用于状态音效、提示音等短音频场景。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | audioUrl | string | - | 音频文件路径 | | volume | number | 1 | 音量 (0-1) | | autoPlay | boolean | true | 是否自动播放 | | onPlay | () => void | - | 播放开始回调 | | onEnded | () => void | - | 播放完成回调 | | onError | (error: Error) => void | - | 播放失败回调 |

特性

  • ✅ 基于 AudioManager 实现,支持预加载和缓存
  • ✅ 支持并发播放(快速点击不会打断)
  • ✅ 自动清理 DOM,避免内存泄漏
  • ✅ 支持动态切换音频源

示例

// 根据状态播放不同音效
<AudioEffect
  audioUrl={status === 'success' ? '/sounds/success.mp3' : '/sounds/error.mp3'}
  volume={0.8}
  onEnded={() => console.log('播放完成')}
/>

// 手动控制播放
<AudioEffect
  audioUrl="/sounds/notification.mp3"
  autoPlay={false}
  onPlay={() => console.log('开始播放')}
/>

NavBar 导航栏

导航栏组件,支持标题居中/左对齐、滚动变色、自定义左右侧内容等功能。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | title | string | - | 标题 | | leftIcon | string | '' | 左侧图标类名 | | rightIcon | string | '' | 右侧图标类名 | | onRightClick | () => void | - | 右侧点击回调 | | onLeftClick | () => void | - | 左侧点击回调 | | type | 'back' \| 'close' | 'close' | 左侧按钮类型 | | className | string | '' | 容器类名 | | children | React.ReactNode | - | 自定义内容 | | enableScrollBg | boolean | false | 是否启用滚动变色 | | scrollBgClassName | string | 'bg-black/60 backdrop-blur-sm' | 滚动时样式类名 | | titleAlign | 'center' \| 'left' | 'center' | 标题对齐方式 | | renderLeft | () => React.ReactNode | - | 自定义左侧内容(优先级高于 leftIcon) | | renderRight | () => React.ReactNode | - | 自定义右侧内容(优先级高于 rightIcon) |

示例

// 基础用法 - 标题居中
<NavBar
  title="页面标题"
  leftIcon="i-custom-back"
  rightIcon="i-custom-more"
  onLeftClick={() => history.back()}
  enableScrollBg={true}
/>

// 左对齐模式 - 左侧图标和标题紧挨着
<NavBar
  title="消息列表"
  leftIcon="i-custom-back"
  rightIcon="i-custom-search"
  titleAlign="left"
/>

// 自定义右侧内容 - 多个操作按钮
<NavBar
  title="购物车"
  leftIcon="i-custom-back"
  renderRight={() => (
    <div className="flex items-center gap-16">
      <span className="text-24 text-gray-400" onClick={() => console.log('管理')}>
        管理
      </span>
      <div className="i-custom-search" onClick={() => console.log('搜索')} />
    </div>
  )}
/>

// 完全自定义左右两侧
<NavBar
  title="设置"
  titleAlign="left"
  renderLeft={() => (
    <button className="flex items-center gap-8" onClick={() => history.back()}>
      <div className="i-custom-back" />
      <span className="text-24">返回</span>
    </button>
  )}
  renderRight={() => (
    <div className="flex items-center gap-16">
      <button className="px-16 py-8 bg-blue-500 rounded-8 text-white">
        保存
      </button>
      <div className="i-custom-more" />
    </div>
  )}
/>

NoticeBar 通知栏

通知栏组件,支持无限滚动和悬停暂停。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | children | React.ReactNode | - | 子元素内容 | | text | string[] \| string | - | 文本数组或字符串 | | textClassName | string | - | 文本类名 | | pixelsPerSecond | number | 25 | 滚动速度(像素/秒) | | speed | number | 8 | 动画持续时间(秒) | | pauseOnHover | boolean | false | 是否悬停暂停 | | gap | string | - | 滚动内容间距 |

示例

<NoticeBar text="通知内容" pauseOnHover />
<NoticeBar>
  <span>自定义内容</span>
</NoticeBar>

Progress 进度条

进度条组件,支持拖拽和按钮控制。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | value | number | - | 当前数值 | | maxCount | number | - | 最大数量 | | onChange | (value: number) => void | - | 改变回调 | | disabled | boolean | false | 是否禁用 | | draggable | boolean | true | 是否允许拖拽 | | innerImageClassName | string | '' | 内层进度条背景类名 | | outerImageClassName | string | '' | 外层轨道背景类名 | | pointClassName | string | '' | 进度条指示点类名 | | decreaseButtonClassName | string | - | 减少按钮类名 | | increaseButtonClassName | string | - | 增加按钮类名 | | step | number | 1 | 步长 |

示例

<Progress
  value={count}
  maxCount={maxExchangeCount}
  innerImageClassName={BackgroundImages.shop_inner_bg_png}
  outerImageClassName={BackgroundImages.shop_process_out_bg_png}
  decreaseButtonClassName={BackgroundImages.shop_reduce_png}
  increaseButtonClassName={BackgroundImages.shop_add_png}
  onChange={setCount}
/>

RankList 排行榜列表

排行榜列表组件,支持顶部展示、我的排名、数据填充等功能。自动将前 N 名单独渲染在顶部区域。 继承 List 组件的所有功能(分页、简单渲染、数据填充、游标分页等)。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | topRender | (topList: T[]) => React.ReactNode | - | 顶部渲染函数 | | topCount | number | 3 | 顶部数量(设为 0 则不渲染顶部区域) | | renderItem | (item: T, index: number) => React.ReactNode | - | 列表项渲染函数 | | myRankRender | (myRank: T) => React.ReactNode | - | 我的排名渲染函数 | | className | string | '' | 容器类名 | | listClassName | string | '' | 列表区域类名 | | listStyle | CSSProperties | {} | 列表区域样式 | | classNameStyle | CSSProperties | {} | 容器样式 | | ...ListProps | - | - | 继承 List 组件的所有属性(url, params, useSimpleRender, enablePadding 等) |

Ref 方法

| 方法 | 参数 | 返回值 | 描述 | |------|------|--------|------| | refresh | - | void | 刷新列表 | | clear | - | void | 清空列表 | | getList | - | T[] | 获取完整列表 | | getTopList | - | T[] | 获取 Top 列表 | | getRestList | - | T[] | 获取剩余列表(去除 Top) |

示例

// 基础用法 - 容器内滚动 + 前 3 名单独展示
<RankList
  url="/api/ranks"
  dataKey="ranks"
  request={request}
  topCount={3}
  listClassName="h-600"
  topRender={topList => (
    <div className="mb-20 flex justify-around">
      {topList.map((item, index) => (
        <div key={index} className="flex flex-col items-center">
          <img src={item.avatar} className="h-80 w-80 rounded-full" />
          <span className="text-20">Top {index + 1}</span>
          <span className="text-24 font-bold">{item.name}</span>
        </div>
      ))}
    </div>
  )}
  renderItem={(item, index) => (
    <div className="flex items-center justify-between px-20 py-16">
      <span className="text-gray-400">#{index + 1}</span>
      <span>{item.name}</span>
      <span className="text-24 font-bold">{item.score}</span>
    </div>
  )}
/>

// 简单渲染模式 - 一次性加载全部排行数据
<RankList
  url="/api/all-ranks"
  dataKey="ranks"
  request={request}
  useSimpleRender={true}
  topCount={3}
  topRender={topList => <TopRankCard list={topList} />}
  renderItem={(item, index) => <RankItem data={item} />}
/>

// 数据填充 - 最后一页不足时自动填充
<RankList
  url="/api/ranks"
  dataKey="ranks"
  request={request}
  pageSize={10}
  enablePadding={true}
  paddingThreshold={10}
  paddingPlaceholder={{ name: '虚位以待', score: 0 }}
  topCount={3}
  topRender={topList => <TopRankCard list={topList} />}
  renderItem={(item, index) => <RankItem data={item} />}
/>

// 简单渲染 + 数据填充 - 固定展示 10 个排名位
<RankList
  url="/api/top10"
  dataKey="ranks"
  request={request}
  useSimpleRender={true}
  enablePadding={true}
  paddingThreshold={10}
  paddingPlaceholder={{ name: '暂无', score: 0 }}
  topCount={3}
  topRender={topList => <TopThree list={topList} />}
  renderItem={(item, index) => (
    <div>#{index + 1} {item.name || '暂无'}</div>
  )}
/>

// 不渲染 Top 区域
<RankList
  url="/api/ranks"
  request={request}
  topCount={0}
  renderItem={(item, index) => <RankItem data={item} />}
/>

// 带我的排名
<RankList
  url="/api/ranks"
  request={request}
  topCount={3}
  listClassName="h-600"
  topRender={topList => <TopRankCard list={topList} />}
  renderItem={(item, index) => <RankItem data={item} />}
  myRankRender={myRank => (
    <div className="fixed bottom-0 left-0 w-full bg-gradient-to-t from-black/80 px-20 py-16">
      <div className="flex items-center justify-between">
        <span>我的排名:#{myRank.rank}</span>
        <span className="text-24 font-bold">{myRank.score}</span>
      </div>
    </div>
  )}
/>

// 使用 ref 方法
const rankListRef = useRef<RankListRef>(null)

<RankList
  ref={rankListRef}
  url="/api/ranks"
  request={request}
  renderItem={(item) => <RankItem data={item} />}
/>

// 刷新列表
<button onClick={() => rankListRef.current?.refresh()}>
  刷新
</button>

// 获取列表数据
const topList = rankListRef.current?.getTopList()
const fullList = rankListRef.current?.getList()

ShadowText 阴影文字

阴影文字组件,支持自定义阴影颜色和偏移。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | children | React.ReactNode | - | 子元素 | | className | string | '' | 类名 | | shadowColor | string | '#FFEE7B' | 阴影颜色 | | shadowOffset | number | 2 | 阴影偏移 | | useResponsive | boolean | true | 是否使用响应式 |

示例

<ShadowText shadowColor="#FFEE7B" shadowOffset={2}>
  阴影文字
</ShadowText>

StrokeText 描边文字

描边文字组件,使用 SVG 实现。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | text | string | - | 文本内容 | | strokeWidth | number | 4 | 描边宽度 | | fontSize | number | 30 | 字体大小 | | stroke | string | '#F57E34' | 描边颜色 | | className | string | '' | 类名 |

示例

<StrokeText
  text="描边文字"
  strokeWidth={4}
  fontSize={30}
  stroke="#F57E34"
/>

TabList 标签列表

标签列表组件,支持自定义样式。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | tabs | TabItem[] | - | 标签列表 | | activeValue | string \| number | - | 激活值 | | onTabClick | (value: string \| number, index: number) => void | - | 点击回调 | | tabClassName | string | - | 标签类名 | | activeTabClassName | string | - | 激活标签类名 | | renderTab | (tab: TabItem, index: number, isActive: boolean) => React.ReactNode | - | 自定义渲染 |

示例

<TabList
  tabs={[
    { value: 1, label: '标签1' },
    { value: 2, label: '标签2' },
  ]}
  activeValue={activeValue}
  onTabClick={setActiveValue}
  tabClassName="text-24 mx-10"
  activeTabClassName="text-red"
/>

Tabs 可滚动标签

可滚动标签组件,支持自动滚动到激活标签。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | tabs | ScrollableTabsItem[] | - | 标签列表 | | activeValue | string \| number | - | 激活值 | | onTabClick | (value: string \| number, index: number) => void | - | 点击回调 | | scrollDelay | number | 50 | 滚动延迟(毫秒) | | disableAutoScroll | boolean | false | 禁用自动滚动 | | tabClassName | string | '' | 标签类名 | | activeTabClassName | string | '' | 激活标签类名 |

示例

<Tabs
  tabs={tabs}
  activeValue={activeValue}
  onTabClick={setActiveValue}
  tabClassName="text-24 mx-10"
  activeTabClassName="text-red"
/>

🎣 Hooks

useAudio

音频播放 Hook,基于 AudioManager 的 React Hook 封装,适用于复杂的音频控制场景。

参数

interface UseAudioOptions {
  volume?: number          // 音量 (0-1),默认 1
  preloadUrls?: string[]   // 预加载的音频列表
  clearOnUnmount?: boolean // 是否在组件卸载时清理缓存
}

返回值

interface UseAudioReturn {
  play: (audioUrl: string, volume?: number, callbacks?: {
    onEnded?: () => void
    onError?: (err: Error) => void
  }) => Promise<void>
  preload: (audioUrl: string) => Promise<void>
  preloadAll: (audioUrls: string[]) => Promise<void>
  isCached: (audioUrl: string) => boolean
  stopAll: () => void
  clear: () => void
  isLoading: boolean
}

示例

import { useAudio } from 'zpd-ui';

function GameComponent() {
  const { play, preloadAll, isLoading } = useAudio({
    volume: 0.8,
    preloadUrls: ['/sounds/click.mp3', '/sounds/success.mp3']
  });

  // 预加载完成后播放
  useEffect(() => {
    if (!isLoading) {
      console.log('音频预加载完成');
    }
  }, [isLoading]);

  return (
    <div>
      <button onClick={() => play('/sounds/click.mp3')}>
        点击播放音效
      </button>
      <button onClick={() => play('/sounds/success.mp3', 1, {
        onEnded: () => console.log('播放完成')
      })}>
        播放成功音效
      </button>
    </div>
  );
}

🛠️ 工具函数

zpd-ui 还提供了一些实用的工具函数:

音频管理

import { audioManager, playSound } from 'zpd-ui';

// 方式1: 使用 audioManager 单例
await audioManager.preloadAll(['/sounds/click.mp3', '/sounds/success.mp3']);
await audioManager.play('/sounds/click.mp3', 0.8);

// 方式2: 使用简化 API
await playSound('/sounds/click.mp3', 0.8, {
  onEnded: () => console.log('播放完成'),
  onError: (err) => console.error('播放失败', err)
});

// 检查是否已缓存
if (audioManager.isCached('/sounds/click.mp3')) {
  console.log('音频已缓存');
}

// 清理所有缓存
audioManager.clear();

AudioManager API

| 方法 | 参数 | 描述 | |------|------|------| | preload(filename) | filename: string | 预加载单个音频 | | preloadAll(filenames) | filenames: string[] | 批量预加载音频 | | play(filename, volume, callbacks) | filename: string, volume?: number, callbacks?: object | 播放音效(支持并发) | | stopAll() | - | 停止所有音频 | | clear() | - | 清除所有缓存 | | isCached(filename) | filename: string | 检查是否已缓存 | | setAssetOrigin(origin) | origin: string | 设置资源地址前缀 |

其他工具

import { classNames, debounce, throttle } from 'zpd-ui';

// 类名合并
const className = classNames('btn', isActive && 'active');

// 防抖
const handleSearch = debounce((value: string) => {
  console.log('搜索:', value);
}, 300);

// 节流
const handleScroll = throttle(() => {
  console.log('滚动');
}, 100);

更多示例请查看 使用示例文档

🛠️ 开发

安装依赖

pnpm install

启动开发服务器

pnpm dev

构建

pnpm build

这会生成:

  • dist/zpd-ui.es.js - ES Module 格式
  • dist/zpd-ui.cjs.js - CommonJS 格式
  • dist/zpd-ui.css - 样式文件
  • dist/index.d.ts 及相关 - TypeScript 类型声明文件

Lint

pnpm lint

📝 发布

  1. 更新版本号:
npm version patch # 或 minor, major
  1. 发布到 npm:
npm publish

注意: 首次发布前,请确保:

  • 已登录 npm 账号 (npm login)
  • package.json 中配置了正确的 nameauthorrepository 等字段
  • 包名在 npm 上是可用的

🎵 音频系统使用指南

zpd-ui 提供了完整的音频管理解决方案,根据不同场景选择合适的方式:

| 场景 | 推荐方案 | 说明 | |------|----------|------| | 背景音乐 | <MusicPlayer /> | 有 UI 控制,支持循环和动态切换 | | 状态音效(声明式) | <AudioEffect /> | 根据状态自动播放,无 UI | | 交互音效(命令式) | useAudio() Hook | 更灵活的控制,适合复杂交互 | | 底层控制 | audioManager | 直接操作音频缓存和播放 |

典型组合

// 页面中同时使用多种音频
function GamePage() {
  const { play } = useAudio({
    preloadUrls: ['/click.mp3', '/success.mp3', '/error.mp3']
  });

  return (
    <>
      {/* 背景音乐 */}
      <MusicPlayer musicUrl="/bg-music.mp3" playIconClass="..." pauseIconClass="..." />
      
      {/* 状态音效 */}
      <AudioEffect 
        audioUrl={gameStatus === 'win' ? '/success.mp3' : '/error.mp3'} 
        volume={0.8}
      />
      
      {/* 交互音效 */}
      <button onClick={() => play('/click.mp3')}>点击</button>
    </>
  );
}

📖 文档

✨ 特性

  • 🎨 精美的组件设计
  • 📦 Tree-shaking 支持,按需加载
  • 💪 使用 TypeScript 编写,完整的类型定义
  • 🔧 提供实用的工具函数
  • 🎵 完整的音频管理体系(播放器、音效、Hook、管理器)
  • 📱 响应式设计
  • ⚡ 基于 Vite 构建,开发体验极佳

📄 License

MIT