@yh-ui/hooks 0.1.17 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,289 @@
1
+ # @yh-ui/hooks
2
+
3
+ <p align="center">
4
+ <img src="https://raw.githubusercontent.com/1079161148/yh-ui/main/docs/public/logo.svg" width="100" height="100" alt="YH-UI Logo">
5
+ </p>
6
+
7
+ <h3 align="center">YH-UI Composable Hooks</h3>
8
+
9
+ <p align="center">
10
+ 为 YH-UI 组件库提供底层 Composition API Hooks,覆盖 AI 对话、虚拟滚动、SKU、倒计时等高频业务场景。
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="https://www.npmjs.com/package/@yh-ui/hooks">
15
+ <img src="https://img.shields.io/npm/v/@yh-ui/hooks.svg?style=flat-square&colorB=409eff" alt="npm version">
16
+ </a>
17
+ <a href="https://www.npmjs.com/package/@yh-ui/hooks">
18
+ <img src="https://img.shields.io/npm/dm/@yh-ui/hooks.svg?style=flat-square&colorB=409eff" alt="npm downloads">
19
+ </a>
20
+ <a href="https://github.com/1079161148/yh-ui/blob/main/LICENSE">
21
+ <img src="https://img.shields.io/npm/l/@yh-ui/hooks.svg?style=flat-square" alt="license">
22
+ </a>
23
+ </p>
24
+
25
+ ---
26
+
27
+ ## ✨ 特性
28
+
29
+ - 🧩 **15 个开箱即用 Hook** — 覆盖组件内核、业务场景、工具能力全维度
30
+ - 🔒 **完整 TypeScript 支持** — 所有 composable 均有精确类型推导,杜绝 `any`
31
+ - ⚡ **性能优先** — 纯函数式、响应式惰性计算,按需激活,零额外开销
32
+ - 🌐 **SSR 友好** — 所有 DOM 操作均有 `isClient` 防护,完美兼容 Nuxt 3
33
+ - 🌍 **i18n 内置** — `useLocale` 与 `@yh-ui/locale` 深度集成,67 种语言开箱即用
34
+ - 🎯 **Tree-shaking** — 每个 Hook 均可单独导入,不引入冗余代码
35
+
36
+ ---
37
+
38
+ ## 📦 安装
39
+
40
+ ```bash
41
+ # pnpm(推荐)
42
+ pnpm add @yh-ui/hooks
43
+
44
+ # npm
45
+ npm install @yh-ui/hooks
46
+
47
+ # yarn
48
+ yarn add @yh-ui/hooks
49
+ ```
50
+
51
+ > **注意**:`@yh-ui/hooks` 是 `@yh-ui/yh-ui` 的子包,若你已安装主包则无需单独安装。
52
+
53
+ ---
54
+
55
+ ## 🔨 快速开始
56
+
57
+ ### 完整导入
58
+
59
+ ```ts
60
+ import { useCountdown, useSKU, useVirtualScroll } from '@yh-ui/hooks'
61
+ ```
62
+
63
+ ### 按需导入(推荐)
64
+
65
+ ```ts
66
+ // 只导入需要的 Hook,完美支持 Tree-shaking
67
+ import { useCountdown } from '@yh-ui/hooks/use-countdown'
68
+ import { useSKU } from '@yh-ui/hooks/use-sku'
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 📚 Hook 一览
74
+
75
+ | Hook | 说明 | SSR |
76
+ | ------------------ | ------------------------------------------- | --- |
77
+ | `useAI` | AI 对话流式能力,支持 abort、重试 | ✅ |
78
+ | `useCache` | 响应式缓存管理(LRU/TTL/持久化) | ✅ |
79
+ | `useClickOutside` | 点击元素外部事件监听 | ✅ |
80
+ | `useConfig` | 读取全局 YH-UI 配置 | ✅ |
81
+ | `useCountdown` | 高精度倒计时(支持暂停/恢复/重置) | ✅ |
82
+ | `useEventListener` | 自动清理的事件监听绑定 | ✅ |
83
+ | `useFormItem` | 表单项上下文集成(validate/resetField) | ✅ |
84
+ | `useId` | 稳定唯一 ID 生成(兼容 Vue 3.5 `useId`) | ✅ |
85
+ | `useLocale` | i18n 国际化文本获取 | ✅ |
86
+ | `useNamespace` | BEM 类名生成(`yh-button__icon--disabled`) | ✅ |
87
+ | `useScrollLock` | 页面/元素滚动锁定 | ✅ |
88
+ | `useSKU` | 电商 SKU 矩阵计算(规格路径算法) | ✅ |
89
+ | `useVirtualScroll` | 大数据虚拟滚动计算 | ✅ |
90
+ | `useZIndex` | 全局 z-index 层级管理 | ✅ |
91
+ | `storage` | localStorage/sessionStorage 响应式封装 | ✅ |
92
+
93
+ ---
94
+
95
+ ## 🚀 详细使用示例
96
+
97
+ ### `useCountdown` — 倒计时
98
+
99
+ ```vue
100
+ <script setup lang="ts">
101
+ import { useCountdown } from '@yh-ui/hooks'
102
+
103
+ const { remaining, isRunning, start, pause, resume, reset } = useCountdown({
104
+ duration: 60, // 秒
105
+ interval: 1000, // 更新间隔 ms
106
+ onFinish: () => console.log('倒计时结束!')
107
+ })
108
+ </script>
109
+
110
+ <template>
111
+ <div>
112
+ <span>剩余:{{ remaining }}s</span>
113
+ <button @click="start">开始</button>
114
+ <button @click="pause">暂停</button>
115
+ <button @click="resume">继续</button>
116
+ <button @click="reset">重置</button>
117
+ </div>
118
+ </template>
119
+ ```
120
+
121
+ ### `useSKU` — 电商 SKU 矩阵
122
+
123
+ ```vue
124
+ <script setup lang="ts">
125
+ import { useSKU } from '@yh-ui/hooks'
126
+
127
+ const skuData = [
128
+ {
129
+ specs: [
130
+ { name: '颜色', value: '红色' },
131
+ { name: '尺寸', value: 'M' }
132
+ ],
133
+ stock: 10
134
+ },
135
+ {
136
+ specs: [
137
+ { name: '颜色', value: '红色' },
138
+ { name: '尺寸', value: 'L' }
139
+ ],
140
+ stock: 0
141
+ },
142
+ {
143
+ specs: [
144
+ { name: '颜色', value: '蓝色' },
145
+ { name: '尺寸', value: 'M' }
146
+ ],
147
+ stock: 5
148
+ }
149
+ ]
150
+
151
+ const { specGroups, selectedSpecs, currentSKU, isDisabled, selectSpec } = useSKU(skuData)
152
+ </script>
153
+
154
+ <template>
155
+ <div v-for="group in specGroups" :key="group.name">
156
+ <h4>{{ group.name }}</h4>
157
+ <button
158
+ v-for="value in group.values"
159
+ :key="value"
160
+ :disabled="isDisabled(group.name, value)"
161
+ :class="{ active: selectedSpecs[group.name] === value }"
162
+ @click="selectSpec(group.name, value)"
163
+ >
164
+ {{ value }}
165
+ </button>
166
+ </div>
167
+ <p v-if="currentSKU">库存:{{ currentSKU.stock }}</p>
168
+ </template>
169
+ ```
170
+
171
+ ### `useVirtualScroll` — 虚拟滚动
172
+
173
+ ```vue
174
+ <script setup lang="ts">
175
+ import { ref } from 'vue'
176
+ import { useVirtualScroll } from '@yh-ui/hooks'
177
+
178
+ const containerRef = ref<HTMLElement>()
179
+ const items = Array.from({ length: 100000 }, (_, i) => ({ id: i, label: `Item ${i}` }))
180
+
181
+ const { visibleItems, totalHeight, offsetY, handleScroll } = useVirtualScroll({
182
+ items,
183
+ itemHeight: 40,
184
+ containerHeight: 600,
185
+ overscan: 5
186
+ })
187
+ </script>
188
+
189
+ <template>
190
+ <div ref="containerRef" style="height: 600px; overflow-y: auto" @scroll="handleScroll">
191
+ <div :style="{ height: `${totalHeight}px`, position: 'relative' }">
192
+ <div :style="{ transform: `translateY(${offsetY}px)` }">
193
+ <div v-for="item in visibleItems" :key="item.id" style="height: 40px">
194
+ {{ item.label }}
195
+ </div>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </template>
200
+ ```
201
+
202
+ ### `useClickOutside` — 点击外部
203
+
204
+ ```vue
205
+ <script setup lang="ts">
206
+ import { ref } from 'vue'
207
+ import { useClickOutside } from '@yh-ui/hooks'
208
+
209
+ const dropdownRef = ref<HTMLElement>()
210
+ const isOpen = ref(false)
211
+
212
+ useClickOutside(dropdownRef, () => {
213
+ isOpen.value = false
214
+ })
215
+ </script>
216
+
217
+ <template>
218
+ <div ref="dropdownRef">
219
+ <button @click="isOpen = !isOpen">切换下拉</button>
220
+ <ul v-if="isOpen">
221
+ <li>选项 1</li>
222
+ <li>选项 2</li>
223
+ </ul>
224
+ </div>
225
+ </template>
226
+ ```
227
+
228
+ ### `useLocale` — 国际化
229
+
230
+ ```ts
231
+ import { useLocale } from '@yh-ui/hooks'
232
+
233
+ const { t, locale } = useLocale()
234
+ // t('common.confirm') => '确认' (zh-CN) | 'Confirm' (en)
235
+ ```
236
+
237
+ ### `useNamespace` — BEM 类名
238
+
239
+ ```ts
240
+ import { useNamespace } from '@yh-ui/hooks'
241
+
242
+ const ns = useNamespace('button')
243
+ ns.b() // 'yh-button'
244
+ ns.e('icon') // 'yh-button__icon'
245
+ ns.m('primary') // 'yh-button--primary'
246
+ ns.em('icon', 'large') // 'yh-button__icon--large'
247
+ ```
248
+
249
+ ### `useEventListener` — 自动清理事件
250
+
251
+ ```ts
252
+ import { ref } from 'vue'
253
+ import { useEventListener } from '@yh-ui/hooks'
254
+
255
+ const target = ref<HTMLElement>()
256
+ // 组件卸载时自动移除监听,无需手动 removeEventListener
257
+ useEventListener(target, 'scroll', (e) => {
258
+ console.log('scrolled', e)
259
+ })
260
+ ```
261
+
262
+ ### `useZIndex` — z-index 管理
263
+
264
+ ```ts
265
+ import { useZIndex } from '@yh-ui/hooks'
266
+
267
+ const { nextZIndex, currentZIndex } = useZIndex()
268
+ const zIndex = nextZIndex() // 2001, 2002, 2003 ...
269
+ ```
270
+
271
+ ---
272
+
273
+ ## ⚠️ 注意事项
274
+
275
+ - **SSR 环境**:`useClickOutside`、`useEventListener`、`useScrollLock` 会在服务端自动跳过 DOM 操作,无需额外处理
276
+ - **Vue 3.5+ 推荐**:`useId` 内部优先使用 Vue 3.5 原生 `useId()`,旧版本会自动 fallback
277
+ - **独立使用**:可脱离 `@yh-ui/components` 单独使用,适合自研组件场景
278
+
279
+ ---
280
+
281
+ ## 🔗 相关资源
282
+
283
+ - [📖 官方文档](https://1079161148.github.io/yh-ui/)
284
+ - [📦 GitHub 仓库](https://github.com/1079161148/yh-ui)
285
+ - [📝 更新日志](https://github.com/1079161148/yh-ui/blob/main/CHANGELOG.md)
286
+
287
+ ## 📄 开源协议
288
+
289
+ MIT License © 2024-present YH-UI Team