@react-fabric/data 1.0.0-beta.5 → 1.0.0-beta.52
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/histogram/Histogram.module.css → css/_histogram.css} +16 -13
- package/css/styles.css +24 -0
- package/dist/cjs/checklist/CheckList.js +48 -16
- package/dist/cjs/histogram/Histogram.js +48 -10
- package/dist/cjs/hooks/useFilteredList.js +20 -0
- package/dist/cjs/hooks/usePagination.js +27 -4
- package/dist/cjs/hooks/useSelectableList.js +29 -0
- package/dist/cjs/i18n/ar.json.js +8 -1
- package/dist/cjs/i18n/en.json.js +8 -1
- package/dist/cjs/json/JsonViewer.js +67 -27
- package/dist/cjs/pagination/Pagination.js +10 -0
- package/dist/cjs/table/AddColumn.js +1 -1
- package/dist/cjs/table/BodyCell.js +38 -5
- package/dist/cjs/table/BodyRow.js +107 -0
- package/dist/cjs/table/CheckboxCell.js +1 -1
- package/dist/cjs/table/ColumnFilters.js +97 -0
- package/dist/cjs/table/HeaderCell.js +70 -37
- package/dist/cjs/table/Table.js +113 -71
- package/dist/cjs/table/types.js +29 -0
- package/dist/cjs/table/useResizer.js +4 -4
- package/dist/cjs/table/useVirtualTable.js +122 -18
- package/dist/cjs/tree/TreeNode.js +45 -25
- package/dist/cjs/tree/TreePanel.js +28 -10
- package/dist/cjs/tree/useTree.js +97 -15
- package/dist/cjs/tree/utils.js +20 -5
- package/dist/cjs/virtual/Gallery.js +84 -35
- package/dist/cjs/virtual/List.js +82 -32
- package/dist/esm/checklist/CheckList.js +50 -18
- package/dist/esm/histogram/Histogram.js +49 -11
- package/dist/esm/hooks/useFilteredList.js +20 -0
- package/dist/esm/hooks/usePagination.js +27 -4
- package/dist/esm/hooks/useSelectableList.js +29 -0
- package/dist/esm/i18n/ar.json.js +8 -2
- package/dist/esm/i18n/en.json.js +8 -2
- package/dist/esm/json/JsonViewer.js +68 -28
- package/dist/esm/pagination/Pagination.js +10 -0
- package/dist/esm/table/AddColumn.js +1 -1
- package/dist/esm/table/BodyCell.js +38 -5
- package/dist/esm/table/BodyRow.js +107 -0
- package/dist/esm/table/CheckboxCell.js +1 -1
- package/dist/esm/table/ColumnFilters.js +97 -0
- package/dist/esm/table/HeaderCell.js +71 -38
- package/dist/esm/table/Table.js +115 -73
- package/dist/esm/table/types.js +29 -0
- package/dist/esm/table/useResizer.js +4 -4
- package/dist/esm/table/useVirtualTable.js +124 -20
- package/dist/esm/tree/TreeNode.js +47 -27
- package/dist/esm/tree/TreePanel.js +28 -10
- package/dist/esm/tree/useTree.js +99 -17
- package/dist/esm/tree/utils.js +20 -5
- package/dist/esm/virtual/Gallery.js +84 -35
- package/dist/esm/virtual/List.js +82 -32
- package/dist/types/checklist/CheckList.d.ts +24 -2
- package/dist/types/histogram/Histogram.d.ts +31 -4
- package/dist/types/hooks/useFilteredList.d.ts +20 -2
- package/dist/types/hooks/usePagination.d.ts +19 -0
- package/dist/types/hooks/useSelectableList.d.ts +29 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/json/JsonViewer.d.ts +27 -2
- package/dist/types/pagination/Pagination.d.ts +10 -1
- package/dist/types/table/AddColumn.d.ts +2 -2
- package/dist/types/table/BodyCell.d.ts +4 -3
- package/dist/types/table/BodyRow.d.ts +20 -0
- package/dist/types/table/ColumnFilters.d.ts +9 -0
- package/dist/types/table/EmptyCell.d.ts +2 -2
- package/dist/types/table/HeaderCell.d.ts +2 -2
- package/dist/types/table/Table.d.ts +14 -1
- package/dist/types/table/types.d.ts +48 -7
- package/dist/types/table/useTableColumns.d.ts +6 -6
- package/dist/types/table/useVirtualTable.d.ts +23 -8
- package/dist/types/tree/TreeNode.d.ts +1 -1
- package/dist/types/tree/TreePanel.d.ts +42 -1
- package/dist/types/tree/types.d.ts +25 -5
- package/dist/types/tree/useTree.d.ts +3 -10
- package/dist/types/tree/utils.d.ts +4 -1
- package/dist/types/virtual/Gallery.d.ts +44 -4
- package/dist/types/virtual/List.d.ts +44 -4
- package/package.json +13 -10
- package/src/checklist/CheckList.tsx +103 -77
- package/src/histogram/Histogram.tsx +45 -11
- package/src/hooks/useFilteredList.tsx +19 -0
- package/src/hooks/usePagination.tsx +32 -7
- package/src/hooks/useSelectableList.ts +29 -0
- package/src/i18n/ar.json +5 -0
- package/src/i18n/en.json +5 -0
- package/src/index.ts +1 -1
- package/src/json/JsonViewer.tsx +71 -35
- package/src/pagination/Pagination.tsx +10 -0
- package/src/table/AddColumn.tsx +3 -3
- package/src/table/BodyCell.tsx +34 -5
- package/src/table/BodyRow.tsx +143 -0
- package/src/table/CheckboxCell.tsx +1 -1
- package/src/table/ColumnFilters.tsx +105 -0
- package/src/table/EmptyCell.tsx +2 -2
- package/src/table/HeaderCell.tsx +72 -14
- package/src/table/Table.tsx +177 -77
- package/src/table/types.ts +52 -6
- package/src/table/useResizer.ts +5 -3
- package/src/table/useTableColumns.ts +7 -7
- package/src/table/useVirtualTable.ts +146 -24
- package/src/tree/TreeNode.tsx +98 -56
- package/src/tree/TreePanel.tsx +64 -3
- package/src/tree/types.ts +32 -4
- package/src/tree/useTree.ts +109 -26
- package/src/tree/utils.ts +23 -8
- package/src/virtual/Gallery.tsx +96 -42
- package/src/virtual/List.tsx +82 -33
- package/dist/cjs/histogram/Histogram.module.css +0 -1
- package/dist/esm/histogram/Histogram.module.css +0 -1
package/src/table/Table.tsx
CHANGED
|
@@ -21,12 +21,25 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
CoreIcons,
|
|
26
|
+
EmptyContent,
|
|
27
|
+
Icon,
|
|
28
|
+
Loading,
|
|
29
|
+
useDebounce,
|
|
30
|
+
} from "@react-fabric/core";
|
|
31
|
+
import { debounce } from "@react-fabric/utilities";
|
|
25
32
|
import classNames from "classnames";
|
|
26
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
useEffect,
|
|
35
|
+
useImperativeHandle,
|
|
36
|
+
useLayoutEffect,
|
|
37
|
+
useMemo,
|
|
38
|
+
useRef,
|
|
39
|
+
} from "react";
|
|
27
40
|
import { useTranslation } from "react-i18next";
|
|
28
41
|
import { AddColumn } from "./AddColumn";
|
|
29
|
-
import {
|
|
42
|
+
import { BodyRow } from "./BodyRow";
|
|
30
43
|
import { CheckboxCell } from "./CheckboxCell";
|
|
31
44
|
import { TableProvider } from "./Context";
|
|
32
45
|
import { EmptyCell } from "./EmptyCell";
|
|
@@ -35,16 +48,38 @@ import { type TableProps } from "./types";
|
|
|
35
48
|
import { useTableColumns } from "./useTableColumns";
|
|
36
49
|
import { useVirtualTable } from "./useVirtualTable";
|
|
37
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Table component for displaying data in a tabular format with features like sorting, filtering, and virtual scrolling.
|
|
53
|
+
* It supports expandable rows, checkable rows, and customizable columns.
|
|
54
|
+
* The component is designed to handle large datasets efficiently by rendering only the visible rows.
|
|
55
|
+
* It also provides a way to manage column visibility and allows for custom rendering of group headers.
|
|
56
|
+
* Uses TanStack's `useVirtual` for virtualization and React's `useMemo` for performance optimization.
|
|
57
|
+
*
|
|
58
|
+
* @param {TableProps<T>} props - The properties for the Table component.
|
|
59
|
+
* @returns {JSX.Element} The rendered Table component.
|
|
60
|
+
*
|
|
61
|
+
* @see {@link https://adarshpastakia.github.io/react-fabric/?path=/story/data-table--table}
|
|
62
|
+
* @see {@link https://tanstack.com/table/v8/docs/api/virtual}
|
|
63
|
+
*/
|
|
38
64
|
export const Table = <T extends KeyValue = KeyValue>({
|
|
39
65
|
ref,
|
|
40
66
|
data,
|
|
41
67
|
columns,
|
|
42
|
-
keyProperty,
|
|
68
|
+
keyProperty = "id",
|
|
69
|
+
groupProperty,
|
|
43
70
|
checkableRows,
|
|
71
|
+
initialScroll,
|
|
44
72
|
hideableColumns,
|
|
45
73
|
sort,
|
|
46
74
|
loading,
|
|
75
|
+
checked,
|
|
76
|
+
emptyDisplay,
|
|
77
|
+
groupRenderer,
|
|
78
|
+
canExpand,
|
|
79
|
+
children,
|
|
47
80
|
onSort,
|
|
81
|
+
onFilter,
|
|
82
|
+
onScroll,
|
|
48
83
|
onRowClick,
|
|
49
84
|
onCheckedChanged,
|
|
50
85
|
}: TableProps<T>) => {
|
|
@@ -58,13 +93,24 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
58
93
|
const {
|
|
59
94
|
scrollerRef,
|
|
60
95
|
items,
|
|
96
|
+
top,
|
|
61
97
|
checkState,
|
|
98
|
+
virtualizer,
|
|
99
|
+
hasActiveSticky,
|
|
100
|
+
toggleExpand,
|
|
62
101
|
toggleChecked,
|
|
63
102
|
toggleAllChecked,
|
|
103
|
+
toggleGroupExpand,
|
|
64
104
|
getData,
|
|
65
105
|
totalSize,
|
|
106
|
+
isActiveSticky,
|
|
66
107
|
measureElement,
|
|
67
|
-
} = useVirtualTable(data,
|
|
108
|
+
} = useVirtualTable(data, {
|
|
109
|
+
checked,
|
|
110
|
+
keyProperty,
|
|
111
|
+
groupProperty,
|
|
112
|
+
onCheckChanged: fireCheckChanged,
|
|
113
|
+
});
|
|
68
114
|
const refBody = useRef<HTMLDivElement>(null);
|
|
69
115
|
|
|
70
116
|
const wrapperStart = useMemo(
|
|
@@ -76,32 +122,51 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
76
122
|
[],
|
|
77
123
|
);
|
|
78
124
|
|
|
125
|
+
useLayoutEffect(() => {
|
|
126
|
+
setTimeout(() => {
|
|
127
|
+
initialScroll &&
|
|
128
|
+
virtualizer.scrollToIndex(initialScroll, { align: "start" });
|
|
129
|
+
}, 100);
|
|
130
|
+
}, []);
|
|
131
|
+
|
|
79
132
|
useImperativeHandle(
|
|
80
133
|
ref,
|
|
81
134
|
() => ({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
?.querySelectorAll<HTMLElement>(`.datatable-row[data-hilight="true"]`)
|
|
85
|
-
.forEach((el) => el && (el.dataset.hilight = undefined));
|
|
86
|
-
const el = refBody.current?.querySelector<HTMLElement>(
|
|
87
|
-
`[data-row="${row}"]`,
|
|
88
|
-
);
|
|
89
|
-
el?.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
90
|
-
el && (el.dataset.hilight = "true");
|
|
135
|
+
scrollTo: (row: number) => {
|
|
136
|
+
virtualizer.scrollToIndex(row, { align: "start" });
|
|
91
137
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
?.
|
|
95
|
-
.
|
|
138
|
+
hilight(row) {
|
|
139
|
+
scrollerRef.current
|
|
140
|
+
?.querySelector(".hilight")
|
|
141
|
+
?.classList.remove("hilight", "ring-1");
|
|
142
|
+
virtualizer.scrollToIndex(Math.floor(row), {
|
|
143
|
+
align: "start",
|
|
144
|
+
});
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
scrollerRef.current
|
|
147
|
+
?.querySelector(`[data-index="${row}"]`)
|
|
148
|
+
?.classList.add("hilight", "ring-1");
|
|
149
|
+
}, 100);
|
|
96
150
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
151
|
+
unhilight() {
|
|
152
|
+
scrollerRef.current
|
|
153
|
+
?.querySelector(".hilight")
|
|
154
|
+
?.classList.remove("hilight", "ring-1");
|
|
100
155
|
},
|
|
101
156
|
}),
|
|
102
157
|
[],
|
|
103
158
|
);
|
|
104
159
|
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
const handle = debounce((top: number) => {
|
|
162
|
+
onScroll?.(top ?? 0);
|
|
163
|
+
});
|
|
164
|
+
handle(top);
|
|
165
|
+
return () => {
|
|
166
|
+
handle.cancel();
|
|
167
|
+
};
|
|
168
|
+
}, [top]);
|
|
169
|
+
|
|
105
170
|
return (
|
|
106
171
|
<TableProvider>
|
|
107
172
|
<div
|
|
@@ -109,10 +174,15 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
109
174
|
style={{
|
|
110
175
|
gridTemplate: `"head" auto "loader" auto "content" 1fr "foot" auto/1fr`,
|
|
111
176
|
}}
|
|
177
|
+
data-ref="tableScroller"
|
|
112
178
|
ref={scrollerRef}
|
|
113
179
|
>
|
|
114
|
-
<div
|
|
180
|
+
<div
|
|
181
|
+
data-ref="tableHeader"
|
|
182
|
+
className="bg-base font-medium sticky top-0 h-8 area-head border-b select-none flex flex-nowrap z-2"
|
|
183
|
+
>
|
|
115
184
|
<div className={wrapperStart}>
|
|
185
|
+
{canExpand && <div className="w-6" />}
|
|
116
186
|
{checkableRows && (
|
|
117
187
|
<CheckboxCell
|
|
118
188
|
state={checkState.allChecked}
|
|
@@ -120,15 +190,33 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
120
190
|
/>
|
|
121
191
|
)}
|
|
122
192
|
{state.start?.map((col, idx) => (
|
|
123
|
-
<HeaderCell
|
|
193
|
+
<HeaderCell
|
|
194
|
+
key={idx}
|
|
195
|
+
{...col}
|
|
196
|
+
sort={sort}
|
|
197
|
+
onSort={onSort}
|
|
198
|
+
onFilter={onFilter}
|
|
199
|
+
/>
|
|
124
200
|
))}
|
|
125
201
|
</div>
|
|
126
202
|
{state.cols?.map((col, idx) => (
|
|
127
|
-
<HeaderCell
|
|
203
|
+
<HeaderCell
|
|
204
|
+
key={idx}
|
|
205
|
+
{...col}
|
|
206
|
+
sort={sort}
|
|
207
|
+
onSort={onSort}
|
|
208
|
+
onFilter={onFilter}
|
|
209
|
+
/>
|
|
128
210
|
))}
|
|
129
211
|
<div className={wrapperEnd}>
|
|
130
212
|
{state.end?.map((col, idx) => (
|
|
131
|
-
<HeaderCell
|
|
213
|
+
<HeaderCell
|
|
214
|
+
key={idx}
|
|
215
|
+
{...col}
|
|
216
|
+
sort={sort}
|
|
217
|
+
onSort={onSort}
|
|
218
|
+
onFilter={onFilter}
|
|
219
|
+
/>
|
|
132
220
|
))}
|
|
133
221
|
|
|
134
222
|
{hideableColumns && (
|
|
@@ -142,66 +230,76 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
142
230
|
{loading && <Loading />}
|
|
143
231
|
{data.length > 0 && (
|
|
144
232
|
<div
|
|
145
|
-
className="area-content flex flex-col flex-nowrap"
|
|
233
|
+
className="area-content flex flex-col flex-nowrap min-h-full"
|
|
146
234
|
style={{ height: totalSize() }}
|
|
147
235
|
ref={refBody}
|
|
148
236
|
>
|
|
149
|
-
<div
|
|
237
|
+
<div
|
|
238
|
+
style={{
|
|
239
|
+
height: items[hasActiveSticky ? 1 : 0]?.start,
|
|
240
|
+
}}
|
|
241
|
+
/>
|
|
150
242
|
{items.map(({ index, key }) => {
|
|
151
243
|
const data = getData(index);
|
|
152
|
-
return (
|
|
244
|
+
return "__GROUP__" in data ? (
|
|
153
245
|
<div
|
|
154
246
|
key={key}
|
|
155
|
-
|
|
156
|
-
data-
|
|
247
|
+
ref={measureElement}
|
|
248
|
+
data-index={index}
|
|
157
249
|
className={classNames(
|
|
158
|
-
"
|
|
159
|
-
index
|
|
160
|
-
onRowClick && "hover:bg-primary-50 active:bg-primary-100",
|
|
250
|
+
"px-2 py-1 text-md bg-base border-y border-tint-100 cursor-pointer flex items-center gap-1 z-1",
|
|
251
|
+
isActiveSticky(index) && "sticky top-8",
|
|
161
252
|
)}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
? toggleChecked(data[keyProperty])
|
|
165
|
-
: onRowClick?.(data)
|
|
166
|
-
}
|
|
167
|
-
data-index={index}
|
|
168
|
-
ref={measureElement}
|
|
253
|
+
role="none"
|
|
254
|
+
onClick={() => toggleGroupExpand(data.key)}
|
|
169
255
|
>
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
column={col}
|
|
183
|
-
item={data}
|
|
184
|
-
/>
|
|
185
|
-
))}
|
|
186
|
-
</div>
|
|
187
|
-
{state.cols?.map((col, idc) => (
|
|
188
|
-
<BodyCell key={`${key}:${idc}`} column={col} item={data} />
|
|
189
|
-
))}
|
|
190
|
-
<div className={wrapperEnd}>
|
|
191
|
-
{state.end?.map((col, ide) => (
|
|
192
|
-
<BodyCell
|
|
193
|
-
key={`${key}:${ide}`}
|
|
194
|
-
column={col}
|
|
195
|
-
item={data}
|
|
196
|
-
/>
|
|
197
|
-
))}
|
|
198
|
-
{hideableColumns && <div className="w-6" />}
|
|
199
|
-
</div>
|
|
256
|
+
<Icon
|
|
257
|
+
rtlFlip
|
|
258
|
+
icon={
|
|
259
|
+
data.open ? CoreIcons.chevronDown : CoreIcons.chevronRight
|
|
260
|
+
}
|
|
261
|
+
/>
|
|
262
|
+
{groupRenderer?.(data) ?? (
|
|
263
|
+
<div className="flex gap-1 items-center">
|
|
264
|
+
<span>{data.key}</span>
|
|
265
|
+
<span className="text-sm">({data.itemCount})</span>
|
|
266
|
+
</div>
|
|
267
|
+
)}
|
|
200
268
|
</div>
|
|
269
|
+
) : (
|
|
270
|
+
<BodyRow
|
|
271
|
+
rowKey={key.toString()}
|
|
272
|
+
index={index}
|
|
273
|
+
checkableRows={checkableRows}
|
|
274
|
+
checked={
|
|
275
|
+
keyProperty &&
|
|
276
|
+
checkState.checked.includes(data[keyProperty])
|
|
277
|
+
? 1
|
|
278
|
+
: 0
|
|
279
|
+
}
|
|
280
|
+
expanded={
|
|
281
|
+
!!keyProperty &&
|
|
282
|
+
checkState.expanded.includes(data[keyProperty])
|
|
283
|
+
}
|
|
284
|
+
data={data}
|
|
285
|
+
hideableColumns={hideableColumns}
|
|
286
|
+
keyProperty={keyProperty}
|
|
287
|
+
measureElement={measureElement}
|
|
288
|
+
onRowClick={onRowClick}
|
|
289
|
+
state={state}
|
|
290
|
+
canExpand={canExpand}
|
|
291
|
+
toggleExpand={toggleExpand}
|
|
292
|
+
expandRow={children}
|
|
293
|
+
toggleChecked={toggleChecked}
|
|
294
|
+
wrapperEnd={wrapperEnd}
|
|
295
|
+
wrapperStart={wrapperStart}
|
|
296
|
+
key={key}
|
|
297
|
+
/>
|
|
201
298
|
);
|
|
202
299
|
})}
|
|
203
300
|
<div className="flex-1 flex flex-nowrap">
|
|
204
301
|
<div className={wrapperStart}>
|
|
302
|
+
{canExpand && <div className="w-6" />}
|
|
205
303
|
{checkableRows && <div className="w-6" />}
|
|
206
304
|
{state.start?.map((col) => (
|
|
207
305
|
<EmptyCell key={String(col.id)} {...col} />
|
|
@@ -220,13 +318,15 @@ export const Table = <T extends KeyValue = KeyValue>({
|
|
|
220
318
|
</div>
|
|
221
319
|
</div>
|
|
222
320
|
)}
|
|
223
|
-
{!loading &&
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
321
|
+
{!loading &&
|
|
322
|
+
data.length === 0 &&
|
|
323
|
+
(emptyDisplay ?? (
|
|
324
|
+
<EmptyContent
|
|
325
|
+
size="sm"
|
|
326
|
+
className="bg-dimmed"
|
|
327
|
+
message={t("datagrid.empty")}
|
|
328
|
+
/>
|
|
329
|
+
))}
|
|
230
330
|
</div>
|
|
231
331
|
</TableProvider>
|
|
232
332
|
);
|
package/src/table/types.ts
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
25
|
type CssProp,
|
|
26
|
+
type Elements,
|
|
26
27
|
type IconProps,
|
|
27
28
|
type RefProp,
|
|
28
29
|
type TestProps,
|
|
@@ -33,21 +34,52 @@ export const COL_MIN_WIDTH = "3rem";
|
|
|
33
34
|
export const COL_MAX_WIDTH = "64rem";
|
|
34
35
|
export const COL_DEFAULT_WIDTH = "12rem";
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
/**
|
|
38
|
+
* TableColumn interface defines the structure of a column in a table.
|
|
39
|
+
* It includes properties for column identification, display options, alignment,
|
|
40
|
+
* visibility, resizing, sorting, filtering, and rendering.
|
|
41
|
+
*
|
|
42
|
+
* @template T - The type of data the column will represent, defaulting to KeyValue.
|
|
43
|
+
* @property {keyof T | string} id - Unique identifier for the column.
|
|
44
|
+
* @property {"string" | "number" | "boolean" | "datetime" | "date" | "time" | "unknown"} [dataType] - Data type of the column values.
|
|
45
|
+
* @property {string} [label] - Display label for the column header.
|
|
46
|
+
* @property {string} [tooltip] - Tooltip text for the column header.
|
|
47
|
+
* @property {string} [format] - Format string for displaying the column values.
|
|
48
|
+
* @property {"start" | "center" | "end"} [align] - Text alignment within the column.
|
|
49
|
+
* @property {"start" | "end"} [locked] - Indicates if the column is locked at the start or end.
|
|
50
|
+
* @property {boolean} [hidden] - Whether the column is hidden.
|
|
51
|
+
* @property {boolean} [truncate] - Whether to truncate the text in the column.
|
|
52
|
+
* @property {boolean} [hideable] - Whether the column can be hidden by the user.
|
|
53
|
+
* @property {boolean} [resizable] - Whether the column can be resized by the user.
|
|
54
|
+
* @property {boolean} [sortable] - Whether the column can be sorted.
|
|
55
|
+
* @property {boolean} [filterable] - Whether the column can be filtered.
|
|
56
|
+
* @property {AnyObject} [filter] - Filter criteria for the column.
|
|
57
|
+
* @property {ReactElement[]} [actions] - Array of action elements to be displayed in the column.
|
|
58
|
+
* @property {AnyObject[]} [filterOptions] - Options for filtering the column.
|
|
59
|
+
* @property {string | number} [width] - Width of the column.
|
|
60
|
+
* @property {string | number} [minWidth] - Minimum width of the column.
|
|
61
|
+
* @property {string | number} [maxWidth] - Maximum width of the column.
|
|
62
|
+
* @property {KeyValue} [valueMap] - Mapping of values for the column.
|
|
63
|
+
* @property {(value: AnyObject, data: T, index: number) => Elements<AnyObject>} [renderer] - Custom renderer function for the column values.
|
|
64
|
+
*/
|
|
65
|
+
export interface TableColumn<T = KeyValue>
|
|
37
66
|
extends CssProp,
|
|
38
67
|
IconProps,
|
|
39
68
|
TestProps {
|
|
40
69
|
id: keyof T | string;
|
|
41
70
|
label?: string;
|
|
42
|
-
|
|
71
|
+
tooltip?: string;
|
|
72
|
+
actions?: ReactElement[];
|
|
43
73
|
align?: "start" | "center" | "end";
|
|
44
74
|
locked?: "start" | "end";
|
|
45
75
|
hidden?: boolean;
|
|
76
|
+
truncate?: boolean;
|
|
46
77
|
hideable?: boolean;
|
|
47
78
|
resizable?: boolean;
|
|
48
79
|
sortable?: boolean;
|
|
49
80
|
filterable?: boolean;
|
|
50
|
-
|
|
81
|
+
filter?: AnyObject;
|
|
82
|
+
filterOptions?: AnyObject[];
|
|
51
83
|
width?: string | number;
|
|
52
84
|
minWidth?: string | number;
|
|
53
85
|
maxWidth?: string | number;
|
|
@@ -60,7 +92,8 @@ export interface ColumnType<T = KeyValue>
|
|
|
60
92
|
| "time"
|
|
61
93
|
| "unknown";
|
|
62
94
|
format?: string;
|
|
63
|
-
|
|
95
|
+
valueMap?: KeyValue;
|
|
96
|
+
renderer?: (value: AnyObject, data: T, index: number) => Elements<AnyObject>;
|
|
64
97
|
}
|
|
65
98
|
|
|
66
99
|
export interface TableRef {
|
|
@@ -70,14 +103,19 @@ export interface TableRef {
|
|
|
70
103
|
}
|
|
71
104
|
|
|
72
105
|
export interface TableProps<T = KeyValue> extends RefProp<TableRef> {
|
|
73
|
-
columns: Array<
|
|
106
|
+
columns: Array<TableColumn<T>>;
|
|
74
107
|
data: T[];
|
|
75
108
|
keyProperty?: keyof T;
|
|
109
|
+
groupProperty?: keyof T;
|
|
110
|
+
groupRenderer?: (key: AnyObject) => ReactElement;
|
|
111
|
+
emptyDisplay?: ReactElement;
|
|
112
|
+
|
|
76
113
|
/**
|
|
77
114
|
* checkable rows
|
|
78
115
|
*/
|
|
116
|
+
checked?: AnyObject[];
|
|
79
117
|
checkableRows?: boolean;
|
|
80
|
-
onCheckedChanged?: (rows:
|
|
118
|
+
onCheckedChanged?: (rows: AnyObject[]) => void;
|
|
81
119
|
/**
|
|
82
120
|
* sorting
|
|
83
121
|
*/
|
|
@@ -88,4 +126,12 @@ export interface TableProps<T = KeyValue> extends RefProp<TableRef> {
|
|
|
88
126
|
hideableColumns?: boolean;
|
|
89
127
|
|
|
90
128
|
onRowClick?: (data: T) => void;
|
|
129
|
+
|
|
130
|
+
initialScroll?: number;
|
|
131
|
+
onScroll?: (firstItem: number) => void;
|
|
132
|
+
|
|
133
|
+
canExpand?: (record: T) => boolean;
|
|
134
|
+
children?: (record: T) => Elements<AnyObject>;
|
|
135
|
+
|
|
136
|
+
onFilter?: (id: keyof T | string, value?: AnyObject) => void;
|
|
91
137
|
}
|
package/src/table/useResizer.ts
CHANGED
|
@@ -47,13 +47,15 @@ export const useResizer = (
|
|
|
47
47
|
/** ***************** attach handlers *******************/
|
|
48
48
|
const box = colEl.getBoundingClientRect();
|
|
49
49
|
if (colEl.parentElement != null) {
|
|
50
|
-
const parentBox = colEl
|
|
50
|
+
const parentBox = colEl
|
|
51
|
+
.closest("[data-ref='tableScroller']")
|
|
52
|
+
?.getBoundingClientRect() as unknown as DOMRect;
|
|
51
53
|
if (isRtl) {
|
|
52
54
|
placeholder.style.left = "unset";
|
|
53
|
-
placeholder.style.right = `${
|
|
55
|
+
placeholder.style.right = `${parentBox.width - box.right}px`;
|
|
54
56
|
} else {
|
|
55
57
|
placeholder.style.right = "unset";
|
|
56
|
-
placeholder.style.left = `${box.left
|
|
58
|
+
placeholder.style.left = `${box.left}px`;
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
placeholder.style.width = `${colEl.offsetWidth}px`;
|
|
@@ -23,20 +23,20 @@
|
|
|
23
23
|
|
|
24
24
|
import { groupBy } from "@react-fabric/utilities";
|
|
25
25
|
import { useEffect, useReducer } from "react";
|
|
26
|
-
import { type
|
|
26
|
+
import { type TableColumn } from "./types";
|
|
27
27
|
|
|
28
28
|
interface ColumnState {
|
|
29
|
-
columns:
|
|
30
|
-
start:
|
|
31
|
-
end:
|
|
32
|
-
cols:
|
|
29
|
+
columns: TableColumn[];
|
|
30
|
+
start: TableColumn[];
|
|
31
|
+
end: TableColumn[];
|
|
32
|
+
cols: TableColumn[];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
type ColumnActions =
|
|
36
|
-
| { type: "columns"; columns:
|
|
36
|
+
| { type: "columns"; columns: TableColumn[] }
|
|
37
37
|
| { type: "hide"; id: string };
|
|
38
38
|
|
|
39
|
-
export const useTableColumns = (columns:
|
|
39
|
+
export const useTableColumns = (columns: TableColumn[]) => {
|
|
40
40
|
const [state, dispatch] = useReducer(
|
|
41
41
|
(state: ColumnState, action: ColumnActions) => {
|
|
42
42
|
if (action.type === "columns") {
|