@leancodepl/utils 8.5.0 → 8.5.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/index.esm.js ADDED
@@ -0,0 +1,406 @@
1
+ import invariant from 'tiny-invariant';
2
+ import { useState, useCallback, useMemo } from 'react';
3
+
4
+ /**
5
+ * Adds a prefix to all keys in an object, creating a new object with prefixed keys.
6
+ *
7
+ * @template T - The type of the input object
8
+ * @template TPrefix - The type of the prefix string
9
+ * @param object - The object whose keys will be prefixed
10
+ * @param prefix - The prefix string to add to each key
11
+ * @returns A new object with all keys prefixed
12
+ * @example
13
+ * ```typescript
14
+ * const apiData = { userId: 1, userName: 'John' };
15
+ * const prefixed = addPrefix(apiData, 'api_');
16
+ * // Result: { api_userId: 1, api_userName: 'John' }
17
+ * ```
18
+ */ function addPrefix(object, prefix) {
19
+ return Object.fromEntries(Object.entries(object).map(([key, value])=>[
20
+ `${prefix}${key}`,
21
+ value
22
+ ]));
23
+ }
24
+
25
+ function transformFirst(value, transformFn) {
26
+ if (value.length === 0) {
27
+ return "";
28
+ }
29
+ return transformFn(value[0]) + value.slice(1);
30
+ }
31
+ /**
32
+ * Converts the first character of a string to lowercase.
33
+ *
34
+ * @param value - The string to transform
35
+ * @returns The string with the first character in lowercase
36
+ * @example
37
+ * ```typescript
38
+ * const result = toLowerFirst('UserName');
39
+ * // Result: 'userName'
40
+ * ```
41
+ */ function toLowerFirst(value) {
42
+ return transformFirst(value, (value)=>value.toLowerCase());
43
+ }
44
+ /**
45
+ * Converts the first character of a string to uppercase.
46
+ *
47
+ * @param value - The string to transform
48
+ * @returns The string with the first character in uppercase
49
+ * @example
50
+ * ```typescript
51
+ * const result = toUpperFirst('userName');
52
+ * // Result: 'UserName'
53
+ * ```
54
+ */ function toUpperFirst(value) {
55
+ return transformFirst(value, (value)=>value.toUpperCase());
56
+ }
57
+
58
+ function _extends() {
59
+ _extends = Object.assign || function assign(target) {
60
+ for(var i = 1; i < arguments.length; i++){
61
+ var source = arguments[i];
62
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
63
+ }
64
+ return target;
65
+ };
66
+ return _extends.apply(this, arguments);
67
+ }
68
+
69
+ function transformDeep(value, mode) {
70
+ if (value === null || value === undefined) {
71
+ return undefined;
72
+ }
73
+ if (Array.isArray(value)) {
74
+ return value.map((val)=>transformDeep(val, mode));
75
+ }
76
+ if (typeof value === "object") {
77
+ const transformKey = mode === "capitalize" ? toUpperFirst : toLowerFirst;
78
+ return Object.entries(value).reduce((accumulator, [key, value])=>_extends({}, accumulator, {
79
+ [transformKey(key)]: transformDeep(value, mode)
80
+ }), {});
81
+ }
82
+ return value;
83
+ }
84
+ /**
85
+ * Recursively transforms all object keys to use uncapitalized (camelCase) format.
86
+ *
87
+ * @template T - The type of the input value
88
+ * @param value - The value to transform (can be object, array, or primitive)
89
+ * @returns A new object with all keys converted to camelCase
90
+ * @example
91
+ * ```typescript
92
+ * const serverData = { UserId: 1, UserName: 'John', Profile: { FirstName: 'John' } };
93
+ * const clientData = uncapitalizeDeep(serverData);
94
+ * // Result: { userId: 1, userName: 'John', profile: { firstName: 'John' } }
95
+ * ```
96
+ */ function uncapitalizeDeep(value) {
97
+ return transformDeep(value, "uncapitalize");
98
+ }
99
+ /**
100
+ * Recursively transforms all object keys to use capitalized (PascalCase) format.
101
+ *
102
+ * @template T - The type of the input value
103
+ * @param value - The value to transform (can be object, array, or primitive)
104
+ * @returns A new object with all keys converted to PascalCase
105
+ * @example
106
+ * ```typescript
107
+ * const clientData = { userId: 1, userName: 'John', profile: { firstName: 'John' } };
108
+ * const serverData = capitalizeDeep(clientData);
109
+ * // Result: { UserId: 1, UserName: 'John', Profile: { FirstName: 'John' } }
110
+ * ```
111
+ */ function capitalizeDeep(value) {
112
+ return transformDeep(value, "capitalize");
113
+ }
114
+
115
+ /**
116
+ * Asserts that a value is not undefined. Throws an error if the value is undefined.
117
+ * This is a type assertion function that narrows the type to exclude undefined.
118
+ *
119
+ * @template T - The type of the value being checked
120
+ * @param value - The value to check for undefined
121
+ * @param message - Optional error message to use if assertion fails
122
+ * @throws {Error} When the value is undefined
123
+ * @example
124
+ * ```typescript
125
+ * function processUser(user?: User) {
126
+ * assertDefined(user);
127
+ * return user.name; // TypeScript knows user is defined
128
+ * }
129
+ * ```
130
+ */ function assertDefined(value, message) {
131
+ invariant(value !== undefined, message);
132
+ }
133
+
134
+ /**
135
+ * Asserts that a value is not null. Throws an error if the value is null.
136
+ * This is a type assertion function that narrows the type to exclude null.
137
+ *
138
+ * @template T - The type of the value being checked
139
+ * @param value - The value to check for null
140
+ * @param message - Optional error message to use if assertion fails
141
+ * @throws {Error} When the value is null
142
+ * @example
143
+ * ```typescript
144
+ * function processData(data: string | null) {
145
+ * assertNotNull(data);
146
+ * return data.toUpperCase(); // TypeScript knows data is not null
147
+ * }
148
+ * ```
149
+ */ function assertNotNull(value, message) {
150
+ invariant(value !== null, message);
151
+ }
152
+
153
+ /**
154
+ * Asserts that a value is not null or undefined. Throws an error if the value is null or undefined.
155
+ * This is a type assertion function that narrows the type to exclude null and undefined.
156
+ *
157
+ * @template T - The type of the value being checked
158
+ * @param value - The value to check for null or undefined
159
+ * @param message - Optional error message to use if assertion fails
160
+ * @throws {Error} When the value is null or undefined
161
+ * @example
162
+ * ```typescript
163
+ * function processOptionalData(data?: string | null) {
164
+ * assertNotEmpty(data);
165
+ * return data.toUpperCase(); // TypeScript knows data is not null/undefined
166
+ * }
167
+ * ```
168
+ */ function assertNotEmpty(value, message) {
169
+ invariant(value !== null && value !== undefined, message);
170
+ }
171
+
172
+ /**
173
+ * Ensures that a value is defined, returning it if defined or throwing an error if undefined.
174
+ *
175
+ * @template T - The type of the value being checked
176
+ * @param value - The value to ensure is defined
177
+ * @param message - Optional error message to use if the value is undefined
178
+ * @returns The value if it is defined
179
+ * @throws {Error} When the value is undefined
180
+ * @example
181
+ * ```typescript
182
+ * function processUser(user?: User) {
183
+ * const definedUser = ensureDefined(user);
184
+ * return definedUser.name; // definedUser is guaranteed to be defined
185
+ * }
186
+ * ```
187
+ */ function ensureDefined(value, message) {
188
+ assertDefined(value, message);
189
+ return value;
190
+ }
191
+
192
+ /**
193
+ * Ensures that a value is not null, returning it if not null or throwing an error if null.
194
+ * Unlike assertNotNull, this function returns the value for use in expressions.
195
+ *
196
+ * @template T - The type of the value being checked
197
+ * @param value - The value to ensure is not null
198
+ * @param message - Optional error message to use if the value is null
199
+ * @returns The value if it is not null
200
+ * @throws {Error} When the value is null
201
+ * @example
202
+ * ```typescript
203
+ * function processData(data: string | null) {
204
+ * const nonNullData = ensureNotNull(data);
205
+ * return nonNullData.toUpperCase(); // nonNullData is guaranteed to be not null
206
+ * }
207
+ * ```
208
+ */ function ensureNotNull(value, message) {
209
+ assertNotNull(value, message);
210
+ return value;
211
+ }
212
+
213
+ /**
214
+ * Ensures that a value is not null or undefined, returning it if valid or throwing an error if empty.
215
+ *
216
+ * @template T - The type of the value being checked
217
+ * @param value - The value to ensure is not null or undefined
218
+ * @param message - Optional error message to use if the value is null or undefined
219
+ * @returns The value if it is not null or undefined
220
+ * @throws {Error} When the value is null or undefined
221
+ * @example
222
+ * ```typescript
223
+ * function processOptionalData(data?: string | null) {
224
+ * const validData = ensureNotEmpty(data);
225
+ * return validData.toUpperCase(); // validData is guaranteed to be not null/undefined
226
+ * }
227
+ * ```
228
+ */ function ensureNotEmpty(value, message) {
229
+ assertNotEmpty(value, message);
230
+ return value;
231
+ }
232
+
233
+ function downloadFile(dataOrUrl, options = {}) {
234
+ if (typeof dataOrUrl === "string") {
235
+ const { name } = options;
236
+ const a = document.createElement("a");
237
+ a.href = dataOrUrl;
238
+ a.target = "_blank";
239
+ if (name) a.download = name;
240
+ a.click();
241
+ } else {
242
+ const url = URL.createObjectURL(dataOrUrl);
243
+ downloadFile(url, options);
244
+ URL.revokeObjectURL(url);
245
+ }
246
+ }
247
+
248
+ /**
249
+ * React hook for tracking async task execution with loading state.
250
+ * Automatically manages a loading counter and provides a wrapper function for tasks.
251
+ *
252
+ * @returns A tuple containing [isLoading: boolean, runInTask: function]
253
+ * @example
254
+ * ```typescript
255
+ * function MyComponent() {
256
+ * const [isLoading, runInTask] = useRunInTask();
257
+ *
258
+ * const handleSave = async () => {
259
+ * await runInTask(async () => {
260
+ * await saveData();
261
+ * });
262
+ * };
263
+ *
264
+ * return (
265
+ * <button onClick={handleSave} disabled={isLoading}>
266
+ * {isLoading ? 'Saving...' : 'Save'}
267
+ * </button>
268
+ * );
269
+ * }
270
+ * ```
271
+ */ function useRunInTask() {
272
+ const [runningTasks, setRunningTasks] = useState(0);
273
+ const runInTask = useCallback(async (task)=>{
274
+ setRunningTasks((runningTasks)=>runningTasks + 1);
275
+ try {
276
+ return await task();
277
+ } finally{
278
+ setRunningTasks((runningTasks)=>runningTasks - 1);
279
+ }
280
+ }, []);
281
+ return [
282
+ runningTasks > 0,
283
+ runInTask
284
+ ];
285
+ }
286
+
287
+ function useBoundRunInTask(block) {
288
+ const [isRunning, runInTask] = useRunInTask();
289
+ const runBlockInTask = useMemo(()=>block ? (...args)=>runInTask(()=>block(...args)) : undefined, [
290
+ block,
291
+ runInTask
292
+ ]);
293
+ return [
294
+ isRunning,
295
+ runBlockInTask
296
+ ];
297
+ }
298
+
299
+ /**
300
+ * React hook for generating keys based on current route matches.
301
+ *
302
+ * @template TKey - The type of the route keys
303
+ * @param routeMatches - Record of route keys to match objects or arrays
304
+ * @returns Array of active route keys
305
+ * @example
306
+ * ```typescript
307
+ * function NavigationComponent() {
308
+ * const routeMatches = {
309
+ * home: useRouteMatch('/'),
310
+ * about: useRouteMatch('/about'),
311
+ * contact: useRouteMatch('/contact')
312
+ * };
313
+ *
314
+ * const activeRoutes = useKeyByRoute(routeMatches);
315
+ * // Returns ['home'] if on home page, ['about'] if on about page, etc.
316
+ *
317
+ * return (
318
+ * <nav>
319
+ * {activeRoutes.map(route => (
320
+ * <span key={route}>Active: {route}</span>
321
+ * ))}
322
+ * </nav>
323
+ * );
324
+ * }
325
+ * ```
326
+ */ function useKeyByRoute(routeMatches) {
327
+ const keys = [];
328
+ for(const key in routeMatches){
329
+ const matches = routeMatches[key];
330
+ if (Array.isArray(matches) ? matches.some((match)=>match !== null) : matches !== null) {
331
+ keys.push(key);
332
+ }
333
+ }
334
+ return keys;
335
+ }
336
+
337
+ /**
338
+ * React hook for boolean state management helpers.
339
+ *
340
+ * @param set - The state setter function from useState
341
+ * @returns A tuple containing [setTrue: function, setFalse: function]
342
+ * @example
343
+ * ```typescript
344
+ * function MyComponent() {
345
+ * const [isVisible, setIsVisible] = useState(false);
346
+ * const [show, hide] = useSetUnset(setIsVisible);
347
+ *
348
+ * return (
349
+ * <div>
350
+ * <button onClick={show}>Show</button>
351
+ * <button onClick={hide}>Hide</button>
352
+ * {isVisible && <div>Content is visible</div>}
353
+ * </div>
354
+ * );
355
+ * }
356
+ * ```
357
+ */ function useSetUnset(set) {
358
+ return [
359
+ useCallback(()=>set(true), [
360
+ set
361
+ ]),
362
+ useCallback(()=>set(false), [
363
+ set
364
+ ])
365
+ ];
366
+ }
367
+
368
+ /**
369
+ * React hook for managing dialog state with optional callback after closing.
370
+ * Provides convenient open/close functions and tracks the dialog's open state.
371
+ *
372
+ * @param onAfterClose - Optional callback function to execute after the dialog closes
373
+ * @returns Object containing dialog state and control functions
374
+ * @example
375
+ * ```typescript
376
+ * function MyComponent() {
377
+ * const { isDialogOpen, openDialog, closeDialog } = useDialog(() => {
378
+ * console.log('Dialog closed');
379
+ * });
380
+ *
381
+ * return (
382
+ * <div>
383
+ * <button onClick={openDialog}>Open Dialog</button>
384
+ * {isDialogOpen && <Dialog onClose={closeDialog} />}
385
+ * </div>
386
+ * );
387
+ * }
388
+ * ```
389
+ */ function useDialog(onAfterClose) {
390
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
391
+ const [openDialog, closeDialog] = useSetUnset(setIsDialogOpen);
392
+ const close = useCallback(()=>{
393
+ closeDialog();
394
+ if (onAfterClose) setTimeout(onAfterClose);
395
+ }, [
396
+ closeDialog,
397
+ onAfterClose
398
+ ]);
399
+ return {
400
+ isDialogOpen,
401
+ openDialog,
402
+ closeDialog: close
403
+ };
404
+ }
405
+
406
+ export { addPrefix, assertDefined, assertNotEmpty, assertNotNull, capitalizeDeep, downloadFile, ensureDefined, ensureNotEmpty, ensureNotNull, toLowerFirst, toUpperFirst, uncapitalizeDeep, useBoundRunInTask, useDialog, useKeyByRoute, useRunInTask, useSetUnset };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leancodepl/utils",
3
- "version": "8.5.0",
3
+ "version": "8.5.1",
4
4
  "license": "Apache-2.0",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -10,7 +10,7 @@
10
10
  "node": ">=18.0.0"
11
11
  },
12
12
  "dependencies": {
13
- "@leancodepl/api-date": "8.5.0",
13
+ "@leancodepl/api-date": "8.5.1",
14
14
  "tiny-invariant": ">=1.3.1"
15
15
  },
16
16
  "peerDependencies": {
@@ -39,11 +39,6 @@
39
39
  "name": "LeanCode",
40
40
  "url": "https://leancode.co"
41
41
  },
42
- "files": [
43
- "dist",
44
- "README.md",
45
- "CHANGELOG.md"
46
- ],
47
42
  "sideEffects": false,
48
43
  "exports": {
49
44
  "./package.json": "./package.json",
package/src/index.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export * from "./lib/types";
2
+ export * from "./lib/addPrefix";
3
+ export * from "./lib/transformFirst";
4
+ export * from "./lib/transformDeep";
5
+ export * from "./lib/assertDefined";
6
+ export * from "./lib/assertNotNull";
7
+ export * from "./lib/assertNotEmpty";
8
+ export * from "./lib/ensureDefined";
9
+ export * from "./lib/ensureNotNull";
10
+ export * from "./lib/ensureNotEmpty";
11
+ export * from "./lib/downloadFile";
12
+ export * from "./lib/hooks/useRunInTask";
13
+ export * from "./lib/hooks/useBoundRunInTask";
14
+ export * from "./lib/hooks/useKeyByRoute";
15
+ export * from "./lib/hooks/useSetUnset";
16
+ export * from "./lib/hooks/useDialog";
@@ -0,0 +1,20 @@
1
+ type PrefixWith<T, TPrefix extends string> = {
2
+ [K in keyof T as K extends string ? `${TPrefix}${K}` : never]: T[K];
3
+ };
4
+ /**
5
+ * Adds a prefix to all keys in an object, creating a new object with prefixed keys.
6
+ *
7
+ * @template T - The type of the input object
8
+ * @template TPrefix - The type of the prefix string
9
+ * @param object - The object whose keys will be prefixed
10
+ * @param prefix - The prefix string to add to each key
11
+ * @returns A new object with all keys prefixed
12
+ * @example
13
+ * ```typescript
14
+ * const apiData = { userId: 1, userName: 'John' };
15
+ * const prefixed = addPrefix(apiData, 'api_');
16
+ * // Result: { api_userId: 1, api_userName: 'John' }
17
+ * ```
18
+ */
19
+ export declare function addPrefix<T extends object, TPrefix extends string>(object: T, prefix: TPrefix): PrefixWith<T, TPrefix>;
20
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Asserts that a value is not undefined. Throws an error if the value is undefined.
3
+ * This is a type assertion function that narrows the type to exclude undefined.
4
+ *
5
+ * @template T - The type of the value being checked
6
+ * @param value - The value to check for undefined
7
+ * @param message - Optional error message to use if assertion fails
8
+ * @throws {Error} When the value is undefined
9
+ * @example
10
+ * ```typescript
11
+ * function processUser(user?: User) {
12
+ * assertDefined(user);
13
+ * return user.name; // TypeScript knows user is defined
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function assertDefined<T>(value: T | undefined, message?: string): asserts value is T;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Asserts that a value is not null or undefined. Throws an error if the value is null or undefined.
3
+ * This is a type assertion function that narrows the type to exclude null and undefined.
4
+ *
5
+ * @template T - The type of the value being checked
6
+ * @param value - The value to check for null or undefined
7
+ * @param message - Optional error message to use if assertion fails
8
+ * @throws {Error} When the value is null or undefined
9
+ * @example
10
+ * ```typescript
11
+ * function processOptionalData(data?: string | null) {
12
+ * assertNotEmpty(data);
13
+ * return data.toUpperCase(); // TypeScript knows data is not null/undefined
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function assertNotEmpty<T>(value: T | null | undefined, message?: string): asserts value is T;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Asserts that a value is not null. Throws an error if the value is null.
3
+ * This is a type assertion function that narrows the type to exclude null.
4
+ *
5
+ * @template T - The type of the value being checked
6
+ * @param value - The value to check for null
7
+ * @param message - Optional error message to use if assertion fails
8
+ * @throws {Error} When the value is null
9
+ * @example
10
+ * ```typescript
11
+ * function processData(data: string | null) {
12
+ * assertNotNull(data);
13
+ * return data.toUpperCase(); // TypeScript knows data is not null
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function assertNotNull<T>(value: T | null, message?: string): asserts value is T;
@@ -0,0 +1,29 @@
1
+ type DownloadFileOptions = {
2
+ name?: string;
3
+ };
4
+ /**
5
+ * Downloads a file from a URL by creating a temporary download link.
6
+ *
7
+ * @param url - The URL to download from
8
+ * @param options - Optional download options including filename
9
+ * @example
10
+ * ```typescript
11
+ * // Download from URL
12
+ * downloadFile('https://example.com/file.pdf', { name: 'document.pdf' });
13
+ * ```
14
+ */
15
+ export declare function downloadFile(url: string, options?: DownloadFileOptions): void;
16
+ /**
17
+ * Downloads a file from a Blob or MediaSource object by creating a temporary object URL.
18
+ *
19
+ * @param obj - The Blob or MediaSource object to download
20
+ * @param options - Optional download options including filename
21
+ * @example
22
+ * ```typescript
23
+ * // Download from Blob
24
+ * const blob = new Blob(['Hello World'], { type: 'text/plain' });
25
+ * downloadFile(blob, { name: 'hello.txt' });
26
+ * ```
27
+ */
28
+ export declare function downloadFile(obj: Blob | MediaSource, options?: DownloadFileOptions): void;
29
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Ensures that a value is defined, returning it if defined or throwing an error if undefined.
3
+ *
4
+ * @template T - The type of the value being checked
5
+ * @param value - The value to ensure is defined
6
+ * @param message - Optional error message to use if the value is undefined
7
+ * @returns The value if it is defined
8
+ * @throws {Error} When the value is undefined
9
+ * @example
10
+ * ```typescript
11
+ * function processUser(user?: User) {
12
+ * const definedUser = ensureDefined(user);
13
+ * return definedUser.name; // definedUser is guaranteed to be defined
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function ensureDefined<T>(value: T | undefined, message?: string): T;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Ensures that a value is not null or undefined, returning it if valid or throwing an error if empty.
3
+ *
4
+ * @template T - The type of the value being checked
5
+ * @param value - The value to ensure is not null or undefined
6
+ * @param message - Optional error message to use if the value is null or undefined
7
+ * @returns The value if it is not null or undefined
8
+ * @throws {Error} When the value is null or undefined
9
+ * @example
10
+ * ```typescript
11
+ * function processOptionalData(data?: string | null) {
12
+ * const validData = ensureNotEmpty(data);
13
+ * return validData.toUpperCase(); // validData is guaranteed to be not null/undefined
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function ensureNotEmpty<T>(value: T | null | undefined, message?: string): T;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Ensures that a value is not null, returning it if not null or throwing an error if null.
3
+ * Unlike assertNotNull, this function returns the value for use in expressions.
4
+ *
5
+ * @template T - The type of the value being checked
6
+ * @param value - The value to ensure is not null
7
+ * @param message - Optional error message to use if the value is null
8
+ * @returns The value if it is not null
9
+ * @throws {Error} When the value is null
10
+ * @example
11
+ * ```typescript
12
+ * function processData(data: string | null) {
13
+ * const nonNullData = ensureNotNull(data);
14
+ * return nonNullData.toUpperCase(); // nonNullData is guaranteed to be not null
15
+ * }
16
+ * ```
17
+ */
18
+ export declare function ensureNotNull<T>(value: T | null, message?: string): T;
@@ -0,0 +1,30 @@
1
+ type AnyFunction = (...args: any[]) => any;
2
+ /**
3
+ * React hook for bound task execution with loading state.
4
+ * Creates a wrapped version of a function that automatically tracks loading state.
5
+ *
6
+ * @template T - The type of the function being wrapped
7
+ * @param block - The function to wrap with task tracking
8
+ * @returns A tuple containing [isLoading: boolean, wrappedFunction: T]
9
+ * @example
10
+ * ```typescript
11
+ * function UserProfile({ userId }: { userId: string }) {
12
+ * const [user, setUser] = useState<User | null>(null);
13
+ *
14
+ * const [isLoading, loadUser] = useBoundRunInTask(async () => {
15
+ * const userData = await fetchUser(userId);
16
+ * setUser(userData);
17
+ * });
18
+ *
19
+ * useEffect(() => {
20
+ * loadUser();
21
+ * }, [userId, loadUser]);
22
+ *
23
+ * if (isLoading) return <div>Loading...</div>;
24
+ * return <div>{user?.name}</div>;
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function useBoundRunInTask<T extends AnyFunction>(block: T): [boolean, T];
29
+ export declare function useBoundRunInTask<T extends AnyFunction>(block: T | undefined): [boolean, T | undefined];
30
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * React hook for managing dialog state with optional callback after closing.
3
+ * Provides convenient open/close functions and tracks the dialog's open state.
4
+ *
5
+ * @param onAfterClose - Optional callback function to execute after the dialog closes
6
+ * @returns Object containing dialog state and control functions
7
+ * @example
8
+ * ```typescript
9
+ * function MyComponent() {
10
+ * const { isDialogOpen, openDialog, closeDialog } = useDialog(() => {
11
+ * console.log('Dialog closed');
12
+ * });
13
+ *
14
+ * return (
15
+ * <div>
16
+ * <button onClick={openDialog}>Open Dialog</button>
17
+ * {isDialogOpen && <Dialog onClose={closeDialog} />}
18
+ * </div>
19
+ * );
20
+ * }
21
+ * ```
22
+ */
23
+ export declare function useDialog(onAfterClose?: () => void): {
24
+ isDialogOpen: boolean;
25
+ openDialog: () => void;
26
+ closeDialog: () => void;
27
+ };