@punch-in/buffet-modern-core 3.3.11

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 (131) hide show
  1. package/README.md +50 -0
  2. package/babel.config.js +18 -0
  3. package/build/bundle.development.js +850 -0
  4. package/build/bundle.production.js +1 -0
  5. package/build/esm/components/AttributeIcon/Div.js +51 -0
  6. package/build/esm/components/AttributeIcon/index.js +53 -0
  7. package/build/esm/components/Button/index.js +75 -0
  8. package/build/esm/components/Checkbox/index.js +78 -0
  9. package/build/esm/components/Count/Wrapper.js +32 -0
  10. package/build/esm/components/Count/index.js +27 -0
  11. package/build/esm/components/DatePicker/index.js +206 -0
  12. package/build/esm/components/DatePicker/reducer.js +42 -0
  13. package/build/esm/components/Enumeration/index.js +54 -0
  14. package/build/esm/components/Error/index.js +137 -0
  15. package/build/esm/components/Error/reducer.js +23 -0
  16. package/build/esm/components/Flex/index.js +29 -0
  17. package/build/esm/components/HeaderActions/index.js +41 -0
  18. package/build/esm/components/HeaderTitle/index.js +45 -0
  19. package/build/esm/components/Icon/index.js +26 -0
  20. package/build/esm/components/IconLinks/index.js +36 -0
  21. package/build/esm/components/InputNumber/index.js +70 -0
  22. package/build/esm/components/InputText/PrefixIcon.js +32 -0
  23. package/build/esm/components/InputText/index.js +89 -0
  24. package/build/esm/components/Label/index.js +40 -0
  25. package/build/esm/components/List/index.js +50 -0
  26. package/build/esm/components/ListHeader/BaselineAlignement.js +5 -0
  27. package/build/esm/components/ListHeader/index.js +52 -0
  28. package/build/esm/components/ListRow/index.js +30 -0
  29. package/build/esm/components/ListRow/tests/index.tests.js +21 -0
  30. package/build/esm/components/NavTabs/index.js +38 -0
  31. package/build/esm/components/Option/RemoveButton.js +5 -0
  32. package/build/esm/components/Option/index.js +32 -0
  33. package/build/esm/components/Padded/index.js +56 -0
  34. package/build/esm/components/Paging/index.js +57 -0
  35. package/build/esm/components/Picker/PickerButton.js +61 -0
  36. package/build/esm/components/Picker/PickerSection.js +48 -0
  37. package/build/esm/components/Picker/PickerWrapper.js +5 -0
  38. package/build/esm/components/Picker/index.js +50 -0
  39. package/build/esm/components/PrefixIcon/index.js +7 -0
  40. package/build/esm/components/Select/index.js +82 -0
  41. package/build/esm/components/Separator/index.js +44 -0
  42. package/build/esm/components/Table/ActionCollapse.js +40 -0
  43. package/build/esm/components/Table/index.js +140 -0
  44. package/build/esm/components/Table/tests/index.js +130 -0
  45. package/build/esm/components/TableHeader/index.js +88 -0
  46. package/build/esm/components/TableRow/index.js +93 -0
  47. package/build/esm/components/Text/index.js +67 -0
  48. package/build/esm/components/Textarea/index.js +16 -0
  49. package/build/esm/components/TimePicker/index.js +288 -0
  50. package/build/esm/components/Toggle/index.js +72 -0
  51. package/build/esm/components/UnknownInput/index.js +19 -0
  52. package/build/esm/index.js +33 -0
  53. package/build/esm/theme/colors.js +48 -0
  54. package/build/index.js +8 -0
  55. package/package.json +123 -0
  56. package/src/components/AttributeIcon/Div.js +63 -0
  57. package/src/components/AttributeIcon/index.js +72 -0
  58. package/src/components/Button/index.js +95 -0
  59. package/src/components/Checkbox/index.js +86 -0
  60. package/src/components/Checkbox/tests/Checkbox.test.js +49 -0
  61. package/src/components/Count/Wrapper.js +36 -0
  62. package/src/components/Count/index.js +30 -0
  63. package/src/components/DatePicker/index.js +213 -0
  64. package/src/components/DatePicker/reducer.js +27 -0
  65. package/src/components/DatePicker/tests/__snapshots__/index.test.js.snap +301 -0
  66. package/src/components/DatePicker/tests/index.test.js +111 -0
  67. package/src/components/Enumeration/index.js +71 -0
  68. package/src/components/Enumeration/tests/index.test.js +41 -0
  69. package/src/components/Error/index.js +118 -0
  70. package/src/components/Error/reducer.js +14 -0
  71. package/src/components/Flex/index.js +25 -0
  72. package/src/components/Flex/tests/__snapshots__/index.test.js.snap +28 -0
  73. package/src/components/Flex/tests/index.test.js +11 -0
  74. package/src/components/HeaderActions/index.js +52 -0
  75. package/src/components/HeaderActions/tests/index.test.js +15 -0
  76. package/src/components/HeaderTitle/index.js +59 -0
  77. package/src/components/HeaderTitle/tests/index.test.js +15 -0
  78. package/src/components/Icon/index.js +50 -0
  79. package/src/components/Icon/tests/Icon.test.js +33 -0
  80. package/src/components/IconLinks/index.js +39 -0
  81. package/src/components/IconLinks/tests/index.test.js +27 -0
  82. package/src/components/InputNumber/index.js +74 -0
  83. package/src/components/InputText/PrefixIcon.js +38 -0
  84. package/src/components/InputText/index.js +88 -0
  85. package/src/components/Label/index.js +53 -0
  86. package/src/components/Label/tests/Label.test.js +38 -0
  87. package/src/components/List/index.js +56 -0
  88. package/src/components/List/tests/index.test.js +19 -0
  89. package/src/components/ListHeader/BaselineAlignement.js +7 -0
  90. package/src/components/ListHeader/index.js +58 -0
  91. package/src/components/ListHeader/tests/index.test.js +11 -0
  92. package/src/components/ListRow/index.js +34 -0
  93. package/src/components/ListRow/tests/index.tests.js +32 -0
  94. package/src/components/NavTabs/index.js +51 -0
  95. package/src/components/Option/RemoveButton.js +18 -0
  96. package/src/components/Option/index.js +32 -0
  97. package/src/components/Padded/index.js +47 -0
  98. package/src/components/Padded/tests/__snapshots__/index.test.js.snap +8 -0
  99. package/src/components/Padded/tests/index.test.js +11 -0
  100. package/src/components/Paging/index.js +66 -0
  101. package/src/components/Picker/PickerButton.js +84 -0
  102. package/src/components/Picker/PickerSection.js +41 -0
  103. package/src/components/Picker/PickerWrapper.js +7 -0
  104. package/src/components/Picker/index.js +44 -0
  105. package/src/components/Picker/tests/__snapshots__/pickerButton.test.js.snap +54 -0
  106. package/src/components/Picker/tests/__snapshots__/pickerSection.test.js.snap +20 -0
  107. package/src/components/Picker/tests/pickerButton.test.js +11 -0
  108. package/src/components/Picker/tests/pickerSection.test.js +11 -0
  109. package/src/components/PrefixIcon/index.js +11 -0
  110. package/src/components/Select/index.js +110 -0
  111. package/src/components/Select/tests/index.test.js +85 -0
  112. package/src/components/Separator/index.js +49 -0
  113. package/src/components/Table/ActionCollapse.js +53 -0
  114. package/src/components/Table/index.js +172 -0
  115. package/src/components/Table/tests/index.js +146 -0
  116. package/src/components/TableHeader/index.js +103 -0
  117. package/src/components/TableHeader/tests/index.test.js +85 -0
  118. package/src/components/TableRow/index.js +116 -0
  119. package/src/components/TableRow/tests/index.test.js +89 -0
  120. package/src/components/Text/index.js +62 -0
  121. package/src/components/Text/tests/__snapshots__/index.test.js.snap +19 -0
  122. package/src/components/Text/tests/index.test.js +11 -0
  123. package/src/components/Textarea/index.js +19 -0
  124. package/src/components/Textarea/tests/index.test.js +23 -0
  125. package/src/components/TimePicker/index.js +328 -0
  126. package/src/components/TimePicker/tests/index.test.js +95 -0
  127. package/src/components/Toggle/index.js +83 -0
  128. package/src/components/Toggle/tests/index.test.js +40 -0
  129. package/src/components/UnknownInput/index.js +20 -0
  130. package/src/index.js +33 -0
  131. package/src/theme/colors.js +48 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ *
3
+ * Table
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import PropTypes from 'prop-types';
9
+
10
+ import {
11
+ LoadingIndicator,
12
+ Table as StyledTable,
13
+ TableRowEmpty,
14
+ } from '@punch-in/buffet-modern';
15
+ import TableHeader from '../TableHeader';
16
+ import TableRow from '../TableRow';
17
+ import ActionCollapse from './ActionCollapse';
18
+
19
+ function Table({
20
+ bulkActionProps,
21
+ className,
22
+ customRow,
23
+ headers,
24
+ isLoading,
25
+ onChangeSort,
26
+ onClickRow,
27
+ onSelect,
28
+ onSelectAll,
29
+ rows,
30
+ rowLinks,
31
+ showActionCollapse,
32
+ sortBy,
33
+ sortOrder,
34
+ tableEmptyText,
35
+ withBulkAction,
36
+ }) {
37
+ let colSpan = withBulkAction ? headers.length + 1 : headers.length;
38
+
39
+ if (rowLinks.length > 0) {
40
+ colSpan += 1;
41
+ }
42
+
43
+ const areAllEntriesSelected =
44
+ rows.length > 0 && rows.some(row => row._isChecked === true);
45
+ const shouldDisplayEmptyRow = rows.length === 0 && !isLoading;
46
+
47
+ return (
48
+ <StyledTable className={className}>
49
+ <table className="">
50
+ <TableHeader
51
+ headers={headers}
52
+ onChangeSort={onChangeSort}
53
+ onSelectAll={onSelectAll}
54
+ rows={rows}
55
+ shouldAddCell={rowLinks.length > 0}
56
+ sortBy={sortBy}
57
+ sortOrder={sortOrder}
58
+ withBulkAction={withBulkAction}
59
+ />
60
+ <tbody>
61
+ {withBulkAction && areAllEntriesSelected && showActionCollapse && (
62
+ <ActionCollapse
63
+ colSpan={colSpan}
64
+ numberOfSelectedEntries={
65
+ rows.filter(row => row._isChecked === true).length
66
+ }
67
+ {...bulkActionProps}
68
+ />
69
+ )}
70
+ {isLoading && (
71
+ <TableRowEmpty isLoading>
72
+ <td colSpan={colSpan}>
73
+ <LoadingIndicator />
74
+ </td>
75
+ </TableRowEmpty>
76
+ )}
77
+ {shouldDisplayEmptyRow && (
78
+ <TableRowEmpty>
79
+ <td colSpan={colSpan}>{tableEmptyText}</td>
80
+ </TableRowEmpty>
81
+ )}
82
+ {!shouldDisplayEmptyRow &&
83
+ rows.map((row, index) => {
84
+ const key = row.id || `key${index}`;
85
+
86
+ if (customRow) {
87
+ const Row = customRow;
88
+
89
+ return (
90
+ <React.Fragment key={JSON.stringify(row)}>
91
+ <Row row={row} headers={headers} onSelect={onSelect} />
92
+ </React.Fragment>
93
+ );
94
+ }
95
+
96
+ return (
97
+ <TableRow
98
+ key={key}
99
+ headers={headers}
100
+ onClick={onClickRow}
101
+ onSelect={() => {
102
+ onSelect(row, index);
103
+ }}
104
+ row={row}
105
+ rowLinks={rowLinks}
106
+ withBulkAction={withBulkAction}
107
+ />
108
+ );
109
+ })}
110
+ </tbody>
111
+ </table>
112
+ </StyledTable>
113
+ );
114
+ }
115
+
116
+ Table.defaultProps = {
117
+ bulkActionProps: {
118
+ icon: 'trash',
119
+ onConfirm: () => {},
120
+ translatedNumberOfEntry: 'entry',
121
+ translatedNumberOfEntries: 'entries',
122
+ translatedAction: 'Delete all',
123
+ },
124
+ className: null,
125
+ customRow: null,
126
+ headers: [],
127
+ isLoading: false,
128
+ onChangeSort: () => {},
129
+ onClickRow: () => {},
130
+ onSelect: () => {},
131
+ onSelectAll: () => {},
132
+ rows: [],
133
+ rowLinks: [],
134
+ showActionCollapse: false,
135
+ sortBy: null,
136
+ sortOrder: 'asc',
137
+ tableEmptyText: 'There is no data',
138
+ withBulkAction: false,
139
+ };
140
+
141
+ Table.propTypes = {
142
+ bulkActionProps: PropTypes.shape({
143
+ icon: PropTypes.string,
144
+ onConfirm: PropTypes.func,
145
+ translatedAction: PropTypes.string,
146
+ translatedNumberOfEntries: PropTypes.string,
147
+ translatedNumberOfEntry: PropTypes.string,
148
+ }),
149
+ className: PropTypes.string,
150
+ customRow: PropTypes.func,
151
+ headers: PropTypes.arrayOf(
152
+ PropTypes.shape({
153
+ isSortEnabled: PropTypes.bool,
154
+ name: PropTypes.string,
155
+ value: PropTypes.string,
156
+ })
157
+ ),
158
+ isLoading: PropTypes.bool,
159
+ onChangeSort: PropTypes.func,
160
+ onClickRow: PropTypes.func,
161
+ onSelect: PropTypes.func,
162
+ onSelectAll: PropTypes.func,
163
+ rowLinks: PropTypes.instanceOf(Array),
164
+ rows: PropTypes.instanceOf(Array),
165
+ showActionCollapse: PropTypes.bool,
166
+ sortBy: PropTypes.string,
167
+ sortOrder: PropTypes.string,
168
+ tableEmptyText: PropTypes.string,
169
+ withBulkAction: PropTypes.bool,
170
+ };
171
+
172
+ export default Table;
@@ -0,0 +1,146 @@
1
+ import React from 'react';
2
+ import { mount } from 'enzyme';
3
+
4
+ import { TableRowEmpty } from '@punch-in/buffet-modern';
5
+ import TableRow from '../../TableRow';
6
+ import Table from '../index';
7
+ import ActionCollapse from '../ActionCollapse';
8
+
9
+ describe('<Table />', () => {
10
+ // eslint-disable-next-line jest/expect-expect
11
+ it('Should not crash', () => {
12
+ mount(<Table />);
13
+ });
14
+
15
+ it('Should display the Empty row if there is no data', () => {
16
+ const wrapper = mount(<Table />);
17
+
18
+ expect(wrapper.find(TableRow)).toHaveLength(0);
19
+ expect(wrapper.find(TableRowEmpty)).toHaveLength(1);
20
+ });
21
+
22
+ it('Should display a custom component if given', () => {
23
+ const Custom = () => (
24
+ <tr>
25
+ <td>Test</td>
26
+ </tr>
27
+ );
28
+ const headers = [
29
+ {
30
+ value: 'test',
31
+ },
32
+ ];
33
+ const rows = [
34
+ {
35
+ test: 'test1',
36
+ other: 'other',
37
+ },
38
+ ];
39
+ const wrapper = mount(
40
+ <Table customRow={Custom} rows={rows} headers={headers} />
41
+ );
42
+
43
+ expect(wrapper.find(TableRow)).toHaveLength(0);
44
+ expect(wrapper.find(TableRowEmpty)).toHaveLength(0);
45
+ expect(wrapper.find(Custom)).toHaveLength(1);
46
+ });
47
+
48
+ it('Should display the ActionCollapse correctly without the rowLinks', () => {
49
+ const headers = [
50
+ {
51
+ value: 'test',
52
+ },
53
+ ];
54
+ const rows = [
55
+ {
56
+ test: 'test1',
57
+ other: 'other',
58
+ _isChecked: true,
59
+ },
60
+ ];
61
+ const wrapper = mount(
62
+ <Table rows={rows} headers={headers} withBulkAction />
63
+ );
64
+ const collapse = wrapper.find(ActionCollapse);
65
+
66
+ expect(collapse).toHaveLength(1);
67
+ expect(collapse.prop('colSpan')).toBe(2);
68
+ });
69
+
70
+ it('Should display the ActionCollapse correctly with the bulkAction', () => {
71
+ const headers = [
72
+ {
73
+ value: 'test',
74
+ },
75
+ ];
76
+ const rows = [
77
+ {
78
+ test: 'test1',
79
+ other: 'other',
80
+ _isChecked: true,
81
+ },
82
+ ];
83
+ const rowLinks = [{ icon: 'trash', onClick: jest.fn() }];
84
+ const wrapper = mount(
85
+ <Table rows={rows} headers={headers} rowLinks={rowLinks} withBulkAction />
86
+ );
87
+ const collapse = wrapper.find(ActionCollapse);
88
+ expect(collapse).toHaveLength(1);
89
+ expect(collapse.prop('colSpan')).toBe(3);
90
+ });
91
+
92
+ it('Should display the ActionCollapse if one of the row is not checked', () => {
93
+ const headers = [
94
+ {
95
+ value: 'test',
96
+ },
97
+ ];
98
+ const rows = [
99
+ {
100
+ test: 'test1',
101
+ other: 'other',
102
+ _isChecked: true,
103
+ },
104
+ {
105
+ test: 'test2',
106
+ other: 'other1',
107
+ _isChecked: false,
108
+ },
109
+ ];
110
+ const rowLinks = [{ icon: 'trash', onClick: jest.fn() }];
111
+ const wrapper = mount(
112
+ <Table rows={rows} headers={headers} rowLinks={rowLinks} withBulkAction />
113
+ );
114
+ const collapse = wrapper.find(ActionCollapse);
115
+
116
+ expect(collapse).toHaveLength(1);
117
+ expect(collapse.prop('numberOfSelectedEntries')).toBe(1);
118
+ });
119
+
120
+ it('Should not display the ActionCollapse if the withBulkAction is false', () => {
121
+ const headers = [
122
+ {
123
+ value: 'test',
124
+ },
125
+ ];
126
+ const rows = [
127
+ {
128
+ test: 'test1',
129
+ other: 'other',
130
+ _isChecked: true,
131
+ },
132
+ {
133
+ test: 'test2',
134
+ other: 'other1',
135
+ _isChecked: true,
136
+ },
137
+ ];
138
+ const rowLinks = [{ icon: 'trash', onClick: jest.fn() }];
139
+ const wrapper = mount(
140
+ <Table rows={rows} headers={headers} rowLinks={rowLinks} />
141
+ );
142
+ const collapse = wrapper.find(ActionCollapse);
143
+
144
+ expect(collapse).toHaveLength(0);
145
+ });
146
+ });
@@ -0,0 +1,103 @@
1
+ /**
2
+ *
3
+ * TableHeader
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { get } from 'lodash';
10
+ import { Checkbox } from '@punch-in/buffet-modern';
11
+ import Icon from '../Icon';
12
+
13
+ /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
14
+ /* eslint-disable jsx-a11y/control-has-associated-label */
15
+ function TableHeader({
16
+ headers,
17
+ onChangeSort,
18
+ onSelectAll,
19
+ rows,
20
+ shouldAddCell,
21
+ sortBy,
22
+ sortOrder,
23
+ withBulkAction,
24
+ }) {
25
+ const checked = rows.length > 0 && rows.every(row => row._isChecked === true);
26
+ const shouldDisplayNotChecked =
27
+ rows.some(row => row._isChecked === true) && !checked;
28
+
29
+ return (
30
+ <thead>
31
+ <tr>
32
+ {withBulkAction && (
33
+ <th className="checkCell">
34
+ <Checkbox
35
+ onChange={onSelectAll}
36
+ checked={checked}
37
+ someChecked={shouldDisplayNotChecked}
38
+ />
39
+ </th>
40
+ )}
41
+ {headers.map(header => {
42
+ const { isSortEnabled, name, value } = header;
43
+ const shouldDisplaySort = isSortEnabled && sortBy === value;
44
+ const firstElementThatCanBeSorted = get(
45
+ headers.filter(h => h.isSortEnabled),
46
+ [0, 'value'],
47
+ null
48
+ );
49
+
50
+ return (
51
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
52
+ <th
53
+ key={value}
54
+ onClick={() => {
55
+ onChangeSort({
56
+ sortBy: value,
57
+ firstElementThatCanBeSorted,
58
+ isSortEnabled,
59
+ });
60
+ }}
61
+ >
62
+ <p className={isSortEnabled ? 'clickable' : ''}>
63
+ {name}
64
+ {shouldDisplaySort && <Icon icon={sortOrder || 'asc'} />}
65
+ </p>
66
+ </th>
67
+ );
68
+ })}
69
+ {shouldAddCell && <th />}
70
+ </tr>
71
+ </thead>
72
+ );
73
+ }
74
+
75
+ TableHeader.defaultProps = {
76
+ headers: [],
77
+ onChangeSort: () => {},
78
+ onSelectAll: () => {},
79
+ rows: [],
80
+ shouldAddCell: false,
81
+ sortBy: null,
82
+ sortOrder: 'asc',
83
+ withBulkAction: false,
84
+ };
85
+
86
+ TableHeader.propTypes = {
87
+ headers: PropTypes.arrayOf(
88
+ PropTypes.shape({
89
+ isSortEnabled: PropTypes.bool,
90
+ name: PropTypes.string,
91
+ value: PropTypes.string,
92
+ })
93
+ ),
94
+ onChangeSort: PropTypes.func,
95
+ onSelectAll: PropTypes.func,
96
+ rows: PropTypes.instanceOf(Array),
97
+ shouldAddCell: PropTypes.bool,
98
+ sortBy: PropTypes.string,
99
+ sortOrder: PropTypes.string,
100
+ withBulkAction: PropTypes.bool,
101
+ };
102
+
103
+ export default TableHeader;
@@ -0,0 +1,85 @@
1
+ import React from 'react';
2
+ import { mount } from 'enzyme';
3
+ import { Checkbox } from '@punch-in/buffet-modern';
4
+
5
+ import TableHeader from '../index';
6
+
7
+ describe('<TableHeader />', () => {
8
+ describe('Checkbox behaviour', () => {
9
+ it('Should display the check sign if all rows are selected (someChecked to false and checked to true)', () => {
10
+ const props = {
11
+ rows: [{ _isChecked: true }, { _isChecked: true }],
12
+ withBulkAction: true,
13
+ };
14
+
15
+ const renderedComponent = mount(
16
+ <table>
17
+ <TableHeader {...props} />
18
+ </table>
19
+ );
20
+ const checkbox = renderedComponent.find(Checkbox);
21
+ const { checked, someChecked } = checkbox.props();
22
+
23
+ expect(checkbox).not.toHaveLength(0);
24
+ expect(checked).toBeTruthy();
25
+ expect(someChecked).toBeFalsy();
26
+ });
27
+
28
+ it('Should display the uncheck sign if not all the rows are selected (someChecked to true and checked to false)', () => {
29
+ const props = {
30
+ withBulkAction: true,
31
+ rows: [{ _isChecked: true }, { _isChecked: false }],
32
+ };
33
+
34
+ const renderedComponent = mount(
35
+ <table>
36
+ <TableHeader {...props} />
37
+ </table>
38
+ );
39
+ const checkbox = renderedComponent.find(Checkbox);
40
+ const { checked, someChecked } = checkbox.props();
41
+
42
+ expect(checkbox).not.toHaveLength(0);
43
+ expect(checked).toBeFalsy();
44
+ expect(someChecked).toBeTruthy();
45
+ });
46
+
47
+ it('Should display nothing if none of the rows are selected (all props to false)', () => {
48
+ const props = {
49
+ withBulkAction: true,
50
+ rows: [{ _isChecked: false }, { _isChecked: false }],
51
+ };
52
+
53
+ const renderedComponent = mount(
54
+ <table>
55
+ <TableHeader {...props} />
56
+ </table>
57
+ );
58
+ const checkbox = renderedComponent.find(Checkbox);
59
+ const { checked, someChecked } = checkbox.props();
60
+
61
+ expect(checkbox).not.toHaveLength(0);
62
+ expect(checked).toBeFalsy();
63
+ expect(someChecked).toBeFalsy();
64
+ });
65
+
66
+ it('Should display nothing if there is no rows', () => {
67
+ const props = {
68
+ withBulkAction: true,
69
+ rows: [],
70
+ };
71
+
72
+ const renderedComponent = mount(
73
+ <table>
74
+ <TableHeader {...props} />
75
+ </table>
76
+ );
77
+ const checkbox = renderedComponent.find(Checkbox);
78
+ const { checked, someChecked } = checkbox.props();
79
+
80
+ expect(checkbox).not.toHaveLength(0);
81
+ expect(checked).toBeFalsy();
82
+ expect(someChecked).toBeFalsy();
83
+ });
84
+ });
85
+ });
@@ -0,0 +1,116 @@
1
+ /**
2
+ *
3
+ * TableRow
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { isFunction, isObject } from 'lodash';
10
+ import { Checkbox, Links as StyledLinks } from '@punch-in/buffet-modern';
11
+ import Icon from '../Icon';
12
+
13
+ function TableRow({
14
+ headers,
15
+ onClick,
16
+ onSelect,
17
+ row,
18
+ rowLinks,
19
+ withBulkAction,
20
+ }) {
21
+ // const displayedCells = headers.map(header => ({ key: header.value, );
22
+
23
+ return (
24
+ <tr
25
+ onClick={e => {
26
+ e.preventDefault();
27
+ e.stopPropagation();
28
+ onClick(e, row);
29
+ }}
30
+ >
31
+ {withBulkAction && (
32
+ <td>
33
+ <Checkbox
34
+ onClick={e => {
35
+ e.stopPropagation();
36
+ }}
37
+ onChange={onSelect}
38
+ checked={row._isChecked}
39
+ />
40
+ </td>
41
+ )}
42
+ {headers.map(({ value: cellName, cellFormatter, cellAdapter }) => {
43
+ let displayedValue = !isObject(row[cellName]) ? row[cellName] : '-';
44
+
45
+ if (isFunction(cellFormatter)) {
46
+ displayedValue = cellFormatter(row[cellName], row);
47
+ }
48
+
49
+ let displayedContent = <p>{displayedValue || '-'}</p>;
50
+
51
+ if (isFunction(cellAdapter)) {
52
+ displayedContent = cellAdapter(row);
53
+ }
54
+
55
+ return (
56
+ <td key={cellName} className={`${cellName}-cell`}>
57
+ {displayedContent}
58
+ </td>
59
+ );
60
+ })}
61
+ {rowLinks.length > 0 && (
62
+ <td>
63
+ <div style={{ width: 'fit-content', float: 'right' }}>
64
+ <StyledLinks>
65
+ {rowLinks.map((icon, index) => (
66
+ <button
67
+ // eslint-disable-next-line react/no-array-index-key
68
+ key={index + icon}
69
+ onClick={e => {
70
+ e.preventDefault();
71
+ e.stopPropagation();
72
+ icon.onClick(row);
73
+ }}
74
+ type="button"
75
+ >
76
+ <Icon className="link-icon" icon={icon.icon} />
77
+ </button>
78
+ ))}
79
+ </StyledLinks>
80
+ </div>
81
+ </td>
82
+ )}
83
+ </tr>
84
+ );
85
+ }
86
+
87
+ TableRow.defaultProps = {
88
+ headers: [],
89
+ onClick: () => {},
90
+ onSelect: () => {},
91
+ row: {},
92
+ rowLinks: [],
93
+ withBulkAction: false,
94
+ };
95
+
96
+ TableRow.propTypes = {
97
+ headers: PropTypes.arrayOf(
98
+ PropTypes.shape({
99
+ isSortEnabled: PropTypes.bool,
100
+ name: PropTypes.string,
101
+ value: PropTypes.string,
102
+ })
103
+ ),
104
+ onClick: PropTypes.func,
105
+ onSelect: PropTypes.func,
106
+ // eslint-disable-next-line react/forbid-prop-types
107
+ row: PropTypes.object,
108
+ rowLinks: PropTypes.arrayOf(
109
+ PropTypes.shape({
110
+ icon: PropTypes.node,
111
+ })
112
+ ),
113
+ withBulkAction: PropTypes.bool,
114
+ };
115
+
116
+ export default TableRow;
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import { mount } from 'enzyme';
3
+ import { Checkbox, Links as StyledLinks } from '@punch-in/buffet-modern';
4
+
5
+ import TableRow from '../index';
6
+
7
+ describe('<TableRow />', () => {
8
+ // eslint-disable-next-line jest/expect-expect
9
+ it('Should not crash', () => {
10
+ mount(
11
+ <table>
12
+ <tbody>
13
+ <TableRow />
14
+ </tbody>
15
+ </table>
16
+ );
17
+ });
18
+
19
+ it('Should the display the checkbox if the withBulkAction prop is true', () => {
20
+ const wrapper = mount(
21
+ <table>
22
+ <tbody>
23
+ <TableRow withBulkAction />
24
+ </tbody>
25
+ </table>
26
+ );
27
+
28
+ expect(wrapper.find(Checkbox)).toHaveLength(1);
29
+ });
30
+
31
+ it('Should display the cells according to the given headers', () => {
32
+ const headers = [
33
+ {
34
+ value: 'test',
35
+ },
36
+ ];
37
+ const row = {
38
+ test: 'test1',
39
+ other: 'other',
40
+ };
41
+
42
+ const wrapper = mount(
43
+ <table>
44
+ <tbody>
45
+ <TableRow headers={headers} row={row} />
46
+ </tbody>
47
+ </table>
48
+ );
49
+
50
+ expect(wrapper.find('td')).toHaveLength(1);
51
+ });
52
+
53
+ it('should display the links', () => {
54
+ const headers = [
55
+ {
56
+ value: 'test',
57
+ },
58
+ ];
59
+ const row = {
60
+ test: 'test1',
61
+ other: 'other',
62
+ };
63
+ const rowLinks = [
64
+ {
65
+ icon: 'trash',
66
+ onClick: jest.fn(),
67
+ },
68
+ ];
69
+
70
+ const wrapper = mount(
71
+ <table>
72
+ <tbody>
73
+ <TableRow headers={headers} row={row} rowLinks={rowLinks} />
74
+ </tbody>
75
+ </table>
76
+ );
77
+
78
+ expect(wrapper.find('td')).toHaveLength(2);
79
+ expect(wrapper.find(StyledLinks)).toHaveLength(1);
80
+
81
+ const button = wrapper.find('button').at(0);
82
+
83
+ expect(button).toHaveLength(1);
84
+
85
+ button.simulate('click');
86
+
87
+ expect(rowLinks[0].onClick).toHaveBeenCalledWith(row);
88
+ });
89
+ });