@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,74 +1,79 @@
1
- import React, { ReactElement, useEffect } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactElement, useEffect } from 'react';
2
2
  import classes from './RadioWrapper.module.scss';
3
3
  import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
4
4
  import { useWrapper } from '../../../hooks/useWrapper';
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
11
  value: string;
12
- onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
12
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
13
13
  }
14
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);
15
+ export const RadioWrapper = React.forwardRef<HTMLDivElement, Props>(
16
+ (
17
+ {
18
+ children,
19
+ error,
20
+ name,
21
+ helperText,
22
+ helperProps,
23
+ fieldsetProps,
24
+ value,
25
+ onChange,
26
+ disabled,
27
+ ...rest
28
+ }: Props,
29
+ ref
30
+ ) => {
31
+ const { errorId, helperId } = useWrapper(value);
28
32
 
29
- useEffect(() => {
30
- if (fieldsetProps.legend === 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
+ useEffect(() => {
34
+ if (fieldsetProps.legend === undefined) {
35
+ console.error(
36
+ `You should give your Fieldset component a legend prop so a legend element is rendered. This error was thrown in RadioWrapper. You can add this legend prop through the fieldsetProps prop by passing an object (fieldsetProps={{ legend: "legend here" }})`
37
+ );
38
+ }
39
+ }, []);
40
+
41
+ const renderChildren = () =>
42
+ React.Children.map(children, (child) =>
43
+ React.cloneElement(child, {
44
+ parentErrorId: errorId,
45
+ error: error,
46
+ checked: child.props.value === value,
47
+ name: name,
48
+ parentHelperId: helperText ? helperId : false,
49
+ onChange: onChange,
50
+ disabled: child.props.disabled !== undefined ? child.props.disabled : disabled,
51
+ })
33
52
  );
34
- }
35
- }, []);
36
53
 
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
- })
54
+ return (
55
+ <Fieldset {...fieldsetProps} error={error} disabled={disabled}>
56
+ <Wrapper
57
+ {...rest}
58
+ ref={ref}
59
+ disabled={disabled}
60
+ name={name}
61
+ helperId={helperId}
62
+ helperText={helperText}
63
+ helperProps={{
64
+ ...helperProps,
65
+ className: `${classes['radio-wrapper-helper']} ${
66
+ error ? classes['radio-wrapper-error'] : ''
67
+ } ${helperProps?.className ?? ''}`,
68
+ }}
69
+ error={error}
70
+ errorId={errorId}
71
+ errorMessageIcon={Icons.Error}
72
+ floatingLabel={false}
73
+ >
74
+ {renderChildren()}
75
+ </Wrapper>
76
+ </Fieldset>
48
77
  );
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
- };
78
+ }
79
+ );
@@ -1,7 +1,7 @@
1
1
  .select-label {
2
2
  left: calc(
3
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.
4
+ ); // 2px is for offset of the selectwrapper border. It's relative to the parent div which doesn't have a border.
5
5
  }
6
6
 
7
7
  .select-helper-text {
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { SelectWrapper, Props } from './SelectWrapper';
3
3
  import { render } from '@testing-library/react';
4
4
  import { Option } from '../../Select/Option';
@@ -55,6 +55,48 @@ describe('SelectWrapper should render', () => {
55
55
  });
56
56
  });
57
57
 
58
+ describe('ref should work', () => {
59
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
60
+ const ExampleComponent = ({
61
+ propagateRef,
62
+ }: {
63
+ propagateRef?: (
64
+ ref: React.RefObject<HTMLElement>,
65
+ innerRef: React.RefObject<HTMLInputElement>
66
+ ) => void;
67
+ }) => {
68
+ const ref = useRef(null);
69
+ const innerRef = useRef(null);
70
+
71
+ useEffect(() => {
72
+ if (ref.current) {
73
+ propagateRef && propagateRef(ref, innerRef);
74
+ }
75
+ }, [ref]);
76
+
77
+ return (
78
+ <SelectWrapper
79
+ {...defaultParams}
80
+ selectProps={{ ref: innerRef, 'data-ref': 'inner-testing' }}
81
+ name="test"
82
+ data-ref="testing"
83
+ ref={ref}
84
+ />
85
+ );
86
+ };
87
+
88
+ const refCheck = (
89
+ ref: React.RefObject<HTMLElement>,
90
+ innerRef: React.RefObject<HTMLElement>
91
+ ) => {
92
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
93
+ expect(innerRef.current!.nodeName).toBe('SELECT');
94
+ };
95
+
96
+ render(<ExampleComponent propagateRef={refCheck} />);
97
+ });
98
+ });
99
+
58
100
  describe('SelectWrapper & Select have the right attributes', () => {
59
101
  it('select has aria values', async () => {
60
102
  const { select, getByTestId, findByText } = createSelectWrapper();
@@ -1,60 +1,70 @@
1
- import React, { ReactChild, ReactElement } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactChild, ReactElement } from 'react';
2
2
  import classes from './SelectWrapper.module.scss';
3
3
  import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
4
4
  import { Select, Props as SelectProps } from '../../Select/Select';
5
5
  import { useWrapper } from '../../../hooks/useWrapper';
6
6
 
7
- export interface Props extends Omit<WrapperProps, 'onChange' | 'error'> {
7
+ interface PartialSelectProps extends Partial<SelectProps> {}
8
+
9
+ export interface Props
10
+ extends Omit<ComponentPropsWithRef<'div'>, 'onChange'>,
11
+ Omit<WrapperProps, 'onChange' | 'error'> {
8
12
  children: ReactChild | ReactChild[];
9
13
  placeholder?: string;
10
14
  value: string;
11
15
  error?: boolean;
12
- selectProps?: SelectProps;
16
+ selectProps?: PartialSelectProps;
13
17
  onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
14
18
  onClear?: () => void;
15
19
  }
16
20
 
17
- export const SelectWrapper = ({
18
- children,
19
- error,
20
- value,
21
- placeholder,
22
- selectProps,
23
- helperProps,
24
- onChange,
25
- onClear,
26
- ...rest
27
- }: Props) => {
28
- const { errorId, floatingLabelActive, helperId, labelId } = useWrapper(value, placeholder);
21
+ export const SelectWrapper = React.forwardRef<HTMLDivElement, Props>(
22
+ (
23
+ {
24
+ children,
25
+ error,
26
+ value,
27
+ placeholder,
28
+ selectProps,
29
+ helperProps,
30
+ onChange,
31
+ onClear,
32
+ ...rest
33
+ }: Props,
34
+ ref
35
+ ) => {
36
+ const { errorId, floatingLabelActive, helperId, labelId } = useWrapper(value, placeholder);
29
37
 
30
- return (
31
- <Wrapper
32
- {...rest}
33
- floatingLabelActive={floatingLabelActive}
34
- errorId={errorId}
35
- helperId={helperId}
36
- labelProps={{ id: labelId, className: classes['select-label'] }}
37
- helperProps={{
38
- ...helperProps,
39
- className: `${classes['select-helper-text']} ${helperProps?.className ?? ''}`,
40
- }}
41
- error={error}
42
- >
43
- <Select
44
- {...selectProps}
45
- value={value}
46
- labeledBy={labelId}
38
+ return (
39
+ <Wrapper
40
+ {...rest}
41
+ ref={ref}
42
+ floatingLabelActive={floatingLabelActive}
43
+ errorId={errorId}
44
+ helperId={helperId}
45
+ labelProps={{ id: labelId, className: classes['select-label'] }}
46
+ helperProps={{
47
+ ...helperProps,
48
+ className: `${classes['select-helper-text']} ${helperProps?.className ?? ''}`,
49
+ }}
47
50
  error={error}
48
- describedBy={error ? errorId : helperId}
49
- onChange={onChange}
50
- onClear={onClear}
51
- placeholder={placeholder}
52
- className={`${floatingLabelActive ? classes['floating-label-active'] : ''} ${
53
- selectProps?.className ?? ''
54
- }`}
55
51
  >
56
- {children as ReactElement[]}
57
- </Select>
58
- </Wrapper>
59
- );
60
- };
52
+ <Select
53
+ {...selectProps}
54
+ value={value}
55
+ labeledBy={labelId}
56
+ error={error}
57
+ describedBy={error ? errorId : helperId}
58
+ onChange={onChange}
59
+ onClear={onClear}
60
+ placeholder={placeholder}
61
+ className={`${floatingLabelActive ? classes['floating-label-active'] : ''} ${
62
+ selectProps?.className ?? ''
63
+ }`}
64
+ >
65
+ {children as ReactElement[]}
66
+ </Select>
67
+ </Wrapper>
68
+ );
69
+ }
70
+ );
@@ -1,7 +1,7 @@
1
1
  .textarea-label {
2
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.
3
+ 1.25rem + 1px
4
+ ); // 1px is for offset of the textarea border. It's relative to the parent div which doesn't have a border.
5
5
 
6
6
  &.focus {
7
7
  color: var(--color-primary);
@@ -9,16 +9,14 @@
9
9
  }
10
10
 
11
11
  .textarea {
12
- border: 0;
13
- padding-top: 0;
14
- padding-right: 0;
12
+ padding-top: 1.625rem;
15
13
 
16
14
  &:active:not(:disabled) {
17
- border-color: white;
15
+ border-color: var(--color-primary);
18
16
  }
19
17
 
20
18
  &:hover:not(:disabled) {
21
- border-color: white;
19
+ border-color: var(--default);
22
20
  }
23
21
 
24
22
  &:focus:not(:disabled) {
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { TextareaWrapper, Props } from './TextareaWrapper';
3
3
  import { render } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
@@ -39,6 +39,48 @@ describe('TextareaWrapper should render', () => {
39
39
  });
40
40
  });
41
41
 
42
+ describe('ref should work', () => {
43
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
44
+ const ExampleComponent = ({
45
+ propagateRef,
46
+ }: {
47
+ propagateRef?: (
48
+ ref: React.RefObject<HTMLElement>,
49
+ innerRef: React.RefObject<HTMLInputElement>
50
+ ) => void;
51
+ }) => {
52
+ const ref = useRef(null);
53
+ const innerRef = useRef(null);
54
+
55
+ useEffect(() => {
56
+ if (ref.current) {
57
+ propagateRef && propagateRef(ref, innerRef);
58
+ }
59
+ }, [ref]);
60
+
61
+ return (
62
+ <TextareaWrapper
63
+ {...defaultParams}
64
+ textareaProps={{ ref: innerRef, 'data-ref': 'inner-testing' }}
65
+ name="test"
66
+ data-ref="testing"
67
+ ref={ref}
68
+ />
69
+ );
70
+ };
71
+
72
+ const refCheck = (
73
+ ref: React.RefObject<HTMLElement>,
74
+ innerRef: React.RefObject<HTMLElement>
75
+ ) => {
76
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
77
+ expect(innerRef.current).toHaveAttribute('data-ref', 'inner-testing');
78
+ };
79
+
80
+ render(<ExampleComponent propagateRef={refCheck} />);
81
+ });
82
+ });
83
+
42
84
  describe('TextareaWrapper & Textarea have the right attributes', () => {
43
85
  it('textarea has aria values', async () => {
44
86
  const { textarea, getByTestId, findByText } = createTextareaWrapper();
@@ -1,11 +1,15 @@
1
- import React, { useState } from 'react';
1
+ import React, { ComponentPropsWithRef, useState } from 'react';
2
2
  import classes from './TextareaWrapper.module.scss';
3
3
  import { Wrapper, WrapperProps } from '../Wrapper/Wrapper';
4
4
  import { Textarea, Props as TextareaProps } from '../../Textarea/Textarea';
5
5
  import { useWrapper } from '../../../hooks/useWrapper';
6
6
 
7
7
  export interface Props
8
- extends Omit<WrapperProps, 'onFocus' | 'onChange' | 'onBlur' | 'onMouseEnter' | 'onMouseLeave'> {
8
+ extends Omit<
9
+ ComponentPropsWithRef<'div'>,
10
+ 'onFocus' | 'onChange' | 'onBlur' | 'onMouseEnter' | 'onMouseLeave'
11
+ >,
12
+ Omit<WrapperProps, 'onFocus' | 'onChange' | 'onBlur' | 'onMouseEnter' | 'onMouseLeave'> {
9
13
  placeholder?: string;
10
14
  textareaProps?: TextareaProps;
11
15
  value: string;
@@ -16,90 +20,101 @@ export interface Props
16
20
  onMouseLeave?: (event: React.MouseEvent<HTMLTextAreaElement>) => void;
17
21
  }
18
22
 
19
- export const TextareaWrapper = ({
20
- name,
21
- error,
22
- value,
23
- label,
24
- placeholder,
25
- textareaProps,
26
- helperProps,
27
- onChange,
28
- onFocus,
29
- onBlur,
30
- onMouseEnter,
31
- onMouseLeave,
32
- disabled,
33
- ...rest
34
- }: Props) => {
35
- const {
36
- errorId,
37
- floatingLabelActive,
38
- setFloatingLabelActive,
39
- hasFocus,
40
- setHasFocus,
41
- helperId,
42
- labelId,
43
- } = useWrapper(value, placeholder);
23
+ export const TextareaWrapper = React.forwardRef<HTMLDivElement, Props>(
24
+ (
25
+ {
26
+ name,
27
+ error,
28
+ value,
29
+ label,
30
+ placeholder,
31
+ textareaProps,
32
+ helperProps,
33
+ onChange,
34
+ onFocus,
35
+ onBlur,
36
+ onMouseEnter,
37
+ onMouseLeave,
38
+ disabled,
39
+ ...rest
40
+ }: Props,
41
+ ref
42
+ ) => {
43
+ const {
44
+ errorId,
45
+ floatingLabelActive,
46
+ setFloatingLabelActive,
47
+ hasFocus,
48
+ setHasFocus,
49
+ helperId,
50
+ labelId,
51
+ } = useWrapper(value, placeholder);
52
+ const [hover, setHover] = useState(false);
44
53
 
45
- const [focus, setFocus] = useState(false);
46
- const [hover, setHover] = useState(false);
54
+ const optionalClasses: string[] = [];
47
55
 
48
- return (
49
- <Wrapper
50
- {...rest}
51
- disabled={disabled}
52
- labelProps={{
53
- id: labelId,
54
- className: `${classes['textarea-label']} ${hasFocus ? classes['focus'] : ''}`,
55
- }}
56
- name={name}
57
- label={label}
58
- helperId={helperId}
59
- helperProps={{
60
- ...helperProps,
61
- className: classes['textarea-helper-text'],
62
- }}
63
- error={error}
64
- floatingLabelActive={floatingLabelActive}
65
- errorId={errorId}
66
- >
67
- <Textarea
68
- {...textareaProps}
69
- error={error}
70
- aria-labelledby={label && labelId}
71
- aria-describedby={error ? errorId : helperId}
72
- placeholder={placeholder}
73
- value={value}
74
- onChange={onChange}
75
- onFocus={(e) => {
76
- onFocus && onFocus(e);
77
- setHasFocus(true);
78
- setFloatingLabelActive(true);
79
- setFocus(true);
80
- }}
81
- onBlur={(e) => {
82
- onBlur && onBlur(e);
83
- setHasFocus(false);
84
- setFocus(false);
85
- e.target.value || textareaProps?.placeholder?.length
86
- ? setFloatingLabelActive(true)
87
- : setFloatingLabelActive(false);
88
- }}
89
- onMouseEnter={(e) => {
90
- onMouseEnter && onMouseEnter(e);
91
- setHover(true);
56
+ hasFocus && optionalClasses.push(classes['focus']);
57
+ hover && optionalClasses.push(classes['hover']);
58
+ disabled && optionalClasses.push(classes['disabled']);
59
+ error && optionalClasses.push(classes['error']);
60
+
61
+ return (
62
+ <Wrapper
63
+ {...rest}
64
+ ref={ref}
65
+ disabled={disabled}
66
+ labelProps={{
67
+ id: labelId,
68
+ className: `${classes['textarea-label']} ${hasFocus ? classes['focus'] : ''}`,
92
69
  }}
93
- onMouseLeave={(e) => {
94
- onMouseLeave && onMouseLeave(e);
95
- setHover(false);
70
+ name={name}
71
+ label={label}
72
+ helperId={helperId}
73
+ helperProps={{
74
+ ...helperProps,
75
+ className: classes['textarea-helper-text'],
96
76
  }}
97
- className={classes['textarea']}
98
- wrapperClassName={`${classes['textarea-wrapper']} ${focus ? classes['focus'] : ''} ${
99
- hover ? classes['hover'] : ''
100
- } ${disabled ? classes['disabled'] : ''} ${error ? classes['error'] : ''}`}
101
- errorClassName={classes['error-icon']}
102
- />
103
- </Wrapper>
104
- );
105
- };
77
+ error={error}
78
+ floatingLabelActive={floatingLabelActive}
79
+ errorId={errorId}
80
+ >
81
+ <Textarea
82
+ {...textareaProps}
83
+ error={error}
84
+ aria-labelledby={label && labelId}
85
+ aria-describedby={error ? errorId : helperId}
86
+ placeholder={placeholder}
87
+ name={name}
88
+ id={name}
89
+ value={value}
90
+ onChange={onChange}
91
+ onFocus={(e) => {
92
+ onFocus && onFocus(e);
93
+ setHasFocus(true);
94
+ setFloatingLabelActive(true);
95
+ }}
96
+ onBlur={(e) => {
97
+ onBlur && onBlur(e);
98
+ setHasFocus(false);
99
+ e.target.value || e.target.placeholder || textareaProps?.placeholder?.length
100
+ ? setFloatingLabelActive(true)
101
+ : setFloatingLabelActive(false);
102
+ }}
103
+ onMouseEnter={(e) => {
104
+ onMouseEnter && onMouseEnter(e);
105
+ setHover(true);
106
+ }}
107
+ onMouseLeave={(e) => {
108
+ onMouseLeave && onMouseLeave(e);
109
+ setHover(false);
110
+ }}
111
+ className={classes['textarea']}
112
+ wrapperProps={{
113
+ className: `${classes['textarea-wrapper']}} ${optionalClasses.join(' ')}`,
114
+ }}
115
+ errorProps={{ className: classes['error-icon'] }}
116
+ />
117
+ </Wrapper>
118
+ );
119
+ }
120
+ );
@@ -7,7 +7,7 @@
7
7
  position: absolute;
8
8
  z-index: 1;
9
9
  top: 1.3125rem;
10
- left: 1.25rem;
10
+ left: 1.35rem;
11
11
  transform-origin: left top;
12
12
  transition: all 0.2s ease-in-out;
13
13
  pointer-events: none;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Wrapper } from './Wrapper';
3
3
  import { render } from '@testing-library/react';
4
4
  import { Input } from '../../Input/Input';
@@ -15,3 +15,29 @@ describe('Wrapper should render', () => {
15
15
  expect(wrapper).toBeDefined();
16
16
  });
17
17
  });
18
+
19
+ describe('ref should work', () => {
20
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
21
+ const ExampleComponent = ({
22
+ propagateRef,
23
+ }: {
24
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
25
+ }) => {
26
+ const ref = useRef(null);
27
+
28
+ useEffect(() => {
29
+ if (ref.current) {
30
+ propagateRef && propagateRef(ref);
31
+ }
32
+ }, [ref]);
33
+
34
+ return <Wrapper name="wrapper" children={<div></div>} data-ref="testing" ref={ref} />;
35
+ };
36
+
37
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
38
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
39
+ };
40
+
41
+ render(<ExampleComponent propagateRef={refCheck} />);
42
+ });
43
+ });