{"version":3,"file":"pv-frontend-pv-shared-components-otp-input.mjs","sources":["../../../projects/pv-shared-components/otp-input/otp-input.component.ts","../../../projects/pv-shared-components/otp-input/otp-input.component.html","../../../projects/pv-shared-components/otp-input/otp-input.module.ts","../../../projects/pv-shared-components/otp-input/pv-frontend-pv-shared-components-otp-input.ts"],"sourcesContent":["import {\n  AfterViewInit,\n  Component,\n  ElementRef,\n  Input,\n  QueryList,\n  ViewChildren,\n  ViewEncapsulation,\n} from '@angular/core';\nimport {\n  ControlValueAccessor,\n  FormArray,\n  FormControl,\n  NG_VALUE_ACCESSOR,\n  Validators,\n} from '@angular/forms';\nimport { OverrideStyleConfig } from '@pv-frontend/pv-shared-components/common/types';\n\nexport interface OTPInputStyleConfig {\n  container?: OverrideStyleConfig;\n  label?: OverrideStyleConfig;\n  inputContainer?: OverrideStyleConfig;\n  input?: OverrideStyleConfig;\n  error?: OverrideStyleConfig;\n}\n\n@Component({\n  selector: 'pv-otp-input',\n  templateUrl: './otp-input.component.html',\n  styleUrls: ['./otp-input.component.scss'],\n  providers: [\n    {\n      provide: NG_VALUE_ACCESSOR,\n      useExisting: OTPInput,\n      multi: true,\n    },\n  ],\n  encapsulation: ViewEncapsulation.None,\n})\nexport class OTPInput implements ControlValueAccessor, AfterViewInit {\n  public onChange?: (value: string) => void;\n  public onTouched?: () => void;\n\n  #size = 4;\n  public inputs = this.getFormArray(this.#size);\n\n  // there is a way to do this without maintaining a variable for focus\n  // but safari has an issue where the order of events (keydown, input, keyup) might get jumbled in some scenarios\n  // hence we are sticking with using a variable here for referencing the position to be focussed on\n  #scheduledFocus: number | null = null;\n\n  @ViewChildren('inputEl')\n  public inputEls!: QueryList<ElementRef<HTMLInputElement>>;\n\n  @Input()\n  public set size(_size: number) {\n    this.#size = _size;\n    this.inputs = this.getFormArray(_size);\n  }\n\n  @Input()\n  public label: string = '';\n\n  /**\n   * Explicitly send this flag when backend sends some erroneous response for OTP\n   */\n  @Input()\n  public isInvalid: boolean = false;\n\n  /**\n   * Error message to be shown below the otp input\n   */\n  @Input()\n  public errorMessage: string = '';\n\n  @Input()\n  public style?: OTPInputStyleConfig = {};\n\n  @Input()\n  public styleClass?: string;\n\n  @Input()\n  public autoFocus?: boolean = false;\n\n  // this is for mainly handling autofocus\n  public ngAfterViewInit(): void {\n    if (this.inputEls && this.inputEls.length > 0 && this.autoFocus)\n      this.inputEls.get(0)?.nativeElement.focus();\n  }\n\n  // All handlers from here on\n\n  public handleInput(): void {\n    this.#updateWiredValue();\n\n    if (this.#scheduledFocus != null) {\n      this.#focusInput(this.#scheduledFocus);\n      this.#scheduledFocus = null;\n    }\n  }\n\n  public handleKeyDown(e: KeyboardEvent, idx: number): void {\n    // allow tabs to switch between inputs\n    if (e.key === 'Tab') {\n      return;\n    }\n\n    if (e.key === 'Backspace' || e.key === 'Delete') {\n      // In case the input is already filled, delete the value and focus on the same input only\n      if (this.inputs.controls[idx].value) {\n        this.#scheduledFocus = idx;\n      } else {\n        // In case of delete or backspace queue up the focus to be done on previous index if the current input isn't filled\n        if (idx > 0) {\n          this.#scheduledFocus = idx - 1;\n          this.#focusInput(this.#scheduledFocus);\n        }\n      }\n      return;\n    }\n\n    const isDigit = /\\d/.test(e.key);\n\n    // Safari fires Cmd + V through keyPress event as well\n    // So we need to handle it here and let it through, this is then handled by the paste handler\n    if (e.key === 'v' && e.metaKey) {\n      return;\n    }\n\n    // return if a non-numeric and unallowed character is pressed\n    if (!isDigit) {\n      e.preventDefault();\n      return;\n    }\n\n    if (isDigit && idx + 1 < this.#size) {\n      // If user inputs digits & we are not on the last input we want to advance the focus\n      this.#scheduledFocus = idx + 1;\n    }\n\n    if (isDigit && this.inputs.controls[idx].value) {\n      // If user deselects an input which already has a value we want to clear it so that it doesn't have more than 1 digit\n      this.inputs.controls[idx].setValue('');\n    }\n  }\n\n  public handleFocus(e: FocusEvent): void {\n    (e.target as HTMLInputElement).focus();\n  }\n\n  public handlePaste(event: ClipboardEvent, idx: number): void {\n    event.preventDefault();\n    if (idx !== 0) {\n      // If the target input is not the first one - ignore\n      // We only allow pasting when the first box is selected, not from any other box\n      return;\n    }\n    const pasteData = event.clipboardData?.getData('text');\n    const regex = new RegExp(`\\\\d{${this.#size}}`);\n\n    if (!pasteData || !regex.test(pasteData)) {\n      // If there is nothing to be pasted or the pasted data does not comply with the required format - ignore the event\n      return;\n    }\n\n    for (let i = 0; i < pasteData.length; i++) {\n      this.inputs.controls[i].setValue(pasteData[i]);\n    }\n\n    this.#focusInput(this.inputEls.length - 1);\n    this.#updateWiredValue();\n    this.onTouched?.();\n  }\n\n  // Private methods referenced in handlers from here on\n\n  #focusInput(idx: number): void {\n    // In order not to interfere with the input we setTimeout before advancing the focus\n    // Without setTimeout this would create issues\n    setTimeout(() => this.inputEls.get(idx)?.nativeElement.focus());\n  }\n\n  #updateWiredValue(): void {\n    // We want to expose the value as a plain string\n    setTimeout(() => this.onChange?.(this.inputs.value.join('')));\n  }\n\n  private getFormArray(_size: number): FormArray {\n    const arr = [];\n    for (let i = 0; i < _size; i++) {\n      arr.push(new FormControl('', Validators.required));\n    }\n\n    return new FormArray(arr);\n  }\n\n  // All the ControlValueAccessor overrides from here on\n\n  public writeValue(): void {\n    // this is called when the form calls reset\n    this.inputs.setValue(new Array(this.#size).fill(''));\n  }\n\n  public registerOnChange(fn: (value: string) => void): void {\n    this.onChange = fn;\n  }\n\n  public registerOnTouched(fn: () => void): void {\n    this.onTouched = fn;\n  }\n\n  public setDisabledState?(isDisabled: boolean): void {\n    if (isDisabled) {\n      this.inputs.disable();\n    } else {\n      this.inputs.enable();\n    }\n  }\n}\n","<div\n  class=\"pv-otp-input-container flex flex-column gap-1 w-max\"\n  [ngClass]=\"styleClass\"\n  [style]=\"this.style?.container\">\n  <span\n    *ngIf=\"this.label\"\n    class=\"pv-otp-input-label mb-3 surface-text-subtle-low-contrast text-sm\"\n    [style]=\"this.style?.label\">\n    {{ this.label }}\n  </span>\n  <div\n    class=\"pv-otp-input flex flex-row gap-2\"\n    [style]=\"this.style?.inputContainer\">\n    <input\n      #inputEl\n      [class.is-invalid-otp]=\"this.isInvalid\"\n      class=\"pv-otp-input-ele text-base w-4rem h-4rem md:w-3rem md:h-3rem text-center font-bold\"\n      *ngFor=\"let input of this.inputs.controls; let i = index\"\n      [attr.autocomplete]=\"'one-time-code'\"\n      (focus)=\"this.handleFocus($event)\"\n      (blur)=\"this.onTouched?.()\"\n      (input)=\"this.handleInput()\"\n      (keydown)=\"this.handleKeyDown($event, i)\"\n      (paste)=\"this.handlePaste($event, i)\"\n      [formControl]=\"$any(input)\"\n      type=\"text\"\n      inputmode=\"numeric\"\n      [style]=\"this.style?.input\" />\n  </div>\n  <span\n    *ngIf=\"this.isInvalid && this.errorMessage\"\n    class=\"pv-invalid-otp-label feedback-text-negative w-max text-sm mt-2 max-w-full\"\n    [style]=\"this.style?.error\">\n    {{ this.errorMessage }}\n  </span>\n</div>\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { ReactiveFormsModule } from '@angular/forms';\n\nimport { OTPInput } from './otp-input.component';\n\n@NgModule({\n  imports: [CommonModule, ReactiveFormsModule],\n  declarations: [OTPInput],\n  exports: [OTPInput],\n})\nexport class PvOTPInputModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}