@etsoo/react 1.4.35 → 1.4.39
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/lib/mu/MUGlobal.d.ts +16 -2
- package/lib/mu/MUGlobal.js +42 -3
- package/lib/mu/MobileListItemRenderer.d.ts +1 -1
- package/lib/mu/MobileListItemRenderer.js +6 -10
- package/lib/mu/ResponsibleContainer.d.ts +2 -2
- package/lib/mu/ScrollerListEx.d.ts +20 -1
- package/lib/mu/ScrollerListEx.js +67 -6
- package/lib/mu/pages/ResponsivePageProps.d.ts +2 -2
- package/package.json +1 -1
- package/src/mu/MUGlobal.ts +50 -4
- package/src/mu/MobileListItemRenderer.tsx +10 -13
- package/src/mu/ResponsibleContainer.tsx +3 -2
- package/src/mu/ScrollerListEx.tsx +117 -8
- package/src/mu/pages/ResponsivePageProps.ts +5 -2
package/lib/mu/MUGlobal.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Theme } from '@mui/material';
|
|
1
2
|
export declare class MUGlobal {
|
|
2
3
|
/**
|
|
3
4
|
* Search field shrink
|
|
@@ -40,14 +41,20 @@ export declare class MUGlobal {
|
|
|
40
41
|
* @returns Updated object
|
|
41
42
|
*/
|
|
42
43
|
static half(input: {}): {};
|
|
44
|
+
/**
|
|
45
|
+
* Reverse object number properties, like 5 to -5
|
|
46
|
+
* @param input Input object
|
|
47
|
+
* @returns Updated object
|
|
48
|
+
*/
|
|
49
|
+
static reverse(input: {}): {};
|
|
43
50
|
/**
|
|
44
51
|
* Update object number properties with adjustment
|
|
45
52
|
* @param input Input object
|
|
46
|
-
* @param adjust Adjust value
|
|
53
|
+
* @param adjust Adjust value or new size object
|
|
47
54
|
* @param field Specific field
|
|
48
55
|
* @returns Updated object
|
|
49
56
|
*/
|
|
50
|
-
static increase(input: {}, adjust: number, field?: string): {};
|
|
57
|
+
static increase(input: {}, adjust: number | {}, field?: string): {};
|
|
51
58
|
/**
|
|
52
59
|
* Adjust size with theme update
|
|
53
60
|
* @param size Base size
|
|
@@ -56,6 +63,13 @@ export declare class MUGlobal {
|
|
|
56
63
|
* @returns Updated object
|
|
57
64
|
*/
|
|
58
65
|
static adjustWithTheme(size: number, adjust: {}, updateFunc: (value: number) => string): {};
|
|
66
|
+
/**
|
|
67
|
+
* Get multple medias theme space
|
|
68
|
+
* @param spaces Spaces
|
|
69
|
+
* @param theme Theme
|
|
70
|
+
* @returns Result
|
|
71
|
+
*/
|
|
72
|
+
static getSpace(spaces: {}, theme: Theme): number;
|
|
59
73
|
/**
|
|
60
74
|
* Update object number properties with theme
|
|
61
75
|
* @param input Input object
|
package/lib/mu/MUGlobal.js
CHANGED
|
@@ -14,10 +14,24 @@ export class MUGlobal {
|
|
|
14
14
|
});
|
|
15
15
|
return newObj;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Reverse object number properties, like 5 to -5
|
|
19
|
+
* @param input Input object
|
|
20
|
+
* @returns Updated object
|
|
21
|
+
*/
|
|
22
|
+
static reverse(input) {
|
|
23
|
+
const newObj = { ...input };
|
|
24
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
25
|
+
if (typeof value === 'number') {
|
|
26
|
+
Reflect.set(newObj, key, -value);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return newObj;
|
|
30
|
+
}
|
|
17
31
|
/**
|
|
18
32
|
* Update object number properties with adjustment
|
|
19
33
|
* @param input Input object
|
|
20
|
-
* @param adjust Adjust value
|
|
34
|
+
* @param adjust Adjust value or new size object
|
|
21
35
|
* @param field Specific field
|
|
22
36
|
* @returns Updated object
|
|
23
37
|
*/
|
|
@@ -25,8 +39,14 @@ export class MUGlobal {
|
|
|
25
39
|
const newObj = { ...input };
|
|
26
40
|
Object.entries(newObj).forEach(([key, value]) => {
|
|
27
41
|
if (typeof value === 'number') {
|
|
28
|
-
if (field == null || field === key)
|
|
29
|
-
|
|
42
|
+
if (field == null || field === key) {
|
|
43
|
+
const adjustValue = typeof adjust === 'number'
|
|
44
|
+
? adjust
|
|
45
|
+
: Reflect.get(adjust, key);
|
|
46
|
+
if (adjustValue == null || typeof adjustValue !== 'number')
|
|
47
|
+
return;
|
|
48
|
+
Reflect.set(newObj, key, value + adjustValue);
|
|
49
|
+
}
|
|
30
50
|
}
|
|
31
51
|
});
|
|
32
52
|
return newObj;
|
|
@@ -50,6 +70,25 @@ export class MUGlobal {
|
|
|
50
70
|
});
|
|
51
71
|
return newObj;
|
|
52
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Get multple medias theme space
|
|
75
|
+
* @param spaces Spaces
|
|
76
|
+
* @param theme Theme
|
|
77
|
+
* @returns Result
|
|
78
|
+
*/
|
|
79
|
+
static getSpace(spaces, theme) {
|
|
80
|
+
for (const [key, value] of Object.entries(spaces)) {
|
|
81
|
+
if (typeof value === 'number' &&
|
|
82
|
+
theme.breakpoints.keys.findIndex((bk) => bk === key) != -1) {
|
|
83
|
+
const mediaRaw = theme.breakpoints.up(key);
|
|
84
|
+
const mediaQuery = mediaRaw.substring(mediaRaw.indexOf('('));
|
|
85
|
+
if (window.matchMedia(mediaQuery).matches) {
|
|
86
|
+
return parseInt(theme.spacing(value), 10);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
53
92
|
/**
|
|
54
93
|
* Update object number properties with theme
|
|
55
94
|
* @param input Input object
|
|
@@ -8,7 +8,7 @@ import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
|
|
|
8
8
|
* @param renderer Renderer for card content
|
|
9
9
|
* @returns Component
|
|
10
10
|
*/
|
|
11
|
-
export declare function MobileListItemRenderer<T>({ data, itemHeight }: ScrollerListExInnerItemRendererProps<T>,
|
|
11
|
+
export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }: ScrollerListExInnerItemRendererProps<T>, renderer: (data: T) => [
|
|
12
12
|
string,
|
|
13
13
|
string | undefined,
|
|
14
14
|
React.ReactNode | (ListItemReact | boolean)[],
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Card, CardContent, CardHeader, LinearProgress } from '@mui/material';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { MoreFab } from './MoreFab';
|
|
4
|
-
import { MUGlobal } from './MUGlobal';
|
|
5
4
|
function getActions(input) {
|
|
6
5
|
// Actions
|
|
7
6
|
const actions = [];
|
|
@@ -19,20 +18,15 @@ function getActions(input) {
|
|
|
19
18
|
* @param renderer Renderer for card content
|
|
20
19
|
* @returns Component
|
|
21
20
|
*/
|
|
22
|
-
export function MobileListItemRenderer({ data, itemHeight },
|
|
21
|
+
export function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
|
|
23
22
|
// Loading
|
|
24
23
|
if (data == null)
|
|
25
24
|
return React.createElement(LinearProgress, null);
|
|
26
25
|
// Elements
|
|
27
26
|
const [title, subheader, actions, children] = renderer(data);
|
|
28
|
-
// Half
|
|
29
|
-
const halfMargin = MUGlobal.half(margin);
|
|
30
27
|
return (React.createElement(Card, { sx: {
|
|
31
|
-
height:
|
|
32
|
-
|
|
33
|
-
marginRight: margin,
|
|
34
|
-
marginTop: halfMargin,
|
|
35
|
-
marginBottom: halfMargin
|
|
28
|
+
height: itemHeight,
|
|
29
|
+
...margins
|
|
36
30
|
} },
|
|
37
31
|
React.createElement(CardHeader, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? (React.createElement(MoreFab, { iconButton: true, size: "small", anchorOrigin: {
|
|
38
32
|
vertical: 'bottom',
|
|
@@ -66,5 +60,7 @@ export function MobileListItemRenderer({ data, itemHeight }, margin, renderer) {
|
|
|
66
60
|
}
|
|
67
61
|
}
|
|
68
62
|
} })) : (actions), title: title, titleTypographyProps: { variant: 'body2' }, subheader: subheader, subheaderTypographyProps: { variant: 'caption' } }),
|
|
69
|
-
React.createElement(CardContent, { sx: {
|
|
63
|
+
React.createElement(CardContent, { sx: {
|
|
64
|
+
paddingTop: 0
|
|
65
|
+
} }, children)));
|
|
70
66
|
}
|
|
@@ -6,7 +6,7 @@ import { GridColumn } from '../components/GridColumn';
|
|
|
6
6
|
import { GridJsonData } from '../components/GridLoader';
|
|
7
7
|
import { DataGridExProps } from './DataGridEx';
|
|
8
8
|
import { GridMethodRef } from './GridMethodRef';
|
|
9
|
-
import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
|
|
9
|
+
import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from './ScrollerListEx';
|
|
10
10
|
/**
|
|
11
11
|
* ResponsibleContainer props
|
|
12
12
|
*/
|
|
@@ -51,7 +51,7 @@ export interface ResponsibleContainerProps<T extends {}, F extends DataTypes.Bas
|
|
|
51
51
|
/**
|
|
52
52
|
* Item size, a function indicates its a variable size list
|
|
53
53
|
*/
|
|
54
|
-
itemSize:
|
|
54
|
+
itemSize: ScrollerListExItemSize;
|
|
55
55
|
/**
|
|
56
56
|
* Load data callback
|
|
57
57
|
*/
|
|
@@ -13,11 +13,26 @@ export interface ScrollerListExInnerItemRendererProps<T> extends ListChildCompon
|
|
|
13
13
|
* Item height
|
|
14
14
|
*/
|
|
15
15
|
itemHeight: number;
|
|
16
|
+
/**
|
|
17
|
+
* Item space
|
|
18
|
+
*/
|
|
19
|
+
space: number;
|
|
20
|
+
/**
|
|
21
|
+
* Default margins
|
|
22
|
+
*/
|
|
23
|
+
margins: {};
|
|
16
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Extended ScrollerList ItemSize type
|
|
27
|
+
* 1. Callback function
|
|
28
|
+
* 2. Static sets
|
|
29
|
+
* 3. Dynamic calculation
|
|
30
|
+
*/
|
|
31
|
+
export declare type ScrollerListExItemSize = ((index: number) => [number, number] | [number, number, {}]) | [number, number] | [number, {}, boolean?];
|
|
17
32
|
/**
|
|
18
33
|
* Extended ScrollerList Props
|
|
19
34
|
*/
|
|
20
|
-
export interface ScrollerListExProps<T> extends Omit<ScrollerListProps<T>, 'itemRenderer'> {
|
|
35
|
+
export interface ScrollerListExProps<T> extends Omit<ScrollerListProps<T>, 'itemRenderer' | 'itemSize'> {
|
|
21
36
|
/**
|
|
22
37
|
* Alternating colors for odd/even rows
|
|
23
38
|
*/
|
|
@@ -34,6 +49,10 @@ export interface ScrollerListExProps<T> extends Omit<ScrollerListProps<T>, 'item
|
|
|
34
49
|
* Item renderer
|
|
35
50
|
*/
|
|
36
51
|
itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
|
|
52
|
+
/**
|
|
53
|
+
* Item size, a function indicates its a variable size list
|
|
54
|
+
*/
|
|
55
|
+
itemSize: ScrollerListExItemSize;
|
|
37
56
|
/**
|
|
38
57
|
* On items select change
|
|
39
58
|
*/
|
package/lib/mu/ScrollerListEx.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { css } from '@emotion/css';
|
|
2
2
|
import { DataTypes, Utils } from '@etsoo/shared';
|
|
3
|
+
import { useTheme } from '@mui/material';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { ScrollerList } from '../components/ScrollerList';
|
|
6
|
+
import { MUGlobal } from './MUGlobal';
|
|
5
7
|
// Scroll bar size
|
|
6
8
|
const scrollbarSize = 16;
|
|
7
9
|
// Selected class name
|
|
@@ -36,15 +38,44 @@ const createGridStyle = (alternatingColors, selectedColor) => {
|
|
|
36
38
|
}
|
|
37
39
|
});
|
|
38
40
|
};
|
|
41
|
+
// Default margin
|
|
42
|
+
const defaultMargin = (margin, isNarrow) => {
|
|
43
|
+
const half = MUGlobal.half(margin);
|
|
44
|
+
if (isNarrow == null) {
|
|
45
|
+
const half = MUGlobal.half(margin);
|
|
46
|
+
return {
|
|
47
|
+
marginLeft: margin,
|
|
48
|
+
marginRight: margin,
|
|
49
|
+
marginTop: half,
|
|
50
|
+
marginBottom: half
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (isNarrow) {
|
|
54
|
+
return {
|
|
55
|
+
marginLeft: 0,
|
|
56
|
+
marginRight: 0,
|
|
57
|
+
marginTop: half,
|
|
58
|
+
marginBottom: half
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
marginLeft: half,
|
|
63
|
+
marginRight: half,
|
|
64
|
+
marginTop: half,
|
|
65
|
+
marginBottom: half
|
|
66
|
+
};
|
|
67
|
+
};
|
|
39
68
|
// Default itemRenderer
|
|
40
|
-
function defaultItemRenderer({ index, innerItemRenderer, data, onMouseDown, selected, style, itemHeight }) {
|
|
69
|
+
function defaultItemRenderer({ index, innerItemRenderer, data, onMouseDown, selected, style, itemHeight, space, margins }) {
|
|
41
70
|
// Child
|
|
42
71
|
const child = innerItemRenderer({
|
|
43
72
|
index,
|
|
44
73
|
data,
|
|
45
74
|
style,
|
|
46
75
|
selected,
|
|
47
|
-
itemHeight
|
|
76
|
+
itemHeight,
|
|
77
|
+
space,
|
|
78
|
+
margins
|
|
48
79
|
});
|
|
49
80
|
let rowClass = `ScrollerListEx-Row${index % 2}`;
|
|
50
81
|
if (selected)
|
|
@@ -80,19 +111,49 @@ export function ScrollerListEx(props) {
|
|
|
80
111
|
: false;
|
|
81
112
|
return selected;
|
|
82
113
|
};
|
|
114
|
+
// Theme
|
|
115
|
+
const theme = useTheme();
|
|
116
|
+
// Calculate size
|
|
117
|
+
const calculateItemSize = (index) => {
|
|
118
|
+
// Callback function
|
|
119
|
+
if (typeof itemSize === 'function') {
|
|
120
|
+
const result = itemSize(index);
|
|
121
|
+
if (result.length == 2)
|
|
122
|
+
return [...result, defaultMargin(MUGlobal.pagePaddings)];
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
// Calculation
|
|
126
|
+
const [size, spaces, isNarrow] = itemSize;
|
|
127
|
+
if (typeof spaces === 'number')
|
|
128
|
+
return [
|
|
129
|
+
size,
|
|
130
|
+
spaces,
|
|
131
|
+
defaultMargin(MUGlobal.pagePaddings, undefined)
|
|
132
|
+
];
|
|
133
|
+
return [
|
|
134
|
+
size,
|
|
135
|
+
MUGlobal.getSpace(spaces, theme),
|
|
136
|
+
defaultMargin(spaces, isNarrow)
|
|
137
|
+
];
|
|
138
|
+
};
|
|
139
|
+
// Local item size
|
|
140
|
+
const itemSizeLocal = (index) => {
|
|
141
|
+
const [size, space] = calculateItemSize(index);
|
|
142
|
+
return size + space;
|
|
143
|
+
};
|
|
83
144
|
// Destruct
|
|
84
145
|
const { alternatingColors = [undefined, undefined], className, idField = 'id', innerItemRenderer, itemSize, itemKey = (index, data) => { var _a; return (_a = DataTypes.getIdValue(data, idField)) !== null && _a !== void 0 ? _a : index; }, itemRenderer = (itemProps) => {
|
|
85
|
-
const itemHeight
|
|
86
|
-
? itemSize(itemProps.index)
|
|
87
|
-
: itemSize;
|
|
146
|
+
const [itemHeight, space, margins] = calculateItemSize(itemProps.index);
|
|
88
147
|
return defaultItemRenderer({
|
|
89
148
|
itemHeight,
|
|
90
149
|
innerItemRenderer,
|
|
91
150
|
onMouseDown,
|
|
151
|
+
space,
|
|
152
|
+
margins,
|
|
92
153
|
selected: isSelected(itemProps.data),
|
|
93
154
|
...itemProps
|
|
94
155
|
});
|
|
95
156
|
}, onSelectChange, selectedColor = '#edf4fb', ...rest } = props;
|
|
96
157
|
// Layout
|
|
97
|
-
return (React.createElement(ScrollerList, { className: Utils.mergeClasses('ScrollerListEx-Body', className, createGridStyle(alternatingColors, selectedColor)), itemKey: itemKey, itemRenderer: itemRenderer, itemSize:
|
|
158
|
+
return (React.createElement(ScrollerList, { className: Utils.mergeClasses('ScrollerListEx-Body', className, createGridStyle(alternatingColors, selectedColor)), itemKey: itemKey, itemRenderer: itemRenderer, itemSize: itemSizeLocal, ...rest }));
|
|
98
159
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { DataTypes } from '@etsoo/shared';
|
|
3
3
|
import { ListChildComponentProps } from 'react-window';
|
|
4
4
|
import { GridMethodRef } from '../GridMethodRef';
|
|
5
|
-
import { ScrollerListExInnerItemRendererProps } from '../ScrollerListEx';
|
|
5
|
+
import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from '../ScrollerListEx';
|
|
6
6
|
import { DataGridPageProps } from './DataGridPageProps';
|
|
7
7
|
/**
|
|
8
8
|
* Response page props
|
|
@@ -23,7 +23,7 @@ export interface ResponsePageProps<T, F extends DataTypes.BasicTemplate> extends
|
|
|
23
23
|
/**
|
|
24
24
|
* Item size, a function indicates its a variable size list
|
|
25
25
|
*/
|
|
26
|
-
itemSize:
|
|
26
|
+
itemSize: ScrollerListExItemSize;
|
|
27
27
|
/**
|
|
28
28
|
* Methods
|
|
29
29
|
*/
|
package/package.json
CHANGED
package/src/mu/MUGlobal.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NumberUtils } from '@etsoo/shared';
|
|
2
|
+
import { Breakpoint, Theme } from '@mui/material';
|
|
2
3
|
|
|
3
4
|
export class MUGlobal {
|
|
4
5
|
/**
|
|
@@ -56,19 +57,42 @@ export class MUGlobal {
|
|
|
56
57
|
return newObj;
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Reverse object number properties, like 5 to -5
|
|
62
|
+
* @param input Input object
|
|
63
|
+
* @returns Updated object
|
|
64
|
+
*/
|
|
65
|
+
static reverse(input: {}) {
|
|
66
|
+
const newObj = { ...input };
|
|
67
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
68
|
+
if (typeof value === 'number') {
|
|
69
|
+
Reflect.set(newObj, key, -value);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return newObj;
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
/**
|
|
60
76
|
* Update object number properties with adjustment
|
|
61
77
|
* @param input Input object
|
|
62
|
-
* @param adjust Adjust value
|
|
78
|
+
* @param adjust Adjust value or new size object
|
|
63
79
|
* @param field Specific field
|
|
64
80
|
* @returns Updated object
|
|
65
81
|
*/
|
|
66
|
-
static increase(input: {}, adjust: number, field?: string) {
|
|
82
|
+
static increase(input: {}, adjust: number | {}, field?: string) {
|
|
67
83
|
const newObj = { ...input };
|
|
68
84
|
Object.entries(newObj).forEach(([key, value]) => {
|
|
69
85
|
if (typeof value === 'number') {
|
|
70
|
-
if (field == null || field === key)
|
|
71
|
-
|
|
86
|
+
if (field == null || field === key) {
|
|
87
|
+
const adjustValue =
|
|
88
|
+
typeof adjust === 'number'
|
|
89
|
+
? adjust
|
|
90
|
+
: Reflect.get(adjust, key);
|
|
91
|
+
if (adjustValue == null || typeof adjustValue !== 'number')
|
|
92
|
+
return;
|
|
93
|
+
|
|
94
|
+
Reflect.set(newObj, key, value + adjustValue);
|
|
95
|
+
}
|
|
72
96
|
}
|
|
73
97
|
});
|
|
74
98
|
return newObj;
|
|
@@ -102,6 +126,28 @@ export class MUGlobal {
|
|
|
102
126
|
return newObj;
|
|
103
127
|
}
|
|
104
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Get multple medias theme space
|
|
131
|
+
* @param spaces Spaces
|
|
132
|
+
* @param theme Theme
|
|
133
|
+
* @returns Result
|
|
134
|
+
*/
|
|
135
|
+
static getSpace(spaces: {}, theme: Theme) {
|
|
136
|
+
for (const [key, value] of Object.entries(spaces)) {
|
|
137
|
+
if (
|
|
138
|
+
typeof value === 'number' &&
|
|
139
|
+
theme.breakpoints.keys.findIndex((bk) => bk === key) != -1
|
|
140
|
+
) {
|
|
141
|
+
const mediaRaw = theme.breakpoints.up(key as Breakpoint);
|
|
142
|
+
const mediaQuery = mediaRaw.substring(mediaRaw.indexOf('('));
|
|
143
|
+
if (window.matchMedia(mediaQuery).matches) {
|
|
144
|
+
return parseInt(theme.spacing(value), 10);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
105
151
|
/**
|
|
106
152
|
* Update object number properties with theme
|
|
107
153
|
* @param input Input object
|
|
@@ -2,7 +2,6 @@ import { Card, CardContent, CardHeader, LinearProgress } from '@mui/material';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { ListItemReact } from '../components/ListItemReact';
|
|
4
4
|
import { MoreFab } from './MoreFab';
|
|
5
|
-
import { MUGlobal } from './MUGlobal';
|
|
6
5
|
import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
|
|
7
6
|
|
|
8
7
|
function getActions(input: (ListItemReact | boolean)[]): ListItemReact[] {
|
|
@@ -23,8 +22,7 @@ function getActions(input: (ListItemReact | boolean)[]): ListItemReact[] {
|
|
|
23
22
|
* @returns Component
|
|
24
23
|
*/
|
|
25
24
|
export function MobileListItemRenderer<T>(
|
|
26
|
-
{ data, itemHeight }: ScrollerListExInnerItemRendererProps<T>,
|
|
27
|
-
margin: {},
|
|
25
|
+
{ data, itemHeight, margins }: ScrollerListExInnerItemRendererProps<T>,
|
|
28
26
|
renderer: (
|
|
29
27
|
data: T
|
|
30
28
|
) => [
|
|
@@ -40,18 +38,11 @@ export function MobileListItemRenderer<T>(
|
|
|
40
38
|
// Elements
|
|
41
39
|
const [title, subheader, actions, children] = renderer(data);
|
|
42
40
|
|
|
43
|
-
// Half
|
|
44
|
-
const halfMargin = MUGlobal.half(margin);
|
|
45
|
-
|
|
46
41
|
return (
|
|
47
42
|
<Card
|
|
48
43
|
sx={{
|
|
49
|
-
height:
|
|
50
|
-
|
|
51
|
-
marginLeft: margin,
|
|
52
|
-
marginRight: margin,
|
|
53
|
-
marginTop: halfMargin,
|
|
54
|
-
marginBottom: halfMargin
|
|
44
|
+
height: itemHeight,
|
|
45
|
+
...margins
|
|
55
46
|
}}
|
|
56
47
|
>
|
|
57
48
|
<CardHeader
|
|
@@ -107,7 +98,13 @@ export function MobileListItemRenderer<T>(
|
|
|
107
98
|
subheader={subheader}
|
|
108
99
|
subheaderTypographyProps={{ variant: 'caption' }}
|
|
109
100
|
/>
|
|
110
|
-
<CardContent
|
|
101
|
+
<CardContent
|
|
102
|
+
sx={{
|
|
103
|
+
paddingTop: 0
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{children}
|
|
107
|
+
</CardContent>
|
|
111
108
|
</Card>
|
|
112
109
|
);
|
|
113
110
|
}
|
|
@@ -21,7 +21,8 @@ import { MUGlobal } from './MUGlobal';
|
|
|
21
21
|
import { PullToRefreshUI } from './PullToRefreshUI';
|
|
22
22
|
import {
|
|
23
23
|
ScrollerListEx,
|
|
24
|
-
ScrollerListExInnerItemRendererProps
|
|
24
|
+
ScrollerListExInnerItemRendererProps,
|
|
25
|
+
ScrollerListExItemSize
|
|
25
26
|
} from './ScrollerListEx';
|
|
26
27
|
import { SearchBar } from './SearchBar';
|
|
27
28
|
|
|
@@ -91,7 +92,7 @@ export interface ResponsibleContainerProps<
|
|
|
91
92
|
/**
|
|
92
93
|
* Item size, a function indicates its a variable size list
|
|
93
94
|
*/
|
|
94
|
-
itemSize:
|
|
95
|
+
itemSize: ScrollerListExItemSize;
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
98
|
* Load data callback
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { css } from '@emotion/css';
|
|
2
2
|
import { DataTypes, Utils } from '@etsoo/shared';
|
|
3
|
+
import { useTheme } from '@mui/material';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { ListChildComponentProps } from 'react-window';
|
|
5
6
|
import { ScrollerList, ScrollerListProps } from '../components/ScrollerList';
|
|
7
|
+
import { MUGlobal } from './MUGlobal';
|
|
6
8
|
|
|
7
9
|
// Scroll bar size
|
|
8
10
|
const scrollbarSize = 16;
|
|
@@ -44,6 +46,37 @@ const createGridStyle = (
|
|
|
44
46
|
});
|
|
45
47
|
};
|
|
46
48
|
|
|
49
|
+
// Default margin
|
|
50
|
+
const defaultMargin = (margin: {}, isNarrow?: boolean) => {
|
|
51
|
+
const half = MUGlobal.half(margin);
|
|
52
|
+
|
|
53
|
+
if (isNarrow == null) {
|
|
54
|
+
const half = MUGlobal.half(margin);
|
|
55
|
+
return {
|
|
56
|
+
marginLeft: margin,
|
|
57
|
+
marginRight: margin,
|
|
58
|
+
marginTop: half,
|
|
59
|
+
marginBottom: half
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (isNarrow) {
|
|
64
|
+
return {
|
|
65
|
+
marginLeft: 0,
|
|
66
|
+
marginRight: 0,
|
|
67
|
+
marginTop: half,
|
|
68
|
+
marginBottom: half
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
marginLeft: half,
|
|
74
|
+
marginRight: half,
|
|
75
|
+
marginTop: half,
|
|
76
|
+
marginBottom: half
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
47
80
|
/**
|
|
48
81
|
* Extended ScrollerList inner item renderer props
|
|
49
82
|
*/
|
|
@@ -58,13 +91,34 @@ export interface ScrollerListExInnerItemRendererProps<T>
|
|
|
58
91
|
* Item height
|
|
59
92
|
*/
|
|
60
93
|
itemHeight: number;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Item space
|
|
97
|
+
*/
|
|
98
|
+
space: number;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Default margins
|
|
102
|
+
*/
|
|
103
|
+
margins: {};
|
|
61
104
|
}
|
|
62
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Extended ScrollerList ItemSize type
|
|
108
|
+
* 1. Callback function
|
|
109
|
+
* 2. Static sets
|
|
110
|
+
* 3. Dynamic calculation
|
|
111
|
+
*/
|
|
112
|
+
export type ScrollerListExItemSize =
|
|
113
|
+
| ((index: number) => [number, number] | [number, number, {}])
|
|
114
|
+
| [number, number]
|
|
115
|
+
| [number, {}, boolean?];
|
|
116
|
+
|
|
63
117
|
/**
|
|
64
118
|
* Extended ScrollerList Props
|
|
65
119
|
*/
|
|
66
120
|
export interface ScrollerListExProps<T>
|
|
67
|
-
extends Omit<ScrollerListProps<T>, 'itemRenderer'> {
|
|
121
|
+
extends Omit<ScrollerListProps<T>, 'itemRenderer' | 'itemSize'> {
|
|
68
122
|
/**
|
|
69
123
|
* Alternating colors for odd/even rows
|
|
70
124
|
*/
|
|
@@ -87,6 +141,11 @@ export interface ScrollerListExProps<T>
|
|
|
87
141
|
*/
|
|
88
142
|
itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
|
|
89
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Item size, a function indicates its a variable size list
|
|
146
|
+
*/
|
|
147
|
+
itemSize: ScrollerListExItemSize;
|
|
148
|
+
|
|
90
149
|
/**
|
|
91
150
|
* On items select change
|
|
92
151
|
*/
|
|
@@ -116,6 +175,16 @@ interface defaultItemRendererProps<T> extends ListChildComponentProps<T> {
|
|
|
116
175
|
*/
|
|
117
176
|
itemHeight: number;
|
|
118
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Item space
|
|
180
|
+
*/
|
|
181
|
+
space: number;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Default margins
|
|
185
|
+
*/
|
|
186
|
+
margins: {};
|
|
187
|
+
|
|
119
188
|
/**
|
|
120
189
|
* Item selected
|
|
121
190
|
*/
|
|
@@ -130,7 +199,9 @@ function defaultItemRenderer<T>({
|
|
|
130
199
|
onMouseDown,
|
|
131
200
|
selected,
|
|
132
201
|
style,
|
|
133
|
-
itemHeight
|
|
202
|
+
itemHeight,
|
|
203
|
+
space,
|
|
204
|
+
margins
|
|
134
205
|
}: defaultItemRendererProps<T>) {
|
|
135
206
|
// Child
|
|
136
207
|
const child = innerItemRenderer({
|
|
@@ -138,7 +209,9 @@ function defaultItemRenderer<T>({
|
|
|
138
209
|
data,
|
|
139
210
|
style,
|
|
140
211
|
selected,
|
|
141
|
-
itemHeight
|
|
212
|
+
itemHeight,
|
|
213
|
+
space,
|
|
214
|
+
margins
|
|
142
215
|
});
|
|
143
216
|
|
|
144
217
|
let rowClass = `ScrollerListEx-Row${index % 2}`;
|
|
@@ -192,6 +265,41 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
192
265
|
return selected;
|
|
193
266
|
};
|
|
194
267
|
|
|
268
|
+
// Theme
|
|
269
|
+
const theme = useTheme();
|
|
270
|
+
|
|
271
|
+
// Calculate size
|
|
272
|
+
const calculateItemSize = (index: number): [number, number, {}] => {
|
|
273
|
+
// Callback function
|
|
274
|
+
if (typeof itemSize === 'function') {
|
|
275
|
+
const result = itemSize(index);
|
|
276
|
+
if (result.length == 2)
|
|
277
|
+
return [...result, defaultMargin(MUGlobal.pagePaddings)];
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Calculation
|
|
282
|
+
const [size, spaces, isNarrow] = itemSize;
|
|
283
|
+
if (typeof spaces === 'number')
|
|
284
|
+
return [
|
|
285
|
+
size,
|
|
286
|
+
spaces,
|
|
287
|
+
defaultMargin(MUGlobal.pagePaddings, undefined)
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
return [
|
|
291
|
+
size,
|
|
292
|
+
MUGlobal.getSpace(spaces, theme),
|
|
293
|
+
defaultMargin(spaces, isNarrow)
|
|
294
|
+
];
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Local item size
|
|
298
|
+
const itemSizeLocal = (index: number) => {
|
|
299
|
+
const [size, space] = calculateItemSize(index);
|
|
300
|
+
return size + space;
|
|
301
|
+
};
|
|
302
|
+
|
|
195
303
|
// Destruct
|
|
196
304
|
const {
|
|
197
305
|
alternatingColors = [undefined, undefined],
|
|
@@ -202,14 +310,15 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
202
310
|
itemKey = (index: number, data: T) =>
|
|
203
311
|
DataTypes.getIdValue(data, idField) ?? index,
|
|
204
312
|
itemRenderer = (itemProps) => {
|
|
205
|
-
const itemHeight =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
: itemSize;
|
|
313
|
+
const [itemHeight, space, margins] = calculateItemSize(
|
|
314
|
+
itemProps.index
|
|
315
|
+
);
|
|
209
316
|
return defaultItemRenderer({
|
|
210
317
|
itemHeight,
|
|
211
318
|
innerItemRenderer,
|
|
212
319
|
onMouseDown,
|
|
320
|
+
space,
|
|
321
|
+
margins,
|
|
213
322
|
selected: isSelected(itemProps.data),
|
|
214
323
|
...itemProps
|
|
215
324
|
});
|
|
@@ -229,7 +338,7 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
229
338
|
)}
|
|
230
339
|
itemKey={itemKey}
|
|
231
340
|
itemRenderer={itemRenderer}
|
|
232
|
-
itemSize={
|
|
341
|
+
itemSize={itemSizeLocal}
|
|
233
342
|
{...rest}
|
|
234
343
|
/>
|
|
235
344
|
);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { DataTypes } from '@etsoo/shared';
|
|
2
2
|
import { ListChildComponentProps } from 'react-window';
|
|
3
3
|
import { GridMethodRef } from '../GridMethodRef';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ScrollerListExInnerItemRendererProps,
|
|
6
|
+
ScrollerListExItemSize
|
|
7
|
+
} from '../ScrollerListEx';
|
|
5
8
|
import { DataGridPageProps } from './DataGridPageProps';
|
|
6
9
|
|
|
7
10
|
/**
|
|
@@ -32,7 +35,7 @@ export interface ResponsePageProps<T, F extends DataTypes.BasicTemplate>
|
|
|
32
35
|
/**
|
|
33
36
|
* Item size, a function indicates its a variable size list
|
|
34
37
|
*/
|
|
35
|
-
itemSize:
|
|
38
|
+
itemSize: ScrollerListExItemSize;
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Methods
|