@etsoo/materialui 1.5.71 → 1.5.73
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/__tests__/ReactAppTests.tsx +12 -7
- package/__tests__/{ResponsePage.tsx → ResponsivePage.tsx} +11 -5
- package/__tests__/SelectEx.tsx +1 -1
- package/lib/cjs/DataGridEx.d.ts +8 -1
- package/lib/cjs/DataGridEx.js +71 -56
- package/lib/cjs/DataGridRenderers.d.ts +1 -1
- package/lib/cjs/DataGridRenderers.js +1 -1
- package/lib/cjs/MUUtils.d.ts +0 -9
- package/lib/cjs/MUUtils.js +0 -26
- package/lib/cjs/MobileListItemRenderer.d.ts +2 -2
- package/lib/cjs/MobileListItemRenderer.js +3 -4
- package/lib/cjs/ResponsibleContainer.d.ts +9 -13
- package/lib/cjs/ResponsibleContainer.js +19 -58
- package/lib/cjs/ScrollerListEx.d.ts +23 -23
- package/lib/cjs/ScrollerListEx.js +32 -84
- package/lib/cjs/TableEx.d.ts +7 -0
- package/lib/cjs/TableEx.js +6 -12
- package/lib/cjs/pages/DataGridPage.js +3 -32
- package/lib/cjs/pages/FixedListPage.js +5 -34
- package/lib/cjs/pages/ListPage.js +1 -29
- package/lib/cjs/pages/ResponsivePage.d.ts +9 -13
- package/lib/cjs/uses/useGridCacheInitLoad.d.ts +2 -0
- package/lib/cjs/uses/useGridCacheInitLoad.js +41 -0
- package/lib/cjs/uses/useListCacheInitLoad.d.ts +2 -0
- package/lib/cjs/uses/useListCacheInitLoad.js +38 -0
- package/lib/mjs/DataGridEx.d.ts +8 -1
- package/lib/mjs/DataGridEx.js +71 -56
- package/lib/mjs/DataGridRenderers.d.ts +1 -1
- package/lib/mjs/DataGridRenderers.js +1 -1
- package/lib/mjs/MUUtils.d.ts +0 -9
- package/lib/mjs/MUUtils.js +0 -26
- package/lib/mjs/MobileListItemRenderer.d.ts +2 -2
- package/lib/mjs/MobileListItemRenderer.js +3 -4
- package/lib/mjs/ResponsibleContainer.d.ts +9 -13
- package/lib/mjs/ResponsibleContainer.js +19 -58
- package/lib/mjs/ScrollerListEx.d.ts +23 -23
- package/lib/mjs/ScrollerListEx.js +32 -84
- package/lib/mjs/TableEx.d.ts +7 -0
- package/lib/mjs/TableEx.js +6 -12
- package/lib/mjs/pages/DataGridPage.js +3 -32
- package/lib/mjs/pages/FixedListPage.js +5 -34
- package/lib/mjs/pages/ListPage.js +1 -29
- package/lib/mjs/pages/ResponsivePage.d.ts +9 -13
- package/lib/mjs/uses/useGridCacheInitLoad.d.ts +2 -0
- package/lib/mjs/uses/useGridCacheInitLoad.js +35 -0
- package/lib/mjs/uses/useListCacheInitLoad.d.ts +2 -0
- package/lib/mjs/uses/useListCacheInitLoad.js +32 -0
- package/package.json +18 -19
- package/src/DataGridEx.tsx +155 -109
- package/src/DataGridRenderers.tsx +2 -1
- package/src/MUUtils.ts +0 -33
- package/src/MobileListItemRenderer.tsx +4 -4
- package/src/ResponsibleContainer.tsx +50 -111
- package/src/ScrollerListEx.tsx +141 -229
- package/src/TableEx.tsx +20 -12
- package/src/pages/DataGridPage.tsx +3 -49
- package/src/pages/FixedListPage.tsx +5 -49
- package/src/pages/ListPage.tsx +0 -43
- package/src/pages/ResponsivePage.tsx +16 -21
- package/src/uses/useGridCacheInitLoad.ts +55 -0
- package/src/uses/useListCacheInitLoad.ts +51 -0
package/src/DataGridEx.tsx
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
GridLoaderStates,
|
|
12
12
|
ScrollerGrid,
|
|
13
13
|
ScrollerGridForwardRef,
|
|
14
|
-
ScrollerGridItemRendererProps,
|
|
15
14
|
ScrollerGridProps,
|
|
16
15
|
useCombinedRefs
|
|
17
16
|
} from "@etsoo/react";
|
|
@@ -24,6 +23,8 @@ import Box, { BoxProps } from "@mui/material/Box";
|
|
|
24
23
|
import TableSortLabel from "@mui/material/TableSortLabel";
|
|
25
24
|
import Checkbox from "@mui/material/Checkbox";
|
|
26
25
|
import Paper from "@mui/material/Paper";
|
|
26
|
+
import { GridUtils } from "./GridUtils";
|
|
27
|
+
import { useGridCacheInitLoad } from "./uses/useGridCacheInitLoad";
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Footer item renderer props
|
|
@@ -44,8 +45,15 @@ export type DataGridExProps<
|
|
|
44
45
|
P extends GridJsonData = GridLoadDataProps
|
|
45
46
|
> = Omit<
|
|
46
47
|
ScrollerGridProps<T, P>,
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
| "cellComponent"
|
|
49
|
+
| "columnCount"
|
|
50
|
+
| "columnWidth"
|
|
51
|
+
| "onClick"
|
|
52
|
+
| "onDoubleClick"
|
|
53
|
+
| "onInitLoad"
|
|
54
|
+
| "rowHeight"
|
|
55
|
+
| "width"
|
|
56
|
+
> & Partial<Pick<ScrollerGridProps<T, P>, "rowHeight">> & {
|
|
49
57
|
/**
|
|
50
58
|
* Alternating colors for odd/even rows
|
|
51
59
|
*/
|
|
@@ -117,6 +125,14 @@ export type DataGridExProps<
|
|
|
117
125
|
*/
|
|
118
126
|
onClick?: MouseEventWithDataHandler<T>;
|
|
119
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Data change handler
|
|
130
|
+
* @param rows Rows
|
|
131
|
+
* @param rowIndex Row index
|
|
132
|
+
* @param columnIndex Column index
|
|
133
|
+
*/
|
|
134
|
+
onDataChange?: (rows: T[], rowIndex: number, columnIndex: number) => void;
|
|
135
|
+
|
|
120
136
|
/**
|
|
121
137
|
* Selectable to support hover over and out effect and row clickable
|
|
122
138
|
* @default true
|
|
@@ -355,6 +371,8 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
355
371
|
alternatingColors = [theme.palette.grey[100], undefined],
|
|
356
372
|
borderRowsCount,
|
|
357
373
|
bottomHeight = 53,
|
|
374
|
+
cacheKey,
|
|
375
|
+
cacheMinutes = 15,
|
|
358
376
|
checkable = false,
|
|
359
377
|
className,
|
|
360
378
|
columns,
|
|
@@ -369,7 +387,10 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
369
387
|
idField = "id" as DataTypes.Keys<T>,
|
|
370
388
|
mRef = React.createRef(),
|
|
371
389
|
onClick,
|
|
390
|
+
onDataChange,
|
|
372
391
|
onDoubleClick,
|
|
392
|
+
onUpdateRows,
|
|
393
|
+
rowHeight = 53,
|
|
373
394
|
selectable = true,
|
|
374
395
|
selectedColor = "#edf4fb",
|
|
375
396
|
width,
|
|
@@ -433,6 +454,9 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
433
454
|
}
|
|
434
455
|
}
|
|
435
456
|
|
|
457
|
+
// Init handler
|
|
458
|
+
const initHandler = useGridCacheInitLoad<T>(cacheKey, cacheMinutes);
|
|
459
|
+
|
|
436
460
|
const refs = React.useRef<{ ref?: ScrollerGridForwardRef<T> }>({});
|
|
437
461
|
|
|
438
462
|
const mRefLocal = useCombinedRefs(mRef, (ref: ScrollerGridForwardRef<T>) => {
|
|
@@ -501,107 +525,6 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
501
525
|
});
|
|
502
526
|
};
|
|
503
527
|
|
|
504
|
-
/**
|
|
505
|
-
* Item renderer
|
|
506
|
-
*/
|
|
507
|
-
const itemRenderer = ({
|
|
508
|
-
columnIndex,
|
|
509
|
-
rowIndex,
|
|
510
|
-
style,
|
|
511
|
-
data,
|
|
512
|
-
selectedItems,
|
|
513
|
-
setItems
|
|
514
|
-
}: ScrollerGridItemRendererProps<T>) => {
|
|
515
|
-
// Column
|
|
516
|
-
const {
|
|
517
|
-
align,
|
|
518
|
-
cellRenderer = DataGridRenderers.defaultCellRenderer,
|
|
519
|
-
cellBoxStyle,
|
|
520
|
-
field,
|
|
521
|
-
type,
|
|
522
|
-
valueFormatter,
|
|
523
|
-
renderProps
|
|
524
|
-
} = columns[columnIndex];
|
|
525
|
-
|
|
526
|
-
// Props
|
|
527
|
-
const formatProps: GridCellFormatterProps<T> = {
|
|
528
|
-
data,
|
|
529
|
-
field,
|
|
530
|
-
rowIndex,
|
|
531
|
-
columnIndex
|
|
532
|
-
};
|
|
533
|
-
|
|
534
|
-
let rowClass = `DataGridEx-Cell${rowIndex % 2}`;
|
|
535
|
-
if (
|
|
536
|
-
borderRowsCount != null &&
|
|
537
|
-
borderRowsCount > 0 &&
|
|
538
|
-
(rowIndex + 1) % borderRowsCount === 0
|
|
539
|
-
) {
|
|
540
|
-
rowClass += ` DataGridEx-Cell-Border`;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// Selected
|
|
544
|
-
const selected =
|
|
545
|
-
data != null &&
|
|
546
|
-
(selectedRowIndex.current === rowIndex ||
|
|
547
|
-
selectedItems.some(
|
|
548
|
-
(selectedItem) =>
|
|
549
|
-
selectedItem != null && selectedItem[idField] === data[idField]
|
|
550
|
-
));
|
|
551
|
-
|
|
552
|
-
if (selected) {
|
|
553
|
-
rowClass += ` DataGridEx-Selected`;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// Box style
|
|
557
|
-
const boxStyle =
|
|
558
|
-
data == null || cellBoxStyle == null
|
|
559
|
-
? undefined
|
|
560
|
-
: typeof cellBoxStyle === "function"
|
|
561
|
-
? cellBoxStyle(data)
|
|
562
|
-
: cellBoxStyle;
|
|
563
|
-
|
|
564
|
-
const cellProps: BoxProps = {
|
|
565
|
-
className: "DataGridEx-Cell",
|
|
566
|
-
textAlign: GridAlignGet(align, type),
|
|
567
|
-
sx: { ...boxStyle }
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
const child = cellRenderer({
|
|
571
|
-
data,
|
|
572
|
-
field,
|
|
573
|
-
formattedValue: valueFormatter ? valueFormatter(formatProps) : undefined,
|
|
574
|
-
selected,
|
|
575
|
-
type,
|
|
576
|
-
rowIndex,
|
|
577
|
-
columnIndex,
|
|
578
|
-
cellProps,
|
|
579
|
-
renderProps:
|
|
580
|
-
typeof renderProps === "function" ? renderProps(data) : renderProps,
|
|
581
|
-
setItems
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
return (
|
|
585
|
-
<div
|
|
586
|
-
className={rowClass}
|
|
587
|
-
style={style}
|
|
588
|
-
data-row={rowIndex}
|
|
589
|
-
data-column={columnIndex}
|
|
590
|
-
onMouseDown={selectable && !checkable ? handleMouseDown : undefined}
|
|
591
|
-
onMouseOver={selectable ? handleMouseOver : undefined}
|
|
592
|
-
onMouseOut={selectable ? handleMouseOut : undefined}
|
|
593
|
-
onClick={(event) => onClick && data != null && onClick(event, data)}
|
|
594
|
-
onDoubleClick={(event) =>
|
|
595
|
-
onDoubleClick && data != null && onDoubleClick(event, data)
|
|
596
|
-
}
|
|
597
|
-
>
|
|
598
|
-
<Box {...cellProps} onMouseEnter={handleMouseEnter}>
|
|
599
|
-
{child}
|
|
600
|
-
</Box>
|
|
601
|
-
</div>
|
|
602
|
-
);
|
|
603
|
-
};
|
|
604
|
-
|
|
605
528
|
// Column width calculator
|
|
606
529
|
const widthCalculator = React.useMemo(
|
|
607
530
|
() => DataGridExCalColumns(columns),
|
|
@@ -630,6 +553,14 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
630
553
|
[columns, width]
|
|
631
554
|
);
|
|
632
555
|
|
|
556
|
+
const onUpdateRowsHandler = React.useCallback(
|
|
557
|
+
(rows: T[], state: GridLoaderStates<T>) => {
|
|
558
|
+
GridUtils.getUpdateRowsHandler<T>(cacheKey)?.(rows, state);
|
|
559
|
+
onUpdateRows?.(rows, state);
|
|
560
|
+
},
|
|
561
|
+
[onUpdateRows, cacheKey]
|
|
562
|
+
);
|
|
563
|
+
|
|
633
564
|
// Table
|
|
634
565
|
const table = React.useMemo(() => {
|
|
635
566
|
return (
|
|
@@ -640,19 +571,134 @@ export function DataGridEx<T extends object>(props: DataGridExProps<T>) {
|
|
|
640
571
|
className,
|
|
641
572
|
createGridStyle(alternatingColors, selectedColor, hoverColor)
|
|
642
573
|
)}
|
|
574
|
+
onCellsRendered={
|
|
575
|
+
cacheKey
|
|
576
|
+
? (visibleCells) =>
|
|
577
|
+
sessionStorage.setItem(
|
|
578
|
+
`${cacheKey}-scroll`,
|
|
579
|
+
JSON.stringify(visibleCells)
|
|
580
|
+
)
|
|
581
|
+
: undefined
|
|
582
|
+
}
|
|
583
|
+
onInitLoad={initHandler}
|
|
584
|
+
onUpdateRows={onUpdateRowsHandler}
|
|
585
|
+
cellComponent={({ rowIndex, columnIndex, style, rows, states }) => {
|
|
586
|
+
// Column
|
|
587
|
+
const {
|
|
588
|
+
align,
|
|
589
|
+
cellRenderer = DataGridRenderers.defaultCellRenderer,
|
|
590
|
+
cellBoxStyle,
|
|
591
|
+
field,
|
|
592
|
+
type,
|
|
593
|
+
valueFormatter,
|
|
594
|
+
renderProps
|
|
595
|
+
} = columns[columnIndex];
|
|
596
|
+
|
|
597
|
+
// Data
|
|
598
|
+
const data = rows[rowIndex];
|
|
599
|
+
|
|
600
|
+
// Props
|
|
601
|
+
const formatProps: GridCellFormatterProps<T> = {
|
|
602
|
+
data,
|
|
603
|
+
field,
|
|
604
|
+
rowIndex,
|
|
605
|
+
columnIndex
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
let rowClass = `DataGridEx-Cell${rowIndex % 2}`;
|
|
609
|
+
if (
|
|
610
|
+
borderRowsCount != null &&
|
|
611
|
+
borderRowsCount > 0 &&
|
|
612
|
+
(rowIndex + 1) % borderRowsCount === 0
|
|
613
|
+
) {
|
|
614
|
+
rowClass += ` DataGridEx-Cell-Border`;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Selected
|
|
618
|
+
const selected =
|
|
619
|
+
data != null &&
|
|
620
|
+
(selectedRowIndex.current === rowIndex ||
|
|
621
|
+
states.selectedItems.some(
|
|
622
|
+
(selectedItem) =>
|
|
623
|
+
selectedItem != null &&
|
|
624
|
+
selectedItem[idField] === data[idField]
|
|
625
|
+
));
|
|
626
|
+
|
|
627
|
+
if (selected) {
|
|
628
|
+
rowClass += ` DataGridEx-Selected`;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Box style
|
|
632
|
+
const boxStyle =
|
|
633
|
+
data == null || cellBoxStyle == null
|
|
634
|
+
? undefined
|
|
635
|
+
: typeof cellBoxStyle === "function"
|
|
636
|
+
? cellBoxStyle(data)
|
|
637
|
+
: cellBoxStyle;
|
|
638
|
+
|
|
639
|
+
const cellProps: BoxProps = {
|
|
640
|
+
className: "DataGridEx-Cell",
|
|
641
|
+
textAlign: GridAlignGet(align, type),
|
|
642
|
+
sx: { ...boxStyle }
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
const child = cellRenderer({
|
|
646
|
+
data,
|
|
647
|
+
field,
|
|
648
|
+
formattedValue: valueFormatter
|
|
649
|
+
? valueFormatter(formatProps)
|
|
650
|
+
: undefined,
|
|
651
|
+
selected,
|
|
652
|
+
type,
|
|
653
|
+
rowIndex,
|
|
654
|
+
columnIndex,
|
|
655
|
+
cellProps,
|
|
656
|
+
renderProps:
|
|
657
|
+
typeof renderProps === "function"
|
|
658
|
+
? renderProps(data)
|
|
659
|
+
: renderProps,
|
|
660
|
+
triggerChange: () => onDataChange?.(rows, rowIndex, columnIndex)
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
return (
|
|
664
|
+
<div
|
|
665
|
+
className={rowClass}
|
|
666
|
+
style={style}
|
|
667
|
+
data-row={rowIndex}
|
|
668
|
+
data-column={columnIndex}
|
|
669
|
+
onMouseDown={
|
|
670
|
+
selectable && !checkable ? handleMouseDown : undefined
|
|
671
|
+
}
|
|
672
|
+
onMouseOver={selectable ? handleMouseOver : undefined}
|
|
673
|
+
onMouseOut={selectable ? handleMouseOut : undefined}
|
|
674
|
+
onClick={(event) =>
|
|
675
|
+
onClick && data != null && onClick(event, data)
|
|
676
|
+
}
|
|
677
|
+
onDoubleClick={(event) =>
|
|
678
|
+
onDoubleClick && data != null && onDoubleClick(event, data)
|
|
679
|
+
}
|
|
680
|
+
>
|
|
681
|
+
<Box {...cellProps} onMouseEnter={handleMouseEnter}>
|
|
682
|
+
{child}
|
|
683
|
+
</Box>
|
|
684
|
+
</div>
|
|
685
|
+
);
|
|
686
|
+
}}
|
|
643
687
|
columnCount={columns.length}
|
|
644
688
|
columnWidth={columnWidth}
|
|
645
689
|
defaultOrderBy={defaultOrderBy}
|
|
646
690
|
height={
|
|
647
|
-
height
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
691
|
+
typeof height === "number"
|
|
692
|
+
? height -
|
|
693
|
+
headerHeight -
|
|
694
|
+
(hideFooter ? 0 : bottomHeight + 1) -
|
|
695
|
+
scrollbarSize
|
|
696
|
+
: height
|
|
651
697
|
}
|
|
652
698
|
headerRenderer={headerRenderer}
|
|
653
699
|
idField={idField}
|
|
654
|
-
itemRenderer={itemRenderer}
|
|
655
700
|
footerRenderer={hideFooter ? undefined : footerRenderer}
|
|
701
|
+
rowHeight={rowHeight}
|
|
656
702
|
width={Math.max(width ?? 0, widthCalculator.total)}
|
|
657
703
|
mRef={mRefLocal}
|
|
658
704
|
{...rest}
|
package/src/MUUtils.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { QueryRQ } from "@etsoo/appscript";
|
|
2
|
-
import { IdType } from "@etsoo/shared";
|
|
3
1
|
import { GridApiCommunity } from "@mui/x-data-grid/internals";
|
|
4
2
|
|
|
5
3
|
/**
|
|
@@ -33,35 +31,4 @@ export namespace MUUtils {
|
|
|
33
31
|
}
|
|
34
32
|
return items;
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Setup paging keysets
|
|
39
|
-
* @param data Paging data
|
|
40
|
-
* @param lastItem Last item of the query
|
|
41
|
-
* @param idField Id field
|
|
42
|
-
*/
|
|
43
|
-
export function setupPagingKeysets<T, K extends IdType = number>(
|
|
44
|
-
data: QueryRQ<K>,
|
|
45
|
-
lastItem: T | undefined,
|
|
46
|
-
idField: keyof T & string
|
|
47
|
-
) {
|
|
48
|
-
// If the id field is not set for ordering, add it with descending
|
|
49
|
-
if (typeof data.queryPaging === "object") {
|
|
50
|
-
const orderBy = (data.queryPaging.orderBy ??= []);
|
|
51
|
-
const idUpper = idField.toUpperCase();
|
|
52
|
-
if (!orderBy.find((o) => o.field.toUpperCase() === idUpper)) {
|
|
53
|
-
orderBy.push({ field: idField, desc: true, unique: true });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Set the paging keysets
|
|
57
|
-
if (lastItem) {
|
|
58
|
-
const keysets = orderBy.map((o) => Reflect.get(lastItem, o.field));
|
|
59
|
-
data.queryPaging.keysets = keysets;
|
|
60
|
-
} else {
|
|
61
|
-
data.queryPaging.keysets = undefined;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return data;
|
|
66
|
-
}
|
|
67
34
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ListItemReact } from "@etsoo/react";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { MoreFab } from "./MoreFab";
|
|
4
|
-
import { ScrollerListExInnerItemRendererProps } from "./ScrollerListEx";
|
|
5
4
|
import LinearProgress from "@mui/material/LinearProgress";
|
|
6
5
|
import Card from "@mui/material/Card";
|
|
7
6
|
import CardHeader from "@mui/material/CardHeader";
|
|
8
7
|
import CardContent from "@mui/material/CardContent";
|
|
8
|
+
import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Default mobile list item renderer
|
|
@@ -15,7 +15,7 @@ import CardContent from "@mui/material/CardContent";
|
|
|
15
15
|
* @returns Component
|
|
16
16
|
*/
|
|
17
17
|
export function MobileListItemRenderer<T>(
|
|
18
|
-
{ data,
|
|
18
|
+
{ data, margins, style }: ScrollerListExItemRendererProps<T>,
|
|
19
19
|
renderer: (
|
|
20
20
|
data: T
|
|
21
21
|
) => [
|
|
@@ -35,9 +35,9 @@ export function MobileListItemRenderer<T>(
|
|
|
35
35
|
return (
|
|
36
36
|
<Card
|
|
37
37
|
sx={{
|
|
38
|
-
height: itemHeight,
|
|
39
38
|
...margins
|
|
40
39
|
}}
|
|
40
|
+
style={style}
|
|
41
41
|
>
|
|
42
42
|
<CardHeader
|
|
43
43
|
sx={{ paddingBottom: 0.5 }}
|
|
@@ -71,7 +71,7 @@ export function MobileListItemRenderer<T>(
|
|
|
71
71
|
sx={{
|
|
72
72
|
paddingTop: 0,
|
|
73
73
|
paddingBottom:
|
|
74
|
-
cardActions == null ? Reflect.get(margins, "marginBottom") : 0
|
|
74
|
+
cardActions == null ? Reflect.get(margins, "marginBottom") ?? 0 : 0
|
|
75
75
|
}}
|
|
76
76
|
>
|
|
77
77
|
{children}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
GridOnScrollProps,
|
|
4
|
-
ListChildComponentProps,
|
|
5
|
-
ListOnScrollProps,
|
|
6
|
-
VariableSizeGrid
|
|
7
|
-
} from "react-window";
|
|
8
2
|
import {
|
|
9
3
|
GridColumn,
|
|
10
4
|
GridJsonData,
|
|
11
5
|
GridLoadDataProps,
|
|
12
|
-
GridLoaderStates,
|
|
13
6
|
GridMethodRef,
|
|
14
7
|
GridTemplateType,
|
|
15
8
|
ReactUtils,
|
|
16
|
-
ScrollerListRef,
|
|
17
9
|
useCombinedRefs,
|
|
18
10
|
useDimensions,
|
|
19
11
|
useSearchParamsWithCache
|
|
@@ -21,11 +13,7 @@ import {
|
|
|
21
13
|
import { DataGridEx, DataGridExProps } from "./DataGridEx";
|
|
22
14
|
import { MUGlobal } from "./MUGlobal";
|
|
23
15
|
import { PullToRefreshUI } from "./PullToRefreshUI";
|
|
24
|
-
import {
|
|
25
|
-
ScrollerListEx,
|
|
26
|
-
ScrollerListExInnerItemRendererProps,
|
|
27
|
-
ScrollerListExItemSize
|
|
28
|
-
} from "./ScrollerListEx";
|
|
16
|
+
import { ScrollerListEx, ScrollerListExProps } from "./ScrollerListEx";
|
|
29
17
|
import { SearchBar } from "./SearchBar";
|
|
30
18
|
import { Labels } from "./app/Labels";
|
|
31
19
|
import { GridUtils } from "./GridUtils";
|
|
@@ -39,14 +27,7 @@ import Stack from "@mui/material/Stack";
|
|
|
39
27
|
*/
|
|
40
28
|
export type ResponsibleContainerProps<T extends object, F> = Omit<
|
|
41
29
|
DataGridExProps<T>,
|
|
42
|
-
| "
|
|
43
|
-
| "itemKey"
|
|
44
|
-
| "loadData"
|
|
45
|
-
| "mRef"
|
|
46
|
-
| "onScroll"
|
|
47
|
-
| "onItemsRendered"
|
|
48
|
-
| "onInitLoad"
|
|
49
|
-
| "onUpdateRows"
|
|
30
|
+
"height" | "loadData" | "mRef" | "onInitLoad" | "onUpdateRows" | "rowHeight"
|
|
50
31
|
> & {
|
|
51
32
|
/**
|
|
52
33
|
* Height will be deducted
|
|
@@ -94,22 +75,10 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<
|
|
|
94
75
|
*/
|
|
95
76
|
height?: number;
|
|
96
77
|
|
|
97
|
-
/**
|
|
98
|
-
* Inner item renderer
|
|
99
|
-
*/
|
|
100
|
-
innerItemRenderer: (
|
|
101
|
-
props: ScrollerListExInnerItemRendererProps<T>
|
|
102
|
-
) => React.ReactNode;
|
|
103
|
-
|
|
104
78
|
/**
|
|
105
79
|
* Item renderer
|
|
106
80
|
*/
|
|
107
|
-
itemRenderer?:
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Item size, a function indicates its a variable size list
|
|
111
|
-
*/
|
|
112
|
-
itemSize: ScrollerListExItemSize;
|
|
81
|
+
itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
|
|
113
82
|
|
|
114
83
|
/**
|
|
115
84
|
* Load data callback
|
|
@@ -122,7 +91,7 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<
|
|
|
122
91
|
/**
|
|
123
92
|
* Methods
|
|
124
93
|
*/
|
|
125
|
-
mRef?: React.
|
|
94
|
+
mRef?: React.RefObject<GridMethodRef<T> | undefined>;
|
|
126
95
|
|
|
127
96
|
/**
|
|
128
97
|
* Element ready callback
|
|
@@ -144,6 +113,19 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<
|
|
|
144
113
|
*/
|
|
145
114
|
quickAction?: (data: T) => void;
|
|
146
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Row height
|
|
118
|
+
* @param isGrid Is displaying as DataGrid
|
|
119
|
+
*/
|
|
120
|
+
rowHeight?:
|
|
121
|
+
| number
|
|
122
|
+
| [number, number]
|
|
123
|
+
| (<B extends boolean>(
|
|
124
|
+
isGrid: B
|
|
125
|
+
) => B extends true
|
|
126
|
+
? DataGridExProps<T>["rowHeight"]
|
|
127
|
+
: ScrollerListExProps<T>["rowHeight"]);
|
|
128
|
+
|
|
147
129
|
/**
|
|
148
130
|
* Size ready to read miliseconds span
|
|
149
131
|
*/
|
|
@@ -211,6 +193,7 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
211
193
|
paddings = MUGlobal.pagePaddings,
|
|
212
194
|
pullToRefresh = true,
|
|
213
195
|
quickAction,
|
|
196
|
+
rowHeight,
|
|
214
197
|
sizeReadyMiliseconds = 0,
|
|
215
198
|
searchBarHeight = 45.6,
|
|
216
199
|
searchBarBottom = 8,
|
|
@@ -228,6 +211,8 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
228
211
|
const mRefs = useCombinedRefs(mRef, (ref: GridMethodRef<T>) => {
|
|
229
212
|
if (ref == null) return;
|
|
230
213
|
state.ref = ref;
|
|
214
|
+
|
|
215
|
+
if (ref.element && elementReady) elementReady(ref.element, true);
|
|
231
216
|
});
|
|
232
217
|
|
|
233
218
|
// Screen size detection
|
|
@@ -252,6 +237,17 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
252
237
|
);
|
|
253
238
|
};
|
|
254
239
|
|
|
240
|
+
const getRowHeight = React.useCallback(
|
|
241
|
+
<B extends boolean>(isGrid: B) => {
|
|
242
|
+
if (rowHeight == null) return undefined;
|
|
243
|
+
else if (typeof rowHeight === "number")
|
|
244
|
+
return isGrid ? undefined : rowHeight;
|
|
245
|
+
else if (Array.isArray(rowHeight)) return rowHeight[isGrid ? 0 : 1];
|
|
246
|
+
else return rowHeight<B>(isGrid);
|
|
247
|
+
},
|
|
248
|
+
[rowHeight]
|
|
249
|
+
);
|
|
250
|
+
|
|
255
251
|
// Search data
|
|
256
252
|
const searchData = useSearchParamsWithCache(cacheKey);
|
|
257
253
|
|
|
@@ -289,57 +285,6 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
289
285
|
}
|
|
290
286
|
);
|
|
291
287
|
|
|
292
|
-
const onInitLoad = (
|
|
293
|
-
ref: VariableSizeGrid<T> | ScrollerListRef
|
|
294
|
-
): [T[], Partial<GridLoaderStates<T>>?] | null | undefined => {
|
|
295
|
-
// Avoid repeatedly load from cache
|
|
296
|
-
if (refs.current.initLoaded || !cacheKey) return undefined;
|
|
297
|
-
|
|
298
|
-
// Cache data
|
|
299
|
-
const cacheData = GridUtils.getCacheData<T>(cacheKey, cacheMinutes);
|
|
300
|
-
if (cacheData) {
|
|
301
|
-
const { rows, state } = cacheData;
|
|
302
|
-
|
|
303
|
-
GridUtils.mergeSearchData(state, searchData);
|
|
304
|
-
|
|
305
|
-
// Scroll position
|
|
306
|
-
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
307
|
-
if (scrollData) {
|
|
308
|
-
if ("resetAfterColumnIndex" in ref) {
|
|
309
|
-
const { scrollLeft, scrollTop } = JSON.parse(
|
|
310
|
-
scrollData
|
|
311
|
-
) as GridOnScrollProps;
|
|
312
|
-
|
|
313
|
-
globalThis.setTimeout(
|
|
314
|
-
() => ref.scrollTo({ scrollLeft, scrollTop }),
|
|
315
|
-
0
|
|
316
|
-
);
|
|
317
|
-
} else {
|
|
318
|
-
const { scrollOffset } = JSON.parse(scrollData) as ListOnScrollProps;
|
|
319
|
-
|
|
320
|
-
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Update flag value
|
|
325
|
-
refs.current.initLoaded = true;
|
|
326
|
-
|
|
327
|
-
// Return cached rows and state
|
|
328
|
-
return [rows, state];
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return undefined;
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const onListScroll = (props: ListOnScrollProps) => {
|
|
335
|
-
if (!cacheKey || !refs.current.initLoaded) return;
|
|
336
|
-
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
337
|
-
};
|
|
338
|
-
const onGridScroll = (props: GridOnScrollProps) => {
|
|
339
|
-
if (!cacheKey || !refs.current.initLoaded) return;
|
|
340
|
-
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
341
|
-
};
|
|
342
|
-
|
|
343
288
|
// Rect
|
|
344
289
|
const rect = dimensions[0][2];
|
|
345
290
|
|
|
@@ -372,8 +317,8 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
372
317
|
heightLocal = adjustFabHeight(heightLocal, showDataGrid);
|
|
373
318
|
|
|
374
319
|
if (showDataGrid) {
|
|
375
|
-
//
|
|
376
|
-
|
|
320
|
+
// Remove useless props
|
|
321
|
+
const { itemRenderer, ...gridProps } = rest;
|
|
377
322
|
|
|
378
323
|
return (
|
|
379
324
|
<Box className="DataGridBox">
|
|
@@ -384,28 +329,27 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
384
329
|
loadData={localLoadData}
|
|
385
330
|
mRef={mRefs}
|
|
386
331
|
onDoubleClick={(_, data) => quickAction && quickAction(data)}
|
|
387
|
-
outerRef={(element?: HTMLDivElement) => {
|
|
388
|
-
if (element != null && elementReady) elementReady(element, true);
|
|
389
|
-
}}
|
|
390
|
-
onScroll={onGridScroll}
|
|
391
332
|
columns={columns}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
{...rest}
|
|
333
|
+
rowHeight={getRowHeight(true)}
|
|
334
|
+
{...gridProps}
|
|
395
335
|
/>
|
|
396
336
|
</Box>
|
|
397
337
|
);
|
|
398
338
|
}
|
|
399
339
|
|
|
400
|
-
//
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
340
|
+
// Remove useless props
|
|
341
|
+
const {
|
|
342
|
+
checkable,
|
|
343
|
+
borderRowsCount,
|
|
344
|
+
bottomHeight,
|
|
345
|
+
footerItemRenderer,
|
|
346
|
+
headerHeight,
|
|
347
|
+
hideFooter,
|
|
348
|
+
hoverColor,
|
|
349
|
+
selectable,
|
|
350
|
+
onCellsRendered,
|
|
351
|
+
...listProps
|
|
352
|
+
} = rest;
|
|
409
353
|
|
|
410
354
|
return (
|
|
411
355
|
<Box className="ListBox" sx={{ height: heightLocal }}>
|
|
@@ -413,17 +357,12 @@ export function ResponsibleContainer<T extends object, F>(
|
|
|
413
357
|
autoLoad={!hasFields}
|
|
414
358
|
height={heightLocal}
|
|
415
359
|
loadData={localLoadData}
|
|
416
|
-
onUpdateRows={GridUtils.getUpdateRowsHandler<T>(cacheKey)}
|
|
417
|
-
onInitLoad={onInitLoad}
|
|
418
360
|
mRef={mRefs}
|
|
419
361
|
onClick={(event, data) =>
|
|
420
362
|
quickAction && ReactUtils.isSafeClick(event) && quickAction(data)
|
|
421
363
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}}
|
|
425
|
-
onScroll={onListScroll}
|
|
426
|
-
{...rest}
|
|
364
|
+
rowHeight={getRowHeight(false)}
|
|
365
|
+
{...listProps}
|
|
427
366
|
/>
|
|
428
367
|
</Box>
|
|
429
368
|
);
|