use-good-hooks 1.0.26 → 1.0.28

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
@@ -33,7 +33,7 @@ pnpm add use-good-hooks
33
33
  Debounces value changes to prevent rapid updates. Useful for search inputs, form validation, and other scenarios where you want to delay state updates until after a user has stopped changing the input.
34
34
 
35
35
  ```typescript
36
- import { useDebounce } from 'use-good-hooks/use-debounce';
36
+ import useDebounce from 'use-good-hooks/use-debounce';
37
37
 
38
38
  const SearchComponent = () => {
39
39
  const [searchTerm, setSearchTerm] = useState('');
@@ -71,7 +71,7 @@ const SearchComponent = () => {
71
71
  Creates a debounced version of a function. This hook ensures that a function is only executed after a specified period of inactivity, preventing it from being called too frequently. It's ideal for handling events like button clicks or API triggers that should not fire on every user action.
72
72
 
73
73
  ```typescript
74
- import { useDebounceFn } from 'use-good-hooks/use-debounce-fn';
74
+ import useDebounceFn from 'use-good-hooks/use-debounce-fn';
75
75
 
76
76
  const SaveButton = () => {
77
77
  const [status, setStatus] = useState('Idle');
@@ -110,7 +110,7 @@ const SaveButton = () => {
110
110
  Limits the rate at which a value can update. Useful for scroll events, window resizing, and other high-frequency events.
111
111
 
112
112
  ```typescript
113
- import { useThrottle } from 'use-good-hooks/use-throttle';
113
+ import useThrottle from 'use-good-hooks/use-throttle';
114
114
 
115
115
  const ScrollTracker = () => {
116
116
  const [scrollY, setScrollY] = useState(0);
@@ -143,7 +143,7 @@ const ScrollTracker = () => {
143
143
  Creates a throttled version of a function, limiting its execution to at most once per specified interval. It is useful for performance-critical scenarios like handling mouse movements, scrolling, or window resizing events without overwhelming the browser.
144
144
 
145
145
  ```typescript
146
- import { useThrottleFn } from 'use-good-hooks/use-throttle-fn';
146
+ import useThrottleFn from 'use-good-hooks/use-throttle-fn';
147
147
 
148
148
  const MouseTracker = () => {
149
149
  const [position, setPosition] = useState({ x: 0, y: 0 });
@@ -179,7 +179,7 @@ const MouseTracker = () => {
179
179
  Captures the previous value of a state or prop. Useful for comparing changes between renders.
180
180
 
181
181
  ```typescript
182
- import { usePrev } from 'use-good-hooks/use-prev';
182
+ import usePrev from 'use-good-hooks/use-prev';
183
183
 
184
184
  const Counter = ({ count }) => {
185
185
  const prevCount = usePrev(count);
@@ -202,12 +202,12 @@ const Counter = ({ count }) => {
202
202
 
203
203
  - The previous value (undefined on first render)
204
204
 
205
- ### `useStateHistory`
205
+ ### `useHistoryState`
206
206
 
207
207
  Tracks the history of a state value, providing undo and redo capabilities. This is perfect for building editors, forms, or any UI where users might want to reverse their actions.
208
208
 
209
209
  ```typescript
210
- import { useStateHistory } from 'use-good-hooks/use-state-history';
210
+ import useHistoryState from 'use-good-hooks/use-history-state';
211
211
 
212
212
  const TextEditor = () => {
213
213
  const {
@@ -218,7 +218,7 @@ const TextEditor = () => {
218
218
  setState,
219
219
  state,
220
220
  undo
221
- } = useStateHistory('', { capacity: 10 });
221
+ } = useHistoryState('', { capacity: 10 });
222
222
 
223
223
  return (
224
224
  <div>
@@ -261,7 +261,7 @@ const TextEditor = () => {
261
261
  Detects distinct changes in values with support for deep comparison and custom equality checks. Useful for tracking whether complex objects have actually changed.
262
262
 
263
263
  ```typescript
264
- import { useDistinct } from 'use-good-hooks/use-distinct';
264
+ import useDistinct from 'use-good-hooks/use-distinct';
265
265
 
266
266
  const UserProfileForm = ({ user }) => {
267
267
  const { distinct, value, prevValue } = useDistinct(user, { deep: true });
@@ -303,7 +303,7 @@ const UserProfileForm = ({ user }) => {
303
303
  Persists state to localStorage or sessionStorage with automatic serialization/deserialization.
304
304
 
305
305
  ```typescript
306
- import { useStorageState } from 'use-good-hooks/use-storage-state';
306
+ import useStorageState from 'use-good-hooks/use-storage-state';
307
307
 
308
308
  const ThemePreferences = () => {
309
309
  const [preferences, setPreferences, { removeKey }] = useStorageState('theme-prefs', {
@@ -354,7 +354,7 @@ const ThemePreferences = () => {
354
354
  Synchronizes state with URL query parameters. Great for shareable UI states, filters, pagination, and search terms.
355
355
 
356
356
  ```typescript
357
- import { useUrlState } from 'use-good-hooks/use-url-state';
357
+ import useUrlState from 'use-good-hooks/use-url-state';
358
358
 
359
359
  const ProductFilter = () => {
360
360
  const [filters, setFilters] = useUrlState({
@@ -496,7 +496,7 @@ const MyComponent = () => {
496
496
  Creates a temporary state that resets after a specified timeout.
497
497
 
498
498
  ```typescript
499
- import { useTemporaryState } from 'use-good-hooks/use-temporary-state';
499
+ import useTemporaryState from 'use-good-hooks/use-temporary-state';
500
500
 
501
501
  const [state, setState] = useTemporaryState('initial', 1000);
502
502
 
@@ -0,0 +1,9 @@
1
+ import { DebouncedFunc } from 'lodash';
2
+ import { DebounceSettings } from 'lodash';
3
+
4
+ export { DebounceSettings }
5
+
6
+ declare const useDebounceFn: <T extends (...args: any[]) => any>(fn: T, delay?: number, options?: DebounceSettings) => DebouncedFunc<(...args: Parameters<T>) => any>;
7
+ export default useDebounceFn;
8
+
9
+ export { }
@@ -0,0 +1,25 @@
1
+ import { useRef as o, useEffect as f } from "react";
2
+ import s from "lodash/debounce";
3
+ const m = 300, E = (r, e = m, n) => {
4
+ const t = o(r);
5
+ f(() => {
6
+ t.current = r;
7
+ }, [r]);
8
+ const u = o(
9
+ s(
10
+ (...c) => t.current(...c),
11
+ e,
12
+ n
13
+ )
14
+ );
15
+ return f(() => (u.current = s(
16
+ (...c) => t.current(...c),
17
+ e,
18
+ n
19
+ ), () => {
20
+ u.current.cancel();
21
+ }), [e, n]), u.current;
22
+ };
23
+ export {
24
+ E as default
25
+ };
@@ -0,0 +1,49 @@
1
+ import { DebounceSettings } from 'lodash';
2
+
3
+ declare type HistoryAction<T> = {
4
+ type: 'CLEAR';
5
+ initialPresent: T;
6
+ } | {
7
+ type: 'REDO';
8
+ } | {
9
+ type: 'SET';
10
+ newPresent: T;
11
+ } | {
12
+ type: 'UNDO';
13
+ };
14
+
15
+ declare type HistoryOnChange<T> = ({ action, state }: {
16
+ action: HistoryAction<T>['type'];
17
+ state: HistoryState<T>['present'];
18
+ }) => void;
19
+
20
+ declare type HistoryState<T> = {
21
+ future: T[];
22
+ past: T[];
23
+ present: T | null;
24
+ };
25
+
26
+ declare type UseHistoryOptionsState<T> = {
27
+ debounceOptions?: DebounceSettings;
28
+ debounceTime?: number;
29
+ maxCapacity?: number;
30
+ onChange?: HistoryOnChange<T>;
31
+ };
32
+
33
+ declare const useHistoryState: <T>(initialPresent: T, options?: UseHistoryOptionsState<T>) => {
34
+ canRedo: boolean;
35
+ canUndo: boolean;
36
+ clear: () => void;
37
+ history: {
38
+ past: T[];
39
+ future: T[];
40
+ };
41
+ redo: () => void;
42
+ set: (newPresent: T) => void;
43
+ setDirect: (newPresent: T) => void;
44
+ state: T;
45
+ undo: () => void;
46
+ };
47
+ export default useHistoryState;
48
+
49
+ export { }
@@ -0,0 +1,114 @@
1
+ import { useRef as P, useReducer as b, useCallback as d } from "react";
2
+ import c from "lodash/cloneDeep";
3
+ import N from "lodash/isNil";
4
+ import f from "lodash/size";
5
+ import T from "./use-debounce-fn.js";
6
+ const U = {
7
+ past: [],
8
+ present: null,
9
+ future: []
10
+ }, A = ({
11
+ action: r,
12
+ maxCapacity: y,
13
+ onChange: s,
14
+ state: n
15
+ }) => {
16
+ const { past: p, present: o, future: l } = n;
17
+ if (r.type === "UNDO") {
18
+ if (f(p) === 0)
19
+ return n;
20
+ const e = p[f(p) - 1], u = {
21
+ past: p.slice(0, f(p) - 1),
22
+ present: c(e),
23
+ future: [c(o), ...l]
24
+ };
25
+ return s == null || s({
26
+ action: r.type,
27
+ state: u.present
28
+ }), u;
29
+ } else if (r.type === "REDO") {
30
+ if (f(l) === 0)
31
+ return n;
32
+ const e = l[0], t = l.slice(1), u = {
33
+ past: [...p, c(o)],
34
+ present: c(e),
35
+ future: t
36
+ };
37
+ return s == null || s({
38
+ action: r.type,
39
+ state: u.present
40
+ }), u;
41
+ } else if (r.type === "SET") {
42
+ const { newPresent: e } = r;
43
+ if (JSON.stringify(e) === JSON.stringify(o))
44
+ return n;
45
+ let t = [...p];
46
+ o !== null && (t = [...t, c(o)]), !N(y) && y > 0 && f(t) > y && (t = t.slice(f(t) - y));
47
+ const u = {
48
+ past: t,
49
+ present: c(e),
50
+ future: []
51
+ };
52
+ return s == null || s({
53
+ action: r.type,
54
+ state: u.present
55
+ }), u;
56
+ } else if (r.type === "CLEAR") {
57
+ const e = {
58
+ past: [],
59
+ present: c(r.initialPresent),
60
+ future: []
61
+ };
62
+ return s == null || s({
63
+ action: r.type,
64
+ state: e.present
65
+ }), e;
66
+ } else
67
+ throw new Error("Unsupported action type");
68
+ }, v = (r, y) => {
69
+ const { maxCapacity: s, debounceTime: n, debounceOptions: p, onChange: o } = y || {}, l = P(r), [e, t] = b(
70
+ (i, a) => A({
71
+ action: a,
72
+ maxCapacity: s,
73
+ onChange: o,
74
+ state: i
75
+ }),
76
+ {
77
+ ...U,
78
+ present: c(l.current)
79
+ }
80
+ ), u = f(e.future) !== 0, S = f(e.past) !== 0, R = d(() => t({
81
+ initialPresent: l.current,
82
+ type: "CLEAR"
83
+ }), []), D = d(() => {
84
+ u && t({ type: "REDO" });
85
+ }, [u]), m = T(
86
+ (i) => t({ type: "SET", newPresent: i }),
87
+ n,
88
+ p
89
+ ), w = d((i) => t({ type: "SET", newPresent: i }), []), E = d(() => {
90
+ S && t({ type: "UNDO" });
91
+ }, [S]), O = d(
92
+ (i) => {
93
+ n ? m(i) : w(i);
94
+ },
95
+ [n, m, w]
96
+ );
97
+ return {
98
+ canRedo: u,
99
+ canUndo: S,
100
+ clear: R,
101
+ history: {
102
+ past: e.past,
103
+ future: e.future
104
+ },
105
+ redo: D,
106
+ set: O,
107
+ setDirect: w,
108
+ state: e.present,
109
+ undo: E
110
+ };
111
+ };
112
+ export {
113
+ v as default
114
+ };
@@ -0,0 +1,9 @@
1
+ import { DebouncedFuncLeading } from 'lodash';
2
+ import { ThrottleSettings } from 'lodash';
3
+
4
+ export { ThrottleSettings }
5
+
6
+ declare const useThrottleFn: <T extends (...args: any[]) => any>(fn: T, delay?: number, options?: ThrottleSettings) => DebouncedFuncLeading<(...args: Parameters<T>) => any>;
7
+ export default useThrottleFn;
8
+
9
+ export { }
@@ -0,0 +1,25 @@
1
+ import { useRef as o, useEffect as f } from "react";
2
+ import s from "lodash/throttle";
3
+ const m = 300, E = (r, t = m, e) => {
4
+ const n = o(r);
5
+ f(() => {
6
+ n.current = r;
7
+ }, [r]);
8
+ const u = o(
9
+ s(
10
+ (...c) => n.current(...c),
11
+ t,
12
+ e
13
+ )
14
+ );
15
+ return f(() => (u.current = s(
16
+ (...c) => n.current(...c),
17
+ t,
18
+ e
19
+ ), () => {
20
+ u.current.cancel();
21
+ }), [t, e]), u.current;
22
+ };
23
+ export {
24
+ E as default
25
+ };
package/package.json CHANGED
@@ -49,5 +49,5 @@
49
49
  "test": "vitest",
50
50
  "test:coverage": "vitest --coverage"
51
51
  },
52
- "version": "1.0.26"
52
+ "version": "1.0.28"
53
53
  }