@sebgroup/green-core-ng 2.37.1 → 2.37.2

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,12 +1,13 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, ElementRef, NgZone, ChangeDetectorRef, EventEmitter, booleanAttribute, Output, Input, ChangeDetectionStrategy, Component, Renderer2, Injector, Directive, forwardRef, NgModule, InjectionToken, ViewContainerRef, TemplateRef, Injectable, RendererFactory2 } from '@angular/core';
3
+ import { inject, ElementRef, NgZone, ChangeDetectorRef, EventEmitter, booleanAttribute, Output, Input, ChangeDetectionStrategy, Component, Renderer2, Injector, Directive, DestroyRef, forwardRef, NgModule, InjectionToken, ViewContainerRef, TemplateRef, Injectable, RendererFactory2 } from '@angular/core';
4
4
  import { GdsAlert } from '@sebgroup/green-core/components/alert/alert.component.js';
5
5
  import { GdsBadge } from '@sebgroup/green-core/components/badge/badge.component.js';
6
6
  import { GdsBlur } from '@sebgroup/green-core/components/blur/blur.component.js';
7
7
  import { GdsBreadcrumbs } from '@sebgroup/green-core/components/breadcrumbs/breadcrumbs.component.js';
8
8
  import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
9
- import { RouterLink, RouterLinkActive } from '@angular/router';
9
+ import { LocationStrategy, DOCUMENT, CommonModule } from '@angular/common';
10
+ import { Router, RouterLink, RouterLinkActive, NavigationEnd } from '@angular/router';
10
11
  import { GdsButton } from '@sebgroup/green-core/components/button/button.component.js';
11
12
  import { GdsCalendar } from '@sebgroup/green-core/components/calendar/calendar.component.js';
12
13
  import { GdsCard } from '@sebgroup/green-core/components/card/card.component.js';
@@ -398,7 +399,6 @@ import { GdsSegment } from '@sebgroup/green-core/components/segmented-control/se
398
399
  import { GdsSensitiveAccount } from '@sebgroup/green-core/components/sensitive/account/sensitive-account.component.js';
399
400
  import { GdsSensitiveDate } from '@sebgroup/green-core/components/sensitive/date/sensitive-date.component.js';
400
401
  import { GdsSensitiveNumber } from '@sebgroup/green-core/components/sensitive/number/sensitive-number.component.js';
401
- import { DOCUMENT, CommonModule } from '@angular/common';
402
402
  import { getScopedTagName } from '@sebgroup/green-core/scoping';
403
403
  import { ɵAnimationRendererFactory as _AnimationRendererFactory, ɵAnimationEngine as _AnimationEngine } from '@angular/animations/browser';
404
404
  import * as i1 from '@angular/platform-browser';
@@ -895,23 +895,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
895
895
  let GdsButtonComponent = class GdsButtonComponent extends GdsFormControlBase {
896
896
  constructor() {
897
897
  super(...arguments);
898
+ this.router = inject(Router);
899
+ this.locationStrategy = inject(LocationStrategy);
900
+ this.destroyRef = inject(DestroyRef);
898
901
  this.routerLink = inject(RouterLink, { optional: true, self: true });
899
902
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
900
903
  /** Fired when the button is clicked. */
901
904
  this.click = new EventEmitter();
902
905
  }
903
906
  /**
904
- * Updates the href attribute from RouterLink
907
+ * Prevent the browser from following the href when RouterLink handles
908
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
909
+ * but only calls preventDefault() for native <a> tags. For custom
910
+ * elements we must do it ourselves, respecting modifier-key and
911
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
912
+ * still open a new tab.
913
+ * @internal
914
+ */
915
+ preventNativeNavigation() {
916
+ // Use capture phase so this runs before Angular's RouterLink host listener.
917
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
918
+ if (!this.routerLink?.urlTree)
919
+ return;
920
+ // When modifier keys are pressed or target is not _self, stop
921
+ // RouterLink from navigating (it skips these checks for non-anchor
922
+ // elements) and let the browser handle the click natively (new tab etc.)
923
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
924
+ event.stopImmediatePropagation();
925
+ return;
926
+ }
927
+ const target = this.elementRef.nativeElement.getAttribute('target');
928
+ if (target && target !== '_self') {
929
+ event.stopImmediatePropagation();
930
+ return;
931
+ }
932
+ // Normal left-click: let RouterLink handle navigation via
933
+ // Router.navigateByUrl(), but prevent the browser from also
934
+ // following the shadow DOM anchor's href.
935
+ event.preventDefault();
936
+ }, true);
937
+ }
938
+ /**
939
+ * Updates the href attribute from RouterLink using only public Angular APIs.
905
940
  * @internal
906
941
  */
907
942
  updateHref() {
908
943
  if (!this.routerLink)
909
944
  return;
910
- // Trick RouterLink into thinking we are an anchor element
911
- this.routerLink.isAnchorElement = true;
912
- this.routerLink.updateHref();
913
- // Set the href attribute on our element
914
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
945
+ const urlTree = this.routerLink.urlTree;
946
+ const href = urlTree
947
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
948
+ : null;
949
+ if (href) {
950
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
951
+ }
915
952
  }
916
953
  get element() {
917
954
  return this.elementRef.nativeElement;
@@ -926,6 +963,19 @@ let GdsButtonComponent = class GdsButtonComponent extends GdsFormControlBase {
926
963
  // Component may not be available in this version of green-core
927
964
  console.warn('Failed to define gds-button:', e);
928
965
  }
966
+ if (this.routerLink) {
967
+ // Prevent the browser from following the href on click – RouterLink
968
+ // handles navigation via Router.navigateByUrl() but only calls
969
+ // preventDefault() for native <a> elements.
970
+ this.preventNativeNavigation();
971
+ // Keep href in sync after client-side navigations (RouterLink only
972
+ // does this for native <a> elements).
973
+ const sub = this.router.events.subscribe((event) => {
974
+ if (event instanceof NavigationEnd)
975
+ this.updateHref();
976
+ });
977
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
978
+ }
929
979
  }
930
980
  ngOnChanges(changes) {
931
981
  // Implementation added by @ProxyInputs decorator
@@ -1345,22 +1395,72 @@ let GdsCardLinkedComponent = class GdsCardLinkedComponent {
1345
1395
  this.zone = inject(NgZone);
1346
1396
  this.cdr = inject(ChangeDetectorRef);
1347
1397
  this.renderer = inject(Renderer2);
1398
+ this.router = inject(Router);
1399
+ this.locationStrategy = inject(LocationStrategy);
1400
+ this.destroyRef = inject(DestroyRef);
1348
1401
  this.routerLink = inject(RouterLink, { optional: true, self: true });
1349
1402
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
1350
1403
  this.cdr.detach();
1404
+ if (this.routerLink) {
1405
+ // Prevent the browser from following the href on click – RouterLink
1406
+ // handles navigation via Router.navigateByUrl() but only calls
1407
+ // preventDefault() for native <a> elements.
1408
+ this.preventNativeNavigation();
1409
+ // Keep href in sync after client-side navigations (RouterLink only
1410
+ // does this for native <a> elements).
1411
+ const sub = this.router.events.subscribe((event) => {
1412
+ if (event instanceof NavigationEnd)
1413
+ this.updateHref();
1414
+ });
1415
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
1416
+ }
1417
+ }
1418
+ /**
1419
+ * Prevent the browser from following the href when RouterLink handles
1420
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
1421
+ * but only calls preventDefault() for native <a> tags. For custom
1422
+ * elements we must do it ourselves, respecting modifier-key and
1423
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
1424
+ * still open a new tab.
1425
+ * @internal
1426
+ */
1427
+ preventNativeNavigation() {
1428
+ // Use capture phase so this runs before Angular's RouterLink host listener.
1429
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
1430
+ if (!this.routerLink?.urlTree)
1431
+ return;
1432
+ // When modifier keys are pressed or target is not _self, stop
1433
+ // RouterLink from navigating (it skips these checks for non-anchor
1434
+ // elements) and let the browser handle the click natively (new tab etc.)
1435
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
1436
+ event.stopImmediatePropagation();
1437
+ return;
1438
+ }
1439
+ const target = this.elementRef.nativeElement.getAttribute('target');
1440
+ if (target && target !== '_self') {
1441
+ event.stopImmediatePropagation();
1442
+ return;
1443
+ }
1444
+ // Normal left-click: let RouterLink handle navigation via
1445
+ // Router.navigateByUrl(), but prevent the browser from also
1446
+ // following the shadow DOM anchor's href.
1447
+ event.preventDefault();
1448
+ }, true);
1351
1449
  }
1352
1450
  /**
1353
- * Updates the href attribute from RouterLink
1451
+ * Updates the href attribute from RouterLink using only public Angular APIs.
1354
1452
  * @internal
1355
1453
  */
1356
1454
  updateHref() {
1357
1455
  if (!this.routerLink)
1358
1456
  return;
1359
- // Trick RouterLink into thinking we are an anchor element
1360
- this.routerLink.isAnchorElement = true;
1361
- this.routerLink.updateHref();
1362
- // Set the href attribute on our element
1363
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
1457
+ const urlTree = this.routerLink.urlTree;
1458
+ const href = urlTree
1459
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
1460
+ : null;
1461
+ if (href) {
1462
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
1463
+ }
1364
1464
  }
1365
1465
  ngOnInit() {
1366
1466
  // Define the custom element
@@ -2732,21 +2832,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
2732
2832
  let GdsFabComponent = class GdsFabComponent extends GdsFormControlBase {
2733
2833
  constructor() {
2734
2834
  super(...arguments);
2835
+ this.router = inject(Router);
2836
+ this.locationStrategy = inject(LocationStrategy);
2837
+ this.destroyRef = inject(DestroyRef);
2735
2838
  this.routerLink = inject(RouterLink, { optional: true, self: true });
2736
2839
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
2737
2840
  }
2738
2841
  /**
2739
- * Updates the href attribute from RouterLink
2842
+ * Prevent the browser from following the href when RouterLink handles
2843
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
2844
+ * but only calls preventDefault() for native <a> tags. For custom
2845
+ * elements we must do it ourselves, respecting modifier-key and
2846
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
2847
+ * still open a new tab.
2848
+ * @internal
2849
+ */
2850
+ preventNativeNavigation() {
2851
+ // Use capture phase so this runs before Angular's RouterLink host listener.
2852
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
2853
+ if (!this.routerLink?.urlTree)
2854
+ return;
2855
+ // When modifier keys are pressed or target is not _self, stop
2856
+ // RouterLink from navigating (it skips these checks for non-anchor
2857
+ // elements) and let the browser handle the click natively (new tab etc.)
2858
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
2859
+ event.stopImmediatePropagation();
2860
+ return;
2861
+ }
2862
+ const target = this.elementRef.nativeElement.getAttribute('target');
2863
+ if (target && target !== '_self') {
2864
+ event.stopImmediatePropagation();
2865
+ return;
2866
+ }
2867
+ // Normal left-click: let RouterLink handle navigation via
2868
+ // Router.navigateByUrl(), but prevent the browser from also
2869
+ // following the shadow DOM anchor's href.
2870
+ event.preventDefault();
2871
+ }, true);
2872
+ }
2873
+ /**
2874
+ * Updates the href attribute from RouterLink using only public Angular APIs.
2740
2875
  * @internal
2741
2876
  */
2742
2877
  updateHref() {
2743
2878
  if (!this.routerLink)
2744
2879
  return;
2745
- // Trick RouterLink into thinking we are an anchor element
2746
- this.routerLink.isAnchorElement = true;
2747
- this.routerLink.updateHref();
2748
- // Set the href attribute on our element
2749
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
2880
+ const urlTree = this.routerLink.urlTree;
2881
+ const href = urlTree
2882
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
2883
+ : null;
2884
+ if (href) {
2885
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
2886
+ }
2750
2887
  }
2751
2888
  get element() {
2752
2889
  return this.elementRef.nativeElement;
@@ -2761,6 +2898,19 @@ let GdsFabComponent = class GdsFabComponent extends GdsFormControlBase {
2761
2898
  // Component may not be available in this version of green-core
2762
2899
  console.warn('Failed to define gds-fab:', e);
2763
2900
  }
2901
+ if (this.routerLink) {
2902
+ // Prevent the browser from following the href on click – RouterLink
2903
+ // handles navigation via Router.navigateByUrl() but only calls
2904
+ // preventDefault() for native <a> elements.
2905
+ this.preventNativeNavigation();
2906
+ // Keep href in sync after client-side navigations (RouterLink only
2907
+ // does this for native <a> elements).
2908
+ const sub = this.router.events.subscribe((event) => {
2909
+ if (event instanceof NavigationEnd)
2910
+ this.updateHref();
2911
+ });
2912
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
2913
+ }
2764
2914
  }
2765
2915
  ngOnChanges(changes) {
2766
2916
  // Implementation added by @ProxyInputs decorator
@@ -3790,24 +3940,74 @@ let GdsLinkComponent = class GdsLinkComponent {
3790
3940
  this.zone = inject(NgZone);
3791
3941
  this.cdr = inject(ChangeDetectorRef);
3792
3942
  this.renderer = inject(Renderer2);
3943
+ this.router = inject(Router);
3944
+ this.locationStrategy = inject(LocationStrategy);
3945
+ this.destroyRef = inject(DestroyRef);
3793
3946
  this.routerLink = inject(RouterLink, { optional: true, self: true });
3794
3947
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
3795
3948
  /** Fired when the link is clicked. */
3796
3949
  this.click = new EventEmitter();
3797
3950
  this.cdr.detach();
3951
+ if (this.routerLink) {
3952
+ // Prevent the browser from following the href on click – RouterLink
3953
+ // handles navigation via Router.navigateByUrl() but only calls
3954
+ // preventDefault() for native <a> elements.
3955
+ this.preventNativeNavigation();
3956
+ // Keep href in sync after client-side navigations (RouterLink only
3957
+ // does this for native <a> elements).
3958
+ const sub = this.router.events.subscribe((event) => {
3959
+ if (event instanceof NavigationEnd)
3960
+ this.updateHref();
3961
+ });
3962
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
3963
+ }
3798
3964
  }
3799
3965
  /**
3800
- * Updates the href attribute from RouterLink
3966
+ * Prevent the browser from following the href when RouterLink handles
3967
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
3968
+ * but only calls preventDefault() for native <a> tags. For custom
3969
+ * elements we must do it ourselves, respecting modifier-key and
3970
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
3971
+ * still open a new tab.
3972
+ * @internal
3973
+ */
3974
+ preventNativeNavigation() {
3975
+ // Use capture phase so this runs before Angular's RouterLink host listener.
3976
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
3977
+ if (!this.routerLink?.urlTree)
3978
+ return;
3979
+ // When modifier keys are pressed or target is not _self, stop
3980
+ // RouterLink from navigating (it skips these checks for non-anchor
3981
+ // elements) and let the browser handle the click natively (new tab etc.)
3982
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
3983
+ event.stopImmediatePropagation();
3984
+ return;
3985
+ }
3986
+ const target = this.elementRef.nativeElement.getAttribute('target');
3987
+ if (target && target !== '_self') {
3988
+ event.stopImmediatePropagation();
3989
+ return;
3990
+ }
3991
+ // Normal left-click: let RouterLink handle navigation via
3992
+ // Router.navigateByUrl(), but prevent the browser from also
3993
+ // following the shadow DOM anchor's href.
3994
+ event.preventDefault();
3995
+ }, true);
3996
+ }
3997
+ /**
3998
+ * Updates the href attribute from RouterLink using only public Angular APIs.
3801
3999
  * @internal
3802
4000
  */
3803
4001
  updateHref() {
3804
4002
  if (!this.routerLink)
3805
4003
  return;
3806
- // Trick RouterLink into thinking we are an anchor element
3807
- this.routerLink.isAnchorElement = true;
3808
- this.routerLink.updateHref();
3809
- // Set the href attribute on our element
3810
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
4004
+ const urlTree = this.routerLink.urlTree;
4005
+ const href = urlTree
4006
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
4007
+ : null;
4008
+ if (href) {
4009
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
4010
+ }
3811
4011
  }
3812
4012
  ngOnInit() {
3813
4013
  // Define the custom element
@@ -4102,26 +4302,76 @@ let GdsMenuButtonComponent = class GdsMenuButtonComponent {
4102
4302
  this.zone = inject(NgZone);
4103
4303
  this.cdr = inject(ChangeDetectorRef);
4104
4304
  this.renderer = inject(Renderer2);
4305
+ this.router = inject(Router);
4306
+ this.locationStrategy = inject(LocationStrategy);
4307
+ this.destroyRef = inject(DestroyRef);
4105
4308
  this.routerLink = inject(RouterLink, { optional: true, self: true });
4106
4309
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
4107
4310
  /** Fired when the button is clicked. */
4108
4311
  this.click = new EventEmitter();
4109
4312
  this.cdr.detach();
4313
+ if (this.routerLink) {
4314
+ // Prevent the browser from following the href on click – RouterLink
4315
+ // handles navigation via Router.navigateByUrl() but only calls
4316
+ // preventDefault() for native <a> elements.
4317
+ this.preventNativeNavigation();
4318
+ // Keep href in sync after client-side navigations (RouterLink only
4319
+ // does this for native <a> elements).
4320
+ const sub = this.router.events.subscribe((event) => {
4321
+ if (event instanceof NavigationEnd)
4322
+ this.updateHref();
4323
+ });
4324
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
4325
+ }
4110
4326
  // Subscribe to router link active changes
4111
4327
  this.routerLinkActive?.isActiveChange.subscribe(() => this.setActive());
4112
4328
  }
4113
4329
  /**
4114
- * Updates the href attribute from RouterLink
4330
+ * Prevent the browser from following the href when RouterLink handles
4331
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
4332
+ * but only calls preventDefault() for native <a> tags. For custom
4333
+ * elements we must do it ourselves, respecting modifier-key and
4334
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
4335
+ * still open a new tab.
4336
+ * @internal
4337
+ */
4338
+ preventNativeNavigation() {
4339
+ // Use capture phase so this runs before Angular's RouterLink host listener.
4340
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
4341
+ if (!this.routerLink?.urlTree)
4342
+ return;
4343
+ // When modifier keys are pressed or target is not _self, stop
4344
+ // RouterLink from navigating (it skips these checks for non-anchor
4345
+ // elements) and let the browser handle the click natively (new tab etc.)
4346
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
4347
+ event.stopImmediatePropagation();
4348
+ return;
4349
+ }
4350
+ const target = this.elementRef.nativeElement.getAttribute('target');
4351
+ if (target && target !== '_self') {
4352
+ event.stopImmediatePropagation();
4353
+ return;
4354
+ }
4355
+ // Normal left-click: let RouterLink handle navigation via
4356
+ // Router.navigateByUrl(), but prevent the browser from also
4357
+ // following the shadow DOM anchor's href.
4358
+ event.preventDefault();
4359
+ }, true);
4360
+ }
4361
+ /**
4362
+ * Updates the href attribute from RouterLink using only public Angular APIs.
4115
4363
  * @internal
4116
4364
  */
4117
4365
  updateHref() {
4118
4366
  if (!this.routerLink)
4119
4367
  return;
4120
- // Trick RouterLink into thinking we are an anchor element
4121
- this.routerLink.isAnchorElement = true;
4122
- this.routerLink.updateHref();
4123
- // Set the href attribute on our element
4124
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
4368
+ const urlTree = this.routerLink.urlTree;
4369
+ const href = urlTree
4370
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
4371
+ : null;
4372
+ if (href) {
4373
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
4374
+ }
4125
4375
  }
4126
4376
  /**
4127
4377
  * Updates the selected state based on RouterLinkActive
@@ -5785,22 +6035,72 @@ let GdsCardPattern01Component = class GdsCardPattern01Component {
5785
6035
  this.zone = inject(NgZone);
5786
6036
  this.cdr = inject(ChangeDetectorRef);
5787
6037
  this.renderer = inject(Renderer2);
6038
+ this.router = inject(Router);
6039
+ this.locationStrategy = inject(LocationStrategy);
6040
+ this.destroyRef = inject(DestroyRef);
5788
6041
  this.routerLink = inject(RouterLink, { optional: true, self: true });
5789
6042
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
5790
6043
  this.cdr.detach();
6044
+ if (this.routerLink) {
6045
+ // Prevent the browser from following the href on click – RouterLink
6046
+ // handles navigation via Router.navigateByUrl() but only calls
6047
+ // preventDefault() for native <a> elements.
6048
+ this.preventNativeNavigation();
6049
+ // Keep href in sync after client-side navigations (RouterLink only
6050
+ // does this for native <a> elements).
6051
+ const sub = this.router.events.subscribe((event) => {
6052
+ if (event instanceof NavigationEnd)
6053
+ this.updateHref();
6054
+ });
6055
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
6056
+ }
5791
6057
  }
5792
6058
  /**
5793
- * Updates the href attribute from RouterLink
6059
+ * Prevent the browser from following the href when RouterLink handles
6060
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
6061
+ * but only calls preventDefault() for native <a> tags. For custom
6062
+ * elements we must do it ourselves, respecting modifier-key and
6063
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
6064
+ * still open a new tab.
6065
+ * @internal
6066
+ */
6067
+ preventNativeNavigation() {
6068
+ // Use capture phase so this runs before Angular's RouterLink host listener.
6069
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
6070
+ if (!this.routerLink?.urlTree)
6071
+ return;
6072
+ // When modifier keys are pressed or target is not _self, stop
6073
+ // RouterLink from navigating (it skips these checks for non-anchor
6074
+ // elements) and let the browser handle the click natively (new tab etc.)
6075
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
6076
+ event.stopImmediatePropagation();
6077
+ return;
6078
+ }
6079
+ const target = this.elementRef.nativeElement.getAttribute('target');
6080
+ if (target && target !== '_self') {
6081
+ event.stopImmediatePropagation();
6082
+ return;
6083
+ }
6084
+ // Normal left-click: let RouterLink handle navigation via
6085
+ // Router.navigateByUrl(), but prevent the browser from also
6086
+ // following the shadow DOM anchor's href.
6087
+ event.preventDefault();
6088
+ }, true);
6089
+ }
6090
+ /**
6091
+ * Updates the href attribute from RouterLink using only public Angular APIs.
5794
6092
  * @internal
5795
6093
  */
5796
6094
  updateHref() {
5797
6095
  if (!this.routerLink)
5798
6096
  return;
5799
- // Trick RouterLink into thinking we are an anchor element
5800
- this.routerLink.isAnchorElement = true;
5801
- this.routerLink.updateHref();
5802
- // Set the href attribute on our element
5803
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
6097
+ const urlTree = this.routerLink.urlTree;
6098
+ const href = urlTree
6099
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
6100
+ : null;
6101
+ if (href) {
6102
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
6103
+ }
5804
6104
  }
5805
6105
  ngOnInit() {
5806
6106
  // Define the custom element
@@ -5938,22 +6238,72 @@ let GdsBreadcrumbComponent = class GdsBreadcrumbComponent {
5938
6238
  this.zone = inject(NgZone);
5939
6239
  this.cdr = inject(ChangeDetectorRef);
5940
6240
  this.renderer = inject(Renderer2);
6241
+ this.router = inject(Router);
6242
+ this.locationStrategy = inject(LocationStrategy);
6243
+ this.destroyRef = inject(DestroyRef);
5941
6244
  this.routerLink = inject(RouterLink, { optional: true, self: true });
5942
6245
  this.routerLinkActive = inject(RouterLinkActive, { optional: true, self: true });
5943
6246
  this.cdr.detach();
6247
+ if (this.routerLink) {
6248
+ // Prevent the browser from following the href on click – RouterLink
6249
+ // handles navigation via Router.navigateByUrl() but only calls
6250
+ // preventDefault() for native <a> elements.
6251
+ this.preventNativeNavigation();
6252
+ // Keep href in sync after client-side navigations (RouterLink only
6253
+ // does this for native <a> elements).
6254
+ const sub = this.router.events.subscribe((event) => {
6255
+ if (event instanceof NavigationEnd)
6256
+ this.updateHref();
6257
+ });
6258
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
6259
+ }
5944
6260
  }
5945
6261
  /**
5946
- * Updates the href attribute from RouterLink
6262
+ * Prevent the browser from following the href when RouterLink handles
6263
+ * navigation. RouterLink calls Router.navigateByUrl() for all elements,
6264
+ * but only calls preventDefault() for native <a> tags. For custom
6265
+ * elements we must do it ourselves, respecting modifier-key and
6266
+ * target-attribute semantics so that ctrl-click / cmd-click / target=_blank
6267
+ * still open a new tab.
6268
+ * @internal
6269
+ */
6270
+ preventNativeNavigation() {
6271
+ // Use capture phase so this runs before Angular's RouterLink host listener.
6272
+ this.elementRef.nativeElement.addEventListener('click', (event) => {
6273
+ if (!this.routerLink?.urlTree)
6274
+ return;
6275
+ // When modifier keys are pressed or target is not _self, stop
6276
+ // RouterLink from navigating (it skips these checks for non-anchor
6277
+ // elements) and let the browser handle the click natively (new tab etc.)
6278
+ if (event.button !== 0 || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
6279
+ event.stopImmediatePropagation();
6280
+ return;
6281
+ }
6282
+ const target = this.elementRef.nativeElement.getAttribute('target');
6283
+ if (target && target !== '_self') {
6284
+ event.stopImmediatePropagation();
6285
+ return;
6286
+ }
6287
+ // Normal left-click: let RouterLink handle navigation via
6288
+ // Router.navigateByUrl(), but prevent the browser from also
6289
+ // following the shadow DOM anchor's href.
6290
+ event.preventDefault();
6291
+ }, true);
6292
+ }
6293
+ /**
6294
+ * Updates the href attribute from RouterLink using only public Angular APIs.
5947
6295
  * @internal
5948
6296
  */
5949
6297
  updateHref() {
5950
6298
  if (!this.routerLink)
5951
6299
  return;
5952
- // Trick RouterLink into thinking we are an anchor element
5953
- this.routerLink.isAnchorElement = true;
5954
- this.routerLink.updateHref();
5955
- // Set the href attribute on our element
5956
- this.renderer.setAttribute(this.elementRef.nativeElement, 'href', this.routerLink.href || '');
6300
+ const urlTree = this.routerLink.urlTree;
6301
+ const href = urlTree
6302
+ ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(urlTree))
6303
+ : null;
6304
+ if (href) {
6305
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'href', href);
6306
+ }
5957
6307
  }
5958
6308
  ngOnInit() {
5959
6309
  // Define the custom element