# All files / src/form utils.ts

84.37% Statements 81/96
25% Branches 2/8
66.66% Functions 2/3
84.37% Lines 81/96

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
    971x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x

    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    13x
    13x
    13x
    13x

    13x
    13x
    13x
    13x

    13x
    13x
    13x
    13x
    13x
     import { type KeyboardEvent } from "react";

    /**
     * This util should be used to implement the native "Enter" keypress behavior
     * for "fake" form components to submit the form if exists.
     *
     * The way this will work will be:
     * - attempt to find a form by querying for a parent form element. if no parent
     *   form element can be found, try to use the `formId` in a
     *   `document.getElementById`
     * - if a form element is found, find the submit button within the form. If
     *   there are no submit buttons within the form, try to find a submit button in
     *   the document that is linked to this form by `form={formId}`
     * - if the submit button was found, click it to trigger the form submit
     *   behavior
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/requestSubmit
     * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
     * @internal
     * @remarks
     * \@since 2.7.0
     * \@since 6.0.0 No longer returns a boolean, added the `formId` parameter, and
     * moved into the form package.
     * \@since 6.0.0 Uses `form.requestSubmit` instead of clicking the submit button
     */
    export function tryToSubmitRelatedForm<E extends HTMLElement>(
      event: KeyboardEvent<E>,
      formId: string | undefined
    ): void {
      const { currentTarget } = event;
      let form: HTMLElement | null = null;
      if (formId) {
        form = document.getElementById(formId);
      } else {
        form = currentTarget.closest("form");
      }

      if (!form || !(form instanceof HTMLFormElement)) {
        return;
      }

      formId = formId || form.id;
      let submit = form.querySelector<HTMLButtonElement>('[type="submit"]');
      if (!submit && formId) {
        submit = document.querySelector<HTMLButtonElement>(
          `[type="submit"][form="${formId}"]`
        );
      }

      form.requestSubmit(submit);
    }

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export type ChangeableHTMLElement =
      | HTMLInputElement
      | HTMLTextAreaElement
      | HTMLSelectElement;

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export function isChangeableHTMLElement(
      element: Element | null
    ): element is ChangeableHTMLElement {
      return !!element && "value" in element;
    }

    /**
     * This is used to trigger a change event for a form element.
     *
     * @internal
     * @see https://stackoverflow.com/a/46012210
     * @remarks \@since 6.0.0
     */
    export function triggerManualChangeEvent(
      element: ChangeableHTMLElement | null,
      value: string | number
    ): void {
      if (!element) {
        return;
      }

      const prototype = Object.getPrototypeOf(element);
      const setter = Object.getOwnPropertyDescriptor(prototype, "value")?.set;
      if (!setter) {
        return;
      }

      setter.call(element, value);
      const event = new Event("input", { bubbles: true });
      element.dispatchEvent(event);
    }