@bigbinary/neeto-commons-frontend 2.1.5 → 2.1.7
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 +104 -94
- package/configs/scripts/jsdoc-builder/constants.mjs +1 -1
- package/configs/scripts/jsdoc-builder/utils.mjs +4 -3
- package/cypress-utils.d.ts +2 -2
- package/initializers.cjs.js +11 -2
- package/initializers.cjs.js.map +1 -1
- package/initializers.d.ts +7 -5
- package/initializers.js +11 -2
- package/initializers.js.map +1 -1
- package/package.json +2 -2
- package/pure.d.ts +325 -324
- package/react-utils.d.ts +674 -153
- package/utils.cjs.js +8 -2
- package/utils.cjs.js.map +1 -1
- package/utils.d.ts +145 -44
- package/utils.js +8 -2
- package/utils.js.map +1 -1
package/react-utils.d.ts
CHANGED
|
@@ -6,7 +6,9 @@ import { StoreApi, UseBoundStore } from "zustand";
|
|
|
6
6
|
import { UseQueryOptions, UseQueryResult, UseMutationOptions, UseMutationResult } from "react-query";
|
|
7
7
|
/**
|
|
8
8
|
*
|
|
9
|
-
* ErrorBoundary which reports frontend errors
|
|
9
|
+
* The HoneybadgerErrorBoundary is an ErrorBoundary which reports frontend errors
|
|
10
|
+
*
|
|
11
|
+
* to HoneyBadger.
|
|
10
12
|
*
|
|
11
13
|
* This component will wrap its children with the error boundary provided by
|
|
12
14
|
*
|
|
@@ -53,9 +55,9 @@ export const HoneybadgerErrorBoundary: React.FC<{
|
|
|
53
55
|
}>;
|
|
54
56
|
/**
|
|
55
57
|
*
|
|
56
|
-
*
|
|
58
|
+
* PrivateRoute is a route that will restrict access to it based on a specified
|
|
57
59
|
*
|
|
58
|
-
* permissions.
|
|
60
|
+
* condition and permissions.
|
|
59
61
|
*
|
|
60
62
|
* If the given condition is true and the user has the required permissions, it
|
|
61
63
|
*
|
|
@@ -89,14 +91,22 @@ type OptionsType = {
|
|
|
89
91
|
};
|
|
90
92
|
/**
|
|
91
93
|
*
|
|
92
|
-
*
|
|
94
|
+
* The useIsElementVisibleInDom hook is a utility that allows you to determine
|
|
95
|
+
*
|
|
96
|
+
* whether a target element is currently visible within the viewport or intersects
|
|
97
|
+
*
|
|
98
|
+
* with an ancestor element. In simpler terms, it helps you know when a specified
|
|
99
|
+
*
|
|
100
|
+
* element is scrolled out of or scrolled into the screen's visible area.
|
|
93
101
|
*
|
|
94
|
-
*
|
|
102
|
+
* The following code snippet demonstrates the usage of useIsElementVisibleInDom
|
|
95
103
|
*
|
|
96
|
-
*
|
|
104
|
+
* to display the heading element.
|
|
97
105
|
*
|
|
98
106
|
* @example
|
|
99
107
|
*
|
|
108
|
+
* import { useIsElementVisibleInDom } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
109
|
+
*
|
|
100
110
|
* const ref = useRef(null);
|
|
101
111
|
* const isHeadingWrapperVisible = useIsElementVisibleInDom(ref.current, {
|
|
102
112
|
* threshold: 0.5,
|
|
@@ -113,22 +123,36 @@ type OptionsType = {
|
|
|
113
123
|
* </div>
|
|
114
124
|
* );
|
|
115
125
|
* @endexample
|
|
126
|
+
* The hook watches for changes in the visibility of the referenced div element
|
|
127
|
+
*
|
|
128
|
+
* and provides a boolean value that you can use to conditionally render the header
|
|
129
|
+
*
|
|
130
|
+
* element with the text Hello I'm on the screen.
|
|
131
|
+
*
|
|
116
132
|
*/
|
|
117
133
|
export function useIsElementVisibleInDom(target: Element | null, options?: OptionsType): Boolean;
|
|
118
134
|
/**
|
|
119
135
|
*
|
|
120
|
-
*
|
|
136
|
+
* The useDebounce hook is a utility that allows you to wrap around a frequently
|
|
121
137
|
*
|
|
122
|
-
*
|
|
138
|
+
* updating state to retrieve the previous value until the updates are halted. This
|
|
123
139
|
*
|
|
124
|
-
*
|
|
140
|
+
* is particularly useful when you want to limit the number of API calls triggered
|
|
125
141
|
*
|
|
126
|
-
*
|
|
142
|
+
* by user inputs, such as a search box. The value returned by this hook will only
|
|
127
143
|
*
|
|
128
|
-
*
|
|
144
|
+
* reflect the latest value when the hook has not been called for the specified
|
|
145
|
+
*
|
|
146
|
+
* time period delay.
|
|
147
|
+
*
|
|
148
|
+
* The following code snippet demonstrates the usage of useDebounce in a search
|
|
149
|
+
*
|
|
150
|
+
* feature.
|
|
129
151
|
*
|
|
130
152
|
* @example
|
|
131
153
|
*
|
|
154
|
+
* import { useDebounce } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
155
|
+
*
|
|
132
156
|
* const [searchKey, setSearchKey] = useState("");
|
|
133
157
|
* const debouncedSearchKey = useDebounce(searchKey, 300);
|
|
134
158
|
*
|
|
@@ -140,20 +164,58 @@ export function useIsElementVisibleInDom(target: Element | null, options?: Optio
|
|
|
140
164
|
* // component
|
|
141
165
|
* <Input onChange={e => setSearchKey(e.target.value)} />;
|
|
142
166
|
* @endexample
|
|
167
|
+
* In the case of a search box, implemented without debouncing, every keystroke
|
|
168
|
+
*
|
|
169
|
+
* typically triggers a search query to find matching results. However, this rapid
|
|
170
|
+
*
|
|
171
|
+
* succession of queries can lead to several issues like performance overhead, poor
|
|
172
|
+
*
|
|
173
|
+
* user experience and inefficient resource usage.
|
|
174
|
+
*
|
|
175
|
+
* The useDebounce hook elegantly solves these problems by delaying the execution
|
|
176
|
+
*
|
|
177
|
+
* of the search function until the user pauses typing for a specified duration.
|
|
178
|
+
*
|
|
179
|
+
* This ensures that only one API request is made for the entire search operation,
|
|
180
|
+
*
|
|
181
|
+
* which solves all the issues mentioned earlier.
|
|
182
|
+
*
|
|
183
|
+
* You can learn more about the concept of debouncing
|
|
184
|
+
*
|
|
185
|
+
* here.
|
|
186
|
+
*
|
|
143
187
|
*/
|
|
144
188
|
export function useDebounce<T>(value: T, delay?: number): T;
|
|
145
189
|
/**
|
|
146
190
|
*
|
|
147
|
-
*
|
|
191
|
+
* The useFuncDebounce hook is a utility that extends the benefits of debouncing
|
|
192
|
+
*
|
|
193
|
+
* to functions.
|
|
194
|
+
*
|
|
195
|
+
* When the debounced function is called, it sets a timer to execute the original
|
|
148
196
|
*
|
|
149
|
-
* function
|
|
197
|
+
* function after a specified delay. If the debounced function is called again
|
|
150
198
|
*
|
|
151
|
-
*
|
|
199
|
+
* before the timer expires, the previous timer is cleared. This effectively delays
|
|
152
200
|
*
|
|
153
|
-
* the
|
|
201
|
+
* the execution of the original function until the debounced function hasn't been
|
|
202
|
+
*
|
|
203
|
+
* called for the specified delay period.
|
|
204
|
+
*
|
|
205
|
+
* The hook also provides a cancel method to manually cancel the execution of the
|
|
206
|
+
*
|
|
207
|
+
* debounced function before it triggers.
|
|
208
|
+
*
|
|
209
|
+
* The following code snippet demonstrates the usage of useFuncDebounce in the
|
|
210
|
+
*
|
|
211
|
+
* delaying the invocation of the fetch method until the user pauses typing for a
|
|
212
|
+
*
|
|
213
|
+
* specific period.
|
|
154
214
|
*
|
|
155
215
|
* @example
|
|
156
216
|
*
|
|
217
|
+
* import { useFuncDebounce } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
218
|
+
*
|
|
157
219
|
* const searchForProducts = useFuncDebounce(async key => {
|
|
158
220
|
* // this function will be triggered once after user stops typing for 300ms
|
|
159
221
|
* const products = await productsApi.fetch(key);
|
|
@@ -170,18 +232,38 @@ export function useFuncDebounce<F extends Function>(func: F, delay?: number): F
|
|
|
170
232
|
};
|
|
171
233
|
/**
|
|
172
234
|
*
|
|
173
|
-
*
|
|
235
|
+
* The useLocalStorage hook is a utility for synchronizing and persisting state
|
|
174
236
|
*
|
|
175
|
-
* a
|
|
237
|
+
* in the local storage of a web browser. It allows you to maintain data across
|
|
176
238
|
*
|
|
177
|
-
*
|
|
239
|
+
* page refreshes or even when the user navigates away from the page. This is
|
|
240
|
+
*
|
|
241
|
+
* useful for storing user preferences, settings, or any other data that should
|
|
242
|
+
*
|
|
243
|
+
* persist between sessions.
|
|
244
|
+
*
|
|
245
|
+
* To remove the value from local storage we can call the setter method with null
|
|
246
|
+
*
|
|
247
|
+
* or undefined.
|
|
248
|
+
*
|
|
249
|
+
* Note: Use this hook only if you need the component to re-render while
|
|
178
250
|
*
|
|
179
251
|
* updating the local storage value. If all you need is plain read and write
|
|
180
252
|
*
|
|
181
253
|
* operations on the localStorage, prefer the vanilla localStorage API functions.
|
|
182
254
|
*
|
|
255
|
+
* This hook will return an array with exactly two values just like useState
|
|
256
|
+
*
|
|
257
|
+
* hook.
|
|
258
|
+
*
|
|
259
|
+
* The following code snippet illustrates the usage of useLocalStorage in
|
|
260
|
+
*
|
|
261
|
+
* implementing a theme-switching feature.
|
|
262
|
+
*
|
|
183
263
|
* @example
|
|
184
264
|
*
|
|
265
|
+
* import { useLocalStorage } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
266
|
+
*
|
|
185
267
|
* // here "theme" is the storage key and "light" is the initial value
|
|
186
268
|
* const [theme, setTheme] = useLocalStorage("theme", "light");
|
|
187
269
|
*
|
|
@@ -196,82 +278,168 @@ export function useFuncDebounce<F extends Function>(func: F, delay?: number): F
|
|
|
196
278
|
* />
|
|
197
279
|
* );
|
|
198
280
|
* @endexample
|
|
199
|
-
*
|
|
281
|
+
* The initial value is used when the key is not found in local storage, ensuring
|
|
200
282
|
*
|
|
201
|
-
*
|
|
283
|
+
* that a default theme is applied when the user first visits the site. Subsequent
|
|
284
|
+
*
|
|
285
|
+
* changes to the theme are automatically synchronized with local storage.
|
|
202
286
|
*
|
|
203
287
|
*/
|
|
204
288
|
export function useLocalStorage<T>(key: string, initialValue?: T): [T, (value: T) => void];
|
|
205
289
|
/**
|
|
206
290
|
*
|
|
207
|
-
*
|
|
291
|
+
* The useOnClickOutside hook is a useful utility for detecting clicks that occur
|
|
292
|
+
*
|
|
293
|
+
* outside of a specified element. It provides an elegant way to handle scenarios
|
|
294
|
+
*
|
|
295
|
+
* where you want to close or perform specific actions when a user clicks outside
|
|
296
|
+
*
|
|
297
|
+
* of a particular component, such as a modal dialog.
|
|
298
|
+
*
|
|
299
|
+
* The following code snippet demonstrates the usage of useOnClickOutside to
|
|
300
|
+
*
|
|
301
|
+
* detect clicks outside of a dropdown element and conditionally render the
|
|
302
|
+
*
|
|
303
|
+
* options.
|
|
208
304
|
*
|
|
209
305
|
* @example
|
|
210
306
|
*
|
|
211
|
-
*
|
|
212
|
-
* const [isModalOpen, setIsModalOpen] = useState(false);
|
|
307
|
+
* import { useOnClickOutside } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
213
308
|
*
|
|
214
|
-
*
|
|
309
|
+
* const Dropdown = () => {
|
|
310
|
+
* const dropdownRef = useRef(null);
|
|
311
|
+
* const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
215
312
|
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
313
|
+
* // Use the useOnClickOutside hook to close the dropdown when clicking outside of it
|
|
314
|
+
* useOnClickOutside(dropdownRef, () => setIsDropdownOpen(false));
|
|
315
|
+
*
|
|
316
|
+
* return (
|
|
317
|
+
* <div className="dropdown" ref={dropdownRef}>
|
|
318
|
+
* <button onClick={() => setIsDropdownOpen(!isDropdownOpen)}>
|
|
319
|
+
* Toggle Dropdown
|
|
320
|
+
* </button>
|
|
321
|
+
* {isDropdownOpen && (
|
|
322
|
+
* <ul className="dropdown-menu">
|
|
323
|
+
* <li>Option 1</li>
|
|
324
|
+
* <li>Option 2</li>
|
|
325
|
+
* <li>Option 3</li>
|
|
326
|
+
* </ul>
|
|
327
|
+
* )}
|
|
328
|
+
* </div>
|
|
329
|
+
* );
|
|
330
|
+
* };
|
|
227
331
|
* @endexample
|
|
228
332
|
*/
|
|
229
333
|
export function useOnClickOutside<T>(ref: React.MutableRefObject<T>, handler: (event: MouseEvent | TouchEvent) => any);
|
|
230
334
|
/**
|
|
231
335
|
*
|
|
232
|
-
*
|
|
336
|
+
* The usePrevious hook is a convenient utility to track the previous value of
|
|
337
|
+
*
|
|
338
|
+
* its argument before its most recent update. When it is called for the first
|
|
339
|
+
*
|
|
340
|
+
* time, it returns the initial value passed as an argument, and subsequently, it
|
|
233
341
|
*
|
|
234
|
-
*
|
|
342
|
+
* returns the previous value every time the component re-renders.
|
|
235
343
|
*
|
|
236
|
-
*
|
|
344
|
+
* The hook can be useful in monitoring modifications to form fields, such as
|
|
345
|
+
*
|
|
346
|
+
* detecting when fields become dirty, and taking action based on these
|
|
347
|
+
*
|
|
348
|
+
* alterations.
|
|
349
|
+
*
|
|
350
|
+
* The following code snippet illustrates the usage of usePrevious in tracking
|
|
351
|
+
*
|
|
352
|
+
* which fields were modified in a form. By comparing the current and previous
|
|
353
|
+
*
|
|
354
|
+
* values of form fields, you can easily identify and handle changes without the
|
|
355
|
+
*
|
|
356
|
+
* need for complex state management.
|
|
237
357
|
*
|
|
238
358
|
* @example
|
|
239
359
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
360
|
+
* import { usePrevious } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
361
|
+
*
|
|
362
|
+
* // Initialize state for a form field (e.g., an input field)
|
|
363
|
+
* const [name, setName] = useState("");
|
|
364
|
+
*
|
|
365
|
+
* // Use the usePrevious hook to obtain the previous value of name
|
|
366
|
+
* const previousName = usePrevious(name);
|
|
367
|
+
*
|
|
368
|
+
* // Use useEffect to detect changes in the 'name' field
|
|
369
|
+
* useEffect(() => {
|
|
370
|
+
* // Check if the 'name' field has changed
|
|
371
|
+
* if (name !== previousName) {
|
|
372
|
+
* // The 'name' field has been modified
|
|
373
|
+
* // You can perform actions here, such as marking it as 'dirty'
|
|
374
|
+
* // or updating other parts of your application
|
|
375
|
+
* }
|
|
376
|
+
* }, [name]);
|
|
242
377
|
* @endexample
|
|
378
|
+
* In the example, the useEffect block listens for changes in the name field.
|
|
379
|
+
*
|
|
380
|
+
* When the name field is updated, it compares the current value to the previous
|
|
381
|
+
*
|
|
382
|
+
* value. If they differ, it signifies that the field has been modified, enabling
|
|
383
|
+
*
|
|
384
|
+
* you to take appropriate actions.
|
|
385
|
+
*
|
|
243
386
|
*/
|
|
244
387
|
export function usePrevious<T>(value: T): T;
|
|
245
388
|
/**
|
|
246
389
|
*
|
|
247
|
-
*
|
|
390
|
+
* The useUpdateEffect hook is a variation of the standard useEffect hook in
|
|
391
|
+
*
|
|
392
|
+
* React. The key difference is that useUpdateEffect does not execute the
|
|
248
393
|
*
|
|
249
|
-
*
|
|
394
|
+
* provided callback during the initial component mount. Instead, it only triggers
|
|
250
395
|
*
|
|
251
|
-
*
|
|
396
|
+
* the callback when the specified dependencies change. This behavior can be
|
|
397
|
+
*
|
|
398
|
+
* advantageous when you want to perform actions or side effects in response to
|
|
399
|
+
*
|
|
400
|
+
* changes in specific variables after the initial rendering of your component.
|
|
401
|
+
*
|
|
402
|
+
* The following code snippet shows the usage of useUpdateEffect in displaying
|
|
403
|
+
*
|
|
404
|
+
* category when its value is modified.
|
|
252
405
|
*
|
|
253
406
|
* @example
|
|
254
407
|
*
|
|
408
|
+
* import { useUpdateEffect } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
409
|
+
*
|
|
410
|
+
* // Initialize state variables
|
|
411
|
+
* const [category, setCategory] = useState("default");
|
|
412
|
+
*
|
|
413
|
+
* // Use useUpdateEffect to update content based on category changes
|
|
255
414
|
* useUpdateEffect(() => {
|
|
256
|
-
*
|
|
257
|
-
* }
|
|
415
|
+
* // This callback will run when 'category' changes, but not during the initial mount
|
|
416
|
+
* console.log(`Category has been modified to ${category}`);
|
|
417
|
+
* }, [category]);
|
|
258
418
|
* @endexample
|
|
419
|
+
* The useUpdateEffect hook allows you to specify a callback function that will
|
|
420
|
+
*
|
|
421
|
+
* only execute when certain dependencies, in this case, the category state,
|
|
422
|
+
*
|
|
423
|
+
* change after the initial mount.
|
|
424
|
+
*
|
|
259
425
|
*/
|
|
260
426
|
export function useUpdateEffect(effect: () => void, deps: any[]): void;
|
|
261
427
|
/**
|
|
262
428
|
*
|
|
263
|
-
*
|
|
429
|
+
* The useDisplayErrorPage hook is a utility that allows you to conditionally
|
|
264
430
|
*
|
|
265
|
-
*
|
|
431
|
+
* render an error page in your application based on the status codes of API
|
|
266
432
|
*
|
|
267
|
-
*
|
|
433
|
+
* responses.
|
|
268
434
|
*
|
|
269
|
-
*
|
|
435
|
+
* The following code snippet demonstrates the usage of useDisplayErrorPage in
|
|
270
436
|
*
|
|
271
|
-
*
|
|
437
|
+
* conditionally rendering an error page.
|
|
272
438
|
*
|
|
273
439
|
* @example
|
|
274
440
|
*
|
|
441
|
+
* import { useDisplayErrorPage } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
442
|
+
*
|
|
275
443
|
* const App = () => {
|
|
276
444
|
* const isError = useDisplayErrorPage();
|
|
277
445
|
*
|
|
@@ -286,7 +454,7 @@ export function useUpdateEffect(effect: () => void, deps: any[]): void;
|
|
|
286
454
|
export function useDisplayErrorPage(): boolean;
|
|
287
455
|
/**
|
|
288
456
|
*
|
|
289
|
-
* A
|
|
457
|
+
* A Zustand store containing the status code of the latest API failed with 403 or
|
|
290
458
|
*
|
|
291
459
|
* 404 status. It stores the following values:
|
|
292
460
|
*
|
|
@@ -309,11 +477,13 @@ type TimerType = {
|
|
|
309
477
|
};
|
|
310
478
|
/**
|
|
311
479
|
*
|
|
312
|
-
* The useTimer hook
|
|
480
|
+
* The useTimer hook is a utility that enables automatic re-renders of a
|
|
313
481
|
*
|
|
314
|
-
*
|
|
482
|
+
* component at specified time intervals. This functionality is particularly useful
|
|
315
483
|
*
|
|
316
|
-
*
|
|
484
|
+
* for updating rendered content, such as elapsed time, without requiring manual
|
|
485
|
+
*
|
|
486
|
+
* refreshes.
|
|
317
487
|
*
|
|
318
488
|
* All invocations of useTimer hooks are attached to a single setInterval call
|
|
319
489
|
*
|
|
@@ -327,14 +497,23 @@ type TimerType = {
|
|
|
327
497
|
*
|
|
328
498
|
* second than the scheduled time interval to re-render.
|
|
329
499
|
*
|
|
500
|
+
* The following demonstrates the usage of useTimer hook in displaying
|
|
501
|
+
*
|
|
502
|
+
* time-sensitive information.
|
|
503
|
+
*
|
|
330
504
|
* @example
|
|
331
505
|
*
|
|
332
|
-
* import { useTimer } from "
|
|
506
|
+
* import { useTimer } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
507
|
+
*
|
|
508
|
+
* const Post = () => {
|
|
509
|
+
* // Use the useTimer hook with a custom interval
|
|
510
|
+
* useTimer(30);
|
|
333
511
|
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
512
|
+
* // Calculate the elapsed time since the post creation
|
|
513
|
+
* const currentTime = new Date();
|
|
514
|
+
* const elapsedTimeInSeconds = Math.floor((currentTime - createdAt) / 1000);
|
|
336
515
|
*
|
|
337
|
-
*
|
|
516
|
+
* return <p>Elapsed Time in seconds: {elapsedTimeInSeconds}</p>;
|
|
338
517
|
* };
|
|
339
518
|
* @endexample
|
|
340
519
|
*/
|
|
@@ -342,9 +521,9 @@ export function useTimer(interval: number): TimerType;
|
|
|
342
521
|
type ZustandConfigType = (set: (data: any) => void, get: () => any, api: any) => any;
|
|
343
522
|
/**
|
|
344
523
|
*
|
|
345
|
-
*
|
|
524
|
+
* withImmutableActions is a Zustand middleware function that prevents the
|
|
346
525
|
*
|
|
347
|
-
* overwritten.
|
|
526
|
+
* actions from getting overwritten.
|
|
348
527
|
*
|
|
349
528
|
* @example
|
|
350
529
|
*
|
|
@@ -358,33 +537,48 @@ type ZustandConfigType = (set: (data: any) => void, get: () => any, api: any) =>
|
|
|
358
537
|
* }))
|
|
359
538
|
* );
|
|
360
539
|
* @endexample
|
|
361
|
-
* In the above
|
|
540
|
+
* In the example above, any attempts like the following will trigger an error
|
|
362
541
|
*
|
|
363
|
-
* should
|
|
542
|
+
* because actions should never be overwritten:
|
|
364
543
|
*
|
|
365
544
|
* @example
|
|
366
545
|
*
|
|
367
546
|
* setGlobalState({ value: 0, setValue: () => {} });
|
|
368
547
|
* @endexample
|
|
369
|
-
*
|
|
548
|
+
* However, actions can be assigned their own values. This enables you to use
|
|
370
549
|
*
|
|
371
|
-
*
|
|
550
|
+
* curried Ramda functions in conjunction with Zustand actions. For instance, the
|
|
372
551
|
*
|
|
373
|
-
* usage will not
|
|
552
|
+
* following usage will not result in an error:
|
|
374
553
|
*
|
|
375
554
|
* @example
|
|
376
555
|
*
|
|
377
556
|
* setGlobalState(state => ({ value: 0, setValue: state.setValue }));
|
|
378
557
|
* @endexample
|
|
379
|
-
* The
|
|
558
|
+
* The second parameter to overwrite the entire state will be ignored. Both of the
|
|
380
559
|
*
|
|
381
|
-
* following lines of code
|
|
560
|
+
* following lines of code are functionally equivalent:
|
|
382
561
|
*
|
|
383
562
|
* @example
|
|
384
563
|
*
|
|
385
564
|
* setGlobalState(state => ({ value: 0 }), true);
|
|
386
565
|
* setGlobalState(state => ({ value: 0 }));
|
|
387
566
|
* @endexample
|
|
567
|
+
* It should be noted that the withImmutableActions middleware intercepts and
|
|
568
|
+
*
|
|
569
|
+
* wraps the set method of the Zustand store to enforce immutability rules.
|
|
570
|
+
*
|
|
571
|
+
* Therefore, usages of useStore.setState() won't be handled by the middleware
|
|
572
|
+
*
|
|
573
|
+
* since they directly update the state in Zustand without going through the set
|
|
574
|
+
*
|
|
575
|
+
* method of the store.
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
*
|
|
579
|
+
* // This won't be handled by the middleware.
|
|
580
|
+
* useStore.setState({ value: 0, setValue: () => {} });
|
|
581
|
+
* @endexample
|
|
388
582
|
*/
|
|
389
583
|
export function withImmutableActions(config: ZustandConfigType): ZustandConfigType;
|
|
390
584
|
export declare type ZustandStoreHook = UseBoundStore<StoreApi<any>> & {
|
|
@@ -392,16 +586,29 @@ export declare type ZustandStoreHook = UseBoundStore<StoreApi<any>> & {
|
|
|
392
586
|
};
|
|
393
587
|
/**
|
|
394
588
|
*
|
|
395
|
-
*
|
|
589
|
+
* The useFieldSubmit hook simplifies the task of capturing the Enter
|
|
590
|
+
*
|
|
591
|
+
* (Return) key press event within an input field and executing a callback
|
|
396
592
|
*
|
|
397
|
-
*
|
|
593
|
+
* function when the Enter key is pressed. This is a common requirement in forms
|
|
398
594
|
*
|
|
399
|
-
*
|
|
595
|
+
* where pressing Enter should trigger specific actions, such as submitting a
|
|
400
596
|
*
|
|
401
|
-
*
|
|
597
|
+
* form or processing user input. Importantly, this hook ensures that pressing
|
|
598
|
+
*
|
|
599
|
+
* Shift + Enter does not trigger the callback, allowing for the creation of
|
|
600
|
+
*
|
|
601
|
+
* multi-line text inputs.
|
|
602
|
+
*
|
|
603
|
+
* The following code snippet illustrates the usage of useFieldSubmit in building
|
|
604
|
+
*
|
|
605
|
+
* an interactive textarea input field.
|
|
402
606
|
*
|
|
403
607
|
* @example
|
|
404
608
|
*
|
|
609
|
+
* import { useFieldSubmit } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
610
|
+
*
|
|
611
|
+
* // Create a ref for the input field using useFieldSubmit
|
|
405
612
|
* const inputRef = useFieldSubmit(() => {
|
|
406
613
|
* const inputValue = inputRef.current.value;
|
|
407
614
|
* console.log(inputValue);
|
|
@@ -409,42 +616,61 @@ export declare type ZustandStoreHook = UseBoundStore<StoreApi<any>> & {
|
|
|
409
616
|
*
|
|
410
617
|
* return <textarea ref={inputRef} />;
|
|
411
618
|
* @endexample
|
|
619
|
+
* When the Enter key is pressed, the onSubmit callback function is executed,
|
|
620
|
+
*
|
|
621
|
+
* allowing you to access the input value and perform the desired action.
|
|
622
|
+
*
|
|
412
623
|
*/
|
|
413
624
|
export function useFieldSubmit(onSubmit: () => any): {
|
|
414
625
|
current: HTMLInputElement & HTMLTextAreaElement;
|
|
415
626
|
};
|
|
416
627
|
/**
|
|
417
628
|
*
|
|
418
|
-
*
|
|
629
|
+
* withTitle is an HOC which sets the browser title with the given value when the
|
|
419
630
|
*
|
|
420
|
-
* component is rendered. If title is not explicitly provided, it will
|
|
631
|
+
* wrapped component is rendered. If title is not explicitly provided, it will
|
|
421
632
|
*
|
|
422
|
-
* globalProps.appName as the page title.
|
|
633
|
+
* render globalProps.appName as the page title.
|
|
423
634
|
*
|
|
424
635
|
* @example
|
|
425
636
|
*
|
|
426
637
|
* // assume this code in neetoStore
|
|
427
638
|
* const ProductsPage = props => <>Your page content here</>;
|
|
428
|
-
*
|
|
639
|
+
*
|
|
429
640
|
* // will set the browser title to `All products | neetoStore` when this page is rendered.
|
|
641
|
+
* export default withTitle(ProductsPage, "All products");
|
|
430
642
|
* @endexample
|
|
431
643
|
*/
|
|
432
644
|
export function withTitle<T>(Component: React.ComponentType<T>, title?: string | null): (props: T) => JSX.Element;
|
|
433
645
|
/**
|
|
434
646
|
*
|
|
435
|
-
*
|
|
647
|
+
* registerBrowserNotifications is a browser push notifications utility function
|
|
648
|
+
*
|
|
649
|
+
* which asks the user permissions to send notifications and then register the
|
|
650
|
+
*
|
|
651
|
+
* browser with the notification service.
|
|
652
|
+
*
|
|
653
|
+
* To enable the notification service to dispatch web push messages to browsers, it
|
|
654
|
+
*
|
|
655
|
+
* relies on VAPID keys. These
|
|
656
|
+
*
|
|
657
|
+
* keys should be securely stored as environment variables and made accessible
|
|
658
|
+
*
|
|
659
|
+
* through process.env. If keys are not accessible from process.env, pass in
|
|
436
660
|
*
|
|
437
|
-
*
|
|
661
|
+
* the vapidPublicKey using global props from application helper.
|
|
438
662
|
*
|
|
439
|
-
*
|
|
663
|
+
* You can find the VAPID keys (PUBLIC and PRIVATE) for neeto products at
|
|
664
|
+
*
|
|
665
|
+
* neetoNotifications Dashboard.
|
|
440
666
|
*
|
|
441
667
|
* After the user logs in, we need to ask the user permissions to send
|
|
442
668
|
*
|
|
443
|
-
* notifications and then register the browser with the notification service.
|
|
669
|
+
* notifications and then register the browser with the notification service. The
|
|
444
670
|
*
|
|
445
|
-
*
|
|
671
|
+
* registerBrowserNotifications utility function facilitates this process. It can
|
|
446
672
|
*
|
|
447
|
-
*
|
|
673
|
+
* be called on any event after login based on the application's logic and
|
|
448
674
|
*
|
|
449
675
|
* requirement.
|
|
450
676
|
*
|
|
@@ -478,23 +704,23 @@ export function withTitle<T>(Component: React.ComponentType<T>, title?: string |
|
|
|
478
704
|
export async function registerBrowserNotifications(): Promise<void>;
|
|
479
705
|
/**
|
|
480
706
|
*
|
|
481
|
-
*
|
|
707
|
+
* destroyBrowserSubscription is a browser push notifications utility function
|
|
482
708
|
*
|
|
483
|
-
* subscriptions from the user's devices. This helps in
|
|
709
|
+
* which destroys the browser subscriptions from the user's devices. This helps in
|
|
484
710
|
*
|
|
485
|
-
* push notifications.
|
|
711
|
+
* unsubscribing from browser push notifications.
|
|
486
712
|
*
|
|
487
713
|
* When the browser subscriptions expires for the user's devices or when the user
|
|
488
714
|
*
|
|
489
|
-
* decides to logout,
|
|
715
|
+
* decides to logout, the generated browser subscription for the user should be
|
|
490
716
|
*
|
|
491
|
-
*
|
|
717
|
+
* destroyed. The destroyBrowserSubscription utility function enables us to do
|
|
492
718
|
*
|
|
493
|
-
* be called on any event before logout based on the application's
|
|
719
|
+
* the same. It can be called on any event before logout based on the application's
|
|
494
720
|
*
|
|
495
|
-
* requirement.
|
|
721
|
+
* logic and requirement.
|
|
496
722
|
*
|
|
497
|
-
* Here
|
|
723
|
+
* Here is an example: In the Logout component, we are calling
|
|
498
724
|
*
|
|
499
725
|
* destroyBrowserSubscription method before the Logout API request. This
|
|
500
726
|
*
|
|
@@ -524,72 +750,157 @@ export async function registerBrowserNotifications(): Promise<void>;
|
|
|
524
750
|
export async function destroyBrowserSubscription(): Promise<void>;
|
|
525
751
|
/**
|
|
526
752
|
*
|
|
527
|
-
*
|
|
753
|
+
* The handleMetaClick function can be used to handle onClick actions that
|
|
754
|
+
*
|
|
755
|
+
* redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event
|
|
756
|
+
*
|
|
757
|
+
* is received. Otherwise, simply redirects to the provided URL in the same tab.
|
|
528
758
|
*
|
|
529
|
-
*
|
|
759
|
+
* URL can be passed as string or a history location object can be passed instead.
|
|
530
760
|
*
|
|
531
|
-
*
|
|
761
|
+
* Let's say you have a navigation menu with several links, and you want to allow
|
|
532
762
|
*
|
|
533
|
-
*
|
|
763
|
+
* users to open these links in a new tab if they hold down the Ctrl (or Cmd on
|
|
534
764
|
*
|
|
535
|
-
*
|
|
765
|
+
* macOS) key while clicking, and if they click without holding down the Ctrl key,
|
|
766
|
+
*
|
|
767
|
+
* the link should open in the same tab. You can use handleMetaClick to achieve
|
|
768
|
+
*
|
|
769
|
+
* this behavior.
|
|
536
770
|
*
|
|
537
771
|
* @example
|
|
538
772
|
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
773
|
+
* const NavigationMenu = () => {
|
|
774
|
+
* const history = useHistory();
|
|
775
|
+
*
|
|
776
|
+
* const handleLinkClick = (url, event) => {
|
|
777
|
+
* // Opens url in a new tab if metaKey/CtrlKey is pressed.
|
|
778
|
+
* // Otherwise simply redirects to url.
|
|
779
|
+
* handleMetaClick(history, url, event);
|
|
780
|
+
* };
|
|
781
|
+
*
|
|
782
|
+
* return (
|
|
783
|
+
* <div>
|
|
784
|
+
* <a href="/home" onClick={e => handleLinkClick("/home", e)}>
|
|
785
|
+
* Home
|
|
786
|
+
* </a>
|
|
787
|
+
* <a href="/dashboard" onClick={e => handleLinkClick("/dashboard", e)}>
|
|
788
|
+
* Dashboard
|
|
789
|
+
* </a>
|
|
790
|
+
* <a href="/profile" onClick={e => handleLinkClick("/profile", e)}>
|
|
791
|
+
* Profile
|
|
792
|
+
* </a>
|
|
793
|
+
* </div>
|
|
794
|
+
* );
|
|
795
|
+
* };
|
|
541
796
|
* @endexample
|
|
542
797
|
*/
|
|
543
798
|
export function handleMetaClick(history: History, params: string | object, event: React.MouseEvent<HTMLElement, MouseEvent>): void;
|
|
544
799
|
/**
|
|
545
800
|
*
|
|
546
|
-
*
|
|
801
|
+
* The handleMetaClick function can be used to handle onClick actions that
|
|
802
|
+
*
|
|
803
|
+
* redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event
|
|
547
804
|
*
|
|
548
|
-
*
|
|
805
|
+
* is received. Otherwise, simply redirects to the provided URL in the same tab.
|
|
549
806
|
*
|
|
550
|
-
*
|
|
807
|
+
* URL can be passed as string or a history location object can be passed instead.
|
|
551
808
|
*
|
|
552
|
-
*
|
|
809
|
+
* Let's say you have a navigation menu with several links, and you want to allow
|
|
553
810
|
*
|
|
554
|
-
*
|
|
811
|
+
* users to open these links in a new tab if they hold down the Ctrl (or Cmd on
|
|
812
|
+
*
|
|
813
|
+
* macOS) key while clicking, and if they click without holding down the Ctrl key,
|
|
814
|
+
*
|
|
815
|
+
* the link should open in the same tab. You can use handleMetaClick to achieve
|
|
816
|
+
*
|
|
817
|
+
* this behavior.
|
|
555
818
|
*
|
|
556
819
|
* @example
|
|
557
820
|
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
821
|
+
* const NavigationMenu = () => {
|
|
822
|
+
* const history = useHistory();
|
|
823
|
+
*
|
|
824
|
+
* const handleLinkClick = (url, event) => {
|
|
825
|
+
* // Opens url in a new tab if metaKey/CtrlKey is pressed.
|
|
826
|
+
* // Otherwise simply redirects to url.
|
|
827
|
+
* handleMetaClick(history, url, event);
|
|
828
|
+
* };
|
|
829
|
+
*
|
|
830
|
+
* return (
|
|
831
|
+
* <div>
|
|
832
|
+
* <a href="/home" onClick={e => handleLinkClick("/home", e)}>
|
|
833
|
+
* Home
|
|
834
|
+
* </a>
|
|
835
|
+
* <a href="/dashboard" onClick={e => handleLinkClick("/dashboard", e)}>
|
|
836
|
+
* Dashboard
|
|
837
|
+
* </a>
|
|
838
|
+
* <a href="/profile" onClick={e => handleLinkClick("/profile", e)}>
|
|
839
|
+
* Profile
|
|
840
|
+
* </a>
|
|
841
|
+
* </div>
|
|
842
|
+
* );
|
|
843
|
+
* };
|
|
560
844
|
* @endexample
|
|
561
845
|
*/
|
|
562
846
|
export function handleMetaClick(history: History, params: string | object): (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
563
847
|
/**
|
|
564
848
|
*
|
|
565
|
-
*
|
|
849
|
+
* The handleMetaClick function can be used to handle onClick actions that
|
|
850
|
+
*
|
|
851
|
+
* redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event
|
|
566
852
|
*
|
|
567
|
-
*
|
|
853
|
+
* is received. Otherwise, simply redirects to the provided URL in the same tab.
|
|
568
854
|
*
|
|
569
|
-
*
|
|
855
|
+
* URL can be passed as string or a history location object can be passed instead.
|
|
570
856
|
*
|
|
571
|
-
*
|
|
857
|
+
* Let's say you have a navigation menu with several links, and you want to allow
|
|
572
858
|
*
|
|
573
|
-
*
|
|
859
|
+
* users to open these links in a new tab if they hold down the Ctrl (or Cmd on
|
|
860
|
+
*
|
|
861
|
+
* macOS) key while clicking, and if they click without holding down the Ctrl key,
|
|
862
|
+
*
|
|
863
|
+
* the link should open in the same tab. You can use handleMetaClick to achieve
|
|
864
|
+
*
|
|
865
|
+
* this behavior.
|
|
574
866
|
*
|
|
575
867
|
* @example
|
|
576
868
|
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
869
|
+
* const NavigationMenu = () => {
|
|
870
|
+
* const history = useHistory();
|
|
871
|
+
*
|
|
872
|
+
* const handleLinkClick = (url, event) => {
|
|
873
|
+
* // Opens url in a new tab if metaKey/CtrlKey is pressed.
|
|
874
|
+
* // Otherwise simply redirects to url.
|
|
875
|
+
* handleMetaClick(history, url, event);
|
|
876
|
+
* };
|
|
877
|
+
*
|
|
878
|
+
* return (
|
|
879
|
+
* <div>
|
|
880
|
+
* <a href="/home" onClick={e => handleLinkClick("/home", e)}>
|
|
881
|
+
* Home
|
|
882
|
+
* </a>
|
|
883
|
+
* <a href="/dashboard" onClick={e => handleLinkClick("/dashboard", e)}>
|
|
884
|
+
* Dashboard
|
|
885
|
+
* </a>
|
|
886
|
+
* <a href="/profile" onClick={e => handleLinkClick("/profile", e)}>
|
|
887
|
+
* Profile
|
|
888
|
+
* </a>
|
|
889
|
+
* </div>
|
|
890
|
+
* );
|
|
891
|
+
* };
|
|
579
892
|
* @endexample
|
|
580
893
|
*/
|
|
581
894
|
export function handleMetaClick(history: History): (params: string | object, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
582
895
|
/**
|
|
583
896
|
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
* This function can be used to check whether an onClick event has metaKey or
|
|
897
|
+
* The isMetaKeyPressed function can be used to check whether an onClick event
|
|
587
898
|
*
|
|
588
|
-
* ctrlKey pressed.
|
|
899
|
+
* has metaKey or ctrlKey pressed.
|
|
589
900
|
*
|
|
590
901
|
* @example
|
|
591
902
|
*
|
|
592
|
-
* isMetaKeyPressed(event);
|
|
903
|
+
* isMetaKeyPressed(event);
|
|
593
904
|
* @endexample
|
|
594
905
|
*/
|
|
595
906
|
export function isMetaKeyPressed(event: React.MouseEvent<HTMLElement, MouseEvent>): boolean;
|
|
@@ -600,14 +911,24 @@ type ConfigType = {
|
|
|
600
911
|
};
|
|
601
912
|
/**
|
|
602
913
|
*
|
|
603
|
-
*
|
|
914
|
+
* The useHotKeys hook is a versatile utility for handling hotkeys in an
|
|
915
|
+
*
|
|
916
|
+
* application. It allows you to define specific hotkey combinations and associate
|
|
917
|
+
*
|
|
918
|
+
* them with handler functions. When the user presses the configured hotkey(s), the
|
|
919
|
+
*
|
|
920
|
+
* corresponding handler is invoked, enabling you to perform actions in response to
|
|
921
|
+
*
|
|
922
|
+
* keyboard input.
|
|
604
923
|
*
|
|
605
|
-
*
|
|
924
|
+
* Following illustrates the usage of useHotKeys in implementing shortcut for
|
|
606
925
|
*
|
|
607
|
-
*
|
|
926
|
+
* Sidebar opening.
|
|
608
927
|
*
|
|
609
928
|
* @example
|
|
610
929
|
*
|
|
930
|
+
* import { useHotKeys } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
931
|
+
*
|
|
611
932
|
* // openSidebar function will only be called if the user is focused inside the textarea and performs the key combination.
|
|
612
933
|
* const ref = useHotKeys("command+shift+r", openSidebar, {
|
|
613
934
|
* mode: "scoped",
|
|
@@ -620,15 +941,33 @@ type ConfigType = {
|
|
|
620
941
|
* </div>
|
|
621
942
|
* );
|
|
622
943
|
* @endexample
|
|
944
|
+
* Hotkeys are a fundamental aspect of many applications, enhancing user efficiency
|
|
945
|
+
*
|
|
946
|
+
* and interactivity. The useHotKeys hook simplifies the implementation of these
|
|
947
|
+
*
|
|
948
|
+
* hotkeys by allowing you to specify the hotkey combinations in various formats,
|
|
949
|
+
*
|
|
950
|
+
* associated handlers, and configuration options.
|
|
951
|
+
*
|
|
623
952
|
*/
|
|
624
953
|
export function useHotKeys(hotkey: string | string[], handler: (event: React.KeyboardEvent) => void, config?: ConfigType): React.MutableRefObject | null;
|
|
625
954
|
/**
|
|
626
955
|
*
|
|
627
|
-
*
|
|
956
|
+
* The useStateWithDependency hook is a utility that returns a state variable and
|
|
957
|
+
*
|
|
958
|
+
* a setter function similar to the useState hook. However, it provides
|
|
959
|
+
*
|
|
960
|
+
* additional functionality: the state variable automatically updates its value to
|
|
628
961
|
*
|
|
629
|
-
* whenever defaultValue changes.
|
|
962
|
+
* the specified defaultValue whenever defaultValue changes. Optionally, you
|
|
630
963
|
*
|
|
631
|
-
*
|
|
964
|
+
* can also specify a dependencies array to listen for changes in other variables,
|
|
965
|
+
*
|
|
966
|
+
* which will trigger the update of the state variable.
|
|
967
|
+
*
|
|
968
|
+
* This hook will return an array with exactly two values just like useState
|
|
969
|
+
*
|
|
970
|
+
* hook.
|
|
632
971
|
*
|
|
633
972
|
* If dependencies is passed, the hook returns a state variable whose value will
|
|
634
973
|
*
|
|
@@ -638,68 +977,221 @@ export function useHotKeys(hotkey: string | string[], handler: (event: React.Key
|
|
|
638
977
|
*
|
|
639
978
|
* @example
|
|
640
979
|
*
|
|
641
|
-
*
|
|
980
|
+
* import { useStateWithDependency } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
981
|
+
*
|
|
982
|
+
* // reset state to `defaultValue` whenever `defaultValue` changes.
|
|
983
|
+
* const [value, setValue] = useStateWithDependency(defaultValue);
|
|
984
|
+
*
|
|
985
|
+
* // reset state to `defaultValue` only when `value1` or `value2` changes.
|
|
642
986
|
* const [value, setValue] = useStateWithDependency(defaultValue, [
|
|
643
987
|
* value1,
|
|
644
988
|
* value2,
|
|
645
|
-
* ]);
|
|
989
|
+
* ]);
|
|
646
990
|
*
|
|
647
|
-
* // In a case, where the value needs to be reset when defaultValue
|
|
991
|
+
* // In a case, where the value needs to be reset when defaultValue
|
|
992
|
+
* // changes too, defaultValue can be passed with the dependencies,
|
|
993
|
+
* // as shown below.
|
|
648
994
|
* const [value, setValue] = useStateWithDependency(defaultValue, [
|
|
649
995
|
* value1,
|
|
650
996
|
* value2,
|
|
651
997
|
* defaultValue,
|
|
652
998
|
* ]);
|
|
653
999
|
* @endexample
|
|
1000
|
+
* The following code snippet demonstrates the usage of useStateWithDependency in
|
|
1001
|
+
*
|
|
1002
|
+
* ensuring that inputValue stays in sync with the value prop in the Rename
|
|
1003
|
+
*
|
|
1004
|
+
* component.
|
|
1005
|
+
*
|
|
1006
|
+
* @example
|
|
1007
|
+
*
|
|
1008
|
+
* const Rename = ({ value }) => {
|
|
1009
|
+
* // Use the useStateWithDependency hook to manage the input value
|
|
1010
|
+
* const [inputValue, setInputValue] = useStateWithDependency(value);
|
|
1011
|
+
*
|
|
1012
|
+
* // Define a handler to update the input value
|
|
1013
|
+
* const handleInputChange = event => {
|
|
1014
|
+
* setInputValue(event.target.value);
|
|
1015
|
+
* };
|
|
1016
|
+
*
|
|
1017
|
+
* return (
|
|
1018
|
+
* <div>
|
|
1019
|
+
* <input type="text" value={inputValue} onChange={handleInputChange} />
|
|
1020
|
+
* { Rest of the component }
|
|
1021
|
+
* </div>
|
|
1022
|
+
* );
|
|
1023
|
+
* };
|
|
1024
|
+
* @endexample
|
|
1025
|
+
* As the user interacts with the input field, the inputValue state is updated to
|
|
1026
|
+
*
|
|
1027
|
+
* reflect the user's input. In a scenario where the value prop changes from
|
|
1028
|
+
*
|
|
1029
|
+
* outside the Rename component, it triggers a re-render of the Rename
|
|
1030
|
+
*
|
|
1031
|
+
* component. When this re-render occurs, the inputValue state is automatically
|
|
1032
|
+
*
|
|
1033
|
+
* updated to match the new value prop.
|
|
1034
|
+
*
|
|
654
1035
|
*/
|
|
655
1036
|
export function useStateWithDependency<T>(defaultValue: T, dependencies?: any[]): T;
|
|
656
1037
|
/**
|
|
657
1038
|
*
|
|
658
|
-
*
|
|
1039
|
+
* The useRegisterNavigationCheckpoint hook is a utility for storing navigation
|
|
659
1040
|
*
|
|
660
|
-
*
|
|
1041
|
+
* checkpoints in a Zustand store. A navigation checkpoint consists of a key that
|
|
661
1042
|
*
|
|
662
|
-
*
|
|
1043
|
+
* identifies the checkpoint and a corresponding path to be stored in the Zustand
|
|
1044
|
+
*
|
|
1045
|
+
* store under that key. These registered checkpoints can be later retrieved using
|
|
1046
|
+
*
|
|
1047
|
+
* the useNavigationCheckpoints hook.
|
|
1048
|
+
*
|
|
1049
|
+
* In web applications, scenarios frequently arise where it's essential to maintain
|
|
1050
|
+
*
|
|
1051
|
+
* user preferences and specific application states as users navigate back and
|
|
1052
|
+
*
|
|
1053
|
+
* forth between different routes.
|
|
1054
|
+
*
|
|
1055
|
+
* A simple button, that hard codes the route as <Link to="/resource" />, won't
|
|
1056
|
+
*
|
|
1057
|
+
* suffice in such scenarios to navigate between pages since it won't retain any
|
|
1058
|
+
*
|
|
1059
|
+
* filter, search, or pagination information.
|
|
1060
|
+
*
|
|
1061
|
+
* This is why we have checkpoints. When a page component is mounted, a checkpoint
|
|
1062
|
+
*
|
|
1063
|
+
* is registered to capture the current state of the page, including the URL with
|
|
1064
|
+
*
|
|
1065
|
+
* applied filters, search parameters, and pagination information. If the URL
|
|
1066
|
+
*
|
|
1067
|
+
* changes due to user interactions, the checkpoint is automatically updated.
|
|
1068
|
+
*
|
|
1069
|
+
* When a user presses the back button, the value stored in the checkpoint is used
|
|
1070
|
+
*
|
|
1071
|
+
* as the URL. This ensures that users return to the listing page with all their
|
|
1072
|
+
*
|
|
1073
|
+
* previous context intact, providing a seamless and user-friendly experience.
|
|
1074
|
+
*
|
|
1075
|
+
* Following code snippet illustrates the usage of
|
|
1076
|
+
*
|
|
1077
|
+
* useRegisterNavigationCheckpoint in retaining user preference and context.
|
|
663
1078
|
*
|
|
664
1079
|
* @example
|
|
665
1080
|
*
|
|
666
|
-
* useRegisterNavigationCheckpoint
|
|
1081
|
+
* // Import the useRegisterNavigationCheckpoint hook
|
|
1082
|
+
* import { useRegisterNavigationCheckpoint } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
1083
|
+
* // ...
|
|
1084
|
+
*
|
|
1085
|
+
* // Register a navigation checkpoint with a key and path
|
|
1086
|
+
* useRegisterNavigationCheckpoint(
|
|
1087
|
+
* NAVIGATION_CHECKPOINT_KEYS.ARTICLES,
|
|
1088
|
+
* window.location.pathname + window.location.search
|
|
1089
|
+
* );
|
|
1090
|
+
* @endexample
|
|
1091
|
+
* When users visit the articles page, apply specific filters, and navigate away,
|
|
1092
|
+
*
|
|
1093
|
+
* the navigation checkpoint captures the current URL path along with the query
|
|
1094
|
+
*
|
|
1095
|
+
* parameters associated with the applied filters. Later, when users return to the
|
|
1096
|
+
*
|
|
1097
|
+
* page, the useNavigationCheckpoints hook can retrieve the saved checkpoint
|
|
1098
|
+
*
|
|
1099
|
+
* using the NAVIGATION_CHECKPOINT_KEYS.ARTICLES key. This retrieved data
|
|
1100
|
+
*
|
|
1101
|
+
* includes the applied filters, which can then be displayed on the articles page.
|
|
1102
|
+
*
|
|
1103
|
+
* It is worth noting that, at BigBinary, we define the object
|
|
1104
|
+
*
|
|
1105
|
+
* NAVIGATION_CHECKPOINT_KEYS to store the check point keys like so:
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
*
|
|
1109
|
+
* export const NAVIGATION_CHECKPOINT_KEYS = {
|
|
1110
|
+
* HOME: "home",
|
|
1111
|
+
* ARTICLES: "articles",
|
|
1112
|
+
* };
|
|
667
1113
|
* @endexample
|
|
668
1114
|
*/
|
|
669
1115
|
export function useRegisterNavigationCheckpoint(key: string, path: string): void;
|
|
670
1116
|
/**
|
|
671
1117
|
*
|
|
672
|
-
*
|
|
1118
|
+
* The useNavigationCheckpoints hook is a convenient tool for fetching designated
|
|
1119
|
+
*
|
|
1120
|
+
* navigation checkpoints stored in a Zustand store.
|
|
1121
|
+
*
|
|
1122
|
+
* In web applications, users frequently move between various pages or routes, and
|
|
1123
|
+
*
|
|
1124
|
+
* useRegisterNavigationCheckpoint empowers us to store particular paths or
|
|
1125
|
+
*
|
|
1126
|
+
* states as checkpoints. By employing the useNavigationCheckpoints hook, you can
|
|
1127
|
+
*
|
|
1128
|
+
* access these checkpoints by specifying their associated keys.
|
|
1129
|
+
*
|
|
1130
|
+
* We recommend reviewing the documentation for the
|
|
1131
|
+
*
|
|
1132
|
+
* useRegisterNavigationCheckpoint hook to
|
|
1133
|
+
*
|
|
1134
|
+
* gain a deeper understanding of the checkpoint concept.
|
|
1135
|
+
*
|
|
1136
|
+
* The following code snippet demonstrates the usage of useNavigationCheckpoints
|
|
1137
|
+
*
|
|
1138
|
+
* in retrieving navigation links that reflect the application's state and history.
|
|
673
1139
|
*
|
|
674
1140
|
* @example
|
|
675
1141
|
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
* );
|
|
1142
|
+
* // Import the useNavigationCheckpoints hook
|
|
1143
|
+
* import { useNavigationCheckpoints } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
1144
|
+
*
|
|
1145
|
+
* const navigationCheckpoints = useNavigationCheckpoints("home");
|
|
680
1146
|
*
|
|
681
1147
|
* return (
|
|
682
1148
|
* <>
|
|
683
|
-
* <Link to={navigationCheckpoints[
|
|
1149
|
+
* <Link to={navigationCheckpoints["home"]}>Home</Link>
|
|
684
1150
|
* </>
|
|
685
1151
|
* );
|
|
686
1152
|
* @endexample
|
|
1153
|
+
* The above code fetches navigation checkpoint data for the home key using the
|
|
1154
|
+
*
|
|
1155
|
+
* useNavigationCheckpoints hook and then renders a link labeled "Home" that,
|
|
1156
|
+
*
|
|
1157
|
+
* when clicked, will navigate the user to the URL associated with the home
|
|
1158
|
+
*
|
|
1159
|
+
* navigation checkpoint.
|
|
1160
|
+
*
|
|
687
1161
|
*/
|
|
688
1162
|
export function useNavigationCheckpoints(...keys: string[]): {
|
|
689
1163
|
[key: string]: string;
|
|
690
1164
|
};
|
|
691
1165
|
/**
|
|
692
1166
|
*
|
|
693
|
-
*
|
|
1167
|
+
* The useFuncDebounce hook is a utility that extends the benefits of debouncing
|
|
1168
|
+
*
|
|
1169
|
+
* to functions.
|
|
1170
|
+
*
|
|
1171
|
+
* When the debounced function is called, it sets a timer to execute the original
|
|
1172
|
+
*
|
|
1173
|
+
* function after a specified delay. If the debounced function is called again
|
|
1174
|
+
*
|
|
1175
|
+
* before the timer expires, the previous timer is cleared. This effectively delays
|
|
1176
|
+
*
|
|
1177
|
+
* the execution of the original function until the debounced function hasn't been
|
|
1178
|
+
*
|
|
1179
|
+
* called for the specified delay period.
|
|
1180
|
+
*
|
|
1181
|
+
* The hook also provides a cancel method to manually cancel the execution of the
|
|
1182
|
+
*
|
|
1183
|
+
* debounced function before it triggers.
|
|
694
1184
|
*
|
|
695
|
-
*
|
|
1185
|
+
* The following code snippet demonstrates the usage of useFuncDebounce in the
|
|
696
1186
|
*
|
|
697
|
-
*
|
|
1187
|
+
* delaying the invocation of the fetch method until the user pauses typing for a
|
|
698
1188
|
*
|
|
699
|
-
*
|
|
1189
|
+
* specific period.
|
|
700
1190
|
*
|
|
701
1191
|
* @example
|
|
702
1192
|
*
|
|
1193
|
+
* import { useFuncDebounce } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
1194
|
+
*
|
|
703
1195
|
* const searchForProducts = useFuncDebounce(async key => {
|
|
704
1196
|
* // this function will be triggered once after user stops typing for 300ms
|
|
705
1197
|
* const products = await productsApi.fetch(key);
|
|
@@ -717,15 +1209,17 @@ export const useFuncDebounce: {
|
|
|
717
1209
|
};
|
|
718
1210
|
/**
|
|
719
1211
|
*
|
|
720
|
-
* usePersistedQuery is an wrapper function around
|
|
1212
|
+
* usePersistedQuery is an wrapper function around
|
|
1213
|
+
*
|
|
1214
|
+
* useQuery hook
|
|
721
1215
|
*
|
|
722
|
-
* react-query. In addition to all the functionalities offered useQuery,
|
|
1216
|
+
* from react-query. In addition to all the functionalities offered useQuery,
|
|
723
1217
|
*
|
|
724
|
-
* hook also stores the received response in localStorage. For subsequent
|
|
1218
|
+
* this hook also stores the received response in localStorage. For subsequent
|
|
725
1219
|
*
|
|
726
|
-
* loads, the hook will be serving data from localStorage until the API
|
|
1220
|
+
* page loads, the hook will be serving data from localStorage until the API
|
|
727
1221
|
*
|
|
728
|
-
* is received.
|
|
1222
|
+
* response is received.
|
|
729
1223
|
*
|
|
730
1224
|
* usePersistedQuery will use the staleTime config from options parameter (if
|
|
731
1225
|
*
|
|
@@ -745,8 +1239,16 @@ export const useFuncDebounce: {
|
|
|
745
1239
|
*
|
|
746
1240
|
* by providing the queryKey.
|
|
747
1241
|
*
|
|
1242
|
+
* The following code snippet demonstrates the usage of usePersistedQuery in
|
|
1243
|
+
*
|
|
1244
|
+
* caching API responses and serving cached data while waiting for fresh data from
|
|
1245
|
+
*
|
|
1246
|
+
* the APIs.
|
|
1247
|
+
*
|
|
748
1248
|
* @example
|
|
749
1249
|
*
|
|
1250
|
+
* import { usePersistedQuery } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
1251
|
+
*
|
|
750
1252
|
* const useFetchUsers = options =>
|
|
751
1253
|
* usePersistedQuery(QUERY_KEYS.FETCH_USERS, usersApi.fetch, options);
|
|
752
1254
|
*
|
|
@@ -765,20 +1267,28 @@ export const usePersistedQuery: {
|
|
|
765
1267
|
};
|
|
766
1268
|
/**
|
|
767
1269
|
*
|
|
768
|
-
*
|
|
1270
|
+
* The useFetchNeetoApps hook calls
|
|
1271
|
+
*
|
|
1272
|
+
* neeto_apps_controller
|
|
1273
|
+
*
|
|
1274
|
+
* and fetches the response. neeto_apps_controller will return two information:
|
|
769
1275
|
*
|
|
770
|
-
*
|
|
1276
|
+
* This hook uses usePersistedQuery under the hood. So
|
|
771
1277
|
*
|
|
772
|
-
*
|
|
1278
|
+
* data will be immediately available except for the first page load. Additionally
|
|
773
1279
|
*
|
|
774
|
-
*
|
|
1280
|
+
* if the data is available in localStorage, it will be served from there until an
|
|
775
1281
|
*
|
|
776
|
-
*
|
|
1282
|
+
* explicit call to refetch is made.
|
|
777
1283
|
*
|
|
778
|
-
*
|
|
1284
|
+
* The following code snippet shows the usage of useFetchNeetoApps in fetching
|
|
1285
|
+
*
|
|
1286
|
+
* neetoApps and ownership status.
|
|
779
1287
|
*
|
|
780
1288
|
* @example
|
|
781
1289
|
*
|
|
1290
|
+
* import { useFetchNeetoApps } from "@bigbinary/neeto-commons-frontend/react-utils";
|
|
1291
|
+
*
|
|
782
1292
|
* const { neetoApps, isOwner } = useFetchNeetoApps();
|
|
783
1293
|
* @endexample
|
|
784
1294
|
*/
|
|
@@ -792,13 +1302,18 @@ export function useFetchNeetoApps(options?: UseQueryOptions): ReturnType<typeof
|
|
|
792
1302
|
}>>;
|
|
793
1303
|
/**
|
|
794
1304
|
*
|
|
795
|
-
*
|
|
1305
|
+
* withT is an HOC which provides the t function from react-i18next to the
|
|
1306
|
+
*
|
|
1307
|
+
* wrapped component as a prop. withT HOC should only be used in dumb components
|
|
1308
|
+
*
|
|
1309
|
+
* i.e, components which have no logic other than rendering something and the
|
|
796
1310
|
*
|
|
797
|
-
*
|
|
1311
|
+
* useTranslation hook.
|
|
798
1312
|
*
|
|
799
1313
|
* @example
|
|
800
1314
|
*
|
|
801
|
-
*
|
|
1315
|
+
* // Example usage of withT:
|
|
1316
|
+
* const ComponentWithTranslation = withT(({ t }) => <div>{t("some.key")}</div>);
|
|
802
1317
|
* @endexample
|
|
803
1318
|
*/
|
|
804
1319
|
export const withT: <Props extends {
|
|
@@ -808,12 +1323,18 @@ export const withT: <Props extends {
|
|
|
808
1323
|
}>) => React.ComponentType<Props>;
|
|
809
1324
|
/**
|
|
810
1325
|
*
|
|
811
|
-
* useMutationWithInvalidation is a wrapper function around the
|
|
1326
|
+
* useMutationWithInvalidation is a wrapper function around the
|
|
1327
|
+
*
|
|
1328
|
+
* useMutation
|
|
812
1329
|
*
|
|
813
1330
|
* hook from react-query. It returns all the props from the useMutation hook and
|
|
814
1331
|
*
|
|
815
1332
|
* additionally, invalidates a list of query keys on mutation success.
|
|
816
1333
|
*
|
|
1334
|
+
* The following code snippet illustrates the usage of
|
|
1335
|
+
*
|
|
1336
|
+
* useMutationWithInvalidation across various scenarios.
|
|
1337
|
+
*
|
|
817
1338
|
* @example
|
|
818
1339
|
*
|
|
819
1340
|
* // useQuestionsApi
|