@pol-studios/hooks 1.0.0 → 1.0.1
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 +357 -0
- package/dist/_utils/index.d.ts +54 -0
- package/dist/debug/index.d.ts +36 -0
- package/dist/device/index.d.ts +139 -0
- package/dist/file/index.d.ts +26 -0
- package/dist/form/index.d.ts +20 -0
- package/dist/index.d.ts +14 -0
- package/dist/lifecycle/index.d.ts +22 -0
- package/dist/network/index.d.ts +79 -0
- package/dist/scroll/index.d.ts +101 -0
- package/dist/state/index.d.ts +41 -0
- package/dist/storage/index.d.ts +86 -0
- package/dist/toast/index.d.ts +48 -0
- package/package.json +67 -24
package/README.md
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# @pol-studios/hooks
|
|
2
|
+
|
|
3
|
+
> React hooks for POL applications
|
|
4
|
+
|
|
5
|
+
A comprehensive collection of React hooks for state management, storage, device detection, network status, file handling, toasts, forms, and debugging.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @pol-studios/hooks
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Peer Dependencies
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add react react-dom @pol-studios/features @pol-studios/utils
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import {
|
|
23
|
+
useLocalStorage,
|
|
24
|
+
useOnline,
|
|
25
|
+
useMobile,
|
|
26
|
+
useToast,
|
|
27
|
+
} from "@pol-studios/hooks";
|
|
28
|
+
|
|
29
|
+
function MyComponent() {
|
|
30
|
+
// Persist state to localStorage
|
|
31
|
+
const [theme, setTheme] = useLocalStorage("theme", "light");
|
|
32
|
+
|
|
33
|
+
// Check network status
|
|
34
|
+
const isOnline = useOnline();
|
|
35
|
+
|
|
36
|
+
// Check device type
|
|
37
|
+
const isMobile = useMobile();
|
|
38
|
+
|
|
39
|
+
// Show toast notifications
|
|
40
|
+
const { toast } = useToast();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<button onClick={() => toast({ title: "Hello!" })}>
|
|
44
|
+
Show Toast
|
|
45
|
+
</button>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Subpath Exports
|
|
51
|
+
|
|
52
|
+
| Path | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| `@pol-studios/hooks` | All exports |
|
|
55
|
+
| `@pol-studios/hooks/state` | State management hooks (usePartialState, useQueuedState, useDelayedValue) |
|
|
56
|
+
| `@pol-studios/hooks/scroll` | Scroll hooks (useScrollPosition, useScrollDirection, useHideOnScroll) |
|
|
57
|
+
| `@pol-studios/hooks/storage` | Storage hooks (useLocalStorage, useSessionStorage, useIndexedDB) |
|
|
58
|
+
| `@pol-studios/hooks/device` | Device hooks (useDevice, useMobile, useTheme, useDimensions) |
|
|
59
|
+
| `@pol-studios/hooks/network` | Network hooks (useOnline, useNetworkStatus, useMutationQueue) |
|
|
60
|
+
| `@pol-studios/hooks/lifecycle` | Lifecycle hooks (useMounted, useAfterMount, useOnScreen) |
|
|
61
|
+
| `@pol-studios/hooks/file` | File hooks (useFileDialog, useDownload) |
|
|
62
|
+
| `@pol-studios/hooks/toast` | Toast hooks (useToast, toast) |
|
|
63
|
+
| `@pol-studios/hooks/form` | Form hooks (OnValueChangedContext) |
|
|
64
|
+
| `@pol-studios/hooks/debug` | Debug hooks (useRenderCount, useStateTracker) |
|
|
65
|
+
| `@pol-studios/hooks/utils` | Utilities (withComponentMemo, isDevEnvironment) |
|
|
66
|
+
|
|
67
|
+
## API Reference
|
|
68
|
+
|
|
69
|
+
### State Hooks
|
|
70
|
+
|
|
71
|
+
#### usePartialState
|
|
72
|
+
Partial state updates without spreading.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { usePartialState } from "@pol-studios/hooks/state";
|
|
76
|
+
|
|
77
|
+
const [state, updateState] = usePartialState({ name: "", email: "" });
|
|
78
|
+
updateState({ name: "John" }); // Only updates name, keeps email
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### useQueuedState
|
|
82
|
+
Queue state updates for batching.
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { useQueuedState } from "@pol-studios/hooks/state";
|
|
86
|
+
|
|
87
|
+
const [state, queueUpdate, flush] = useQueuedState(initialState);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### useDelayedValue
|
|
91
|
+
Debounce value changes.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { useDelayedValue, useDelayedState } from "@pol-studios/hooks/state";
|
|
95
|
+
|
|
96
|
+
const debouncedSearch = useDelayedValue(searchTerm, 300);
|
|
97
|
+
const [value, setValue, debouncedValue] = useDelayedState("", 300);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### useChangeTracking
|
|
101
|
+
Track changes to state values.
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { useChangeTracking, ChangeTrackingProvider } from "@pol-studios/hooks/state";
|
|
105
|
+
|
|
106
|
+
const { hasChanges, trackChange, resetChanges } = useChangeTracking();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Storage Hooks
|
|
110
|
+
|
|
111
|
+
#### useLocalStorage
|
|
112
|
+
Persist state to localStorage.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { useLocalStorage, useLocalStorageState } from "@pol-studios/hooks/storage";
|
|
116
|
+
|
|
117
|
+
const [value, setValue] = useLocalStorage("key", defaultValue);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### useSessionStorage
|
|
121
|
+
Persist state to sessionStorage.
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { useSessionStorage } from "@pol-studios/hooks/storage";
|
|
125
|
+
|
|
126
|
+
const [value, setValue] = useSessionStorage("key", defaultValue);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### useIndexedDB
|
|
130
|
+
Interact with IndexedDB.
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { useIndexedDB, IndexedDBService } from "@pol-studios/hooks/storage";
|
|
134
|
+
|
|
135
|
+
const db = useIndexedDB({ dbName: "myDb", storeName: "myStore" });
|
|
136
|
+
await db.set("key", value);
|
|
137
|
+
const data = await db.get("key");
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Device Hooks
|
|
141
|
+
|
|
142
|
+
#### useMobile
|
|
143
|
+
Detect mobile devices.
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { useMobile, useIsMobile } from "@pol-studios/hooks/device";
|
|
147
|
+
|
|
148
|
+
const isMobile = useMobile();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### useTheme
|
|
152
|
+
Detect and manage theme preference.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { useTheme, useThemeDetector } from "@pol-studios/hooks/device";
|
|
156
|
+
|
|
157
|
+
const theme = useThemeDetector(); // "light" | "dark"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### useDimensions
|
|
161
|
+
Track element dimensions.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { useDimensions, useWindowDimensions } from "@pol-studios/hooks/device";
|
|
165
|
+
|
|
166
|
+
const [ref, dimensions] = useDimensions();
|
|
167
|
+
const { width, height } = useWindowDimensions();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### useReducedMotion
|
|
171
|
+
Respect user motion preferences.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { useReducedMotion } from "@pol-studios/hooks/device";
|
|
175
|
+
|
|
176
|
+
const prefersReducedMotion = useReducedMotion();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Network Hooks
|
|
180
|
+
|
|
181
|
+
#### useOnline
|
|
182
|
+
Check online status.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { useOnline, useNetworkStatus } from "@pol-studios/hooks/network";
|
|
186
|
+
|
|
187
|
+
const isOnline = useOnline();
|
|
188
|
+
const { online, effectiveType } = useNetworkStatus();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### useMutationQueue
|
|
192
|
+
Queue mutations for offline support.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { useMutationQueue } from "@pol-studios/hooks/network";
|
|
196
|
+
|
|
197
|
+
const { queue, addMutation, processMutations } = useMutationQueue();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Scroll Hooks
|
|
201
|
+
|
|
202
|
+
#### useScrollPosition
|
|
203
|
+
Track scroll position.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
import { useScrollPosition, useScrollDirection } from "@pol-studios/hooks/scroll";
|
|
207
|
+
|
|
208
|
+
const scrollY = useScrollPosition();
|
|
209
|
+
const direction = useScrollDirection(); // "up" | "down"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### useHideOnScroll
|
|
213
|
+
Hide elements on scroll down.
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { useHideOnScroll } from "@pol-studios/hooks/scroll";
|
|
217
|
+
|
|
218
|
+
const isHidden = useHideOnScroll();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Lifecycle Hooks
|
|
222
|
+
|
|
223
|
+
#### useMounted
|
|
224
|
+
Check if component is mounted.
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { useMounted, useAfterMount } from "@pol-studios/hooks/lifecycle";
|
|
228
|
+
|
|
229
|
+
const isMounted = useMounted();
|
|
230
|
+
|
|
231
|
+
useAfterMount(() => {
|
|
232
|
+
// Runs after first render
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### useOnScreen
|
|
237
|
+
Detect element visibility.
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { useOnScreen } from "@pol-studios/hooks/lifecycle";
|
|
241
|
+
|
|
242
|
+
const [ref, isVisible] = useOnScreen({ threshold: 0.5 });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### File Hooks
|
|
246
|
+
|
|
247
|
+
#### useFileDialog
|
|
248
|
+
Open file picker dialog.
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { useFileDialog } from "@pol-studios/hooks/file";
|
|
252
|
+
|
|
253
|
+
const { openDialog, files } = useFileDialog({ accept: "image/*" });
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### useDownload
|
|
257
|
+
Download files programmatically.
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
import { useDownload, useDownloadApiFile } from "@pol-studios/hooks/file";
|
|
261
|
+
|
|
262
|
+
const download = useDownload();
|
|
263
|
+
download(blob, "filename.pdf");
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Toast Hooks
|
|
267
|
+
|
|
268
|
+
#### useToast
|
|
269
|
+
Show toast notifications.
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import { useToast, toast } from "@pol-studios/hooks/toast";
|
|
273
|
+
|
|
274
|
+
const { toast: showToast, dismiss } = useToast();
|
|
275
|
+
|
|
276
|
+
// Imperative API
|
|
277
|
+
toast({ title: "Success!", description: "Operation completed." });
|
|
278
|
+
|
|
279
|
+
// Hook API
|
|
280
|
+
showToast({ title: "Hello", variant: "success" });
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Form Hooks
|
|
284
|
+
|
|
285
|
+
#### OnValueChangedContext
|
|
286
|
+
Track form value changes.
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import {
|
|
290
|
+
OnValueChangedContextProvider,
|
|
291
|
+
OnValueChangedContext,
|
|
292
|
+
} from "@pol-studios/hooks/form";
|
|
293
|
+
|
|
294
|
+
<OnValueChangedContextProvider onTrigger={handleFieldChange}>
|
|
295
|
+
<MyForm />
|
|
296
|
+
</OnValueChangedContextProvider>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Debug Hooks
|
|
300
|
+
|
|
301
|
+
#### useRenderCount
|
|
302
|
+
Count component renders (dev only).
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import { useRenderCount, useStateTracker } from "@pol-studios/hooks/debug";
|
|
306
|
+
|
|
307
|
+
useRenderCount("MyComponent"); // Logs render count
|
|
308
|
+
|
|
309
|
+
useStateTracker(state, "myState"); // Logs state changes
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Utilities
|
|
313
|
+
|
|
314
|
+
#### withComponentMemo
|
|
315
|
+
HOC for memoizing components.
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
import { withComponentMemo } from "@pol-studios/hooks/utils";
|
|
319
|
+
|
|
320
|
+
const MemoizedComponent = withComponentMemo(MyComponent);
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## TypeScript Types
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
import type {
|
|
327
|
+
// Toast types
|
|
328
|
+
ToasterToast,
|
|
329
|
+
Toast,
|
|
330
|
+
ToastState,
|
|
331
|
+
ToastAction,
|
|
332
|
+
|
|
333
|
+
// Network types
|
|
334
|
+
NetworkStatus,
|
|
335
|
+
OnlineStatus,
|
|
336
|
+
QueuedMutation,
|
|
337
|
+
|
|
338
|
+
// Storage types
|
|
339
|
+
StorageService,
|
|
340
|
+
IndexDbService,
|
|
341
|
+
DBOptions,
|
|
342
|
+
|
|
343
|
+
// Form types
|
|
344
|
+
ValueChangeTrigger,
|
|
345
|
+
OnValueChangedContextValue,
|
|
346
|
+
} from "@pol-studios/hooks";
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Related Packages
|
|
350
|
+
|
|
351
|
+
- [@pol-studios/utils](../utils) - Utility functions
|
|
352
|
+
- [@pol-studios/features](../features) - Feature modules
|
|
353
|
+
- [@pol-studios/ui](../ui) - UI components
|
|
354
|
+
|
|
355
|
+
## License
|
|
356
|
+
|
|
357
|
+
UNLICENSED
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React__default, { ComponentType } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a value is usable (not undefined, not null, and not NaN if it's a number)
|
|
5
|
+
*/
|
|
6
|
+
declare function isUsable(value: any): value is {};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks if the current environment is development mode
|
|
10
|
+
*/
|
|
11
|
+
declare function isDevEnvironment(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Alias for isDevEnvironment
|
|
14
|
+
*/
|
|
15
|
+
declare function isDev(): boolean;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* JSON reviver function that converts ISO date strings to Moment objects
|
|
19
|
+
*/
|
|
20
|
+
declare function dateReviver(key: any, value: any): any;
|
|
21
|
+
/**
|
|
22
|
+
* JSON reviver function that converts ISO date strings to native Date objects
|
|
23
|
+
*/
|
|
24
|
+
declare function parseWithDate(key: any, value: any): any;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Downloads a file using POST request
|
|
28
|
+
*/
|
|
29
|
+
declare function getFilePost(url: string, fileName: string, queryParams: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Downloads a file using GET request
|
|
32
|
+
*/
|
|
33
|
+
declare function getFile(url: string | Request, fileName: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Downloads text content as a file
|
|
36
|
+
*/
|
|
37
|
+
declare function downloadFile(text: string): Promise<void>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Checks if the app is running as a PWA (Progressive Web App)
|
|
41
|
+
*/
|
|
42
|
+
declare function isPwaLaunched(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Checks if the current device is an iPhone
|
|
45
|
+
*/
|
|
46
|
+
declare function isIphone(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Checks if the device has a camera available
|
|
49
|
+
*/
|
|
50
|
+
declare function hasCameraAsync(): Promise<boolean>;
|
|
51
|
+
|
|
52
|
+
declare function withComponentMemo<T extends ComponentType<any>>(Component: T, compareFn?: (prevProps: React__default.ComponentProps<T>, nextProps: React__default.ComponentProps<T>) => boolean): T;
|
|
53
|
+
|
|
54
|
+
export { dateReviver, downloadFile, getFile, getFilePost, hasCameraAsync, isDev, isDevEnvironment, isIphone, isPwaLaunched, isUsable, parseWithDate, withComponentMemo };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug hook that tracks how many times a component has rendered.
|
|
3
|
+
* Useful for debugging unnecessary re-renders.
|
|
4
|
+
*
|
|
5
|
+
* @returns The current render count
|
|
6
|
+
*/
|
|
7
|
+
declare const useRenderCount: () => number;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Debug hook that tracks how many times a specific hook's value has changed.
|
|
11
|
+
* Useful for debugging when a dependency is causing unnecessary updates.
|
|
12
|
+
*
|
|
13
|
+
* @param hook - The hook value to track changes on
|
|
14
|
+
* @returns The number of times the hook value has changed
|
|
15
|
+
*/
|
|
16
|
+
declare const useRenderHookCount: <T>(hook: T) => number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Debug hook that logs state changes to the console.
|
|
20
|
+
* Only runs in development environment.
|
|
21
|
+
*
|
|
22
|
+
* @param state - The state value to track
|
|
23
|
+
*/
|
|
24
|
+
declare function useStateTracker<T>(state: T): void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Debug hook that provides useState with detailed logging of value changes.
|
|
28
|
+
* Logs the old value, new value, and stack trace when state changes.
|
|
29
|
+
*
|
|
30
|
+
* @param initialValue - Initial state value
|
|
31
|
+
* @param hookName - Name to identify this state in logs
|
|
32
|
+
* @returns Tuple of [state, setState]
|
|
33
|
+
*/
|
|
34
|
+
declare function useTrackedState<T>(initialValue: T, hookName: string): [T, (value: React.SetStateAction<T>) => void];
|
|
35
|
+
|
|
36
|
+
export { useRenderCount, useRenderHookCount, useStateTracker, useTrackedState };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
interface DeviceInfo {
|
|
4
|
+
isMobile: boolean;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
isPwa: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook to get device information including viewport size, mobile status, and PWA status.
|
|
11
|
+
* Combines useWindowDimensions, useMobile, and isPwaLaunched for a complete device context.
|
|
12
|
+
*
|
|
13
|
+
* @returns Object containing isMobile, width, height, and isPwa status
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const { isMobile, width, height, isPwa } = useDevice();
|
|
18
|
+
*
|
|
19
|
+
* if (isPwa) {
|
|
20
|
+
* // Show PWA-specific features
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function useDevice(): DeviceInfo;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Hook to detect if the current viewport is mobile-sized.
|
|
28
|
+
* Uses a media query listener for responsive updates.
|
|
29
|
+
*
|
|
30
|
+
* @returns true if viewport width is less than 768px, false otherwise
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const isMobile = useMobile();
|
|
35
|
+
*
|
|
36
|
+
* return isMobile ? <MobileNav /> : <DesktopNav />;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
declare function useMobile(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use `useMobile` instead. This alias is provided for backwards compatibility.
|
|
42
|
+
*/
|
|
43
|
+
declare const useIsMobile: typeof useMobile;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Hook to detect and apply the user's preferred color scheme (dark/light mode).
|
|
47
|
+
* Automatically listens for system preference changes and updates the document.
|
|
48
|
+
*
|
|
49
|
+
* @returns true if dark theme is active, false for light theme
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* const isDarkTheme = useTheme();
|
|
54
|
+
*
|
|
55
|
+
* return (
|
|
56
|
+
* <div className={isDarkTheme ? 'bg-gray-900' : 'bg-white'}>
|
|
57
|
+
* Content
|
|
58
|
+
* </div>
|
|
59
|
+
* );
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function useTheme(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* @deprecated Use `useTheme` instead. This alias is provided for backwards compatibility.
|
|
65
|
+
*/
|
|
66
|
+
declare const useThemeDetector: typeof useTheme;
|
|
67
|
+
|
|
68
|
+
interface Dimensions {
|
|
69
|
+
width: number;
|
|
70
|
+
height: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Hook to get the dimensions of a DOM element.
|
|
74
|
+
*
|
|
75
|
+
* Note: This is a naive implementation - for production use, consider attaching
|
|
76
|
+
* a resize observer. Also uses ref/effect instead of state/layoutEffect,
|
|
77
|
+
* so dimensions won't be available on initial render.
|
|
78
|
+
*
|
|
79
|
+
* @param ref - React ref to the element to measure
|
|
80
|
+
* @returns Object containing width and height of the element
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
85
|
+
* const { width, height } = useDimensions(containerRef);
|
|
86
|
+
*
|
|
87
|
+
* return (
|
|
88
|
+
* <div ref={containerRef}>
|
|
89
|
+
* Size: {width}x{height}
|
|
90
|
+
* </div>
|
|
91
|
+
* );
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function useDimensions(ref: RefObject<HTMLElement>): Dimensions;
|
|
95
|
+
|
|
96
|
+
interface WindowDimensions {
|
|
97
|
+
width: number;
|
|
98
|
+
height: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Hook to get the current window dimensions.
|
|
102
|
+
* Updates automatically when the window is resized.
|
|
103
|
+
*
|
|
104
|
+
* @returns Object containing current window width and height
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```tsx
|
|
108
|
+
* const { width, height } = useWindowDimensions();
|
|
109
|
+
*
|
|
110
|
+
* return <div>Window size: {width}x{height}</div>;
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
declare function useWindowDimensions(): WindowDimensions;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Hook to detect if the user prefers reduced motion.
|
|
117
|
+
* Checks both the CSS media query and localStorage preference (if set).
|
|
118
|
+
*
|
|
119
|
+
* @returns true if reduced motion is preferred, false otherwise
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```tsx
|
|
123
|
+
* const prefersReducedMotion = useReducedMotion();
|
|
124
|
+
*
|
|
125
|
+
* <motion.div
|
|
126
|
+
* animate={{ opacity: prefersReducedMotion ? 1 : 0 }}
|
|
127
|
+
* transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
|
|
128
|
+
* />
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function useReducedMotion(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Set a user preference for reduced motion (overrides system preference).
|
|
134
|
+
*
|
|
135
|
+
* @param enabled - true to enable reduced motion, false to disable, null to use system preference
|
|
136
|
+
*/
|
|
137
|
+
declare function setReducedMotionPreference(enabled: boolean | null): void;
|
|
138
|
+
|
|
139
|
+
export { setReducedMotionPreference, useDevice, useDimensions, useIsMobile, useMobile, useReducedMotion, useTheme, useThemeDetector, useWindowDimensions };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook that provides a function to open a file dialog programmatically.
|
|
3
|
+
*
|
|
4
|
+
* @returns Object containing openFileDialog function
|
|
5
|
+
*/
|
|
6
|
+
declare function useFileDialog(): {
|
|
7
|
+
openFileDialog: () => Promise<FileList>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
interface DownloadOptions {
|
|
11
|
+
url: string;
|
|
12
|
+
fileName: string;
|
|
13
|
+
queryParams: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook that provides a function to download files via POST request.
|
|
17
|
+
*
|
|
18
|
+
* @returns Download function
|
|
19
|
+
*/
|
|
20
|
+
declare function useDownload(): ({ url, fileName, queryParams }: DownloadOptions) => Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated Use useDownload instead
|
|
23
|
+
*/
|
|
24
|
+
declare const useDownloadApiFile: typeof useDownload;
|
|
25
|
+
|
|
26
|
+
export { useDownload, useDownloadApiFile, useFileDialog };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
type ValueChangeTrigger = "change" | "blur" | number;
|
|
6
|
+
interface OnValueChangedContextValue {
|
|
7
|
+
trigger: ValueChangeTrigger;
|
|
8
|
+
}
|
|
9
|
+
declare const OnValueChangedContext: React.Context<OnValueChangedContextValue>;
|
|
10
|
+
interface OnValueChangedContextProviderProps {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
trigger: ValueChangeTrigger;
|
|
13
|
+
}
|
|
14
|
+
declare const OnValueChangedContextProvider: ({ children, trigger, }: OnValueChangedContextProviderProps) => react_jsx_runtime.JSX.Element;
|
|
15
|
+
/** @deprecated Use OnValueChangedContext instead */
|
|
16
|
+
declare const OnValueChangedTriggerContext: React.Context<OnValueChangedContextValue>;
|
|
17
|
+
/** @deprecated Use OnValueChangedContextProvider instead */
|
|
18
|
+
declare const OnValueChangedTriggerContextProvider: ({ children, trigger, }: OnValueChangedContextProviderProps) => react_jsx_runtime.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { OnValueChangedContext, OnValueChangedContextProvider, type OnValueChangedContextProviderProps, type OnValueChangedContextValue, OnValueChangedTriggerContext, OnValueChangedTriggerContextProvider, type ValueChangeTrigger };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { ChangeTrackingContext, ChangeTrackingProvider, useChangeTracking, useDelayedState, useDelayedValue, useForceUpdate, usePartialState, useQueuedState } from './state/index.js';
|
|
2
|
+
export { DBOptions, IndexedDBService as IndexDb, IndexDbProvider, IndexDbService, IndexedDBService, LocalStorageProvider, LocalStorageService, StorageService, indexDbContext, localStorageContext, useIndexedDB as useIndexDbService, useIndexedDB, useLocalStorage, useLocalStorageService, useLocalStorageState, useQueuedLocalStorage, useQueuedLocalStorageState, useSessionStorage, useSessionStorageState } from './storage/index.js';
|
|
3
|
+
export { useAfterMountedEffect as useAfterMount, useAfterMountedEffect, useMounted, useOnScreen } from './lifecycle/index.js';
|
|
4
|
+
export { setReducedMotionPreference, useDevice, useDimensions, useIsMobile, useMobile, useReducedMotion, useTheme, useThemeDetector, useWindowDimensions } from './device/index.js';
|
|
5
|
+
export { useDownload, useDownloadApiFile, useFileDialog } from './file/index.js';
|
|
6
|
+
export { OnValueChangedContext, OnValueChangedContextProvider, OnValueChangedContextProviderProps, OnValueChangedContextValue, OnValueChangedTriggerContext, OnValueChangedTriggerContextProvider, ValueChangeTrigger } from './form/index.js';
|
|
7
|
+
export { ActionType, Toast, ToastAction, ToastState, ToasterToast, actionTypes, reducer, toast, useToast } from './toast/index.js';
|
|
8
|
+
export { useHideOnScroll, useHidingOnScroll, useScrollDirection, useScrollPosition, useScrollRestoration } from './scroll/index.js';
|
|
9
|
+
export { NetworkStatus, NetworkStatus as OnlineStatus, QueuedMutation, useMutationQueue, useNetworkStatus, useOnline } from './network/index.js';
|
|
10
|
+
export { useRenderCount, useRenderHookCount, useStateTracker, useTrackedState } from './debug/index.js';
|
|
11
|
+
export { dateReviver, downloadFile, getFile, getFilePost, hasCameraAsync, isDev, isDevEnvironment, isIphone, isPwaLaunched, isUsable, parseWithDate, withComponentMemo } from './_utils/index.js';
|
|
12
|
+
export { CommentProvider as CommentSectionProvider, FilterProvider, genId, getComparisonOptions, getDefaultCondition, getDefaultValue, useComments as useCommentSection, useFilterContext, useOrderManager as useOrderHintOld } from '@pol-studios/features';
|
|
13
|
+
import 'react';
|
|
14
|
+
import 'react/jsx-runtime';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook that returns a function to check if the component is currently mounted.
|
|
5
|
+
* Useful for avoiding state updates after unmount in async operations.
|
|
6
|
+
*
|
|
7
|
+
* @returns A function that returns true if mounted, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
declare function useMounted(): () => boolean;
|
|
10
|
+
|
|
11
|
+
declare function useAfterMountedEffect(effect: React__default.EffectCallback, deps?: React__default.DependencyList): void;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Hook that detects if an element is visible in the viewport using IntersectionObserver.
|
|
15
|
+
*
|
|
16
|
+
* @param ref - React ref to the element to observe
|
|
17
|
+
* @param rootMargin - Margin around the root (default: "0px")
|
|
18
|
+
* @returns boolean indicating if element is visible
|
|
19
|
+
*/
|
|
20
|
+
declare function useOnScreen(ref: React.RefObject<HTMLElement>, rootMargin?: string): boolean;
|
|
21
|
+
|
|
22
|
+
export { useAfterMountedEffect as useAfterMount, useAfterMountedEffect, useMounted, useOnScreen };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
interface NetworkStatus {
|
|
2
|
+
isOnline: boolean;
|
|
3
|
+
isOffline: boolean;
|
|
4
|
+
wasOffline: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Hook to track network status across platforms.
|
|
8
|
+
* Works with TanStack Query's onlineManager for consistent offline handling.
|
|
9
|
+
*
|
|
10
|
+
* @returns Object with isOnline, isOffline, and wasOffline status
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const { isOnline, isOffline, wasOffline } = useOnline();
|
|
15
|
+
*
|
|
16
|
+
* if (isOffline) {
|
|
17
|
+
* return <OfflineBanner />;
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* if (wasOffline) {
|
|
21
|
+
* // Show "back online" notification
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function useOnline(): NetworkStatus;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use `useOnline` instead. This alias is provided for backwards compatibility.
|
|
28
|
+
*/
|
|
29
|
+
declare const useNetworkStatus: typeof useOnline;
|
|
30
|
+
|
|
31
|
+
interface QueuedMutation {
|
|
32
|
+
id: string;
|
|
33
|
+
mutationKey: string[];
|
|
34
|
+
mutationFn: () => Promise<any>;
|
|
35
|
+
variables: any;
|
|
36
|
+
timestamp: number;
|
|
37
|
+
retryCount: number;
|
|
38
|
+
error?: Error;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Hook to manage offline mutation queue.
|
|
42
|
+
* Queues mutations when offline and automatically retries when back online.
|
|
43
|
+
*
|
|
44
|
+
* Note: Currently stores mutations in memory only. Functions cannot be serialized,
|
|
45
|
+
* so mutations are lost on page refresh. Future enhancement: store mutation parameters
|
|
46
|
+
* and recreate mutations on retry.
|
|
47
|
+
*
|
|
48
|
+
* @returns Object with queue management functions and state
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* const {
|
|
53
|
+
* queueMutation,
|
|
54
|
+
* queuedMutations,
|
|
55
|
+
* queueCount,
|
|
56
|
+
* clearQueue
|
|
57
|
+
* } = useMutationQueue();
|
|
58
|
+
*
|
|
59
|
+
* // Queue a mutation for offline execution
|
|
60
|
+
* queueMutation(
|
|
61
|
+
* ['updateUser', userId],
|
|
62
|
+
* () => api.updateUser(userId, data),
|
|
63
|
+
* data
|
|
64
|
+
* );
|
|
65
|
+
*
|
|
66
|
+
* // Show pending count
|
|
67
|
+
* <Badge>{queueCount} pending</Badge>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function useMutationQueue(): {
|
|
71
|
+
queuedMutations: QueuedMutation[];
|
|
72
|
+
queueMutation: (mutationKey: string[], mutationFn: () => Promise<any>, variables: any) => void;
|
|
73
|
+
removeQueuedMutation: (id: string) => void;
|
|
74
|
+
clearQueue: () => void;
|
|
75
|
+
processQueue: () => Promise<void>;
|
|
76
|
+
queueCount: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { type NetworkStatus, type NetworkStatus as OnlineStatus, type QueuedMutation, useMutationQueue, useNetworkStatus, useOnline };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React__default, { RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ScrollPosition {
|
|
4
|
+
scrollY: number;
|
|
5
|
+
scrollHeight: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Hook to track scroll position of an element or the window.
|
|
9
|
+
*
|
|
10
|
+
* @param elementRef - Optional ref to a scrollable element. If not provided, tracks window scroll.
|
|
11
|
+
* @returns Object containing current scrollY position and total scrollHeight
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* // Track window scroll
|
|
16
|
+
* const { scrollY, scrollHeight } = useScrollPosition();
|
|
17
|
+
*
|
|
18
|
+
* // Track element scroll
|
|
19
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
20
|
+
* const { scrollY, scrollHeight } = useScrollPosition(containerRef);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function useScrollPosition(elementRef?: RefObject<HTMLElement>): ScrollPosition;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Hook to detect the user's scroll direction.
|
|
27
|
+
*
|
|
28
|
+
* @param elementRef - Ref to the scrollable element to monitor
|
|
29
|
+
* @param threshold - Scroll position threshold for direction detection
|
|
30
|
+
* @returns true if user is scrolling up, false if scrolling down
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
* const isScrollingUp = useScrollDirection(containerRef, 100);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <div ref={containerRef}>
|
|
39
|
+
* <header className={isScrollingUp ? 'visible' : 'hidden'}>
|
|
40
|
+
* Navigation
|
|
41
|
+
* </header>
|
|
42
|
+
* </div>
|
|
43
|
+
* );
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function useScrollDirection(elementRef: RefObject<HTMLElement>, threshold: number): boolean;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Hook to save and restore scroll position using sessionStorage.
|
|
50
|
+
* Useful for maintaining scroll position when navigating away and returning to a page.
|
|
51
|
+
*
|
|
52
|
+
* @param scrollAreaId - Unique identifier for this scroll area (used as storage key)
|
|
53
|
+
* @param ref - Optional ref to a scrollable element. If not provided, uses window scroll.
|
|
54
|
+
* @returns The restored scroll position (or NaN if none was saved)
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```tsx
|
|
58
|
+
* // Restore window scroll
|
|
59
|
+
* useScrollRestoration("my-page");
|
|
60
|
+
*
|
|
61
|
+
* // Restore element scroll
|
|
62
|
+
* const containerRef = useRef<HTMLDivElement>(null);
|
|
63
|
+
* useScrollRestoration("my-list", containerRef);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function useScrollRestoration(scrollAreaId?: string, ref?: React__default.RefObject<any>): number;
|
|
67
|
+
|
|
68
|
+
interface UseHideOnScrollProps {
|
|
69
|
+
height: number;
|
|
70
|
+
scrollRef?: React.MutableRefObject<HTMLElement>;
|
|
71
|
+
initialPercentVisible?: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Hook to create a hide-on-scroll effect, typically used for headers/navigation.
|
|
75
|
+
* Returns the percent visibility (0-1) that can be used to animate the element.
|
|
76
|
+
*
|
|
77
|
+
* @param props.height - The height of the element being hidden
|
|
78
|
+
* @param props.scrollRef - Optional ref to a scrollable element. Uses window if not provided.
|
|
79
|
+
* @param props.initialPercentVisible - Initial visibility (default: 1, fully visible)
|
|
80
|
+
* @returns Percent visible from 0 to 1
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* const percentVisible = useHideOnScroll({ height: 64 });
|
|
85
|
+
*
|
|
86
|
+
* return (
|
|
87
|
+
* <motion.header
|
|
88
|
+
* style={{ transform: `translateY(${(1 - percentVisible) * -100}%)` }}
|
|
89
|
+
* >
|
|
90
|
+
* Navigation
|
|
91
|
+
* </motion.header>
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
declare function useHideOnScroll({ height, scrollRef, initialPercentVisible }: UseHideOnScrollProps): number;
|
|
96
|
+
/**
|
|
97
|
+
* @deprecated Use `useHideOnScroll` instead. This alias is provided for backwards compatibility.
|
|
98
|
+
*/
|
|
99
|
+
declare const useHidingOnScroll: typeof useHideOnScroll;
|
|
100
|
+
|
|
101
|
+
export { useHideOnScroll, useHidingOnScroll, useScrollDirection, useScrollPosition, useScrollRestoration };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
declare function usePartialState<T>(initialState: T): {
|
|
6
|
+
state: T;
|
|
7
|
+
patch: (newProps: Partial<T>) => void;
|
|
8
|
+
setState: React$1.Dispatch<React$1.SetStateAction<T>>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
declare function useQueuedState<T>(initialState: T): [
|
|
12
|
+
T,
|
|
13
|
+
(updateFn: React.SetStateAction<T>) => void
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
declare function useDelayedValue<T>(value: T, delayInMs: number): T;
|
|
17
|
+
/** @deprecated Use useDelayedValue instead */
|
|
18
|
+
declare const useDelayedState: typeof useDelayedValue;
|
|
19
|
+
|
|
20
|
+
declare function useChangeTracking<T>(initialValue: T): {
|
|
21
|
+
initialValue: T;
|
|
22
|
+
update: (newProps: Partial<T>) => void;
|
|
23
|
+
value: T;
|
|
24
|
+
propertiesChanged: Set<string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
declare function useForceUpdate(): () => void;
|
|
28
|
+
|
|
29
|
+
interface ChangeTrackingContextValue {
|
|
30
|
+
initialValue: any;
|
|
31
|
+
value: any;
|
|
32
|
+
onChange: (newValue: Partial<any>) => void;
|
|
33
|
+
propertiesChanged: Set<any>;
|
|
34
|
+
}
|
|
35
|
+
declare const ChangeTrackingContext: React__default.Context<ChangeTrackingContextValue>;
|
|
36
|
+
declare function ChangeTrackingProvider({ children, initialValue }: {
|
|
37
|
+
children: React__default.ReactNode;
|
|
38
|
+
initialValue?: any;
|
|
39
|
+
}): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { ChangeTrackingContext, ChangeTrackingProvider, useChangeTracking, useDelayedState, useDelayedValue, useForceUpdate, usePartialState, useQueuedState };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default, { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
declare function useLocalStorage<T>(key: string, initialValue?: T | (() => T) | undefined): [T | undefined, (value: React.SetStateAction<T>) => void, boolean];
|
|
5
|
+
/** @deprecated Use useLocalStorage instead */
|
|
6
|
+
declare const useLocalStorageState: typeof useLocalStorage;
|
|
7
|
+
|
|
8
|
+
declare function useSessionStorage<T>(key: string, initialValue?: T): [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>];
|
|
9
|
+
/** @deprecated Use useSessionStorage instead */
|
|
10
|
+
declare const useSessionStorageState: typeof useSessionStorage;
|
|
11
|
+
|
|
12
|
+
interface StorageService {
|
|
13
|
+
getItem<T>(key: string): Promise<T | null>;
|
|
14
|
+
setItem<T>(key: string, value: T): Promise<void>;
|
|
15
|
+
removeItem(key: string): void;
|
|
16
|
+
addItemChangeListener(key: string, handler: (event: {
|
|
17
|
+
key: string;
|
|
18
|
+
newValue: string;
|
|
19
|
+
}) => any): any;
|
|
20
|
+
removeItemChangeListener(key: string, handler: any): any;
|
|
21
|
+
}
|
|
22
|
+
declare const localStorageContext: React__default.Context<StorageService>;
|
|
23
|
+
declare function LocalStorageProvider({ children, value, }: {
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
value: StorageService;
|
|
26
|
+
}): react_jsx_runtime.JSX.Element;
|
|
27
|
+
interface IndexDbService {
|
|
28
|
+
getItem<T = any>(key: string): Promise<T | null>;
|
|
29
|
+
setItem<T = any>(key: string, value: T): Promise<void>;
|
|
30
|
+
removeItem(key: string): Promise<void>;
|
|
31
|
+
getAllKeys(): Promise<readonly string[]>;
|
|
32
|
+
}
|
|
33
|
+
declare const storeNames$1: readonly ["cached-urls", "metadata"];
|
|
34
|
+
type PolStoreName$1 = (typeof storeNames$1)[keyof typeof storeNames$1] & string;
|
|
35
|
+
interface DBOptions$1 {
|
|
36
|
+
dbName: string;
|
|
37
|
+
storeName: PolStoreName$1;
|
|
38
|
+
}
|
|
39
|
+
declare const indexDbContext: React__default.Context<{
|
|
40
|
+
services: Map<DBOptions$1, IndexDbService>;
|
|
41
|
+
}>;
|
|
42
|
+
declare function IndexDbProvider({ children, value, }: {
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
value: Map<DBOptions$1, IndexDbService>;
|
|
45
|
+
}): react_jsx_runtime.JSX.Element;
|
|
46
|
+
|
|
47
|
+
declare function useIndexedDB(options: DBOptions$1): IndexDbService;
|
|
48
|
+
|
|
49
|
+
declare function useQueuedLocalStorage<T>(storageKey: string, initialState: T): [T, (updateFn: React.SetStateAction<T>) => void, boolean];
|
|
50
|
+
/** @deprecated Use useQueuedLocalStorage instead */
|
|
51
|
+
declare const useQueuedLocalStorageState: typeof useQueuedLocalStorage;
|
|
52
|
+
|
|
53
|
+
declare function useLocalStorageService(): StorageService;
|
|
54
|
+
|
|
55
|
+
declare class LocalStorageService implements StorageService {
|
|
56
|
+
constructor();
|
|
57
|
+
addItemChangeListener(key: string, handler: (event: {
|
|
58
|
+
key: string;
|
|
59
|
+
newValue: string;
|
|
60
|
+
}) => any): () => void;
|
|
61
|
+
removeItemChangeListener(key: string, handler: any): void;
|
|
62
|
+
setItem<T>(key: string, value: T): Promise<void>;
|
|
63
|
+
getItem<T>(key: string): Promise<T | null>;
|
|
64
|
+
removeItem(key: string): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface DBOptions<T> {
|
|
68
|
+
dbName: string;
|
|
69
|
+
storeName: PolStoreName;
|
|
70
|
+
}
|
|
71
|
+
declare const storeNames: readonly ["cached-urls", "metadata"];
|
|
72
|
+
type PolStoreName = ((typeof storeNames)[keyof typeof storeNames]) & string;
|
|
73
|
+
declare class IndexedDBService<T> implements IndexDbService {
|
|
74
|
+
private dbName;
|
|
75
|
+
private storeName;
|
|
76
|
+
private db;
|
|
77
|
+
constructor(options: DBOptions<T>);
|
|
78
|
+
private openDB;
|
|
79
|
+
private getDB;
|
|
80
|
+
setItem<T>(key: string, record: T): Promise<void>;
|
|
81
|
+
getItem<T = any>(key: string): Promise<T | null>;
|
|
82
|
+
removeItem(key: string): Promise<void>;
|
|
83
|
+
getAllKeys(): Promise<readonly string[]>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { type DBOptions$1 as DBOptions, IndexedDBService as IndexDb, IndexDbProvider, type IndexDbService, IndexedDBService, LocalStorageProvider, LocalStorageService, type StorageService, indexDbContext, localStorageContext, useIndexedDB, useLocalStorage, useLocalStorageService, useLocalStorageState, useQueuedLocalStorage, useQueuedLocalStorageState, useSessionStorage, useSessionStorageState };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type ToasterToast = {
|
|
4
|
+
id: string;
|
|
5
|
+
title?: React.ReactNode;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
open?: boolean;
|
|
9
|
+
onOpenChange?: (open: boolean) => void;
|
|
10
|
+
} & React.HTMLAttributes<HTMLLIElement>;
|
|
11
|
+
type Toast = Omit<ToasterToast, "id">;
|
|
12
|
+
interface ToastState {
|
|
13
|
+
toasts: ToasterToast[];
|
|
14
|
+
}
|
|
15
|
+
declare const actionTypes: {
|
|
16
|
+
readonly ADD_TOAST: "ADD_TOAST";
|
|
17
|
+
readonly UPDATE_TOAST: "UPDATE_TOAST";
|
|
18
|
+
readonly DISMISS_TOAST: "DISMISS_TOAST";
|
|
19
|
+
readonly REMOVE_TOAST: "REMOVE_TOAST";
|
|
20
|
+
};
|
|
21
|
+
type ActionType = typeof actionTypes;
|
|
22
|
+
type ToastAction = {
|
|
23
|
+
type: ActionType["ADD_TOAST"];
|
|
24
|
+
toast: ToasterToast;
|
|
25
|
+
} | {
|
|
26
|
+
type: ActionType["UPDATE_TOAST"];
|
|
27
|
+
toast: Partial<ToasterToast>;
|
|
28
|
+
} | {
|
|
29
|
+
type: ActionType["DISMISS_TOAST"];
|
|
30
|
+
toastId?: ToasterToast["id"];
|
|
31
|
+
} | {
|
|
32
|
+
type: ActionType["REMOVE_TOAST"];
|
|
33
|
+
toastId?: ToasterToast["id"];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
declare const reducer: (state: ToastState, action: ToastAction) => ToastState;
|
|
37
|
+
declare function toast({ ...props }: Toast): {
|
|
38
|
+
id: string;
|
|
39
|
+
dismiss: () => void;
|
|
40
|
+
update: (props: ToasterToast) => void;
|
|
41
|
+
};
|
|
42
|
+
declare function useToast(): {
|
|
43
|
+
toast: typeof toast;
|
|
44
|
+
dismiss: (toastId?: string) => void;
|
|
45
|
+
toasts: ToasterToast[];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export { type ActionType, type Toast, type ToastAction, type ToastState, type ToasterToast, actionTypes, useToast as default, reducer, toast, useToast };
|
package/package.json
CHANGED
|
@@ -1,30 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pol-studios/hooks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "React hooks for POL applications",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
-
"files": [
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
10
12
|
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"./
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"./
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./state": {
|
|
18
|
+
"import": "./dist/state/index.js",
|
|
19
|
+
"types": "./dist/state/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./scroll": {
|
|
22
|
+
"import": "./dist/scroll/index.js",
|
|
23
|
+
"types": "./dist/scroll/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./storage": {
|
|
26
|
+
"import": "./dist/storage/index.js",
|
|
27
|
+
"types": "./dist/storage/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./device": {
|
|
30
|
+
"import": "./dist/device/index.js",
|
|
31
|
+
"types": "./dist/device/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./network": {
|
|
34
|
+
"import": "./dist/network/index.js",
|
|
35
|
+
"types": "./dist/network/index.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./lifecycle": {
|
|
38
|
+
"import": "./dist/lifecycle/index.js",
|
|
39
|
+
"types": "./dist/lifecycle/index.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./file": {
|
|
42
|
+
"import": "./dist/file/index.js",
|
|
43
|
+
"types": "./dist/file/index.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./toast": {
|
|
46
|
+
"import": "./dist/toast/index.js",
|
|
47
|
+
"types": "./dist/toast/index.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./form": {
|
|
50
|
+
"import": "./dist/form/index.js",
|
|
51
|
+
"types": "./dist/form/index.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"./debug": {
|
|
54
|
+
"import": "./dist/debug/index.js",
|
|
55
|
+
"types": "./dist/debug/index.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"./utils": {
|
|
58
|
+
"import": "./dist/_utils/index.js",
|
|
59
|
+
"types": "./dist/_utils/index.d.ts"
|
|
60
|
+
}
|
|
28
61
|
},
|
|
29
62
|
"publishConfig": {
|
|
30
63
|
"access": "public"
|
|
@@ -41,10 +74,20 @@
|
|
|
41
74
|
"lodash": "^4.17.21"
|
|
42
75
|
},
|
|
43
76
|
"devDependencies": {
|
|
44
|
-
"@pol-studios/features": "workspace:*",
|
|
45
|
-
"@pol-studios/utils": "workspace:*",
|
|
46
77
|
"tsup": "^8.0.0",
|
|
47
|
-
"typescript": "^5.0.0"
|
|
78
|
+
"typescript": "^5.0.0",
|
|
79
|
+
"@pol-studios/features": "1.0.1",
|
|
80
|
+
"@pol-studios/utils": "1.0.1"
|
|
48
81
|
},
|
|
49
|
-
"keywords": [
|
|
50
|
-
|
|
82
|
+
"keywords": [
|
|
83
|
+
"hooks",
|
|
84
|
+
"react",
|
|
85
|
+
"state",
|
|
86
|
+
"storage",
|
|
87
|
+
"toast"
|
|
88
|
+
],
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsup",
|
|
91
|
+
"dev": "tsup --watch"
|
|
92
|
+
}
|
|
93
|
+
}
|