@onewelcome/react-lib-components 0.1.0-alpha → 0.1.3-alpha

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 (240) hide show
  1. package/README.md +16 -1
  2. package/dist/Breadcrumbs/Breadcrumbs.d.ts +3 -3
  3. package/dist/Button/BaseButton.d.ts +3 -4
  4. package/dist/Button/Button.d.ts +3 -4
  5. package/dist/Button/IconButton.d.ts +4 -5
  6. package/dist/ContextMenu/ContextMenu.d.ts +3 -3
  7. package/dist/Form/Checkbox/Checkbox.d.ts +5 -5
  8. package/dist/Form/Fieldset/Fieldset.d.ts +9 -7
  9. package/dist/Form/FormControl/FormControl.d.ts +6 -5
  10. package/dist/Form/FormGroup/FormGroup.d.ts +4 -4
  11. package/dist/Form/FormHelperText/FormHelperText.d.ts +4 -5
  12. package/dist/Form/FormSelectorWrapper/FormSelectorWrapper.d.ts +8 -12
  13. package/dist/Form/Input/Input.d.ts +7 -6
  14. package/dist/Form/Label/Label.d.ts +4 -5
  15. package/dist/Form/Radio/Radio.d.ts +5 -5
  16. package/dist/Form/Select/Option.d.ts +3 -4
  17. package/dist/Form/Select/Select.d.ts +4 -4
  18. package/dist/Form/Textarea/Textarea.d.ts +9 -5
  19. package/dist/Form/Toggle/Toggle.d.ts +3 -3
  20. package/dist/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.d.ts +4 -3
  21. package/dist/Form/Wrapper/InputWrapper/InputWrapper.d.ts +5 -5
  22. package/dist/Form/Wrapper/RadioWrapper/RadioWrapper.d.ts +4 -4
  23. package/dist/Form/Wrapper/SelectWrapper/SelectWrapper.d.ts +8 -4
  24. package/dist/Form/Wrapper/TextareaWrapper/TextareaWrapper.d.ts +3 -3
  25. package/dist/Form/Wrapper/Wrapper/Wrapper.d.ts +6 -6
  26. package/dist/Form/form.interfaces.d.ts +4 -3
  27. package/dist/Icon/Icon.d.ts +4 -4
  28. package/dist/Link/Link.d.ts +3 -5
  29. package/dist/Notifications/BaseModal/BaseModal.d.ts +17 -0
  30. package/dist/Notifications/BaseModal/BaseModalActions/BaseModalActions.d.ts +5 -0
  31. package/dist/Notifications/BaseModal/BaseModalContent/BaseModalContent.d.ts +8 -0
  32. package/dist/{BaseModal → Notifications/BaseModal}/BaseModalContext.d.ts +0 -0
  33. package/dist/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.d.ts +8 -0
  34. package/dist/Notifications/Dialog/Dialog.d.ts +19 -0
  35. package/dist/Notifications/Dialog/DialogActions/DialogActions.d.ts +6 -0
  36. package/dist/Notifications/Dialog/DialogTitle/DialogTitle.d.ts +6 -0
  37. package/dist/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.d.ts +13 -0
  38. package/dist/Notifications/DiscardChangesModal/DiscardChangesModal.d.ts +13 -0
  39. package/dist/{Modal → Notifications/Modal}/Modal.d.ts +0 -0
  40. package/dist/{Modal → Notifications/Modal}/ModalActions/ModalActions.d.ts +0 -0
  41. package/dist/{Modal → Notifications/Modal}/ModalContent/ModalContent.d.ts +0 -0
  42. package/dist/{Modal → Notifications/Modal}/ModalHeader/ModalHeader.d.ts +0 -0
  43. package/dist/{Snackbar → Notifications/Snackbar}/SnackbarContainer/SnackbarContainer.d.ts +0 -0
  44. package/dist/{Snackbar → Notifications/Snackbar}/SnackbarItem/SnackbarItem.d.ts +0 -0
  45. package/dist/{Snackbar → Notifications/Snackbar}/SnackbarProvider/SnackbarProvider.d.ts +1 -1
  46. package/dist/{Snackbar → Notifications/Snackbar}/SnackbarProvider/SnackbarStateProvider.d.ts +0 -0
  47. package/dist/{Snackbar → Notifications/Snackbar}/interfaces.d.ts +0 -0
  48. package/dist/{Snackbar → Notifications/Snackbar}/useSnackbar.d.ts +0 -0
  49. package/dist/Pagination/Pagination.d.ts +19 -0
  50. package/dist/Popover/Popover.d.ts +3 -3
  51. package/dist/Tabs/Tab.d.ts +11 -0
  52. package/dist/Tabs/TabButton.d.ts +10 -0
  53. package/dist/Tabs/TabPanel.d.ts +8 -0
  54. package/dist/Tabs/Tabs.d.ts +9 -0
  55. package/dist/TextEllipsis/TextEllipsis.d.ts +6 -0
  56. package/dist/Tiles/Tile.d.ts +6 -7
  57. package/dist/Tiles/Tiles.d.ts +3 -3
  58. package/dist/Tooltip/Tooltip.d.ts +3 -3
  59. package/dist/Typography/Typography.d.ts +6 -4
  60. package/dist/Wizard/BaseWizardSteps/BaseWizardSteps.d.ts +3 -3
  61. package/dist/Wizard/WizardSteps/WizardSteps.d.ts +3 -3
  62. package/dist/_BaseStyling_/BaseStyling.d.ts +9 -0
  63. package/dist/hooks/useRepeater.d.ts +10 -0
  64. package/dist/hooks/useSpacing.d.ts +2 -2
  65. package/dist/hooks/useWrapper.d.ts +1 -1
  66. package/dist/index.d.ts +12 -7
  67. package/dist/interfaces.d.ts +2 -11
  68. package/dist/react-lib-components.cjs.development.js +1861 -1287
  69. package/dist/react-lib-components.cjs.development.js.map +1 -1
  70. package/dist/react-lib-components.cjs.production.min.js +1 -1
  71. package/dist/react-lib-components.cjs.production.min.js.map +1 -1
  72. package/dist/react-lib-components.esm.js +1858 -1289
  73. package/dist/react-lib-components.esm.js.map +1 -1
  74. package/dist/util/helper.d.ts +6 -1
  75. package/package.json +30 -24
  76. package/src/Breadcrumbs/Breadcrumbs.tsx +39 -37
  77. package/src/Button/BaseButton.test.tsx +65 -19
  78. package/src/Button/BaseButton.tsx +2 -3
  79. package/src/Button/Button.test.tsx +63 -17
  80. package/src/Button/Button.tsx +15 -4
  81. package/src/Button/IconButton.test.tsx +57 -22
  82. package/src/Button/IconButton.tsx +21 -12
  83. package/src/ContextMenu/ContextMenu.test.tsx +27 -1
  84. package/src/ContextMenu/ContextMenu.tsx +70 -65
  85. package/src/Form/Checkbox/Checkbox.module.scss +4 -0
  86. package/src/Form/Checkbox/Checkbox.test.tsx +28 -2
  87. package/src/Form/Checkbox/Checkbox.tsx +132 -117
  88. package/src/Form/Fieldset/Fieldset.module.scss +11 -1
  89. package/src/Form/Fieldset/Fieldset.test.tsx +30 -4
  90. package/src/Form/Fieldset/Fieldset.tsx +101 -43
  91. package/src/Form/FormControl/FormControl.test.tsx +27 -1
  92. package/src/Form/FormControl/FormControl.tsx +37 -37
  93. package/src/Form/FormGroup/FormGroup.test.tsx +27 -1
  94. package/src/Form/FormGroup/FormGroup.tsx +64 -58
  95. package/src/Form/FormHelperText/FormHelperText.test.tsx +27 -1
  96. package/src/Form/FormHelperText/FormHelperText.tsx +20 -16
  97. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.test.tsx +78 -0
  98. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.tsx +61 -55
  99. package/src/Form/Input/Input.module.scss +34 -15
  100. package/src/Form/Input/Input.test.tsx +27 -1
  101. package/src/Form/Input/Input.tsx +88 -47
  102. package/src/Form/Label/Label.test.tsx +27 -1
  103. package/src/Form/Label/Label.tsx +18 -14
  104. package/src/Form/Radio/Radio.module.scss +4 -0
  105. package/src/Form/Radio/Radio.test.tsx +28 -2
  106. package/src/Form/Radio/Radio.tsx +98 -80
  107. package/src/Form/Select/Option.test.tsx +27 -1
  108. package/src/Form/Select/Option.tsx +49 -42
  109. package/src/Form/Select/Select.module.scss +5 -1
  110. package/src/Form/Select/Select.test.tsx +224 -30
  111. package/src/Form/Select/Select.tsx +248 -182
  112. package/src/Form/Textarea/Textarea.module.scss +2 -1
  113. package/src/Form/Textarea/Textarea.test.tsx +28 -2
  114. package/src/Form/Textarea/Textarea.tsx +44 -29
  115. package/src/Form/Toggle/Toggle.module.scss +9 -0
  116. package/src/Form/Toggle/Toggle.test.tsx +27 -1
  117. package/src/Form/Toggle/Toggle.tsx +25 -12
  118. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.test.tsx +28 -2
  119. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.tsx +45 -48
  120. package/src/Form/Wrapper/InputWrapper/InputWrapper.module.scss +17 -1
  121. package/src/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +89 -1
  122. package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +134 -74
  123. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.test.tsx +1 -1
  124. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.tsx +64 -59
  125. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.module.scss +1 -1
  126. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.test.tsx +43 -1
  127. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.tsx +55 -44
  128. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.module.scss +5 -7
  129. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.test.tsx +43 -1
  130. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.tsx +100 -85
  131. package/src/Form/Wrapper/Wrapper/Wrapper.module.scss +1 -1
  132. package/src/Form/Wrapper/Wrapper/Wrapper.test.tsx +27 -1
  133. package/src/Form/Wrapper/Wrapper/Wrapper.tsx +76 -71
  134. package/src/Form/form.interfaces.ts +4 -3
  135. package/src/Icon/Icon.module.scss +4 -0
  136. package/src/Icon/Icon.test.tsx +30 -2
  137. package/src/Icon/Icon.tsx +5 -5
  138. package/src/Link/Link.test.tsx +27 -1
  139. package/src/Link/Link.tsx +4 -6
  140. package/src/{BaseModal → Notifications/BaseModal}/BaseModal.module.scss +0 -0
  141. package/src/{BaseModal → Notifications/BaseModal}/BaseModal.test.tsx +35 -16
  142. package/src/Notifications/BaseModal/BaseModal.tsx +105 -0
  143. package/src/{BaseModal → Notifications/BaseModal}/BaseModalActions/BaseModalActions.module.scss +0 -0
  144. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.test.tsx +42 -0
  145. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.tsx +16 -0
  146. package/src/{BaseModal → Notifications/BaseModal}/BaseModalContent/BaseModalContent.module.scss +0 -0
  147. package/src/{BaseModal → Notifications/BaseModal}/BaseModalContent/BaseModalContent.test.tsx +27 -1
  148. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.tsx +36 -0
  149. package/src/{BaseModal → Notifications/BaseModal}/BaseModalContext.ts +0 -0
  150. package/src/{BaseModal → Notifications/BaseModal}/BaseModalHeader/BaseModalHeader.module.scss +0 -0
  151. package/src/{BaseModal → Notifications/BaseModal}/BaseModalHeader/BaseModalHeader.test.tsx +29 -1
  152. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.tsx +30 -0
  153. package/src/{Dialog → Notifications/Dialog}/Dialog.module.scss +0 -0
  154. package/src/{Dialog → Notifications/Dialog}/Dialog.test.tsx +52 -17
  155. package/src/Notifications/Dialog/Dialog.tsx +113 -0
  156. package/src/{Dialog → Notifications/Dialog}/DialogActions/DialogActions.module.scss +0 -0
  157. package/src/Notifications/Dialog/DialogActions/DialogActions.test.tsx +51 -0
  158. package/src/Notifications/Dialog/DialogActions/DialogActions.tsx +24 -0
  159. package/src/{Dialog → Notifications/Dialog}/DialogTitle/DialogTitle.module.scss +0 -0
  160. package/src/Notifications/Dialog/DialogTitle/DialogTitle.test.tsx +44 -0
  161. package/src/Notifications/Dialog/DialogTitle/DialogTitle.tsx +20 -0
  162. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.test.tsx +95 -0
  163. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.tsx +55 -0
  164. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.test.tsx +162 -0
  165. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.tsx +61 -0
  166. package/src/{Modal → Notifications/Modal}/Modal.test.tsx +0 -0
  167. package/src/{Modal → Notifications/Modal}/Modal.tsx +0 -0
  168. package/src/{Modal → Notifications/Modal}/ModalActions/ModalActions.tsx +0 -0
  169. package/src/{Modal → Notifications/Modal}/ModalContent/ModalContent.tsx +0 -0
  170. package/src/{Modal → Notifications/Modal}/ModalHeader/ModalHeader.tsx +0 -0
  171. package/src/{Snackbar → Notifications/Snackbar}/SnackbarContainer/SnackbarContainer.module.scss +0 -0
  172. package/src/{Snackbar → Notifications/Snackbar}/SnackbarContainer/SnackbarContainer.test.tsx +0 -0
  173. package/src/{Snackbar → Notifications/Snackbar}/SnackbarContainer/SnackbarContainer.tsx +0 -0
  174. package/src/{Snackbar → Notifications/Snackbar}/SnackbarItem/SnackbarItem.module.scss +1 -1
  175. package/src/{Snackbar → Notifications/Snackbar}/SnackbarItem/SnackbarItem.test.tsx +0 -0
  176. package/src/{Snackbar → Notifications/Snackbar}/SnackbarItem/SnackbarItem.tsx +6 -7
  177. package/src/{Snackbar → Notifications/Snackbar}/SnackbarProvider/SnackbarProvider.test.tsx +0 -0
  178. package/src/{Snackbar → Notifications/Snackbar}/SnackbarProvider/SnackbarProvider.tsx +2 -2
  179. package/src/{Snackbar → Notifications/Snackbar}/SnackbarProvider/SnackbarStateProvider.tsx +0 -0
  180. package/src/{Snackbar → Notifications/Snackbar}/interfaces.ts +0 -0
  181. package/src/{Snackbar → Notifications/Snackbar}/useSnackbar.ts +0 -0
  182. package/src/Pagination/Pagination.module.scss +120 -0
  183. package/src/Pagination/Pagination.test.tsx +176 -0
  184. package/src/Pagination/Pagination.tsx +205 -0
  185. package/src/Popover/Popover.test.tsx +3 -3
  186. package/src/Popover/Popover.tsx +3 -3
  187. package/src/Tabs/Tab.test.tsx +71 -0
  188. package/src/Tabs/Tab.tsx +17 -0
  189. package/src/Tabs/TabButton.module.scss +36 -0
  190. package/src/Tabs/TabButton.test.tsx +77 -0
  191. package/src/Tabs/TabButton.tsx +58 -0
  192. package/src/Tabs/TabPanel.module.scss +7 -0
  193. package/src/Tabs/TabPanel.test.tsx +76 -0
  194. package/src/Tabs/TabPanel.tsx +27 -0
  195. package/src/Tabs/Tabs.module.scss +41 -0
  196. package/src/Tabs/Tabs.test.tsx +268 -0
  197. package/src/Tabs/Tabs.tsx +149 -0
  198. package/src/TextEllipsis/TextEllipsis.module.scss +18 -0
  199. package/src/TextEllipsis/TextEllipsis.test.tsx +80 -0
  200. package/src/TextEllipsis/TextEllipsis.tsx +55 -0
  201. package/src/Tiles/Tile.module.scss +1 -1
  202. package/src/Tiles/Tile.test.tsx +48 -12
  203. package/src/Tiles/Tile.tsx +68 -34
  204. package/src/Tiles/Tiles.test.tsx +38 -10
  205. package/src/Tiles/Tiles.tsx +42 -39
  206. package/src/Tooltip/Tooltip.test.tsx +27 -1
  207. package/src/Tooltip/Tooltip.tsx +104 -92
  208. package/src/Typography/Typography.test.tsx +27 -1
  209. package/src/Typography/Typography.tsx +66 -68
  210. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +67 -62
  211. package/src/Wizard/Wizard.tsx +2 -2
  212. package/src/Wizard/WizardActions/WizardActions.tsx +3 -3
  213. package/src/Wizard/WizardSteps/WizardSteps.tsx +24 -21
  214. package/src/_BaseStyling_/BaseStyling.tsx +19 -1
  215. package/src/hooks/usePosition.test.tsx +3 -3
  216. package/src/hooks/useRepeater.test.tsx +139 -0
  217. package/src/hooks/useRepeater.ts +34 -0
  218. package/src/hooks/useSpacing.ts +1 -1
  219. package/src/hooks/useWrapper.ts +7 -2
  220. package/src/index.ts +20 -8
  221. package/src/interfaces.ts +2 -12
  222. package/src/util/helper.test.tsx +38 -1
  223. package/src/util/helper.tsx +21 -0
  224. package/dist/BaseModal/BaseModal.d.ts +0 -16
  225. package/dist/BaseModal/BaseModalActions/BaseModalActions.d.ts +0 -5
  226. package/dist/BaseModal/BaseModalContent/BaseModalContent.d.ts +0 -8
  227. package/dist/BaseModal/BaseModalHeader/BaseModalHeader.d.ts +0 -8
  228. package/dist/Dialog/Dialog.d.ts +0 -18
  229. package/dist/Dialog/DialogActions/DialogActions.d.ts +0 -6
  230. package/dist/Dialog/DialogTitle/DialogTitle.d.ts +0 -6
  231. package/src/BaseModal/BaseModal.tsx +0 -113
  232. package/src/BaseModal/BaseModalActions/BaseModalActions.test.tsx +0 -17
  233. package/src/BaseModal/BaseModalActions/BaseModalActions.tsx +0 -14
  234. package/src/BaseModal/BaseModalContent/BaseModalContent.tsx +0 -35
  235. package/src/BaseModal/BaseModalHeader/BaseModalHeader.tsx +0 -28
  236. package/src/Dialog/Dialog.tsx +0 -96
  237. package/src/Dialog/DialogActions/DialogActions.test.tsx +0 -25
  238. package/src/Dialog/DialogActions/DialogActions.tsx +0 -21
  239. package/src/Dialog/DialogTitle/DialogTitle.test.tsx +0 -18
  240. package/src/Dialog/DialogTitle/DialogTitle.tsx +0 -18
@@ -0,0 +1,162 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { DiscardChangesModal, Props } from './DiscardChangesModal';
3
+ import { findByTestId, getAllByRole, render, waitFor } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+
6
+ const defaultParams: Props = {
7
+ id: 'modal',
8
+ open: true,
9
+ hasUnsavedChanges: jest.fn(),
10
+ onClose: jest.fn(),
11
+ headerProps: {
12
+ title: 'Header',
13
+ },
14
+ discardChangedDialogProps: {
15
+ 'data-testid': 'discardChangesDialog',
16
+ discardChangesButtonLabel: 'Discard',
17
+ keepEditingButtonLabel: 'Keep editing',
18
+ contentLabel: 'Unsaved changes',
19
+ titleLabel: 'Dialog',
20
+ },
21
+ children: <span>children</span>,
22
+ };
23
+
24
+ const createDiscardChangesModal = (params?: (defaultParams: Props) => Props) => {
25
+ let parameters: Props = defaultParams;
26
+ if (params) {
27
+ parameters = params(defaultParams);
28
+ }
29
+ const queries = render(<DiscardChangesModal {...parameters} data-testid="discardChangesModal" />);
30
+ const discardChangesModal = queries.getByTestId('discardChangesModal');
31
+ const closeBtn = queries.getByRole('button', { name: 'close modal' });
32
+
33
+ return {
34
+ ...queries,
35
+ discardChangesModal,
36
+ closeBtn,
37
+ };
38
+ };
39
+
40
+ const getDiscardChangesButtons = (container: HTMLElement) =>
41
+ getAllByRole(container, 'button', {
42
+ name: new RegExp(
43
+ `(${defaultParams.discardChangedDialogProps.discardChangesButtonLabel}|${defaultParams.discardChangedDialogProps.keepEditingButtonLabel})`
44
+ ),
45
+ });
46
+
47
+ const findDiscardChangesDialog = (container: HTMLElement) =>
48
+ findByTestId(container, 'discardChangesDialog');
49
+
50
+ describe('DiscardChangesModal should render', () => {
51
+ it('renders without crashing', () => {
52
+ const { discardChangesModal, container } = createDiscardChangesModal();
53
+
54
+ expect(discardChangesModal).toBeDefined();
55
+ expect(discardChangesModal).toHaveTextContent('children');
56
+ expect(discardChangesModal).toHaveTextContent(defaultParams.headerProps.title);
57
+ expect(container).not.toHaveTextContent(defaultParams.discardChangedDialogProps.titleLabel);
58
+ });
59
+
60
+ it('clicking on close button without making any changes close the modal', () => {
61
+ (
62
+ defaultParams.hasUnsavedChanges as jest.MockedFunction<typeof defaultParams.hasUnsavedChanges>
63
+ ).mockReturnValue(false);
64
+ const { closeBtn } = createDiscardChangesModal();
65
+
66
+ userEvent.click(closeBtn);
67
+ expect(defaultParams.onClose).toBeCalledTimes(1);
68
+ });
69
+ });
70
+
71
+ describe('DiscardChangesModal should show DiscardChangesDialog', () => {
72
+ it('showing DiscardChangesDialog and clicking on `keep editing` button', async () => {
73
+ (
74
+ defaultParams.hasUnsavedChanges as jest.MockedFunction<typeof defaultParams.hasUnsavedChanges>
75
+ ).mockReturnValue(true);
76
+ const { closeBtn } = createDiscardChangesModal();
77
+ const container = document.body;
78
+ expect(defaultParams.onClose).not.toBeCalled();
79
+
80
+ userEvent.click(closeBtn);
81
+
82
+ expect(defaultParams.onClose).not.toBeCalled();
83
+ await findDiscardChangesDialog(container);
84
+ const [_, keepEditingBtn] = getDiscardChangesButtons(container);
85
+ expect(container).toHaveTextContent(defaultParams.discardChangedDialogProps.titleLabel);
86
+ expect(container).toHaveTextContent(defaultParams.discardChangedDialogProps.contentLabel);
87
+
88
+ userEvent.click(keepEditingBtn);
89
+ expect(defaultParams.onClose).not.toBeCalled();
90
+ await waitFor(() =>
91
+ expect(container).not.toHaveTextContent(defaultParams.discardChangedDialogProps.titleLabel)
92
+ );
93
+ });
94
+
95
+ it('showing DiscardChangesDialog and clicking on `discard` button', async () => {
96
+ (
97
+ defaultParams.hasUnsavedChanges as jest.MockedFunction<typeof defaultParams.hasUnsavedChanges>
98
+ ).mockReturnValue(true);
99
+ const { closeBtn } = createDiscardChangesModal();
100
+ const container = document.body;
101
+
102
+ userEvent.click(closeBtn);
103
+
104
+ await findDiscardChangesDialog(container);
105
+ const [discardBtn] = getDiscardChangesButtons(container);
106
+ expect(container).toHaveTextContent(defaultParams.discardChangedDialogProps.titleLabel);
107
+
108
+ userEvent.click(discardBtn);
109
+ expect(defaultParams.onClose).toBeCalled();
110
+ });
111
+ });
112
+
113
+ describe('ref should work', () => {
114
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
115
+ const ExampleComponent = ({
116
+ propagateRef,
117
+ }: {
118
+ propagateRef?: (
119
+ ref1: React.RefObject<HTMLElement>,
120
+ ref2: React.RefObject<HTMLElement>
121
+ ) => void;
122
+ }) => {
123
+ const modalRef = useRef(null);
124
+ const dialogRef = useRef(null);
125
+
126
+ useEffect(() => {
127
+ if (dialogRef.current && modalRef.current) {
128
+ propagateRef && propagateRef(modalRef, dialogRef);
129
+ }
130
+ }, [modalRef, dialogRef]);
131
+
132
+ return (
133
+ <DiscardChangesModal
134
+ modalRef={modalRef}
135
+ dialogRef={dialogRef}
136
+ data-ref="testing"
137
+ hasUnsavedChanges={jest.fn()}
138
+ onClose={jest.fn()}
139
+ headerProps={{ title: 'test' }}
140
+ open={false}
141
+ children="test"
142
+ discardChangedDialogProps={{
143
+ contentLabel: 'test',
144
+ discardChangesButtonLabel: 'test',
145
+ keepEditingButtonLabel: 'test',
146
+ titleLabel: 'test',
147
+ 'data-ref': 'testing',
148
+ }}
149
+ title="test"
150
+ id="test"
151
+ />
152
+ );
153
+ };
154
+
155
+ const refCheck = (ref1: React.RefObject<HTMLElement>, ref2: React.RefObject<HTMLElement>) => {
156
+ expect(ref1.current).toHaveAttribute('data-ref', 'testing');
157
+ expect(ref2.current).toHaveAttribute('data-ref', 'testing');
158
+ };
159
+
160
+ render(<ExampleComponent propagateRef={refCheck} />);
161
+ });
162
+ });
@@ -0,0 +1,61 @@
1
+ import React, { Fragment, useState } from 'react';
2
+ import { Modal, Props as ModalProps } from '../Modal/Modal';
3
+ import { ModalHeader, Props as ModalHeaderProps } from '../Modal/ModalHeader/ModalHeader';
4
+ import {
5
+ DiscardChangesDialog,
6
+ Props as DiscardChangesDialogProps,
7
+ } from './DiscardChangesDialog/DiscardChangesDialog';
8
+
9
+ export interface Props extends Omit<ModalProps, 'onClose'> {
10
+ hasUnsavedChanges: () => boolean;
11
+ onClose: (event?: React.MouseEvent<HTMLElement>) => unknown;
12
+ headerProps: Omit<ModalHeaderProps, 'onClose' | 'id'>;
13
+ discardChangedDialogProps: Omit<
14
+ DiscardChangesDialogProps,
15
+ 'open' | 'onKeepEditing' | 'onDiscardChanges'
16
+ >;
17
+ modalRef?: React.RefObject<HTMLDivElement>;
18
+ dialogRef?: React.RefObject<HTMLDivElement>;
19
+ }
20
+
21
+ export const DiscardChangesModal = ({
22
+ id,
23
+ children,
24
+ headerProps,
25
+ discardChangedDialogProps,
26
+ modalRef,
27
+ dialogRef,
28
+ onClose,
29
+ hasUnsavedChanges,
30
+ ...rest
31
+ }: Props) => {
32
+ const [openDiscardChangesDialog, setOpenDiscardChangesDialog] = useState(false);
33
+
34
+ const onCloseWrapper = () =>
35
+ hasUnsavedChanges() ? setOpenDiscardChangesDialog(true) : onClose();
36
+
37
+ const onDialogKeepEditing = () => {
38
+ setOpenDiscardChangesDialog(false);
39
+ };
40
+
41
+ const onDialogDiscardChanges = () => {
42
+ setOpenDiscardChangesDialog(false);
43
+ onClose();
44
+ };
45
+
46
+ return (
47
+ <Fragment>
48
+ <Modal id={id} ref={modalRef} onClose={onCloseWrapper} {...rest}>
49
+ <ModalHeader {...headerProps} id={`${id}-label`} onClose={onCloseWrapper} />
50
+ {children}
51
+ </Modal>
52
+ <DiscardChangesDialog
53
+ {...discardChangedDialogProps}
54
+ ref={dialogRef}
55
+ open={openDiscardChangesDialog}
56
+ onKeepEditing={onDialogKeepEditing}
57
+ onDiscardChanges={onDialogDiscardChanges}
58
+ />
59
+ </Fragment>
60
+ );
61
+ };
File without changes
@@ -1,4 +1,4 @@
1
- @import '../../readyclasses.module.scss';
1
+ @import '../../../readyclasses.module.scss';
2
2
 
3
3
  .snackbar {
4
4
  padding: 1rem 1.25rem;
@@ -1,11 +1,11 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
- import { IconButton } from '../../Button/IconButton';
3
- import { Icon, Icons } from '../../Icon/Icon';
2
+ import { IconButton } from '../../../Button/IconButton';
3
+ import { Icon, Icons } from '../../../Icon/Icon';
4
4
  import { Variant, Actions } from '../interfaces';
5
5
  import classes from './SnackbarItem.module.scss';
6
- import readyclasses from '../../readyclasses.module.scss';
7
- import { useAnimation } from '../../hooks/useAnimation';
8
- import { Typography } from '../../Typography/Typography';
6
+ import readyclasses from '../../../readyclasses.module.scss';
7
+ import { useAnimation } from '../../../hooks/useAnimation';
8
+ import { Typography } from '../../../Typography/Typography';
9
9
 
10
10
  const textColor = 'var(--snackbar-text-color)';
11
11
 
@@ -51,7 +51,7 @@ export const SnackbarItem = ({
51
51
 
52
52
  const getVariantIcon = () => {
53
53
  if (variant === 'error') {
54
- return Icons.TimesCircleAlt;
54
+ return Icons.Error;
55
55
  }
56
56
  return variant === 'success' ? Icons.CheckmarkCircleBreakout : Icons.InfoCircle;
57
57
  };
@@ -92,7 +92,6 @@ export const SnackbarItem = ({
92
92
  <Icon icon={Icons.Times} color={textColor} />
93
93
  </IconButton>
94
94
  </div>
95
- {/* @TODO: change it to Typography*/}
96
95
  {!!content && (
97
96
  <Typography className={classes['content']} variant="body">
98
97
  {content}
@@ -3,7 +3,7 @@ import { createPortal } from 'react-dom';
3
3
  import { SnackbarContextProvider } from './SnackbarStateProvider';
4
4
  import { Actions, SnackbarOptionsProps, Variant } from '../interfaces';
5
5
  import { Placement, SnackbarContainer } from '../SnackbarContainer/SnackbarContainer';
6
- import { generateID } from '../../util/helper';
6
+ import { generateID } from '../../../util/helper';
7
7
  import { SnackbarItem } from '../SnackbarItem/SnackbarItem';
8
8
 
9
9
  /** Short msg is when only title is provided. Long one when content or/and actions are provided (or type is error). */
@@ -14,7 +14,7 @@ interface Duration {
14
14
 
15
15
  export interface Props {
16
16
  closeButtonTitle: string;
17
- children?: ReactNode | ReactNode[];
17
+ children?: ReactNode;
18
18
  placement?: Placement;
19
19
  stackSize?: number;
20
20
  domRoot?: HTMLElement;
@@ -0,0 +1,120 @@
1
+ .pagination-wrapper {
2
+ font-family: var(--font-family);
3
+ font-size: var(--font-size);
4
+ color: var(--greyed-out);
5
+ display: flex;
6
+ flex-direction: column;
7
+ }
8
+
9
+ .form-element {
10
+ height: 2.5rem;
11
+
12
+ button {
13
+ min-height: 2.5rem;
14
+ }
15
+ }
16
+
17
+ .total {
18
+ flex: 1 0 auto;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+
23
+ span > span {
24
+ font-weight: 700;
25
+ font-family: var(--font-family);
26
+ font-size: var(--font-size);
27
+ margin-left: 0.25rem;
28
+ }
29
+ }
30
+
31
+ .pagination {
32
+ flex: 1 0 auto;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ margin-top: 1rem;
37
+
38
+ .previous,
39
+ .next {
40
+ display: flex;
41
+ align-items: center;
42
+
43
+ button {
44
+ margin: 0.25rem;
45
+ }
46
+
47
+ button span:before {
48
+ font-size: 0.75rem;
49
+ }
50
+ }
51
+ }
52
+
53
+ .per-page {
54
+ display: none;
55
+ align-items: center;
56
+ }
57
+
58
+ .page {
59
+ display: flex;
60
+ align-items: center;
61
+ flex-basis: min-content;
62
+ }
63
+
64
+ .page-size-select {
65
+ border-color: #fff;
66
+ margin: 0 0.25rem;
67
+
68
+ button {
69
+ min-width: 55px;
70
+ padding: 0;
71
+
72
+ div[data-display] {
73
+ left: 0.5rem;
74
+ }
75
+
76
+ div:not([data-display]) {
77
+ right: 0.5rem;
78
+ }
79
+ }
80
+ }
81
+
82
+ .current-value-input {
83
+ margin: 0 0.25rem 0 0;
84
+ padding: 0;
85
+
86
+ input {
87
+ border-radius: var(--input-border-radius);
88
+ padding: 0 1rem;
89
+ width: auto;
90
+ text-align: center;
91
+ }
92
+ }
93
+
94
+ @media screen and (min-width: 30em) {
95
+ .pagination-wrapper {
96
+ flex-direction: row;
97
+ }
98
+
99
+ .total {
100
+ justify-content: flex-start;
101
+ }
102
+
103
+ .pagination {
104
+ margin-top: 0;
105
+ justify-content: flex-end;
106
+
107
+ .previous,
108
+ .next {
109
+ button {
110
+ margin: 0.5rem;
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ @media screen and (min-width: 48em) {
117
+ .per-page {
118
+ display: flex;
119
+ }
120
+ }
@@ -0,0 +1,176 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { Pagination, Props } from './Pagination';
3
+ import { render, waitFor } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+
6
+ const defaultParams: Props = {
7
+ currentPage: 1,
8
+ totalElements: 500,
9
+ onPageChange: jest.fn(),
10
+ onPageSizeChange: jest.fn(),
11
+ };
12
+
13
+ const createPagination = (params?: (defaultParams: Props) => Props) => {
14
+ let parameters: Props = defaultParams;
15
+
16
+ if (params) {
17
+ parameters = params(defaultParams);
18
+ }
19
+
20
+ const queries = render(<Pagination data-testid="pagination" {...parameters} />);
21
+
22
+ const pagination = queries.getByTestId('pagination');
23
+
24
+ return {
25
+ ...queries,
26
+ pagination,
27
+ };
28
+ };
29
+
30
+ describe('Pagination should render', () => {
31
+ it('renders without crashing', () => {
32
+ const { pagination } = createPagination();
33
+
34
+ expect(pagination).toBeTruthy();
35
+ });
36
+ });
37
+
38
+ describe('Pagination events', () => {
39
+ it('should give us the correct values', async () => {
40
+ const onPageChange = jest.fn();
41
+
42
+ const onPageSizeChange = jest.fn();
43
+
44
+ const { pagination } = createPagination((defaultParams) => ({
45
+ ...defaultParams,
46
+ currentPage: 10,
47
+ onPageChange: onPageChange,
48
+ onPageSizeChange: onPageSizeChange,
49
+ }));
50
+
51
+ const next = pagination.querySelector('[data-paginate="next"]')!;
52
+ const previous = pagination.querySelector('[data-paginate="previous"]')!;
53
+ const first = pagination.querySelector('[data-paginate="first"]')!;
54
+ const last = pagination.querySelector('[data-paginate="last"]')!;
55
+ const pageSizeSelect = pagination.querySelector('.page-size-select')!;
56
+ const currentPageInput = pagination.querySelector('#current-value-input')!;
57
+
58
+ userEvent.click(next);
59
+
60
+ await waitFor(() => expect(onPageChange).toHaveBeenCalledWith(11));
61
+
62
+ userEvent.click(previous);
63
+ await waitFor(() => expect(onPageChange).toHaveBeenCalledWith(9));
64
+
65
+ userEvent.click(first);
66
+ await waitFor(() => expect(onPageChange).toHaveBeenCalledWith(0));
67
+
68
+ userEvent.click(last);
69
+ await waitFor(() => expect(onPageChange).toHaveBeenCalledWith(50));
70
+
71
+ userEvent.click(pageSizeSelect);
72
+
73
+ const option25 = pageSizeSelect.querySelector('[data-value="25"]')!;
74
+
75
+ userEvent.click(option25);
76
+
77
+ await waitFor(() => expect(onPageSizeChange).toHaveBeenCalledWith(25));
78
+
79
+ (currentPageInput as HTMLInputElement).focus();
80
+
81
+ userEvent.keyboard('{backspace}{backspace}30{enter}');
82
+
83
+ await waitFor(() => expect(onPageChange).toHaveBeenCalledWith(30));
84
+ });
85
+ });
86
+
87
+ describe('different current pages and their effect on what renders', () => {
88
+ it('is on the first page and does not render previous and first', () => {
89
+ const { pagination } = createPagination();
90
+
91
+ expect(pagination.querySelector('.next')).toBeTruthy();
92
+ expect(pagination.querySelector('.previous')).toBeFalsy();
93
+ });
94
+
95
+ it('is on the second page and does not render first', () => {
96
+ const { pagination } = createPagination((defaultParams) => ({
97
+ ...defaultParams,
98
+ currentPage: 2,
99
+ }));
100
+
101
+ expect(pagination.querySelector('[data-paginate="first"]')).toBeFalsy();
102
+ expect((pagination.querySelector('.current-value-input input') as HTMLInputElement).value).toBe(
103
+ '2'
104
+ );
105
+ });
106
+
107
+ it('is on the second to last page and does not render last', () => {
108
+ const { pagination } = createPagination((defaultParams) => ({
109
+ ...defaultParams,
110
+ currentPage: 499,
111
+ }));
112
+
113
+ expect(pagination.querySelector('[data-paginate="last"]')).toBeFalsy();
114
+ });
115
+
116
+ it('is on the last page and does not render next & last', () => {
117
+ const { pagination } = createPagination((defaultParams) => ({
118
+ ...defaultParams,
119
+ currentPage: 500,
120
+ }));
121
+
122
+ expect(pagination.querySelector('[data-paginate="last"]')).toBeFalsy();
123
+ expect(pagination.querySelector('[data-paginate="next"]')).toBeFalsy();
124
+ });
125
+ });
126
+
127
+ describe('omitted attributes still renders correctly', () => {
128
+ it("still renders next if totalItems prop isn't given and we're on the first page", () => {
129
+ const { pagination } = createPagination((defaultParams) => ({
130
+ ...defaultParams,
131
+ totalElements: undefined,
132
+ }));
133
+
134
+ expect(pagination.querySelector('.page')).toBeFalsy();
135
+ expect(pagination.querySelector('.next')).toBeTruthy();
136
+ expect(pagination.querySelector('.previous')).toBeFalsy();
137
+ });
138
+
139
+ it("still renders next if totalItems prop isn't given and we're on the first page", () => {
140
+ const { pagination } = createPagination((defaultParams) => ({
141
+ ...defaultParams,
142
+ currentPage: 4,
143
+ totalElements: undefined,
144
+ }));
145
+
146
+ expect(pagination.querySelector('.page')).toBeFalsy();
147
+ expect(pagination.querySelector('.next')).toBeTruthy();
148
+ expect(pagination.querySelector('.previous')).toBeTruthy();
149
+ });
150
+ });
151
+
152
+ describe('ref should work', () => {
153
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
154
+ const ExampleComponent = ({
155
+ propagateRef,
156
+ }: {
157
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
158
+ }) => {
159
+ const ref = useRef(null);
160
+
161
+ useEffect(() => {
162
+ if (ref.current) {
163
+ propagateRef && propagateRef(ref);
164
+ }
165
+ }, [ref]);
166
+
167
+ return <Pagination {...defaultParams} data-ref="testing" ref={ref} />;
168
+ };
169
+
170
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
171
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
172
+ };
173
+
174
+ render(<ExampleComponent propagateRef={refCheck} />);
175
+ });
176
+ });