UNPKG

primeng

Version:

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

1,050 lines (1,034 loc) 55.6 kB
export * from 'primeng/types/password'; import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { Injectable, InjectionToken, inject, input, booleanAttribute, computed, effect, signal, HostListener, Directive, Pipe, forwardRef, numberAttribute, output, viewChild, contentChild, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { addClass, absolutePosition, removeClass, hasClass, isTouchDevice } from '@primeuix/utils'; import { OverlayService, TranslationKeys, SharedModule } from 'primeng/api'; import { AutoFocus } from 'primeng/autofocus'; import { PARENT_INSTANCE } from 'primeng/basecomponent'; import { BaseEditableHolder } from 'primeng/baseeditableholder'; import { BaseInput } from 'primeng/baseinput'; import * as i1 from 'primeng/bind'; import { Bind, BindModule } from 'primeng/bind'; import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom'; import { Fluid } from 'primeng/fluid'; import { Eye } from '@primeicons/angular/eye'; import { EyeSlash } from '@primeicons/angular/eye-slash'; import { Times } from '@primeicons/angular/times'; import { InputText } from 'primeng/inputtext'; import { Overlay } from 'primeng/overlay'; import { style as style$1 } from '@primeuix/styles/password'; import { BaseStyle } from 'primeng/base'; const style = /*css*/ ` ${style$1} /* For PrimeNG */ .p-password-overlay { min-width: 100%; } p-password.ng-invalid.ng-dirty .p-inputtext { border-color: dt('inputtext.invalid.border.color'); } p-password.ng-invalid.ng-dirty .p-inputtext:enabled:focus { border-color: dt('inputtext.focus.border.color'); } p-password.ng-invalid.ng-dirty .p-inputtext::placeholder { color: dt('inputtext.invalid.placeholder.color'); } .p-password-fluid-directive { width: 100%; } /* Animations */ .p-password-enter { animation: p-animate-password-enter 300ms cubic-bezier(.19,1,.22,1); } .p-password-leave { animation: p-animate-password-leave 300ms cubic-bezier(.19,1,.22,1); } @keyframes p-animate-password-enter { from { opacity: 0; transform: scale(0.93); } } @keyframes p-animate-password-leave { to { opacity: 0; transform: scale(0.93); } } `; const inlineStyles = { root: ({ instance }) => ({ position: instance.$appendTo() === 'self' ? 'relative' : undefined }), overlay: { position: 'absolute' } }; const classes = { root: ({ instance }) => [ 'p-password p-component p-inputwrapper', { 'p-inputwrapper-filled': instance.$filled(), 'p-variant-filled': instance.$variant() === 'filled', 'p-inputwrapper-focus': instance.focused, 'p-password-fluid': instance.hasFluid } ], rootDirective: ({ instance }) => [ 'p-password p-inputtext p-component p-inputwrapper', { 'p-inputwrapper-filled': instance.$filled(), 'p-variant-filled': instance.$variant() === 'filled', 'p-password-fluid-directive': instance.hasFluid } ], pcInputText: 'p-password-input', maskIcon: 'p-password-toggle-mask-icon p-password-mask-icon', unmaskIcon: 'p-password-toggle-mask-icon p-password-unmask-icon', overlay: 'p-password-overlay p-component', content: 'p-password-content', meter: 'p-password-meter', meterLabel: ({ instance }) => `p-password-meter-label ${instance.meter ? 'p-password-meter-' + instance.meter.strength : ''}`, meterText: 'p-password-meter-text', clearIcon: 'p-password-clear-icon' }; class PasswordStyle extends BaseStyle { name = 'password'; style = style; classes = classes; inlineStyles = inlineStyles; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PasswordStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PasswordStyle }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PasswordStyle, decorators: [{ type: Injectable }] }); /** * * Password displays strength indicator for password fields. * * [Live Demo](https://www.primeng.org/password/) * * @module passwordstyle * */ var PasswordClasses; (function (PasswordClasses) { /** * Class name of the root element */ PasswordClasses["root"] = "p-password"; /** * Class name of the pt input element */ PasswordClasses["pcInputText"] = "p-password-input"; /** * Class name of the mask icon element */ PasswordClasses["maskIcon"] = "p-password-mask-icon"; /** * Class name of the unmask icon element */ PasswordClasses["unmaskIcon"] = "p-password-unmask-icon"; /** * Class name of the overlay element */ PasswordClasses["overlay"] = "p-password-overlay"; /** * Class name of the meter element */ PasswordClasses["meter"] = "p-password-meter"; /** * Class name of the meter label element */ PasswordClasses["meterLabel"] = "p-password-meter-label"; /** * Class name of the meter text element */ PasswordClasses["meterText"] = "p-password-meter-text"; /** * Class name of the clear icon */ PasswordClasses["clearIcon"] = "p-password-clear-icon"; })(PasswordClasses || (PasswordClasses = {})); const PASSWORD_DIRECTIVE_INSTANCE = new InjectionToken('PASSWORD_DIRECTIVE_INSTANCE'); const PASSWORD_INSTANCE = new InjectionToken('PASSWORD_INSTANCE'); /** * Password directive. * @deprecated since v22, use pInputPassword directive instead. * @group Components */ class PasswordDirective extends BaseEditableHolder { bindDirectiveInstance = inject(Bind, { self: true }); $pcPasswordDirective = inject(PASSWORD_DIRECTIVE_INSTANCE, { optional: true, skipSelf: true }) ?? undefined; /** * Used to pass attributes to DOM elements inside the Password component. * @defaultValue undefined * @group Props */ pPasswordPT = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "pPasswordPT" }] : /* istanbul ignore next */ [])); /** * Indicates whether the component should be rendered without styles. * @defaultValue undefined * @group Props */ pPasswordUnstyled = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "pPasswordUnstyled" }] : /* istanbul ignore next */ [])); onAfterViewChecked() { this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root'])); } /** * Text to prompt password entry. Defaults to PrimeNG I18N API configuration. * @group Props */ promptLabel = input('Enter a password', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "promptLabel" }] : /* istanbul ignore next */ [])); /** * Text for a weak password. Defaults to PrimeNG I18N API configuration. * @group Props */ weakLabel = input('Weak', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "weakLabel" }] : /* istanbul ignore next */ [])); /** * Text for a medium password. Defaults to PrimeNG I18N API configuration. * @group Props */ mediumLabel = input('Medium', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "mediumLabel" }] : /* istanbul ignore next */ [])); /** * Text for a strong password. Defaults to PrimeNG I18N API configuration. * @group Props */ strongLabel = input('Strong', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "strongLabel" }] : /* istanbul ignore next */ [])); /** * Whether to show the strength indicator or not. * @group Props */ feedback = input(true, { ...(ngDevMode ? { debugName: "feedback" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Sets the visibility of the password field. * @defaultValue false * @type boolean * @group Props */ showPassword = input(false, { ...(ngDevMode ? { debugName: "showPassword" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Specifies the input variant of the component. * @defaultValue 'outlined' * @group Props */ variant = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "variant" }] : /* istanbul ignore next */ [])); /** * Spans 100% width of the container when enabled. * @defaultValue false * @group Props */ fluid = input(undefined, { ...(ngDevMode ? { debugName: "fluid" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Specifies the size of the component. * @defaultValue undefined * @group Props */ size = input(undefined, { ...(ngDevMode ? { debugName: "size" } : /* istanbul ignore next */ {}), alias: 'pSize' }); pcFluid = inject(Fluid, { optional: true, host: true, skipSelf: true }); $variant = computed(() => this.variant() || this.config.inputVariant(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "$variant" }] : /* istanbul ignore next */ [])); get hasFluid() { return this.fluid() ?? !!this.pcFluid; } panel; meter; info; filled; content; label; scrollHandler; documentResizeListener; _componentStyle = inject(PasswordStyle); constructor() { super(); effect(() => { const pt = this.pPasswordPT(); pt && this.directivePT.set(pt); }); effect(() => { this.pPasswordUnstyled() && this.directiveUnstyled.set(this.pPasswordUnstyled()); }); effect(() => { const show = this.showPassword(); this.el.nativeElement.type = show ? 'text' : 'password'; }); } onInput(e) { this.writeModelValue(this.el.nativeElement.value); } createPanel() { if (isPlatformBrowser(this.platformId)) { this.panel = this.renderer.createElement('div'); this.renderer.addClass(this.panel, 'p-password-overlay'); this.renderer.addClass(this.panel, 'p-component'); this.content = this.renderer.createElement('div'); this.renderer.addClass(this.content, 'p-password-content'); this.renderer.appendChild(this.panel, this.content); this.meter = this.renderer.createElement('div'); this.renderer.addClass(this.meter, 'p-password-meter'); this.renderer.appendChild(this.content, this.meter); this.label = this.renderer.createElement('div'); this.renderer.addClass(this.label, 'p-password-meter-label'); this.renderer.appendChild(this.meter, this.label); this.info = this.renderer.createElement('div'); this.renderer.addClass(this.info, 'p-password-meter-text'); this.renderer.setProperty(this.info, 'textContent', this.promptLabel()); this.renderer.appendChild(this.content, this.info); this.renderer.setStyle(this.panel, 'minWidth', `${this.el.nativeElement.offsetWidth}px`); this.renderer.appendChild(document.body, this.panel); this.updateMeter(); } } showOverlay() { if (this.feedback()) { if (!this.panel) { this.createPanel(); } this.renderer.setStyle(this.panel, 'zIndex', String(++DomHandler.zindex)); this.renderer.setStyle(this.panel, 'display', 'block'); setTimeout(() => { addClass(this.panel, 'p-connected-overlay-visible'); this.bindScrollListener(); this.bindDocumentResizeListener(); }, 1); absolutePosition(this.panel, this.el.nativeElement); } } hideOverlay() { if (this.feedback() && this.panel) { addClass(this.panel, 'p-connected-overlay-hidden'); removeClass(this.panel, 'p-connected-overlay-visible'); this.unbindScrollListener(); this.unbindDocumentResizeListener(); setTimeout(() => { this.onDestroy(); }, 150); } } onFocus() { this.showOverlay(); } onBlur() { this.hideOverlay(); } labelSignal = signal('', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "labelSignal" }] : /* istanbul ignore next */ [])); onKeyup(e) { if (this.feedback()) { let value = e.target.value, label = null, meterPos = null; if (value.length === 0) { label = this.promptLabel(); meterPos = '0px 0px'; } else { var score = this.testStrength(value); if (score < 30) { label = this.weakLabel(); meterPos = '0px -10px'; } else if (score >= 30 && score < 80) { label = this.mediumLabel(); meterPos = '0px -20px'; } else if (score >= 80) { label = this.strongLabel(); meterPos = '0px -30px'; } this.labelSignal.set(label); this.updateMeter(); } if (!this.panel || !hasClass(this.panel, 'p-connected-overlay-visible')) { this.showOverlay(); } if (this.meter) { this.renderer.setStyle(this.meter, 'backgroundPosition', meterPos); } if (this.info) { this.info.textContent = label; } } } updateMeter() { if (this.labelSignal() && this.meter && this.info) { const label = this.labelSignal(); const strengthClass = this.strengthClass(label.toLowerCase()); const width = this.getWidth(label.toLowerCase()); this.renderer.addClass(this.meter, strengthClass); this.renderer.setStyle(this.meter, 'width', width); this.info.textContent = label; } } getWidth(label) { return label === 'weak' ? '33.33%' : label === 'medium' ? '66.66%' : label === 'strong' ? '100%' : ''; } strengthClass(label) { return `p-password-meter${label ? `-${label}` : ''}`; } testStrength(str) { let grade = 0; let val; val = str.match('[0-9]'); grade += this.normalize(val ? val.length : 1 / 4, 1) * 25; val = str.match('[a-zA-Z]'); grade += this.normalize(val ? val.length : 1 / 2, 3) * 10; val = str.match('[!@#$%^&*?_~.,;=]'); grade += this.normalize(val ? val.length : 1 / 6, 1) * 35; val = str.match('[A-Z]'); grade += this.normalize(val ? val.length : 1 / 6, 1) * 30; grade *= str.length / 8; return grade > 100 ? 100 : grade; } normalize(x, y) { let diff = x - y; if (diff <= 0) return x / y; else return 1 + 0.5 * (x / (x + y / 4)); } bindScrollListener() { if (!this.scrollHandler) { this.scrollHandler = new ConnectedOverlayScrollHandler(this.el.nativeElement, () => { if (hasClass(this.panel, 'p-connected-overlay-visible')) { this.hideOverlay(); } }); } this.scrollHandler.bindScrollListener(); } unbindScrollListener() { if (this.scrollHandler) { this.scrollHandler.unbindScrollListener(); } } bindDocumentResizeListener() { if (isPlatformBrowser(this.platformId)) { if (!this.documentResizeListener) { 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; } } onWindowResize() { if (!isTouchDevice()) { this.hideOverlay(); } } onDestroy() { if (this.panel) { if (this.scrollHandler) { this.scrollHandler.destroy(); this.scrollHandler = null; } this.unbindDocumentResizeListener(); this.renderer.removeChild(this.document.body, this.panel); this.panel = null; this.meter = null; this.info = null; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PasswordDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: PasswordDirective, isStandalone: true, selector: "[pPassword]", inputs: { pPasswordPT: { classPropertyName: "pPasswordPT", publicName: "pPasswordPT", isSignal: true, isRequired: false, transformFunction: null }, pPasswordUnstyled: { classPropertyName: "pPasswordUnstyled", publicName: "pPasswordUnstyled", isSignal: true, isRequired: false, transformFunction: null }, promptLabel: { classPropertyName: "promptLabel", publicName: "promptLabel", isSignal: true, isRequired: false, transformFunction: null }, weakLabel: { classPropertyName: "weakLabel", publicName: "weakLabel", isSignal: true, isRequired: false, transformFunction: null }, mediumLabel: { classPropertyName: "mediumLabel", publicName: "mediumLabel", isSignal: true, isRequired: false, transformFunction: null }, strongLabel: { classPropertyName: "strongLabel", publicName: "strongLabel", isSignal: true, isRequired: false, transformFunction: null }, feedback: { classPropertyName: "feedback", publicName: "feedback", isSignal: true, isRequired: false, transformFunction: null }, showPassword: { classPropertyName: "showPassword", publicName: "showPassword", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, fluid: { classPropertyName: "fluid", publicName: "fluid", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "pSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput($event)", "focus": "onFocus()", "blur": "onBlur()", "keyup": "onKeyup($event)" }, properties: { "class": "cx('rootDirective')" } }, providers: [PasswordStyle, { provide: PASSWORD_DIRECTIVE_INSTANCE, useExisting: PasswordDirective }, { provide: PARENT_INSTANCE, useExisting: PasswordDirective }], usesInheritance: true, hostDirectives: [{ directive: i1.Bind }], ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PasswordDirective, decorators: [{ type: Directive, args: [{ selector: '[pPassword]', standalone: true, host: { '[class]': "cx('rootDirective')" }, providers: [PasswordStyle, { provide: PASSWORD_DIRECTIVE_INSTANCE, useExisting: PasswordDirective }, { provide: PARENT_INSTANCE, useExisting: PasswordDirective }], hostDirectives: [Bind] }] }], ctorParameters: () => [], propDecorators: { pPasswordPT: [{ type: i0.Input, args: [{ isSignal: true, alias: "pPasswordPT", required: false }] }], pPasswordUnstyled: [{ type: i0.Input, args: [{ isSignal: true, alias: "pPasswordUnstyled", required: false }] }], promptLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptLabel", required: false }] }], weakLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weakLabel", required: false }] }], mediumLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediumLabel", required: false }] }], strongLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "strongLabel", required: false }] }], feedback: [{ type: i0.Input, args: [{ isSignal: true, alias: "feedback", required: false }] }], showPassword: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPassword", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], fluid: [{ type: i0.Input, args: [{ isSignal: true, alias: "fluid", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "pSize", required: false }] }], onInput: [{ type: HostListener, args: ['input', ['$event']] }], onFocus: [{ type: HostListener, args: ['focus'] }], onBlur: [{ type: HostListener, args: ['blur'] }], onKeyup: [{ type: HostListener, args: ['keyup', ['$event']] }] } }); class MapperPipe { transform(value, mapper, ...args) { return mapper(value, ...args); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MapperPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.6", ngImport: i0, type: MapperPipe, isStandalone: true, name: "mapper" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: MapperPipe, decorators: [{ type: Pipe, args: [{ name: 'mapper', pure: true, standalone: true }] }] }); const Password_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Password), multi: true }; /** * Password displays strength indicator for password fields. * @deprecated since v22, use pInputPassword directive instead. * @group Components */ class Password extends BaseInput { componentName = 'Password'; bindDirectiveInstance = inject(Bind, { self: true }); $pcPassword = inject(PASSWORD_INSTANCE, { optional: true, skipSelf: true }) ?? undefined; onAfterViewChecked() { this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root'])); } /** * Defines a string that labels the input for accessibility. * @group Props */ ariaLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ [])); /** * Specifies one or more IDs in the DOM that labels the input field. * @group Props */ ariaLabelledBy = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ [])); /** * Label of the input for accessibility. * @group Props */ label = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ [])); /** * Text to prompt password entry. Defaults to PrimeNG I18N API configuration. * @group Props */ promptLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "promptLabel" }] : /* istanbul ignore next */ [])); /** * Regex value for medium regex. * @group Props */ mediumRegex = input('^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "mediumRegex" }] : /* istanbul ignore next */ [])); /** * Regex value for strong regex. * @group Props */ strongRegex = input('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "strongRegex" }] : /* istanbul ignore next */ [])); /** * Text for a weak password. Defaults to PrimeNG I18N API configuration. * @group Props */ weakLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "weakLabel" }] : /* istanbul ignore next */ [])); /** * Text for a medium password. Defaults to PrimeNG I18N API configuration. * @group Props */ mediumLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "mediumLabel" }] : /* istanbul ignore next */ [])); /** * Text for a strong password. Defaults to PrimeNG I18N API configuration. * @group Props */ strongLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "strongLabel" }] : /* istanbul ignore next */ [])); /** * Identifier of the accessible input element. * @group Props */ inputId = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputId" }] : /* istanbul ignore next */ [])); /** * Whether to show the strength indicator or not. * @group Props */ feedback = input(true, { ...(ngDevMode ? { debugName: "feedback" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether to show an icon to display the password as plain text. * @group Props */ toggleMask = input(undefined, { ...(ngDevMode ? { debugName: "toggleMask" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Style class of the input field. * @group Props */ inputStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputStyleClass" }] : /* istanbul ignore next */ [])); /** * Inline style of the input field. * @group Props */ inputStyle = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputStyle" }] : /* istanbul ignore next */ [])); /** * Specify automated assistance in filling out password by browser. * @group Props */ autocomplete = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "autocomplete" }] : /* istanbul ignore next */ [])); /** * Advisory information to display on input. * @group Props */ placeholder = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ [])); /** * When enabled, a clear icon is displayed to clear the value. * @group Props */ showClear = input(false, { ...(ngDevMode ? { debugName: "showClear" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When present, it specifies that the component should automatically get focus on load. * @group Props */ autofocus = input(undefined, { ...(ngDevMode ? { debugName: "autofocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Index of the element in tabbing order. * @group Props */ tabindex = input(undefined, { ...(ngDevMode ? { debugName: "tabindex" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * 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). * @defaultValue 'self' * @group Props */ appendTo = input('self', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ [])); /** * The motion options. * @group Props */ motionOptions = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "motionOptions" }] : /* istanbul ignore next */ [])); /** * Whether to use overlay API feature. The properties of overlay API can be used like an object in it. * @group Props */ overlayOptions = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "overlayOptions" }] : /* istanbul ignore next */ [])); /** * Callback to invoke when the component receives focus. * @param {Event} event - Browser event. * @group Emits */ onFocus = output(); /** * Callback to invoke when the component loses focus. * @param {Event} event - Browser event. * @group Emits */ onBlur = output(); /** * Callback to invoke when clear button is clicked. * @group Emits */ onClear = output(); overlayViewChild = viewChild('overlay', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "overlayViewChild" }] : /* istanbul ignore next */ [])); inputViewChild = viewChild('input', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "inputViewChild" }] : /* istanbul ignore next */ [])); /** * Custom template of content. * @group Templates */ contentTemplate = contentChild('content', { ...(ngDevMode ? { debugName: "contentTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template of footer. * @group Templates */ footerTemplate = contentChild('footer', { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template of header. * @group Templates */ headerTemplate = contentChild('header', { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template of clear icon. * @group Templates */ clearIconTemplate = contentChild('clearicon', { ...(ngDevMode ? { debugName: "clearIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template of hide icon. * @param {PasswordIconTemplateContext} context - icon context. * @see {@link PasswordIconTemplateContext} * @group Templates */ hideIconTemplate = contentChild('hideicon', { ...(ngDevMode ? { debugName: "hideIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template of show icon. * @param {PasswordIconTemplateContext} context - icon context. * @see {@link PasswordIconTemplateContext} * @group Templates */ showIconTemplate = contentChild('showicon', { ...(ngDevMode ? { debugName: "showIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); $appendTo = computed(() => this.appendTo() || this.config.overlayAppendTo(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "$appendTo" }] : /* istanbul ignore next */ [])); overlayVisible = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "overlayVisible" }] : /* istanbul ignore next */ [])); meter; infoText; focused = false; unmasked = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "unmasked" }] : /* istanbul ignore next */ [])); requiredAttr = computed(() => (this.required() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "requiredAttr" }] : /* istanbul ignore next */ [])); disabledAttr = computed(() => (this.$disabled() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "disabledAttr" }] : /* istanbul ignore next */ [])); inputType = computed(() => (this.unmasked() ? 'text' : 'password'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "inputType" }] : /* istanbul ignore next */ [])); get showClearIcon() { return this.showClear() && this.value != null; } get maskIconContext() { return { class: this.cx('maskIcon') ?? '' }; } get unmaskIconContext() { return { class: this.cx('unmaskIcon') ?? '' }; } mediumCheckRegExp; strongCheckRegExp; resizeListener; scrollHandler; value = null; translationSubscription; _componentStyle = inject(PasswordStyle); overlayService = inject(OverlayService); onInit() { this.infoText = this.promptText(); this.mediumCheckRegExp = new RegExp(this.mediumRegex()); this.strongCheckRegExp = new RegExp(this.strongRegex()); this.translationSubscription = this.config.translationObserver.subscribe(() => { this.updateUI(this.value || ''); }); } onInput(event) { this.value = event.target.value; this.onModelChange(this.value); } onInputFocus(event) { this.focused = true; if (this.feedback()) { this.overlayVisible.set(true); } this.onFocus.emit(event); } onInputBlur(event) { this.focused = false; if (this.feedback()) { this.overlayVisible.set(false); } this.onModelTouched(); this.onBlur.emit(event); } onKeyUp(event) { if (this.feedback()) { let value = event.target.value; this.updateUI(value); if (event.code === 'Escape') { this.overlayVisible() && this.overlayVisible.set(false); return; } if (!this.overlayVisible()) { this.overlayVisible.set(true); } } } updateUI(value) { let label = null; let meter = null; switch (this.testStrength(value)) { case 1: label = this.weakText(); meter = { strength: 'weak', width: '33.33%' }; break; case 2: label = this.mediumText(); meter = { strength: 'medium', width: '66.66%' }; break; case 3: label = this.strongText(); meter = { strength: 'strong', width: '100%' }; break; default: label = this.promptText(); meter = null; break; } this.meter = meter; this.infoText = label; } onMaskToggle() { this.unmasked.update((v) => !v); } onOverlayClick(event) { this.overlayService.add({ originalEvent: event, target: this.el.nativeElement }); } testStrength(str) { let level = 0; if (this.strongCheckRegExp?.test(str)) level = 3; else if (this.mediumCheckRegExp?.test(str)) level = 2; else if (str.length) level = 1; return level; } promptText() { return this.promptLabel() || this.translate(TranslationKeys.PASSWORD_PROMPT); } weakText() { return this.weakLabel() || this.translate(TranslationKeys.WEAK); } mediumText() { return this.mediumLabel() || this.translate(TranslationKeys.MEDIUM); } strongText() { return this.strongLabel() || this.translate(TranslationKeys.STRONG); } clear() { this.value = null; this.onModelChange(this.value); this.writeValue(this.value); this.onClear.emit(); } /** * @override * * @see {@link BaseEditableHolder.writeControlValue} * Writes the value to the control. */ writeControlValue(value, setModelValue) { if (value === undefined) this.value = null; else this.value = value; if (this.feedback()) this.updateUI(this.value || ''); setModelValue(this.value); } onDestroy() { if (this.translationSubscription) { this.translationSubscription.unsubscribe(); } } get containerDataP() { return this.cn({ fluid: this.hasFluid }); } get meterDataP() { return this.cn({ [this.meter?.strength]: this.meter?.strength }); } get overlayDataP() { return this.cn({ ['overlay-' + this.$appendTo()]: 'overlay-' + this.$appendTo() }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: Password, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: Password, isStandalone: true, selector: "p-password", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, promptLabel: { classPropertyName: "promptLabel", publicName: "promptLabel", isSignal: true, isRequired: false, transformFunction: null }, mediumRegex: { classPropertyName: "mediumRegex", publicName: "mediumRegex", isSignal: true, isRequired: false, transformFunction: null }, strongRegex: { classPropertyName: "strongRegex", publicName: "strongRegex", isSignal: true, isRequired: false, transformFunction: null }, weakLabel: { classPropertyName: "weakLabel", publicName: "weakLabel", isSignal: true, isRequired: false, transformFunction: null }, mediumLabel: { classPropertyName: "mediumLabel", publicName: "mediumLabel", isSignal: true, isRequired: false, transformFunction: null }, strongLabel: { classPropertyName: "strongLabel", publicName: "strongLabel", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, feedback: { classPropertyName: "feedback", publicName: "feedback", isSignal: true, isRequired: false, transformFunction: null }, toggleMask: { classPropertyName: "toggleMask", publicName: "toggleMask", isSignal: true, isRequired: false, transformFunction: null }, inputStyleClass: { classPropertyName: "inputStyleClass", publicName: "inputStyleClass", isSignal: true, isRequired: false, transformFunction: null }, inputStyle: { classPropertyName: "inputStyle", publicName: "inputStyle", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, motionOptions: { classPropertyName: "motionOptions", publicName: "motionOptions", isSignal: true, isRequired: false, transformFunction: null }, overlayOptions: { classPropertyName: "overlayOptions", publicName: "overlayOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFocus: "onFocus", onBlur: "onBlur", onClear: "onClear" }, host: { properties: { "class": "cx('root')", "style": "sx('root')", "attr.data-p": "containerDataP" } }, providers: [Password_VALUE_ACCESSOR, PasswordStyle, { provide: PASSWORD_INSTANCE, useExisting: Password }, { provide: PARENT_INSTANCE, useExisting: Password }], queries: [{ propertyName: "contentTemplate", first: true, predicate: ["content"], isSignal: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], isSignal: true }, { propertyName: "headerTemplate", first: true, predicate: ["header"], isSignal: true }, { propertyName: "clearIconTemplate", first: true, predicate: ["clearicon"], isSignal: true }, { propertyName: "hideIconTemplate", first: true, predicate: ["hideicon"], isSignal: true }, { propertyName: "showIconTemplate", first: true, predicate: ["showicon"], isSignal: true }], viewQueries: [{ propertyName: "overlayViewChild", first: true, predicate: ["overlay"], descendants: true, isSignal: true }, { propertyName: "inputViewChild", first: true, predicate: ["input"], descendants: true, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.Bind }], ngImport: i0, template: ` <input #input [attr.label]="label()" [attr.aria-label]="ariaLabel()" [attr.aria-labelledBy]="ariaLabelledBy()" [attr.id]="inputId()" [attr.tabindex]="tabindex()" pInputText [pSize]="size()" [style]="inputStyle()" [class]="cn(cx('pcInputText'), inputStyleClass())" [attr.type]="inputType()" [attr.placeholder]="placeholder()" [attr.autocomplete]="autocomplete()" [value]="value" [variant]="$variant()" [attr.name]="name()" [attr.maxlength]="maxlength()" [attr.minlength]="minlength()" [attr.required]="requiredAttr()" [attr.disabled]="disabledAttr()" [invalid]="invalid()" (input)="onInput($event)" (focus)="onInputFocus($event)" (blur)="onInputBlur($event)" (keyup)="onKeyUp($event)" [pAutoFocus]="autofocus()" [pt]="ptm('pcInputText')" [unstyled]="unstyled()" /> @if (showClearIcon) { @if (!clearIconTemplate()) { <svg data-p-icon="times" [class]="cx('clearIcon')" (click)="clear()" [pBind]="ptm('clearIcon')" /> } <span (click)="clear()" [class]="cx('clearIcon')" [pBind]="ptm('clearIcon')"> <ng-container *ngTemplateOutlet="clearIconTemplate()"></ng-container> </span> } @if (toggleMask()) { @if (unmasked()) { @if (!hideIconTemplate()) { <svg data-p-icon="eye-slash" [class]="cx('maskIcon')" [pBind]="ptm('maskIcon')" (click)="onMaskToggle()" /> } @else { <span (click)="onMaskToggle()" [pBind]="ptm('maskIcon')"> <ng-container *ngTemplateOutlet="hideIconTemplate(); context: maskIconContext"></ng-container> </span> } } @else { @if (!showIconTemplate()) { <svg data-p-icon="eye" [class]="cx('unmaskIcon')" [pBind]="ptm('unmaskIcon')" (click)="onMaskToggle()" /> } @else { <span (click)="onMaskToggle()" [pBind]="ptm('unmaskIcon')"> <ng-container *ngTemplateOutlet="showIconTemplate(); context: unmaskIconContext"></ng-container> </span> } } } <p-overlay #overlay [hostAttrSelector]="$attrSelector" [visible]="overlayVisible()" (visibleChange)="overlayVisible.set($event)" [options]="overlayOptions()" [target]="'@parent'" [appendTo]="$appendTo()" [unstyled]="unstyled()" [pt]="ptm('pcOverlay')" [motionOptions]="motionOptions()" > <ng-template #content> <div [class]="cx('overlay')" [style]="sx('overlay')" (click)="onOverlayClick($event)" [pBind]="ptm('overlay')" [attr.data-p]="overlayDataP"> <ng-container *ngTemplateOutlet="headerTemplate()"></ng-container> @if (contentTemplate()) { <ng-container *ngTemplateOutlet="contentTemplate()"></ng-container> } @else { <div [class]="cx('content')" [pBind]="ptm('content')"> <div [class]="cx('meter')" [pBind]="ptm('meter')"> <div [class]="cx('meterLabel')" [style.width]="meter ? meter.width : ''" [pBind]="ptm('meterLabel')" [attr.data-p]="meterDataP"></div> </div> <div [class]="cx('meterText')" [pBind]="ptm('meterText')">{{ infoText }}</div> </div> } <ng-container *ngTemplateOutlet="footerTemplate()"></ng-container> </div> </ng-template> </p-overlay> `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: AutoFocus, selector: "[pAutoFocus]", inputs: ["pAutoFocus"] }, { kind: "component", type: Times, selector: "svg[data-p-icon=\"times\"]" }, { kind: "component", type: EyeSlash, selector: "svg[data-p-icon=\"eye-slash\"]" }, { kind: "component", type: Eye, selector: "svg[data-p-icon=\"eye\"]" }, { kind: "component", type: Overlay, selector: "p-overlay", inputs: ["hostName", "visible", "mode", "style", "styleClass", "contentStyle", "contentStyleClass", "target", "autoZIndex", "baseZIndex", "listener", "responsive", "options", "appendTo", "inline", "motionOptions", "hostAttrSelector"], outputs: ["visibleChange", "onBeforeShow", "onShow", "onBeforeHide", "onHide", "onAnimationStart", "onAnimationDone", "onBeforeEnter", "onEnter", "onAfterEnter", "onBeforeLeave", "onLeave", "onAfterLeave"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: BindModule }, { kind: "directive", type: i1.Bind, selector: "[pBind]", inputs: ["pBind"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: Password, decorators: [{ type: Component, args: [{ selector: 'p-password', standalone: true, imports: [NgTemplateOutlet, InputText, AutoFocus, Times, EyeSlash, Eye, Overlay, SharedModule, BindModule], template: ` <input #input [attr.label]="label()" [attr.aria-label]="ariaLabel()" [attr.aria-labelledBy]="ariaLabelledBy()" [attr.id]="inputId()" [attr.tabindex]="tabindex()" pInputText [pSize]="size()" [style]="inputStyle()" [class]="cn(cx('pcInputText'), inputStyleClass())" [attr.type]="inputType()" [attr.placeholder]="placeholder()" [attr.autocomplete]="autocomplete()" [value]="value" [variant]="$variant()" [attr.name]="name()" [attr.maxlength]="maxlength()" [attr.minlength]="minlength()" [attr.required]="requiredAttr()" [attr.disabled]="disabledAttr()" [invalid]="invalid()" (input)="onInput($event)" (focus)="onInputFocus($event)" (blur)="onInputBlur($event)" (keyup)="onKeyUp($event)" [pAutoFocus]="autofocus()" [pt]="ptm('pcInputText')" [unstyled]="unstyled()" /> @if (showClearIcon) { @if (!clearIconTemplate()) { <svg data-p-icon="times" [class]="cx('clearIcon')" (click)="clear()" [pBind]="ptm('clearIcon')" /> } <span (click)="clear()" [class]="cx('clearIcon')" [pBind]="ptm('clearIcon')"> <ng-container *ngTemplateOutlet="clearIconTemplate()"></ng-container> </span> } @if (toggleMask()) { @if (unmasked()) { @if (!hideIconTemplate()) { <svg data-p-icon="eye-slash" [class]="cx('maskIcon')" [pBind]="ptm('maskIcon')" (click)="onMaskToggle()" /> } @else { <span (click)="onMaskToggle()" [pBind]="ptm('maskIcon')"> <ng-container *ngTemplateOutlet="hideIconTemplate(); context: maskIconContext"></ng-container> </span> } } @else { @if (!showIconTemplate()) { <svg data-p-icon="eye" [class]="cx('unmaskIcon')" [pBind]="ptm('unmaskIcon')" (click)="onMaskToggle()" /> } @else { <span (click)="onMaskToggle()" [pBind]="ptm('unmaskIcon')"> <ng-container *ngTemplateOutlet="showIconTemplate(); context: unmaskIconContext"></ng-container> </span> } } } <p-overlay #overlay [hostAttrSelector]="$attrSelector" [visible]="overlayVisible()" (visibleChange)="overlayVisible.set($event)" [options]="overlayOptions()" [target]="'@parent'" [appendTo]="$appendTo()" [unstyled]="unstyled()" [pt]="ptm('pcOverlay')" [motionOptions]="motionOptions()" > <ng-template #content> <div [class]="cx('overlay')" [style]="sx('overlay')" (click)="onOverlayClick($event)" [pBind]="ptm('overlay')" [attr.data-p]="overlayDataP"> <ng-container *ngTemplateOutlet="headerTemplate()"></ng-container> @if (contentTemplate()) { <ng-container *ngTemplateOutlet="contentTemplate()"></ng-container> } @else { <div [class]="cx('content')" [pBind]="ptm('content')"> <div [class]="cx('meter')" [pBind]="ptm('meter')">