@onewelcome/react-lib-components 0.1.1-alpha → 0.1.4-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 (180) 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 +3 -4
  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 +4 -4
  9. package/dist/Form/FormControl/FormControl.d.ts +5 -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 +7 -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 +4 -6
  29. package/dist/Notifications/BaseModal/BaseModal.d.ts +3 -4
  30. package/dist/Notifications/BaseModal/BaseModalActions/BaseModalActions.d.ts +3 -3
  31. package/dist/Notifications/BaseModal/BaseModalContent/BaseModalContent.d.ts +3 -3
  32. package/dist/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.d.ts +3 -3
  33. package/dist/Notifications/Dialog/Dialog.d.ts +3 -3
  34. package/dist/Notifications/Dialog/DialogActions/DialogActions.d.ts +3 -3
  35. package/dist/Notifications/Dialog/DialogTitle/DialogTitle.d.ts +3 -3
  36. package/dist/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.d.ts +5 -4
  37. package/dist/Notifications/DiscardChangesModal/DiscardChangesModal.d.ts +3 -1
  38. package/dist/Pagination/Pagination.d.ts +19 -0
  39. package/dist/Popover/Popover.d.ts +3 -3
  40. package/dist/Tabs/Tab.d.ts +11 -0
  41. package/dist/Tabs/TabButton.d.ts +10 -0
  42. package/dist/Tabs/TabPanel.d.ts +8 -0
  43. package/dist/Tabs/Tabs.d.ts +9 -0
  44. package/dist/TextEllipsis/TextEllipsis.d.ts +6 -0
  45. package/dist/Tiles/Tile.d.ts +3 -3
  46. package/dist/Tiles/Tiles.d.ts +3 -3
  47. package/dist/Tooltip/Tooltip.d.ts +3 -3
  48. package/dist/Typography/Typography.d.ts +6 -4
  49. package/dist/Wizard/BaseWizardSteps/BaseWizardSteps.d.ts +3 -3
  50. package/dist/Wizard/WizardSteps/WizardSteps.d.ts +3 -3
  51. package/dist/_BaseStyling_/BaseStyling.d.ts +9 -0
  52. package/dist/hooks/useRepeater.d.ts +10 -0
  53. package/dist/hooks/useSpacing.d.ts +2 -2
  54. package/dist/hooks/useWrapper.d.ts +1 -1
  55. package/dist/index.d.ts +6 -0
  56. package/dist/interfaces.d.ts +2 -11
  57. package/dist/react-lib-components.cjs.development.js +2395 -1696
  58. package/dist/react-lib-components.cjs.development.js.map +1 -1
  59. package/dist/react-lib-components.cjs.production.min.js +1 -1
  60. package/dist/react-lib-components.cjs.production.min.js.map +1 -1
  61. package/dist/react-lib-components.esm.js +2391 -1698
  62. package/dist/react-lib-components.esm.js.map +1 -1
  63. package/dist/util/helper.d.ts +6 -1
  64. package/package.json +30 -24
  65. package/src/Breadcrumbs/Breadcrumbs.tsx +39 -37
  66. package/src/Button/BaseButton.test.tsx +65 -19
  67. package/src/Button/BaseButton.tsx +2 -3
  68. package/src/Button/Button.test.tsx +63 -17
  69. package/src/Button/Button.tsx +15 -4
  70. package/src/Button/IconButton.test.tsx +57 -22
  71. package/src/Button/IconButton.tsx +14 -9
  72. package/src/ContextMenu/ContextMenu.test.tsx +27 -1
  73. package/src/ContextMenu/ContextMenu.tsx +70 -65
  74. package/src/Form/Checkbox/Checkbox.test.tsx +28 -2
  75. package/src/Form/Checkbox/Checkbox.tsx +132 -122
  76. package/src/Form/Fieldset/Fieldset.test.tsx +28 -2
  77. package/src/Form/Fieldset/Fieldset.tsx +96 -50
  78. package/src/Form/FormControl/FormControl.test.tsx +27 -1
  79. package/src/Form/FormControl/FormControl.tsx +36 -39
  80. package/src/Form/FormGroup/FormGroup.test.tsx +51 -1
  81. package/src/Form/FormGroup/FormGroup.tsx +64 -58
  82. package/src/Form/FormHelperText/FormHelperText.test.tsx +27 -1
  83. package/src/Form/FormHelperText/FormHelperText.tsx +20 -16
  84. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.test.tsx +78 -0
  85. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.tsx +61 -55
  86. package/src/Form/Input/Input.module.scss +34 -15
  87. package/src/Form/Input/Input.test.tsx +27 -1
  88. package/src/Form/Input/Input.tsx +88 -47
  89. package/src/Form/Label/Label.test.tsx +27 -1
  90. package/src/Form/Label/Label.tsx +18 -14
  91. package/src/Form/Radio/Radio.test.tsx +28 -2
  92. package/src/Form/Radio/Radio.tsx +98 -90
  93. package/src/Form/Select/Option.test.tsx +27 -1
  94. package/src/Form/Select/Option.tsx +49 -42
  95. package/src/Form/Select/Select.module.scss +5 -1
  96. package/src/Form/Select/Select.test.tsx +224 -30
  97. package/src/Form/Select/Select.tsx +248 -182
  98. package/src/Form/Textarea/Textarea.module.scss +2 -1
  99. package/src/Form/Textarea/Textarea.test.tsx +28 -2
  100. package/src/Form/Textarea/Textarea.tsx +44 -29
  101. package/src/Form/Toggle/Toggle.module.scss +9 -0
  102. package/src/Form/Toggle/Toggle.test.tsx +27 -1
  103. package/src/Form/Toggle/Toggle.tsx +25 -12
  104. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.test.tsx +27 -1
  105. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.tsx +45 -48
  106. package/src/Form/Wrapper/InputWrapper/InputWrapper.module.scss +17 -1
  107. package/src/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +89 -1
  108. package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +134 -74
  109. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.tsx +64 -59
  110. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.module.scss +1 -1
  111. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.test.tsx +43 -1
  112. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.tsx +54 -44
  113. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.module.scss +5 -7
  114. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.test.tsx +43 -1
  115. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.tsx +100 -85
  116. package/src/Form/Wrapper/Wrapper/Wrapper.module.scss +1 -1
  117. package/src/Form/Wrapper/Wrapper/Wrapper.test.tsx +27 -1
  118. package/src/Form/Wrapper/Wrapper/Wrapper.tsx +76 -71
  119. package/src/Form/form.interfaces.ts +4 -3
  120. package/src/Icon/Icon.module.scss +4 -0
  121. package/src/Icon/Icon.test.tsx +30 -2
  122. package/src/Icon/Icon.tsx +5 -5
  123. package/src/Link/Link.test.tsx +27 -1
  124. package/src/Link/Link.tsx +10 -7
  125. package/src/Notifications/BaseModal/BaseModal.test.tsx +27 -1
  126. package/src/Notifications/BaseModal/BaseModal.tsx +59 -54
  127. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.test.tsx +26 -1
  128. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.tsx +11 -9
  129. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.test.tsx +27 -1
  130. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.tsx +27 -26
  131. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.test.tsx +29 -1
  132. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.tsx +18 -16
  133. package/src/Notifications/Dialog/Dialog.test.tsx +39 -1
  134. package/src/Notifications/Dialog/Dialog.tsx +84 -78
  135. package/src/Notifications/Dialog/DialogActions/DialogActions.test.tsx +27 -1
  136. package/src/Notifications/Dialog/DialogActions/DialogActions.tsx +15 -12
  137. package/src/Notifications/Dialog/DialogTitle/DialogTitle.test.tsx +28 -2
  138. package/src/Notifications/Dialog/DialogTitle/DialogTitle.tsx +13 -11
  139. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.test.tsx +41 -1
  140. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.tsx +43 -36
  141. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.test.tsx +52 -1
  142. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.tsx +8 -3
  143. package/src/Notifications/Snackbar/SnackbarItem/SnackbarItem.tsx +1 -1
  144. package/src/Pagination/Pagination.module.scss +120 -0
  145. package/src/Pagination/Pagination.test.tsx +176 -0
  146. package/src/Pagination/Pagination.tsx +205 -0
  147. package/src/Popover/Popover.tsx +3 -3
  148. package/src/Tabs/Tab.test.tsx +71 -0
  149. package/src/Tabs/Tab.tsx +17 -0
  150. package/src/Tabs/TabButton.module.scss +36 -0
  151. package/src/Tabs/TabButton.test.tsx +77 -0
  152. package/src/Tabs/TabButton.tsx +58 -0
  153. package/src/Tabs/TabPanel.module.scss +7 -0
  154. package/src/Tabs/TabPanel.test.tsx +76 -0
  155. package/src/Tabs/TabPanel.tsx +27 -0
  156. package/src/Tabs/Tabs.module.scss +41 -0
  157. package/src/Tabs/Tabs.test.tsx +268 -0
  158. package/src/Tabs/Tabs.tsx +149 -0
  159. package/src/TextEllipsis/TextEllipsis.module.scss +18 -0
  160. package/src/TextEllipsis/TextEllipsis.test.tsx +80 -0
  161. package/src/TextEllipsis/TextEllipsis.tsx +55 -0
  162. package/src/Tiles/Tile.test.tsx +27 -1
  163. package/src/Tiles/Tile.tsx +59 -62
  164. package/src/Tiles/Tiles.test.tsx +27 -1
  165. package/src/Tiles/Tiles.tsx +42 -39
  166. package/src/Tooltip/Tooltip.test.tsx +27 -1
  167. package/src/Tooltip/Tooltip.tsx +104 -92
  168. package/src/Typography/Typography.test.tsx +27 -1
  169. package/src/Typography/Typography.tsx +66 -68
  170. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +67 -62
  171. package/src/Wizard/WizardSteps/WizardSteps.tsx +24 -21
  172. package/src/_BaseStyling_/BaseStyling.tsx +19 -1
  173. package/src/hooks/useRepeater.test.tsx +139 -0
  174. package/src/hooks/useRepeater.ts +34 -0
  175. package/src/hooks/useSpacing.ts +1 -1
  176. package/src/hooks/useWrapper.ts +7 -2
  177. package/src/index.ts +15 -1
  178. package/src/interfaces.ts +2 -12
  179. package/src/util/helper.test.tsx +38 -1
  180. package/src/util/helper.tsx +21 -0
@@ -1,65 +1,71 @@
1
- import React, { ReactNode } from 'react';
1
+ import React, { ComponentPropsWithRef, createRef, ReactNode } from 'react';
2
2
  import { Icon, Icons } from '../../Icon/Icon';
3
- import { HTMLProps } from '../../interfaces';
3
+ import { KeyValuePair } from '../../interfaces';
4
+ import { FormSelector } from '../form.interfaces';
4
5
  import { FormHelperText, Props as FormHelperTextProps } from '../FormHelperText/FormHelperText';
5
6
  import classes from './FormSelectorWrapper.module.scss';
6
7
 
7
- export interface Props extends HTMLProps<HTMLDivElement> {
8
+ export interface Props extends ComponentPropsWithRef<'div'>, FormSelector {
8
9
  children?: ReactNode;
9
10
  nestedChildren?: ReactNode;
10
- containerProps: HTMLProps<HTMLDivElement>;
11
+ containerProps?: ComponentPropsWithRef<'div'> & KeyValuePair;
11
12
  helperProps?: FormHelperTextProps;
12
- error?: boolean;
13
13
  disabled?: boolean;
14
- helperText?: string;
15
- errorMessage?: string;
16
- parentHelperId?: string;
17
- parentErrorId?: string;
18
- errorId: string;
19
- identifier: string;
14
+ errorId?: string;
15
+ identifier?: string;
20
16
  }
21
17
 
22
- export const FormSelectorWrapper = ({
23
- children,
24
- className,
25
- nestedChildren,
26
- containerProps,
27
- helperProps,
28
- error,
29
- disabled,
30
- helperText,
31
- errorMessage,
32
- parentErrorId,
33
- errorId,
34
- identifier,
35
- ...rest
36
- }: Props) => {
37
- return (
38
- <div
39
- {...rest}
40
- className={`${error ? classes['error'] : ''} ${disabled ? classes['disabled'] : ''} ${
41
- className ?? ''
42
- }`}
43
- >
44
- <div {...containerProps}>{children}</div>
45
- {helperText && (!error || parentErrorId || !errorMessage) && (
46
- <FormHelperText
47
- {...helperProps}
48
- id={`${identifier}`}
49
- className={`${classes['helper-text']} ${helperProps?.className ?? ''} ${
50
- error ? classes['error'] : ''
51
- }`}
52
- >
53
- {helperText}
54
- </FormHelperText>
55
- )}
56
- {errorMessage && !parentErrorId && error && (
57
- <span className={classes['error-message']}>
58
- <Icon className={classes['error-icon']} icon={Icons.Warning} />
59
- <span id={errorId}>{errorMessage}</span>
60
- </span>
61
- )}
62
- {nestedChildren}
63
- </div>
64
- );
65
- };
18
+ export const FormSelectorWrapper = React.forwardRef<HTMLDivElement, Props>(
19
+ (
20
+ {
21
+ children,
22
+ className,
23
+ nestedChildren,
24
+ containerProps,
25
+ helperProps,
26
+ error,
27
+ disabled,
28
+ helperText,
29
+ errorMessage,
30
+ parentErrorId,
31
+ errorId,
32
+ identifier,
33
+ ...rest
34
+ }: Props,
35
+ ref
36
+ ) => {
37
+ const helperRef = helperProps?.ref || createRef();
38
+
39
+ return (
40
+ <div
41
+ {...rest}
42
+ ref={ref}
43
+ className={`${error ? classes['error'] : ''} ${disabled ? classes['disabled'] : ''} ${
44
+ className ?? ''
45
+ }`}
46
+ >
47
+ <div {...containerProps}>{children}</div>
48
+ {(helperText || (helperProps && helperProps.children)) &&
49
+ (!error || parentErrorId || !errorMessage) && (
50
+ <FormHelperText
51
+ {...helperProps}
52
+ ref={helperRef}
53
+ id={`${identifier}`}
54
+ className={`${classes['helper-text']} ${helperProps?.className ?? ''} ${
55
+ error ? classes['error'] : ''
56
+ }`}
57
+ >
58
+ {(helperProps && helperProps.children) || helperText}
59
+ </FormHelperText>
60
+ )}
61
+ {errorMessage && !parentErrorId && error && (
62
+ <span className={classes['error-message']}>
63
+ <Icon className={classes['error-icon']} icon={Icons.Error} />
64
+ <span id={errorId}>{errorMessage}</span>
65
+ </span>
66
+ )}
67
+ {nestedChildren}
68
+ </div>
69
+ );
70
+ }
71
+ );
@@ -1,31 +1,44 @@
1
1
  .input-wrapper {
2
2
  position: relative;
3
- }
4
-
5
- .input {
6
- height: 4rem;
3
+ display: flex;
4
+ align-items: center;
7
5
  padding: 0 1.25rem;
6
+ background-color: var(--input-background-color);
8
7
  border-color: var(--input-border-color);
9
8
  border-style: var(--input-border-style);
10
9
  border-width: var(--input-border-width);
11
10
  border-radius: var(--input-border-radius);
12
11
  transition: all 0.2s ease-in-out;
13
- color: var(--greyed-out);
14
- font-size: var(--font-size);
15
- font-family: var(--font-family);
16
- width: 100%;
17
- box-sizing: border-box;
18
12
 
19
- &:disabled {
20
- color: var(--greyed-out);
13
+ &:hover:not(:disabled) {
14
+ border-color: var(--default);
15
+ }
16
+
17
+ &.disabled,
18
+ &.disabled input {
21
19
  background-color: var(--disabled);
22
20
  border-color: #fff;
23
21
  cursor: not-allowed;
24
22
  }
25
23
 
26
- &:hover:not(:disabled) {
27
- border-color: var(--default);
24
+ &.error {
25
+ border-color: var(--error);
26
+ }
27
+
28
+ &.focus {
29
+ border-color: var(--color-primary);
28
30
  }
31
+ }
32
+
33
+ .input {
34
+ height: 4rem;
35
+ border: 0;
36
+ color: var(--greyed-out);
37
+ font-size: var(--font-size);
38
+ font-family: var(--font-family);
39
+ width: 100%;
40
+ box-sizing: border-box;
41
+ padding: 0;
29
42
 
30
43
  &:focus:not(:disabled) {
31
44
  outline: none;
@@ -33,8 +46,7 @@
33
46
  }
34
47
  }
35
48
 
36
- .error {
37
- border-color: var(--error);
49
+ .error input {
38
50
  color: var(--error);
39
51
  padding-right: 3.75rem;
40
52
 
@@ -63,3 +75,10 @@
63
75
  right: 3.75rem;
64
76
  }
65
77
  }
78
+
79
+ .input-wrapper [data-prefix],
80
+ .input-wrapper [data-suffix] {
81
+ transition: all 0.2s ease-in-out;
82
+ display: block;
83
+ z-index: 1;
84
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Input, Props } from './Input';
3
3
  import { render } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
@@ -29,6 +29,32 @@ describe('Input should render', () => {
29
29
  });
30
30
  });
31
31
 
32
+ describe('ref should work', () => {
33
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
34
+ const ExampleComponent = ({
35
+ propagateRef,
36
+ }: {
37
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
38
+ }) => {
39
+ const ref = useRef(null);
40
+
41
+ useEffect(() => {
42
+ if (ref.current) {
43
+ propagateRef && propagateRef(ref);
44
+ }
45
+ }, [ref]);
46
+
47
+ return <Input {...defaultParams} data-ref="testing" ref={ref} />;
48
+ };
49
+
50
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
51
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
52
+ };
53
+
54
+ render(<ExampleComponent propagateRef={refCheck} />);
55
+ });
56
+ });
57
+
32
58
  describe('Should have the appropriate attributes', () => {
33
59
  it('is disabled and has a class', () => {
34
60
  const { input } = createInput((defaultParams) => ({
@@ -1,8 +1,8 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { ComponentPropsWithRef, Ref, useEffect, useState } from 'react';
2
2
  import classes from './Input.module.scss';
3
3
  import readyclasses from '../../readyclasses.module.scss';
4
4
  import { Icon, Icons } from '../../Icon/Icon';
5
- import { HTMLProps } from '../../interfaces';
5
+ import { FormElement } from '../form.interfaces';
6
6
 
7
7
  const dateTypes = ['date', 'time', 'datetime-local'] as const;
8
8
 
@@ -18,55 +18,96 @@ export type Type =
18
18
  | 'hidden'
19
19
  | typeof dateTypes[number];
20
20
 
21
- export interface Props extends HTMLProps<HTMLInputElement> {
22
- wrapperProps?: HTMLProps<HTMLInputElement>;
21
+ export interface Props extends ComponentPropsWithRef<'input'>, FormElement {
22
+ wrapperProps?: ComponentPropsWithRef<'div'>;
23
23
  labeledBy?: string;
24
24
  type: Type;
25
- error?: boolean;
25
+ suffix?: string;
26
+ prefix?: string;
26
27
  }
27
28
 
28
- export const Input = ({
29
- error = false,
30
- className,
31
- name,
32
- style,
33
- wrapperProps,
34
- type,
35
- labeledBy,
36
- ...rest
37
- }: Props) => {
38
- useEffect(() => {
39
- if (name === undefined) {
40
- throw new Error("Please give your <Input /> component a 'name' attribute");
41
- }
42
- }, []);
29
+ export const Input = React.forwardRef(
30
+ (
31
+ {
32
+ error = false,
33
+ className,
34
+ name,
35
+ style,
36
+ wrapperProps,
37
+ type,
38
+ labeledBy,
39
+ prefix,
40
+ suffix,
41
+ disabled,
42
+ onFocus,
43
+ onBlur,
44
+ ...rest
45
+ }: Props,
46
+ ref: Ref<HTMLInputElement>
47
+ ) => {
48
+ const [focus, setFocus] = useState(false);
43
49
 
44
- const inputClassNames = [classes['input']];
45
- error && inputClassNames.push(classes['error']);
46
- (dateTypes as ReadonlyArray<string>).includes(type) &&
47
- inputClassNames.push(classes['remove-extra-indent']);
48
- className && inputClassNames.push(className);
50
+ useEffect(() => {
51
+ if (name === undefined) {
52
+ throw new Error("Please give your <Input /> component a 'name' attribute");
53
+ }
54
+ }, []);
49
55
 
50
- const iconClassNames = [classes['warning']];
51
- (dateTypes as ReadonlyArray<string>).includes(type) &&
52
- iconClassNames.push(classes['extra-indent']);
56
+ const inputClassNames = [classes['input']];
53
57
 
54
- return (
55
- <div
56
- {...wrapperProps}
57
- style={{ ...style }}
58
- className={`${classes['input-wrapper']} ${wrapperProps?.className ?? ''} ${
59
- type === 'hidden' ? readyclasses['hidden'] : ''
60
- }`}
61
- >
62
- <input
63
- {...rest}
64
- aria-labelledby={labeledBy}
65
- type={type}
66
- name={name}
67
- className={inputClassNames.join(' ')}
68
- />
69
- {error && <Icon className={iconClassNames.join(' ')} icon={Icons.Warning} />}
70
- </div>
71
- );
72
- };
58
+ (dateTypes as ReadonlyArray<string>).includes(type) &&
59
+ inputClassNames.push(classes['remove-extra-indent']);
60
+ className && inputClassNames.push(className);
61
+
62
+ const iconClassNames = [classes['warning']];
63
+ (dateTypes as ReadonlyArray<string>).includes(type) &&
64
+ iconClassNames.push(classes['extra-indent']);
65
+
66
+ const wrapperClasses = [classes['input-wrapper']];
67
+
68
+ wrapperProps?.className && wrapperClasses.push(wrapperProps.className);
69
+ type === 'hidden' && wrapperClasses.push(readyclasses['hidden']);
70
+ prefix && wrapperClasses.push(classes['prefix']);
71
+ suffix && wrapperClasses.push(classes['suffix']);
72
+ disabled && wrapperClasses.push(classes['disabled']);
73
+ error && wrapperClasses.push(classes['error']);
74
+ focus && wrapperClasses.push(classes['focus']);
75
+
76
+ return (
77
+ <div
78
+ {...wrapperProps}
79
+ style={{ ...style }}
80
+ className={`${classes['input-wrapper']} ${wrapperClasses.join(' ')}`}
81
+ >
82
+ {prefix && (
83
+ <div data-prefix className={classes['prefix']}>
84
+ <span>{prefix}</span>
85
+ </div>
86
+ )}
87
+ <input
88
+ {...rest}
89
+ ref={ref}
90
+ onFocus={(event) => {
91
+ setFocus(true);
92
+ onFocus && onFocus(event);
93
+ }}
94
+ onBlur={(event) => {
95
+ setFocus(false);
96
+ onBlur && onBlur(event);
97
+ }}
98
+ aria-labelledby={labeledBy}
99
+ type={type}
100
+ name={name}
101
+ disabled={disabled}
102
+ className={inputClassNames.join(' ')}
103
+ />
104
+ {suffix && (
105
+ <div data-suffix className={classes['suffix']}>
106
+ <span>{suffix}</span>
107
+ </div>
108
+ )}
109
+ {error && <Icon className={iconClassNames.join(' ')} icon={Icons.Error} />}
110
+ </div>
111
+ );
112
+ }
113
+ );
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Label } from './Label';
3
3
  import { render } from '@testing-library/react';
4
4
 
@@ -24,3 +24,29 @@ describe('Label should render', () => {
24
24
  expect(component.getAttribute('for')).toBe('input-name');
25
25
  });
26
26
  });
27
+
28
+ describe('ref should work', () => {
29
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
30
+ const ExampleComponent = ({
31
+ propagateRef,
32
+ }: {
33
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
34
+ }) => {
35
+ const ref = useRef(null);
36
+
37
+ useEffect(() => {
38
+ if (ref.current) {
39
+ propagateRef && propagateRef(ref);
40
+ }
41
+ }, [ref]);
42
+
43
+ return <Label data-ref="testing" ref={ref} />;
44
+ };
45
+
46
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
47
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
48
+ };
49
+
50
+ render(<ExampleComponent propagateRef={refCheck} />);
51
+ });
52
+ });
@@ -1,19 +1,23 @@
1
- import React from 'react';
1
+ import React, { ComponentPropsWithRef, ReactNode } from 'react';
2
2
  import classes from './Label.module.scss';
3
3
  import readyclasses from '../../readyclasses.module.scss';
4
- import { HTMLProps } from '../../interfaces';
5
4
 
6
- export interface Props extends HTMLProps<HTMLLabelElement> {
7
- children?: string;
5
+ export interface Props extends ComponentPropsWithRef<'label'> {
6
+ children?: ReactNode;
8
7
  }
9
8
 
10
- export const Label = ({ children, className, hidden = false, ...rest }: Props) => {
11
- return (
12
- <label
13
- {...rest}
14
- className={`${hidden ? readyclasses['sr-only'] : ''} ${classes['label']} ${className ?? ''}`}
15
- >
16
- {children}
17
- </label>
18
- );
19
- };
9
+ export const Label = React.forwardRef<HTMLLabelElement, Props>(
10
+ ({ children, className, hidden = false, ...rest }: Props, ref) => {
11
+ return (
12
+ <label
13
+ {...rest}
14
+ ref={ref}
15
+ className={`${hidden ? readyclasses['sr-only'] : ''} ${classes['label']} ${
16
+ className ?? ''
17
+ }`}
18
+ >
19
+ {children}
20
+ </label>
21
+ );
22
+ }
23
+ );
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Radio, Props } from './Radio';
3
3
  import { render } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
@@ -12,7 +12,7 @@ const defaultParams: Props = {
12
12
  error: false,
13
13
  errorMessage: 'errormessage',
14
14
  disabled: false,
15
- wrapperProps: { 'data-testid': 'radiowrapper' },
15
+ formSelectorWrapperProps: { 'data-testid': 'radiowrapper' },
16
16
  helperText: 'helpertext',
17
17
  onChange: onChangeHandeler,
18
18
  };
@@ -70,6 +70,32 @@ describe('Radio should render', () => {
70
70
  });
71
71
  });
72
72
 
73
+ describe('ref should work', () => {
74
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
75
+ const ExampleComponent = ({
76
+ propagateRef,
77
+ }: {
78
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
79
+ }) => {
80
+ const ref = useRef(null);
81
+
82
+ useEffect(() => {
83
+ if (ref.current) {
84
+ propagateRef && propagateRef(ref);
85
+ }
86
+ }, [ref]);
87
+
88
+ return <Radio {...defaultParams} data-ref="testing" ref={ref} />;
89
+ };
90
+
91
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
92
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
93
+ };
94
+
95
+ render(<ExampleComponent propagateRef={refCheck} />);
96
+ });
97
+ });
98
+
73
99
  describe('Radio should be interactive', () => {
74
100
  it('should call onChange when clicked', () => {
75
101
  const { radio } = createRadio();