cemtrik-dependencies 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README copy.md +54 -0
  2. package/README.md +29 -0
  3. package/components.js +47 -0
  4. package/hooks.js +4 -0
  5. package/package.json +58 -0
  6. package/postcss.config.js +6 -0
  7. package/src/assets/cemtrik-icons-v1.0/Read Me.txt +7 -0
  8. package/src/assets/cemtrik-icons-v1.0/demo-files/demo.css +152 -0
  9. package/src/assets/cemtrik-icons-v1.0/demo-files/demo.js +30 -0
  10. package/src/assets/cemtrik-icons-v1.0/demo.html +318 -0
  11. package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.eot +0 -0
  12. package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.svg +31 -0
  13. package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.ttf +0 -0
  14. package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.woff +0 -0
  15. package/src/assets/cemtrik-icons-v1.0/selection.json +1 -0
  16. package/src/assets/cemtrik-icons-v1.0/style.css +96 -0
  17. package/src/assets/icons/actions.svg +4 -0
  18. package/src/assets/icons/attributes.svg +5 -0
  19. package/src/assets/icons/bars.svg +3 -0
  20. package/src/assets/icons/bell.svg +4 -0
  21. package/src/assets/icons/cemtrik.svg +9 -0
  22. package/src/assets/icons/clipboardCheck.svg +4 -0
  23. package/src/assets/icons/clipboardList.svg +5 -0
  24. package/src/assets/icons/clock.svg +3 -0
  25. package/src/assets/icons/flag.svg +3 -0
  26. package/src/assets/icons/folder.svg +3 -0
  27. package/src/assets/icons/graph_indicators.svg +3 -0
  28. package/src/assets/icons/group.svg +3 -0
  29. package/src/assets/icons/letter.svg +3 -0
  30. package/src/assets/icons/measuring_points.svg +3 -0
  31. package/src/assets/icons/reports.svg +4 -0
  32. package/src/assets/icons/roboot.svg +3 -0
  33. package/src/assets/icons/user.svg +4 -0
  34. package/src/assets/icons/user_point.svg +10 -0
  35. package/src/assets/icons/vector.svg +3 -0
  36. package/src/assets/icons/vector2.svg +3 -0
  37. package/src/components/atoms/Alert/index.js +104 -0
  38. package/src/components/atoms/Alert/index.test.js +36 -0
  39. package/src/components/atoms/Avatar/index.js +63 -0
  40. package/src/components/atoms/Avatar/index.test.js +30 -0
  41. package/src/components/atoms/Bullets/Bullets.test.js +22 -0
  42. package/src/components/atoms/Bullets/index.js +51 -0
  43. package/src/components/atoms/ButtonOutline/index.js +43 -0
  44. package/src/components/atoms/ButtonOutline/index.test.js +36 -0
  45. package/src/components/atoms/ButtonPagination/index.js +37 -0
  46. package/src/components/atoms/ButtonPagination/index.test.js +36 -0
  47. package/src/components/atoms/ButtonSolid/index.js +74 -0
  48. package/src/components/atoms/ButtonSolid/index.test.js +59 -0
  49. package/src/components/atoms/Checkbox/index.js +52 -0
  50. package/src/components/atoms/Checkbox/index.test.js +15 -0
  51. package/src/components/atoms/ConfirmationAbandoningCreation/index.js +70 -0
  52. package/src/components/atoms/ConfirmationAbandoningCreation/index.test.js +70 -0
  53. package/src/components/atoms/Divider/index.js +10 -0
  54. package/src/components/atoms/Divider/index.test.js +12 -0
  55. package/src/components/atoms/GoBack/index.js +30 -0
  56. package/src/components/atoms/GoBack/index.test.js +24 -0
  57. package/src/components/atoms/Input/index.js +107 -0
  58. package/src/components/atoms/Input/index.test.js +63 -0
  59. package/src/components/atoms/InputDropdown/index.js +111 -0
  60. package/src/components/atoms/InputDropdown/index.test.js +86 -0
  61. package/src/components/atoms/Select/index.js +199 -0
  62. package/src/components/atoms/Select/index.test.js +86 -0
  63. package/src/components/atoms/Spinner/index.js +49 -0
  64. package/src/components/atoms/Spinner/index.test.js +9 -0
  65. package/src/components/atoms/Switch/index.js +46 -0
  66. package/src/components/atoms/Switch/index.test.js +18 -0
  67. package/src/components/atoms/Textarea/index.js +136 -0
  68. package/src/components/atoms/Textarea/index.spec.js +51 -0
  69. package/src/components/atoms/Tooltip/index.js +64 -0
  70. package/src/components/atoms/Tooltip/index.test.js +31 -0
  71. package/src/components/atoms/UploadImage/index.js +55 -0
  72. package/src/components/atoms/UploadImage/index.test.js +36 -0
  73. package/src/components/molecules/Dropdown/index.js +315 -0
  74. package/src/components/molecules/Dropdown/index.test.js +190 -0
  75. package/src/components/molecules/Modal/index.js +103 -0
  76. package/src/components/molecules/Modal/index.test.js +42 -0
  77. package/src/components/molecules/Pagination/index.js +126 -0
  78. package/src/components/molecules/Pagination/index.test.js +57 -0
  79. package/src/components/templates/Accordion/index.js +174 -0
  80. package/src/components/templates/Accordion/index.test.js +130 -0
  81. package/src/hooks/useCloseModal/index.js +27 -0
  82. package/src/hooks/useCloseModal/index.test.js +26 -0
  83. package/src/hooks/useForm/index.js +70 -0
  84. package/src/hooks/useForm/useForm.test.js +104 -0
  85. package/src/hooks/useMediaQuery/index.js +53 -0
  86. package/src/hooks/useMediaQuery/useMediaQuery.test.js +46 -0
  87. package/src/hooks/useWindowDimensions/index.js +34 -0
  88. package/src/hooks/useWindowDimensions/useWindowDimensions.test.js +19 -0
  89. package/src/utils/index.js +32 -0
  90. package/src/utils/index.test.js +56 -0
  91. package/tailwind.config.js +117 -0
  92. package/utils.js +8 -0
@@ -0,0 +1,74 @@
1
+ // 1.- libraries
2
+ import { useState } from "react";
3
+ import classnames from "classnames";
4
+
5
+ // 2.- utils
6
+ import { classNames } from "../../../utils";
7
+
8
+ const ButtonSolid = ({
9
+ children,
10
+ classNameButton = "bg-indigo-600 hover:bg-indigo-700 focus-visible:outline-indigo-600 shadow-indigo-500 rounded font-semibold px-3 py-1.5 text-white w-full",
11
+ classNameText = "",
12
+ icon = null,
13
+ edge = null,
14
+ disabled = false,
15
+ type = "button",
16
+ onClick,
17
+ id,
18
+ outline = "0px 0px 0px 2px #6366F1, 0px 0px 0px 2px #FFF, 0px 1px 2px 0px rgba(0, 0, 0, 0.05)",
19
+ classNameContainer = "",
20
+ }) => {
21
+ const [isShadow, setIsShadow] = useState(false);
22
+
23
+ const classText = classnames({
24
+ "ml-2": edge === "start" && icon !== null,
25
+ "mr-2": edge === "end" && icon !== null,
26
+ });
27
+
28
+ const handleClick = () => {
29
+ onClick && onClick();
30
+ };
31
+
32
+ return (
33
+ <div
34
+ className={classNames(
35
+ "rounded-md p-0.5",
36
+ classNameContainer !== "" && classNameContainer,
37
+ )}
38
+ style={{
39
+ boxShadow: isShadow
40
+ ? outline
41
+ : "0px 0px 0px 0px #6366F1, 0px 0px 0px 0px #FFF, 0px 0px 0px 0px rgba(0, 0, 0, 0.05)",
42
+ transition: "box-shadow .1s ease-in-out",
43
+ }}
44
+ data-testid="container-button"
45
+ >
46
+ <button
47
+ className={classNames(
48
+ "flex justify-center items-center text-sm leading-6 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2",
49
+ disabled && "text-white bg-gray-300 rounded focus:outline-none cursor-default",
50
+ disabled ? classNameButton.replace(/\bbg-\w+\b/g, "") : classNameButton,
51
+ )}
52
+ type={type}
53
+ onClick={handleClick}
54
+ onFocus={() => setIsShadow(true)}
55
+ onBlur={() => setIsShadow(false)}
56
+ disabled={disabled}
57
+ data-testid={`button-solid-${id}`}
58
+ >
59
+ {edge === "start" && icon !== null && <span className="flex">{icon}</span>}
60
+ <span
61
+ className={classNames(
62
+ classNameText.length === 0 && classText,
63
+ classNameText.length !== 0 && classNameText,
64
+ )}
65
+ >
66
+ {children}
67
+ </span>
68
+ {edge === "end" && icon !== null && <span>{icon}</span>}
69
+ </button>
70
+ </div>
71
+ );
72
+ };
73
+
74
+ export default ButtonSolid;
@@ -0,0 +1,59 @@
1
+ import { render, fireEvent } from "@testing-library/react";
2
+ import Button from "./index";
3
+
4
+ describe("Button", () => {
5
+ it("renders Button component without errors", () => {
6
+ render(
7
+ <Button disabled classNameText="text-xs" type="button">
8
+ Click
9
+ </Button>,
10
+ );
11
+ });
12
+
13
+ it("button with icon start", () => {
14
+ const component = render(
15
+ <Button
16
+ id="test"
17
+ edge="start"
18
+ icon={<span className="icon-inbox" data-testid="icon-start"></span>}
19
+ classNameContainer="tex-xs"
20
+ >
21
+ Click
22
+ </Button>,
23
+ );
24
+ const iconStart = component.getByTestId("icon-start");
25
+ expect(iconStart).toHaveClass("icon-inbox");
26
+ });
27
+
28
+ it("button with icon end", () => {
29
+ const component = render(
30
+ <Button
31
+ id="test"
32
+ edge="end"
33
+ icon={<span className="icon-inbox" data-testid="icon-end"></span>}
34
+ >
35
+ Click
36
+ </Button>,
37
+ );
38
+ const iconEnd = component.getByTestId("icon-end");
39
+ expect(iconEnd).toHaveClass("icon-inbox");
40
+ });
41
+
42
+ it("focus button", () => {
43
+ const handleClickMock = jest.fn();
44
+ const outline = "0px 0px 0px 0px red, 0px 0px 0px 0px blue, 0px 0px 0px 0px yellow";
45
+ const component = render(
46
+ <Button id="test" onClick={handleClickMock} classNameButton="w-full" outline={outline}>
47
+ Click
48
+ </Button>,
49
+ );
50
+ const containerButton = component.getByTestId("container-button");
51
+ const button = component.getByTestId("button-solid-test");
52
+
53
+ fireEvent.focus(button);
54
+ expect(containerButton).toHaveStyle(`box-shadow: ${outline}`);
55
+ fireEvent.blur(button);
56
+ fireEvent.click(button);
57
+ expect(handleClickMock).toHaveBeenCalled();
58
+ });
59
+ });
@@ -0,0 +1,52 @@
1
+ // 1.- libraries
2
+ import { useState, useEffect } from "react";
3
+
4
+ // 2.- utils
5
+ import { classNames } from "../../../utils";
6
+
7
+ const Checkbox = ({
8
+ label = null,
9
+ checked = false,
10
+ onChange,
11
+ id,
12
+ className = "",
13
+ classNameCheckbox = "h-4 w-4",
14
+ style = {},
15
+ disabled = false,
16
+ }) => {
17
+ const [checkedCheckbox, setCheckedCheckbox] = useState(false);
18
+ useEffect(() => {
19
+ setCheckedCheckbox(checked);
20
+ }, [checked]);
21
+ return (
22
+ <div className="flex items-center" style={style} data-testid={`container-check-${id}`}>
23
+ <input
24
+ checked={checkedCheckbox}
25
+ id={`${label}-${id}`}
26
+ value={id}
27
+ aria-describedby="comments-description"
28
+ type="checkbox"
29
+ onChange={onChange}
30
+ className={classNames(
31
+ "cursor-pointer rounded border-gray-300 text-indigo-600 focus:ring-indigo-600",
32
+ classNameCheckbox !== "" && classNameCheckbox,
33
+ )}
34
+ data-testid={`checkbox-${id}`}
35
+ disabled={disabled}
36
+ />
37
+
38
+ {label !== null ? (
39
+ <label
40
+ htmlFor={`${label}-${id}`}
41
+ className={`ml-2.5 font-normal cursor-pointer ${className}`}
42
+ id={`label-${id}`}
43
+ data-testid="label"
44
+ >
45
+ {label}
46
+ </label>
47
+ ) : null}
48
+ </div>
49
+ );
50
+ };
51
+
52
+ export default Checkbox;
@@ -0,0 +1,15 @@
1
+ import { render } from "@testing-library/react";
2
+ import Checkbox from "./index";
3
+
4
+ describe("Checkbox", () => {
5
+ it("renders Checkbox component without errors", () => {
6
+ render(<Checkbox bgColor="bg-white" className="h-3 w-3" onChange={() => {}} id="header" />);
7
+ });
8
+
9
+ it("label", () => {
10
+ const component = render(<Checkbox onChange={() => {}} id="header" label="test" />);
11
+ const label = component.getByTestId("label");
12
+
13
+ expect(label.textContent).toBe("test");
14
+ });
15
+ });
@@ -0,0 +1,70 @@
1
+ // 1.- libraries
2
+
3
+ // 2.- components
4
+ import Modal from "../../molecules/Modal";
5
+ import ButtonSolid from "../ButtonSolid";
6
+ import ButtonOutline from "../ButtonOutline";
7
+
8
+ // 3.- utils
9
+ import { classNames } from "../../../utils";
10
+
11
+ const ConfirmationAbandoningCreation = ({
12
+ isOpenModalConfirmation,
13
+ setIsOpenModalConfirmation,
14
+ close,
15
+ title = "¿Estás seguro de abandonar la creación de la acción?",
16
+ description = "La información se perderá si no creas la acción",
17
+ classNameTitle = "",
18
+ classNameDescription = "",
19
+ }) => {
20
+ const closeModal = () => {
21
+ setIsOpenModalConfirmation(false);
22
+ close();
23
+ };
24
+
25
+ return (
26
+ <Modal
27
+ isOpen={isOpenModalConfirmation}
28
+ setIsOpen={() => setIsOpenModalConfirmation()}
29
+ showButton={false}
30
+ showIconSuccess={false}
31
+ >
32
+ <p
33
+ className={classNames(
34
+ "text-center text-sm",
35
+ classNameTitle !== "" && classNameTitle,
36
+ )}
37
+ >
38
+ {title}
39
+ </p>
40
+ <p
41
+ className={classNames(
42
+ "text-center text-sm",
43
+ classNameDescription !== "" && classNameDescription,
44
+ )}
45
+ >
46
+ {description}
47
+ </p>
48
+
49
+ <div className="flex w-full justify-center mt-5">
50
+ <ButtonOutline
51
+ className="rounded-md bg-white text-gray-500 text-sm shadow-sm ring-1 ring-inset ring-gray-300 bg-gray-50 w-24 h-9 mr-6"
52
+ onClick={() => setIsOpenModalConfirmation()}
53
+ id="cancel"
54
+ >
55
+ Cancelar
56
+ </ButtonOutline>
57
+ <ButtonSolid
58
+ classNameButton="bg-secondary-2 hover:bg-secondary-3 focus-visible:outline-secondary-2 shadow-secondary-2 rounded py-1.5 text-white w-full px-5"
59
+ outline="0px 0px 0px 2px #3758F9, 0px 0px 0px 2px #243BBD, 0px 1px 2px 0px rgba(0, 0, 0, 0.05)"
60
+ onClick={closeModal}
61
+ id="confirmation"
62
+ >
63
+ Aceptar
64
+ </ButtonSolid>
65
+ </div>
66
+ </Modal>
67
+ );
68
+ };
69
+
70
+ export default ConfirmationAbandoningCreation;
@@ -0,0 +1,70 @@
1
+ import { render, fireEvent } from "@testing-library/react";
2
+ import ConfirmationAbandoningCreation from "./index";
3
+
4
+ global.ResizeObserver = class ResizeObserver {
5
+ observe() {}
6
+ unobserve() {}
7
+ disconnect() {}
8
+ };
9
+
10
+ describe("ConfirmationAbandoningCreation", () => {
11
+ afterEach(() => {
12
+ jest.resetAllMocks();
13
+ });
14
+
15
+ it("renders ConfirmationAbandoningCreation component without errors", () => {
16
+ render(
17
+ <ConfirmationAbandoningCreation
18
+ isOpenModalConfirmation={false}
19
+ setIsOpenModalConfirmation={() => {}}
20
+ close={() => {}}
21
+ classNameDescription="text-sm"
22
+ classNameTitle="text-sm"
23
+ />,
24
+ );
25
+ });
26
+
27
+ it("close modal", () => {
28
+ const mockSetIsOpenModalConfirmation = jest.fn();
29
+ const component = render(
30
+ <ConfirmationAbandoningCreation
31
+ isOpenModalConfirmation
32
+ setIsOpenModalConfirmation={mockSetIsOpenModalConfirmation}
33
+ close={() => {}}
34
+ title="title"
35
+ description="description"
36
+ />,
37
+ );
38
+ const close = component.getByTestId("window-close");
39
+ fireEvent.click(close);
40
+ expect(mockSetIsOpenModalConfirmation).toHaveBeenCalled();
41
+ });
42
+
43
+ it("button cancel", () => {
44
+ const mockSetIsOpenModalConfirmation = jest.fn();
45
+ const component = render(
46
+ <ConfirmationAbandoningCreation
47
+ isOpenModalConfirmation
48
+ setIsOpenModalConfirmation={mockSetIsOpenModalConfirmation}
49
+ close={() => {}}
50
+ />,
51
+ );
52
+ const button = component.getByTestId("button-outline-cancel");
53
+ fireEvent.click(button);
54
+ expect(mockSetIsOpenModalConfirmation).toHaveBeenCalled();
55
+ });
56
+
57
+ it("button accept", () => {
58
+ const mockClose = jest.fn();
59
+ const component = render(
60
+ <ConfirmationAbandoningCreation
61
+ isOpenModalConfirmation
62
+ setIsOpenModalConfirmation={() => {}}
63
+ close={mockClose}
64
+ />,
65
+ );
66
+ const button = component.getByTestId("button-solid-confirmation");
67
+ fireEvent.click(button);
68
+ expect(mockClose).toHaveBeenCalled();
69
+ });
70
+ });
@@ -0,0 +1,10 @@
1
+ // 1.- libraries
2
+
3
+ // 2.- utils
4
+ import { classNames } from "../../../utils";
5
+
6
+ const Divider = ({ className = "", style = {} }) => {
7
+ return <div className={classNames("w-px", className !== "" && className)} style={style}></div>;
8
+ };
9
+
10
+ export default Divider;
@@ -0,0 +1,12 @@
1
+ import { render } from "@testing-library/react";
2
+ import Divider from "./index";
3
+
4
+ describe("Divider", () => {
5
+ it("renders Divider component without errors", () => {
6
+ render(<Divider />);
7
+ });
8
+
9
+ it("className", () => {
10
+ render(<Divider className="mt-2" />);
11
+ });
12
+ });
@@ -0,0 +1,30 @@
1
+ // 1.- libraries
2
+
3
+ // 2.- icons
4
+ import { ChevronLeftIcon } from "@heroicons/react/24/solid";
5
+
6
+ // 3.- utils
7
+ import { classNames } from "../../../utils";
8
+
9
+ const GoBack = ({ onClick, id = "", className = "" }) => {
10
+ return (
11
+ <div
12
+ className={classNames(
13
+ "flex items-center text-default-5",
14
+ className !== "" && className,
15
+ )}
16
+ data-testid={id}
17
+ >
18
+ <ChevronLeftIcon
19
+ className="w-3 h-3 3xs:w-4 3xs:h-4 stroke-current cursor-pointer"
20
+ data-testid="chevron-left-icon"
21
+ onClick={onClick}
22
+ />
23
+ <span onClick={onClick} className="text-sm cursor-pointer" data-testid="go-back">
24
+ Volver
25
+ </span>
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export default GoBack;
@@ -0,0 +1,24 @@
1
+ import { render, fireEvent } from "@testing-library/react";
2
+ import GoBack from "./index";
3
+
4
+ describe("GoBack", () => {
5
+ it("renders GoBack component without errors", () => {
6
+ render(<GoBack onClick={() => {}} className="text-sm" />);
7
+ });
8
+
9
+ it("go back with icon", () => {
10
+ const mockOnClick = jest.fn();
11
+ const component = render(<GoBack onClick={mockOnClick} />);
12
+ const goBack = component.getByTestId("chevron-left-icon");
13
+ fireEvent.click(goBack);
14
+ expect(mockOnClick).toHaveBeenCalled();
15
+ });
16
+
17
+ it("go back", () => {
18
+ const mockOnClick = jest.fn();
19
+ const component = render(<GoBack onClick={mockOnClick} />);
20
+ const goBack = component.getByTestId("go-back");
21
+ fireEvent.click(goBack);
22
+ expect(mockOnClick).toHaveBeenCalled();
23
+ });
24
+ });
@@ -0,0 +1,107 @@
1
+ // 1.- libraries
2
+ import { useState } from "react";
3
+ import classnames from "classnames";
4
+ import { ExclamationCircleIcon } from "@heroicons/react/20/solid";
5
+
6
+ // 2.- utils
7
+ import { validateEmail, classNames } from "../../../utils";
8
+
9
+ const Input = ({
10
+ placeholder = "",
11
+ label = "",
12
+ htmlFor,
13
+ type = "text",
14
+ name,
15
+ handleChange,
16
+ onClick = () => {},
17
+ value,
18
+ isReadOnly = false,
19
+ isError = false,
20
+ helperText = "",
21
+ autocomplete = "on",
22
+ id,
23
+ classNameLabel = "",
24
+ classNameContainerInput = "",
25
+ classNameContainer = "",
26
+ className = "",
27
+ icon = null,
28
+ onKeyDown,
29
+ onFocus,
30
+ }) => {
31
+ const [isErrorEmail, setIsErrorEmail] = useState(false);
32
+
33
+ const classnamesInput = classnames({
34
+ "ring-red-300 focus:ring-red-300 text-red-900": isError || isErrorEmail,
35
+ "focus:ring-indigo-600 text-gray-500": !isError && !isErrorEmail,
36
+ });
37
+
38
+ const onChange = (e) => {
39
+ handleChange && handleChange(e);
40
+ if (type !== "email") return;
41
+
42
+ const { value } = e.target;
43
+ const isEmail = validateEmail(value);
44
+ setIsErrorEmail(!isEmail);
45
+ };
46
+
47
+ return (
48
+ <div data-testid={`container-input-${id}`} className={classNameContainer}>
49
+ {label !== "" && (
50
+ <label
51
+ htmlFor={htmlFor}
52
+ className={classNames(
53
+ "block text-sm font-medium leading-6",
54
+ classNameLabel !== "" ? classNameLabel : "text-gray-700",
55
+ )}
56
+ data-testid={`label-${id}`}
57
+ >
58
+ {label}
59
+ </label>
60
+ )}
61
+ <div
62
+ className={classNames(
63
+ "relative mt-1 rounded-md",
64
+ classNameContainerInput !== "" && classNameContainerInput,
65
+ )}
66
+ >
67
+ <input
68
+ id={id}
69
+ name={name}
70
+ type={type}
71
+ autoComplete={autocomplete}
72
+ placeholder={placeholder}
73
+ onChange={onChange}
74
+ onClick={onClick}
75
+ onKeyDown={onKeyDown}
76
+ onFocus={onFocus}
77
+ value={value}
78
+ readOnly={isReadOnly}
79
+ data-testid={`input-${id}`}
80
+ className={classNames(
81
+ "block w-full rounded-md border-0 py-1.5 shadow-sm placeholder-gray-300 ring-1 ring-gray-300 ring-inset focus:ring-1 focus:ring-inset text-sm sm:leading-6",
82
+ classnamesInput,
83
+ className !== "" && className,
84
+ )}
85
+ />
86
+ {icon !== null && (
87
+ <div className="absolute inset-y-0 right-0 flex items-center pr-3">{icon}</div>
88
+ )}
89
+ {isError && icon === null && (
90
+ <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
91
+ <ExclamationCircleIcon
92
+ className="h-5 w-5 text-red-500"
93
+ aria-hidden="true"
94
+ />
95
+ </div>
96
+ )}
97
+ </div>
98
+ {helperText.length === 0 || !isError ? null : (
99
+ <p className="text-red-600 text-sm text-left mt-1" data-testid={`helperText-${id}`}>
100
+ {helperText}
101
+ </p>
102
+ )}
103
+ </div>
104
+ );
105
+ };
106
+
107
+ export default Input;
@@ -0,0 +1,63 @@
1
+ import { render, fireEvent } from "@testing-library/react";
2
+ import Input from "./index";
3
+
4
+ describe("Input", () => {
5
+ it("renders Input component without errors", () => {
6
+ render(<Input name="email" handleChange={() => {}} value="example.com" id="email" />);
7
+ });
8
+
9
+ it("input success", () => {
10
+ const component = render(
11
+ <Input
12
+ placeholder="email"
13
+ label="Email"
14
+ type="email"
15
+ htmlFor="email"
16
+ name="email"
17
+ handleChange={() => {}}
18
+ value="example.com"
19
+ id="email"
20
+ isError={false}
21
+ helperText="Email required"
22
+ classNameLabel="w-100"
23
+ classNameContainerInput="text-sm"
24
+ className="w-1/2"
25
+ icon={<span>Icon</span>}
26
+ />,
27
+ );
28
+
29
+ const labelEmail = component.getByTestId("label-email");
30
+ const input = component.getByTestId("input-email");
31
+ fireEvent.change(input, { target: { value: "test@gmail.com" } });
32
+ fireEvent.click(input);
33
+
34
+ expect(labelEmail.textContent).toBe("Email");
35
+ expect(input).not.toHaveClass("ring-red-300 focus:ring-red-300");
36
+ });
37
+
38
+ it("input error", () => {
39
+ const mockOnClick = jest.fn();
40
+ const component = render(
41
+ <Input
42
+ placeholder="email"
43
+ label="Email"
44
+ htmlFor="email"
45
+ name="email"
46
+ handleChange={() => {}}
47
+ onClick={mockOnClick}
48
+ value="example.com"
49
+ id="email"
50
+ isError={true}
51
+ helperText="Email required"
52
+ />,
53
+ );
54
+ const helperText = component.getByTestId("helperText-email");
55
+ const input = component.getByTestId("input-email");
56
+ fireEvent.change(input, { target: { value: "test@gmail.com" } });
57
+ fireEvent.click(input);
58
+
59
+ expect(mockOnClick).toHaveBeenCalled();
60
+ expect(helperText.textContent).toBe("Email required");
61
+ expect(input).toHaveClass("ring-red-300 focus:ring-red-300");
62
+ });
63
+ });