ng-hub-ui-utils 1.1.0 → 1.2.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.
@@ -1,7 +1,7 @@
1
- import { fromEvent, Observable, EMPTY, of, Subject, timer, race, isObservable } from 'rxjs';
1
+ import { fromEvent, Observable, Subject, isObservable, EMPTY, of, timer, race } from 'rxjs';
2
2
  import { takeUntil, map, filter, withLatestFrom, endWith, take, mergeMap, tap } from 'rxjs/operators';
3
3
  import * as i0 from '@angular/core';
4
- import { ElementRef, TemplateRef, createComponent, inject, ApplicationRef, Injectable, Injector, ViewContainerRef, NgZone, Pipe, ChangeDetectorRef } from '@angular/core';
4
+ import { InjectionToken, inject, Injectable, ElementRef, TemplateRef, createComponent, ApplicationRef, Pipe, ChangeDetectorRef, Injector, ViewContainerRef, NgZone } from '@angular/core';
5
5
  import { DOCUMENT } from '@angular/common';
6
6
 
7
7
  const FOCUSABLE_ELEMENTS_SELECTOR = [
@@ -60,6 +60,274 @@ const hubFocusTrap = (zone, element, stopFocusTrap$, refocusOnClick = false) =>
60
60
  });
61
61
  };
62
62
 
63
+ /**
64
+ * Converts a value to an integer using parseInt.
65
+ *
66
+ * @param {any} value - The `value` parameter in the `toInteger` function is the input value that needs to be converted to an
67
+ * integer.
68
+ *
69
+ * @returns Is returning the parsed integer value of the input `value`.
70
+ */
71
+ function toInteger(value) {
72
+ return parseInt(`${value}`, 10);
73
+ }
74
+ function toString(value) {
75
+ return value !== undefined && value !== null ? `${value}` : '';
76
+ }
77
+ function getValueInRange(value, max, min = 0) {
78
+ return Math.max(Math.min(value, max), min);
79
+ }
80
+ function isString(value) {
81
+ return typeof value === 'string';
82
+ }
83
+ function isNumber(value) {
84
+ return !isNaN(toInteger(value));
85
+ }
86
+ function isInteger(value) {
87
+ return (typeof value === 'number' &&
88
+ isFinite(value) &&
89
+ Math.floor(value) === value);
90
+ }
91
+ function isDefined(value) {
92
+ return value !== undefined && value !== null;
93
+ }
94
+ /**
95
+ * Determines if two objects or values are equivalent.
96
+ *
97
+ * @param o1 Object or value to compare.
98
+ * @param o2 Object or value to compare.
99
+ * @returns true if arguments are equal.
100
+ */
101
+ function equals(o1, o2) {
102
+ if (o1 === o2) {
103
+ return true;
104
+ }
105
+ if (o1 === null || o2 === null) {
106
+ return false;
107
+ }
108
+ if (o1 !== o1 && o2 !== o2) {
109
+ return true;
110
+ } // NaN === NaN
111
+ let t1 = typeof o1, t2 = typeof o2, length, key, keySet;
112
+ if (t1 == t2 && t1 == 'object') {
113
+ if (Array.isArray(o1)) {
114
+ if (!Array.isArray(o2)) {
115
+ return false;
116
+ }
117
+ if ((length = o1.length) == o2.length) {
118
+ for (key = 0; key < length; key++) {
119
+ if (!equals(o1[key], o2[key])) {
120
+ return false;
121
+ }
122
+ }
123
+ return true;
124
+ }
125
+ }
126
+ else {
127
+ if (Array.isArray(o2)) {
128
+ return false;
129
+ }
130
+ keySet = Object.create(null);
131
+ for (key in o1) {
132
+ if (!equals(o1[key], o2[key])) {
133
+ return false;
134
+ }
135
+ keySet[key] = true;
136
+ }
137
+ for (key in o2) {
138
+ if (!(key in keySet) && typeof o2[key] !== 'undefined') {
139
+ return false;
140
+ }
141
+ }
142
+ return true;
143
+ }
144
+ }
145
+ return false;
146
+ }
147
+ /**
148
+ * Checks if a value is a Promise.
149
+ *
150
+ * @param {any} v - The parameter `v` in the `isPromise` function represents any value that is being checked to determine if it is
151
+ * a Promise.
152
+ *
153
+ * @returns A boolean value indicating whether the input `v` is a Promise or not. If `v` has a `then` property, it is considered
154
+ * a Promise and the function returns `true`. Otherwise, it returns `false`.
155
+ */
156
+ function isPromise(v) {
157
+ return v && v.then;
158
+ }
159
+ /**
160
+ * Pads a number with a leading zero if it is a valid number.
161
+ *
162
+ * @param {number} value - The `padNumber` function takes a number as input and pads it with a leading zero if it is a valid
163
+ * number. If the input is not a number, it returns an empty string.
164
+ *
165
+ * @returns Takes a number as input and pads it with a leading zero if it is a valid number. If the input is a number, the function
166
+ * returns the input value padded with a leading zero and sliced to keep only the last two characters. If the input is not a number,
167
+ * an empty string is returned.
168
+ */
169
+ function padNumber(value) {
170
+ if (isNumber(value)) {
171
+ return `0${value}`.slice(-2);
172
+ }
173
+ else {
174
+ return '';
175
+ }
176
+ }
177
+ /**
178
+ * Escapes special characters in a given text to be used in a regular expression.
179
+ *
180
+ * @param text - The `regExpEscape` function takes a `text` parameter as input. This function is designed to escape special
181
+ * characters in a given text so that it can be safely used within a regular expression pattern.
182
+ *
183
+ * @returns A new string with any special characters in the input `text` escaped with a backslash.
184
+ */
185
+ function regExpEscape(text) {
186
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
187
+ }
188
+ function closest(element, selector) {
189
+ if (!selector) {
190
+ return null;
191
+ }
192
+ /*
193
+ * In certain browsers (e.g. Edge 44.18362.449.0) HTMLDocument does
194
+ * not support `Element.prototype.closest`. To emulate the correct behaviour
195
+ * we return null when the method is missing.
196
+ *
197
+ * Note that in evergreen browsers `closest(document.documentElement, 'html')`
198
+ * will return the document element whilst in Edge null will be returned. This
199
+ * compromise was deemed good enough.
200
+ */
201
+ if (typeof element.closest === 'undefined') {
202
+ return null;
203
+ }
204
+ return element.closest(selector);
205
+ }
206
+ /**
207
+ * Force a browser reflow
208
+ *
209
+ * @param element element where to apply the reflow
210
+ */
211
+ function reflow(element) {
212
+ return (element || document.body).getBoundingClientRect();
213
+ }
214
+ /**
215
+ * Creates an observable where all callbacks are executed inside a given zone
216
+ *
217
+ * @param zone
218
+ */
219
+ function runInZone(zone) {
220
+ return (source) => {
221
+ return new Observable((observer) => {
222
+ const next = (value) => zone.run(() => observer.next(value));
223
+ const error = (e) => zone.run(() => observer.error(e));
224
+ const complete = () => zone.run(() => observer.complete());
225
+ return source.subscribe({ next, error, complete });
226
+ });
227
+ };
228
+ }
229
+ function removeAccents(str) {
230
+ return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
231
+ }
232
+ /**
233
+ * Replaces placeholders in a string with corresponding values from a given object.
234
+ *
235
+ * @param expr a string that represents the expression to be interpolated.
236
+ * @param params an optional object that contains the values to be interpolated into the expr string.
237
+ * @returns the interpolated string.
238
+ */
239
+ function interpolateString(expr = '', params = {}, templateMatcher = /{{\s?([^{}\s]*)\s?}}/g) {
240
+ if (!params) {
241
+ return expr;
242
+ }
243
+ return expr.replace(templateMatcher, (substring, b) => {
244
+ let r = getValue(params, b);
245
+ return isDefined(r) ? r : substring;
246
+ });
247
+ }
248
+ /**
249
+ * Retrieves the value of a nested property from an object using dot notation.
250
+ *
251
+ * @param target the object from which you want to retrieve a value.
252
+ * @param key a string that represents the property or nested properties of the target object.
253
+ * @returns the value of the specified key in the target object.
254
+ */
255
+ function getValue(target, key) {
256
+ let keys = typeof key === 'string' ? key.split('.') : [key];
257
+ key = '';
258
+ do {
259
+ key += keys.shift();
260
+ if (isDefined(target) &&
261
+ isDefined(target[key]) &&
262
+ (typeof target[key] === 'object' || !keys.length)) {
263
+ target = target[key];
264
+ key = '';
265
+ }
266
+ else if (!keys.length) {
267
+ target = undefined;
268
+ }
269
+ else {
270
+ key += '.';
271
+ }
272
+ } while (keys.length);
273
+ return target;
274
+ }
275
+ /**
276
+ * Returns the active element in the given root.
277
+ *
278
+ * If the active element is inside a shadow root, it is searched recursively.
279
+ */
280
+ function getActiveElement(root = document) {
281
+ const activeEl = root?.activeElement;
282
+ if (!activeEl) {
283
+ return null;
284
+ }
285
+ return activeEl.shadowRoot
286
+ ? getActiveElement(activeEl.shadowRoot)
287
+ : activeEl;
288
+ }
289
+
290
+ const HUB_TRANSLATION_CONFIG = new InjectionToken('HUB_TRANSLATION_CONFIG');
291
+
292
+ class HubTranslationService {
293
+ #config = inject(HUB_TRANSLATION_CONFIG, { optional: true }) ?? {};
294
+ defaultTranslations = this.#config.dictionaries ?? {};
295
+ translations;
296
+ translationSource = new Subject();
297
+ translationObserver = this.translationSource.asObservable();
298
+ constructor() {
299
+ this.initialize();
300
+ }
301
+ initialize() {
302
+ const language = this.#config.language ?? this.#config.fallbackLanguage ?? 'en';
303
+ const fallbackLanguage = this.#config.fallbackLanguage ?? 'en';
304
+ const fallbackTranslations = this.defaultTranslations[fallbackLanguage] ?? {};
305
+ const selectedTranslations = this.defaultTranslations[language] ?? fallbackTranslations;
306
+ this.setTranslations(selectedTranslations);
307
+ }
308
+ /**
309
+ * Retrieves a value from a translations object based on a given key.
310
+ */
311
+ getTranslation(key) {
312
+ return getValue(this.translations, key);
313
+ }
314
+ /**
315
+ * Merges fallback translations with the provided translations and updates observers.
316
+ */
317
+ setTranslations(translations = {}) {
318
+ const fallbackLanguage = this.#config.fallbackLanguage ?? 'en';
319
+ const fallbackTranslations = this.defaultTranslations[fallbackLanguage] ?? {};
320
+ const nextTranslations = translations ?? {};
321
+ this.translations = { ...fallbackTranslations, ...nextTranslations };
322
+ this.translationSource.next(this.translations);
323
+ }
324
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HubTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
325
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HubTranslationService });
326
+ }
327
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HubTranslationService, decorators: [{
328
+ type: Injectable
329
+ }], ctorParameters: () => [] });
330
+
63
331
  /**
64
332
  * Positions an overlay container relative to an origin element.
65
333
  * The first configured position that fits within the viewport is applied.
@@ -446,136 +714,251 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImpor
446
714
  }]
447
715
  }] });
448
716
 
449
- /**
450
- * Converts a value to an integer using parseInt.
451
- *
452
- * @param {any} value - The `value` parameter in the `toInteger` function is the input value that needs to be converted to an
453
- * integer.
454
- *
455
- * @returns Is returning the parsed integer value of the input `value`.
456
- */
457
- function toInteger(value) {
458
- return parseInt(`${value}`, 10);
459
- }
460
- function toString(value) {
461
- return value !== undefined && value !== null ? `${value}` : '';
462
- }
463
- function getValueInRange(value, max, min = 0) {
464
- return Math.max(Math.min(value, max), min);
717
+ class GetPipe {
718
+ /**
719
+ * @param value The object to retrieve the property from.
720
+ * @param path The dot-separated path string to the property.
721
+ * @param defaultValue The value to return if the property is not found.
722
+ */
723
+ transform(value, path, defaultValue) {
724
+ if (typeof path !== 'string') {
725
+ return value;
726
+ }
727
+ return path
728
+ .split('.')
729
+ .reduce((a, c) => a && a[c] !== null && a[c] !== undefined
730
+ ? a[c]
731
+ : defaultValue || null, value);
732
+ }
733
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
734
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, isStandalone: true, name: "get" });
465
735
  }
466
- function isString(value) {
467
- return typeof value === 'string';
736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, decorators: [{
737
+ type: Pipe,
738
+ args: [{
739
+ name: 'get',
740
+ standalone: true
741
+ }]
742
+ }] });
743
+
744
+ class IsObjectPipe {
745
+ transform(value) {
746
+ return typeof value === 'object';
747
+ }
748
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
749
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, isStandalone: true, name: "isObject" });
468
750
  }
469
- function isNumber(value) {
470
- return !isNaN(toInteger(value));
751
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, decorators: [{
752
+ type: Pipe,
753
+ args: [{
754
+ name: 'isObject'
755
+ }]
756
+ }] });
757
+
758
+ class IsObservablePipe {
759
+ transform(value) {
760
+ return isObservable(value);
761
+ }
762
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
763
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, isStandalone: true, name: "isObservable" });
471
764
  }
472
- function isInteger(value) {
473
- return (typeof value === 'number' &&
474
- isFinite(value) &&
475
- Math.floor(value) === value);
765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, decorators: [{
766
+ type: Pipe,
767
+ args: [{
768
+ name: 'isObservable',
769
+ standalone: true
770
+ }]
771
+ }] });
772
+
773
+ class IsStringPipe {
774
+ transform(value) {
775
+ return typeof value === 'string';
776
+ }
777
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
778
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, isStandalone: true, name: "isString" });
476
779
  }
477
- function isDefined(value) {
478
- return value !== undefined && value !== null;
479
- }
480
- /**
481
- * Checks if a value is a Promise.
482
- *
483
- * @param {any} v - The parameter `v` in the `isPromise` function represents any value that is being checked to determine if it is
484
- * a Promise.
485
- *
486
- * @returns A boolean value indicating whether the input `v` is a Promise or not. If `v` has a `then` property, it is considered
487
- * a Promise and the function returns `true`. Otherwise, it returns `false`.
488
- */
489
- function isPromise(v) {
490
- return v && v.then;
491
- }
492
- /**
493
- * Pads a number with a leading zero if it is a valid number.
494
- *
495
- * @param {number} value - The `padNumber` function takes a number as input and pads it with a leading zero if it is a valid
496
- * number. If the input is not a number, it returns an empty string.
497
- *
498
- * @returns Takes a number as input and pads it with a leading zero if it is a valid number. If the input is a number, the function
499
- * returns the input value padded with a leading zero and sliced to keep only the last two characters. If the input is not a number,
500
- * an empty string is returned.
501
- */
502
- function padNumber(value) {
503
- if (isNumber(value)) {
504
- return `0${value}`.slice(-2);
780
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, decorators: [{
781
+ type: Pipe,
782
+ args: [{
783
+ name: 'isString'
784
+ }]
785
+ }] });
786
+
787
+ class TranslatePipe {
788
+ _ref = inject(ChangeDetectorRef);
789
+ _translationSvc = inject(HubTranslationService);
790
+ value = '';
791
+ lastKey = null;
792
+ lastParams = [];
793
+ translationSubscription;
794
+ /**
795
+ * Updates the value of a key by interpolating the translation and marking for change detection.
796
+ */
797
+ updateValue(key, interpolateParams) {
798
+ const value = interpolateString(this._translationSvc.getTranslation(key), interpolateParams);
799
+ this.value = value !== undefined ? value : key;
800
+ this.lastKey = key;
801
+ this._ref.markForCheck();
505
802
  }
506
- else {
507
- return '';
803
+ /**
804
+ * Transforms a translation key with optional interpolation params.
805
+ */
806
+ transform(query, ...args) {
807
+ if (!query || !query.length) {
808
+ return query;
809
+ }
810
+ // If we ask another time for the same key, return the last value.
811
+ if (equals(query, this.lastKey) && equals(args, this.lastParams)) {
812
+ return this.value;
813
+ }
814
+ let interpolateParams = undefined;
815
+ if (isDefined(args[0]) && args.length) {
816
+ if (typeof args[0] === 'string' && args[0].length) {
817
+ // We accept objects written in the template such as {n:1}, {'n':1}, {n:'v'}.
818
+ // This converts them to valid JSON.
819
+ let validArgs = args[0]
820
+ .replace(/(\')?([a-zA-Z0-9_]+)(\')?(\s)?:/g, '"$2":')
821
+ .replace(/:(\s)?(\')(.*?)(\')/g, ':"$3"');
822
+ try {
823
+ interpolateParams = JSON.parse(validArgs);
824
+ }
825
+ catch (e) {
826
+ throw new SyntaxError(`Wrong parameter in TranslatePipe. Expected a valid Object, received: ${args[0]}`);
827
+ }
828
+ }
829
+ else if (typeof args[0] === 'object' && !Array.isArray(args[0])) {
830
+ interpolateParams = args[0];
831
+ }
832
+ }
833
+ // Store the query, in case it changes.
834
+ this.lastKey = query;
835
+ // Store the params, in case they change.
836
+ this.lastParams = args;
837
+ // Set the value.
838
+ this.updateValue(query, interpolateParams);
839
+ // Clean any existing subscription.
840
+ this._dispose();
841
+ if (!this.translationSubscription) {
842
+ this.translationSubscription =
843
+ this._translationSvc.translationObserver.subscribe(() => {
844
+ if (this.lastKey) {
845
+ this.lastKey = null;
846
+ this.updateValue(query, interpolateParams);
847
+ }
848
+ });
849
+ }
850
+ return this.value;
851
+ }
852
+ /**
853
+ * Clean any existing subscription to change events.
854
+ */
855
+ _dispose() {
856
+ if (typeof this.translationSubscription !== 'undefined') {
857
+ this.translationSubscription.unsubscribe();
858
+ this.translationSubscription = undefined;
859
+ }
860
+ }
861
+ ngOnDestroy() {
862
+ this._dispose();
863
+ }
864
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: TranslatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
865
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: TranslatePipe, isStandalone: true, name: "translate", pure: false });
866
+ }
867
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: TranslatePipe, decorators: [{
868
+ type: Pipe,
869
+ args: [{
870
+ name: 'translate',
871
+ standalone: true,
872
+ pure: false
873
+ }]
874
+ }] });
875
+
876
+ class UcfirstPipe {
877
+ transform(value = '') {
878
+ return value.charAt(0).toUpperCase() + value.slice(1);
508
879
  }
880
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
881
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, isStandalone: true, name: "ucfirst" });
509
882
  }
883
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, decorators: [{
884
+ type: Pipe,
885
+ args: [{
886
+ name: 'ucfirst',
887
+ standalone: true
888
+ }]
889
+ }] });
890
+
510
891
  /**
511
- * Escapes special characters in a given text to be used in a regular expression.
892
+ * A standalone pipe that unwraps the value of an observable or returns the value directly if it's not an observable.
512
893
  *
513
- * @param text - The `regExpEscape` function takes a `text` parameter as input. This function is designed to escape special
514
- * characters in a given text so that it can be safely used within a regular expression pattern.
894
+ * @description
895
+ * The `UnwrapAsyncPipe` is used to unwrap the value emitted by an observable or return the value directly if it's not an observable.
896
+ * It subscribes to the observable and returns the emitted value. If the input is not an observable, it simply returns the value.
515
897
  *
516
- * @returns A new string with any special characters in the input `text` escaped with a backslash.
898
+ * @usageNotes
899
+ * ```html
900
+ * <div>{{ observableOrValue | unwrapAsync }}</div>
901
+ * ```
902
+ *
903
+ * @publicApi
517
904
  */
518
- function regExpEscape(text) {
519
- return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
520
- }
521
- function closest(element, selector) {
522
- if (!selector) {
523
- return null;
905
+ class UnwrapAsyncPipe {
906
+ #cdr = inject(ChangeDetectorRef);
907
+ /**
908
+ * The unwrapped value of the observable or the direct value.
909
+ */
910
+ value = null;
911
+ /**
912
+ * The subscription to the observable.
913
+ */
914
+ subscription = null;
915
+ /**
916
+ * Performs cleanup tasks when the pipe is destroyed.
917
+ */
918
+ ngOnDestroy() {
919
+ this.unsubscribe();
524
920
  }
525
- /*
526
- * In certain browsers (e.g. Edge 44.18362.449.0) HTMLDocument does
527
- * not support `Element.prototype.closest`. To emulate the correct behaviour
528
- * we return null when the method is missing.
921
+ /**
922
+ * Transforms the input value.
529
923
  *
530
- * Note that in evergreen browsers `closest(document.documentElement, 'html')`
531
- * will return the document element whilst in Edge null will be returned. This
532
- * compromise was deemed good enough.
924
+ * @param value The input value to transform. It can be an observable or a direct value.
925
+ * @returns The unwrapped value of the observable or the direct value.
533
926
  */
534
- if (typeof element.closest === 'undefined') {
535
- return null;
927
+ transform(value) {
928
+ if (value instanceof Observable) {
929
+ this.unsubscribe();
930
+ this.subscription = value.subscribe((result) => {
931
+ this.value = result;
932
+ this.#cdr.markForCheck();
933
+ });
934
+ }
935
+ else {
936
+ // Clean up subscription when switching to direct value
937
+ this.unsubscribe();
938
+ this.value = value;
939
+ }
940
+ return this.value;
536
941
  }
537
- return element.closest(selector);
538
- }
539
- /**
540
- * Force a browser reflow
541
- *
542
- * @param element element where to apply the reflow
543
- */
544
- function reflow(element) {
545
- return (element || document.body).getBoundingClientRect();
546
- }
547
- /**
548
- * Creates an observable where all callbacks are executed inside a given zone
549
- *
550
- * @param zone
551
- */
552
- function runInZone(zone) {
553
- return (source) => {
554
- return new Observable((observer) => {
555
- const next = (value) => zone.run(() => observer.next(value));
556
- const error = (e) => zone.run(() => observer.error(e));
557
- const complete = () => zone.run(() => observer.complete());
558
- return source.subscribe({ next, error, complete });
559
- });
560
- };
561
- }
562
- function removeAccents(str) {
563
- return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
564
- }
565
- /**
566
- * Returns the active element in the given root.
567
- *
568
- * If the active element is inside a shadow root, it is searched recursively.
569
- */
570
- function getActiveElement(root = document) {
571
- const activeEl = root?.activeElement;
572
- if (!activeEl) {
573
- return null;
942
+ /**
943
+ * Unsubscribes from the current subscription.
944
+ */
945
+ unsubscribe() {
946
+ if (this.subscription) {
947
+ this.subscription.unsubscribe();
948
+ this.subscription = null;
949
+ }
574
950
  }
575
- return activeEl.shadowRoot
576
- ? getActiveElement(activeEl.shadowRoot)
577
- : activeEl;
951
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
952
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, isStandalone: true, name: "unwrapAsync", pure: false });
578
953
  }
954
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, decorators: [{
955
+ type: Pipe,
956
+ args: [{
957
+ name: 'unwrapAsync',
958
+ standalone: true,
959
+ pure: false
960
+ }]
961
+ }] });
579
962
 
580
963
  function getTransitionDurationMs(element) {
581
964
  const { transitionDelay, transitionDuration } = window.getComputedStyle(element);
@@ -763,163 +1146,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImpor
763
1146
  args: [{ providedIn: 'root' }]
764
1147
  }] });
765
1148
 
766
- class GetPipe {
767
- /**
768
- * @param value The object to retrieve the property from.
769
- * @param path The dot-separated path string to the property.
770
- * @param defaultValue The value to return if the property is not found.
771
- */
772
- transform(value, path, defaultValue) {
773
- if (typeof path !== 'string') {
774
- return value;
775
- }
776
- return path
777
- .split('.')
778
- .reduce((a, c) => a && a[c] !== null && a[c] !== undefined
779
- ? a[c]
780
- : defaultValue || null, value);
781
- }
782
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
783
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, isStandalone: true, name: "get" });
784
- }
785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: GetPipe, decorators: [{
786
- type: Pipe,
787
- args: [{
788
- name: 'get',
789
- standalone: true
790
- }]
791
- }] });
792
-
793
- class IsObjectPipe {
794
- transform(value) {
795
- return typeof value === 'object';
796
- }
797
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
798
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, isStandalone: true, name: "isObject" });
799
- }
800
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObjectPipe, decorators: [{
801
- type: Pipe,
802
- args: [{
803
- name: 'isObject'
804
- }]
805
- }] });
806
-
807
- class IsObservablePipe {
808
- transform(value) {
809
- return isObservable(value);
810
- }
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
812
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, isStandalone: true, name: "isObservable" });
813
- }
814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsObservablePipe, decorators: [{
815
- type: Pipe,
816
- args: [{
817
- name: 'isObservable',
818
- standalone: true
819
- }]
820
- }] });
821
-
822
- class IsStringPipe {
823
- transform(value) {
824
- return typeof value === 'string';
825
- }
826
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
827
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, isStandalone: true, name: "isString" });
828
- }
829
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: IsStringPipe, decorators: [{
830
- type: Pipe,
831
- args: [{
832
- name: 'isString'
833
- }]
834
- }] });
835
-
836
- class UcfirstPipe {
837
- transform(value = '') {
838
- return value.charAt(0).toUpperCase() + value.slice(1);
839
- }
840
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
841
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, isStandalone: true, name: "ucfirst" });
842
- }
843
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UcfirstPipe, decorators: [{
844
- type: Pipe,
845
- args: [{
846
- name: 'ucfirst',
847
- standalone: true
848
- }]
849
- }] });
850
-
851
- /**
852
- * A standalone pipe that unwraps the value of an observable or returns the value directly if it's not an observable.
853
- *
854
- * @description
855
- * The `UnwrapAsyncPipe` is used to unwrap the value emitted by an observable or return the value directly if it's not an observable.
856
- * It subscribes to the observable and returns the emitted value. If the input is not an observable, it simply returns the value.
857
- *
858
- * @usageNotes
859
- * ```html
860
- * <div>{{ observableOrValue | unwrapAsync }}</div>
861
- * ```
862
- *
863
- * @publicApi
864
- */
865
- class UnwrapAsyncPipe {
866
- #cdr = inject(ChangeDetectorRef);
867
- /**
868
- * The unwrapped value of the observable or the direct value.
869
- */
870
- value = null;
871
- /**
872
- * The subscription to the observable.
873
- */
874
- subscription = null;
875
- /**
876
- * Performs cleanup tasks when the pipe is destroyed.
877
- */
878
- ngOnDestroy() {
879
- this.unsubscribe();
880
- }
881
- /**
882
- * Transforms the input value.
883
- *
884
- * @param value The input value to transform. It can be an observable or a direct value.
885
- * @returns The unwrapped value of the observable or the direct value.
886
- */
887
- transform(value) {
888
- if (value instanceof Observable) {
889
- this.unsubscribe();
890
- this.subscription = value.subscribe((result) => {
891
- this.value = result;
892
- this.#cdr.markForCheck();
893
- });
894
- }
895
- else {
896
- // Clean up subscription when switching to direct value
897
- this.unsubscribe();
898
- this.value = value;
899
- }
900
- return this.value;
901
- }
902
- /**
903
- * Unsubscribes from the current subscription.
904
- */
905
- unsubscribe() {
906
- if (this.subscription) {
907
- this.subscription.unsubscribe();
908
- this.subscription = null;
909
- }
910
- }
911
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
912
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, isStandalone: true, name: "unwrapAsync", pure: false });
913
- }
914
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: UnwrapAsyncPipe, decorators: [{
915
- type: Pipe,
916
- args: [{
917
- name: 'unwrapAsync',
918
- standalone: true,
919
- pure: false
920
- }]
921
- }] });
922
-
923
1149
  /*
924
1150
  * Public API Surface of utils
925
1151
  */
@@ -928,5 +1154,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImpor
928
1154
  * Generated bundle index. Do not edit.
929
1155
  */
930
1156
 
931
- export { ContentRef, FOCUSABLE_ELEMENTS_SELECTOR, GetPipe, IsObjectPipe, IsObservablePipe, IsStringPipe, OverlayPosition, OverlayRef, OverlayService, PopupService, ScrollBar, UcfirstPipe, UnwrapAsyncPipe, closest, getActiveElement, getFocusableBoundaryElements, getValueInRange, hubCompleteTransition, hubFocusTrap, hubRunTransition, isDefined, isInteger, isNumber, isPromise, isString, padNumber, reflow, regExpEscape, removeAccents, runInZone, toInteger, toString };
1157
+ export { ContentRef, FOCUSABLE_ELEMENTS_SELECTOR, GetPipe, HUB_TRANSLATION_CONFIG, HubTranslationService, IsObjectPipe, IsObservablePipe, IsStringPipe, OverlayPosition, OverlayRef, OverlayService, PopupService, ScrollBar, TranslatePipe, UcfirstPipe, UnwrapAsyncPipe, closest, equals, getActiveElement, getFocusableBoundaryElements, getValue, getValueInRange, hubCompleteTransition, hubFocusTrap, hubRunTransition, interpolateString, isDefined, isInteger, isNumber, isPromise, isString, padNumber, reflow, regExpEscape, removeAccents, runInZone, toInteger, toString };
932
1158
  //# sourceMappingURL=ng-hub-ui-utils.mjs.map