@pautena/react-design-system 0.4.7 → 0.5.0

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 (146) hide show
  1. package/dist/cjs/index.js +4 -4
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/alerts/expandable-alert/expandable-alert.d.ts +11 -0
  4. package/dist/cjs/types/components/alerts/expandable-alert/index.d.ts +1 -0
  5. package/dist/cjs/types/components/alerts/index.d.ts +1 -0
  6. package/dist/cjs/types/components/data-display/board/board.d.ts +10 -0
  7. package/dist/cjs/types/components/data-display/board/index.d.ts +1 -0
  8. package/dist/cjs/types/components/data-display/index.d.ts +2 -0
  9. package/dist/cjs/types/components/data-display/markdown/index.d.ts +1 -0
  10. package/dist/cjs/types/components/data-display/markdown/markdown.d.ts +7 -0
  11. package/dist/cjs/types/components/dialogs/bootstrap-dialog/bootstrap-dialog.d.ts +2 -0
  12. package/dist/cjs/types/components/dialogs/bootstrap-dialog/index.d.ts +1 -0
  13. package/dist/cjs/types/components/dialogs/confirm-dialog/confirm-dialog.d.ts +10 -0
  14. package/dist/cjs/types/components/dialogs/confirm-dialog/index.d.ts +1 -0
  15. package/dist/cjs/types/components/dialogs/dialog-hooks/index.d.ts +1 -0
  16. package/dist/cjs/types/components/dialogs/dialog-hooks/use-dialog.d.ts +7 -0
  17. package/dist/cjs/types/components/dialogs/dialog.types.d.ts +26 -0
  18. package/dist/cjs/types/components/dialogs/form-dialog/form-dialog.d.ts +10 -0
  19. package/dist/cjs/types/components/dialogs/form-dialog/index.d.ts +1 -0
  20. package/dist/cjs/types/components/dialogs/index.d.ts +5 -0
  21. package/dist/cjs/types/components/index.d.ts +2 -0
  22. package/dist/cjs/types/components/inputs/enhanced-autocomplete/enhanced-autocomplete.d.ts +10 -0
  23. package/dist/cjs/types/components/inputs/enhanced-autocomplete/index.d.ts +1 -0
  24. package/dist/cjs/types/components/inputs/enhanced-text-field/enhanced-text-field.d.ts +7 -0
  25. package/dist/cjs/types/components/inputs/enhanced-text-field/index.d.ts +1 -0
  26. package/dist/cjs/types/components/inputs/index.d.ts +1 -0
  27. package/dist/cjs/types/components/value-displays/index.d.ts +2 -1
  28. package/dist/cjs/types/components/value-displays/value-base/index.d.ts +2 -0
  29. package/dist/cjs/types/components/value-displays/{value-displays.types.d.ts → value-base/value-displays.types.d.ts} +10 -0
  30. package/dist/cjs/types/components/value-displays/value-base/value-edit.d.ts +19 -0
  31. package/dist/cjs/types/components/value-displays/value-boolean/value-boolean.d.ts +3 -3
  32. package/dist/cjs/types/components/value-displays/value-datetime/value-datetime.d.ts +8 -3
  33. package/dist/cjs/types/components/value-displays/value-image/value-image.d.ts +1 -1
  34. package/dist/cjs/types/components/value-displays/value-rating/value-rating.d.ts +3 -3
  35. package/dist/cjs/types/components/value-displays/value-text/value-text.d.ts +3 -17
  36. package/dist/esm/index.js +4 -4
  37. package/dist/esm/index.js.map +1 -1
  38. package/dist/esm/types/components/alerts/expandable-alert/expandable-alert.d.ts +11 -0
  39. package/dist/esm/types/components/alerts/expandable-alert/index.d.ts +1 -0
  40. package/dist/esm/types/components/alerts/index.d.ts +1 -0
  41. package/dist/esm/types/components/data-display/board/board.d.ts +10 -0
  42. package/dist/esm/types/components/data-display/board/index.d.ts +1 -0
  43. package/dist/esm/types/components/data-display/index.d.ts +2 -0
  44. package/dist/esm/types/components/data-display/markdown/index.d.ts +1 -0
  45. package/dist/esm/types/components/data-display/markdown/markdown.d.ts +7 -0
  46. package/dist/esm/types/components/dialogs/bootstrap-dialog/bootstrap-dialog.d.ts +2 -0
  47. package/dist/esm/types/components/dialogs/bootstrap-dialog/index.d.ts +1 -0
  48. package/dist/esm/types/components/dialogs/confirm-dialog/confirm-dialog.d.ts +10 -0
  49. package/dist/esm/types/components/dialogs/confirm-dialog/index.d.ts +1 -0
  50. package/dist/esm/types/components/dialogs/dialog-hooks/index.d.ts +1 -0
  51. package/dist/esm/types/components/dialogs/dialog-hooks/use-dialog.d.ts +7 -0
  52. package/dist/esm/types/components/dialogs/dialog.types.d.ts +26 -0
  53. package/dist/esm/types/components/dialogs/form-dialog/form-dialog.d.ts +10 -0
  54. package/dist/esm/types/components/dialogs/form-dialog/index.d.ts +1 -0
  55. package/dist/esm/types/components/dialogs/index.d.ts +5 -0
  56. package/dist/esm/types/components/index.d.ts +2 -0
  57. package/dist/esm/types/components/inputs/enhanced-autocomplete/enhanced-autocomplete.d.ts +10 -0
  58. package/dist/esm/types/components/inputs/enhanced-autocomplete/index.d.ts +1 -0
  59. package/dist/esm/types/components/inputs/enhanced-text-field/enhanced-text-field.d.ts +7 -0
  60. package/dist/esm/types/components/inputs/enhanced-text-field/index.d.ts +1 -0
  61. package/dist/esm/types/components/inputs/index.d.ts +1 -0
  62. package/dist/esm/types/components/value-displays/index.d.ts +2 -1
  63. package/dist/esm/types/components/value-displays/value-base/index.d.ts +2 -0
  64. package/dist/esm/types/components/value-displays/{value-displays.types.d.ts → value-base/value-displays.types.d.ts} +10 -0
  65. package/dist/esm/types/components/value-displays/value-base/value-edit.d.ts +19 -0
  66. package/dist/esm/types/components/value-displays/value-boolean/value-boolean.d.ts +3 -3
  67. package/dist/esm/types/components/value-displays/value-datetime/value-datetime.d.ts +8 -3
  68. package/dist/esm/types/components/value-displays/value-image/value-image.d.ts +1 -1
  69. package/dist/esm/types/components/value-displays/value-rating/value-rating.d.ts +3 -3
  70. package/dist/esm/types/components/value-displays/value-text/value-text.d.ts +3 -17
  71. package/dist/index.d.ts +130 -22
  72. package/package.json +34 -32
  73. package/src/components/alerts/alerts.stories.mdx +10 -0
  74. package/src/components/alerts/expandable-alert/expandable-alert.stories.tsx +48 -0
  75. package/src/components/alerts/expandable-alert/expandable-alert.test.tsx +114 -0
  76. package/src/components/alerts/expandable-alert/expandable-alert.tsx +71 -0
  77. package/src/components/alerts/expandable-alert/index.ts +1 -0
  78. package/src/components/alerts/index.ts +1 -0
  79. package/src/components/components.stories.mdx +2 -0
  80. package/src/components/data-display/board/board.stories.tsx +54 -0
  81. package/src/components/data-display/board/board.test.tsx +100 -0
  82. package/src/components/data-display/board/board.tsx +63 -0
  83. package/src/components/data-display/board/index.ts +1 -0
  84. package/src/components/data-display/data-display.stories.mdx +2 -0
  85. package/src/components/data-display/index.ts +2 -0
  86. package/src/components/data-display/markdown/index.ts +1 -0
  87. package/src/components/data-display/markdown/markdown.stories.tsx +25 -0
  88. package/src/components/data-display/markdown/markdown.test.tsx +64 -0
  89. package/src/components/data-display/markdown/markdown.tsx +38 -0
  90. package/src/components/dialogs/bootstrap-dialog/bootstrap-dialog.stories.tsx +81 -0
  91. package/src/components/dialogs/bootstrap-dialog/bootstrap-dialog.test.tsx +233 -0
  92. package/src/components/dialogs/bootstrap-dialog/bootstrap-dialog.tsx +95 -0
  93. package/src/components/dialogs/bootstrap-dialog/index.ts +1 -0
  94. package/src/components/dialogs/confirm-dialog/confirm-dialog.stories.tsx +43 -0
  95. package/src/components/dialogs/confirm-dialog/confirm-dialog.test.tsx +150 -0
  96. package/src/components/dialogs/confirm-dialog/confirm-dialog.tsx +51 -0
  97. package/src/components/dialogs/confirm-dialog/index.ts +1 -0
  98. package/src/components/dialogs/dialog-hooks/index.ts +1 -0
  99. package/src/components/dialogs/dialog-hooks/use-dialog.ts +10 -0
  100. package/src/components/dialogs/dialog.types.ts +27 -0
  101. package/src/components/dialogs/dialogs.stories.mdx +12 -0
  102. package/src/components/dialogs/form-dialog/form-dialog.stories.tsx +52 -0
  103. package/src/components/dialogs/form-dialog/form-dialog.test.tsx +164 -0
  104. package/src/components/dialogs/form-dialog/form-dialog.tsx +69 -0
  105. package/src/components/dialogs/form-dialog/index.ts +1 -0
  106. package/src/components/dialogs/index.ts +5 -0
  107. package/src/components/drawers/drawer-collapsable-item/drawer-collapsable-item.tsx +1 -3
  108. package/src/components/index.ts +2 -0
  109. package/src/components/inputs/enhanced-autocomplete/enhanced-autocomplete.stories.tsx +109 -0
  110. package/src/components/inputs/enhanced-autocomplete/enhanced-autocomplete.test.tsx +74 -0
  111. package/src/components/inputs/enhanced-autocomplete/enhanced-autocomplete.tsx +64 -0
  112. package/src/components/inputs/enhanced-autocomplete/index.ts +1 -0
  113. package/src/components/inputs/enhanced-text-field/enhanced-text-field.stories.tsx +120 -0
  114. package/src/components/inputs/enhanced-text-field/enhanced-text-field.test.tsx +63 -0
  115. package/src/components/inputs/enhanced-text-field/enhanced-text-field.tsx +101 -0
  116. package/src/components/inputs/enhanced-text-field/index.ts +1 -0
  117. package/src/components/inputs/index.ts +1 -0
  118. package/src/components/inputs/inputs.stories.mdx +2 -0
  119. package/src/components/value-displays/index.ts +2 -1
  120. package/src/components/value-displays/value-base/index.ts +2 -0
  121. package/src/components/value-displays/{value-displays.types.ts → value-base/value-displays.types.ts} +12 -2
  122. package/src/components/value-displays/value-base/value-edit.tsx +59 -0
  123. package/src/components/value-displays/value-boolean/value-boolean.stories.tsx +7 -0
  124. package/src/components/value-displays/value-boolean/value-boolean.test.tsx +81 -2
  125. package/src/components/value-displays/value-boolean/value-boolean.tsx +33 -8
  126. package/src/components/value-displays/value-datetime/value-datetime.stories.tsx +29 -2
  127. package/src/components/value-displays/value-datetime/value-datetime.test.tsx +103 -5
  128. package/src/components/value-displays/value-datetime/value-datetime.tsx +67 -6
  129. package/src/components/value-displays/value-image/value-image.tsx +1 -1
  130. package/src/components/value-displays/value-rating/value-rating.stories.tsx +8 -0
  131. package/src/components/value-displays/value-rating/value-rating.test.tsx +71 -2
  132. package/src/components/value-displays/value-rating/value-rating.tsx +29 -5
  133. package/src/components/value-displays/value-text/value-text.test.tsx +5 -8
  134. package/src/components/value-displays/value-text/value-text.tsx +16 -60
  135. package/src/generators/generators.mock.ts +3 -14
  136. package/src/generators/model-form/model-form.tsx +3 -6
  137. package/src/storybook.tsx +34 -2
  138. package/src/tests/actions.ts +3 -2
  139. package/src/tests/assertions.ts +17 -5
  140. package/src/tests/datatable-placeholder/datatable-placeholder.tsx +2 -4
  141. package/src/tests/mocks/markdown.mock.ts +25 -0
  142. package/src/types/index.d.ts +6 -0
  143. package/dist/cjs/types/generators/generators.model.test.d.ts +0 -1
  144. package/dist/cjs/types/utils/arrays.test.d.ts +0 -1
  145. package/dist/esm/types/generators/generators.model.test.d.ts +0 -1
  146. package/dist/esm/types/utils/arrays.test.d.ts +0 -1
@@ -0,0 +1,150 @@
1
+ import { DialogContentText } from "@mui/material";
2
+ import React from "react";
3
+ import { render, screen } from "~/tests/testing-library";
4
+ import { ConfirmDialog } from "./confirm-dialog";
5
+ import userEvent from "@testing-library/user-event";
6
+
7
+ interface DialogRenderArgs {
8
+ open: boolean;
9
+ disabled?: boolean;
10
+ confirmText?: string;
11
+ cancelText?: string;
12
+ loading?: boolean;
13
+ content?: string | string[];
14
+ }
15
+
16
+ describe("ConfirmDialog", () => {
17
+ const renderComponent = ({
18
+ open,
19
+ disabled,
20
+ confirmText,
21
+ cancelText,
22
+ loading,
23
+ }: DialogRenderArgs) => {
24
+ const onCancel = jest.fn();
25
+ const onConfirm = jest.fn();
26
+
27
+ render(
28
+ <ConfirmDialog
29
+ open={open}
30
+ disabled={disabled}
31
+ loading={loading}
32
+ title="lorem ipsum"
33
+ onCancel={onCancel}
34
+ onConfirm={onConfirm}
35
+ cancelText={cancelText}
36
+ confirmText={confirmText}
37
+ >
38
+ <DialogContentText>This is the content</DialogContentText>
39
+ </ConfirmDialog>,
40
+ );
41
+
42
+ return { onCancel, onConfirm };
43
+ };
44
+
45
+ it("should render the dialog if open is true", () => {
46
+ renderComponent({ open: true });
47
+
48
+ expect(screen.getByRole("dialog")).toBeVisible();
49
+ });
50
+
51
+ it("shouldn't render the dialog if open is false", () => {
52
+ renderComponent({ open: false });
53
+
54
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
55
+ });
56
+
57
+ it("should render the title", () => {
58
+ renderComponent({ open: true });
59
+
60
+ expect(screen.getByText("lorem ipsum")).toBeVisible();
61
+ });
62
+
63
+ it("should render the children content", () => {
64
+ renderComponent({ open: true });
65
+
66
+ expect(screen.getByText(/this is the content/i)).toBeVisible();
67
+ });
68
+
69
+ it("should call onCancel if the close button is clicked", async () => {
70
+ const { onCancel } = renderComponent({ open: true });
71
+
72
+ await userEvent.click(screen.getByRole("button", { name: "close" }));
73
+
74
+ expect(onCancel).toHaveBeenCalledTimes(1);
75
+ });
76
+
77
+ it("should call onCancel if the cancel button is clicked", async () => {
78
+ const { onCancel } = renderComponent({ open: true });
79
+
80
+ await userEvent.click(screen.getByRole("button", { name: /cancel/i }));
81
+
82
+ expect(onCancel).toHaveBeenCalledTimes(1);
83
+ });
84
+
85
+ it("should call onConfirm if the confirm button is clicked", async () => {
86
+ const { onConfirm } = renderComponent({ open: true });
87
+
88
+ await userEvent.click(screen.getByRole("button", { name: /confirm/i }));
89
+
90
+ expect(onConfirm).toHaveBeenCalledTimes(1);
91
+ });
92
+
93
+ describe("disabled", () => {
94
+ it("should have the close button as disabled", () => {
95
+ renderComponent({ open: true, disabled: true });
96
+
97
+ expect(screen.getByRole("button", { name: "close" })).toBeDisabled();
98
+ });
99
+
100
+ it("should have the Cancel button as disabled", () => {
101
+ renderComponent({ open: true, disabled: true });
102
+
103
+ expect(screen.getByRole("button", { name: /cancel/i })).toBeDisabled();
104
+ });
105
+
106
+ it("should have the confirm button as disabled", () => {
107
+ renderComponent({ open: true, disabled: true });
108
+
109
+ expect(screen.getByRole("button", { name: /confirm/i })).toBeDisabled();
110
+ });
111
+ });
112
+
113
+ it("should be able to change the cancel button text", () => {
114
+ renderComponent({ open: true, cancelText: "updated cancel" });
115
+
116
+ expect(screen.getByRole("button", { name: /updated cancel/i })).toBeVisible();
117
+ });
118
+
119
+ it("should be able to change the confirm button text", () => {
120
+ renderComponent({ open: true, confirmText: "updated confirm" });
121
+
122
+ expect(screen.getByRole("button", { name: /updated confirm/i })).toBeVisible();
123
+ });
124
+
125
+ describe("loading", () => {
126
+ it("should render a loading indicator if is true", async () => {
127
+ renderComponent({ open: true, loading: true });
128
+
129
+ expect(screen.getByRole("progressbar")).toBeVisible();
130
+ });
131
+
132
+ it("should have the close button as disabled", () => {
133
+ renderComponent({ open: true, loading: true });
134
+
135
+ expect(screen.getByRole("button", { name: "close" })).toBeDisabled();
136
+ });
137
+
138
+ it("should have the Cancel button as disabled", () => {
139
+ renderComponent({ open: true, loading: true });
140
+
141
+ expect(screen.getByRole("button", { name: /cancel/i })).toBeDisabled();
142
+ });
143
+
144
+ it("should have the confirm button as disabled", () => {
145
+ renderComponent({ open: true, loading: true });
146
+
147
+ expect(screen.getByRole("button", { name: /confirm/i })).toBeDisabled();
148
+ });
149
+ });
150
+ });
@@ -0,0 +1,51 @@
1
+ import React from "react";
2
+ import { BootstrapDialog } from "../bootstrap-dialog";
3
+ import { BootstrapDialogDialogProps } from "../dialog.types";
4
+
5
+ type OmitBaseDialogProps =
6
+ | "cancelable"
7
+ | "acceptable"
8
+ | "onAccept"
9
+ | "onCancel"
10
+ | "onClose"
11
+ | "actions"
12
+ | "callCloseWhenCancel"
13
+ | "component"
14
+ | "acceptType";
15
+ export interface ConfirmDialogProps extends Omit<BootstrapDialogDialogProps, OmitBaseDialogProps> {
16
+ confirmText?: string;
17
+ canceText?: string;
18
+ onCancel: () => void;
19
+ onConfirm: () => void;
20
+ }
21
+
22
+ export const ConfirmDialog = ({
23
+ open,
24
+ title,
25
+ loading,
26
+ disabled,
27
+ confirmText = "Confirm",
28
+ cancelText = "Cancel",
29
+ children,
30
+ onConfirm,
31
+ onCancel,
32
+ }: ConfirmDialogProps) => {
33
+ return (
34
+ <BootstrapDialog
35
+ title={title}
36
+ loading={loading}
37
+ disabled={loading || disabled}
38
+ open={open}
39
+ onClose={onCancel}
40
+ acceptable
41
+ cancelable
42
+ callCloseWhenCancel={false}
43
+ acceptText={confirmText}
44
+ cancelText={cancelText}
45
+ onCancel={onCancel}
46
+ onAccept={onConfirm}
47
+ >
48
+ {children}
49
+ </BootstrapDialog>
50
+ );
51
+ };
@@ -0,0 +1 @@
1
+ export * from "./confirm-dialog";
@@ -0,0 +1 @@
1
+ export * from "./use-dialog";
@@ -0,0 +1,10 @@
1
+ import { useState } from "react";
2
+
3
+ export const useDialog = (intialOpen = false) => {
4
+ const [isOpen, setIsOpen] = useState(intialOpen);
5
+
6
+ const open = () => setIsOpen(true);
7
+ const close = () => setIsOpen(false);
8
+
9
+ return { isOpen, open, close, setIsOpen };
10
+ };
@@ -0,0 +1,27 @@
1
+ import { PropsWithChildren } from "react";
2
+
3
+ export interface DialogAction {
4
+ id: string;
5
+ text: string;
6
+ type?: "button" | "submit";
7
+ color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning";
8
+ onClick?: () => void;
9
+ }
10
+ export type BootstrapDialogDialogProps = PropsWithChildren<{
11
+ open: boolean;
12
+ title: string;
13
+ loading?: boolean;
14
+ disabled?: boolean;
15
+ cancelable?: boolean;
16
+ acceptable?: boolean;
17
+ callCloseWhenCancel?: boolean;
18
+ actions?: DialogAction[];
19
+ cancelText?: string;
20
+ acceptText?: string;
21
+ acceptType?: "button" | "submit";
22
+ onClose: () => void;
23
+ onCancel?: () => void;
24
+ onAccept?: () => void;
25
+ component?: React.ElementType;
26
+ componentProps?: any;
27
+ }>;
@@ -0,0 +1,12 @@
1
+ import { Meta } from '@storybook/addon-docs';
2
+ import LinkTo from '@storybook/addon-links/react';
3
+
4
+ <Meta title="Components/Drawers/Introduction" />
5
+
6
+ # Drawers
7
+
8
+ <ul>
9
+ <li><LinkTo kind="Components/Dialogs/ConfirmDialog">ConfirmDialog</LinkTo></li>
10
+ <li><LinkTo kind="Components/Dialogs/FormDialog">FormDialog</LinkTo></li>
11
+ <li><LinkTo kind="Components/Dialogs/BootstrapDialog">BootstrapDialog</LinkTo></li>
12
+ </ul>
@@ -0,0 +1,52 @@
1
+ import { Grid, TextField } from "@mui/material";
2
+ import { ComponentMeta, ComponentStory } from "@storybook/react";
3
+ import React from "react";
4
+ import { StoryDialogManager } from "~/storybook";
5
+ import { FormDialog } from "./form-dialog";
6
+
7
+ export default {
8
+ title: "Components/Dialogs/FormDialog",
9
+ component: FormDialog,
10
+ parameters: {
11
+ layout: "centered",
12
+ },
13
+ } as ComponentMeta<typeof FormDialog>;
14
+
15
+ const Template: ComponentStory<typeof FormDialog> = (args) => (
16
+ <StoryDialogManager component={FormDialog} args={args} />
17
+ );
18
+
19
+ export const Default = Template.bind({});
20
+ Default.args = {
21
+ open: true,
22
+ title: "Lorem ipsum",
23
+ children: (
24
+ <Grid container spacing={2}>
25
+ <Grid item xs={12}>
26
+ <TextField name="message" label="Message" fullWidth required variant="outlined" />
27
+ </Grid>
28
+ <Grid item xs={12}>
29
+ <TextField name="amount" label="Amount" fullWidth required variant="outlined" />
30
+ </Grid>
31
+ </Grid>
32
+ ),
33
+ };
34
+
35
+ export const Loading = Template.bind({});
36
+ Loading.args = {
37
+ ...Default.args,
38
+ loading: true,
39
+ };
40
+
41
+ export const Disabled = Template.bind({});
42
+ Disabled.args = {
43
+ ...Default.args,
44
+ disabled: true,
45
+ };
46
+
47
+ export const CustomButtonText = Template.bind({});
48
+ CustomButtonText.args = {
49
+ ...Default.args,
50
+ submitText: "Create token",
51
+ cancelText: "Don't create a token",
52
+ };
@@ -0,0 +1,164 @@
1
+ import { Grid, TextField } from "@mui/material";
2
+ import React from "react";
3
+ import { render, screen } from "~/tests/testing-library";
4
+ import { FormDialog } from "./form-dialog";
5
+ import userEvent from "@testing-library/user-event";
6
+
7
+ interface DialogRenderArgs {
8
+ open: boolean;
9
+ disabled?: boolean;
10
+ submitText?: string;
11
+ cancelText?: string;
12
+ loading?: boolean;
13
+ content?: string | string[];
14
+ }
15
+
16
+ describe("FormDialog", () => {
17
+ const renderComponent = ({
18
+ open,
19
+ disabled,
20
+ submitText,
21
+ cancelText,
22
+ loading,
23
+ }: DialogRenderArgs) => {
24
+ const onCancel = jest.fn();
25
+ const onSubmit = jest.fn();
26
+
27
+ render(
28
+ <FormDialog
29
+ open={open}
30
+ disabled={disabled}
31
+ loading={loading}
32
+ title="lorem ipsum"
33
+ onCancel={onCancel}
34
+ onSubmit={onSubmit}
35
+ cancelText={cancelText}
36
+ submitText={submitText}
37
+ >
38
+ <Grid container spacing={2}>
39
+ <Grid item xs={12}>
40
+ <TextField name="message" label="Message" fullWidth required variant="outlined" />
41
+ </Grid>
42
+ <Grid item xs={12}>
43
+ <TextField name="amount" label="Amount" fullWidth required variant="outlined" />
44
+ </Grid>
45
+ </Grid>
46
+ </FormDialog>,
47
+ );
48
+
49
+ return { onCancel, onSubmit };
50
+ };
51
+
52
+ it("should render the dialog if open is true", () => {
53
+ renderComponent({ open: true });
54
+
55
+ expect(screen.getByRole("dialog")).toBeVisible();
56
+ });
57
+
58
+ it("shouldn't render the dialog if open is false", () => {
59
+ renderComponent({ open: false });
60
+
61
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
62
+ });
63
+
64
+ it("should render the title", () => {
65
+ renderComponent({ open: true });
66
+
67
+ expect(screen.getByText("lorem ipsum")).toBeVisible();
68
+ });
69
+
70
+ it("should render the form", () => {
71
+ renderComponent({ open: true });
72
+
73
+ expect(screen.getByRole("textbox", { name: /message/i })).toBeVisible();
74
+ expect(screen.getByRole("textbox", { name: /amount/i })).toBeVisible();
75
+ });
76
+
77
+ it("should call onCancel if the close button is clicked", async () => {
78
+ const { onCancel } = renderComponent({ open: true });
79
+
80
+ await userEvent.click(screen.getByRole("button", { name: "close" }));
81
+
82
+ expect(onCancel).toHaveBeenCalledTimes(1);
83
+ });
84
+
85
+ it("should call onCancel if the cancel button is clicked", async () => {
86
+ const { onCancel } = renderComponent({ open: true });
87
+
88
+ await userEvent.click(screen.getByRole("button", { name: /cancel/i }));
89
+
90
+ expect(onCancel).toHaveBeenCalledTimes(1);
91
+ });
92
+
93
+ it("should call onSubmit if the form is submited", async () => {
94
+ const { onSubmit } = renderComponent({ open: true });
95
+
96
+ await userEvent.type(screen.getByRole("textbox", { name: /message/i }), "this is the message");
97
+ await userEvent.type(screen.getByRole("textbox", { name: /amount/i }), "100");
98
+ await userEvent.click(screen.getByRole("button", { name: /submit/i }));
99
+
100
+ expect(onSubmit).toHaveBeenCalledTimes(1);
101
+ expect(onSubmit).toHaveBeenCalledWith({
102
+ message: "this is the message",
103
+ amount: "100",
104
+ });
105
+ });
106
+
107
+ describe("disabled", () => {
108
+ it("should have the close button as disabled", () => {
109
+ renderComponent({ open: true, disabled: true });
110
+
111
+ expect(screen.getByRole("button", { name: "close" })).toBeDisabled();
112
+ });
113
+
114
+ it("should have the Cancel button as disabled", () => {
115
+ renderComponent({ open: true, disabled: true });
116
+
117
+ expect(screen.getByRole("button", { name: /cancel/i })).toBeDisabled();
118
+ });
119
+
120
+ it("should have the submit button as disabled", () => {
121
+ renderComponent({ open: true, disabled: true });
122
+
123
+ expect(screen.getByRole("button", { name: /submit/i })).toBeDisabled();
124
+ });
125
+ });
126
+
127
+ it("should be able to change the cancel button text", () => {
128
+ renderComponent({ open: true, cancelText: "updated cancel" });
129
+
130
+ expect(screen.getByRole("button", { name: /updated cancel/i })).toBeVisible();
131
+ });
132
+
133
+ it("should be able to change the submit button text", () => {
134
+ renderComponent({ open: true, submitText: "updated submit" });
135
+
136
+ expect(screen.getByRole("button", { name: /updated submit/i })).toBeVisible();
137
+ });
138
+
139
+ describe("loading", () => {
140
+ it("should render a loading indicator if is true", async () => {
141
+ renderComponent({ open: true, loading: true });
142
+
143
+ expect(screen.getByRole("progressbar")).toBeVisible();
144
+ });
145
+
146
+ it("should have the close button as disabled", () => {
147
+ renderComponent({ open: true, loading: true });
148
+
149
+ expect(screen.getByRole("button", { name: "close" })).toBeDisabled();
150
+ });
151
+
152
+ it("should have the Cancel button as disabled", () => {
153
+ renderComponent({ open: true, loading: true });
154
+
155
+ expect(screen.getByRole("button", { name: /cancel/i })).toBeDisabled();
156
+ });
157
+
158
+ it("should have the submit button as disabled", () => {
159
+ renderComponent({ open: true, loading: true });
160
+
161
+ expect(screen.getByRole("button", { name: /submit/i })).toBeDisabled();
162
+ });
163
+ });
164
+ });
@@ -0,0 +1,69 @@
1
+ import { BootstrapDialog } from "../bootstrap-dialog";
2
+ import { FormEvent } from "react";
3
+ import React from "react";
4
+ import { BootstrapDialogDialogProps } from "../dialog.types";
5
+
6
+ type OmitBaseDialogProps =
7
+ | "cancelable"
8
+ | "acceptable"
9
+ | "onAccept"
10
+ | "onCancel"
11
+ | "onClose"
12
+ | "actions"
13
+ | "callCloseWhenCancel"
14
+ | "component"
15
+ | "acceptType";
16
+ export interface FormDialogProps<T> extends Omit<BootstrapDialogDialogProps, OmitBaseDialogProps> {
17
+ submitText?: string;
18
+ canceText?: string;
19
+ onCancel: () => void;
20
+ onSubmit: (data: T) => void;
21
+ }
22
+
23
+ export const FormDialog = <T,>({
24
+ open,
25
+ title,
26
+ loading,
27
+ disabled,
28
+ submitText = "Submit",
29
+ cancelText = "Cancel",
30
+ children,
31
+ onSubmit,
32
+ onCancel,
33
+ }: FormDialogProps<T>) => {
34
+ const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
35
+ e.preventDefault();
36
+
37
+ const data = new FormData(e.currentTarget);
38
+ const rawData: Record<string, any> = {};
39
+
40
+ data.forEach((value, key) => {
41
+ rawData[key] = value;
42
+ });
43
+
44
+ onSubmit(rawData as T);
45
+ };
46
+
47
+ return (
48
+ <BootstrapDialog
49
+ component="form"
50
+ componentProps={{
51
+ onSubmit: handleSubmit,
52
+ }}
53
+ title={title}
54
+ loading={loading}
55
+ disabled={loading || disabled}
56
+ open={open}
57
+ onClose={onCancel}
58
+ callCloseWhenCancel={false}
59
+ cancelable
60
+ acceptable
61
+ cancelText={cancelText}
62
+ onCancel={onCancel}
63
+ acceptText={submitText}
64
+ acceptType="submit"
65
+ >
66
+ {children}
67
+ </BootstrapDialog>
68
+ );
69
+ };
@@ -0,0 +1 @@
1
+ export * from "./form-dialog";
@@ -0,0 +1,5 @@
1
+ export * from "./confirm-dialog";
2
+ export * from "./form-dialog";
3
+ export * from "./bootstrap-dialog";
4
+ export * from "./dialog-hooks";
5
+ export * from "./dialog.types";
@@ -2,14 +2,12 @@ import {
2
2
  ListItem,
3
3
  ListItemButton,
4
4
  ListItemIcon,
5
- ListItemAvatar,
6
- Avatar,
7
5
  ListItemText,
8
6
  Collapse,
9
7
  List,
10
8
  } from "@mui/material";
11
9
  import React, { ReactElement, useState } from "react";
12
- import { NavItem, NavItemLink } from "../drawer/drawer.types";
10
+ import { NavItemLink } from "../drawer/drawer.types";
13
11
  import ExpandLess from "@mui/icons-material/ExpandLess";
14
12
  import ExpandMore from "@mui/icons-material/ExpandMore";
15
13
  import { DrawerItem } from "../drawer-item";
@@ -8,3 +8,5 @@ export * from "./inputs";
8
8
  export * from "./navigation";
9
9
  export * from "./tables";
10
10
  export * from "./placeholders";
11
+ export * from "./alerts";
12
+ export * from "./dialogs";
@@ -0,0 +1,109 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { createTemplate, withContainer } from "../../../storybook";
3
+ import { EnhancedAutocomplete } from "./enhanced-autocomplete";
4
+ import { faker } from "@faker-js/faker";
5
+ import { Box, useTheme } from "@mui/material";
6
+ import React from "react";
7
+
8
+ export default {
9
+ title: "Components/Inputs/EnhancedAutocomplete",
10
+ component: EnhancedAutocomplete,
11
+ decorators: [withContainer({ width: 300 })],
12
+ parameters: {
13
+ layout: "centered",
14
+ },
15
+ } as ComponentMeta<typeof EnhancedAutocomplete>;
16
+
17
+ const options: string[] = faker.definitions.vehicle?.model || [];
18
+
19
+ const Template = createTemplate(EnhancedAutocomplete);
20
+
21
+ export const Default = Template.bind({});
22
+ Default.args = {
23
+ label: "Car model",
24
+ options,
25
+ };
26
+
27
+ export const HelperText = Template.bind({});
28
+ HelperText.args = {
29
+ ...Default.args,
30
+ helperText: "This is a helper text",
31
+ };
32
+
33
+ export const Loading = Template.bind({});
34
+ Loading.args = {
35
+ ...Default.args,
36
+ loading: true,
37
+ };
38
+
39
+ export const LoadingWithValue = Template.bind({});
40
+ LoadingWithValue.args = {
41
+ ...Default.args,
42
+ loading: true,
43
+ value: options[0],
44
+ };
45
+
46
+ export const Fetching = Template.bind({});
47
+ Fetching.args = {
48
+ ...Default.args,
49
+ fetching: true,
50
+ };
51
+
52
+ export const SizeSmall = Template.bind({});
53
+ SizeSmall.args = {
54
+ ...Default.args,
55
+ size: "small",
56
+ };
57
+
58
+ export const SizeSmallLoading = Template.bind({});
59
+ SizeSmallLoading.args = {
60
+ ...Default.args,
61
+ size: "small",
62
+ value: options[0],
63
+ loading: true,
64
+ };
65
+
66
+ export const SizeSmallFetching = Template.bind({});
67
+ SizeSmallFetching.args = {
68
+ ...Default.args,
69
+ size: "small",
70
+ fetching: true,
71
+ value: options[0],
72
+ };
73
+
74
+ type WithBackgroundProps = {
75
+ bgcolor: "primary" | "secondary";
76
+ loading: boolean;
77
+ fetching: boolean;
78
+ };
79
+ export const WithBackground = ({
80
+ bgcolor: bgcolorProp,
81
+ loading,
82
+ fetching,
83
+ }: WithBackgroundProps) => {
84
+ const { palette } = useTheme();
85
+ const BackgroundColors: Record<"primary" | "secondary", string> = {
86
+ primary: palette.primary.main,
87
+ secondary: palette.secondary.main,
88
+ };
89
+ const bgcolor = BackgroundColors[bgcolorProp];
90
+ const selectColor = palette.getContrastText(bgcolor);
91
+
92
+ return (
93
+ <Box bgcolor={bgcolor} padding={3}>
94
+ <EnhancedAutocomplete
95
+ label="Car model"
96
+ options={options}
97
+ color={selectColor}
98
+ loading={loading}
99
+ fetching={fetching}
100
+ />
101
+ </Box>
102
+ );
103
+ };
104
+
105
+ WithBackground.args = {
106
+ bgcolor: "secondary",
107
+ loading: true,
108
+ fetching: true,
109
+ };