@etsoo/react 1.4.24 → 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/ScrollerList.js +2 -0
- package/lib/mu/ResponsibleContainer.d.ts +1 -1
- package/lib/mu/ResponsibleContainer.js +27 -9
- package/lib/mu/SearchBar.js +28 -26
- 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 +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 +1 -1
- package/src/components/ScrollerList.tsx +3 -0
- package/src/mu/ResponsibleContainer.tsx +44 -12
- package/src/mu/SearchBar.tsx +25 -23
- 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
|
@@ -51,7 +51,7 @@ export interface ResponsibleContainerProps<T extends {}, F extends DataTypes.Bas
|
|
|
51
51
|
/**
|
|
52
52
|
* Listbox SX (dataGrid determines the case)
|
|
53
53
|
*/
|
|
54
|
-
listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
54
|
+
listBoxSx?: (dataGrid: boolean, height: number) => SxProps<Theme>;
|
|
55
55
|
/**
|
|
56
56
|
* Load data callback
|
|
57
57
|
*/
|
|
@@ -9,6 +9,15 @@ import { MUGlobal } from './MUGlobal';
|
|
|
9
9
|
import { PullToRefreshUI } from './PullToRefreshUI';
|
|
10
10
|
import { ScrollerListEx } from './ScrollerListEx';
|
|
11
11
|
import { SearchBar } from './SearchBar';
|
|
12
|
+
function getDefaultSearchBoxSx(paddings) {
|
|
13
|
+
const half = MUGlobal.half(paddings);
|
|
14
|
+
return {
|
|
15
|
+
paddingLeft: half,
|
|
16
|
+
paddingRight: half,
|
|
17
|
+
paddingTop: half,
|
|
18
|
+
marginBottom: half
|
|
19
|
+
};
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Responsible container
|
|
14
23
|
* @param props Props
|
|
@@ -16,7 +25,7 @@ import { SearchBar } from './SearchBar';
|
|
|
16
25
|
*/
|
|
17
26
|
export function ResponsibleContainer(props) {
|
|
18
27
|
// Destruct
|
|
19
|
-
const { adjustHeight, columns, dataGridMinWidth = DataGridExCalColumns(columns).total, fields, fieldTemplate, height, listBoxSx, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, searchBoxSx =
|
|
28
|
+
const { adjustHeight, columns, dataGridMinWidth = DataGridExCalColumns(columns).total, fields, fieldTemplate, height, listBoxSx, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, searchBoxSx = getDefaultSearchBoxSx(paddings), sizeReadyMiliseconds = 0, ...rest } = props;
|
|
20
29
|
// Labels
|
|
21
30
|
const labels = Labels.CommonPage;
|
|
22
31
|
// Refs
|
|
@@ -70,7 +79,7 @@ export function ResponsibleContainer(props) {
|
|
|
70
79
|
const [list, showDataGrid] = (() => {
|
|
71
80
|
// No layout
|
|
72
81
|
if (rect == null)
|
|
73
|
-
return [null,
|
|
82
|
+
return [null, undefined];
|
|
74
83
|
// Width
|
|
75
84
|
const width = rect.width;
|
|
76
85
|
// Show DataGrid or List dependng on width
|
|
@@ -95,7 +104,9 @@ export function ResponsibleContainer(props) {
|
|
|
95
104
|
// Delete
|
|
96
105
|
delete rest.itemRenderer;
|
|
97
106
|
return [
|
|
98
|
-
React.createElement(Box, { sx: listBoxSx == null
|
|
107
|
+
React.createElement(Box, { sx: listBoxSx == null
|
|
108
|
+
? undefined
|
|
109
|
+
: listBoxSx(true, heightLocal) },
|
|
99
110
|
React.createElement(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, columns: columns, ...rest })),
|
|
100
111
|
true
|
|
101
112
|
];
|
|
@@ -110,21 +121,28 @@ export function ResponsibleContainer(props) {
|
|
|
110
121
|
delete rest.hoverColor;
|
|
111
122
|
delete rest.selectable;
|
|
112
123
|
return [
|
|
113
|
-
React.createElement(Box, { sx: listBoxSx == null
|
|
124
|
+
React.createElement(Box, { sx: listBoxSx == null
|
|
125
|
+
? undefined
|
|
126
|
+
: listBoxSx(false, heightLocal) },
|
|
114
127
|
React.createElement(ScrollerListEx, { autoLoad: !hasFields, width: rect.width, height: heightLocal, loadData: localLoadData, mRef: mRefs, ...rest })),
|
|
115
128
|
false
|
|
116
129
|
];
|
|
117
130
|
})();
|
|
131
|
+
const searchBar = React.useMemo(() => {
|
|
132
|
+
if (!hasFields || showDataGrid == null)
|
|
133
|
+
return;
|
|
134
|
+
return (React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit, className: `searchBar${showDataGrid ? 'Grid' : 'List'}` }));
|
|
135
|
+
}, [showDataGrid, hasFields]);
|
|
118
136
|
// Pull container
|
|
119
|
-
const pullContainer =
|
|
120
|
-
?
|
|
137
|
+
const pullContainer = showDataGrid == null
|
|
138
|
+
? undefined
|
|
139
|
+
: showDataGrid
|
|
121
140
|
? '.DataGridEx-Body'
|
|
122
|
-
: '.ScrollerListEx-Body'
|
|
123
|
-
: undefined;
|
|
141
|
+
: '.ScrollerListEx-Body';
|
|
124
142
|
// Layout
|
|
125
143
|
return (React.createElement(React.Fragment, null,
|
|
126
144
|
React.createElement(Stack, null,
|
|
127
|
-
React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx },
|
|
145
|
+
React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx }, searchBar),
|
|
128
146
|
list),
|
|
129
147
|
pullToRefresh && pullContainer && (React.createElement(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => { var _a; return (_a = state.ref) === null || _a === void 0 ? void 0 : _a.reset(); }, shouldPullToRefresh: () => {
|
|
130
148
|
const container = document.querySelector(pullContainer);
|
package/lib/mu/SearchBar.js
CHANGED
|
@@ -63,12 +63,12 @@ export function SearchBar(props) {
|
|
|
63
63
|
const [index, updateIndex] = React.useState();
|
|
64
64
|
// Drawer open / close
|
|
65
65
|
const [open, updateOpen] = React.useState(false);
|
|
66
|
-
//
|
|
67
|
-
const
|
|
66
|
+
// State
|
|
67
|
+
const state = React.useRef({}).current;
|
|
68
68
|
// Watch container
|
|
69
69
|
const { dimensions } = useDimensions(1, (target, rect) => {
|
|
70
70
|
// Same logic from resetButtonRef
|
|
71
|
-
if (rect.width ===
|
|
71
|
+
if (rect.width === state.lastMaxWidth)
|
|
72
72
|
return false;
|
|
73
73
|
// Len
|
|
74
74
|
const len = target.children.length;
|
|
@@ -96,10 +96,10 @@ export function SearchBar(props) {
|
|
|
96
96
|
return;
|
|
97
97
|
// Container width
|
|
98
98
|
let maxWidth = containerRect.width;
|
|
99
|
-
if (maxWidth ===
|
|
99
|
+
if (maxWidth === state.lastMaxWidth) {
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
state.lastMaxWidth = maxWidth;
|
|
103
103
|
// More button
|
|
104
104
|
const buttonMore = resetButton.previousElementSibling;
|
|
105
105
|
// Cached button width
|
|
@@ -174,8 +174,8 @@ export function SearchBar(props) {
|
|
|
174
174
|
const handleForm = (event) => {
|
|
175
175
|
if (event.nativeEvent.cancelable && !event.nativeEvent.composed)
|
|
176
176
|
return;
|
|
177
|
-
if (
|
|
178
|
-
|
|
177
|
+
if (state.form == null)
|
|
178
|
+
state.form = event.currentTarget;
|
|
179
179
|
handleSubmit();
|
|
180
180
|
};
|
|
181
181
|
// Handle more button click
|
|
@@ -186,54 +186,56 @@ export function SearchBar(props) {
|
|
|
186
186
|
const moreFormChange = (event) => {
|
|
187
187
|
if (event.nativeEvent.cancelable && !event.nativeEvent.composed)
|
|
188
188
|
return;
|
|
189
|
-
if (
|
|
190
|
-
|
|
189
|
+
if (state.moreForm == null)
|
|
190
|
+
state.moreForm = event.currentTarget;
|
|
191
191
|
handleSubmit();
|
|
192
192
|
};
|
|
193
193
|
// Reset
|
|
194
194
|
const handleReset = () => {
|
|
195
195
|
// Clear form values
|
|
196
|
-
if (
|
|
197
|
-
resetForm(
|
|
198
|
-
if (
|
|
199
|
-
resetForm(
|
|
196
|
+
if (state.form != null)
|
|
197
|
+
resetForm(state.form);
|
|
198
|
+
if (state.moreForm != null)
|
|
199
|
+
resetForm(state.moreForm);
|
|
200
200
|
// Resubmit
|
|
201
201
|
handleSubmitInstant(true);
|
|
202
202
|
};
|
|
203
203
|
// Submit
|
|
204
204
|
const handleSubmit = (delay = 480) => {
|
|
205
|
-
if (
|
|
206
|
-
clearTimeout(
|
|
205
|
+
if (state.submitSeed != null) {
|
|
206
|
+
clearTimeout(state.submitSeed);
|
|
207
207
|
}
|
|
208
208
|
// Delay the change
|
|
209
|
-
|
|
209
|
+
state.submitSeed = window.setTimeout(handleSubmitInstant, delay);
|
|
210
210
|
};
|
|
211
211
|
// Submit at once
|
|
212
212
|
const handleSubmitInstant = (reset = false) => {
|
|
213
213
|
// Reset timeout
|
|
214
|
-
|
|
214
|
+
state.submitSeed = undefined;
|
|
215
215
|
// Prepare data
|
|
216
|
-
const data = new FormData(
|
|
217
|
-
if (
|
|
218
|
-
DomUtils.mergeFormData(data, new FormData(
|
|
216
|
+
const data = new FormData(state.form);
|
|
217
|
+
if (state.moreForm != null) {
|
|
218
|
+
DomUtils.mergeFormData(data, new FormData(state.moreForm));
|
|
219
219
|
}
|
|
220
220
|
onSubmit(data, reset);
|
|
221
221
|
};
|
|
222
222
|
// First loading
|
|
223
223
|
React.useEffect(() => {
|
|
224
|
-
// Delayed way
|
|
225
|
-
handleSubmit(100);
|
|
226
224
|
return () => {
|
|
227
225
|
// Clear the seeds
|
|
228
|
-
if (
|
|
229
|
-
clearTimeout(
|
|
226
|
+
if (state.submitSeed != null)
|
|
227
|
+
clearTimeout(state.submitSeed);
|
|
230
228
|
};
|
|
231
229
|
}, []);
|
|
230
|
+
React.useEffect(() => {
|
|
231
|
+
// Delayed way
|
|
232
|
+
handleSubmit(100);
|
|
233
|
+
}, [className]);
|
|
232
234
|
// Layout
|
|
233
235
|
return (React.createElement(React.Fragment, null,
|
|
234
236
|
React.createElement("form", { id: "SearchBarForm", className: className, onChange: handleForm, ref: (form) => {
|
|
235
237
|
if (form)
|
|
236
|
-
|
|
238
|
+
state.form = form;
|
|
237
239
|
} },
|
|
238
240
|
React.createElement(Stack, { ref: dimensions[0][0], justifyContent: "center", alignItems: "center", direction: "row", spacing: 1, height: innerHeight, sx: {
|
|
239
241
|
'& > :not(style)': {
|
|
@@ -260,7 +262,7 @@ export function SearchBar(props) {
|
|
|
260
262
|
}, open: open, onClose: () => updateOpen(false) },
|
|
261
263
|
React.createElement("form", { onChange: moreFormChange, ref: (form) => {
|
|
262
264
|
if (form)
|
|
263
|
-
|
|
265
|
+
state.moreForm = form;
|
|
264
266
|
} },
|
|
265
267
|
React.createElement(Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2 }, moreItems))))));
|
|
266
268
|
}
|
|
@@ -1,17 +1,12 @@
|
|
|
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 { MoreFab } from '../MoreFab';
|
|
8
7
|
import { ReactAppStateDetector } from '../../app/ReactApp';
|
|
9
8
|
import { Container, Fab } from '@mui/material';
|
|
10
9
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
11
|
-
/**
|
|
12
|
-
* Default pull container
|
|
13
|
-
*/
|
|
14
|
-
export const CommonPagePullContainer = '#page-container';
|
|
15
10
|
/**
|
|
16
11
|
* Default scroll container
|
|
17
12
|
*/
|
|
@@ -22,7 +17,7 @@ export const CommonPageScrollContainer = global;
|
|
|
22
17
|
*/
|
|
23
18
|
export function CommonPage(props) {
|
|
24
19
|
// Destruct
|
|
25
|
-
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, targetFields,
|
|
20
|
+
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, targetFields, sx = {}, ...rest } = props;
|
|
26
21
|
// Merge style
|
|
27
22
|
Object.assign(sx, {
|
|
28
23
|
padding: paddings
|
|
@@ -59,9 +54,5 @@ export function CommonPage(props) {
|
|
|
59
54
|
onRefresh != null && (React.createElement(Fab, { title: labels.refresh, size: fabSize, onClick: onRefresh, sx: { display: { xs: 'none', md: 'inherit' } } },
|
|
60
55
|
React.createElement(RefreshIcon, null))),
|
|
61
56
|
React.createElement(MoreFab, { size: fabSize, title: labels.more, actions: moreActions })),
|
|
62
|
-
children)
|
|
63
|
-
onRefresh != null && pullContainer != null && (React.createElement(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: onRefresh, shouldPullToRefresh: () => {
|
|
64
|
-
const container = document.querySelector(pullContainer);
|
|
65
|
-
return !(container === null || container === void 0 ? void 0 : container.scrollTop);
|
|
66
|
-
} }))));
|
|
57
|
+
children)));
|
|
67
58
|
}
|
|
@@ -13,7 +13,7 @@ import { CommonPage } from './CommonPage';
|
|
|
13
13
|
* @returns Component
|
|
14
14
|
*/
|
|
15
15
|
export function DataGridPage(props) {
|
|
16
|
-
var _a
|
|
16
|
+
var _a;
|
|
17
17
|
// Destruct
|
|
18
18
|
const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, ...rest } = props;
|
|
19
19
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
@@ -69,12 +69,8 @@ export function DataGridPage(props) {
|
|
|
69
69
|
return;
|
|
70
70
|
ref.reset({ data });
|
|
71
71
|
}, [ref, data]);
|
|
72
|
-
// Pull container id
|
|
73
|
-
const pullContainer = ((_b = states.element) === null || _b === void 0 ? void 0 : _b.parentElement)
|
|
74
|
-
? '.DataGridEx-Body'
|
|
75
|
-
: undefined;
|
|
76
72
|
// Layout
|
|
77
|
-
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: states.element
|
|
73
|
+
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: states.element },
|
|
78
74
|
React.createElement(Stack, null,
|
|
79
75
|
React.createElement(Box, { ref: dimensions[0][0], sx: {
|
|
80
76
|
paddingBottom: pageProps.paddings
|
|
@@ -61,13 +61,9 @@ export function FixedListPage(props) {
|
|
|
61
61
|
}, ...rest })));
|
|
62
62
|
}
|
|
63
63
|
}, [rect]);
|
|
64
|
-
// Pull container id
|
|
65
|
-
const pullContainer = (scrollContainer === null || scrollContainer === void 0 ? void 0 : scrollContainer.parentElement)
|
|
66
|
-
? '#' + (scrollContainer === null || scrollContainer === void 0 ? void 0 : scrollContainer.parentElement.id)
|
|
67
|
-
: undefined;
|
|
68
64
|
const { paddings, ...pageRest } = pageProps;
|
|
69
65
|
// Layout
|
|
70
|
-
return (React.createElement(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer
|
|
66
|
+
return (React.createElement(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer },
|
|
71
67
|
React.createElement(Stack, null,
|
|
72
68
|
React.createElement(Box, { ref: dimensions[0][0], sx: { padding: paddings } },
|
|
73
69
|
React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit })),
|
package/lib/mu/pages/ListPage.js
CHANGED
|
@@ -5,7 +5,7 @@ import useCombinedRefs from '../../uses/useCombinedRefs';
|
|
|
5
5
|
import { MUGlobal } from '../MUGlobal';
|
|
6
6
|
import { ScrollerListEx } from '../ScrollerListEx';
|
|
7
7
|
import { SearchBar } from '../SearchBar';
|
|
8
|
-
import { CommonPage,
|
|
8
|
+
import { CommonPage, CommonPageScrollContainer } from './CommonPage';
|
|
9
9
|
/**
|
|
10
10
|
* List page
|
|
11
11
|
* @param props Props
|
|
@@ -41,7 +41,7 @@ export function ListPage(props) {
|
|
|
41
41
|
return loadData(data);
|
|
42
42
|
};
|
|
43
43
|
// Layout
|
|
44
|
-
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer
|
|
44
|
+
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer },
|
|
45
45
|
React.createElement(Stack, null,
|
|
46
46
|
React.createElement(Box, { sx: {
|
|
47
47
|
paddingBottom: pageProps.paddings
|
|
@@ -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
|
@@ -91,7 +91,7 @@ export interface ResponsibleContainerProps<
|
|
|
91
91
|
/**
|
|
92
92
|
* Listbox SX (dataGrid determines the case)
|
|
93
93
|
*/
|
|
94
|
-
listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
94
|
+
listBoxSx?: (dataGrid: boolean, height: number) => SxProps<Theme>;
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
97
|
* Load data callback
|
|
@@ -132,6 +132,16 @@ interface LocalRefs {
|
|
|
132
132
|
mounted?: boolean;
|
|
133
133
|
}
|
|
134
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
|
+
|
|
135
145
|
/**
|
|
136
146
|
* Responsible container
|
|
137
147
|
* @param props Props
|
|
@@ -154,7 +164,7 @@ export function ResponsibleContainer<
|
|
|
154
164
|
mRef,
|
|
155
165
|
paddings = MUGlobal.pagePaddings,
|
|
156
166
|
pullToRefresh = true,
|
|
157
|
-
searchBoxSx =
|
|
167
|
+
searchBoxSx = getDefaultSearchBoxSx(paddings),
|
|
158
168
|
sizeReadyMiliseconds = 0,
|
|
159
169
|
...rest
|
|
160
170
|
} = props;
|
|
@@ -228,7 +238,7 @@ export function ResponsibleContainer<
|
|
|
228
238
|
// Create list
|
|
229
239
|
const [list, showDataGrid] = (() => {
|
|
230
240
|
// No layout
|
|
231
|
-
if (rect == null) return [null,
|
|
241
|
+
if (rect == null) return [null, undefined];
|
|
232
242
|
|
|
233
243
|
// Width
|
|
234
244
|
const width = rect.width;
|
|
@@ -258,7 +268,13 @@ export function ResponsibleContainer<
|
|
|
258
268
|
delete rest.itemRenderer;
|
|
259
269
|
|
|
260
270
|
return [
|
|
261
|
-
<Box
|
|
271
|
+
<Box
|
|
272
|
+
sx={
|
|
273
|
+
listBoxSx == null
|
|
274
|
+
? undefined
|
|
275
|
+
: listBoxSx(true, heightLocal)
|
|
276
|
+
}
|
|
277
|
+
>
|
|
262
278
|
<DataGridEx<T>
|
|
263
279
|
autoLoad={!hasFields}
|
|
264
280
|
height={heightLocal}
|
|
@@ -284,7 +300,13 @@ export function ResponsibleContainer<
|
|
|
284
300
|
delete rest.selectable;
|
|
285
301
|
|
|
286
302
|
return [
|
|
287
|
-
<Box
|
|
303
|
+
<Box
|
|
304
|
+
sx={
|
|
305
|
+
listBoxSx == null
|
|
306
|
+
? undefined
|
|
307
|
+
: listBoxSx(false, heightLocal)
|
|
308
|
+
}
|
|
309
|
+
>
|
|
288
310
|
<ScrollerListEx<T>
|
|
289
311
|
autoLoad={!hasFields}
|
|
290
312
|
width={rect.width}
|
|
@@ -298,21 +320,31 @@ export function ResponsibleContainer<
|
|
|
298
320
|
];
|
|
299
321
|
})();
|
|
300
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
|
+
|
|
301
334
|
// Pull container
|
|
302
|
-
const pullContainer =
|
|
303
|
-
|
|
335
|
+
const pullContainer =
|
|
336
|
+
showDataGrid == null
|
|
337
|
+
? undefined
|
|
338
|
+
: showDataGrid
|
|
304
339
|
? '.DataGridEx-Body'
|
|
305
|
-
: '.ScrollerListEx-Body'
|
|
306
|
-
: undefined;
|
|
340
|
+
: '.ScrollerListEx-Body';
|
|
307
341
|
|
|
308
342
|
// Layout
|
|
309
343
|
return (
|
|
310
344
|
<React.Fragment>
|
|
311
345
|
<Stack>
|
|
312
346
|
<Box ref={dimensions[0][0]} sx={searchBoxSx}>
|
|
313
|
-
{
|
|
314
|
-
<SearchBar fields={fields} onSubmit={onSubmit} />
|
|
315
|
-
)}
|
|
347
|
+
{searchBar}
|
|
316
348
|
</Box>
|
|
317
349
|
{list}
|
|
318
350
|
</Stack>
|
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,8 +263,8 @@ 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);
|
|
@@ -272,23 +272,23 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
272
272
|
|
|
273
273
|
// Submit
|
|
274
274
|
const handleSubmit = (delay = 480) => {
|
|
275
|
-
if (
|
|
276
|
-
clearTimeout(
|
|
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(100);
|
|
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
|
}
|
|
@@ -113,18 +113,9 @@ export function DataGridPage<
|
|
|
113
113
|
ref.reset({ data });
|
|
114
114
|
}, [ref, data]);
|
|
115
115
|
|
|
116
|
-
// Pull container id
|
|
117
|
-
const pullContainer = states.element?.parentElement
|
|
118
|
-
? '.DataGridEx-Body'
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
116
|
// Layout
|
|
122
117
|
return (
|
|
123
|
-
<CommonPage
|
|
124
|
-
{...pageProps}
|
|
125
|
-
scrollContainer={states.element}
|
|
126
|
-
pullContainer={pullContainer}
|
|
127
|
-
>
|
|
118
|
+
<CommonPage {...pageProps} scrollContainer={states.element}>
|
|
128
119
|
<Stack>
|
|
129
120
|
<Box
|
|
130
121
|
ref={dimensions[0][0]}
|
|
@@ -113,11 +113,6 @@ export function FixedListPage<
|
|
|
113
113
|
}
|
|
114
114
|
}, [rect]);
|
|
115
115
|
|
|
116
|
-
// Pull container id
|
|
117
|
-
const pullContainer = scrollContainer?.parentElement
|
|
118
|
-
? '#' + scrollContainer?.parentElement.id
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
116
|
const { paddings, ...pageRest } = pageProps;
|
|
122
117
|
|
|
123
118
|
// Layout
|
|
@@ -126,7 +121,6 @@ export function FixedListPage<
|
|
|
126
121
|
{...pageRest}
|
|
127
122
|
paddings={{}}
|
|
128
123
|
scrollContainer={scrollContainer}
|
|
129
|
-
pullContainer={pullContainer}
|
|
130
124
|
>
|
|
131
125
|
<Stack>
|
|
132
126
|
<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={{
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { DataTypes } from '@etsoo/shared';
|
|
2
|
-
import { Box, Stack } from '@mui/material';
|
|
3
2
|
import React from 'react';
|
|
4
|
-
import { GridDataGet, GridLoadDataProps } from '../../components/GridLoader';
|
|
5
|
-
import useCombinedRefs from '../../uses/useCombinedRefs';
|
|
6
|
-
import { useDimensions } from '../../uses/useDimensions';
|
|
7
|
-
import { DataGridEx, DataGridExCalColumns } from '../DataGridEx';
|
|
8
|
-
import { GridMethodRef } from '../GridMethodRef';
|
|
9
3
|
import { MUGlobal } from '../MUGlobal';
|
|
10
|
-
import {
|
|
11
|
-
import { SearchBar } from '../SearchBar';
|
|
4
|
+
import { ResponsibleContainer } from '../ResponsibleContainer';
|
|
12
5
|
import { CommonPage } from './CommonPage';
|
|
13
6
|
import { ResponsePageProps } from './ResponsivePageProps';
|
|
14
7
|
|
|
15
|
-
interface LocalStates {
|
|
16
|
-
data?: FormData;
|
|
17
|
-
element?: HTMLElement;
|
|
18
|
-
height?: number;
|
|
19
|
-
ref?: GridMethodRef;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
8
|
/**
|
|
23
9
|
* Fixed height list page
|
|
24
10
|
* @param props Props
|
|
@@ -29,193 +15,33 @@ export function ResponsivePage<
|
|
|
29
15
|
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
|
|
30
16
|
>(props: ResponsePageProps<T, F>) {
|
|
31
17
|
// Destruct
|
|
32
|
-
const {
|
|
33
|
-
adjustHeight,
|
|
34
|
-
columns,
|
|
35
|
-
dataGridMinWidth = DataGridExCalColumns(columns).total,
|
|
36
|
-
fields,
|
|
37
|
-
fieldTemplate,
|
|
38
|
-
height,
|
|
39
|
-
loadData,
|
|
40
|
-
innerItemRenderer,
|
|
41
|
-
itemSize,
|
|
42
|
-
mRef,
|
|
43
|
-
sizeReadyMiliseconds = 0,
|
|
44
|
-
pageProps = {},
|
|
45
|
-
...rest
|
|
46
|
-
} = props;
|
|
18
|
+
const { pageProps = {}, ...rest } = props;
|
|
47
19
|
|
|
48
20
|
pageProps.paddings ??= MUGlobal.pagePaddings;
|
|
49
|
-
|
|
50
|
-
// States
|
|
51
|
-
const [states, setStates] = React.useReducer(
|
|
52
|
-
(currentState: LocalStates, newState: Partial<LocalStates>) => {
|
|
53
|
-
return { ...currentState, ...newState };
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
height
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
const localLoadData = (props: GridLoadDataProps) => {
|
|
61
|
-
const data = GridDataGet(props, fieldTemplate);
|
|
62
|
-
return loadData(data);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const refs = useCombinedRefs(mRef, (ref: GridMethodRef) => {
|
|
66
|
-
if (ref == null) return;
|
|
67
|
-
states.ref = ref;
|
|
68
|
-
// setStates({ ref });
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// On submit callback
|
|
72
|
-
const onSubmit = (data: FormData, _reset: boolean) => {
|
|
73
|
-
setStates({ data });
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// Watch container
|
|
77
|
-
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
78
|
-
const rect = dimensions[0][2];
|
|
79
|
-
const showDataGrid = (rect?.width ?? 0) >= dataGridMinWidth;
|
|
80
|
-
|
|
81
|
-
React.useEffect(() => {
|
|
82
|
-
if (rect != null && rect.height > 50 && height == null) {
|
|
83
|
-
let gridHeight =
|
|
84
|
-
window.innerHeight - Math.round(rect.top + rect.height + 1);
|
|
85
|
-
|
|
86
|
-
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
87
|
-
const boxPadding = parseFloat(style.paddingLeft);
|
|
88
|
-
if (!isNaN(boxPadding)) gridHeight -= 2 * boxPadding;
|
|
89
|
-
|
|
90
|
-
if (adjustHeight != null) {
|
|
91
|
-
gridHeight -= adjustHeight(gridHeight);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (gridHeight !== states.height) setStates({ height: gridHeight });
|
|
95
|
-
}
|
|
96
|
-
}, [rect]);
|
|
97
|
-
|
|
98
21
|
const { paddings, ...pageRest } = pageProps;
|
|
99
22
|
|
|
100
|
-
const
|
|
101
|
-
const gridHeight = states.height;
|
|
102
|
-
if (gridHeight == null) return;
|
|
103
|
-
|
|
104
|
-
// Show in a row when under DataGrid
|
|
105
|
-
pageProps.fabColumnDirection = !showDataGrid;
|
|
106
|
-
|
|
107
|
-
if (showDataGrid) {
|
|
108
|
-
// Delete
|
|
109
|
-
delete rest.itemRenderer;
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<Box
|
|
113
|
-
sx={{
|
|
114
|
-
padding: paddings
|
|
115
|
-
}}
|
|
116
|
-
>
|
|
117
|
-
<DataGridEx<T>
|
|
118
|
-
autoLoad={false}
|
|
119
|
-
height={gridHeight}
|
|
120
|
-
loadData={localLoadData}
|
|
121
|
-
mRef={refs}
|
|
122
|
-
columns={columns}
|
|
123
|
-
outerRef={(element?: HTMLDivElement) => {
|
|
124
|
-
if (element != null) setStates({ element });
|
|
125
|
-
}}
|
|
126
|
-
{...rest}
|
|
127
|
-
/>
|
|
128
|
-
</Box>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Delete
|
|
133
|
-
delete rest.checkable;
|
|
134
|
-
delete rest.borderRowsCount;
|
|
135
|
-
delete rest.bottomHeight;
|
|
136
|
-
delete rest.footerItemRenderer;
|
|
137
|
-
delete rest.headerHeight;
|
|
138
|
-
delete rest.hideFooter;
|
|
139
|
-
delete rest.hoverColor;
|
|
140
|
-
delete rest.selectable;
|
|
141
|
-
|
|
142
|
-
// Half
|
|
143
|
-
const halfPadding = MUGlobal.half(paddings);
|
|
144
|
-
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
145
|
-
const boxPadding = parseFloat(style.paddingLeft);
|
|
146
|
-
|
|
147
|
-
return (
|
|
148
|
-
<Box
|
|
149
|
-
sx={{
|
|
150
|
-
height: gridHeight + (isNaN(boxPadding) ? 0 : boxPadding),
|
|
151
|
-
paddingTop: halfPadding,
|
|
152
|
-
paddingBottom: halfPadding
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
<ScrollerListEx<T>
|
|
156
|
-
autoLoad={false}
|
|
157
|
-
height={gridHeight}
|
|
158
|
-
innerItemRenderer={innerItemRenderer}
|
|
159
|
-
itemSize={itemSize}
|
|
160
|
-
loadData={localLoadData}
|
|
161
|
-
mRef={refs}
|
|
162
|
-
oRef={(element) => {
|
|
163
|
-
if (element != null) setStates({ element });
|
|
164
|
-
}}
|
|
165
|
-
{...rest}
|
|
166
|
-
/>
|
|
167
|
-
</Box>
|
|
168
|
-
);
|
|
169
|
-
}, [states.height, showDataGrid, localLoadData]);
|
|
170
|
-
|
|
171
|
-
const sizeRef = React.useRef<[number, number]>();
|
|
172
|
-
|
|
173
|
-
const { ref, data } = states;
|
|
174
|
-
React.useEffect(() => {
|
|
175
|
-
if (ref == null || data == null || rect == null) return;
|
|
176
|
-
|
|
177
|
-
// Resize without reset
|
|
178
|
-
if (sizeRef.current == null) {
|
|
179
|
-
sizeRef.current = [rect.width, rect.height];
|
|
180
|
-
} else if (
|
|
181
|
-
sizeRef.current[0] !== rect.width ||
|
|
182
|
-
sizeRef.current[1] !== rect.height
|
|
183
|
-
) {
|
|
184
|
-
sizeRef.current = [rect.width, rect.height];
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
ref.reset({ data });
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Pull container id
|
|
192
|
-
const pullContainer = states.element
|
|
193
|
-
? showDataGrid
|
|
194
|
-
? '.DataGridEx-Body'
|
|
195
|
-
: '.ScrollerListEx-Body'
|
|
196
|
-
: undefined;
|
|
23
|
+
const halfPadding = MUGlobal.half(paddings);
|
|
197
24
|
|
|
198
25
|
// Layout
|
|
199
26
|
return (
|
|
200
|
-
<CommonPage
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
</Stack>
|
|
27
|
+
<CommonPage {...pageRest} paddings={{}}>
|
|
28
|
+
<ResponsibleContainer<T, F>
|
|
29
|
+
paddings={paddings}
|
|
30
|
+
listBoxSx={(dataGrid, height) => {
|
|
31
|
+
if (dataGrid) {
|
|
32
|
+
return {
|
|
33
|
+
padding: paddings
|
|
34
|
+
};
|
|
35
|
+
} else {
|
|
36
|
+
return {
|
|
37
|
+
height,
|
|
38
|
+
paddingTop: halfPadding,
|
|
39
|
+
paddingBottom: halfPadding
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}}
|
|
43
|
+
{...rest}
|
|
44
|
+
/>
|
|
219
45
|
</CommonPage>
|
|
220
46
|
);
|
|
221
47
|
}
|
|
@@ -7,11 +7,7 @@ import { useDimensions } from '../../uses/useDimensions';
|
|
|
7
7
|
import { MUGlobal } from '../MUGlobal';
|
|
8
8
|
import { SearchBar } from '../SearchBar';
|
|
9
9
|
import { TableEx, TableExMethodRef, TableExMinWidth } from '../TableEx';
|
|
10
|
-
import {
|
|
11
|
-
CommonPage,
|
|
12
|
-
CommonPagePullContainer,
|
|
13
|
-
CommonPageScrollContainer
|
|
14
|
-
} from './CommonPage';
|
|
10
|
+
import { CommonPage, CommonPageScrollContainer } from './CommonPage';
|
|
15
11
|
import { TablePageProps } from './TablePageProps';
|
|
16
12
|
|
|
17
13
|
/**
|
|
@@ -104,11 +100,7 @@ export function TablePage<
|
|
|
104
100
|
|
|
105
101
|
// Layout
|
|
106
102
|
return (
|
|
107
|
-
<CommonPage
|
|
108
|
-
{...pageProps}
|
|
109
|
-
scrollContainer={CommonPageScrollContainer}
|
|
110
|
-
pullContainer={CommonPagePullContainer}
|
|
111
|
-
>
|
|
103
|
+
<CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
|
|
112
104
|
<Stack>
|
|
113
105
|
<Box
|
|
114
106
|
ref={dimensions[0][0]}
|