UNPKG

primeng

Version:

[![npm version](https://badge.fury.io/js/primeng.svg)](https://badge.fury.io/js/primeng) [![npm downloads](https://img.shields.io/npm/dm/primeng.svg)](https://www.npmjs.com/package/primeng) [![Actions CI](https://github.com/primefaces/primeng/workflows/No

957 lines (953 loc) 109 kB
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: "18.0.1", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: PLATFORM_ID }, { token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.0.1", ngImport: i0, type: SafeHtmlPipe, name: "safeHtml" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", 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: "18.0.1", ngImport: i0, type: MenuItemContent, deps: [{ token: forwardRef(() => Menu) }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.1", 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: "18.0.1", 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: "18.0.1", 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: "18.0.1", 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: "18.0.1", 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: "18.0.1", ngImport: i0, type: MenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.0.1", 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: "18.0.1", ngImport: i0, type: MenuModule, imports: [CommonModule, RouterModule, RippleModule, TooltipModule, RouterModule, TooltipModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9tZW51L21lbnUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFrQixPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVFLE9BQU8sRUFDSCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULGVBQWUsRUFFZixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxRQUFRLEVBRVIsTUFBTSxFQUNOLFdBQVcsRUFDWCxJQUFJLEVBS0osU0FBUyxFQUNULGlCQUFpQixFQUVqQixnQkFBZ0IsRUFDaEIsUUFBUSxFQUVSLFVBQVUsRUFDVixlQUFlLEVBQ2YsTUFBTSxFQUNULE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQTJDLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyRixPQUFPLEVBQUUsNkJBQTZCLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7Ozs7Ozs7QUFLL0QsTUFBTSxPQUFPLFlBQVk7SUFFcUI7SUFDckI7SUFGckIsWUFDMEMsVUFBZSxFQUNwQyxTQUF1QjtRQURGLGVBQVUsR0FBVixVQUFVLENBQUs7UUFDcEMsY0FBUyxHQUFULFNBQVMsQ0FBYztJQUN6QyxDQUFDO0lBRUcsU0FBUyxDQUFDLEtBQWE7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