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
JavaScript
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')">