@bigbinary/neeto-commons-frontend 2.0.65 → 2.0.66
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/package.json +1 -1
- package/react-utils.d.ts +419 -154
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigbinary/neeto-commons-frontend",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.66",
|
|
4
4
|
"description": "A package encapsulating common code across neeto projects including initializers, utility functions, common components and hooks and so on.",
|
|
5
5
|
"repository": "git@github.com:bigbinary/neeto-commons-frontend.git",
|
|
6
6
|
"author": "Amaljith K <amaljith.k@bigbinary.com>",
|
package/react-utils.d.ts
CHANGED
|
@@ -1,139 +1,309 @@
|
|
|
1
|
-
import dayjs from "dayjs";
|
|
2
1
|
import React from "react";
|
|
3
|
-
|
|
2
|
+
import { RouteProps } from "react-router-dom";
|
|
3
|
+
import { Notice } from "@honeybadger-io/js/dist/server/types/core/types";
|
|
4
|
+
import { History } from "history";
|
|
5
|
+
import { StoreApi, UseBoundStore } from "zustand";
|
|
4
6
|
/**
|
|
5
7
|
*
|
|
6
|
-
*
|
|
8
|
+
* ErrorBoundary which reports frontend errors to HoneyBadger
|
|
7
9
|
*
|
|
8
|
-
*
|
|
10
|
+
* This component will wrap its children with the error boundary provided by
|
|
9
11
|
*
|
|
10
|
-
*
|
|
12
|
+
* @honeybadger-io/react package. In this component, we will create a honeybadger
|
|
11
13
|
*
|
|
12
|
-
*
|
|
14
|
+
* configuration object using the API key, environment and project version which we
|
|
15
|
+
*
|
|
16
|
+
* obtained from the globalProps and pass the created object to error boundary
|
|
17
|
+
*
|
|
18
|
+
* provided by honeybadger. We are also filtering the false-positive errors using
|
|
19
|
+
*
|
|
20
|
+
* beforeNotify method.
|
|
21
|
+
*
|
|
22
|
+
* For global error handling, we need to wrap the Main component with this
|
|
23
|
+
*
|
|
24
|
+
* HoneybadgerErrorBoundary component as shown below.
|
|
13
25
|
*
|
|
14
26
|
* @example
|
|
15
27
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
28
|
+
* <HoneybadgerErrorBoundary
|
|
29
|
+
* ErrorComponent={ErrorComponent}
|
|
30
|
+
* filterErrors={notice => !/IgnorableError/.test(notice.message)}
|
|
31
|
+
* >
|
|
32
|
+
* <Main />
|
|
33
|
+
* </HoneybadgerErrorBoundary>
|
|
21
34
|
* @endexample
|
|
35
|
+
* ErrorComponent is the component which will be rendered when an error is thrown
|
|
36
|
+
*
|
|
37
|
+
* during rendering. This is an optional prop and if this prop is not provided then
|
|
38
|
+
*
|
|
39
|
+
* honeybadger will use DefaultErrorComponent for fallback UI.
|
|
40
|
+
*
|
|
41
|
+
* filterErrors is a function which takes the honeybadger notice as argument and
|
|
42
|
+
*
|
|
43
|
+
* returns a boolean. It should return true if the error is to be reported and
|
|
44
|
+
*
|
|
45
|
+
* false if not.
|
|
46
|
+
*
|
|
22
47
|
*/
|
|
23
|
-
export
|
|
48
|
+
export const HoneybadgerErrorBoundary: React.FC<{
|
|
49
|
+
ErrorComponent?: React.ReactNode | React.ComponentType<any>;
|
|
50
|
+
filterErrors?: (error: Notice) => boolean;
|
|
51
|
+
}>;
|
|
24
52
|
/**
|
|
25
53
|
*
|
|
26
|
-
*
|
|
54
|
+
* A route that will restrict access to it based on a specified condition.
|
|
27
55
|
*
|
|
28
|
-
*
|
|
56
|
+
* If the given condition is true, it acts identical to a normal route. Otherwise
|
|
29
57
|
*
|
|
30
|
-
*
|
|
58
|
+
* we have two options: it can either redirect user to a different path or it can
|
|
31
59
|
*
|
|
32
|
-
*
|
|
60
|
+
* render a supplied error page instead of the actual component in that route.
|
|
61
|
+
*
|
|
62
|
+
* If condition is not specified, it will assume the value of
|
|
63
|
+
*
|
|
64
|
+
* globalProps.authenticated by default.
|
|
65
|
+
*
|
|
66
|
+
* Here are some example use cases:
|
|
67
|
+
*
|
|
68
|
+
*/
|
|
69
|
+
export function PrivateRoute(props: {
|
|
70
|
+
condition?: boolean;
|
|
71
|
+
redirectRoute?: string;
|
|
72
|
+
errorPage?: React.ReactNode;
|
|
73
|
+
} & RouteProps): JSX.Element;
|
|
74
|
+
type OptionsType = {
|
|
75
|
+
root?: Element | null;
|
|
76
|
+
rootMargin?: String;
|
|
77
|
+
threshold?: Number | Number[];
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* This hook allows you to detect when a target element intersects with an ancestor
|
|
82
|
+
*
|
|
83
|
+
* element. In simple words, it lets us know whether the target element is visible
|
|
84
|
+
*
|
|
85
|
+
* on the screen.
|
|
86
|
+
*
|
|
87
|
+
* This hook will accept two arguments an element and an options object. Passing an
|
|
88
|
+
*
|
|
89
|
+
* element using ref requires you to pass ref.current as an argument or pass an
|
|
90
|
+
*
|
|
91
|
+
* element that you accessed via getElementById/querySelector etc. Since it uses
|
|
92
|
+
*
|
|
93
|
+
* Intersection Observer API you can pass observer options such as root,
|
|
94
|
+
*
|
|
95
|
+
* rootMargin, threshold, etc as the second argument. You can read more about
|
|
96
|
+
*
|
|
97
|
+
* Intersection Observer API and the supported options from
|
|
98
|
+
*
|
|
99
|
+
* MDN Intersection Observer API.
|
|
33
100
|
*
|
|
34
101
|
* @example
|
|
35
102
|
*
|
|
36
|
-
* const
|
|
37
|
-
*
|
|
38
|
-
*
|
|
103
|
+
* const ref = useRef(null);
|
|
104
|
+
* const isHeadingWrapperVisible = useIsElementVisibleInDom(ref.current, {
|
|
105
|
+
* threshold: 0.5,
|
|
106
|
+
* });
|
|
39
107
|
*
|
|
40
|
-
*
|
|
108
|
+
* return (
|
|
109
|
+
* <div>
|
|
110
|
+
* <div style={{ height: "100vh" }}>
|
|
111
|
+
* <h1>Scroll down to next section</h1>
|
|
112
|
+
* </div>
|
|
113
|
+
* <div ref={ref}>
|
|
114
|
+
* {isHeadingWrapperVisible && <h1>Hello I'm on the screen</h1>}
|
|
115
|
+
* </div>
|
|
116
|
+
* </div>
|
|
117
|
+
* );
|
|
41
118
|
* @endexample
|
|
42
119
|
*/
|
|
43
|
-
export function
|
|
120
|
+
export function useIsElementVisibleInDom(target: Element | null, options?: OptionsType): Boolean;
|
|
44
121
|
/**
|
|
45
122
|
*
|
|
46
|
-
*
|
|
123
|
+
* Wrap this hook around a frequently updating state to get the previous value
|
|
47
124
|
*
|
|
48
|
-
*
|
|
125
|
+
* until the updates are stopped. We can use this to limit the number of API calls
|
|
49
126
|
*
|
|
50
|
-
*
|
|
127
|
+
* triggered from a user input like search box.
|
|
128
|
+
*
|
|
129
|
+
* This hook accepts a value and a delay as an argument. The value returned by the
|
|
130
|
+
*
|
|
131
|
+
* hook will only reflect the latest value when the hook has not been called for
|
|
132
|
+
*
|
|
133
|
+
* the specified time period delay.
|
|
51
134
|
*
|
|
52
135
|
* @example
|
|
53
136
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
137
|
+
* const [searchKey, setSearchKey] = useState("");
|
|
138
|
+
* const debouncedSearchKey = useDebounce(searchKey, 300);
|
|
56
139
|
*
|
|
57
|
-
*
|
|
140
|
+
* useEffect(() => {
|
|
141
|
+
* // will be triggered with the latest value of input
|
|
142
|
+
* // only after 300ms after the user stops typing
|
|
143
|
+
* }, [debouncedSearchKey]);
|
|
144
|
+
*
|
|
145
|
+
* // component
|
|
146
|
+
* <Input onChange={e => setSearchKey(e.target.value)} />;
|
|
58
147
|
* @endexample
|
|
59
148
|
*/
|
|
60
|
-
export function
|
|
149
|
+
export function useDebounce<T>(value: T, delay?: number): T;
|
|
61
150
|
/**
|
|
62
151
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Returns the specified hardcoded data after some delay for simulating an API
|
|
152
|
+
* Similar to useDebounce but this hook accepts a function as an argument. That
|
|
66
153
|
*
|
|
67
|
-
*
|
|
154
|
+
* function will be executed only when the dependencies stops changing for a while.
|
|
68
155
|
*
|
|
69
|
-
* This function
|
|
156
|
+
* This hook accepts a function as an argument. It will return a debounced version
|
|
70
157
|
*
|
|
71
|
-
*
|
|
158
|
+
* of that function. The debounced function comes with a cancel method which can
|
|
72
159
|
*
|
|
73
|
-
*
|
|
160
|
+
* be used to cancel the delayed function invocation.
|
|
74
161
|
*
|
|
75
162
|
* @example
|
|
76
163
|
*
|
|
77
|
-
*
|
|
164
|
+
* const searchForProducts = useFuncDebounce(async key => {
|
|
165
|
+
* // this function will be triggered once after user stops typing for 300ms
|
|
166
|
+
* const products = await productsApi.fetch(key);
|
|
167
|
+
* // do something with the products
|
|
168
|
+
* }, 300);
|
|
169
|
+
*
|
|
170
|
+
* // component
|
|
171
|
+
* <Input onChange={e => searchForProducts(e.target.value)} />;
|
|
172
|
+
* <Button onClick={() => searchForProducts.cancel()}>Cancel search</Button>;
|
|
78
173
|
* @endexample
|
|
79
174
|
*/
|
|
80
|
-
export function
|
|
175
|
+
export function useFuncDebounce<F extends Function>(func: F, delay?: number): F & {
|
|
176
|
+
cancel: () => void;
|
|
177
|
+
};
|
|
81
178
|
/**
|
|
82
179
|
*
|
|
83
|
-
*
|
|
180
|
+
* This hook can be used to sync state to local storage so that it persists through
|
|
84
181
|
*
|
|
85
|
-
*
|
|
182
|
+
* a page refresh.
|
|
86
183
|
*
|
|
87
|
-
*
|
|
184
|
+
* Note: use this hook only if you need the component to re-render while
|
|
88
185
|
*
|
|
89
|
-
*
|
|
186
|
+
* updating the local storage value. If all you need is plain read and write
|
|
90
187
|
*
|
|
91
|
-
*
|
|
188
|
+
* operations on the localStorage, prefer the vanilla localStorage API functions.
|
|
92
189
|
*
|
|
93
|
-
*
|
|
190
|
+
* This hook is very similar to useState. The only difference is that you must
|
|
94
191
|
*
|
|
95
|
-
*
|
|
192
|
+
* pass the storage key in the 1st parameter so that we can default to that value
|
|
96
193
|
*
|
|
97
|
-
*
|
|
194
|
+
* on page load instead of specified initial value.
|
|
98
195
|
*
|
|
99
196
|
* @example
|
|
100
197
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* message: "URL copied successfully!",
|
|
104
|
-
* });
|
|
198
|
+
* // here "theme" is the storage key and "light" is the initial value
|
|
199
|
+
* const [theme, setTheme] = useLocalStorage("theme", "light");
|
|
105
200
|
*
|
|
106
|
-
*
|
|
201
|
+
* return (
|
|
202
|
+
* <Select
|
|
203
|
+
* options={[
|
|
204
|
+
* { label: "light", value: "light" },
|
|
205
|
+
* { label: "dark", value: "dark" },
|
|
206
|
+
* ]}
|
|
207
|
+
* // when we change the theme, the same will be stored in local storage with the key "theme"
|
|
208
|
+
* onChange={option => setTheme(option.value)}
|
|
209
|
+
* />
|
|
210
|
+
* );
|
|
107
211
|
* @endexample
|
|
212
|
+
* To remove the value from local storage we can call the setter method with null
|
|
213
|
+
*
|
|
214
|
+
* or undefined.
|
|
215
|
+
*
|
|
108
216
|
*/
|
|
109
|
-
export function
|
|
110
|
-
showToastr?: boolean;
|
|
111
|
-
message?: string;
|
|
112
|
-
}): void;
|
|
217
|
+
export function useLocalStorage<T>(key: string, initialValue?: T): [T, (value: T) => void];
|
|
113
218
|
/**
|
|
114
219
|
*
|
|
115
|
-
*
|
|
220
|
+
* A hook used to detect clicks outside of a specified element.
|
|
116
221
|
*
|
|
117
|
-
*
|
|
222
|
+
* This hook will accept two arguments: a ref and a handler. The ref is a reference
|
|
118
223
|
*
|
|
119
|
-
*
|
|
224
|
+
* to the element for which we want to detect outside clicks and handler is the
|
|
120
225
|
*
|
|
121
|
-
*
|
|
226
|
+
* action we want to perform when we click outside the element.
|
|
122
227
|
*
|
|
123
228
|
* @example
|
|
124
229
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
230
|
+
* const ref = useRef();
|
|
231
|
+
* const [isModalOpen, setIsModalOpen] = useState(false);
|
|
232
|
+
*
|
|
233
|
+
* useOnClickOutside(ref, () => setIsModalOpen(false));
|
|
234
|
+
*
|
|
235
|
+
* return (
|
|
236
|
+
* <>
|
|
237
|
+
* { When we click inside of this modal, it won't close. But when we click outside, it'll close! }
|
|
238
|
+
* {isModalOpen && (
|
|
239
|
+
* <div ref={ref}>
|
|
240
|
+
* <p>Hello from Modal!</p>
|
|
241
|
+
* </div>
|
|
242
|
+
* )}
|
|
243
|
+
* <button onClick={() => setIsModalOpen(true)}>Open Modal</button>
|
|
244
|
+
* </>
|
|
245
|
+
* );
|
|
134
246
|
* @endexample
|
|
135
247
|
*/
|
|
136
|
-
export function
|
|
248
|
+
export function useOnClickOutside<T>(ref: React.MutableRefObject<T>, handler: (event: MouseEvent | TouchEvent) => any);
|
|
249
|
+
/**
|
|
250
|
+
*
|
|
251
|
+
* A hook that returns the previous value of a variable before the last update.
|
|
252
|
+
*
|
|
253
|
+
* In the below example, when count is updated to 10, previousCount will be 0.
|
|
254
|
+
*
|
|
255
|
+
* If count is again updated to 20, previousCount will be 10.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
*
|
|
259
|
+
* const [count, setCount] = useState(0);
|
|
260
|
+
* const previousCount = usePrevious(count);
|
|
261
|
+
* @endexample
|
|
262
|
+
*/
|
|
263
|
+
export function usePrevious<T>(value: T): T;
|
|
264
|
+
/**
|
|
265
|
+
*
|
|
266
|
+
* A hook very similar to useEffect. The only difference is that it will not
|
|
267
|
+
*
|
|
268
|
+
* execute the callback in the initial mount. The callback will be triggered only
|
|
269
|
+
*
|
|
270
|
+
* if the dependencies change.
|
|
271
|
+
*
|
|
272
|
+
*/
|
|
273
|
+
export function useUpdateEffect(effect: () => void, deps: any[]): void;
|
|
274
|
+
/**
|
|
275
|
+
*
|
|
276
|
+
* This hook will return true if any API request fails with 404 or 403 status.
|
|
277
|
+
*
|
|
278
|
+
* Until any such API response is received, it will return false. It can be used
|
|
279
|
+
*
|
|
280
|
+
* to render ErrorPage conditionally. Refer:
|
|
281
|
+
*
|
|
282
|
+
* axios error response handler
|
|
283
|
+
*
|
|
284
|
+
* for more details.
|
|
285
|
+
*
|
|
286
|
+
*/
|
|
287
|
+
export function useDisplayErrorPage(): boolean;
|
|
288
|
+
/**
|
|
289
|
+
*
|
|
290
|
+
* A zustand store containing the status code of the latest API failed with 403 or
|
|
291
|
+
*
|
|
292
|
+
* 404 status (statusCode) and a boolean flag (showErrorPage) stating whether
|
|
293
|
+
*
|
|
294
|
+
* the error page should be rendered or not.
|
|
295
|
+
*
|
|
296
|
+
* This store is automatically managed by neeto-commons-frontend using its axios
|
|
297
|
+
*
|
|
298
|
+
* interceptors. You can also use this store if you need to display an error page
|
|
299
|
+
*
|
|
300
|
+
* from your frontend logic.
|
|
301
|
+
*
|
|
302
|
+
*/
|
|
303
|
+
export const useErrorDisplayStore: UseBoundStore<StoreApi<{
|
|
304
|
+
showErrorPage: boolean;
|
|
305
|
+
statusCode: number;
|
|
306
|
+
}>>;
|
|
137
307
|
type TimerType = {
|
|
138
308
|
lastUpdated: number;
|
|
139
309
|
interval: number;
|
|
@@ -176,168 +346,263 @@ type TimerType = {
|
|
|
176
346
|
* @endexample
|
|
177
347
|
*/
|
|
178
348
|
export function useTimer(interval: number): TimerType;
|
|
179
|
-
type
|
|
180
|
-
export const timeFormat: {
|
|
181
|
-
fromNow: (time: DateTimeType) => string;
|
|
182
|
-
time: (time: DateTimeType) => string;
|
|
183
|
-
date: (time: DateTimeType) => string;
|
|
184
|
-
dateWeek: (time: DateTimeType) => string;
|
|
185
|
-
dateWeekWithoutYear: (time: DateTimeType) => string;
|
|
186
|
-
dateTime: (time: DateTimeType) => string;
|
|
187
|
-
dateWeekTime: (time: DateTimeType) => string;
|
|
188
|
-
extended: (time: DateTimeType) => string;
|
|
189
|
-
};
|
|
190
|
-
export const dateFormat: typeof timeFormat;
|
|
349
|
+
type ZustandConfigType = (set: (data: any) => void, get: () => any, api: any) => any;
|
|
191
350
|
/**
|
|
192
351
|
*
|
|
193
|
-
*
|
|
352
|
+
* A zustand middleware function that prevents the actions from getting
|
|
353
|
+
*
|
|
354
|
+
* overwritten.
|
|
355
|
+
*
|
|
356
|
+
* Usage:
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
*
|
|
360
|
+
* const useStore = create(
|
|
361
|
+
* withImmutableActions(set => ({
|
|
362
|
+
* value: 10,
|
|
363
|
+
* // other properties ...
|
|
364
|
+
* setValue: ({ value }) => set({ value }),
|
|
365
|
+
* setGlobalState: set,
|
|
366
|
+
* // other actions ...
|
|
367
|
+
* }))
|
|
368
|
+
* );
|
|
369
|
+
* @endexample
|
|
370
|
+
* In the above example, usages like this will throw an error, because, actions
|
|
371
|
+
*
|
|
372
|
+
* should not be overwritten:
|
|
194
373
|
*
|
|
195
|
-
*
|
|
374
|
+
* @example
|
|
196
375
|
*
|
|
197
|
-
*
|
|
376
|
+
* setGlobalState({ value: 0, setValue: () => {} });
|
|
377
|
+
* @endexample
|
|
378
|
+
* Actions can be assigned its own value. This is to ensure that curried ramda
|
|
198
379
|
*
|
|
199
|
-
*
|
|
380
|
+
* functions can be used in conjunction with zustand action. For example, this
|
|
200
381
|
*
|
|
201
|
-
*
|
|
382
|
+
* usage will not throw any error:
|
|
202
383
|
*
|
|
203
|
-
*
|
|
384
|
+
* @example
|
|
204
385
|
*
|
|
205
|
-
*
|
|
386
|
+
* setGlobalState(state => ({ value: 0, setValue: state.setValue }));
|
|
387
|
+
* @endexample
|
|
388
|
+
* The 2nd parameter to overwrite the entire state will be ignored. Both of the
|
|
206
389
|
*
|
|
207
|
-
*
|
|
390
|
+
* following lines of code work identical to each other:
|
|
208
391
|
*
|
|
209
392
|
* @example
|
|
210
393
|
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* toLocale(1000000.987, { maximumFractionDigits: 2 }); // "1,000,000.99"
|
|
214
|
-
* toLocale(1000000.987, {
|
|
215
|
-
* currencyDisplay: "narrowSymbol",
|
|
216
|
-
* style: "currency",
|
|
217
|
-
* currency: "INR",
|
|
218
|
-
* }); // "₹1,000,000.99"
|
|
394
|
+
* setGlobalState(state => ({ value: 0 }), true);
|
|
395
|
+
* setGlobalState(state => ({ value: 0 }));
|
|
219
396
|
* @endexample
|
|
220
397
|
*/
|
|
221
|
-
export function
|
|
222
|
-
type
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
depth?: number | false | undefined;
|
|
226
|
-
decoder?: ((str: string, defaultDecoder: any, charset: string, type: "key" | "value") => any) | undefined;
|
|
227
|
-
arrayLimit?: number | undefined;
|
|
228
|
-
parseArrays?: boolean | undefined;
|
|
229
|
-
allowDots?: boolean | undefined;
|
|
230
|
-
plainObjects?: boolean | undefined;
|
|
231
|
-
allowPrototypes?: boolean | undefined;
|
|
232
|
-
parameterLimit?: number | undefined;
|
|
233
|
-
strictNullHandling?: boolean | undefined;
|
|
234
|
-
ignoreQueryPrefix?: boolean | undefined;
|
|
235
|
-
charset?: "utf-8" | "iso-8859-1" | undefined;
|
|
236
|
-
charsetSentinel?: boolean | undefined;
|
|
237
|
-
interpretNumericEntities?: boolean | undefined;
|
|
398
|
+
export function withImmutableActions(config: ZustandConfigType): ZustandConfigType;
|
|
399
|
+
export declare type ZustandStoreHook = {
|
|
400
|
+
(selector: (state: any) => any, comparator?: (a: any, b: any) => boolean): any;
|
|
401
|
+
(): any;
|
|
238
402
|
};
|
|
239
|
-
|
|
240
|
-
|
|
403
|
+
/**
|
|
404
|
+
*
|
|
405
|
+
* This hook calls onSubmit callback when Enter (aka Return) key is pressed. It
|
|
406
|
+
*
|
|
407
|
+
* will not submit when Shift + Enter is pressed. Shift + Enter can be used to
|
|
408
|
+
*
|
|
409
|
+
* add new lines to text area in the form.
|
|
410
|
+
*
|
|
411
|
+
* The hook accepts a callback, onSubmit, which will be called with no arguments
|
|
412
|
+
*
|
|
413
|
+
* when Enter key press is detected.
|
|
414
|
+
*
|
|
415
|
+
* The hook returns a ref. This need to be attached to the input element to be
|
|
416
|
+
*
|
|
417
|
+
* listened to.
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
*
|
|
421
|
+
* const inputRef = useFieldSubmit(() => {
|
|
422
|
+
* const inputValue = inputRef.current.value;
|
|
423
|
+
* console.log(inputValue);
|
|
424
|
+
* });
|
|
425
|
+
*
|
|
426
|
+
* return <textarea ref={inputRef} />;
|
|
427
|
+
* @endexample
|
|
428
|
+
*/
|
|
429
|
+
export function useFieldSubmit(onSubmit: () => any): {
|
|
430
|
+
current: HTMLInputElement & HTMLTextAreaElement;
|
|
241
431
|
};
|
|
242
432
|
/**
|
|
243
433
|
*
|
|
244
|
-
*
|
|
434
|
+
* An HOC which sets the browser title with the given value when the wrapped
|
|
245
435
|
*
|
|
246
|
-
*
|
|
436
|
+
* component is rendered. If title is not explicitly provided, it will render
|
|
247
437
|
*
|
|
248
|
-
*
|
|
438
|
+
* globalProps.appName as the page title.
|
|
249
439
|
*
|
|
250
440
|
* @example
|
|
251
441
|
*
|
|
252
|
-
* //
|
|
253
|
-
*
|
|
442
|
+
* // assume this code in neetoStore
|
|
443
|
+
* const ProductsPage = props => <>Your page content here</>;
|
|
444
|
+
* export default withTitle(ProductsPage, "All products");
|
|
445
|
+
* // will set the browser title to `All products | neetoStore` when this page is rendered.
|
|
446
|
+
* @endexample
|
|
447
|
+
*/
|
|
448
|
+
export function withTitle(Component: () => JSX.Element, title?: string): (props) => JSX.Element;
|
|
449
|
+
/**
|
|
450
|
+
*
|
|
451
|
+
* A browser push notifications utility function which asks the user permissions to send notifications and then register the browser with the notification service.
|
|
452
|
+
*
|
|
453
|
+
* After the user logs in, we need to ask the user permissions to send notifications and then register the browser with the notification service.
|
|
454
|
+
*
|
|
455
|
+
* You can use the registerBrowserNotifications utility function to do this. It can be called on any event after login based on the application's logic and requirement.
|
|
456
|
+
*
|
|
457
|
+
* Here as an example, we are calling registerBrowserNotifications method inside the Login component after the Authentication API request. This helps to associate the browser for that particular user.
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
*
|
|
461
|
+
* import { registerBrowserNotifications } from "neetocommons/react-utils";
|
|
254
462
|
*
|
|
255
|
-
*
|
|
463
|
+
* const handleLogin = async () => {
|
|
464
|
+
* try {
|
|
465
|
+
* // Authentication API request
|
|
466
|
+
* await registerBrowserNotifications();
|
|
467
|
+
* history.push(DASHBOARD_URL);
|
|
468
|
+
* } catch {}
|
|
469
|
+
* };
|
|
256
470
|
* @endexample
|
|
471
|
+
* The above mentioned feature is currently supported for chromium-based browsers.
|
|
472
|
+
*
|
|
473
|
+
* Safari (iOS) is currently WIP.
|
|
474
|
+
*
|
|
475
|
+
* Any other browser which is not mentioned in above will be considered as
|
|
476
|
+
*
|
|
477
|
+
* unsupported.
|
|
478
|
+
*
|
|
257
479
|
*/
|
|
258
|
-
export function
|
|
480
|
+
export async function registerBrowserNotifications(): Promise<void>;
|
|
259
481
|
/**
|
|
260
482
|
*
|
|
261
|
-
*
|
|
483
|
+
* A browser push notifications utility function which destroys the browser subscriptions from the user's devices. This helps in unsubscribing from browser push notifications.
|
|
262
484
|
*
|
|
263
|
-
*
|
|
485
|
+
* When the browser subscriptions expires for the user's devices or when the user decides to logout,then destroy the generated browser subscription for the user.
|
|
264
486
|
*
|
|
265
|
-
*
|
|
487
|
+
* You can use the destroyBrowserSubscription utility function to do this. It can be called on any event before logout based on the application's logic and requirement.
|
|
488
|
+
*
|
|
489
|
+
* Here as an example:
|
|
490
|
+
*
|
|
491
|
+
* In the Logout component, we are calling destroyBrowserSubscription method before the Logout API request. This helps to destroy the browser subscription from the user's devices.
|
|
266
492
|
*
|
|
267
493
|
* @example
|
|
268
494
|
*
|
|
269
|
-
*
|
|
495
|
+
* import {destroyBrowserSubscription } from "neetocommons/react-utils";
|
|
496
|
+
*
|
|
497
|
+
* const handleLogout = async () => {
|
|
498
|
+
* try {
|
|
499
|
+
* await destroyBrowserSubscription(); //Before logout request
|
|
500
|
+
* // Logout API request
|
|
501
|
+
* window.location.href = LOGIN_PATH;
|
|
502
|
+
* } catch {}
|
|
503
|
+
* };
|
|
270
504
|
* @endexample
|
|
505
|
+
* The above mentioned feature is currently supported for chromium-based browsers.
|
|
506
|
+
*
|
|
507
|
+
* Safari (iOS) is currently WIP.
|
|
508
|
+
*
|
|
509
|
+
* Any other browser which is not mentioned in above will be considered as
|
|
510
|
+
*
|
|
511
|
+
* unsupported.
|
|
512
|
+
*
|
|
271
513
|
*/
|
|
272
|
-
export function
|
|
514
|
+
export async function destroyBrowserSubscription(): Promise<void>;
|
|
273
515
|
/**
|
|
274
516
|
*
|
|
275
|
-
* Curried:
|
|
517
|
+
* Curried: true
|
|
518
|
+
*
|
|
519
|
+
* This function can be used to handle onClick actions that redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event is recieved. Otherwise, simply redirects to the provided URL in the same tab. URL can be passed as string or a history location object can be passed instead.
|
|
520
|
+
*
|
|
521
|
+
* Usage:
|
|
276
522
|
*
|
|
277
|
-
*
|
|
523
|
+
* @example
|
|
278
524
|
*
|
|
279
|
-
*
|
|
525
|
+
* handleMetaClick(history, "/dashboard", e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise simply redirects to "/dashboard".
|
|
526
|
+
* handleMetaClick(history, {pathname: "/dashboard", state: "abc"}, e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise, redirects to "/dashboard" by preserving the state.
|
|
527
|
+
*
|
|
528
|
+
* @endexample
|
|
529
|
+
*/
|
|
530
|
+
export function handleMetaClick(history: History, params: string | object, event: React.MouseEvent<HTMLElement, MouseEvent>): void;
|
|
531
|
+
/**
|
|
280
532
|
*
|
|
281
|
-
*
|
|
533
|
+
* Curried: true
|
|
282
534
|
*
|
|
283
|
-
*
|
|
535
|
+
* This function can be used to handle onClick actions that redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event is recieved. Otherwise, simply redirects to the provided URL in the same tab. URL can be passed as string or a history location object can be passed instead.
|
|
284
536
|
*
|
|
285
537
|
* Usage:
|
|
286
538
|
*
|
|
287
539
|
* @example
|
|
288
540
|
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
* // do something with the products
|
|
293
|
-
* }, 300);
|
|
294
|
-
* <input onChange={e => searchForProducts(e.target.value)} />;
|
|
541
|
+
* handleMetaClick(history, "/dashboard", e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise simply redirects to "/dashboard".
|
|
542
|
+
* handleMetaClick(history, {pathname: "/dashboard", state: "abc"}, e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise, redirects to "/dashboard" by preserving the state.
|
|
543
|
+
*
|
|
295
544
|
* @endexample
|
|
296
545
|
*/
|
|
297
|
-
export function
|
|
546
|
+
export function handleMetaClick(history: History, params: string | object): (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
298
547
|
/**
|
|
299
548
|
*
|
|
300
|
-
* Curried:
|
|
549
|
+
* Curried: true
|
|
301
550
|
*
|
|
302
|
-
* This function
|
|
551
|
+
* This function can be used to handle onClick actions that redirects to a URL. It opens up the URL in a new tab if ctrl/cmd + click event is recieved. Otherwise, simply redirects to the provided URL in the same tab. URL can be passed as string or a history location object can be passed instead.
|
|
303
552
|
*
|
|
304
553
|
* Usage:
|
|
305
554
|
*
|
|
306
555
|
* @example
|
|
307
556
|
*
|
|
308
|
-
*
|
|
557
|
+
* handleMetaClick(history, "/dashboard", e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise simply redirects to "/dashboard".
|
|
558
|
+
* handleMetaClick(history, {pathname: "/dashboard", state: "abc"}, e); //Opens "/dashboard" in a new tab if metaKey/CtrlKey is pressed. Otherwise, redirects to "/dashboard" by preserving the state.
|
|
559
|
+
*
|
|
309
560
|
* @endexample
|
|
310
561
|
*/
|
|
311
|
-
export function
|
|
562
|
+
export function handleMetaClick(history: History): (params: string | object, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
312
563
|
/**
|
|
313
564
|
*
|
|
314
565
|
* Curried: false
|
|
315
566
|
*
|
|
316
|
-
* This function
|
|
317
|
-
*
|
|
318
|
-
* permissions.
|
|
567
|
+
* This function can be used to check whether an onClick event has metaKey or ctrlKey pressed.
|
|
319
568
|
*
|
|
320
569
|
* Usage:
|
|
321
570
|
*
|
|
322
571
|
* @example
|
|
323
572
|
*
|
|
324
|
-
*
|
|
573
|
+
* isMetaKeyPressed(event); //returns true if "event.metaKey || event.ctrlKey" is true, otherwise returns false.
|
|
574
|
+
*
|
|
325
575
|
* @endexample
|
|
326
576
|
*/
|
|
327
|
-
export function
|
|
577
|
+
export function isMetaKeyPressed(event: React.MouseEvent<HTMLElement, MouseEvent>): boolean;
|
|
578
|
+
type ConfigType = {
|
|
579
|
+
mode?: "default" | "global" | "scoped";
|
|
580
|
+
unbindOnUnmount?: boolean;
|
|
581
|
+
enabled?: boolean;
|
|
582
|
+
};
|
|
328
583
|
/**
|
|
329
584
|
*
|
|
330
|
-
*
|
|
585
|
+
* This is a configurable hook used for handling hotkeys in an application. We
|
|
331
586
|
*
|
|
332
|
-
*
|
|
587
|
+
* specify a hotkey and handler, whenever the hotkey is pressed by the user the
|
|
333
588
|
*
|
|
334
|
-
*
|
|
589
|
+
* corresponding handler will be invoked.
|
|
335
590
|
*
|
|
336
|
-
*
|
|
591
|
+
* This hook accepts 3 arguments hotkey, handler & config.
|
|
337
592
|
*
|
|
338
593
|
* @example
|
|
339
594
|
*
|
|
340
|
-
*
|
|
595
|
+
* // openSidebar function will only be called if the user is focused inside the textarea and performs the key combination.
|
|
596
|
+
* const ref = useHotKeys("command+shift+r", openSidebar, {
|
|
597
|
+
* mode: "scoped",
|
|
598
|
+
* });
|
|
599
|
+
*
|
|
600
|
+
* return (
|
|
601
|
+
* <div>
|
|
602
|
+
* <div>Hello world</div>
|
|
603
|
+
* <textarea ref={ref}></textarea>
|
|
604
|
+
* </div>
|
|
605
|
+
* );
|
|
341
606
|
* @endexample
|
|
342
607
|
*/
|
|
343
|
-
export function
|
|
608
|
+
export function useHotKeys(hotkey: string | string[], handler: (event: React.KeyboardEvent) => void, config?: ConfigType): React.MutableRefObject | null;
|