{"version":3,"sources":["../../src/elements/otp-input.ts","../../src/styles/elements/otp-input.ts"],"sourcesContent":["import { html, LitElement } from 'lit';\nimport {\n customElement, property, queryAll, state\n} from 'lit/decorators.js';\nimport { stylesBase } from '../styles/elements/otp-input';\nimport { EnumKeyCodes } from '../utilities/constants';\nimport { emitEvent } from '../utilities/events';\n\n\n/**\n * @since 4.1.0\n * @status stable\n *\n * @tagname kemet-otp-input\n * @summary An input element that accepts multiple items from a combo.\n *\n * @prop {number} digits - The number of inputs.\n * @prop {string} pattern - The pattern to match against for stripping characters\n * @prop {string} value - All digits entered by the user combined in one string.\n *\n * @csspart input - The input elements.\n *\n * @cssproperty --kemet-otp-input-color - The text color of the otp inputs.\n * @cssproperty --kemet-otp-input-min-width - The minimum width of the otp inputs.\n * @cssproperty --kemet-otp-input-font-size - The font size of the otp inputs.\n * @cssproperty --kemet-otp-input-border - The border of the otp inputs.\n * @cssproperty --kemet-otp-input-border-radius - The border radius of the otp inputs.\n *\n * @event kemet-completed - Fires when otp is filled out completely\n *\n */\n\n@customElement('kemet-otp-input')\nexport default class KemetOtpInput extends LitElement {\n  static styles = [stylesBase];\n\n  @property({ type: Number })\n  digits: number = 6;\n\n  @property({ type: String, reflect: true })\n  value: string = '';\n\n  @property()\n  pattern: string;\n\n  @state()\n  autoFocus: boolean = true;\n\n  @state()\n  values: string[] = [];\n\n  @state()\n  lastInput: string;\n\n  @state()\n  completed: boolean = false;\n\n  @queryAll('input')\n  inputElements: NodeListOf<HTMLInputElement>;\n\n  updated() {\n    this.determineCompleted();\n  }\n\n  render() {\n    return this.makeInputs();\n  }\n\n  determineCompleted() {\n    const hasBlankValues = this.values.includes('');\n    if (this.values.length === this.digits && !hasBlankValues && !this.completed) {\n      emitEvent(this, 'kemet-completed', {\n        detail: { value: this.value },\n        bubbles: true,\n        composed: true,\n      });\n      this.completed = true;\n    }\n  }\n\n  makeInputs() {\n    return Array.from(\n      { length: this.digits },\n      (_, index) => html`\n        <label>\n          <span>Enter digit ${index + 1}</span>\n          <input\n            part=\"input\"\n            id=\"${index}\"\n            maxlength=\"1\"\n            @input=${this.handleInput}\n            @keydown=${this.handleKeyDown}\n            @paste=${this.handlePaste}\n          />\n        </label>\n      `\n    );\n  }\n\n  eatCharacters(inputValue: string) {\n    const regex = new RegExp(this.pattern);\n    return inputValue.replace(regex, '');\n  }\n\n  handleInput(event: InputEvent) {\n    const input = event.target as HTMLInputElement;\n    const currentIndex = parseInt(input.getAttribute('id'));\n    const nextInput = this.inputElements[currentIndex + 1];\n\n    if (this.pattern) {\n      input.value = this.eatCharacters(input.value);\n    }\n\n    this.values[currentIndex] = input.value;\n    this.value = this.values.join('');\n    this.lastInput = input.value;\n\n    const fullDigits = this.values.length === this.digits && !!input.value;\n\n    if (!fullDigits) {\n      this.completed = false;\n    }\n\n    if (nextInput && this.autoFocus && !!input.value) {\n      nextInput.focus();\n    }\n  }\n\n  handleKeyDown(event: KeyboardEvent) {\n    this.autoFocus = event.key !== EnumKeyCodes.BACKSPACE;\n  }\n\n  handlePaste(event: ClipboardEvent) {\n    event.preventDefault();\n    const pasteData = event.clipboardData?.getData('text') ?? '';\n\n    // Trim and limit to number of digits\n    const charactersString = this.eatCharacters(pasteData.trim().slice(0, this.digits).split('').join(''));\n    const charactersArray = charactersString.split('');\n\n    // Fill the inputs and values array one by one\n    charactersArray.forEach((character, index) => {\n      const input = this.inputElements[index];\n      if (input && !!character) {\n        input.value = character;\n        this.values[index] = character;\n      }\n    });\n\n    const lastFilled = this.inputElements[charactersArray.length - 1];\n    lastFilled?.focus();\n    this.value = this.values.join('');\n    this.determineCompleted();\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'kemet-otp-input': KemetOtpInput\n  }\n}\n","import { css } from 'lit';\n\nexport const stylesBase = css`\n  :host {\n    --kemet-otp-input-color: rgb(var(--kemet-color-gray-600));\n    --kemet-otp-input-min-width: 3rem;\n    --kemet-otp-input-font-size: 2rem;\n    --kemet-otp-input-border: 1px solid rgb(var(--kemet-color-gray-300));\n    --kemet-otp-input-border-radius: var(--kemet-border-radius-md);\n\n    display: grid;\n    gap: var(--kemet-spacer-md);\n    grid-template-columns: repeat(auto-fit, minmax(var(--kemet-otp-input-min-width), 1fr));\n  }\n\n  label {\n    display: flex;\n    aspect-ratio: 4/3;\n  }\n\n  span {\n    position: absolute;\n    margin: -1px;\n    width: 1px;\n    height: 1px;\n    display: block;\n    overflow: hidden;\n    border-width: 0;\n    clip: rect(0, 0, 0, 0);\n    white-space: nowrap;\n  }\n\n  [part=\"input\"] {\n    color: var(--kemet-otp-input-color);\n    text-align: center;\n    width: 100%;\n    height: 100%;\n    font-size: var(--kemet-otp-input-font-size);\n    border: var(--kemet-otp-input-border);\n    border-radius: var(--kemet-otp-input-border-radius);\n  }\n`;\n"],"mappings":"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","names":[]}