All files / src/utils input.ts

82.97% Statements 39/47
64.1% Branches 25/39
53.33% Functions 8/15
84.78% Lines 39/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 1035x                     5x             61x     61x 61x   61x 61x 499x 499x         157x       61x 61x       61x   61x 61x       61x 61x       61x 61x 61x 36x 36x     61x 61x             61x 61x 74x   61x     61x 61x 89x   61x     61x 61x 378x     61x 61x         61x     61x            
import { findAll } from "./dom"
 
type Callbacks = {
  onSubmit?: (value: string) => void
  onInput?: (value: string) => void
  onFocus?: (value: string) => void
  onBlur?: (value: string) => void
  onKeyDown?: (value: string, key: string) => void
  onClick?: (value: string) => void
}
 
export function bindInput(
  selector: string | HTMLInputElement,
  callbacks: Callbacks
): {
  destroy: () => void
} {
  const target =
    selector instanceof HTMLInputElement
      ? [selector]
      : findAll(selector, HTMLInputElement)
  const unbindCallbacks = target.flatMap(el => {
    const cbs: Array<() => void> = []
 
    if (callbacks.onSubmit) {
      const onKeyDown = (event: KeyboardEvent) => {
        callbacks.onKeyDown?.(el.value, event.key)
        if (
          event.key === "ArrowDown" ||
          event.key === "ArrowUp" ||
          event.key === "Enter"
        ) {
          event.preventDefault()
        }
      }
 
      el.addEventListener("keydown", onKeyDown)
      cbs.push(() => {
        el.removeEventListener("keydown", onKeyDown)
      })
 
      const form = el.form
 
      if (form) {
        const onSubmit = (event: SubmitEvent) => {
          event.preventDefault()
          callbacks.onSubmit?.(el.value)
        }
        form.addEventListener("submit", onSubmit)
        cbs.push(() => {
          form?.removeEventListener("submit", onSubmit)
        })
 
        const buttons = Array.from(form.querySelectorAll("[type=submit]"))
        buttons.forEach(button => {
          const onClick = (event: Event) => {
            event.preventDefault()
            callbacks.onSubmit?.(el.value)
          }
 
          button.addEventListener("click", onClick)
          cbs.push(() => {
            button.removeEventListener("click", onClick)
          })
        })
      }
    }
 
    if (callbacks.onClick) {
      const onClick = () => {
        callbacks.onClick?.(el.value)
      }
      el.addEventListener("click", onClick)
    }
 
    if (callbacks.onFocus) {
      const onFocus = () => {
        callbacks.onFocus?.(el.value)
      }
      el.addEventListener("focus", onFocus)
    }
 
    if (callbacks.onInput) {
      const onInput = () => {
        callbacks.onInput?.(el.value)
      }
 
      el.addEventListener("input", onInput)
      cbs.push(() => {
        el.removeEventListener("input", onInput)
      })
    }
 
    return cbs
  })
 
  return {
    destroy() {
      unbindCallbacks.forEach(v => v())
    },
  }
}