@onewelcome/react-lib-components 0.1.0-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 (248) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/BaseModal/BaseModal.d.ts +16 -0
  4. package/dist/BaseModal/BaseModalActions/BaseModalActions.d.ts +5 -0
  5. package/dist/BaseModal/BaseModalContent/BaseModalContent.d.ts +8 -0
  6. package/dist/BaseModal/BaseModalContext.d.ts +2 -0
  7. package/dist/BaseModal/BaseModalHeader/BaseModalHeader.d.ts +8 -0
  8. package/dist/Breadcrumbs/Breadcrumbs.d.ts +9 -0
  9. package/dist/Button/BaseButton.d.ts +8 -0
  10. package/dist/Button/Button.d.ts +10 -0
  11. package/dist/Button/IconButton.d.ts +10 -0
  12. package/dist/ContextMenu/ContextMenu.d.ts +18 -0
  13. package/dist/ContextMenu/ContextMenuItem.d.ts +6 -0
  14. package/dist/Dialog/Dialog.d.ts +18 -0
  15. package/dist/Dialog/DialogActions/DialogActions.d.ts +6 -0
  16. package/dist/Dialog/DialogTitle/DialogTitle.d.ts +6 -0
  17. package/dist/Form/Checkbox/Checkbox.d.ts +13 -0
  18. package/dist/Form/Fieldset/Fieldset.d.ts +13 -0
  19. package/dist/Form/Form.d.ts +5 -0
  20. package/dist/Form/FormControl/FormControl.d.ts +8 -0
  21. package/dist/Form/FormGroup/FormGroup.d.ts +18 -0
  22. package/dist/Form/FormHelperText/FormHelperText.d.ts +7 -0
  23. package/dist/Form/FormSelectorWrapper/FormSelectorWrapper.d.ts +18 -0
  24. package/dist/Form/Input/Input.d.ts +12 -0
  25. package/dist/Form/Label/Label.d.ts +6 -0
  26. package/dist/Form/Radio/Radio.d.ts +11 -0
  27. package/dist/Form/Select/Option.d.ts +12 -0
  28. package/dist/Form/Select/Select.d.ts +15 -0
  29. package/dist/Form/Textarea/Textarea.d.ts +7 -0
  30. package/dist/Form/Toggle/Toggle.d.ts +6 -0
  31. package/dist/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.d.ts +8 -0
  32. package/dist/Form/Wrapper/InputWrapper/InputWrapper.d.ts +17 -0
  33. package/dist/Form/Wrapper/RadioWrapper/RadioWrapper.d.ts +10 -0
  34. package/dist/Form/Wrapper/SelectWrapper/SelectWrapper.d.ts +12 -0
  35. package/dist/Form/Wrapper/TextareaWrapper/TextareaWrapper.d.ts +14 -0
  36. package/dist/Form/Wrapper/Wrapper/Wrapper.d.ts +28 -0
  37. package/dist/Form/form.interfaces.d.ts +12 -0
  38. package/dist/Icon/Icon.d.ts +75 -0
  39. package/dist/Link/Link.d.ts +15 -0
  40. package/dist/Modal/Modal.d.ts +1 -0
  41. package/dist/Modal/ModalActions/ModalActions.d.ts +1 -0
  42. package/dist/Modal/ModalContent/ModalContent.d.ts +1 -0
  43. package/dist/Modal/ModalHeader/ModalHeader.d.ts +1 -0
  44. package/dist/Popover/Popover.d.ts +11 -0
  45. package/dist/Snackbar/SnackbarContainer/SnackbarContainer.d.ts +12 -0
  46. package/dist/Snackbar/SnackbarItem/SnackbarItem.d.ts +13 -0
  47. package/dist/Snackbar/SnackbarProvider/SnackbarProvider.d.ts +18 -0
  48. package/dist/Snackbar/SnackbarProvider/SnackbarStateProvider.d.ts +14 -0
  49. package/dist/Snackbar/interfaces.d.ts +10 -0
  50. package/dist/Snackbar/useSnackbar.d.ts +1 -0
  51. package/dist/Tiles/Tile.d.ts +16 -0
  52. package/dist/Tiles/Tiles.d.ts +6 -0
  53. package/dist/Tooltip/Tooltip.d.ts +11 -0
  54. package/dist/Typography/Typography.d.ts +12 -0
  55. package/dist/Wizard/BaseWizardSteps/BaseWizardSteps.d.ts +13 -0
  56. package/dist/Wizard/Wizard.d.ts +12 -0
  57. package/dist/Wizard/WizardActions/WizardActions.d.ts +12 -0
  58. package/dist/Wizard/WizardStateProvider.d.ts +12 -0
  59. package/dist/Wizard/WizardSteps/WizardSteps.d.ts +5 -0
  60. package/dist/Wizard/wizardStateReducer.d.ts +26 -0
  61. package/dist/_BaseStyling_/BaseStyling.d.ts +47 -0
  62. package/dist/hooks/useAnimation.d.ts +6 -0
  63. package/dist/hooks/useBodyClick.d.ts +1 -0
  64. package/dist/hooks/useFormSelector.d.ts +13 -0
  65. package/dist/hooks/usePosition.d.ts +36 -0
  66. package/dist/hooks/useScroll.d.ts +2 -0
  67. package/dist/hooks/useSpacing.d.ts +18 -0
  68. package/dist/hooks/useWrapper.d.ts +11 -0
  69. package/dist/index.d.ts +43 -0
  70. package/dist/index.js +8 -0
  71. package/dist/interfaces.d.ts +13 -0
  72. package/dist/react-lib-components.cjs.development.js +3282 -0
  73. package/dist/react-lib-components.cjs.development.js.map +1 -0
  74. package/dist/react-lib-components.cjs.production.min.js +2 -0
  75. package/dist/react-lib-components.cjs.production.min.js.map +1 -0
  76. package/dist/react-lib-components.esm.js +3235 -0
  77. package/dist/react-lib-components.esm.js.map +1 -0
  78. package/dist/util/helper.d.ts +1 -0
  79. package/package.json +88 -0
  80. package/src/BaseModal/BaseModal.module.scss +58 -0
  81. package/src/BaseModal/BaseModal.test.tsx +59 -0
  82. package/src/BaseModal/BaseModal.tsx +113 -0
  83. package/src/BaseModal/BaseModalActions/BaseModalActions.module.scss +9 -0
  84. package/src/BaseModal/BaseModalActions/BaseModalActions.test.tsx +17 -0
  85. package/src/BaseModal/BaseModalActions/BaseModalActions.tsx +14 -0
  86. package/src/BaseModal/BaseModalContent/BaseModalContent.module.scss +6 -0
  87. package/src/BaseModal/BaseModalContent/BaseModalContent.test.tsx +29 -0
  88. package/src/BaseModal/BaseModalContent/BaseModalContent.tsx +35 -0
  89. package/src/BaseModal/BaseModalContext.ts +2 -0
  90. package/src/BaseModal/BaseModalHeader/BaseModalHeader.module.scss +17 -0
  91. package/src/BaseModal/BaseModalHeader/BaseModalHeader.test.tsx +30 -0
  92. package/src/BaseModal/BaseModalHeader/BaseModalHeader.tsx +28 -0
  93. package/src/Breadcrumbs/Breadcrumbs.module.scss +14 -0
  94. package/src/Breadcrumbs/Breadcrumbs.test.tsx +42 -0
  95. package/src/Breadcrumbs/Breadcrumbs.tsx +48 -0
  96. package/src/Button/BaseButton.module.scss +20 -0
  97. package/src/Button/BaseButton.test.tsx +59 -0
  98. package/src/Button/BaseButton.tsx +31 -0
  99. package/src/Button/Button.module.scss +336 -0
  100. package/src/Button/Button.test.tsx +76 -0
  101. package/src/Button/Button.tsx +44 -0
  102. package/src/Button/IconButton.module.scss +161 -0
  103. package/src/Button/IconButton.test.tsx +47 -0
  104. package/src/Button/IconButton.tsx +29 -0
  105. package/src/ContextMenu/ContextMenu.module.scss +20 -0
  106. package/src/ContextMenu/ContextMenu.test.tsx +93 -0
  107. package/src/ContextMenu/ContextMenu.tsx +91 -0
  108. package/src/ContextMenu/ContextMenuItem.module.scss +31 -0
  109. package/src/ContextMenu/ContextMenuItem.tsx +15 -0
  110. package/src/Dialog/Dialog.module.scss +16 -0
  111. package/src/Dialog/Dialog.test.tsx +79 -0
  112. package/src/Dialog/Dialog.tsx +96 -0
  113. package/src/Dialog/DialogActions/DialogActions.module.scss +11 -0
  114. package/src/Dialog/DialogActions/DialogActions.test.tsx +25 -0
  115. package/src/Dialog/DialogActions/DialogActions.tsx +21 -0
  116. package/src/Dialog/DialogTitle/DialogTitle.module.scss +7 -0
  117. package/src/Dialog/DialogTitle/DialogTitle.test.tsx +18 -0
  118. package/src/Dialog/DialogTitle/DialogTitle.tsx +18 -0
  119. package/src/Form/Checkbox/Checkbox.module.scss +65 -0
  120. package/src/Form/Checkbox/Checkbox.test.tsx +119 -0
  121. package/src/Form/Checkbox/Checkbox.tsx +145 -0
  122. package/src/Form/Fieldset/Fieldset.module.scss +19 -0
  123. package/src/Form/Fieldset/Fieldset.test.tsx +85 -0
  124. package/src/Form/Fieldset/Fieldset.tsx +55 -0
  125. package/src/Form/Form.module.scss +3 -0
  126. package/src/Form/Form.test.tsx +47 -0
  127. package/src/Form/Form.tsx +14 -0
  128. package/src/Form/FormControl/FormControl.module.scss +67 -0
  129. package/src/Form/FormControl/FormControl.test.tsx +56 -0
  130. package/src/Form/FormControl/FormControl.tsx +47 -0
  131. package/src/Form/FormGroup/FormGroup.module.scss +29 -0
  132. package/src/Form/FormGroup/FormGroup.test.tsx +61 -0
  133. package/src/Form/FormGroup/FormGroup.tsx +78 -0
  134. package/src/Form/FormHelperText/FormHelperText.module.scss +8 -0
  135. package/src/Form/FormHelperText/FormHelperText.test.tsx +42 -0
  136. package/src/Form/FormHelperText/FormHelperText.tsx +22 -0
  137. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.module.scss +33 -0
  138. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.tsx +65 -0
  139. package/src/Form/Input/Input.module.scss +65 -0
  140. package/src/Form/Input/Input.test.tsx +135 -0
  141. package/src/Form/Input/Input.tsx +72 -0
  142. package/src/Form/Label/Label.module.scss +5 -0
  143. package/src/Form/Label/Label.test.tsx +26 -0
  144. package/src/Form/Label/Label.tsx +19 -0
  145. package/src/Form/Radio/Radio.module.scss +100 -0
  146. package/src/Form/Radio/Radio.test.tsx +88 -0
  147. package/src/Form/Radio/Radio.tsx +98 -0
  148. package/src/Form/Select/Option.test.tsx +15 -0
  149. package/src/Form/Select/Option.tsx +57 -0
  150. package/src/Form/Select/Select.module.scss +189 -0
  151. package/src/Form/Select/Select.test.tsx +96 -0
  152. package/src/Form/Select/Select.tsx +217 -0
  153. package/src/Form/Textarea/Textarea.module.scss +53 -0
  154. package/src/Form/Textarea/Textarea.test.tsx +76 -0
  155. package/src/Form/Textarea/Textarea.tsx +33 -0
  156. package/src/Form/Toggle/Toggle.module.scss +58 -0
  157. package/src/Form/Toggle/Toggle.test.tsx +29 -0
  158. package/src/Form/Toggle/Toggle.tsx +20 -0
  159. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.module.scss +12 -0
  160. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.test.tsx +99 -0
  161. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.tsx +62 -0
  162. package/src/Form/Wrapper/InputWrapper/InputWrapper.module.scss +24 -0
  163. package/src/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +93 -0
  164. package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +92 -0
  165. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.module.scss +12 -0
  166. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.test.tsx +101 -0
  167. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.tsx +74 -0
  168. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.module.scss +14 -0
  169. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.test.tsx +101 -0
  170. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.tsx +59 -0
  171. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.module.scss +65 -0
  172. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.test.tsx +125 -0
  173. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.tsx +105 -0
  174. package/src/Form/Wrapper/Wrapper/Wrapper.module.scss +35 -0
  175. package/src/Form/Wrapper/Wrapper/Wrapper.test.tsx +17 -0
  176. package/src/Form/Wrapper/Wrapper/Wrapper.tsx +101 -0
  177. package/src/Form/form.interfaces.ts +14 -0
  178. package/src/Icon/Icon.module.scss +278 -0
  179. package/src/Icon/Icon.test.tsx +39 -0
  180. package/src/Icon/Icon.tsx +94 -0
  181. package/src/Link/Link.module.scss +46 -0
  182. package/src/Link/Link.test.tsx +122 -0
  183. package/src/Link/Link.tsx +80 -0
  184. package/src/Link/types.d.ts +9 -0
  185. package/src/Modal/Modal.test.tsx +16 -0
  186. package/src/Modal/Modal.tsx +1 -0
  187. package/src/Modal/ModalActions/ModalActions.tsx +4 -0
  188. package/src/Modal/ModalContent/ModalContent.tsx +4 -0
  189. package/src/Modal/ModalHeader/ModalHeader.tsx +4 -0
  190. package/src/Popover/Popover.module.scss +18 -0
  191. package/src/Popover/Popover.test.tsx +84 -0
  192. package/src/Popover/Popover.tsx +46 -0
  193. package/src/Snackbar/SnackbarContainer/SnackbarContainer.module.scss +35 -0
  194. package/src/Snackbar/SnackbarContainer/SnackbarContainer.test.tsx +37 -0
  195. package/src/Snackbar/SnackbarContainer/SnackbarContainer.tsx +28 -0
  196. package/src/Snackbar/SnackbarItem/SnackbarItem.module.scss +135 -0
  197. package/src/Snackbar/SnackbarItem/SnackbarItem.test.tsx +47 -0
  198. package/src/Snackbar/SnackbarItem/SnackbarItem.tsx +105 -0
  199. package/src/Snackbar/SnackbarProvider/SnackbarProvider.test.tsx +179 -0
  200. package/src/Snackbar/SnackbarProvider/SnackbarProvider.tsx +127 -0
  201. package/src/Snackbar/SnackbarProvider/SnackbarStateProvider.tsx +25 -0
  202. package/src/Snackbar/interfaces.ts +11 -0
  203. package/src/Snackbar/useSnackbar.ts +4 -0
  204. package/src/Tiles/Tile.module.scss +72 -0
  205. package/src/Tiles/Tile.test.tsx +129 -0
  206. package/src/Tiles/Tile.tsx +48 -0
  207. package/src/Tiles/Tiles.module.scss +11 -0
  208. package/src/Tiles/Tiles.test.tsx +118 -0
  209. package/src/Tiles/Tiles.tsx +48 -0
  210. package/src/Tooltip/Tooltip.module.scss +42 -0
  211. package/src/Tooltip/Tooltip.test.tsx +72 -0
  212. package/src/Tooltip/Tooltip.tsx +130 -0
  213. package/src/Typography/Typography.module.scss +46 -0
  214. package/src/Typography/Typography.test.tsx +114 -0
  215. package/src/Typography/Typography.tsx +84 -0
  216. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.module.scss +192 -0
  217. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.test.tsx +75 -0
  218. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +86 -0
  219. package/src/Wizard/Wizard.test.tsx +198 -0
  220. package/src/Wizard/Wizard.tsx +49 -0
  221. package/src/Wizard/WizardActions/WizardActions.test.tsx +168 -0
  222. package/src/Wizard/WizardActions/WizardActions.tsx +100 -0
  223. package/src/Wizard/WizardStateProvider.tsx +26 -0
  224. package/src/Wizard/WizardSteps/WizardSteps.test.tsx +110 -0
  225. package/src/Wizard/WizardSteps/WizardSteps.tsx +30 -0
  226. package/src/Wizard/wizardStateReducer.ts +51 -0
  227. package/src/_BaseStyling_/BaseStyling.test.tsx +39 -0
  228. package/src/_BaseStyling_/BaseStyling.tsx +115 -0
  229. package/src/hooks/useAnimation.test.tsx +45 -0
  230. package/src/hooks/useAnimation.ts +20 -0
  231. package/src/hooks/useBodyClick.test.tsx +39 -0
  232. package/src/hooks/useBodyClick.ts +20 -0
  233. package/src/hooks/useFormSelector.test.ts +40 -0
  234. package/src/hooks/useFormSelector.ts +47 -0
  235. package/src/hooks/usePosition.test.tsx +494 -0
  236. package/src/hooks/usePosition.ts +347 -0
  237. package/src/hooks/useScroll.test.tsx +20 -0
  238. package/src/hooks/useScroll.ts +16 -0
  239. package/src/hooks/useSpacing.test.ts +70 -0
  240. package/src/hooks/useSpacing.ts +42 -0
  241. package/src/hooks/useWrapper.test.ts +49 -0
  242. package/src/hooks/useWrapper.ts +35 -0
  243. package/src/index.ts +52 -0
  244. package/src/interfaces.ts +15 -0
  245. package/src/readyclasses.module.scss +77 -0
  246. package/src/types.d.ts +4 -0
  247. package/src/util/helper.test.tsx +15 -0
  248. package/src/util/helper.tsx +80 -0
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import { InputWrapper, Props } from './InputWrapper';
3
+ import { render } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+
6
+ const defaultParams: Props = {
7
+ label: 'Example label',
8
+ type: 'text',
9
+ name: 'Example input',
10
+ helperText: 'this is helpertext',
11
+ errorMessage: 'This is an error',
12
+ error: false,
13
+ value: 'value',
14
+ onChange: jest.fn(),
15
+ };
16
+
17
+ const createInputWrapper = (params?: (defaultParams: Props) => Props) => {
18
+ let parameters: Props = defaultParams;
19
+ if (params) {
20
+ parameters = params(defaultParams);
21
+ }
22
+ const queries = render(<InputWrapper {...parameters} data-testid="inputwrapper" />);
23
+ const inputwrapper = queries.getByTestId('inputwrapper');
24
+
25
+ return {
26
+ ...queries,
27
+ inputwrapper,
28
+ };
29
+ };
30
+
31
+ describe('InputWrapper should render', () => {
32
+ it('renders without crashing', () => {
33
+ const { inputwrapper } = createInputWrapper();
34
+
35
+ expect(inputwrapper).toBeTruthy();
36
+ });
37
+
38
+ it('has helpertext', () => {
39
+ const { getByTestId } = createInputWrapper((defaultParams) => ({
40
+ ...defaultParams,
41
+ helperProps: { 'data-testid': 'helper_text' },
42
+ }));
43
+
44
+ const helperText = getByTestId('helper_text');
45
+
46
+ expect(helperText).toBeTruthy();
47
+ });
48
+
49
+ it('is described by the helpertext', () => {
50
+ const { getByTestId } = createInputWrapper((defaultParams) => ({
51
+ ...defaultParams,
52
+ inputProps: { 'data-testid': 'input' },
53
+ helperProps: { 'data-testid': 'helper_text' },
54
+ }));
55
+
56
+ const input = getByTestId('input');
57
+ const helperId = getByTestId('helper_text').getAttribute('id');
58
+
59
+ expect(input).toHaveAttribute('aria-describedby', helperId);
60
+ });
61
+ });
62
+
63
+ describe('InputWrapper should be interactive', () => {
64
+ it('executes the eventlisteners', () => {
65
+ const onFocusHandler = jest.fn();
66
+ const onChangeHandler = jest.fn();
67
+ const onBlurHandler = jest.fn();
68
+
69
+ const { getByTestId } = createInputWrapper((defaultParams) => ({
70
+ ...defaultParams,
71
+ inputProps: {
72
+ 'data-testid': 'input',
73
+ },
74
+ onChange: onChangeHandler,
75
+ onFocus: onFocusHandler,
76
+ onBlur: onBlurHandler,
77
+ value: '',
78
+ }));
79
+
80
+ const input = getByTestId('input');
81
+
82
+ userEvent.tab();
83
+ userEvent.keyboard('test');
84
+
85
+ expect(input).toHaveFocus();
86
+ expect(onChangeHandler).toHaveBeenCalled();
87
+ expect(onFocusHandler).toHaveBeenCalled();
88
+
89
+ userEvent.tab();
90
+
91
+ expect(onBlurHandler).toHaveBeenCalled();
92
+ });
93
+ });
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import { Input, Type, Props as InputProps } from '../../Input/Input';
3
+ import classes from './InputWrapper.module.scss';
4
+ import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
5
+ import { useWrapper } from '../../../hooks/useWrapper';
6
+
7
+ interface OptionalInputProps extends Omit<InputProps, 'type'> {}
8
+
9
+ export interface Props extends WrapperProps {
10
+ label: string;
11
+ type: Type;
12
+ name: string;
13
+ inputProps?: OptionalInputProps;
14
+ value: string;
15
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
16
+ onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
17
+ onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
18
+ }
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);
42
+
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'] : ''}
84
+ name={name}
85
+ error={error}
86
+ id={name}
87
+ value={value}
88
+ type={type}
89
+ />
90
+ </Wrapper>
91
+ );
92
+ };
@@ -0,0 +1,12 @@
1
+ .radio-wrapper-helper {
2
+ margin-top: 1.25rem;
3
+ }
4
+
5
+ .radio-wrapper-error span {
6
+ font-size: 1rem;
7
+ }
8
+
9
+ .radio-wrapper-error [data-icon] {
10
+ font-size: 1.25rem;
11
+ vertical-align: bottom;
12
+ }
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { RadioWrapper, Props } from './RadioWrapper';
3
+ import { Radio } from '../../Radio/Radio';
4
+ import { render } from '@testing-library/react';
5
+
6
+ const onChangeHandler = jest.fn();
7
+ const checkedOptionValue = 'option1';
8
+
9
+ const defaultParams: Props = {
10
+ label: 'Label',
11
+ errorMessage: 'Error message',
12
+ helperText: 'Helper text',
13
+ error: false,
14
+ onChange: onChangeHandler,
15
+ fieldsetProps: { title: 'Example title' },
16
+ value: checkedOptionValue,
17
+ name: 'my-group',
18
+ children: [
19
+ <Radio helperText="This is helpertext" value="option1">
20
+ Option 1
21
+ </Radio>,
22
+ <Radio value="option2">Option 2</Radio>,
23
+ <Radio value="option3">Option 3</Radio>,
24
+ ],
25
+ };
26
+
27
+ const createRadioWrapper = (params?: (defaultParams: Props) => Props) => {
28
+ let parameters: Props = defaultParams;
29
+ if (params) {
30
+ parameters = params(defaultParams);
31
+ }
32
+ const queries = render(<RadioWrapper {...parameters} data-testid="radiowrapper" />);
33
+ const radiowrapper = queries.getByTestId('radiowrapper');
34
+
35
+ return {
36
+ ...queries,
37
+ radiowrapper,
38
+ };
39
+ };
40
+
41
+ describe('RadioWrapper should render', () => {
42
+ it('renders without crashing', () => {
43
+ const { radiowrapper } = createRadioWrapper();
44
+
45
+ expect(radiowrapper).toBeTruthy();
46
+ });
47
+
48
+ it('has option 1 properly linked with aria-describedby to its helpertext', () => {
49
+ const { radiowrapper } = createRadioWrapper();
50
+
51
+ const option1RadioWrapper = radiowrapper
52
+ ?.querySelector('input[value="option1"]')
53
+ ?.closest('.radio-wrapper');
54
+ const option1 = radiowrapper?.querySelector('input[value="option1"]');
55
+ const option1helper = option1RadioWrapper?.querySelector('.helper-text');
56
+
57
+ if (option1helper && option1) {
58
+ expect(`${option1helper.getAttribute('id')}-radio`).toBe(`${option1.getAttribute('id')}`);
59
+ expect(option1).toHaveAccessibleDescription();
60
+ expect(option1).toHaveAttribute('aria-describedby', option1helper.getAttribute('id'));
61
+ }
62
+ });
63
+
64
+ it("has all option's aria-describedby linked with the error message ID", () => {
65
+ const { radiowrapper } = createRadioWrapper((defaultParams) => ({
66
+ ...defaultParams,
67
+ error: true,
68
+ errorMessage: 'This is an error message',
69
+ }));
70
+
71
+ const errorMessage = radiowrapper?.querySelector('.error-message .message');
72
+ const option1 = radiowrapper?.querySelector('input[value="option1"]');
73
+
74
+ expect(errorMessage).toBeTruthy();
75
+ if (errorMessage) {
76
+ expect(option1).toHaveAttribute('aria-describedby', errorMessage.id);
77
+ }
78
+ });
79
+ });
80
+
81
+ describe('RadioWrapper selection', () => {
82
+ it('has option 2 selected, the rest is unselected', () => {
83
+ const { radiowrapper } = createRadioWrapper((defaultParams) => ({
84
+ ...defaultParams,
85
+ value: 'option2',
86
+ }));
87
+
88
+ expect(radiowrapper?.querySelector('input[value="option1"]')).toHaveAttribute(
89
+ 'aria-checked',
90
+ 'false'
91
+ );
92
+ expect(radiowrapper?.querySelector('input[value="option2"]')).toHaveAttribute(
93
+ 'aria-checked',
94
+ 'true'
95
+ );
96
+ expect(radiowrapper?.querySelector('input[value="option3"]')).toHaveAttribute(
97
+ 'aria-checked',
98
+ 'false'
99
+ );
100
+ });
101
+ });
@@ -0,0 +1,74 @@
1
+ import React, { ReactElement, useEffect } from 'react';
2
+ import classes from './RadioWrapper.module.scss';
3
+ import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
4
+ import { useWrapper } from '../../../hooks/useWrapper';
5
+ import { Icons } from '../../../Icon/Icon';
6
+ import { Fieldset, Props as FieldsetProps } from '../../../Form/Fieldset/Fieldset';
7
+
8
+ export interface Props extends WrapperProps {
9
+ children: ReactElement | ReactElement[];
10
+ fieldsetProps: FieldsetProps;
11
+ value: string;
12
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
13
+ }
14
+
15
+ export const RadioWrapper = ({
16
+ children,
17
+ error,
18
+ name,
19
+ helperText,
20
+ helperProps,
21
+ fieldsetProps,
22
+ value,
23
+ onChange,
24
+ disabled,
25
+ ...rest
26
+ }: Props) => {
27
+ const { errorId, helperId } = useWrapper(value);
28
+
29
+ useEffect(() => {
30
+ if (fieldsetProps.title === undefined) {
31
+ console.error(
32
+ `You should give your Fieldset component a title prop so a legend element is rendered. This error was thrown in RadioWrapper. You can add this title prop through the fieldsetProps prop by passing an object (fieldsetProps={{ title: "title here" }})`
33
+ );
34
+ }
35
+ }, []);
36
+
37
+ const renderChildren = () =>
38
+ React.Children.map(children, (child) =>
39
+ React.cloneElement(child, {
40
+ parentErrorId: errorId,
41
+ error: error,
42
+ checked: child.props.value === value,
43
+ name: name,
44
+ parentHelperId: helperText ? helperId : false,
45
+ onChange: onChange,
46
+ disabled: child.props.disabled !== undefined ? child.props.disabled : disabled,
47
+ })
48
+ );
49
+
50
+ return (
51
+ <Fieldset {...fieldsetProps}>
52
+ <Wrapper
53
+ {...rest}
54
+ disabled={disabled}
55
+ name={name}
56
+ label=""
57
+ helperId={helperId}
58
+ helperText={helperText}
59
+ helperProps={{
60
+ ...helperProps,
61
+ className: `${classes['radio-wrapper-helper']} ${
62
+ error ? classes['radio-wrapper-error'] : ''
63
+ } ${helperProps?.className ?? ''}`,
64
+ }}
65
+ error={error}
66
+ errorId={errorId}
67
+ errorMessageIcon={Icons.Warning}
68
+ floatingLabel={false}
69
+ >
70
+ {renderChildren()}
71
+ </Wrapper>
72
+ </Fieldset>
73
+ );
74
+ };
@@ -0,0 +1,14 @@
1
+ .select-label {
2
+ left: calc(
3
+ 1.25rem + 2px
4
+ ); // 2px is for offset of the textarea border. It's relative to the parent div which doesn't have a border.
5
+ }
6
+
7
+ .select-helper-text {
8
+ margin-top: 0.25rem;
9
+ margin-left: 1.25rem;
10
+ }
11
+
12
+ .floating-label-active [data-display] {
13
+ top: calc(50% + 0.5rem);
14
+ }
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { SelectWrapper, Props } from './SelectWrapper';
3
+ import { render } from '@testing-library/react';
4
+ import { Option } from '../../Select/Option';
5
+ import userEvent from '@testing-library/user-event';
6
+
7
+ const onChangeHandler = jest.fn();
8
+
9
+ const defaultParams: Props = {
10
+ children: [
11
+ <Option key="1" value="option1">
12
+ Option 1
13
+ </Option>,
14
+ <Option key="2" value="option2">
15
+ Option 2
16
+ </Option>,
17
+ <Option key="3" value="option3">
18
+ Option 3
19
+ </Option>,
20
+ <Option key="4" value="option4">
21
+ Option 4
22
+ </Option>,
23
+ ],
24
+ label: 'select_label',
25
+ name: 'select',
26
+ helperText: 'helpertext',
27
+ helperProps: { 'data-testid': 'helpertext' },
28
+ errorMessage: 'errormessage',
29
+ error: false,
30
+ value: 'option1',
31
+ onChange: onChangeHandler,
32
+ };
33
+
34
+ const createSelectWrapper = (params?: (defaultParams: Props) => Props) => {
35
+ let parameters: Props = defaultParams;
36
+ if (params) {
37
+ parameters = params(defaultParams);
38
+ }
39
+ const queries = render(<SelectWrapper {...parameters} data-testid="selectwrapper" />);
40
+ const selectwrapper = queries.getByTestId('selectwrapper');
41
+ const select = selectwrapper.querySelector('button');
42
+
43
+ return {
44
+ ...queries,
45
+ selectwrapper,
46
+ select,
47
+ };
48
+ };
49
+
50
+ describe('SelectWrapper should render', () => {
51
+ it('renders without crashing', () => {
52
+ const { selectwrapper } = createSelectWrapper();
53
+
54
+ expect(selectwrapper).toBeDefined();
55
+ });
56
+ });
57
+
58
+ describe('SelectWrapper & Select have the right attributes', () => {
59
+ it('select has aria values', async () => {
60
+ const { select, getByTestId, findByText } = createSelectWrapper();
61
+
62
+ const helpertext = getByTestId('helpertext');
63
+ const label = await findByText('select_label');
64
+
65
+ expect(select).toHaveAttribute('aria-describedby', helpertext.id);
66
+ expect(select).toHaveAttribute('aria-labelledby', label.id);
67
+ });
68
+
69
+ it('SelectWrapper has the right helpertext', () => {
70
+ const { getByTestId } = createSelectWrapper();
71
+
72
+ const helpertext = getByTestId('helpertext');
73
+
74
+ expect(helpertext).toBeTruthy();
75
+ expect(helpertext).toHaveTextContent('helpertext');
76
+ });
77
+
78
+ it('SelectWrapper has the right errormessage', async () => {
79
+ const { findByText, select } = createSelectWrapper((defaultParams) => ({
80
+ ...defaultParams,
81
+ error: true,
82
+ }));
83
+
84
+ const errorMessage = await findByText('errormessage');
85
+
86
+ expect(errorMessage).toBeTruthy();
87
+ expect(select).toHaveAttribute('aria-describedby', errorMessage.id);
88
+ });
89
+
90
+ it('Fires the onChange event', async () => {
91
+ const { select, findByText } = createSelectWrapper();
92
+
93
+ userEvent.click(select as Element);
94
+
95
+ const option3 = await findByText('Option 3');
96
+
97
+ userEvent.click(option3 as Element);
98
+
99
+ expect(onChangeHandler).toHaveBeenCalled();
100
+ });
101
+ });
@@ -0,0 +1,59 @@
1
+ import React, { ReactChild, ReactElement } from 'react';
2
+ import classes from './SelectWrapper.module.scss';
3
+ import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
4
+ import { Select, Props as SelectProps } from '../../Select/Select';
5
+ import { useWrapper } from '../../../hooks/useWrapper';
6
+
7
+ export interface Props extends Omit<WrapperProps, 'onChange'> {
8
+ children: ReactChild | ReactChild[];
9
+ placeholder?: string;
10
+ value: string;
11
+ selectProps?: SelectProps;
12
+ onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
13
+ onClear?: () => void;
14
+ }
15
+
16
+ export const SelectWrapper = ({
17
+ children,
18
+ error,
19
+ value,
20
+ placeholder,
21
+ selectProps,
22
+ helperProps,
23
+ onChange,
24
+ onClear,
25
+ ...rest
26
+ }: Props) => {
27
+ const { errorId, floatingLabelActive, helperId, labelId } = useWrapper(value, placeholder);
28
+
29
+ return (
30
+ <Wrapper
31
+ {...rest}
32
+ floatingLabelActive={floatingLabelActive}
33
+ errorId={errorId}
34
+ helperId={helperId}
35
+ labelProps={{ id: labelId, className: classes['select-label'] }}
36
+ helperProps={{
37
+ ...helperProps,
38
+ className: `${classes['select-helper-text']} ${helperProps?.className ?? ''}`,
39
+ }}
40
+ error={error}
41
+ >
42
+ <Select
43
+ {...selectProps}
44
+ value={value}
45
+ labeledBy={labelId}
46
+ error={error}
47
+ describedBy={error ? errorId : helperId}
48
+ onChange={onChange}
49
+ onClear={onClear}
50
+ placeholder={placeholder}
51
+ className={`${floatingLabelActive ? classes['floating-label-active'] : ''} ${
52
+ selectProps?.className ?? ''
53
+ }`}
54
+ >
55
+ {children as ReactElement[]}
56
+ </Select>
57
+ </Wrapper>
58
+ );
59
+ };
@@ -0,0 +1,65 @@
1
+ .textarea-label {
2
+ left: calc(
3
+ 1.25rem + 2px
4
+ ); // 2px is for offset of the textarea border. It's relative to the parent div which doesn't have a border.
5
+
6
+ &.focus {
7
+ color: var(--color-primary);
8
+ }
9
+ }
10
+
11
+ .textarea {
12
+ border: 0;
13
+ padding-top: 0;
14
+ padding-right: 0;
15
+
16
+ &:active:not(:disabled) {
17
+ border-color: white;
18
+ }
19
+
20
+ &:hover:not(:disabled) {
21
+ border-color: white;
22
+ }
23
+
24
+ &:focus:not(:disabled) {
25
+ outline: none;
26
+ }
27
+ }
28
+
29
+ .textarea-helper-text {
30
+ margin-top: 0.25rem;
31
+ margin-left: 1.25rem;
32
+ }
33
+
34
+ .textarea-wrapper {
35
+ padding-top: 1.75rem;
36
+ padding-right: 3.75rem;
37
+ padding-bottom: 0.75rem;
38
+ border-color: var(--input-border-color);
39
+ border-style: var(--input-border-style);
40
+ border-width: var(--input-border-width);
41
+ border-radius: var(--input-border-radius);
42
+
43
+ &.error {
44
+ border-color: var(--error);
45
+ }
46
+
47
+ &.hover {
48
+ border-color: var(--default);
49
+ }
50
+
51
+ &.focus {
52
+ border-color: var(--color-primary);
53
+ }
54
+
55
+ &.disabled {
56
+ color: var(--greyed-out);
57
+ background-color: var(--disabled);
58
+ border-color: #fff;
59
+ cursor: not-allowed;
60
+ }
61
+ }
62
+
63
+ .error-icon {
64
+ top: 1.75rem;
65
+ }