@spaced-out/ui-design-system 0.1.15 → 0.1.17

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 (102) hide show
  1. package/.cspell/custom-words.txt +3 -0
  2. package/.flowconfig +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/CONTRIBUTING.md +52 -6
  5. package/README.md +144 -8
  6. package/gulpfile.js +1 -0
  7. package/lib/components/Avatar/Avatar.module.css +8 -2
  8. package/lib/components/AvatarGroup/AvatarGroup.js +25 -14
  9. package/lib/components/AvatarGroup/AvatarGroup.js.flow +118 -103
  10. package/lib/components/Badge/Badge.js +4 -3
  11. package/lib/components/Badge/Badge.js.flow +21 -21
  12. package/lib/components/Badge/index.js +11 -7
  13. package/lib/components/Badge/index.js.flow +1 -2
  14. package/lib/components/Banner/Banner.js +3 -2
  15. package/lib/components/Banner/Banner.js.flow +42 -35
  16. package/lib/components/Button/Button.js +50 -10
  17. package/lib/components/Button/Button.js.flow +87 -23
  18. package/lib/components/Button/Button.module.css +14 -0
  19. package/lib/components/ButtonTabs/ButtonTab/ButtonTab.js +3 -2
  20. package/lib/components/ButtonTabs/ButtonTab/ButtonTab.js.flow +48 -38
  21. package/lib/components/ButtonTabs/ButtonTabs.js +3 -2
  22. package/lib/components/ButtonTabs/ButtonTabs.js.flow +50 -41
  23. package/lib/components/Card/Card.js +16 -7
  24. package/lib/components/Card/Card.js.flow +73 -55
  25. package/lib/components/Checkbox/Checkbox.js +15 -10
  26. package/lib/components/Checkbox/Checkbox.js.flow +121 -100
  27. package/lib/components/Checkbox/Checkbox.module.css +4 -1
  28. package/lib/components/Checkbox/CheckboxGroup.js +4 -3
  29. package/lib/components/Checkbox/CheckboxGroup.js.flow +76 -65
  30. package/lib/components/Chip/Chip.js +3 -2
  31. package/lib/components/Chip/Chip.js.flow +66 -59
  32. package/lib/components/CircularLoader/CircularLoader.js +9 -4
  33. package/lib/components/CircularLoader/CircularLoader.js.flow +38 -24
  34. package/lib/components/CollapsibleCard/CollapsibleCard.js +4 -3
  35. package/lib/components/CollapsibleCard/CollapsibleCard.js.flow +68 -59
  36. package/lib/components/Dropdown/Dropdown.js +4 -3
  37. package/lib/components/Dropdown/Dropdown.js.flow +83 -74
  38. package/lib/components/EmptyState/EmptyState.js +4 -3
  39. package/lib/components/EmptyState/EmptyState.js.flow +53 -44
  40. package/lib/components/ErrorMessage/ErrorMessage.js +4 -3
  41. package/lib/components/ErrorMessage/ErrorMessage.js.flow +58 -49
  42. package/lib/components/InContextAlert/InContextAlert.js +4 -3
  43. package/lib/components/InContextAlert/InContextAlert.js.flow +79 -73
  44. package/lib/components/InlineDropdown/InlineDropdown.js +4 -3
  45. package/lib/components/InlineDropdown/InlineDropdown.js.flow +94 -85
  46. package/lib/components/LinearLoader/LinearLoader.js +4 -3
  47. package/lib/components/LinearLoader/LinearLoader.js.flow +20 -18
  48. package/lib/components/Link/Link.js +8 -1
  49. package/lib/components/Link/Link.js.flow +44 -36
  50. package/lib/components/Notification/Notification.js +8 -6
  51. package/lib/components/Notification/Notification.js.flow +96 -84
  52. package/lib/components/OptionButton/OptionButton.js +7 -4
  53. package/lib/components/OptionButton/OptionButton.js.flow +69 -59
  54. package/lib/components/PageTitle/PageTitle.js +4 -3
  55. package/lib/components/PageTitle/PageTitle.js.flow +46 -44
  56. package/lib/components/Pagination/PaginationItem.js +2 -2
  57. package/lib/components/Pagination/PaginationItem.js.flow +2 -2
  58. package/lib/components/RadioButton/RadioButton.js +15 -9
  59. package/lib/components/RadioButton/RadioButton.js.flow +91 -70
  60. package/lib/components/RadioButton/RadioButton.module.css +4 -1
  61. package/lib/components/RadioButton/RadioGroup.js +4 -3
  62. package/lib/components/RadioButton/RadioGroup.js.flow +56 -47
  63. package/lib/components/SearchInput/SearchInput.js +3 -2
  64. package/lib/components/SearchInput/SearchInput.js.flow +59 -50
  65. package/lib/components/SideMenuLink/SideMenuLink.js +4 -3
  66. package/lib/components/SideMenuLink/SideMenuLink.js.flow +54 -45
  67. package/lib/components/StatusIndicator/StatusIndicator.js +3 -2
  68. package/lib/components/StatusIndicator/StatusIndicator.js.flow +32 -23
  69. package/lib/components/SubMenu/SubMenu.js +4 -3
  70. package/lib/components/SubMenu/SubMenu.js.flow +41 -38
  71. package/lib/components/Table/StaticTable.js +3 -0
  72. package/lib/components/Table/StaticTable.js.flow +3 -0
  73. package/lib/components/Table/Table.js +10 -0
  74. package/lib/components/Table/Table.js.flow +10 -0
  75. package/lib/components/Table/hooks.js +1 -0
  76. package/lib/components/Table/hooks.js.flow +1 -0
  77. package/lib/components/Tabs/TabList/TabList.js +3 -2
  78. package/lib/components/Tabs/TabList/TabList.js.flow +127 -117
  79. package/lib/components/Toast/Toast.js +8 -10
  80. package/lib/components/Toast/Toast.js.flow +19 -27
  81. package/lib/components/Toast/Toast.module.css +8 -0
  82. package/lib/components/Toggle/Toggle.js +11 -7
  83. package/lib/components/Toggle/Toggle.js.flow +16 -12
  84. package/lib/components/Toggle/Toggle.module.css +2 -0
  85. package/lib/components/Toggle/index.js +11 -7
  86. package/lib/components/Toggle/index.js.flow +1 -1
  87. package/lib/components/Tooltip/Tooltip.js.flow +2 -2
  88. package/lib/components/index.js +511 -0
  89. package/lib/components/index.js.flow +48 -0
  90. package/lib/index.js +60 -0
  91. package/lib/index.js.flow +7 -0
  92. package/lib/styles/index.css +15 -0
  93. package/lib/styles/index.js +104 -0
  94. package/lib/styles/index.js.flow +12 -0
  95. package/lib/styles/typography.module.css +0 -1
  96. package/lib/styles/utils.module.css +26 -0
  97. package/lib/types/index.js +38 -0
  98. package/lib/types/index.js.flow +5 -0
  99. package/lib/utils/click-away.js.flow +1 -1
  100. package/lib/utils/index.js +93 -0
  101. package/lib/utils/index.js.flow +10 -0
  102. package/package.json +2 -1
@@ -3,6 +3,7 @@
3
3
  import * as React from 'react';
4
4
 
5
5
  import {classify} from '../../utils/classify';
6
+ import {CircularLoader} from '../CircularLoader';
6
7
  import type {IconType} from '../Icon';
7
8
  import {Icon} from '../Icon';
8
9
  import {Truncate} from '../Truncate';
@@ -29,32 +30,33 @@ export const BUTTON_ACTION_TYPE = Object.freeze({
29
30
  export type ButtonType = $Values<typeof BUTTON_TYPES>;
30
31
  export type ButtonActionType = $Values<typeof BUTTON_ACTION_TYPE>;
31
32
 
32
- export type UnstyledButtonProps = {
33
+ export type BaseButtonProps = {
33
34
  children?: React.Node,
34
35
  disabled?: mixed,
35
36
  actionType?: ButtonActionType,
36
37
  onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
37
- className?: string,
38
38
  ariaLabel?: string,
39
39
  tabIndex?: number,
40
+ isLoading?: boolean,
41
+ ...
42
+ };
43
+
44
+ export type UnstyledButtonProps = {
45
+ ...BaseButtonProps,
46
+ className?: string,
40
47
  ...
41
48
  };
42
49
 
43
50
  export type ButtonProps = {
44
- onClick?: ?(SyntheticEvent<HTMLElement>) => mixed,
51
+ ...BaseButtonProps,
45
52
  classNames?: ClassNames,
46
53
  iconLeftName?: string,
47
54
  iconLeftType?: IconType,
48
55
  iconRightName?: string,
49
56
  iconRightType?: IconType,
50
- children?: React.Node,
51
57
  type?: ButtonType,
52
- actionType?: ButtonActionType,
53
58
  isFluid?: boolean,
54
- disabled?: boolean,
55
59
  size?: 'medium' | 'small',
56
- ariaLabel?: string,
57
- tabIndex?: number,
58
60
  ...
59
61
  };
60
62
 
@@ -66,6 +68,14 @@ const ButtonTypeToIconColorMap = {
66
68
  danger: 'inversePrimary',
67
69
  };
68
70
 
71
+ const ButtonTypeToLoaderColorMap = {
72
+ primary: 'colorTextInversePrimary',
73
+ secondary: 'colorTextClickable',
74
+ tertiary: 'colorTextPrimary',
75
+ ghost: 'colorTextPrimary',
76
+ danger: 'colorTextInversePrimary',
77
+ };
78
+
69
79
  export const UnstyledButton: React$AbstractComponent<
70
80
  UnstyledButtonProps,
71
81
  HTMLButtonElement,
@@ -78,9 +88,10 @@ export const UnstyledButton: React$AbstractComponent<
78
88
  ariaLabel,
79
89
  actionType,
80
90
  tabIndex = 0,
91
+ isLoading,
81
92
  ...props
82
93
  }: UnstyledButtonProps,
83
- ref: React.Ref<'button'>,
94
+ ref,
84
95
  ) => (
85
96
  <button
86
97
  {...props}
@@ -92,7 +103,7 @@ export const UnstyledButton: React$AbstractComponent<
92
103
  tabIndex={disabled ? -1 : tabIndex}
93
104
  type={actionType}
94
105
  onClick={(event) => {
95
- if (disabled) {
106
+ if (disabled || isLoading) {
96
107
  event.preventDefault();
97
108
  } else if (onClick) {
98
109
  onClick(event);
@@ -117,6 +128,7 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
117
128
  disabled = false,
118
129
  actionType = 'button',
119
130
  size = 'medium',
131
+ isLoading,
120
132
  ...props
121
133
  }: ButtonProps,
122
134
  ref,
@@ -125,6 +137,7 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
125
137
  {...props}
126
138
  actionType={actionType}
127
139
  disabled={disabled}
140
+ isLoading={isLoading}
128
141
  className={classify(
129
142
  css.button,
130
143
  {
@@ -149,18 +162,49 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
149
162
  <div className={css.buttonRow}>
150
163
  {/* Has no icon, only child */}
151
164
  {!(iconLeftName || iconRightName) ? (
152
- <div className={css.textContainerCenter}>
153
- <Truncate>{children}</Truncate>
165
+ <div className={css.textContainer}>
166
+ {isLoading && (
167
+ <div className={css.loader}>
168
+ <CircularLoader
169
+ size={size}
170
+ colorToken={
171
+ disabled
172
+ ? 'colorTextDisabled'
173
+ : ButtonTypeToLoaderColorMap[type]
174
+ }
175
+ />
176
+ </div>
177
+ )}
178
+ <Truncate className={classify({[css.hidden]: isLoading})}>
179
+ {children}
180
+ </Truncate>
154
181
  </div>
155
182
  ) : // has icon, but no child
156
183
  children == null ? (
157
- <Icon
158
- name={iconLeftName || iconRightName}
159
- color={disabled ? 'disabled' : ButtonTypeToIconColorMap[type]}
160
- size={size === 'medium' ? 'medium' : 'small'}
161
- type={iconLeftName ? iconLeftType : iconRightType}
162
- className={classNames?.icon}
163
- />
184
+ <>
185
+ {isLoading && (
186
+ <div className={css.loader}>
187
+ <CircularLoader
188
+ size={size}
189
+ colorToken={
190
+ disabled
191
+ ? 'colorTextDisabled'
192
+ : ButtonTypeToLoaderColorMap[type]
193
+ }
194
+ />
195
+ </div>
196
+ )}
197
+ <Icon
198
+ name={iconLeftName || iconRightName}
199
+ color={disabled ? 'disabled' : ButtonTypeToIconColorMap[type]}
200
+ size={size === 'medium' ? 'medium' : 'small'}
201
+ type={iconLeftName ? iconLeftType : iconRightType}
202
+ className={classify(
203
+ {[css.hidden]: isLoading},
204
+ classNames?.icon,
205
+ )}
206
+ />
207
+ </>
164
208
  ) : (
165
209
  // has icon _and_ child
166
210
  (iconLeftName || iconRightName) && (
@@ -173,11 +217,28 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
173
217
  }
174
218
  size={size === 'medium' ? 'medium' : 'small'}
175
219
  type={iconLeftType}
176
- className={classNames?.icon}
220
+ className={classify(
221
+ {[css.hidden]: isLoading},
222
+ classNames?.icon,
223
+ )}
177
224
  />
178
225
  )}
179
- <div className={css.textContainerLeft}>
180
- <Truncate>{children}</Truncate>
226
+ <div className={css.textContainer}>
227
+ {isLoading && (
228
+ <div className={css.loader}>
229
+ <CircularLoader
230
+ size={size}
231
+ colorToken={
232
+ disabled
233
+ ? 'colorTextDisabled'
234
+ : ButtonTypeToLoaderColorMap[type]
235
+ }
236
+ />
237
+ </div>
238
+ )}
239
+ <Truncate className={classify({[css.hidden]: isLoading})}>
240
+ {children}
241
+ </Truncate>
181
242
  </div>
182
243
  {iconRightName && (
183
244
  <Icon
@@ -187,7 +248,10 @@ export const Button: React$AbstractComponent<ButtonProps, HTMLButtonElement> =
187
248
  }
188
249
  size={size === 'medium' ? 'medium' : 'small'}
189
250
  type={iconRightType}
190
- className={classNames?.icon}
251
+ className={classify(
252
+ {[css.hidden]: isLoading},
253
+ classNames?.icon,
254
+ )}
191
255
  />
192
256
  )}
193
257
  </>
@@ -63,6 +63,7 @@ button {
63
63
 
64
64
  .button {
65
65
  composes: motionEaseInEaseOut from '../../styles/animation.module.css';
66
+ position: relative;
66
67
  display: flex;
67
68
  flex-direction: row;
68
69
  padding: spaceNone spaceMedium;
@@ -84,6 +85,11 @@ button {
84
85
  column-gap: spaceXSmall;
85
86
  }
86
87
 
88
+ .textContainer {
89
+ display: flex;
90
+ align-items: center;
91
+ }
92
+
87
93
  .withIconLeft {
88
94
  padding: spaceNone spaceMedium spaceNone spaceSmall;
89
95
  }
@@ -226,3 +232,11 @@ button {
226
232
  background-color: colorFillDisabled;
227
233
  border: initial;
228
234
  }
235
+
236
+ .hidden {
237
+ visibility: hidden;
238
+ }
239
+
240
+ .loader {
241
+ composes: absoluteCenter from '../../styles/utils.module.css';
242
+ }
@@ -12,7 +12,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
12
12
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
13
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
14
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
15
- const ButtonTab = _ref => {
15
+ const ButtonTab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
16
16
  let {
17
17
  classNames,
18
18
  children,
@@ -29,6 +29,7 @@ const ButtonTab = _ref => {
29
29
  disabled: disabled,
30
30
  size: size,
31
31
  type: id === selectedButtonTabId ? 'tertiary' : 'ghost',
32
+ ref: ref,
32
33
  classNames: {
33
34
  wrapper: (0, _classify.default)(_ButtonTabModule.default.buttonTabWrapper, {
34
35
  [_ButtonTabModule.default.mediumButtonTab]: size === 'medium',
@@ -44,5 +45,5 @@ const ButtonTab = _ref => {
44
45
  iconLeftType: iconType,
45
46
  onClick: e => onButtonTabSelect && onButtonTabSelect(id, e)
46
47
  }), children);
47
- };
48
+ });
48
49
  exports.ButtonTab = ButtonTab;
@@ -23,45 +23,55 @@ export type ButtonTabProps = {
23
23
  ariaLabel?: string,
24
24
  id: string,
25
25
  selectedButtonTabId?: string,
26
+ isLoading?: boolean,
26
27
  ...
27
28
  };
28
29
 
29
- export const ButtonTab = ({
30
- classNames,
31
- children,
32
- iconName,
33
- iconType = 'regular',
34
- size,
35
- onButtonTabSelect,
36
- id,
37
- selectedButtonTabId,
38
- disabled,
39
- ...props
40
- }: ButtonTabProps): React.Node => (
41
- <Button
42
- {...props}
43
- disabled={disabled}
44
- size={size}
45
- type={id === selectedButtonTabId ? 'tertiary' : 'ghost'}
46
- classNames={{
47
- wrapper: classify(
48
- css.buttonTabWrapper,
49
- {
50
- [css.mediumButtonTab]: size === 'medium',
51
- [css.smallButtonTab]: size === 'small',
52
- [css.onlyIcon]: iconName && !children,
53
- [css.isSelected]: id === selectedButtonTabId,
54
- [css.isUnSelected]: id !== selectedButtonTabId,
55
- [css.disabled]: disabled,
56
- },
57
- classNames?.wrapper,
58
- ),
59
- icon: css.icon,
60
- }}
61
- iconLeftName={iconName}
62
- iconLeftType={iconType}
63
- onClick={(e) => onButtonTabSelect && onButtonTabSelect(id, e)}
64
- >
65
- {children}
66
- </Button>
30
+ export const ButtonTab: React$AbstractComponent<
31
+ ButtonTabProps,
32
+ HTMLButtonElement,
33
+ > = React.forwardRef<ButtonTabProps, HTMLButtonElement>(
34
+ (
35
+ {
36
+ classNames,
37
+ children,
38
+ iconName,
39
+ iconType = 'regular',
40
+ size,
41
+ onButtonTabSelect,
42
+ id,
43
+ selectedButtonTabId,
44
+ disabled,
45
+ ...props
46
+ }: ButtonTabProps,
47
+ ref,
48
+ ): React.Node => (
49
+ <Button
50
+ {...props}
51
+ disabled={disabled}
52
+ size={size}
53
+ type={id === selectedButtonTabId ? 'tertiary' : 'ghost'}
54
+ ref={ref}
55
+ classNames={{
56
+ wrapper: classify(
57
+ css.buttonTabWrapper,
58
+ {
59
+ [css.mediumButtonTab]: size === 'medium',
60
+ [css.smallButtonTab]: size === 'small',
61
+ [css.onlyIcon]: iconName && !children,
62
+ [css.isSelected]: id === selectedButtonTabId,
63
+ [css.isUnSelected]: id !== selectedButtonTabId,
64
+ [css.disabled]: disabled,
65
+ },
66
+ classNames?.wrapper,
67
+ ),
68
+ icon: css.icon,
69
+ }}
70
+ iconLeftName={iconName}
71
+ iconLeftType={iconType}
72
+ onClick={(e) => onButtonTabSelect && onButtonTabSelect(id, e)}
73
+ >
74
+ {children}
75
+ </Button>
76
+ ),
67
77
  );
@@ -11,7 +11,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
11
11
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
12
12
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
13
 
14
- const ButtonTabs = _ref => {
14
+ const ButtonTabs = /*#__PURE__*/React.forwardRef((_ref, ref) => {
15
15
  let {
16
16
  classNames,
17
17
  children,
@@ -36,6 +36,7 @@ const ButtonTabs = _ref => {
36
36
  });
37
37
  return /*#__PURE__*/React.createElement("div", {
38
38
  "data-testid": "ButtonTabs",
39
+ ref: ref,
39
40
  className: (0, _classify.default)(_ButtonTabsModule.default.buttonTabsWrapper, {
40
41
  [_ButtonTabsModule.default.medium]: size === 'medium',
41
42
  [_ButtonTabsModule.default.small]: size === 'small',
@@ -43,5 +44,5 @@ const ButtonTabs = _ref => {
43
44
  [_ButtonTabsModule.default.disabled]: disabled
44
45
  }, classNames?.wrapper)
45
46
  }, childrenWithProps);
46
- };
47
+ });
47
48
  exports.ButtonTabs = ButtonTabs;
@@ -19,44 +19,53 @@ export type ButtonTabsProps = {
19
19
  onButtonTabSelect?: ?(id: string, e?: SyntheticEvent<HTMLElement>) => mixed,
20
20
  };
21
21
 
22
- export const ButtonTabs = ({
23
- classNames,
24
- children,
25
- isFluid,
26
- size = 'medium',
27
- disabled,
28
- selectedButtonTabId,
29
- onButtonTabSelect,
30
- }: ButtonTabsProps): React.Node => {
31
- const childrenWithProps = React.Children.map(children, (child) => {
32
- if (React.isValidElement(child)) {
33
- return React.cloneElement(child, {
34
- ...child.props,
35
- isFluid,
36
- size,
37
- disabled,
38
- selectedButtonTabId,
39
- onButtonTabSelect,
40
- });
41
- }
42
- return child;
43
- });
44
-
45
- return (
46
- <div
47
- data-testid="ButtonTabs"
48
- className={classify(
49
- css.buttonTabsWrapper,
50
- {
51
- [css.medium]: size === 'medium',
52
- [css.small]: size === 'small',
53
- [css.isFluid]: isFluid,
54
- [css.disabled]: disabled,
55
- },
56
- classNames?.wrapper,
57
- )}
58
- >
59
- {childrenWithProps}
60
- </div>
61
- );
62
- };
22
+ export const ButtonTabs: React$AbstractComponent<
23
+ ButtonTabsProps,
24
+ HTMLDivElement,
25
+ > = React.forwardRef<ButtonTabsProps, HTMLDivElement>(
26
+ (
27
+ {
28
+ classNames,
29
+ children,
30
+ isFluid,
31
+ size = 'medium',
32
+ disabled,
33
+ selectedButtonTabId,
34
+ onButtonTabSelect,
35
+ }: ButtonTabsProps,
36
+ ref,
37
+ ): React.Node => {
38
+ const childrenWithProps = React.Children.map(children, (child) => {
39
+ if (React.isValidElement(child)) {
40
+ return React.cloneElement(child, {
41
+ ...child.props,
42
+ isFluid,
43
+ size,
44
+ disabled,
45
+ selectedButtonTabId,
46
+ onButtonTabSelect,
47
+ });
48
+ }
49
+ return child;
50
+ });
51
+
52
+ return (
53
+ <div
54
+ data-testid="ButtonTabs"
55
+ ref={ref}
56
+ className={classify(
57
+ css.buttonTabsWrapper,
58
+ {
59
+ [css.medium]: size === 'medium',
60
+ [css.small]: size === 'small',
61
+ [css.isFluid]: isFluid,
62
+ [css.disabled]: disabled,
63
+ },
64
+ classNames?.wrapper,
65
+ )}
66
+ >
67
+ {childrenWithProps}
68
+ </div>
69
+ );
70
+ },
71
+ );
@@ -23,7 +23,7 @@ const getPaddingValue = size => {
23
23
  const spaceKey = 'space' + (0, _string.capitalize)(size);
24
24
  return SPACES[spaceKey] || SPACES['spaceNone'];
25
25
  };
26
- const Card = _ref => {
26
+ const Card = /*#__PURE__*/React.forwardRef((_ref, ref) => {
27
27
  let {
28
28
  children,
29
29
  classNames,
@@ -41,17 +41,25 @@ const Card = _ref => {
41
41
  '--card-padding-left': getPaddingValue(paddingLeft)
42
42
  },
43
43
  "data-testid": "Card",
44
- className: (0, _classify.default)(_CardModule.default.cardWrapper, classNames?.wrapper)
44
+ className: (0, _classify.default)(_CardModule.default.cardWrapper, classNames?.wrapper),
45
+ ref: ref
45
46
  }), children);
46
- };
47
+ });
47
48
  exports.Card = Card;
48
- const ClickableCard = _ref2 => {
49
+ const ClickableCard = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
49
50
  let {
50
51
  classNames,
51
52
  onClick,
52
53
  disabled = false,
53
54
  ...props
54
55
  } = _ref2;
56
+ const componentRef = React.useRef(null);
57
+ React.useImperativeHandle(ref, () => componentRef.current);
58
+ React.useEffect(() => {
59
+ if (disabled) {
60
+ componentRef.current?.blur();
61
+ }
62
+ }, [disabled]);
55
63
  const onClickHandler = e => {
56
64
  if (!disabled) {
57
65
  onClick && onClick(e);
@@ -68,9 +76,10 @@ const ClickableCard = _ref2 => {
68
76
  [_CardModule.default.disabled]: disabled
69
77
  }, classNames?.wrapper)
70
78
  },
71
- tabIndex: "0",
79
+ tabIndex: disabled ? -1 : 0,
72
80
  onClick: onClickHandler,
73
- onKeyDown: onKeyDownHandler
81
+ onKeyDown: onKeyDownHandler,
82
+ ref: ref
74
83
  }));
75
- };
84
+ });
76
85
  exports.ClickableCard = ClickableCard;
@@ -41,59 +41,77 @@ const getPaddingValue = (size: PaddingSizeType): string => {
41
41
  return SPACES[spaceKey] || SPACES['spaceNone'];
42
42
  };
43
43
 
44
- export const Card = ({
45
- children,
46
- classNames,
47
- paddingTop = 'medium',
48
- paddingRight = 'medium',
49
- paddingBottom = 'medium',
50
- paddingLeft = 'medium',
51
- ...props
52
- }: CardProps): React.Node => (
53
- <div
54
- {...props}
55
- style={{
56
- '--card-padding-top': getPaddingValue(paddingTop),
57
- '--card-padding-right': getPaddingValue(paddingRight),
58
- '--card-padding-bottom': getPaddingValue(paddingBottom),
59
- '--card-padding-left': getPaddingValue(paddingLeft),
60
- }}
61
- data-testid="Card"
62
- className={classify(css.cardWrapper, classNames?.wrapper)}
63
- >
64
- {children}
65
- </div>
66
- );
67
-
68
- export const ClickableCard = ({
69
- classNames,
70
- onClick,
71
- disabled = false,
72
- ...props
73
- }: ClickableCardProps): React.Node => {
74
- const onClickHandler = (e) => {
75
- if (!disabled) {
76
- onClick && onClick(e);
77
- }
78
- };
79
- const onKeyDownHandler = (e) => {
80
- if (e.key === 'Enter') {
81
- onClickHandler(e);
82
- }
83
- };
84
- return (
85
- <Card
86
- {...props}
87
- classNames={{
88
- wrapper: classify(
89
- css.clickableCard,
90
- {[css.disabled]: disabled},
91
- classNames?.wrapper,
92
- ),
93
- }}
94
- tabIndex="0"
95
- onClick={onClickHandler}
96
- onKeyDown={onKeyDownHandler}
97
- />
44
+ export const Card: React$AbstractComponent<CardProps, HTMLDivElement> =
45
+ React.forwardRef<CardProps, HTMLDivElement>(
46
+ (
47
+ {
48
+ children,
49
+ classNames,
50
+ paddingTop = 'medium',
51
+ paddingRight = 'medium',
52
+ paddingBottom = 'medium',
53
+ paddingLeft = 'medium',
54
+ ...props
55
+ }: CardProps,
56
+ ref,
57
+ ): React.Node => (
58
+ <div
59
+ {...props}
60
+ style={{
61
+ '--card-padding-top': getPaddingValue(paddingTop),
62
+ '--card-padding-right': getPaddingValue(paddingRight),
63
+ '--card-padding-bottom': getPaddingValue(paddingBottom),
64
+ '--card-padding-left': getPaddingValue(paddingLeft),
65
+ }}
66
+ data-testid="Card"
67
+ className={classify(css.cardWrapper, classNames?.wrapper)}
68
+ ref={ref}
69
+ >
70
+ {children}
71
+ </div>
72
+ ),
98
73
  );
99
- };
74
+
75
+ export const ClickableCard: React$AbstractComponent<
76
+ ClickableCardProps,
77
+ HTMLDivElement,
78
+ > = React.forwardRef<ClickableCardProps, HTMLDivElement>(
79
+ (
80
+ {classNames, onClick, disabled = false, ...props}: ClickableCardProps,
81
+ ref,
82
+ ): React.Node => {
83
+ const componentRef = React.useRef(null);
84
+ React.useImperativeHandle(ref, () => componentRef.current);
85
+ React.useEffect(() => {
86
+ if (disabled) {
87
+ componentRef.current?.blur();
88
+ }
89
+ }, [disabled]);
90
+ const onClickHandler = (e) => {
91
+ if (!disabled) {
92
+ onClick && onClick(e);
93
+ }
94
+ };
95
+ const onKeyDownHandler = (e) => {
96
+ if (e.key === 'Enter') {
97
+ onClickHandler(e);
98
+ }
99
+ };
100
+ return (
101
+ <Card
102
+ {...props}
103
+ classNames={{
104
+ wrapper: classify(
105
+ css.clickableCard,
106
+ {[css.disabled]: disabled},
107
+ classNames?.wrapper,
108
+ ),
109
+ }}
110
+ tabIndex={disabled ? -1 : 0}
111
+ onClick={onClickHandler}
112
+ onKeyDown={onKeyDownHandler}
113
+ ref={ref}
114
+ />
115
+ );
116
+ },
117
+ );