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

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 (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
+ }