Skip to content

Commit 6224d2b

Browse files
committed
fixup! feat(cdk-experimental/menu): allow configuration of typeahead and menu position
1 parent e3fad64 commit 6224d2b

File tree

10 files changed

+91
-32
lines changed

10 files changed

+91
-32
lines changed

src/cdk-experimental/menu/context-menu.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
Overlay,
2828
OverlayConfig,
2929
OverlayRef,
30+
STANDARD_DROPDOWN_BELOW_POSITIONS,
3031
} from '@angular/cdk/overlay';
3132
import {Portal, TemplatePortal} from '@angular/cdk/portal';
3233
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
@@ -239,14 +240,7 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
239240
.flexibleConnectedTo(coordinates)
240241
.withDefaultOffsetX(this._options?.offsetX ?? 2)
241242
.withDefaultOffsetY(this._options?.offsetY ?? 2)
242-
.withPositions(
243-
this._options?.preferredPositions ?? [
244-
{originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top'},
245-
{originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top'},
246-
{originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom'},
247-
{originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom'},
248-
],
249-
);
243+
.withPositions(this._options?.preferredPositions ?? STANDARD_DROPDOWN_BELOW_POSITIONS);
250244
}
251245

252246
/**

src/cdk-experimental/menu/menu-item-trigger.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929
Overlay,
3030
OverlayConfig,
3131
OverlayRef,
32+
STANDARD_DROPDOWN_ADJACENT_POSITIONS,
33+
STANDARD_DROPDOWN_BELOW_POSITIONS,
3234
} from '@angular/cdk/overlay';
3335
import {DOWN_ARROW, ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE, UP_ARROW} from '@angular/cdk/keycodes';
3436
import {fromEvent, merge, Subject} from 'rxjs';
@@ -288,18 +290,8 @@ export class CdkMenuItemTrigger extends MenuTrigger implements OnDestroy {
288290
/** Determine and return where to position the opened menu relative to the menu item */
289291
private _getOverlayPositions(): ConnectedPosition[] {
290292
return !this._parentMenu || this._parentMenu.orientation === 'horizontal'
291-
? [
292-
{originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top'},
293-
{originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom'},
294-
{originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top'},
295-
{originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom'},
296-
]
297-
: [
298-
{originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top'},
299-
{originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom'},
300-
{originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top'},
301-
{originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom'},
302-
];
293+
? STANDARD_DROPDOWN_BELOW_POSITIONS
294+
: STANDARD_DROPDOWN_ADJACENT_POSITIONS;
303295
}
304296

305297
/**

src/cdk-experimental/menu/menu-item.spec.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ describe('MenuItem', () => {
9090
fixture.detectChanges();
9191

9292
menuItem = fixture.debugElement.query(By.directive(CdkMenuItem)).injector.get(CdkMenuItem);
93+
return fixture;
9394
}
9495

9596
it('should get the text for a simple menu item with no nested or wrapped elements', () => {
@@ -98,15 +99,21 @@ describe('MenuItem', () => {
9899
});
99100

100101
it('should get the text for menu item with a single nested mat icon component', () => {
101-
createComponent(MenuItemWithIcon);
102+
const fixture = createComponent(MenuItemWithIcon);
103+
expect(menuItem.getLabel()).toEqual('unicorn Click me!');
104+
fixture.componentInstance.typeahead = 'Click me!';
105+
fixture.detectChanges();
102106
expect(menuItem.getLabel()).toEqual('Click me!');
103107
});
104108

105109
it(
106110
'should get the text for menu item with single nested component with the material ' +
107111
'icon class',
108112
() => {
109-
createComponent(MenuItemWithIconClass);
113+
const fixture = createComponent(MenuItemWithIconClass);
114+
expect(menuItem.getLabel()).toEqual('unicorn Click me!');
115+
fixture.componentInstance.typeahead = 'Click me!';
116+
fixture.detectChanges();
110117
expect(menuItem.getLabel()).toEqual('Click me!');
111118
},
112119
);
@@ -120,7 +127,10 @@ describe('MenuItem', () => {
120127
'should get the text for a menu item with nested icon, nested icon class and nested ' +
121128
'wrapping elements',
122129
() => {
123-
createComponent(MenuItemWithMultipleNestings);
130+
const fixture = createComponent(MenuItemWithMultipleNestings);
131+
expect(menuItem.getLabel()).toEqual('unicorn Click menume!');
132+
fixture.componentInstance.typeahead = 'Click me!';
133+
fixture.detectChanges();
124134
expect(menuItem.getLabel()).toEqual('Click me!');
125135
},
126136
);
@@ -134,22 +144,27 @@ class SingleMenuItem {}
134144

135145
@Component({
136146
template: `
137-
<button cdkMenuItem>
147+
<button cdkMenuItem [typeahead]="typeahead">
138148
<mat-icon>unicorn</mat-icon>
139149
Click me!
140150
</button>
141151
`,
142152
})
143-
class MenuItemWithIcon {}
153+
class MenuItemWithIcon {
154+
typeahead: string;
155+
}
156+
144157
@Component({
145158
template: `
146-
<button cdkMenuItem>
159+
<button cdkMenuItem [typeahead]="typeahead">
147160
<div class="material-icons">unicorn</div>
148161
Click me!
149162
</button>
150163
`,
151164
})
152-
class MenuItemWithIconClass {}
165+
class MenuItemWithIconClass {
166+
typeahead: string;
167+
}
153168

154169
@Component({
155170
template: ` <button cdkMenuItem><b>Click</b> me!</button> `,
@@ -158,7 +173,7 @@ class MenuItemWithBoldElement {}
158173

159174
@Component({
160175
template: `
161-
<button cdkMenuItem>
176+
<button cdkMenuItem [typeahead]="typeahead">
162177
<div>
163178
<div class="material-icons">unicorn</div>
164179
<div>
@@ -170,7 +185,9 @@ class MenuItemWithBoldElement {}
170185
</button>
171186
`,
172187
})
173-
class MenuItemWithMultipleNestings {}
188+
class MenuItemWithMultipleNestings {
189+
typeahead: string;
190+
}
174191

175192
@Component({
176193
selector: 'mat-icon',

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,3 +1288,17 @@ function getRoundedBoundingClientRect(clientRect: Dimensions): Dimensions {
12881288
height: Math.floor(clientRect.height),
12891289
};
12901290
}
1291+
1292+
export const STANDARD_DROPDOWN_BELOW_POSITIONS: ConnectedPosition[] = [
1293+
{originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top'},
1294+
{originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom'},
1295+
{originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top'},
1296+
{originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom'},
1297+
];
1298+
1299+
export const STANDARD_DROPDOWN_ADJACENT_POSITIONS: ConnectedPosition[] = [
1300+
{originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top'},
1301+
{originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom'},
1302+
{originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top'},
1303+
{originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom'},
1304+
];

src/cdk/overlay/public-api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ export {
2727
ConnectedPosition,
2828
FlexibleConnectedPositionStrategy,
2929
FlexibleConnectedPositionStrategyOrigin,
30+
STANDARD_DROPDOWN_ADJACENT_POSITIONS,
31+
STANDARD_DROPDOWN_BELOW_POSITIONS,
3032
} from './position/flexible-connected-position-strategy';

src/dev-app/cdk-experimental-menu/cdk-menu-demo-module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {RouterModule} from '@angular/router';
1212
import {CdkMenuModule} from '@angular/cdk-experimental/menu';
1313
import {CdkMenuExamplesModule} from '@angular/components-examples/cdk-experimental/menu';
1414

15-
import {CdkMenuDemo} from './cdk-menu-demo';
15+
import {CdkMenuDemo, DemoCustomMenuOptions} from './cdk-menu-demo';
1616

1717
@NgModule({
1818
imports: [
@@ -21,6 +21,6 @@ import {CdkMenuDemo} from './cdk-menu-demo';
2121
CdkMenuExamplesModule,
2222
RouterModule.forChild([{path: '', component: CdkMenuDemo}]),
2323
],
24-
declarations: [CdkMenuDemo],
24+
declarations: [CdkMenuDemo, DemoCustomMenuOptions],
2525
})
2626
export class CdkMenuDemoModule {}

src/dev-app/cdk-experimental-menu/cdk-menu-demo.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@
1717
border: solid 2px black;
1818
padding: 6px;
1919
}
20+
21+
demo-custom-position {
22+
display: block;
23+
margin-top: 20px;
24+
}

src/dev-app/cdk-experimental-menu/cdk-menu-demo.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ <h4>Inner Context</h4>
100100
</div>
101101
</div>
102102

103+
<demo-custom-position>
104+
<div class="example-context" [cdkContextMenuTriggerFor]="outer">
105+
<h4>Custom Context Menu Position (Centered on Cursor)</h4>
106+
107+
Lucas ipsum dolor sit amet maul jade jawa ben wookiee binks lando jinn baba tatooine. Jade biggs
108+
padmé sebulba cade dagobah. Baba lars mothma yoda. Bothan calrissian c-3p0 maul fisto lando
109+
obi-wan. Skywalker solo darth bothan droid obi-wan ahsoka. Maul solo obi-wan calrissian antilles
110+
yavin chewbacca lando. Mustafar ponda kit jango. C-3p0 skywalker baba grievous moff. Hutt ben
111+
darth solo skywalker bothan skywalker maul organa. Grievous cade antilles utapau skywalker
112+
grievous antilles chewbacca.
113+
</div>
114+
</demo-custom-position>
115+
103116
<ng-template #outer>
104117
<div cdkMenu class="example-menu" id="outer_menu">
105118
<button id="undo_button" cdkMenuItem>Undo</button>

src/dev-app/cdk-experimental-menu/cdk-menu-demo.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Component} from '@angular/core';
9+
import {Component, Directive} from '@angular/core';
10+
import {CDK_CONTEXT_MENU_DEFAULT_OPTIONS} from '@angular/cdk-experimental/menu';
1011

1112
@Component({
1213
templateUrl: 'cdk-menu-demo.html',
1314
styleUrls: ['cdk-menu-demo.css'],
1415
})
1516
export class CdkMenuDemo {}
17+
18+
@Directive({
19+
selector: 'demo-custom-position',
20+
providers: [
21+
{
22+
provide: CDK_CONTEXT_MENU_DEFAULT_OPTIONS,
23+
useValue: {
24+
preferredPositions: [
25+
{originX: 'center', originY: 'center', overlayX: 'center', overlayY: 'center'},
26+
],
27+
},
28+
},
29+
],
30+
})
31+
export class DemoCustomMenuOptions {}

tools/public_api_guard/cdk/overlay.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,12 @@ export class ScrollStrategyOptions {
471471
static ɵprov: i0.ɵɵInjectableDeclaration<ScrollStrategyOptions>;
472472
}
473473

474+
// @public (undocumented)
475+
export const STANDARD_DROPDOWN_ADJACENT_POSITIONS: ConnectedPosition[];
476+
477+
// @public (undocumented)
478+
export const STANDARD_DROPDOWN_BELOW_POSITIONS: ConnectedPosition[];
479+
474480
// @public
475481
export function validateHorizontalPosition(property: string, value: HorizontalConnectionPos): void;
476482

0 commit comments

Comments
 (0)