@ethlete/core 0.2.0-next.20 → 0.2.0-next.22

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,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, HostBinding, InjectionToken, Injectable, Inject, Optional, ElementRef, EventEmitter, Directive, Output, NgZone, Pipe, QueryList } from '@angular/core';
2
+ import { inject, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, HostBinding, InjectionToken, Injectable, ElementRef, Inject, Optional, EventEmitter, Directive, Output, NgZone, Pipe, QueryList } from '@angular/core';
3
3
  import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
4
4
  import { coerceElement, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
5
- import { fromEvent, Observable, Subject, BehaviorSubject, filter, distinctUntilChanged, map, pairwise, combineLatest, shareReplay, takeUntil, startWith, debounceTime, tap, take } from 'rxjs';
5
+ import { fromEvent, Observable, Subject, takeUntil, distinctUntilChanged, BehaviorSubject, filter, map, combineLatest, pairwise, debounceTime, shareReplay, startWith, tap, take } from 'rxjs';
6
6
  import { DOCUMENT } from '@angular/common';
7
7
  import { Router, NavigationEnd } from '@angular/router';
8
8
  import { __decorate, __metadata } from 'tslib';
@@ -346,6 +346,371 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImpor
346
346
  args: [{ providedIn: 'root' }]
347
347
  }], ctorParameters: function () { return [{ type: ResizeObserverFactory }]; } });
348
348
 
349
+ const clamp = (value, min = 0, max = 100) => {
350
+ return Math.max(min, Math.min(max, value));
351
+ };
352
+
353
+ /* eslint-disable @typescript-eslint/no-explicit-any */
354
+ /* eslint-disable no-var */
355
+ /**
356
+ * Stolen from klona to avoid adding a dependency
357
+ * https://github.com/lukeed/klona
358
+ *
359
+ * MIT License
360
+ *
361
+ * Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
362
+ *
363
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
364
+ *
365
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
366
+ *
367
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
368
+ */
369
+ const set = (obj, key, val) => {
370
+ if (typeof val.value === 'object')
371
+ val.value = clone(val.value);
372
+ if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {
373
+ Object.defineProperty(obj, key, val);
374
+ }
375
+ else
376
+ obj[key] = val.value;
377
+ };
378
+ const clone = (original) => {
379
+ if (typeof original !== 'object')
380
+ return original;
381
+ var _og = original;
382
+ var i = 0, k, list, tmp, str = Object.prototype.toString.call(_og);
383
+ if (str === '[object Object]') {
384
+ tmp = Object.create(_og.__proto__ || null);
385
+ }
386
+ else if (str === '[object Array]') {
387
+ tmp = Array(_og.length);
388
+ }
389
+ else if (str === '[object Set]') {
390
+ tmp = new Set();
391
+ _og.forEach(function (val) {
392
+ tmp.add(clone(val));
393
+ });
394
+ }
395
+ else if (str === '[object Map]') {
396
+ tmp = new Map();
397
+ _og.forEach(function (val, key) {
398
+ tmp.set(clone(key), clone(val));
399
+ });
400
+ }
401
+ else if (str === '[object Date]') {
402
+ tmp = new Date(+_og);
403
+ }
404
+ else if (str === '[object RegExp]') {
405
+ tmp = new RegExp(_og.source, _og.flags);
406
+ }
407
+ else if (str === '[object DataView]') {
408
+ tmp = new _og.constructor(clone(_og.buffer));
409
+ }
410
+ else if (str === '[object ArrayBuffer]') {
411
+ tmp = _og.slice(0);
412
+ }
413
+ else if (str.slice(-6) === 'Array]') {
414
+ // ArrayBuffer.isView(x)
415
+ // ~> `new` bcuz `Buffer.slice` => ref
416
+ tmp = new _og.constructor(_og);
417
+ }
418
+ if (tmp) {
419
+ for (list = Object.getOwnPropertySymbols(_og); i < list.length; i++) {
420
+ set(tmp, list[i], Object.getOwnPropertyDescriptor(_og, list[i]));
421
+ }
422
+ for (i = 0, list = Object.getOwnPropertyNames(_og); i < list.length; i++) {
423
+ if (Object.hasOwnProperty.call(tmp, (k = list[i])) && tmp[k] === _og[k])
424
+ continue;
425
+ set(tmp, k, Object.getOwnPropertyDescriptor(_og, k));
426
+ }
427
+ }
428
+ return tmp || _og;
429
+ };
430
+
431
+ const hasCookie = (name) => {
432
+ if (typeof document === 'undefined') {
433
+ return false;
434
+ }
435
+ return document.cookie.split(';').some((c) => {
436
+ return c.trim().startsWith(name + '=');
437
+ });
438
+ };
439
+ const getCookie = (name) => {
440
+ if (typeof document === 'undefined') {
441
+ return null;
442
+ }
443
+ // From https://stackoverflow.com/questions/10730362/get-cookie-by-name
444
+ return ('; ' + document.cookie).split(`; ${name}=`).pop()?.split(';')[0];
445
+ };
446
+ const setCookie = (name, data, expiresInDays = 30, domain = getDomain()) => {
447
+ if (typeof document === 'undefined') {
448
+ return;
449
+ }
450
+ const date = new Date();
451
+ date.setTime(date.getTime() + expiresInDays * 24 * 60 * 60 * 1000);
452
+ document.cookie = `${name}=${data}; path=/; expires=${date.toUTCString()}; domain=${domain}; SameSite=Lax;`;
453
+ };
454
+ const deleteCookie = (name, path, domain = getDomain()) => {
455
+ if (hasCookie(name)) {
456
+ document.cookie =
457
+ name +
458
+ '=' +
459
+ (path ? ';path=' + path : '') +
460
+ (domain ? ';domain=' + domain : '') +
461
+ ';expires=Thu, 01 Jan 1970 00:00:01 GMT';
462
+ }
463
+ };
464
+ const getDomain = () => {
465
+ if (typeof navigator === 'undefined') {
466
+ return null;
467
+ }
468
+ const hostname = window.location.hostname;
469
+ if (hostname.includes('localhost')) {
470
+ return 'localhost';
471
+ }
472
+ const splitHost = hostname.split('.');
473
+ if (splitHost.length > 2) {
474
+ return `${splitHost[splitHost.length - 2]}.${splitHost[splitHost.length - 1]}`;
475
+ }
476
+ return hostname;
477
+ };
478
+
479
+ /* eslint-disable @typescript-eslint/no-explicit-any */
480
+ /* eslint-disable no-var */
481
+ /**
482
+ * Stolen from dequal to avoid adding a dependency
483
+ * https://github.com/lukeed/dequal
484
+ *
485
+ * The MIT License (MIT)
486
+ *
487
+ * Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
488
+ *
489
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
490
+ * of this software and associated documentation files (the "Software"), to deal
491
+ * in the Software without restriction, including without limitation the rights
492
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
493
+ * copies of the Software, and to permit persons to whom the Software is
494
+ * furnished to do so, subject to the following conditions:
495
+ *
496
+ * The above copyright notice and this permission notice shall be included in
497
+ * all copies or substantial portions of the Software.
498
+ *
499
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
500
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
501
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
502
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
503
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
504
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
505
+ * THE SOFTWARE.
506
+ */
507
+ const has = Object.prototype.hasOwnProperty;
508
+ function find(iter, tar, key) {
509
+ for (key of iter.keys()) {
510
+ if (equal(key, tar))
511
+ return key;
512
+ }
513
+ }
514
+ const equal = (foo, bar) => {
515
+ var ctor, len, tmp;
516
+ if (foo === bar)
517
+ return true;
518
+ if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
519
+ if (ctor === Date)
520
+ return foo.getTime() === bar.getTime();
521
+ if (ctor === RegExp)
522
+ return foo.toString() === bar.toString();
523
+ if (ctor === Array) {
524
+ if ((len = foo.length) === bar.length) {
525
+ while (len-- && equal(foo[len], bar[len]))
526
+ ;
527
+ }
528
+ return len === -1;
529
+ }
530
+ if (ctor === Set) {
531
+ if (foo.size !== bar.size) {
532
+ return false;
533
+ }
534
+ for (len of foo) {
535
+ tmp = len;
536
+ if (tmp && typeof tmp === 'object') {
537
+ tmp = find(bar, tmp);
538
+ if (!tmp)
539
+ return false;
540
+ }
541
+ if (!bar.has(tmp))
542
+ return false;
543
+ }
544
+ return true;
545
+ }
546
+ if (ctor === Map) {
547
+ if (foo.size !== bar.size) {
548
+ return false;
549
+ }
550
+ for (len of foo) {
551
+ tmp = len[0];
552
+ if (tmp && typeof tmp === 'object') {
553
+ tmp = find(bar, tmp);
554
+ if (!tmp)
555
+ return false;
556
+ }
557
+ if (!equal(len[1], bar.get(tmp))) {
558
+ return false;
559
+ }
560
+ }
561
+ return true;
562
+ }
563
+ if (ctor === ArrayBuffer) {
564
+ foo = new Uint8Array(foo);
565
+ bar = new Uint8Array(bar);
566
+ }
567
+ else if (ctor === DataView) {
568
+ if ((len = foo.byteLength) === bar.byteLength) {
569
+ while (len-- && foo.getInt8(len) === bar.getInt8(len))
570
+ ;
571
+ }
572
+ return len === -1;
573
+ }
574
+ if (ArrayBuffer.isView(foo)) {
575
+ if ((len = foo.byteLength) === bar.byteLength) {
576
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
577
+ //@ts-ignore
578
+ while (len-- && foo[len] === bar[len])
579
+ ;
580
+ }
581
+ return len === -1;
582
+ }
583
+ if (!ctor || typeof foo === 'object') {
584
+ len = 0;
585
+ for (ctor in foo) {
586
+ if (has.call(foo, ctor) && ++len && !has.call(bar, ctor))
587
+ return false;
588
+ if (!(ctor in bar) || !equal(foo[ctor], bar[ctor]))
589
+ return false;
590
+ }
591
+ return Object.keys(bar).length === len;
592
+ }
593
+ }
594
+ return foo !== foo && bar !== bar;
595
+ };
596
+
597
+ const isAttributeRenderBinding = (value) => typeof value === 'boolean';
598
+ const isAttributeValueBinding = (value) => typeof value === 'object';
599
+ const createReactiveBindings = (...values) => {
600
+ const rootElementRef = inject(ElementRef);
601
+ const destroy$ = inject(DestroyService, { host: true }).destroy$;
602
+ const subscriptions = [];
603
+ const pushedAttributes = [];
604
+ const defaults = {};
605
+ const push = (value) => {
606
+ const { attribute, observable, elementRef } = value;
607
+ const elRef = elementRef || rootElementRef;
608
+ const attributes = Array.isArray(attribute) ? attribute : [attribute];
609
+ pushedAttributes.push(attributes);
610
+ for (const attribute of attributes) {
611
+ if (!defaults[attribute]) {
612
+ defaults[attribute] = elRef.nativeElement.getAttribute(attribute) || undefined;
613
+ }
614
+ }
615
+ const subscription = observable
616
+ .pipe(takeUntil(destroy$), distinctUntilChanged((a, b) => {
617
+ if (isAttributeRenderBinding(a) && isAttributeRenderBinding(b)) {
618
+ return a === b;
619
+ }
620
+ else if (isAttributeValueBinding(a) && isAttributeValueBinding(b)) {
621
+ return a.render === b.render && a.value === b.value;
622
+ }
623
+ return false;
624
+ }))
625
+ .subscribe((value) => {
626
+ const currentAttributes = pushedAttributes.find((s) => s.some((current) => attributes.includes(current))) || [];
627
+ for (const attribute of currentAttributes) {
628
+ const isSingleClassMutation = attribute.startsWith('class.');
629
+ const isMultipleClassMutation = attribute === 'class';
630
+ const render = isAttributeRenderBinding(value) ? value : value.render;
631
+ if (isSingleClassMutation) {
632
+ const className = attribute.replace('class.', '');
633
+ if (!className) {
634
+ continue;
635
+ }
636
+ if (!render) {
637
+ elRef.nativeElement.classList.remove(className);
638
+ }
639
+ else {
640
+ elRef.nativeElement.classList.add(className);
641
+ }
642
+ }
643
+ else if (isMultipleClassMutation) {
644
+ const classes = isAttributeRenderBinding(value) ? '' : `${value.value}`;
645
+ if (!classes) {
646
+ continue;
647
+ }
648
+ if (!render) {
649
+ elRef.nativeElement.classList.remove(...classes.split(' '));
650
+ }
651
+ else {
652
+ elRef.nativeElement.classList.add(...classes.split(' '));
653
+ }
654
+ }
655
+ else {
656
+ const attributeValue = isAttributeRenderBinding(value) ? true : `${value.value}`;
657
+ if (!attribute) {
658
+ continue;
659
+ }
660
+ if (!render) {
661
+ elRef.nativeElement.removeAttribute(attribute);
662
+ }
663
+ else {
664
+ elRef.nativeElement.setAttribute(attribute, `${attributeValue}`);
665
+ }
666
+ }
667
+ }
668
+ });
669
+ subscriptions.push({ attributes, subscription });
670
+ };
671
+ const remove = (...attributes) => {
672
+ for (const attribute of attributes) {
673
+ const sub = subscriptions.find((s) => s.attributes.includes(attribute));
674
+ const attributeStack = pushedAttributes.find((a) => a.includes(attribute));
675
+ if (sub) {
676
+ sub.attributes = sub.attributes.filter((a) => a !== attribute);
677
+ attributeStack?.splice(attributeStack.indexOf(attribute), 1);
678
+ if (sub.attributes.length === 0) {
679
+ sub.subscription.unsubscribe();
680
+ subscriptions.splice(subscriptions.indexOf(sub), 1);
681
+ }
682
+ }
683
+ }
684
+ };
685
+ const reset = () => {
686
+ for (const attribute in defaults) {
687
+ if (defaults[attribute] === undefined) {
688
+ rootElementRef.nativeElement.removeAttribute(attribute);
689
+ }
690
+ else {
691
+ rootElementRef.nativeElement.setAttribute(attribute, defaults[attribute]);
692
+ }
693
+ }
694
+ };
695
+ for (const value of values) {
696
+ push(value);
697
+ }
698
+ return {
699
+ push,
700
+ remove,
701
+ reset,
702
+ };
703
+ };
704
+
705
+ const elementCanScroll = (element) => {
706
+ const { scrollHeight, clientHeight, scrollWidth, clientWidth } = element;
707
+ return scrollHeight > clientHeight || scrollWidth > clientWidth;
708
+ };
709
+
710
+ const provideViewportConfig = (viewportConfig) => {
711
+ return { provide: VIEWPORT_CONFIG, useValue: viewportConfig };
712
+ };
713
+
349
714
  const routerDisableScrollTop = (config = {}) => {
350
715
  if (!config.asReturnRoute) {
351
716
  return {
@@ -368,13 +733,19 @@ class RouterStateService {
368
733
  this._router = inject(Router);
369
734
  this._route$ = new BehaviorSubject('/');
370
735
  this._state$ = new BehaviorSubject({
371
- title: undefined,
736
+ title: null,
737
+ fragment: null,
372
738
  data: {},
373
739
  pathParams: {},
374
740
  queryParams: {},
375
741
  });
376
742
  this._router.events
377
- .pipe(filter((event) => event instanceof NavigationEnd), distinctUntilChanged((a, b) => a.url === b.url), map((event) => event.url))
743
+ .pipe(filter((event) => event instanceof NavigationEnd), distinctUntilChanged((a, b) => a.url === b.url), map((event) => {
744
+ const { url } = event;
745
+ const urlWithoutQueryParams = url.split('?')[0];
746
+ const withoutFragment = urlWithoutQueryParams.split('#')[0];
747
+ return withoutFragment;
748
+ }))
378
749
  .subscribe(this._route$);
379
750
  this._route$
380
751
  .pipe(map(() => {
@@ -382,605 +753,267 @@ class RouterStateService {
382
753
  while (route.firstChild) {
383
754
  route = route.firstChild;
384
755
  }
385
- const { data, params, queryParams, title } = route;
756
+ const { data, params, queryParams, title, fragment } = route;
386
757
  return {
387
758
  data,
388
759
  pathParams: params,
389
760
  queryParams,
390
- title,
761
+ title: title ?? null,
762
+ fragment,
391
763
  };
392
764
  }))
393
765
  .subscribe(this._state$);
394
766
  }
395
- enableScrollTopOnNavigation(config = {}) {
767
+ enableScrollEnhancements(config = {}) {
396
768
  if (this._isScrollTopOnNavigationEnabled) {
397
769
  return;
398
770
  }
399
771
  this._isScrollTopOnNavigationEnabled = true;
400
- this._state$.pipe(pairwise()).subscribe(([oldData, newData]) => {
401
- if (!(newData.data['disableScrollTopAsReturnRoute'] && oldData.data['disableScrollTop']) &&
402
- !newData.data['disableScrollTop']) {
403
- (config.scrollElement ?? document.documentElement).scrollTop = 0;
772
+ combineLatest([this._state$.pipe(pairwise()), this._route$.pipe(pairwise())])
773
+ .pipe(debounceTime(1))
774
+ .subscribe(([[prevState, currState], [prevRoute, currRoute]]) => {
775
+ const sameUrlNavigation = prevRoute === currRoute && equal(prevState.pathParams, currState.pathParams);
776
+ const didFragmentChange = prevState.fragment !== currState.fragment;
777
+ if (sameUrlNavigation) {
778
+ const allQueryParams = [
779
+ ...new Set(Object.keys(prevState.queryParams).concat(Object.keys(currState.queryParams))),
780
+ ];
781
+ const changedQueryParams = allQueryParams.filter((key) => currState.queryParams[key] !== prevState.queryParams[key]);
782
+ if (!config.queryParamTriggerList?.length && !didFragmentChange) {
783
+ return;
784
+ }
785
+ const caseQueryParams = changedQueryParams.some((key) => config.queryParamTriggerList?.includes(key));
786
+ const caseFragment = didFragmentChange && config.fragment?.enabled;
787
+ if (caseQueryParams) {
788
+ (config.scrollElement ?? document.documentElement).scrollTop = 0;
789
+ }
790
+ else if (caseFragment) {
791
+ const fragmentElement = document.getElementById(currState.fragment ?? '');
792
+ if (fragmentElement) {
793
+ fragmentElement.scrollIntoView({ behavior: config.fragment?.smooth ? 'smooth' : 'auto' });
794
+ }
795
+ }
796
+ }
797
+ else {
798
+ if (!(currState.data['disableScrollTopAsReturnRoute'] && prevState.data['disableScrollTop']) &&
799
+ !currState.data['disableScrollTop']) {
800
+ (config.scrollElement ?? document.documentElement).scrollTop = 0;
801
+ }
404
802
  }
405
803
  });
406
804
  }
407
805
  selectQueryParam(key) {
408
806
  return this._state$.pipe(map((state) => state.queryParams[key]));
409
807
  }
410
- selectPathParam(key) {
411
- return this._state$.pipe(map((state) => state.pathParams[key]));
412
- }
413
- selectData(key) {
414
- return this._state$.pipe(map((state) => state.data[key]));
415
- }
416
- }
417
- RouterStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
418
- RouterStateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, providedIn: 'root' });
419
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, decorators: [{
420
- type: Injectable,
421
- args: [{
422
- providedIn: 'root',
423
- }]
424
- }], ctorParameters: function () { return []; } });
425
-
426
- class ViewportService {
427
- get isXs$() {
428
- return this._isXs$.asObservable();
429
- }
430
- get isXs() {
431
- return this._isXs$.value;
432
- }
433
- get isSm$() {
434
- return this._isSm$.asObservable();
435
- }
436
- get isSm() {
437
- return this._isSm$.value;
438
- }
439
- get isMd$() {
440
- return this._isMd$.asObservable();
441
- }
442
- get isMd() {
443
- return this._isMd$.value;
444
- }
445
- get isLg$() {
446
- return this._isLg$.asObservable();
447
- }
448
- get isLg() {
449
- return this._isLg$.value;
450
- }
451
- get isXl$() {
452
- return this._isXl$.asObservable();
453
- }
454
- get isXl() {
455
- return this._isXl$.value;
456
- }
457
- get is2Xl$() {
458
- return this._is2Xl$.asObservable();
459
- }
460
- get is2Xl() {
461
- return this._is2Xl$.value;
462
- }
463
- get currentViewport() {
464
- return this.getCurrentViewport([this.isXs, this.isSm, this.isMd, this.isLg, this.isXl, this.is2Xl]);
465
- }
466
- constructor(_viewportConfig, _breakpointObserver) {
467
- this._breakpointObserver = _breakpointObserver;
468
- this._isXs$ = new BehaviorSubject(false);
469
- this._isSm$ = new BehaviorSubject(false);
470
- this._isMd$ = new BehaviorSubject(false);
471
- this._isLg$ = new BehaviorSubject(false);
472
- this._isXl$ = new BehaviorSubject(false);
473
- this._is2Xl$ = new BehaviorSubject(false);
474
- this.currentViewport$ = combineLatest([this.isXs$, this.isSm$, this.isMd$, this.isLg$, this.isXl$, this.is2Xl$]).pipe(map((val) => this.getCurrentViewport(val)), shareReplay());
475
- this._viewportConfig = _viewportConfig || DEFAULT_VIEWPORT_CONFIG;
476
- this._observeDefaultBreakpoints();
477
- }
478
- observe(options) {
479
- const mediaQuery = this._buildMediaQuery(options);
480
- return this._breakpointObserver.observe(mediaQuery).pipe(map((x) => x.matches), shareReplay());
481
- }
482
- isMatched(options) {
483
- const mediaQuery = this._buildMediaQuery(options);
484
- return this._breakpointObserver.isMatched(mediaQuery);
485
- }
486
- _observeDefaultBreakpoints() {
487
- this.observe({ max: 'xs' }).subscribe(this._isXs$);
488
- this.observe({ min: 'sm', max: 'sm' }).subscribe(this._isSm$);
489
- this.observe({ min: 'md', max: 'md' }).subscribe(this._isMd$);
490
- this.observe({ min: 'lg', max: 'lg' }).subscribe(this._isLg$);
491
- this.observe({ min: 'xl', max: 'xl' }).subscribe(this._isXl$);
492
- this.observe({ min: '2xl' }).subscribe(this._is2Xl$);
493
- }
494
- _getViewportSize(type, option) {
495
- const index = option === 'min' ? 0 : 1;
496
- const size = this._viewportConfig.breakpoints[type][index];
497
- if (size === Infinity || size === 0) {
498
- return size;
499
- }
500
- if (option === 'min') {
501
- return size;
502
- }
503
- // Due to scaling, the actual size of the viewport may be a decimal number.
504
- // Eg. on Windows 11 with 150% scaling, the viewport size may be 1535.33px
505
- // and thus not matching any of the default breakpoints.
506
- return size + 0.9;
507
- }
508
- _buildMediaQuery(options) {
509
- if (!options.min && !options.max) {
510
- throw new Error('At least one of min or max must be defined');
511
- }
512
- const mediaQueryParts = [];
513
- if (options.min) {
514
- if (typeof options.min === 'number') {
515
- mediaQueryParts.push(`(min-width: ${options.min}px)`);
516
- }
517
- else {
518
- mediaQueryParts.push(`(min-width: ${this._getViewportSize(options.min, 'min')}px)`);
519
- }
520
- }
521
- if (options.min && options.max) {
522
- mediaQueryParts.push('and');
523
- }
524
- if (options.max) {
525
- if (typeof options.max === 'number') {
526
- mediaQueryParts.push(`(max-width: ${options.max}px)`);
527
- }
528
- else {
529
- mediaQueryParts.push(`(max-width: ${this._getViewportSize(options.max, 'max')}px)`);
530
- }
531
- }
532
- return mediaQueryParts.join(' ');
533
- }
534
- getCurrentViewport([isXs, isSm, isMd, isLg, isXl, is2Xl]) {
535
- if (isXs) {
536
- return 'xs';
537
- }
538
- else if (isSm) {
539
- return 'sm';
540
- }
541
- else if (isMd) {
542
- return 'md';
543
- }
544
- else if (isLg) {
545
- return 'lg';
546
- }
547
- else if (isXl) {
548
- return 'xl';
549
- }
550
- else if (is2Xl) {
551
- return '2xl';
552
- }
553
- return 'xs';
554
- }
555
- }
556
- ViewportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, deps: [{ token: VIEWPORT_CONFIG, optional: true }, { token: i1.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Injectable });
557
- ViewportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, providedIn: 'root' });
558
- __decorate([
559
- Memo(),
560
- __metadata("design:type", Function),
561
- __metadata("design:paramtypes", [String, String]),
562
- __metadata("design:returntype", void 0)
563
- ], ViewportService.prototype, "_getViewportSize", null);
564
- __decorate([
565
- Memo({
566
- resolver: (v) => {
567
- return `${v.min ?? ''}-${v.max ?? ''}`;
568
- },
569
- }),
570
- __metadata("design:type", Function),
571
- __metadata("design:paramtypes", [Object]),
572
- __metadata("design:returntype", void 0)
573
- ], ViewportService.prototype, "_buildMediaQuery", null);
574
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, decorators: [{
575
- type: Injectable,
576
- args: [{
577
- providedIn: 'root',
578
- }]
579
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
580
- type: Inject,
581
- args: [VIEWPORT_CONFIG]
582
- }, {
583
- type: Optional
584
- }] }, { type: i1.BreakpointObserver }]; }, propDecorators: { _getViewportSize: [], _buildMediaQuery: [] } });
585
-
586
- class ClickOutsideDirective {
587
- constructor() {
588
- this._elementRef = inject(ElementRef);
589
- this._clickObserverService = inject(ClickObserverService);
590
- this._subscription = null;
591
- this.etClickOutside = new EventEmitter();
592
- }
593
- ngOnInit() {
594
- setTimeout(() => {
595
- this._subscription = this._clickObserverService.observe(this._elementRef.nativeElement).subscribe((event) => {
596
- const activeElement = event.target;
597
- const isInside = this._elementRef.nativeElement.contains(activeElement);
598
- if (!isInside) {
599
- this.etClickOutside.emit(event);
600
- }
601
- });
602
- });
808
+ selectPathParam(key) {
809
+ return this._state$.pipe(map((state) => state.pathParams[key]));
603
810
  }
604
- ngOnDestroy() {
605
- this._subscription?.unsubscribe();
811
+ selectData(key) {
812
+ return this._state$.pipe(map((state) => state.data[key]));
606
813
  }
607
814
  }
608
- ClickOutsideDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
609
- ClickOutsideDirectivedir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ClickOutsideDirective, isStandalone: true, selector: "[etClickOutside]", outputs: { etClickOutside: "etClickOutside" }, ngImport: i0 });
610
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ClickOutsideDirective, decorators: [{
611
- type: Directive,
815
+ RouterStateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
816
+ RouterStateServiceprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, providedIn: 'root' });
817
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: RouterStateService, decorators: [{
818
+ type: Injectable,
612
819
  args: [{
613
- selector: '[etClickOutside]',
614
- standalone: true,
820
+ providedIn: 'root',
615
821
  }]
616
- }], propDecorators: { etClickOutside: [{
617
- type: Output
618
- }] } });
619
-
620
- const clamp = (value, min = 0, max = 100) => {
621
- return Math.max(min, Math.min(max, value));
622
- };
822
+ }], ctorParameters: function () { return []; } });
623
823
 
624
- /* eslint-disable @typescript-eslint/no-explicit-any */
625
- /* eslint-disable no-var */
626
- /**
627
- * Stolen from klona to avoid adding a dependency
628
- * https://github.com/lukeed/klona
629
- *
630
- * MIT License
631
- *
632
- * Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
633
- *
634
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
635
- *
636
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
637
- *
638
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
639
- */
640
- const set = (obj, key, val) => {
641
- if (typeof val.value === 'object')
642
- val.value = clone(val.value);
643
- if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') {
644
- Object.defineProperty(obj, key, val);
645
- }
646
- else
647
- obj[key] = val.value;
648
- };
649
- const clone = (original) => {
650
- if (typeof original !== 'object')
651
- return original;
652
- var _og = original;
653
- var i = 0, k, list, tmp, str = Object.prototype.toString.call(_og);
654
- if (str === '[object Object]') {
655
- tmp = Object.create(_og.__proto__ || null);
824
+ class ViewportService {
825
+ get isXs$() {
826
+ return this._isXs$.asObservable();
656
827
  }
657
- else if (str === '[object Array]') {
658
- tmp = Array(_og.length);
828
+ get isXs() {
829
+ return this._isXs$.value;
659
830
  }
660
- else if (str === '[object Set]') {
661
- tmp = new Set();
662
- _og.forEach(function (val) {
663
- tmp.add(clone(val));
664
- });
831
+ get isSm$() {
832
+ return this._isSm$.asObservable();
665
833
  }
666
- else if (str === '[object Map]') {
667
- tmp = new Map();
668
- _og.forEach(function (val, key) {
669
- tmp.set(clone(key), clone(val));
670
- });
834
+ get isSm() {
835
+ return this._isSm$.value;
671
836
  }
672
- else if (str === '[object Date]') {
673
- tmp = new Date(+_og);
837
+ get isMd$() {
838
+ return this._isMd$.asObservable();
674
839
  }
675
- else if (str === '[object RegExp]') {
676
- tmp = new RegExp(_og.source, _og.flags);
840
+ get isMd() {
841
+ return this._isMd$.value;
677
842
  }
678
- else if (str === '[object DataView]') {
679
- tmp = new _og.constructor(clone(_og.buffer));
843
+ get isLg$() {
844
+ return this._isLg$.asObservable();
680
845
  }
681
- else if (str === '[object ArrayBuffer]') {
682
- tmp = _og.slice(0);
846
+ get isLg() {
847
+ return this._isLg$.value;
683
848
  }
684
- else if (str.slice(-6) === 'Array]') {
685
- // ArrayBuffer.isView(x)
686
- // ~> `new` bcuz `Buffer.slice` => ref
687
- tmp = new _og.constructor(_og);
849
+ get isXl$() {
850
+ return this._isXl$.asObservable();
688
851
  }
689
- if (tmp) {
690
- for (list = Object.getOwnPropertySymbols(_og); i < list.length; i++) {
691
- set(tmp, list[i], Object.getOwnPropertyDescriptor(_og, list[i]));
692
- }
693
- for (i = 0, list = Object.getOwnPropertyNames(_og); i < list.length; i++) {
694
- if (Object.hasOwnProperty.call(tmp, (k = list[i])) && tmp[k] === _og[k])
695
- continue;
696
- set(tmp, k, Object.getOwnPropertyDescriptor(_og, k));
697
- }
852
+ get isXl() {
853
+ return this._isXl$.value;
698
854
  }
699
- return tmp || _og;
700
- };
701
-
702
- const hasCookie = (name) => {
703
- if (typeof document === 'undefined') {
704
- return false;
855
+ get is2Xl$() {
856
+ return this._is2Xl$.asObservable();
705
857
  }
706
- return document.cookie.split(';').some((c) => {
707
- return c.trim().startsWith(name + '=');
708
- });
709
- };
710
- const getCookie = (name) => {
711
- if (typeof document === 'undefined') {
712
- return null;
858
+ get is2Xl() {
859
+ return this._is2Xl$.value;
713
860
  }
714
- // From https://stackoverflow.com/questions/10730362/get-cookie-by-name
715
- return ('; ' + document.cookie).split(`; ${name}=`).pop()?.split(';')[0];
716
- };
717
- const setCookie = (name, data, expiresInDays = 30, domain = getDomain()) => {
718
- if (typeof document === 'undefined') {
719
- return;
861
+ get currentViewport() {
862
+ return this.getCurrentViewport([this.isXs, this.isSm, this.isMd, this.isLg, this.isXl, this.is2Xl]);
720
863
  }
721
- const date = new Date();
722
- date.setTime(date.getTime() + expiresInDays * 24 * 60 * 60 * 1000);
723
- document.cookie = `${name}=${data}; path=/; expires=${date.toUTCString()}; domain=${domain}; SameSite=Lax;`;
724
- };
725
- const deleteCookie = (name, path, domain = getDomain()) => {
726
- if (hasCookie(name)) {
727
- document.cookie =
728
- name +
729
- '=' +
730
- (path ? ';path=' + path : '') +
731
- (domain ? ';domain=' + domain : '') +
732
- ';expires=Thu, 01 Jan 1970 00:00:01 GMT';
864
+ constructor(_viewportConfig, _breakpointObserver) {
865
+ this._breakpointObserver = _breakpointObserver;
866
+ this._isXs$ = new BehaviorSubject(false);
867
+ this._isSm$ = new BehaviorSubject(false);
868
+ this._isMd$ = new BehaviorSubject(false);
869
+ this._isLg$ = new BehaviorSubject(false);
870
+ this._isXl$ = new BehaviorSubject(false);
871
+ this._is2Xl$ = new BehaviorSubject(false);
872
+ this.currentViewport$ = combineLatest([this.isXs$, this.isSm$, this.isMd$, this.isLg$, this.isXl$, this.is2Xl$]).pipe(map((val) => this.getCurrentViewport(val)), shareReplay());
873
+ this._viewportConfig = _viewportConfig || DEFAULT_VIEWPORT_CONFIG;
874
+ this._observeDefaultBreakpoints();
733
875
  }
734
- };
735
- const getDomain = () => {
736
- if (typeof navigator === 'undefined') {
737
- return null;
876
+ observe(options) {
877
+ const mediaQuery = this._buildMediaQuery(options);
878
+ return this._breakpointObserver.observe(mediaQuery).pipe(map((x) => x.matches), shareReplay());
738
879
  }
739
- const hostname = window.location.hostname;
740
- if (hostname.includes('localhost')) {
741
- return 'localhost';
880
+ isMatched(options) {
881
+ const mediaQuery = this._buildMediaQuery(options);
882
+ return this._breakpointObserver.isMatched(mediaQuery);
742
883
  }
743
- const splitHost = hostname.split('.');
744
- if (splitHost.length > 2) {
745
- return `${splitHost[splitHost.length - 2]}.${splitHost[splitHost.length - 1]}`;
884
+ _observeDefaultBreakpoints() {
885
+ this.observe({ max: 'xs' }).subscribe(this._isXs$);
886
+ this.observe({ min: 'sm', max: 'sm' }).subscribe(this._isSm$);
887
+ this.observe({ min: 'md', max: 'md' }).subscribe(this._isMd$);
888
+ this.observe({ min: 'lg', max: 'lg' }).subscribe(this._isLg$);
889
+ this.observe({ min: 'xl', max: 'xl' }).subscribe(this._isXl$);
890
+ this.observe({ min: '2xl' }).subscribe(this._is2Xl$);
746
891
  }
747
- return hostname;
748
- };
749
-
750
- /* eslint-disable @typescript-eslint/no-explicit-any */
751
- /* eslint-disable no-var */
752
- /**
753
- * Stolen from dequal to avoid adding a dependency
754
- * https://github.com/lukeed/dequal
755
- *
756
- * The MIT License (MIT)
757
- *
758
- * Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
759
- *
760
- * Permission is hereby granted, free of charge, to any person obtaining a copy
761
- * of this software and associated documentation files (the "Software"), to deal
762
- * in the Software without restriction, including without limitation the rights
763
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
764
- * copies of the Software, and to permit persons to whom the Software is
765
- * furnished to do so, subject to the following conditions:
766
- *
767
- * The above copyright notice and this permission notice shall be included in
768
- * all copies or substantial portions of the Software.
769
- *
770
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
771
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
773
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
774
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
775
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
776
- * THE SOFTWARE.
777
- */
778
- const has = Object.prototype.hasOwnProperty;
779
- function find(iter, tar, key) {
780
- for (key of iter.keys()) {
781
- if (equal(key, tar))
782
- return key;
892
+ _getViewportSize(type, option) {
893
+ const index = option === 'min' ? 0 : 1;
894
+ const size = this._viewportConfig.breakpoints[type][index];
895
+ if (size === Infinity || size === 0) {
896
+ return size;
897
+ }
898
+ if (option === 'min') {
899
+ return size;
900
+ }
901
+ // Due to scaling, the actual size of the viewport may be a decimal number.
902
+ // Eg. on Windows 11 with 150% scaling, the viewport size may be 1535.33px
903
+ // and thus not matching any of the default breakpoints.
904
+ return size + 0.9;
783
905
  }
784
- }
785
- const equal = (foo, bar) => {
786
- var ctor, len, tmp;
787
- if (foo === bar)
788
- return true;
789
- if (foo && bar && (ctor = foo.constructor) === bar.constructor) {
790
- if (ctor === Date)
791
- return foo.getTime() === bar.getTime();
792
- if (ctor === RegExp)
793
- return foo.toString() === bar.toString();
794
- if (ctor === Array) {
795
- if ((len = foo.length) === bar.length) {
796
- while (len-- && equal(foo[len], bar[len]))
797
- ;
798
- }
799
- return len === -1;
906
+ _buildMediaQuery(options) {
907
+ if (!options.min && !options.max) {
908
+ throw new Error('At least one of min or max must be defined');
800
909
  }
801
- if (ctor === Set) {
802
- if (foo.size !== bar.size) {
803
- return false;
910
+ const mediaQueryParts = [];
911
+ if (options.min) {
912
+ if (typeof options.min === 'number') {
913
+ mediaQueryParts.push(`(min-width: ${options.min}px)`);
804
914
  }
805
- for (len of foo) {
806
- tmp = len;
807
- if (tmp && typeof tmp === 'object') {
808
- tmp = find(bar, tmp);
809
- if (!tmp)
810
- return false;
811
- }
812
- if (!bar.has(tmp))
813
- return false;
915
+ else {
916
+ mediaQueryParts.push(`(min-width: ${this._getViewportSize(options.min, 'min')}px)`);
814
917
  }
815
- return true;
816
918
  }
817
- if (ctor === Map) {
818
- if (foo.size !== bar.size) {
819
- return false;
919
+ if (options.min && options.max) {
920
+ mediaQueryParts.push('and');
921
+ }
922
+ if (options.max) {
923
+ if (typeof options.max === 'number') {
924
+ mediaQueryParts.push(`(max-width: ${options.max}px)`);
820
925
  }
821
- for (len of foo) {
822
- tmp = len[0];
823
- if (tmp && typeof tmp === 'object') {
824
- tmp = find(bar, tmp);
825
- if (!tmp)
826
- return false;
827
- }
828
- if (!equal(len[1], bar.get(tmp))) {
829
- return false;
830
- }
926
+ else {
927
+ mediaQueryParts.push(`(max-width: ${this._getViewportSize(options.max, 'max')}px)`);
831
928
  }
832
- return true;
833
929
  }
834
- if (ctor === ArrayBuffer) {
835
- foo = new Uint8Array(foo);
836
- bar = new Uint8Array(bar);
930
+ return mediaQueryParts.join(' ');
931
+ }
932
+ getCurrentViewport([isXs, isSm, isMd, isLg, isXl, is2Xl]) {
933
+ if (isXs) {
934
+ return 'xs';
837
935
  }
838
- else if (ctor === DataView) {
839
- if ((len = foo.byteLength) === bar.byteLength) {
840
- while (len-- && foo.getInt8(len) === bar.getInt8(len))
841
- ;
842
- }
843
- return len === -1;
936
+ else if (isSm) {
937
+ return 'sm';
844
938
  }
845
- if (ArrayBuffer.isView(foo)) {
846
- if ((len = foo.byteLength) === bar.byteLength) {
847
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
848
- //@ts-ignore
849
- while (len-- && foo[len] === bar[len])
850
- ;
851
- }
852
- return len === -1;
939
+ else if (isMd) {
940
+ return 'md';
853
941
  }
854
- if (!ctor || typeof foo === 'object') {
855
- len = 0;
856
- for (ctor in foo) {
857
- if (has.call(foo, ctor) && ++len && !has.call(bar, ctor))
858
- return false;
859
- if (!(ctor in bar) || !equal(foo[ctor], bar[ctor]))
860
- return false;
861
- }
862
- return Object.keys(bar).length === len;
942
+ else if (isLg) {
943
+ return 'lg';
863
944
  }
945
+ else if (isXl) {
946
+ return 'xl';
947
+ }
948
+ else if (is2Xl) {
949
+ return '2xl';
950
+ }
951
+ return 'xs';
864
952
  }
865
- return foo !== foo && bar !== bar;
866
- };
953
+ }
954
+ ViewportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, deps: [{ token: VIEWPORT_CONFIG, optional: true }, { token: i1.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Injectable });
955
+ ViewportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, providedIn: 'root' });
956
+ __decorate([
957
+ Memo(),
958
+ __metadata("design:type", Function),
959
+ __metadata("design:paramtypes", [String, String]),
960
+ __metadata("design:returntype", void 0)
961
+ ], ViewportService.prototype, "_getViewportSize", null);
962
+ __decorate([
963
+ Memo({
964
+ resolver: (v) => {
965
+ return `${v.min ?? ''}-${v.max ?? ''}`;
966
+ },
967
+ }),
968
+ __metadata("design:type", Function),
969
+ __metadata("design:paramtypes", [Object]),
970
+ __metadata("design:returntype", void 0)
971
+ ], ViewportService.prototype, "_buildMediaQuery", null);
972
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ViewportService, decorators: [{
973
+ type: Injectable,
974
+ args: [{
975
+ providedIn: 'root',
976
+ }]
977
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
978
+ type: Inject,
979
+ args: [VIEWPORT_CONFIG]
980
+ }, {
981
+ type: Optional
982
+ }] }, { type: i1.BreakpointObserver }]; }, propDecorators: { _getViewportSize: [], _buildMediaQuery: [] } });
867
983
 
868
- const isAttributeRenderBinding = (value) => typeof value === 'boolean';
869
- const isAttributeValueBinding = (value) => typeof value === 'object';
870
- const createReactiveBindings = (...values) => {
871
- const rootElementRef = inject(ElementRef);
872
- const destroy$ = inject(DestroyService, { host: true }).destroy$;
873
- const subscriptions = [];
874
- const pushedAttributes = [];
875
- const defaults = {};
876
- const push = (value) => {
877
- const { attribute, observable, elementRef } = value;
878
- const elRef = elementRef || rootElementRef;
879
- const attributes = Array.isArray(attribute) ? attribute : [attribute];
880
- pushedAttributes.push(attributes);
881
- for (const attribute of attributes) {
882
- if (!defaults[attribute]) {
883
- defaults[attribute] = elRef.nativeElement.getAttribute(attribute) || undefined;
884
- }
885
- }
886
- const subscription = observable
887
- .pipe(takeUntil(destroy$), distinctUntilChanged((a, b) => {
888
- if (isAttributeRenderBinding(a) && isAttributeRenderBinding(b)) {
889
- return a === b;
890
- }
891
- else if (isAttributeValueBinding(a) && isAttributeValueBinding(b)) {
892
- return a.render === b.render && a.value === b.value;
893
- }
894
- return false;
895
- }))
896
- .subscribe((value) => {
897
- const currentAttributes = pushedAttributes.find((s) => s.some((current) => attributes.includes(current))) || [];
898
- for (const attribute of currentAttributes) {
899
- const isSingleClassMutation = attribute.startsWith('class.');
900
- const isMultipleClassMutation = attribute === 'class';
901
- const render = isAttributeRenderBinding(value) ? value : value.render;
902
- if (isSingleClassMutation) {
903
- const className = attribute.replace('class.', '');
904
- if (!className) {
905
- continue;
906
- }
907
- if (!render) {
908
- elRef.nativeElement.classList.remove(className);
909
- }
910
- else {
911
- elRef.nativeElement.classList.add(className);
912
- }
913
- }
914
- else if (isMultipleClassMutation) {
915
- const classes = isAttributeRenderBinding(value) ? '' : `${value.value}`;
916
- if (!classes) {
917
- continue;
918
- }
919
- if (!render) {
920
- elRef.nativeElement.classList.remove(...classes.split(' '));
921
- }
922
- else {
923
- elRef.nativeElement.classList.add(...classes.split(' '));
924
- }
925
- }
926
- else {
927
- const attributeValue = isAttributeRenderBinding(value) ? true : `${value.value}`;
928
- if (!attribute) {
929
- continue;
930
- }
931
- if (!render) {
932
- elRef.nativeElement.removeAttribute(attribute);
933
- }
934
- else {
935
- elRef.nativeElement.setAttribute(attribute, `${attributeValue}`);
936
- }
984
+ class ClickOutsideDirective {
985
+ constructor() {
986
+ this._elementRef = inject(ElementRef);
987
+ this._clickObserverService = inject(ClickObserverService);
988
+ this._subscription = null;
989
+ this.etClickOutside = new EventEmitter();
990
+ }
991
+ ngOnInit() {
992
+ setTimeout(() => {
993
+ this._subscription = this._clickObserverService.observe(this._elementRef.nativeElement).subscribe((event) => {
994
+ const activeElement = event.target;
995
+ const isInside = this._elementRef.nativeElement.contains(activeElement);
996
+ if (!isInside) {
997
+ this.etClickOutside.emit(event);
937
998
  }
938
- }
999
+ });
939
1000
  });
940
- subscriptions.push({ attributes, subscription });
941
- };
942
- const remove = (...attributes) => {
943
- for (const attribute of attributes) {
944
- const sub = subscriptions.find((s) => s.attributes.includes(attribute));
945
- const attributeStack = pushedAttributes.find((a) => a.includes(attribute));
946
- if (sub) {
947
- sub.attributes = sub.attributes.filter((a) => a !== attribute);
948
- attributeStack?.splice(attributeStack.indexOf(attribute), 1);
949
- if (sub.attributes.length === 0) {
950
- sub.subscription.unsubscribe();
951
- subscriptions.splice(subscriptions.indexOf(sub), 1);
952
- }
953
- }
954
- }
955
- };
956
- const reset = () => {
957
- for (const attribute in defaults) {
958
- if (defaults[attribute] === undefined) {
959
- rootElementRef.nativeElement.removeAttribute(attribute);
960
- }
961
- else {
962
- rootElementRef.nativeElement.setAttribute(attribute, defaults[attribute]);
963
- }
964
- }
965
- };
966
- for (const value of values) {
967
- push(value);
968
1001
  }
969
- return {
970
- push,
971
- remove,
972
- reset,
973
- };
974
- };
975
-
976
- const elementCanScroll = (element) => {
977
- const { scrollHeight, clientHeight, scrollWidth, clientWidth } = element;
978
- return scrollHeight > clientHeight || scrollWidth > clientWidth;
979
- };
980
-
981
- const provideViewportConfig = (viewportConfig) => {
982
- return { provide: VIEWPORT_CONFIG, useValue: viewportConfig };
983
- };
1002
+ ngOnDestroy() {
1003
+ this._subscription?.unsubscribe();
1004
+ }
1005
+ }
1006
+ ClickOutsideDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ClickOutsideDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1007
+ ClickOutsideDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ClickOutsideDirective, isStandalone: true, selector: "[etClickOutside]", outputs: { etClickOutside: "etClickOutside" }, ngImport: i0 });
1008
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ClickOutsideDirective, decorators: [{
1009
+ type: Directive,
1010
+ args: [{
1011
+ selector: '[etClickOutside]',
1012
+ standalone: true,
1013
+ }]
1014
+ }], propDecorators: { etClickOutside: [{
1015
+ type: Output
1016
+ }] } });
984
1017
 
985
1018
  const CURSOR_DRAG_SCROLLING_CLASS = 'et-cursor-drag-scroll--scrolling';
986
1019
  const CURSOR_DRAG_SCROLLING_PREPARED_CLASS = 'et-cursor-drag-scroll--prepared';
@@ -1176,7 +1209,7 @@ class ObserveContentDirective {
1176
1209
  this._contentObserver = inject(ContentObserverService);
1177
1210
  this._elementRef = inject(ElementRef);
1178
1211
  this._ngZone = inject(NgZone);
1179
- this.event = new EventEmitter();
1212
+ this.valueChange = new EventEmitter();
1180
1213
  this._disabled = false;
1181
1214
  this._debounce = null;
1182
1215
  this._currentSubscription = null;
@@ -1207,7 +1240,7 @@ class ObserveContentDirective {
1207
1240
  this._unsubscribe();
1208
1241
  const stream = this._contentObserver.observe(this._elementRef);
1209
1242
  this._ngZone.runOutsideAngular(() => {
1210
- this._currentSubscription = (this.debounce ? stream.pipe(debounceTime$1(this.debounce)) : stream).subscribe(this.event);
1243
+ this._currentSubscription = (this.debounce ? stream.pipe(debounceTime$1(this.debounce)) : stream).subscribe(this.valueChange);
1211
1244
  });
1212
1245
  }
1213
1246
  _unsubscribe() {
@@ -1215,7 +1248,7 @@ class ObserveContentDirective {
1215
1248
  }
1216
1249
  }
1217
1250
  ObserveContentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ObserveContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1218
- ObserveContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveContentDirective, isStandalone: true, selector: "[etObserveContent]", inputs: { disabled: ["etObserveContentDisabled", "disabled"], debounce: ["etObserveContentDebounce", "debounce"] }, outputs: { event: "etObserveContent" }, exportAs: ["etObserveContent"], ngImport: i0 });
1251
+ ObserveContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveContentDirective, isStandalone: true, selector: "[etObserveContent]", inputs: { disabled: ["etObserveContentDisabled", "disabled"], debounce: ["etObserveContentDebounce", "debounce"] }, outputs: { valueChange: "etObserveContent" }, exportAs: ["etObserveContent"], ngImport: i0 });
1219
1252
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ObserveContentDirective, decorators: [{
1220
1253
  type: Directive,
1221
1254
  args: [{
@@ -1223,7 +1256,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImpor
1223
1256
  exportAs: 'etObserveContent',
1224
1257
  standalone: true,
1225
1258
  }]
1226
- }], propDecorators: { event: [{
1259
+ }], propDecorators: { valueChange: [{
1227
1260
  type: Output,
1228
1261
  args: ['etObserveContent']
1229
1262
  }], disabled: [{
@@ -1239,7 +1272,7 @@ class ObserveResizeDirective {
1239
1272
  this._resizeObserver = inject(ResizeObserverService);
1240
1273
  this._elementRef = inject(ElementRef);
1241
1274
  this._ngZone = inject(NgZone);
1242
- this.event = new EventEmitter();
1275
+ this.valueChange = new EventEmitter();
1243
1276
  this._disabled = false;
1244
1277
  this._debounce = null;
1245
1278
  this._currentSubscription = null;
@@ -1270,7 +1303,7 @@ class ObserveResizeDirective {
1270
1303
  this._unsubscribe();
1271
1304
  const stream = this._resizeObserver.observe(this._elementRef);
1272
1305
  this._ngZone.runOutsideAngular(() => {
1273
- this._currentSubscription = (this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream).subscribe(this.event);
1306
+ this._currentSubscription = (this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream).subscribe(this.valueChange);
1274
1307
  });
1275
1308
  }
1276
1309
  _unsubscribe() {
@@ -1278,7 +1311,7 @@ class ObserveResizeDirective {
1278
1311
  }
1279
1312
  }
1280
1313
  ObserveResizeDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ObserveResizeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1281
- ObserveResizeDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveResizeDirective, isStandalone: true, selector: "[etObserveResize]", inputs: { disabled: ["etObserveResizeDisabled", "disabled"], debounce: ["etObserveResizeDebounce", "debounce"] }, outputs: { event: "etObserveResize" }, exportAs: ["etObserveResize"], ngImport: i0 });
1314
+ ObserveResizeDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveResizeDirective, isStandalone: true, selector: "[etObserveResize]", inputs: { disabled: ["etObserveResizeDisabled", "disabled"], debounce: ["etObserveResizeDebounce", "debounce"] }, outputs: { valueChange: "etObserveResize" }, exportAs: ["etObserveResize"], ngImport: i0 });
1282
1315
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ObserveResizeDirective, decorators: [{
1283
1316
  type: Directive,
1284
1317
  args: [{
@@ -1286,7 +1319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImpor
1286
1319
  exportAs: 'etObserveResize',
1287
1320
  standalone: true,
1288
1321
  }]
1289
- }], propDecorators: { event: [{
1322
+ }], propDecorators: { valueChange: [{
1290
1323
  type: Output,
1291
1324
  args: ['etObserveResize']
1292
1325
  }], disabled: [{
@@ -1387,7 +1420,7 @@ class ObserveScrollStateDirective {
1387
1420
  this._rootMargin = 0;
1388
1421
  this._threshold = 1;
1389
1422
  this._intersectionObserver = null;
1390
- this.etObserveScrollState = new EventEmitter();
1423
+ this.valueChange = new EventEmitter();
1391
1424
  }
1392
1425
  get _firstCurrentChild() {
1393
1426
  const explicitFirstElement = this._elementRef.nativeElement.querySelector(`.${SCROLL_OBSERVER_FIRST_ELEMENT_CLASS}`);
@@ -1444,7 +1477,7 @@ class ObserveScrollStateDirective {
1444
1477
  !elementCanScroll(this._elementRef.nativeElement)) {
1445
1478
  this._unobserveChild('first');
1446
1479
  this._unobserveChild('last');
1447
- this.etObserveScrollState.emit({
1480
+ this.valueChange.emit({
1448
1481
  isAtStart: true,
1449
1482
  isAtEnd: true,
1450
1483
  canScroll: false,
@@ -1461,7 +1494,7 @@ class ObserveScrollStateDirective {
1461
1494
  const { first, last } = this._observedChildren;
1462
1495
  const isAtStart = entries.find((entry) => entry.target === first)?.isIntersecting ?? false;
1463
1496
  const isAtEnd = entries.find((entry) => entry.target === last)?.isIntersecting ?? false;
1464
- this.etObserveScrollState.emit({
1497
+ this.valueChange.emit({
1465
1498
  isAtStart,
1466
1499
  isAtEnd,
1467
1500
  canScroll: !isAtStart || !isAtEnd,
@@ -1506,7 +1539,7 @@ class ObserveScrollStateDirective {
1506
1539
  }
1507
1540
  }
1508
1541
  ObserveScrollStateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: ObserveScrollStateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1509
- ObserveScrollStateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveScrollStateDirective, isStandalone: true, selector: "[etObserveScrollState]", inputs: { observerRootMargin: "observerRootMargin", observerThreshold: "observerThreshold" }, outputs: { etObserveScrollState: "etObserveScrollState" }, providers: [
1542
+ ObserveScrollStateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: ObserveScrollStateDirective, isStandalone: true, selector: "[etObserveScrollState]", inputs: { observerRootMargin: "observerRootMargin", observerThreshold: "observerThreshold" }, outputs: { valueChange: "etObserveScrollState" }, providers: [
1510
1543
  {
1511
1544
  provide: OBSERVE_SCROLL_STATE,
1512
1545
  useExisting: ObserveScrollStateDirective,
@@ -1531,8 +1564,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImpor
1531
1564
  type: Input
1532
1565
  }], observerThreshold: [{
1533
1566
  type: Input
1534
- }], etObserveScrollState: [{
1535
- type: Output
1567
+ }], valueChange: [{
1568
+ type: Output,
1569
+ args: ['etObserveScrollState']
1536
1570
  }] } });
1537
1571
 
1538
1572
  class RepeatDirective {