diff --git a/README.md b/README.md index 676073e..6698398 100644 --- a/README.md +++ b/README.md @@ -327,14 +327,14 @@ export class AppModule {} You can use the keyboard to manipulate the context menu. Note: Keyboard navigation should be used in conjunction with `autoFocus`, since key events are only captured when the context menu is focused. -| Key | Action | -|:--------------:|------------------------------------------------| -| ArrowDown | Move to next menu item (wrapping) | -| ArrowUp | Move to previous menu item (wrapping) | -| ArrowRight | Open submenu of current menu item if present | -| ArrowLeft | Close current menu unless already at root menu | -| Enter \| Space | Open submenu or execute current menu item | -| Esc | Close current menu | +| Key | Action | +|:-------------------------------:|------------------------------------------------| +| Arrow Down | Move to next menu item (wrapping) | +| Arrow Up | Move to previous menu item (wrapping) | +| Arrow Right (LTR) \/ Left (RTL) | Open submenu of current menu item if present | +| Arrow Left (LTR) \/ Right (RTL) | Close current menu unless already at root menu | +| Enter \/ Space | Open submenu or execute current menu item | +| Escape | Close current menu | ## Disable Context Menu diff --git a/projects/ngx-contextmenu/src/lib/contextMenu.component.ts b/projects/ngx-contextmenu/src/lib/contextMenu.component.ts index ed623dc..4946b08 100644 --- a/projects/ngx-contextmenu/src/lib/contextMenu.component.ts +++ b/projects/ngx-contextmenu/src/lib/contextMenu.component.ts @@ -1,18 +1,19 @@ +import { Directionality } from '@angular/cdk/bidi'; import { - ChangeDetectorRef, - Component, - ContentChildren, - ElementRef, - EventEmitter, - HostListener, - Inject, - Input, - OnDestroy, - Optional, - Output, - QueryList, - ViewChild, - ViewEncapsulation, + ChangeDetectorRef, + Component, + ContentChildren, + ElementRef, + EventEmitter, + HostListener, + Inject, + Input, + OnDestroy, + Optional, + Output, + QueryList, + ViewChild, + ViewEncapsulation, } from '@angular/core'; import { Subscription } from 'rxjs'; import { first } from 'rxjs/operators'; @@ -75,6 +76,7 @@ export class ContextMenuComponent implements OnDestroy { private _contextMenuService: ContextMenuService, private changeDetector: ChangeDetectorRef, private elementRef: ElementRef, + public directionality: Directionality, @Optional() @Inject(CONTEXT_MENU_OPTIONS) private options: IContextMenuOptions, ) { @@ -102,7 +104,12 @@ export class ContextMenuComponent implements OnDestroy { this.event = event; this.item = item; this.setVisibleMenuItems(); - this._contextMenuService.openContextMenu({ ...menuEvent, menuItems: this.visibleMenuItems, menuClass: this.menuClass }); + this._contextMenuService.openContextMenu({ + ...menuEvent, + menuItems: this.visibleMenuItems, + menuClass: this.menuClass, + directionality: this.directionality, + }); this._contextMenuService.close.asObservable().pipe(first()).subscribe(closeEvent => this.close.emit(closeEvent)); this.open.next(menuEvent); } diff --git a/projects/ngx-contextmenu/src/lib/contextMenu.service.ts b/projects/ngx-contextmenu/src/lib/contextMenu.service.ts index 123accf..c6eddf8 100644 --- a/projects/ngx-contextmenu/src/lib/contextMenu.service.ts +++ b/projects/ngx-contextmenu/src/lib/contextMenu.service.ts @@ -1,3 +1,4 @@ +import { Directionality } from '@angular/cdk/bidi'; import { Overlay, OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentRef, Injectable, ElementRef } from '@angular/core'; @@ -18,6 +19,7 @@ export interface IContextMenuClickEvent { export interface IContextMenuContext extends IContextMenuClickEvent { menuItems: ContextMenuItemDirective[]; menuClass: string; + directionality: Directionality; } export interface CloseLeafMenuEvent { exceptRootMenu?: boolean; @@ -66,7 +68,7 @@ export class ContextMenuService { ) { } public openContextMenu(context: IContextMenuContext) { - const { anchorElement, event, parentContextMenu } = context; + const { anchorElement, event, parentContextMenu, directionality } = context; if (!parentContextMenu) { const mouseEvent = event as MouseEvent; @@ -103,6 +105,7 @@ export class ContextMenuService { positionStrategy, panelClass: 'ngx-contextmenu', scrollStrategy: this.scrollStrategy.close(), + direction: directionality, })]; this.attachContextMenu(this.overlays[0], context); } else { @@ -124,6 +127,7 @@ export class ContextMenuService { positionStrategy, panelClass: 'ngx-contextmenu', scrollStrategy: this.scrollStrategy.close(), + direction: directionality, }); this.destroySubMenus(parentContextMenu); this.overlays = this.overlays.concat(newOverlay); diff --git a/projects/ngx-contextmenu/src/lib/contextMenuContent.component.ts b/projects/ngx-contextmenu/src/lib/contextMenuContent.component.ts index 6fc62a9..8336881 100644 --- a/projects/ngx-contextmenu/src/lib/contextMenuContent.component.ts +++ b/projects/ngx-contextmenu/src/lib/contextMenuContent.component.ts @@ -1,23 +1,31 @@ -import { CloseLeafMenuEvent, IContextMenuClickEvent } from './contextMenu.service'; +import { ActiveDescendantKeyManager } from '@angular/cdk/a11y'; +import { Directionality } from '@angular/cdk/bidi'; +import { LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, SPACE, ENTER, ESCAPE } from '@angular/cdk/keycodes'; import { OverlayRef } from '@angular/cdk/overlay'; import { - AfterViewInit, - ChangeDetectorRef, - Component, - ElementRef, - Inject, - Input, - Optional, - ViewChild, - ViewChildren, + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + EventEmitter, + HostListener, + Inject, + Input, + OnDestroy, + OnInit, + Optional, + Output, + QueryList, + Renderer, + ViewChild, + ViewChildren, } from '@angular/core'; -import { EventEmitter, OnDestroy, OnInit, Output, QueryList, HostListener } from '@angular/core'; import { Subscription } from 'rxjs'; import { ContextMenuItemDirective } from './contextMenu.item.directive'; import { IContextMenuOptions } from './contextMenu.options'; +import { CloseLeafMenuEvent, IContextMenuClickEvent } from './contextMenu.service'; import { CONTEXT_MENU_OPTIONS } from './contextMenu.tokens'; -import { ActiveDescendantKeyManager } from '@angular/cdk/a11y'; export interface ILinkConfig { click: (item: any, $event?: MouseEvent) => void; @@ -25,8 +33,6 @@ export interface ILinkConfig { html: (item: any) => string; } -const ARROW_LEFT_KEYCODE = 37; - @Component({ selector: 'context-menu-content', styles: [ @@ -38,13 +44,23 @@ const ARROW_LEFT_KEYCODE = 37; line-height: @line-height-base; white-space: nowrap; } - .hasSubMenu:before { + :dir(ltr) .hasSubMenu:before { content: "\u25B6"; float: right; + } + :dir(rtl) .dropdown { + direction: rtl; + } + :dir(rtl) .dropdown-menu { + text-align: right; + } + :dir(rtl) .hasSubMenu:before { + content: "\u25C0"; + float: left; }`, ], template: - `
`, }) export class ContextMenuContentComponent implements OnInit, OnDestroy, AfterViewInit { @Input() public menuItems: ContextMenuItemDirective[] = []; @@ -87,11 +102,14 @@ export class ContextMenuContentComponent implements OnInit, OnDestroy, AfterView public useBootstrap4 = false; private _keyManager: ActiveDescendantKeyManager