Skip to content

Commit 1f77a5b

Browse files
authored
Merge branch 'optimize-everything' into optimize-list-base
2 parents 9fbd828 + 8c95d6f commit 1f77a5b

File tree

137 files changed

+3443
-944
lines changed

Some content is hidden

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

137 files changed

+3443
-944
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
/src/e2e-app/mdc-radio/** @mmalerba
237237
/src/e2e-app/mdc-slide-toggle/** @crisbeto
238238
/src/e2e-app/mdc-tabs/** @crisbeto
239+
/src/e2e-app/mdc-table/** @andrewseguin
239240
/src/e2e-app/menu/** @crisbeto
240241
/src/e2e-app/progress-bar/** @jelbourn @crisbeto
241242
/src/e2e-app/progress-spinner/** @jelbourn @crisbeto

goldens/size-test.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
cdk/drag-drop/all-directives: 153594
2-
cdk/drag-drop/basic: 151498
1+
cdk/drag-drop/all-directives: 154096
2+
cdk/drag-drop/basic: 151353
33
material-experimental/mdc-chips/basic: 147607
44
material-experimental/mdc-form-field/advanced: 220897
55
material-experimental/mdc-form-field/basic: 220060

goldens/ts-circular-deps.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
"src/cdk-experimental/dialog/dialog-config.ts",
44
"src/cdk-experimental/dialog/dialog-container.ts"
55
],
6-
[
7-
"src/cdk-experimental/popover-edit/edit-event-dispatcher.ts",
8-
"src/cdk-experimental/popover-edit/edit-ref.ts"
9-
],
106
[
117
"src/cdk/drag-drop/directives/drag.ts",
128
"src/cdk/drag-drop/directives/drop-list.ts"
@@ -28,10 +24,6 @@
2824
"src/cdk/scrolling/scroll-dispatcher.ts",
2925
"src/cdk/scrolling/scrollable.ts"
3026
],
31-
[
32-
"src/cdk/scrolling/virtual-for-of.ts",
33-
"src/cdk/scrolling/virtual-scroll-viewport.ts"
34-
],
3527
[
3628
"src/cdk/scrolling/virtual-scroll-strategy.ts",
3729
"src/cdk/scrolling/virtual-scroll-viewport.ts"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"@types/youtube": "^0.0.38",
6060
"@webcomponents/custom-elements": "^1.1.0",
6161
"core-js": "^2.6.9",
62-
"material-components-web": "7.0.0-canary.7461aad68.0",
62+
"material-components-web": "8.0.0-canary.d850de590.0",
6363
"rxjs": "^6.5.3",
6464
"rxjs-tslint-rules": "^4.33.1",
6565
"systemjs": "0.19.43",

src/cdk-experimental/popover-edit/edit-event-dispatcher.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222

2323
import {CELL_SELECTOR, ROW_SELECTOR} from './constants';
2424
import {closest} from './polyfill';
25-
import {EditRef} from './edit-ref';
2625

2726
/** The delay applied to mouse events before hiding or showing hover content. */
2827
const MOUSE_EVENT_DELAY_MS = 40;
@@ -42,11 +41,15 @@ export const enum HoverContentState {
4241
ON,
4342
}
4443

44+
// Note: this class is generic, rather than referencing EditRef directly, in order to avoid
45+
// circular imports. If we were to reference it here, importing the registry into the
46+
// class that is registering itself will introduce a circular import.
47+
4548
/**
4649
* Service for sharing delegated events and state for triggering table edits.
4750
*/
4851
@Injectable()
49-
export class EditEventDispatcher {
52+
export class EditEventDispatcher<R> {
5053
/** A subject that indicates which table cell is currently editing (unless it is disabled). */
5154
readonly editing = new Subject<Element|null>();
5255

@@ -70,10 +73,10 @@ export class EditEventDispatcher {
7073
readonly disabledCells = new WeakMap<Element, boolean>();
7174

7275
/** The EditRef for the currently active edit lens (if any). */
73-
get editRef(): EditRef<any>|null {
76+
get editRef(): R|null {
7477
return this._editRef;
7578
}
76-
private _editRef: EditRef<any>|null = null;
79+
private _editRef: R|null = null;
7780

7881
// Optimization: Precompute common pipeable operators used per row/cell.
7982
private readonly _distinctUntilChanged =
@@ -181,12 +184,12 @@ export class EditEventDispatcher {
181184
}
182185

183186
/** Sets the currently active EditRef. */
184-
setActiveEditRef(ref: EditRef<any>) {
187+
setActiveEditRef(ref: R) {
185188
this._editRef = ref;
186189
}
187190

188191
/** Unsets the currently active EditRef, if the specified editRef is active. */
189-
unsetActiveEditRef(ref: EditRef<any>) {
192+
unsetActiveEditRef(ref: R) {
190193
if (this._editRef !== ref) {
191194
return;
192195
}

src/cdk-experimental/popover-edit/edit-ref.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class EditRef<FormValue> implements OnDestroy {
3232

3333
constructor(
3434
@Self() private readonly _form: ControlContainer,
35-
private readonly _editEventDispatcher: EditEventDispatcher,
35+
private readonly _editEventDispatcher: EditEventDispatcher<EditRef<FormValue>>,
3636
private readonly _ngZone: NgZone) {
3737
this._editEventDispatcher.setActiveEditRef(this);
3838
}

src/cdk-experimental/popover-edit/edit-services.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {ScrollDispatcher, ViewportRuler} from '@angular/cdk/scrolling';
1515
import {EditEventDispatcher} from './edit-event-dispatcher';
1616
import {FocusDispatcher} from './focus-dispatcher';
1717
import {PopoverEditPositionStrategyFactory} from './popover-edit-position-strategy-factory';
18+
import {EditRef} from './edit-ref';
1819

1920
/**
2021
* Optimization
@@ -26,7 +27,8 @@ import {PopoverEditPositionStrategyFactory} from './popover-edit-position-strate
2627
export class EditServices {
2728
constructor(
2829
readonly directionality: Directionality,
29-
readonly editEventDispatcher: EditEventDispatcher, readonly focusDispatcher: FocusDispatcher,
30+
readonly editEventDispatcher: EditEventDispatcher<EditRef<unknown>>,
31+
readonly focusDispatcher: FocusDispatcher,
3032
readonly focusTrapFactory: FocusTrapFactory, readonly ngZone: NgZone,
3133
readonly overlay: Overlay, readonly positionFactory: PopoverEditPositionStrategyFactory,
3234
readonly scrollDispatcher: ScrollDispatcher, readonly viewportRuler: ViewportRuler) {}

src/cdk-experimental/popover-edit/table-directives.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
FocusEscapeNotifierFactory
4242
} from './focus-escape-notifier';
4343
import {closest} from './polyfill';
44+
import {EditRef} from './edit-ref';
4445

4546
/**
4647
* Describes the number of columns before and after the originating cell that the
@@ -69,7 +70,7 @@ export class CdkEditable implements AfterViewInit, OnDestroy {
6970

7071
constructor(
7172
protected readonly elementRef: ElementRef,
72-
protected readonly editEventDispatcher: EditEventDispatcher,
73+
protected readonly editEventDispatcher: EditEventDispatcher<EditRef<unknown>>,
7374
protected readonly focusDispatcher: FocusDispatcher, protected readonly ngZone: NgZone) {}
7475

7576
ngAfterViewInit(): void {
@@ -487,7 +488,7 @@ export class CdkRowHoverContent implements AfterViewInit, OnDestroy {
487488
export class CdkEditOpen {
488489
constructor(
489490
protected readonly elementRef: ElementRef<HTMLElement>,
490-
protected readonly editEventDispatcher: EditEventDispatcher) {
491+
protected readonly editEventDispatcher: EditEventDispatcher<EditRef<unknown>>) {
491492

492493
const nativeElement = elementRef.nativeElement;
493494

src/cdk/a11y/key-manager/list-key-manager.spec.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, UP_ARROW} from '@angular/cdk/keycodes';
1+
import {DOWN_ARROW, END, HOME, LEFT_ARROW, RIGHT_ARROW, TAB, UP_ARROW} from '@angular/cdk/keycodes';
22
import {createKeyboardEvent} from '@angular/cdk/testing/private';
33
import {QueryList} from '@angular/core';
44
import {fakeAsync, tick} from '@angular/core/testing';
@@ -51,6 +51,8 @@ describe('Key managers', () => {
5151
leftArrow: KeyboardEvent,
5252
rightArrow: KeyboardEvent,
5353
tab: KeyboardEvent,
54+
home: KeyboardEvent,
55+
end: KeyboardEvent,
5456
unsupported: KeyboardEvent
5557
};
5658

@@ -62,6 +64,8 @@ describe('Key managers', () => {
6264
leftArrow: createKeyboardEvent('keydown', LEFT_ARROW),
6365
rightArrow: createKeyboardEvent('keydown', RIGHT_ARROW),
6466
tab: createKeyboardEvent('keydown', TAB),
67+
home: createKeyboardEvent('keydown', HOME),
68+
end: createKeyboardEvent('keydown', END),
6569
unsupported: createKeyboardEvent('keydown', 192) // corresponds to the tilde character (~)
6670
};
6771
});
@@ -207,6 +211,30 @@ describe('Key managers', () => {
207211
expect(fakeKeyEvents.downArrow.defaultPrevented).toBe(false);
208212
});
209213

214+
describe('withHomeAndEnd', () => {
215+
beforeEach(() => {
216+
keyManager.withHomeAndEnd();
217+
});
218+
219+
it('should focus the first item when Home is pressed', () => {
220+
keyManager.setActiveItem(1);
221+
expect(keyManager.activeItemIndex).toBe(1);
222+
223+
keyManager.onKeydown(fakeKeyEvents.home);
224+
225+
expect(keyManager.activeItemIndex).toBe(0);
226+
});
227+
228+
it('should focus the last item when End is pressed', () => {
229+
keyManager.setActiveItem(0);
230+
expect(keyManager.activeItemIndex).toBe(0);
231+
232+
keyManager.onKeydown(fakeKeyEvents.end);
233+
234+
expect(keyManager.activeItemIndex).toBe(itemList.items.length - 1);
235+
});
236+
});
237+
210238
describe('with `vertical` direction', function(this: KeyEventTestContext) {
211239
beforeEach(() => {
212240
keyManager.withVerticalOrientation();

src/cdk/a11y/key-manager/list-key-manager.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
ZERO,
2020
NINE,
2121
hasModifierKey,
22+
HOME,
23+
END,
2224
} from '@angular/cdk/keycodes';
2325
import {debounceTime, filter, map, tap} from 'rxjs/operators';
2426

@@ -47,6 +49,7 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
4749
private _vertical = true;
4850
private _horizontal: 'ltr' | 'rtl' | null;
4951
private _allowedModifierKeys: ListKeyManagerModifierKey[] = [];
52+
private _homeAndEnd = false;
5053

5154
/**
5255
* Predicate function that can be used to check whether an item should be skipped
@@ -174,6 +177,15 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
174177
return this;
175178
}
176179

180+
/**
181+
* Configures the key manager to focus the first and last items
182+
* respectively when the Home key and End Key are pressed.
183+
*/
184+
withHomeAndEnd(): this {
185+
this._homeAndEnd = true;
186+
return this;
187+
}
188+
177189
/**
178190
* Sets the active item to the item at the index specified.
179191
* @param index The index of the item to be set as active.
@@ -244,6 +256,22 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
244256
return;
245257
}
246258

259+
case HOME:
260+
if (this._homeAndEnd && isModifierAllowed) {
261+
this.setFirstItemActive();
262+
break;
263+
} else {
264+
return;
265+
}
266+
267+
case END:
268+
if (this._homeAndEnd && isModifierAllowed) {
269+
this.setLastItemActive();
270+
break;
271+
} else {
272+
return;
273+
}
274+
247275
default:
248276
if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
249277
// Attempt to use the `event.key` which also maps it to the user's keyboard language,

src/cdk/drag-drop/directives/drag.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
191191
@Optional() @Inject(CDK_DRAG_CONFIG) config: DragDropConfig,
192192
@Optional() private _dir: Directionality, dragDrop: DragDrop,
193193
private _changeDetectorRef: ChangeDetectorRef,
194-
@Optional() @Self() private _selfHandle?: CdkDragHandle) {
194+
@Optional() @Self() @Inject(CDK_DRAG_HANDLE) private _selfHandle?: CdkDragHandle) {
195195
this._dragRef = dragDrop.createDrag(element, {
196196
dragStartThreshold: config && config.dragStartThreshold != null ?
197197
config.dragStartThreshold : 5,

src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
6767

6868
/** Click event listener that will be attached to the body propagate phase. */
6969
private _clickListener = (event: MouseEvent) => {
70+
// Get the target through the `composedPath` if possible to account for shadow DOM.
71+
const target = event.composedPath ? event.composedPath()[0] : event.target;
7072
const overlays = this._attachedOverlays;
7173

7274
// Dispatch the mouse event to the top overlay which has subscribers to its mouse events.
@@ -81,7 +83,7 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
8183

8284
const config = overlayRef.getConfig();
8385
const excludeElements = [...config.excludeFromOutsideClick!, overlayRef.overlayElement];
84-
const isInsideClick: boolean = excludeElements.some(e => e.contains(event.target as Node));
86+
const isInsideClick: boolean = excludeElements.some(e => e.contains(target));
8587

8688
// If it is inside click just break - we should do nothing
8789
// If it is outside click dispatch the mouse event, and proceed with the next overlay

src/cdk/platform/features/scrolling.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export function getRtlScrollAxisType(): RtlScrollAxisType {
4848
const scrollContainer = document.createElement('div');
4949
const containerStyle = scrollContainer.style;
5050
scrollContainer.dir = 'rtl';
51-
containerStyle.height = '1px';
5251
containerStyle.width = '1px';
5352
containerStyle.overflow = 'auto';
5453
containerStyle.visibility = 'hidden';

src/cdk/schematics/ng-update/devkit-file-system.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,26 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {normalize, Path, relative} from '@angular-devkit/core';
9+
import {normalize, Path, PathIsDirectoryException} from '@angular-devkit/core';
1010
import {Tree, UpdateRecorder} from '@angular-devkit/schematics';
11+
import {DirectoryEntry, FileSystem} from '../update-tool/file-system';
1112
import * as path from 'path';
12-
import {FileSystem} from '../update-tool/file-system';
1313

1414
/**
1515
* File system that leverages the virtual tree from the CLI devkit. This file
1616
* system is commonly used by `ng update` migrations that run as part of the
1717
* Angular CLI.
1818
*/
19-
export class DevkitFileSystem extends FileSystem<Path> {
19+
export class DevkitFileSystem extends FileSystem {
2020
private _updateRecorderCache = new Map<string, UpdateRecorder>();
21-
private _workspaceFsPath: Path;
2221

23-
constructor(private _tree: Tree, workspaceFsPath: string) {
22+
constructor(private _tree: Tree) {
2423
super();
25-
this._workspaceFsPath = normalize(workspaceFsPath);
2624
}
2725

2826
resolve(...segments: string[]): Path {
2927
// Note: We use `posix.resolve` as the devkit paths are using posix separators.
30-
const resolvedPath = normalize(path.posix.resolve(...segments.map(normalize)));
31-
// If the resolved path points to the workspace root, then this is an absolute disk
32-
// path and we need to compute a devkit tree relative path.
33-
if (resolvedPath.startsWith(this._workspaceFsPath)) {
34-
return relative(this._workspaceFsPath, resolvedPath);
35-
}
36-
// Otherwise we know that the path is absolute (due to the resolve), and that it
37-
// refers to an absolute devkit tree path (like `/angular.json`). We keep those
38-
// unmodified as they are already resolved workspace paths.
39-
return resolvedPath;
28+
return normalize(path.posix.resolve('/', ...segments.map(normalize)));
4029
}
4130

4231
edit(filePath: Path) {
@@ -53,8 +42,18 @@ export class DevkitFileSystem extends FileSystem<Path> {
5342
this._updateRecorderCache.clear();
5443
}
5544

56-
exists(filePath: Path) {
57-
return this._tree.exists(filePath);
45+
exists(fileOrDirPath: Path) {
46+
// The devkit tree does not expose an API for checking whether a given
47+
// directory exists. It throws a specific error though if a directory
48+
// is being read as a file. We use that to check if a directory exists.
49+
try {
50+
return this._tree.get(fileOrDirPath) !== null;
51+
} catch (e) {
52+
if (e instanceof PathIsDirectoryException) {
53+
return true;
54+
}
55+
}
56+
return false;
5857
}
5958

6059
overwrite(filePath: Path, content: string) {
@@ -73,4 +72,9 @@ export class DevkitFileSystem extends FileSystem<Path> {
7372
const buffer = this._tree.read(filePath);
7473
return buffer !== null ? buffer.toString() : null;
7574
}
75+
76+
readDirectory(dirPath: Path): DirectoryEntry {
77+
const {subdirs: directories, subfiles: files} = this._tree.getDir(dirPath);
78+
return {directories, files};
79+
}
7680
}

0 commit comments

Comments
 (0)