ngx-lift 1.4.2 → 1.6.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.
@@ -2,8 +2,8 @@ import { startWith, Subject, combineLatest, pipe, tap, map, catchError, of, Obse
2
2
  import { toObservable, toSignal } from '@angular/core/rxjs-interop';
3
3
  import * as i0 from '@angular/core';
4
4
  import { Pipe, inject, LOCALE_ID, assertInInjectionContext, isSignal, untracked, computed, DestroyRef, signal, effect } from '@angular/core';
5
- import { ActivatedRoute } from '@angular/router';
6
5
  import { Validators, FormArray } from '@angular/forms';
6
+ import { ActivatedRoute } from '@angular/router';
7
7
 
8
8
  /**
9
9
  * Combines multiple observables into a single observable emitting an array or dictionary
@@ -207,18 +207,6 @@ function isPromise$1(obj) {
207
207
  return !!obj && typeof obj.then === 'function';
208
208
  }
209
209
 
210
- /**
211
- * Polls data at a specified interval and can be triggered manually.
212
- *
213
- * @template Data - The type of the data emitted by the polling function.
214
- * @template Input - The type of the input parameter used to build polling parameters.
215
- * @param {object} options - The configuration options for polling.
216
- * @param {number} options.interval - The interval in milliseconds between each poll.
217
- * @param {(params: any) => Observable<Data> | Data} options.pollingFn - A function that returns an Observable, Promise, or primitive value.
218
- * @param {(input: Input | undefined) => any} [options.paramsBuilder] - An optional function that builds parameters for the polling function based on the input. The value emitted by the trigger observable will serve as the parameter.
219
- * @param {Observable<Input> | Signal<Input>} [options.trigger] - An optional Observable or Signal that triggers a manual poll.
220
- * @returns {Observable<AsyncState<Data>>} An Observable emitting objects representing the state of the asynchronous operation.
221
- */
222
210
  function poll(options) {
223
211
  const timerEmitValue = '__timer__emission__';
224
212
  const timer$ = timer(0, options.interval).pipe(map((i) => `${timerEmitValue}${i}`));
@@ -466,14 +454,204 @@ const translations = {
466
454
  },
467
455
  };
468
456
 
457
+ /**
458
+ * Calculates the difference in whole days between two dates.
459
+ *
460
+ * @param {Date | number | string} dateLeft - The date from which the difference is measured (the reference date).
461
+ * Can be a Date object, a number representing milliseconds since the Unix epoch,
462
+ * or a string in a format parseable by the Date constructor.
463
+ * @param {Date | number | string} dateRight - The date to be compared against the reference date.
464
+ * Can be a Date object, a number representing milliseconds since the Unix epoch,
465
+ * or a string in a format parseable by the Date constructor.
466
+ * @returns {number} The number of whole days between the reference date (dateLeft) and the compared date (dateRight).
467
+ *
468
+ * @example
469
+ * // How many whole days are between '2022-09-08' and '2023-09-18'?
470
+ * const result = differenceInDays('2022-09-08', new Date('2023-09-18'));
471
+ */
472
+ function differenceInDays(dateLeft, dateRight) {
473
+ const _dateLeft = new Date(dateLeft);
474
+ const _dateRight = new Date(dateRight);
475
+ const difference = (_dateLeft.getTime() - _dateRight.getTime()) / (1000 * 60 * 60 * 24);
476
+ return Math.floor(difference);
477
+ }
478
+
479
+ /**
480
+ * Provides a conditional validator that applies the specified validator functions only if the condition is met.
481
+ *
482
+ * @param condition A function that determines whether the validators should be applied.
483
+ * @param trueValidatorFn The validator function or an array of validator functions to be applied when the condition is true.
484
+ * @param falseValidatorFn Optional. The validator function or an array of validator functions to be applied when the condition is false.
485
+ * @returns A validator function that can be used with Angular Reactive Forms.
486
+ */
487
+ function ifValidator(condition, trueValidatorFn, falseValidatorFn) {
488
+ /**
489
+ * @param control The AbstractControl to validate.
490
+ * @returns Validation errors if the condition is met; otherwise, null.
491
+ */
492
+ return (control) => {
493
+ if (!trueValidatorFn || !condition(control)) {
494
+ return composeValidators(control, falseValidatorFn);
495
+ }
496
+ return composeValidators(control, trueValidatorFn);
497
+ };
498
+ }
499
+ /**
500
+ * Provides a conditional async validator that applies the specified async validator function only if the condition is met.
501
+ *
502
+ * @param condition A function that determines whether the async validator should be applied.
503
+ * @param validatorFn The async validator function to be applied conditionally.
504
+ * @returns An async validator function that can be used with Angular Reactive Forms.
505
+ */
506
+ function ifAsyncValidator(condition, validatorFn) {
507
+ /**
508
+ * @param control The AbstractControl to validate asynchronously.
509
+ * @returns An observable that emits validation errors if the condition is met; otherwise, emits null.
510
+ */
511
+ return (control) => {
512
+ if (!validatorFn || !condition(control)) {
513
+ return of(null);
514
+ }
515
+ return validatorFn(control);
516
+ };
517
+ }
518
+ /**
519
+ * Composes and applies the provided validators to the given AbstractControl.
520
+ *
521
+ * @param control The AbstractControl to validate.
522
+ * @param validatorFn The validator function or an array of validator functions to be applied.
523
+ * @returns Validation errors if the validators are applicable; otherwise, null.
524
+ */
525
+ function composeValidators(control, validatorFn) {
526
+ if (!validatorFn) {
527
+ return null;
528
+ }
529
+ const validatorFns = Array.isArray(validatorFn) ? validatorFn : [validatorFn];
530
+ return Validators.compose(validatorFns)?.(control) || null;
531
+ }
532
+
533
+ /**
534
+ * Check if a value is empty.
535
+ * @param {T | undefined | null} value - The value to check for emptiness.
536
+ * @returns {boolean} - Returns true if the value is empty, otherwise false.
537
+ */
538
+ function isEmpty(value) {
539
+ if (value == null)
540
+ return true;
541
+ if (typeof value === 'string' || Array.isArray(value)) {
542
+ return value.length === 0;
543
+ }
544
+ if (typeof value === 'object') {
545
+ return Object.keys(value).length === 0;
546
+ }
547
+ return false;
548
+ }
549
+
550
+ /**
551
+ * Check if two values are deeply equal.
552
+ * @param {T} value1 - The first value to compare.
553
+ * @param {T} value2 - The second value to compare.
554
+ * @returns {boolean} - Returns true if the values are deeply equal, otherwise false.
555
+ */
556
+ function isEqual(value1, value2) {
557
+ if (value1 === value2)
558
+ return true;
559
+ if (typeof value1 !== 'object' || typeof value2 !== 'object' || value1 === null || value2 === null) {
560
+ return false;
561
+ }
562
+ const keys1 = Object.keys(value1);
563
+ const keys2 = Object.keys(value2);
564
+ if (keys1.length !== keys2.length)
565
+ return false;
566
+ for (const key of keys1) {
567
+ if (!keys2.includes(key) || !isEqual(value1[key], value2[key])) {
568
+ return false;
569
+ }
570
+ }
571
+ return true;
572
+ }
573
+
574
+ /**
575
+ * Create an object composed of object properties that satisfy a given condition.
576
+ * @param {T} source - The object to pick properties from.
577
+ * @param {(value: T[keyof T], key: string) => boolean} predicate - The function invoked per property.
578
+ * @returns {Partial<T>} - Returns the new object.
579
+ */
580
+ function pickBy(source, predicate) {
581
+ const result = {};
582
+ for (const key in source) {
583
+ if (Object.prototype.hasOwnProperty.call(source, key) && predicate(source[key], key)) {
584
+ result[key] = source[key];
585
+ }
586
+ }
587
+ return result;
588
+ }
589
+
590
+ /**
591
+ * Create an object composed of object properties that do not satisfy a given condition.
592
+ * @param {T} source - The object to omit properties from.
593
+ * @param {(value: T[keyof T], key: string) => boolean} predicate - The function invoked per property.
594
+ * @returns {Partial<T>} - Returns the new object.
595
+ */
596
+ function omitBy(source, predicate) {
597
+ // Negate the predicate and pass it to pickBy
598
+ return pickBy(source, (value, key) => !predicate(value, key));
599
+ }
600
+
601
+ /**
602
+ * Creates an array of numbers (positive and/or negative) progressing from start up to, but not including, end.
603
+ * A step of -1 is used if a negative start is specified without an end or step.
604
+ * If end is not specified, it's set to start with start then set to 0.
605
+ *
606
+ * @param {number} start The start of the range.
607
+ * @param {number} end The end of the range.
608
+ * @param {number} step The value to increment or decrement by.
609
+ * @param {boolean} [fromRight] Specify iterating from right to left.
610
+ * @returns {Array} Returns the range of numbers.
611
+ */
612
+ function range(start, end, step, fromRight = false) {
613
+ // if range takes only 1 input, that input is end, start with 0
614
+ if (end === undefined) {
615
+ end = start;
616
+ start = 0;
617
+ }
618
+ step = step === undefined ? (start < end ? 1 : -1) : step;
619
+ let index = -1;
620
+ let length = Math.max(Math.ceil((end - start) / (step || 1)), 0);
621
+ const result = new Array(length);
622
+ while (length--) {
623
+ result[fromRight ? length : ++index] = start;
624
+ start += step;
625
+ }
626
+ return result;
627
+ }
628
+
469
629
  // https://regex101.com/library/mX1xW0
470
630
  const emailPattern = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/;
471
631
  const urlPattern = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
472
632
  const httpsPattern = /^https:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
633
+ // https://regex101.com/library/dT0vT3?orderBy=RELEVANCE&search=ip
634
+ 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]?)$/;
635
+ // 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)
636
+ // https://www.regextester.com/103452
637
+ const fqdnRegex = /(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)/;
638
+
639
+ function isIP(ip) {
640
+ return ipRegex.test(ip);
641
+ }
642
+ function isFQDN(fqdn) {
643
+ return fqdnRegex.test(fqdn);
644
+ }
645
+ function isURL(url) {
646
+ return urlPattern.test(url);
647
+ }
648
+ function isHttps(url) {
649
+ return httpsPattern.test(url);
650
+ }
473
651
 
474
652
  class IsHttpsPipe {
475
653
  transform(value) {
476
- return httpsPattern.test(value);
654
+ return isHttps(value);
477
655
  }
478
656
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: IsHttpsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
479
657
  static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.1.2", ngImport: i0, type: IsHttpsPipe, isStandalone: true, name: "isHttps" }); }
@@ -520,6 +698,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImpor
520
698
  }]
521
699
  }] });
522
700
 
701
+ class RangePipe {
702
+ transform(value) {
703
+ const input = value;
704
+ return range(...input);
705
+ }
706
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RangePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
707
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.1.2", ngImport: i0, type: RangePipe, isStandalone: true, name: "range" }); }
708
+ }
709
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: RangePipe, decorators: [{
710
+ type: Pipe,
711
+ args: [{
712
+ name: 'range',
713
+ standalone: true,
714
+ }]
715
+ }] });
716
+
523
717
  /* eslint-disable @typescript-eslint/no-explicit-any */
524
718
  /**
525
719
  * Combines multiple `Observable` or `Signal` sources into a `Signal` that emits their values. It's like combineLatest.
@@ -818,136 +1012,38 @@ function parseArgs(args) {
818
1012
  }
819
1013
 
820
1014
  /**
821
- * Calculates the difference in whole days between two dates.
822
- *
823
- * @param {Date | number | string} dateLeft - The date from which the difference is measured (the reference date).
824
- * Can be a Date object, a number representing milliseconds since the Unix epoch,
825
- * or a string in a format parseable by the Date constructor.
826
- * @param {Date | number | string} dateRight - The date to be compared against the reference date.
827
- * Can be a Date object, a number representing milliseconds since the Unix epoch,
828
- * or a string in a format parseable by the Date constructor.
829
- * @returns {number} The number of whole days between the reference date (dateLeft) and the compared date (dateRight).
830
- *
831
- * @example
832
- * // How many whole days are between '2022-09-08' and '2023-09-18'?
833
- * const result = differenceInDays('2022-09-08', new Date('2023-09-18'));
834
- */
835
- function differenceInDays(dateLeft, dateRight) {
836
- const _dateLeft = new Date(dateLeft);
837
- const _dateRight = new Date(dateRight);
838
- const difference = (_dateLeft.getTime() - _dateRight.getTime()) / (1000 * 60 * 60 * 24);
839
- return Math.floor(difference);
840
- }
841
-
842
- /**
843
- * Provides a conditional validator that applies the specified validator functions only if the condition is met.
1015
+ * A custom validator function that checks for intersection between two form controls. The two controls' values must be arrays.
844
1016
  *
845
- * @param condition A function that determines whether the validators should be applied.
846
- * @param trueValidatorFn The validator function or an array of validator functions to be applied when the condition is true.
847
- * @param falseValidatorFn Optional. The validator function or an array of validator functions to be applied when the condition is false.
848
- * @returns A validator function that can be used with Angular Reactive Forms.
1017
+ * @param {string} controlName1 - The name of the first form control.
1018
+ * @param {string} controlName2 - The name of the second form control.
1019
+ * @returns {ValidatorFn} A function that validates the form group and returns an error if there is an intersection.
849
1020
  */
850
- function ifValidator(condition, trueValidatorFn, falseValidatorFn) {
851
- /**
852
- * @param control The AbstractControl to validate.
853
- * @returns Validation errors if the condition is met; otherwise, null.
854
- */
855
- return (control) => {
856
- if (!trueValidatorFn || !condition(control)) {
857
- return composeValidators(control, falseValidatorFn);
1021
+ function intersectionValidator(controlName1, controlName2) {
1022
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1023
+ return (formGroup) => {
1024
+ const control1 = formGroup.get(controlName1);
1025
+ const control2 = formGroup.get(controlName2);
1026
+ if (!control1 || !control2) {
1027
+ return null; // If either control is undefined or null
858
1028
  }
859
- return composeValidators(control, trueValidatorFn);
860
- };
861
- }
862
- /**
863
- * Provides a conditional async validator that applies the specified async validator function only if the condition is met.
864
- *
865
- * @param condition A function that determines whether the async validator should be applied.
866
- * @param validatorFn The async validator function to be applied conditionally.
867
- * @returns An async validator function that can be used with Angular Reactive Forms.
868
- */
869
- function ifAsyncValidator(condition, validatorFn) {
870
- /**
871
- * @param control The AbstractControl to validate asynchronously.
872
- * @returns An observable that emits validation errors if the condition is met; otherwise, emits null.
873
- */
874
- return (control) => {
875
- if (!validatorFn || !condition(control)) {
876
- return of(null);
1029
+ const value1 = control1.value;
1030
+ const value2 = control2.value;
1031
+ // Assuming both values are arrays
1032
+ if (!Array.isArray(value1) || !Array.isArray(value2)) {
1033
+ return null;
877
1034
  }
878
- return validatorFn(control);
879
- };
880
- }
881
- /**
882
- * Composes and applies the provided validators to the given AbstractControl.
883
- *
884
- * @param control The AbstractControl to validate.
885
- * @param validatorFn The validator function or an array of validator functions to be applied.
886
- * @returns Validation errors if the validators are applicable; otherwise, null.
887
- */
888
- function composeValidators(control, validatorFn) {
889
- if (!validatorFn) {
890
- return null;
891
- }
892
- const validatorFns = Array.isArray(validatorFn) ? validatorFn : [validatorFn];
893
- return Validators.compose(validatorFns)?.(control) || null;
894
- }
895
-
896
- /**
897
- * Check if a value is empty.
898
- * @param {T | undefined | null} value - The value to check for emptiness.
899
- * @returns {boolean} - Returns true if the value is empty, otherwise false.
900
- */
901
- function isEmpty(value) {
902
- if (value == null)
903
- return true;
904
- if (typeof value === 'string' || Array.isArray(value)) {
905
- return value.length === 0;
906
- }
907
- if (typeof value === 'object') {
908
- return Object.keys(value).length === 0;
909
- }
910
- return false;
911
- }
912
-
913
- /**
914
- * Check if two values are deeply equal.
915
- * @param {T} value1 - The first value to compare.
916
- * @param {T} value2 - The second value to compare.
917
- * @returns {boolean} - Returns true if the values are deeply equal, otherwise false.
918
- */
919
- function isEqual(value1, value2) {
920
- if (value1 === value2)
921
- return true;
922
- if (typeof value1 !== 'object' || typeof value2 !== 'object' || value1 === null || value2 === null) {
923
- return false;
924
- }
925
- const keys1 = Object.keys(value1);
926
- const keys2 = Object.keys(value2);
927
- if (keys1.length !== keys2.length)
928
- return false;
929
- for (const key of keys1) {
930
- if (!keys2.includes(key) || !isEqual(value1[key], value2[key])) {
931
- return false;
1035
+ const intersection = value1.filter((value) => value2.includes(value));
1036
+ if (intersection.length > 0) {
1037
+ control1.setErrors({ intersection: true });
1038
+ control2.setErrors({ intersection: true });
1039
+ return { intersection: true };
932
1040
  }
933
- }
934
- return true;
935
- }
936
-
937
- /**
938
- * Create an object composed of object properties that satisfy a given condition.
939
- * @param {T} source - The object to pick properties from.
940
- * @param {(value: T[keyof T], key: string) => boolean} predicate - The function invoked per property.
941
- * @returns {Partial<T>} - Returns the new object.
942
- */
943
- function pickBy(source, predicate) {
944
- const result = {};
945
- for (const key in source) {
946
- if (Object.prototype.hasOwnProperty.call(source, key) && predicate(source[key], key)) {
947
- result[key] = source[key];
1041
+ else {
1042
+ control1.setErrors(null);
1043
+ control2.setErrors(null);
1044
+ return null;
948
1045
  }
949
- }
950
- return result;
1046
+ };
951
1047
  }
952
1048
 
953
1049
  /**
@@ -1034,5 +1130,5 @@ function httpsValidator(control) {
1034
1130
  * Generated bundle index. Do not edit.
1035
1131
  */
1036
1132
 
1037
- export { ArrayJoinPipe, ByteConverterPipe, IsHttpsPipe, MaskPipe, UniqueValidator, combineFrom, combineLatestEager, computedAsync, createAsyncState, createTrigger, differenceInDays, distinctOnChange, httpsValidator, ifAsyncValidator, ifValidator, injectParams, injectQueryParams, isEmpty, isEqual, logger, mergeFrom, pickBy, poll, startWithTap, switchMapWithAsyncState, urlValidator };
1133
+ export { ArrayJoinPipe, ByteConverterPipe, IsHttpsPipe, MaskPipe, RangePipe, UniqueValidator, combineFrom, combineLatestEager, computedAsync, createAsyncState, createTrigger, differenceInDays, distinctOnChange, httpsValidator, ifAsyncValidator, ifValidator, injectParams, injectQueryParams, intersectionValidator, isEmpty, isEqual, isFQDN, isHttps, isIP, isURL, logger, mergeFrom, omitBy, pickBy, poll, range, startWithTap, switchMapWithAsyncState, urlValidator };
1038
1134
  //# sourceMappingURL=ngx-lift.mjs.map