ngx-lift 1.10.3 → 19.0.0

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.
Files changed (106) hide show
  1. package/README.md +5 -1
  2. package/fesm2022/ngx-lift.mjs +729 -194
  3. package/fesm2022/ngx-lift.mjs.map +1 -1
  4. package/index.d.ts +1638 -3
  5. package/package.json +6 -6
  6. package/esm2022/lib/const.mjs +0 -10
  7. package/esm2022/lib/models/async-state.model.mjs +0 -2
  8. package/esm2022/lib/models/index.mjs +0 -6
  9. package/esm2022/lib/models/kubernetes-list.model.mjs +0 -2
  10. package/esm2022/lib/models/kubernetes-object-condition.model.mjs +0 -2
  11. package/esm2022/lib/models/kubernetes-object-meta.model.mjs +0 -2
  12. package/esm2022/lib/models/kubernetes-object.model.mjs +0 -2
  13. package/esm2022/lib/operators/combine-latest-eager.operator.mjs +0 -48
  14. package/esm2022/lib/operators/create-async-state.operator.mjs +0 -61
  15. package/esm2022/lib/operators/distinct-on-change.operator.mjs +0 -80
  16. package/esm2022/lib/operators/index.mjs +0 -9
  17. package/esm2022/lib/operators/kubernetes-pagination.operator.mjs +0 -71
  18. package/esm2022/lib/operators/logger.operator.mjs +0 -21
  19. package/esm2022/lib/operators/poll.operator.mjs +0 -39
  20. package/esm2022/lib/operators/start-with-tap.operator.mjs +0 -15
  21. package/esm2022/lib/operators/switch-map-with-async-state.operator.mjs +0 -33
  22. package/esm2022/lib/pipes/array-join.pipe.mjs +0 -21
  23. package/esm2022/lib/pipes/byte-converter.pipe.mjs +0 -150
  24. package/esm2022/lib/pipes/index.mjs +0 -6
  25. package/esm2022/lib/pipes/is-https.pipe.mjs +0 -18
  26. package/esm2022/lib/pipes/mask.pipe.mjs +0 -36
  27. package/esm2022/lib/pipes/range.pipe.mjs +0 -19
  28. package/esm2022/lib/signals/combine-from.mjs +0 -90
  29. package/esm2022/lib/signals/computed-async.mjs +0 -63
  30. package/esm2022/lib/signals/create-trigger.mjs +0 -11
  31. package/esm2022/lib/signals/index.mjs +0 -7
  32. package/esm2022/lib/signals/inject-params.mjs +0 -35
  33. package/esm2022/lib/signals/inject-query-params.mjs +0 -53
  34. package/esm2022/lib/signals/merge-from.mjs +0 -71
  35. package/esm2022/lib/utils/difference-in-days.util.mjs +0 -25
  36. package/esm2022/lib/utils/form.util.mjs +0 -56
  37. package/esm2022/lib/utils/idle-detection/idle-detection.config.mjs +0 -7
  38. package/esm2022/lib/utils/idle-detection/idle-detection.module.mjs +0 -25
  39. package/esm2022/lib/utils/idle-detection/idle-detection.service.mjs +0 -190
  40. package/esm2022/lib/utils/idle-detection/index.mjs +0 -4
  41. package/esm2022/lib/utils/index.mjs +0 -10
  42. package/esm2022/lib/utils/internal.util.mjs +0 -13
  43. package/esm2022/lib/utils/is-empty.util.mjs +0 -49
  44. package/esm2022/lib/utils/is-equal.util.mjs +0 -24
  45. package/esm2022/lib/utils/is-promise.util.mjs +0 -5
  46. package/esm2022/lib/utils/omit-by.util.mjs +0 -12
  47. package/esm2022/lib/utils/pick-by.util.mjs +0 -16
  48. package/esm2022/lib/utils/range.util.mjs +0 -28
  49. package/esm2022/lib/utils/url.util.mjs +0 -34
  50. package/esm2022/lib/validators/date-range.validator.mjs +0 -58
  51. package/esm2022/lib/validators/index.mjs +0 -5
  52. package/esm2022/lib/validators/intersection.validator.mjs +0 -34
  53. package/esm2022/lib/validators/unique.validator.mjs +0 -64
  54. package/esm2022/lib/validators/url.validator.mjs +0 -14
  55. package/esm2022/ngx-lift.mjs +0 -5
  56. package/esm2022/public-api.mjs +0 -10
  57. package/lib/const.d.ts +0 -5
  58. package/lib/models/async-state.model.d.ts +0 -22
  59. package/lib/models/index.d.ts +0 -5
  60. package/lib/models/kubernetes-list.model.d.ts +0 -10
  61. package/lib/models/kubernetes-object-condition.model.d.ts +0 -28
  62. package/lib/models/kubernetes-object-meta.model.d.ts +0 -38
  63. package/lib/models/kubernetes-object.model.d.ts +0 -8
  64. package/lib/operators/combine-latest-eager.operator.d.ts +0 -7
  65. package/lib/operators/create-async-state.operator.d.ts +0 -64
  66. package/lib/operators/distinct-on-change.operator.d.ts +0 -55
  67. package/lib/operators/index.d.ts +0 -8
  68. package/lib/operators/kubernetes-pagination.operator.d.ts +0 -30
  69. package/lib/operators/logger.operator.d.ts +0 -11
  70. package/lib/operators/poll.operator.d.ts +0 -39
  71. package/lib/operators/start-with-tap.operator.d.ts +0 -10
  72. package/lib/operators/switch-map-with-async-state.operator.d.ts +0 -31
  73. package/lib/pipes/array-join.pipe.d.ts +0 -7
  74. package/lib/pipes/byte-converter.pipe.d.ts +0 -40
  75. package/lib/pipes/index.d.ts +0 -5
  76. package/lib/pipes/is-https.pipe.d.ts +0 -7
  77. package/lib/pipes/mask.pipe.d.ts +0 -19
  78. package/lib/pipes/range.pipe.d.ts +0 -10
  79. package/lib/signals/combine-from.d.ts +0 -25
  80. package/lib/signals/computed-async.d.ts +0 -29
  81. package/lib/signals/create-trigger.d.ts +0 -4
  82. package/lib/signals/index.d.ts +0 -6
  83. package/lib/signals/inject-params.d.ts +0 -63
  84. package/lib/signals/inject-query-params.d.ts +0 -71
  85. package/lib/signals/merge-from.d.ts +0 -13
  86. package/lib/utils/difference-in-days.util.d.ts +0 -19
  87. package/lib/utils/form.util.d.ts +0 -18
  88. package/lib/utils/idle-detection/idle-detection.config.d.ts +0 -5
  89. package/lib/utils/idle-detection/idle-detection.module.d.ts +0 -13
  90. package/lib/utils/idle-detection/idle-detection.service.d.ts +0 -119
  91. package/lib/utils/idle-detection/index.d.ts +0 -3
  92. package/lib/utils/index.d.ts +0 -9
  93. package/lib/utils/internal.util.d.ts +0 -4
  94. package/lib/utils/is-empty.util.d.ts +0 -10
  95. package/lib/utils/is-equal.util.d.ts +0 -7
  96. package/lib/utils/is-promise.util.d.ts +0 -1
  97. package/lib/utils/omit-by.util.d.ts +0 -7
  98. package/lib/utils/pick-by.util.d.ts +0 -7
  99. package/lib/utils/range.util.d.ts +0 -12
  100. package/lib/utils/url.util.d.ts +0 -24
  101. package/lib/validators/date-range.validator.d.ts +0 -19
  102. package/lib/validators/index.d.ts +0 -4
  103. package/lib/validators/intersection.validator.d.ts +0 -9
  104. package/lib/validators/unique.validator.d.ts +0 -18
  105. package/lib/validators/url.validator.d.ts +0 -3
  106. package/public-api.d.ts +0 -6
@@ -1,29 +1,46 @@
1
1
  import { startWith, Subject, combineLatest, pipe, tap, map, catchError, of, Observable, expand, EMPTY, reduce, timer, isObservable, merge, exhaustMap, from, share, switchMap, fromEvent, throttleTime, identity, distinctUntilChanged, exhaustAll, concatAll, mergeAll, switchAll } from 'rxjs';
2
2
  import { toObservable, toSignal } from '@angular/core/rxjs-interop';
3
3
  import * as i0 from '@angular/core';
4
- import { Pipe, inject, LOCALE_ID, makeEnvironmentProviders, NgModule, Optional, Injectable, assertInInjectionContext, isSignal, untracked, computed, DestroyRef, signal, effect } from '@angular/core';
4
+ import { Pipe, inject, LOCALE_ID, makeEnvironmentProviders, NgModule, Injectable, assertInInjectionContext, isSignal, untracked, computed, DestroyRef, signal, effect } from '@angular/core';
5
5
  import { Validators, FormArray } from '@angular/forms';
6
6
  import { ActivatedRoute } from '@angular/router';
7
7
 
8
8
  /**
9
9
  * Combines multiple observables into a single observable emitting an array or dictionary
10
10
  * of the latest values from each source observable.
11
- * Adds startWith(null) for each Subject in combineLatest when the second parameter startWithNullForAll is false.
12
- * When startWithNullForAll is true, each observable will startWith null.
11
+ *
12
+ * This operator is similar to RxJS `combineLatest`, but with additional behavior:
13
+ * - When `startWithNullForAll` is `false` (default), only `Subject` instances get `startWith(null)`
14
+ * - When `startWithNullForAll` is `true`, all observables get `startWith(null)`
15
+ *
16
+ * This ensures that `combineLatest` emits immediately with initial values, even if some
17
+ * observables haven't emitted yet.
13
18
  *
14
19
  * @template T - The type of the data in the observables.
15
20
  *
16
- * @param {Array<Observable<T>> | Record<string, Observable<T>>} sources -
17
- * An array of observables or a dictionary of observables to be combined.
21
+ * @param sources - An array of observables or a dictionary (object) of observables to be combined.
22
+ * @param startWithNullForAll - When `true`, all observables will start with `null`.
23
+ * When `false` (default), only `Subject` instances will start with `null`.
24
+ * @returns An observable emitting an array or dictionary of the latest values from each source observable.
25
+ * Values may be `null` initially if `startWithNullForAll` is `true` or for `Subject` instances.
18
26
  *
19
- * @param {boolean} [startWithNullForAll=false] -
20
- * Determines whether to start each observable with a `null` value.
27
+ * @throws {Error} Throws an error if the provided argument is not an array of observables or a dictionary of observables.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Array of observables
32
+ * const combined$ = combineLatestEager([obs1$, obs2$, obs3$]);
21
33
  *
22
- * @returns {Observable<Array<T | null> | Record<string, T | null>>} -
23
- * An observable emitting an array or dictionary of the latest values from each source observable.
34
+ * // Dictionary of observables
35
+ * const combined$ = combineLatestEager({
36
+ * users: users$,
37
+ * posts: posts$,
38
+ * comments: comments$
39
+ * });
24
40
  *
25
- * @throws {Error} -
26
- * Throws an error if the provided argument is not an array of observables or a dictionary of observables.
41
+ * // Start all with null
42
+ * const combined$ = combineLatestEager([obs1$, obs2$], true);
43
+ * ```
27
44
  */
28
45
  function combineLatestEager(sources, startWithNullForAll = false) {
29
46
  function observableMapper(observable) {
@@ -199,17 +216,35 @@ function distinctOnChange(onChangeCallback, comparator = (prev, curr) => prev ==
199
216
  * ******************************************************************
200
217
  */
201
218
  /**
202
- * Fetches paginated Kubernetes resources by continually making requests
203
- * until all pages have been retrieved, and aggregates the items from all pages
204
- * into a single KubernetesList.
205
- *
206
- * @template T The type of the items contained within the KubernetesList.
207
- * @param http The HttpClient instance used to make the HTTP requests.
208
- * @param endpoint The API endpoint to fetch the resources from.
209
- * @param initialParams Optional initial parameters to include in the request.
210
- * Can include query parameters like filters and pagination settings.
211
- * `limit` and `continue` parameters are parameters for kubernetes
212
- * @returns An observable that emits a single KubernetesList containing all items from all pages.
219
+ * Creates an RxJS operator that fetches paginated Kubernetes resources by continually making requests
220
+ * until all pages have been retrieved, and aggregates the items from all pages into a single KubernetesList.
221
+ *
222
+ * This operator uses Kubernetes' pagination mechanism with the `continue` token. It:
223
+ * - Starts with the initial request
224
+ * - Checks for a `continue` token in the response metadata
225
+ * - Makes subsequent requests with the `continue` token until no more pages exist
226
+ * - Aggregates all items from all pages into a single KubernetesList
227
+ *
228
+ * @template T - The type of Kubernetes objects in the list. Must extend `KubernetesObject`.
229
+ * @param http - The HttpClient instance used to make the HTTP requests.
230
+ * @param endpoint - The API endpoint to fetch the resources from.
231
+ * @param initialParams - Optional initial parameters to include in the request.
232
+ * Can include query parameters like filters and pagination settings.
233
+ * Note: `limit` and `continue` are Kubernetes-specific pagination parameters.
234
+ * @returns An RxJS operator function that transforms a source Observable into an Observable
235
+ * that emits a single KubernetesList containing all aggregated items from all pages.
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * // Use as an operator
240
+ * this.http.get<KubernetesList<Pod>>('/api/v1/pods')
241
+ * .pipe(
242
+ * aggregatePaginatedKubernetesResources(this.http, '/api/v1/pods', { limit: 100 })
243
+ * )
244
+ * .subscribe(list => {
245
+ * console.log(`Total pods: ${list.items.length}`);
246
+ * });
247
+ * ```
213
248
  */
214
249
  function aggregatePaginatedKubernetesResources(http, endpoint, initialParams = {}) {
215
250
  return (source$) => {
@@ -231,16 +266,33 @@ function aggregatePaginatedKubernetesResources(http, endpoint, initialParams = {
231
266
  };
232
267
  }
233
268
  /**
234
- * Fetches paginated Kubernetes resources by continually making requests
235
- * until all pages have been retrieved.
236
- *
237
- * @template T The type of the items contained within the KubernetesList.
238
- * @param http The HttpClient instance used to make the HTTP requests.
239
- * @param endpoint The API endpoint to fetch the resources from.
240
- * @param initialParams Optional initial parameters to include in the request.
241
- * Can include query parameters like filters and pagination settings.
242
- * `limit` and `continue` parameters are parameters for kubernetes
243
- * @returns An observable that emits a single KubernetesList containing all items from all pages.
269
+ * Fetches paginated Kubernetes resources by continually making requests until all pages have been retrieved.
270
+ *
271
+ * This function is a convenience wrapper that combines the initial HTTP request with pagination handling.
272
+ * It automatically handles Kubernetes pagination using the `continue` token mechanism.
273
+ *
274
+ * Unlike `aggregatePaginatedKubernetesResources`, this function makes the initial request itself
275
+ * rather than being used as an operator on an existing Observable.
276
+ *
277
+ * @template T - The type of Kubernetes objects in the list. Must extend `KubernetesObject`.
278
+ * @param http - The HttpClient instance used to make the HTTP requests.
279
+ * @param endpoint - The API endpoint to fetch the resources from.
280
+ * @param initialParams - Optional initial parameters to include in the request.
281
+ * Can include query parameters like filters and pagination settings.
282
+ * Note: `limit` and `continue` are Kubernetes-specific pagination parameters.
283
+ * @returns An Observable that emits a single KubernetesList containing all aggregated items from all pages.
284
+ *
285
+ * @example
286
+ * ```typescript
287
+ * // Fetch all pods across all pages
288
+ * fetchPaginatedKubernetesResources<Pod>(
289
+ * this.http,
290
+ * '/api/v1/pods',
291
+ * { limit: 100 }
292
+ * ).subscribe(list => {
293
+ * console.log(`Total pods: ${list.items.length}`);
294
+ * });
295
+ * ```
244
296
  */
245
297
  function fetchPaginatedKubernetesResources(http, endpoint, initialParams = {}) {
246
298
  const initialRequest$ = http.get(endpoint, { params: initialParams });
@@ -270,17 +322,50 @@ const loggerFunctions = {
270
322
  table: console.table.bind(console),
271
323
  };
272
324
  /**
273
- * Logger operator for RxJS observables.
325
+ * RxJS operator that logs values emitted by an observable using various console methods.
326
+ * Useful for debugging and monitoring observable streams during development.
274
327
  *
275
- * @param loggerType The type of logger to be used: 'count', 'debug', 'dir', 'log', 'table'.
276
- * Defaults to 'log' if not provided or if an unknown type is specified.
328
+ * @template T - The type of values emitted by the observable.
329
+ * @param loggerType - The type of logger to be used. Options:
330
+ * - `'log'`: Standard console.log (default)
331
+ * - `'debug'`: Console.debug for debug messages
332
+ * - `'dir'`: Console.dir for object inspection
333
+ * - `'count'`: Console.count for counting emissions
334
+ * - `'table'`: Console.table for tabular data display
277
335
  * @returns An RxJS operator function that logs values using the specified console function.
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * // Log all values
340
+ * source$.pipe(logger()).subscribe();
341
+ *
342
+ * // Use debug logger
343
+ * source$.pipe(logger('debug')).subscribe();
344
+ *
345
+ * // Display objects in table format
346
+ * users$.pipe(logger('table')).subscribe();
347
+ * ```
278
348
  */
279
349
  const logger = (loggerType = 'log') => pipe(tap((value) => {
280
350
  const logFunction = loggerFunctions[loggerType] || console.log.bind(console);
281
351
  logFunction(value);
282
352
  }));
283
353
 
354
+ /**
355
+ * Type guard that checks if a value is a Promise.
356
+ *
357
+ * @param obj - The value to check.
358
+ * @returns `true` if the value is a Promise (has a `then` method), `false` otherwise.
359
+ *
360
+ * @example
361
+ * ```typescript
362
+ * const promise = Promise.resolve(42);
363
+ * isPromise(promise); // true
364
+ *
365
+ * const notPromise = 42;
366
+ * isPromise(notPromise); // false
367
+ * ```
368
+ */
284
369
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
285
370
  function isPromise$1(obj) {
286
371
  return !!obj && typeof obj.then === 'function';
@@ -323,12 +408,28 @@ function poll(options) {
323
408
  }
324
409
 
325
410
  /**
326
- * Operator that taps into a callback before the source Observable starts emitting values.
411
+ * RxJS operator that executes a callback function before the source Observable starts emitting values.
412
+ * This operator is useful for triggering side effects (like logging, state updates, or initialization)
413
+ * before the main Observable begins emitting.
327
414
  *
328
- * This operator is useful for triggering a side effect before the main Observable starts emitting.
415
+ * @template T - The type of values emitted by the observable.
416
+ * @param callback - A function to be executed synchronously before the source Observable emits its first value.
417
+ * @returns An RxJS operator function that executes the callback and then returns the source Observable unchanged.
418
+ *
419
+ * @example
420
+ * ```typescript
421
+ * // Log before starting
422
+ * data$.pipe(
423
+ * startWithTap(() => console.log('Starting data fetch...')),
424
+ * switchMap(() => this.http.get('/api/data'))
425
+ * ).subscribe();
329
426
  *
330
- * @param callback A function to be executed before the source Observable emits its first value.
331
- * @returns An RxJS operator function that taps into the callback and then switchMaps to the source Observable.
427
+ * // Update loading state
428
+ * data$.pipe(
429
+ * startWithTap(() => this.loading.set(true)),
430
+ * finalize(() => this.loading.set(false))
431
+ * ).subscribe();
432
+ * ```
332
433
  */
333
434
  function startWithTap(callback) {
334
435
  return (source) => {
@@ -368,7 +469,28 @@ function switchMapWithAsyncState(project) {
368
469
  return (source) => source.pipe(switchMap((value, index) => project(value, index).pipe(createAsyncState())));
369
470
  }
370
471
 
472
+ /**
473
+ * Angular pipe that joins array elements into a string using a specified separator.
474
+ *
475
+ * @example
476
+ * ```html
477
+ * <!-- Join array with default comma separator -->
478
+ * <div>{{ ['apple', 'banana', 'cherry'] | arrayJoin }}</div>
479
+ * <!-- Output: "apple,banana,cherry" -->
480
+ *
481
+ * <!-- Join array with custom separator -->
482
+ * <div>{{ ['apple', 'banana', 'cherry'] | arrayJoin: ' - ' }}</div>
483
+ * <!-- Output: "apple - banana - cherry" -->
484
+ * ```
485
+ */
371
486
  class ArrayJoinPipe {
487
+ /**
488
+ * Transforms an array into a string by joining its elements with a separator.
489
+ *
490
+ * @param value - The array to join. If not an array, returns the value as-is.
491
+ * @param separator - The separator string to use between array elements. Defaults to ','.
492
+ * @returns A string containing the joined array elements, or the original value if not an array
493
+ */
372
494
  transform(value, separator = ',') {
373
495
  if (Array.isArray(value)) {
374
496
  return value.join(separator);
@@ -376,50 +498,57 @@ class ArrayJoinPipe {
376
498
  // For non-array cases or unexpected types, return the value as is
377
499
  return value;
378
500
  }
379
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ArrayJoinPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
380
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ArrayJoinPipe, isStandalone: true, name: "arrayJoin" }); }
501
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ArrayJoinPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
502
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ArrayJoinPipe, isStandalone: true, name: "arrayJoin" });
381
503
  }
382
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ArrayJoinPipe, decorators: [{
504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ArrayJoinPipe, decorators: [{
383
505
  type: Pipe,
384
506
  args: [{
385
507
  name: 'arrayJoin',
386
- standalone: true,
387
508
  }]
388
509
  }] });
389
510
 
390
511
  /**
512
+ * Angular pipe that converts a number of bytes into a human-readable string format
513
+ * (e.g., "1.5 MB", "2.3 GB") with locale-aware formatting.
514
+ *
515
+ * Supports multiple locales including English, French, Chinese, Japanese, and more.
516
+ * The pipe uses the application's LOCALE_ID to determine the appropriate unit translations.
517
+ *
518
+ * @example
519
+ * ```html
520
+ * <!-- Convert bytes to human-readable format -->
521
+ * <div>{{ 1024 | byteConverter }}</div>
522
+ * <!-- Output: "1 KB" (English) or "1 Ko" (French) -->
523
+ *
524
+ * <div>{{ 1048576 | byteConverter }}</div>
525
+ * <!-- Output: "1 MB" (English) or "1 Mo" (French) -->
526
+ * ```
527
+ *
528
+ * @example
529
+ * To use locale-specific formatting, configure LOCALE_ID in your app:
530
+ * ```typescript
391
531
  * import { LOCALE_ID, NgModule } from '@angular/core';
392
- * import { BrowserModule } from '@angular/platform-browser';
393
- * import { AppComponent } from './app.component';
394
532
  * import { registerLocaleData } from '@angular/common';
395
- *
396
533
  * import localeEn from '@angular/common/locales/en';
397
534
  * import localeFr from '@angular/common/locales/fr';
398
535
  *
399
- * // Register locales
400
536
  * registerLocaleData(localeEn);
401
537
  * registerLocaleData(localeFr);
402
538
  *
403
539
  * @NgModule({
404
- * declarations: [AppComponent],
405
- * imports: [BrowserModule],
406
540
  * providers: [
407
541
  * {
408
542
  * provide: LOCALE_ID,
409
- * useFactory: () => {
410
- * // Use the browser's language or a default language
411
- * return navigator.language || 'en';
412
- * },
543
+ * useFactory: () => navigator.language || 'en',
413
544
  * },
414
545
  * ],
415
- * bootstrap: [AppComponent],
416
546
  * })
417
547
  * export class AppModule {}
548
+ * ```
418
549
  */
419
550
  class ByteConverterPipe {
420
- constructor() {
421
- this.locale = inject(LOCALE_ID);
422
- }
551
+ locale = inject(LOCALE_ID);
423
552
  transform(value) {
424
553
  if (value === null || value === undefined || isNaN(value)) {
425
554
  return null;
@@ -435,16 +564,17 @@ class ByteConverterPipe {
435
564
  return this.formatNumber(value) + ' ' + translationObject[key];
436
565
  }
437
566
  formatNumber(value) {
438
- return new Intl.NumberFormat(this.locale, { maximumFractionDigits: 2 }).format(value);
567
+ return new Intl.NumberFormat(this.locale, {
568
+ maximumFractionDigits: 2,
569
+ }).format(value);
439
570
  }
440
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ByteConverterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
441
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ByteConverterPipe, isStandalone: true, name: "byteConverter" }); }
571
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ByteConverterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
572
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ByteConverterPipe, isStandalone: true, name: "byteConverter" });
442
573
  }
443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ByteConverterPipe, decorators: [{
574
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ByteConverterPipe, decorators: [{
444
575
  type: Pipe,
445
576
  args: [{
446
577
  name: 'byteConverter',
447
- standalone: true,
448
578
  }]
449
579
  }] });
450
580
  const translations = {
@@ -614,8 +744,44 @@ function composeValidators(control, validatorFn) {
614
744
  return Validators.compose(validatorFns)?.(control) || null;
615
745
  }
616
746
 
747
+ /**
748
+ * Configuration options for the idle detection service.
749
+ * Used to customize the idle duration and timeout duration for user inactivity detection.
750
+ */
617
751
  class IdleDetectionConfig {
752
+ /**
753
+ * The duration in seconds before the user is considered idle.
754
+ * After this duration, the idle detection phase ends and countdown begins.
755
+ * Defaults to 19 minutes (1140 seconds) if not provided.
756
+ */
757
+ idleDurationInSeconds;
758
+ /**
759
+ * The duration in seconds for the countdown phase after idle detection.
760
+ * During this phase, the user can still interact to reset the timer.
761
+ * After this duration, the timeout event is emitted.
762
+ * Defaults to 1 minute (60 seconds) if not provided.
763
+ */
764
+ timeoutDurationInSeconds;
618
765
  }
766
+ /**
767
+ * Provides configuration for the idle detection service.
768
+ * This function should be used in the application's providers array to configure idle detection.
769
+ *
770
+ * @param config - The idle detection configuration object.
771
+ * @returns Environment providers for the idle detection configuration.
772
+ *
773
+ * @example
774
+ * ```typescript
775
+ * export const appConfig: ApplicationConfig = {
776
+ * providers: [
777
+ * provideIdleDetectionConfig({
778
+ * idleDurationInSeconds: 15 * 60, // 15 minutes
779
+ * timeoutDurationInSeconds: 60 // 1 minute
780
+ * })
781
+ * ]
782
+ * };
783
+ * ```
784
+ */
619
785
  function provideIdleDetectionConfig(config) {
620
786
  return makeEnvironmentProviders([{ provide: IdleDetectionConfig, useValue: config }]);
621
787
  }
@@ -631,69 +797,77 @@ class IdleDetectionModule {
631
797
  providers: [provideIdleDetectionConfig(config)],
632
798
  };
633
799
  }
634
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
635
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionModule }); }
636
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionModule }); }
800
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
801
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionModule });
802
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionModule });
637
803
  }
638
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionModule, decorators: [{
804
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionModule, decorators: [{
639
805
  type: NgModule,
640
- args: [{
641
- imports: [],
642
- }]
806
+ args: [{}]
643
807
  }] });
644
808
 
645
809
  /**
646
810
  * Service for detecting user idle time and implementing a countdown.
647
811
  */
648
812
  class IdleDetectionService {
813
+ /**
814
+ * The list of interruption events that will end the idle detection.
815
+ */
816
+ interruptionEvents = [
817
+ 'click',
818
+ 'keydown',
819
+ 'keypress',
820
+ 'mousemove',
821
+ 'mousedown',
822
+ 'scroll',
823
+ 'wheel',
824
+ 'touchmove',
825
+ 'pointermove',
826
+ 'resize',
827
+ ];
828
+ interruptionSubscription;
829
+ /**
830
+ * The default idle duration in seconds (19 minutes).
831
+ */
832
+ idleDuration = 19 * 60;
833
+ /**
834
+ * The default timeout duration in seconds (1 minute).
835
+ */
836
+ timeoutDuration = 60;
837
+ /**
838
+ * Timer for idle detection.
839
+ */
840
+ idleTimer;
841
+ /**
842
+ * Timer for countdown.
843
+ */
844
+ countdownTimer;
845
+ /**
846
+ * Flag to indicate if countdown is in progress.
847
+ */
848
+ isCountingDown = false;
849
+ /**
850
+ * The current countdown value.
851
+ */
852
+ countdown = this.timeoutDuration;
853
+ /**
854
+ * Subject to emit when idle period ends.
855
+ */
856
+ idleEndSubject = new Subject();
857
+ /**
858
+ * Subject to emit the countdown value.
859
+ */
860
+ countdownSubject = new Subject();
861
+ /**
862
+ * Subject to emit when countdown ends.
863
+ */
864
+ countdownEndSubject = new Subject();
649
865
  /**
650
866
  * Constructs the IdleDetectionService.
651
867
  * @param config - Optional configuration for idle and timeout durations.
652
868
  */
653
- constructor(config) {
654
- /**
655
- * The list of interruption events that will end the idle detection.
656
- */
657
- this.interruptionEvents = [
658
- 'click',
659
- 'keydown',
660
- 'keypress',
661
- 'mousemove',
662
- 'mousedown',
663
- 'scroll',
664
- 'wheel',
665
- 'touchmove',
666
- 'pointermove',
667
- 'resize',
668
- ];
669
- /**
670
- * The default idle duration in seconds (19 minutes).
671
- */
672
- this.idleDuration = 19 * 60;
673
- /**
674
- * The default timeout duration in seconds (1 minute).
675
- */
676
- this.timeoutDuration = 60;
677
- /**
678
- * Flag to indicate if countdown is in progress.
679
- */
680
- this.isCountingDown = false;
681
- /**
682
- * The current countdown value.
683
- */
684
- this.countdown = this.timeoutDuration;
685
- /**
686
- * Subject to emit when idle period ends.
687
- */
688
- this.idleEndSubject = new Subject();
689
- /**
690
- * Subject to emit the countdown value.
691
- */
692
- this.countdownSubject = new Subject();
693
- /**
694
- * Subject to emit when countdown ends.
695
- */
696
- this.countdownEndSubject = new Subject();
869
+ constructor() {
870
+ const config = inject(IdleDetectionConfig, { optional: true });
697
871
  if (config) {
698
872
  this.setConfig(config);
699
873
  }
@@ -728,7 +902,7 @@ class IdleDetectionService {
728
902
  setupInterruptionEvents() {
729
903
  if (!this.interruptionSubscription) {
730
904
  const throttledInterruptionEvents = this.interruptionEvents.map((eventName) => fromEvent(document, eventName).pipe(throttleTime(1000)));
731
- this.interruptionSubscription = merge(...throttledInterruptionEvents).subscribe(() => this.resetTimer());
905
+ this.interruptionSubscription = merge(...throttledInterruptionEvents).subscribe(() => this.resetTimer(true));
732
906
  }
733
907
  }
734
908
  /**
@@ -801,6 +975,8 @@ class IdleDetectionService {
801
975
  clearTimers() {
802
976
  clearTimeout(this.idleTimer);
803
977
  clearInterval(this.countdownTimer);
978
+ this.idleTimer = undefined;
979
+ this.countdownTimer = undefined;
804
980
  this.interruptionSubscription?.unsubscribe();
805
981
  this.interruptionSubscription = undefined;
806
982
  }
@@ -816,19 +992,33 @@ class IdleDetectionService {
816
992
  this.countdown = this.timeoutDuration = config.timeoutDurationInSeconds;
817
993
  }
818
994
  }
819
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionService, deps: [{ token: IdleDetectionConfig, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
820
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionService, providedIn: 'root' }); }
995
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
996
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionService, providedIn: 'root' });
821
997
  }
822
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IdleDetectionService, decorators: [{
998
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IdleDetectionService, decorators: [{
823
999
  type: Injectable,
824
1000
  args: [{
825
1001
  providedIn: 'root',
826
1002
  }]
827
- }], ctorParameters: () => [{ type: IdleDetectionConfig, decorators: [{
828
- type: Optional
829
- }] }] });
1003
+ }], ctorParameters: () => [] });
830
1004
 
831
1005
  /* eslint-disable @typescript-eslint/no-explicit-any */
1006
+ /**
1007
+ * Type guard that checks if a value is array-like (has a numeric length property).
1008
+ * Array-like objects include arrays, strings, NodeLists, and similar structures.
1009
+ *
1010
+ * @param value - The value to check.
1011
+ * @returns `true` if the value is array-like, `false` otherwise.
1012
+ *
1013
+ * @example
1014
+ * ```typescript
1015
+ * isArrayLike([1, 2, 3]); // true
1016
+ * isArrayLike('string'); // true
1017
+ * isArrayLike({length: 5}); // true
1018
+ * isArrayLike(null); // false
1019
+ * isArrayLike(() => {}); // false
1020
+ * ```
1021
+ */
832
1022
  function isArrayLike(value) {
833
1023
  return (value != null &&
834
1024
  typeof value !== 'function' &&
@@ -836,6 +1026,20 @@ function isArrayLike(value) {
836
1026
  value.length >= 0 &&
837
1027
  value.length <= Number.MAX_SAFE_INTEGER);
838
1028
  }
1029
+ /**
1030
+ * Checks if a value is a prototype object.
1031
+ * A prototype object is an object that is the prototype property of a constructor function.
1032
+ *
1033
+ * @param value - The value to check.
1034
+ * @returns `true` if the value is a prototype object, `false` otherwise.
1035
+ *
1036
+ * @example
1037
+ * ```typescript
1038
+ * isPrototype(Array.prototype); // true
1039
+ * isPrototype(Object.prototype); // true
1040
+ * isPrototype({}); // false
1041
+ * ```
1042
+ */
839
1043
  function isPrototype(value) {
840
1044
  const Ctor = value?.constructor;
841
1045
  return Ctor && Ctor.prototype === value;
@@ -968,73 +1172,197 @@ function range(start, end, step, fromRight = false) {
968
1172
  return result;
969
1173
  }
970
1174
 
971
- // https://regex101.com/library/mX1xW0
1175
+ /**
1176
+ * Regular expression pattern for validating email addresses.
1177
+ * Supports standard email formats including subdomains and various TLDs.
1178
+ *
1179
+ * @see {@link https://regex101.com/library/mX1xW0 | Regex Pattern Reference}
1180
+ *
1181
+ * @example
1182
+ * ```typescript
1183
+ * emailPattern.test('user@example.com'); // true
1184
+ * emailPattern.test('invalid-email'); // false
1185
+ * ```
1186
+ */
972
1187
  const emailPattern = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/;
1188
+ /**
1189
+ * Regular expression pattern for validating HTTP and HTTPS URLs.
1190
+ * Supports URLs with or without www subdomain, various protocols, and query parameters.
1191
+ *
1192
+ * @example
1193
+ * ```typescript
1194
+ * urlPattern.test('https://example.com'); // true
1195
+ * urlPattern.test('http://www.example.com/path?query=1'); // true
1196
+ * urlPattern.test('invalid-url'); // false
1197
+ * ```
1198
+ */
973
1199
  const urlPattern = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
1200
+ /**
1201
+ * Regular expression pattern for validating HTTPS URLs only.
1202
+ * Similar to `urlPattern` but requires the HTTPS protocol.
1203
+ *
1204
+ * @example
1205
+ * ```typescript
1206
+ * httpsPattern.test('https://example.com'); // true
1207
+ * httpsPattern.test('http://example.com'); // false
1208
+ * ```
1209
+ */
974
1210
  const httpsPattern = /^https:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
975
- // https://regex101.com/library/dT0vT3?orderBy=RELEVANCE&search=ip
1211
+ /**
1212
+ * Regular expression pattern for validating IPv4 addresses.
1213
+ * Supports all valid IPv4 address ranges (0.0.0.0 to 255.255.255.255).
1214
+ *
1215
+ * @see {@link https://regex101.com/library/dT0vT3?orderBy=RELEVANCE&search=ip | Regex Pattern Reference}
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * ipRegex.test('192.168.1.1'); // true
1220
+ * ipRegex.test('256.1.1.1'); // false
1221
+ * ipRegex.test('not-an-ip'); // false
1222
+ * ```
1223
+ */
976
1224
  const ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
977
- // A fully qualified domain name (FQDN) is a domain name that specifies its exact location in the tree hierarchy of the Domain Name System (DNS)
978
- // https://www.regextester.com/103452
1225
+ /**
1226
+ * Regular expression pattern for validating Fully Qualified Domain Names (FQDN).
1227
+ * A FQDN is a domain name that specifies its exact location in the tree hierarchy of the Domain Name System (DNS).
1228
+ * The pattern validates domain names between 4 and 253 characters with proper formatting.
1229
+ *
1230
+ * @see {@link https://www.regextester.com/103452 | Regex Pattern Reference}
1231
+ *
1232
+ * @example
1233
+ * ```typescript
1234
+ * fqdnRegex.test('example.com'); // true
1235
+ * fqdnRegex.test('subdomain.example.com'); // true
1236
+ * fqdnRegex.test('invalid..domain'); // false
1237
+ * ```
1238
+ */
979
1239
  const fqdnRegex = /(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)/;
980
1240
 
981
1241
  /**
982
- * Check if hostname is IP
983
- * @param hostname new URL(your-url).hostname
984
- * @returns true if hostname is a IP
1242
+ * Checks if a hostname is a valid IP address (IPv4 or IPv6).
1243
+ *
1244
+ * @param hostname - The hostname to check. Should be extracted from `new URL(url).hostname`
1245
+ * @returns `true` if the hostname is a valid IP address, `false` otherwise
1246
+ *
1247
+ * @example
1248
+ * ```typescript
1249
+ * const url = new URL('http://192.168.1.1');
1250
+ * isIP(url.hostname); // true
1251
+ *
1252
+ * const url2 = new URL('http://example.com');
1253
+ * isIP(url2.hostname); // false
1254
+ * ```
985
1255
  */
986
1256
  function isIP(hostname) {
987
1257
  return ipRegex.test(hostname);
988
1258
  }
989
1259
  /**
990
- * Check if hostname is FQDN
991
- * @param hostname new URL(your-url).hostname
992
- * @returns true if hostname is a FQDN
1260
+ * Checks if a hostname is a valid Fully Qualified Domain Name (FQDN).
1261
+ *
1262
+ * @param hostname - The hostname to check. Should be extracted from `new URL(url).hostname`
1263
+ * @returns `true` if the hostname is a valid FQDN, `false` otherwise
1264
+ *
1265
+ * @example
1266
+ * ```typescript
1267
+ * const url = new URL('http://example.com');
1268
+ * isFQDN(url.hostname); // true
1269
+ *
1270
+ * const url2 = new URL('http://192.168.1.1');
1271
+ * isFQDN(url2.hostname); // false
1272
+ * ```
993
1273
  */
994
1274
  function isFQDN(hostname) {
995
1275
  return fqdnRegex.test(hostname);
996
1276
  }
997
1277
  /**
998
- * Check if url is valid
999
- * @param url
1000
- * @returns true if valid
1278
+ * Checks if a string is a valid URL.
1279
+ *
1280
+ * @param url - The URL string to validate
1281
+ * @returns `true` if the string is a valid URL, `false` otherwise
1282
+ *
1283
+ * @example
1284
+ * ```typescript
1285
+ * isURL('https://example.com'); // true
1286
+ * isURL('not-a-url'); // false
1287
+ * ```
1001
1288
  */
1002
1289
  function isURL(url) {
1003
1290
  return urlPattern.test(url);
1004
1291
  }
1005
1292
  /**
1006
- * Check if a url starts with https, the url must be a valid url.
1007
- * @param url
1008
- * @returns true if it's a https valid url
1293
+ * Checks if a URL string uses the HTTPS protocol.
1294
+ * The URL must be a valid URL format.
1295
+ *
1296
+ * @param url - The URL string to check
1297
+ * @returns `true` if the URL is valid and uses HTTPS protocol, `false` otherwise
1298
+ *
1299
+ * @example
1300
+ * ```typescript
1301
+ * isHttps('https://example.com'); // true
1302
+ * isHttps('http://example.com'); // false
1303
+ * ```
1009
1304
  */
1010
1305
  function isHttps(url) {
1011
1306
  return httpsPattern.test(url);
1012
1307
  }
1013
1308
 
1309
+ /**
1310
+ * Angular pipe that checks if a URL string uses the HTTPS protocol.
1311
+ *
1312
+ * @example
1313
+ * ```html
1314
+ * <!-- Check if URL is HTTPS -->
1315
+ * <div>{{ 'https://example.com' | isHttps }}</div>
1316
+ * <!-- Output: true -->
1317
+ *
1318
+ * <div>{{ 'http://example.com' | isHttps }}</div>
1319
+ * <!-- Output: false -->
1320
+ * ```
1321
+ */
1014
1322
  class IsHttpsPipe {
1323
+ /**
1324
+ * Transforms a URL string into a boolean indicating whether it uses HTTPS.
1325
+ *
1326
+ * @param value - The URL string to check
1327
+ * @returns `true` if the URL uses HTTPS protocol, `false` otherwise
1328
+ */
1015
1329
  transform(value) {
1016
1330
  return isHttps(value);
1017
1331
  }
1018
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IsHttpsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1019
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: IsHttpsPipe, isStandalone: true, name: "isHttps" }); }
1332
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IsHttpsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1333
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: IsHttpsPipe, isStandalone: true, name: "isHttps" });
1020
1334
  }
1021
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IsHttpsPipe, decorators: [{
1335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IsHttpsPipe, decorators: [{
1022
1336
  type: Pipe,
1023
1337
  args: [{
1024
1338
  name: 'isHttps',
1025
- standalone: true,
1026
1339
  }]
1027
1340
  }] });
1028
1341
 
1029
1342
  const unmaskNumber = 6;
1030
1343
  const maskChar = '*';
1344
+ /**
1345
+ * Angular pipe that masks sensitive string data by replacing characters with asterisks,
1346
+ * while preserving a configurable number of characters at the beginning and end.
1347
+ *
1348
+ * @example
1349
+ * ```html
1350
+ * <!-- Mask a credit card number -->
1351
+ * <div>{{ '1234567890123456' | mask }}</div>
1352
+ * <!-- Output: "123456******3456" -->
1353
+ *
1354
+ * <!-- Custom masking options -->
1355
+ * <div>{{ '1234567890123456' | mask: { unmaskedPrefixLength: 4, unmaskedSuffixLength: 4 } }}</div>
1356
+ * <!-- Output: "1234********3456" -->
1357
+ * ```
1358
+ */
1031
1359
  class MaskPipe {
1032
1360
  /**
1033
1361
  * Transforms the input string by masking characters based on the provided options.
1034
1362
  *
1035
- * @param {string} value - The input string to be masked.
1036
- * @param {MaskOptions} [options={}] - Options for customizing the masking behavior.
1037
- * @returns {string} - The masked string.
1363
+ * @param value - The input string to be masked
1364
+ * @param options - Options for customizing the masking behavior
1365
+ * @returns The masked string, or the original string if masking is disabled or the string is too short
1038
1366
  */
1039
1367
  transform(value, options = {}) {
1040
1368
  const { unmaskedPrefixLength = unmaskNumber, unmaskedSuffixLength = unmaskNumber, masked = true } = options;
@@ -1049,62 +1377,102 @@ class MaskPipe {
1049
1377
  .map((char, i) => (i < unmaskedPrefixLength || i > value.length - unmaskedSuffixLength - 1 ? char : maskChar))
1050
1378
  .join('');
1051
1379
  }
1052
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MaskPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1053
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: MaskPipe, isStandalone: true, name: "mask" }); }
1380
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaskPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1381
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: MaskPipe, isStandalone: true, name: "mask" });
1054
1382
  }
1055
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MaskPipe, decorators: [{
1383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaskPipe, decorators: [{
1056
1384
  type: Pipe,
1057
1385
  args: [{
1058
1386
  name: 'mask',
1059
- standalone: true,
1060
1387
  }]
1061
1388
  }] });
1062
1389
 
1390
+ /**
1391
+ * Angular pipe that generates an array of numbers within a specified range.
1392
+ *
1393
+ * @example
1394
+ * ```html
1395
+ * <!-- Generate array from 0 to 4 -->
1396
+ * <div *ngFor="let i of [5] | range">{{ i }}</div>
1397
+ *
1398
+ * <!-- Generate array from 1 to 5 -->
1399
+ * <div *ngFor="let i of [1, 5] | range">{{ i }}</div>
1400
+ *
1401
+ * <!-- Generate array from 0 to 10 with step 2 -->
1402
+ * <div *ngFor="let i of [0, 10, 2] | range">{{ i }}</div>
1403
+ * ```
1404
+ */
1063
1405
  class RangePipe {
1064
1406
  transform(value) {
1065
1407
  const input = value;
1066
1408
  return range(...input);
1067
1409
  }
1068
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
1069
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: RangePipe, isStandalone: true, name: "range" }); }
1410
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: RangePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1411
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: RangePipe, isStandalone: true, name: "range" });
1070
1412
  }
1071
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangePipe, decorators: [{
1413
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: RangePipe, decorators: [{
1072
1414
  type: Pipe,
1073
1415
  args: [{
1074
1416
  name: 'range',
1075
- standalone: true,
1076
1417
  }]
1077
1418
  }] });
1078
1419
 
1079
1420
  /* eslint-disable @typescript-eslint/no-explicit-any */
1080
1421
  /**
1081
- * Combines multiple `Observable` or `Signal` sources into a `Signal` that emits their values. It's like combineLatest.
1422
+ * Combines multiple `Observable` or `Signal` sources into a `Signal` that emits their combined values.
1423
+ * This function is similar to RxJS `combineLatest`, but works with both Observables and Signals,
1424
+ * and returns a Signal instead of an Observable.
1425
+ *
1426
+ * The function supports:
1427
+ * - Array of sources: Returns a Signal of an array
1428
+ * - Object of sources: Returns a Signal of an object with the same keys
1429
+ * - Optional RxJS operator: Apply transformations to the combined values
1430
+ * - Optional initial value: Provide an initial value for the Signal
1082
1431
  *
1083
- * @param {ObservableSignalInputTuple} sources - Array or object of `Observable` or `Signal` values
1084
- * @param {OperatorFunction} [operator] - Operator to apply to the combined values
1085
- * @param {CombineFromOptions} [options] - Options including `initialValue` and `injector`
1086
- * @returns Signal emitting the combined values
1432
+ * @template Input - The type of the input sources (array or object).
1433
+ * @template Output - The type of the output Signal (defaults to Input).
1434
+ *
1435
+ * @param sources - Array or object of `Observable` or `Signal` values to combine.
1436
+ * @param operator - Optional RxJS operator function to transform the combined values.
1437
+ * @param options - Optional configuration object:
1438
+ * - `initialValue`: Initial value for the Signal (required if sources don't emit synchronously)
1439
+ * - `injector`: Angular injector to use for signal conversion
1440
+ * @returns A Signal that emits the combined values from all sources.
1087
1441
  *
1088
1442
  * @example
1089
- * ```ts
1443
+ * ```typescript
1444
+ * // Array of sources
1090
1445
  * export class Component {
1091
- * private readonly userService = inject(UserService);
1092
- * page = signal(2);
1093
- *
1094
- * data = combineFrom(
1095
- * [this.page, this.userService.users$],
1096
- * pipe(
1097
- * switchMap(([page, users]) => this.dataService.getData(page, users)),
1098
- * startWith([])
1099
- * )
1100
- * );
1446
+ * private readonly userService = inject(UserService);
1447
+ * page = signal(2);
1448
+ *
1449
+ * data = combineFrom(
1450
+ * [this.page, this.userService.users$],
1451
+ * pipe(
1452
+ * switchMap(([page, users]) => this.dataService.getData(page, users)),
1453
+ * startWith([])
1454
+ * )
1455
+ * );
1101
1456
  * }
1457
+ *
1458
+ * // Object of sources
1459
+ * const vm = combineFrom({
1460
+ * users: users$,
1461
+ * filters: filtersSignal,
1462
+ * page: pageSignal
1463
+ * });
1464
+ *
1465
+ * // With initial value
1466
+ * const data = combineFrom(
1467
+ * [source1$, source2$],
1468
+ * { initialValue: [null, null] }
1469
+ * );
1102
1470
  * ```
1103
1471
  */
1104
1472
  function combineFrom(...args) {
1105
1473
  assertInInjectionContext(combineFrom);
1106
1474
  const { normalizedSources, hasInitValue, operator, options } = normalizeArgs(args);
1107
- const ret = hasInitValue
1475
+ const ret = hasInitValue && options?.initialValue !== undefined
1108
1476
  ? toSignal(combineLatest(normalizedSources).pipe(operator), {
1109
1477
  initialValue: options.initialValue,
1110
1478
  injector: options?.injector,
@@ -1139,20 +1507,24 @@ function normalizeArgs(args) {
1139
1507
  try {
1140
1508
  initialValue = untracked(source);
1141
1509
  }
1142
- catch (e) {
1510
+ catch {
1143
1511
  // If the input is not set, skip startWith or provide a fallback
1144
1512
  initialValue = undefined;
1145
1513
  }
1146
1514
  // toObservable doesn't immediately emit initialValue of the signal
1147
- acc[keyOrIndex] = toObservable(source, { injector: options?.injector }).pipe(startWith(initialValue));
1515
+ acc[keyOrIndex] = toObservable(source, {
1516
+ injector: options?.injector,
1517
+ }).pipe(startWith(initialValue));
1148
1518
  }
1149
1519
  else if (isObservable(source)) {
1150
1520
  acc[keyOrIndex] = source.pipe(distinctUntilChanged());
1151
1521
  }
1152
1522
  else if (typeof source === 'function') {
1153
1523
  // seldom use: pass function like () => 5
1154
- const computedRes = computed(source);
1155
- acc[keyOrIndex] = toObservable(computedRes, { injector: options?.injector }).pipe(startWith(source()));
1524
+ const computedRes = computed(source, ...(ngDevMode ? [{ debugName: "computedRes" }] : []));
1525
+ acc[keyOrIndex] = toObservable(computedRes, {
1526
+ injector: options?.injector,
1527
+ }).pipe(startWith(source()));
1156
1528
  }
1157
1529
  else {
1158
1530
  // seldom use: pass promise, Map, array, etc that from accepts
@@ -1168,7 +1540,7 @@ function computedAsync(computeFn, options = {}) {
1168
1540
  const destroyRef = inject(DestroyRef);
1169
1541
  const sourceSubject = new Subject();
1170
1542
  const source$ = flattenObservable(sourceSubject, options.behavior || 'switch');
1171
- const sourceValue = signal(options.initialValue);
1543
+ const sourceValue = signal(options.initialValue, ...(ngDevMode ? [{ debugName: "sourceValue" }] : []));
1172
1544
  const sourceResult = source$.subscribe({
1173
1545
  next: (value) => sourceValue.set(value),
1174
1546
  error: (error) => {
@@ -1224,12 +1596,43 @@ function isPromise(value) {
1224
1596
  return value && typeof value.then === 'function';
1225
1597
  }
1226
1598
 
1599
+ /**
1600
+ * Creates a trigger signal that can be used to manually trigger updates or side effects.
1601
+ * The trigger maintains an internal counter that increments each time `next()` is called.
1602
+ *
1603
+ * @returns An object containing:
1604
+ * - `next()`: A function to trigger an update (increments the internal counter)
1605
+ * - `value`: A readonly signal that emits the current counter value
1606
+ *
1607
+ * @example
1608
+ * ```typescript
1609
+ * export class MyComponent {
1610
+ * private refreshTrigger = createTrigger();
1611
+ *
1612
+ * // Use the trigger to refresh data
1613
+ * refreshData() {
1614
+ * this.refreshTrigger.next();
1615
+ * }
1616
+ *
1617
+ * // React to trigger changes
1618
+ * data$ = toObservable(this.refreshTrigger.value).pipe(
1619
+ * switchMap(() => this.dataService.getData())
1620
+ * );
1621
+ * }
1622
+ * ```
1623
+ */
1227
1624
  function createTrigger() {
1228
- const sourceSignal = signal(0);
1625
+ const sourceSignal = signal(0, ...(ngDevMode ? [{ debugName: "sourceSignal" }] : []));
1229
1626
  return {
1627
+ /**
1628
+ * Triggers an update by incrementing the internal counter.
1629
+ */
1230
1630
  next: () => {
1231
1631
  sourceSignal.update((v) => v + 1);
1232
1632
  },
1633
+ /**
1634
+ * A readonly signal that emits the current counter value.
1635
+ */
1233
1636
  value: sourceSignal.asReadonly(),
1234
1637
  };
1235
1638
  }
@@ -1316,26 +1719,46 @@ function injectQueryParams(keyOrParamsTransform, options = {}) {
1316
1719
 
1317
1720
  // No object inputs
1318
1721
  /**
1319
- * merge multiple `Observable` or `Signal` sources into a `Signal` that emits the last value. It's like merge.
1722
+ * Merges multiple `Observable` or `Signal` sources into a `Signal` that emits values from any source.
1723
+ * This function is similar to RxJS `merge`, but works with both Observables and Signals,
1724
+ * and returns a Signal instead of an Observable.
1320
1725
  *
1321
- * @param {ObservableSignalInputTuple} sources - Array of `Observable` or `Signal` values
1322
- * @param {OperatorFunction} [operator] - Operator to apply to the merge
1323
- * @param {MergeFromOptions} [options] - Options including `initialValue` and `injector`
1324
- * @returns Signal emitting the latest merge result
1726
+ * When any source emits a value, the Signal will emit that value. This is useful for
1727
+ * combining multiple event streams or reactive sources.
1728
+ *
1729
+ * @template Input - The type of values in the input sources array.
1730
+ * @template Output - The type of the output Signal (defaults to Input[number]).
1731
+ *
1732
+ * @param sources - Array of `Observable` or `Signal` values to merge.
1733
+ * @param operator - Optional RxJS operator function to transform the merged values.
1734
+ * @param options - Optional configuration object:
1735
+ * - `initialValue`: Initial value for the Signal
1736
+ * - `injector`: Angular injector to use for signal conversion
1737
+ * @returns A Signal that emits values from any of the merged sources.
1325
1738
  *
1326
1739
  * @example
1327
- * ```ts
1740
+ * ```typescript
1328
1741
  * export class Component {
1329
1742
  * e$ = of(1).pipe(delay(1000));
1330
1743
  * f = signal(2);
1331
1744
  *
1745
+ * // Merge with operator
1332
1746
  * data = mergeFrom(
1333
1747
  * [this.e$, this.f],
1334
1748
  * pipe(
1335
- * switchMap((res) => of(`${res} is coming~`)),
1749
+ * map((res) => `${res} is coming~`),
1336
1750
  * startWith(0),
1337
1751
  * ),
1338
1752
  * );
1753
+ *
1754
+ * // Simple merge
1755
+ * merged = mergeFrom([source1$, source2$, sourceSignal]);
1756
+ *
1757
+ * // With initial value
1758
+ * merged = mergeFrom(
1759
+ * [source1$, source2$],
1760
+ * { initialValue: null }
1761
+ * );
1339
1762
  * }
1340
1763
  * ```
1341
1764
  */
@@ -1383,10 +1806,45 @@ function parseArgs(args) {
1383
1806
  }
1384
1807
 
1385
1808
  /**
1386
- * Validates a date against a specified date range.
1809
+ * Creates a validator function that validates a date against a specified date range.
1810
+ *
1811
+ * The validator checks if the form control's date value falls within the specified range.
1812
+ * It supports:
1813
+ * - Minimum and maximum date constraints
1814
+ * - Inclusive or exclusive boundary comparisons
1815
+ * - Time-aware or date-only comparisons
1816
+ *
1817
+ * @param options - The options for the date range validation.
1818
+ * @returns A validator function that validates a FormControl and returns an error object if the date is out of range,
1819
+ * or `null` if the date is valid. Error objects contain:
1820
+ * - `minDate`: ISO string of the minimum date (if value is too early)
1821
+ * - `maxDate`: ISO string of the maximum date (if value is too late)
1822
+ * - `invalidDate`: `true` (if the value cannot be parsed as a date)
1387
1823
  *
1388
- * @param {DateRangeOptions} options - The options for the date range validation.
1389
- * @returns {ValidatorFn} A function that validates a FormControl and returns an error if the date is out of range.
1824
+ * @example
1825
+ * ```typescript
1826
+ * // Date range with inclusive boundaries
1827
+ * const form = new FormGroup({
1828
+ * startDate: new FormControl('', [
1829
+ * dateRangeValidator({
1830
+ * minDate: new Date('2024-01-01'),
1831
+ * maxDate: new Date('2024-12-31'),
1832
+ * minInclusive: true,
1833
+ * maxInclusive: true
1834
+ * })
1835
+ * ])
1836
+ * });
1837
+ *
1838
+ * // Date-only comparison (ignores time)
1839
+ * const form = new FormGroup({
1840
+ * appointment: new FormControl('', [
1841
+ * dateRangeValidator({
1842
+ * minDate: '2024-01-01',
1843
+ * compareTime: false
1844
+ * })
1845
+ * ])
1846
+ * });
1847
+ * ```
1390
1848
  */
1391
1849
  function dateRangeValidator(options) {
1392
1850
  return (control) => {
@@ -1440,11 +1898,30 @@ function dateRangeValidator(options) {
1440
1898
  }
1441
1899
 
1442
1900
  /**
1443
- * A custom validator function that checks for intersection between two form controls. The two controls' values must be arrays.
1901
+ * Creates a validator function that checks for intersection between two form controls within a FormGroup.
1902
+ * Both controls' values must be arrays. The validator sets an error on both controls if they have any common values.
1903
+ *
1904
+ * This is useful for scenarios where you need to ensure two arrays don't share any elements,
1905
+ * such as preventing duplicate selections in multi-select scenarios.
1906
+ *
1907
+ * @template T - The type of elements in the arrays (defaults to `string`).
1908
+ * @param controlName1 - The name of the first form control in the FormGroup.
1909
+ * @param controlName2 - The name of the second form control in the FormGroup.
1910
+ * @returns A validator function that validates the FormGroup and returns an error object with `intersection: true`
1911
+ * if there is an intersection between the two arrays, or `null` if there is no intersection.
1912
+ *
1913
+ * @example
1914
+ * ```typescript
1915
+ * const form = new FormGroup({
1916
+ * selectedUsers: new FormControl(['user1', 'user2']),
1917
+ * excludedUsers: new FormControl(['user3', 'user4']),
1918
+ * }, {
1919
+ * validators: [intersectionValidator('selectedUsers', 'excludedUsers')]
1920
+ * });
1444
1921
  *
1445
- * @param {string} controlName1 - The name of the first form control.
1446
- * @param {string} controlName2 - The name of the second form control.
1447
- * @returns {ValidatorFn} A function that validates the form group and returns an error if there is an intersection.
1922
+ * // If selectedUsers contains 'user1' and excludedUsers also contains 'user1',
1923
+ * // both controls will have an error: { intersection: true }
1924
+ * ```
1448
1925
  */
1449
1926
  function intersectionValidator(controlName1, controlName2) {
1450
1927
  return (formGroup) => {
@@ -1478,15 +1955,47 @@ function intersectionValidator(controlName1, controlName2) {
1478
1955
  *
1479
1956
  * This validator can be applied to a FormArray or FormGroup containing the controls to be validated.
1480
1957
  * It ensures that each control's value is unique among all other controls within the array or group.
1958
+ *
1959
+ * When duplicate values are found, the validator sets a `notUnique` error on all affected controls.
1960
+ * The error is automatically removed when the value becomes unique again.
1961
+ *
1962
+ * @example
1963
+ * ```typescript
1964
+ * // FormArray with unique values
1965
+ * const formArray = new FormArray([
1966
+ * new FormControl('value1'),
1967
+ * new FormControl('value2'),
1968
+ * new FormControl('value1') // This will have notUnique error
1969
+ * ], [UniqueValidator.unique()]);
1970
+ *
1971
+ * // FormArray with custom key selector
1972
+ * const formArray = new FormArray([
1973
+ * new FormGroup({
1974
+ * id: new FormControl(1),
1975
+ * name: new FormControl('Item 1')
1976
+ * }),
1977
+ * new FormGroup({
1978
+ * id: new FormControl(2),
1979
+ * name: new FormControl('Item 2')
1980
+ * })
1981
+ * ], [UniqueValidator.unique(control => control.get('id'))]);
1982
+ * ```
1481
1983
  */
1482
1984
  class UniqueValidator {
1483
1985
  /**
1484
- * Validator function to be attached to a FormArray or FormGroup.
1986
+ * Creates a validator function that checks for uniqueness of values across controls in a FormArray or FormGroup.
1485
1987
  *
1486
- * This validator checks for uniqueness of each control's value within the array or group.
1988
+ * The validator:
1989
+ * - Compares values using the provided key selector function
1990
+ * - Sets `notUnique` error on controls with duplicate values
1991
+ * - Automatically removes errors when values become unique
1992
+ * - Ignores null, undefined, empty strings, and 'NaN' values
1487
1993
  *
1488
- * @param keySelector A function to select the key control for comparison (default is the control itself).
1489
- * @typeparam T The type of the control value.
1994
+ * @template T - The type of the control value.
1995
+ * @param keySelector - A function to select the key control for comparison.
1996
+ * Defaults to the control itself if not provided.
1997
+ * This is useful when validating FormGroups where you want to check uniqueness of a specific field.
1998
+ * @returns A validator function that can be attached to a FormArray or FormGroup.
1490
1999
  */
1491
2000
  static unique(keySelector = (control) => control) {
1492
2001
  return (formArray) => {
@@ -1536,14 +2045,40 @@ class UniqueValidator {
1536
2045
  }
1537
2046
  }
1538
2047
 
2048
+ /**
2049
+ * Validator function that checks if a form control value is a valid URL.
2050
+ *
2051
+ * @param control - The form control to validate
2052
+ * @returns `null` if the value is a valid URL, or an error object with `invalidUrl: true` if invalid
2053
+ *
2054
+ * @example
2055
+ * ```typescript
2056
+ * const form = new FormGroup({
2057
+ * website: new FormControl('', urlValidator)
2058
+ * });
2059
+ * ```
2060
+ */
1539
2061
  function urlValidator(control) {
1540
- if (!urlPattern.test(control.value)) {
2062
+ if (!control.value || !urlPattern.test(control.value)) {
1541
2063
  return { invalidUrl: true };
1542
2064
  }
1543
2065
  return null;
1544
2066
  }
2067
+ /**
2068
+ * Validator function that checks if a form control value is a valid HTTPS URL.
2069
+ *
2070
+ * @param control - The form control to validate
2071
+ * @returns `null` if the value is a valid HTTPS URL, or an error object with `invalidUrl: true` if invalid
2072
+ *
2073
+ * @example
2074
+ * ```typescript
2075
+ * const form = new FormGroup({
2076
+ * secureUrl: new FormControl('', httpsValidator)
2077
+ * });
2078
+ * ```
2079
+ */
1545
2080
  function httpsValidator(control) {
1546
- if (!httpsPattern.test(control.value)) {
2081
+ if (!control.value || !httpsPattern.test(control.value)) {
1547
2082
  return { invalidUrl: true };
1548
2083
  }
1549
2084
  return null;