@etsoo/react 1.4.22 → 1.4.26
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/ScrollerList.js +3 -1
- 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 +9 -1
- package/lib/mu/ResponsibleContainer.js +41 -13
- package/lib/mu/SearchBar.js +29 -27
- package/lib/mu/pages/CommonPage.d.ts +0 -4
- package/lib/mu/pages/CommonPage.js +2 -11
- package/lib/mu/pages/CommonPageProps.d.ts +0 -4
- package/lib/mu/pages/DataGridPage.js +4 -7
- package/lib/mu/pages/FixedListPage.js +3 -6
- package/lib/mu/pages/ListPage.js +2 -2
- package/lib/mu/pages/ResponsivePage.js +33 -119
- package/lib/mu/pages/ResponsivePageProps.d.ts +4 -0
- package/lib/mu/pages/TablePage.js +4 -3
- package/lib/uses/useWindowSize.d.ts +6 -5
- package/lib/uses/useWindowSize.js +22 -16
- package/package.json +2 -2
- package/src/components/ScrollerList.tsx +4 -1
- package/src/mu/DataGridEx.tsx +2 -2
- package/src/mu/DataGridRenderers.tsx +14 -11
- package/src/mu/ResponsibleContainer.tsx +75 -16
- 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 +3 -11
- package/src/mu/pages/FixedListPage.tsx +2 -7
- package/src/mu/pages/ListPage.tsx +2 -10
- package/src/mu/pages/ResponsivePage.tsx +37 -192
- package/src/mu/pages/ResponsivePageProps.ts +5 -0
- package/src/mu/pages/TablePage.tsx +5 -11
- package/src/uses/useWindowSize.ts +32 -19
|
@@ -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
|
|
@@ -51,7 +51,8 @@ export function TablePage(props) {
|
|
|
51
51
|
const rect = dimensions[0][2];
|
|
52
52
|
const list = React.useMemo(() => {
|
|
53
53
|
if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
|
|
54
|
-
let maxHeight =
|
|
54
|
+
let maxHeight = document.documentElement.clientHeight -
|
|
55
|
+
(rect.top + rect.height + 1);
|
|
55
56
|
const style = window.getComputedStyle(dimensions[0][1]);
|
|
56
57
|
const paddingBottom = parseFloat(style.paddingBottom);
|
|
57
58
|
if (!isNaN(paddingBottom))
|
|
@@ -60,7 +61,7 @@ export function TablePage(props) {
|
|
|
60
61
|
}
|
|
61
62
|
}, [rect]);
|
|
62
63
|
// Layout
|
|
63
|
-
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer
|
|
64
|
+
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer },
|
|
64
65
|
React.createElement(Stack, null,
|
|
65
66
|
React.createElement(Box, { ref: dimensions[0][0], sx: {
|
|
66
67
|
paddingBottom: pageProps.paddings
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
interface ISize {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* Detect window size
|
|
3
|
-
* @param miliseconds Miliseconds delayed
|
|
4
7
|
* @returns Window size
|
|
5
8
|
*/
|
|
6
|
-
export declare const useWindowSize: (
|
|
7
|
-
|
|
8
|
-
height: number;
|
|
9
|
-
};
|
|
9
|
+
export declare const useWindowSize: () => ISize;
|
|
10
|
+
export {};
|
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Detect window size
|
|
4
|
-
* @param miliseconds Miliseconds delayed
|
|
5
4
|
* @returns Window size
|
|
6
5
|
*/
|
|
7
|
-
export const useWindowSize = (
|
|
6
|
+
export const useWindowSize = () => {
|
|
8
7
|
// State
|
|
9
8
|
const [size, setSize] = React.useState({
|
|
10
9
|
width: 0,
|
|
11
10
|
height: 0
|
|
12
11
|
});
|
|
13
|
-
const [state] = React.useState({});
|
|
14
|
-
const resizeHandler = () => {
|
|
15
|
-
if (state.seed != null)
|
|
16
|
-
window.clearTimeout(state.seed);
|
|
17
|
-
state.seed = window.setTimeout(() => {
|
|
18
|
-
setSize({
|
|
19
|
-
width: window.innerWidth,
|
|
20
|
-
height: window.innerHeight
|
|
21
|
-
});
|
|
22
|
-
state.seed = undefined;
|
|
23
|
-
}, miliseconds);
|
|
24
|
-
};
|
|
25
12
|
React.useEffect(() => {
|
|
13
|
+
let ticking = false;
|
|
14
|
+
let lastKnownSize;
|
|
15
|
+
let requestAnimationFrameSeed = 0;
|
|
16
|
+
const resizeHandler = () => {
|
|
17
|
+
lastKnownSize = {
|
|
18
|
+
width: document.documentElement.clientWidth,
|
|
19
|
+
height: document.documentElement.clientHeight
|
|
20
|
+
};
|
|
21
|
+
if (!ticking) {
|
|
22
|
+
requestAnimationFrameSeed = window.requestAnimationFrame(() => {
|
|
23
|
+
setSize(lastKnownSize);
|
|
24
|
+
ticking = false;
|
|
25
|
+
requestAnimationFrameSeed = 0;
|
|
26
|
+
});
|
|
27
|
+
ticking = true;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
26
30
|
window.addEventListener('resize', resizeHandler);
|
|
27
31
|
return () => {
|
|
32
|
+
// Cancel animation frame
|
|
33
|
+
if (requestAnimationFrameSeed > 0)
|
|
34
|
+
window.cancelAnimationFrame(requestAnimationFrameSeed);
|
|
35
|
+
// Remove scroll event
|
|
28
36
|
window.removeEventListener('resize', resizeHandler);
|
|
29
|
-
if (state.seed != null)
|
|
30
|
-
window.clearTimeout(state.seed);
|
|
31
37
|
};
|
|
32
38
|
}, []);
|
|
33
39
|
// Return
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.26",
|
|
4
4
|
"description": "TypeScript ReactJs framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
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",
|
|
@@ -106,7 +106,7 @@ export const ScrollerList = <T extends Record<string, any>>(
|
|
|
106
106
|
autoLoad = true,
|
|
107
107
|
defaultOrderBy,
|
|
108
108
|
defaultOrderByAsc,
|
|
109
|
-
height =
|
|
109
|
+
height = document.documentElement.clientHeight,
|
|
110
110
|
width = '100%',
|
|
111
111
|
mRef,
|
|
112
112
|
oRef,
|
|
@@ -248,6 +248,9 @@ export const ScrollerList = <T extends Record<string, any>>(
|
|
|
248
248
|
...add
|
|
249
249
|
};
|
|
250
250
|
Object.assign(state, resetState);
|
|
251
|
+
|
|
252
|
+
// Reset
|
|
253
|
+
setRows([]);
|
|
251
254
|
},
|
|
252
255
|
|
|
253
256
|
scrollTo(scrollOffset: number): void {
|
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;
|
|
@@ -51,6 +51,11 @@ export interface ResponsibleContainerProps<
|
|
|
51
51
|
*/
|
|
52
52
|
columns: GridColumn<T>[];
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Container box SX (dataGrid determines the case)
|
|
56
|
+
*/
|
|
57
|
+
containerBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
58
|
+
|
|
54
59
|
/**
|
|
55
60
|
* Min width to show Datagrid
|
|
56
61
|
*/
|
|
@@ -91,7 +96,7 @@ export interface ResponsibleContainerProps<
|
|
|
91
96
|
/**
|
|
92
97
|
* Listbox SX (dataGrid determines the case)
|
|
93
98
|
*/
|
|
94
|
-
listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
99
|
+
listBoxSx?: (dataGrid: boolean, height: number) => SxProps<Theme>;
|
|
95
100
|
|
|
96
101
|
/**
|
|
97
102
|
* Load data callback
|
|
@@ -105,6 +110,11 @@ export interface ResponsibleContainerProps<
|
|
|
105
110
|
*/
|
|
106
111
|
mRef?: React.MutableRefObject<GridMethodRef | undefined>;
|
|
107
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Element ready callback
|
|
115
|
+
*/
|
|
116
|
+
elementReady?: (element: HTMLElement, isDataGrid: boolean) => void;
|
|
117
|
+
|
|
108
118
|
/**
|
|
109
119
|
* Paddings
|
|
110
120
|
*/
|
|
@@ -132,6 +142,16 @@ interface LocalRefs {
|
|
|
132
142
|
mounted?: boolean;
|
|
133
143
|
}
|
|
134
144
|
|
|
145
|
+
function getDefaultSearchBoxSx(paddings: {}): SxProps<Theme> {
|
|
146
|
+
const half = MUGlobal.half(paddings);
|
|
147
|
+
return {
|
|
148
|
+
paddingLeft: (theme) => theme.spacing(0.5),
|
|
149
|
+
paddingRight: (theme) => theme.spacing(0.5),
|
|
150
|
+
paddingTop: half,
|
|
151
|
+
marginBottom: half
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
135
155
|
/**
|
|
136
156
|
* Responsible container
|
|
137
157
|
* @param props Props
|
|
@@ -145,7 +165,9 @@ export function ResponsibleContainer<
|
|
|
145
165
|
const {
|
|
146
166
|
adjustHeight,
|
|
147
167
|
columns,
|
|
168
|
+
containerBoxSx,
|
|
148
169
|
dataGridMinWidth = DataGridExCalColumns(columns).total,
|
|
170
|
+
elementReady,
|
|
149
171
|
fields,
|
|
150
172
|
fieldTemplate,
|
|
151
173
|
height,
|
|
@@ -154,7 +176,7 @@ export function ResponsibleContainer<
|
|
|
154
176
|
mRef,
|
|
155
177
|
paddings = MUGlobal.pagePaddings,
|
|
156
178
|
pullToRefresh = true,
|
|
157
|
-
searchBoxSx =
|
|
179
|
+
searchBoxSx = getDefaultSearchBoxSx(paddings),
|
|
158
180
|
sizeReadyMiliseconds = 0,
|
|
159
181
|
...rest
|
|
160
182
|
} = props;
|
|
@@ -228,7 +250,7 @@ export function ResponsibleContainer<
|
|
|
228
250
|
// Create list
|
|
229
251
|
const [list, showDataGrid] = (() => {
|
|
230
252
|
// No layout
|
|
231
|
-
if (rect == null) return [null,
|
|
253
|
+
if (rect == null) return [null, undefined];
|
|
232
254
|
|
|
233
255
|
// Width
|
|
234
256
|
const width = rect.width;
|
|
@@ -242,7 +264,9 @@ export function ResponsibleContainer<
|
|
|
242
264
|
heightLocal = height;
|
|
243
265
|
} else {
|
|
244
266
|
// Auto calculation
|
|
245
|
-
heightLocal =
|
|
267
|
+
heightLocal =
|
|
268
|
+
document.documentElement.clientHeight -
|
|
269
|
+
Math.round(rect.bottom + 1);
|
|
246
270
|
|
|
247
271
|
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
248
272
|
const boxMargin = parseFloat(style.marginBottom);
|
|
@@ -258,13 +282,23 @@ export function ResponsibleContainer<
|
|
|
258
282
|
delete rest.itemRenderer;
|
|
259
283
|
|
|
260
284
|
return [
|
|
261
|
-
<Box
|
|
285
|
+
<Box
|
|
286
|
+
sx={
|
|
287
|
+
listBoxSx == null
|
|
288
|
+
? undefined
|
|
289
|
+
: listBoxSx(true, heightLocal)
|
|
290
|
+
}
|
|
291
|
+
>
|
|
262
292
|
<DataGridEx<T>
|
|
263
293
|
autoLoad={!hasFields}
|
|
264
294
|
height={heightLocal}
|
|
265
295
|
width={rect.width}
|
|
266
296
|
loadData={localLoadData}
|
|
267
297
|
mRef={mRefs}
|
|
298
|
+
outerRef={(element?: HTMLDivElement) => {
|
|
299
|
+
if (element != null && elementReady)
|
|
300
|
+
elementReady(element, true);
|
|
301
|
+
}}
|
|
268
302
|
columns={columns}
|
|
269
303
|
{...rest}
|
|
270
304
|
/>
|
|
@@ -284,13 +318,22 @@ export function ResponsibleContainer<
|
|
|
284
318
|
delete rest.selectable;
|
|
285
319
|
|
|
286
320
|
return [
|
|
287
|
-
<Box
|
|
321
|
+
<Box
|
|
322
|
+
sx={
|
|
323
|
+
listBoxSx == null
|
|
324
|
+
? undefined
|
|
325
|
+
: listBoxSx(false, heightLocal)
|
|
326
|
+
}
|
|
327
|
+
>
|
|
288
328
|
<ScrollerListEx<T>
|
|
289
329
|
autoLoad={!hasFields}
|
|
290
|
-
width={rect.width}
|
|
291
330
|
height={heightLocal}
|
|
292
331
|
loadData={localLoadData}
|
|
293
332
|
mRef={mRefs}
|
|
333
|
+
oRef={(element) => {
|
|
334
|
+
if (element != null && elementReady)
|
|
335
|
+
elementReady(element, false);
|
|
336
|
+
}}
|
|
294
337
|
{...rest}
|
|
295
338
|
/>
|
|
296
339
|
</Box>,
|
|
@@ -298,21 +341,37 @@ export function ResponsibleContainer<
|
|
|
298
341
|
];
|
|
299
342
|
})();
|
|
300
343
|
|
|
344
|
+
const searchBar = React.useMemo(() => {
|
|
345
|
+
if (!hasFields || showDataGrid == null) return;
|
|
346
|
+
return (
|
|
347
|
+
<SearchBar
|
|
348
|
+
fields={fields}
|
|
349
|
+
onSubmit={onSubmit}
|
|
350
|
+
className={`searchBar${showDataGrid ? 'Grid' : 'List'}`}
|
|
351
|
+
/>
|
|
352
|
+
);
|
|
353
|
+
}, [showDataGrid, hasFields]);
|
|
354
|
+
|
|
301
355
|
// Pull container
|
|
302
|
-
const pullContainer =
|
|
303
|
-
|
|
356
|
+
const pullContainer =
|
|
357
|
+
showDataGrid == null
|
|
358
|
+
? undefined
|
|
359
|
+
: showDataGrid
|
|
304
360
|
? '.DataGridEx-Body'
|
|
305
|
-
: '.ScrollerListEx-Body'
|
|
306
|
-
: undefined;
|
|
361
|
+
: '.ScrollerListEx-Body';
|
|
307
362
|
|
|
308
363
|
// Layout
|
|
309
364
|
return (
|
|
310
|
-
<
|
|
365
|
+
<Box
|
|
366
|
+
sx={
|
|
367
|
+
containerBoxSx == null || showDataGrid == null
|
|
368
|
+
? undefined
|
|
369
|
+
: containerBoxSx(showDataGrid)
|
|
370
|
+
}
|
|
371
|
+
>
|
|
311
372
|
<Stack>
|
|
312
373
|
<Box ref={dimensions[0][0]} sx={searchBoxSx}>
|
|
313
|
-
{
|
|
314
|
-
<SearchBar fields={fields} onSubmit={onSubmit} />
|
|
315
|
-
)}
|
|
374
|
+
{searchBar}
|
|
316
375
|
</Box>
|
|
317
376
|
{list}
|
|
318
377
|
</Stack>
|
|
@@ -330,6 +389,6 @@ export function ResponsibleContainer<
|
|
|
330
389
|
}}
|
|
331
390
|
/>
|
|
332
391
|
)}
|
|
333
|
-
</
|
|
392
|
+
</Box>
|
|
334
393
|
);
|
|
335
394
|
}
|
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
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { FabBox } from '../FabBox';
|
|
3
3
|
import { ScrollTopFab } from '../ScrollTopFab';
|
|
4
|
-
import { PullToRefreshUI } from '../PullToRefreshUI';
|
|
5
4
|
import { Labels } from '../../app/Labels';
|
|
6
5
|
import { MUGlobal } from '../MUGlobal';
|
|
7
6
|
import { CommonPageProps } from './CommonPageProps';
|
|
@@ -10,11 +9,6 @@ import { ReactAppStateDetector } from '../../app/ReactApp';
|
|
|
10
9
|
import { Container, Fab } from '@mui/material';
|
|
11
10
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
12
11
|
|
|
13
|
-
/**
|
|
14
|
-
* Default pull container
|
|
15
|
-
*/
|
|
16
|
-
export const CommonPagePullContainer = '#page-container';
|
|
17
|
-
|
|
18
12
|
/**
|
|
19
13
|
* Default scroll container
|
|
20
14
|
*/
|
|
@@ -41,7 +35,6 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
41
35
|
paddings = MUGlobal.pagePaddings,
|
|
42
36
|
scrollContainer,
|
|
43
37
|
targetFields,
|
|
44
|
-
pullContainer,
|
|
45
38
|
sx = {},
|
|
46
39
|
...rest
|
|
47
40
|
} = props;
|
|
@@ -125,20 +118,6 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
125
118
|
</FabBox>
|
|
126
119
|
{children}
|
|
127
120
|
</Container>
|
|
128
|
-
{onRefresh != null && pullContainer != null && (
|
|
129
|
-
<PullToRefreshUI
|
|
130
|
-
mainElement={pullContainer}
|
|
131
|
-
triggerElement={pullContainer}
|
|
132
|
-
instructionsPullToRefresh={labels.pullToRefresh}
|
|
133
|
-
instructionsReleaseToRefresh={labels.releaseToRefresh}
|
|
134
|
-
instructionsRefreshing={labels.refreshing}
|
|
135
|
-
onRefresh={onRefresh}
|
|
136
|
-
shouldPullToRefresh={() => {
|
|
137
|
-
const container = document.querySelector(pullContainer);
|
|
138
|
-
return !container?.scrollTop;
|
|
139
|
-
}}
|
|
140
|
-
/>
|
|
141
|
-
)}
|
|
142
121
|
</React.Fragment>
|
|
143
122
|
);
|
|
144
123
|
}
|
|
@@ -75,7 +75,8 @@ export function DataGridPage<
|
|
|
75
75
|
React.useEffect(() => {
|
|
76
76
|
if (rect != null && rect.height > 50 && height == null) {
|
|
77
77
|
let gridHeight =
|
|
78
|
-
|
|
78
|
+
document.documentElement.clientHeight -
|
|
79
|
+
Math.round(rect.top + rect.height + 1);
|
|
79
80
|
|
|
80
81
|
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
81
82
|
const paddingBottom = parseFloat(style.paddingBottom);
|
|
@@ -113,18 +114,9 @@ export function DataGridPage<
|
|
|
113
114
|
ref.reset({ data });
|
|
114
115
|
}, [ref, data]);
|
|
115
116
|
|
|
116
|
-
// Pull container id
|
|
117
|
-
const pullContainer = states.element?.parentElement
|
|
118
|
-
? '.DataGridEx-Body'
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
117
|
// Layout
|
|
122
118
|
return (
|
|
123
|
-
<CommonPage
|
|
124
|
-
{...pageProps}
|
|
125
|
-
scrollContainer={states.element}
|
|
126
|
-
pullContainer={pullContainer}
|
|
127
|
-
>
|
|
119
|
+
<CommonPage {...pageProps} scrollContainer={states.element}>
|
|
128
120
|
<Stack>
|
|
129
121
|
<Box
|
|
130
122
|
ref={dimensions[0][0]}
|
|
@@ -85,7 +85,8 @@ export function FixedListPage<
|
|
|
85
85
|
const list = React.useMemo(() => {
|
|
86
86
|
if (rect != null && rect.height > 50) {
|
|
87
87
|
let height =
|
|
88
|
-
|
|
88
|
+
document.documentElement.clientHeight -
|
|
89
|
+
Math.round(rect.top + rect.height + 1);
|
|
89
90
|
|
|
90
91
|
if (adjustHeight != null) {
|
|
91
92
|
height -= adjustHeight(height);
|
|
@@ -113,11 +114,6 @@ export function FixedListPage<
|
|
|
113
114
|
}
|
|
114
115
|
}, [rect]);
|
|
115
116
|
|
|
116
|
-
// Pull container id
|
|
117
|
-
const pullContainer = scrollContainer?.parentElement
|
|
118
|
-
? '#' + scrollContainer?.parentElement.id
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
117
|
const { paddings, ...pageRest } = pageProps;
|
|
122
118
|
|
|
123
119
|
// Layout
|
|
@@ -126,7 +122,6 @@ export function FixedListPage<
|
|
|
126
122
|
{...pageRest}
|
|
127
123
|
paddings={{}}
|
|
128
124
|
scrollContainer={scrollContainer}
|
|
129
|
-
pullContainer={pullContainer}
|
|
130
125
|
>
|
|
131
126
|
<Stack>
|
|
132
127
|
<Box ref={dimensions[0][0]} sx={{ padding: paddings }}>
|
|
@@ -7,11 +7,7 @@ import useCombinedRefs from '../../uses/useCombinedRefs';
|
|
|
7
7
|
import { MUGlobal } from '../MUGlobal';
|
|
8
8
|
import { ScrollerListEx } from '../ScrollerListEx';
|
|
9
9
|
import { SearchBar } from '../SearchBar';
|
|
10
|
-
import {
|
|
11
|
-
CommonPage,
|
|
12
|
-
CommonPagePullContainer,
|
|
13
|
-
CommonPageScrollContainer
|
|
14
|
-
} from './CommonPage';
|
|
10
|
+
import { CommonPage, CommonPageScrollContainer } from './CommonPage';
|
|
15
11
|
import { ListPageProps } from './ListPageProps';
|
|
16
12
|
|
|
17
13
|
/**
|
|
@@ -69,11 +65,7 @@ export function ListPage<
|
|
|
69
65
|
|
|
70
66
|
// Layout
|
|
71
67
|
return (
|
|
72
|
-
<CommonPage
|
|
73
|
-
{...pageProps}
|
|
74
|
-
scrollContainer={CommonPageScrollContainer}
|
|
75
|
-
pullContainer={CommonPagePullContainer}
|
|
76
|
-
>
|
|
68
|
+
<CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
|
|
77
69
|
<Stack>
|
|
78
70
|
<Box
|
|
79
71
|
sx={{
|