@ethlete/cdk 4.12.0 → 4.13.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,8 +1,8 @@
1
1
  import * as i1 from '@angular/cdk/portal';
2
2
  import { CdkPortal, PortalModule, ComponentPortal, TemplatePortal, CdkPortalOutlet } from '@angular/cdk/portal';
3
- import { AsyncPipe, NgClass, NgTemplateOutlet, JsonPipe, NgComponentOutlet, DOCUMENT } from '@angular/common';
3
+ import { AsyncPipe, NgClass, NgTemplateOutlet, JsonPipe, NgComponentOutlet, DOCUMENT, Location } from '@angular/common';
4
4
  import * as i0 from '@angular/core';
5
- import { Component, ViewEncapsulation, ChangeDetectionStrategy, InjectionToken, Directive, booleanAttribute, Input, ContentChild, ContentChildren, inject, ElementRef, Injector, HostBinding, isDevMode, Injectable, ChangeDetectorRef, TemplateRef, ViewContainerRef, ViewChild, forwardRef, numberAttribute, signal, input, EventEmitter, Output, computed, ViewChildren, Optional, Inject, SkipSelf, HostListener, effect, NgZone, NgModule, isSignal, viewChild, contentChild, assertInInjectionContext, Pipe, Attribute } from '@angular/core';
5
+ import { Component, ViewEncapsulation, ChangeDetectionStrategy, InjectionToken, Directive, booleanAttribute, Input, ContentChild, ContentChildren, inject, ElementRef, Injector, HostBinding, isDevMode, Injectable, ChangeDetectorRef, TemplateRef, ViewContainerRef, ViewChild, forwardRef, numberAttribute, signal, input, EventEmitter, Output, computed, ViewChildren, Optional, Inject, SkipSelf, HostListener, effect, NgZone, NgModule, isSignal, DestroyRef, viewChild, contentChild, assertInInjectionContext, Pipe, Attribute } from '@angular/core';
6
6
  import * as i1$1 from '@ethlete/core';
7
7
  import { LetDirective, createDestroy, Memo, signalHostAttributes, signalHostClasses, ObserveVisibilityDirective, signalVisibilityChangeClasses, IS_EMAIL, MUST_MATCH, IS_ARRAY_NOT_EMPTY, AT_LEAST_ONE_REQUIRED, equal, switchQueryListChanges, signalAttributes, ResizeObserverService, createFlipAnimation, AnimatedOverlayDirective, RuntimeError, SelectionModel, ActiveSelectionModel, KeyPressManager, signalClasses, scrollToElement, isEmptyArray, isObjectArray, isPrimitiveArray, createComponentId, ClickOutsideDirective, ANIMATED_LIFECYCLE_TOKEN, AnimatedLifecycleDirective, ObserveContentDirective, clamp, nextFrame, DELAYABLE_TOKEN, ObserveResizeDirective, SmartBlockScrollStrategy, RouterStateService, signalElementScrollState, signalElementIntersection, signalElementChildren, signalHostElementDimensions, signalHostStyles, isElementVisible, getFirstAndLastPartialIntersection, CursorDragScrollDirective, ObserveScrollStateDirective, ClickObserverService, RootBoundaryDirective, elementCanScroll, cloneFormGroup, getFormGroupValue, fromNextFrame, ViewportService, ROOT_BOUNDARY_TOKEN, AnimatedIfDirective, syncSignal, FocusVisibleService, inferMimeType, ScrollObserverIgnoreTargetDirective, TypedQueryList } from '@ethlete/core';
8
8
  import { BehaviorSubject, startWith, map, switchMap, combineLatest, pairwise, tap, takeUntil, skip, of, filter, Subject, Observable, debounceTime, withLatestFrom, distinctUntilChanged, take, merge, skipUntil, skipWhile, catchError, throwError, fromEvent, timer, defer, partition, from, finalize, Subscription } from 'rxjs';
@@ -26,8 +26,8 @@ import { ViewportRuler, STANDARD_DROPDOWN_BELOW_POSITIONS, Overlay, OverlayConfi
26
26
  import { coerceBooleanProperty, coerceCssPixelValue, coerceElement, _isNumberValue } from '@angular/cdk/coercion';
27
27
  import { startWith as startWith$1, debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1, takeUntil as takeUntil$1, skip as skip$1, filter as filter$1, mergeMap, mapTo, mergeAll, switchMap as switchMap$1, take as take$1 } from 'rxjs/operators';
28
28
  import { UniqueSelectionDispatcher, _VIEW_REPEATER_STRATEGY, _DisposeViewRepeaterStrategy, _RecycleViewRepeaterStrategy, DataSource } from '@angular/cdk/collections';
29
- import { Title } from '@angular/platform-browser';
30
29
  import { Router, RouterLink, RouterLinkActive, NavigationEnd } from '@angular/router';
30
+ import { Title } from '@angular/platform-browser';
31
31
  import * as i1$3 from '@angular/cdk/table';
32
32
  import { CdkColumnDef, CDK_TABLE, CdkTable, _COALESCED_STYLE_SCHEDULER, _CoalescedStyleScheduler, STICKY_POSITIONING_LISTENER, HeaderRowOutlet, DataRowOutlet, NoDataRowOutlet, FooterRowOutlet, CdkCell, CdkCellDef, CdkFooterCell, CdkFooterCellDef, CdkHeaderCell, CdkHeaderCellDef, CdkTextColumn, TEXT_COLUMN_OPTIONS, CdkFooterRow, CdkTableModule, CDK_ROW_TEMPLATE, CdkFooterRowDef, CdkHeaderRow, CdkHeaderRowDef, CdkNoDataRow, CdkRow, CdkRowDef } from '@angular/cdk/table';
33
33
  import * as i1$4 from '@angular/cdk/scrolling';
@@ -4015,6 +4015,7 @@ class OverlayRef {
4015
4015
  }
4016
4016
  constructor(_ref, config, _containerInstance) {
4017
4017
  this._ref = _ref;
4018
+ this.config = config;
4018
4019
  this._containerInstance = _containerInstance;
4019
4020
  this.componentInstance = null;
4020
4021
  this.componentRef = null;
@@ -11626,15 +11627,18 @@ class OverlayPositionBuilder {
11626
11627
  const OVERLAY_ROUTER_CONFIG_TOKEN = new InjectionToken('OVERLAY_ROUTER_CONFIG_TOKEN');
11627
11628
  class OverlayRouterService {
11628
11629
  constructor() {
11629
- this.config = inject(OVERLAY_ROUTER_CONFIG_TOKEN);
11630
- this.syncCurrentRoute = signal('/');
11630
+ this._router = inject(Router);
11631
+ this._routerStateService = inject(RouterStateService);
11632
+ this._id = createComponentId('ovr');
11633
+ this._overlayRef = inject(OverlayRef);
11634
+ this._config = inject(OVERLAY_ROUTER_CONFIG_TOKEN);
11635
+ this._syncCurrentRoute = signal(this._getInitialRoute());
11636
+ this._nativeBrowserTempBackNavigationStack = signal([]);
11631
11637
  // The current route, but delayed by one frame to ensure that the needed animation classes are applied.
11632
- this.currentRoute = toSignal(toObservable(this.syncCurrentRoute).pipe(switchMap((r) => fromNextFrame().pipe(map(() => r)))), { initialValue: '/' });
11633
- this.routeHistory = signal([]);
11634
- this.rootHistoryItem = signal(null);
11638
+ this.currentRoute = toSignal(toObservable(this._syncCurrentRoute).pipe(switchMap((r) => fromNextFrame().pipe(map(() => r)))), { initialValue: this._getInitialRoute() });
11635
11639
  this.extraRoutes = signal([]);
11636
11640
  this.routes = computed(() => {
11637
- const allRoutes = [...this.config.routes, ...this.extraRoutes()];
11641
+ const allRoutes = [...this._config.routes, ...this.extraRoutes()];
11638
11642
  const allRoundsWithTransformedInputs = allRoutes.map((route) => {
11639
11643
  return {
11640
11644
  ...route,
@@ -11652,7 +11656,7 @@ class OverlayRouterService {
11652
11656
  return allRoundsWithTransformedInputs;
11653
11657
  });
11654
11658
  this.currentPage = computed(() => {
11655
- const currentRoute = this.syncCurrentRoute();
11659
+ const currentRoute = this._syncCurrentRoute();
11656
11660
  for (const route of this.routes()) {
11657
11661
  if (route.path === currentRoute) {
11658
11662
  return route;
@@ -11660,18 +11664,50 @@ class OverlayRouterService {
11660
11664
  }
11661
11665
  return null;
11662
11666
  });
11663
- this.lastPage = computed(() => {
11664
- const history = this.routeHistory();
11665
- if (history.length) {
11666
- return history[history.length - 1];
11667
+ this.navigationDirection = signal('forward');
11668
+ this._disableCloseOnNavigation();
11669
+ this._updateBrowserUrl(this._syncCurrentRoute());
11670
+ this._routerStateService
11671
+ .selectQueryParam(this._id)
11672
+ .pipe(takeUntilDestroyed(), skip(1), tap((route) => {
11673
+ // The user navigated back or forward using the browser history
11674
+ if (!route) {
11675
+ // The route query param no longer exists - close the overlay
11676
+ this._overlayRef.close();
11677
+ }
11678
+ else if (route !== this._syncCurrentRoute()) {
11679
+ const navStack = this._nativeBrowserTempBackNavigationStack();
11680
+ const currentRoute = this._syncCurrentRoute();
11681
+ if (!navStack.length) {
11682
+ // If the nav stack is empty the only way to navigate is back.
11683
+ this.navigate(route, { navigationDirection: 'backward' });
11684
+ this._nativeBrowserTempBackNavigationStack.set([currentRoute]);
11685
+ }
11686
+ else {
11687
+ const lastItem = navStack[navStack.length - 1];
11688
+ if (route === lastItem) {
11689
+ // The new route matches the last item in the back nav stack.
11690
+ // This means we are going forward again.
11691
+ this.navigate(route, { navigationDirection: 'forward' });
11692
+ this._nativeBrowserTempBackNavigationStack.set(navStack.slice(0, -1));
11693
+ }
11694
+ else {
11695
+ // Else we are going back.
11696
+ this.navigate(route, { navigationDirection: 'backward' });
11697
+ this._nativeBrowserTempBackNavigationStack.set([...navStack, currentRoute]);
11698
+ }
11699
+ }
11667
11700
  }
11668
- return null;
11669
- });
11670
- this.canGoBack = computed(() => {
11671
- return this.routeHistory().length;
11701
+ else {
11702
+ // The navigation was triggered by ui interaction. Clear the back nav stack.
11703
+ this._nativeBrowserTempBackNavigationStack.set([]);
11704
+ }
11705
+ }))
11706
+ .subscribe();
11707
+ inject(DestroyRef).onDestroy(() => {
11708
+ // Remove the dialog route from the browser url
11709
+ this._updateBrowserUrl(undefined);
11672
11710
  });
11673
- this.navigationDirection = signal('forward');
11674
- this._navigateToInitialRoute();
11675
11711
  }
11676
11712
  navigate(route, config) {
11677
11713
  const resolvedRoute = this.resolvePath(route);
@@ -11686,14 +11722,6 @@ class OverlayRouterService {
11686
11722
  }
11687
11723
  this._updateCurrentRoute(resolvedRoute.route);
11688
11724
  }
11689
- back() {
11690
- const prevRoute = this.lastPage();
11691
- if (!prevRoute)
11692
- return;
11693
- this.navigationDirection.set('backward');
11694
- this.routeHistory.set(this.routeHistory().slice(0, -1));
11695
- this._updateCurrentRoute(prevRoute, { updateHistory: false });
11696
- }
11697
11725
  resolvePath(route) {
11698
11726
  if (Array.isArray(route)) {
11699
11727
  route = route.join('/');
@@ -11705,7 +11733,7 @@ class OverlayRouterService {
11705
11733
  const isReplaceCurrent = route.startsWith('./');
11706
11734
  const isBack = route.startsWith('../');
11707
11735
  const isForward = !isAbsolute && !isReplaceCurrent && !isBack;
11708
- const curr = this.syncCurrentRoute();
11736
+ const curr = this._syncCurrentRoute();
11709
11737
  if (isForward) {
11710
11738
  route = `${curr}/${route}`;
11711
11739
  }
@@ -11743,56 +11771,30 @@ class OverlayRouterService {
11743
11771
  removeRoute(path) {
11744
11772
  this.extraRoutes.set(this.extraRoutes().filter((r) => r.path !== path));
11745
11773
  }
11746
- _updateCurrentRoute(route, config) {
11747
- if (route === this.syncCurrentRoute())
11774
+ _updateCurrentRoute(route) {
11775
+ if (route === this._syncCurrentRoute())
11748
11776
  return;
11749
11777
  if (this.routes().findIndex((r) => r.path === route) === -1) {
11750
- console.error(`The route "${route}" does not exist.`, this.config);
11778
+ console.error(`The route "${route}" does not exist.`, this._config);
11751
11779
  return;
11752
11780
  }
11753
- const lastRoute = this.syncCurrentRoute();
11754
- if (config?.updateHistory === true || config?.updateHistory === undefined) {
11755
- const history = this.routeHistory();
11756
- if (history[history.length - 1] !== lastRoute) {
11757
- const newHistory = [...history, lastRoute];
11758
- // limit the history to 25 items
11759
- if (newHistory.length > 25) {
11760
- newHistory.shift();
11761
- }
11762
- const rootHistoryItem = this.rootHistoryItem();
11763
- if (rootHistoryItem && newHistory[0] !== rootHistoryItem) {
11764
- newHistory.unshift(rootHistoryItem);
11765
- }
11766
- this.routeHistory.set(newHistory);
11767
- }
11768
- }
11769
- this.syncCurrentRoute.set(route);
11781
+ this._syncCurrentRoute.set(route);
11782
+ this._updateBrowserUrl(route);
11770
11783
  }
11771
- _removeItemFromHistory(item) {
11772
- const history = this.routeHistory();
11773
- const cleanedHistory = history.filter((i) => i !== item);
11774
- if (cleanedHistory.length === 1 && cleanedHistory[0] === this.syncCurrentRoute()) {
11775
- this.routeHistory.set([]);
11776
- }
11777
- else {
11778
- this.routeHistory.set(cleanedHistory);
11779
- }
11784
+ _getInitialRoute() {
11785
+ return this._config.initialRoute ?? this._config.routes[0]?.path ?? '/';
11780
11786
  }
11781
11787
  _navigateToInitialRoute() {
11782
- if (this.config.initialRoute) {
11783
- this._updateCurrentRoute(this.config.initialRoute ?? '/', { updateHistory: false });
11784
- }
11785
- else {
11786
- const first = this.config.routes[0]?.path;
11787
- this._updateCurrentRoute(first ?? '/', { updateHistory: false });
11788
- }
11788
+ this._updateCurrentRoute(this._getInitialRoute());
11789
+ }
11790
+ _updateBrowserUrl(route) {
11791
+ this._router.navigate(['.'], { queryParams: { [this._id]: route }, queryParamsHandling: 'merge' });
11792
+ }
11793
+ _disableCloseOnNavigation() {
11794
+ // @ts-expect-error - private property
11795
+ this._overlayRef._cdkRef.overlayRef._locationChanges?.unsubscribe?.();
11789
11796
  }
11790
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: OverlayRouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
11791
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: OverlayRouterService }); }
11792
11797
  }
11793
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: OverlayRouterService, decorators: [{
11794
- type: Injectable
11795
- }], ctorParameters: () => [] });
11796
11798
  const provideOverlayRouterConfig = (config) => {
11797
11799
  return [
11798
11800
  {
@@ -11907,7 +11909,6 @@ class OverlayService {
11907
11909
  { provide: RootBoundaryDirective, useValue: container._rootBoundary },
11908
11910
  { provide: OVERLAY_DATA, useValue: cdkConfig.data },
11909
11911
  { provide: OverlayRef, useValue: overlayRef },
11910
- { provide: OverlayRef, useValue: overlayRef },
11911
11912
  ...(composedConfig.providers ?? []),
11912
11913
  ];
11913
11914
  },
@@ -12363,14 +12364,10 @@ class SidebarOverlayService {
12363
12364
  .pipe(distinctUntilChanged(), tap((renderSidebar) => {
12364
12365
  if (renderSidebar) {
12365
12366
  this.router.removeRoute(sidebarPageRoute);
12366
- this.router.rootHistoryItem.set(null);
12367
12367
  // if the user is currently on the sidebar route, navigate to the initial route.
12368
12368
  if (this.router.currentRoute() === sidebarPageRoute) {
12369
12369
  this.router._navigateToInitialRoute();
12370
12370
  }
12371
- // clean up all history entries that are the sidebar route.
12372
- // we don't want to navigate to the sidebar route if the sidebar is already visible as a actual sidebar.
12373
- this.router._removeItemFromHistory(sidebarPageRoute);
12374
12371
  }
12375
12372
  else {
12376
12373
  this.router.addRoute({
@@ -12381,18 +12378,11 @@ class SidebarOverlayService {
12381
12378
  bodyTemplate: this.sidebarContentTemplate,
12382
12379
  },
12383
12380
  });
12384
- // ensure that the sidebar route is always the last route in the history so it can be reached.
12385
- this.router.rootHistoryItem.set(sidebarPageRoute);
12386
12381
  }
12387
12382
  }), takeUntilDestroyed())
12388
12383
  .subscribe();
12389
12384
  }
12390
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: SidebarOverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
12391
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: SidebarOverlayService }); }
12392
12385
  }
12393
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: SidebarOverlayService, decorators: [{
12394
- type: Injectable
12395
- }], ctorParameters: () => [] });
12396
12386
  const provideSidebarOverlayConfig = (config) => {
12397
12387
  return [
12398
12388
  {
@@ -12406,22 +12396,12 @@ const provideSidebarOverlayConfig = (config) => {
12406
12396
  const OVERLAY_BACK_OR_CLOSE_TOKEN = new InjectionToken('OVERLAY_BACK_OR_CLOSE_TOKEN');
12407
12397
  class OverlayBackOrCloseDirective {
12408
12398
  constructor() {
12399
+ this.locationService = inject(Location);
12409
12400
  this.overlayRef = inject(OverlayRef);
12410
12401
  this.router = inject(OverlayRouterService);
12411
12402
  this.disabled = input(false, { transform: booleanAttribute });
12412
- this.hostClassBindings = signalHostClasses({
12413
- 'et-overlay-back-or-close--is-back': this.router.canGoBack,
12414
- 'et-overlay-back-or-close--is-close': computed(() => !this.router.canGoBack()),
12415
- });
12416
12403
  fromEvent(inject(ElementRef).nativeElement, 'click')
12417
- .pipe(filter(() => !this.disabled()), tap(() => {
12418
- if (this.router.canGoBack()) {
12419
- this.router.back();
12420
- }
12421
- else {
12422
- this.overlayRef.close();
12423
- }
12424
- }), takeUntilDestroyed())
12404
+ .pipe(filter(() => !this.disabled()), tap(() => this.locationService.back()), takeUntilDestroyed())
12425
12405
  .subscribe();
12426
12406
  }
12427
12407
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.1", ngImport: i0, type: OverlayBackOrCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }