@etsoo/react 1.4.21 → 1.4.25
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/components/ScrollerGrid.js +2 -0
- package/lib/components/ScrollerList.js +2 -0
- package/lib/mu/DataGridEx.js +2 -2
- package/lib/mu/DataGridRenderers.d.ts +4 -2
- package/lib/mu/DataGridRenderers.js +14 -10
- package/lib/mu/ResponsibleContainer.d.ts +5 -1
- package/lib/mu/ResponsibleContainer.js +42 -23
- package/lib/mu/SearchBar.js +29 -27
- package/lib/mu/pages/CommonPage.d.ts +1 -6
- package/lib/mu/pages/CommonPage.js +2 -11
- package/lib/mu/pages/CommonPageProps.d.ts +0 -4
- package/lib/mu/pages/DataGridPage.js +2 -6
- package/lib/mu/pages/FixedListPage.js +1 -5
- package/lib/mu/pages/ListPage.js +2 -2
- package/lib/mu/pages/ResponsivePage.js +19 -118
- package/lib/mu/pages/ResponsivePageProps.d.ts +4 -0
- package/lib/mu/pages/TablePage.js +2 -2
- package/package.json +9 -9
- package/src/components/ScrollerGrid.tsx +3 -0
- package/src/components/ScrollerList.tsx +3 -0
- package/src/mu/DataGridEx.tsx +2 -2
- package/src/mu/DataGridRenderers.tsx +14 -11
- package/src/mu/ResponsibleContainer.tsx +64 -25
- package/src/mu/SearchBar.tsx +26 -24
- package/src/mu/pages/CommonPage.tsx +0 -21
- package/src/mu/pages/CommonPageProps.ts +0 -5
- package/src/mu/pages/DataGridPage.tsx +1 -10
- package/src/mu/pages/FixedListPage.tsx +0 -6
- package/src/mu/pages/ListPage.tsx +2 -10
- package/src/mu/pages/ResponsivePage.tsx +21 -195
- package/src/mu/pages/ResponsivePageProps.ts +5 -0
- package/src/mu/pages/TablePage.tsx +2 -10
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { Box, Stack } from '@mui/material';
|
|
2
1
|
import React from 'react';
|
|
3
|
-
import { GridDataGet } from '../../components/GridLoader';
|
|
4
|
-
import useCombinedRefs from '../../uses/useCombinedRefs';
|
|
5
|
-
import { useDimensions } from '../../uses/useDimensions';
|
|
6
|
-
import { DataGridEx, DataGridExCalColumns } from '../DataGridEx';
|
|
7
2
|
import { MUGlobal } from '../MUGlobal';
|
|
8
|
-
import {
|
|
9
|
-
import { SearchBar } from '../SearchBar';
|
|
3
|
+
import { ResponsibleContainer } from '../ResponsibleContainer';
|
|
10
4
|
import { CommonPage } from './CommonPage';
|
|
11
5
|
/**
|
|
12
6
|
* Fixed height list page
|
|
@@ -14,119 +8,26 @@ import { CommonPage } from './CommonPage';
|
|
|
14
8
|
* @returns Component
|
|
15
9
|
*/
|
|
16
10
|
export function ResponsivePage(props) {
|
|
17
|
-
var _a
|
|
11
|
+
var _a;
|
|
18
12
|
// Destruct
|
|
19
|
-
const {
|
|
13
|
+
const { pageProps = {}, ...rest } = props;
|
|
20
14
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
21
|
-
// States
|
|
22
|
-
const [states, setStates] = React.useReducer((currentState, newState) => {
|
|
23
|
-
return { ...currentState, ...newState };
|
|
24
|
-
}, {
|
|
25
|
-
height
|
|
26
|
-
});
|
|
27
|
-
const localLoadData = (props) => {
|
|
28
|
-
const data = GridDataGet(props, fieldTemplate);
|
|
29
|
-
return loadData(data);
|
|
30
|
-
};
|
|
31
|
-
const refs = useCombinedRefs(mRef, (ref) => {
|
|
32
|
-
if (ref == null)
|
|
33
|
-
return;
|
|
34
|
-
states.ref = ref;
|
|
35
|
-
// setStates({ ref });
|
|
36
|
-
});
|
|
37
|
-
// On submit callback
|
|
38
|
-
const onSubmit = (data, _reset) => {
|
|
39
|
-
setStates({ data });
|
|
40
|
-
};
|
|
41
|
-
// Watch container
|
|
42
|
-
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
43
|
-
const rect = dimensions[0][2];
|
|
44
|
-
const showDataGrid = ((_b = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _b !== void 0 ? _b : 0) >= dataGridMinWidth;
|
|
45
|
-
React.useEffect(() => {
|
|
46
|
-
if (rect != null && rect.height > 50 && height == null) {
|
|
47
|
-
let gridHeight = window.innerHeight - Math.round(rect.top + rect.height + 1);
|
|
48
|
-
const style = window.getComputedStyle(dimensions[0][1]);
|
|
49
|
-
const boxPadding = parseFloat(style.paddingLeft);
|
|
50
|
-
if (!isNaN(boxPadding))
|
|
51
|
-
gridHeight -= 2 * boxPadding;
|
|
52
|
-
if (adjustHeight != null) {
|
|
53
|
-
gridHeight -= adjustHeight(gridHeight);
|
|
54
|
-
}
|
|
55
|
-
if (gridHeight !== states.height)
|
|
56
|
-
setStates({ height: gridHeight });
|
|
57
|
-
}
|
|
58
|
-
}, [rect]);
|
|
59
15
|
const { paddings, ...pageRest } = pageProps;
|
|
60
|
-
const
|
|
61
|
-
const gridHeight = states.height;
|
|
62
|
-
if (gridHeight == null)
|
|
63
|
-
return;
|
|
64
|
-
// Show in a row when under DataGrid
|
|
65
|
-
pageProps.fabColumnDirection = !showDataGrid;
|
|
66
|
-
if (showDataGrid) {
|
|
67
|
-
// Delete
|
|
68
|
-
delete rest.itemRenderer;
|
|
69
|
-
return (React.createElement(Box, { sx: {
|
|
70
|
-
padding: paddings
|
|
71
|
-
} },
|
|
72
|
-
React.createElement(DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, columns: columns, outerRef: (element) => {
|
|
73
|
-
if (element != null)
|
|
74
|
-
setStates({ element });
|
|
75
|
-
}, ...rest })));
|
|
76
|
-
}
|
|
77
|
-
// Delete
|
|
78
|
-
delete rest.checkable;
|
|
79
|
-
delete rest.borderRowsCount;
|
|
80
|
-
delete rest.bottomHeight;
|
|
81
|
-
delete rest.footerItemRenderer;
|
|
82
|
-
delete rest.headerHeight;
|
|
83
|
-
delete rest.hideFooter;
|
|
84
|
-
delete rest.hoverColor;
|
|
85
|
-
delete rest.selectable;
|
|
86
|
-
// Half
|
|
87
|
-
const halfPadding = MUGlobal.half(paddings);
|
|
88
|
-
const style = window.getComputedStyle(dimensions[0][1]);
|
|
89
|
-
const boxPadding = parseFloat(style.paddingLeft);
|
|
90
|
-
return (React.createElement(Box, { sx: {
|
|
91
|
-
height: gridHeight + (isNaN(boxPadding) ? 0 : boxPadding),
|
|
92
|
-
paddingTop: halfPadding,
|
|
93
|
-
paddingBottom: halfPadding
|
|
94
|
-
} },
|
|
95
|
-
React.createElement(ScrollerListEx, { autoLoad: false, height: gridHeight, innerItemRenderer: innerItemRenderer, itemSize: itemSize, loadData: localLoadData, mRef: refs, oRef: (element) => {
|
|
96
|
-
if (element != null)
|
|
97
|
-
setStates({ element });
|
|
98
|
-
}, ...rest })));
|
|
99
|
-
}, [states.height, showDataGrid, localLoadData]);
|
|
100
|
-
const sizeRef = React.useRef();
|
|
101
|
-
const { ref, data } = states;
|
|
102
|
-
React.useEffect(() => {
|
|
103
|
-
if (ref == null || data == null || rect == null)
|
|
104
|
-
return;
|
|
105
|
-
// Resize without reset
|
|
106
|
-
if (sizeRef.current == null) {
|
|
107
|
-
sizeRef.current = [rect.width, rect.height];
|
|
108
|
-
}
|
|
109
|
-
else if (sizeRef.current[0] !== rect.width ||
|
|
110
|
-
sizeRef.current[1] !== rect.height) {
|
|
111
|
-
sizeRef.current = [rect.width, rect.height];
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
ref.reset({ data });
|
|
115
|
-
});
|
|
116
|
-
// Pull container id
|
|
117
|
-
const pullContainer = states.element
|
|
118
|
-
? showDataGrid
|
|
119
|
-
? '.DataGridEx-Body'
|
|
120
|
-
: '.ScrollerListEx-Body'
|
|
121
|
-
: undefined;
|
|
16
|
+
const halfPadding = MUGlobal.half(paddings);
|
|
122
17
|
// Layout
|
|
123
|
-
return (React.createElement(CommonPage, { ...pageRest, paddings: {}
|
|
124
|
-
React.createElement(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
18
|
+
return (React.createElement(CommonPage, { ...pageRest, paddings: {} },
|
|
19
|
+
React.createElement(ResponsibleContainer, { paddings: paddings, listBoxSx: (dataGrid, height) => {
|
|
20
|
+
if (dataGrid) {
|
|
21
|
+
return {
|
|
22
|
+
padding: paddings
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return {
|
|
27
|
+
height,
|
|
28
|
+
paddingTop: halfPadding,
|
|
29
|
+
paddingBottom: halfPadding
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}, ...rest })));
|
|
132
33
|
}
|
|
@@ -6,7 +6,7 @@ import { useDimensions } from '../../uses/useDimensions';
|
|
|
6
6
|
import { MUGlobal } from '../MUGlobal';
|
|
7
7
|
import { SearchBar } from '../SearchBar';
|
|
8
8
|
import { TableEx, TableExMinWidth } from '../TableEx';
|
|
9
|
-
import { CommonPage,
|
|
9
|
+
import { CommonPage, CommonPageScrollContainer } from './CommonPage';
|
|
10
10
|
/**
|
|
11
11
|
* Table page
|
|
12
12
|
* @param props Props
|
|
@@ -60,7 +60,7 @@ export function TablePage(props) {
|
|
|
60
60
|
}
|
|
61
61
|
}, [rect]);
|
|
62
62
|
// Layout
|
|
63
|
-
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer
|
|
63
|
+
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer },
|
|
64
64
|
React.createElement(Stack, null,
|
|
65
65
|
React.createElement(Box, { ref: dimensions[0][0], sx: {
|
|
66
66
|
paddingBottom: pageProps.paddings
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.25",
|
|
4
4
|
"description": "TypeScript ReactJs framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"@emotion/react": "^11.7.1",
|
|
51
51
|
"@emotion/style": "^0.8.0",
|
|
52
52
|
"@emotion/styled": "^11.6.0",
|
|
53
|
-
"@etsoo/appscript": "^1.2.
|
|
53
|
+
"@etsoo/appscript": "^1.2.22",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.0",
|
|
55
55
|
"@etsoo/shared": "^1.1.3",
|
|
56
56
|
"@mui/icons-material": "^5.2.5",
|
|
57
|
-
"@mui/material": "^5.2.
|
|
57
|
+
"@mui/material": "^5.2.8",
|
|
58
58
|
"@reach/router": "^1.3.4",
|
|
59
59
|
"@types/pica": "^5.1.3",
|
|
60
60
|
"@types/pulltorefreshjs": "^0.1.5",
|
|
@@ -76,15 +76,15 @@
|
|
|
76
76
|
"react-window": "^1.8.6"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@babel/cli": "^7.16.
|
|
79
|
+
"@babel/cli": "^7.16.8",
|
|
80
80
|
"@babel/core": "^7.16.7",
|
|
81
|
-
"@babel/plugin-transform-runtime": "^7.16.
|
|
82
|
-
"@babel/preset-env": "^7.16.
|
|
83
|
-
"@babel/runtime-corejs3": "^7.16.
|
|
81
|
+
"@babel/plugin-transform-runtime": "^7.16.8",
|
|
82
|
+
"@babel/preset-env": "^7.16.8",
|
|
83
|
+
"@babel/runtime-corejs3": "^7.16.8",
|
|
84
84
|
"@types/jest": "^27.4.0",
|
|
85
85
|
"@types/react-test-renderer": "^17.0.1",
|
|
86
|
-
"@typescript-eslint/eslint-plugin": "^5.9.
|
|
87
|
-
"@typescript-eslint/parser": "^5.9.
|
|
86
|
+
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
|
87
|
+
"@typescript-eslint/parser": "^5.9.1",
|
|
88
88
|
"eslint": "^8.6.0",
|
|
89
89
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
90
90
|
"eslint-plugin-import": "^2.25.4",
|
package/src/mu/DataGridEx.tsx
CHANGED
|
@@ -241,7 +241,7 @@ export function DataGridEx<T extends Record<string, any>>(
|
|
|
241
241
|
sortLabel = headerCellRenderer({
|
|
242
242
|
cellProps,
|
|
243
243
|
column,
|
|
244
|
-
columnIndex: index,
|
|
244
|
+
columnIndex: checkable ? index - 1 : index, // Ignore the checkbox case,
|
|
245
245
|
states
|
|
246
246
|
});
|
|
247
247
|
} else if (sortable && field != null) {
|
|
@@ -306,7 +306,7 @@ export function DataGridEx<T extends Record<string, any>>(
|
|
|
306
306
|
const cell = footerItemRenderer
|
|
307
307
|
? footerItemRenderer(rows, {
|
|
308
308
|
column,
|
|
309
|
-
index,
|
|
309
|
+
index: checkable ? index - 1 : index, // Ignore the checkbox case
|
|
310
310
|
states,
|
|
311
311
|
cellProps,
|
|
312
312
|
checkable
|
|
@@ -112,24 +112,27 @@ export namespace DataGridRenderers {
|
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
114
|
* Default footer item renderer
|
|
115
|
-
* @param
|
|
115
|
+
* @param rows Rows
|
|
116
|
+
* @param props Renderer props
|
|
117
|
+
* @param location Renderer location (column index)
|
|
116
118
|
* @returns Component
|
|
117
119
|
*/
|
|
118
120
|
export function defaultFooterItemRenderer<T>(
|
|
119
121
|
_rows: T[],
|
|
120
|
-
{ index, states, checkable }: DataGridExFooterItemRendererProps<T
|
|
122
|
+
{ index, states, checkable }: DataGridExFooterItemRendererProps<T>,
|
|
123
|
+
location: number = 0
|
|
121
124
|
) {
|
|
122
125
|
const { selectedItems, loadedItems, hasNextPage } = states;
|
|
123
126
|
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
if (index === location) {
|
|
128
|
+
if (checkable) {
|
|
129
|
+
return [
|
|
130
|
+
selectedItems.length,
|
|
131
|
+
loadedItems.toLocaleString() + (hasNextPage ? '+' : '')
|
|
132
|
+
].join(' / ');
|
|
133
|
+
} else {
|
|
134
|
+
return loadedItems.toLocaleString() + (hasNextPage ? '+' : '');
|
|
135
|
+
}
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
return undefined;
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
DataGridExProps
|
|
18
18
|
} from './DataGridEx';
|
|
19
19
|
import { GridMethodRef } from './GridMethodRef';
|
|
20
|
+
import { MUGlobal } from './MUGlobal';
|
|
20
21
|
import { PullToRefreshUI } from './PullToRefreshUI';
|
|
21
22
|
import {
|
|
22
23
|
ScrollerListEx,
|
|
@@ -90,7 +91,7 @@ export interface ResponsibleContainerProps<
|
|
|
90
91
|
/**
|
|
91
92
|
* Listbox SX (dataGrid determines the case)
|
|
92
93
|
*/
|
|
93
|
-
listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
94
|
+
listBoxSx?: (dataGrid: boolean, height: number) => SxProps<Theme>;
|
|
94
95
|
|
|
95
96
|
/**
|
|
96
97
|
* Load data callback
|
|
@@ -104,6 +105,11 @@ export interface ResponsibleContainerProps<
|
|
|
104
105
|
*/
|
|
105
106
|
mRef?: React.MutableRefObject<GridMethodRef | undefined>;
|
|
106
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Paddings
|
|
110
|
+
*/
|
|
111
|
+
paddings?: {};
|
|
112
|
+
|
|
107
113
|
/**
|
|
108
114
|
* Pull to refresh data
|
|
109
115
|
*/
|
|
@@ -126,6 +132,16 @@ interface LocalRefs {
|
|
|
126
132
|
mounted?: boolean;
|
|
127
133
|
}
|
|
128
134
|
|
|
135
|
+
function getDefaultSearchBoxSx(paddings: {}): SxProps<Theme> {
|
|
136
|
+
const half = MUGlobal.half(paddings);
|
|
137
|
+
return {
|
|
138
|
+
paddingLeft: half,
|
|
139
|
+
paddingRight: half,
|
|
140
|
+
paddingTop: half,
|
|
141
|
+
marginBottom: half
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
129
145
|
/**
|
|
130
146
|
* Responsible container
|
|
131
147
|
* @param props Props
|
|
@@ -146,8 +162,9 @@ export function ResponsibleContainer<
|
|
|
146
162
|
listBoxSx,
|
|
147
163
|
loadData,
|
|
148
164
|
mRef,
|
|
165
|
+
paddings = MUGlobal.pagePaddings,
|
|
149
166
|
pullToRefresh = true,
|
|
150
|
-
searchBoxSx,
|
|
167
|
+
searchBoxSx = getDefaultSearchBoxSx(paddings),
|
|
151
168
|
sizeReadyMiliseconds = 0,
|
|
152
169
|
...rest
|
|
153
170
|
} = props;
|
|
@@ -157,16 +174,17 @@ export function ResponsibleContainer<
|
|
|
157
174
|
|
|
158
175
|
// Refs
|
|
159
176
|
const refs = React.useRef<LocalRefs>({});
|
|
177
|
+
const state = refs.current;
|
|
160
178
|
|
|
161
179
|
const mRefs = useCombinedRefs(mRef, (ref: GridMethodRef) => {
|
|
162
180
|
if (ref == null) return;
|
|
163
|
-
|
|
181
|
+
state.ref = ref;
|
|
164
182
|
});
|
|
165
183
|
|
|
166
184
|
// Update mounted state
|
|
167
185
|
React.useEffect(() => {
|
|
168
186
|
return () => {
|
|
169
|
-
|
|
187
|
+
state.mounted = false;
|
|
170
188
|
};
|
|
171
189
|
}, []);
|
|
172
190
|
|
|
@@ -175,15 +193,15 @@ export function ResponsibleContainer<
|
|
|
175
193
|
|
|
176
194
|
// Load data
|
|
177
195
|
const localLoadData = (props: GridLoadDataProps) => {
|
|
178
|
-
|
|
196
|
+
state.mounted = true;
|
|
179
197
|
const data = GridDataGet(props, fieldTemplate);
|
|
180
198
|
return loadData(data);
|
|
181
199
|
};
|
|
182
200
|
|
|
183
201
|
// On submit callback
|
|
184
202
|
const onSubmit = (data: FormData, _reset: boolean) => {
|
|
185
|
-
if (data == null ||
|
|
186
|
-
|
|
203
|
+
if (data == null || state.ref == null) return;
|
|
204
|
+
state.ref.reset({ data });
|
|
187
205
|
};
|
|
188
206
|
|
|
189
207
|
// Watch container
|
|
@@ -196,19 +214,19 @@ export function ResponsibleContainer<
|
|
|
196
214
|
if (rect == null) return true;
|
|
197
215
|
|
|
198
216
|
// Last rect
|
|
199
|
-
const lastRect =
|
|
217
|
+
const lastRect = state.rect;
|
|
200
218
|
|
|
201
219
|
// 32 = scroll bar width
|
|
202
220
|
if (
|
|
203
221
|
lastRect != null &&
|
|
204
|
-
|
|
222
|
+
state.mounted !== true &&
|
|
205
223
|
Math.abs(rect.width - lastRect.width) <= 32 &&
|
|
206
224
|
Math.abs(rect.height - lastRect.height) <= 32
|
|
207
225
|
)
|
|
208
226
|
return true;
|
|
209
227
|
|
|
210
228
|
// Hold the new rect
|
|
211
|
-
|
|
229
|
+
state.rect = rect;
|
|
212
230
|
|
|
213
231
|
return false;
|
|
214
232
|
}
|
|
@@ -220,7 +238,7 @@ export function ResponsibleContainer<
|
|
|
220
238
|
// Create list
|
|
221
239
|
const [list, showDataGrid] = (() => {
|
|
222
240
|
// No layout
|
|
223
|
-
if (rect == null) return [null,
|
|
241
|
+
if (rect == null) return [null, undefined];
|
|
224
242
|
|
|
225
243
|
// Width
|
|
226
244
|
const width = rect.width;
|
|
@@ -234,12 +252,11 @@ export function ResponsibleContainer<
|
|
|
234
252
|
heightLocal = height;
|
|
235
253
|
} else {
|
|
236
254
|
// Auto calculation
|
|
237
|
-
heightLocal =
|
|
238
|
-
window.innerHeight - Math.round(rect.top + rect.height + 1);
|
|
255
|
+
heightLocal = window.innerHeight - Math.round(rect.bottom + 1);
|
|
239
256
|
|
|
240
257
|
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
241
|
-
const
|
|
242
|
-
if (!isNaN(
|
|
258
|
+
const boxMargin = parseFloat(style.marginBottom);
|
|
259
|
+
if (!isNaN(boxMargin)) heightLocal -= 3 * boxMargin; // 1 - Box, 2 - Page bottom
|
|
243
260
|
|
|
244
261
|
if (adjustHeight != null) {
|
|
245
262
|
heightLocal -= adjustHeight(heightLocal);
|
|
@@ -251,7 +268,13 @@ export function ResponsibleContainer<
|
|
|
251
268
|
delete rest.itemRenderer;
|
|
252
269
|
|
|
253
270
|
return [
|
|
254
|
-
<Box
|
|
271
|
+
<Box
|
|
272
|
+
sx={
|
|
273
|
+
listBoxSx == null
|
|
274
|
+
? undefined
|
|
275
|
+
: listBoxSx(true, heightLocal)
|
|
276
|
+
}
|
|
277
|
+
>
|
|
255
278
|
<DataGridEx<T>
|
|
256
279
|
autoLoad={!hasFields}
|
|
257
280
|
height={heightLocal}
|
|
@@ -277,7 +300,13 @@ export function ResponsibleContainer<
|
|
|
277
300
|
delete rest.selectable;
|
|
278
301
|
|
|
279
302
|
return [
|
|
280
|
-
<Box
|
|
303
|
+
<Box
|
|
304
|
+
sx={
|
|
305
|
+
listBoxSx == null
|
|
306
|
+
? undefined
|
|
307
|
+
: listBoxSx(false, heightLocal)
|
|
308
|
+
}
|
|
309
|
+
>
|
|
281
310
|
<ScrollerListEx<T>
|
|
282
311
|
autoLoad={!hasFields}
|
|
283
312
|
width={rect.width}
|
|
@@ -291,21 +320,31 @@ export function ResponsibleContainer<
|
|
|
291
320
|
];
|
|
292
321
|
})();
|
|
293
322
|
|
|
323
|
+
const searchBar = React.useMemo(() => {
|
|
324
|
+
if (!hasFields || showDataGrid == null) return;
|
|
325
|
+
return (
|
|
326
|
+
<SearchBar
|
|
327
|
+
fields={fields}
|
|
328
|
+
onSubmit={onSubmit}
|
|
329
|
+
className={`searchBar${showDataGrid ? 'Grid' : 'List'}`}
|
|
330
|
+
/>
|
|
331
|
+
);
|
|
332
|
+
}, [showDataGrid, hasFields]);
|
|
333
|
+
|
|
294
334
|
// Pull container
|
|
295
|
-
const pullContainer =
|
|
296
|
-
|
|
335
|
+
const pullContainer =
|
|
336
|
+
showDataGrid == null
|
|
337
|
+
? undefined
|
|
338
|
+
: showDataGrid
|
|
297
339
|
? '.DataGridEx-Body'
|
|
298
|
-
: '.ScrollerListEx-Body'
|
|
299
|
-
: undefined;
|
|
340
|
+
: '.ScrollerListEx-Body';
|
|
300
341
|
|
|
301
342
|
// Layout
|
|
302
343
|
return (
|
|
303
344
|
<React.Fragment>
|
|
304
345
|
<Stack>
|
|
305
346
|
<Box ref={dimensions[0][0]} sx={searchBoxSx}>
|
|
306
|
-
{
|
|
307
|
-
<SearchBar fields={fields} onSubmit={onSubmit} />
|
|
308
|
-
)}
|
|
347
|
+
{searchBar}
|
|
309
348
|
</Box>
|
|
310
349
|
{list}
|
|
311
350
|
</Stack>
|
|
@@ -316,7 +355,7 @@ export function ResponsibleContainer<
|
|
|
316
355
|
instructionsPullToRefresh={labels.pullToRefresh}
|
|
317
356
|
instructionsReleaseToRefresh={labels.releaseToRefresh}
|
|
318
357
|
instructionsRefreshing={labels.refreshing}
|
|
319
|
-
onRefresh={() =>
|
|
358
|
+
onRefresh={() => state.ref?.reset()}
|
|
320
359
|
shouldPullToRefresh={() => {
|
|
321
360
|
const container = document.querySelector(pullContainer);
|
|
322
361
|
return !container?.scrollTop;
|
package/src/mu/SearchBar.tsx
CHANGED
|
@@ -99,18 +99,18 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
99
99
|
// Drawer open / close
|
|
100
100
|
const [open, updateOpen] = React.useState(false);
|
|
101
101
|
|
|
102
|
-
//
|
|
103
|
-
const
|
|
102
|
+
// State
|
|
103
|
+
const state = React.useRef<{
|
|
104
104
|
form?: HTMLFormElement;
|
|
105
105
|
moreForm?: HTMLFormElement;
|
|
106
106
|
submitSeed?: number;
|
|
107
107
|
lastMaxWidth?: number;
|
|
108
|
-
}>({});
|
|
108
|
+
}>({}).current;
|
|
109
109
|
|
|
110
110
|
// Watch container
|
|
111
111
|
const { dimensions } = useDimensions(1, (target, rect) => {
|
|
112
112
|
// Same logic from resetButtonRef
|
|
113
|
-
if (rect.width ===
|
|
113
|
+
if (rect.width === state.lastMaxWidth) return false;
|
|
114
114
|
|
|
115
115
|
// Len
|
|
116
116
|
const len = target.children.length;
|
|
@@ -143,10 +143,10 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
143
143
|
|
|
144
144
|
// Container width
|
|
145
145
|
let maxWidth = containerRect.width;
|
|
146
|
-
if (maxWidth ===
|
|
146
|
+
if (maxWidth === state.lastMaxWidth) {
|
|
147
147
|
return;
|
|
148
148
|
}
|
|
149
|
-
|
|
149
|
+
state.lastMaxWidth = maxWidth;
|
|
150
150
|
|
|
151
151
|
// More button
|
|
152
152
|
const buttonMore = resetButton.previousElementSibling!;
|
|
@@ -241,7 +241,7 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
241
241
|
const handleForm = (event: React.FormEvent<HTMLFormElement>) => {
|
|
242
242
|
if (event.nativeEvent.cancelable && !event.nativeEvent.composed) return;
|
|
243
243
|
|
|
244
|
-
if (
|
|
244
|
+
if (state.form == null) state.form = event.currentTarget;
|
|
245
245
|
|
|
246
246
|
handleSubmit();
|
|
247
247
|
};
|
|
@@ -255,7 +255,7 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
255
255
|
const moreFormChange = (event: React.FormEvent<HTMLFormElement>) => {
|
|
256
256
|
if (event.nativeEvent.cancelable && !event.nativeEvent.composed) return;
|
|
257
257
|
|
|
258
|
-
if (
|
|
258
|
+
if (state.moreForm == null) state.moreForm = event.currentTarget;
|
|
259
259
|
|
|
260
260
|
handleSubmit();
|
|
261
261
|
};
|
|
@@ -263,32 +263,32 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
263
263
|
// Reset
|
|
264
264
|
const handleReset = () => {
|
|
265
265
|
// Clear form values
|
|
266
|
-
if (
|
|
267
|
-
if (
|
|
266
|
+
if (state.form != null) resetForm(state.form);
|
|
267
|
+
if (state.moreForm != null) resetForm(state.moreForm);
|
|
268
268
|
|
|
269
269
|
// Resubmit
|
|
270
270
|
handleSubmitInstant(true);
|
|
271
271
|
};
|
|
272
272
|
|
|
273
273
|
// Submit
|
|
274
|
-
const handleSubmit = () => {
|
|
275
|
-
if (
|
|
276
|
-
clearTimeout(
|
|
274
|
+
const handleSubmit = (delay = 480) => {
|
|
275
|
+
if (state.submitSeed != null) {
|
|
276
|
+
clearTimeout(state.submitSeed);
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
// Delay the change
|
|
280
|
-
|
|
280
|
+
state.submitSeed = window.setTimeout(handleSubmitInstant, delay);
|
|
281
281
|
};
|
|
282
282
|
|
|
283
283
|
// Submit at once
|
|
284
284
|
const handleSubmitInstant = (reset: boolean = false) => {
|
|
285
285
|
// Reset timeout
|
|
286
|
-
|
|
286
|
+
state.submitSeed = undefined;
|
|
287
287
|
|
|
288
288
|
// Prepare data
|
|
289
|
-
const data = new FormData(
|
|
290
|
-
if (
|
|
291
|
-
DomUtils.mergeFormData(data, new FormData(
|
|
289
|
+
const data = new FormData(state.form);
|
|
290
|
+
if (state.moreForm != null) {
|
|
291
|
+
DomUtils.mergeFormData(data, new FormData(state.moreForm));
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
onSubmit(data, reset);
|
|
@@ -296,15 +296,17 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
296
296
|
|
|
297
297
|
// First loading
|
|
298
298
|
React.useEffect(() => {
|
|
299
|
-
// Delayed way
|
|
300
|
-
handleSubmit();
|
|
301
|
-
|
|
302
299
|
return () => {
|
|
303
300
|
// Clear the seeds
|
|
304
|
-
if (
|
|
301
|
+
if (state.submitSeed != null) clearTimeout(state.submitSeed);
|
|
305
302
|
};
|
|
306
303
|
}, []);
|
|
307
304
|
|
|
305
|
+
React.useEffect(() => {
|
|
306
|
+
// Delayed way
|
|
307
|
+
handleSubmit(100);
|
|
308
|
+
}, [className]);
|
|
309
|
+
|
|
308
310
|
// Layout
|
|
309
311
|
return (
|
|
310
312
|
<React.Fragment>
|
|
@@ -313,7 +315,7 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
313
315
|
className={className}
|
|
314
316
|
onChange={handleForm}
|
|
315
317
|
ref={(form) => {
|
|
316
|
-
if (form)
|
|
318
|
+
if (form) state.form = form;
|
|
317
319
|
}}
|
|
318
320
|
>
|
|
319
321
|
<Stack
|
|
@@ -374,7 +376,7 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
374
376
|
<form
|
|
375
377
|
onChange={moreFormChange}
|
|
376
378
|
ref={(form) => {
|
|
377
|
-
if (form)
|
|
379
|
+
if (form) state.moreForm = form;
|
|
378
380
|
}}
|
|
379
381
|
>
|
|
380
382
|
<Stack
|