@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 { ContextMenu, Props } from './ContextMenu';
3
3
  import { render, getByRole } from '@testing-library/react';
4
4
  import { Button } from '../Button/Button';
@@ -91,3 +91,29 @@ describe('ContextMenu should render', () => {
91
91
  console.error = err;
92
92
  });
93
93
  });
94
+
95
+ describe('ref should work', () => {
96
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
97
+ const ExampleComponent = ({
98
+ propagateRef,
99
+ }: {
100
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
101
+ }) => {
102
+ const ref = useRef(null);
103
+
104
+ useEffect(() => {
105
+ if (ref.current) {
106
+ propagateRef && propagateRef(ref);
107
+ }
108
+ }, [ref]);
109
+
110
+ return <ContextMenu {...defaultParams} data-ref="testing" ref={ref} />;
111
+ };
112
+
113
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
114
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
115
+ };
116
+
117
+ render(<ExampleComponent propagateRef={refCheck} />);
118
+ });
119
+ });
@@ -1,4 +1,4 @@
1
- import React, { HTMLProps, ReactElement, useEffect, useRef, useState } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactElement, useEffect, useRef, useState } from 'react';
2
2
  import { Props as ButtonProps } from '../Button/Button';
3
3
  import { Props as IconButtonProps } from '../Button/IconButton';
4
4
  import { Popover } from '../Popover/Popover';
@@ -8,7 +8,7 @@ import classes from './ContextMenu.module.scss';
8
8
  import { useBodyClick } from '../hooks/useBodyClick';
9
9
  import { createPortal } from 'react-dom';
10
10
 
11
- export interface Props extends HTMLProps<HTMLDivElement> {
11
+ export interface Props extends ComponentPropsWithRef<'div'> {
12
12
  trigger: ReactElement<ButtonProps> | ReactElement<IconButtonProps>;
13
13
  children: ReactElement<ContextMenuItemProps> | ReactElement<ContextMenuItemProps>[];
14
14
  placement?: Placement;
@@ -21,71 +21,76 @@ export interface Props extends HTMLProps<HTMLDivElement> {
21
21
  onClose?: () => void;
22
22
  }
23
23
 
24
- export const ContextMenu = ({
25
- trigger,
26
- children,
27
- id,
28
- show = false,
29
- onShow,
30
- onClose,
31
- placement = { horizontal: 'right', vertical: 'top' },
32
- offset = { top: 0, bottom: 0, left: 0, right: 0 },
33
- transformOrigin = { horizontal: 'left', vertical: 'top' },
34
- domRoot = document.body,
35
- ...rest
36
- }: Props) => {
37
- const anchorEl = useRef<HTMLButtonElement>(null);
38
- const [showContextMenu, setShowContextMenu] = useState(show);
24
+ export const ContextMenu = React.forwardRef<HTMLDivElement, Props>(
25
+ (
26
+ {
27
+ trigger,
28
+ children,
29
+ id,
30
+ show = false,
31
+ onShow,
32
+ onClose,
33
+ placement = { horizontal: 'right', vertical: 'top' },
34
+ offset = { top: 0, bottom: 0, left: 0, right: 0 },
35
+ transformOrigin = { horizontal: 'left', vertical: 'top' },
36
+ domRoot = document.body,
37
+ ...rest
38
+ }: Props,
39
+ ref
40
+ ) => {
41
+ const anchorEl = useRef<HTMLButtonElement>(null);
42
+ const [showContextMenu, setShowContextMenu] = useState(show);
39
43
 
40
- if (!id) {
41
- throw new Error('You need to provide an ID to the context menu');
42
- }
44
+ if (!id) {
45
+ throw new Error('You need to provide an ID to the context menu');
46
+ }
43
47
 
44
- useBodyClick(
45
- (event) => {
46
- return showContextMenu && anchorEl.current !== event.target;
47
- },
48
- () => {
49
- setShowContextMenu(false);
50
- },
51
- showContextMenu
52
- );
48
+ useBodyClick(
49
+ (event) => {
50
+ return showContextMenu && anchorEl.current !== event.target;
51
+ },
52
+ () => {
53
+ setShowContextMenu(false);
54
+ },
55
+ showContextMenu
56
+ );
53
57
 
54
- useEffect(() => {
55
- if (showContextMenu === true) {
56
- onShow && onShow();
57
- } else {
58
- onClose && onClose();
59
- }
60
- }, [showContextMenu]);
58
+ useEffect(() => {
59
+ if (showContextMenu === true) {
60
+ onShow && onShow();
61
+ } else {
62
+ onClose && onClose();
63
+ }
64
+ }, [showContextMenu]);
61
65
 
62
- const renderTrigger = () =>
63
- React.cloneElement(trigger, {
64
- id: id,
65
- ['aria-haspopup']: 'true',
66
- ['aria-controls']: `${id}-menu`,
67
- ['aria-expanded']: show,
68
- onClick: () => setShowContextMenu(!showContextMenu),
69
- ref: anchorEl,
70
- });
66
+ const renderTrigger = () =>
67
+ React.cloneElement(trigger, {
68
+ id: id,
69
+ 'aria-haspopup': 'true',
70
+ 'aria-controls': `${id}-menu`,
71
+ 'aria-expanded': show,
72
+ onClick: () => setShowContextMenu(!showContextMenu),
73
+ ref: anchorEl,
74
+ });
71
75
 
72
- return (
73
- <div {...rest} className={classes['context-menu']}>
74
- {renderTrigger()}
75
- {createPortal(
76
- <Popover
77
- placement={placement}
78
- transformOrigin={transformOrigin}
79
- offset={offset}
80
- anchorEl={anchorEl}
81
- show={showContextMenu}
82
- >
83
- <ul className={classes.menu} id={`${id}-menu`} aria-describedby={id} role="menu">
84
- {children}
85
- </ul>
86
- </Popover>,
87
- domRoot
88
- )}
89
- </div>
90
- );
91
- };
76
+ return (
77
+ <div {...rest} ref={ref} className={classes['context-menu']}>
78
+ {renderTrigger()}
79
+ {createPortal(
80
+ <Popover
81
+ placement={placement}
82
+ transformOrigin={transformOrigin}
83
+ offset={offset}
84
+ anchorEl={anchorEl}
85
+ show={showContextMenu}
86
+ >
87
+ <ul className={classes.menu} id={`${id}-menu`} aria-describedby={id} role="menu">
88
+ {children}
89
+ </ul>
90
+ </Popover>,
91
+ domRoot
92
+ )}
93
+ </div>
94
+ );
95
+ }
96
+ );
@@ -63,3 +63,7 @@
63
63
  font-size: 1.25rem;
64
64
  pointer-events: none;
65
65
  }
66
+
67
+ .disabled {
68
+ color: var(--disabled);
69
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Checkbox, CheckboxProps as Props } from './Checkbox';
3
3
  import { render } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
@@ -33,6 +33,32 @@ describe('Checkbox should render', () => {
33
33
  });
34
34
  });
35
35
 
36
+ describe('ref should work', () => {
37
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
38
+ const ExampleComponent = ({
39
+ propagateRef,
40
+ }: {
41
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
42
+ }) => {
43
+ const ref = useRef(null);
44
+
45
+ useEffect(() => {
46
+ if (ref.current) {
47
+ propagateRef && propagateRef(ref);
48
+ }
49
+ }, [ref]);
50
+
51
+ return <Checkbox {...defaultParams} data-ref="testing" ref={ref} />;
52
+ };
53
+
54
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
55
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
56
+ };
57
+
58
+ render(<ExampleComponent propagateRef={refCheck} />);
59
+ });
60
+ });
61
+
36
62
  describe('Checkbox should have proper attributes', () => {
37
63
  it('should be unchecked', () => {
38
64
  const { checkbox } = createCheckbox();
@@ -75,7 +101,7 @@ describe('Checkbox should have proper attributes', () => {
75
101
  ...defaultParams,
76
102
  error: true,
77
103
  errorMessage: 'This is an error',
78
- wrapperProps: { 'data-testid': 'checkbox-wrapper' },
104
+ formSelectorWrapperProps: { 'data-testid': 'checkbox-wrapper' },
79
105
  }));
80
106
 
81
107
  expect(checkbox).toHaveAttribute(
@@ -1,145 +1,160 @@
1
- import React, { ReactElement, ReactNode, useEffect } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactElement, ReactNode, useEffect } from 'react';
2
2
  import { Icon, Icons } from '../../Icon/Icon';
3
3
  import { Props as FormHelperTextProps } from '../FormHelperText/FormHelperText';
4
4
  import classes from './Checkbox.module.scss';
5
5
  import { useFormSelector } from '../../hooks/useFormSelector';
6
+ import {
7
+ FormSelectorWrapper,
8
+ Props as FormSelectorWrapperProps,
9
+ } from '../FormSelectorWrapper/FormSelectorWrapper';
6
10
  import { FormSelector } from '../form.interfaces';
7
- import { HTMLProps } from '../../interfaces';
8
- import { FormSelectorWrapper } from '../FormSelectorWrapper/FormSelectorWrapper';
9
11
 
10
12
  const isToggle = (children: ReactNode) => (children as ReactElement)?.props?.['data-toggle'];
11
13
 
12
- export interface CheckboxProps extends FormSelector<HTMLInputElement> {
14
+ export interface CheckboxProps extends ComponentPropsWithRef<'input'>, FormSelector {
13
15
  children: ReactNode;
14
16
  label?: string;
15
17
  indeterminate?: boolean;
16
18
  helperProps?: FormHelperTextProps;
17
- wrapperProps?: HTMLProps<HTMLDivElement>;
19
+ formSelectorWrapperProps?: FormSelectorWrapperProps;
18
20
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
19
21
  }
20
22
 
21
- export const Checkbox = ({
22
- children,
23
- name,
24
- helperText,
25
- helperProps,
26
- indeterminate,
27
- parentErrorId,
28
- errorMessage,
29
- disabled,
30
- label,
31
- parentHelperId,
32
- className,
33
- error,
34
- checked = false,
35
- wrapperProps,
36
- onChange,
37
- ...rest
38
- }: CheckboxProps) => {
39
- const { errorId, identifier, describedBy } = useFormSelector({
40
- name,
41
- helperText,
42
- parentErrorId,
43
- errorMessage,
44
- error,
45
- parentHelperId,
46
- });
23
+ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
24
+ (
25
+ {
26
+ children,
27
+ name,
28
+ helperText,
29
+ helperProps,
30
+ indeterminate,
31
+ parentErrorId,
32
+ errorMessage,
33
+ disabled,
34
+ label,
35
+ parentHelperId,
36
+ className,
37
+ error,
38
+ checked = false,
39
+ formSelectorWrapperProps,
40
+ onChange,
41
+ ...rest
42
+ }: CheckboxProps,
43
+ ref
44
+ ) => {
45
+ const { errorId, identifier, describedBy } = useFormSelector({
46
+ name,
47
+ helperText,
48
+ parentErrorId,
49
+ errorMessage,
50
+ error,
51
+ parentHelperId,
52
+ });
47
53
 
48
- useEffect(() => {
49
- if (!name) {
50
- console.error("Please pass a 'name' prop to your <Checkbox> component.");
51
- }
54
+ useEffect(() => {
55
+ if (!name) {
56
+ console.error("Please pass a 'name' prop to your <Checkbox> component.");
57
+ }
52
58
 
53
- if (typeof children === 'object' && !isToggle(children) && indeterminate === undefined) {
54
- throw new Error(
55
- 'If you have nested checkboxes you have to manage the indeterminate state by passing a boolean to the `indeterminate` prop.'
56
- );
57
- }
58
- }, []);
59
+ if (typeof children === 'object' && !isToggle(children) && indeterminate === undefined) {
60
+ throw new Error(
61
+ 'If you have nested checkboxes you have to manage the indeterminate state by passing a boolean to the `indeterminate` prop.'
62
+ );
63
+ }
64
+ }, []);
65
+
66
+ const determineLabel = () => {
67
+ if (label) {
68
+ return label;
69
+ } else if (children === undefined) {
70
+ throw new Error(
71
+ 'Please make sure to pass either a string or more Checkbox components as a child of your Checkbox component.'
72
+ );
73
+ }
74
+
75
+ if (typeof children === 'string') {
76
+ return children;
77
+ }
59
78
 
60
- const determineLabel = () => {
61
- if (label) {
62
- return label;
63
- } else if (children === undefined) {
64
79
  throw new Error(
65
- 'Please make sure to pass either a string or more Checkbox components as a child of your Checkbox component.'
80
+ 'If you pass Checkboxes as a child component (to create nested checkbox tree) you need to pass a label to the parent checkbox.'
66
81
  );
67
- }
82
+ };
68
83
 
69
- if (typeof children === 'string') {
70
- return children;
71
- }
72
-
73
- throw new Error(
74
- 'If you pass Checkboxes as a child component (to create nested checkbox tree) you need to pass a label to the parent checkbox.'
84
+ const renderNestedCheckboxes = () => (
85
+ <ul className={classes['checkbox-list']}>
86
+ {React.Children.map(children as ReactNode[], (child) => {
87
+ return (
88
+ <li>
89
+ <Checkbox
90
+ {...(child as ReactElement).props}
91
+ parentHelperId={parentHelperId}
92
+ parentErrorId={parentErrorId}
93
+ error={error}
94
+ disabled={disabled ? disabled : (child as CheckboxProps).disabled}
95
+ >
96
+ {(child as ReactElement).props.children}
97
+ </Checkbox>
98
+ </li>
99
+ );
100
+ })}
101
+ </ul>
75
102
  );
76
- };
77
103
 
78
- const renderNestedCheckboxes = () => (
79
- <ul className={classes['checkbox-list']}>
80
- {React.Children.map(children as ReactElement[], (child) => {
81
- return (
82
- <li>
83
- <Checkbox
84
- {...child.props}
85
- parentHelperId={parentHelperId}
86
- parentErrorId={parentErrorId}
87
- error={error}
88
- >
89
- {child.props.children}
90
- </Checkbox>
91
- </li>
92
- );
93
- })}
94
- </ul>
95
- );
104
+ const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
105
+ if (disabled) {
106
+ return;
107
+ }
108
+ onChange && onChange(event);
109
+ };
96
110
 
97
- const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
98
- if (disabled) {
99
- return;
100
- }
101
- onChange && onChange(event);
102
- };
111
+ const renderToggle = () => React.Children.toArray(children).filter(isToggle);
103
112
 
104
- const renderToggle = () => React.Children.toArray(children).filter(isToggle);
113
+ const iconClasses = [classes['input'], disabled ? classes['disabled'] : ''];
105
114
 
106
- /** Default return value is the default checkbox */
107
- return (
108
- <FormSelectorWrapper
109
- {...wrapperProps}
110
- className={`${classes['checkbox-wrapper']} ${className ? className : ''}`}
111
- containerProps={{ className: classes['checkbox-container'] }}
112
- helperText={helperText}
113
- helperProps={helperProps}
114
- parentErrorId={parentErrorId}
115
- errorId={errorId}
116
- errorMessage={errorMessage}
117
- error={error}
118
- disabled={disabled}
119
- identifier={identifier}
120
- nestedChildren={
121
- typeof children === 'object' && !isToggle(children) && renderNestedCheckboxes()
122
- }
123
- >
124
- <input
125
- {...rest}
115
+ /** Default return value is the default checkbox */
116
+ return (
117
+ <FormSelectorWrapper
118
+ {...formSelectorWrapperProps}
119
+ className={`${classes['checkbox-wrapper']} ${className ? className : ''}`}
120
+ containerProps={{ className: classes['checkbox-container'] }}
121
+ helperText={helperText}
122
+ helperProps={helperProps}
123
+ parentErrorId={parentErrorId}
124
+ errorId={errorId}
125
+ errorMessage={errorMessage}
126
+ error={error}
126
127
  disabled={disabled}
127
- className={`${classes['native-input']} ${error ? classes['error'] : ''}`}
128
- checked={checked}
129
- onChange={onChangeHandler}
130
- aria-invalid={error as boolean}
131
- aria-checked={indeterminate ? 'mixed' : checked}
132
- aria-describedby={describedBy}
133
- id={`${identifier}-checkbox`}
134
- name={name}
135
- type="checkbox"
136
- />
137
- {renderToggle()}
128
+ identifier={identifier}
129
+ nestedChildren={
130
+ typeof children === 'object' && !isToggle(children) && renderNestedCheckboxes()
131
+ }
132
+ >
133
+ <input
134
+ {...rest}
135
+ ref={ref}
136
+ disabled={disabled}
137
+ className={`${classes['native-input']} ${error ? classes['error'] : ''}`}
138
+ checked={checked}
139
+ onChange={onChangeHandler}
140
+ aria-invalid={error as boolean}
141
+ aria-checked={indeterminate ? 'mixed' : checked}
142
+ aria-describedby={describedBy}
143
+ id={`${identifier}-checkbox`}
144
+ name={name}
145
+ type="checkbox"
146
+ />
147
+ {renderToggle()}
138
148
 
139
- {indeterminate && <Icon className={classes.input} icon={Icons.MinusSquare} />}
140
- {checked && !indeterminate && <Icon className={classes.input} icon={Icons.CheckmarkSquare} />}
141
- {!checked && !indeterminate && <Icon className={classes.input} icon={Icons.Square} />}
142
- <label htmlFor={`${identifier}-checkbox`}>{determineLabel()}</label>
143
- </FormSelectorWrapper>
144
- );
145
- };
149
+ {indeterminate && <Icon className={iconClasses.join(' ')} icon={Icons.MinusSquare} />}
150
+ {checked && !indeterminate && (
151
+ <Icon className={iconClasses.join(' ')} icon={Icons.CheckmarkSquare} />
152
+ )}
153
+ {!checked && !indeterminate && (
154
+ <Icon className={iconClasses.join(' ')} icon={Icons.Square} />
155
+ )}
156
+ <label htmlFor={`${identifier}-checkbox`}>{determineLabel()}</label>
157
+ </FormSelectorWrapper>
158
+ );
159
+ }
160
+ );
@@ -13,7 +13,17 @@
13
13
  margin-top: 1rem;
14
14
  }
15
15
 
16
- .title {
16
+ .legend {
17
17
  display: block;
18
+
19
+ &.required {
20
+ &:after {
21
+ content: ' *';
22
+ }
23
+ }
24
+
25
+ &.error {
26
+ color: var(--error);
27
+ }
18
28
  }
19
29
  }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Fieldset, Props } from './Fieldset';
3
3
  import { render } from '@testing-library/react';
4
4
  import { FormControl } from '../FormControl/FormControl';
@@ -7,14 +7,14 @@ import { Select } from '../Select/Select';
7
7
  import { Option } from '../Select/Option';
8
8
 
9
9
  const defaultParams: Props = {
10
- title: 'Example',
11
- titleVariant: 'h2',
10
+ legend: 'Example',
11
+ legendStyle: 'h2',
12
12
  children: [
13
13
  <FormControl data-testid="form-control">
14
14
  <Input placeholder="This is a placeholder" name="example" type="text" />
15
15
  </FormControl>,
16
16
  <FormControl data-testid="form-control">
17
- <Select value="placeholder" onChange={jest.fn}>
17
+ <Select name="Example select" value="placeholder" onChange={jest.fn}>
18
18
  <Option value="option1">Option1</Option>
19
19
  <Option value="option2">Option2</Option>
20
20
  <Option value="option3">Option3</Option>
@@ -45,6 +45,32 @@ describe('Fieldset should render', () => {
45
45
  });
46
46
  });
47
47
 
48
+ describe('ref should work', () => {
49
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
50
+ const ExampleComponent = ({
51
+ propagateRef,
52
+ }: {
53
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
54
+ }) => {
55
+ const ref = useRef(null);
56
+
57
+ useEffect(() => {
58
+ if (ref.current) {
59
+ propagateRef && propagateRef(ref);
60
+ }
61
+ }, [ref]);
62
+
63
+ return <Fieldset {...defaultParams} data-ref="testing" ref={ref} />;
64
+ };
65
+
66
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
67
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
68
+ };
69
+
70
+ render(<ExampleComponent propagateRef={refCheck} />);
71
+ });
72
+ });
73
+
48
74
  describe('Fieldset should get proper attributes and classes', () => {
49
75
  it('has no padding class', () => {
50
76
  const { fieldset } = createFieldset((defaultParams) => ({ ...defaultParams, noPadding: true }));