Skip to content

Commit 9d2ac16

Browse files
authored
Merge branch 'angular:master' into align-attr-as-input-in-dialog-actions-#18479
2 parents 54d0a60 + 3de4ab8 commit 9d2ac16

File tree

65 files changed

+1742
-849
lines changed

Some content is hidden

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

65 files changed

+1742
-849
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ node_modules
3131
/.vs
3232
*.swo
3333
*.swp
34+
.vimrc
35+
.nvimrc
3436

3537
# misc
3638
.DS_Store

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License
22

3-
Copyright (c) 2021 Google LLC.
3+
Copyright (c) 2022 Google LLC.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

goldens/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
exports_files([
22
"size-test.yaml",
3+
"tsec-exemption.json",
34
])

goldens/tsec-exemption.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"ban-trustedtypes-createpolicy": [
3+
"../src/material/icon/trusted-types.ts"
4+
],
5+
"ban-element-innerhtml-assignments": [
6+
"../src/material/icon/icon-registry.ts"
7+
],
8+
"ban-element-setattribute": [
9+
"../src/cdk/a11y/aria-describer/aria-reference.ts",
10+
"../src/material-experimental/mdc-checkbox/checkbox.ts",
11+
"../src/material-experimental/mdc-list/interactive-list-base.ts",
12+
"../src/material-experimental/mdc-progress-spinner/progress-spinner.ts",
13+
"../src/material-experimental/mdc-slide-toggle/slide-toggle.ts",
14+
"../src/material/icon/icon-registry.ts",
15+
"../src/material/icon/icon.ts"
16+
]
17+
}

package.json

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"test": "node ./scripts/run-component-tests.js",
2323
"test-local": "yarn -s test --local",
2424
"test-firefox": "yarn -s test --firefox",
25+
"test-tsec": "yarn bazelisk test //... --build_tag_filters=tsec --test_tag_filters=tsec",
2526
"lint": "yarn -s tslint && yarn -s stylelint && yarn -s ownerslint && yarn -s ng-dev format changed --check",
2627
"e2e": "bazel test //src/... --build_tag_filters=e2e --test_tag_filters=e2e --build_tests_only",
2728
"deploy-dev-app": "node ./scripts/deploy-dev-app.js",
@@ -60,7 +61,7 @@
6061
"@types/google.maps": "^3.45.6",
6162
"@types/youtube": "^0.0.42",
6263
"core-js-bundle": "^3.8.2",
63-
"material-components-web": "14.0.0-canary.7d8ea4624.0",
64+
"material-components-web": "14.0.0-canary.c047f7c19.0",
6465
"rxjs": "^6.6.7",
6566
"rxjs-tslint-rules": "^4.33.1",
6667
"tslib": "^2.3.0",
@@ -92,53 +93,53 @@
9293
"@bazel/terser": "4.4.5",
9394
"@bazel/typescript": "4.4.5",
9495
"@firebase/app-types": "^0.6.1",
95-
"@material/animation": "14.0.0-canary.7d8ea4624.0",
96-
"@material/auto-init": "14.0.0-canary.7d8ea4624.0",
97-
"@material/banner": "14.0.0-canary.7d8ea4624.0",
98-
"@material/base": "14.0.0-canary.7d8ea4624.0",
99-
"@material/button": "14.0.0-canary.7d8ea4624.0",
100-
"@material/card": "14.0.0-canary.7d8ea4624.0",
101-
"@material/checkbox": "14.0.0-canary.7d8ea4624.0",
102-
"@material/chips": "14.0.0-canary.7d8ea4624.0",
103-
"@material/circular-progress": "14.0.0-canary.7d8ea4624.0",
104-
"@material/data-table": "14.0.0-canary.7d8ea4624.0",
105-
"@material/density": "14.0.0-canary.7d8ea4624.0",
106-
"@material/dialog": "14.0.0-canary.7d8ea4624.0",
107-
"@material/dom": "14.0.0-canary.7d8ea4624.0",
108-
"@material/drawer": "14.0.0-canary.7d8ea4624.0",
109-
"@material/elevation": "14.0.0-canary.7d8ea4624.0",
110-
"@material/fab": "14.0.0-canary.7d8ea4624.0",
111-
"@material/feature-targeting": "14.0.0-canary.7d8ea4624.0",
112-
"@material/floating-label": "14.0.0-canary.7d8ea4624.0",
113-
"@material/form-field": "14.0.0-canary.7d8ea4624.0",
114-
"@material/icon-button": "14.0.0-canary.7d8ea4624.0",
115-
"@material/image-list": "14.0.0-canary.7d8ea4624.0",
116-
"@material/layout-grid": "14.0.0-canary.7d8ea4624.0",
117-
"@material/line-ripple": "14.0.0-canary.7d8ea4624.0",
118-
"@material/linear-progress": "14.0.0-canary.7d8ea4624.0",
119-
"@material/list": "14.0.0-canary.7d8ea4624.0",
120-
"@material/menu": "14.0.0-canary.7d8ea4624.0",
121-
"@material/menu-surface": "14.0.0-canary.7d8ea4624.0",
122-
"@material/notched-outline": "14.0.0-canary.7d8ea4624.0",
123-
"@material/radio": "14.0.0-canary.7d8ea4624.0",
124-
"@material/ripple": "14.0.0-canary.7d8ea4624.0",
125-
"@material/rtl": "14.0.0-canary.7d8ea4624.0",
126-
"@material/segmented-button": "14.0.0-canary.7d8ea4624.0",
127-
"@material/select": "14.0.0-canary.7d8ea4624.0",
128-
"@material/shape": "14.0.0-canary.7d8ea4624.0",
129-
"@material/slider": "14.0.0-canary.7d8ea4624.0",
130-
"@material/snackbar": "14.0.0-canary.7d8ea4624.0",
131-
"@material/switch": "14.0.0-canary.7d8ea4624.0",
132-
"@material/tab": "14.0.0-canary.7d8ea4624.0",
133-
"@material/tab-bar": "14.0.0-canary.7d8ea4624.0",
134-
"@material/tab-indicator": "14.0.0-canary.7d8ea4624.0",
135-
"@material/tab-scroller": "14.0.0-canary.7d8ea4624.0",
136-
"@material/textfield": "14.0.0-canary.7d8ea4624.0",
137-
"@material/theme": "14.0.0-canary.7d8ea4624.0",
138-
"@material/tooltip": "14.0.0-canary.7d8ea4624.0",
139-
"@material/top-app-bar": "14.0.0-canary.7d8ea4624.0",
140-
"@material/touch-target": "14.0.0-canary.7d8ea4624.0",
141-
"@material/typography": "14.0.0-canary.7d8ea4624.0",
96+
"@material/animation": "14.0.0-canary.c047f7c19.0",
97+
"@material/auto-init": "14.0.0-canary.c047f7c19.0",
98+
"@material/banner": "14.0.0-canary.c047f7c19.0",
99+
"@material/base": "14.0.0-canary.c047f7c19.0",
100+
"@material/button": "14.0.0-canary.c047f7c19.0",
101+
"@material/card": "14.0.0-canary.c047f7c19.0",
102+
"@material/checkbox": "14.0.0-canary.c047f7c19.0",
103+
"@material/chips": "14.0.0-canary.c047f7c19.0",
104+
"@material/circular-progress": "14.0.0-canary.c047f7c19.0",
105+
"@material/data-table": "14.0.0-canary.c047f7c19.0",
106+
"@material/density": "14.0.0-canary.c047f7c19.0",
107+
"@material/dialog": "14.0.0-canary.c047f7c19.0",
108+
"@material/dom": "14.0.0-canary.c047f7c19.0",
109+
"@material/drawer": "14.0.0-canary.c047f7c19.0",
110+
"@material/elevation": "14.0.0-canary.c047f7c19.0",
111+
"@material/fab": "14.0.0-canary.c047f7c19.0",
112+
"@material/feature-targeting": "14.0.0-canary.c047f7c19.0",
113+
"@material/floating-label": "14.0.0-canary.c047f7c19.0",
114+
"@material/form-field": "14.0.0-canary.c047f7c19.0",
115+
"@material/icon-button": "14.0.0-canary.c047f7c19.0",
116+
"@material/image-list": "14.0.0-canary.c047f7c19.0",
117+
"@material/layout-grid": "14.0.0-canary.c047f7c19.0",
118+
"@material/line-ripple": "14.0.0-canary.c047f7c19.0",
119+
"@material/linear-progress": "14.0.0-canary.c047f7c19.0",
120+
"@material/list": "14.0.0-canary.c047f7c19.0",
121+
"@material/menu": "14.0.0-canary.c047f7c19.0",
122+
"@material/menu-surface": "14.0.0-canary.c047f7c19.0",
123+
"@material/notched-outline": "14.0.0-canary.c047f7c19.0",
124+
"@material/radio": "14.0.0-canary.c047f7c19.0",
125+
"@material/ripple": "14.0.0-canary.c047f7c19.0",
126+
"@material/rtl": "14.0.0-canary.c047f7c19.0",
127+
"@material/segmented-button": "14.0.0-canary.c047f7c19.0",
128+
"@material/select": "14.0.0-canary.c047f7c19.0",
129+
"@material/shape": "14.0.0-canary.c047f7c19.0",
130+
"@material/slider": "14.0.0-canary.c047f7c19.0",
131+
"@material/snackbar": "14.0.0-canary.c047f7c19.0",
132+
"@material/switch": "14.0.0-canary.c047f7c19.0",
133+
"@material/tab": "14.0.0-canary.c047f7c19.0",
134+
"@material/tab-bar": "14.0.0-canary.c047f7c19.0",
135+
"@material/tab-indicator": "14.0.0-canary.c047f7c19.0",
136+
"@material/tab-scroller": "14.0.0-canary.c047f7c19.0",
137+
"@material/textfield": "14.0.0-canary.c047f7c19.0",
138+
"@material/theme": "14.0.0-canary.c047f7c19.0",
139+
"@material/tooltip": "14.0.0-canary.c047f7c19.0",
140+
"@material/top-app-bar": "14.0.0-canary.c047f7c19.0",
141+
"@material/touch-target": "14.0.0-canary.c047f7c19.0",
142+
"@material/typography": "14.0.0-canary.c047f7c19.0",
142143
"@octokit/rest": "18.3.5",
143144
"@rollup/plugin-commonjs": "^21.0.0",
144145
"@rollup/plugin-node-resolve": "^13.0.5",
@@ -211,6 +212,7 @@
211212
"stylelint": "^14.0.1",
212213
"terser": "^5.9.0",
213214
"ts-node": "^10.2.1",
215+
"tsec": "0.2.1",
214216
"tsickle": "0.39.1",
215217
"tslint": "^6.1.3",
216218
"tsutils": "^3.21.0",

src/BUILD.bazel

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,12 @@ ts_library(
4949
name = "dev_mode_types",
5050
srcs = ["dev-mode-types.d.ts"],
5151
)
52+
53+
ts_config(
54+
name = "tsec_config",
55+
src = "tsconfig-tsec.json",
56+
deps = [
57+
":bazel-tsconfig-build.json",
58+
"//goldens:tsec-exemption.json",
59+
],
60+
)

src/cdk/a11y/focus-monitor/focus-monitor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class FocusMonitor implements OnDestroy {
134134
// Make a note of when the window regains focus, so we can
135135
// restore the origin info for the focused element.
136136
this._windowFocused = true;
137-
this._windowFocusTimeoutId = setTimeout(() => (this._windowFocused = false));
137+
this._windowFocusTimeoutId = window.setTimeout(() => (this._windowFocused = false));
138138
};
139139

140140
/** Used to reference correct document/window */

src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,46 @@ describe('FlexibleConnectedPositionStrategy', () => {
164164
originElement.remove();
165165
});
166166

167+
it('should calculate position with simulated zoom in Safari', () => {
168+
let containerElement = overlayContainer.getContainerElement();
169+
spyOn(containerElement, 'getBoundingClientRect').and.returnValue({
170+
top: -200,
171+
bottom: 900,
172+
left: -200,
173+
right: 100,
174+
width: 100,
175+
height: 100,
176+
} as DOMRect);
177+
178+
const originElement = createPositionedBlockElement();
179+
document.body.appendChild(originElement);
180+
181+
// Position the element so it would have enough space to fit.
182+
originElement.style.top = '200px';
183+
originElement.style.left = '70px';
184+
185+
attachOverlay({
186+
positionStrategy: overlay
187+
.position()
188+
.flexibleConnectedTo(originElement)
189+
.withFlexibleDimensions(false)
190+
.withPush(false)
191+
.withPositions([
192+
{
193+
originX: 'start',
194+
originY: 'top',
195+
overlayX: 'start',
196+
overlayY: 'top',
197+
},
198+
]),
199+
});
200+
201+
expect(getComputedStyle(overlayRef.overlayElement).left).toBe('270px');
202+
expect(getComputedStyle(overlayRef.overlayElement).top).toBe('400px');
203+
204+
originElement.remove();
205+
});
206+
167207
it('should clean up after itself when disposed', () => {
168208
const origin = document.createElement('div');
169209
const positionStrategy = overlay

src/cdk/overlay/position/flexible-connected-position-strategy.ts

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
8585
/** Cached viewport dimensions */
8686
private _viewportRect: Dimensions;
8787

88+
/** Cached container dimensions */
89+
private _containerRect: Dimensions;
90+
8891
/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
8992
private _viewportMargin = 0;
9093

@@ -213,16 +216,18 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
213216
this._resetOverlayElementStyles();
214217
this._resetBoundingBoxStyles();
215218

216-
// We need the bounding rects for the origin and the overlay to determine how to position
219+
// We need the bounding rects for the origin, the overlay and the container to determine how to position
217220
// the overlay relative to the origin.
218221
// We use the viewport rect to determine whether a position would go off-screen.
219222
this._viewportRect = this._getNarrowedViewportRect();
220223
this._originRect = this._getOriginRect();
221224
this._overlayRect = this._pane.getBoundingClientRect();
225+
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
222226

223227
const originRect = this._originRect;
224228
const overlayRect = this._overlayRect;
225229
const viewportRect = this._viewportRect;
230+
const containerRect = this._containerRect;
226231

227232
// Positions where the overlay will fit with flexible dimensions.
228233
const flexibleFits: FlexibleFit[] = [];
@@ -234,7 +239,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
234239
// If a good fit is found, it will be applied immediately.
235240
for (let pos of this._preferredPositions) {
236241
// Get the exact (x, y) coordinate for the point-of-origin on the origin element.
237-
let originPoint = this._getOriginPoint(originRect, pos);
242+
let originPoint = this._getOriginPoint(originRect, containerRect, pos);
238243

239244
// From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the
240245
// overlay in this position. We use the top-left corner for calculations and later translate
@@ -359,9 +364,10 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
359364
this._originRect = this._getOriginRect();
360365
this._overlayRect = this._pane.getBoundingClientRect();
361366
this._viewportRect = this._getNarrowedViewportRect();
367+
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
362368

363369
const lastPosition = this._lastPosition || this._preferredPositions[0];
364-
const originPoint = this._getOriginPoint(this._originRect, lastPosition);
370+
const originPoint = this._getOriginPoint(this._originRect, this._containerRect, lastPosition);
365371

366372
this._applyPosition(lastPosition, originPoint);
367373
}
@@ -479,7 +485,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
479485
/**
480486
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
481487
*/
482-
private _getOriginPoint(originRect: Dimensions, pos: ConnectedPosition): Point {
488+
private _getOriginPoint(
489+
originRect: Dimensions,
490+
containerRect: Dimensions,
491+
pos: ConnectedPosition,
492+
): Point {
483493
let x: number;
484494
if (pos.originX == 'center') {
485495
// Note: when centering we should always use the `left`
@@ -491,13 +501,28 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
491501
x = pos.originX == 'start' ? startX : endX;
492502
}
493503

504+
// When zooming in Safari the container rectangle contains negative values for the position
505+
// and we need to re-add them to the calculated coordinates.
506+
if (containerRect.left < 0) {
507+
x -= containerRect.left;
508+
}
509+
494510
let y: number;
495511
if (pos.originY == 'center') {
496512
y = originRect.top + originRect.height / 2;
497513
} else {
498514
y = pos.originY == 'top' ? originRect.top : originRect.bottom;
499515
}
500516

517+
// Normally the containerRect's top value would be zero, however when the overlay is attached to an input
518+
// (e.g. in an autocomplete), mobile browsers will shift everything in order to put the input in the middle
519+
// of the screen and to make space for the virtual keyboard. We need to account for this offset,
520+
// otherwise our positioning will be thrown off.
521+
// Additionally, when zooming in Safari this fixes the vertical position.
522+
if (containerRect.top < 0) {
523+
y -= containerRect.top;
524+
}
525+
501526
return {x, y};
502527
}
503528

@@ -580,7 +605,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
580605
/**
581606
* Whether the overlay can fit within the viewport when it may resize either its width or height.
582607
* @param fit How well the overlay fits in the viewport at some position.
583-
* @param point The (x, y) coordinates of the overlat at some position.
608+
* @param point The (x, y) coordinates of the overlay at some position.
584609
* @param viewport The geometry of the viewport.
585610
*/
586611
private _canFitWithFlexibleDimensions(fit: OverlayFit, point: Point, viewport: Dimensions) {
@@ -606,7 +631,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
606631
* right and bottom).
607632
*
608633
* @param start Starting point from which the overlay is pushed.
609-
* @param overlay Dimensions of the overlay.
634+
* @param rawOverlayRect Dimensions of the overlay.
610635
* @param scrollPosition Current viewport scroll position.
611636
* @returns The point at which to position the overlay after pushing. This is effectively a new
612637
* originPoint.
@@ -958,16 +983,6 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
958983
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
959984
}
960985

961-
let virtualKeyboardOffset = this._overlayContainer
962-
.getContainerElement()
963-
.getBoundingClientRect().top;
964-
965-
// Normally this would be zero, however when the overlay is attached to an input (e.g. in an
966-
// autocomplete), mobile browsers will shift everything in order to put the input in the middle
967-
// of the screen and to make space for the virtual keyboard. We need to account for this offset,
968-
// otherwise our positioning will be thrown off.
969-
overlayPoint.y -= virtualKeyboardOffset;
970-
971986
// We want to set either `top` or `bottom` based on whether the overlay wants to appear
972987
// above or below the origin and the direction in which the element will expand.
973988
if (position.overlayY === 'bottom') {
@@ -1183,7 +1198,7 @@ interface OverlayFit {
11831198
visibleArea: number;
11841199
}
11851200

1186-
/** Record of the measurments determining whether an overlay will fit in a specific position. */
1201+
/** Record of the measurements determining whether an overlay will fit in a specific position. */
11871202
interface FallbackPosition {
11881203
position: ConnectedPosition;
11891204
originPoint: Point;

src/cdk/schematics/ng-update/migrations/tilde-import-v13/tilde-import-migration.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ export class TildeImportMigration extends DevkitMigration<null> {
2121
if (extension === '.scss' || extension === '.css') {
2222
const content = stylesheet.content;
2323
const migratedContent = content.replace(
24-
/@(?:import|use) +['"]~@angular\/.*['"].*;?/g,
25-
match => {
26-
const index = match.indexOf('~@angular');
27-
return match.slice(0, index) + match.slice(index + 1);
24+
/@(?:import|use) +['"](~@angular\/.*)['"].*;?/g,
25+
(match, importPath) => {
26+
const index = match.indexOf(importPath);
27+
const newImportPath = importPath.replace(/^~|\.scss$/g, '');
28+
return match.slice(0, index) + newImportPath + match.slice(index + importPath.length);
2829
},
2930
);
3031

0 commit comments

Comments
 (0)