@phsa.tec/design-system-react 0.1.5 → 0.1.8

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 (212) hide show
  1. package/README.md +390 -209
  2. package/dist/index.d.mts +485 -0
  3. package/dist/index.d.ts +485 -0
  4. package/dist/index.js +4259 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +4186 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +46 -6
  9. package/.eslintrc.json +0 -7
  10. package/.github/workflows/deploy-storybook.yml +0 -75
  11. package/.storybook/main.ts +0 -16
  12. package/.storybook/preview.ts +0 -15
  13. package/components.json +0 -21
  14. package/jest.config.ts +0 -25
  15. package/next.config.ts +0 -7
  16. package/postcss.config.mjs +0 -8
  17. package/public/file.svg +0 -1
  18. package/public/globe.svg +0 -1
  19. package/public/next.svg +0 -1
  20. package/public/vercel.svg +0 -1
  21. package/public/window.svg +0 -1
  22. package/src/app/columns.tsx +0 -178
  23. package/src/app/favicon.ico +0 -0
  24. package/src/app/fonts/GeistMonoVF.woff +0 -0
  25. package/src/app/fonts/GeistVF.woff +0 -0
  26. package/src/app/globals.css +0 -94
  27. package/src/app/layout.tsx +0 -35
  28. package/src/app/page.tsx +0 -7
  29. package/src/components/actions/AlertDialog/AlertDialog.tsx +0 -45
  30. package/src/components/actions/AlertDialog/alert-dialog.stories.tsx +0 -21
  31. package/src/components/actions/AlertDialog/index.ts +0 -1
  32. package/src/components/actions/Button/Button.stories.ts +0 -38
  33. package/src/components/actions/Button/Button.tsx +0 -23
  34. package/src/components/actions/Button/index.ts +0 -1
  35. package/src/components/actions/Collapsible/index.ts +0 -1
  36. package/src/components/actions/Dialog/Dialog.stories.tsx +0 -70
  37. package/src/components/actions/Dialog/Dialog.tsx +0 -87
  38. package/src/components/actions/Dialog/components/DialogWithActions/index.tsx +0 -40
  39. package/src/components/actions/Dialog/index.ts +0 -1
  40. package/src/components/actions/Steps/Steps.stories.tsx +0 -25
  41. package/src/components/actions/Steps/Steps.tsx +0 -51
  42. package/src/components/actions/Steps/index.ts +0 -1
  43. package/src/components/actions/index.ts +0 -5
  44. package/src/components/dataDisplay/Avatar/Avatar.stories.tsx +0 -22
  45. package/src/components/dataDisplay/Avatar/Avatar.tsx +0 -21
  46. package/src/components/dataDisplay/Avatar/index.ts +0 -2
  47. package/src/components/dataDisplay/Badge/Badge.stories.tsx +0 -36
  48. package/src/components/dataDisplay/Badge/index.ts +0 -1
  49. package/src/components/dataDisplay/Card/Card.stories.tsx +0 -24
  50. package/src/components/dataDisplay/Card/Card.tsx +0 -34
  51. package/src/components/dataDisplay/Card/index.ts +0 -1
  52. package/src/components/dataDisplay/DataPairList/DataPairList.tsx +0 -56
  53. package/src/components/dataDisplay/DataPairList/data-pair-list.stories.tsx +0 -87
  54. package/src/components/dataDisplay/DataPairList/index.ts +0 -2
  55. package/src/components/dataDisplay/DataPairList/types.ts +0 -10
  56. package/src/components/dataDisplay/DropDownMenu/index.ts +0 -1
  57. package/src/components/dataDisplay/ErrorMessage/ErrorMessage.tsx +0 -6
  58. package/src/components/dataDisplay/ErrorMessage/index.ts +0 -1
  59. package/src/components/dataDisplay/Icon/Icon.stories.tsx +0 -21
  60. package/src/components/dataDisplay/Icon/Icon.tsx +0 -47
  61. package/src/components/dataDisplay/Icon/index.ts +0 -1
  62. package/src/components/dataDisplay/Icon/types.ts +0 -6
  63. package/src/components/dataDisplay/Label/Label.stories.tsx +0 -21
  64. package/src/components/dataDisplay/Label/Label.tsx +0 -10
  65. package/src/components/dataDisplay/Label/index.ts +0 -1
  66. package/src/components/dataDisplay/Table/Table.tsx +0 -173
  67. package/src/components/dataDisplay/Table/columns.tsx +0 -223
  68. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-column-header.tsx +0 -72
  69. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-pagination.tsx +0 -91
  70. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-toolbar.tsx +0 -17
  71. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-view-options.tsx +0 -58
  72. package/src/components/dataDisplay/Table/components/DynamicTable/data-table.stories.tsx +0 -118
  73. package/src/components/dataDisplay/Table/components/DynamicTable/index.tsx +0 -136
  74. package/src/components/dataDisplay/Table/components/DynamicTable/types.ts +0 -43
  75. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-column-header.tsx +0 -71
  76. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-faceted-filter.tsx +0 -147
  77. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-pagination.tsx +0 -97
  78. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-row-actions.tsx +0 -78
  79. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-toolbar.tsx +0 -60
  80. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-view-options.tsx +0 -59
  81. package/src/components/dataDisplay/Table/custom/CustomTable/data-table.tsx +0 -145
  82. package/src/components/dataDisplay/Table/custom/CustomTable/data.ts +0 -71
  83. package/src/components/dataDisplay/Table/custom/CustomTable/index.tsx +0 -34
  84. package/src/components/dataDisplay/Table/custom/CustomTable/schema.ts +0 -11
  85. package/src/components/dataDisplay/Table/index.ts +0 -2
  86. package/src/components/dataDisplay/Table/table.stories.tsx +0 -147
  87. package/src/components/dataDisplay/Table/types.ts +0 -15
  88. package/src/components/dataDisplay/Tabs/Tabs.stories.tsx +0 -34
  89. package/src/components/dataDisplay/Tabs/Tabs.tsx +0 -53
  90. package/src/components/dataDisplay/Tabs/index.ts +0 -1
  91. package/src/components/dataDisplay/Text/Text.stories.tsx +0 -66
  92. package/src/components/dataDisplay/Text/Text.tsx +0 -56
  93. package/src/components/dataDisplay/Text/index.ts +0 -1
  94. package/src/components/dataDisplay/index.ts +0 -8
  95. package/src/components/dataInput/Input/components/Input/Input.stories.tsx +0 -99
  96. package/src/components/dataInput/Input/components/Input/InputBase.tsx +0 -50
  97. package/src/components/dataInput/Input/components/Input/__tests__/input.test.tsx +0 -38
  98. package/src/components/dataInput/Input/components/Input/index.tsx +0 -48
  99. package/src/components/dataInput/Input/components/Input/types.ts +0 -15
  100. package/src/components/dataInput/Input/components/InputBase/index.tsx +0 -31
  101. package/src/components/dataInput/Input/components/MaskInput/__tests__/mask-input.test.tsx +0 -77
  102. package/src/components/dataInput/Input/components/MaskInput/index.ts +0 -1
  103. package/src/components/dataInput/Input/components/MaskInput/mask-input.stories.tsx +0 -85
  104. package/src/components/dataInput/Input/components/MaskInput/mask-input.tsx +0 -73
  105. package/src/components/dataInput/Input/components/MultipleInput/MultipleInput.tsx +0 -105
  106. package/src/components/dataInput/Input/components/MultipleInput/MultipleInputBase.tsx +0 -100
  107. package/src/components/dataInput/Input/components/MultipleInput/MultipleMaskInput.tsx +0 -35
  108. package/src/components/dataInput/Input/components/MultipleInput/MultipleNumberInput.tsx +0 -35
  109. package/src/components/dataInput/Input/components/MultipleInput/__tests__/multiple-input.test.tsx +0 -152
  110. package/src/components/dataInput/Input/components/MultipleInput/index.ts +0 -2
  111. package/src/components/dataInput/Input/components/MultipleInput/multiple-input.stories.tsx +0 -96
  112. package/src/components/dataInput/Input/components/NumberInput/index.ts +0 -1
  113. package/src/components/dataInput/Input/components/NumberInput/number-input.stories.tsx +0 -76
  114. package/src/components/dataInput/Input/components/NumberInput/number-input.tsx +0 -68
  115. package/src/components/dataInput/Input/index.ts +0 -4
  116. package/src/components/dataInput/Select/MultiSelect/MultiSelect.stories.tsx +0 -119
  117. package/src/components/dataInput/Select/MultiSelect/MultiSelectBase.tsx +0 -135
  118. package/src/components/dataInput/Select/MultiSelect/index.tsx +0 -75
  119. package/src/components/dataInput/Select/Select.stories.tsx +0 -61
  120. package/src/components/dataInput/Select/Select.tsx +0 -73
  121. package/src/components/dataInput/Select/SelectBase.tsx +0 -58
  122. package/src/components/dataInput/Select/index.ts +0 -2
  123. package/src/components/dataInput/Switch/Switch.stories.tsx +0 -75
  124. package/src/components/dataInput/Switch/Switch.tsx +0 -52
  125. package/src/components/dataInput/Switch/index.ts +0 -1
  126. package/src/components/dataInput/checkbox/Checkbox.tsx +0 -57
  127. package/src/components/dataInput/checkbox/Checkbox_old.tsx +0 -58
  128. package/src/components/dataInput/checkbox/Checkout.stories.tsx +0 -62
  129. package/src/components/dataInput/checkbox/index.ts +0 -1
  130. package/src/components/dataInput/form/Form.tsx +0 -47
  131. package/src/components/dataInput/form/index.ts +0 -3
  132. package/src/components/dataInput/index.ts +0 -5
  133. package/src/components/feedback/ErrorLabel/index.tsx +0 -24
  134. package/src/components/feedback/Spinner/index.ts +0 -1
  135. package/src/components/feedback/Toast/Toast.stories.tsx +0 -45
  136. package/src/components/feedback/Toast/index.ts +0 -2
  137. package/src/components/feedback/index.ts +0 -2
  138. package/src/components/index.ts +0 -6
  139. package/src/components/layout/Crud/components/Table/index.tsx +0 -183
  140. package/src/components/layout/Crud/components/Table/types.ts +0 -15
  141. package/src/components/layout/Crud/crud.stories.tsx +0 -317
  142. package/src/components/layout/Crud/hook/useCrudLayout/index.tsx +0 -94
  143. package/src/components/layout/Crud/hook/useRequest/index.tsx +0 -156
  144. package/src/components/layout/Crud/index.tsx +0 -295
  145. package/src/components/layout/Crud/store/CrudLayoutStore.ts +0 -75
  146. package/src/components/layout/Crud/types.ts +0 -14
  147. package/src/components/layout/Drawer/CustomDrawer/index.tsx +0 -33
  148. package/src/components/layout/Drawer/Drawer.stories.tsx +0 -80
  149. package/src/components/layout/Drawer/index.ts +0 -2
  150. package/src/components/layout/PageLayout/PageLayout.stories.tsx +0 -42
  151. package/src/components/layout/PageLayout/index.tsx +0 -28
  152. package/src/components/layout/Separator/index.ts +0 -1
  153. package/src/components/layout/Sheet/Sheet.stories.tsx +0 -28
  154. package/src/components/layout/Sheet/Sheet.tsx +0 -22
  155. package/src/components/layout/Sheet/index.ts +0 -1
  156. package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -116
  157. package/src/components/layout/Sidebar/Sidebar.tsx +0 -50
  158. package/src/components/layout/Sidebar/components/app-sidebar.tsx +0 -203
  159. package/src/components/layout/Sidebar/components/footer-sidebar.tsx +0 -17
  160. package/src/components/layout/Sidebar/components/header-sidebar.tsx +0 -90
  161. package/src/components/layout/Sidebar/components/menus.tsx +0 -55
  162. package/src/components/layout/Sidebar/components/nav-projects.tsx +0 -88
  163. package/src/components/layout/Sidebar/components/nav-user.tsx +0 -114
  164. package/src/components/layout/Sidebar/components/team-switcher.tsx +0 -85
  165. package/src/components/layout/Sidebar/index.ts +0 -2
  166. package/src/components/layout/Sidebar/provider/index.tsx +0 -51
  167. package/src/components/layout/Tabs/Tabs.tsx +0 -51
  168. package/src/components/layout/Tabs/index.ts +0 -1
  169. package/src/components/layout/Tabs/tabs.stories.tsx +0 -57
  170. package/src/components/layout/index.ts +0 -6
  171. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +0 -66
  172. package/src/components/navigation/Breadcrumbs/index.ts +0 -2
  173. package/src/components/navigation/index.ts +0 -1
  174. package/src/components/ui/alert-dialog.tsx +0 -141
  175. package/src/components/ui/alert.tsx +0 -59
  176. package/src/components/ui/avatar.tsx +0 -50
  177. package/src/components/ui/badge.tsx +0 -40
  178. package/src/components/ui/breadcrumb.tsx +0 -115
  179. package/src/components/ui/button.tsx +0 -57
  180. package/src/components/ui/card.tsx +0 -83
  181. package/src/components/ui/checkbox.tsx +0 -34
  182. package/src/components/ui/collapsible.tsx +0 -11
  183. package/src/components/ui/command.tsx +0 -153
  184. package/src/components/ui/dialog.tsx +0 -124
  185. package/src/components/ui/drawer.tsx +0 -117
  186. package/src/components/ui/dropdown-menu.tsx +0 -201
  187. package/src/components/ui/form.tsx +0 -179
  188. package/src/components/ui/input.tsx +0 -24
  189. package/src/components/ui/label.tsx +0 -30
  190. package/src/components/ui/popover.tsx +0 -33
  191. package/src/components/ui/select.tsx +0 -161
  192. package/src/components/ui/separator.tsx +0 -31
  193. package/src/components/ui/sheet.tsx +0 -140
  194. package/src/components/ui/sidebar.tsx +0 -763
  195. package/src/components/ui/skeleton.tsx +0 -15
  196. package/src/components/ui/sonner.tsx +0 -31
  197. package/src/components/ui/spinner.tsx +0 -54
  198. package/src/components/ui/switch.tsx +0 -33
  199. package/src/components/ui/table.tsx +0 -120
  200. package/src/components/ui/tabs.tsx +0 -55
  201. package/src/components/ui/toast.tsx +0 -130
  202. package/src/components/ui/toaster.tsx +0 -35
  203. package/src/components/ui/tooltip.tsx +0 -32
  204. package/src/hooks/use-conditional-controller.tsx +0 -35
  205. package/src/hooks/use-mask.tsx +0 -116
  206. package/src/hooks/use-mobile.tsx +0 -19
  207. package/src/hooks/use-toast.ts +0 -191
  208. package/src/index.ts +0 -1
  209. package/src/introduction.mdx +0 -132
  210. package/src/lib/utils.ts +0 -6
  211. package/tailwind.config.ts +0 -83
  212. package/tsconfig.json +0 -27
@@ -1,77 +0,0 @@
1
- import "@testing-library/jest-dom";
2
- import { render, screen } from "@testing-library/react";
3
- import userEvent from "@testing-library/user-event";
4
- import { MaskInput } from "../mask-input";
5
-
6
- describe("MaskInput", () => {
7
- it("should render label", () => {
8
- render(
9
- <MaskInput label="test" data-testid="mask-input" mask="999.999.999-99" />
10
- );
11
- const label = screen.getByTestId("mask-input-label");
12
- expect(label).toBeInTheDocument();
13
- expect(label).toHaveTextContent("test");
14
- });
15
-
16
- it("should render error", () => {
17
- render(
18
- <MaskInput error="test" data-testid="mask-input" mask="999.999.999-99" />
19
- );
20
- const error = screen.getByTestId("mask-input-error-label");
21
- expect(error).toBeInTheDocument();
22
- expect(error).toHaveTextContent("test");
23
- });
24
-
25
- it("should be disabled", () => {
26
- render(
27
- <MaskInput disabled data-testid="mask-input" mask="999.999.999-99" />
28
- );
29
- const input = screen.getByTestId("mask-input");
30
- expect(input).toBeDisabled();
31
- });
32
-
33
- it("should be required", () => {
34
- render(
35
- <MaskInput
36
- required
37
- data-testid="mask-input"
38
- label="test"
39
- mask="999.999.999-99"
40
- />
41
- );
42
- const label = screen.getByTestId("mask-input-label");
43
- expect(label).toHaveTextContent("test *");
44
- });
45
-
46
- it("should apply mask to input value", async () => {
47
- const user = userEvent.setup();
48
- render(<MaskInput data-testid="mask-input" mask="999.999.999-99" />);
49
- const input = screen.getByTestId("mask-input");
50
-
51
- await user.type(input, "12345678901");
52
-
53
- expect(input).toHaveValue("123.456.789-01");
54
- });
55
-
56
- it("should handle placeholder", () => {
57
- render(
58
- <MaskInput
59
- data-testid="mask-input"
60
- mask="999.999.999-99"
61
- placeholder="Digite seu CPF"
62
- />
63
- );
64
- const input = screen.getByTestId("mask-input");
65
-
66
- expect(input).toHaveAttribute("placeholder", "Digite seu CPF");
67
- });
68
-
69
- it("should handle name attribute", () => {
70
- render(
71
- <MaskInput data-testid="mask-input" mask="999.999.999-99" name="cpf" />
72
- );
73
- const input = screen.getByTestId("mask-input");
74
-
75
- expect(input).toHaveAttribute("name", "cpf");
76
- });
77
- });
@@ -1 +0,0 @@
1
- export * from "./mask-input";
@@ -1,85 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { MaskInput } from "./mask-input";
3
- import { useForm } from "react-hook-form";
4
- import { Form } from "../../../../../components/ui/form";
5
-
6
- const meta = {
7
- title: "Data Input/Input/MaskInput",
8
- component: MaskInput,
9
- parameters: {
10
- layout: "centered",
11
- },
12
- tags: ["autodocs"],
13
- } satisfies Meta<typeof MaskInput>;
14
-
15
- export default meta;
16
- type Story = StoryObj<typeof meta>;
17
-
18
- export const Default: Story = {
19
- args: {
20
- placeholder: "99999-999",
21
- label: "CEP",
22
- mask: "99999-999",
23
- },
24
- };
25
-
26
- export const CPF: Story = {
27
- args: {
28
- placeholder: "999.999.999-99",
29
- label: "CPF",
30
- mask: "999.999.999-99",
31
- },
32
- };
33
-
34
- export const Phone: Story = {
35
- args: {
36
- placeholder: "(99) 99999-9999",
37
- label: "Telefone",
38
- mask: "(99) 99999-9999",
39
- },
40
- };
41
-
42
- export const Date: Story = {
43
- args: {
44
- placeholder: "99/99/9999",
45
- label: "Data",
46
- mask: "99/99/9999",
47
- },
48
- };
49
-
50
- export const LettersExample: Story = {
51
- args: {
52
- placeholder: "AAA-9999",
53
- label: "Código com Letras",
54
- mask: "AAA-9999",
55
- },
56
- };
57
-
58
- export const MixedExample: Story = {
59
- args: {
60
- placeholder: "A99-AAA-999",
61
- label: "Código Misto",
62
- mask: "A99-AAA-999",
63
- },
64
- };
65
-
66
- export const WithForm = () => {
67
- const form = useForm({
68
- defaultValues: {
69
- cpf: "",
70
- },
71
- });
72
-
73
- return (
74
- <Form {...form}>
75
- <form className="space-y-6">
76
- <MaskInput
77
- name="cpf"
78
- label="CPF"
79
- placeholder="999.999.999-99"
80
- mask="999.999.999-99"
81
- />
82
- </form>
83
- </Form>
84
- );
85
- };
@@ -1,73 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import { Input } from "../Input";
4
- import { useConditionalController } from "@/hooks/use-conditional-controller";
5
- import { InputProps } from "../Input/types";
6
- import { useMask } from "@/hooks/use-mask";
7
- import { useRef } from "react";
8
-
9
- export type MaskInputProps = {
10
- mask?: string;
11
- } & InputProps;
12
-
13
- export const MaskInput = ({
14
- "data-testid": dataTestId,
15
- withoutForm = false,
16
- extraElement,
17
- mask = "",
18
- ...props
19
- }: MaskInputProps) => {
20
- const formData = useConditionalController({
21
- name: props.name || "",
22
- withoutForm,
23
- });
24
-
25
- const inputProps = React.useMemo(() => {
26
- return {
27
- ...formData,
28
- ...props,
29
- };
30
- }, [formData, props]);
31
-
32
- const { applyMask } = useMask({ mask });
33
-
34
- const inputRef = useRef<HTMLInputElement>(null);
35
-
36
- const applyMaskToInput = React.useCallback(
37
- (value: string) => {
38
- if (inputRef.current && mask) {
39
- const maskedValue = applyMask(value);
40
- inputRef.current.value = maskedValue;
41
- }
42
- },
43
- [applyMask, mask]
44
- );
45
-
46
- const handleChange = React.useCallback(
47
- (e: React.ChangeEvent<HTMLInputElement>) => {
48
- const maskedValue = mask ? applyMask(e.target.value) : e.target.value;
49
-
50
- const response = {
51
- ...e,
52
- target: {
53
- ...e.target,
54
- value: maskedValue,
55
- },
56
- };
57
- applyMaskToInput(maskedValue);
58
- return inputProps?.onChange?.(response);
59
- },
60
- [applyMask, inputProps, mask, applyMaskToInput]
61
- );
62
-
63
- return (
64
- <Input
65
- {...inputProps}
66
- ref={inputRef}
67
- onChange={handleChange}
68
- extraElement={extraElement}
69
- data-testid={dataTestId}
70
- withoutForm={true}
71
- />
72
- );
73
- };
@@ -1,105 +0,0 @@
1
- import { Button } from "../../../../actions/Button";
2
- import { Icon } from "../../../../dataDisplay/Icon";
3
- import { useCallback, useMemo, useState } from "react";
4
- import { useConditionalController } from "@/hooks/use-conditional-controller";
5
- import { MaskInput, MaskInputProps } from "../MaskInput";
6
-
7
- export type MultipleInputProps = MaskInputProps & {
8
- data?: string[];
9
- onAdd?: (data: string) => void;
10
- onRemove?: (position: number) => void;
11
- name: string;
12
- defaultValue?: string;
13
- "data-testid"?: string;
14
- };
15
-
16
- export const MultipleInput = ({
17
- data = [],
18
- onAdd = () => {},
19
- defaultValue = "",
20
- onRemove = () => {},
21
- withoutForm = false,
22
- ...props
23
- }: MultipleInputProps) => {
24
- const [inputValue, setInputValue] = useState(defaultValue);
25
-
26
- const formData = useConditionalController({
27
- name: props.name || "",
28
- withoutForm,
29
- });
30
-
31
- const inputItems = useMemo(() => {
32
- if (formData?.value) {
33
- return formData.value;
34
- }
35
- return data;
36
- }, [data, formData]);
37
-
38
- const onAddData = useCallback(() => {
39
- const trimmedValue = inputValue.trim();
40
- if (trimmedValue) {
41
- if (formData?.onChange) {
42
- formData.onChange([...inputItems, trimmedValue]);
43
- } else {
44
- onAdd(trimmedValue);
45
- }
46
- setInputValue("");
47
- }
48
- }, [inputValue, formData, onAdd, inputItems]);
49
-
50
- const onRemoveData = useCallback(
51
- (index: number) => {
52
- if (formData?.onChange) {
53
- const newData = inputItems.filter(
54
- (_: string, i: number) => i !== index
55
- );
56
- formData.onChange(newData);
57
- } else {
58
- onRemove(index);
59
- }
60
- },
61
- [formData, inputItems, onRemove]
62
- );
63
-
64
- const renderItens = useCallback(() => {
65
- return inputItems?.map((item: string, index: number) => {
66
- return (
67
- <div key={item} className="flex justify-between">
68
- {item}
69
- <Button
70
- variant="ghost"
71
- className="text-destructive"
72
- size={"icon"}
73
- onClick={() => onRemoveData(index)}
74
- >
75
- <Icon name="MdDelete" />
76
- </Button>
77
- </div>
78
- );
79
- });
80
- }, [inputItems, onRemoveData]);
81
-
82
- const extraElement = useMemo(
83
- () => (
84
- <Button type="button" onClick={onAddData} disabled={!inputValue}>
85
- <Icon name="MdAdd" />
86
- </Button>
87
- ),
88
- [onAddData, inputValue]
89
- );
90
-
91
- return (
92
- <div className="flex flex-col gap-2">
93
- <MaskInput
94
- {...props}
95
- withoutForm
96
- extraElement={extraElement}
97
- onChange={(e) => {
98
- setInputValue(e.target.value);
99
- }}
100
- value={inputValue}
101
- />
102
- {renderItens()}
103
- </div>
104
- );
105
- };
@@ -1,100 +0,0 @@
1
- import { Button } from "../../../../../components/actions";
2
- import { Icon } from "../../../../../components/dataDisplay";
3
- import { useCallback, useMemo, useState } from "react";
4
- import { useFormContext } from "react-hook-form";
5
- import _ from "lodash";
6
-
7
- export type MultipleInputBaseProps = {
8
- children: (params: {
9
- onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
10
- addItem: () => void;
11
- value: string;
12
- error?: string;
13
- }) => React.ReactNode;
14
- data: string[];
15
- name?: string;
16
- onChangeData?: (data: string[]) => void;
17
- error?: string;
18
- };
19
-
20
- export const MultipleInputBase = ({
21
- children,
22
- data = [],
23
- name,
24
- onChangeData = () => {},
25
- error,
26
- }: MultipleInputBaseProps) => {
27
- const form = useFormContext();
28
- const withForm = !!form && !!name;
29
- const [inputValue, setInputValue] = useState("");
30
-
31
- const inputData = useMemo(() => {
32
- if (withForm) {
33
- return _.get(form.watch(), name) || [];
34
- }
35
- return data;
36
- }, [withForm, form, name, data]);
37
-
38
- const errorMessage = useMemo(() => {
39
- if (withForm) {
40
- return _.get(form.formState.errors, name)?.message as string;
41
- }
42
- return error;
43
- }, [error, form, name, withForm]);
44
-
45
- const updateData = useCallback(() => {
46
- if (!inputValue.length) return;
47
- if (withForm) {
48
- form.setValue(name, [...inputData, inputValue]);
49
- } else {
50
- onChangeData?.(inputData.concat(inputValue));
51
- }
52
- setInputValue("");
53
- }, [inputData, inputValue, withForm, form, name, onChangeData]);
54
-
55
- const removeItem = useCallback(
56
- (index: number) => {
57
- if (withForm) {
58
- form.setValue(
59
- name,
60
- inputData.filter((_: string, i: number) => i !== index)
61
- );
62
- } else {
63
- onChangeData?.(inputData.filter((_: string, i: number) => i !== index));
64
- }
65
- },
66
- [withForm, form, name, inputData, onChangeData]
67
- );
68
-
69
- const renderOptions = useCallback(() => {
70
- return inputData?.map((item: string, index: number) => {
71
- return (
72
- <div key={index} className="flex justify-between mt-2">
73
- <div>{item}</div>
74
- <Button
75
- onClick={() => removeItem(index)}
76
- variant={"ghost"}
77
- size={"icon"}
78
- type="button"
79
- >
80
- <Icon name="MdDelete" className="fill-destructive" />
81
- </Button>
82
- </div>
83
- );
84
- });
85
- }, [inputData, removeItem]);
86
-
87
- return (
88
- <div>
89
- {children({
90
- onChange: ({ target: { value } }) => {
91
- setInputValue(value);
92
- },
93
- addItem: updateData,
94
- value: inputValue,
95
- error: errorMessage,
96
- })}
97
- {renderOptions()}
98
- </div>
99
- );
100
- };
@@ -1,35 +0,0 @@
1
- import { Button } from "../../../../../components/actions";
2
- import { MaskInput, MaskInputProps } from "../MaskInput";
3
- import { MultipleInputBase } from "./MultipleInputBase";
4
- import { Icon } from "../../../../../components/dataDisplay";
5
-
6
- export type MultipleMaskInputProps = MaskInputProps & {
7
- data?: string[];
8
- onChangeData?: (data: string[]) => void;
9
- name: string;
10
- };
11
-
12
- export const MultipleMaskInput = ({
13
- data = [],
14
- ...props
15
- }: MultipleMaskInputProps) => {
16
- return (
17
- <MultipleInputBase data={data} {...props}>
18
- {({ onChange, addItem, value }) => {
19
- return (
20
- <MaskInput
21
- {...props}
22
- value={value}
23
- onChange={onChange}
24
- withoutForm
25
- component={
26
- <Button type="button" onClick={() => addItem()}>
27
- <Icon name="MdAdd" />
28
- </Button>
29
- }
30
- />
31
- );
32
- }}
33
- </MultipleInputBase>
34
- );
35
- };
@@ -1,35 +0,0 @@
1
- import { Button } from "../../../../actions/Button";
2
- import { Input, InputProps } from "../Input";
3
- import { MultipleInputBase } from "./MultipleInputBase";
4
- import { Icon } from "../../../../dataDisplay/Icon";
5
-
6
- export type MultipleNumberInputProps = InputProps & {
7
- data: string[];
8
- onChangeData: (data: string[]) => void;
9
- name: string;
10
- };
11
-
12
- export const MultipleNumberInput = ({
13
- data,
14
- ...props
15
- }: MultipleNumberInputProps) => {
16
- return (
17
- <MultipleInputBase data={data} {...props}>
18
- {({ onChange, addItem, value }) => (
19
- <Input
20
- {...props}
21
- value={value}
22
- onChange={(e) => {
23
- onChange(e.target.value);
24
- }}
25
- withoutForm
26
- component={
27
- <Button onClick={() => addItem()}>
28
- <Icon name="MdAdd" />
29
- </Button>
30
- }
31
- />
32
- )}
33
- </MultipleInputBase>
34
- );
35
- };
@@ -1,152 +0,0 @@
1
- import "@testing-library/jest-dom";
2
- import { fireEvent, render, screen } from "@testing-library/react";
3
- import { MultipleInput } from "../MultipleInput";
4
-
5
- describe("MultipleInput", () => {
6
- it("should render label", () => {
7
- render(
8
- <MultipleInput
9
- label="test"
10
- name="test-input"
11
- data-testid="multiple-input"
12
- />
13
- );
14
- const label = screen.getByTestId("multiple-input-label");
15
- expect(label).toBeInTheDocument();
16
- expect(label).toHaveTextContent("test");
17
- });
18
-
19
- it("should render error", () => {
20
- render(
21
- <MultipleInput
22
- error="test"
23
- name="test-input"
24
- data-testid="multiple-input"
25
- />
26
- );
27
- const error = screen.getByTestId("multiple-input-error-label");
28
- expect(error).toBeInTheDocument();
29
- expect(error).toHaveTextContent("test");
30
- });
31
-
32
- it("should be disabled", () => {
33
- render(
34
- <MultipleInput disabled name="test-input" data-testid="multiple-input" />
35
- );
36
- const input = screen.getByTestId("multiple-input");
37
- expect(input).toBeDisabled();
38
- });
39
-
40
- it("should be required", () => {
41
- render(
42
- <MultipleInput
43
- required
44
- name="test-input"
45
- label="test"
46
- data-testid="multiple-input"
47
- />
48
- );
49
- const label = screen.getByTestId("multiple-input-label");
50
- expect(label).toHaveTextContent("test *");
51
- });
52
-
53
- it("should change value", () => {
54
- render(<MultipleInput name="test-input" data-testid="multiple-input" />);
55
- const input = screen.getByTestId("multiple-input");
56
- fireEvent.change(input, { target: { value: "test" } });
57
- expect(input).toHaveValue("test");
58
- });
59
-
60
- it("should render add button", () => {
61
- render(<MultipleInput name="test-input" data-testid="multiple-input" />);
62
- const addButton = screen.getByRole("button");
63
- expect(addButton).toBeInTheDocument();
64
- });
65
-
66
- it("should add item when add button is clicked", () => {
67
- const mockOnAdd = jest.fn();
68
- render(
69
- <MultipleInput
70
- name="test-input"
71
- data-testid="multiple-input"
72
- onAdd={mockOnAdd}
73
- withoutForm
74
- />
75
- );
76
-
77
- const input = screen.getByTestId("multiple-input");
78
- const addButton = screen.getByRole("button");
79
-
80
- fireEvent.change(input, { target: { value: "test item" } });
81
- fireEvent.click(addButton);
82
-
83
- expect(mockOnAdd).toHaveBeenCalledWith("test item");
84
- });
85
-
86
- it("should render with initial data", () => {
87
- const initialData = ["item 1", "item 2"];
88
-
89
- render(
90
- <MultipleInput
91
- name="test-input"
92
- data={initialData}
93
- data-testid="multiple-input"
94
- withoutForm
95
- />
96
- );
97
-
98
- expect(screen.getByText("item 1")).toBeInTheDocument();
99
- expect(screen.getByText("item 2")).toBeInTheDocument();
100
- });
101
-
102
- it("should handle mask prop", () => {
103
- render(
104
- <MultipleInput
105
- name="test-input"
106
- mask="(99) 99999-9999"
107
- data-testid="multiple-input"
108
- />
109
- );
110
-
111
- const input = screen.getByTestId("multiple-input");
112
- expect(input).toBeInTheDocument();
113
- });
114
-
115
- it("should remove item when remove button is clicked", () => {
116
- const mockOnRemove = jest.fn();
117
- const initialData = ["item 1", "item 2"];
118
-
119
- render(
120
- <MultipleInput
121
- name="test-input"
122
- data={initialData}
123
- onRemove={mockOnRemove}
124
- data-testid="multiple-input"
125
- withoutForm
126
- />
127
- );
128
-
129
- const removeButtons = screen.getAllByRole("button");
130
- const removeButton = removeButtons.find((button) =>
131
- button.querySelector('[data-icon="MdDelete"]')
132
- );
133
-
134
- if (removeButton) {
135
- fireEvent.click(removeButton);
136
- expect(mockOnRemove).toHaveBeenCalledWith(0);
137
- }
138
- });
139
-
140
- it("should disable add button when input is empty", () => {
141
- render(
142
- <MultipleInput
143
- name="test-input"
144
- data-testid="multiple-input"
145
- withoutForm
146
- />
147
- );
148
-
149
- const addButton = screen.getByRole("button");
150
- expect(addButton).toBeDisabled();
151
- });
152
- });
@@ -1,2 +0,0 @@
1
- export * from "./MultipleInput";
2
- export * from "./MultipleMaskInput";