Skip to content

Commit

Permalink
Merge branch 'angular:master' into align-attr-as-input-in-dialog-acti…
Browse files Browse the repository at this point in the history
…ons-#18479
  • Loading branch information
PooSham committed Jan 9, 2022
2 parents 54d0a60 + 3de4ab8 commit 9d2ac16
Show file tree
Hide file tree
Showing 65 changed files with 1,742 additions and 849 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ node_modules
/.vs
*.swo
*.swp
.vimrc
.nvimrc

# misc
.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2021 Google LLC.
Copyright (c) 2022 Google LLC.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions goldens/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exports_files([
"size-test.yaml",
"tsec-exemption.json",
])
17 changes: 17 additions & 0 deletions goldens/tsec-exemption.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"ban-trustedtypes-createpolicy": [
"../src/material/icon/trusted-types.ts"
],
"ban-element-innerhtml-assignments": [
"../src/material/icon/icon-registry.ts"
],
"ban-element-setattribute": [
"../src/cdk/a11y/aria-describer/aria-reference.ts",
"../src/material-experimental/mdc-checkbox/checkbox.ts",
"../src/material-experimental/mdc-list/interactive-list-base.ts",
"../src/material-experimental/mdc-progress-spinner/progress-spinner.ts",
"../src/material-experimental/mdc-slide-toggle/slide-toggle.ts",
"../src/material/icon/icon-registry.ts",
"../src/material/icon/icon.ts"
]
}
98 changes: 50 additions & 48 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"test": "node ./scripts/run-component-tests.js",
"test-local": "yarn -s test --local",
"test-firefox": "yarn -s test --firefox",
"test-tsec": "yarn bazelisk test //... --build_tag_filters=tsec --test_tag_filters=tsec",
"lint": "yarn -s tslint && yarn -s stylelint && yarn -s ownerslint && yarn -s ng-dev format changed --check",
"e2e": "bazel test //src/... --build_tag_filters=e2e --test_tag_filters=e2e --build_tests_only",
"deploy-dev-app": "node ./scripts/deploy-dev-app.js",
Expand Down Expand Up @@ -60,7 +61,7 @@
"@types/google.maps": "^3.45.6",
"@types/youtube": "^0.0.42",
"core-js-bundle": "^3.8.2",
"material-components-web": "14.0.0-canary.7d8ea4624.0",
"material-components-web": "14.0.0-canary.c047f7c19.0",
"rxjs": "^6.6.7",
"rxjs-tslint-rules": "^4.33.1",
"tslib": "^2.3.0",
Expand Down Expand Up @@ -92,53 +93,53 @@
"@bazel/terser": "4.4.5",
"@bazel/typescript": "4.4.5",
"@firebase/app-types": "^0.6.1",
"@material/animation": "14.0.0-canary.7d8ea4624.0",
"@material/auto-init": "14.0.0-canary.7d8ea4624.0",
"@material/banner": "14.0.0-canary.7d8ea4624.0",
"@material/base": "14.0.0-canary.7d8ea4624.0",
"@material/button": "14.0.0-canary.7d8ea4624.0",
"@material/card": "14.0.0-canary.7d8ea4624.0",
"@material/checkbox": "14.0.0-canary.7d8ea4624.0",
"@material/chips": "14.0.0-canary.7d8ea4624.0",
"@material/circular-progress": "14.0.0-canary.7d8ea4624.0",
"@material/data-table": "14.0.0-canary.7d8ea4624.0",
"@material/density": "14.0.0-canary.7d8ea4624.0",
"@material/dialog": "14.0.0-canary.7d8ea4624.0",
"@material/dom": "14.0.0-canary.7d8ea4624.0",
"@material/drawer": "14.0.0-canary.7d8ea4624.0",
"@material/elevation": "14.0.0-canary.7d8ea4624.0",
"@material/fab": "14.0.0-canary.7d8ea4624.0",
"@material/feature-targeting": "14.0.0-canary.7d8ea4624.0",
"@material/floating-label": "14.0.0-canary.7d8ea4624.0",
"@material/form-field": "14.0.0-canary.7d8ea4624.0",
"@material/icon-button": "14.0.0-canary.7d8ea4624.0",
"@material/image-list": "14.0.0-canary.7d8ea4624.0",
"@material/layout-grid": "14.0.0-canary.7d8ea4624.0",
"@material/line-ripple": "14.0.0-canary.7d8ea4624.0",
"@material/linear-progress": "14.0.0-canary.7d8ea4624.0",
"@material/list": "14.0.0-canary.7d8ea4624.0",
"@material/menu": "14.0.0-canary.7d8ea4624.0",
"@material/menu-surface": "14.0.0-canary.7d8ea4624.0",
"@material/notched-outline": "14.0.0-canary.7d8ea4624.0",
"@material/radio": "14.0.0-canary.7d8ea4624.0",
"@material/ripple": "14.0.0-canary.7d8ea4624.0",
"@material/rtl": "14.0.0-canary.7d8ea4624.0",
"@material/segmented-button": "14.0.0-canary.7d8ea4624.0",
"@material/select": "14.0.0-canary.7d8ea4624.0",
"@material/shape": "14.0.0-canary.7d8ea4624.0",
"@material/slider": "14.0.0-canary.7d8ea4624.0",
"@material/snackbar": "14.0.0-canary.7d8ea4624.0",
"@material/switch": "14.0.0-canary.7d8ea4624.0",
"@material/tab": "14.0.0-canary.7d8ea4624.0",
"@material/tab-bar": "14.0.0-canary.7d8ea4624.0",
"@material/tab-indicator": "14.0.0-canary.7d8ea4624.0",
"@material/tab-scroller": "14.0.0-canary.7d8ea4624.0",
"@material/textfield": "14.0.0-canary.7d8ea4624.0",
"@material/theme": "14.0.0-canary.7d8ea4624.0",
"@material/tooltip": "14.0.0-canary.7d8ea4624.0",
"@material/top-app-bar": "14.0.0-canary.7d8ea4624.0",
"@material/touch-target": "14.0.0-canary.7d8ea4624.0",
"@material/typography": "14.0.0-canary.7d8ea4624.0",
"@material/animation": "14.0.0-canary.c047f7c19.0",
"@material/auto-init": "14.0.0-canary.c047f7c19.0",
"@material/banner": "14.0.0-canary.c047f7c19.0",
"@material/base": "14.0.0-canary.c047f7c19.0",
"@material/button": "14.0.0-canary.c047f7c19.0",
"@material/card": "14.0.0-canary.c047f7c19.0",
"@material/checkbox": "14.0.0-canary.c047f7c19.0",
"@material/chips": "14.0.0-canary.c047f7c19.0",
"@material/circular-progress": "14.0.0-canary.c047f7c19.0",
"@material/data-table": "14.0.0-canary.c047f7c19.0",
"@material/density": "14.0.0-canary.c047f7c19.0",
"@material/dialog": "14.0.0-canary.c047f7c19.0",
"@material/dom": "14.0.0-canary.c047f7c19.0",
"@material/drawer": "14.0.0-canary.c047f7c19.0",
"@material/elevation": "14.0.0-canary.c047f7c19.0",
"@material/fab": "14.0.0-canary.c047f7c19.0",
"@material/feature-targeting": "14.0.0-canary.c047f7c19.0",
"@material/floating-label": "14.0.0-canary.c047f7c19.0",
"@material/form-field": "14.0.0-canary.c047f7c19.0",
"@material/icon-button": "14.0.0-canary.c047f7c19.0",
"@material/image-list": "14.0.0-canary.c047f7c19.0",
"@material/layout-grid": "14.0.0-canary.c047f7c19.0",
"@material/line-ripple": "14.0.0-canary.c047f7c19.0",
"@material/linear-progress": "14.0.0-canary.c047f7c19.0",
"@material/list": "14.0.0-canary.c047f7c19.0",
"@material/menu": "14.0.0-canary.c047f7c19.0",
"@material/menu-surface": "14.0.0-canary.c047f7c19.0",
"@material/notched-outline": "14.0.0-canary.c047f7c19.0",
"@material/radio": "14.0.0-canary.c047f7c19.0",
"@material/ripple": "14.0.0-canary.c047f7c19.0",
"@material/rtl": "14.0.0-canary.c047f7c19.0",
"@material/segmented-button": "14.0.0-canary.c047f7c19.0",
"@material/select": "14.0.0-canary.c047f7c19.0",
"@material/shape": "14.0.0-canary.c047f7c19.0",
"@material/slider": "14.0.0-canary.c047f7c19.0",
"@material/snackbar": "14.0.0-canary.c047f7c19.0",
"@material/switch": "14.0.0-canary.c047f7c19.0",
"@material/tab": "14.0.0-canary.c047f7c19.0",
"@material/tab-bar": "14.0.0-canary.c047f7c19.0",
"@material/tab-indicator": "14.0.0-canary.c047f7c19.0",
"@material/tab-scroller": "14.0.0-canary.c047f7c19.0",
"@material/textfield": "14.0.0-canary.c047f7c19.0",
"@material/theme": "14.0.0-canary.c047f7c19.0",
"@material/tooltip": "14.0.0-canary.c047f7c19.0",
"@material/top-app-bar": "14.0.0-canary.c047f7c19.0",
"@material/touch-target": "14.0.0-canary.c047f7c19.0",
"@material/typography": "14.0.0-canary.c047f7c19.0",
"@octokit/rest": "18.3.5",
"@rollup/plugin-commonjs": "^21.0.0",
"@rollup/plugin-node-resolve": "^13.0.5",
Expand Down Expand Up @@ -211,6 +212,7 @@
"stylelint": "^14.0.1",
"terser": "^5.9.0",
"ts-node": "^10.2.1",
"tsec": "0.2.1",
"tsickle": "0.39.1",
"tslint": "^6.1.3",
"tsutils": "^3.21.0",
Expand Down
9 changes: 9 additions & 0 deletions src/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,12 @@ ts_library(
name = "dev_mode_types",
srcs = ["dev-mode-types.d.ts"],
)

ts_config(
name = "tsec_config",
src = "tsconfig-tsec.json",
deps = [
":bazel-tsconfig-build.json",
"//goldens:tsec-exemption.json",
],
)
2 changes: 1 addition & 1 deletion src/cdk/a11y/focus-monitor/focus-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export class FocusMonitor implements OnDestroy {
// Make a note of when the window regains focus, so we can
// restore the origin info for the focused element.
this._windowFocused = true;
this._windowFocusTimeoutId = setTimeout(() => (this._windowFocused = false));
this._windowFocusTimeoutId = window.setTimeout(() => (this._windowFocused = false));
};

/** Used to reference correct document/window */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,46 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.remove();
});

it('should calculate position with simulated zoom in Safari', () => {
let containerElement = overlayContainer.getContainerElement();
spyOn(containerElement, 'getBoundingClientRect').and.returnValue({
top: -200,
bottom: 900,
left: -200,
right: 100,
width: 100,
height: 100,
} as DOMRect);

const originElement = createPositionedBlockElement();
document.body.appendChild(originElement);

// Position the element so it would have enough space to fit.
originElement.style.top = '200px';
originElement.style.left = '70px';

attachOverlay({
positionStrategy: overlay
.position()
.flexibleConnectedTo(originElement)
.withFlexibleDimensions(false)
.withPush(false)
.withPositions([
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'top',
},
]),
});

expect(getComputedStyle(overlayRef.overlayElement).left).toBe('270px');
expect(getComputedStyle(overlayRef.overlayElement).top).toBe('400px');

originElement.remove();
});

it('should clean up after itself when disposed', () => {
const origin = document.createElement('div');
const positionStrategy = overlay
Expand Down
49 changes: 32 additions & 17 deletions src/cdk/overlay/position/flexible-connected-position-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
/** Cached viewport dimensions */
private _viewportRect: Dimensions;

/** Cached container dimensions */
private _containerRect: Dimensions;

/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
private _viewportMargin = 0;

Expand Down Expand Up @@ -213,16 +216,18 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
this._resetOverlayElementStyles();
this._resetBoundingBoxStyles();

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

const originRect = this._originRect;
const overlayRect = this._overlayRect;
const viewportRect = this._viewportRect;
const containerRect = this._containerRect;

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

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

const lastPosition = this._lastPosition || this._preferredPositions[0];
const originPoint = this._getOriginPoint(this._originRect, lastPosition);
const originPoint = this._getOriginPoint(this._originRect, this._containerRect, lastPosition);

this._applyPosition(lastPosition, originPoint);
}
Expand Down Expand Up @@ -479,7 +485,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
/**
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
*/
private _getOriginPoint(originRect: Dimensions, pos: ConnectedPosition): Point {
private _getOriginPoint(
originRect: Dimensions,
containerRect: Dimensions,
pos: ConnectedPosition,
): Point {
let x: number;
if (pos.originX == 'center') {
// Note: when centering we should always use the `left`
Expand All @@ -491,13 +501,28 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
x = pos.originX == 'start' ? startX : endX;
}

// When zooming in Safari the container rectangle contains negative values for the position
// and we need to re-add them to the calculated coordinates.
if (containerRect.left < 0) {
x -= containerRect.left;
}

let y: number;
if (pos.originY == 'center') {
y = originRect.top + originRect.height / 2;
} else {
y = pos.originY == 'top' ? originRect.top : originRect.bottom;
}

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

return {x, y};
}

Expand Down Expand Up @@ -580,7 +605,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
/**
* Whether the overlay can fit within the viewport when it may resize either its width or height.
* @param fit How well the overlay fits in the viewport at some position.
* @param point The (x, y) coordinates of the overlat at some position.
* @param point The (x, y) coordinates of the overlay at some position.
* @param viewport The geometry of the viewport.
*/
private _canFitWithFlexibleDimensions(fit: OverlayFit, point: Point, viewport: Dimensions) {
Expand All @@ -606,7 +631,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
* right and bottom).
*
* @param start Starting point from which the overlay is pushed.
* @param overlay Dimensions of the overlay.
* @param rawOverlayRect Dimensions of the overlay.
* @param scrollPosition Current viewport scroll position.
* @returns The point at which to position the overlay after pushing. This is effectively a new
* originPoint.
Expand Down Expand Up @@ -958,16 +983,6 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
}

let virtualKeyboardOffset = this._overlayContainer
.getContainerElement()
.getBoundingClientRect().top;

// Normally this would be zero, however when the overlay is attached to an input (e.g. in an
// autocomplete), mobile browsers will shift everything in order to put the input in the middle
// of the screen and to make space for the virtual keyboard. We need to account for this offset,
// otherwise our positioning will be thrown off.
overlayPoint.y -= virtualKeyboardOffset;

// We want to set either `top` or `bottom` based on whether the overlay wants to appear
// above or below the origin and the direction in which the element will expand.
if (position.overlayY === 'bottom') {
Expand Down Expand Up @@ -1183,7 +1198,7 @@ interface OverlayFit {
visibleArea: number;
}

/** Record of the measurments determining whether an overlay will fit in a specific position. */
/** Record of the measurements determining whether an overlay will fit in a specific position. */
interface FallbackPosition {
position: ConnectedPosition;
originPoint: Point;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ export class TildeImportMigration extends DevkitMigration<null> {
if (extension === '.scss' || extension === '.css') {
const content = stylesheet.content;
const migratedContent = content.replace(
/@(?:import|use) +['"]~@angular\/.*['"].*;?/g,
match => {
const index = match.indexOf('~@angular');
return match.slice(0, index) + match.slice(index + 1);
/@(?:import|use) +['"](~@angular\/.*)['"].*;?/g,
(match, importPath) => {
const index = match.indexOf(importPath);
const newImportPath = importPath.replace(/^~|\.scss$/g, '');
return match.slice(0, index) + newImportPath + match.slice(index + importPath.length);
},
);

Expand Down
Loading

0 comments on commit 9d2ac16

Please sign in to comment.