@propellerads/table 5.1.1 → 6.0.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/src/index.tsx DELETED
@@ -1,544 +0,0 @@
1
- import {ArrowDown, ArrowUp, Color, Size} from '@propellerads/icon';
2
- import Checkbox from '@propellerads/input-checkbox';
3
- import React, {FunctionComponent, useEffect, useMemo, useRef} from 'react';
4
- import {
5
- Column,
6
- TableState,
7
- useExpanded,
8
- useFlexLayout,
9
- usePagination,
10
- useResizeColumns,
11
- useRowSelect,
12
- useSortBy,
13
- useTable,
14
- } from 'react-table';
15
- import {
16
- cellGetter,
17
- getTableProps as getTableBodyProps,
18
- getTableCellProps,
19
- getTableElementInternalProps,
20
- getTableElementProps,
21
- getTableRowProps,
22
- mainCellGetter,
23
- } from './propsGetter';
24
- import {
25
- EmptyStateCell as _EmptyStateCell,
26
- HeadCell as _HeadCell,
27
- TableContent as _TableContent,
28
- TableCore as _TableCore,
29
- TableLoading as _TableLoading,
30
- TableLoadingInner as _TableLoadingInner,
31
- TableRoot as _TableRoot,
32
- TableWrapper as _TableWrapper,
33
- TBody as _TBody,
34
- TD as _TD,
35
- TFoot as _TFoot,
36
- TH as _TH,
37
- THead as _THead,
38
- TR as _TR,
39
- TResizer as _TResizer,
40
- TRGroup as _TRGroup,
41
- } from './style';
42
-
43
- import {
44
- ColumnWithSort,
45
- DefaultObject,
46
- FOOTER_PLACEMENT,
47
- PaginationProps,
48
- SelectableRow,
49
- StandardCell,
50
- StandardColumn,
51
- StandardHooks,
52
- StandardRow,
53
- TableHooksInstanceProps,
54
- TableOptionsProps,
55
- TableProps,
56
- } from './types';
57
- import useLoadingState from './useLoadingState';
58
- import useTableShadow from './useTableShadow';
59
-
60
- const TableRoot = _TableRoot as unknown as React.FunctionComponent<DefaultObject>;
61
- const TableWrapper = _TableWrapper as unknown as React.FunctionComponent<DefaultObject>;
62
- const TableContent = _TableContent as unknown as React.FunctionComponent<DefaultObject>;
63
- const HeadCell = _HeadCell as unknown as React.FunctionComponent<DefaultObject>;
64
- const TableLoading = _TableLoading as unknown as React.FunctionComponent<DefaultObject>;
65
- const TableLoadingInner = _TableLoadingInner as unknown as React.FunctionComponent<DefaultObject>;
66
- const TD = _TD as unknown as React.FunctionComponent<DefaultObject>;
67
- const TableCore = _TableCore as unknown as React.FunctionComponent<DefaultObject>;
68
- const THead = _THead as unknown as React.FunctionComponent<DefaultObject>;
69
- const TR = _TR as unknown as React.FunctionComponent<DefaultObject>;
70
- const TH = _TH as unknown as React.FunctionComponent<DefaultObject>;
71
- const TBody = _TBody as unknown as React.FunctionComponent<DefaultObject>;
72
- const TRGroup = _TRGroup as unknown as React.FunctionComponent<DefaultObject>;
73
- const TFoot = _TFoot as unknown as React.FunctionComponent<DefaultObject>;
74
- const EmptyStateCell = _EmptyStateCell as unknown as React.FunctionComponent<DefaultObject>;
75
- const TResizer = _TResizer as unknown as React.FunctionComponent<DefaultObject>;
76
-
77
- const isEnableRowSelectDefault: (_original?: DefaultObject) => boolean = () => true;
78
- const selectColumnPropsDefault = {};
79
- const getRowPrePropsDefault: () => DefaultObject = () => ({});
80
-
81
- export const defaultProps = {
82
- hasDefaultPagination: false,
83
- isLoading: false,
84
- footerPlacement: [] as FOOTER_PLACEMENT[],
85
- loadingMessage: 'loading...',
86
- labelPerPage: 'Show rows',
87
- parentElementId: 'parent-element',
88
- tableContentId: '',
89
- showLoadingState: false,
90
- initialState: {} as Partial<TableState<DefaultObject>>,
91
- LoadingCellComponent: EmptyStateCell,
92
- getRowPreProps: getRowPrePropsDefault,
93
- isEnableRowSelect: isEnableRowSelectDefault,
94
- selectColumnProps: selectColumnPropsDefault,
95
- noDataMessage: '',
96
- };
97
-
98
- type DefaultProps = Readonly<typeof defaultProps>;
99
-
100
- const disableSortRemove = true;
101
- const disableMultiSort = true;
102
- const disabledMultiRemove = true;
103
-
104
- const DEFAULT_PAGE_INDEX = 0;
105
- const DEFAULT_PAGE_SIZE = 10;
106
-
107
- function isFunction(reference?: (arg1?: any, arg2?: any) => void) {
108
- return typeof reference === 'function';
109
- }
110
-
111
- function renderResizer(column) {
112
- if (column.isResizable) {
113
- return (
114
- <TResizer
115
- {...column.getResizerProps()}
116
- onClick={(e) => {
117
- e.preventDefault();
118
- e.stopPropagation();
119
- }}
120
- />
121
- );
122
- }
123
-
124
- return null;
125
- }
126
-
127
- function getHeadContent(column: ColumnWithSort) {
128
- if (column.isSorted && column.isSortedDesc) {
129
- return (
130
- <HeadCell>
131
- {column.render('Header')}
132
- <ArrowUp size={Size.Small} color={Color.GrayDark} />
133
- </HeadCell>
134
- );
135
- }
136
-
137
- if (column.isSorted && !column.isSortedDesc) {
138
- return (
139
- <HeadCell>
140
- {column.render('Header')}
141
- <ArrowDown size={Size.Small} color={Color.GrayDark} />
142
- </HeadCell>
143
- );
144
- }
145
-
146
- return column.render('Header');
147
- }
148
-
149
- const Table: FunctionComponent<TableProps & DefaultProps> = ({
150
- columns,
151
- data,
152
- totalItems,
153
- fetchData,
154
- controlledPagination,
155
- initialState = defaultProps.initialState,
156
- isLoading = defaultProps.isLoading,
157
- loadingMessage = defaultProps.loadingMessage,
158
- labelPerPage = defaultProps.labelPerPage,
159
- footerPlacement = defaultProps.footerPlacement,
160
- onSortedChange,
161
- hasDefaultPagination = defaultProps.hasDefaultPagination,
162
- onSelectRowsChange,
163
- parentElementId = defaultProps.parentElementId,
164
- tableContentId = defaultProps.tableContentId,
165
- LoadingCellComponent = defaultProps.LoadingCellComponent,
166
- PaginationComponent,
167
- getRowPreProps = defaultProps.getRowPreProps as NonNullable<TableProps['getRowPreProps']>,
168
- getTableProps,
169
- getHeaderGroupProps,
170
- getHeaderProps,
171
- getRowProps,
172
- getCellProps,
173
- getFooterProps,
174
- getFooterGroupProps,
175
- showLoadingState = defaultProps.showLoadingState,
176
- noDataMessage = defaultProps.noDataMessage,
177
- rowSubComponent,
178
- isEnableRowSelect = defaultProps.isEnableRowSelect,
179
- selectColumnProps = defaultProps.selectColumnProps,
180
- }) => {
181
- const memoColumns = useMemo(() => columns, [columns]);
182
-
183
- const {loadingColumns, loadingData} = useLoadingState(
184
- showLoadingState,
185
- isLoading,
186
- controlledPagination?.pageSize ?? DEFAULT_PAGE_SIZE,
187
- memoColumns,
188
- LoadingCellComponent,
189
- );
190
-
191
- const showLoading = showLoadingState && isLoading;
192
- const hasSelectedRowsAbility = onSelectRowsChange && isFunction(onSelectRowsChange);
193
- const hasManualSortBy = onSortedChange && isFunction(onSortedChange);
194
- const hasControlledPagination = fetchData && controlledPagination && Object.keys(controlledPagination).length > 0;
195
-
196
- const options: TableOptionsProps = {
197
- columns: showLoading ? (loadingColumns as Column<DefaultObject>[]) : memoColumns,
198
- data: showLoading ? loadingData : data,
199
- initialState,
200
- disableSortRemove,
201
- disableMultiSort,
202
- disabledMultiRemove,
203
- };
204
-
205
- if (hasManualSortBy) {
206
- options.manualSortBy = true;
207
- }
208
-
209
- if (hasControlledPagination) {
210
- if (typeof controlledPagination?.pageCount === 'undefined') {
211
- throw new Error('You have to pass pageCount in controlledPagination data');
212
- }
213
-
214
- options.initialState = {
215
- ...options.initialState,
216
- pageIndex: controlledPagination.pageIndex ?? DEFAULT_PAGE_INDEX,
217
- pageSize: controlledPagination.pageSize ?? DEFAULT_PAGE_SIZE,
218
- };
219
-
220
- options.autoResetPage = true;
221
- options.manualPagination = true;
222
- options.pageCount = controlledPagination.pageCount;
223
- }
224
-
225
- const useSelect = (hooks: StandardHooks) => {
226
- if (!hasSelectedRowsAbility) {
227
- return;
228
- }
229
-
230
- const newColumn = {
231
- id: 'selection',
232
- disableSortBy: true,
233
- Header: (instance: TableHooksInstanceProps & {toggleAllPageRowsSelected: () => void}) => {
234
- const {getToggleAllPageRowsSelectedProps, toggleAllPageRowsSelected, page} = instance;
235
-
236
- const isDisabledAllRows = page.map(({original}) => original).filter(isEnableRowSelect).length === 0;
237
-
238
- return (
239
- <Checkbox
240
- elementId="all"
241
- onChange={toggleAllPageRowsSelected}
242
- isChecked={getToggleAllPageRowsSelectedProps().checked}
243
- isDisabled={isDisabledAllRows}
244
- />
245
- );
246
- },
247
- Cell: ({row}: {row: SelectableRow}) => {
248
- const {id, original, toggleRowSelected, getToggleRowSelectedProps} = row;
249
-
250
- const elementId = Number.isInteger(original.id) ? original.id : id;
251
- const isEnabled = isEnableRowSelect(row.original);
252
-
253
- return (
254
- <Checkbox
255
- elementId={elementId}
256
- onChange={toggleRowSelected}
257
- isDisabled={!isEnabled}
258
- isChecked={isEnabled && getToggleRowSelectedProps().checked}
259
- />
260
- );
261
- },
262
- ...selectColumnProps,
263
- };
264
-
265
- // @ts-ignore
266
- hooks.visibleColumns.push((tableColumns: Array<StandardColumn>) => [newColumn, ...tableColumns]);
267
- };
268
-
269
- const {
270
- getTableProps: _getTableProps,
271
- headerGroups,
272
- footerGroups,
273
- setHiddenColumns,
274
- rows,
275
- prepareRow,
276
- visibleColumns,
277
- ...rest
278
- } = useTable(
279
- options,
280
- useFlexLayout,
281
- useSortBy,
282
- useExpanded,
283
- usePagination,
284
- useRowSelect,
285
- useSelect,
286
- useResizeColumns,
287
- );
288
-
289
- const {
290
- selectedFlatRows,
291
- setSortBy,
292
- page,
293
- canPreviousPage,
294
- canNextPage,
295
- pageCount,
296
- gotoPage,
297
- nextPage,
298
- previousPage,
299
- setPageSize,
300
- state: {selectedRowIds, pageIndex, pageSize},
301
- // @ts-ignore
302
- } = rest as TableHooksInstanceProps;
303
-
304
- const tableRef = useRef(null);
305
- const tableWrapperRef = useRef(null);
306
-
307
- useTableShadow(tableRef, tableWrapperRef);
308
-
309
- useEffect(() => {
310
- if (!initialState?.hiddenColumns) {
311
- return;
312
- }
313
-
314
- setHiddenColumns(initialState.hiddenColumns);
315
- }, [initialState?.hiddenColumns]);
316
-
317
- useEffect(() => {
318
- if (hasSelectedRowsAbility) {
319
- onSelectRowsChange?.(selectedFlatRows?.map((row: StandardRow) => row.original).filter(isEnableRowSelect));
320
- }
321
- }, [selectedRowIds]);
322
-
323
- let pagination: JSX.Element | null = null;
324
-
325
- if (hasDefaultPagination && hasControlledPagination) {
326
- throw new Error(
327
- 'You have to pass either hasDefaultPagination true boolean prop or ' +
328
- 'pass fetchData callback and controlledPagination data',
329
- );
330
- }
331
-
332
- if (hasControlledPagination || hasDefaultPagination) {
333
- const paginationData: PaginationProps = {
334
- setPageSize,
335
- gotoPage,
336
- canNextPage,
337
- canPreviousPage,
338
- parentElementId,
339
- labelPerPage,
340
- pageIndex,
341
- previousPageHandler: previousPage,
342
- nextPageHandler: nextPage,
343
- totalPages: pageCount,
344
- perPage: pageSize,
345
- totalItems: totalItems ?? data.length,
346
- };
347
-
348
- if (hasControlledPagination && controlledPagination) {
349
- paginationData.canNextPage = controlledPagination.pageIndex + 1 !== paginationData.totalPages;
350
- paginationData.canPreviousPage = controlledPagination.pageIndex !== 0;
351
- paginationData.pageIndex = controlledPagination.pageIndex;
352
- paginationData.perPage = controlledPagination.pageSize;
353
-
354
- paginationData.setPageSize = (newPageSize: number) => {
355
- fetchData?.({
356
- pageIndex: paginationData.pageIndex,
357
- pageSize: newPageSize,
358
- });
359
- };
360
-
361
- paginationData.gotoPage = (newPageIndex: number) => {
362
- fetchData?.({
363
- pageIndex: newPageIndex,
364
- pageSize: paginationData.perPage,
365
- });
366
- };
367
-
368
- paginationData.nextPageHandler = () => {
369
- const newPageIndex = paginationData.pageIndex + 1;
370
- paginationData.gotoPage(newPageIndex);
371
- };
372
-
373
- paginationData.previousPageHandler = () => {
374
- const newPageIndex = paginationData.pageIndex - 1;
375
- paginationData.gotoPage(newPageIndex);
376
- };
377
-
378
- if (controlledPagination?.paginationAmount) {
379
- paginationData.paginationAmount = controlledPagination.paginationAmount;
380
- }
381
- }
382
-
383
- pagination = <PaginationComponent {...paginationData} />;
384
- }
385
-
386
- function extendSortByProps(column: ColumnWithSort) {
387
- const headerProps = column.getSortByToggleProps && column.getSortByToggleProps();
388
-
389
- delete headerProps?.style;
390
-
391
- if (hasManualSortBy && column.canSort && headerProps) {
392
- headerProps.onClick = () => {
393
- onSortedChange?.(column.id, Boolean(column.isSortedDesc));
394
- setSortBy([
395
- {
396
- id: column.id,
397
- desc: !column.isSortedDesc,
398
- },
399
- ]);
400
- };
401
- }
402
-
403
- return headerProps;
404
- }
405
-
406
- const tBodyTr = hasControlledPagination || hasDefaultPagination ? page : rows;
407
-
408
- return (
409
- <TableRoot className="table-root">
410
- <TableLoading isLoading={!showLoadingState && isLoading} className="table-loading">
411
- <TableLoadingInner>{loadingMessage}</TableLoadingInner>
412
- </TableLoading>
413
- <TableWrapper ref={tableWrapperRef} className="table-wrapper">
414
- <TableContent id={tableContentId} className="table-content">
415
- <TableCore {..._getTableProps(getTableBodyProps(getTableProps))} ref={tableRef}>
416
- <THead className="table-head" data-role="table-head">
417
- {headerGroups.map((headerGroup) => {
418
- const {key: headerGroupKey, ...headerGroupProps} = headerGroup.getHeaderGroupProps(
419
- getTableElementProps(getHeaderGroupProps),
420
- );
421
- return (
422
- <TR key={headerGroupKey} {...headerGroupProps}>
423
- {headerGroup.headers.map((column) => {
424
- const headerProps = extendSortByProps(column) as DefaultObject;
425
- const {key: columnKey, ...thProps} = column.getHeaderProps(
426
- getTableElementInternalProps(headerProps, getHeaderProps, mainCellGetter),
427
- );
428
-
429
- return (
430
- <TH key={columnKey} {...thProps}>
431
- {getHeadContent(column)}
432
- {renderResizer(column)}
433
- </TH>
434
- );
435
- })}
436
- </TR>
437
- );
438
- })}
439
- </THead>
440
- {footerPlacement.includes(FOOTER_PLACEMENT.TOP) && (
441
- <TFoot className="table-footer-top" data-role="table-footer-top">
442
- {footerGroups.map((group) => {
443
- const {key: footerTopGroupKey, ...footerTopGroupProps} = group.getFooterGroupProps(
444
- getTableElementProps(getFooterGroupProps),
445
- );
446
- return (
447
- <TR key={footerTopGroupKey} {...footerTopGroupProps}>
448
- {group.headers.map((column) => {
449
- const {key: footerTopColumnKey, ...footerTopTdProps} = column.getFooterProps(
450
- getTableElementProps(getFooterProps, mainCellGetter),
451
- );
452
- return (
453
- <TD key={footerTopColumnKey} {...footerTopTdProps}>
454
- {column.render('Footer')}
455
- </TD>
456
- );
457
- })}
458
- </TR>
459
- );
460
- })}
461
- </TFoot>
462
- )}
463
- <TBody className="table-body" data-role="table-body">
464
- {tBodyTr.map((row: StandardRow) => {
465
- prepareRow(row);
466
- const {isDelimiterTd} = getRowPreProps(row);
467
-
468
- if (isDelimiterTd) {
469
- const cell = row.cells[0].render('Cell') as React.ReactNode;
470
- const {key: delimiterRowKey, ...delimiterRowProps} = row.getRowProps(getTableRowProps(getRowProps));
471
- const {key: delimiterCellKey, ...delimiterCellProps} = row.cells[0].getCellProps(
472
- getTableCellProps(getCellProps, cellGetter),
473
- );
474
-
475
- return (
476
- <React.Fragment key={`group_${row.index}`}>
477
- <TRGroup>
478
- <TR key={delimiterRowKey} {...delimiterRowProps}>
479
- <TD key={delimiterCellKey} colSpan={visibleColumns.length} {...delimiterCellProps}>
480
- <strong>{cell}</strong>
481
- </TD>
482
- </TR>
483
- </TRGroup>
484
- {row?.isExpanded && rowSubComponent && rowSubComponent(row)}
485
- </React.Fragment>
486
- );
487
- }
488
-
489
- const {key: rowKey, ...rowProps} = row.getRowProps(getTableRowProps(getRowProps));
490
-
491
- return (
492
- <React.Fragment key={`group_${row.index}`}>
493
- <TRGroup>
494
- <TR key={rowKey} {...rowProps}>
495
- {row.cells.map((cell: StandardCell) => {
496
- const {key: cellKey, ...cellProps} = cell.getCellProps(
497
- getTableCellProps(getCellProps, cellGetter),
498
- );
499
- return (
500
- <TD key={cellKey} {...cellProps}>
501
- {cell.render('Cell')}
502
- </TD>
503
- );
504
- })}
505
- </TR>
506
- </TRGroup>
507
- {row?.isExpanded && rowSubComponent && rowSubComponent(row)}
508
- </React.Fragment>
509
- );
510
- })}
511
- </TBody>
512
- {footerPlacement.includes(FOOTER_PLACEMENT.BOTTOM) && (
513
- <TFoot className="table-footer-bottom" data-role="table-footer-bottom">
514
- {footerGroups.map((group) => {
515
- const {key: footerBottomGroupKey, ...footerBottomGroupProps} = group.getFooterGroupProps(
516
- getTableElementProps(getFooterGroupProps),
517
- );
518
- return (
519
- <TR key={footerBottomGroupKey} {...footerBottomGroupProps}>
520
- {group.headers.map((column) => {
521
- const {key: footerBottomColumnKey, ...footerBottomTdProps} = column.getFooterProps(
522
- getTableElementProps(getFooterProps, mainCellGetter),
523
- );
524
- return (
525
- <TD key={footerBottomColumnKey} {...footerBottomTdProps}>
526
- {column.render('Footer')}
527
- </TD>
528
- );
529
- })}
530
- </TR>
531
- );
532
- })}
533
- </TFoot>
534
- )}
535
- </TableCore>
536
- </TableContent>
537
- </TableWrapper>
538
- {!isLoading && !data.length && noDataMessage}
539
- {pagination}
540
- </TableRoot>
541
- );
542
- };
543
-
544
- export {Table};
@@ -1,93 +0,0 @@
1
- import {
2
- BaseMeta,
3
- DefaultObject,
4
- ElementCellPropGetter,
5
- ElementGetter,
6
- ElementHeaderFooterPropGetter,
7
- ElementRowPropGetter,
8
- GetTableContainerPropsGetter,
9
- GetTableElementInternalPropsGetter,
10
- GetTableElementPropsGetter,
11
- TableGetter,
12
- } from './types';
13
-
14
- export const defaultGetter: ElementGetter = (props) => props;
15
-
16
- export const cellGetter: ElementGetter = (props, {cell}) => ({
17
- ...props,
18
- // @ts-ignore
19
- align: cell?.column?.align,
20
- });
21
- export const mainCellGetter: ElementGetter = (props, {column}) => ({
22
- ...props,
23
- // @ts-ignore
24
- align: column?.align,
25
- });
26
-
27
- export const getTableProps: GetTableContainerPropsGetter = (userGetter, getter = defaultGetter as TableGetter) => {
28
- if (userGetter) {
29
- return (props) => ({
30
- ...getter(props),
31
- ...userGetter(props),
32
- });
33
- }
34
-
35
- return getter;
36
- };
37
-
38
- export const getTableElementProps: GetTableElementPropsGetter<ElementHeaderFooterPropGetter> = (
39
- userGetter,
40
- getter = defaultGetter,
41
- ) => {
42
- if (userGetter) {
43
- return (props, meta) => ({
44
- ...getter(props, meta),
45
- ...userGetter(props, meta),
46
- });
47
- }
48
-
49
- return getter;
50
- };
51
-
52
- export const getTableRowProps: GetTableElementPropsGetter<ElementRowPropGetter> = (
53
- userGetter,
54
- getter = defaultGetter,
55
- ) => {
56
- if (userGetter) {
57
- return (props, meta) => ({
58
- ...getter(props, meta),
59
- ...userGetter(props, meta),
60
- });
61
- }
62
-
63
- return getter;
64
- };
65
-
66
- export const getTableCellProps: GetTableElementPropsGetter<ElementCellPropGetter> = (
67
- userGetter,
68
- getter = defaultGetter,
69
- ) => {
70
- if (userGetter) {
71
- return (props, meta) => ({
72
- ...getter(props, meta),
73
- ...userGetter(props, meta),
74
- });
75
- }
76
-
77
- return getter;
78
- };
79
-
80
- export const getTableElementInternalProps: GetTableElementInternalPropsGetter = (
81
- internalProps,
82
- userGetter,
83
- getter = defaultGetter,
84
- ) => {
85
- if (userGetter) {
86
- return (props, meta) => ({
87
- ...getter({...props, ...internalProps}, meta),
88
- ...userGetter(props, meta),
89
- });
90
- }
91
-
92
- return (props: DefaultObject, meta: BaseMeta) => getter({...props, ...internalProps}, meta);
93
- };