@onewelcome/react-lib-components 0.1.1-alpha → 0.1.2-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 (179) 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 +3 -5
  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 +4 -0
  56. package/dist/interfaces.d.ts +2 -11
  57. package/dist/react-lib-components.cjs.development.js +2023 -1551
  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 +2021 -1553
  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 +27 -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 +60 -55
  86. package/src/Form/Input/Input.module.scss +33 -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 +11 -0
  107. package/src/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +89 -1
  108. package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +127 -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 +3 -5
  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.test.tsx +27 -1
  117. package/src/Form/Wrapper/Wrapper/Wrapper.tsx +76 -71
  118. package/src/Form/form.interfaces.ts +4 -3
  119. package/src/Icon/Icon.module.scss +4 -0
  120. package/src/Icon/Icon.test.tsx +30 -2
  121. package/src/Icon/Icon.tsx +5 -5
  122. package/src/Link/Link.test.tsx +27 -1
  123. package/src/Link/Link.tsx +4 -6
  124. package/src/Notifications/BaseModal/BaseModal.test.tsx +27 -1
  125. package/src/Notifications/BaseModal/BaseModal.tsx +59 -54
  126. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.test.tsx +26 -1
  127. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.tsx +11 -9
  128. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.test.tsx +27 -1
  129. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.tsx +27 -26
  130. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.test.tsx +29 -1
  131. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.tsx +18 -16
  132. package/src/Notifications/Dialog/Dialog.test.tsx +39 -1
  133. package/src/Notifications/Dialog/Dialog.tsx +84 -78
  134. package/src/Notifications/Dialog/DialogActions/DialogActions.test.tsx +27 -1
  135. package/src/Notifications/Dialog/DialogActions/DialogActions.tsx +15 -12
  136. package/src/Notifications/Dialog/DialogTitle/DialogTitle.test.tsx +28 -2
  137. package/src/Notifications/Dialog/DialogTitle/DialogTitle.tsx +13 -11
  138. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.test.tsx +41 -1
  139. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.tsx +43 -36
  140. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.test.tsx +52 -1
  141. package/src/Notifications/DiscardChangesModal/DiscardChangesModal.tsx +8 -3
  142. package/src/Notifications/Snackbar/SnackbarItem/SnackbarItem.tsx +1 -1
  143. package/src/Pagination/Pagination.module.scss +120 -0
  144. package/src/Pagination/Pagination.test.tsx +176 -0
  145. package/src/Pagination/Pagination.tsx +205 -0
  146. package/src/Popover/Popover.tsx +3 -3
  147. package/src/Tabs/Tab.test.tsx +71 -0
  148. package/src/Tabs/Tab.tsx +17 -0
  149. package/src/Tabs/TabButton.module.scss +36 -0
  150. package/src/Tabs/TabButton.test.tsx +77 -0
  151. package/src/Tabs/TabButton.tsx +58 -0
  152. package/src/Tabs/TabPanel.module.scss +7 -0
  153. package/src/Tabs/TabPanel.test.tsx +76 -0
  154. package/src/Tabs/TabPanel.tsx +27 -0
  155. package/src/Tabs/Tabs.module.scss +41 -0
  156. package/src/Tabs/Tabs.test.tsx +268 -0
  157. package/src/Tabs/Tabs.tsx +149 -0
  158. package/src/TextEllipsis/TextEllipsis.module.scss +18 -0
  159. package/src/TextEllipsis/TextEllipsis.test.tsx +80 -0
  160. package/src/TextEllipsis/TextEllipsis.tsx +55 -0
  161. package/src/Tiles/Tile.test.tsx +27 -1
  162. package/src/Tiles/Tile.tsx +59 -62
  163. package/src/Tiles/Tiles.test.tsx +27 -1
  164. package/src/Tiles/Tiles.tsx +42 -39
  165. package/src/Tooltip/Tooltip.test.tsx +27 -1
  166. package/src/Tooltip/Tooltip.tsx +104 -92
  167. package/src/Typography/Typography.test.tsx +27 -1
  168. package/src/Typography/Typography.tsx +66 -68
  169. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +67 -62
  170. package/src/Wizard/WizardSteps/WizardSteps.tsx +24 -21
  171. package/src/_BaseStyling_/BaseStyling.tsx +19 -1
  172. package/src/hooks/useRepeater.test.tsx +139 -0
  173. package/src/hooks/useRepeater.ts +34 -0
  174. package/src/hooks/useSpacing.ts +1 -1
  175. package/src/hooks/useWrapper.ts +7 -2
  176. package/src/index.ts +12 -1
  177. package/src/interfaces.ts +2 -12
  178. package/src/util/helper.test.tsx +38 -1
  179. package/src/util/helper.tsx +21 -0
@@ -1,11 +1,18 @@
1
- import React, { HTMLProps, ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react';
1
+ import React, {
2
+ ComponentPropsWithRef,
3
+ ReactNode,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useRef,
7
+ useState,
8
+ } from 'react';
2
9
  import { Icon, Icons } from '../Icon/Icon';
3
10
  import classes from './Tooltip.module.scss';
4
11
  import { generateID } from '../util/helper';
5
12
  import { Offset, Placement, usePosition } from '../hooks/usePosition';
6
13
  import { createPortal } from 'react-dom';
7
14
 
8
- export interface Props extends Omit<HTMLProps<HTMLDivElement>, 'label'> {
15
+ export interface Props extends ComponentPropsWithRef<'div'> {
9
16
  label: string | ReactNode;
10
17
  children: string;
11
18
  placement?: Placement;
@@ -26,105 +33,110 @@ const defaultPosition: DefaultPosition = {
26
33
  transformOrigin: { horizontal: 'left', vertical: 'center' },
27
34
  };
28
35
 
29
- export const Tooltip = ({
30
- children,
31
- className,
32
- placement = defaultPosition.placement,
33
- offset = defaultPosition.offset,
34
- transformOrigin = defaultPosition.transformOrigin,
35
- domRoot = document.body,
36
- label,
37
- ...rest
38
- }: Props) => {
39
- const [identifier] = useState(generateID());
40
- const [visible, setVisible] = useState(false);
36
+ export const Tooltip = React.forwardRef<HTMLDivElement, Props>(
37
+ (
38
+ {
39
+ children,
40
+ className,
41
+ placement = defaultPosition.placement,
42
+ offset = defaultPosition.offset,
43
+ transformOrigin = defaultPosition.transformOrigin,
44
+ domRoot = document.body,
45
+ label,
46
+ ...rest
47
+ }: Props,
48
+ ref
49
+ ) => {
50
+ const [identifier] = useState(generateID());
51
+ const [visible, setVisible] = useState(false);
41
52
 
42
- const relativeElement = useRef<HTMLOrSVGElement>(null);
43
- const elementToBePositioned = useRef<HTMLDivElement>(null);
53
+ const relativeElement = useRef<HTMLDivElement>(null);
54
+ const elementToBePositioned = useRef<HTMLDivElement>(null);
44
55
 
45
- const { top, bottom, right, left, calculatePosition } = usePosition({
46
- relativeElement: relativeElement,
47
- elementToBePositioned: elementToBePositioned,
48
- placement: placement,
49
- offset: offset,
50
- transformOrigin: transformOrigin,
51
- });
56
+ const { top, bottom, right, left, calculatePosition } = usePosition({
57
+ relativeElement: relativeElement,
58
+ elementToBePositioned: elementToBePositioned,
59
+ placement: placement,
60
+ offset: offset,
61
+ transformOrigin: transformOrigin,
62
+ });
52
63
 
53
- useEffect(() => {
54
- if (!visible) return;
64
+ useEffect(() => {
65
+ if (!visible) return;
55
66
 
56
- function escapePressHandler(event: KeyboardEvent) {
57
- if (event.key === 'Escape') {
58
- setVisible(false);
67
+ function escapePressHandler(event: KeyboardEvent) {
68
+ if (event.key === 'Escape') {
69
+ setVisible(false);
70
+ }
59
71
  }
60
- }
61
72
 
62
- document.addEventListener('keyup', escapePressHandler);
73
+ document.addEventListener('keyup', escapePressHandler);
63
74
 
64
- return () => {
65
- document.removeEventListener('keyup', escapePressHandler);
66
- };
67
- }, [visible]);
75
+ return () => {
76
+ document.removeEventListener('keyup', escapePressHandler);
77
+ };
78
+ }, [visible]);
68
79
 
69
- useLayoutEffect(() => {
70
- calculatePosition();
71
- }, [visible]);
80
+ useLayoutEffect(() => {
81
+ calculatePosition();
82
+ }, [visible]);
72
83
 
73
- const renderChildren = () => {
74
- if (React.isValidElement(label)) {
75
- return React.cloneElement(label, {
76
- onFocus: () => setVisible(true),
77
- onBlur: () => setVisible(false),
78
- 'aria-describedby': identifier,
79
- tabIndex: 0,
80
- className: classes['label'],
81
- });
82
- }
84
+ const renderChildren = () => {
85
+ if (React.isValidElement(label)) {
86
+ return React.cloneElement(label, {
87
+ onFocus: () => setVisible(true),
88
+ onBlur: () => setVisible(false),
89
+ 'aria-describedby': identifier,
90
+ tabIndex: 0,
91
+ className: classes['label'],
92
+ });
93
+ }
83
94
 
84
- return (
85
- <span
86
- className={classes['label']}
87
- tabIndex={0}
88
- onFocus={() => setVisible(true)}
89
- onBlur={() => setVisible(false)}
90
- aria-describedby={identifier}
91
- >
92
- {label}
93
- </span>
94
- );
95
- };
95
+ return (
96
+ <span
97
+ className={classes['label']}
98
+ tabIndex={0}
99
+ onFocus={() => setVisible(true)}
100
+ onBlur={() => setVisible(false)}
101
+ aria-describedby={identifier}
102
+ >
103
+ {label}
104
+ </span>
105
+ );
106
+ };
96
107
 
97
- return (
98
- <div {...rest} className={`${classes.wrapper} ${className ?? ''}`}>
99
- {renderChildren()}
100
- <div className={`${classes['tooltip-wrapper']}`}>
101
- <Icon
102
- ref={relativeElement}
103
- tag="div"
104
- onMouseEnter={() => setVisible(true)}
105
- onMouseLeave={() => setVisible(false)}
106
- icon={Icons.InfoCircle}
107
- className={classes.icon}
108
- />
109
- {createPortal(
110
- <div
111
- ref={elementToBePositioned}
112
- style={{
113
- ...rest.style,
114
- top: top,
115
- left: left,
116
- right: right,
117
- bottom: bottom,
118
- }}
119
- aria-hidden={!visible}
120
- id={identifier}
121
- className={`${classes.tooltip} ${visible ? classes.visible : ''}`}
122
- >
123
- {children}
124
- </div>,
125
- domRoot
126
- )}
108
+ return (
109
+ <div {...rest} ref={ref} className={`${classes.wrapper} ${className ?? ''}`}>
110
+ {renderChildren()}
111
+ <div className={`${classes['tooltip-wrapper']}`}>
112
+ <Icon
113
+ ref={relativeElement}
114
+ tag="div"
115
+ onMouseEnter={() => setVisible(true)}
116
+ onMouseLeave={() => setVisible(false)}
117
+ icon={Icons.InfoCircle}
118
+ className={classes.icon}
119
+ />
120
+ {createPortal(
121
+ <div
122
+ ref={elementToBePositioned}
123
+ style={{
124
+ ...rest.style,
125
+ top: top,
126
+ left: left,
127
+ right: right,
128
+ bottom: bottom,
129
+ }}
130
+ aria-hidden={!visible}
131
+ id={identifier}
132
+ className={`${classes.tooltip} ${visible ? classes.visible : ''}`}
133
+ >
134
+ {children}
135
+ </div>,
136
+ domRoot
137
+ )}
138
+ </div>
127
139
  </div>
128
- </div>
129
- );
130
- };
140
+ );
141
+ }
142
+ );
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { Typography, Props } from './Typography';
3
3
  import { render } from '@testing-library/react';
4
4
  import { Spacing } from '../hooks/useSpacing';
@@ -112,3 +112,29 @@ describe('Should override styling', () => {
112
112
  expect(typography.style).toHaveProperty('margin', '1rem 1rem 2rem 1rem');
113
113
  });
114
114
  });
115
+
116
+ describe('ref should work', () => {
117
+ it('should give back the proper data prop, this also checks if the component propagates ...rest properly', () => {
118
+ const ExampleComponent = ({
119
+ propagateRef,
120
+ }: {
121
+ propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
122
+ }) => {
123
+ const ref = useRef(null);
124
+
125
+ useEffect(() => {
126
+ if (ref.current) {
127
+ propagateRef && propagateRef(ref);
128
+ }
129
+ }, [ref]);
130
+
131
+ return <Typography variant="body" data-ref="testing" ref={ref} />;
132
+ };
133
+
134
+ const refCheck = (ref: React.RefObject<HTMLElement>) => {
135
+ expect(ref.current).toHaveAttribute('data-ref', 'testing');
136
+ };
137
+
138
+ render(<ExampleComponent propagateRef={refCheck} />);
139
+ });
140
+ });
@@ -1,84 +1,82 @@
1
- import React, { HTMLAttributes, ReactNode } from 'react';
1
+ import React, { ComponentPropsWithRef, ReactNode } from 'react';
2
2
  import classes from './Typography.module.scss';
3
3
  import { Spacing, useSpacing } from '../hooks/useSpacing';
4
4
 
5
5
  const validVariants = ['h1', 'h2', 'h3', 'h4', 'body', 'body-bold', 'sub-text', 'code'] as const;
6
6
  export type Variant = typeof validVariants[number];
7
7
 
8
- export interface Props extends HTMLAttributes<HTMLElement> {
8
+ type Tags =
9
+ | 'h1'
10
+ | 'h2'
11
+ | 'h3'
12
+ | 'h4'
13
+ | 'p'
14
+ | 'div'
15
+ | 'code'
16
+ | 'span'
17
+ | 'sup'
18
+ | 'sub'
19
+ | 'strong'
20
+ | 'em'
21
+ | 'small'
22
+ | 'mark'
23
+ | 'del'
24
+ | 'ins'
25
+ | 'blockquote';
26
+
27
+ /** I couldn't find anything on the internet that indicated that ComponentPropsWithRef can take multiple tags. Since the TagName can be many different things I have to use any here. Using a mix of tags (like the Tags type) will throw an error. */
28
+ export interface Props extends ComponentPropsWithRef<any> {
9
29
  children: ReactNode;
10
30
  variant: Variant;
11
- tag?:
12
- | 'h1'
13
- | 'h2'
14
- | 'h3'
15
- | 'h4'
16
- | 'p'
17
- | 'div'
18
- | 'code'
19
- | 'span'
20
- | 'sup'
21
- | 'sub'
22
- | 'strong'
23
- | 'em'
24
- | 'small'
25
- | 'mark'
26
- | 'del'
27
- | 'ins'
28
- | 'blockquote';
31
+ tag?: Tags;
29
32
  spacing?: Spacing;
30
33
  }
31
34
 
32
- export const Typography = ({
33
- children,
34
- variant,
35
- tag,
36
- style,
37
- spacing,
38
- className = '',
39
- ...rest
40
- }: Props) => {
41
- if (!validVariants.includes(variant)) {
42
- throw new Error(
43
- `You entered an invalid variant. You can choose from: ${validVariants}, you entered: ${variant}`
44
- );
45
- }
35
+ export const Typography = React.forwardRef<any, Props>(
36
+ ({ children, variant, tag, style, spacing, className = '', ...rest }: Props, ref) => {
37
+ if (!validVariants.includes(variant)) {
38
+ throw new Error(
39
+ `You entered an invalid variant. You can choose from: ${validVariants}, you entered: ${variant}`
40
+ );
41
+ }
46
42
 
47
- const styleWithSpacing = useSpacing(spacing, style);
43
+ const styleWithSpacing = useSpacing(spacing, style);
48
44
 
49
- if (!tag) {
50
- switch (variant) {
51
- case 'h1':
52
- case 'h2':
53
- case 'h3':
54
- case 'h4':
55
- case 'code':
56
- tag = variant;
57
- break;
58
- case 'body':
59
- tag = 'p';
60
- break;
61
- case 'body-bold':
62
- tag = 'p';
63
- break;
64
- case 'sub-text':
65
- tag = 'span';
66
- break;
67
- default:
68
- tag = 'div';
69
- break;
45
+ if (!tag) {
46
+ switch (variant) {
47
+ case 'h1':
48
+ case 'h2':
49
+ case 'h3':
50
+ case 'h4':
51
+ case 'code':
52
+ tag = variant;
53
+ break;
54
+ case 'body':
55
+ tag = 'p';
56
+ break;
57
+ case 'body-bold':
58
+ tag = 'p';
59
+ break;
60
+ case 'sub-text':
61
+ tag = 'span';
62
+ break;
63
+ default:
64
+ tag = 'div';
65
+ break;
66
+ }
70
67
  }
71
- }
72
68
 
73
- let TagName = tag;
69
+ let TagName = tag;
74
70
 
75
- return (
76
- <TagName
77
- {...rest}
78
- style={styleWithSpacing}
79
- className={`${classes['typography_style_' + variant]} ${className}`}
80
- >
81
- {children}
82
- </TagName>
83
- );
84
- };
71
+ return (
72
+ <TagName
73
+ {...rest}
74
+ ref={ref}
75
+ style={styleWithSpacing}
76
+ className={`${classes['typography_style_' + variant]} ${className}`}
77
+ >
78
+ {children}
79
+ </TagName>
80
+ );
81
+ }
82
+ );
@@ -1,4 +1,4 @@
1
- import React, { Fragment } from 'react';
1
+ import React, { ComponentPropsWithRef, Fragment } from 'react';
2
2
  import classes from './BaseWizardSteps.module.scss';
3
3
  import readyclasses from '../../readyclasses.module.scss';
4
4
  import { Icon, Icons } from '../../Icon/Icon';
@@ -10,7 +10,7 @@ export interface Step {
10
10
  disabled?: boolean;
11
11
  }
12
12
 
13
- export interface Props extends Omit<React.HTMLProps<HTMLDivElement>, 'onClick'> {
13
+ export interface Props extends Omit<ComponentPropsWithRef<'div'>, 'onClick'> {
14
14
  steps: Step[];
15
15
  currentStepNo: number;
16
16
  onClick?: (stepNo: number) => void;
@@ -18,69 +18,74 @@ export interface Props extends Omit<React.HTMLProps<HTMLDivElement>, 'onClick'>
18
18
  stepScreenReaderLabel: string;
19
19
  }
20
20
 
21
- export const BaseWizardSteps = ({
22
- steps,
23
- currentStepNo,
24
- onClick,
25
- futureStepsClickable = false,
26
- stepScreenReaderLabel,
27
- ...restProps
28
- }: Props) => {
29
- const getStepState = (stepNo: number): StepState => {
30
- if (currentStepNo === stepNo) {
31
- return 'current';
32
- } else if (stepNo < currentStepNo) {
33
- return 'finished';
34
- }
35
- return 'future';
36
- };
21
+ export const BaseWizardSteps = React.forwardRef<HTMLDivElement, Props>(
22
+ (
23
+ {
24
+ steps,
25
+ currentStepNo,
26
+ onClick,
27
+ futureStepsClickable = false,
28
+ stepScreenReaderLabel,
29
+ ...rest
30
+ }: Props,
31
+ ref
32
+ ) => {
33
+ const getStepState = (stepNo: number): StepState => {
34
+ if (currentStepNo === stepNo) {
35
+ return 'current';
36
+ } else if (stepNo < currentStepNo) {
37
+ return 'finished';
38
+ }
39
+ return 'future';
40
+ };
41
+
42
+ const getStepContent = (stepState: StepState, index: number, disabled?: boolean) => {
43
+ const stepNumberString = String(index + 1);
44
+ if (stepState === 'finished') {
45
+ return disabled ? null : <Icon className={classes['checkmark']} icon={Icons.Checkmark} />;
46
+ } else {
47
+ return (
48
+ <Fragment>
49
+ <span className={readyclasses['sr-only']}>{stepScreenReaderLabel} </span>
50
+ {stepNumberString}
51
+ </Fragment>
52
+ );
53
+ }
54
+ };
55
+
56
+ const generatedSteps = steps.map((step, index) => {
57
+ const stepState = getStepState(index);
58
+ const disabledStyleClassName = step.disabled ? classes['disabled'] : '';
59
+ const clickableClassName = futureStepsClickable ? classes['clickable'] : '';
37
60
 
38
- const getStepContent = (stepState: StepState, index: number, disabled?: boolean) => {
39
- const stepNumberString = String(index + 1);
40
- if (stepState === 'finished') {
41
- return disabled ? null : <Icon className={classes['checkmark']} icon={Icons.Checkmark} />;
42
- } else {
43
61
  return (
44
- <Fragment>
45
- <span className={readyclasses['sr-only']}>{stepScreenReaderLabel} </span>
46
- {stepNumberString}
47
- </Fragment>
62
+ <button
63
+ key={step.label.toLowerCase().replace(/\s/, '-')}
64
+ disabled={
65
+ step.disabled ||
66
+ (stepState === 'future' && !futureStepsClickable) ||
67
+ stepState === 'current'
68
+ }
69
+ aria-current={stepState === 'current' ? 'step' : undefined}
70
+ onClick={() => onClick && onClick(index)}
71
+ className={`${classes['wizard-element']} ${classes[stepState]} ${clickableClassName} ${disabledStyleClassName}`}
72
+ >
73
+ <div className={classes['number-wrapper']}>
74
+ <span className={classes['number']}>
75
+ {getStepContent(stepState, index, step.disabled)}
76
+ </span>
77
+ </div>
78
+ <div className={classes['two-line-text-overflow']}>
79
+ <span className={classes['label']}>{step.label}</span>
80
+ </div>
81
+ </button>
48
82
  );
49
- }
50
- };
51
-
52
- const generatedSteps = steps.map((step, index) => {
53
- const stepState = getStepState(index);
54
- const disabledStyleClassName = step.disabled ? classes['disabled'] : '';
55
- const clickableClassName = futureStepsClickable ? classes['clickable'] : '';
83
+ });
56
84
 
57
85
  return (
58
- <button
59
- key={step.label.toLowerCase().replace(/\s/, '-')}
60
- disabled={
61
- step.disabled ||
62
- (stepState === 'future' && !futureStepsClickable) ||
63
- stepState === 'current'
64
- }
65
- aria-current={stepState === 'current' ? 'step' : undefined}
66
- onClick={() => onClick && onClick(index)}
67
- className={`${classes['wizard-element']} ${classes[stepState]} ${clickableClassName} ${disabledStyleClassName}`}
68
- >
69
- <div className={classes['number-wrapper']}>
70
- <span className={classes['number']}>
71
- {getStepContent(stepState, index, step.disabled)}
72
- </span>
73
- </div>
74
- <div className={classes['two-line-text-overflow']}>
75
- <span className={classes['label']}>{step.label}</span>
76
- </div>
77
- </button>
86
+ <div {...rest} ref={ref} className={classes['wizard']}>
87
+ {generatedSteps}
88
+ </div>
78
89
  );
79
- });
80
-
81
- return (
82
- <div {...restProps} className={classes['wizard']}>
83
- {generatedSteps}
84
- </div>
85
- );
86
- };
90
+ }
91
+ );
@@ -1,30 +1,33 @@
1
- import React, { useContext } from 'react';
1
+ import React, { ComponentPropsWithRef, useContext } from 'react';
2
2
  import { WizardStateContext } from '../WizardStateProvider';
3
3
  import { BaseWizardSteps } from '../BaseWizardSteps/BaseWizardSteps';
4
4
  import { changeCurrentStepNo } from '../wizardStateReducer';
5
5
 
6
- export interface Props extends Omit<React.HTMLProps<HTMLDivElement>, 'onClick'> {
6
+ export interface Props extends ComponentPropsWithRef<'div'> {
7
7
  onStepClick: (currentStepNo: number, selectedStepNo: number) => boolean;
8
8
  }
9
9
 
10
- export const WizardSteps = ({ onStepClick, ...restProps }: Props) => {
11
- const {
12
- state: { currentStepNo, mode, stepScreenReaderLabel, steps },
13
- dispatch,
14
- } = useContext(WizardStateContext);
10
+ export const WizardSteps = React.forwardRef<HTMLDivElement, Props>(
11
+ ({ onStepClick, ...rest }: Props, ref) => {
12
+ const {
13
+ state: { currentStepNo, mode, stepScreenReaderLabel, steps },
14
+ dispatch,
15
+ } = useContext(WizardStateContext);
15
16
 
16
- const onClick = (selectedStepNo: number) => {
17
- onStepClick(currentStepNo, selectedStepNo) && dispatch(changeCurrentStepNo(selectedStepNo));
18
- };
17
+ const onClick = (selectedStepNo: number) => {
18
+ onStepClick(currentStepNo, selectedStepNo) && dispatch(changeCurrentStepNo(selectedStepNo));
19
+ };
19
20
 
20
- return (
21
- <BaseWizardSteps
22
- {...restProps}
23
- onClick={onClick}
24
- steps={steps}
25
- currentStepNo={currentStepNo}
26
- stepScreenReaderLabel={stepScreenReaderLabel}
27
- futureStepsClickable={mode === 'edit'}
28
- />
29
- );
30
- };
21
+ return (
22
+ <BaseWizardSteps
23
+ {...rest}
24
+ ref={ref}
25
+ onClick={onClick}
26
+ steps={steps}
27
+ currentStepNo={currentStepNo}
28
+ stepScreenReaderLabel={stepScreenReaderLabel}
29
+ futureStepsClickable={mode === 'edit'}
30
+ />
31
+ );
32
+ }
33
+ );