@ltht-react/table 2.0.2 → 2.0.4
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/README.md +15 -15
- package/package.json +10 -9
- package/src/atoms/questionnaire-withdrawn-table-cell.tsx +15 -0
- package/src/index.tsx +7 -0
- package/src/molecules/table-cell.tsx +93 -0
- package/src/molecules/table-component.tsx +146 -0
- package/src/molecules/table-methods.tsx +234 -0
- package/src/molecules/table-styled-components.tsx +233 -0
- package/src/molecules/table.tsx +161 -0
- package/src/molecules/useDimensionRef.tsx +37 -0
- package/src/molecules/useScrollRef.tsx +36 -0
- package/src/organisms/generic-table.tsx +33 -0
- package/src/organisms/questionnaire-table-methods.tsx +334 -0
- package/src/organisms/questionnaire-table.tsx +55 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CSS_RESET,
|
|
3
|
+
TRANSLUCENT_MID_GREY,
|
|
4
|
+
SCROLLBAR,
|
|
5
|
+
TRANSLUCENT_BRIGHT_BLUE,
|
|
6
|
+
BTN_COLOURS,
|
|
7
|
+
TABLE_COLOURS,
|
|
8
|
+
StickyTableData,
|
|
9
|
+
StickyTableHead,
|
|
10
|
+
getZIndex,
|
|
11
|
+
} from '@ltht-react/styles'
|
|
12
|
+
import styled from '@emotion/styled'
|
|
13
|
+
import Icon, { IconButton } from '@ltht-react/icon'
|
|
14
|
+
import { Axis } from '@ltht-react/types'
|
|
15
|
+
|
|
16
|
+
const ScrollableContainer = styled.div<IScrollableContainer>`
|
|
17
|
+
${CSS_RESET};
|
|
18
|
+
background-color: white;
|
|
19
|
+
${({ tableHeaderAxis, maxWidth, maxHeight }) => `
|
|
20
|
+
display: ${tableHeaderAxis === 'y' ? 'inline-flex' : 'inline-block'};
|
|
21
|
+
max-width: ${maxWidth ?? '100%'};
|
|
22
|
+
max-height: ${maxHeight ?? '100%'};
|
|
23
|
+
`}
|
|
24
|
+
border-radius: 6px;
|
|
25
|
+
overflow: auto;
|
|
26
|
+
&::-webkit-scrollbar {
|
|
27
|
+
width: 7px;
|
|
28
|
+
height: 7px;
|
|
29
|
+
border: 0;
|
|
30
|
+
}
|
|
31
|
+
&::-webkit-scrollbar-thumb {
|
|
32
|
+
background: ${SCROLLBAR};
|
|
33
|
+
border-radius: 10px;
|
|
34
|
+
}
|
|
35
|
+
`
|
|
36
|
+
const StyledTable = styled.table`
|
|
37
|
+
border-spacing: 0px;
|
|
38
|
+
border-radius: 6px;
|
|
39
|
+
`
|
|
40
|
+
const StyledTableHeader = styled.th<IStyledTableCell>`
|
|
41
|
+
background-color: ${TABLE_COLOURS.HEADER};
|
|
42
|
+
border: thin solid ${TABLE_COLOURS.BORDER};
|
|
43
|
+
font-weight: bold;
|
|
44
|
+
padding: 0.5rem;
|
|
45
|
+
|
|
46
|
+
${({ stickyWidth }) =>
|
|
47
|
+
stickyWidth !== undefined &&
|
|
48
|
+
`
|
|
49
|
+
position: sticky !important;
|
|
50
|
+
left: ${stickyWidth}px;
|
|
51
|
+
top: 0;
|
|
52
|
+
z-index: ${getZIndex(StickyTableData)};`}
|
|
53
|
+
`
|
|
54
|
+
const StyledTableData = styled.td<IStyledTableCell>`
|
|
55
|
+
border: thin solid ${TABLE_COLOURS.BORDER};
|
|
56
|
+
white-space: normal;
|
|
57
|
+
text-align: center;
|
|
58
|
+
padding: 0.15rem;
|
|
59
|
+
|
|
60
|
+
&:first-of-type {
|
|
61
|
+
background-color: ${TABLE_COLOURS.HEADER} !important;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
${({ stickyWidth }) =>
|
|
66
|
+
stickyWidth !== undefined &&
|
|
67
|
+
`
|
|
68
|
+
background-color: ${TABLE_COLOURS.STRIPE_LIGHT};
|
|
69
|
+
position: sticky !important;
|
|
70
|
+
left: ${stickyWidth}px;
|
|
71
|
+
top: 0;
|
|
72
|
+
z-index: ${getZIndex(StickyTableData)};`}
|
|
73
|
+
|
|
74
|
+
${({ tableHeaderAxis }) =>
|
|
75
|
+
tableHeaderAxis === 'y' &&
|
|
76
|
+
`
|
|
77
|
+
&:nth-of-type(even) {
|
|
78
|
+
background-color: ${TABLE_COLOURS.STRIPE_DARK};
|
|
79
|
+
}`}
|
|
80
|
+
`
|
|
81
|
+
const StyledTableRow = styled.tr<IStyledTableCell>`
|
|
82
|
+
${({ tableHeaderAxis }) =>
|
|
83
|
+
tableHeaderAxis === 'x' &&
|
|
84
|
+
`
|
|
85
|
+
&:nth-of-type(odd) {
|
|
86
|
+
background-color: ${TABLE_COLOURS.STRIPE_DARK};
|
|
87
|
+
}`}
|
|
88
|
+
`
|
|
89
|
+
const PaginationContainer = styled.div`
|
|
90
|
+
${CSS_RESET};
|
|
91
|
+
margin-top: 5px;
|
|
92
|
+
display: block;
|
|
93
|
+
`
|
|
94
|
+
const StyledPaginationPageInput = styled.input`
|
|
95
|
+
${CSS_RESET};
|
|
96
|
+
width: 50px;
|
|
97
|
+
border: 1px solid gray;
|
|
98
|
+
`
|
|
99
|
+
const StyledPaginationPageSelect = styled.select`
|
|
100
|
+
${CSS_RESET};
|
|
101
|
+
width: 45px;
|
|
102
|
+
display: inline-block;
|
|
103
|
+
font-size: 0.9rem;
|
|
104
|
+
border: 1px solid gray;
|
|
105
|
+
`
|
|
106
|
+
const StyledHideOnMobile = styled.span`
|
|
107
|
+
font-size: 1.1em;
|
|
108
|
+
padding: 2px;
|
|
109
|
+
@media (max-width: 320px) {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
`
|
|
113
|
+
const StyledPaginationButtonDiv = styled.div`
|
|
114
|
+
float: right;
|
|
115
|
+
display: flex;
|
|
116
|
+
justify-content: space-between;
|
|
117
|
+
align-items: stretch;
|
|
118
|
+
`
|
|
119
|
+
const StyledPageCountDiv = styled.div`
|
|
120
|
+
margin-right: 5px;
|
|
121
|
+
margin-left: 5px;
|
|
122
|
+
display: flex;
|
|
123
|
+
font-size: 1.1em;
|
|
124
|
+
padding: 1px;
|
|
125
|
+
`
|
|
126
|
+
const StyledStandardButton = styled(IconButton)`
|
|
127
|
+
color: ${BTN_COLOURS.STANDARD.TEXT};
|
|
128
|
+
background-color: ${BTN_COLOURS.STANDARD.VALUE};
|
|
129
|
+
padding: 2px 5px;
|
|
130
|
+
border-radius: 5px;
|
|
131
|
+
&:hover {
|
|
132
|
+
background-color: ${BTN_COLOURS.STANDARD.HOVER};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&:disabled {
|
|
136
|
+
background-color: ${BTN_COLOURS.STANDARD.DISABLED};
|
|
137
|
+
}
|
|
138
|
+
`
|
|
139
|
+
const StyledPaginationButton = styled(IconButton)`
|
|
140
|
+
padding: 2px 5px;
|
|
141
|
+
background-color: ${TRANSLUCENT_BRIGHT_BLUE};
|
|
142
|
+
color: black;
|
|
143
|
+
border: 1px solid ${TRANSLUCENT_MID_GREY};
|
|
144
|
+
margin: 0 2.5px;
|
|
145
|
+
border-radius: 3px;
|
|
146
|
+
|
|
147
|
+
&:disabled {
|
|
148
|
+
background-color: inherit;
|
|
149
|
+
color: gray;
|
|
150
|
+
border-color: ${TRANSLUCENT_MID_GREY};
|
|
151
|
+
pointer-events: none;
|
|
152
|
+
}
|
|
153
|
+
`
|
|
154
|
+
const StyledSpinnerIcon = styled(Icon)`
|
|
155
|
+
margin: 3px 0;
|
|
156
|
+
font-size: 1.1em;
|
|
157
|
+
padding: 1.5px;
|
|
158
|
+
`
|
|
159
|
+
const StyledNextPageButtonContainer = styled.div<IStyledNextPageButtonContainer>`
|
|
160
|
+
display: ${({ hidden, elementPosition }) => {
|
|
161
|
+
if (!hidden) {
|
|
162
|
+
return elementPosition === 'bottom' ? 'flex' : 'inline-flex'
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return 'none'
|
|
166
|
+
}};
|
|
167
|
+
justify-content: center;
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
align-items: center;
|
|
170
|
+
padding: 10px;
|
|
171
|
+
font-size: 1.3em;
|
|
172
|
+
border: solid 2px #eeeeee;
|
|
173
|
+
border-left: solid 1px #eeeeee;
|
|
174
|
+
|
|
175
|
+
:hover {
|
|
176
|
+
background-color: #f3f6f6;
|
|
177
|
+
}
|
|
178
|
+
`
|
|
179
|
+
|
|
180
|
+
const StyledSpinnerContainer = styled.div<IStyledNextPageButtonContainer>`
|
|
181
|
+
display: ${({ hidden, elementPosition }) => {
|
|
182
|
+
if (!hidden) {
|
|
183
|
+
return elementPosition === 'bottom' ? 'flex' : 'inline-flex'
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return 'none'
|
|
187
|
+
}};
|
|
188
|
+
justify-content: center;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
align-items: center;
|
|
191
|
+
padding: 5px;
|
|
192
|
+
`
|
|
193
|
+
const StyledTHead = styled.thead`
|
|
194
|
+
position: sticky;
|
|
195
|
+
left: 0;
|
|
196
|
+
top: 0;
|
|
197
|
+
z-index: ${getZIndex(StickyTableHead)};
|
|
198
|
+
`
|
|
199
|
+
|
|
200
|
+
interface IStyledTableCell {
|
|
201
|
+
stickyWidth?: number
|
|
202
|
+
tableHeaderAxis?: string
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
interface IStyledNextPageButtonContainer {
|
|
206
|
+
elementPosition: 'right' | 'bottom'
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
interface IScrollableContainer {
|
|
210
|
+
tableHeaderAxis: Axis
|
|
211
|
+
maxHeight?: string
|
|
212
|
+
maxWidth?: string
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export {
|
|
216
|
+
StyledTable,
|
|
217
|
+
StyledTableHeader,
|
|
218
|
+
StyledTableRow,
|
|
219
|
+
StyledTableData,
|
|
220
|
+
PaginationContainer,
|
|
221
|
+
StyledPaginationPageInput,
|
|
222
|
+
StyledPaginationPageSelect,
|
|
223
|
+
StyledHideOnMobile,
|
|
224
|
+
StyledPaginationButton,
|
|
225
|
+
ScrollableContainer,
|
|
226
|
+
StyledPaginationButtonDiv,
|
|
227
|
+
StyledPageCountDiv,
|
|
228
|
+
StyledStandardButton,
|
|
229
|
+
StyledSpinnerIcon,
|
|
230
|
+
StyledNextPageButtonContainer,
|
|
231
|
+
StyledTHead,
|
|
232
|
+
StyledSpinnerContainer,
|
|
233
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { FC, useEffect, useMemo, useRef, useState } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
getCoreRowModel,
|
|
4
|
+
useReactTable,
|
|
5
|
+
getExpandedRowModel,
|
|
6
|
+
getSortedRowModel,
|
|
7
|
+
ExpandedState,
|
|
8
|
+
SortingState,
|
|
9
|
+
PaginationState,
|
|
10
|
+
ColumnDef,
|
|
11
|
+
SortingFn,
|
|
12
|
+
} from '@tanstack/react-table'
|
|
13
|
+
import { Axis } from '@ltht-react/types'
|
|
14
|
+
import { ScrollableContainer } from './table-styled-components'
|
|
15
|
+
import useScrollRef from './useScrollRef'
|
|
16
|
+
import { handleDataUpdate, handleDataUpdateForManualPagination, handleScrollEvent } from './table-methods'
|
|
17
|
+
import TableComponent, { TableNavigationButton, TableSpinner } from './table-component'
|
|
18
|
+
import { CellProps } from './table-cell'
|
|
19
|
+
|
|
20
|
+
const Table: FC<IProps> = ({
|
|
21
|
+
tableData,
|
|
22
|
+
staticColumns = 0,
|
|
23
|
+
currentPage = 1,
|
|
24
|
+
pageSize: pageSizeParam = 10,
|
|
25
|
+
headerAxis = 'x',
|
|
26
|
+
manualPagination = false,
|
|
27
|
+
getCanNextPage = () => false,
|
|
28
|
+
nextPage = () => null,
|
|
29
|
+
isFetching = false,
|
|
30
|
+
keepPreviousData = false,
|
|
31
|
+
maxHeight,
|
|
32
|
+
maxWidth,
|
|
33
|
+
enableSorting = true,
|
|
34
|
+
sortingFunctions = undefined,
|
|
35
|
+
}) => {
|
|
36
|
+
const scrollableDivElement = useRef(null)
|
|
37
|
+
const scrollState = useScrollRef(scrollableDivElement)
|
|
38
|
+
|
|
39
|
+
const [expanded, setExpanded] = useState<ExpandedState>({})
|
|
40
|
+
const [sorting, setSorting] = useState<SortingState>([])
|
|
41
|
+
const [{ pageIndex, pageSize }, setPagination] = useState<PaginationState>({
|
|
42
|
+
pageIndex: currentPage - 1,
|
|
43
|
+
pageSize: pageSizeParam,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const pagination = useMemo(() => ({ pageIndex, pageSize }), [pageIndex, pageSize])
|
|
47
|
+
const [data, setData] = useState<DataEntity[]>([])
|
|
48
|
+
const [columns, setColumns] = useState<ColumnDef<DataEntity>[]>([])
|
|
49
|
+
const [pageCount, setPageCount] = useState<number>(-1)
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!manualPagination) {
|
|
53
|
+
handleDataUpdate(tableData, pageIndex, pageSize, headerAxis, setColumns, setData, setPageCount)
|
|
54
|
+
}
|
|
55
|
+
}, [pageIndex, pageSize, headerAxis, tableData, manualPagination])
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (manualPagination) {
|
|
59
|
+
handleDataUpdateForManualPagination(tableData, headerAxis, keepPreviousData, setColumns, setData)
|
|
60
|
+
}
|
|
61
|
+
}, [headerAxis, tableData, manualPagination, keepPreviousData])
|
|
62
|
+
|
|
63
|
+
const table = useReactTable({
|
|
64
|
+
data,
|
|
65
|
+
columns,
|
|
66
|
+
...(!manualPagination ? { pageCount } : {}),
|
|
67
|
+
state: {
|
|
68
|
+
expanded,
|
|
69
|
+
sorting,
|
|
70
|
+
...(!manualPagination ? { pagination } : {}),
|
|
71
|
+
},
|
|
72
|
+
manualPagination: true,
|
|
73
|
+
onExpandedChange: setExpanded,
|
|
74
|
+
onSortingChange: setSorting,
|
|
75
|
+
enableSorting,
|
|
76
|
+
sortingFns: sortingFunctions,
|
|
77
|
+
getSubRows: (row) => row.subRows,
|
|
78
|
+
getCoreRowModel: getCoreRowModel(),
|
|
79
|
+
getExpandedRowModel: getExpandedRowModel(),
|
|
80
|
+
getSortedRowModel: getSortedRowModel(),
|
|
81
|
+
...(!manualPagination ? { onPaginationChange: setPagination } : {}),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!scrollState) {
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!manualPagination) {
|
|
90
|
+
handleScrollEvent(table, headerAxis, scrollState)
|
|
91
|
+
}
|
|
92
|
+
}, [scrollState, table, headerAxis, manualPagination])
|
|
93
|
+
|
|
94
|
+
const getNextPage = () => {
|
|
95
|
+
if (manualPagination) {
|
|
96
|
+
nextPage()
|
|
97
|
+
} else {
|
|
98
|
+
table.nextPage()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<ScrollableContainer ref={scrollableDivElement} tableHeaderAxis={headerAxis} {...{ maxHeight, maxWidth }}>
|
|
104
|
+
<TableComponent table={table} staticColumns={staticColumns} headerAxis={headerAxis} />
|
|
105
|
+
{manualPagination ? (
|
|
106
|
+
<TableSpinner position={headerAxis === 'x' ? 'bottom' : 'right'} hidden={!isFetching} />
|
|
107
|
+
) : null}
|
|
108
|
+
<TableNavigationButton
|
|
109
|
+
position={headerAxis === 'x' ? 'bottom' : 'right'}
|
|
110
|
+
hidden={isFetching || (manualPagination ? !getCanNextPage() : !table.getCanNextPage())}
|
|
111
|
+
clickHandler={getNextPage}
|
|
112
|
+
/>
|
|
113
|
+
</ScrollableContainer>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface IProps extends ITableConfig, IPaginationProps, ITableDimensionProps {
|
|
118
|
+
tableData: TableData
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface ITableConfig {
|
|
122
|
+
staticColumns?: 0 | 1 | 2
|
|
123
|
+
headerAxis?: Axis
|
|
124
|
+
enableSorting?: boolean
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
sortingFunctions?: Record<string, SortingFn<any>> | undefined
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface IPaginationProps {
|
|
130
|
+
currentPage?: number
|
|
131
|
+
pageSize?: number
|
|
132
|
+
manualPagination?: boolean
|
|
133
|
+
nextPage?: () => void
|
|
134
|
+
getCanNextPage?: () => boolean
|
|
135
|
+
isFetching?: boolean
|
|
136
|
+
keepPreviousData?: boolean
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface ITableDimensionProps {
|
|
140
|
+
maxWidth?: string
|
|
141
|
+
maxHeight?: string
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
type DataEntity = Record<string, CellProps | DataEntity[]> & {
|
|
145
|
+
subRows?: DataEntity[]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
interface Header {
|
|
149
|
+
type: 'accessor' | 'group' | 'display'
|
|
150
|
+
id: string
|
|
151
|
+
cellProps: CellProps
|
|
152
|
+
subHeaders?: Header[]
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
interface TableData {
|
|
156
|
+
headers: Header[]
|
|
157
|
+
rows: DataEntity[]
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export default Table
|
|
161
|
+
export { DataEntity, CellProps, Header, TableData }
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
const useDimensionsRef = (elementRef: React.RefObject<HTMLElement>, parentElementRef: React.RefObject<HTMLElement>) => {
|
|
4
|
+
const [dimensions, setDimensions] = useState({
|
|
5
|
+
width: 0,
|
|
6
|
+
height: 0,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const getDimensions = () => ({
|
|
11
|
+
width: (elementRef && elementRef.current && elementRef.current.offsetWidth) || 0,
|
|
12
|
+
height: (elementRef && elementRef.current && elementRef.current.offsetHeight) || 0,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const handleResize = () => {
|
|
16
|
+
setDimensions(getDimensions())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (elementRef.current) {
|
|
20
|
+
setDimensions(getDimensions())
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parentElementResizeObserver = new ResizeObserver((_e: ResizeObserverEntry[]) => handleResize())
|
|
24
|
+
|
|
25
|
+
if (parentElementRef?.current) {
|
|
26
|
+
parentElementResizeObserver.observe(parentElementRef.current)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return () => {
|
|
30
|
+
parentElementResizeObserver?.disconnect()
|
|
31
|
+
}
|
|
32
|
+
}, [elementRef, parentElementRef])
|
|
33
|
+
|
|
34
|
+
return dimensions
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default useDimensionsRef
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
const useScrollRef = (elementRef: React.RefObject<HTMLElement>) => {
|
|
4
|
+
const [scrollState, setScrollState] = useState<ScrollState>()
|
|
5
|
+
const element = elementRef.current
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const getScrollState = (): ScrollState => ({
|
|
9
|
+
scrollWidth: element?.scrollWidth ?? 0,
|
|
10
|
+
scrollHeight: element?.scrollHeight ?? 0,
|
|
11
|
+
currentXScroll: (element?.scrollLeft ?? 0) + (element?.clientWidth ?? 0),
|
|
12
|
+
currentYScroll: (element?.scrollTop ?? 0) + (element?.clientHeight ?? 0),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const handleScroll = () => {
|
|
16
|
+
setScrollState(getScrollState())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
element?.addEventListener('scroll', handleScroll)
|
|
20
|
+
|
|
21
|
+
return () => {
|
|
22
|
+
element?.removeEventListener('scroll', handleScroll)
|
|
23
|
+
}
|
|
24
|
+
}, [element])
|
|
25
|
+
|
|
26
|
+
return scrollState
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ScrollState {
|
|
30
|
+
scrollWidth: number
|
|
31
|
+
scrollHeight: number
|
|
32
|
+
currentXScroll: number
|
|
33
|
+
currentYScroll: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default useScrollRef
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Table, { IPaginationProps, ITableDimensionProps, ITableConfig, TableData } from '../molecules/table'
|
|
2
|
+
|
|
3
|
+
const GenericTable = <TColumn, TRow>({
|
|
4
|
+
columnData,
|
|
5
|
+
rowData,
|
|
6
|
+
mapToTableData,
|
|
7
|
+
headerAxis = 'x',
|
|
8
|
+
pageSize = 10,
|
|
9
|
+
currentPage = 1,
|
|
10
|
+
keepPreviousData = true,
|
|
11
|
+
...props
|
|
12
|
+
}: IProps<TColumn, TRow>) => {
|
|
13
|
+
const tableData = mapToTableData(columnData, rowData)
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Table
|
|
17
|
+
tableData={tableData}
|
|
18
|
+
headerAxis={headerAxis}
|
|
19
|
+
pageSize={pageSize}
|
|
20
|
+
currentPage={currentPage}
|
|
21
|
+
keepPreviousData={keepPreviousData}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface IProps<TColumn, TRow> extends ITableConfig, IPaginationProps, ITableDimensionProps {
|
|
28
|
+
columnData: TColumn
|
|
29
|
+
rowData: TRow
|
|
30
|
+
mapToTableData: (colData: TColumn, rowData: TRow) => TableData
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default GenericTable
|