Skip to content

feat(material/menu): add support for context menu #31383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 44 additions & 7 deletions goldens/material/menu/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import { AfterContentInit } from '@angular/core';
import { AfterViewInit } from '@angular/core';
import { Direction } from '@angular/cdk/bidi';
import { ElementRef } from '@angular/core';
import { EventEmitter } from '@angular/core';
import { FlexibleConnectedPositionStrategyOrigin } from '@angular/cdk/overlay';
import { FocusableOption } from '@angular/cdk/a11y';
import { FocusOrigin } from '@angular/cdk/a11y';
import * as i0 from '@angular/core';
Expand All @@ -18,7 +20,9 @@ import { InjectionToken } from '@angular/core';
import { Observable } from 'rxjs';
import { OnDestroy } from '@angular/core';
import { OnInit } from '@angular/core';
import { OverlayRef } from '@angular/cdk/overlay';
import { QueryList } from '@angular/core';
import * as rxjs from 'rxjs';
import { ScrollStrategy } from '@angular/cdk/overlay';
import { Subject } from 'rxjs';
import { TemplateRef } from '@angular/core';
Expand All @@ -45,6 +49,40 @@ export const MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER: {
useFactory: typeof MAT_MENU_SCROLL_STRATEGY_FACTORY;
};

// @public
export class MatContextMenuTrigger extends MatMenuTriggerBase implements OnDestroy {
constructor();
// (undocumented)
protected _destroyMenu(reason: MenuCloseReason): void;
disabled: boolean;
// (undocumented)
protected _getOutsideClickStream(overlayRef: OverlayRef): rxjs.Observable<MouseEvent>;
// (undocumented)
protected _getOverlayOrigin(): {
x: number;
y: number;
initialX: number;
initialY: number;
initialScrollX: number;
initialScrollY: number;
};
protected _handleContextMenuEvent(event: MouseEvent): void;
get menu(): MatMenuPanel | null;
set menu(menu: MatMenuPanel | null);
readonly menuClosed: EventEmitter<void>;
menuData: any;
readonly menuOpened: EventEmitter<void>;
// (undocumented)
static ngAcceptInputType_disabled: unknown;
// (undocumented)
ngOnDestroy(): void;
restoreFocus: boolean;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<MatContextMenuTrigger, "[matContextMenuTriggerFor]", ["matContextMenuTrigger"], { "menu": { "alias": "matContextMenuTriggerFor"; "required": true; }; "menuData": { "alias": "matContextMenuTriggerData"; "required": false; }; "restoreFocus": { "alias": "matContextMenuTriggerRestoreFocus"; "required": false; }; "disabled": { "alias": "matContextMenuTriggerDisabled"; "required": false; }; }, { "menuOpened": "menuOpened"; "menuClosed": "menuClosed"; }, never, never, true, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<MatContextMenuTrigger, never>;
}

// @public (undocumented)
export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnInit, OnDestroy {
constructor(...args: unknown[]);
Expand Down Expand Up @@ -190,7 +228,7 @@ export class MatMenuModule {
// (undocumented)
static ɵinj: i0.ɵɵInjectorDeclaration<MatMenuModule>;
// (undocumented)
static ɵmod: i0.ɵɵNgModuleDeclaration<MatMenuModule, never, [typeof MatRippleModule, typeof MatCommonModule, typeof i2.OverlayModule, typeof MatMenu, typeof MatMenuItem, typeof MatMenuContent, typeof MatMenuTrigger], [typeof i5.CdkScrollableModule, typeof MatMenu, typeof MatCommonModule, typeof MatMenuItem, typeof MatMenuContent, typeof MatMenuTrigger]>;
static ɵmod: i0.ɵɵNgModuleDeclaration<MatMenuModule, never, [typeof MatRippleModule, typeof MatCommonModule, typeof i2.OverlayModule, typeof MatMenu, typeof MatMenuItem, typeof MatMenuContent, typeof MatMenuTrigger, typeof MatContextMenuTrigger], [typeof i5.CdkScrollableModule, typeof MatMenu, typeof MatCommonModule, typeof MatMenuItem, typeof MatMenuContent, typeof MatMenuTrigger, typeof MatContextMenuTrigger]>;
}

// @public
Expand Down Expand Up @@ -234,22 +272,23 @@ export interface MatMenuPanel<T = any> {
}

// @public
export class MatMenuTrigger implements AfterContentInit, OnDestroy {
export class MatMenuTrigger extends MatMenuTriggerBase implements AfterContentInit, OnDestroy {
constructor(...args: unknown[]);
closeMenu(): void;
// @deprecated (undocumented)
get _deprecatedMatMenuTriggerFor(): MatMenuPanel | null;
set _deprecatedMatMenuTriggerFor(v: MatMenuPanel | null);
get dir(): Direction;
focus(origin?: FocusOrigin, options?: FocusOptions): void;
// (undocumented)
protected _getOutsideClickStream(overlayRef: OverlayRef): rxjs.Observable<MouseEvent>;
// (undocumented)
protected _getOverlayOrigin(): i0.ElementRef<HTMLElement>;
_handleClick(event: MouseEvent): void;
_handleKeydown(event: KeyboardEvent): void;
_handleMousedown(event: MouseEvent): void;
get menu(): MatMenuPanel | null;
set menu(menu: MatMenuPanel | null);
readonly menuClosed: EventEmitter<void>;
menuData: any;
get menuOpen(): boolean;
readonly menuOpened: EventEmitter<void>;
// (undocumented)
ngAfterContentInit(): void;
Expand All @@ -259,8 +298,6 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
readonly onMenuClose: EventEmitter<void>;
// @deprecated
readonly onMenuOpen: EventEmitter<void>;
// (undocumented)
_openedBy: Exclude<FocusOrigin, 'program' | null> | undefined;
openMenu(): void;
restoreFocus: boolean;
toggleMenu(): void;
Expand Down
18 changes: 18 additions & 0 deletions goldens/material/menu/testing/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ import { ContentContainerComponentHarness } from '@angular/cdk/testing';
import { HarnessLoader } from '@angular/cdk/testing';
import { HarnessPredicate } from '@angular/cdk/testing';

// @public
export interface ContextMenuHarnessFilters extends BaseHarnessFilters {
}

// @public
export class MatContextMenuHarness extends ContentContainerComponentHarness<string> {
clickItem(itemFilter: Omit<MenuItemHarnessFilters, 'ancestor'>, ...subItemFilters: Omit<MenuItemHarnessFilters, 'ancestor'>[]): Promise<void>;
close(): Promise<void>;
getItems(filters?: Omit<MenuItemHarnessFilters, 'ancestor'>): Promise<MatMenuItemHarness[]>;
// (undocumented)
protected getRootHarnessLoader(): Promise<HarnessLoader>;
static hostSelector: string;
isDisabled(): Promise<boolean>;
isOpen(): Promise<boolean>;
open(relativeX?: number, relativeY?: number): Promise<void>;
static with<T extends MatContextMenuHarness>(this: ComponentHarnessConstructor<T>, options?: ContextMenuHarnessFilters): HarnessPredicate<T>;
}

// @public
export class MatMenuHarness extends ContentContainerComponentHarness<string> {
blur(): Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.example-context-menu-area {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 300px;
max-width: 300px;
border: dashed 1px;
text-align: center;
padding: 30px;
box-sizing: border-box;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="example-context-menu-area" [matContextMenuTriggerFor]="contextMenu">
Right click here to trigger a context menu
</div>

<mat-menu #contextMenu>
<button mat-menu-item>
<mat-icon>content_cut</mat-icon>
Cut
</button>
<button mat-menu-item>
<mat-icon>content_copy</mat-icon>
Copy
</button>
<button mat-menu-item>
<mat-icon>content_paste</mat-icon>
Paste
</button>
<button mat-menu-item>
<mat-icon>print</mat-icon>
Print
</button>
</mat-menu>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {Component} from '@angular/core';
import {MatMenuModule} from '@angular/material/menu';
import {MatIconModule} from '@angular/material/icon';

/**
* @title Context menu
*/
@Component({
selector: 'context-menu-example',
templateUrl: 'context-menu-example.html',
styleUrl: './context-menu-example.css',
imports: [MatMenuModule, MatIconModule],
})
export class ContextMenuExample {}
1 change: 1 addition & 0 deletions src/components-examples/material/menu/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export {MenuOverviewExample} from './menu-overview/menu-overview-example';
export {MenuPositionExample} from './menu-position/menu-position-example';
export {MenuNestedExample} from './menu-nested/menu-nested-example';
export {MenuHarnessExample} from './menu-harness/menu-harness-example';
export {ContextMenuExample} from './context-menu/context-menu-example';
27 changes: 26 additions & 1 deletion src/dev-app/menu/menu-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,29 @@
</div>
</div>

<div style="height: 500px">This div is for testing scrolled menus.</div>
<div class="demo-context-menu-area" [matContextMenuTriggerFor]="contextMenu">
Right click here to trigger a context menu
</div>

<mat-menu #contextMenu>
<button mat-menu-item>
<mat-icon>content_cut</mat-icon>
Cut
</button>
<button mat-menu-item>
<mat-icon>content_copy</mat-icon>
Copy
</button>
<button mat-menu-item>
<mat-icon>content_paste</mat-icon>
Paste
</button>
<button mat-menu-item>
<mat-icon>print</mat-icon>
Print
</button>
</mat-menu>

<div style="height: 500px">
<!-- Makes the page scrollable for easier testing. -->
</div>
10 changes: 10 additions & 0 deletions src/dev-app/menu/menu-demo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,13 @@
justify-content: flex-end;
}
}

.demo-context-menu-area {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 500px;
max-width: 500px;
outline: dashed 1px;
}
2 changes: 2 additions & 0 deletions src/material/menu/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ sass_binary(
ng_project(
name = "menu",
srcs = [
"context-menu-trigger.ts",
"index.ts",
"menu.ts",
"menu-animations.ts",
Expand All @@ -76,6 +77,7 @@ ng_project(
"menu-panel.ts",
"menu-positions.ts",
"menu-trigger.ts",
"menu-trigger-base.ts",
"module.ts",
"public-api.ts",
],
Expand Down
Loading
Loading