diff --git a/src/angular/breadcrumb/breadcrumb/breadcrumb.ts b/src/angular/breadcrumb/breadcrumb/breadcrumb.ts index 4c8fe30..ed58f95 100644 --- a/src/angular/breadcrumb/breadcrumb/breadcrumb.ts +++ b/src/angular/breadcrumb/breadcrumb/breadcrumb.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbBreadcrumbElement } from '@sbb-esta/lyne-elements/breadcrumb/breadcrumb.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -8,7 +8,7 @@ import '@sbb-esta/lyne-elements/breadcrumb/breadcrumb.js'; @Directive({ selector: 'sbb-breadcrumb', }) -export class SbbBreadcrumb { +export class SbbBreadcrumb extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/button/accent-button-link/accent-button-link.ts b/src/angular/button/accent-button-link/accent-button-link.ts index 7f6f67b..d2c0388 100644 --- a/src/angular/button/accent-button-link/accent-button-link.ts +++ b/src/angular/button/accent-button-link/accent-button-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbAccentButtonLinkElement } from '@sbb-esta/lyne-elements/button/accent-button-link.js'; import { SbbButtonSize } from '@sbb-esta/lyne-elements/button.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -9,7 +9,7 @@ import '@sbb-esta/lyne-elements/button/accent-button-link.js'; @Directive({ selector: 'sbb-accent-button-link', }) -export class SbbAccentButtonLink { +export class SbbAccentButtonLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/button/button-link/button-link.ts b/src/angular/button/button-link/button-link.ts index 348885a..e129a1e 100644 --- a/src/angular/button/button-link/button-link.ts +++ b/src/angular/button/button-link/button-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbButtonLinkElement } from '@sbb-esta/lyne-elements/button/button-link.js'; import { SbbButtonSize } from '@sbb-esta/lyne-elements/button.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -9,7 +9,7 @@ import '@sbb-esta/lyne-elements/button/button-link.js'; @Directive({ selector: 'sbb-button-link', }) -export class SbbButtonLink { +export class SbbButtonLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/button/secondary-button-link/secondary-button-link.ts b/src/angular/button/secondary-button-link/secondary-button-link.ts index a1a39b6..5fe7711 100644 --- a/src/angular/button/secondary-button-link/secondary-button-link.ts +++ b/src/angular/button/secondary-button-link/secondary-button-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbSecondaryButtonLinkElement } from '@sbb-esta/lyne-elements/button/secondary-button-link.js'; import { SbbButtonSize } from '@sbb-esta/lyne-elements/button.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -9,7 +9,7 @@ import '@sbb-esta/lyne-elements/button/secondary-button-link.js'; @Directive({ selector: 'sbb-secondary-button-link', }) -export class SbbSecondaryButtonLink { +export class SbbSecondaryButtonLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject( ElementRef, ); diff --git a/src/angular/button/transparent-button-link/transparent-button-link.ts b/src/angular/button/transparent-button-link/transparent-button-link.ts index a618a4e..71f29f3 100644 --- a/src/angular/button/transparent-button-link/transparent-button-link.ts +++ b/src/angular/button/transparent-button-link/transparent-button-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbTransparentButtonLinkElement } from '@sbb-esta/lyne-elements/button/transparent-button-link.js'; import { SbbButtonSize } from '@sbb-esta/lyne-elements/button.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -9,7 +9,7 @@ import '@sbb-esta/lyne-elements/button/transparent-button-link.js'; @Directive({ selector: 'sbb-transparent-button-link', }) -export class SbbTransparentButtonLink { +export class SbbTransparentButtonLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject( ElementRef, ); diff --git a/src/angular/card/card-link/card-link.ts b/src/angular/card/card-link/card-link.ts index 64b80f7..517343b 100644 --- a/src/angular/card/card-link/card-link.ts +++ b/src/angular/card/card-link/card-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import type { SbbCardLinkElement } from '@sbb-esta/lyne-elements/card/card-link.js'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; @@ -8,7 +8,7 @@ import '@sbb-esta/lyne-elements/card/card-link.js'; @Directive({ selector: 'sbb-card-link', }) -export class SbbCardLink { +export class SbbCardLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/core/index.ts b/src/angular/core/index.ts index d8da131..f7f11a4 100644 --- a/src/angular/core/index.ts +++ b/src/angular/core/index.ts @@ -1,2 +1,3 @@ export * from './attribute-transform'; export * from './control-value-accessor-mixin'; +export * from './router-link-support-mixin'; diff --git a/src/angular/core/router-link-support-mixin.ts b/src/angular/core/router-link-support-mixin.ts new file mode 100644 index 0000000..2b0f80b --- /dev/null +++ b/src/angular/core/router-link-support-mixin.ts @@ -0,0 +1,45 @@ +import { inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { NavigationEnd, Router, RouterLink } from '@angular/router'; +import { AbstractConstructor } from '@sbb-esta/lyne-elements/core/mixins.js'; + +/** + * Patches the behavior of the Angular RouterLink. + * With this patch the RouterLink recognizes the web component links + * as native links and processes them correctly. + * TODO: Check whether there is support of Angular for that case: + * - https://github.com/angular/angular/pull/59567 + * - https://github.com/angular/angular/issues/28345 + */ +export const SbbRouterLinkSupportMixin = ( + superclass: T, +): AbstractConstructor & T => { + abstract class SbbRouterLink extends superclass { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + constructor(...args: any[]) { + super(...args); + + const routerLink = inject(RouterLink, { optional: true }) as unknown as { + isAnchorElement: boolean; + updateHref: () => void; + setTabIndexIfNotOnNativeEl: (newTabIndex: string | null) => void; + }; + + if (!routerLink) { + return; + } + + routerLink.setTabIndexIfNotOnNativeEl(null); + routerLink.isAnchorElement = true; + + inject(Router) + .events.pipe(takeUntilDestroyed()) + .subscribe((s) => { + if (s instanceof NavigationEnd) { + routerLink.updateHref(); + } + }); + } + } + return SbbRouterLink as unknown as AbstractConstructor & T; +}; diff --git a/src/angular/header/header-link/header-link.ts b/src/angular/header/header-link/header-link.ts index e03e4fb..ace508c 100644 --- a/src/angular/header/header-link/header-link.ts +++ b/src/angular/header/header-link/header-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import { SbbHorizontalFrom } from '@sbb-esta/lyne-elements/core/interfaces.js'; import type { SbbHeaderLinkElement } from '@sbb-esta/lyne-elements/header/header-link.js'; @@ -8,7 +8,7 @@ import '@sbb-esta/lyne-elements/header/header-link.js'; @Directive({ selector: 'sbb-header-link', }) -export class SbbHeaderLink { +export class SbbHeaderLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/link/block-link/block-link.ts b/src/angular/link/block-link/block-link.ts index c1cab19..ab28f06 100644 --- a/src/angular/link/block-link/block-link.ts +++ b/src/angular/link/block-link/block-link.ts @@ -1,15 +1,16 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import { SbbIconPlacement } from '@sbb-esta/lyne-elements/core/interfaces.js'; import type { SbbBlockLinkElement } from '@sbb-esta/lyne-elements/link/block-link.js'; import { SbbLinkSize } from '@sbb-esta/lyne-elements/link.js'; + import '@sbb-esta/lyne-elements/link/block-link.js'; @Directive({ selector: 'sbb-block-link', }) -export class SbbBlockLink { +export class SbbBlockLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/link/link/link.ts b/src/angular/link/link/link.ts index dd5d2d6..6b0b8cc 100644 --- a/src/angular/link/link/link.ts +++ b/src/angular/link/link/link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbLinkElement } from '@sbb-esta/lyne-elements/link/link.js'; import { SbbLinkSize } from '@sbb-esta/lyne-elements/link.js'; @@ -8,7 +8,7 @@ import '@sbb-esta/lyne-elements/link/link.js'; @Directive({ selector: 'sbb-link', }) -export class SbbLink { +export class SbbLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/menu/menu-link/menu-link.ts b/src/angular/menu/menu-link/menu-link.ts index 1626ddc..db352c7 100644 --- a/src/angular/menu/menu-link/menu-link.ts +++ b/src/angular/menu/menu-link/menu-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbMenuLinkElement } from '@sbb-esta/lyne-elements/menu/menu-link.js'; import '@sbb-esta/lyne-elements/menu/menu-link.js'; @@ -7,7 +7,7 @@ import '@sbb-esta/lyne-elements/menu/menu-link.js'; @Directive({ selector: 'sbb-menu-link', }) -export class SbbMenuLink { +export class SbbMenuLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/navigation/navigation-link/navigation-link.ts b/src/angular/navigation/navigation-link/navigation-link.ts index 3ac22bf..19b1b97 100644 --- a/src/angular/navigation/navigation-link/navigation-link.ts +++ b/src/angular/navigation/navigation-link/navigation-link.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbNavigationLinkElement } from '@sbb-esta/lyne-elements/navigation/navigation-link.js'; import { SbbNavigationMarkerElement } from '@sbb-esta/lyne-elements/navigation/navigation-marker.js'; @@ -10,7 +10,7 @@ import '@sbb-esta/lyne-elements/navigation/navigation-link.js'; @Directive({ selector: 'sbb-navigation-link', }) -export class SbbNavigationLink { +export class SbbNavigationLink extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/teaser-hero/teaser-hero.ts b/src/angular/teaser-hero/teaser-hero.ts index eed8132..a2837db 100644 --- a/src/angular/teaser-hero/teaser-hero.ts +++ b/src/angular/teaser-hero/teaser-hero.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbTeaserHeroElement } from '@sbb-esta/lyne-elements/teaser-hero.js'; import '@sbb-esta/lyne-elements/teaser-hero.js'; @@ -7,7 +7,7 @@ import '@sbb-esta/lyne-elements/teaser-hero.js'; @Directive({ selector: 'sbb-teaser-hero', }) -export class SbbTeaserHero { +export class SbbTeaserHero extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/teaser-product/teaser-product/teaser-product.ts b/src/angular/teaser-product/teaser-product/teaser-product.ts index 843d666..740f44a 100644 --- a/src/angular/teaser-product/teaser-product/teaser-product.ts +++ b/src/angular/teaser-product/teaser-product/teaser-product.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbTeaserProductElement } from '@sbb-esta/lyne-elements/teaser-product/teaser-product.js'; import '@sbb-esta/lyne-elements/teaser-product/teaser-product.js'; @@ -7,7 +7,7 @@ import '@sbb-esta/lyne-elements/teaser-product/teaser-product.js'; @Directive({ selector: 'sbb-teaser-product', }) -export class SbbTeaserProduct { +export class SbbTeaserProduct extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/angular/teaser/teaser.ts b/src/angular/teaser/teaser.ts index bc645ae..2d60d6b 100644 --- a/src/angular/teaser/teaser.ts +++ b/src/angular/teaser/teaser.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, inject, Input, NgZone } from '@angular/core'; -import { booleanAttribute } from '@sbb-esta/lyne-angular/core'; +import { booleanAttribute, SbbRouterLinkSupportMixin } from '@sbb-esta/lyne-angular/core'; import { LinkTargetType } from '@sbb-esta/lyne-elements/core/base-elements.js'; import type { SbbTeaserElement } from '@sbb-esta/lyne-elements/teaser.js'; import { SbbTitleLevel } from '@sbb-esta/lyne-elements/title.js'; @@ -8,7 +8,7 @@ import '@sbb-esta/lyne-elements/teaser.js'; @Directive({ selector: 'sbb-teaser', }) -export class SbbTeaser { +export class SbbTeaser extends SbbRouterLinkSupportMixin(class {}) { #element: ElementRef = inject(ElementRef); #ngZone: NgZone = inject(NgZone); diff --git a/src/showcase/styles.scss b/src/showcase/styles.scss index 90d4ee0..5f97aee 100644 --- a/src/showcase/styles.scss +++ b/src/showcase/styles.scss @@ -1 +1,3 @@ +@import '@sbb-esta/lyne-elements/standard-theme.css'; + /* You can add global styles to this file, and also import other style files */