Skip to content

Commit fa310a2

Browse files
committed
feat: chore: upgrade to angular v21
BREAKING CHANGES: - Angular 21.2.0 (all @angular/* packages) - Angular CDK 21.2.0 (flat package structure with exports map) - TypeScript 5.9.3 - zone.js 0.16.1 - angular-eslint 21.2.0 - ng-packagr 21.2.0 Key changes: - tsconfig: moduleResolution changed from 'node' to 'bundler', module from 'esnext' to 'es2022' (required for CDK 21 flat package format) - EventEmitter no longer extends RxJS Subject: modal-container uses Subject for internal _animationStateChanged, snack-bar wraps onMicrotaskEmpty with from(), tabs stores Subscription objects for proper cleanup - Replace detectChanges() with markForCheck() in lifecycle hooks of pagination, system-header, and dropdown-menu components - Remove unused ChangeDetectorRef from button component - file-input: private to protected for _isDragOver (typeCheckHostBindings) - modal-ref: typed KeyboardEvent for CDK 21 overlay keydown events - Add provideZoneChangeDetection() to test modules (Angular 21 TestBed uses zoneless CD internally, requiring explicit zone CD for zone-based component tests) - Add provideZoneChangeDetection to storybook AppModule - Add .npmrc with legacy-peer-deps=true (Storybook 9 peer dep conflict) fix(radio): correct ViewChild and ContentChildren decorators in radio button group The radio button group component had incorrect decorator syntax that caused 'Cannot read properties of undefined (reading children)' errors in Storybook and potentially in production apps. Issues fixed: - staticContainer was using malformed @ContentChildren with read: ViewChild() instead of proper @ViewChild decorator - _radios QueryList was missing @ContentChildren decorator entirely - Added null safety check in setAriaDescribedByToDescription() to handle cases where staticContainer might not be initialized yet The fixes ensure that: - staticContainer properly references the #container template element - _radios properly queries all BaoRadioButtonComponent children - No runtime errors occur during component initialization feat(storybook): upgrade from v9 to v10 Storybook v10, unlike v9, natively supports Angular 21 (peer dep range >=18.0.0 <22.0.0). This eliminates the need for npm overrides that were forcing Angular peer dependency resolution for @storybook/angular. Packages upgraded: - storybook: ^9.1.16 → ^10.2.15 - @storybook/angular: ^9.1.16 → ^10.2.15 - @storybook/addon-docs: ^9.1.16 → ^10.2.15 - @storybook/addon-links: ^9.1.16 → ^10.2.15 - @storybook/addon-a11y: ^9.1.16 → ^10.2.15 - eslint-plugin-storybook: ^0.11.5 → ^10.2.15 Configuration changes: - Removed npm overrides section from package.json (no longer needed) - Removed zone.js from Storybook polyfills (Angular 21 uses zoneless CD) - Removed provideZoneChangeDetection from app.module.ts (not needed) fix: package-lock.json + lint Signed-off-by: Francis Chabot <francis.chabot@montreal.ca>
1 parent 986c478 commit fa310a2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2836
-2935
lines changed

package-lock.json

Lines changed: 2476 additions & 2647 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-ui",
3-
"version": "20.0.0",
3+
"version": "21.0.0",
44
"engines": {
55
"node": ">=20"
66
},
@@ -27,42 +27,42 @@
2727
},
2828
"private": true,
2929
"dependencies": {
30-
"@angular/animations": "~20.3.17",
31-
"@angular/common": "~20.3.17",
32-
"@angular/compiler": "~20.3.17",
33-
"@angular/core": "~20.3.17",
34-
"@angular/forms": "~20.3.17",
35-
"@angular/platform-browser": "~20.3.17",
36-
"@angular/platform-browser-dynamic": "~20.3.17",
37-
"@angular/router": "~20.3.17",
30+
"@angular/animations": "~21.2.0",
31+
"@angular/common": "~21.2.0",
32+
"@angular/compiler": "~21.2.0",
33+
"@angular/core": "~21.2.0",
34+
"@angular/forms": "~21.2.0",
35+
"@angular/platform-browser": "~21.2.0",
36+
"@angular/platform-browser-dynamic": "~21.2.0",
37+
"@angular/router": "~21.2.0",
3838
"@villedemontreal/hochelaga": "^5.5.0",
3939
"rxjs": "~7.4.0",
4040
"tslib": "^2.7.0",
41-
"zone.js": "~0.15.1"
41+
"zone.js": "~0.16.1"
4242
},
4343
"devDependencies": {
44-
"@angular-devkit/build-angular": "^20.3.18",
45-
"@angular-eslint/builder": "^20.7.0",
46-
"@angular-eslint/eslint-plugin": "^20.7.0",
47-
"@angular-eslint/eslint-plugin-template": "^20.7.0",
48-
"@angular-eslint/schematics": "^20.7.0",
49-
"@angular-eslint/template-parser": "^20.7.0",
50-
"@angular/cdk": "^20.2.14",
51-
"@angular/cli": "~20.3.18",
52-
"@angular/compiler-cli": "~20.3.17",
53-
"@angular/elements": "^20.3.17",
44+
"@angular-devkit/build-angular": "^21.2.0",
45+
"@angular-eslint/builder": "^21.2.0",
46+
"@angular-eslint/eslint-plugin": "^21.2.0",
47+
"@angular-eslint/eslint-plugin-template": "^21.2.0",
48+
"@angular-eslint/schematics": "^21.2.0",
49+
"@angular-eslint/template-parser": "^21.2.0",
50+
"@angular/cdk": "^21.2.0",
51+
"@angular/cli": "~21.2.0",
52+
"@angular/compiler-cli": "~21.2.0",
53+
"@angular/elements": "^21.2.0",
5454
"@babel/core": "^7.20.12",
5555
"@babel/preset-typescript": "^7.18.6",
5656
"@commitlint/cli": "^17.4.2",
5757
"@compodoc/compodoc": "^1.1.21",
58-
"@storybook/addon-a11y": "^9.1.16",
59-
"@storybook/addon-docs": "^9.1.16",
60-
"@storybook/addon-links": "^9.1.16",
61-
"@storybook/angular": "^9.1.16",
58+
"@storybook/addon-a11y": "^10.2.15",
59+
"@storybook/addon-docs": "^10.2.15",
60+
"@storybook/addon-links": "^10.2.15",
61+
"@storybook/angular": "^10.2.15",
6262
"@types/jasmine": "^4.3.1",
6363
"@types/node": "^18.13.0",
64-
"@typescript-eslint/eslint-plugin": "8.33.1",
65-
"@typescript-eslint/parser": "8.33.1",
64+
"@typescript-eslint/eslint-plugin": "8.56.1",
65+
"@typescript-eslint/parser": "8.56.1",
6666
"@webcomponents/custom-elements": "^1.5.1",
6767
"babel-loader": "^9.1.2",
6868
"chromatic": "9.0.0",
@@ -71,7 +71,7 @@
7171
"eslint": "^8.56.0",
7272
"eslint-config-prettier": "^10.1.5",
7373
"eslint-plugin-header": "^3.1.1",
74-
"eslint-plugin-storybook": "^0.11.5",
74+
"eslint-plugin-storybook": "^10.2.15",
7575
"husky": "^8.0.3",
7676
"jasmine-core": "^4.5.0",
7777
"karma": "^6.4.1",
@@ -80,13 +80,13 @@
8080
"karma-jasmine": "^5.1.0",
8181
"karma-jasmine-html-reporter": "^2.0.0",
8282
"karma-viewport": "1.0.9",
83-
"ng-packagr": "^20.3.2",
83+
"ng-packagr": "^21.2.0",
8484
"prettier": "3.5.3",
8585
"react": "^18.2.0",
8686
"react-dom": "^18.2.0",
8787
"scss-bundle": "^3.1.2",
88-
"storybook": "^9.1.16",
89-
"typescript": "~5.8.3",
88+
"storybook": "^10.2.15",
89+
"typescript": "~5.9.3",
9090
"wait-on": "^7.0.1"
9191
},
9292
"workspaces": [

projects/angular-ui/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "@villedemontreal/angular-ui",
3-
"version": "20.0.0",
3+
"version": "21.0.0",
44
"dependencies": {
55
"tslib": "^2.7.0"
66
},
77
"peerDependencies": {
8-
"@angular/cdk": ">=20.0.0 <21.0.0",
9-
"@angular/common": ">=20.0.0 <21.0.0",
10-
"@angular/core": ">=20.0.0 <21.0.0",
11-
"@angular/forms": ">=20.0.0 <21.0.0"
8+
"@angular/cdk": ">=21.0.0 <22.0.0",
9+
"@angular/common": ">=21.0.0 <22.0.0",
10+
"@angular/core": ">=21.0.0 <22.0.0",
11+
"@angular/forms": ">=21.0.0 <22.0.0"
1212
}
1313
}

projects/angular-ui/src/lib/alert/alert.component.html

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
<div class="bao-alert-content-container">
33
<ng-content></ng-content>
44
</div>
5-
<button
6-
bao-button
7-
*ngIf="dismissible"
8-
type="utility"
9-
level="tertiary"
10-
data-dismiss="alert"
11-
role="button"
12-
[attr.aria-label]="dismissibleButtonAriaLabel"
13-
(click)="onDismissClicked()"
14-
>
15-
<bao-icon svgIcon="icon-x"></bao-icon>
16-
</button>
5+
@if (dismissible) {
6+
<button
7+
bao-button
8+
type="utility"
9+
level="tertiary"
10+
data-dismiss="alert"
11+
[attr.aria-label]="dismissibleButtonAriaLabel"
12+
(click)="onDismissClicked()"
13+
(keypress)="onDismissClicked()"
14+
>
15+
<bao-icon svgIcon="icon-x"></bao-icon>
16+
</button>
17+
}

projects/angular-ui/src/lib/avatar/avatar.component.spec.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* See LICENSE file in the project root for full license information.
55
*/
66

7-
import { DebugElement } from '@angular/core';
7+
import { DebugElement, provideZoneChangeDetection } from '@angular/core';
88
import { ComponentFixture, TestBed } from '@angular/core/testing';
99
import { By } from '@angular/platform-browser';
1010

@@ -27,7 +27,8 @@ describe('BaoAvatarComponent', () => {
2727
BaoAvatarComponent,
2828
BaoAvatarContent,
2929
TestAvatarIconHostComponent
30-
]
30+
],
31+
providers: [provideZoneChangeDetection()]
3132
}).compileComponents();
3233
});
3334

@@ -62,7 +63,8 @@ describe('BaoAvatarComponent', () => {
6263
BaoAvatarComponent,
6364
BaoAvatarContent,
6465
TestAvatarTextHostComponent
65-
]
66+
],
67+
providers: [provideZoneChangeDetection()]
6668
});
6769
return TestBed.compileComponents();
6870
});
@@ -114,7 +116,8 @@ describe('BaoAvatarComponent', () => {
114116
BaoAvatarComponent,
115117
BaoAvatarContent,
116118
TestAvatarImageHostComponent
117-
]
119+
],
120+
providers: [provideZoneChangeDetection()]
118121
}).compileComponents();
119122
});
120123

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
<bao-icon
2-
*ngIf="loading && !rightIcon"
3-
class="loading-spinner"
4-
svgIcon="icon-spinner"
5-
[title]="loadingSpinnerAriaLabel"
6-
></bao-icon>
1+
@if (loading && !rightIcon) {
2+
<bao-icon
3+
class="loading-spinner"
4+
svgIcon="icon-spinner"
5+
[title]="loadingSpinnerAriaLabel"
6+
></bao-icon>
7+
}
78
<ng-content></ng-content>
8-
<bao-icon
9-
*ngIf="loading && rightIcon"
10-
class="loading-spinner loading-spinner-right"
11-
svgIcon="icon-spinner"
12-
[title]="loadingSpinnerAriaLabel"
13-
></bao-icon>
9+
@if (loading && rightIcon) {
10+
<bao-icon
11+
class="loading-spinner loading-spinner-right"
12+
svgIcon="icon-spinner"
13+
[title]="loadingSpinnerAriaLabel"
14+
></bao-icon>
15+
}

projects/angular-ui/src/lib/button/button.component.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* See LICENSE file in the project root for full license information.
55
*/
66
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
7-
import { DebugElement } from '@angular/core';
7+
import { DebugElement, provideZoneChangeDetection } from '@angular/core';
88
import { By } from '@angular/platform-browser';
99
import { BaoButtonComponent } from './index';
1010
import {
@@ -25,7 +25,8 @@ describe('BaoButtonComponent', () => {
2525
BaoButtonComponent,
2626
TestButtonHostComponent,
2727
BaoIconComponent
28-
]
28+
],
29+
providers: [provideZoneChangeDetection()]
2930
});
3031

3132
return TestBed.compileComponents();
@@ -280,7 +281,8 @@ describe('BaoButtonComponent', () => {
280281
BaoButtonComponent,
281282
TestButtonWithIconHostComponent,
282283
BaoIconComponent
283-
]
284+
],
285+
providers: [provideZoneChangeDetection()]
284286
});
285287

286288
return TestBed.compileComponents();

projects/angular-ui/src/lib/button/button.component.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import {
77
AfterContentInit,
88
ChangeDetectionStrategy,
9-
ChangeDetectorRef,
109
Component,
1110
ElementRef,
1211
Input,
@@ -86,10 +85,7 @@ export class BaoButtonComponent implements AfterContentInit {
8685
*/
8786
public rightIcon = false;
8887

89-
constructor(
90-
private elementRef: ElementRef<HTMLElement>,
91-
private cdr: ChangeDetectorRef
92-
) {}
88+
constructor(private elementRef: ElementRef<HTMLElement>) {}
9389

9490
get nativeElement(): HTMLElement {
9591
return this.elementRef.nativeElement;
@@ -105,6 +101,5 @@ export class BaoButtonComponent implements AfterContentInit {
105101
!(c as HTMLElement).classList.contains(LOADING_SPINNER_CLASS)
106102
);
107103
this.rightIcon = iconIdex > textIndex;
108-
this.cdr.detectChanges();
109104
}
110105
}

projects/angular-ui/src/lib/common-components/label-text/labelText.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Component, Input, ViewEncapsulation } from '@angular/core';
99
standalone: false,
1010
selector: 'bao-label, [bao-label]',
1111
encapsulation: ViewEncapsulation.None,
12-
template: '<ng-content></ng-content><span *ngIf="required">&nbsp;*</span>',
12+
template: '<ng-content></ng-content>@if (required) {<span>&nbsp;*</span>}',
1313
styleUrls: ['./labelText.component.scss'],
1414
host: { class: 'bao-label' }
1515
})

projects/angular-ui/src/lib/dropdown-menu/dropdown-menu.component.spec.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { OverlayModule } from '@angular/cdk/overlay';
8-
import { DebugElement } from '@angular/core';
8+
import { DebugElement, provideZoneChangeDetection } from '@angular/core';
99
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
1010
import { By } from '@angular/platform-browser';
1111
import {
@@ -44,7 +44,8 @@ describe('BaoDropdownMenuComponent', () => {
4444
TestDropdownMenuHostComponent,
4545
BaoIconComponent
4646
],
47-
imports: [OverlayModule]
47+
imports: [OverlayModule],
48+
providers: [provideZoneChangeDetection()]
4849
});
4950
return TestBed.compileComponents();
5051
}));
@@ -128,7 +129,8 @@ describe('BaoDropdownMenuComponent', () => {
128129
TestButtonMenuHostComponent,
129130
BaoIconComponent
130131
],
131-
imports: [OverlayModule]
132+
imports: [OverlayModule],
133+
providers: [provideZoneChangeDetection()]
132134
});
133135
return TestBed.compileComponents();
134136
}));
@@ -170,7 +172,8 @@ describe('BaoDropdownMenuComponent', () => {
170172
BaoCheckboxComponent,
171173
BaoRadioButtonComponent
172174
],
173-
imports: [OverlayModule]
175+
imports: [OverlayModule],
176+
providers: [provideZoneChangeDetection()]
174177
});
175178
return TestBed.compileComponents();
176179
}));

0 commit comments

Comments
 (0)