Icard/angular-clarity-master(work.../node_modules/primeng/esm2022/menu/menu.mjs

957 lines
106 KiB
JavaScript
Raw Permalink Normal View History

2024-07-16 14:55:36 +00:00
import { animate, style, transition, trigger } from '@angular/animations';
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
import { ChangeDetectionStrategy, Component, ContentChildren, EventEmitter, Inject, Input, NgModule, Output, PLATFORM_ID, Pipe, ViewChild, ViewEncapsulation, booleanAttribute, computed, forwardRef, numberAttribute, signal } from '@angular/core';
import { RouterModule } from '@angular/router';
import { PrimeTemplate } from 'primeng/api';
import { ConnectedOverlayScrollHandler, DomHandler } from 'primeng/dom';
import { RippleModule } from 'primeng/ripple';
import { TooltipModule } from 'primeng/tooltip';
import { UniqueComponentId, ZIndexUtils } from 'primeng/utils';
import * as i0 from "@angular/core";
import * as i1 from "@angular/platform-browser";
import * as i2 from "@angular/common";
import * as i3 from "@angular/router";
import * as i4 from "primeng/ripple";
import * as i5 from "primeng/api";
import * as i6 from "primeng/tooltip";
export 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 }] });
export 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
*/
export 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]
}] } });
export 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]
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9tZW51L21lbnUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFrQixPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVFLE9BQU8sRUFDSCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULGVBQWUsRUFFZixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxRQUFRLEVBRVIsTUFBTSxFQUNOLFdBQVcsRUFDWCxJQUFJLEVBS0osU0FBUyxFQUNULGlCQUFpQixFQUVqQixnQkFBZ0IsRUFDaEIsUUFBUSxFQUVSLFVBQVUsRUFDVixlQUFlLEVBQ2YsTUFBTSxFQUNULE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQTJDLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyRixPQUFPLEVBQUUsNkJBQTZCLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7Ozs7Ozs7QUFLL0QsTUFBTSxPQUFPLFlBQVk7SUFDNkI7SUFBa0M7SUFBcEYsWUFBa0QsVUFBZSxFQUFtQixTQUF1QjtRQUF6RCxlQUFVLEdBQVYsVUFBVSxDQUFLO1FBQW1CLGNBQVMsR0FBVCxTQUFTLENBQWM7SUFBRyxDQUFDO0lBRXhHLFNBQVMsQ0FBQyxLQUFh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