965 lines
45 KiB
JavaScript
965 lines
45 KiB
JavaScript
import { trigger, transition, style, animate } from '@angular/animations';
|
|
import * as i2 from '@angular/common';
|
|
import { isPlatformBrowser, DOCUMENT, CommonModule } from '@angular/common';
|
|
import * as i0 from '@angular/core';
|
|
import { PLATFORM_ID, Pipe, Inject, EventEmitter, forwardRef, Component, ViewEncapsulation, Input, Output, computed, signal, booleanAttribute, numberAttribute, ChangeDetectionStrategy, ViewChild, ContentChildren, NgModule } from '@angular/core';
|
|
import * as i3 from '@angular/router';
|
|
import { RouterModule } from '@angular/router';
|
|
import * as i5 from 'primeng/api';
|
|
import { PrimeTemplate } from 'primeng/api';
|
|
import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom';
|
|
import * as i4 from 'primeng/ripple';
|
|
import { RippleModule } from 'primeng/ripple';
|
|
import * as i6 from 'primeng/tooltip';
|
|
import { TooltipModule } from 'primeng/tooltip';
|
|
import { UniqueComponentId, ZIndexUtils } from 'primeng/utils';
|
|
import * as i1 from '@angular/platform-browser';
|
|
|
|
class SafeHtmlPipe {
|
|
platformId;
|
|
sanitizer;
|
|
constructor(platformId, sanitizer) {
|
|
this.platformId = platformId;
|
|
this.sanitizer = sanitizer;
|
|
}
|
|
transform(value) {
|
|
if (!value || !isPlatformBrowser(this.platformId)) {
|
|
return value;
|
|
}
|
|
return this.sanitizer.bypassSecurityTrustHtml(value);
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: PLATFORM_ID }, { token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
|
|
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "17.3.7", ngImport: i0, type: SafeHtmlPipe, name: "safeHtml" });
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: SafeHtmlPipe, decorators: [{
|
|
type: Pipe,
|
|
args: [{
|
|
name: 'safeHtml'
|
|
}]
|
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }, { type: i1.DomSanitizer }] });
|
|
class MenuItemContent {
|
|
item;
|
|
itemTemplate;
|
|
onMenuItemClick = new EventEmitter();
|
|
menu;
|
|
constructor(menu) {
|
|
this.menu = menu;
|
|
}
|
|
onItemClick(event, item) {
|
|
this.onMenuItemClick.emit({ originalEvent: event, item });
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: MenuItemContent, deps: [{ token: forwardRef(() => Menu) }], target: i0.ɵɵFactoryTarget.Component });
|
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.7", type: MenuItemContent, selector: "[pMenuItemContent]", inputs: { item: ["pMenuItemContent", "item"], itemTemplate: "itemTemplate" }, outputs: { onMenuItemClick: "onMenuItemClick" }, host: { classAttribute: "p-element" }, ngImport: i0, template: `
|
|
<div [attr.data-pc-section]="'content'" class="p-menuitem-content" (click)="onItemClick($event, item)">
|
|
<ng-container *ngIf="!itemTemplate">
|
|
<a
|
|
*ngIf="!item?.routerLink"
|
|
[attr.title]="item.title"
|
|
[attr.href]="item.url || null"
|
|
[attr.data-automationid]="item.automationId"
|
|
[attr.tabindex]="-1"
|
|
[attr.data-pc-section]="'action'"
|
|
[attr.aria-hidden]="true"
|
|
class="p-menuitem-link"
|
|
[target]="item.target"
|
|
[ngClass]="{ 'p-disabled': item.disabled }"
|
|
pRipple
|
|
>
|
|
<ng-container *ngTemplateOutlet="itemContent; context: { $implicit: item }"></ng-container>
|
|
</a>
|
|
<a
|
|
*ngIf="item?.routerLink"
|
|
[routerLink]="item.routerLink"
|
|
[attr.data-automationid]="item.automationId"
|
|
[attr.tabindex]="-1"
|
|
[attr.data-pc-section]="'action'"
|
|
[attr.aria-hidden]="true"
|
|
[attr.title]="item.title"
|
|
[queryParams]="item.queryParams"
|
|
routerLinkActive="p-menuitem-link-active"
|
|
[routerLinkActiveOptions]="item.routerLinkActiveOptions || { exact: false }"
|
|
class="p-menuitem-link"
|
|
[target]="item.target"
|
|
[ngClass]="{ 'p-disabled': item.disabled }"
|
|
[fragment]="item.fragment"
|
|
[queryParamsHandling]="item.queryParamsHandling"
|
|
[preserveFragment]="item.preserveFragment"
|
|
[skipLocationChange]="item.skipLocationChange"
|
|
[replaceUrl]="item.replaceUrl"
|
|
[state]="item.state"
|
|
pRipple
|
|
>
|
|
<ng-container *ngTemplateOutlet="itemContent; context: { $implicit: item }"></ng-container>
|
|
</a>
|
|
</ng-container>
|
|
|
|
<ng-container *ngIf="itemTemplate">
|
|
<ng-template *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-template>
|
|
</ng-container>
|
|
|
|
<ng-template #itemContent>
|
|
<span class="p-menuitem-icon" *ngIf="item.icon" [ngClass]="item.icon" [class]="item.iconClass" [ngStyle]="item.iconStyle"></span>
|
|
<span class="p-menuitem-text" *ngIf="item.escape !== false; else htmlLabel">{{ item.label }}</span>
|
|
<ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="item.label | safeHtml"></span></ng-template>
|
|
<span class="p-menuitem-badge" *ngIf="item.badge" [ngClass]="item.badgeStyleClass">{{ item.badge }}</span>
|
|
</ng-template>
|
|
</div>
|
|
`, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i4.Ripple, selector: "[pRipple]" }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], encapsulation: i0.ViewEncapsulation.None });
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: MenuItemContent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: '[pMenuItemContent]',
|
|
template: `
|
|
<div [attr.data-pc-section]="'content'" class="p-menuitem-content" (click)="onItemClick($event, item)">
|
|
<ng-container *ngIf="!itemTemplate">
|
|
<a
|
|
*ngIf="!item?.routerLink"
|
|
[attr.title]="item.title"
|
|
[attr.href]="item.url || null"
|
|
[attr.data-automationid]="item.automationId"
|
|
[attr.tabindex]="-1"
|
|
[attr.data-pc-section]="'action'"
|
|
[attr.aria-hidden]="true"
|
|
class="p-menuitem-link"
|
|
[target]="item.target"
|
|
[ngClass]="{ 'p-disabled': item.disabled }"
|
|
pRipple
|
|
>
|
|
<ng-container *ngTemplateOutlet="itemContent; context: { $implicit: item }"></ng-container>
|
|
</a>
|
|
<a
|
|
*ngIf="item?.routerLink"
|
|
[routerLink]="item.routerLink"
|
|
[attr.data-automationid]="item.automationId"
|
|
[attr.tabindex]="-1"
|
|
[attr.data-pc-section]="'action'"
|
|
[attr.aria-hidden]="true"
|
|
[attr.title]="item.title"
|
|
[queryParams]="item.queryParams"
|
|
routerLinkActive="p-menuitem-link-active"
|
|
[routerLinkActiveOptions]="item.routerLinkActiveOptions || { exact: false }"
|
|
class="p-menuitem-link"
|
|
[target]="item.target"
|
|
[ngClass]="{ 'p-disabled': item.disabled }"
|
|
[fragment]="item.fragment"
|
|
[queryParamsHandling]="item.queryParamsHandling"
|
|
[preserveFragment]="item.preserveFragment"
|
|
[skipLocationChange]="item.skipLocationChange"
|
|
[replaceUrl]="item.replaceUrl"
|
|
[state]="item.state"
|
|
pRipple
|
|
>
|
|
<ng-container *ngTemplateOutlet="itemContent; context: { $implicit: item }"></ng-container>
|
|
</a>
|
|
</ng-container>
|
|
|
|
<ng-container *ngIf="itemTemplate">
|
|
<ng-template *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-template>
|
|
</ng-container>
|
|
|
|
<ng-template #itemContent>
|
|
<span class="p-menuitem-icon" *ngIf="item.icon" [ngClass]="item.icon" [class]="item.iconClass" [ngStyle]="item.iconStyle"></span>
|
|
<span class="p-menuitem-text" *ngIf="item.escape !== false; else htmlLabel">{{ item.label }}</span>
|
|
<ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="item.label | safeHtml"></span></ng-template>
|
|
<span class="p-menuitem-badge" *ngIf="item.badge" [ngClass]="item.badgeStyleClass">{{ item.badge }}</span>
|
|
</ng-template>
|
|
</div>
|
|
`,
|
|
encapsulation: ViewEncapsulation.None,
|
|
host: {
|
|
class: 'p-element'
|
|
}
|
|
}]
|
|
}], ctorParameters: () => [{ type: Menu, decorators: [{
|
|
type: Inject,
|
|
args: [forwardRef(() => Menu)]
|
|
}] }], propDecorators: { item: [{
|
|
type: Input,
|
|
args: ['pMenuItemContent']
|
|
}], itemTemplate: [{
|
|
type: Input
|
|
}], onMenuItemClick: [{
|
|
type: Output
|
|
}] } });
|
|
/**
|
|
* Menu is a navigation / command component that supports dynamic and static positioning.
|
|
* @group Components
|
|
*/
|
|
class Menu {
|
|
document;
|
|
platformId;
|
|
el;
|
|
renderer;
|
|
cd;
|
|
config;
|
|
overlayService;
|
|
/**
|
|
* An array of menuitems.
|
|
* @group Props
|
|
*/
|
|
model;
|
|
/**
|
|
* Defines if menu would displayed as a popup.
|
|
* @group Props
|
|
*/
|
|
popup;
|
|
/**
|
|
* Inline style of the component.
|
|
* @group Props
|
|
*/
|
|
style;
|
|
/**
|
|
* Style class of the component.
|
|
* @group Props
|
|
*/
|
|
styleClass;
|
|
/**
|
|
* Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]="mydiv" for a div element having #mydiv as variable name).
|
|
* @group Props
|
|
*/
|
|
appendTo;
|
|
/**
|
|
* Whether to automatically manage layering.
|
|
* @group Props
|
|
*/
|
|
autoZIndex = true;
|
|
/**
|
|
* Base zIndex value to use in layering.
|
|
* @group Props
|
|
*/
|
|
baseZIndex = 0;
|
|
/**
|
|
* Transition options of the show animation.
|
|
* @group Props
|
|
*/
|
|
showTransitionOptions = '.12s cubic-bezier(0, 0, 0.2, 1)';
|
|
/**
|
|
* Transition options of the hide animation.
|
|
* @group Props
|
|
*/
|
|
hideTransitionOptions = '.1s linear';
|
|
/**
|
|
* Defines a string value that labels an interactive element.
|
|
* @group Props
|
|
*/
|
|
ariaLabel;
|
|
/**
|
|
* Identifier of the underlying input element.
|
|
* @group Props
|
|
*/
|
|
ariaLabelledBy;
|
|
/**
|
|
* Current id state as a string.
|
|
* @group Props
|
|
*/
|
|
id;
|
|
/**
|
|
* Index of the element in tabbing order.
|
|
* @group Props
|
|
*/
|
|
tabindex = 0;
|
|
/**
|
|
* Callback to invoke when overlay menu is shown.
|
|
* @group Emits
|
|
*/
|
|
onShow = new EventEmitter();
|
|
/**
|
|
* Callback to invoke when overlay menu is hidden.
|
|
* @group Emits
|
|
*/
|
|
onHide = new EventEmitter();
|
|
/**
|
|
* Callback to invoke when the list loses focus.
|
|
* @param {Event} event - blur event.
|
|
* @group Emits
|
|
*/
|
|
onBlur = new EventEmitter();
|
|
/**
|
|
* Callback to invoke when the list receives focus.
|
|
* @param {Event} event - focus event.
|
|
* @group Emits
|
|
*/
|
|
onFocus = new EventEmitter();
|
|
listViewChild;
|
|
containerViewChild;
|
|
templates;
|
|
startTemplate;
|
|
endTemplate;
|
|
itemTemplate;
|
|
submenuHeaderTemplate;
|
|
container;
|
|
scrollHandler;
|
|
documentClickListener;
|
|
documentResizeListener;
|
|
preventDocumentDefault;
|
|
target;
|
|
visible;
|
|
focusedOptionId = computed(() => {
|
|
return this.focusedOptionIndex() !== -1 ? this.focusedOptionIndex() : null;
|
|
});
|
|
focusedOptionIndex = signal(-1);
|
|
selectedOptionIndex = signal(-1);
|
|
focused = false;
|
|
overlayVisible = false;
|
|
relativeAlign;
|
|
constructor(document, platformId, el, renderer, cd, config, overlayService) {
|
|
this.document = document;
|
|
this.platformId = platformId;
|
|
this.el = el;
|
|
this.renderer = renderer;
|
|
this.cd = cd;
|
|
this.config = config;
|
|
this.overlayService = overlayService;
|
|
this.id = this.id || UniqueComponentId();
|
|
}
|
|
/**
|
|
* Toggles the visibility of the popup menu.
|
|
* @param {Event} event - Browser event.
|
|
* @group Method
|
|
*/
|
|
toggle(event) {
|
|
if (this.visible)
|
|
this.hide();
|
|
else
|
|
this.show(event);
|
|
this.preventDocumentDefault = true;
|
|
}
|
|
/**
|
|
* Displays the popup menu.
|
|
* @param {Event} event - Browser event.
|
|
* @group Method
|
|
*/
|
|
show(event) {
|
|
this.target = event.currentTarget;
|
|
this.relativeAlign = event.relativeAlign;
|
|
this.visible = true;
|
|
this.preventDocumentDefault = true;
|
|
this.overlayVisible = true;
|
|
this.cd.markForCheck();
|
|
}
|
|
ngOnInit() {
|
|
if (!this.popup) {
|
|
this.bindDocumentClickListener();
|
|
}
|
|
}
|
|
ngAfterContentInit() {
|
|
this.templates?.forEach((item) => {
|
|
switch (item.getType()) {
|
|
case 'start':
|
|
this.startTemplate = item.template;
|
|
break;
|
|
case 'end':
|
|
this.endTemplate = item.template;
|
|
break;
|
|
case 'itemTemplate':
|
|
this.itemTemplate = item.template;
|
|
break;
|
|
case 'submenuheader':
|
|
this.submenuHeaderTemplate = item.template;
|
|
break;
|
|
default:
|
|
this.itemTemplate = item.template;
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
getTabIndexValue() {
|
|
return this.tabindex !== undefined ? this.tabindex.toString() : null;
|
|
}
|
|
onOverlayAnimationStart(event) {
|
|
switch (event.toState) {
|
|
case 'visible':
|
|
if (this.popup) {
|
|
this.container = event.element;
|
|
this.moveOnTop();
|
|
this.onShow.emit({});
|
|
this.appendOverlay();
|
|
this.alignOverlay();
|
|
this.bindDocumentClickListener();
|
|
this.bindDocumentResizeListener();
|
|
this.bindScrollListener();
|
|
DomHandler.focus(this.listViewChild.nativeElement);
|
|
}
|
|
break;
|
|
case 'void':
|
|
this.onOverlayHide();
|
|
this.onHide.emit({});
|
|
break;
|
|
}
|
|
}
|
|
onOverlayAnimationEnd(event) {
|
|
switch (event.toState) {
|
|
case 'void':
|
|
if (this.autoZIndex) {
|
|
ZIndexUtils.clear(event.element);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
alignOverlay() {
|
|
if (this.relativeAlign)
|
|
DomHandler.relativePosition(this.container, this.target);
|
|
else
|
|
DomHandler.absolutePosition(this.container, this.target);
|
|
}
|
|
appendOverlay() {
|
|
if (this.appendTo) {
|
|
if (this.appendTo === 'body')
|
|
this.renderer.appendChild(this.document.body, this.container);
|
|
else
|
|
DomHandler.appendChild(this.container, this.appendTo);
|
|
}
|
|
}
|
|
restoreOverlayAppend() {
|
|
if (this.container && this.appendTo) {
|
|
this.renderer.appendChild(this.el.nativeElement, this.container);
|
|
}
|
|
}
|
|
moveOnTop() {
|
|
if (this.autoZIndex) {
|
|
ZIndexUtils.set('menu', this.container, this.baseZIndex + this.config.zIndex.menu);
|
|
}
|
|
}
|
|
/**
|
|
* Hides the popup menu.
|
|
* @group Method
|
|
*/
|
|
hide() {
|
|
this.visible = false;
|
|
this.relativeAlign = false;
|
|
this.cd.markForCheck();
|
|
}
|
|
onWindowResize() {
|
|
if (this.visible && !DomHandler.isTouchDevice()) {
|
|
this.hide();
|
|
}
|
|
}
|
|
menuitemId(item, id, index, childIndex) {
|
|
return item?.id ?? `${id}_${index}${childIndex !== undefined ? '_' + childIndex : ''}`;
|
|
}
|
|
isItemFocused(id) {
|
|
return this.focusedOptionId() === id;
|
|
}
|
|
label(label) {
|
|
return typeof label === 'function' ? label() : label;
|
|
}
|
|
disabled(disabled) {
|
|
return typeof disabled === 'function' ? disabled() : typeof disabled === 'undefined' ? false : disabled;
|
|
}
|
|
activedescendant() {
|
|
return this.focused ? this.focusedOptionId() : undefined;
|
|
}
|
|
onListFocus(event) {
|
|
if (!this.focused) {
|
|
this.focused = true;
|
|
this.onFocus.emit(event);
|
|
}
|
|
}
|
|
onListBlur(event) {
|
|
if (this.focused) {
|
|
this.focused = false;
|
|
this.changeFocusedOptionIndex(-1);
|
|
this.selectedOptionIndex.set(-1);
|
|
this.focusedOptionIndex.set(-1);
|
|
this.onBlur.emit(event);
|
|
}
|
|
}
|
|
onListKeyDown(event) {
|
|
switch (event.code) {
|
|
case 'ArrowDown':
|
|
this.onArrowDownKey(event);
|
|
break;
|
|
case 'ArrowUp':
|
|
this.onArrowUpKey(event);
|
|
break;
|
|
case 'Home':
|
|
this.onHomeKey(event);
|
|
break;
|
|
case 'End':
|
|
this.onEndKey(event);
|
|
break;
|
|
case 'Enter':
|
|
this.onEnterKey(event);
|
|
break;
|
|
case 'NumpadEnter':
|
|
this.onEnterKey(event);
|
|
break;
|
|
case 'Space':
|
|
this.onSpaceKey(event);
|
|
break;
|
|
case 'Escape':
|
|
case 'Tab':
|
|
if (this.popup) {
|
|
DomHandler.focus(this.target);
|
|
this.hide();
|
|
}
|
|
this.overlayVisible && this.hide();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
onArrowDownKey(event) {
|
|
const optionIndex = this.findNextOptionIndex(this.focusedOptionIndex());
|
|
this.changeFocusedOptionIndex(optionIndex);
|
|
event.preventDefault();
|
|
}
|
|
onArrowUpKey(event) {
|
|
if (event.altKey && this.popup) {
|
|
DomHandler.focus(this.target);
|
|
this.hide();
|
|
event.preventDefault();
|
|
}
|
|
else {
|
|
const optionIndex = this.findPrevOptionIndex(this.focusedOptionIndex());
|
|
this.changeFocusedOptionIndex(optionIndex);
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
onHomeKey(event) {
|
|
this.changeFocusedOptionIndex(0);
|
|
event.preventDefault();
|
|
}
|
|
onEndKey(event) {
|
|
this.changeFocusedOptionIndex(DomHandler.find(this.containerViewChild.nativeElement, 'li[data-pc-section="menuitem"][data-p-disabled="false"]').length - 1);
|
|
event.preventDefault();
|
|
}
|
|
onEnterKey(event) {
|
|
const element = DomHandler.findSingle(this.containerViewChild.nativeElement, `li[id="${`${this.focusedOptionIndex()}`}"]`);
|
|
const anchorElement = element && DomHandler.findSingle(element, 'a[data-pc-section="action"]');
|
|
this.popup && DomHandler.focus(this.target);
|
|
anchorElement ? anchorElement.click() : element && element.click();
|
|
event.preventDefault();
|
|
}
|
|
onSpaceKey(event) {
|
|
this.onEnterKey(event);
|
|
}
|
|
findNextOptionIndex(index) {
|
|
const links = DomHandler.find(this.containerViewChild.nativeElement, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
|
const matchedOptionIndex = [...links].findIndex((link) => link.id === index);
|
|
return matchedOptionIndex > -1 ? matchedOptionIndex + 1 : 0;
|
|
}
|
|
findPrevOptionIndex(index) {
|
|
const links = DomHandler.find(this.containerViewChild.nativeElement, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
|
const matchedOptionIndex = [...links].findIndex((link) => link.id === index);
|
|
return matchedOptionIndex > -1 ? matchedOptionIndex - 1 : 0;
|
|
}
|
|
changeFocusedOptionIndex(index) {
|
|
const links = DomHandler.find(this.containerViewChild.nativeElement, 'li[data-pc-section="menuitem"][data-p-disabled="false"]');
|
|
if (links.length > 0) {
|
|
let order = index >= links.length ? links.length - 1 : index < 0 ? 0 : index;
|
|
order > -1 && this.focusedOptionIndex.set(links[order].getAttribute('id'));
|
|
}
|
|
}
|
|
itemClick(event, id) {
|
|
const { originalEvent, item } = event;
|
|
if (!this.focused) {
|
|
this.focused = true;
|
|
this.onFocus.emit();
|
|
}
|
|
if (item.disabled) {
|
|
originalEvent.preventDefault();
|
|
return;
|
|
}
|
|
if (!item.url && !item.routerLink) {
|
|
originalEvent.preventDefault();
|
|
}
|
|
if (item.command) {
|
|
item.command({
|
|
originalEvent: originalEvent,
|
|
item: item
|
|
});
|
|
}
|
|
if (this.popup) {
|
|
this.hide();
|
|
}
|
|
if (!this.popup && this.focusedOptionIndex() !== id) {
|
|
this.focusedOptionIndex.set(id);
|
|
}
|
|
}
|
|
onOverlayClick(event) {
|
|
if (this.popup) {
|
|
this.overlayService.add({
|
|
originalEvent: event,
|
|
target: this.el.nativeElement
|
|
});
|
|
}
|
|
this.preventDocumentDefault = true;
|
|
}
|
|
bindDocumentClickListener() {
|
|
if (!this.documentClickListener && isPlatformBrowser(this.platformId)) {
|
|
const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
|
|
this.documentClickListener = this.renderer.listen(documentTarget, 'click', (event) => {
|
|
const isOutsideContainer = this.containerViewChild.nativeElement && !this.containerViewChild.nativeElement.contains(event.target);
|
|
const isOutsideTarget = !(this.target && (this.target === event.target || this.target.contains(event.target)));
|
|
if (!this.popup && isOutsideContainer && isOutsideTarget) {
|
|
this.onListBlur(event);
|
|
}
|
|
if (this.preventDocumentDefault && this.overlayVisible && isOutsideContainer && isOutsideTarget) {
|
|
this.hide();
|
|
this.preventDocumentDefault = false;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
unbindDocumentClickListener() {
|
|
if (this.documentClickListener) {
|
|
this.documentClickListener();
|
|
this.documentClickListener = null;
|
|
}
|
|
}
|
|
bindDocumentResizeListener() {
|
|
if (!this.documentResizeListener && isPlatformBrowser(this.platformId)) {
|
|
const window = this.document.defaultView;
|
|
this.documentResizeListener = this.renderer.listen(window, 'resize', this.onWindowResize.bind(this));
|
|
}
|
|
}
|
|
unbindDocumentResizeListener() {
|
|
if (this.documentResizeListener) {
|
|
this.documentResizeListener();
|
|
this.documentResizeListener = null;
|
|
}
|
|
}
|
|
bindScrollListener() {
|
|
if (!this.scrollHandler && isPlatformBrowser(this.platformId)) {
|
|
this.scrollHandler = new ConnectedOverlayScrollHandler(this.target, () => {
|
|
if (this.visible) {
|
|
this.hide();
|
|
}
|
|
});
|
|
}
|
|
this.scrollHandler?.bindScrollListener();
|
|
}
|
|
unbindScrollListener() {
|
|
if (this.scrollHandler) {
|
|
this.scrollHandler.unbindScrollListener();
|
|
}
|
|
}
|
|
onOverlayHide() {
|
|
this.unbindDocumentClickListener();
|
|
this.unbindDocumentResizeListener();
|
|
this.unbindScrollListener();
|
|
this.preventDocumentDefault = false;
|
|
if (!this.cd.destroyed) {
|
|
this.target = null;
|
|
}
|
|
}
|
|
ngOnDestroy() {
|
|
if (this.popup) {
|
|
if (this.scrollHandler) {
|
|
this.scrollHandler.destroy();
|
|
this.scrollHandler = null;
|
|
}
|
|
if (this.container && this.autoZIndex) {
|
|
ZIndexUtils.clear(this.container);
|
|
}
|
|
this.restoreOverlayAppend();
|
|
this.onOverlayHide();
|
|
}
|
|
if (!this.popup) {
|
|
this.unbindDocumentClickListener();
|
|
}
|
|
}
|
|
hasSubMenu() {
|
|
if (this.model) {
|
|
for (var item of this.model) {
|
|
if (item.items) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
isItemHidden(item) {
|
|
if (item.separator) {
|
|
return item.visible === false || (item.items && item.items.some((subitem) => subitem.visible !== false));
|
|
}
|
|
return item.visible === false;
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: Menu, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i5.PrimeNGConfig }, { token: i5.OverlayService }], target: i0.ɵɵFactoryTarget.Component });
|
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "17.3.7", type: Menu, selector: "p-menu", inputs: { model: "model", popup: ["popup", "popup", booleanAttribute], style: "style", styleClass: "styleClass", appendTo: "appendTo", autoZIndex: ["autoZIndex", "autoZIndex", booleanAttribute], baseZIndex: ["baseZIndex", "baseZIndex", numberAttribute], showTransitionOptions: "showTransitionOptions", hideTransitionOptions: "hideTransitionOptions", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", id: "id", tabindex: ["tabindex", "tabindex", numberAttribute] }, outputs: { onShow: "onShow", onHide: "onHide", onBlur: "onBlur", onFocus: "onFocus" }, host: { classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "listViewChild", first: true, predicate: ["list"], descendants: true }, { propertyName: "containerViewChild", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
|
|
<div
|
|
#container
|
|
[ngClass]="{ 'p-menu p-component': true, 'p-menu-overlay': popup }"
|
|
[class]="styleClass"
|
|
[ngStyle]="style"
|
|
*ngIf="!popup || visible"
|
|
(click)="onOverlayClick($event)"
|
|
[@overlayAnimation]="{ value: 'visible', params: { showTransitionParams: showTransitionOptions, hideTransitionParams: hideTransitionOptions } }"
|
|
[@.disabled]="popup !== true"
|
|
(@overlayAnimation.start)="onOverlayAnimationStart($event)"
|
|
(@overlayAnimation.done)="onOverlayAnimationEnd($event)"
|
|
[attr.data-pc-name]="'menu'"
|
|
[attr.id]="id"
|
|
>
|
|
<div *ngIf="startTemplate" class="p-menu-start" [attr.data-pc-section]="'start'">
|
|
<ng-container *ngTemplateOutlet="startTemplate"></ng-container>
|
|
</div>
|
|
<ul
|
|
#list
|
|
class="p-menu-list p-reset"
|
|
role="menu"
|
|
[attr.id]="id + '_list'"
|
|
[attr.tabindex]="getTabIndexValue()"
|
|
[attr.data-pc-section]="'menu'"
|
|
[attr.aria-activedescendant]="activedescendant()"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.aria-labelledBy]="ariaLabelledBy"
|
|
(focus)="onListFocus($event)"
|
|
(blur)="onListBlur($event)"
|
|
(keydown)="onListKeyDown($event)"
|
|
>
|
|
<ng-template ngFor let-submenu let-i="index" [ngForOf]="model" *ngIf="hasSubMenu()">
|
|
<li class="p-menuitem-separator" *ngIf="submenu.separator" [ngClass]="{ 'p-hidden': submenu.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-submenu-header"
|
|
[attr.data-automationid]="submenu.automationId"
|
|
*ngIf="!submenu.separator"
|
|
[ngClass]="{ 'p-hidden': submenu.visible === false, flex: submenu.visible }"
|
|
pTooltip
|
|
[tooltipOptions]="submenu.tooltipOptions"
|
|
role="none"
|
|
[attr.id]="menuitemId(submenu, id, i)"
|
|
>
|
|
<ng-container *ngIf="!submenuHeaderTemplate">
|
|
<span *ngIf="submenu.escape !== false; else htmlSubmenuLabel">{{ submenu.label }}</span>
|
|
<ng-template #htmlSubmenuLabel><span [innerHTML]="submenu.label | safeHtml"></span></ng-template>
|
|
</ng-container>
|
|
<ng-container *ngTemplateOutlet="submenuHeaderTemplate; context: { $implicit: submenu }"></ng-container>
|
|
</li>
|
|
<ng-template ngFor let-item let-j="index" [ngForOf]="submenu.items">
|
|
<li class="p-menuitem-separator" *ngIf="item.separator" [ngClass]="{ 'p-hidden': item.visible === false || submenu.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-menuitem"
|
|
*ngIf="!item.separator"
|
|
[pMenuItemContent]="item"
|
|
[itemTemplate]="itemTemplate"
|
|
[ngClass]="{ 'p-hidden': item.visible === false || submenu.visible === false, 'p-focus': focusedOptionId() && menuitemId(item, id, i, j) === focusedOptionId(), 'p-disabled': disabled(item.disabled) }"
|
|
[ngStyle]="item.style"
|
|
[class]="item.styleClass"
|
|
(onMenuItemClick)="itemClick($event, menuitemId(item, id, i, j))"
|
|
pTooltip
|
|
[tooltipOptions]="item.tooltipOptions"
|
|
role="menuitem"
|
|
[attr.data-pc-section]="'menuitem'"
|
|
[attr.aria-label]="label(item.label)"
|
|
[attr.data-p-focused]="isItemFocused(menuitemId(item, id, i, j))"
|
|
[attr.data-p-disabled]="disabled(item.disabled)"
|
|
[attr.aria-disabled]="disabled(item.disabled)"
|
|
[attr.id]="menuitemId(item, id, i, j)"
|
|
></li>
|
|
</ng-template>
|
|
</ng-template>
|
|
<ng-template ngFor let-item let-i="index" [ngForOf]="model" *ngIf="!hasSubMenu()">
|
|
<li class="p-menuitem-separator" *ngIf="item.separator" [ngClass]="{ 'p-hidden': item.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-menuitem"
|
|
*ngIf="!item.separator"
|
|
[pMenuItemContent]="item"
|
|
[itemTemplate]="itemTemplate"
|
|
[ngClass]="{ 'p-hidden': item.visible === false, 'p-focus': focusedOptionId() && menuitemId(item, id, i, j) === focusedOptionId(), 'p-disabled': disabled(item.disabled) }"
|
|
[ngStyle]="item.style"
|
|
[class]="item.styleClass"
|
|
(onMenuItemClick)="itemClick($event, menuitemId(item, id, i))"
|
|
pTooltip
|
|
[tooltipOptions]="item.tooltipOptions"
|
|
role="menuitem"
|
|
[attr.data-pc-section]="'menuitem'"
|
|
[attr.aria-label]="label(item.label)"
|
|
[attr.data-p-focused]="isItemFocused(menuitemId(item, id, i))"
|
|
[attr.data-p-disabled]="disabled(item.disabled)"
|
|
[attr.aria-disabled]="disabled(item.disabled)"
|
|
[attr.id]="menuitemId(item, id, i)"
|
|
></li>
|
|
</ng-template>
|
|
</ul>
|
|
<div *ngIf="endTemplate" class="p-menu-end" [attr.data-pc-section]="'end'">
|
|
<ng-container *ngTemplateOutlet="endTemplate"></ng-container>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: ["@layer primeng{.p-menu-overlay{position:absolute;top:0;left:0}.p-menu ul{margin:0;padding:0;list-style:none}.p-menu .p-submenu-header{align-items:center}.p-menu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-menu .p-menuitem-text{line-height:1}}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: MenuItemContent, selector: "[pMenuItemContent]", inputs: ["pMenuItemContent", "itemTemplate"], outputs: ["onMenuItemClick"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0, transform: 'scaleY(0.8)' }), animate('{{showTransitionParams}}')]), transition(':leave', [animate('{{hideTransitionParams}}', style({ opacity: 0 }))])])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: Menu, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'p-menu', template: `
|
|
<div
|
|
#container
|
|
[ngClass]="{ 'p-menu p-component': true, 'p-menu-overlay': popup }"
|
|
[class]="styleClass"
|
|
[ngStyle]="style"
|
|
*ngIf="!popup || visible"
|
|
(click)="onOverlayClick($event)"
|
|
[@overlayAnimation]="{ value: 'visible', params: { showTransitionParams: showTransitionOptions, hideTransitionParams: hideTransitionOptions } }"
|
|
[@.disabled]="popup !== true"
|
|
(@overlayAnimation.start)="onOverlayAnimationStart($event)"
|
|
(@overlayAnimation.done)="onOverlayAnimationEnd($event)"
|
|
[attr.data-pc-name]="'menu'"
|
|
[attr.id]="id"
|
|
>
|
|
<div *ngIf="startTemplate" class="p-menu-start" [attr.data-pc-section]="'start'">
|
|
<ng-container *ngTemplateOutlet="startTemplate"></ng-container>
|
|
</div>
|
|
<ul
|
|
#list
|
|
class="p-menu-list p-reset"
|
|
role="menu"
|
|
[attr.id]="id + '_list'"
|
|
[attr.tabindex]="getTabIndexValue()"
|
|
[attr.data-pc-section]="'menu'"
|
|
[attr.aria-activedescendant]="activedescendant()"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.aria-labelledBy]="ariaLabelledBy"
|
|
(focus)="onListFocus($event)"
|
|
(blur)="onListBlur($event)"
|
|
(keydown)="onListKeyDown($event)"
|
|
>
|
|
<ng-template ngFor let-submenu let-i="index" [ngForOf]="model" *ngIf="hasSubMenu()">
|
|
<li class="p-menuitem-separator" *ngIf="submenu.separator" [ngClass]="{ 'p-hidden': submenu.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-submenu-header"
|
|
[attr.data-automationid]="submenu.automationId"
|
|
*ngIf="!submenu.separator"
|
|
[ngClass]="{ 'p-hidden': submenu.visible === false, flex: submenu.visible }"
|
|
pTooltip
|
|
[tooltipOptions]="submenu.tooltipOptions"
|
|
role="none"
|
|
[attr.id]="menuitemId(submenu, id, i)"
|
|
>
|
|
<ng-container *ngIf="!submenuHeaderTemplate">
|
|
<span *ngIf="submenu.escape !== false; else htmlSubmenuLabel">{{ submenu.label }}</span>
|
|
<ng-template #htmlSubmenuLabel><span [innerHTML]="submenu.label | safeHtml"></span></ng-template>
|
|
</ng-container>
|
|
<ng-container *ngTemplateOutlet="submenuHeaderTemplate; context: { $implicit: submenu }"></ng-container>
|
|
</li>
|
|
<ng-template ngFor let-item let-j="index" [ngForOf]="submenu.items">
|
|
<li class="p-menuitem-separator" *ngIf="item.separator" [ngClass]="{ 'p-hidden': item.visible === false || submenu.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-menuitem"
|
|
*ngIf="!item.separator"
|
|
[pMenuItemContent]="item"
|
|
[itemTemplate]="itemTemplate"
|
|
[ngClass]="{ 'p-hidden': item.visible === false || submenu.visible === false, 'p-focus': focusedOptionId() && menuitemId(item, id, i, j) === focusedOptionId(), 'p-disabled': disabled(item.disabled) }"
|
|
[ngStyle]="item.style"
|
|
[class]="item.styleClass"
|
|
(onMenuItemClick)="itemClick($event, menuitemId(item, id, i, j))"
|
|
pTooltip
|
|
[tooltipOptions]="item.tooltipOptions"
|
|
role="menuitem"
|
|
[attr.data-pc-section]="'menuitem'"
|
|
[attr.aria-label]="label(item.label)"
|
|
[attr.data-p-focused]="isItemFocused(menuitemId(item, id, i, j))"
|
|
[attr.data-p-disabled]="disabled(item.disabled)"
|
|
[attr.aria-disabled]="disabled(item.disabled)"
|
|
[attr.id]="menuitemId(item, id, i, j)"
|
|
></li>
|
|
</ng-template>
|
|
</ng-template>
|
|
<ng-template ngFor let-item let-i="index" [ngForOf]="model" *ngIf="!hasSubMenu()">
|
|
<li class="p-menuitem-separator" *ngIf="item.separator" [ngClass]="{ 'p-hidden': item.visible === false }" role="separator"></li>
|
|
<li
|
|
class="p-menuitem"
|
|
*ngIf="!item.separator"
|
|
[pMenuItemContent]="item"
|
|
[itemTemplate]="itemTemplate"
|
|
[ngClass]="{ 'p-hidden': item.visible === false, 'p-focus': focusedOptionId() && menuitemId(item, id, i, j) === focusedOptionId(), 'p-disabled': disabled(item.disabled) }"
|
|
[ngStyle]="item.style"
|
|
[class]="item.styleClass"
|
|
(onMenuItemClick)="itemClick($event, menuitemId(item, id, i))"
|
|
pTooltip
|
|
[tooltipOptions]="item.tooltipOptions"
|
|
role="menuitem"
|
|
[attr.data-pc-section]="'menuitem'"
|
|
[attr.aria-label]="label(item.label)"
|
|
[attr.data-p-focused]="isItemFocused(menuitemId(item, id, i))"
|
|
[attr.data-p-disabled]="disabled(item.disabled)"
|
|
[attr.aria-disabled]="disabled(item.disabled)"
|
|
[attr.id]="menuitemId(item, id, i)"
|
|
></li>
|
|
</ng-template>
|
|
</ul>
|
|
<div *ngIf="endTemplate" class="p-menu-end" [attr.data-pc-section]="'end'">
|
|
<ng-container *ngTemplateOutlet="endTemplate"></ng-container>
|
|
</div>
|
|
</div>
|
|
`, animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0, transform: 'scaleY(0.8)' }), animate('{{showTransitionParams}}')]), transition(':leave', [animate('{{hideTransitionParams}}', style({ opacity: 0 }))])])], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
class: 'p-element'
|
|
}, styles: ["@layer primeng{.p-menu-overlay{position:absolute;top:0;left:0}.p-menu ul{margin:0;padding:0;list-style:none}.p-menu .p-submenu-header{align-items:center}.p-menu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-menu .p-menuitem-text{line-height:1}}\n"] }]
|
|
}], ctorParameters: () => [{ type: Document, decorators: [{
|
|
type: Inject,
|
|
args: [DOCUMENT]
|
|
}] }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i5.PrimeNGConfig }, { type: i5.OverlayService }], propDecorators: { model: [{
|
|
type: Input
|
|
}], popup: [{
|
|
type: Input,
|
|
args: [{ transform: booleanAttribute }]
|
|
}], style: [{
|
|
type: Input
|
|
}], styleClass: [{
|
|
type: Input
|
|
}], appendTo: [{
|
|
type: Input
|
|
}], autoZIndex: [{
|
|
type: Input,
|
|
args: [{ transform: booleanAttribute }]
|
|
}], baseZIndex: [{
|
|
type: Input,
|
|
args: [{ transform: numberAttribute }]
|
|
}], showTransitionOptions: [{
|
|
type: Input
|
|
}], hideTransitionOptions: [{
|
|
type: Input
|
|
}], ariaLabel: [{
|
|
type: Input
|
|
}], ariaLabelledBy: [{
|
|
type: Input
|
|
}], id: [{
|
|
type: Input
|
|
}], tabindex: [{
|
|
type: Input,
|
|
args: [{ transform: numberAttribute }]
|
|
}], onShow: [{
|
|
type: Output
|
|
}], onHide: [{
|
|
type: Output
|
|
}], onBlur: [{
|
|
type: Output
|
|
}], onFocus: [{
|
|
type: Output
|
|
}], listViewChild: [{
|
|
type: ViewChild,
|
|
args: ['list']
|
|
}], containerViewChild: [{
|
|
type: ViewChild,
|
|
args: ['container']
|
|
}], templates: [{
|
|
type: ContentChildren,
|
|
args: [PrimeTemplate]
|
|
}] } });
|
|
class MenuModule {
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: MenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.7", ngImport: i0, type: MenuModule, declarations: [Menu, MenuItemContent, SafeHtmlPipe], imports: [CommonModule, RouterModule, RippleModule, TooltipModule], exports: [Menu, RouterModule, TooltipModule] });
|
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: MenuModule, imports: [CommonModule, RouterModule, RippleModule, TooltipModule, RouterModule, TooltipModule] });
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: MenuModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [CommonModule, RouterModule, RippleModule, TooltipModule],
|
|
exports: [Menu, RouterModule, TooltipModule],
|
|
declarations: [Menu, MenuItemContent, SafeHtmlPipe]
|
|
}]
|
|
}] });
|
|
|
|
/**
|
|
* Generated bundle index. Do not edit.
|
|
*/
|
|
|
|
export { Menu, MenuItemContent, MenuModule, SafeHtmlPipe };
|
|
//# sourceMappingURL=primeng-menu.mjs.map
|