Passed
Push — task/application-profile-react... ( 9a6ac9...5f3abf )
by Yonathan
07:55
created

resources/assets/js/helpers/forms.ts   A

Complexity

Total Complexity 6
Complexity/F 0

Size

Lines of Code 80
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 6
eloc 47
mnd 6
bc 6
fnc 0
dl 0
loc 80
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
import { FormikProps, FormikValues } from "formik";
2
import isEmpty from "lodash/isEmpty";
3
import { RefObject } from "react";
4
import { notEmpty } from "./queries";
5
6
export const focusableElementSelector =
7
  "button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])";
8
9
/**
10
 * Get all focusable elements that are decendent of element,
11
 * or all focusable elements in the document body if element is null.
12
 */
13
export const getFocusableElements = (
14
  element: HTMLElement | null = null,
15
): NodeListOf<HTMLElement> =>
16
  element
17
    ? element.querySelectorAll<HTMLElement>(focusableElementSelector)
18
    : document.body.querySelectorAll<HTMLElement>(focusableElementSelector);
19
20
/**
21
 * Focuses on a element with given id.
22
 * @param id
23
 */
24
export const focusOnElement = (elementId: string): void => {
25
  const element = document.getElementById(elementId);
26
  if (element) {
27
    element.focus();
28
  }
29
};
30
31
/**
32
 * Toggle accordion with given id.
33
 * @param id
34
 */
35
export const toggleAccordion = (elementId: string): void => {
36
  const element = document.getElementById(elementId);
37
  if (element) {
38
    element.classList.toggle("active");
39
    const { firstElementChild } = element;
40
    if (firstElementChild) {
41
      firstElementChild.setAttribute("aria-expanded", "true");
42
    }
43
  }
44
};
45
46
/**
47
 * Runs validation on all forms, then returns true if they are all valid.
48
 * TODO: Figure out how to focus the first (or last) invalid input, if any.
49
 * @param refs
50
 */
51
export const validateAllForms = (
52
  refs: RefObject<FormikProps<FormikValues>>[],
53
): Promise<boolean> => {
54
  return Promise.all(
55
    refs
56
      .filter(notEmpty)
57
      .map(
58
        (ref: RefObject<FormikProps<FormikValues>>): Promise<any> =>
59
          ref.current !== null ? ref.current.validateForm() : Promise.resolve(),
60
      ),
61
  ).then((errors) => errors.every(isEmpty));
62
};
63
64
/**
65
 * Submits all forms.
66
 * @param refs
67
 */
68
export const submitAllForms = (
69
  refs: React.RefObject<FormikProps<FormikValues>>[],
70
): Promise<void[]> => {
71
  return Promise.all(
72
    refs.filter(notEmpty).map((ref: RefObject<FormikProps<FormikValues>>) => {
73
      // TODO: Might need to make one mass submission by combining all values into an array.
74
      return ref.current !== null
75
        ? ref.current.submitForm()
76
        : Promise.resolve();
77
    }),
78
  );
79
};
80