@usefy/usefy 0.0.12 โ†’ 0.0.13

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.
Files changed (2) hide show
  1. package/README.md +461 -0
  2. package/package.json +11 -11
package/README.md ADDED
@@ -0,0 +1,461 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/geon0529/usefy/master/assets/logo.png" alt="usefy logo" width="180" />
3
+ </p>
4
+
5
+ <h1 align="center">usefy</h1>
6
+
7
+ <p align="center">
8
+ <strong>๐Ÿช A collection of production-ready React hooks for modern applications</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@usefy/usefy">
13
+ <img src="https://img.shields.io/npm/v/@usefy/usefy.svg?style=flat-square&color=007acc" alt="npm version" />
14
+ </a>
15
+ <a href="https://www.npmjs.com/package/@usefy/usefy">
16
+ <img src="https://img.shields.io/npm/dm/@usefy/usefy.svg?style=flat-square&color=007acc" alt="npm downloads" />
17
+ </a>
18
+ <a href="https://bundlephobia.com/package/@usefy/usefy">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/@usefy/usefy?style=flat-square&color=007acc" alt="bundle size" />
20
+ </a>
21
+ <a href="https://github.com/geon0529/usefy/blob/master/LICENSE">
22
+ <img src="https://img.shields.io/npm/l/@usefy/usefy.svg?style=flat-square&color=007acc" alt="license" />
23
+ </a>
24
+ </p>
25
+
26
+ <p align="center">
27
+ <a href="#installation">Installation</a> โ€ข
28
+ <a href="#packages">Packages</a> โ€ข
29
+ <a href="#quick-start">Quick Start</a> โ€ข
30
+ <a href="#features">Features</a> โ€ข
31
+ <a href="#contributing">Contributing</a>
32
+ </p>
33
+
34
+ ---
35
+
36
+ > โš ๏ธ **Pre-release Notice**: This project is currently in version `0.x.x` (alpha/beta stage). APIs may change between minor versions. While fully functional and tested, please use with caution in production environments. We welcome feedback and contributions to help stabilize the API!
37
+ >
38
+ > ๐Ÿšง **Actively Developing**: New hooks are being added regularly. Stay tuned for more utilities!
39
+
40
+ ---
41
+
42
+ ## Overview
43
+
44
+ **usefy** is a collection of production-ready custom hooks designed for modern React applications. All hooks are written in TypeScript, providing complete type safety, comprehensive testing, and minimal bundle size.
45
+
46
+ ### โœจ Why usefy?
47
+
48
+ - **๐Ÿš€ Zero Dependencies** โ€” Pure React implementation with no external dependencies
49
+ - **๐Ÿ“ฆ Tree Shakeable** โ€” Import only the hooks you need to optimize bundle size
50
+ - **๐Ÿ”ท TypeScript First** โ€” Complete type safety with full autocomplete support
51
+ - **โšก SSR Compatible** โ€” Works seamlessly with Next.js, Remix, and other SSR frameworks
52
+ - **๐Ÿงช Well Tested** โ€” High test coverage ensures reliability and stability
53
+ - **๐Ÿ“– Well Documented** โ€” Detailed documentation with practical examples
54
+
55
+ ---
56
+
57
+ ## Installation
58
+
59
+ ### All-in-One Package
60
+
61
+ Install all hooks at once:
62
+
63
+ ```bash
64
+ # npm
65
+ npm install @usefy/usefy
66
+
67
+ # yarn
68
+ yarn add @usefy/usefy
69
+
70
+ # pnpm
71
+ pnpm add @usefy/usefy
72
+ ```
73
+
74
+ ### Individual Packages
75
+
76
+ You can also install only the hooks you need:
77
+
78
+ ```bash
79
+ # Example: Install only use-toggle
80
+ pnpm add @usefy/use-toggle
81
+
82
+ # Install multiple packages
83
+ pnpm add @usefy/use-debounce @usefy/use-local-storage
84
+ ```
85
+
86
+ ### Peer Dependencies
87
+
88
+ All packages require React 18 or 19:
89
+
90
+ ```json
91
+ {
92
+ "peerDependencies": {
93
+ "react": "^18.0.0 || ^19.0.0"
94
+ }
95
+ }
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Packages
101
+
102
+ ### ๐Ÿ“ฆ Available Hooks
103
+
104
+ | Hook | Description | npm | Coverage |
105
+ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
106
+ | [@usefy/use-toggle](https://www.npmjs.com/package/@usefy/use-toggle) | Boolean state management with toggle, setTrue, setFalse | [![npm](https://img.shields.io/npm/v/@usefy/use-toggle.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-toggle) | ![100%](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square) |
107
+ | [@usefy/use-counter](https://www.npmjs.com/package/@usefy/use-counter) | Counter state with increment, decrement, reset | [![npm](https://img.shields.io/npm/v/@usefy/use-counter.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-counter) | ![100%](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square) |
108
+ | [@usefy/use-debounce](https://www.npmjs.com/package/@usefy/use-debounce) | Value debouncing with leading/trailing edge | [![npm](https://img.shields.io/npm/v/@usefy/use-debounce.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-debounce) | ![91%](https://img.shields.io/badge/coverage-91%25-brightgreen?style=flat-square) |
109
+ | [@usefy/use-debounce-callback](https://www.npmjs.com/package/@usefy/use-debounce-callback) | Debounced callbacks with cancel/flush/pending | [![npm](https://img.shields.io/npm/v/@usefy/use-debounce-callback.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-debounce-callback) | ![94%](https://img.shields.io/badge/coverage-94%25-brightgreen?style=flat-square) |
110
+ | [@usefy/use-throttle](https://www.npmjs.com/package/@usefy/use-throttle) | Value throttling for rate-limiting updates | [![npm](https://img.shields.io/npm/v/@usefy/use-throttle.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-throttle) | ![100%](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square) |
111
+ | [@usefy/use-throttle-callback](https://www.npmjs.com/package/@usefy/use-throttle-callback) | Throttled callbacks with cancel/flush/pending | [![npm](https://img.shields.io/npm/v/@usefy/use-throttle-callback.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-throttle-callback) | ![100%](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square) |
112
+ | [@usefy/use-local-storage](https://www.npmjs.com/package/@usefy/use-local-storage) | localStorage persistence with cross-tab sync | [![npm](https://img.shields.io/npm/v/@usefy/use-local-storage.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-local-storage) | ![95%](https://img.shields.io/badge/coverage-95%25-brightgreen?style=flat-square) |
113
+ | [@usefy/use-session-storage](https://www.npmjs.com/package/@usefy/use-session-storage) | sessionStorage persistence for tab lifetime | [![npm](https://img.shields.io/npm/v/@usefy/use-session-storage.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-session-storage) | ![94%](https://img.shields.io/badge/coverage-94%25-brightgreen?style=flat-square) |
114
+ | [@usefy/use-click-any-where](https://www.npmjs.com/package/@usefy/use-click-any-where) | Document-wide click event detection | [![npm](https://img.shields.io/npm/v/@usefy/use-click-any-where.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-click-any-where) | ![92%](https://img.shields.io/badge/coverage-92%25-brightgreen?style=flat-square) |
115
+ | [@usefy/use-copy-to-clipboard](https://www.npmjs.com/package/@usefy/use-copy-to-clipboard) | Clipboard copy with fallback support | [![npm](https://img.shields.io/npm/v/@usefy/use-copy-to-clipboard.svg?style=flat-square&color=007acc)](https://www.npmjs.com/package/@usefy/use-copy-to-clipboard) | ![88%](https://img.shields.io/badge/coverage-88%25-brightgreen?style=flat-square) |
116
+
117
+ ---
118
+
119
+ ## Quick Start
120
+
121
+ ### Using the All-in-One Package
122
+
123
+ ```tsx
124
+ import {
125
+ useToggle,
126
+ useCounter,
127
+ useDebounce,
128
+ useLocalStorage,
129
+ useCopyToClipboard,
130
+ } from "@usefy/usefy";
131
+
132
+ function App() {
133
+ // Boolean state management
134
+ const { value: isOpen, toggle, setFalse: close } = useToggle(false);
135
+
136
+ // Counter with controls
137
+ const { count, increment, decrement, reset } = useCounter(0);
138
+
139
+ // Debounced search
140
+ const [query, setQuery] = useState("");
141
+ const debouncedQuery = useDebounce(query, 300);
142
+
143
+ // Persistent theme preference
144
+ const [theme, setTheme] = useLocalStorage("theme", "light");
145
+
146
+ // Copy functionality
147
+ const [copiedText, copy] = useCopyToClipboard();
148
+
149
+ return (
150
+ <div data-theme={theme}>
151
+ {/* Modal */}
152
+ <button onClick={toggle}>Open Modal</button>
153
+ {isOpen && (
154
+ <div className="modal">
155
+ <button onClick={close}>Close</button>
156
+ </div>
157
+ )}
158
+
159
+ {/* Counter */}
160
+ <div>
161
+ <button onClick={decrement}>-</button>
162
+ <span>{count}</span>
163
+ <button onClick={increment}>+</button>
164
+ </div>
165
+
166
+ {/* Search */}
167
+ <input
168
+ value={query}
169
+ onChange={(e) => setQuery(e.target.value)}
170
+ placeholder="Search..."
171
+ />
172
+
173
+ {/* Theme Toggle */}
174
+ <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
175
+ Toggle Theme
176
+ </button>
177
+
178
+ {/* Copy */}
179
+ <button onClick={() => copy("Hello World!")}>
180
+ {copiedText ? "Copied!" : "Copy"}
181
+ </button>
182
+ </div>
183
+ );
184
+ }
185
+ ```
186
+
187
+ ### Using Individual Packages
188
+
189
+ ```tsx
190
+ import { useToggle } from "@usefy/use-toggle";
191
+ import { useDebounce } from "@usefy/use-debounce";
192
+
193
+ function SearchModal() {
194
+ const { value: isOpen, toggle } = useToggle(false);
195
+ const [query, setQuery] = useState("");
196
+ const debouncedQuery = useDebounce(query, 300);
197
+
198
+ useEffect(() => {
199
+ if (debouncedQuery) {
200
+ searchAPI(debouncedQuery);
201
+ }
202
+ }, [debouncedQuery]);
203
+
204
+ return (
205
+ <>
206
+ <button onClick={toggle}>Search</button>
207
+ {isOpen && (
208
+ <input value={query} onChange={(e) => setQuery(e.target.value)} />
209
+ )}
210
+ </>
211
+ );
212
+ }
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Features
218
+
219
+ ### ๐Ÿ”„ State Management
220
+
221
+ <details>
222
+ <summary><strong>useToggle</strong> โ€” Boolean state with utility functions</summary>
223
+
224
+ ```tsx
225
+ const { value, toggle, setTrue, setFalse, setValue } = useToggle(false);
226
+ ```
227
+
228
+ Perfect for modals, dropdowns, accordions, and switches.
229
+
230
+ </details>
231
+
232
+ <details>
233
+ <summary><strong>useCounter</strong> โ€” Counter state with controls</summary>
234
+
235
+ ```tsx
236
+ const { count, increment, decrement, reset } = useCounter(0);
237
+ ```
238
+
239
+ Ideal for quantity selectors, pagination, and score tracking.
240
+
241
+ </details>
242
+
243
+ ### โฑ๏ธ Timing Utilities
244
+
245
+ <details>
246
+ <summary><strong>useDebounce</strong> โ€” Debounce value updates</summary>
247
+
248
+ ```tsx
249
+ const debouncedValue = useDebounce(value, 300, {
250
+ leading: false,
251
+ trailing: true,
252
+ maxWait: 1000,
253
+ });
254
+ ```
255
+
256
+ Best for search inputs, form validation, and API calls.
257
+
258
+ </details>
259
+
260
+ <details>
261
+ <summary><strong>useDebounceCallback</strong> โ€” Debounce function calls</summary>
262
+
263
+ ```tsx
264
+ const debouncedFn = useDebounceCallback(callback, 300);
265
+
266
+ debouncedFn(args); // Call debounced
267
+ debouncedFn.cancel(); // Cancel pending
268
+ debouncedFn.flush(); // Execute immediately
269
+ debouncedFn.pending(); // Check if pending
270
+ ```
271
+
272
+ </details>
273
+
274
+ <details>
275
+ <summary><strong>useThrottle</strong> โ€” Throttle value updates</summary>
276
+
277
+ ```tsx
278
+ const throttledValue = useThrottle(value, 100, {
279
+ leading: true,
280
+ trailing: true,
281
+ });
282
+ ```
283
+
284
+ Perfect for scroll events, resize handlers, and mouse tracking.
285
+
286
+ </details>
287
+
288
+ <details>
289
+ <summary><strong>useThrottleCallback</strong> โ€” Throttle function calls</summary>
290
+
291
+ ```tsx
292
+ const throttledFn = useThrottleCallback(callback, 100);
293
+ ```
294
+
295
+ </details>
296
+
297
+ ### ๐Ÿ’พ Storage
298
+
299
+ <details>
300
+ <summary><strong>useLocalStorage</strong> โ€” Persistent storage with sync</summary>
301
+
302
+ ```tsx
303
+ const [value, setValue, removeValue] = useLocalStorage("key", initialValue, {
304
+ serializer: JSON.stringify,
305
+ deserializer: JSON.parse,
306
+ syncTabs: true,
307
+ onError: (error) => console.error(error),
308
+ });
309
+ ```
310
+
311
+ Supports cross-tab synchronization and custom serialization.
312
+
313
+ </details>
314
+
315
+ <details>
316
+ <summary><strong>useSessionStorage</strong> โ€” Session-scoped storage</summary>
317
+
318
+ ```tsx
319
+ const [value, setValue, removeValue] = useSessionStorage("key", initialValue);
320
+ ```
321
+
322
+ Data persists during tab lifetime, isolated per tab.
323
+
324
+ </details>
325
+
326
+ ### ๐Ÿ–ฑ๏ธ Events
327
+
328
+ <details>
329
+ <summary><strong>useClickAnyWhere</strong> โ€” Global click detection</summary>
330
+
331
+ ```tsx
332
+ useClickAnyWhere(
333
+ (event) => {
334
+ if (!ref.current?.contains(event.target)) {
335
+ closeMenu();
336
+ }
337
+ },
338
+ { enabled: isOpen }
339
+ );
340
+ ```
341
+
342
+ Ideal for closing dropdowns, modals, and context menus.
343
+
344
+ </details>
345
+
346
+ <details>
347
+ <summary><strong>useCopyToClipboard</strong> โ€” Clipboard operations</summary>
348
+
349
+ ```tsx
350
+ const [copiedText, copy] = useCopyToClipboard({
351
+ timeout: 2000,
352
+ onSuccess: (text) => toast.success("Copied!"),
353
+ onError: (error) => toast.error("Failed to copy"),
354
+ });
355
+
356
+ const success = await copy("text to copy");
357
+ ```
358
+
359
+ Modern Clipboard API with automatic fallback for older browsers.
360
+
361
+ </details>
362
+
363
+ ---
364
+
365
+ ## Test Coverage
366
+
367
+ All packages are comprehensively tested using Vitest to ensure reliability and stability.
368
+
369
+ | Package | Statements | Branches | Functions | Lines |
370
+ | --------------------- | ---------- | -------- | --------- | ----- |
371
+ | use-toggle | 100% | 100% | 100% | 100% |
372
+ | use-counter | 100% | 100% | 100% | 100% |
373
+ | use-throttle | 100% | 100% | 100% | 100% |
374
+ | use-throttle-callback | 100% | 100% | 100% | 100% |
375
+ | use-local-storage | 95% | 86% | 100% | 95% |
376
+ | use-session-storage | 94% | 79% | 100% | 94% |
377
+ | use-debounce-callback | 94% | 83% | 94% | 94% |
378
+ | use-click-any-where | 92% | 88% | 100% | 92% |
379
+ | use-debounce | 91% | 90% | 67% | 93% |
380
+ | use-copy-to-clipboard | 88% | 79% | 86% | 88% |
381
+
382
+ ---
383
+
384
+ ## Browser Support
385
+
386
+ | Browser | Version |
387
+ | ------- | ---------------- |
388
+ | Chrome | 66+ |
389
+ | Firefox | 63+ |
390
+ | Safari | 13.1+ |
391
+ | Edge | 79+ |
392
+ | IE 11 | Fallback support |
393
+
394
+ ---
395
+
396
+ ## Contributing
397
+
398
+ We welcome contributions! Please see our [Contributing Guide](https://github.com/geon0529/usefy/blob/master/CONTRIBUTING.md) for details.
399
+
400
+ ```bash
401
+ # Clone the repository
402
+ git clone https://github.com/geon0529/usefy.git
403
+
404
+ # Install dependencies
405
+ pnpm install
406
+
407
+ # Run tests
408
+ pnpm test
409
+
410
+ # Build all packages
411
+ pnpm build
412
+
413
+ # Run tests with coverage
414
+ pnpm test --coverage
415
+ ```
416
+
417
+ ### ๐Ÿ—‚๏ธ Project Structure
418
+
419
+ ```
420
+ usefy/
421
+ โ”œโ”€โ”€ packages/
422
+ โ”‚ โ”œโ”€โ”€ usefy/ # All-in-one package
423
+ โ”‚ โ”œโ”€โ”€ use-toggle/ # Boolean state
424
+ โ”‚ โ”œโ”€โ”€ use-counter/ # Counter state
425
+ โ”‚ โ”œโ”€โ”€ use-debounce/ # Value debouncing
426
+ โ”‚ โ”œโ”€โ”€ use-debounce-callback/ # Callback debouncing
427
+ โ”‚ โ”œโ”€โ”€ use-throttle/ # Value throttling
428
+ โ”‚ โ”œโ”€โ”€ use-throttle-callback/ # Callback throttling
429
+ โ”‚ โ”œโ”€โ”€ use-local-storage/ # localStorage
430
+ โ”‚ โ”œโ”€โ”€ use-session-storage/ # sessionStorage
431
+ โ”‚ โ”œโ”€โ”€ use-click-any-where/ # Click detection
432
+ โ”‚ โ””โ”€โ”€ use-copy-to-clipboard/ # Clipboard
433
+ โ””โ”€โ”€ ...
434
+ ```
435
+
436
+ ---
437
+
438
+ ## Related Links
439
+
440
+ - ๐Ÿ“ฆ [npm Organization](https://www.npmjs.com/org/usefy)
441
+ - ๐Ÿ™ [GitHub Repository](https://github.com/geon0529/usefy)
442
+ - ๐Ÿ“ [Changelog](https://github.com/geon0529/usefy/blob/master/CHANGELOG.md)
443
+ - ๐Ÿ› [Issue Tracker](https://github.com/geon0529/usefy/issues)
444
+
445
+ ---
446
+
447
+ ## License
448
+
449
+ MIT ยฉ [mirunamu](https://github.com/geon0529)
450
+
451
+ ---
452
+
453
+ <p align="center">
454
+ <sub>Built with โค๏ธ by the usefy team</sub>
455
+ </p>
456
+
457
+ <p align="center">
458
+ <a href="https://github.com/geon0529/usefy">
459
+ <img src="https://img.shields.io/github/stars/geon0529/usefy?style=social" alt="GitHub stars" />
460
+ </a>
461
+ </p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usefy/usefy",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "A collection of useful React hooks",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -17,16 +17,16 @@
17
17
  ],
18
18
  "sideEffects": false,
19
19
  "dependencies": {
20
- "@usefy/use-copy-to-clipboard": "0.0.12",
21
- "@usefy/use-counter": "0.0.12",
22
- "@usefy/use-toggle": "0.0.12",
23
- "@usefy/use-click-any-where": "0.0.12",
24
- "@usefy/use-debounce-callback": "0.0.12",
25
- "@usefy/use-throttle": "0.0.12",
26
- "@usefy/use-debounce": "0.0.12",
27
- "@usefy/use-throttle-callback": "0.0.12",
28
- "@usefy/use-local-storage": "0.0.12",
29
- "@usefy/use-session-storage": "0.0.12"
20
+ "@usefy/use-click-any-where": "0.0.13",
21
+ "@usefy/use-copy-to-clipboard": "0.0.13",
22
+ "@usefy/use-counter": "0.0.13",
23
+ "@usefy/use-toggle": "0.0.13",
24
+ "@usefy/use-debounce-callback": "0.0.13",
25
+ "@usefy/use-debounce": "0.0.13",
26
+ "@usefy/use-throttle": "0.0.13",
27
+ "@usefy/use-throttle-callback": "0.0.13",
28
+ "@usefy/use-session-storage": "0.0.13",
29
+ "@usefy/use-local-storage": "0.0.13"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "^18.0.0 || ^19.0.0"