@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
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Toggle } from './Toggle';
3
3
  import { render } from '@testing-library/react';
4
4
 
@@ -14,6 +14,32 @@ describe('Toggle should render', () => {
14
14
  });
15
15
  });
16
16
 
17
+ describe('ref should work', () => {
18
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
19
+ const ExampleComponent = ({
20
+ propagateRef,
21
+ }: {
22
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
23
+ }) => {
24
+ const ref = useRef(null);
25
+
26
+ useEffect(() => {
27
+ if (ref.current) {
28
+ propagateRef && propagateRef(ref);
29
+ }
30
+ }, [ref]);
31
+
32
+ return <Toggle name="test" children="test" data-ref="testing" ref={ref} />;
33
+ };
34
+
35
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
36
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
37
+ };
38
+
39
+ render(<ExampleComponent propagateRef={refCheck} />);
40
+ });
41
+ });
42
+
17
43
  describe('Toggle attributes', () => {
18
44
  it('should be checked', () => {
19
45
  const { getByTestId } = render(
@@ -1,20 +1,33 @@
1
- import React from 'react';
1
+ import React, { ComponentPropsWithRef } from 'react';
2
2
  import { Checkbox, CheckboxProps } from '../Checkbox/Checkbox';
3
3
  import classes from './Toggle.module.scss';
4
4
 
5
5
  export interface Props
6
- extends Omit<CheckboxProps, 'indeterminate' | 'errorMessage' | 'error' | 'children'> {
6
+ extends ComponentPropsWithRef<'input'>,
7
+ Omit<CheckboxProps, 'indeterminate' | 'errorMessage' | 'error' | 'children' | 'label'> {
7
8
  children: string;
8
9
  }
9
10
 
10
- export const Toggle = ({ children, checked, ...rest }: Props) => (
11
- <div className={classes['toggle-wrapper']}>
12
- <Checkbox {...rest} checked={checked} className={classes.checkbox} label={children}>
13
- <span
14
- data-toggle
15
- aria-hidden="true"
16
- className={`${classes.toggle} ${checked ? classes.checked : ''} `}
17
- ></span>
18
- </Checkbox>
19
- </div>
11
+ export const Toggle = React.forwardRef<HTMLInputElement, Props>(
12
+ ({ children, checked, disabled, ...rest }: Props, ref) => (
13
+ <div className={classes['toggle-wrapper']}>
14
+ <Checkbox
15
+ {...rest}
16
+ ref={ref}
17
+ checked={checked}
18
+ className={classes['checkbox']}
19
+ helperProps={{ className: classes['toggle-helper'] }}
20
+ disabled={disabled}
21
+ label={children}
22
+ >
23
+ <span
24
+ data-toggle
25
+ aria-hidden="true"
26
+ className={`${classes['toggle']} ${checked ? classes['checked'] : ''} ${
27
+ disabled ? classes['disabled'] : ''
28
+ } `}
29
+ ></span>
30
+ </Checkbox>
31
+ </div>
32
+ )
20
33
  );
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { CheckboxWrapper, Props } from './CheckboxWrapper';
3
3
  import { Checkbox, CheckboxProps } from '../../Checkbox/Checkbox';
4
4
  import { render } from '@testing-library/react';
@@ -21,7 +21,7 @@ const defaultParams: Props = {
21
21
  error: false,
22
22
  helperText: 'Helpertext',
23
23
  name: 'Checkboxwrapper',
24
- fieldsetProps: { title: 'Example title' },
24
+ fieldsetProps: { legend: 'Example title' },
25
25
  label: 'Label',
26
26
  children: [],
27
27
  };
@@ -63,6 +63,32 @@ describe('checkboxwrapper should render', () => {
63
63
  });
64
64
  });
65
65
 
66
+ describe('ref should work', () => {
67
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
68
+ const ExampleComponent = ({
69
+ propagateRef,
70
+ }: {
71
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
72
+ }) => {
73
+ const ref = useRef(null);
74
+
75
+ useEffect(() => {
76
+ if (ref.current) {
77
+ propagateRef && propagateRef(ref);
78
+ }
79
+ }, [ref]);
80
+
81
+ return <CheckboxWrapper {...defaultParams} name="test" data-ref="testing" ref={ref} />;
82
+ };
83
+
84
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
85
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
86
+ };
87
+
88
+ render(<ExampleComponent propagateRef={refCheck} />);
89
+ });
90
+ });
91
+
66
92
  describe('CheckboxWrapper should have an error', () => {
67
93
  it('should have an error and the children checkboxes should have aria-describedby of the error message of the group.', () => {
68
94
  const { checkboxwrapper } = createCheckboxWrapper((defaultParams) => ({
@@ -1,62 +1,59 @@
1
- import React, { ReactElement, useEffect } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactElement, useEffect } from 'react';
2
2
  import classes from './CheckboxWrapper.module.scss';
3
3
  import { useWrapper } from '../../../hooks/useWrapper';
4
4
  import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
5
5
  import { Icons } from '../../../Icon/Icon';
6
6
  import { Fieldset, Props as FieldsetProps } from '../../../Form/Fieldset/Fieldset';
7
7
 
8
- export interface Props extends WrapperProps {
8
+ export interface Props extends ComponentPropsWithRef<'div'>, WrapperProps {
9
9
  children: ReactElement[] | ReactElement;
10
10
  fieldsetProps: FieldsetProps;
11
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
11
12
  }
12
13
 
13
- export const CheckboxWrapper = ({
14
- children,
15
- error = false,
16
- helperText,
17
- helperProps,
18
- fieldsetProps,
19
- ...rest
20
- }: Props) => {
21
- const { errorId, helperId } = useWrapper();
14
+ export const CheckboxWrapper = React.forwardRef<HTMLDivElement, Props>(
15
+ ({ children, error = false, helperText, helperProps, fieldsetProps, ...rest }: Props, ref) => {
16
+ const { errorId, helperId } = useWrapper();
22
17
 
23
- useEffect(() => {
24
- if (fieldsetProps.title === undefined) {
25
- console.error(
26
- `You should give your Fieldset component a title prop so a legend element is rendered. This error was thrown in CheckboxWrapper. You can add this title prop through the fieldsetProps prop by passing an object (fieldsetProps={{ title: "title here" }})`
18
+ useEffect(() => {
19
+ if (fieldsetProps.legend === undefined) {
20
+ console.error(
21
+ `You should give your Fieldset component a legend prop so a legend element is rendered. This error was thrown in CheckboxWrapper. You can add this legend prop through the fieldsetProps prop by passing an object (fieldsetProps={{ legend: "legend here" }})`
22
+ );
23
+ }
24
+ }, []);
25
+
26
+ const renderChildren = () =>
27
+ React.Children.map(children, (child) =>
28
+ React.cloneElement(child, {
29
+ parentErrorId: errorId,
30
+ error: error,
31
+ parentHelperId: helperText ? helperId : false,
32
+ disabled: rest.disabled,
33
+ })
27
34
  );
28
- }
29
- }, []);
30
35
 
31
- const renderChildren = () =>
32
- React.Children.map(children, (child) =>
33
- React.cloneElement(child, {
34
- parentErrorId: errorId,
35
- error: error,
36
- parentHelperId: helperText ? helperId : false,
37
- disabled: rest.disabled,
38
- })
36
+ return (
37
+ <Fieldset {...fieldsetProps} error={error} required={rest.required}>
38
+ <Wrapper
39
+ {...rest}
40
+ ref={ref}
41
+ label=""
42
+ helperId={helperId}
43
+ helperText={helperText}
44
+ helperProps={{
45
+ ...helperProps,
46
+ className: `${classes['checkbox-wrapper-helper']} ${
47
+ error ? classes['checkbox-wrapper-error'] : ''
48
+ } ${helperProps?.className ?? ''}`,
49
+ }}
50
+ error={error}
51
+ errorMessageIcon={Icons.Error}
52
+ errorId={errorId}
53
+ >
54
+ {renderChildren()}
55
+ </Wrapper>
56
+ </Fieldset>
39
57
  );
40
-
41
- return (
42
- <Fieldset {...fieldsetProps}>
43
- <Wrapper
44
- {...rest}
45
- label=""
46
- helperId={helperId}
47
- helperText={helperText}
48
- helperProps={{
49
- ...helperProps,
50
- className: `${classes['checkbox-wrapper-helper']} ${
51
- error ? classes['checkbox-wrapper-error'] : ''
52
- } ${helperProps?.className ?? ''}`,
53
- }}
54
- error={error}
55
- errorMessageIcon={Icons.Warning}
56
- errorId={errorId}
57
- >
58
- {renderChildren()}
59
- </Wrapper>
60
- </Fieldset>
61
- );
62
- };
58
+ }
59
+ );
@@ -19,6 +19,22 @@ input {
19
19
  }
20
20
 
21
21
  .input-wrapper [data-icon]:before {
22
- transform: translateY(5px);
22
+ transition: 0.2s ease-in-out;
23
+ transform: translateY(0px);
23
24
  font-size: 1.125rem;
24
25
  }
26
+
27
+ .input-wrapper .floating-label-active [data-icon]:before {
28
+ transform: translateY(5px);
29
+ }
30
+
31
+ .input-wrapper [data-prefix],
32
+ .input-wrapper [data-suffix] {
33
+ transform: translateY(-0.125rem);
34
+ }
35
+
36
+ .floating-label-active [data-prefix],
37
+ .floating-label-active [data-suffix] {
38
+ padding-top: 0.5rem;
39
+ transform: translateY(0);
40
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { InputWrapper, Props } from './InputWrapper';
3
3
  import { render } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
@@ -60,6 +60,48 @@ describe('InputWrapper should render', () => {
60
60
  });
61
61
  });
62
62
 
63
+ describe('ref should work', () => {
64
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
65
+ const ExampleComponent = ({
66
+ propagateRef,
67
+ }: {
68
+ propagateRef?: (
69
+ ref: React.RefObject<HTMLElement>,
70
+ innerRef: React.RefObject<HTMLInputElement>
71
+ ) => void;
72
+ }) => {
73
+ const ref = useRef(null);
74
+ const innerRef = useRef(null);
75
+
76
+ useEffect(() => {
77
+ if (ref.current) {
78
+ propagateRef && propagateRef(ref, innerRef);
79
+ }
80
+ }, [ref]);
81
+
82
+ return (
83
+ <InputWrapper
84
+ {...defaultParams}
85
+ inputProps={{ ref: innerRef, 'data-ref': 'inner-testing' }}
86
+ name="test"
87
+ data-ref="testing"
88
+ ref={ref}
89
+ />
90
+ );
91
+ };
92
+
93
+ const refCheck = (
94
+ ref: React.RefObject<HTMLElement>,
95
+ innerRef: React.RefObject<HTMLElement>
96
+ ) => {
97
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
98
+ expect(innerRef.current).toHaveAttribute('data-ref', 'inner-testing');
99
+ };
100
+
101
+ render(<ExampleComponent propagateRef={refCheck} />);
102
+ });
103
+ });
104
+
63
105
  describe('InputWrapper should be interactive', () => {
64
106
  it('executes the eventlisteners', () => {
65
107
  const onFocusHandler = jest.fn();
@@ -91,3 +133,49 @@ describe('InputWrapper should be interactive', () => {
91
133
  expect(onBlurHandler).toHaveBeenCalled();
92
134
  });
93
135
  });
136
+
137
+ describe('InputWrapper should support prefix and suffix', () => {
138
+ const prefix = 'prefix';
139
+ const suffix = 'suffix';
140
+
141
+ const hasPrefixAndSuffixDefined = (container: HTMLElement) => {
142
+ expect(container.querySelector('[data-prefix]')).toHaveTextContent(prefix);
143
+ expect(container.querySelector('[data-suffix]')).toHaveTextContent(suffix);
144
+ };
145
+
146
+ it('renders prefix and sufix when input has focus', () => {
147
+ const { container, getByTestId } = createInputWrapper((defaultParams) => ({
148
+ ...defaultParams,
149
+ value: '',
150
+ inputProps: { 'data-testid': 'input', prefix, suffix },
151
+ }));
152
+
153
+ const input = getByTestId('input');
154
+
155
+ expect(container.querySelector('[data-prefix]')).toBeNull();
156
+ expect(container.querySelector('[data-suffix]')).toBeNull();
157
+
158
+ userEvent.tab();
159
+ expect(input).toHaveFocus();
160
+ hasPrefixAndSuffixDefined(container);
161
+ });
162
+
163
+ it('renders prefix and sufix when input has value', () => {
164
+ const { container, getByTestId } = createInputWrapper((defaultParams) => ({
165
+ ...defaultParams,
166
+ inputProps: { 'data-testid': 'input', prefix, suffix },
167
+ }));
168
+
169
+ const input = getByTestId('input');
170
+
171
+ hasPrefixAndSuffixDefined(container);
172
+
173
+ userEvent.tab();
174
+ expect(input).toHaveFocus();
175
+ hasPrefixAndSuffixDefined(container);
176
+
177
+ userEvent.tab();
178
+ expect(input).not.toHaveFocus();
179
+ hasPrefixAndSuffixDefined(container);
180
+ });
181
+ });
@@ -1,92 +1,152 @@
1
- import React from 'react';
1
+ import React, { ComponentPropsWithRef, useEffect, useRef, useState } from 'react';
2
2
  import { Input, Type, Props as InputProps } from '../../Input/Input';
3
3
  import classes from './InputWrapper.module.scss';
4
4
  import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
5
5
  import { useWrapper } from '../../../hooks/useWrapper';
6
6
 
7
- interface OptionalInputProps extends Omit<InputProps, 'type'> {}
7
+ interface PartialInputProps extends Partial<InputProps> {}
8
8
 
9
- export interface Props extends WrapperProps {
9
+ export interface Props extends ComponentPropsWithRef<'div'>, WrapperProps {
10
10
  label: string;
11
11
  type: Type;
12
12
  name: string;
13
- inputProps?: OptionalInputProps;
13
+ inputProps?: PartialInputProps;
14
14
  value: string;
15
15
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
16
16
  onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
17
17
  onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
18
18
  }
19
19
 
20
- export const InputWrapper = ({
21
- type,
22
- name,
23
- inputProps,
24
- helperText,
25
- helperProps,
26
- value,
27
- error,
28
- onChange,
29
- onBlur,
30
- onFocus,
31
- ...rest
32
- }: Props) => {
33
- const {
34
- errorId,
35
- floatingLabelActive,
36
- setFloatingLabelActive,
37
- hasFocus,
38
- setHasFocus,
39
- helperId,
40
- labelId,
41
- } = useWrapper(value, inputProps?.placeholder, type);
20
+ const useLabelOffset = (
21
+ wrapper: React.RefObject<HTMLDivElement>,
22
+ input: React.RefObject<HTMLInputElement>,
23
+ floatingLabelActive: boolean,
24
+ prefix?: string
25
+ ) => {
26
+ const [labelOffset, setLabelOffset] = useState({});
42
27
 
43
- return (
44
- <Wrapper
45
- {...rest}
46
- name={name}
47
- className={classes['input-wrapper']}
48
- labelProps={{
49
- id: labelId,
50
- className: `${classes['input-label']} ${hasFocus ? classes['focus'] : ''}`,
51
- }}
52
- floatingLabelActive={floatingLabelActive}
53
- errorId={errorId}
54
- error={error}
55
- helperId={helperId}
56
- helperText={helperText}
57
- helperProps={{
58
- ...helperProps,
59
- className: `${classes['input-wrapper-helper']} ${helperProps?.className ?? ''} `,
60
- }}
61
- helperIndent={20}
62
- >
63
- <Input
64
- {...inputProps}
65
- aria-labelledby={labelId}
66
- aria-describedby={error ? errorId : helperId}
67
- onChange={onChange}
68
- onFocus={(e) => {
69
- onFocus && onFocus(e);
70
- setHasFocus(true);
71
- setFloatingLabelActive(true);
72
- }}
73
- onBlur={(e) => {
74
- onBlur && onBlur(e);
75
- setHasFocus(false);
76
- e.target.value ||
77
- inputProps?.placeholder?.length ||
78
- type === 'datetime-local' ||
79
- type === 'time'
80
- ? setFloatingLabelActive(true)
81
- : setFloatingLabelActive(false);
82
- }}
83
- className={floatingLabelActive ? classes['floating-label'] : ''}
28
+ const resetLabelOffset = () => setLabelOffset({ left: undefined });
29
+
30
+ useEffect(() => {
31
+ if (wrapper.current && input.current && prefix) {
32
+ if (floatingLabelActive) {
33
+ resetLabelOffset();
34
+ } else {
35
+ const prefixDifference =
36
+ input.current.getBoundingClientRect().left -
37
+ wrapper.current.getBoundingClientRect().left +
38
+ 4;
39
+
40
+ setLabelOffset({ left: `${prefixDifference}px` });
41
+ }
42
+ }
43
+ }, [wrapper.current, input.current, prefix, floatingLabelActive]);
44
+
45
+ return { labelOffset };
46
+ };
47
+
48
+ export const InputWrapper = React.forwardRef<HTMLDivElement, Props>(
49
+ (
50
+ {
51
+ type,
52
+ name,
53
+ inputProps,
54
+ helperText,
55
+ helperProps,
56
+ value,
57
+ className,
58
+ error,
59
+ onChange,
60
+ onBlur,
61
+ onFocus,
62
+ ...rest
63
+ }: Props,
64
+ ref
65
+ ) => {
66
+ const {
67
+ errorId,
68
+ floatingLabelActive,
69
+ setFloatingLabelActive,
70
+ hasFocus,
71
+ setHasFocus,
72
+ helperId,
73
+ labelId,
74
+ } = useWrapper(value, inputProps?.placeholder, type);
75
+ const { prefix, suffix } = inputProps || {};
76
+ const wrapper = useRef<HTMLDivElement>(null);
77
+ const input = useRef<HTMLInputElement>(null);
78
+ const hasValueOrActiveFloatingLabel = !!value || floatingLabelActive;
79
+ const labelClasses = [classes['input-label']];
80
+ const { labelOffset } = useLabelOffset(
81
+ (ref as React.RefObject<HTMLDivElement>) || wrapper,
82
+ (inputProps && (inputProps.ref as React.RefObject<HTMLInputElement>)) || input,
83
+ floatingLabelActive,
84
+ prefix
85
+ );
86
+
87
+ hasFocus && labelClasses.push(classes['focus']);
88
+
89
+ return (
90
+ <Wrapper
91
+ {...rest}
92
+ ref={ref || wrapper}
84
93
  name={name}
94
+ className={`${classes['input-wrapper']} ${className ?? ''}`}
95
+ labelProps={{
96
+ id: labelId,
97
+ className: labelClasses.join(' '),
98
+ style: { ...labelOffset },
99
+ }}
100
+ floatingLabelActive={floatingLabelActive}
101
+ errorId={errorId}
85
102
  error={error}
86
- id={name}
87
- value={value}
88
- type={type}
89
- />
90
- </Wrapper>
91
- );
92
- };
103
+ helperId={helperId}
104
+ helperText={helperText}
105
+ helperProps={{
106
+ ...helperProps,
107
+ className: `${classes['input-wrapper-helper']} ${helperProps?.className ?? ''} `,
108
+ }}
109
+ helperIndent={20}
110
+ >
111
+ <Input
112
+ {...inputProps}
113
+ prefix={hasValueOrActiveFloatingLabel ? prefix : ''}
114
+ suffix={hasValueOrActiveFloatingLabel ? suffix : ''}
115
+ wrapperProps={{
116
+ className: `${floatingLabelActive ? classes['floating-label-active'] : ''} ${
117
+ inputProps?.wrapperProps?.className ?? ''
118
+ }`,
119
+ }}
120
+ ref={(inputProps && inputProps.ref) || input}
121
+ aria-labelledby={labelId}
122
+ aria-describedby={error ? errorId : helperId}
123
+ onChange={onChange}
124
+ onFocus={(e) => {
125
+ onFocus && onFocus(e);
126
+ setHasFocus(true);
127
+ setFloatingLabelActive(true);
128
+ }}
129
+ onBlur={(e) => {
130
+ onBlur && onBlur(e);
131
+ setHasFocus(false);
132
+ e.target.value ||
133
+ e.target.placeholder ||
134
+ inputProps?.placeholder?.length ||
135
+ type === 'datetime-local' ||
136
+ type === 'time'
137
+ ? setFloatingLabelActive(true)
138
+ : setFloatingLabelActive(false);
139
+ }}
140
+ className={`${floatingLabelActive ? classes['floating-label'] : ''} ${
141
+ inputProps?.className ?? ''
142
+ }`}
143
+ name={name}
144
+ error={error}
145
+ id={name}
146
+ value={value}
147
+ type={type}
148
+ />
149
+ </Wrapper>
150
+ );
151
+ }
152
+ );
@@ -12,7 +12,7 @@ const defaultParams: Props = {
12
12
  helperText: 'Helper text',
13
13
  error: false,
14
14
  onChange: onChangeHandler,
15
- fieldsetProps: { title: 'Example title' },
15
+ fieldsetProps: { legend: 'Example title' },
16
16
  value: checkedOptionValue,
17
17
  name: 'my-group',
18
18
  children: [