Skip to content

Commit

Permalink
Merge branch 'angular:main' into add-footer-cell-to-text-column
Browse files Browse the repository at this point in the history
  • Loading branch information
jullierme authored Jul 10, 2024
2 parents b273831 + 9401323 commit b20ecd7
Show file tree
Hide file tree
Showing 29 changed files with 873 additions and 208 deletions.
18 changes: 18 additions & 0 deletions src/cdk-experimental/popover-edit/popover-edit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const POPOVER_EDIT_DIRECTIVE_NAME = `
[cdkPopoverEdit]="nameEdit"
[cdkPopoverEditColspan]="colspan"
[cdkPopoverEditDisabled]="nameEditDisabled"
[cdkPopoverEditAriaLabel]="nameEditAriaLabel"
`;

const POPOVER_EDIT_DIRECTIVE_WEIGHT = `[cdkPopoverEdit]="weightEdit" cdkPopoverEditTabOut`;
Expand All @@ -77,6 +78,7 @@ abstract class BaseTestComponent {

preservedValues = new FormValueContainer<PeriodicElement, {'name': string}>();
nameEditDisabled = false;
nameEditAriaLabel: string | undefined = undefined;
ignoreSubmitUnlessValid = true;
clickOutBehavior: PopoverEditClickOutBehavior = 'close';
colspan: CdkPopoverEditColspan = {};
Expand Down Expand Up @@ -557,6 +559,22 @@ describe('CDK Popover Edit', () => {
expect(component.lensIsOpen()).toBe(false);
clearLeftoverTimers();
}));

it('sets aria label and role dialog on the popup', fakeAsync(() => {
component.nameEditAriaLabel = 'Label of name!!';
fixture.changeDetectorRef.markForCheck();
fixture.detectChanges();

// Uses Enter to open the lens.
component.openLens();
fixture.detectChanges();

expect(component.lensIsOpen()).toBe(true);
const dialogElem = component.getEditPane()!;
expect(dialogElem.getAttribute('aria-label')).toBe('Label of name!!');
expect(dialogElem.getAttribute('role')).toBe('dialog');
clearLeftoverTimers();
}));
});

describe('focus manipulation', () => {
Expand Down
9 changes: 8 additions & 1 deletion src/cdk-experimental/popover-edit/table-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ const POPOVER_EDIT_INPUTS = [
{name: 'context', alias: 'cdkPopoverEditContext'},
{name: 'colspan', alias: 'cdkPopoverEditColspan'},
{name: 'disabled', alias: 'cdkPopoverEditDisabled'},
{name: 'ariaLabel', alias: 'cdkPopoverEditAriaLabel'},
];

/**
Expand All @@ -196,6 +197,9 @@ export class CdkPopoverEdit<C> implements AfterViewInit, OnDestroy {
*/
context?: C;

/** Aria label to set on the popover dialog element. */
ariaLabel?: string;

/**
* Specifies that the popup should cover additional table cells before and/or after
* this one.
Expand Down Expand Up @@ -302,7 +306,10 @@ export class CdkPopoverEdit<C> implements AfterViewInit, OnDestroy {
});

this.initFocusTrap();
this.overlayRef.overlayElement.setAttribute('aria-role', 'dialog');
this.overlayRef.overlayElement.setAttribute('role', 'dialog');
if (this.ariaLabel) {
this.overlayRef.overlayElement.setAttribute('aria-label', this.ariaLabel);
}

this.overlayRef.detachments().subscribe(() => this.closeEditOverlay());
}
Expand Down
8 changes: 8 additions & 0 deletions src/cdk/dialog/dialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ If you're using a `TemplateRef` for your dialog content, the data is available i
</ng-template>
```

If you're using a `TemplateRef` and need to access the `DialogRef`, you can use the following:

```html
<ng-template let-data let-dialogRef="dialogRef">
Hello, {{data.name}}
</ng-template>
```

<!-- example(cdk-dialog-data) -->

### Accessibility
Expand Down
14 changes: 14 additions & 0 deletions src/cdk/drag-drop/directives/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
AfterViewInit,
inject,
Injector,
numberAttribute,
} from '@angular/core';
import {coerceElement, coerceNumberProperty} from '@angular/cdk/coercion';
import {BehaviorSubject, Observable, Observer, Subject, merge} from 'rxjs';
Expand Down Expand Up @@ -159,6 +160,13 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
*/
@Input('cdkDragPreviewContainer') previewContainer: PreviewContainer;

/**
* If the parent of the dragged element has a `scale` transform, it can throw off the
* positioning when the user starts dragging. Use this input to notify the CDK of the scale.
*/
@Input({alias: 'cdkDragScale', transform: numberAttribute})
scale: number = 1;

/** Emits when the user starts dragging the item. */
@Output('cdkDragStarted') readonly started: EventEmitter<CdkDragStart> =
new EventEmitter<CdkDragStart>();
Expand Down Expand Up @@ -261,6 +269,11 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
if (dropContainer) {
this._dragRef._withDropContainer(dropContainer._dropListRef);
dropContainer.addItem(this);

// The drop container reads this so we need to sync it here.
dropContainer._dropListRef.beforeStarted.pipe(takeUntil(this._destroyed)).subscribe(() => {
this._dragRef.scale = this.scale;
});
}

this._syncInputs(this._dragRef);
Expand Down Expand Up @@ -448,6 +461,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {

ref.disabled = this.disabled;
ref.lockAxis = this.lockAxis;
ref.scale = this.scale;
ref.dragStartDelay =
typeof dragStartDelay === 'object' && dragStartDelay
? dragStartDelay
Expand Down
2 changes: 2 additions & 0 deletions src/cdk/drag-drop/directives/drop-list-shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5006,6 +5006,7 @@ const DROP_ZONE_FIXTURE_TEMPLATE = `
[cdkDragBoundary]="boundarySelector"
[cdkDragPreviewClass]="previewClass"
[cdkDragPreviewContainer]="previewContainer"
[cdkDragScale]="scale"
[style.height.px]="item.height"
[style.margin-bottom.px]="item.margin"
(cdkDragStarted)="startedSpy($event)"
Expand Down Expand Up @@ -5041,6 +5042,7 @@ export class DraggableInDropZone implements AfterViewInit {
previewContainer: PreviewContainer = 'global';
dropDisabled = signal(false);
dropLockAxis = signal<DragAxis | undefined>(undefined);
scale = 1;

constructor(protected _elementRef: ElementRef) {}

Expand Down
25 changes: 25 additions & 0 deletions src/cdk/drag-drop/directives/single-axis-drop-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,29 @@ describe('Single-axis drop list', () => {

dispatchMouseEvent(document, 'mouseup');
}));

it('should lay out the elements correctly when scaled', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZone);
fixture.componentInstance.scale = 0.5;
fixture.detectChanges();

const items = fixture.componentInstance.dragItems.map(i => i.element.nativeElement);
const {top, left} = items[0].getBoundingClientRect();

startDraggingViaMouse(fixture, items[0], left, top);

const placeholder = document.querySelector('.cdk-drag-placeholder')! as HTMLElement;
const target = items[1];
const targetRect = target.getBoundingClientRect();

dispatchMouseEvent(document, 'mousemove', targetRect.left, targetRect.top + 5);
fixture.detectChanges();

expect(placeholder.style.transform).toBe(`translate3d(0px, ${ITEM_HEIGHT * 2}px, 0px)`);
expect(target.style.transform).toBe(`translate3d(0px, ${-ITEM_HEIGHT * 2}px, 0px)`);

dispatchMouseEvent(document, 'mouseup');
fixture.detectChanges();
flush();
}));
});
53 changes: 31 additions & 22 deletions src/cdk/drag-drop/directives/standalone-drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1470,34 +1470,41 @@ describe('Standalone CdkDrag', () => {
cleanup();
}));

it(
'should update the free drag position if the user moves their pointer after the page ' +
'is scrolled',
fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.detectChanges();
it('should update the free drag position if the user moves their pointer after the page is scrolled', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.detectChanges();

const cleanup = makeScrollable();
const dragElement = fixture.componentInstance.dragElement.nativeElement;
const cleanup = makeScrollable();
const dragElement = fixture.componentInstance.dragElement.nativeElement;

expect(dragElement.style.transform).toBeFalsy();
startDraggingViaMouse(fixture, dragElement, 0, 0);
dispatchMouseEvent(document, 'mousemove', 50, 100);
fixture.detectChanges();
expect(dragElement.style.transform).toBeFalsy();
startDraggingViaMouse(fixture, dragElement, 0, 0);
dispatchMouseEvent(document, 'mousemove', 50, 100);
fixture.detectChanges();

expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');

scrollTo(0, 500);
dispatchFakeEvent(document, 'scroll');
fixture.detectChanges();
dispatchMouseEvent(document, 'mousemove', 50, 200);
fixture.detectChanges();
scrollTo(0, 500);
dispatchFakeEvent(document, 'scroll');
fixture.detectChanges();
dispatchMouseEvent(document, 'mousemove', 50, 200);
fixture.detectChanges();

expect(dragElement.style.transform).toBe('translate3d(50px, 700px, 0px)');
expect(dragElement.style.transform).toBe('translate3d(50px, 700px, 0px)');

cleanup();
}),
);
cleanup();
}));

it('should account for scale when moving the element', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.componentInstance.scale = 0.5;
fixture.detectChanges();
const dragElement = fixture.componentInstance.dragElement.nativeElement;

expect(dragElement.style.transform).toBeFalsy();
dragElementViaMouse(fixture, dragElement, 50, 100);
expect(dragElement.style.transform).toBe('translate3d(100px, 200px, 0px)');
}));

describe('with a handle', () => {
it('should not be able to drag the entire element if it has a handle', fakeAsync(() => {
Expand Down Expand Up @@ -1718,6 +1725,7 @@ describe('Standalone CdkDrag', () => {
[cdkDragFreeDragPosition]="freeDragPosition"
[cdkDragDisabled]="dragDisabled()"
[cdkDragLockAxis]="dragLockAxis()"
[cdkDragScale]="scale"
(cdkDragStarted)="startedSpy($event)"
(cdkDragReleased)="releasedSpy($event)"
(cdkDragEnded)="endedSpy($event)"
Expand Down Expand Up @@ -1745,6 +1753,7 @@ class StandaloneDraggable {
freeDragPosition?: {x: number; y: number};
dragDisabled = signal(false);
dragLockAxis = signal<DragAxis | undefined>(undefined);
scale = 1;
}

@Component({
Expand Down
9 changes: 8 additions & 1 deletion src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ export class DragRef<T = any> {
/** Class to be added to the preview element. */
previewClass: string | string[] | undefined;

/**
* If the parent of the dragged element has a `scale` transform, it can throw off the
* positioning when the user starts dragging. Use this input to notify the CDK of the scale.
*/
scale: number = 1;

/** Whether starting to drag this element is disabled. */
get disabled(): boolean {
return this._disabled || !!(this._dropContainer && this._dropContainer.disabled);
Expand Down Expand Up @@ -1288,7 +1294,8 @@ export class DragRef<T = any> {
* @param y New transform value along the Y axis.
*/
private _applyRootElementTransform(x: number, y: number) {
const transform = getTransform(x, y);
const scale = 1 / this.scale;
const transform = getTransform(x * scale, y * scale);
const styles = this._rootElement.style;

// Cache the previous transform amount only after the first drag sequence, because
Expand Down
6 changes: 4 additions & 2 deletions src/cdk/drag-drop/sorting/single-axis-sort-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ export class SingleAxisSortStrategy implements DropListSortStrategy {
// Update the offset to reflect the new position.
sibling.offset += offset;

const transformAmount = Math.round(sibling.offset * (1 / sibling.drag.scale));

// Since we're moving the items with a `transform`, we need to adjust their cached
// client rects to reflect their new position, as well as swap their positions in the cache.
// Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
Expand All @@ -136,13 +138,13 @@ export class SingleAxisSortStrategy implements DropListSortStrategy {
// Round the transforms since some browsers will
// blur the elements, for sub-pixel transforms.
elementToOffset.style.transform = combineTransforms(
`translate3d(${Math.round(sibling.offset)}px, 0, 0)`,
`translate3d(${transformAmount}px, 0, 0)`,
sibling.initialTransform,
);
adjustDomRect(sibling.clientRect, 0, offset);
} else {
elementToOffset.style.transform = combineTransforms(
`translate3d(0, ${Math.round(sibling.offset)}px, 0)`,
`translate3d(0, ${transformAmount}px, 0)`,
sibling.initialTransform,
);
adjustDomRect(sibling.clientRect, offset, 0);
Expand Down
18 changes: 18 additions & 0 deletions src/material-experimental/popover-edit/popover-edit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const POPOVER_EDIT_DIRECTIVE_NAME = `
[matPopoverEdit]="nameEdit"
[matPopoverEditColspan]="colspan"
[matPopoverEditDisabled]="nameEditDisabled"
[matPopoverEditAriaLabel]="nameEditAriaLabel"
`;

const POPOVER_EDIT_DIRECTIVE_WEIGHT = `[matPopoverEdit]="weightEdit" matPopoverEditTabOut`;
Expand All @@ -69,6 +70,7 @@ abstract class BaseTestComponent {
preservedValues = new FormValueContainer<PeriodicElement, {'name': string}>();

nameEditDisabled = false;
nameEditAriaLabel: string | undefined = undefined;
ignoreSubmitUnlessValid = true;
clickOutBehavior: PopoverEditClickOutBehavior = 'close';
colspan: CdkPopoverEditColspan = {};
Expand Down Expand Up @@ -430,6 +432,22 @@ describe('Material Popover Edit', () => {
expect(component.lensIsOpen()).toBe(false);
clearLeftoverTimers();
}));

it('sets aria label and role dialog on the popup', fakeAsync(() => {
component.nameEditAriaLabel = 'Label of name!!';
fixture.changeDetectorRef.markForCheck();
fixture.detectChanges();

// Uses Enter to open the lens.
component.openLens();
fixture.detectChanges();

expect(component.lensIsOpen()).toBe(true);
const dialogElem = component.getEditPane()!;
expect(dialogElem.getAttribute('aria-label')).toBe('Label of name!!');
expect(dialogElem.getAttribute('role')).toBe('dialog');
clearLeftoverTimers();
}));
});

describe('focus manipulation', () => {
Expand Down
1 change: 1 addition & 0 deletions src/material-experimental/popover-edit/table-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const POPOVER_EDIT_INPUTS = [
{name: 'context', alias: 'matPopoverEditContext'},
{name: 'colspan', alias: 'matPopoverEditColspan'},
{name: 'disabled', alias: 'matPopoverEditDisabled'},
{name: 'ariaLabel', alias: 'matPopoverEditAriaLabel'},
];

const EDIT_PANE_CLASS = 'mat-edit-pane';
Expand Down
42 changes: 35 additions & 7 deletions src/material/core/internal-form-field/internal-form-field.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
@use '@material/form-field/form-field' as mdc-form-field;
@use '@material/theme/custom-properties' as mdc-custom-properties;
@use '../style/vendor-prefixes';
@use '../mdc-helpers/mdc-helpers';

@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
@include mdc-form-field.static-styles($query: mdc-helpers.$mdc-base-styles-query);
}

.mat-internal-form-field {
@include vendor-prefixes.smooth-font();
display: inline-flex;
align-items: center;
vertical-align: middle;

& > label {
margin-left: 0;
margin-right: auto;
padding-left: 4px;
padding-right: 0;
order: 0;
}

[dir='rtl'] & > label {
margin-left: auto;
margin-right: 0;
padding-left: 0;
padding-right: 4px;
}
}

.mdc-form-field--align-end {
& > label {
margin-left: auto;
margin-right: 0;
padding-left: 0;
padding-right: 4px;
order: -1;
}

[dir='rtl'] .mdc-form-field--align-end & label {
margin-left: 0;
margin-right: auto;
padding-left: 4px;
padding-right: 0;
}
}
Loading

0 comments on commit b20ecd7

Please sign in to comment.