@propellerads/table 4.3.2 → 4.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propellerads/table",
3
- "version": "4.3.2",
3
+ "version": "4.5.1",
4
4
  "repository": "https://github.com/propellerads/ui-components",
5
5
  "author": "i.pasyuk@propellerads.net",
6
6
  "license": "MIT",
@@ -41,5 +41,5 @@
41
41
  "@types/react-table": "^7.7.12",
42
42
  "react-table": "^7.8.0"
43
43
  },
44
- "gitHead": "258e659f14a8f803795b18b0f2771c04e0a7d2e6"
44
+ "gitHead": "f5580dc4afc1f8c4d92868e854dd3d659d64021b"
45
45
  }
package/src/index.tsx CHANGED
@@ -1,20 +1,18 @@
1
1
  import React, {
2
- FunctionComponent,
3
- useEffect,
4
- useMemo,
5
- useRef,
2
+ FunctionComponent, useEffect, useMemo, useRef,
6
3
  } from 'react';
7
4
  import {
8
5
  useSortBy,
9
6
  useTable,
10
7
  useRowSelect,
11
8
  usePagination,
9
+ useExpanded,
12
10
  useFlexLayout,
13
11
  Column,
14
12
  } from 'react-table';
15
13
 
16
14
  import {
17
- ArrowDownFull, ArrowUp, COLOR, SIZE,
15
+ ArrowDown, ArrowUp, COLOR, SIZE,
18
16
  } from '@propellerads/icon';
19
17
  import Checkbox from '@propellerads/input-checkbox';
20
18
 
@@ -74,6 +72,7 @@ export const defaultProps = {
74
72
  parentElementId: 'parent-element',
75
73
  tableContentId: '',
76
74
  showLoadingState: false,
75
+ initialState: {},
77
76
  LoadingCellComponent: EmptyStateCell,
78
77
  getRowPreProps: () => ({}),
79
78
  noDataMessage: '',
@@ -97,10 +96,7 @@ function getHeadContent(column: ColumnWithSort) {
97
96
  return (
98
97
  <HeadCell>
99
98
  {column.render('Header')}
100
- <ArrowDownFull
101
- size={SIZE.SMALL}
102
- color={COLOR.GRAY_DARK}
103
- />
99
+ <ArrowDown size={SIZE.SMALL} color={COLOR.GRAY_DARK} />
104
100
  </HeadCell>
105
101
  );
106
102
  }
@@ -109,10 +105,7 @@ function getHeadContent(column: ColumnWithSort) {
109
105
  return (
110
106
  <HeadCell>
111
107
  {column.render('Header')}
112
- <ArrowUp
113
- size={SIZE.SMALL}
114
- color={COLOR.GRAY_DARK}
115
- />
108
+ <ArrowUp size={SIZE.SMALL} color={COLOR.GRAY_DARK} />
116
109
  </HeadCell>
117
110
  );
118
111
  }
@@ -149,21 +142,30 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
149
142
  getFooterGroupProps,
150
143
  showLoadingState,
151
144
  noDataMessage,
145
+ rowSubComponent,
152
146
  } = props;
153
147
 
154
148
  const memoColumns = useMemo(() => columns, [columns]);
155
149
 
156
150
  const {loadingColumns, loadingData} = useLoadingState(
157
- showLoadingState, isLoading, controlledPagination?.pageSize ?? DEFAULT_PAGE_SIZE, memoColumns, LoadingCellComponent,
151
+ showLoadingState,
152
+ isLoading,
153
+ controlledPagination?.pageSize ?? DEFAULT_PAGE_SIZE,
154
+ memoColumns,
155
+ LoadingCellComponent,
158
156
  );
159
157
 
160
158
  const showLoading = showLoadingState && isLoading;
161
159
  const hasSelectedRowsAbility = onSelectRowsChange && isFunction(onSelectRowsChange);
162
160
  const hasManualSortBy = onSortedChange && isFunction(onSortedChange);
163
- const hasControlledPagination = fetchData && controlledPagination && Object.keys(controlledPagination).length > 0;
161
+ const hasControlledPagination = fetchData
162
+ && controlledPagination
163
+ && Object.keys(controlledPagination).length > 0;
164
164
 
165
165
  const options: TableOptionsProps = {
166
- columns: showLoading ? (loadingColumns as Column<DefaultObject>[]) : memoColumns,
166
+ columns: showLoading
167
+ ? (loadingColumns as Column<DefaultObject>[])
168
+ : memoColumns,
167
169
  data: showLoading ? loadingData : data,
168
170
  initialState,
169
171
  disableSortRemove,
@@ -177,7 +179,9 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
177
179
 
178
180
  if (hasControlledPagination) {
179
181
  if (typeof controlledPagination?.pageCount === 'undefined') {
180
- throw new Error('You have to pass pageCount in controlledPagination data');
182
+ throw new Error(
183
+ 'You have to pass pageCount in controlledPagination data',
184
+ );
181
185
  }
182
186
 
183
187
  options.initialState = {
@@ -200,7 +204,10 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
200
204
  id: 'selection',
201
205
  disableSortBy: true,
202
206
  Header: (instance: SelectableRowInstanceProps) => {
203
- const {getToggleAllRowsSelectedProps, toggleAllRowsSelected} = instance;
207
+ const {
208
+ getToggleAllRowsSelectedProps,
209
+ toggleAllRowsSelected,
210
+ } = instance;
204
211
 
205
212
  return (
206
213
  <Checkbox
@@ -230,10 +237,10 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
230
237
  },
231
238
  };
232
239
 
233
- hooks.visibleColumns.push((tableColumns: Array<StandardColumn>) => ([
240
+ hooks.visibleColumns.push((tableColumns: Array<StandardColumn>) => [
234
241
  newColumn,
235
242
  ...tableColumns,
236
- ]));
243
+ ]);
237
244
  };
238
245
 
239
246
  const {
@@ -249,6 +256,7 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
249
256
  options,
250
257
  useFlexLayout,
251
258
  useSortBy,
259
+ useExpanded,
252
260
  usePagination,
253
261
  useRowSelect,
254
262
  useSelect,
@@ -285,15 +293,19 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
285
293
 
286
294
  useEffect(() => {
287
295
  if (hasSelectedRowsAbility) {
288
- onSelectRowsChange?.(selectedFlatRows?.map((row: StandardRow) => row.original));
296
+ onSelectRowsChange?.(
297
+ selectedFlatRows?.map((row: StandardRow) => row.original),
298
+ );
289
299
  }
290
300
  }, [selectedRowIds]);
291
301
 
292
302
  let pagination: JSX.Element | null = null;
293
303
 
294
304
  if (hasDefaultPagination && hasControlledPagination) {
295
- // eslint-disable-next-line max-len
296
- throw new Error('You have to pass either hasDefaultPagination true boolean prop or pass fetchData callback and controlledPagination data');
305
+ throw new Error(
306
+ 'You have to pass either hasDefaultPagination true boolean prop or '
307
+ + 'pass fetchData callback and controlledPagination data',
308
+ );
297
309
  }
298
310
 
299
311
  if (hasControlledPagination || hasDefaultPagination) {
@@ -347,9 +359,7 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
347
359
  }
348
360
  }
349
361
 
350
- pagination = (
351
- <PaginationComponent {...paginationData} />
352
- );
362
+ pagination = <PaginationComponent {...paginationData} />;
353
363
  }
354
364
 
355
365
  function extendSortByProps(column: ColumnWithSort) {
@@ -360,39 +370,55 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
360
370
  if (hasManualSortBy && column.canSort && headerProps) {
361
371
  headerProps.onClick = () => {
362
372
  onSortedChange?.(column.id, Boolean(column.isSortedDesc));
363
- setSortBy([{
364
- id: column.id,
365
- desc: !column.isSortedDesc,
366
- }]);
373
+ setSortBy([
374
+ {
375
+ id: column.id,
376
+ desc: !column.isSortedDesc,
377
+ },
378
+ ]);
367
379
  };
368
380
  }
369
381
 
370
382
  return headerProps;
371
383
  }
372
384
 
373
- const tBodyTr = (hasControlledPagination || hasDefaultPagination) ? page : rows;
385
+ const tBodyTr = hasControlledPagination || hasDefaultPagination ? page : rows;
374
386
 
375
387
  return (
376
388
  <TableRoot className="table-root">
377
- <TableLoading isLoading={!showLoadingState && isLoading} className="table-loading">
378
- <TableLoadingInner>
379
- {loadingMessage}
380
- </TableLoadingInner>
389
+ <TableLoading
390
+ isLoading={!showLoadingState && isLoading}
391
+ className="table-loading"
392
+ >
393
+ <TableLoadingInner>{loadingMessage}</TableLoadingInner>
381
394
  </TableLoading>
382
395
  <TableWrapper ref={tableWrapperRef} className="table-wrapper">
383
396
  <TableContent id={tableContentId} className="table-content">
384
- <TableCore {..._getTableProps(getTableBodyProps(getTableProps))} ref={tableRef}>
397
+ <TableCore
398
+ {..._getTableProps(getTableBodyProps(getTableProps))}
399
+ ref={tableRef}
400
+ >
385
401
  <THead className="table-head">
386
402
  {headerGroups.map((headerGroup) => (
387
- <TR {...headerGroup.getHeaderGroupProps(getTableElementProps(getHeaderGroupProps))}>
403
+ <TR
404
+ {...headerGroup.getHeaderGroupProps(
405
+ getTableElementProps(getHeaderGroupProps),
406
+ )}
407
+ >
388
408
  {headerGroup.headers.map((column) => {
389
- const headerProps = extendSortByProps(column) as DefaultObject;
409
+ const headerProps = extendSortByProps(
410
+ column,
411
+ ) as DefaultObject;
390
412
 
391
413
  return (
392
414
  <TH
393
- {...column.getHeaderProps(getTableElementInternalProps(
394
- headerProps, getHeaderProps, mainCellGetter,
395
- ))}
415
+ {...column.getHeaderProps(
416
+ getTableElementInternalProps(
417
+ headerProps,
418
+ getHeaderProps,
419
+ mainCellGetter,
420
+ ),
421
+ )}
396
422
  >
397
423
  {getHeadContent(column)}
398
424
  </TH>
@@ -404,9 +430,17 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
404
430
  {footerPlacement.includes(FOOTER_PLACEMENT.TOP) && (
405
431
  <TFoot className="table-footer-top">
406
432
  {footerGroups.map((group) => (
407
- <TR {...group.getFooterGroupProps(getTableElementProps(getFooterGroupProps))}>
433
+ <TR
434
+ {...group.getFooterGroupProps(
435
+ getTableElementProps(getFooterGroupProps),
436
+ )}
437
+ >
408
438
  {group.headers.map((column) => (
409
- <TD {...column.getFooterProps(getTableElementProps(getFooterProps, mainCellGetter))}>
439
+ <TD
440
+ {...column.getFooterProps(
441
+ getTableElementProps(getFooterProps, mainCellGetter),
442
+ )}
443
+ >
410
444
  {column.render('Footer')}
411
445
  </TD>
412
446
  ))}
@@ -421,38 +455,58 @@ const Table: FunctionComponent<TableProps & DefaultProps> = (props) => {
421
455
 
422
456
  if (isDelimiterTd) {
423
457
  return (
424
- <TRGroup key={`group_${row.index}`}>
425
- <TR {...row.getRowProps(getTableRowProps(getRowProps))}>
426
- <TD
427
- colSpan={visibleColumns.length}
428
- {...row.cells[0].getCellProps(getTableCellProps(getCellProps, cellGetter))}
429
- >
430
- <strong>{row.cells[0].render('Cell')}</strong>
431
- </TD>
432
- </TR>
433
- </TRGroup>
458
+ <React.Fragment key={`group_${row.index}`}>
459
+ <TRGroup>
460
+ <TR {...row.getRowProps(getTableRowProps(getRowProps))}>
461
+ <TD
462
+ colSpan={visibleColumns.length}
463
+ {...row.cells[0].getCellProps(
464
+ getTableCellProps(getCellProps, cellGetter),
465
+ )}
466
+ >
467
+ <strong>{row.cells[0].render('Cell')}</strong>
468
+ </TD>
469
+ </TR>
470
+ </TRGroup>
471
+ {row?.isExpanded && rowSubComponent && rowSubComponent(row)}
472
+ </React.Fragment>
434
473
  );
435
474
  }
436
475
 
437
476
  return (
438
- <TRGroup key={`group_${row.index}`}>
439
- <TR {...row.getRowProps(getTableRowProps(getRowProps))}>
440
- {row.cells.map((cell: StandardCell) => (
441
- <TD {...cell.getCellProps(getTableCellProps(getCellProps, cellGetter))}>
442
- {cell.render('Cell')}
443
- </TD>
444
- ))}
445
- </TR>
446
- </TRGroup>
477
+ <React.Fragment key={`group_${row.index}`}>
478
+ <TRGroup>
479
+ <TR {...row.getRowProps(getTableRowProps(getRowProps))}>
480
+ {row.cells.map((cell: StandardCell) => (
481
+ <TD
482
+ {...cell.getCellProps(
483
+ getTableCellProps(getCellProps, cellGetter),
484
+ )}
485
+ >
486
+ {cell.render('Cell')}
487
+ </TD>
488
+ ))}
489
+ </TR>
490
+ </TRGroup>
491
+ {row?.isExpanded && rowSubComponent && rowSubComponent(row)}
492
+ </React.Fragment>
447
493
  );
448
494
  })}
449
495
  </TBody>
450
496
  {footerPlacement.includes(FOOTER_PLACEMENT.BOTTOM) && (
451
497
  <TFoot className="table-footer-bottom">
452
498
  {footerGroups.map((group) => (
453
- <TR {...group.getFooterGroupProps(getTableElementProps(getFooterGroupProps))}>
499
+ <TR
500
+ {...group.getFooterGroupProps(
501
+ getTableElementProps(getFooterGroupProps),
502
+ )}
503
+ >
454
504
  {group.headers.map((column) => (
455
- <TD {...column.getFooterProps(getTableElementProps(getFooterProps, mainCellGetter))}>
505
+ <TD
506
+ {...column.getFooterProps(
507
+ getTableElementProps(getFooterProps, mainCellGetter),
508
+ )}
509
+ >
456
510
  {column.render('Footer')}
457
511
  </TD>
458
512
  ))}
package/src/types.tsx CHANGED
@@ -85,6 +85,7 @@ export type TableProps = {
85
85
  showLoadingState?: boolean,
86
86
  LoadingCellComponent?: FunctionComponent<DefaultObject>,
87
87
  noDataMessage?: string | ReactElement
88
+ rowSubComponent?: (row: StandardRow) => ReactElement
88
89
  }
89
90
 
90
91
  export type TableOptions = {
@@ -135,7 +136,7 @@ export type ColumnWithSort = HeaderGroup<DefaultObject> & Partial<UseSortByColum
135
136
 
136
137
  export type StandardColumn = Column<DefaultObject>
137
138
 
138
- export type StandardRow = Row<DefaultObject>
139
+ export type StandardRow = Row<DefaultObject> & { isExpanded?: boolean }
139
140
 
140
141
  export type SelectableRow = Row<{ id: string }> & UseRowSelectRowProps<DefaultObject>
141
142
 
@@ -10,22 +10,13 @@ const useLoadingState = (
10
10
  LoadingCellComponent: FunctionComponent<DefaultObject>,
11
11
  ): LoadingState => {
12
12
  const loadingColumns: Column<DefaultObject>[] | undefined = useMemo(() => (showLoadingState && loading ? columns
13
- .map(({maxWidth, width, Header}: Column, key: number) => {
14
- const column: Column<DefaultObject> = {
13
+ .map((column: Column<DefaultObject>) => {
14
+ const loadingColumn: Column<DefaultObject> = {
15
+ ...column,
15
16
  Cell: () => <LoadingCellComponent />,
16
- accessor: `empty_${key}`,
17
17
  };
18
- if (maxWidth) {
19
- column.maxWidth = maxWidth;
20
- }
21
- if (width) {
22
- column.width = width;
23
- }
24
- if (Header) {
25
- column.Header = Header;
26
- }
27
18
 
28
- return column;
19
+ return loadingColumn;
29
20
  }) : []), [columns, loading, showLoadingState]);
30
21
 
31
22
  const loadingData = useMemo(() => {