381 lines
38 KiB
JavaScript
381 lines
38 KiB
JavaScript
|
import { CommonModule } from '@angular/common';
|
||
|
import { ChangeDetectionStrategy, Component, ContentChildren, EventEmitter, Input, NgModule, Output, ViewEncapsulation, booleanAttribute, forwardRef } from '@angular/core';
|
||
|
import { PrimeTemplate, SharedModule } from 'primeng/api';
|
||
|
import { InputTextModule } from 'primeng/inputtext';
|
||
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||
|
import { AutoFocusModule } from 'primeng/autofocus';
|
||
|
import * as i0 from "@angular/core";
|
||
|
import * as i1 from "@angular/common";
|
||
|
import * as i2 from "primeng/inputtext";
|
||
|
import * as i3 from "primeng/autofocus";
|
||
|
export const INPUT_OTP_VALUE_ACCESSOR = {
|
||
|
provide: NG_VALUE_ACCESSOR,
|
||
|
useExisting: forwardRef(() => InputOtp),
|
||
|
multi: true
|
||
|
};
|
||
|
/**
|
||
|
* Input Otp is used to enter one time passwords.
|
||
|
* @group Components
|
||
|
*/
|
||
|
export class InputOtp {
|
||
|
cd;
|
||
|
/**
|
||
|
* When present, it specifies that the component should have invalid state style.
|
||
|
* @group Props
|
||
|
*/
|
||
|
invalid = false;
|
||
|
/**
|
||
|
* When present, it specifies that the component should be disabled.
|
||
|
* @group Props
|
||
|
*/
|
||
|
disabled = false;
|
||
|
/**
|
||
|
* When present, it specifies that an input field is read-only.
|
||
|
* @group Props
|
||
|
*/
|
||
|
readonly = false;
|
||
|
/**
|
||
|
* Specifies the input variant of the component.
|
||
|
* @group Props
|
||
|
*/
|
||
|
variant = 'outlined';
|
||
|
/**
|
||
|
* Index of the element in tabbing order.
|
||
|
* @group Props
|
||
|
*/
|
||
|
tabindex = null;
|
||
|
/**
|
||
|
* Number of characters to initiate.
|
||
|
* @group Props
|
||
|
*/
|
||
|
length = 4;
|
||
|
/**
|
||
|
* Mask pattern.
|
||
|
* @group Props
|
||
|
*/
|
||
|
mask = false;
|
||
|
/**
|
||
|
* When present, it specifies that an input field is integer-only.
|
||
|
* @group Props
|
||
|
*/
|
||
|
integerOnly = false;
|
||
|
/**
|
||
|
* When present, it specifies that the component should automatically get focus on load.
|
||
|
* @group Props
|
||
|
*/
|
||
|
autofocus;
|
||
|
/**
|
||
|
* Callback to invoke on value change.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onChange = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when the component receives focus.
|
||
|
* @param {Event} event - Browser event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onFocus = new EventEmitter();
|
||
|
/**
|
||
|
* Callback to invoke when the component loses focus.
|
||
|
* @param {Event} event - Browser event.
|
||
|
* @group Emits
|
||
|
*/
|
||
|
onBlur = new EventEmitter();
|
||
|
templates;
|
||
|
inputTemplate;
|
||
|
tokens = [];
|
||
|
onModelChange = () => { };
|
||
|
onModelTouched = () => { };
|
||
|
value;
|
||
|
get inputMode() {
|
||
|
return this.integerOnly ? 'numeric' : 'text';
|
||
|
}
|
||
|
get inputType() {
|
||
|
return this.mask ? 'password' : 'text';
|
||
|
}
|
||
|
constructor(cd) {
|
||
|
this.cd = cd;
|
||
|
}
|
||
|
ngAfterContentInit() {
|
||
|
this.templates.forEach((item) => {
|
||
|
switch (item.getType()) {
|
||
|
case 'input':
|
||
|
this.inputTemplate = item.template;
|
||
|
break;
|
||
|
default:
|
||
|
this.inputTemplate = item.template;
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
getToken(index) {
|
||
|
return this.tokens[index];
|
||
|
}
|
||
|
getTemplateEvents(index) {
|
||
|
return {
|
||
|
input: (event) => this.onInput(event, index),
|
||
|
keydown: (event) => this.onKeyDown(event),
|
||
|
focus: (event) => this.onFocus.emit(event),
|
||
|
blur: (event) => this.onBlur.emit(event),
|
||
|
paste: (event) => this.onPaste(event)
|
||
|
};
|
||
|
}
|
||
|
onInput(event, index) {
|
||
|
this.tokens[index] = event.target.value;
|
||
|
this.updateModel(event);
|
||
|
if (event.inputType === 'deleteContentBackward') {
|
||
|
this.moveToPrev(event);
|
||
|
}
|
||
|
else if (event.inputType === 'insertText' || event.inputType === 'deleteContentForward') {
|
||
|
this.moveToNext(event);
|
||
|
}
|
||
|
}
|
||
|
updateModel(event) {
|
||
|
const newValue = this.tokens.join('');
|
||
|
this.onModelChange(newValue);
|
||
|
this.onChange.emit({
|
||
|
originalEvent: event,
|
||
|
value: newValue
|
||
|
});
|
||
|
}
|
||
|
writeValue(value) {
|
||
|
if (value) {
|
||
|
if (Array.isArray(value) && value.length > 0) {
|
||
|
this.value = value.slice(0, this.length);
|
||
|
}
|
||
|
else {
|
||
|
this.value = value.toString().split('').slice(0, this.length);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
this.value = value;
|
||
|
}
|
||
|
this.updateTokens();
|
||
|
this.cd.markForCheck();
|
||
|
}
|
||
|
updateTokens() {
|
||
|
if (this.value !== null && this.value !== undefined) {
|
||
|
if (Array.isArray(this.value)) {
|
||
|
this.tokens = [...this.value];
|
||
|
}
|
||
|
else {
|
||
|
this.tokens = this.value.toString().split('');
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
this.tokens = [];
|
||
|
}
|
||
|
}
|
||
|
getModelValue(i) {
|
||
|
return this.tokens[i - 1] || '';
|
||
|
}
|
||
|
getAutofocus(i) {
|
||
|
if (i === 1) {
|
||
|
return this.autofocus;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
registerOnChange(fn) {
|
||
|
this.onModelChange = fn;
|
||
|
}
|
||
|
registerOnTouched(fn) {
|
||
|
this.onModelTouched = fn;
|
||
|
}
|
||
|
moveToPrev(event) {
|
||
|
let prevInput = this.findPrevInput(event.target);
|
||
|
if (prevInput) {
|
||
|
prevInput.focus();
|
||
|
prevInput.select();
|
||
|
}
|
||
|
}
|
||
|
moveToNext(event) {
|
||
|
let nextInput = this.findNextInput(event.target);
|
||
|
if (nextInput) {
|
||
|
nextInput.focus();
|
||
|
nextInput.select();
|
||
|
}
|
||
|
}
|
||
|
findNextInput(element) {
|
||
|
let nextElement = element.nextElementSibling;
|
||
|
if (!nextElement)
|
||
|
return;
|
||
|
return nextElement.nodeName === 'INPUT' ? nextElement : this.findNextInput(nextElement);
|
||
|
}
|
||
|
findPrevInput(element) {
|
||
|
let prevElement = element.previousElementSibling;
|
||
|
if (!prevElement)
|
||
|
return;
|
||
|
return prevElement.nodeName === 'INPUT' ? prevElement : this.findPrevInput(prevElement);
|
||
|
}
|
||
|
onInputFocus(event) {
|
||
|
event.target.select();
|
||
|
this.onFocus.emit(event);
|
||
|
}
|
||
|
onInputBlur(event) {
|
||
|
this.onBlur.emit(event);
|
||
|
}
|
||
|
onKeyDown(event) {
|
||
|
if (event.altKey || event.ctrlKey || event.metaKey) {
|
||
|
return;
|
||
|
}
|
||
|
switch (event.code) {
|
||
|
case 'ArrowLeft':
|
||
|
this.moveToPrev(event);
|
||
|
event.preventDefault();
|
||
|
break;
|
||
|
case 'ArrowUp':
|
||
|
case 'ArrowDown':
|
||
|
event.preventDefault();
|
||
|
break;
|
||
|
case 'Backspace':
|
||
|
if (event.target.value.length === 0) {
|
||
|
this.moveToPrev(event);
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
break;
|
||
|
case 'ArrowRight':
|
||
|
this.moveToNext(event);
|
||
|
event.preventDefault();
|
||
|
break;
|
||
|
default:
|
||
|
if ((this.integerOnly && !((event.code.startsWith('Digit') || event.code.startsWith('Numpad')) && Number(event.key) >= 0 && Number(event.key) <= 9)) || (this.tokens.join('').length >= this.length && event.code !== 'Delete')) {
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
onPaste(event) {
|
||
|
let paste = event.clipboardData.getData('text');
|
||
|
if (paste.length) {
|
||
|
let pastedCode = paste.substring(0, this.length + 1);
|
||
|
if (!this.integerOnly || !isNaN(pastedCode)) {
|
||
|
this.tokens = pastedCode.split('');
|
||
|
this.updateModel(event);
|
||
|
}
|
||
|
}
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
getRange(n) {
|
||
|
return Array.from({ length: n }, (_, index) => index + 1);
|
||
|
}
|
||
|
trackByFn(index) {
|
||
|
return index;
|
||
|
}
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: InputOtp, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
||
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "17.3.7", type: InputOtp, selector: "p-inputOtp", inputs: { invalid: "invalid", disabled: "disabled", readonly: "readonly", variant: "variant", tabindex: "tabindex", length: "length", mask: "mask", integerOnly: "integerOnly", autofocus: ["autofocus", "autofocus", booleanAttribute] }, outputs: { onChange: "onChange", onFocus: "onFocus", onBlur: "onBlur" }, host: { classAttribute: "p-inputotp p-component" }, providers: [INPUT_OTP_VALUE_ACCESSOR], queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: `
|
||
|
<ng-container *ngFor="let i of getRange(length); trackBy: trackByFn">
|
||
|
<ng-container *ngIf="!inputTemplate">
|
||
|
<input
|
||
|
type="text"
|
||
|
pInputText
|
||
|
[value]="getModelValue(i)"
|
||
|
[maxLength]="1"
|
||
|
[type]="inputType"
|
||
|
class="p-inputotp-input"
|
||
|
[inputmode]="inputMode"
|
||
|
[variant]="variant"
|
||
|
[readonly]="readonly"
|
||
|
[disabled]="disabled"
|
||
|
[invalid]="invalid"
|
||
|
[tabindex]="tabindex"
|
||
|
[unstyled]="unstyled"
|
||
|
(input)="onInput($event, i - 1)"
|
||
|
(focus)="onInputFocus($event)"
|
||
|
(blur)="onInputBlur($event)"
|
||
|
(paste)="onPaste($event)"
|
||
|
(keydown)="onKeyDown($event)"
|
||
|
pAutoFocus
|
||
|
[autofocus]="getAutofocus(i)"
|
||
|
/>
|
||
|
</ng-container>
|
||
|
<ng-container *ngIf="inputTemplate">
|
||
|
<ng-container *ngTemplateOutlet="inputTemplate; context: { $implicit: getToken(i - 1), events: getTemplateEvents(i - 1), index: i }"> </ng-container>
|
||
|
</ng-container>
|
||
|
</ng-container>
|
||
|
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.AutoFocus, selector: "[pAutoFocus]", inputs: ["autofocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
||
|
}
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: InputOtp, decorators: [{
|
||
|
type: Component,
|
||
|
args: [{
|
||
|
selector: 'p-inputOtp',
|
||
|
template: `
|
||
|
<ng-container *ngFor="let i of getRange(length); trackBy: trackByFn">
|
||
|
<ng-container *ngIf="!inputTemplate">
|
||
|
<input
|
||
|
type="text"
|
||
|
pInputText
|
||
|
[value]="getModelValue(i)"
|
||
|
[maxLength]="1"
|
||
|
[type]="inputType"
|
||
|
class="p-inputotp-input"
|
||
|
[inputmode]="inputMode"
|
||
|
[variant]="variant"
|
||
|
[readonly]="readonly"
|
||
|
[disabled]="disabled"
|
||
|
[invalid]="invalid"
|
||
|
[tabindex]="tabindex"
|
||
|
[unstyled]="unstyled"
|
||
|
(input)="onInput($event, i - 1)"
|
||
|
(focus)="onInputFocus($event)"
|
||
|
(blur)="onInputBlur($event)"
|
||
|
(paste)="onPaste($event)"
|
||
|
(keydown)="onKeyDown($event)"
|
||
|
pAutoFocus
|
||
|
[autofocus]="getAutofocus(i)"
|
||
|
/>
|
||
|
</ng-container>
|
||
|
<ng-container *ngIf="inputTemplate">
|
||
|
<ng-container *ngTemplateOutlet="inputTemplate; context: { $implicit: getToken(i - 1), events: getTemplateEvents(i - 1), index: i }"> </ng-container>
|
||
|
</ng-container>
|
||
|
</ng-container>
|
||
|
`,
|
||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||
|
encapsulation: ViewEncapsulation.None,
|
||
|
host: {
|
||
|
class: 'p-inputotp p-component'
|
||
|
},
|
||
|
providers: [INPUT_OTP_VALUE_ACCESSOR]
|
||
|
}]
|
||
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { invalid: [{
|
||
|
type: Input
|
||
|
}], disabled: [{
|
||
|
type: Input
|
||
|
}], readonly: [{
|
||
|
type: Input
|
||
|
}], variant: [{
|
||
|
type: Input
|
||
|
}], tabindex: [{
|
||
|
type: Input
|
||
|
}], length: [{
|
||
|
type: Input
|
||
|
}], mask: [{
|
||
|
type: Input
|
||
|
}], integerOnly: [{
|
||
|
type: Input
|
||
|
}], autofocus: [{
|
||
|
type: Input,
|
||
|
args: [{ transform: booleanAttribute }]
|
||
|
}], onChange: [{
|
||
|
type: Output
|
||
|
}], onFocus: [{
|
||
|
type: Output
|
||
|
}], onBlur: [{
|
||
|
type: Output
|
||
|
}], templates: [{
|
||
|
type: ContentChildren,
|
||
|
args: [PrimeTemplate]
|
||
|
}] } });
|
||
|
export class InputOtpModule {
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: InputOtpModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
||
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.7", ngImport: i0, type: InputOtpModule, declarations: [InputOtp], imports: [CommonModule, SharedModule, InputTextModule, AutoFocusModule], exports: [InputOtp, SharedModule] });
|
||
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: InputOtpModule, imports: [CommonModule, SharedModule, InputTextModule, AutoFocusModule, SharedModule] });
|
||
|
}
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: InputOtpModule, decorators: [{
|
||
|
type: NgModule,
|
||
|
args: [{
|
||
|
imports: [CommonModule, SharedModule, InputTextModule, AutoFocusModule],
|
||
|
exports: [InputOtp, SharedModule],
|
||
|
declarations: [InputOtp]
|
||
|
}]
|
||
|
}] });
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXRvdHAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwL2NvbXBvbmVudHMvaW5wdXRvdHAvaW5wdXRvdHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBb0IsdUJBQXVCLEVBQXFCLFNBQVMsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUEwQixpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDek8sT0FBTyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRW5ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7QUFHcEQsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQVE7SUFDekMsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQztJQUN2QyxLQUFLLEVBQUUsSUFBSTtDQUNkLENBQUM7QUFDRjs7O0dBR0c7QUF5Q0gsTUFBTSxPQUFPLFFBQVE7SUFxRkU7SUFwRm5COzs7T0FHRztJQUNNLE9BQU8sR0FBWSxLQUFLLENBQUM7SUFDbEM7OztPQUdHO0lBRU0sUUFBUSxHQUFZLEtBQUssQ0FBQztJQUNuQzs7O09BR0c7SUFDTSxRQUFRLEdBQVksS0FBSyxDQUFDO0lBQ25DOzs7T0FHRztJQUNNLE9BQU8sR0FBMEIsVUFBVSxDQUFDO0lBQ3JEOzs7T0FHRztJQUNNLFFBQVEsR0FBa0IsSUFBSSxDQUFDO0lBQ3hDOzs7T0FHRztJQUNNLE1BQU0sR0FB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
|