@phsa.tec/design-system-react 0.1.6 → 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 (213) 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/__tests__/number-input.test.tsx +0 -175
  113. package/src/components/dataInput/Input/components/NumberInput/index.ts +0 -1
  114. package/src/components/dataInput/Input/components/NumberInput/number-input.stories.tsx +0 -76
  115. package/src/components/dataInput/Input/components/NumberInput/number-input.tsx +0 -70
  116. package/src/components/dataInput/Input/index.ts +0 -4
  117. package/src/components/dataInput/Select/MultiSelect/MultiSelect.stories.tsx +0 -119
  118. package/src/components/dataInput/Select/MultiSelect/MultiSelectBase.tsx +0 -135
  119. package/src/components/dataInput/Select/MultiSelect/index.tsx +0 -75
  120. package/src/components/dataInput/Select/Select.stories.tsx +0 -61
  121. package/src/components/dataInput/Select/Select.tsx +0 -73
  122. package/src/components/dataInput/Select/SelectBase.tsx +0 -58
  123. package/src/components/dataInput/Select/index.ts +0 -2
  124. package/src/components/dataInput/Switch/Switch.stories.tsx +0 -75
  125. package/src/components/dataInput/Switch/Switch.tsx +0 -52
  126. package/src/components/dataInput/Switch/index.ts +0 -1
  127. package/src/components/dataInput/checkbox/Checkbox.tsx +0 -57
  128. package/src/components/dataInput/checkbox/Checkbox_old.tsx +0 -58
  129. package/src/components/dataInput/checkbox/Checkout.stories.tsx +0 -62
  130. package/src/components/dataInput/checkbox/index.ts +0 -1
  131. package/src/components/dataInput/form/Form.tsx +0 -47
  132. package/src/components/dataInput/form/index.ts +0 -3
  133. package/src/components/dataInput/index.ts +0 -5
  134. package/src/components/feedback/ErrorLabel/index.tsx +0 -24
  135. package/src/components/feedback/Spinner/index.ts +0 -1
  136. package/src/components/feedback/Toast/Toast.stories.tsx +0 -45
  137. package/src/components/feedback/Toast/index.ts +0 -2
  138. package/src/components/feedback/index.ts +0 -2
  139. package/src/components/index.ts +0 -6
  140. package/src/components/layout/Crud/components/Table/index.tsx +0 -183
  141. package/src/components/layout/Crud/components/Table/types.ts +0 -15
  142. package/src/components/layout/Crud/crud.stories.tsx +0 -317
  143. package/src/components/layout/Crud/hook/useCrudLayout/index.tsx +0 -94
  144. package/src/components/layout/Crud/hook/useRequest/index.tsx +0 -156
  145. package/src/components/layout/Crud/index.tsx +0 -295
  146. package/src/components/layout/Crud/store/CrudLayoutStore.ts +0 -75
  147. package/src/components/layout/Crud/types.ts +0 -14
  148. package/src/components/layout/Drawer/CustomDrawer/index.tsx +0 -33
  149. package/src/components/layout/Drawer/Drawer.stories.tsx +0 -80
  150. package/src/components/layout/Drawer/index.ts +0 -2
  151. package/src/components/layout/PageLayout/PageLayout.stories.tsx +0 -42
  152. package/src/components/layout/PageLayout/index.tsx +0 -28
  153. package/src/components/layout/Separator/index.ts +0 -1
  154. package/src/components/layout/Sheet/Sheet.stories.tsx +0 -28
  155. package/src/components/layout/Sheet/Sheet.tsx +0 -22
  156. package/src/components/layout/Sheet/index.ts +0 -1
  157. package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -116
  158. package/src/components/layout/Sidebar/Sidebar.tsx +0 -50
  159. package/src/components/layout/Sidebar/components/app-sidebar.tsx +0 -203
  160. package/src/components/layout/Sidebar/components/footer-sidebar.tsx +0 -17
  161. package/src/components/layout/Sidebar/components/header-sidebar.tsx +0 -90
  162. package/src/components/layout/Sidebar/components/menus.tsx +0 -55
  163. package/src/components/layout/Sidebar/components/nav-projects.tsx +0 -88
  164. package/src/components/layout/Sidebar/components/nav-user.tsx +0 -114
  165. package/src/components/layout/Sidebar/components/team-switcher.tsx +0 -85
  166. package/src/components/layout/Sidebar/index.ts +0 -2
  167. package/src/components/layout/Sidebar/provider/index.tsx +0 -51
  168. package/src/components/layout/Tabs/Tabs.tsx +0 -51
  169. package/src/components/layout/Tabs/index.ts +0 -1
  170. package/src/components/layout/Tabs/tabs.stories.tsx +0 -57
  171. package/src/components/layout/index.ts +0 -6
  172. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +0 -66
  173. package/src/components/navigation/Breadcrumbs/index.ts +0 -2
  174. package/src/components/navigation/index.ts +0 -1
  175. package/src/components/ui/alert-dialog.tsx +0 -141
  176. package/src/components/ui/alert.tsx +0 -59
  177. package/src/components/ui/avatar.tsx +0 -50
  178. package/src/components/ui/badge.tsx +0 -40
  179. package/src/components/ui/breadcrumb.tsx +0 -115
  180. package/src/components/ui/button.tsx +0 -57
  181. package/src/components/ui/card.tsx +0 -83
  182. package/src/components/ui/checkbox.tsx +0 -34
  183. package/src/components/ui/collapsible.tsx +0 -11
  184. package/src/components/ui/command.tsx +0 -153
  185. package/src/components/ui/dialog.tsx +0 -124
  186. package/src/components/ui/drawer.tsx +0 -117
  187. package/src/components/ui/dropdown-menu.tsx +0 -201
  188. package/src/components/ui/form.tsx +0 -179
  189. package/src/components/ui/input.tsx +0 -24
  190. package/src/components/ui/label.tsx +0 -30
  191. package/src/components/ui/popover.tsx +0 -33
  192. package/src/components/ui/select.tsx +0 -161
  193. package/src/components/ui/separator.tsx +0 -31
  194. package/src/components/ui/sheet.tsx +0 -140
  195. package/src/components/ui/sidebar.tsx +0 -763
  196. package/src/components/ui/skeleton.tsx +0 -15
  197. package/src/components/ui/sonner.tsx +0 -31
  198. package/src/components/ui/spinner.tsx +0 -54
  199. package/src/components/ui/switch.tsx +0 -33
  200. package/src/components/ui/table.tsx +0 -120
  201. package/src/components/ui/tabs.tsx +0 -55
  202. package/src/components/ui/toast.tsx +0 -130
  203. package/src/components/ui/toaster.tsx +0 -35
  204. package/src/components/ui/tooltip.tsx +0 -32
  205. package/src/hooks/use-conditional-controller.tsx +0 -35
  206. package/src/hooks/use-mask.tsx +0 -116
  207. package/src/hooks/use-mobile.tsx +0 -19
  208. package/src/hooks/use-toast.ts +0 -191
  209. package/src/index.ts +0 -1
  210. package/src/introduction.mdx +0 -132
  211. package/src/lib/utils.ts +0 -6
  212. package/tailwind.config.ts +0 -83
  213. package/tsconfig.json +0 -27
@@ -1,96 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { MultipleInput } from "./MultipleInput";
3
- import { Form } from "@/components/ui/form";
4
- import { useForm } from "react-hook-form";
5
-
6
- const meta: Meta<typeof MultipleInput> = {
7
- title: "Data Input/Input/Multiple Input",
8
- component: MultipleInput,
9
- tags: ["autodocs"],
10
- parameters: {
11
- layout: "centered",
12
- },
13
- };
14
-
15
- export default meta;
16
- type Story = StoryObj<typeof MultipleInput>;
17
-
18
- export const Default: Story = {
19
- args: {
20
- label: "Multiple Input",
21
- name: "multipleInput",
22
- data: ["Item 1", "Item 2", "Item 3"],
23
- placeholder: "Multiple Input",
24
- withoutForm: true,
25
- onAdd: (data: string) => {
26
- console.log("Added:", data);
27
- },
28
- onRemove: (index: number) => {
29
- console.log("Removed index:", index);
30
- },
31
- },
32
- };
33
-
34
- export const WithError: Story = {
35
- args: {
36
- label: "Multiple Input",
37
- name: "multipleInput",
38
- error: "This is an error",
39
- data: ["Item 1", "Item 2", "Item 3"],
40
- placeholder: "Multiple Input",
41
- withoutForm: true,
42
- onAdd: (data: string) => {
43
- console.log("Added:", data);
44
- },
45
- onRemove: (index: number) => {
46
- console.log("Removed index:", index);
47
- },
48
- },
49
- };
50
-
51
- export const WithForm: Story = {
52
- args: {
53
- label: "Multiple Input",
54
- name: "client",
55
- placeholder: "Multiple Input",
56
- },
57
- decorators: [
58
- (Story: React.ComponentType) => {
59
- const form = useForm({
60
- defaultValues: {
61
- client: ["Item 1", "Item 2", "Item 3"],
62
- },
63
- });
64
-
65
- return (
66
- <Form {...form}>
67
- <Story />
68
- </Form>
69
- );
70
- },
71
- ],
72
- };
73
-
74
- export const WithMaskAndForm: Story = {
75
- args: {
76
- label: "Phone Numbers",
77
- name: "phoneNumbers",
78
- placeholder: "Enter phone number",
79
- mask: "(99) 99999-9999",
80
- },
81
- decorators: [
82
- (Story: React.ComponentType) => {
83
- const form = useForm({
84
- defaultValues: {
85
- phoneNumbers: ["(11) 99999-9999", "(21) 88888-8888"],
86
- },
87
- });
88
-
89
- return (
90
- <Form {...form}>
91
- <Story />
92
- </Form>
93
- );
94
- },
95
- ],
96
- };
@@ -1,175 +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 { NumberInput } from "../number-input";
5
-
6
- describe("NumberInput", () => {
7
- it("should render label", () => {
8
- render(<NumberInput label="test" data-testid="number-input" />);
9
- const label = screen.getByTestId("number-input-label");
10
- expect(label).toBeInTheDocument();
11
- expect(label).toHaveTextContent("test");
12
- });
13
-
14
- it("should render error", () => {
15
- render(<NumberInput error="test" data-testid="number-input" />);
16
- const error = screen.getByTestId("number-input-error-label");
17
- expect(error).toBeInTheDocument();
18
- expect(error).toHaveTextContent("test");
19
- });
20
-
21
- it("should be disabled", () => {
22
- render(<NumberInput disabled data-testid="number-input" />);
23
- const input = screen.getByTestId("number-input");
24
- expect(input).toBeDisabled();
25
- });
26
-
27
- it("should be required", () => {
28
- render(<NumberInput required data-testid="number-input" label="test" />);
29
- const label = screen.getByTestId("number-input-label");
30
- expect(label).toHaveTextContent("test *");
31
- });
32
-
33
- it("should handle placeholder", () => {
34
- render(
35
- <NumberInput data-testid="number-input" placeholder="Digite um número" />
36
- );
37
- const input = screen.getByTestId("number-input");
38
-
39
- expect(input).toHaveAttribute("placeholder", "Digite um número");
40
- });
41
-
42
- it("should handle name attribute", () => {
43
- render(<NumberInput data-testid="number-input" name="amount" />);
44
- const input = screen.getByTestId("number-input");
45
-
46
- expect(input).toHaveAttribute("name", "amount");
47
- });
48
-
49
- it("should format numbers with thousands separator", async () => {
50
- const user = userEvent.setup();
51
- render(<NumberInput data-testid="number-input" thousandSeparator={true} />);
52
- const input = screen.getByTestId("number-input");
53
-
54
- await user.type(input, "1234567");
55
-
56
- expect(input).toHaveValue("1,234,567");
57
- });
58
-
59
- it("should format currency values", async () => {
60
- const user = userEvent.setup();
61
- render(
62
- <NumberInput
63
- data-testid="number-input"
64
- thousandSeparator={true}
65
- prefix="R$ "
66
- decimalScale={2}
67
- fixedDecimalScale={true}
68
- />
69
- );
70
- const input = screen.getByTestId("number-input");
71
-
72
- await user.type(input, "1234.56");
73
-
74
- expect(input).toHaveValue("R$ 1,234.56");
75
- });
76
-
77
- it("should limit decimal places", async () => {
78
- const user = userEvent.setup();
79
- render(<NumberInput data-testid="number-input" decimalScale={2} />);
80
- const input = screen.getByTestId("number-input");
81
-
82
- await user.type(input, "123.456789");
83
-
84
- expect(input).toHaveValue("123.45");
85
- });
86
-
87
- it("should handle percentage format", async () => {
88
- const user = userEvent.setup();
89
- render(
90
- <NumberInput data-testid="number-input" suffix="%" decimalScale={2} />
91
- );
92
- const input = screen.getByTestId("number-input");
93
-
94
- await user.type(input, "15.75");
95
-
96
- expect(input).toHaveValue("15.75%");
97
- });
98
-
99
- it("should call onChange with synthetic event", async () => {
100
- const user = userEvent.setup();
101
- const mockOnChange = jest.fn();
102
- render(
103
- <NumberInput
104
- data-testid="number-input"
105
- onChange={mockOnChange}
106
- name="testInput"
107
- />
108
- );
109
- const input = screen.getByTestId("number-input");
110
-
111
- await user.type(input, "123");
112
-
113
- expect(mockOnChange).toHaveBeenCalled();
114
- const lastCall =
115
- mockOnChange.mock.calls[mockOnChange.mock.calls.length - 1][0];
116
- expect(lastCall.target.name).toBe("testInput");
117
- expect(lastCall.target.value).toBe("123");
118
- });
119
-
120
- it("should call onValueChange with formatted data", async () => {
121
- const user = userEvent.setup();
122
- const mockOnValueChange = jest.fn();
123
- render(
124
- <NumberInput
125
- data-testid="number-input"
126
- onValueChange={mockOnValueChange}
127
- thousandSeparator={true}
128
- />
129
- );
130
- const input = screen.getByTestId("number-input");
131
-
132
- await user.type(input, "1234");
133
-
134
- expect(mockOnValueChange).toHaveBeenCalled();
135
- const lastCall =
136
- mockOnValueChange.mock.calls[mockOnValueChange.mock.calls.length - 1][0];
137
- expect(lastCall.value).toBe("1234");
138
- expect(lastCall.floatValue).toBe(1234);
139
- expect(lastCall.formattedValue).toBe("1,234");
140
- });
141
-
142
- it("should handle negative numbers", async () => {
143
- const user = userEvent.setup();
144
- render(<NumberInput data-testid="number-input" allowNegative={true} />);
145
- const input = screen.getByTestId("number-input");
146
-
147
- await user.type(input, "-123");
148
-
149
- expect(input).toHaveValue("-123");
150
- });
151
-
152
- it("should prevent negative numbers when allowNegative is false", async () => {
153
- const user = userEvent.setup();
154
- render(<NumberInput data-testid="number-input" allowNegative={false} />);
155
- const input = screen.getByTestId("number-input");
156
-
157
- await user.type(input, "-123");
158
-
159
- expect(input).toHaveValue("123");
160
- });
161
-
162
- it("should handle controlled value", () => {
163
- render(<NumberInput data-testid="number-input" value="1000" />);
164
- const input = screen.getByTestId("number-input");
165
-
166
- expect(input).toHaveValue("1000");
167
- });
168
-
169
- it("should handle empty value", () => {
170
- render(<NumberInput data-testid="number-input" value="" />);
171
- const input = screen.getByTestId("number-input");
172
-
173
- expect(input).toHaveValue("");
174
- });
175
- });
@@ -1 +0,0 @@
1
- export * from "./number-input";
@@ -1,76 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { NumberInput } from "./number-input";
3
- import { useForm } from "react-hook-form";
4
- import { Form } from "../../../../../components/ui/form";
5
-
6
- const meta = {
7
- title: "Data Input/Input/NumberInput",
8
- component: NumberInput,
9
- parameters: {
10
- layout: "centered",
11
- },
12
- tags: ["autodocs"],
13
- } satisfies Meta<typeof NumberInput>;
14
-
15
- export default meta;
16
- type Story = StoryObj<typeof meta>;
17
-
18
- export const Default: Story = {
19
- args: {
20
- placeholder: "0,00",
21
- label: "Valor",
22
- },
23
- };
24
-
25
- export const Currency: Story = {
26
- args: {
27
- placeholder: "0,00",
28
- label: "Preço",
29
- prefix: "R$ ",
30
- decimalScale: 2,
31
- fixedDecimalScale: false,
32
- value: 1234.56,
33
- },
34
- };
35
-
36
- export const Percentage: Story = {
37
- args: {
38
- placeholder: "0,00",
39
- label: "Porcentagem",
40
- suffix: "%",
41
- decimalScale: 1,
42
- fixedDecimalScale: true,
43
- value: 85.5,
44
- },
45
- };
46
-
47
- export const CustomFormat: Story = {
48
- args: {
49
- placeholder: "0",
50
- label: "Número",
51
- thousandSeparator: ",",
52
- decimalSeparator: ".",
53
- value: 1234567.89,
54
- },
55
- };
56
-
57
- export const WithForm = () => {
58
- const form = useForm({
59
- defaultValues: {
60
- price: 99.99,
61
- },
62
- });
63
-
64
- return (
65
- <Form {...form}>
66
- <form className="space-y-6">
67
- <NumberInput
68
- name="price"
69
- label="Preço"
70
- prefix="R$ "
71
- placeholder="Digite o preço do produto"
72
- />
73
- </form>
74
- </Form>
75
- );
76
- };
@@ -1,70 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import {
5
- NumericFormat,
6
- NumericFormatProps,
7
- SourceInfo,
8
- } from "react-number-format";
9
- import { InputBase } from "../InputBase";
10
- import { Input } from "../../../../ui/input";
11
- import { InputProps } from "../Input/types";
12
- import { useCallback, useMemo } from "react";
13
- import { useConditionalController } from "@/hooks/use-conditional-controller";
14
-
15
- export type NumberInputProps = Omit<NumericFormatProps, "onChange"> &
16
- InputProps;
17
-
18
- export const NumberInput = (props: NumberInputProps) => {
19
- const formData = useConditionalController({
20
- name: props.name || "",
21
- withoutForm: props.withoutForm,
22
- });
23
-
24
- const inputProps = useMemo(() => {
25
- return {
26
- ...formData,
27
- ...props,
28
- };
29
- }, [formData, props]);
30
-
31
- const onValueChange = useCallback(
32
- (
33
- data: {
34
- value: string;
35
- floatValue: number | undefined;
36
- formattedValue: string;
37
- },
38
- sourceInfo: SourceInfo
39
- ) => {
40
- const syntheticEvent = {
41
- target: {
42
- value: data.formattedValue,
43
- name: props.name,
44
- },
45
- currentTarget: {
46
- value: data.formattedValue,
47
- name: props.name,
48
- },
49
- } as React.ChangeEvent<HTMLInputElement>;
50
-
51
- props.onChange?.(syntheticEvent);
52
- props.onValueChange?.(data, sourceInfo);
53
- if (formData.onChange) {
54
- formData.onChange(data.formattedValue);
55
- }
56
- },
57
- [props, formData]
58
- );
59
-
60
- return (
61
- <InputBase {...props}>
62
- <NumericFormat
63
- {...inputProps}
64
- customInput={Input}
65
- value={props.value}
66
- onValueChange={onValueChange}
67
- />
68
- </InputBase>
69
- );
70
- };
@@ -1,4 +0,0 @@
1
- export * from "./components/Input";
2
- export * from "./components/NumberInput";
3
- export * from "./components/MaskInput";
4
- export * from "./components/MultipleInput";
@@ -1,119 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { MultiSelect } from "./index";
3
- import { useState } from "react";
4
- import { Form } from "../../form";
5
- import { useForm } from "react-hook-form";
6
-
7
- const meta: Meta<typeof MultiSelect> = {
8
- title: "Data Input/MultiSelect",
9
- component: MultiSelect,
10
- tags: ["autodocs"],
11
- };
12
-
13
- export default meta;
14
- type Story = StoryObj<typeof MultiSelect>;
15
-
16
- const options = [
17
- { label: "Next.js", value: "nextjs" },
18
- { label: "SvelteKit", value: "sveltekit" },
19
- { label: "Nuxt.js", value: "nuxtjs" },
20
- { label: "Remix", value: "remix" },
21
- { label: "Astro", value: "astro" },
22
- ];
23
-
24
- const MultiSelectWithHooks = () => {
25
- const [selected, setSelected] = useState<string[]>([]);
26
-
27
- return (
28
- <MultiSelect
29
- label="MultiSelect"
30
- options={options}
31
- selected={selected}
32
- onChange={setSelected}
33
- placeholder="Select frameworks..."
34
- />
35
- );
36
- };
37
-
38
- export const Default: Story = {
39
- render: () => <MultiSelectWithHooks />,
40
- };
41
-
42
- export const Preselected: Story = {
43
- render: () => {
44
- const [selected, setSelected] = useState<string[]>(["nextjs", "nuxtjs"]);
45
-
46
- return (
47
- <MultiSelect
48
- options={options}
49
- selected={selected}
50
- onChange={setSelected}
51
- placeholder="Select frameworks..."
52
- />
53
- );
54
- },
55
- };
56
-
57
- export const CustomPlaceholder: Story = {
58
- render: () => {
59
- const [selected, setSelected] = useState<string[]>([]);
60
-
61
- return (
62
- <MultiSelect
63
- options={options}
64
- selected={selected}
65
- onChange={setSelected}
66
- placeholder="Choose your favorite frameworks..."
67
- />
68
- );
69
- },
70
- };
71
-
72
- export const ManyOptions: Story = {
73
- render: () => {
74
- const [selected, setSelected] = useState<string[]>([]);
75
- const manyOptions = [
76
- ...options,
77
- { label: "React", value: "react" },
78
- { label: "Vue", value: "vue" },
79
- { label: "Angular", value: "angular" },
80
- { label: "Solid", value: "solid" },
81
- { label: "Qwik", value: "qwik" },
82
- { label: "Ember", value: "ember" },
83
- { label: "Preact", value: "preact" },
84
- { label: "Alpine", value: "alpine" },
85
- ];
86
-
87
- return (
88
- <MultiSelect
89
- options={manyOptions}
90
- selected={selected}
91
- onChange={setSelected}
92
- placeholder="Select frameworks..."
93
- />
94
- );
95
- },
96
- };
97
-
98
- export const WithForm: Story = {
99
- args: {
100
- name: "multiSelect",
101
- options: [{ label: "Next.js", value: "nextjs" }],
102
- label: "MultiSelect",
103
- required: true,
104
- },
105
- decorators: [
106
- (Story: React.ComponentType) => {
107
- const form = useForm({
108
- defaultValues: {
109
- multiSelect: ["nextjs"],
110
- },
111
- });
112
- return (
113
- <Form {...form}>
114
- <Story />
115
- </Form>
116
- );
117
- },
118
- ],
119
- };
@@ -1,135 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import { Search, X } from "lucide-react";
5
- import { cn } from "../../../../lib/utils";
6
- import * as Popover from "@radix-ui/react-popover";
7
-
8
- export type MultiSelectBaseProps = {
9
- options: { label: string; value: string }[];
10
- selected?: string[];
11
- onChange?: (values: string[]) => void;
12
- placeholder?: string;
13
- className?: string;
14
- };
15
-
16
- export function MultiSelectBase({
17
- options = [],
18
- selected = [],
19
- onChange = () => {},
20
- placeholder = "Select frameworks...",
21
- className,
22
- }: MultiSelectBaseProps) {
23
- const [open, setOpen] = React.useState(false);
24
- const [inputValue, setInputValue] = React.useState("");
25
- const inputRef = React.useRef<HTMLInputElement>(null);
26
-
27
- const handleRemoveItem = (valueToRemove: string) => {
28
- onChange(selected.filter((value) => value !== valueToRemove));
29
- };
30
-
31
- const handleSelectItem = (value: string) => {
32
- if (selected.includes(value)) {
33
- onChange(selected.filter((v) => v !== value));
34
- } else {
35
- onChange([...selected, value]);
36
- }
37
- };
38
-
39
- const filteredOptions = options.filter((option) =>
40
- option.label.toLowerCase().includes(inputValue.toLowerCase())
41
- );
42
-
43
- return (
44
- <Popover.Root open={open} onOpenChange={setOpen}>
45
- <Popover.Trigger asChild>
46
- <div
47
- className={cn(
48
- "flex min-h-[40px] w-full flex-wrap gap-1.5 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
49
- className
50
- )}
51
- >
52
- {selected.map((value) => {
53
- const option = options.find((o) => o.value === value);
54
- if (!option) return null;
55
-
56
- return (
57
- <div
58
- key={value}
59
- className="flex items-center gap-1 rounded-md bg-secondary px-2 py-1 text-sm text-secondary-foreground"
60
- >
61
- {option.label}
62
- <button
63
- type="button"
64
- onClick={(e) => {
65
- e.stopPropagation();
66
- handleRemoveItem(value);
67
- }}
68
- className="rounded-full hover:bg-secondary-foreground/20"
69
- >
70
- <X className="h-3 w-3" />
71
- <span className="sr-only">Remove {option.label}</span>
72
- </button>
73
- </div>
74
- );
75
- })}
76
- <div className="flex-1">
77
- {selected.length === 0 && (
78
- <span className="text-muted-foreground">{placeholder}</span>
79
- )}
80
- </div>
81
- </div>
82
- </Popover.Trigger>
83
-
84
- <Popover.Portal>
85
- <Popover.Content
86
- className="w-[--radix-popover-trigger-width] z-50 mt-1 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95"
87
- align="start"
88
- sideOffset={4}
89
- >
90
- <div className="flex items-center border-b border-border px-3 py-2">
91
- <Search className="h-4 w-4 text-muted-foreground" />
92
- <input
93
- ref={inputRef}
94
- value={inputValue}
95
- onChange={(e) => setInputValue(e.target.value)}
96
- placeholder="Search..."
97
- className="flex-1 bg-transparent px-2 outline-none placeholder:text-muted-foreground"
98
- />
99
- </div>
100
- <div className="max-h-[200px] overflow-auto">
101
- {filteredOptions.length === 0 ? (
102
- <div className="px-2 py-4 text-center text-sm text-muted-foreground">
103
- No results found.
104
- </div>
105
- ) : (
106
- filteredOptions.map((option) => (
107
- <div
108
- key={option.value}
109
- onClick={() => handleSelectItem(option.value)}
110
- className={cn(
111
- "flex cursor-pointer items-center gap-2 px-4 py-2 text-sm hover:bg-accent",
112
- selected.includes(option.value) && "bg-accent"
113
- )}
114
- >
115
- <div
116
- className={cn(
117
- "flex h-4 w-4 items-center justify-center rounded border border-primary",
118
- selected.includes(option.value) &&
119
- "bg-primary text-primary-foreground"
120
- )}
121
- >
122
- {selected.includes(option.value) && (
123
- <span className="text-[10px]">✓</span>
124
- )}
125
- </div>
126
- {option.label}
127
- </div>
128
- ))
129
- )}
130
- </div>
131
- </Popover.Content>
132
- </Popover.Portal>
133
- </Popover.Root>
134
- );
135
- }