@ltht-react/table 2.0.190 → 2.0.192

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.
@@ -1,238 +1,238 @@
1
- import { ColumnDef, ColumnHelper, createColumnHelper, HeaderContext } from '@tanstack/react-table'
2
- import { IconProps } from '@ltht-react/icon'
3
- import { Axis } from '@ltht-react/types'
4
- import React from 'react'
5
- import { Header, TableData, DataEntity } from './table'
6
- import TableCell, { CellProps } from './table-cell'
7
- import { ScrollState } from './useScrollRef'
8
-
9
- const createColumns = (tableData: TableData, headerAxis: Axis): ColumnDef<DataEntity>[] => {
10
- const columnHelper = createColumnHelper<DataEntity>()
11
-
12
- let columns = createColumnsRecursively(tableData.headers, columnHelper, headerAxis)
13
-
14
- if (tableData.rows.some((row) => row.subRows)) {
15
- columns = prependColumnWithExpansionControls(columns, columnHelper, headerAxis)
16
- }
17
-
18
- return columns
19
- }
20
-
21
- const createColumnsRecursively = (
22
- headers: Header[],
23
- columnHelper: ColumnHelper<DataEntity>,
24
- headerAxis: Axis
25
- ): ColumnDef<DataEntity>[] => {
26
- const result: ColumnDef<DataEntity>[] = headers.map((header) => {
27
- if (header.type === 'display') {
28
- return columnHelper.display({
29
- id: header.id,
30
- header: () => {
31
- const headerCellProps: CellProps = { ...header.cellProps, headerAxis }
32
- return <TableCell {...headerCellProps} />
33
- },
34
- cell: (props) => {
35
- const cellProps: CellProps = { ...(props.getValue() as CellProps), headerAxis }
36
- return <TableCell {...cellProps} />
37
- },
38
- })
39
- }
40
-
41
- if (header.type === 'accessor') {
42
- return columnHelper.accessor(header.id, {
43
- header: (props) => {
44
- const cellProps: CellProps = { ...header.cellProps, iconProps: deriveHeaderIconProps(props), headerAxis }
45
- return <TableCell {...cellProps} />
46
- },
47
- cell: (props) => {
48
- const cellProps: CellProps = { ...(props.getValue() as CellProps), headerAxis }
49
- return <TableCell {...cellProps} />
50
- },
51
- }) as ColumnDef<DataEntity, unknown>
52
- }
53
-
54
- return columnHelper.group({
55
- header: header.cellProps.text ?? '',
56
- columns: createColumnsRecursively(header.subHeaders ?? [], columnHelper, headerAxis),
57
- })
58
- })
59
-
60
- return result
61
- }
62
-
63
- const deriveHeaderIconProps = (props: HeaderContext<DataEntity, CellProps | DataEntity[]>): IconProps | undefined => {
64
- if (props.column.getIsSorted() === 'asc') {
65
- return {
66
- type: 'chevron',
67
- direction: 'up',
68
- size: 'medium',
69
- }
70
- }
71
- if (props.column.getIsSorted() === 'desc') {
72
- return {
73
- type: 'chevron',
74
- direction: 'down',
75
- size: 'medium',
76
- }
77
- }
78
- return undefined
79
- }
80
-
81
- const prependColumnWithExpansionControls = (
82
- columns: ColumnDef<DataEntity, unknown>[],
83
- columnHelper: ColumnHelper<DataEntity>,
84
- headerAxis: Axis
85
- ) => {
86
- const expanderColumn = columnHelper.display({
87
- id: 'expander',
88
- header: ({ table }) => {
89
- const headerCellProps: CellProps = {
90
- iconProps: {
91
- type: 'chevron',
92
- direction: table.getIsAllRowsExpanded() ? 'down' : 'right',
93
- size: 'medium',
94
- },
95
- headerAxis,
96
- clickHandler: table.getToggleAllRowsExpandedHandler(),
97
- }
98
- return <TableCell {...headerCellProps} />
99
- },
100
- cell: (props) => {
101
- const cellProps: CellProps = props.row.getCanExpand()
102
- ? {
103
- iconProps: {
104
- type: 'chevron',
105
- direction: props.row.getIsExpanded() ? 'down' : 'right',
106
- size: 'medium',
107
- },
108
- headerAxis,
109
- clickHandler: props.row.getToggleExpandedHandler(),
110
- }
111
- : { headerAxis }
112
- return <TableCell {...cellProps} />
113
- },
114
- })
115
-
116
- return [expanderColumn].concat(columns)
117
- }
118
-
119
- const calculateStaticColumnOffset = (
120
- cellIdx: number,
121
- staticColumns: number,
122
- firstColumnWidth: number,
123
- secondColumnWidth: number
124
- ) => {
125
- if (staticColumns === 0) {
126
- return undefined
127
- }
128
-
129
- switch (cellIdx) {
130
- case 0:
131
- return 0
132
- case 1:
133
- return cellIdx < staticColumns ? firstColumnWidth : undefined
134
- case 2:
135
- return cellIdx < staticColumns ? firstColumnWidth + secondColumnWidth : undefined
136
- default:
137
- return undefined
138
- }
139
- }
140
-
141
- const handleScrollEvent = (
142
- pagination: { getCanNextPage: () => boolean; nextPage: VoidFunction },
143
- headerAxis: Axis,
144
- scrollState: ScrollState
145
- ) => {
146
- const { scrollWidth, scrollHeight, currentXScroll, currentYScroll } = scrollState
147
- if (
148
- headerAxis === 'x' &&
149
- currentYScroll >= scrollHeight - getPercentageOfMax(5, scrollHeight) &&
150
- currentYScroll <= scrollHeight &&
151
- pagination.getCanNextPage()
152
- ) {
153
- pagination.nextPage()
154
- }
155
-
156
- if (
157
- headerAxis === 'y' &&
158
- currentXScroll >= scrollWidth - getPercentageOfMax(5, scrollWidth) &&
159
- currentXScroll <= scrollWidth &&
160
- pagination.getCanNextPage()
161
- ) {
162
- pagination.nextPage()
163
- }
164
- }
165
-
166
- const getPercentageOfMax = (percentage: number, max: number) => max * (percentage / 100)
167
-
168
- const handleDataUpdate = (
169
- tableData: TableData,
170
- pageIndex: number,
171
- pageSize: number,
172
- headerAxis: Axis,
173
- setColumns: (value: React.SetStateAction<ColumnDef<DataEntity>[]>) => void,
174
- setData: (value: React.SetStateAction<DataEntity[]>) => void,
175
- setPageCount: (value: React.SetStateAction<number>) => void
176
- ) => {
177
- if (tableData && tableData.headers.length > 0) {
178
- if (headerAxis === 'x') {
179
- setColumns(createColumns(tableData, headerAxis))
180
- setData(tableData.rows.slice(0, (pageIndex + 1) * pageSize))
181
- setPageCount(Math.ceil(tableData.rows.length / pageSize))
182
- } else {
183
- const head = tableData.headers[0]
184
- const tail = tableData.headers.slice(1, tableData.headers.length)
185
- setColumns(
186
- createColumns(
187
- { headers: [head, ...tail.slice(0, (pageIndex + 1) * pageSize)], rows: tableData.rows },
188
- headerAxis
189
- )
190
- )
191
- setData(tableData.rows)
192
- setPageCount(Math.ceil(tail.length / pageSize))
193
- }
194
- }
195
- }
196
-
197
- const calculateSliceStartPoint = (oldLength: number, usingExpanderColumn: boolean) => {
198
- if (oldLength > 0) {
199
- return usingExpanderColumn ? 2 : 1
200
- }
201
-
202
- return 0
203
- }
204
-
205
- const handleDataUpdateForManualPagination = (
206
- tableData: TableData,
207
- headerAxis: Axis,
208
- keepPreviousData: boolean,
209
- setColumns: (value: React.SetStateAction<ColumnDef<DataEntity>[]>) => void,
210
- setData: (value: React.SetStateAction<DataEntity[]>) => void
211
- ) => {
212
- if (headerAxis === 'x') {
213
- setData((old) => {
214
- const newData = keepPreviousData ? [...old, ...tableData.rows] : tableData.rows
215
- setColumns(createColumns({ headers: tableData.headers, rows: newData }, headerAxis))
216
- return newData
217
- })
218
- } else if (tableData.headers.length > 0) {
219
- setColumns((old) => {
220
- const newColumns = createColumns(tableData, headerAxis)
221
- const sliceStartPoint = calculateSliceStartPoint(
222
- old.length,
223
- tableData.rows.some((x) => x.subRows)
224
- )
225
-
226
- return keepPreviousData ? [...old, ...newColumns.slice(sliceStartPoint, newColumns.length)] : newColumns
227
- })
228
- setData(tableData.rows)
229
- }
230
- }
231
-
232
- export {
233
- createColumns,
234
- calculateStaticColumnOffset,
235
- handleScrollEvent,
236
- handleDataUpdate,
237
- handleDataUpdateForManualPagination,
238
- }
1
+ import { ColumnDef, ColumnHelper, createColumnHelper, HeaderContext } from '@tanstack/react-table'
2
+ import { IconProps } from '@ltht-react/icon'
3
+ import { Axis } from '@ltht-react/types'
4
+ import React from 'react'
5
+ import { Header, TableData, DataEntity } from './table'
6
+ import TableCell, { CellProps } from './table-cell'
7
+ import { ScrollState } from './useScrollRef'
8
+
9
+ const createColumns = (tableData: TableData, headerAxis: Axis): ColumnDef<DataEntity>[] => {
10
+ const columnHelper = createColumnHelper<DataEntity>()
11
+
12
+ let columns = createColumnsRecursively(tableData.headers, columnHelper, headerAxis)
13
+
14
+ if (tableData.rows.some((row) => row.subRows)) {
15
+ columns = prependColumnWithExpansionControls(columns, columnHelper, headerAxis)
16
+ }
17
+
18
+ return columns
19
+ }
20
+
21
+ const createColumnsRecursively = (
22
+ headers: Header[],
23
+ columnHelper: ColumnHelper<DataEntity>,
24
+ headerAxis: Axis
25
+ ): ColumnDef<DataEntity>[] => {
26
+ const result: ColumnDef<DataEntity>[] = headers.map((header) => {
27
+ if (header.type === 'display') {
28
+ return columnHelper.display({
29
+ id: header.id,
30
+ header: () => {
31
+ const headerCellProps: CellProps = { ...header.cellProps, headerAxis }
32
+ return <TableCell {...headerCellProps} />
33
+ },
34
+ cell: (props) => {
35
+ const cellProps: CellProps = { ...(props.getValue() as CellProps), headerAxis }
36
+ return <TableCell {...cellProps} />
37
+ },
38
+ })
39
+ }
40
+
41
+ if (header.type === 'accessor') {
42
+ return columnHelper.accessor(header.id, {
43
+ header: (props) => {
44
+ const cellProps: CellProps = { ...header.cellProps, iconProps: deriveHeaderIconProps(props), headerAxis }
45
+ return <TableCell {...cellProps} />
46
+ },
47
+ cell: (props) => {
48
+ const cellProps: CellProps = { ...(props.getValue() as CellProps), headerAxis }
49
+ return <TableCell {...cellProps} />
50
+ },
51
+ }) as ColumnDef<DataEntity, unknown>
52
+ }
53
+
54
+ return columnHelper.group({
55
+ header: header.cellProps.text ?? '',
56
+ columns: createColumnsRecursively(header.subHeaders ?? [], columnHelper, headerAxis),
57
+ })
58
+ })
59
+
60
+ return result
61
+ }
62
+
63
+ const deriveHeaderIconProps = (props: HeaderContext<DataEntity, CellProps | DataEntity[]>): IconProps | undefined => {
64
+ if (props.column.getIsSorted() === 'asc') {
65
+ return {
66
+ type: 'chevron',
67
+ direction: 'up',
68
+ size: 'medium',
69
+ }
70
+ }
71
+ if (props.column.getIsSorted() === 'desc') {
72
+ return {
73
+ type: 'chevron',
74
+ direction: 'down',
75
+ size: 'medium',
76
+ }
77
+ }
78
+ return undefined
79
+ }
80
+
81
+ const prependColumnWithExpansionControls = (
82
+ columns: ColumnDef<DataEntity, unknown>[],
83
+ columnHelper: ColumnHelper<DataEntity>,
84
+ headerAxis: Axis
85
+ ) => {
86
+ const expanderColumn = columnHelper.display({
87
+ id: 'expander',
88
+ header: ({ table }) => {
89
+ const headerCellProps: CellProps = {
90
+ iconProps: {
91
+ type: 'chevron',
92
+ direction: table.getIsAllRowsExpanded() ? 'down' : 'right',
93
+ size: 'medium',
94
+ },
95
+ headerAxis,
96
+ clickHandler: table.getToggleAllRowsExpandedHandler(),
97
+ }
98
+ return <TableCell {...headerCellProps} />
99
+ },
100
+ cell: (props) => {
101
+ const cellProps: CellProps = props.row.getCanExpand()
102
+ ? {
103
+ iconProps: {
104
+ type: 'chevron',
105
+ direction: props.row.getIsExpanded() ? 'down' : 'right',
106
+ size: 'medium',
107
+ },
108
+ headerAxis,
109
+ clickHandler: props.row.getToggleExpandedHandler(),
110
+ }
111
+ : { headerAxis }
112
+ return <TableCell {...cellProps} />
113
+ },
114
+ })
115
+
116
+ return [expanderColumn].concat(columns)
117
+ }
118
+
119
+ const calculateStaticColumnOffset = (
120
+ cellIdx: number,
121
+ staticColumns: number,
122
+ firstColumnWidth: number,
123
+ secondColumnWidth: number
124
+ ) => {
125
+ if (staticColumns === 0) {
126
+ return undefined
127
+ }
128
+
129
+ switch (cellIdx) {
130
+ case 0:
131
+ return 0
132
+ case 1:
133
+ return cellIdx < staticColumns ? firstColumnWidth : undefined
134
+ case 2:
135
+ return cellIdx < staticColumns ? firstColumnWidth + secondColumnWidth : undefined
136
+ default:
137
+ return undefined
138
+ }
139
+ }
140
+
141
+ const handleScrollEvent = (
142
+ pagination: { getCanNextPage: () => boolean; nextPage: VoidFunction },
143
+ headerAxis: Axis,
144
+ scrollState: ScrollState
145
+ ) => {
146
+ const { scrollWidth, scrollHeight, currentXScroll, currentYScroll } = scrollState
147
+ if (
148
+ headerAxis === 'x' &&
149
+ currentYScroll >= scrollHeight - getPercentageOfMax(5, scrollHeight) &&
150
+ currentYScroll <= scrollHeight &&
151
+ pagination.getCanNextPage()
152
+ ) {
153
+ pagination.nextPage()
154
+ }
155
+
156
+ if (
157
+ headerAxis === 'y' &&
158
+ currentXScroll >= scrollWidth - getPercentageOfMax(5, scrollWidth) &&
159
+ currentXScroll <= scrollWidth &&
160
+ pagination.getCanNextPage()
161
+ ) {
162
+ pagination.nextPage()
163
+ }
164
+ }
165
+
166
+ const getPercentageOfMax = (percentage: number, max: number) => max * (percentage / 100)
167
+
168
+ const handleDataUpdate = (
169
+ tableData: TableData,
170
+ pageIndex: number,
171
+ pageSize: number,
172
+ headerAxis: Axis,
173
+ setColumns: (value: React.SetStateAction<ColumnDef<DataEntity>[]>) => void,
174
+ setData: (value: React.SetStateAction<DataEntity[]>) => void,
175
+ setPageCount: (value: React.SetStateAction<number>) => void
176
+ ) => {
177
+ if (tableData && tableData.headers.length > 0) {
178
+ if (headerAxis === 'x') {
179
+ setColumns(createColumns(tableData, headerAxis))
180
+ setData(tableData.rows.slice(0, (pageIndex + 1) * pageSize))
181
+ setPageCount(Math.ceil(tableData.rows.length / pageSize))
182
+ } else {
183
+ const head = tableData.headers[0]
184
+ const tail = tableData.headers.slice(1, tableData.headers.length)
185
+ setColumns(
186
+ createColumns(
187
+ { headers: [head, ...tail.slice(0, (pageIndex + 1) * pageSize)], rows: tableData.rows },
188
+ headerAxis
189
+ )
190
+ )
191
+ setData(tableData.rows)
192
+ setPageCount(Math.ceil(tail.length / pageSize))
193
+ }
194
+ }
195
+ }
196
+
197
+ const calculateSliceStartPoint = (oldLength: number, usingExpanderColumn: boolean) => {
198
+ if (oldLength > 0) {
199
+ return usingExpanderColumn ? 2 : 1
200
+ }
201
+
202
+ return 0
203
+ }
204
+
205
+ const handleDataUpdateForManualPagination = (
206
+ tableData: TableData,
207
+ headerAxis: Axis,
208
+ keepPreviousData: boolean,
209
+ setColumns: (value: React.SetStateAction<ColumnDef<DataEntity>[]>) => void,
210
+ setData: (value: React.SetStateAction<DataEntity[]>) => void
211
+ ) => {
212
+ if (headerAxis === 'x') {
213
+ setData((old) => {
214
+ const newData = keepPreviousData ? [...old, ...tableData.rows] : tableData.rows
215
+ setColumns(createColumns({ headers: tableData.headers, rows: newData }, headerAxis))
216
+ return newData
217
+ })
218
+ } else if (tableData.headers.length > 0) {
219
+ setColumns((old) => {
220
+ const newColumns = createColumns(tableData, headerAxis)
221
+ const sliceStartPoint = calculateSliceStartPoint(
222
+ old.length,
223
+ tableData.rows.some((x) => x.subRows)
224
+ )
225
+
226
+ return keepPreviousData ? [...old, ...newColumns.slice(sliceStartPoint, newColumns.length)] : newColumns
227
+ })
228
+ setData(tableData.rows)
229
+ }
230
+ }
231
+
232
+ export {
233
+ createColumns,
234
+ calculateStaticColumnOffset,
235
+ handleScrollEvent,
236
+ handleDataUpdate,
237
+ handleDataUpdateForManualPagination,
238
+ }