@telus-uds/components-community.data-grid 0.1.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.
- package/.eslintrc.cjs +21 -0
- package/CHANGELOG.md +17 -0
- package/__mocks__/styleMock.js +7 -0
- package/babel.config.cjs +4 -0
- package/jest.config.cjs +19 -0
- package/lib/DataGrid.js +368 -0
- package/lib/DataGridBody.js +20 -0
- package/lib/DataGridCell.js +184 -0
- package/lib/DataGridHead.js +20 -0
- package/lib/DataGridRow.js +103 -0
- package/lib/DataGridTable.js +70 -0
- package/lib/dictionary.js +18 -0
- package/lib/index.js +12 -0
- package/lib/utility.js +75 -0
- package/package.json +48 -0
- package/src/DataGrid.jsx +465 -0
- package/src/DataGridBody.jsx +17 -0
- package/src/DataGridCell.jsx +200 -0
- package/src/DataGridHead.jsx +15 -0
- package/src/DataGridRow.jsx +110 -0
- package/src/DataGridTable.jsx +68 -0
- package/src/dictionary.js +18 -0
- package/src/index.js +14 -0
- package/src/utility.jsx +76 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const base = require('../../../../eslintrc.base.cjs')
|
|
3
|
+
|
|
4
|
+
base.rules['import/no-extraneous-dependencies'] = [
|
|
5
|
+
'error',
|
|
6
|
+
{ packageDir: [__dirname, path.join(__dirname, '../..')] }
|
|
7
|
+
]
|
|
8
|
+
base.settings = {
|
|
9
|
+
...base.settings,
|
|
10
|
+
'import/resolver': {
|
|
11
|
+
node: {
|
|
12
|
+
...base.settings?.['import/resolver']?.node,
|
|
13
|
+
moduleDirectory: [
|
|
14
|
+
path.join(__dirname, '../../node_modules'),
|
|
15
|
+
path.join(__dirname, '../../../../node_modules')
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = base
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Change Log - @telus-uds/components-community.data-grid
|
|
2
|
+
|
|
3
|
+
This log was last generated on Thu, 19 Dec 2024 04:54:39 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
<!-- Start content -->
|
|
6
|
+
|
|
7
|
+
## 0.1.0
|
|
8
|
+
|
|
9
|
+
Thu, 19 Dec 2024 04:54:39 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- `DataGrid` - enhancement of DataGrid with sortable columns (sam.obisesan@telus.com)
|
|
14
|
+
- Bump @telus-uds/components-web to v3.2.1
|
|
15
|
+
- Bump @telus-uds/components-base to v2.3.0
|
|
16
|
+
- Bump @telus-uds/system-theme-tokens to v3.2.0
|
|
17
|
+
- Bump @telus-uds/browserslist-config to v1.0.5
|
package/babel.config.cjs
ADDED
package/jest.config.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module.exports = () => ({
|
|
2
|
+
displayName: {
|
|
3
|
+
name: require('./package.json').name.split('@telus-uds/').pop(),
|
|
4
|
+
color: 'magenta'
|
|
5
|
+
},
|
|
6
|
+
testEnvironment: 'jsdom',
|
|
7
|
+
transform: { '.(js|jsx)$': ['babel-jest', { cwd: __dirname }] },
|
|
8
|
+
moduleNameMapper: {
|
|
9
|
+
'.+\\.(otf|png|jpg)$': 'identity-obj-proxy',
|
|
10
|
+
'\\.icon.svg': '<rootDir>/__mocks__/iconMock.jsx',
|
|
11
|
+
'\\.css': '<rootDir>/__mocks__/styleMock.js',
|
|
12
|
+
'^@telus-uds/components-base/server$': '<rootDir>/../../../components-base/lib/server.js'
|
|
13
|
+
},
|
|
14
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
15
|
+
transformIgnorePatterns: [
|
|
16
|
+
'node_modules/(?!(jest-)?react-native|@react-native|@react-native-community|react-native-web|@react-native-picker)'
|
|
17
|
+
],
|
|
18
|
+
collectCoverageFrom: ['src/*.{js,jsx}']
|
|
19
|
+
})
|
package/lib/DataGrid.js
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Typography, Checkbox, useCopy, useThemeTokens, variantProp, IconButton } from '@telus-uds/components-base';
|
|
4
|
+
import { styledComponents } from '@telus-uds/components-web';
|
|
5
|
+
import dictionary from './dictionary';
|
|
6
|
+
import { resetColumnsData, resetRowData, DATA_TYPE, SORT_DIRECTION, isAtLeastOneRowUnselected, toggleAllCheckBoxes, toggleExpandedRow, toggleRowCheckbox, ROW_TYPE, CELL_TYPE } from './utility';
|
|
7
|
+
import DataGridTable from './DataGridTable';
|
|
8
|
+
import DataGridHead from './DataGridHead';
|
|
9
|
+
import DataGridBody from './DataGridBody';
|
|
10
|
+
import DataGridRow from './DataGridRow';
|
|
11
|
+
import DataGridCell from './DataGridCell';
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
+
const {
|
|
14
|
+
styled
|
|
15
|
+
} = styledComponents;
|
|
16
|
+
export const StyledIconContainer = styled.div`
|
|
17
|
+
display: flex;
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
align-items: center;
|
|
20
|
+
width: 60px;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
`;
|
|
23
|
+
const DataGrid = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
24
|
+
let {
|
|
25
|
+
rows = [],
|
|
26
|
+
columns = [],
|
|
27
|
+
groupedRows,
|
|
28
|
+
showCheckbox = false,
|
|
29
|
+
isSortable = false,
|
|
30
|
+
makeScrollBarAlwaysVisible = true,
|
|
31
|
+
tokens,
|
|
32
|
+
variant,
|
|
33
|
+
copy = 'en',
|
|
34
|
+
testID = 'data-grid'
|
|
35
|
+
} = _ref;
|
|
36
|
+
const themeTokens = useThemeTokens('DataGrid', tokens, variant);
|
|
37
|
+
const getCopy = useCopy({
|
|
38
|
+
dictionary,
|
|
39
|
+
copy
|
|
40
|
+
});
|
|
41
|
+
const {
|
|
42
|
+
expandRowIcon,
|
|
43
|
+
hideExpandedRowIcon,
|
|
44
|
+
sortColumnIconDown,
|
|
45
|
+
sortColumnIconUp
|
|
46
|
+
} = themeTokens;
|
|
47
|
+
const [data, setData] = React.useState(groupedRows ? resetRowData([...groupedRows], true) : resetRowData([...rows]));
|
|
48
|
+
const [columnsData, setColumnsData] = React.useState(resetColumnsData(columns));
|
|
49
|
+
const [checkAllState, setCheckAllState] = React.useState(false);
|
|
50
|
+
const shouldCheckHeaderBox = allData => {
|
|
51
|
+
let isARowUnselectedInAllGroups = null;
|
|
52
|
+
if (groupedRows) {
|
|
53
|
+
isARowUnselectedInAllGroups = Object.keys(allData).some(el => {
|
|
54
|
+
return isAtLeastOneRowUnselected(allData[el].data);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
isARowUnselectedInAllGroups = isAtLeastOneRowUnselected(allData);
|
|
58
|
+
}
|
|
59
|
+
return !isARowUnselectedInAllGroups;
|
|
60
|
+
};
|
|
61
|
+
const shouldDisplayIconColumn = (allData, _showCheckbox) => {
|
|
62
|
+
let doesOneRowHaveExpandedContent = null;
|
|
63
|
+
if (groupedRows) {
|
|
64
|
+
doesOneRowHaveExpandedContent = Object.keys(allData).some(el => {
|
|
65
|
+
return allData[el].data.some(eachData => eachData.hasExpandedRow === true);
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
doesOneRowHaveExpandedContent = allData.some(el => el.hasExpandedRow === true);
|
|
69
|
+
}
|
|
70
|
+
return !!(_showCheckbox || doesOneRowHaveExpandedContent);
|
|
71
|
+
};
|
|
72
|
+
const toggleSelectAll = () => {
|
|
73
|
+
let _rows = null;
|
|
74
|
+
if (groupedRows) {
|
|
75
|
+
_rows = {};
|
|
76
|
+
Object.keys(data).forEach(el => {
|
|
77
|
+
_rows[el] = {
|
|
78
|
+
...data[el]
|
|
79
|
+
};
|
|
80
|
+
_rows[el].data = toggleAllCheckBoxes(data[el].data, checkAllState);
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
_rows = toggleAllCheckBoxes(data, checkAllState);
|
|
84
|
+
}
|
|
85
|
+
setData(_rows);
|
|
86
|
+
setCheckAllState(!checkAllState);
|
|
87
|
+
};
|
|
88
|
+
const toggleCheckbox = rowId => {
|
|
89
|
+
let _data = null;
|
|
90
|
+
if (groupedRows) {
|
|
91
|
+
const [group, _] = rowId.split('-');
|
|
92
|
+
const id = parseInt(_, 10);
|
|
93
|
+
_data = {
|
|
94
|
+
...data
|
|
95
|
+
};
|
|
96
|
+
_data[group].data = toggleRowCheckbox(_data[group].data, id);
|
|
97
|
+
} else {
|
|
98
|
+
_data = toggleRowCheckbox(data, rowId);
|
|
99
|
+
}
|
|
100
|
+
setData(_data);
|
|
101
|
+
};
|
|
102
|
+
const toggleRowExpansion = rowId => {
|
|
103
|
+
let _row = null;
|
|
104
|
+
if (groupedRows) {
|
|
105
|
+
const [group, _] = rowId.split('-');
|
|
106
|
+
const id = parseInt(_, 10);
|
|
107
|
+
_row = {
|
|
108
|
+
...data
|
|
109
|
+
};
|
|
110
|
+
_row[group].data = toggleExpandedRow(_row[group].data, id);
|
|
111
|
+
} else {
|
|
112
|
+
_row = toggleExpandedRow(data, rowId);
|
|
113
|
+
}
|
|
114
|
+
setData(_row);
|
|
115
|
+
};
|
|
116
|
+
const HeaderCheckBoxDisplay = showCheckbox && /*#__PURE__*/_jsx(Checkbox, {
|
|
117
|
+
label: getCopy('all'),
|
|
118
|
+
checked: shouldCheckHeaderBox(data),
|
|
119
|
+
onChange: toggleSelectAll
|
|
120
|
+
});
|
|
121
|
+
const buildCheckBoxDisplay = (_showCheckbox, row, rowId) => _showCheckbox && /*#__PURE__*/_jsx(Checkbox, {
|
|
122
|
+
checked: row.isSelected,
|
|
123
|
+
onChange: () => toggleCheckbox(rowId)
|
|
124
|
+
});
|
|
125
|
+
const buildDisplayCaret = (row, rowId) => row.hasExpandedRow && /*#__PURE__*/_jsx(IconButton, {
|
|
126
|
+
onPress: () => toggleRowExpansion(rowId),
|
|
127
|
+
icon: row.isExpandedRowOpen === true ? hideExpandedRowIcon : expandRowIcon,
|
|
128
|
+
accessibilityRole: `button-${rowId}`,
|
|
129
|
+
accessibilityLabel: row.isExpandedRowOpen === true ? getCopy('hideRow') : getCopy('expandRow')
|
|
130
|
+
});
|
|
131
|
+
const buildExpandedRow = (row, rowId) => row.isExpandedRowOpen && /*#__PURE__*/_jsx(DataGridRow, {
|
|
132
|
+
type: ROW_TYPE.EXPANDEDROW,
|
|
133
|
+
tokens: themeTokens,
|
|
134
|
+
rowId: rowId,
|
|
135
|
+
isExpandedRowOpen: row.isExpandedRowOpen,
|
|
136
|
+
children: /*#__PURE__*/_jsx(DataGridCell, {
|
|
137
|
+
type: CELL_TYPE.EXPANDEDROWCELL,
|
|
138
|
+
tokens: themeTokens,
|
|
139
|
+
columnsLength: columns.length,
|
|
140
|
+
showCheckbox: showCheckbox,
|
|
141
|
+
isExpandedRowOpen: row.isExpandedRowOpen,
|
|
142
|
+
children: row.expandedRowChildComponent.component
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
const buildRowContent = (row, rowId, _showCheckbox, CheckBoxDisplay, DisplayCaret, ExpandedRow) => /*#__PURE__*/_jsxs(React.Fragment, {
|
|
146
|
+
children: [/*#__PURE__*/_jsxs(DataGridRow, {
|
|
147
|
+
tokens: themeTokens,
|
|
148
|
+
rowId: rowId,
|
|
149
|
+
isExpandedRowOpen: row.isExpandedRowOpen,
|
|
150
|
+
hasExpandedContent: row.hasExpandedRow,
|
|
151
|
+
onClick: toggleRowExpansion,
|
|
152
|
+
children: [shouldDisplayIconColumn(data, _showCheckbox) && /*#__PURE__*/_jsx(DataGridCell, {
|
|
153
|
+
tokens: themeTokens,
|
|
154
|
+
isExpandedRowOpen: row.isExpandedRowOpen,
|
|
155
|
+
children: /*#__PURE__*/_jsxs(StyledIconContainer, {
|
|
156
|
+
children: [CheckBoxDisplay, DisplayCaret]
|
|
157
|
+
})
|
|
158
|
+
}), columnsData.map(column => /*#__PURE__*/_jsx(DataGridCell, {
|
|
159
|
+
tokens: themeTokens,
|
|
160
|
+
isExpandedRowOpen: row.isExpandedRowOpen,
|
|
161
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
162
|
+
block: true,
|
|
163
|
+
variant: {
|
|
164
|
+
size: 'small'
|
|
165
|
+
},
|
|
166
|
+
tokens: {
|
|
167
|
+
color: themeTokens.cellTextColor
|
|
168
|
+
},
|
|
169
|
+
children: row[column.key]
|
|
170
|
+
})
|
|
171
|
+
}, `${rowId}-${column.key}`))]
|
|
172
|
+
}, rowId), ExpandedRow]
|
|
173
|
+
}, rowId);
|
|
174
|
+
const sortColumn = column => {
|
|
175
|
+
const _col = {
|
|
176
|
+
...column
|
|
177
|
+
};
|
|
178
|
+
if (!groupedRows) {
|
|
179
|
+
const _data = [...data].sort((a, b) => {
|
|
180
|
+
const first = _col.dataType === DATA_TYPE.NUMBER ? parseFloat(a[_col.key]) : a[_col.key].toUpperCase();
|
|
181
|
+
const next = _col.dataType === DATA_TYPE.NUMBER ? parseFloat(b[_col.key]) : b[_col.key].toUpperCase();
|
|
182
|
+
if (_col.sortDirection === SORT_DIRECTION.DESC) {
|
|
183
|
+
if (first < next) return -1;
|
|
184
|
+
return next === first ? 0 : 1;
|
|
185
|
+
}
|
|
186
|
+
if (next < first) return -1;
|
|
187
|
+
return first === next ? 0 : 1;
|
|
188
|
+
});
|
|
189
|
+
_col.sortDirection = _col.sortDirection === SORT_DIRECTION.DESC ? SORT_DIRECTION.ASC : SORT_DIRECTION.DESC;
|
|
190
|
+
_col.currentSort = true;
|
|
191
|
+
const _columns = resetColumnsData(columnsData);
|
|
192
|
+
_columns[columnsData.findIndex(_el => _el.key === column.key)] = _col;
|
|
193
|
+
setColumnsData(_columns);
|
|
194
|
+
setData(_data);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
let HeaderContent = null;
|
|
198
|
+
let BodyContent = null;
|
|
199
|
+
if (groupedRows) {
|
|
200
|
+
BodyContent = Object.keys(data).map(group => {
|
|
201
|
+
const DefaultSubHeading = /*#__PURE__*/_jsx(Typography, {
|
|
202
|
+
variant: {
|
|
203
|
+
size: 'h3'
|
|
204
|
+
},
|
|
205
|
+
children: data[group].name
|
|
206
|
+
});
|
|
207
|
+
const GroupHeaderRow = /*#__PURE__*/_jsx(DataGridRow, {
|
|
208
|
+
type: ROW_TYPE.EXPANDEDROW,
|
|
209
|
+
tokens: themeTokens,
|
|
210
|
+
children: /*#__PURE__*/_jsx(DataGridCell, {
|
|
211
|
+
type: CELL_TYPE.SUBHEADING,
|
|
212
|
+
tokens: themeTokens,
|
|
213
|
+
columnsLength: columnsData.length,
|
|
214
|
+
children: data[group].groupHeaderComponent || DefaultSubHeading
|
|
215
|
+
})
|
|
216
|
+
}, group);
|
|
217
|
+
const DataRow = data[group].data.map(row => {
|
|
218
|
+
const rowId = `${group}-${row.id}`;
|
|
219
|
+
const CheckBoxDisplay = buildCheckBoxDisplay(showCheckbox, row, rowId);
|
|
220
|
+
const DisplayCaret = buildDisplayCaret(row, rowId);
|
|
221
|
+
const ExpandedRow = buildExpandedRow(row, rowId);
|
|
222
|
+
return buildRowContent(row, rowId, showCheckbox, CheckBoxDisplay, DisplayCaret, ExpandedRow);
|
|
223
|
+
});
|
|
224
|
+
return /*#__PURE__*/_jsxs(React.Fragment, {
|
|
225
|
+
children: [GroupHeaderRow, DataRow]
|
|
226
|
+
}, group);
|
|
227
|
+
});
|
|
228
|
+
} else {
|
|
229
|
+
BodyContent = data.map(row => {
|
|
230
|
+
const rowId = row.id;
|
|
231
|
+
const CheckBoxDisplay = buildCheckBoxDisplay(showCheckbox, row, rowId);
|
|
232
|
+
const DisplayCaret = buildDisplayCaret(row, rowId);
|
|
233
|
+
const ExpandedRow = buildExpandedRow(row, rowId);
|
|
234
|
+
return buildRowContent(row, rowId, showCheckbox, CheckBoxDisplay, DisplayCaret, ExpandedRow);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
HeaderContent = /*#__PURE__*/_jsxs(_Fragment, {
|
|
238
|
+
children: [shouldDisplayIconColumn(data, showCheckbox) && /*#__PURE__*/_jsx(DataGridCell, {
|
|
239
|
+
type: CELL_TYPE.HEADING,
|
|
240
|
+
tokens: themeTokens,
|
|
241
|
+
isFirstCol: true,
|
|
242
|
+
children: HeaderCheckBoxDisplay
|
|
243
|
+
}), columnsData.map(column => /*#__PURE__*/_jsxs(DataGridCell, {
|
|
244
|
+
type: CELL_TYPE.HEADING,
|
|
245
|
+
tokens: themeTokens,
|
|
246
|
+
isSortable: isSortable,
|
|
247
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
248
|
+
block: true,
|
|
249
|
+
variant: {
|
|
250
|
+
size: 'h4'
|
|
251
|
+
},
|
|
252
|
+
tokens: {
|
|
253
|
+
color: themeTokens.headerTextColor
|
|
254
|
+
},
|
|
255
|
+
children: column.label
|
|
256
|
+
}), isSortable && column.isSortable && /*#__PURE__*/_jsx(IconButton, {
|
|
257
|
+
variant: {
|
|
258
|
+
size: 'small'
|
|
259
|
+
},
|
|
260
|
+
tokens: {
|
|
261
|
+
iconColor: column.currentSort ? themeTokens.sortColumnIconActiveColor : themeTokens.sortColumnIconDefaultColor
|
|
262
|
+
},
|
|
263
|
+
onPress: () => {
|
|
264
|
+
if (typeof column.fn === 'function') {
|
|
265
|
+
column.fn(column, data, setData, columnsData, setColumnsData);
|
|
266
|
+
} else sortColumn(column);
|
|
267
|
+
},
|
|
268
|
+
icon: column.sortDirection === SORT_DIRECTION.ASC ? sortColumnIconUp : sortColumnIconDown,
|
|
269
|
+
accessibilityRole: "sort-button",
|
|
270
|
+
accessibilityLabel: getCopy('button')
|
|
271
|
+
})]
|
|
272
|
+
}, column.key))]
|
|
273
|
+
});
|
|
274
|
+
return /*#__PURE__*/_jsx(DataGridTable, {
|
|
275
|
+
tokens: themeTokens,
|
|
276
|
+
makeScrollBarAlwaysVisible: makeScrollBarAlwaysVisible,
|
|
277
|
+
ref: ref,
|
|
278
|
+
testID: testID,
|
|
279
|
+
children: /*#__PURE__*/_jsxs(_Fragment, {
|
|
280
|
+
children: [/*#__PURE__*/_jsx(DataGridHead, {
|
|
281
|
+
children: /*#__PURE__*/_jsx(DataGridRow, {
|
|
282
|
+
type: ROW_TYPE.HEADING,
|
|
283
|
+
children: HeaderContent
|
|
284
|
+
})
|
|
285
|
+
}), /*#__PURE__*/_jsx(DataGridBody, {
|
|
286
|
+
children: BodyContent
|
|
287
|
+
})]
|
|
288
|
+
})
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
DataGrid.displayName = 'DataGrid';
|
|
292
|
+
DataGrid.propTypes = {
|
|
293
|
+
/**
|
|
294
|
+
* Use `columns` to pass the data for data-grid column header items.
|
|
295
|
+
*/
|
|
296
|
+
columns: PropTypes.arrayOf(PropTypes.shape({
|
|
297
|
+
key: PropTypes.string.isRequired,
|
|
298
|
+
label: PropTypes.string.isRequired,
|
|
299
|
+
width: PropTypes.string,
|
|
300
|
+
dataType: PropTypes.oneOf(['string', 'number']),
|
|
301
|
+
isSortable: PropTypes.bool,
|
|
302
|
+
// Set this to true to enable sorting for this column
|
|
303
|
+
fn: PropTypes.func
|
|
304
|
+
})).isRequired,
|
|
305
|
+
/**
|
|
306
|
+
* Use `groupedRows` to pass the grouped data for display
|
|
307
|
+
*/
|
|
308
|
+
groupedRows: PropTypes.arrayOf(PropTypes.shape({
|
|
309
|
+
key: PropTypes.string.isRequired,
|
|
310
|
+
name: PropTypes.string.isRequired,
|
|
311
|
+
groupHeaderComponent: PropTypes.node,
|
|
312
|
+
data: PropTypes.arrayOf(PropTypes.shape({
|
|
313
|
+
id: PropTypes.number.isRequired,
|
|
314
|
+
expandedRow: PropTypes.shape({
|
|
315
|
+
rows: PropTypes.arrayOf(PropTypes.shape({
|
|
316
|
+
id: PropTypes.number.isRequired
|
|
317
|
+
})),
|
|
318
|
+
columns: PropTypes.arrayOf(PropTypes.shape({
|
|
319
|
+
key: PropTypes.string.isRequired,
|
|
320
|
+
label: PropTypes.string.isRequired
|
|
321
|
+
}))
|
|
322
|
+
}),
|
|
323
|
+
expandedRowChildComponent: PropTypes.shape({
|
|
324
|
+
component: PropTypes.node,
|
|
325
|
+
displayOnLoad: PropTypes.bool.isRequired
|
|
326
|
+
})
|
|
327
|
+
}))
|
|
328
|
+
})),
|
|
329
|
+
/**
|
|
330
|
+
* Use `rows` to pass ungrouped data for data-grid row cells items.
|
|
331
|
+
*/
|
|
332
|
+
rows: PropTypes.arrayOf(PropTypes.shape({
|
|
333
|
+
id: PropTypes.number.isRequired,
|
|
334
|
+
expandedRowChildComponent: PropTypes.shape({
|
|
335
|
+
component: PropTypes.node,
|
|
336
|
+
displayOnLoad: PropTypes.bool.isRequired
|
|
337
|
+
})
|
|
338
|
+
})),
|
|
339
|
+
/**
|
|
340
|
+
* Set this to true to enable columns to become sortable.
|
|
341
|
+
*/
|
|
342
|
+
isSortable: PropTypes.bool,
|
|
343
|
+
/**
|
|
344
|
+
* Set this to true to make scrollbar always visible when content is larger than the grid
|
|
345
|
+
*/
|
|
346
|
+
makeScrollBarAlwaysVisible: PropTypes.bool,
|
|
347
|
+
/**
|
|
348
|
+
* Set this to true to enable checkboxes in the first column.
|
|
349
|
+
*/
|
|
350
|
+
showCheckbox: PropTypes.bool,
|
|
351
|
+
/**
|
|
352
|
+
* Use tokens prop to override theme tokens
|
|
353
|
+
*/
|
|
354
|
+
tokens: PropTypes.object,
|
|
355
|
+
/**
|
|
356
|
+
* No available variants
|
|
357
|
+
*/
|
|
358
|
+
variant: variantProp.propType,
|
|
359
|
+
/**
|
|
360
|
+
* Use copy for localisations of keys.
|
|
361
|
+
*/
|
|
362
|
+
copy: PropTypes.oneOf(['en', 'fr']),
|
|
363
|
+
/**
|
|
364
|
+
* Use in tests if the datagrid test cases need to find the element with the id.
|
|
365
|
+
*/
|
|
366
|
+
testID: PropTypes.string
|
|
367
|
+
};
|
|
368
|
+
export default DataGrid;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
const DataGridBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
5
|
+
let {
|
|
6
|
+
children
|
|
7
|
+
} = _ref;
|
|
8
|
+
return /*#__PURE__*/_jsx("tbody", {
|
|
9
|
+
ref: ref,
|
|
10
|
+
children: children
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
DataGridBody.displayName = 'DataGridBody';
|
|
14
|
+
DataGridBody.propTypes = {
|
|
15
|
+
/**
|
|
16
|
+
* Accepts any React or HTML node
|
|
17
|
+
*/
|
|
18
|
+
children: PropTypes.node.isRequired
|
|
19
|
+
};
|
|
20
|
+
export default DataGridBody;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { styledComponents } from '@telus-uds/components-web';
|
|
4
|
+
import { CELL_TYPE } from './utility';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
const {
|
|
7
|
+
styled,
|
|
8
|
+
css
|
|
9
|
+
} = styledComponents;
|
|
10
|
+
const StyledHeaderCell = styled.th`
|
|
11
|
+
${props => {
|
|
12
|
+
return css`
|
|
13
|
+
background-color: ${props.headerRowBackgroundColor};
|
|
14
|
+
border-top: solid ${props.headerBorderTopWidth}px ${props.headerBorderTopColor};
|
|
15
|
+
border-bottom: solid ${props.headerBorderBottomWidth}px ${props.headerBorderBottomColor};
|
|
16
|
+
padding: ${props.headerPadding}px;
|
|
17
|
+
text-align: ${props.headerTextAlign};
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
font-size: ${props.headerFontSize}px;
|
|
20
|
+
font-weight: bold;
|
|
21
|
+
line-height: ${props.headerLineHeight * props.headerFontSize}px;
|
|
22
|
+
color: ${props.headerTextColor};
|
|
23
|
+
width: ${props.firstColWidth};
|
|
24
|
+
font-family: ${props.headerFontFamily};
|
|
25
|
+
`;
|
|
26
|
+
}}
|
|
27
|
+
`;
|
|
28
|
+
const StyledHeaderCellDiv = styled.div`
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
`;
|
|
32
|
+
const StyledGroupHeaderCell = styled.td`
|
|
33
|
+
${props => {
|
|
34
|
+
return css`
|
|
35
|
+
background-color: ${props.subHeadingBackgroundColor};
|
|
36
|
+
padding: ${props.cellPadding}px;
|
|
37
|
+
border-top: solid ${props.cellBorderBottomWidth}px ${props.cellBorderBottomColor};
|
|
38
|
+
text-align: ${props.cellTextAlign};
|
|
39
|
+
font-size: ${props.cellFontSize}px;
|
|
40
|
+
font-weight: normal;
|
|
41
|
+
line-height: ${props.cellLineHeight * props.cellFontSize}px;
|
|
42
|
+
color: ${props.cellTextColor};
|
|
43
|
+
font-family: ${props.cellFontFamily};
|
|
44
|
+
`;
|
|
45
|
+
}}
|
|
46
|
+
`;
|
|
47
|
+
const StyledGroupHeaderCellDiv = styled.div`
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: start;
|
|
51
|
+
`;
|
|
52
|
+
const StyledExpandedCell = styled.td`
|
|
53
|
+
${props => {
|
|
54
|
+
return css`
|
|
55
|
+
padding: ${props.cellPadding}px;
|
|
56
|
+
border-bottom: ${props.isExpandedRowOpen ? `solid ${props.cellBorderBottomWidth}px ${props.headerBorderBottomColor};` : `solid ${props.cellBorderBottomWidth}px ${props.cellBorderBottomColor};`}
|
|
57
|
+
text-align: ${props.cellTextAlign};
|
|
58
|
+
font-size: ${props.cellFontSize}px;
|
|
59
|
+
font-weight: normal;
|
|
60
|
+
line-height: ${props.cellLineHeight * props.cellFontSize}px;
|
|
61
|
+
color: ${props.cellTextColor};
|
|
62
|
+
font-family: ${props.cellFontFamily};
|
|
63
|
+
`;
|
|
64
|
+
}}
|
|
65
|
+
`;
|
|
66
|
+
const StyledExpandedCellDiv = styled.div`
|
|
67
|
+
${props => {
|
|
68
|
+
return css`
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: ${props.expandedContentAlignment ? props.expandedContentAlignment : 'start'};
|
|
72
|
+
padding-left: ${props.showCheckbox ? `${props.expandedContentLeftPadding}px` : `${props.expandedContentDefaultLeftPadding}px`};
|
|
73
|
+
`;
|
|
74
|
+
}}
|
|
75
|
+
`;
|
|
76
|
+
export const StyledCell = styled.td`
|
|
77
|
+
${props => {
|
|
78
|
+
if (props.isExpandedRowOpen) {
|
|
79
|
+
return css`
|
|
80
|
+
padding: ${props.cellPadding}px;
|
|
81
|
+
text-align: ${props.cellTextAlign};
|
|
82
|
+
font-size: ${props.cellFontSize}px;
|
|
83
|
+
font-weight: normal;
|
|
84
|
+
line-height: ${props.cellLineHeight * props.cellFontSize}px;
|
|
85
|
+
color: ${props.cellTextColor};
|
|
86
|
+
font-family: ${props.cellFontFamily};
|
|
87
|
+
border-top: solid ${props.headerBorderTopWidth}px ${props.headerBorderTopColor};
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
return css`
|
|
91
|
+
padding: ${props.cellPadding}px;
|
|
92
|
+
border-bottom: ${props.hideRowBottomBorder === 1 ? `none` : `solid ${props.cellBorderBottomWidth}px ${props.cellBorderBottomColor}`};
|
|
93
|
+
text-align: ${props.cellTextAlign};
|
|
94
|
+
font-size: ${props.cellFontSize}px;
|
|
95
|
+
font-weight: normal;
|
|
96
|
+
line-height: ${props.cellLineHeight * props.cellFontSize}px;
|
|
97
|
+
color: ${props.cellTextColor};
|
|
98
|
+
font-family: ${props.cellFontFamily};
|
|
99
|
+
`;
|
|
100
|
+
}}
|
|
101
|
+
`;
|
|
102
|
+
const DataGridCell = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
103
|
+
let {
|
|
104
|
+
children,
|
|
105
|
+
tokens,
|
|
106
|
+
type,
|
|
107
|
+
columnsLength,
|
|
108
|
+
showCheckbox = false,
|
|
109
|
+
isFirstCol = false,
|
|
110
|
+
isExpandedRowOpen = false
|
|
111
|
+
} = _ref;
|
|
112
|
+
if (type === CELL_TYPE.HEADING) {
|
|
113
|
+
return /*#__PURE__*/_jsx(StyledHeaderCell, {
|
|
114
|
+
...tokens,
|
|
115
|
+
firstColWidth: isFirstCol ? tokens.firstColWidth : 'auto',
|
|
116
|
+
ref: ref,
|
|
117
|
+
children: /*#__PURE__*/_jsx(StyledHeaderCellDiv, {
|
|
118
|
+
children: children
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (type === CELL_TYPE.SUBHEADING) {
|
|
123
|
+
return /*#__PURE__*/_jsx(StyledGroupHeaderCell, {
|
|
124
|
+
colSpan: columnsLength + 1,
|
|
125
|
+
...tokens,
|
|
126
|
+
ref: ref,
|
|
127
|
+
children: /*#__PURE__*/_jsx(StyledGroupHeaderCellDiv, {
|
|
128
|
+
...tokens,
|
|
129
|
+
children: children
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (type === CELL_TYPE.EXPANDEDROWCELL) {
|
|
134
|
+
return /*#__PURE__*/_jsx(StyledExpandedCell, {
|
|
135
|
+
colSpan: columnsLength + 1,
|
|
136
|
+
...tokens,
|
|
137
|
+
isExpandedRowOpen: isExpandedRowOpen,
|
|
138
|
+
ref: ref,
|
|
139
|
+
children: /*#__PURE__*/_jsx(StyledExpandedCellDiv, {
|
|
140
|
+
showCheckbox: showCheckbox,
|
|
141
|
+
...tokens,
|
|
142
|
+
children: children
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return /*#__PURE__*/_jsx(StyledCell, {
|
|
147
|
+
...tokens,
|
|
148
|
+
isExpandedRowOpen: isExpandedRowOpen,
|
|
149
|
+
ref: ref,
|
|
150
|
+
children: children
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
DataGridCell.displayName = 'DataGridCell';
|
|
154
|
+
DataGridCell.propTypes = {
|
|
155
|
+
/**
|
|
156
|
+
cell type
|
|
157
|
+
*/
|
|
158
|
+
type: PropTypes.oneOf(['heading', 'subHeading', 'expandedRowCell']),
|
|
159
|
+
/**
|
|
160
|
+
* Accepts any React or HTML node
|
|
161
|
+
*/
|
|
162
|
+
children: PropTypes.node,
|
|
163
|
+
/**
|
|
164
|
+
* Tokens passed to the component
|
|
165
|
+
*/
|
|
166
|
+
tokens: PropTypes.object,
|
|
167
|
+
/**
|
|
168
|
+
* columnsLength passed to the component for certain scenarios in which colSpan is required
|
|
169
|
+
*/
|
|
170
|
+
columnsLength: PropTypes.number,
|
|
171
|
+
/**
|
|
172
|
+
* showCheckbox passed to the component for certain scenarios in which checkbox visibility impacts the display design
|
|
173
|
+
*/
|
|
174
|
+
showCheckbox: PropTypes.bool,
|
|
175
|
+
/**
|
|
176
|
+
* isFirstCol passed to the component to determine if cell is first within the row
|
|
177
|
+
*/
|
|
178
|
+
isFirstCol: PropTypes.bool,
|
|
179
|
+
/**
|
|
180
|
+
* isExpandedRowOpen passed to the component to determine if cell is displaying additional data
|
|
181
|
+
*/
|
|
182
|
+
isExpandedRowOpen: PropTypes.bool
|
|
183
|
+
};
|
|
184
|
+
export default DataGridCell;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
const DataGridHead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
5
|
+
let {
|
|
6
|
+
children
|
|
7
|
+
} = _ref;
|
|
8
|
+
return /*#__PURE__*/_jsx("thead", {
|
|
9
|
+
ref: ref,
|
|
10
|
+
children: children
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
DataGridHead.displayName = 'DataGridHead';
|
|
14
|
+
DataGridHead.propTypes = {
|
|
15
|
+
/**
|
|
16
|
+
* Accepts any React or HTML node
|
|
17
|
+
*/
|
|
18
|
+
children: PropTypes.node
|
|
19
|
+
};
|
|
20
|
+
export default DataGridHead;
|