@react-ui-org/react-ui 0.47.0 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. package/dist/lib.development.js +465 -93
  2. package/dist/lib.js +1 -1
  3. package/package.json +1 -1
  4. package/src/lib/components/Alert/Alert.jsx +3 -0
  5. package/src/lib/components/Alert/Alert.scss +10 -10
  6. package/src/lib/components/Alert/README.mdx +18 -2
  7. package/src/lib/components/Alert/index.js +1 -1
  8. package/src/lib/components/Badge/Badge.jsx +4 -8
  9. package/src/lib/components/Badge/Badge.scss +21 -21
  10. package/src/lib/components/Badge/README.mdx +15 -1
  11. package/src/lib/components/Badge/index.js +1 -1
  12. package/src/lib/components/Button/Button.jsx +23 -34
  13. package/src/lib/components/Button/README.mdx +21 -7
  14. package/src/lib/components/Button/_base.scss +20 -20
  15. package/src/lib/components/Button/_priorities.scss +35 -35
  16. package/src/lib/components/Button/helpers/getRootLabelVisibilityClassName.js +7 -7
  17. package/src/lib/components/Button/helpers/getRootPriorityClassName.js +3 -3
  18. package/src/lib/components/Button/index.js +1 -1
  19. package/src/lib/components/ButtonGroup/ButtonGroup.jsx +2 -8
  20. package/src/lib/components/ButtonGroup/README.mdx +18 -2
  21. package/src/lib/components/Card/Card.jsx +6 -10
  22. package/src/lib/components/Card/Card.scss +13 -13
  23. package/src/lib/components/Card/CardBody.jsx +6 -10
  24. package/src/lib/components/Card/CardFooter.jsx +6 -7
  25. package/src/lib/components/Card/README.mdx +21 -5
  26. package/src/lib/components/CheckboxField/CheckboxField.jsx +17 -44
  27. package/src/lib/components/CheckboxField/README.mdx +18 -6
  28. package/src/lib/components/CheckboxField/index.js +1 -1
  29. package/src/lib/components/FileInputField/FileInputField.jsx +20 -29
  30. package/src/lib/components/FileInputField/FileInputField.scss +3 -3
  31. package/src/lib/components/FileInputField/README.mdx +30 -28
  32. package/src/lib/components/FileInputField/index.js +1 -1
  33. package/src/lib/components/FormLayout/FormLayout.jsx +5 -9
  34. package/src/lib/components/FormLayout/FormLayout.scss +3 -3
  35. package/src/lib/components/FormLayout/FormLayoutCustomField.jsx +4 -1
  36. package/src/lib/components/FormLayout/FormLayoutCustomField.scss +8 -8
  37. package/src/lib/components/FormLayout/README.mdx +28 -13
  38. package/src/lib/components/Grid/Grid.jsx +31 -35
  39. package/src/lib/components/Grid/Grid.scss +10 -15
  40. package/src/lib/components/Grid/GridSpan.jsx +5 -11
  41. package/src/lib/components/Grid/README.mdx +48 -36
  42. package/src/lib/components/Grid/_helpers/generateResponsiveCustomProperties.js +11 -3
  43. package/src/lib/components/Grid/_settings.scss +18 -0
  44. package/src/lib/components/Grid/_tools.scss +5 -5
  45. package/src/lib/components/Modal/Modal.jsx +147 -254
  46. package/src/lib/components/Modal/Modal.scss +7 -55
  47. package/src/lib/components/Modal/ModalBody.jsx +60 -0
  48. package/src/lib/components/Modal/ModalBody.scss +18 -0
  49. package/src/lib/components/Modal/ModalCloseButton.jsx +45 -0
  50. package/src/lib/components/Modal/ModalCloseButton.scss +18 -0
  51. package/src/lib/components/Modal/ModalContent.jsx +39 -0
  52. package/src/lib/components/Modal/ModalContent.scss +5 -0
  53. package/src/lib/components/Modal/ModalFooter.jsx +42 -0
  54. package/src/lib/components/Modal/ModalFooter.scss +35 -0
  55. package/src/lib/components/Modal/ModalHeader.jsx +44 -0
  56. package/src/lib/components/Modal/ModalHeader.scss +30 -0
  57. package/src/lib/components/Modal/ModalTitle.jsx +44 -0
  58. package/src/lib/components/Modal/ModalTitle.scss +10 -0
  59. package/src/lib/components/Modal/README.mdx +865 -195
  60. package/src/lib/components/Modal/_helpers/getJustifyClassName.js +19 -0
  61. package/src/lib/components/Modal/_helpers/getScrollingClassName.js +11 -0
  62. package/src/lib/components/Modal/_settings.scss +1 -5
  63. package/src/lib/components/Modal/_theme.scss +6 -0
  64. package/src/lib/components/Modal/index.js +7 -1
  65. package/src/lib/components/Paper/Paper.jsx +5 -9
  66. package/src/lib/components/Paper/Paper.scss +2 -2
  67. package/src/lib/components/Paper/README.mdx +15 -1
  68. package/src/lib/components/Paper/index.js +1 -1
  69. package/src/lib/components/Popover/Popover.jsx +14 -30
  70. package/src/lib/components/Popover/Popover.scss +7 -6
  71. package/src/lib/components/Popover/PopoverWrapper.jsx +5 -12
  72. package/src/lib/components/Popover/PopoverWrapper.scss +3 -0
  73. package/src/lib/components/Popover/README.mdx +32 -11
  74. package/src/lib/components/Popover/_theme.scss +1 -1
  75. package/src/lib/components/Radio/README.mdx +13 -6
  76. package/src/lib/components/Radio/Radio.jsx +39 -29
  77. package/src/lib/components/Radio/Radio.scss +3 -3
  78. package/src/lib/components/Radio/index.js +1 -1
  79. package/src/lib/components/ScrollView/README.mdx +165 -84
  80. package/src/lib/components/ScrollView/ScrollView.jsx +115 -117
  81. package/src/lib/components/ScrollView/ScrollView.scss +18 -16
  82. package/src/lib/components/ScrollView/index.js +1 -1
  83. package/src/lib/components/SelectField/README.mdx +83 -7
  84. package/src/lib/components/SelectField/SelectField.jsx +86 -61
  85. package/src/lib/components/SelectField/SelectField.scss +8 -8
  86. package/src/lib/components/SelectField/_components/Option/Option.jsx +46 -0
  87. package/src/lib/components/SelectField/_components/Option/index.js +1 -0
  88. package/src/lib/components/SelectField/index.js +1 -1
  89. package/src/lib/components/Table/README.mdx +25 -9
  90. package/src/lib/components/Table/Table.jsx +43 -101
  91. package/src/lib/components/Table/Table.scss +0 -24
  92. package/src/lib/components/Table/_components/TableBodyCell/TableBodyCell.jsx +46 -0
  93. package/src/lib/components/Table/_components/TableBodyCell/index.js +1 -0
  94. package/src/lib/components/Table/_components/TableCell.scss +25 -0
  95. package/src/lib/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx +71 -0
  96. package/src/lib/components/Table/_components/TableHeaderCell/index.js +1 -0
  97. package/src/lib/components/Table/index.js +1 -1
  98. package/src/lib/components/Tabs/README.mdx +21 -3
  99. package/src/lib/components/Tabs/Tabs.jsx +6 -1
  100. package/src/lib/components/Tabs/TabsItem.jsx +3 -0
  101. package/src/lib/components/Tabs/TabsItem.scss +1 -2
  102. package/src/lib/components/Text/README.mdx +25 -7
  103. package/src/lib/components/Text/Text.jsx +3 -7
  104. package/src/lib/components/Text/Text.scss +6 -6
  105. package/src/lib/components/Text/_helpers/getRootClampClassName.js +2 -2
  106. package/src/lib/components/Text/_helpers/getRootHyphensClassName.js +2 -2
  107. package/src/lib/components/Text/_helpers/getRootWordWrappingClassName.js +2 -2
  108. package/src/lib/components/Text/index.js +1 -1
  109. package/src/lib/components/TextArea/README.mdx +34 -31
  110. package/src/lib/components/TextArea/TextArea.jsx +23 -63
  111. package/src/lib/components/TextArea/TextArea.scss +8 -8
  112. package/src/lib/components/TextArea/index.js +1 -1
  113. package/src/lib/components/TextField/README.mdx +56 -54
  114. package/src/lib/components/TextField/TextField.jsx +25 -52
  115. package/src/lib/components/TextField/TextField.scss +9 -9
  116. package/src/lib/components/TextField/index.js +1 -1
  117. package/src/lib/components/TextLink/README.mdx +13 -6
  118. package/src/lib/components/TextLink/TextLink.jsx +0 -10
  119. package/src/lib/components/TextLink/index.js +1 -1
  120. package/src/lib/components/Toggle/README.mdx +18 -6
  121. package/src/lib/components/Toggle/Toggle.jsx +18 -44
  122. package/src/lib/components/Toggle/index.js +1 -1
  123. package/src/lib/components/Toolbar/README.mdx +21 -6
  124. package/src/lib/components/Toolbar/Toolbar.jsx +9 -43
  125. package/src/lib/components/Toolbar/Toolbar.scss +24 -12
  126. package/src/lib/components/Toolbar/ToolbarGroup.jsx +7 -26
  127. package/src/lib/components/Toolbar/ToolbarItem.jsx +3 -7
  128. package/src/lib/components/Toolbar/_helpers/getAlignClassName.js +19 -0
  129. package/src/lib/components/Toolbar/_helpers/getJustifyClassName.js +16 -0
  130. package/src/lib/components/_helpers/getRootColorClassName.js +10 -10
  131. package/src/lib/components/_helpers/getRootSizeClassName.js +3 -3
  132. package/src/lib/components/_helpers/transferProps.js +1 -1
  133. package/src/lib/index.js +24 -16
  134. package/src/lib/provider/withGlobalProps.jsx +20 -3
  135. package/src/lib/styles/tools/form-fields/_box-field-layout.scss +15 -15
  136. package/src/lib/styles/tools/form-fields/_inline-field-elements.scss +1 -1
  137. package/src/lib/styles/tools/form-fields/_inline-field-layout.scss +9 -9
  138. package/src/lib/theme.scss +18 -26
  139. package/src/lib/translations/en.js +1 -1
  140. package/src/lib/components/Grid/_theme.scss +0 -11
  141. package/src/lib/components/ScrollView/_theme.scss +0 -2
  142. package/src/lib/components/withForwardedRef.jsx +0 -11
@@ -7,27 +7,27 @@ import { getRootValidationStateClassName } from '../_helpers/getRootValidationSt
7
7
  import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
8
8
  import { transferProps } from '../_helpers/transferProps';
9
9
  import { FormLayoutContext } from '../FormLayout';
10
- import withForwardedRef from '../withForwardedRef';
10
+ import { Option } from './_components/Option';
11
11
  import styles from './SelectField.scss';
12
12
 
13
- export const SelectField = ({
14
- disabled,
15
- forwardedRef,
16
- fullWidth,
17
- helpText,
18
- id,
19
- isLabelVisible,
20
- label,
21
- layout,
22
- options,
23
- required,
24
- size,
25
- validationState,
26
- validationText,
27
- value,
28
- variant,
29
- ...restProps
30
- }) => {
13
+ export const SelectField = React.forwardRef((props, ref) => {
14
+ const {
15
+ disabled,
16
+ fullWidth,
17
+ helpText,
18
+ id,
19
+ isLabelVisible,
20
+ label,
21
+ layout,
22
+ options,
23
+ required,
24
+ size,
25
+ validationState,
26
+ validationText,
27
+ variant,
28
+ ...restProps
29
+ } = props;
30
+
31
31
  const context = useContext(FormLayoutContext);
32
32
 
33
33
  return (
@@ -37,13 +37,13 @@ export const SelectField = ({
37
37
  fullWidth && styles.isRootFullWidth,
38
38
  context && styles.isRootInFormLayout,
39
39
  resolveContextOrProp(context && context.layout, layout) === 'horizontal'
40
- ? styles.rootLayoutHorizontal
41
- : styles.rootLayoutVertical,
40
+ ? styles.isRootLayoutHorizontal
41
+ : styles.isRootLayoutVertical,
42
42
  disabled && styles.isRootDisabled,
43
43
  required && styles.isRootRequired,
44
44
  getRootSizeClassName(size, styles),
45
45
  getRootValidationStateClassName(validationState, styles),
46
- variant === 'filled' ? styles.rootVariantFilled : styles.rootVariantOutline,
46
+ variant === 'filled' ? styles.isRootVariantFilled : styles.isRootVariantOutline,
47
47
  )}
48
48
  htmlFor={id}
49
49
  id={id && `${id}__label`}
@@ -64,21 +64,35 @@ export const SelectField = ({
64
64
  className={styles.input}
65
65
  disabled={disabled}
66
66
  id={id}
67
- ref={forwardedRef}
67
+ ref={ref}
68
68
  required={required}
69
- value={value}
70
69
  >
71
70
  {
72
- options.map((option) => (
73
- <option
74
- disabled={option.disabled}
75
- id={id && `${id}__item__${option.value}`}
76
- key={option.value}
77
- value={option.value}
78
- >
79
- {option.label}
80
- </option>
81
- ))
71
+ options.map((option) => {
72
+ if ('options' in option) {
73
+ return (
74
+ <optgroup
75
+ key={option.key ?? option.label}
76
+ label={option.label}
77
+ >
78
+ {option.options.map((optgroupOption) => (
79
+ <Option
80
+ key={optgroupOption.key ?? optgroupOption.value}
81
+ {...optgroupOption}
82
+ {...(id && { id: `${id}__item__${optgroupOption.key ?? optgroupOption.value}` })}
83
+ />
84
+ ))}
85
+ </optgroup>
86
+ );
87
+ }
88
+ return (
89
+ <Option
90
+ key={option.key ?? option.value}
91
+ {...option}
92
+ {...(id && { id: `${id}__item__${option.key ?? option.value}` })}
93
+ />
94
+ );
95
+ })
82
96
  }
83
97
  </select>
84
98
  <div className={styles.caret}>
@@ -107,11 +121,10 @@ export const SelectField = ({
107
121
  </div>
108
122
  </label>
109
123
  );
110
- };
124
+ });
111
125
 
112
126
  SelectField.defaultProps = {
113
127
  disabled: false,
114
- forwardedRef: undefined,
115
128
  fullWidth: false,
116
129
  helpText: null,
117
130
  id: undefined,
@@ -121,7 +134,6 @@ SelectField.defaultProps = {
121
134
  size: 'medium',
122
135
  validationState: null,
123
136
  validationText: null,
124
- value: undefined,
125
137
  variant: 'outline',
126
138
  };
127
139
 
@@ -130,14 +142,6 @@ SelectField.propTypes = {
130
142
  * If `true`, the input will be disabled.
131
143
  */
132
144
  disabled: PropTypes.bool,
133
- /**
134
- * Reference forwarded to the `select` element.
135
- */
136
- forwardedRef: PropTypes.oneOfType([
137
- PropTypes.func,
138
- // eslint-disable-next-line react/forbid-prop-types
139
- PropTypes.shape({ current: PropTypes.any }),
140
- ]),
141
145
  /**
142
146
  * If `true`, the field will span the full width of its parent.
143
147
  */
@@ -157,6 +161,9 @@ SelectField.propTypes = {
157
161
  *
158
162
  * and of individual options:
159
163
  * * `<ID>__item__<VALUE>`
164
+ *
165
+ * If `key` in the option definition object is set,
166
+ * then `option.key` is used instead of `option.value` in place of `<VALUE>`.
160
167
  */
161
168
  id: PropTypes.string,
162
169
  /**
@@ -177,15 +184,40 @@ SelectField.propTypes = {
177
184
  layout: PropTypes.oneOf(['horizontal', 'vertical']),
178
185
  /**
179
186
  * Set of options to be chosen from.
187
+ *
188
+ * Either set of individual or grouped options is acceptable.
189
+ *
190
+ * For generating unique IDs the `option.value` is normally used. For cases when this is not practical or
191
+ * the `option.value` values are not unique the `option.key` attribute can be set manually.
192
+ * The same applies for the `label` value of grouped options which is supposed to be unique.
193
+ * To ensure uniqueness `key` attribute can be set manually.
180
194
  */
181
- options: PropTypes.arrayOf(PropTypes.shape({
182
- disabled: PropTypes.bool,
183
- label: PropTypes.string.isRequired,
184
- value: PropTypes.oneOfType([
185
- PropTypes.string,
186
- PropTypes.number,
187
- ]),
188
- })).isRequired,
195
+ options: PropTypes.oneOfType([
196
+ PropTypes.arrayOf(
197
+ PropTypes.shape({
198
+ key: PropTypes.string,
199
+ label: PropTypes.string.isRequired,
200
+ options: PropTypes.arrayOf(PropTypes.shape({
201
+ disabled: PropTypes.bool,
202
+ key: PropTypes.string,
203
+ label: PropTypes.string.isRequired,
204
+ value: PropTypes.oneOfType([
205
+ PropTypes.string,
206
+ PropTypes.number,
207
+ ]),
208
+ })),
209
+ }),
210
+ ),
211
+ PropTypes.arrayOf(PropTypes.shape({
212
+ disabled: PropTypes.bool,
213
+ key: PropTypes.string,
214
+ label: PropTypes.string.isRequired,
215
+ value: PropTypes.oneOfType([
216
+ PropTypes.string,
217
+ PropTypes.number,
218
+ ]),
219
+ })),
220
+ ]).isRequired,
189
221
  /**
190
222
  * If `true`, the input will be required.
191
223
  */
@@ -202,19 +234,12 @@ SelectField.propTypes = {
202
234
  * Validation message to be displayed.
203
235
  */
204
236
  validationText: PropTypes.node,
205
- /**
206
- * Value of the input.
207
- */
208
- value: PropTypes.oneOfType([
209
- PropTypes.string,
210
- PropTypes.number,
211
- ]),
212
237
  /**
213
238
  * Design variant of the field, further customizable with CSS custom properties.
214
239
  */
215
240
  variant: PropTypes.oneOf(['filled', 'outline']),
216
241
  };
217
242
 
218
- export const SelectFieldWithGlobalProps = withForwardedRef(withGlobalProps(SelectField, 'SelectField'));
243
+ export const SelectFieldWithGlobalProps = withGlobalProps(SelectField, 'SelectField');
219
244
 
220
245
  export default SelectFieldWithGlobalProps;
@@ -46,11 +46,11 @@
46
46
  }
47
47
 
48
48
  // Variants
49
- .rootVariantFilled {
49
+ .isRootVariantFilled {
50
50
  @include variants.visual(box, $variant: filled, $has-caret: true);
51
51
  }
52
52
 
53
- .rootVariantOutline {
53
+ .isRootVariantOutline {
54
54
  @include variants.visual(box, $variant: outline, $has-caret: true);
55
55
  }
56
56
 
@@ -73,12 +73,12 @@
73
73
  }
74
74
 
75
75
  // Layouts
76
- .rootLayoutVertical,
77
- .rootLayoutHorizontal {
76
+ .isRootLayoutVertical,
77
+ .isRootLayoutHorizontal {
78
78
  @include box-field-layout.vertical();
79
79
  }
80
80
 
81
- .rootLayoutHorizontal {
81
+ .isRootLayoutHorizontal {
82
82
  @include box-field-layout.horizontal();
83
83
  }
84
84
 
@@ -91,14 +91,14 @@
91
91
  }
92
92
 
93
93
  // Sizes
94
- .rootSizeSmall {
94
+ .isRootSizeSmall {
95
95
  @include box-field-sizes.size(small);
96
96
  }
97
97
 
98
- .rootSizeMedium {
98
+ .isRootSizeMedium {
99
99
  @include box-field-sizes.size(medium);
100
100
  }
101
101
 
102
- .rootSizeLarge {
102
+ .isRootSizeLarge {
103
103
  @include box-field-sizes.size(large);
104
104
  }
@@ -0,0 +1,46 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+
4
+ export const Option = ({
5
+ disabled,
6
+ id,
7
+ label,
8
+ value,
9
+ }) => (
10
+ <option
11
+ disabled={disabled}
12
+ id={id}
13
+ value={value}
14
+ >
15
+ {label}
16
+ </option>
17
+ );
18
+
19
+ Option.defaultProps = {
20
+ disabled: false,
21
+ id: undefined,
22
+ };
23
+
24
+ Option.propTypes = {
25
+ /**
26
+ * If `true` the option cannot be selected.
27
+ */
28
+ disabled: PropTypes.bool,
29
+ /**
30
+ * ID of an individual option.
31
+ */
32
+ id: PropTypes.string,
33
+ /**
34
+ * Option label.
35
+ */
36
+ label: PropTypes.string.isRequired,
37
+ /**
38
+ * Option value.
39
+ */
40
+ value: PropTypes.oneOfType([
41
+ PropTypes.string,
42
+ PropTypes.number,
43
+ ]).isRequired,
44
+ };
45
+
46
+ export default Option;
@@ -0,0 +1 @@
1
+ export { default as Option } from './Option';
@@ -1 +1 @@
1
- export { default } from './SelectField';
1
+ export { default as SelectField } from './SelectField';
@@ -13,8 +13,10 @@ import {
13
13
  Props,
14
14
  } from 'docz'
15
15
  import Icon from '../../../docs/_components/Icon'
16
- import ScrollView from '../ScrollView'
17
- import { Table } from './Table'
16
+ import {
17
+ ScrollView,
18
+ Table,
19
+ } from '../..'
18
20
 
19
21
  ## Basic Usage
20
22
 
@@ -38,7 +40,7 @@ And use it:
38
40
  name: 'name',
39
41
  },
40
42
  {
41
- format: (row) => row.dateOfBirth.toLocaleDateString('en-GB'),
43
+ format: (date) => date.toLocaleDateString('en-GB'),
42
44
  label: 'Date of birth',
43
45
  name: 'dateOfBirth',
44
46
  },
@@ -97,21 +99,21 @@ The easiest way to make tables responsive is to wrap them with the
97
99
  name: 'id',
98
100
  },
99
101
  {
100
- format: (row) => (
101
- <span style={{ whiteSpace: 'nowrap' }}>{row.name}</span>
102
+ format: (name) => (
103
+ <span style={{ whiteSpace: 'nowrap' }}>{name}</span>
102
104
  ),
103
105
  label: 'Name',
104
106
  name: 'name',
105
107
  },
106
108
  {
107
- format: (row) => (
108
- <span style={{ whiteSpace: 'nowrap' }}>{row.note}</span>
109
+ format: (note) => (
110
+ <span style={{ whiteSpace: 'nowrap' }}>{note}</span>
109
111
  ),
110
112
  label: 'Note',
111
113
  name: 'note',
112
114
  },
113
115
  {
114
- format: (row) => row.dateOfBirth.toLocaleDateString('en-GB'),
116
+ format: (date) => date.toLocaleDateString('en-GB'),
115
117
  label: 'Date of birth',
116
118
  name: 'dateOfBirth',
117
119
  },
@@ -228,7 +230,7 @@ The following is an example of custom sorting function executed on the client.
228
230
  name: 'name',
229
231
  },
230
232
  {
231
- format: (row) => row.dateOfBirth.toISOString(),
233
+ format: (date) => date.toISOString(),
232
234
  isSortable: true,
233
235
  label: 'Date of birth',
234
236
  name: 'dateOfBirth',
@@ -254,6 +256,20 @@ The following is an example of custom sorting function executed on the client.
254
256
  }}
255
257
  </Playground>
256
258
 
259
+ ## Forwarding HTML Attributes
260
+
261
+ In addition to the options below in the [component's API](#api) section, you
262
+ can specify [React synthetic events] or **any HTML attribute you like.** All
263
+ attributes that don't interfere with the API are forwarded to the `<table>` HTML
264
+ element. This enables making the component interactive and helps to improve its
265
+ accessibility.
266
+
267
+ 👉 Refer to the MDN reference for the full list of supported attributes of the
268
+ [table] element.
269
+
257
270
  ## API
258
271
 
259
272
  <Props table of={Table} />
273
+
274
+ [React synthetic events]: https://reactjs.org/docs/events.html
275
+ [table]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table#attributes
@@ -1,110 +1,52 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { withGlobalProps } from '../../provider';
4
- import Button from '../Button';
4
+ import { transferProps } from '../_helpers/transferProps';
5
+ import { TableHeaderCell } from './_components/TableHeaderCell';
6
+ import { TableBodyCell } from './_components/TableBodyCell';
5
7
  import styles from './Table.scss';
6
8
 
7
- export class Table extends React.Component {
8
- constructor(props) {
9
- super(props);
10
-
11
- this.renderHeaderCell = this.renderHeaderCell.bind(this);
12
-
13
- this.sortCellStyle = {
14
- backgroundColor: 'lightgray',
15
- };
16
- }
17
-
18
- renderHeaderCell(column) {
19
- const {
20
- id,
21
- sort,
22
- } = this.props;
23
- const sortDirection = sort && column.name === sort.column ? sort.direction : 'asc';
24
- const isSortingActive = sort && column.name === sort.column;
25
-
26
- return (
27
- <th
28
- className={isSortingActive ? styles.isTableHeadCellSortingActive : styles.tableHeadCell}
29
- key={column.name}
30
- {...(id && { id: `${id}__headerCell__${column.name}` })}
31
- >
32
- {sort && column.isSortable && (
33
- <div className={styles.sortButton}>
34
- <Button
35
- beforeLabel={
36
- sortDirection === 'asc'
37
- ? sort.ascendingIcon
38
- : sort.descendingIcon
39
- }
40
- label={sortDirection}
41
- labelVisibility="none"
42
- onClick={() => sort.onClick(column.name, sortDirection)}
43
- priority="flat"
44
- {...(id && { id: `${id}__headerCell__${column.name}__sortButton` })}
9
+ export const Table = ({
10
+ columns,
11
+ id,
12
+ rows,
13
+ sort,
14
+ ...restProps
15
+ }) => (
16
+ <table
17
+ {...transferProps(restProps)}
18
+ className={styles.table}
19
+ id={id}
20
+ >
21
+ <thead>
22
+ <tr className={styles.tableHeadRow}>
23
+ {columns.map((column) => (
24
+ <TableHeaderCell
25
+ column={column}
26
+ key={column.name}
27
+ sort={sort}
28
+ {...(id && { id: `${id}__headerCell__${column.name}` })}
29
+ />
30
+ ))}
31
+ </tr>
32
+ </thead>
33
+ <tbody>
34
+ {rows.map((row) => (
35
+ <tr key={row.id} className={styles.tableRow}>
36
+ {columns.map((column) => (
37
+ <TableBodyCell
38
+ format={column.format}
39
+ isSortingActive={sort && column.name === sort.column}
40
+ key={`${row.id}-${column.name}`}
41
+ value={row[column.name]}
42
+ {...(id && { id: `${id}__bodyCell__${column.name}__${row.id}` })}
45
43
  />
46
- </div>
47
- )}
48
- {column.label}
49
- </th>
50
- );
51
- }
52
-
53
- renderBodyCell(column, row) {
54
- const {
55
- id,
56
- sort,
57
- } = this.props;
58
- const isSortingActive = sort && column.name === sort.column;
59
-
60
- if (column.format) {
61
- return (
62
- <td
63
- className={isSortingActive ? styles.isTableCellSortingActive : styles.tableCell}
64
- key={`${row.id}-${column.name}`}
65
- {...(id && { id: `${id}__bodyCell__${column.name}__${row.id}` })}
66
- >
67
- {column.format(row)}
68
- </td>
69
- );
70
- }
71
-
72
- return (
73
- <td
74
- className={isSortingActive ? styles.isTableCellSortingActive : styles.tableCell}
75
- key={`${row.id}-${column.name}`}
76
- {...(id && { id: `${id}__bodyCell__${column.name}__${row.id}` })}
77
- >
78
- {row[column.name]}
79
- </td>
80
- );
81
- }
82
-
83
- render() {
84
- const {
85
- columns,
86
- id,
87
- rows,
88
- } = this.props;
89
-
90
- return (
91
- <table id={id} className={styles.table}>
92
- <thead>
93
- <tr className={styles.tableHeadRow}>
94
- {columns.map(this.renderHeaderCell)}
95
- </tr>
96
- </thead>
97
- <tbody>
98
- {rows.map((row) => (
99
- <tr key={row.id} className={styles.tableRow}>
100
- {columns.map((column) => this.renderBodyCell(column, row))}
101
- </tr>
102
44
  ))}
103
- </tbody>
104
- </table>
105
- );
106
- }
107
- }
45
+ </tr>
46
+ ))}
47
+ </tbody>
48
+ </table>
49
+ );
108
50
 
109
51
  Table.defaultProps = {
110
52
  id: undefined,
@@ -123,7 +65,7 @@ Table.propTypes = {
123
65
  name: PropTypes.string.isRequired,
124
66
  })).isRequired,
125
67
  /**
126
- * ID of the root HTML element. It also serves as base fo nested elements:
68
+ * ID of the root HTML element. It also serves as base for nested elements:
127
69
  * * `<ID>__headerCell__<COLUMN_NAME>`
128
70
  * * `<ID>__headerCell__<COLUMN_NAME>__sortButton`
129
71
  * * `<ID>__bodyCell__<COLUMN_NAME>__<ROW_ID>`
@@ -26,27 +26,3 @@
26
26
  background-color: settings.$head-background-color;
27
27
  }
28
28
  }
29
-
30
- .tableCell,
31
- .tableHeadCell,
32
- .isTableCellSortingActive,
33
- .isTableHeadCellSortingActive {
34
- padding: settings.$cell-padding-y settings.$cell-padding-x;
35
- text-align: left;
36
- border-bottom: settings.$border-width solid settings.$border-color;
37
- }
38
-
39
- .tableHeadCell {
40
- font-weight: settings.$head-font-weight;
41
- border-bottom-width: 2px;
42
- }
43
-
44
- .isTableCellSortingActive,
45
- .isTableHeadCellSortingActive {
46
- background-color: settings.$sorted-background-color;
47
- }
48
-
49
- .sortButton {
50
- display: inline-block;
51
- margin-right: settings.$cell-padding-x;
52
- }
@@ -0,0 +1,46 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import styles from '../TableCell.scss';
4
+
5
+ export const TableBodyCell = ({
6
+ format,
7
+ id,
8
+ isSortingActive,
9
+ value,
10
+ }) => (
11
+ <td
12
+ className={isSortingActive ? styles.isTableCellSortingActive : styles.tableCell}
13
+ id={id}
14
+ >
15
+ {format ? format(value) : value}
16
+ </td>
17
+ );
18
+
19
+ TableBodyCell.defaultProps = {
20
+ format: undefined,
21
+ id: undefined,
22
+ isSortingActive: false,
23
+ value: null,
24
+ };
25
+
26
+ TableBodyCell.propTypes = {
27
+ /**
28
+ * Function that can be used to process the column data before displaying them.
29
+ */
30
+ format: PropTypes.func,
31
+ /**
32
+ * ID of the HTML <td> element:
33
+ */
34
+ id: PropTypes.string,
35
+ /**
36
+ * If `true`, cell is gray marked as sorted.
37
+ */
38
+ isSortingActive: PropTypes.bool,
39
+ /**
40
+ * Cell value.
41
+ */
42
+ // eslint-disable-next-line react/forbid-prop-types
43
+ value: PropTypes.any,
44
+ };
45
+
46
+ export default TableBodyCell;
@@ -0,0 +1 @@
1
+ export { default as TableBodyCell } from './TableBodyCell';
@@ -0,0 +1,25 @@
1
+ @use "../settings";
2
+
3
+ .tableCell,
4
+ .tableHeadCell,
5
+ .isTableCellSortingActive,
6
+ .isTableHeadCellSortingActive {
7
+ padding: settings.$cell-padding-y settings.$cell-padding-x;
8
+ text-align: left;
9
+ border-bottom: settings.$border-width solid settings.$border-color;
10
+ }
11
+
12
+ .tableHeadCell {
13
+ font-weight: settings.$head-font-weight;
14
+ border-bottom-width: 2px;
15
+ }
16
+
17
+ .isTableCellSortingActive,
18
+ .isTableHeadCellSortingActive {
19
+ background-color: settings.$sorted-background-color;
20
+ }
21
+
22
+ .sortButton {
23
+ display: inline-block;
24
+ margin-right: settings.$cell-padding-x;
25
+ }