@ttoss/react-hooks 2.0.9 → 2.0.10

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
@@ -2,35 +2,15 @@
2
2
 
3
3
  ## 📚 About
4
4
 
5
- **@ttoss/react-hooks** is an easy way to use Utility Hooks in your React application.
5
+ **@ttoss/react-hooks** is a collection of custom React hooks that can be used to simplify the development of React applications.
6
6
 
7
- ## 🚀 Getting Started
7
+ ## Installation
8
8
 
9
- ### Installing @ttoss/react-hooks
10
-
11
- ```shell
12
- $ yarn add @ttoss/react-hooks
13
- # or
14
- $ npm install @ttoss/react-hooks
9
+ ```bash
10
+ pnpm add @ttoss/react-hooks
15
11
  ```
16
12
 
17
- ## 📄 Usage Examples
18
-
19
- ### useScript
20
-
21
- The `useScript` hook is used to load external scripts into your React component.
22
-
23
- ```tsx
24
- import React from 'react';
25
- import { useScript } from '@ttoss/react-hooks';
26
-
27
- export const ComponentWithScript = () => {
28
- const url = 'https://your-domain.com/bundle-api.js';
29
- const { status } = useScript(url);
30
-
31
- return <div>{status === 'ready' ? 'Script loaded' : 'Loading'}</div>;
32
- };
33
- ```
13
+ ## API
34
14
 
35
15
  ### useDebounce
36
16
 
@@ -55,20 +35,50 @@ export const DebouncedInputComponent = () => {
55
35
  };
56
36
  ```
57
37
 
58
- ## 📘 Types
38
+ ### useLocalStorage
59
39
 
60
- ### useScript
40
+ The `useLocalStorage` hook is used to store and retrieve values from the local storage.
41
+
42
+ ```tsx
43
+ import * as React from 'react';
44
+ import { useLocalStorage } from '@ttoss/react-hooks';
61
45
 
62
- ```ts
63
- type ScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
46
+ export const LocalStorageComponent = () => {
47
+ const [value, setValue] = useLocalStorage('key', 'default value');
64
48
 
65
- const useScript: (src: string) => {
66
- status: ScriptStatus;
49
+ return (
50
+ <div>
51
+ <input
52
+ type="text"
53
+ value={value}
54
+ onChange={(e) => setValue(e.target.value)}
55
+ placeholder="Type to save..."
56
+ />
57
+ </div>
58
+ );
67
59
  };
68
60
  ```
69
61
 
70
- ### useDebounce
62
+ It uses the `localStorage` storage by default, but you can also use the `sessionStorage` storage by passing the `Storage` option.
63
+
64
+ ```tsx
65
+ const [value, setValue] = useLocalStorage('key', 'default value', {
66
+ storage: window.sessionStorage,
67
+ });
68
+ ```
69
+
70
+ ### useScript
71
+
72
+ The `useScript` hook is used to load external scripts into your React component.
71
73
 
72
- ```ts
73
- const useDebounce: <T>(value: T, delay?: number) => T;
74
+ ```tsx
75
+ import React from 'react';
76
+ import { useScript } from '@ttoss/react-hooks';
77
+
78
+ export const ComponentWithScript = () => {
79
+ const url = 'https://your-domain.com/bundle-api.js';
80
+ const { status } = useScript(url);
81
+
82
+ return <div>{status === 'ready' ? 'Script loaded' : 'Loading'}</div>;
83
+ };
74
84
  ```
package/dist/esm/index.js CHANGED
@@ -1,10 +1,25 @@
1
1
  /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
2
 
3
- // src/useScript.ts
3
+ // src/useDebounce.ts
4
4
  import * as React from "react";
5
- var useScript = src => {
6
- const [status, setStatus] = React.useState(src ? "loading" : "idle");
5
+ var useDebounce = (value, delay) => {
6
+ const [debouncedValue, setDebouncedValue] = React.useState(value);
7
7
  React.useEffect(() => {
8
+ const timer = setTimeout(() => {
9
+ return setDebouncedValue(value);
10
+ }, delay || 500);
11
+ return () => {
12
+ clearTimeout(timer);
13
+ };
14
+ }, [value, delay]);
15
+ return debouncedValue;
16
+ };
17
+
18
+ // src/useScript.ts
19
+ import * as React2 from "react";
20
+ var useScript = src => {
21
+ const [status, setStatus] = React2.useState(src ? "loading" : "idle");
22
+ React2.useEffect(() => {
8
23
  if (!src) {
9
24
  setStatus("idle");
10
25
  return;
@@ -47,18 +62,98 @@ var useScript = src => {
47
62
  };
48
63
  };
49
64
 
50
- // src/useDebounce.ts
51
- import * as React2 from "react";
52
- var useDebounce = (value, delay) => {
53
- const [debouncedValue, setDebouncedValue] = React2.useState(value);
54
- React2.useEffect(() => {
55
- const timer = setTimeout(() => {
56
- return setDebouncedValue(value);
57
- }, delay || 500);
65
+ // src/useStorage.ts
66
+ import * as React3 from "react";
67
+ function useStorage(key, defaultValue, options) {
68
+ const opts = React3.useMemo(() => {
69
+ return {
70
+ serializer: JSON.stringify,
71
+ parser: JSON.parse,
72
+ // eslint-disable-next-line no-console
73
+ logger: console.log,
74
+ syncData: true,
75
+ ...options
76
+ };
77
+ }, [options]);
78
+ const {
79
+ serializer,
80
+ parser,
81
+ logger,
82
+ syncData,
83
+ storage
84
+ } = opts;
85
+ const effectiveStorage = storage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
86
+ const rawValueRef = React3.useRef(null);
87
+ const [value, setValue] = React3.useState(() => {
88
+ if (typeof window === "undefined" || !effectiveStorage) {
89
+ return defaultValue;
90
+ }
91
+ try {
92
+ rawValueRef.current = effectiveStorage.getItem(key);
93
+ const res = rawValueRef.current ? parser(rawValueRef.current) : defaultValue;
94
+ return res;
95
+ } catch (e) {
96
+ logger(e);
97
+ return defaultValue;
98
+ }
99
+ });
100
+ React3.useEffect(() => {
101
+ if (typeof window === "undefined" || !effectiveStorage) {
102
+ return;
103
+ }
104
+ const updateLocalStorage = () => {
105
+ if (value !== void 0) {
106
+ const newValue = serializer(value);
107
+ const oldValue = rawValueRef.current;
108
+ rawValueRef.current = newValue;
109
+ effectiveStorage.setItem(key, newValue);
110
+ window.dispatchEvent(new StorageEvent("storage", {
111
+ storageArea: effectiveStorage,
112
+ url: window.location.href,
113
+ key,
114
+ newValue,
115
+ oldValue
116
+ }));
117
+ } else {
118
+ effectiveStorage.removeItem(key);
119
+ window.dispatchEvent(new StorageEvent("storage", {
120
+ storageArea: effectiveStorage,
121
+ url: window.location.href,
122
+ key
123
+ }));
124
+ }
125
+ };
126
+ try {
127
+ updateLocalStorage();
128
+ } catch (e) {
129
+ logger(e);
130
+ }
131
+ }, [key, logger, serializer, effectiveStorage, value]);
132
+ React3.useEffect(() => {
133
+ if (!syncData) {
134
+ return;
135
+ }
136
+ const handleStorageChange = e => {
137
+ if (e.key !== key || e.storageArea !== effectiveStorage) {
138
+ return;
139
+ }
140
+ try {
141
+ if (e.newValue !== rawValueRef.current) {
142
+ rawValueRef.current = e.newValue;
143
+ setValue(e.newValue ? parser(e.newValue) : void 0);
144
+ }
145
+ } catch (e2) {
146
+ logger(e2);
147
+ }
148
+ };
149
+ if (typeof window === "undefined") {
150
+ return;
151
+ }
152
+ window.addEventListener("storage", handleStorageChange);
58
153
  return () => {
59
- clearTimeout(timer);
154
+ return window.removeEventListener("storage", handleStorageChange);
60
155
  };
61
- }, [value, delay]);
62
- return debouncedValue;
63
- };
64
- export { useDebounce, useScript };
156
+ }, [key, logger, parser, effectiveStorage, syncData]);
157
+ return [value, setValue];
158
+ }
159
+ export { useDebounce, useScript, useStorage };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import * as React from 'react';
2
+
3
+ declare const useDebounce: <T>(value: T, delay?: number) => T;
4
+
1
5
  type ScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
2
6
  /**
3
7
  * https://usehooks.com/useScript/
@@ -9,6 +13,17 @@ declare const useScript: (src: string) => {
9
13
  status: ScriptStatus;
10
14
  };
11
15
 
12
- declare const useDebounce: <T>(value: T, delay?: number) => T;
16
+ type Serializer<T> = (object: T | undefined) => string;
17
+ type Parser<T> = (val: string) => T | undefined;
18
+ type Setter<T> = React.Dispatch<React.SetStateAction<T | undefined>>;
19
+ type Options<T> = Partial<{
20
+ serializer: Serializer<T>;
21
+ parser: Parser<T>;
22
+ logger: (error: any) => void;
23
+ syncData: boolean;
24
+ storage?: Storage;
25
+ }>;
26
+ declare function useStorage<T>(key: string, defaultValue: T, options?: Options<T>): [T, Setter<T>];
27
+ declare function useStorage<T>(key: string, defaultValue?: undefined, options?: Options<T>): [T | undefined, Setter<T>];
13
28
 
14
- export { type ScriptStatus, useDebounce, useScript };
29
+ export { type ScriptStatus, useDebounce, useScript, useStorage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/react-hooks",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
4
4
  "description": "React hooks.",
5
5
  "license": "MIT",
6
6
  "author": "ttoss",