UNPKG

primeng

Version:

PrimeNG is an open source UI library for Angular featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeB

547 lines (528 loc) 23.5 kB
import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { Injectable, EventEmitter, inject, booleanAttribute, numberAttribute, ViewChild, Output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core'; import * as i2 from '@angular/router'; import { Router, ActivatedRoute, RouterModule } from '@angular/router'; import { find, findSingle } from '@primeuix/utils'; import { SharedModule } from 'primeng/api'; import { BaseComponent } from 'primeng/basecomponent'; import * as i3 from 'primeng/tooltip'; import { TooltipModule } from 'primeng/tooltip'; import { BaseStyle } from 'primeng/base'; const theme = ({ dt }) => ` .p-steps { position: relative; } .p-steps-list { padding: 0; margin: 0; list-style-type: none; display: flex; } .p-steps-item { position: relative; display: flex; justify-content: center; flex: 1 1 auto; } .p-steps-item.p-disabled, .p-steps-item.p-disabled * { opacity: 1; pointer-events: auto; user-select: auto; cursor: auto; } .p-steps-item:before { content: " "; border-top: 2px solid ${dt('steps.separator.background')}; width: 100%; top: 50%; left: 0; display: block; position: absolute; margin-top: -1rem; margin-top: calc(-1rem + 1px); } .p-steps-item:first-child::before { width: calc(50% + 1rem); transform: translateX(100%); } .p-steps-item:last-child::before { width: 50%; } .p-steps-item-link { display: inline-flex; flex-direction: column; align-items: center; overflow: hidden; text-decoration: none; transition: outline-color ${dt('steps.transition.duration')}, box-shadow ${dt('steps.transition.duration')}; border-radius: ${dt('steps.item.link.border.radius')}; outline-color: transparent; gap: ${dt('steps.item.link.gap')}; } .p-steps-item-link:not(.p-disabled):focus-visible { box-shadow: ${dt('steps.item.link.focus.ring.shadow')}; outline: ${dt('steps.item.link.focus.ring.width')} ${dt('steps.item.link.focus.ring.style')} ${dt('steps.item.link.focus.ring.color')}; outline-offset: ${dt('steps.item.link.focus.ring.offset')}; } .p-steps-item-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; color: ${dt('steps.item.label.color')}; display: block; font-weight: ${dt('steps.item.label.font.weight')}; } .p-steps-item-number { display: flex; align-items: center; justify-content: center; color: ${dt('steps.item.number.color')}; border: 2px solid ${dt('steps.item.number.border.color')}; background: ${dt('steps.item.number.background')}; min-width: ${dt('steps.item.number.size')}; height: ${dt('steps.item.number.size')}; line-height: ${dt('steps.item.number.size')}; font-size: ${dt('steps.item.number.font.size')}; z-index: 1; border-radius: ${dt('steps.item.number.border.radius')}; position: relative; font-weight: ${dt('steps.item.number.font.weight')}; } .p-steps-item-number::after { content: " "; position: absolute; width: 100%; height: 100%; border-radius: ${dt('steps.item.number.border.radius')}; box-shadow: ${dt('steps.item.number.shadow')}; } .p-steps:not(.p-readonly) .p-steps-item { cursor: pointer; } .p-steps-item-active .p-steps-item-number { background: ${dt('steps.item.number.active.background')}; border-color: ${dt('steps.item.number.active.border.color')}; color: ${dt('steps.item.number.active.color')}; } .p-steps-item-active .p-steps-item-label { color: ${dt('steps.item.label.active.color')}; } `; const classes = { root: ({ props }) => ['p-steps p-component', { 'p-readonly': props.readonly }], list: 'p-steps-list', item: ({ instance, item, index }) => [ 'p-steps-item', { 'p-steps-item-active': instance.isActive(index), 'p-disabled': instance.isItemDisabled(item, index) } ], itemLink: 'p-steps-item-link', itemNumber: 'p-steps-item-number', itemLabel: 'p-steps-item-label' }; class StepsStyle extends BaseStyle { name = 'steps'; theme = theme; classes = classes; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsStyle }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsStyle, decorators: [{ type: Injectable }] }); /** * * Steps components is an indicator for the steps in a wizard workflow. Example below uses nested routes with Steps. * * [Live Demo](https://www.primeng.org/steps/) * * @module stepsstyle * */ var StepsClasses; (function (StepsClasses) { /** * Class name of the root element */ StepsClasses["root"] = "p-steps"; /** * Class name of the list element */ StepsClasses["list"] = "p-steps-list"; /** * Class name of the item element */ StepsClasses["item"] = "p-steps-item"; /** * Class name of the item link element */ StepsClasses["itemLink"] = "p-steps-item-link"; /** * Class name of the item number element */ StepsClasses["itemNumber"] = "p-steps-item-number"; /** * Class name of the item label element */ StepsClasses["itemLabel"] = "p-steps-item-label"; })(StepsClasses || (StepsClasses = {})); /** * Steps components is an indicator for the steps in a wizard workflow. * @group Components */ class Steps extends BaseComponent { /** * Index of the active item. * @group Props */ activeIndex = 0; /** * An array of menu items. * @group Props */ model; /** * Whether the items are clickable or not. * @group Props */ readonly = true; /** * Inline style of the component. * @group Props */ style; /** * Style class of the component. * @group Props */ styleClass; /** * Whether to apply 'router-link-active-exact' class if route exactly matches the item path. * @group Props */ exact = true; /** * Callback to invoke when the new step is selected. * @param {number} number - current index. * @group Emits */ activeIndexChange = new EventEmitter(); listViewChild; router = inject(Router); route = inject(ActivatedRoute); _componentStyle = inject(StepsStyle); subscription; ngOnInit() { super.ngOnInit(); this.subscription = this.router.events.subscribe(() => this.cd.markForCheck()); } onItemClick(event, item, i) { if (this.readonly || item.disabled) { event.preventDefault(); return; } this.activeIndexChange.emit(i); if (!item.url && !item.routerLink) { event.preventDefault(); } if (item.command) { item.command({ originalEvent: event, item: item, index: i }); } } onItemKeydown(event, item, i) { switch (event.code) { case 'ArrowRight': { this.navigateToNextItem(event.target); event.preventDefault(); break; } case 'ArrowLeft': { this.navigateToPrevItem(event.target); event.preventDefault(); break; } case 'Home': { this.navigateToFirstItem(event.target); event.preventDefault(); break; } case 'End': { this.navigateToLastItem(event.target); event.preventDefault(); break; } case 'Tab': if (i !== this.activeIndex) { const siblings = find(this.listViewChild.nativeElement, '[data-pc-section="menuitem"]'); siblings[i].children[0].tabIndex = '-1'; siblings[this.activeIndex].children[0].tabIndex = '0'; } break; case 'Enter': case 'Space': { this.onItemClick(event, item, i); event.preventDefault(); break; } default: break; } } navigateToNextItem(target) { const nextItem = this.findNextItem(target); nextItem && this.setFocusToMenuitem(target, nextItem); } navigateToPrevItem(target) { const prevItem = this.findPrevItem(target); prevItem && this.setFocusToMenuitem(target, prevItem); } navigateToFirstItem(target) { const firstItem = this.findFirstItem(); firstItem && this.setFocusToMenuitem(target, firstItem); } navigateToLastItem(target) { const lastItem = this.findLastItem(); lastItem && this.setFocusToMenuitem(target, lastItem); } findNextItem(item) { const nextItem = item.parentElement.nextElementSibling; return nextItem ? nextItem.children[0] : null; } findPrevItem(item) { const prevItem = item.parentElement.previousElementSibling; return prevItem ? prevItem.children[0] : null; } findFirstItem() { const firstSibling = findSingle(this.listViewChild.nativeElement, '[data-pc-section="menuitem"]'); return firstSibling ? firstSibling.children[0] : null; } findLastItem() { const siblings = find(this.listViewChild.nativeElement, '[data-pc-section="menuitem"]'); return siblings ? siblings[siblings.length - 1].children[0] : null; } setFocusToMenuitem(target, focusableItem) { target.tabIndex = '-1'; focusableItem.tabIndex = '0'; focusableItem.focus(); } isClickableRouterLink(item) { return item.routerLink && !this.readonly && !item.disabled; } isActive(item, index) { if (item.routerLink) { let routerLink = Array.isArray(item.routerLink) ? item.routerLink : [item.routerLink]; return this.router.isActive(this.router.createUrlTree(routerLink, { relativeTo: this.route }).toString(), false); } return index === this.activeIndex; } getItemTabIndex(item, index) { if (item.disabled) { return '-1'; } if (!item.disabled && this.activeIndex === index) { return item.tabindex || '0'; } return item.tabindex ?? '-1'; } ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } super.ngOnDestroy(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: Steps, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: Steps, isStandalone: true, selector: "p-steps", inputs: { activeIndex: ["activeIndex", "activeIndex", numberAttribute], model: "model", readonly: ["readonly", "readonly", booleanAttribute], style: "style", styleClass: "styleClass", exact: ["exact", "exact", booleanAttribute] }, outputs: { activeIndexChange: "activeIndexChange" }, providers: [StepsStyle], viewQueries: [{ propertyName: "listViewChild", first: true, predicate: ["list"], descendants: true }], usesInheritance: true, ngImport: i0, template: ` <nav [ngClass]="{ 'p-steps p-component': true, 'p-readonly': readonly }" [ngStyle]="style" [class]="styleClass" [attr.data-pc-name]="'steps'"> <ul #list [attr.data-pc-section]="'menu'" class="p-steps-list"> @for (item of model; track item.label; let i = $index) { <li *ngIf="item.visible !== false" class="p-steps-item" #menuitem [ngStyle]="item.style" [class]="item.styleClass" [attr.aria-current]="isActive(item, i) ? 'step' : undefined" [attr.id]="item.id" pTooltip [tooltipOptions]="item.tooltipOptions" [ngClass]="{ 'p-steps-item-active': isActive(item, i), 'p-disabled': item.disabled || (readonly && !isActive(item, i)) }" [attr.data-pc-section]="'menuitem'" > <a role="link" *ngIf="isClickableRouterLink(item); else elseBlock" [routerLink]="item.routerLink" [queryParams]="item.queryParams" [routerLinkActiveOptions]="item.routerLinkActiveOptions || { exact: false }" class="p-steps-item-link" (click)="onItemClick($event, item, i)" (keydown)="onItemKeydown($event, item, i)" [target]="item.target" [attr.tabindex]="getItemTabIndex(item, i)" [attr.aria-expanded]="i === activeIndex" [attr.aria-disabled]="item.disabled || (readonly && i !== activeIndex)" [fragment]="item.fragment" [queryParamsHandling]="item.queryParamsHandling" [preserveFragment]="item.preserveFragment" [skipLocationChange]="item.skipLocationChange" [replaceUrl]="item.replaceUrl" [state]="item.state" [attr.ariaCurrentWhenActive]="exact ? 'step' : undefined" > <span class="p-steps-item-number">{{ i + 1 }}</span> <span class="p-steps-item-label" *ngIf="item.escape !== false; else htmlLabel">{{ item.label }}</span> <ng-template #htmlLabel><span class="p-steps-item-label" [innerHTML]="item.label"></span></ng-template> </a> <ng-template #elseBlock> <a role="link" [attr.href]="item.url" class="p-steps-item-link" (click)="onItemClick($event, item, i)" (keydown)="onItemKeydown($event, item, i)" [target]="item.target" [attr.tabindex]="getItemTabIndex(item, i)" [attr.aria-expanded]="i === activeIndex" [attr.aria-disabled]="item.disabled || (readonly && i !== activeIndex)" [attr.ariaCurrentWhenActive]="exact && (!item.disabled || readonly) ? 'step' : undefined" > <span class="p-steps-item-number">{{ i + 1 }}</span> <span class="p-steps-item-label" *ngIf="item.escape !== false; else htmlRouteLabel">{{ item.label }}</span> <ng-template #htmlRouteLabel><span class="p-steps-item-label" [innerHTML]="item.label"></span></ng-template> </a> </ng-template> </li> } </ul> </nav> `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: SharedModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: Steps, decorators: [{ type: Component, args: [{ selector: 'p-steps', standalone: true, imports: [CommonModule, RouterModule, TooltipModule, SharedModule], template: ` <nav [ngClass]="{ 'p-steps p-component': true, 'p-readonly': readonly }" [ngStyle]="style" [class]="styleClass" [attr.data-pc-name]="'steps'"> <ul #list [attr.data-pc-section]="'menu'" class="p-steps-list"> @for (item of model; track item.label; let i = $index) { <li *ngIf="item.visible !== false" class="p-steps-item" #menuitem [ngStyle]="item.style" [class]="item.styleClass" [attr.aria-current]="isActive(item, i) ? 'step' : undefined" [attr.id]="item.id" pTooltip [tooltipOptions]="item.tooltipOptions" [ngClass]="{ 'p-steps-item-active': isActive(item, i), 'p-disabled': item.disabled || (readonly && !isActive(item, i)) }" [attr.data-pc-section]="'menuitem'" > <a role="link" *ngIf="isClickableRouterLink(item); else elseBlock" [routerLink]="item.routerLink" [queryParams]="item.queryParams" [routerLinkActiveOptions]="item.routerLinkActiveOptions || { exact: false }" class="p-steps-item-link" (click)="onItemClick($event, item, i)" (keydown)="onItemKeydown($event, item, i)" [target]="item.target" [attr.tabindex]="getItemTabIndex(item, i)" [attr.aria-expanded]="i === activeIndex" [attr.aria-disabled]="item.disabled || (readonly && i !== activeIndex)" [fragment]="item.fragment" [queryParamsHandling]="item.queryParamsHandling" [preserveFragment]="item.preserveFragment" [skipLocationChange]="item.skipLocationChange" [replaceUrl]="item.replaceUrl" [state]="item.state" [attr.ariaCurrentWhenActive]="exact ? 'step' : undefined" > <span class="p-steps-item-number">{{ i + 1 }}</span> <span class="p-steps-item-label" *ngIf="item.escape !== false; else htmlLabel">{{ item.label }}</span> <ng-template #htmlLabel><span class="p-steps-item-label" [innerHTML]="item.label"></span></ng-template> </a> <ng-template #elseBlock> <a role="link" [attr.href]="item.url" class="p-steps-item-link" (click)="onItemClick($event, item, i)" (keydown)="onItemKeydown($event, item, i)" [target]="item.target" [attr.tabindex]="getItemTabIndex(item, i)" [attr.aria-expanded]="i === activeIndex" [attr.aria-disabled]="item.disabled || (readonly && i !== activeIndex)" [attr.ariaCurrentWhenActive]="exact && (!item.disabled || readonly) ? 'step' : undefined" > <span class="p-steps-item-number">{{ i + 1 }}</span> <span class="p-steps-item-label" *ngIf="item.escape !== false; else htmlRouteLabel">{{ item.label }}</span> <ng-template #htmlRouteLabel><span class="p-steps-item-label" [innerHTML]="item.label"></span></ng-template> </a> </ng-template> </li> } </ul> </nav> `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [StepsStyle] }] }], propDecorators: { activeIndex: [{ type: Input, args: [{ transform: numberAttribute }] }], model: [{ type: Input }], readonly: [{ type: Input, args: [{ transform: booleanAttribute }] }], style: [{ type: Input }], styleClass: [{ type: Input }], exact: [{ type: Input, args: [{ transform: booleanAttribute }] }], activeIndexChange: [{ type: Output }], listViewChild: [{ type: ViewChild, args: ['list', { static: false }] }] } }); class StepsModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.2", ngImport: i0, type: StepsModule, imports: [Steps, SharedModule], exports: [Steps, SharedModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsModule, imports: [Steps, SharedModule, SharedModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: StepsModule, decorators: [{ type: NgModule, args: [{ imports: [Steps, SharedModule], exports: [Steps, SharedModule] }] }] }); /** * Generated bundle index. Do not edit. */ export { Steps, StepsClasses, StepsModule, StepsStyle }; //# sourceMappingURL=primeng-steps.mjs.map