diff --git a/.stylelintrc.json b/.stylelintrc.json index a162e2394e36..cd68ab6a477d 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -87,7 +87,9 @@ "selector-max-id": 0, "no-missing-end-of-source-newline": true, "no-eol-whitespace": true, - "max-line-length": 100, + "max-line-length": [100, { + "ignorePattern": "/https?://.*/" + }], "linebreaks": "unix", "selector-class-pattern": ["^_?(mat-|cdk-|example-|demo-|ng-|mdc-|map-)", { "resolveNestedSelectors": true diff --git a/src/components-examples/material/list/list-sections/list-sections-example.html b/src/components-examples/material/list/list-sections/list-sections-example.html index ecb32bb2e8e6..935f0e77178a 100644 --- a/src/components-examples/material/list/list-sections/list-sections-example.html +++ b/src/components-examples/material/list/list-sections/list-sections-example.html @@ -1,15 +1,15 @@ -

Folders

+
Folders
folder -

{{folder.name}}

-

{{folder.updated | date}}

+
{{folder.name}}
+
{{folder.updated | date}}
-

Notes

+
Notes
note -

{{note.name}}

-

{{note.updated | date}}

+
{{note.name}}
+
{{note.updated | date}}
diff --git a/src/dev-app/list/list-demo.html b/src/dev-app/list/list-demo.html index 83918a690db0..b238517189eb 100644 --- a/src/dev-app/list/list-demo.html +++ b/src/dev-app/list/list-demo.html @@ -8,7 +8,7 @@

mat-list demo

Normal lists

-

Items

+
Items
{{item}} @@ -16,28 +16,28 @@

Items

-

{{contact.name}}

-

extra line

-

{{contact.headline}}

+
{{contact.name}}
+
extra line
+
{{contact.headline}}
-

Today

+
Today
Image of {{message.from}} -

{{message.from}}

-

+

{{message.from}}
+
{{message.subject}} -- {{message.message}} -

+
-

{{message.from}}

-

{{message.subject}}

-

{{message.message}}

+
{{message.from}}
+
{{message.subject}}
+
{{message.message}}
@@ -45,7 +45,7 @@

{{message.from}}

Dense lists

-

Items

+
Items
{{item}} @@ -53,18 +53,18 @@

Items

-

{{contact.name}}

-

{{contact.headline}}

+
{{contact.name}}
+
{{contact.headline}}
-

Today

+
Today
Image of {{message.from}} -

{{message.from}}

-

{{message.subject}}

-

{{message.message}}

+
{{message.from}}
+
{{message.subject}}
+
{{message.message}}
@@ -122,7 +122,7 @@

Selection list

[disabled]="selectionListDisabled" [disableRipple]="selectionListRippleDisabled" color="primary"> -

Groceries

+
Groceries
Bananas Oranges @@ -131,7 +131,7 @@

Groceries

-

Dogs

+
Dogs
@@ -170,7 +170,7 @@

Single Selection list

[(ngModel)]="favoriteOptions" [multiple]="false" color="primary"> -

Favorite Grocery

+
Favorite Grocery
Bananas Oranges diff --git a/src/dev-app/mdc-list/mdc-list-demo.html b/src/dev-app/mdc-list/mdc-list-demo.html index 80fe14661e23..83cbb5ed2020 100644 --- a/src/dev-app/mdc-list/mdc-list-demo.html +++ b/src/dev-app/mdc-list/mdc-list-demo.html @@ -8,7 +8,7 @@

mat-list demo

Normal lists

-

Items

+
Items
{{item}} @@ -16,28 +16,28 @@

Items

-

{{contact.name}}

-

extra line

-

{{contact.headline}}

+
{{contact.name}}
+
extra line
+
{{contact.headline}}
-

Today

+
Today
Image of {{message.from}} -

{{message.from}}

-

+

{{message.from}}
+
{{message.subject}} -- - {{message.message}} -

+ {{message.message}} +
-

{{message.from}}

-

{{message.subject}}

-

{{message.message}}

+
{{message.from}}
+
{{message.subject}}
+
{{message.message}}
@@ -45,7 +45,7 @@

{{message.from}}

Dense lists

-

Items

+
Items
{{item}} @@ -53,18 +53,18 @@

Items

-

{{contact.name}}

-

{{contact.headline}}

+
{{contact.name}}
+
{{contact.headline}}
-

Today

+
Today
Image of {{message.from}} -

{{message.from}}

-

{{message.subject}}

-

{{message.message}}

+
{{message.from}}
+
{{message.subject}}
+
{{message.message}}
@@ -90,7 +90,7 @@

Nav lists

folder {{ link.name }} - Description + Description diff --git a/src/material-experimental/mdc-list/list-base.ts b/src/material-experimental/mdc-list/list-base.ts index 1c42e8a22378..a233d777b733 100644 --- a/src/material-experimental/mdc-list/list-base.ts +++ b/src/material-experimental/mdc-list/list-base.ts @@ -6,6 +6,42 @@ * found in the LICENSE file at https://angular.io/license */ +import {AfterContentInit, ElementRef, NgZone, OnDestroy, QueryList} from '@angular/core'; +import {setLines} from '@angular/material/core'; +import {Subscription} from 'rxjs'; +import {startWith} from 'rxjs/operators'; + export class MatListBase {} -export class MatListItemBase {} +export class MatListItemBase implements AfterContentInit, OnDestroy { + lines: QueryList>; + + private _subscriptions = new Subscription(); + + constructor(protected _element: ElementRef, protected _ngZone: NgZone) {} + + ngAfterContentInit() { + this._monitorLines(); + } + + /** + * Subscribes to changes in `MatLine` content children and annotates them appropriately when they + * change. + */ + private _monitorLines() { + this._ngZone.runOutsideAngular(() => { + this._subscriptions.add(this.lines.changes.pipe(startWith(this.lines)) + .subscribe((lines: QueryList>) => { + lines.forEach((line: ElementRef, index: number) => { + line.nativeElement.classList.toggle('mdc-list-item__primary-text', index === 0); + line.nativeElement.classList.toggle('mdc-list-item__secondary-text', index !== 0); + }); + setLines(lines, this._element, 'mat-mdc'); + })); + }); + } + + ngOnDestroy() { + this._subscriptions.unsubscribe(); + } +} diff --git a/src/material-experimental/mdc-list/list-item.html b/src/material-experimental/mdc-list/list-item.html index 91b88fdf57fa..fbaeab2cecaa 100644 --- a/src/material-experimental/mdc-list/list-item.html +++ b/src/material-experimental/mdc-list/list-item.html @@ -1 +1,3 @@ + + diff --git a/src/material-experimental/mdc-list/list.scss b/src/material-experimental/mdc-list/list.scss index efba495ceb33..e08b039b73e7 100644 --- a/src/material-experimental/mdc-list/list.scss +++ b/src/material-experimental/mdc-list/list.scss @@ -1,4 +1,5 @@ @import '@material/list/mixins.import'; +@import '@material/list/variables.import'; @import '../mdc-helpers/mdc-helpers'; @include mdc-list-without-ripple($query: $mat-base-styles-query); @@ -8,3 +9,75 @@ .mat-mdc-list-base { display: block; } + +// .mdc-list-item__primary-text adds its own margin settings, so only reset if it doesn't have that +// class +.mat-mdc-list-base .mdc-list-item__text > :not(.mdc-list-item__primary-text), +.mat-mdc-list-base .mdc-list-item__text > :not(.mdc-list-item__primary-text) { + margin: 0; + + // Fixes the gap between the 2nd & 3rd lines. + &.mdc-list-item__secondary-text { + margin-top: -3px; + } +} + + +// MDC does have 2-line support, but it's a per-list setting, whereas ours applies to individual +// items. Therefore, we need to add our own styles. +.mat-mdc-2-line { + height: 72px; + + .mdc-list-item__text { + align-self: flex-start; + } +} + +// MDC does not support more than 2 lines, so we need to add our own styles. +.mat-mdc-3-line { + height: 88px; + + .mdc-list-item__text { + align-self: flex-start; + } +} + +// MDC supports avatars, but it's a per-list setting, whereas ours applies to individual +// items. Therefore, we need to add our own styles. +.mat-mdc-list-avatar { + // Styles here come from `$mdc-list-graphic-size_`: + // https://github.com/material-components/material-components-web/blob/3ca8c4c45a3d2a654ef3cb8fc7525bcde37badf0/packages/mdc-list/_mixins.scss#L538 + $size: 40px; + $margin-value: 72px - $mdc-list-side-padding - $size; + + margin-left: 0; + margin-right: $margin-value; + width: $size; + height: $size; + border-radius: 50%; + + // `.mdc-list-item` added for extra specificity to override MDC's built in styles. + [dir='rtl'] .mdc-list-item & { + margin-left: $margin-value; + margin-right: 0; + } +} + +// MDC doesn't have list dividers, so we use mat-divider and style appropriately. +.mat-mdc-list-item, +.mat-mdc-list-option { + .mat-divider-inset { + position: absolute; + left: 0; + right: 0; + bottom: 0; + } + + .mat-mdc-list-avatar ~ .mat-divider-inset { + margin-left: 72px; + + [dir='rtl'] & { + margin-right: 72px; + } + } +} diff --git a/src/material-experimental/mdc-list/list.ts b/src/material-experimental/mdc-list/list.ts index cc0d4c205cfb..343ca498420b 100644 --- a/src/material-experimental/mdc-list/list.ts +++ b/src/material-experimental/mdc-list/list.ts @@ -6,7 +6,17 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectionStrategy, Component, Directive, ViewEncapsulation} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ContentChildren, + Directive, + ElementRef, + NgZone, + QueryList, + ViewEncapsulation +} from '@angular/core'; +import {MatLine} from '@angular/material/core'; import {MatListBase, MatListItemBase} from './list-base'; /** @@ -15,7 +25,7 @@ import {MatListBase, MatListItemBase} from './list-base'; */ @Directive({ selector: '[mat-list-avatar], [matListAvatar]', - host: {'class': 'mat-mdc-list-avatar'} + host: {'class': 'mat-mdc-list-avatar mdc-list-item__graphic'} }) export class MatListAvatarCssMatStyler {} @@ -25,7 +35,7 @@ export class MatListAvatarCssMatStyler {} */ @Directive({ selector: '[mat-list-icon], [matListIcon]', - host: {'class': 'mat-mdc-list-icon'} + host: {'class': 'mat-mdc-list-icon mdc-list-item__graphic'} }) export class MatListIconCssMatStyler {} @@ -35,7 +45,9 @@ export class MatListIconCssMatStyler {} */ @Directive({ selector: '[mat-subheader], [matSubheader]', - host: {'class': 'mat-mdc-subheader'} + // TODO(mmalerba): MDC's subheader font looks identical to the list item font, figure out why and + // make a change in one of the repos to visually distinguish. + host: {'class': 'mat-mdc-subheader mdc-list-group__subheader'} }) export class MatListSubheaderCssMatStyler {} @@ -62,4 +74,11 @@ export class MatList extends MatListBase {} encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MatListItem extends MatListItemBase {} +export class MatListItem extends MatListItemBase { + @ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines: + QueryList>; + + constructor(element: ElementRef, ngZone: NgZone) { + super(element, ngZone); + } +} diff --git a/src/material-experimental/mdc-list/module.ts b/src/material-experimental/mdc-list/module.ts index dd26e817da30..081a23ba2cf6 100644 --- a/src/material-experimental/mdc-list/module.ts +++ b/src/material-experimental/mdc-list/module.ts @@ -7,6 +7,7 @@ */ import {NgModule} from '@angular/core'; +import {MatLineModule} from '@angular/material/core'; import {MatDividerModule} from '@angular/material/divider'; import {MatActionList} from './action-list'; import { @@ -20,6 +21,7 @@ import {MatNavList} from './nav-list'; import {MatListOption, MatSelectionList} from './selection-list'; @NgModule({ + imports: [MatLineModule], exports: [ MatList, MatActionList, @@ -31,6 +33,7 @@ import {MatListOption, MatSelectionList} from './selection-list'; MatListIconCssMatStyler, MatListSubheaderCssMatStyler, MatDividerModule, + MatLineModule, ], declarations: [ MatList, diff --git a/src/material-experimental/mdc-list/selection-list.ts b/src/material-experimental/mdc-list/selection-list.ts index ea725da19ce2..f42aa9384420 100644 --- a/src/material-experimental/mdc-list/selection-list.ts +++ b/src/material-experimental/mdc-list/selection-list.ts @@ -6,8 +6,18 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectionStrategy, Component, forwardRef, ViewEncapsulation} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ContentChildren, + ElementRef, + forwardRef, + NgZone, + QueryList, + ViewEncapsulation +} from '@angular/core'; import {NG_VALUE_ACCESSOR} from '@angular/forms'; +import {MatLine} from '@angular/material/core'; import {MatListBase, MatListItemBase} from './list-base'; const MAT_SELECTION_LIST_VALUE_ACCESSOR: any = { @@ -49,4 +59,11 @@ export class MatSelectionList extends MatListBase {} encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MatListOption extends MatListItemBase {} +export class MatListOption extends MatListItemBase { + @ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines: + QueryList>; + + constructor(element: ElementRef, ngZone: NgZone) { + super(element, ngZone); + } +} diff --git a/src/material/core/line/line.ts b/src/material/core/line/line.ts index 724a1dfe1226..33888dd858e2 100644 --- a/src/material/core/line/line.ts +++ b/src/material/core/line/line.ts @@ -31,18 +31,19 @@ export class MatLine {} * Helper that takes a query list of lines and sets the correct class on the host. * @docs-private */ -export function setLines(lines: QueryList, element: ElementRef) { +export function setLines(lines: QueryList, element: ElementRef, + prefix = 'mat') { // Note: doesn't need to unsubscribe, because `changes` // gets completed by Angular when the view is destroyed. lines.changes.pipe(startWith(lines)).subscribe(({length}) => { - setClass(element, 'mat-2-line', false); - setClass(element, 'mat-3-line', false); - setClass(element, 'mat-multi-line', false); + setClass(element, `${prefix}-2-line`, false); + setClass(element, `${prefix}-3-line`, false); + setClass(element, `${prefix}-multi-line`, false); if (length === 2 || length === 3) { - setClass(element, `mat-${length}-line`, true); + setClass(element, `${prefix}-${length}-line`, true); } else if (length > 3) { - setClass(element, `mat-multi-line`, true); + setClass(element, `${prefix}-multi-line`, true); } }); } diff --git a/tools/public_api_guard/material/core.d.ts b/tools/public_api_guard/material/core.d.ts index 28990691207f..61775aa88254 100644 --- a/tools/public_api_guard/material/core.d.ts +++ b/tools/public_api_guard/material/core.d.ts @@ -457,7 +457,7 @@ export declare type SanityChecks = boolean | GranularSanityChecks; export declare const JAN = 0, FEB = 1, MAR = 2, APR = 3, MAY = 4, JUN = 5, JUL = 6, AUG = 7, SEP = 8, OCT = 9, NOV = 10, DEC = 11; -export declare function setLines(lines: QueryList, element: ElementRef): void; +export declare function setLines(lines: QueryList, element: ElementRef, prefix?: string): void; export declare class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean;