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.
- package/README copy.md +54 -0
- package/README.md +29 -0
- package/components.js +47 -0
- package/hooks.js +4 -0
- package/package.json +58 -0
- package/postcss.config.js +6 -0
- package/src/assets/cemtrik-icons-v1.0/Read Me.txt +7 -0
- package/src/assets/cemtrik-icons-v1.0/demo-files/demo.css +152 -0
- package/src/assets/cemtrik-icons-v1.0/demo-files/demo.js +30 -0
- package/src/assets/cemtrik-icons-v1.0/demo.html +318 -0
- package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.eot +0 -0
- package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.svg +31 -0
- package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.ttf +0 -0
- package/src/assets/cemtrik-icons-v1.0/fonts/cemtrik-icons.woff +0 -0
- package/src/assets/cemtrik-icons-v1.0/selection.json +1 -0
- package/src/assets/cemtrik-icons-v1.0/style.css +96 -0
- package/src/assets/icons/actions.svg +4 -0
- package/src/assets/icons/attributes.svg +5 -0
- package/src/assets/icons/bars.svg +3 -0
- package/src/assets/icons/bell.svg +4 -0
- package/src/assets/icons/cemtrik.svg +9 -0
- package/src/assets/icons/clipboardCheck.svg +4 -0
- package/src/assets/icons/clipboardList.svg +5 -0
- package/src/assets/icons/clock.svg +3 -0
- package/src/assets/icons/flag.svg +3 -0
- package/src/assets/icons/folder.svg +3 -0
- package/src/assets/icons/graph_indicators.svg +3 -0
- package/src/assets/icons/group.svg +3 -0
- package/src/assets/icons/letter.svg +3 -0
- package/src/assets/icons/measuring_points.svg +3 -0
- package/src/assets/icons/reports.svg +4 -0
- package/src/assets/icons/roboot.svg +3 -0
- package/src/assets/icons/user.svg +4 -0
- package/src/assets/icons/user_point.svg +10 -0
- package/src/assets/icons/vector.svg +3 -0
- package/src/assets/icons/vector2.svg +3 -0
- package/src/components/atoms/Alert/index.js +104 -0
- package/src/components/atoms/Alert/index.test.js +36 -0
- package/src/components/atoms/Avatar/index.js +63 -0
- package/src/components/atoms/Avatar/index.test.js +30 -0
- package/src/components/atoms/Bullets/Bullets.test.js +22 -0
- package/src/components/atoms/Bullets/index.js +51 -0
- package/src/components/atoms/ButtonOutline/index.js +43 -0
- package/src/components/atoms/ButtonOutline/index.test.js +36 -0
- package/src/components/atoms/ButtonPagination/index.js +37 -0
- package/src/components/atoms/ButtonPagination/index.test.js +36 -0
- package/src/components/atoms/ButtonSolid/index.js +74 -0
- package/src/components/atoms/ButtonSolid/index.test.js +59 -0
- package/src/components/atoms/Checkbox/index.js +52 -0
- package/src/components/atoms/Checkbox/index.test.js +15 -0
- package/src/components/atoms/ConfirmationAbandoningCreation/index.js +70 -0
- package/src/components/atoms/ConfirmationAbandoningCreation/index.test.js +70 -0
- package/src/components/atoms/Divider/index.js +10 -0
- package/src/components/atoms/Divider/index.test.js +12 -0
- package/src/components/atoms/GoBack/index.js +30 -0
- package/src/components/atoms/GoBack/index.test.js +24 -0
- package/src/components/atoms/Input/index.js +107 -0
- package/src/components/atoms/Input/index.test.js +63 -0
- package/src/components/atoms/InputDropdown/index.js +111 -0
- package/src/components/atoms/InputDropdown/index.test.js +86 -0
- package/src/components/atoms/Select/index.js +199 -0
- package/src/components/atoms/Select/index.test.js +86 -0
- package/src/components/atoms/Spinner/index.js +49 -0
- package/src/components/atoms/Spinner/index.test.js +9 -0
- package/src/components/atoms/Switch/index.js +46 -0
- package/src/components/atoms/Switch/index.test.js +18 -0
- package/src/components/atoms/Textarea/index.js +136 -0
- package/src/components/atoms/Textarea/index.spec.js +51 -0
- package/src/components/atoms/Tooltip/index.js +64 -0
- package/src/components/atoms/Tooltip/index.test.js +31 -0
- package/src/components/atoms/UploadImage/index.js +55 -0
- package/src/components/atoms/UploadImage/index.test.js +36 -0
- package/src/components/molecules/Dropdown/index.js +315 -0
- package/src/components/molecules/Dropdown/index.test.js +190 -0
- package/src/components/molecules/Modal/index.js +103 -0
- package/src/components/molecules/Modal/index.test.js +42 -0
- package/src/components/molecules/Pagination/index.js +126 -0
- package/src/components/molecules/Pagination/index.test.js +57 -0
- package/src/components/templates/Accordion/index.js +174 -0
- package/src/components/templates/Accordion/index.test.js +130 -0
- package/src/hooks/useCloseModal/index.js +27 -0
- package/src/hooks/useCloseModal/index.test.js +26 -0
- package/src/hooks/useForm/index.js +70 -0
- package/src/hooks/useForm/useForm.test.js +104 -0
- package/src/hooks/useMediaQuery/index.js +53 -0
- package/src/hooks/useMediaQuery/useMediaQuery.test.js +46 -0
- package/src/hooks/useWindowDimensions/index.js +34 -0
- package/src/hooks/useWindowDimensions/useWindowDimensions.test.js +19 -0
- package/src/utils/index.js +32 -0
- package/src/utils/index.test.js +56 -0
- package/tailwind.config.js +117 -0
- 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
|
+
});
|