Skip to content

Commit 8710842

Browse files
authored
Merge branch 'angular:main' into slider-fix-pt2
2 parents 7856471 + 9db29c9 commit 8710842

File tree

11 files changed

+132
-57
lines changed

11 files changed

+132
-57
lines changed

.circleci/bazel.rc

Lines changed: 0 additions & 19 deletions
This file was deleted.

.circleci/config.yml

Lines changed: 0 additions & 16 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
<a name="19.0.0-rc.2"></a>
2+
# 19.0.0-rc.2 "barium-binoculars" (2024-11-13)
3+
### cdk
4+
| Commit | Type | Description |
5+
| -- | -- | -- |
6+
| [8141e45a8](https://github.com/angular/components/commit/8141e45a892a9f5bb6643a3ce606845d9a302251) | fix | **listbox:** make tabindex zoneless compatible ([#29970](https://github.com/angular/components/pull/29970)) |
7+
| [a78f47551](https://github.com/angular/components/commit/a78f475510b49aa6ddd9052ef6fdfc1e0c0c15d4) | fix | **table:** set explicit role on all cells ([#29987](https://github.com/angular/components/pull/29987)) |
8+
| [fda61f565](https://github.com/angular/components/commit/fda61f565093cb9f8de5b3339de01ac92cc6926f) | fix | **testing:** allow use of `plaintext-only` for `contenteditable` ([#29999](https://github.com/angular/components/pull/29999)) |
9+
| [f6066c23f](https://github.com/angular/components/commit/f6066c23feee5a23d870104860f1e18bb9f3db83) | fix | **tree:** warn if mixed node types are used within the same tree |
10+
### material
11+
| Commit | Type | Description |
12+
| -- | -- | -- |
13+
| [de6c20686](https://github.com/angular/components/commit/de6c20686c441ff39b872b69c725c3c46b1f3a93) | fix | **bottom-sheet:** add `height` `minHeight` `maxHeight` to config ([#29794](https://github.com/angular/components/pull/29794)) |
14+
| [d0d59b784](https://github.com/angular/components/commit/d0d59b784abdde79bebaf9cff6d316c952228fa7) | fix | **core:** change ng-add to use mat.theme ([#29990](https://github.com/angular/components/pull/29990)) |
15+
| [b7f509c5b](https://github.com/angular/components/commit/b7f509c5bf943c2b3bc11f72183b90545f6571a7) | fix | **core:** incorrect validation in get-theme-color ([#29994](https://github.com/angular/components/pull/29994)) |
16+
| [d55ec612c](https://github.com/angular/components/commit/d55ec612cc66b42971c9da2677bc6e54017dd271) | fix | **core:** update prebuilt themes to use mat.theme ([#29989](https://github.com/angular/components/pull/29989)) |
17+
| [482009bac](https://github.com/angular/components/commit/482009bac173bd4453d20dfec283e3cab23d2af0) | fix | **schematics:** add explicit system variable prefix schematic ([#29980](https://github.com/angular/components/pull/29980)) |
18+
| [75631fb0b](https://github.com/angular/components/commit/75631fb0b305891ea22e422f8bd9d9d991c1d6ef) | fix | **sidenav:** prevent the content from jumping when hydrated ([#29991](https://github.com/angular/components/pull/29991)) |
19+
| [bb66db738](https://github.com/angular/components/commit/bb66db73867df02f55feed8fca4daf7cb9d8dc83) | fix | **snack-bar:** prevent override of snack bar action button color ([#27511](https://github.com/angular/components/pull/27511)) |
20+
### youtube-player
21+
| Commit | Type | Description |
22+
| -- | -- | -- |
23+
| [09da06b42](https://github.com/angular/components/commit/09da06b42e2aad668bbdeb9adecdad401b0d8df6) | fix | ready event not emitting |
24+
| [288598750](https://github.com/angular/components/commit/2885987500f9005fbdf981c700b516096896868b) | fix | startSeconds not applied when using placeholder |
25+
26+
<!-- CHANGELOG SPLIT MARKER -->
27+
28+
<a name="18.2.13"></a>
29+
# 18.2.13 "strontium-sauce" (2024-11-13)
30+
### cdk
31+
| Commit | Type | Description |
32+
| -- | -- | -- |
33+
| [1ea3ba383](https://github.com/angular/components/commit/1ea3ba38337d8b59518c073c95e0ca64e6fd5db3) | fix | **listbox:** make tabindex zoneless compatible ([#29970](https://github.com/angular/components/pull/29970)) |
34+
| [890036064](https://github.com/angular/components/commit/890036064a825ddc44068d4b6fc71edfd7ddb43c) | fix | **table:** set explicit role on all cells ([#29987](https://github.com/angular/components/pull/29987)) |
35+
| [3c7de8400](https://github.com/angular/components/commit/3c7de8400b60558b1c39d13278d7a325ade2be1a) | fix | **testing:** allow use of `plaintext-only` for `contenteditable` ([#29999](https://github.com/angular/components/pull/29999)) |
36+
### material
37+
| Commit | Type | Description |
38+
| -- | -- | -- |
39+
| [c643f04ef](https://github.com/angular/components/commit/c643f04ef042eb16606c8b490854db79e413a34d) | fix | **core:** incorrect validation in get-theme-color ([#29994](https://github.com/angular/components/pull/29994)) |
40+
| [aed9094f9](https://github.com/angular/components/commit/aed9094f9c33bbb2134ae9551f8c5d4db4b24356) | fix | **snack-bar:** prevent override of snack bar action button color ([#27511](https://github.com/angular/components/pull/27511)) |
41+
42+
<!-- CHANGELOG SPLIT MARKER -->
43+
144
<a name="18.2.12"></a>
245
# 18.2.12 "galaxite-galaxy" (2024-11-06)
346
### material

src/cdk/scrolling/virtual-scroll-viewport.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ cdk-virtual-scroll-viewport {
3939
overflow: auto;
4040
will-change: scroll-position;
4141
contain: strict;
42-
-webkit-overflow-scrolling: touch;
4342
}
4443

4544
// Wrapper element for the rendered content. This element will be transformed to push the rendered

src/cdk/testing/selenium-webdriver/selenium-web-driver-element.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,11 @@ export class SeleniumWebDriverElement implements TestElement {
161161
async setContenteditableValue(value: string): Promise<void> {
162162
const contenteditableAttr = await this.getAttribute('contenteditable');
163163

164-
if (contenteditableAttr !== '' && contenteditableAttr !== 'true') {
164+
if (
165+
contenteditableAttr !== '' &&
166+
contenteditableAttr !== 'true' &&
167+
contenteditableAttr !== 'plaintext-only'
168+
) {
165169
throw new Error('setContenteditableValue can only be called on a `contenteditable` element.');
166170
}
167171

src/cdk/testing/testbed/unit-test-element.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,11 @@ export class UnitTestElement implements TestElement {
196196
async setContenteditableValue(value: string): Promise<void> {
197197
const contenteditableAttr = await this.getAttribute('contenteditable');
198198

199-
if (contenteditableAttr !== '' && contenteditableAttr !== 'true') {
199+
if (
200+
contenteditableAttr !== '' &&
201+
contenteditableAttr !== 'true' &&
202+
contenteditableAttr !== 'plaintext-only'
203+
) {
200204
throw new Error('setContenteditableValue can only be called on a `contenteditable` element.');
201205
}
202206

src/material/core/style/_menu-common.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ $icon-margin: 16px !default;
1818
min-width: $overlay-min-width;
1919
max-width: $overlay-max-width;
2020
overflow: auto;
21-
-webkit-overflow-scrolling: touch; // for momentum scroll on mobile
2221
}
2322

2423
@mixin item-base() {

src/material/form-field/form-field.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {AbstractControlDirective} from '@angular/forms';
3636
import {ThemePalette} from '@angular/material/core';
3737
import {_IdGenerator} from '@angular/cdk/a11y';
3838
import {Subject, Subscription, merge} from 'rxjs';
39-
import {takeUntil} from 'rxjs/operators';
39+
import {map, pairwise, takeUntil, filter, startWith} from 'rxjs/operators';
4040
import {MAT_ERROR, MatError} from './directives/error';
4141
import {
4242
FLOATING_LABEL_PARENT,
@@ -328,6 +328,7 @@ export class MatFormField
328328
private _previousControl: MatFormFieldControl<unknown> | null = null;
329329
private _stateChanges: Subscription | undefined;
330330
private _valueChanges: Subscription | undefined;
331+
private _describedByChanges: Subscription | undefined;
331332

332333
private _injector = inject(Injector);
333334

@@ -377,6 +378,7 @@ export class MatFormField
377378
ngOnDestroy() {
378379
this._stateChanges?.unsubscribe();
379380
this._valueChanges?.unsubscribe();
381+
this._describedByChanges?.unsubscribe();
380382
this._destroyed.next();
381383
this._destroyed.complete();
382384
}
@@ -426,10 +428,22 @@ export class MatFormField
426428
this._stateChanges?.unsubscribe();
427429
this._stateChanges = control.stateChanges.subscribe(() => {
428430
this._updateFocusState();
429-
this._syncDescribedByIds();
430431
this._changeDetectorRef.markForCheck();
431432
});
432433

434+
// Updating the `aria-describedby` touches the DOM. Only do it if it actually needs to change.
435+
this._describedByChanges?.unsubscribe();
436+
this._describedByChanges = control.stateChanges
437+
.pipe(
438+
startWith([undefined, undefined] as const),
439+
map(() => [control.errorState, control.userAriaDescribedBy] as const),
440+
pairwise(),
441+
filter(([[prevErrorState, prevDescribedBy], [currentErrorState, currentDescribedBy]]) => {
442+
return prevErrorState !== currentErrorState || prevDescribedBy !== currentDescribedBy;
443+
}),
444+
)
445+
.subscribe(() => this._syncDescribedByIds());
446+
433447
this._valueChanges?.unsubscribe();
434448

435449
// Run change detection if the value changes.

src/material/input/input.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,18 @@ describe('MatMdcInput without forms', () => {
643643
expect(input.getAttribute('aria-describedby')).toBe('start end');
644644
}));
645645

646+
it('should preserve aria-describedby set directly in the DOM', fakeAsync(() => {
647+
const fixture = createComponent(MatInputHintLabel2TestController);
648+
const input = fixture.nativeElement.querySelector('input');
649+
input.setAttribute('aria-describedby', 'custom');
650+
fixture.componentInstance.label = 'label';
651+
fixture.changeDetectorRef.markForCheck();
652+
fixture.detectChanges();
653+
const hint = fixture.nativeElement.querySelector('.mat-mdc-form-field-hint');
654+
655+
expect(input.getAttribute('aria-describedby')).toBe(`${hint.getAttribute('id')} custom`);
656+
}));
657+
646658
it('should set a class on the hint element based on its alignment', fakeAsync(() => {
647659
const fixture = createComponent(MatInputMultipleHintTestController);
648660

src/material/input/input.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ export class MatInput
111111
private _webkitBlinkWheelListenerAttached = false;
112112
private _config = inject(MAT_INPUT_CONFIG, {optional: true});
113113

114+
/** `aria-describedby` IDs assigned by the form field. */
115+
private _formFieldDescribedBy: string[] | undefined;
116+
114117
/** Whether the component is being rendered on the server. */
115118
readonly _isServer: boolean;
116119

@@ -551,10 +554,29 @@ export class MatInput
551554
* @docs-private
552555
*/
553556
setDescribedByIds(ids: string[]) {
554-
if (ids.length) {
555-
this._elementRef.nativeElement.setAttribute('aria-describedby', ids.join(' '));
557+
const element = this._elementRef.nativeElement;
558+
const existingDescribedBy = element.getAttribute('aria-describedby');
559+
let toAssign: string[];
560+
561+
// In some cases there might be some `aria-describedby` IDs that were assigned directly,
562+
// like by the `AriaDescriber` (see #30011). Attempt to preserve them by taking the previous
563+
// attribute value and filtering out the IDs that came from the previous `setDescribedByIds`
564+
// call. Note the `|| ids` here allows us to avoid duplicating IDs on the first render.
565+
if (existingDescribedBy) {
566+
const exclude = this._formFieldDescribedBy || ids;
567+
toAssign = ids.concat(
568+
existingDescribedBy.split(' ').filter(id => id && !exclude.includes(id)),
569+
);
570+
} else {
571+
toAssign = ids;
572+
}
573+
574+
this._formFieldDescribedBy = ids;
575+
576+
if (toAssign.length) {
577+
element.setAttribute('aria-describedby', toAssign.join(' '));
556578
} else {
557-
this._elementRef.nativeElement.removeAttribute('aria-describedby');
579+
element.removeAttribute('aria-describedby');
558580
}
559581
}
560582

0 commit comments

Comments
 (0)