tona-hooks 1.0.21 → 1.0.22

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 CHANGED
@@ -1,15 +1,169 @@
1
1
  # tona-hooks
2
2
 
3
- 博客园皮肤开发用的 React Hooks 工具库。
3
+ <p align="center">
4
+ <img src="../../assets/tona.png" alt="Tona" width="100" />
5
+ </p>
4
6
 
5
- ## 安装
7
+ <p align="center">
8
+ React hooks collection for CNBlogs theme development.
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/tona-hooks"><img src="https://img.shields.io/npm/v/tona-hooks?style=flat-square" alt="npm version"></a>
13
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/tona-hooks?style=flat-square" alt="license"></a>
14
+ <a href="https://preactjs.com"><img src="https://img.shields.io/badge/Preact->=10.0.0-673AB8?style=flat-square&logo=preact" alt="Preact"></a>
15
+ </p>
16
+
17
+ **English** | [中文](./README.zh-CN.md)
18
+
19
+ ## Features
20
+
21
+ - **Preact Compatible** - Built for Preact, works with React
22
+ - **CNBlogs Optimized** - Hooks designed specifically for CNBlogs environment
23
+ - **TypeScript Support** - Full type definitions included
24
+ - **Lightweight** - Tree-shakeable and minimal footprint
25
+
26
+ ## Installation
6
27
 
7
28
  ```bash
8
29
  npm install tona-hooks
9
30
  ```
10
31
 
11
- ## 使用
32
+ ```bash
33
+ pnpm add tona-hooks
34
+ ```
35
+
36
+ ```bash
37
+ yarn add tona-hooks
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ```typescript
43
+ import { useQueryDOM, useLocalStorage, useScroll } from 'tona-hooks'
44
+ ```
45
+
46
+ ## Available Hooks
47
+
48
+ ### `useAjaxComplete`
49
+
50
+ Listen for AJAX requests completion.
51
+
52
+ ```typescript
53
+ import { useAjaxComplete } from 'tona-hooks'
54
+
55
+ useAjaxComplete((event, xhr, settings) => {
56
+ console.log('AJAX completed:', settings.url)
57
+ })
58
+ ```
59
+
60
+ ### `useEffectOnce`
61
+
62
+ Run effect only once on mount.
63
+
64
+ ```typescript
65
+ import { useEffectOnce } from 'tona-hooks'
66
+
67
+ useEffectOnce(() => {
68
+ console.log('Component mounted')
69
+ })
70
+ ```
71
+
72
+ ### `useEventCallback`
73
+
74
+ Create a stable callback reference.
75
+
76
+ ```typescript
77
+ import { useEventCallback } from 'tona-hooks'
78
+
79
+ const handleClick = useEventCallback(() => {
80
+ console.log('Clicked!')
81
+ })
82
+ ```
83
+
84
+ ### `useIsomorphicLayoutEffect`
85
+
86
+ Safe layout effect for SSR and browser.
87
+
88
+ ```typescript
89
+ import { useIsomorphicLayoutEffect } from 'tona-hooks'
90
+
91
+ useIsomorphicLayoutEffect(() => {
92
+ // DOM measurements
93
+ }, [])
94
+ ```
12
95
 
13
- ```javascript
96
+ ### `useLocalStorage`
97
+
98
+ Persist state to localStorage.
99
+
100
+ ```typescript
101
+ import { useLocalStorage } from 'tona-hooks'
102
+
103
+ const [value, setValue] = useLocalStorage('key', 'defaultValue')
104
+ ```
105
+
106
+ ### `useQueryDOM`
107
+
108
+ Query and observe DOM elements.
109
+
110
+ ```typescript
14
111
  import { useQueryDOM } from 'tona-hooks'
112
+
113
+ const element = useQueryDOM('#my-element')
15
114
  ```
115
+
116
+ ### `useRafState`
117
+
118
+ State updates synced with requestAnimationFrame.
119
+
120
+ ```typescript
121
+ import { useRafState } from 'tona-hooks'
122
+
123
+ const [position, setPosition] = useRafState({ x: 0, y: 0 })
124
+ ```
125
+
126
+ ### `useScroll`
127
+
128
+ Track scroll position of an element.
129
+
130
+ ```typescript
131
+ import { useScroll } from 'tona-hooks'
132
+
133
+ const [x, y] = useScroll(ref)
134
+ ```
135
+
136
+ ### `useUnmount`
137
+
138
+ Run cleanup on component unmount.
139
+
140
+ ```typescript
141
+ import { useUnmount } from 'tona-hooks'
142
+
143
+ useUnmount(() => {
144
+ console.log('Component unmounted')
145
+ })
146
+ ```
147
+
148
+ ### `useWindowScroll`
149
+
150
+ Track window scroll position.
151
+
152
+ ```typescript
153
+ import { useWindowScroll } from 'tona-hooks'
154
+
155
+ const [x, y] = useWindowScroll()
156
+ ```
157
+
158
+ ## Peer Dependencies
159
+
160
+ ```json
161
+ {
162
+ "preact": ">=10.0.0"
163
+ }
164
+ ```
165
+
166
+ ## Related
167
+
168
+ - [tona](https://github.com/guangzan/tona/tree/main/packages/core) - Core framework
169
+ - [tona-ui](https://github.com/guangzan/tona/tree/main/packages/ui) - UI components
@@ -0,0 +1,169 @@
1
+ # tona-hooks
2
+
3
+ <p align="center">
4
+ <img src="../../assets/tona.png" alt="Tona" width="100" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ 用于博客园主题开发的 React Hooks 集合。
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/tona-hooks"><img src="https://img.shields.io/npm/v/tona-hooks?style=flat-square" alt="npm version"></a>
13
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/tona-hooks?style=flat-square" alt="license"></a>
14
+ <a href="https://preactjs.com"><img src="https://img.shields.io/badge/Preact->=10.0.0-673AB8?style=flat-square&logo=preact" alt="Preact"></a>
15
+ </p>
16
+
17
+ [English](./README.md) | **中文**
18
+
19
+ ## 特性
20
+
21
+ - **Preact 兼容** - 为 Preact 构建,兼容 React
22
+ - **博客园优化** - 专为博客园环境设计的 Hooks
23
+ - **TypeScript 支持** - 包含完整的类型定义
24
+ - **轻量级** - 可摇树优化,占用空间小
25
+
26
+ ## 安装
27
+
28
+ ```bash
29
+ npm install tona-hooks
30
+ ```
31
+
32
+ ```bash
33
+ pnpm add tona-hooks
34
+ ```
35
+
36
+ ```bash
37
+ yarn add tona-hooks
38
+ ```
39
+
40
+ ## 使用
41
+
42
+ ```typescript
43
+ import { useQueryDOM, useLocalStorage, useScroll } from 'tona-hooks'
44
+ ```
45
+
46
+ ## 可用的 Hooks
47
+
48
+ ### `useAjaxComplete`
49
+
50
+ 监听 AJAX 请求完成。
51
+
52
+ ```typescript
53
+ import { useAjaxComplete } from 'tona-hooks'
54
+
55
+ useAjaxComplete((event, xhr, settings) => {
56
+ console.log('AJAX completed:', settings.url)
57
+ })
58
+ ```
59
+
60
+ ### `useEffectOnce`
61
+
62
+ 仅在挂载时运行一次 effect。
63
+
64
+ ```typescript
65
+ import { useEffectOnce } from 'tona-hooks'
66
+
67
+ useEffectOnce(() => {
68
+ console.log('Component mounted')
69
+ })
70
+ ```
71
+
72
+ ### `useEventCallback`
73
+
74
+ 创建稳定的回调引用。
75
+
76
+ ```typescript
77
+ import { useEventCallback } from 'tona-hooks'
78
+
79
+ const handleClick = useEventCallback(() => {
80
+ console.log('Clicked!')
81
+ })
82
+ ```
83
+
84
+ ### `useIsomorphicLayoutEffect`
85
+
86
+ 适用于 SSR 和浏览器的安全 layout effect。
87
+
88
+ ```typescript
89
+ import { useIsomorphicLayoutEffect } from 'tona-hooks'
90
+
91
+ useIsomorphicLayoutEffect(() => {
92
+ // DOM 测量
93
+ }, [])
94
+ ```
95
+
96
+ ### `useLocalStorage`
97
+
98
+ 将状态持久化到 localStorage。
99
+
100
+ ```typescript
101
+ import { useLocalStorage } from 'tona-hooks'
102
+
103
+ const [value, setValue] = useLocalStorage('key', 'defaultValue')
104
+ ```
105
+
106
+ ### `useQueryDOM`
107
+
108
+ 查询和观察 DOM 元素。
109
+
110
+ ```typescript
111
+ import { useQueryDOM } from 'tona-hooks'
112
+
113
+ const element = useQueryDOM('#my-element')
114
+ ```
115
+
116
+ ### `useRafState`
117
+
118
+ 与 requestAnimationFrame 同步的状态更新。
119
+
120
+ ```typescript
121
+ import { useRafState } from 'tona-hooks'
122
+
123
+ const [position, setPosition] = useRafState({ x: 0, y: 0 })
124
+ ```
125
+
126
+ ### `useScroll`
127
+
128
+ 跟踪元素的滚动位置。
129
+
130
+ ```typescript
131
+ import { useScroll } from 'tona-hooks'
132
+
133
+ const [x, y] = useScroll(ref)
134
+ ```
135
+
136
+ ### `useUnmount`
137
+
138
+ 在组件卸载时运行清理。
139
+
140
+ ```typescript
141
+ import { useUnmount } from 'tona-hooks'
142
+
143
+ useUnmount(() => {
144
+ console.log('Component unmounted')
145
+ })
146
+ ```
147
+
148
+ ### `useWindowScroll`
149
+
150
+ 跟踪窗口滚动位置。
151
+
152
+ ```typescript
153
+ import { useWindowScroll } from 'tona-hooks'
154
+
155
+ const [x, y] = useWindowScroll()
156
+ ```
157
+
158
+ ## 对等依赖
159
+
160
+ ```json
161
+ {
162
+ "preact": ">=10.0.0"
163
+ }
164
+ ```
165
+
166
+ ## 相关
167
+
168
+ - [tona](https://github.com/guangzan/tona/tree/main/packages/core) - 核心框架
169
+ - [tona-ui](https://github.com/guangzan/tona/tree/main/packages/ui) - UI 组件
package/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@ import { Dispatch as Dispatch$1, SetStateAction } from "preact/compat";
3
3
  import { RefObject } from "preact";
4
4
 
5
5
  //#region src/use-ajax-complete.d.ts
6
-
7
6
  /**
8
7
  * 通用的 Ajax 完成监听 Hook
9
8
  * @param config 配置对象
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
2
2
  import { useCallback as useCallback$1, useLayoutEffect as useLayoutEffect$1, useRef as useRef$1, useState as useState$1 } from "preact/compat";
3
-
4
3
  //#region src/use-ajax-complete.ts
5
4
  /**
6
5
  * 通用的 Ajax 完成监听 Hook
@@ -27,17 +26,14 @@ function useAjaxComplete(config) {
27
26
  };
28
27
  }, [config]);
29
28
  }
30
-
31
29
  //#endregion
32
30
  //#region src/use-effect-once.ts
33
31
  const useEffectOnce = (effect) => {
34
32
  useEffect(effect, []);
35
33
  };
36
-
37
34
  //#endregion
38
35
  //#region src/use-isomorphic-layout-effect.ts
39
36
  const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
40
-
41
37
  //#endregion
42
38
  //#region src/use-event-callback.ts
43
39
  function useEventCallback(fn) {
@@ -49,7 +45,6 @@ function useEventCallback(fn) {
49
45
  }, [fn]);
50
46
  return useCallback$1((...args) => ref.current?.(...args), [ref]);
51
47
  }
52
-
53
48
  //#endregion
54
49
  //#region src/misc/util.ts
55
50
  const noop = () => {};
@@ -60,7 +55,6 @@ function off(obj, ...args) {
60
55
  if (obj?.removeEventListener) obj.removeEventListener(...args);
61
56
  }
62
57
  const isBrowser = typeof window !== "undefined";
63
-
64
58
  //#endregion
65
59
  //#region src/use-local-storage.ts
66
60
  const useLocalStorage = (key, initialValue, options) => {
@@ -71,13 +65,13 @@ const useLocalStorage = (key, initialValue, options) => {
71
65
  ];
72
66
  if (!key) throw new Error("useLocalStorage key may not be falsy");
73
67
  const deserializer = options ? options.raw ? (value) => value : options.deserializer : JSON.parse;
74
- const initializer = useRef$1((key$1) => {
68
+ const initializer = useRef$1((key) => {
75
69
  try {
76
70
  const serializer = options ? options.raw ? String : options.serializer : JSON.stringify;
77
- const localStorageValue = localStorage.getItem(key$1);
71
+ const localStorageValue = localStorage.getItem(key);
78
72
  if (localStorageValue !== null) return deserializer(localStorageValue);
79
73
  else {
80
- initialValue && localStorage.setItem(key$1, serializer(initialValue));
74
+ initialValue && localStorage.setItem(key, serializer(initialValue));
81
75
  return initialValue;
82
76
  }
83
77
  } catch {
@@ -110,7 +104,6 @@ const useLocalStorage = (key, initialValue, options) => {
110
104
  }, [key, setState])
111
105
  ];
112
106
  };
113
-
114
107
  //#endregion
115
108
  //#region src/use-query-dom.ts
116
109
  function useQueryDOM({ selector, observe = false, queryFn, ajaxUrl }) {
@@ -211,7 +204,6 @@ function useQueryDOM({ selector, observe = false, queryFn, ajaxUrl }) {
211
204
  isPending
212
205
  };
213
206
  }
214
-
215
207
  //#endregion
216
208
  //#region src/use-unmount.ts
217
209
  const useUnmount = (fn) => {
@@ -219,7 +211,6 @@ const useUnmount = (fn) => {
219
211
  fnRef.current = fn;
220
212
  useEffectOnce(() => () => fnRef.current());
221
213
  };
222
-
223
214
  //#endregion
224
215
  //#region src/use-raf-state.ts
225
216
  const useRafState = (initialState) => {
@@ -236,11 +227,9 @@ const useRafState = (initialState) => {
236
227
  });
237
228
  return [state, setRafState];
238
229
  };
239
-
240
230
  //#endregion
241
231
  //#region src/use-scroll.ts
242
232
  const useScroll = (ref) => {
243
- if (typeof ref !== "object" || typeof ref.current === "undefined") console.error("`useScroll` expects a single ref argument.");
244
233
  const [state, setState] = useRafState({
245
234
  x: 0,
246
235
  y: 0
@@ -262,7 +251,6 @@ const useScroll = (ref) => {
262
251
  }, [ref, setState]);
263
252
  return state;
264
253
  };
265
-
266
254
  //#endregion
267
255
  //#region src/use-window-scroll.ts
268
256
  const useWindowScroll = () => {
@@ -272,12 +260,12 @@ const useWindowScroll = () => {
272
260
  }));
273
261
  useEffect(() => {
274
262
  const handler = () => {
275
- setState((state$1) => {
263
+ setState((state) => {
276
264
  const { pageXOffset, pageYOffset } = window;
277
- return state$1.x !== pageXOffset || state$1.y !== pageYOffset ? {
265
+ return state.x !== pageXOffset || state.y !== pageYOffset ? {
278
266
  x: pageXOffset,
279
267
  y: pageYOffset
280
- } : state$1;
268
+ } : state;
281
269
  });
282
270
  };
283
271
  handler();
@@ -291,6 +279,5 @@ const useWindowScroll = () => {
291
279
  }, [setState]);
292
280
  return state;
293
281
  };
294
-
295
282
  //#endregion
296
- export { useAjaxComplete, useEffectOnce, useEventCallback, useIsomorphicLayoutEffect, useLocalStorage, useQueryDOM, useRafState, useScroll, useUnmount, useWindowScroll };
283
+ export { useAjaxComplete, useEffectOnce, useEventCallback, useIsomorphicLayoutEffect, useLocalStorage, useQueryDOM, useRafState, useScroll, useUnmount, useWindowScroll };
package/package.json CHANGED
@@ -1,46 +1,46 @@
1
1
  {
2
2
  "name": "tona-hooks",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "",
5
+ "keywords": [
6
+ "博客园"
7
+ ],
8
+ "homepage": "https://github.com/guangzan/tona/tree/main/packages/hooks#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/guangzan/tona/issues"
11
+ },
12
+ "license": "MIT",
5
13
  "author": {
6
14
  "name": "guangzan",
7
- "url": "https://www.cnblogs.com/guangzan",
8
- "email": "guangzan1999@outlook.com"
15
+ "email": "guangzan1999@outlook.com",
16
+ "url": "https://www.cnblogs.com/guangzan"
9
17
  },
10
- "license": "MIT",
11
- "homepage": "https://github.com/guangzan/tona/tree/main/packages/hooks#readme",
12
18
  "repository": {
13
19
  "type": "git",
14
20
  "url": "git+https://github.com/guangzan/tona.git",
15
21
  "directory": "packages/hooks"
16
22
  },
17
- "bugs": {
18
- "url": "https://github.com/guangzan/tona/issues"
19
- },
20
- "keywords": [
21
- "博客园"
23
+ "files": [
24
+ "dist"
22
25
  ],
23
26
  "type": "module",
27
+ "main": "./dist/index.js",
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
24
30
  "exports": {
25
31
  ".": {
26
32
  "types": "./dist/index.d.ts",
27
33
  "import": "./dist/index.js"
28
34
  }
29
35
  },
30
- "main": "./dist/index.js",
31
- "module": "./dist/index.js",
32
- "types": "./dist/index.d.ts",
33
- "files": [
34
- "dist"
35
- ],
36
36
  "devDependencies": {
37
- "tsdown": "latest"
37
+ "vite-plus": "latest"
38
38
  },
39
39
  "peerDependencies": {
40
- "preact": "^10.28.2"
40
+ "preact": "^10.29.0"
41
41
  },
42
42
  "scripts": {
43
- "dev": "tsdown --watch",
44
- "build": "tsdown"
43
+ "dev": "vp pack --watch",
44
+ "build": "vp pack"
45
45
  }
46
46
  }