@etsoo/react 1.4.25 → 1.4.29
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 +1 -1
- package/lib/mu/ResponsibleContainer.d.ts +8 -0
- package/lib/mu/ResponsibleContainer.js +19 -9
- package/lib/mu/SearchBar.js +8 -3
- package/lib/mu/pages/DataGridPage.js +2 -1
- package/lib/mu/pages/FixedListPage.js +2 -1
- package/lib/mu/pages/ResponsivePage.js +20 -7
- package/lib/mu/pages/TablePage.js +2 -1
- package/lib/uses/useWindowSize.d.ts +6 -5
- package/lib/uses/useWindowSize.js +22 -16
- package/package.json +1 -1
- package/src/components/ScrollerList.tsx +1 -1
- package/src/mu/ResponsibleContainer.tsx +34 -7
- package/src/mu/SearchBar.tsx +13 -3
- package/src/mu/pages/DataGridPage.tsx +2 -1
- package/src/mu/pages/FixedListPage.tsx +2 -1
- package/src/mu/pages/ResponsivePage.tsx +26 -7
- package/src/mu/pages/TablePage.tsx +3 -1
- package/src/uses/useWindowSize.ts +32 -19
|
@@ -15,7 +15,7 @@ const calculateBatchSize = (height, itemSize) => {
|
|
|
15
15
|
*/
|
|
16
16
|
export const ScrollerList = (props) => {
|
|
17
17
|
// Destruct
|
|
18
|
-
const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height =
|
|
18
|
+
const { autoLoad = true, defaultOrderBy, defaultOrderByAsc, height = document.documentElement.clientHeight, width = '100%', mRef, oRef, style = {}, itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, ...rest } = props;
|
|
19
19
|
// Style
|
|
20
20
|
Object.assign(style, {
|
|
21
21
|
width: '100%',
|
|
@@ -20,6 +20,10 @@ export interface ResponsibleContainerProps<T extends {}, F extends DataTypes.Bas
|
|
|
20
20
|
* Columns
|
|
21
21
|
*/
|
|
22
22
|
columns: GridColumn<T>[];
|
|
23
|
+
/**
|
|
24
|
+
* Container box SX (dataGrid determines the case)
|
|
25
|
+
*/
|
|
26
|
+
containerBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
|
|
23
27
|
/**
|
|
24
28
|
* Min width to show Datagrid
|
|
25
29
|
*/
|
|
@@ -60,6 +64,10 @@ export interface ResponsibleContainerProps<T extends {}, F extends DataTypes.Bas
|
|
|
60
64
|
* Methods
|
|
61
65
|
*/
|
|
62
66
|
mRef?: React.MutableRefObject<GridMethodRef | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Element ready callback
|
|
69
|
+
*/
|
|
70
|
+
elementReady?: (element: HTMLElement, isDataGrid: boolean) => void;
|
|
63
71
|
/**
|
|
64
72
|
* Paddings
|
|
65
73
|
*/
|
|
@@ -12,8 +12,8 @@ import { SearchBar } from './SearchBar';
|
|
|
12
12
|
function getDefaultSearchBoxSx(paddings) {
|
|
13
13
|
const half = MUGlobal.half(paddings);
|
|
14
14
|
return {
|
|
15
|
-
paddingLeft:
|
|
16
|
-
paddingRight:
|
|
15
|
+
paddingLeft: (theme) => theme.spacing(0.5),
|
|
16
|
+
paddingRight: (theme) => theme.spacing(0.5),
|
|
17
17
|
paddingTop: half,
|
|
18
18
|
marginBottom: half
|
|
19
19
|
};
|
|
@@ -25,7 +25,7 @@ function getDefaultSearchBoxSx(paddings) {
|
|
|
25
25
|
*/
|
|
26
26
|
export function ResponsibleContainer(props) {
|
|
27
27
|
// Destruct
|
|
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;
|
|
28
|
+
const { adjustHeight, columns, containerBoxSx, dataGridMinWidth = DataGridExCalColumns(columns).total, elementReady, fields, fieldTemplate, height, listBoxSx, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, searchBoxSx = getDefaultSearchBoxSx(paddings), sizeReadyMiliseconds = 0, ...rest } = props;
|
|
29
29
|
// Labels
|
|
30
30
|
const labels = Labels.CommonPage;
|
|
31
31
|
// Refs
|
|
@@ -64,6 +64,7 @@ export function ResponsibleContainer(props) {
|
|
|
64
64
|
// Last rect
|
|
65
65
|
const lastRect = state.rect;
|
|
66
66
|
// 32 = scroll bar width
|
|
67
|
+
console.log(lastRect, rect);
|
|
67
68
|
if (lastRect != null &&
|
|
68
69
|
state.mounted !== true &&
|
|
69
70
|
Math.abs(rect.width - lastRect.width) <= 32 &&
|
|
@@ -91,7 +92,9 @@ export function ResponsibleContainer(props) {
|
|
|
91
92
|
}
|
|
92
93
|
else {
|
|
93
94
|
// Auto calculation
|
|
94
|
-
heightLocal =
|
|
95
|
+
heightLocal =
|
|
96
|
+
document.documentElement.clientHeight -
|
|
97
|
+
Math.round(rect.bottom + 1);
|
|
95
98
|
const style = window.getComputedStyle(dimensions[0][1]);
|
|
96
99
|
const boxMargin = parseFloat(style.marginBottom);
|
|
97
100
|
if (!isNaN(boxMargin))
|
|
@@ -107,7 +110,10 @@ export function ResponsibleContainer(props) {
|
|
|
107
110
|
React.createElement(Box, { sx: listBoxSx == null
|
|
108
111
|
? undefined
|
|
109
112
|
: listBoxSx(true, heightLocal) },
|
|
110
|
-
React.createElement(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs,
|
|
113
|
+
React.createElement(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, outerRef: (element) => {
|
|
114
|
+
if (element != null && elementReady)
|
|
115
|
+
elementReady(element, true);
|
|
116
|
+
}, columns: columns, ...rest })),
|
|
111
117
|
true
|
|
112
118
|
];
|
|
113
119
|
}
|
|
@@ -124,7 +130,10 @@ export function ResponsibleContainer(props) {
|
|
|
124
130
|
React.createElement(Box, { sx: listBoxSx == null
|
|
125
131
|
? undefined
|
|
126
132
|
: listBoxSx(false, heightLocal) },
|
|
127
|
-
React.createElement(ScrollerListEx, { autoLoad: !hasFields,
|
|
133
|
+
React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, oRef: (element) => {
|
|
134
|
+
if (element != null && elementReady)
|
|
135
|
+
elementReady(element, false);
|
|
136
|
+
}, ...rest })),
|
|
128
137
|
false
|
|
129
138
|
];
|
|
130
139
|
})();
|
|
@@ -140,10 +149,11 @@ export function ResponsibleContainer(props) {
|
|
|
140
149
|
? '.DataGridEx-Body'
|
|
141
150
|
: '.ScrollerListEx-Body';
|
|
142
151
|
// Layout
|
|
143
|
-
return (React.createElement(
|
|
152
|
+
return (React.createElement(Box, { sx: containerBoxSx == null || showDataGrid == null
|
|
153
|
+
? undefined
|
|
154
|
+
: containerBoxSx(showDataGrid) },
|
|
144
155
|
React.createElement(Stack, null,
|
|
145
|
-
React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx }, searchBar),
|
|
146
|
-
list),
|
|
156
|
+
React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx }, searchBar)),
|
|
147
157
|
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: () => {
|
|
148
158
|
const container = document.querySelector(pullContainer);
|
|
149
159
|
return !(container === null || container === void 0 ? void 0 : container.scrollTop);
|
package/lib/mu/SearchBar.js
CHANGED
|
@@ -52,6 +52,7 @@ const setChildState = (child, enabled) => {
|
|
|
52
52
|
* @returns Component
|
|
53
53
|
*/
|
|
54
54
|
export function SearchBar(props) {
|
|
55
|
+
var _a;
|
|
55
56
|
// Destruct
|
|
56
57
|
const { className, fields, innerHeight = 40, onSubmit } = props;
|
|
57
58
|
// Labels
|
|
@@ -64,11 +65,13 @@ export function SearchBar(props) {
|
|
|
64
65
|
// Drawer open / close
|
|
65
66
|
const [open, updateOpen] = React.useState(false);
|
|
66
67
|
// State
|
|
67
|
-
const state = React.useRef({}).current;
|
|
68
|
+
const state = React.useRef({ hasMore: true }).current;
|
|
69
|
+
const lastMaxWidth = (_a = state.lastMaxWidth) !== null && _a !== void 0 ? _a : 9999;
|
|
68
70
|
// Watch container
|
|
69
71
|
const { dimensions } = useDimensions(1, (target, rect) => {
|
|
70
72
|
// Same logic from resetButtonRef
|
|
71
|
-
if (rect.width ===
|
|
73
|
+
if (rect.width === lastMaxWidth ||
|
|
74
|
+
(!state.hasMore && rect.width > lastMaxWidth))
|
|
72
75
|
return false;
|
|
73
76
|
// Len
|
|
74
77
|
const len = target.children.length;
|
|
@@ -96,7 +99,8 @@ export function SearchBar(props) {
|
|
|
96
99
|
return;
|
|
97
100
|
// Container width
|
|
98
101
|
let maxWidth = containerRect.width;
|
|
99
|
-
if (maxWidth ===
|
|
102
|
+
if (maxWidth === lastMaxWidth ||
|
|
103
|
+
(!state.hasMore && maxWidth > lastMaxWidth)) {
|
|
100
104
|
return;
|
|
101
105
|
}
|
|
102
106
|
state.lastMaxWidth = maxWidth;
|
|
@@ -158,6 +162,7 @@ export function SearchBar(props) {
|
|
|
158
162
|
}
|
|
159
163
|
}
|
|
160
164
|
// Show or hide more button
|
|
165
|
+
state.hasMore = hasMore;
|
|
161
166
|
setElementVisible(buttonMore, hasMore);
|
|
162
167
|
setElementVisible(resetButton, true);
|
|
163
168
|
// Update menu start index
|
|
@@ -42,7 +42,8 @@ export function DataGridPage(props) {
|
|
|
42
42
|
const rect = dimensions[0][2];
|
|
43
43
|
React.useEffect(() => {
|
|
44
44
|
if (rect != null && rect.height > 50 && height == null) {
|
|
45
|
-
let gridHeight =
|
|
45
|
+
let gridHeight = document.documentElement.clientHeight -
|
|
46
|
+
Math.round(rect.top + rect.height + 1);
|
|
46
47
|
const style = window.getComputedStyle(dimensions[0][1]);
|
|
47
48
|
const paddingBottom = parseFloat(style.paddingBottom);
|
|
48
49
|
if (!isNaN(paddingBottom))
|
|
@@ -48,7 +48,8 @@ export function FixedListPage(props) {
|
|
|
48
48
|
const rect = dimensions[0][2];
|
|
49
49
|
const list = React.useMemo(() => {
|
|
50
50
|
if (rect != null && rect.height > 50) {
|
|
51
|
-
let height =
|
|
51
|
+
let height = document.documentElement.clientHeight -
|
|
52
|
+
Math.round(rect.top + rect.height + 1);
|
|
52
53
|
if (adjustHeight != null) {
|
|
53
54
|
height -= adjustHeight(height);
|
|
54
55
|
}
|
|
@@ -12,11 +12,13 @@ export function ResponsivePage(props) {
|
|
|
12
12
|
// Destruct
|
|
13
13
|
const { pageProps = {}, ...rest } = props;
|
|
14
14
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
15
|
-
const { paddings, ...pageRest } = pageProps;
|
|
16
|
-
|
|
15
|
+
const { paddings, fabColumnDirection, ...pageRest } = pageProps;
|
|
16
|
+
// State
|
|
17
|
+
const [scrollContainer, setScrollContainer] = React.useState();
|
|
18
|
+
const [direction, setDirection] = React.useState(fabColumnDirection);
|
|
17
19
|
// Layout
|
|
18
|
-
return (React.createElement(CommonPage, { ...pageRest, paddings: {} },
|
|
19
|
-
React.createElement(ResponsibleContainer, { paddings: paddings,
|
|
20
|
+
return (React.createElement(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, fabColumnDirection: direction },
|
|
21
|
+
React.createElement(ResponsibleContainer, { paddings: paddings, containerBoxSx: (dataGrid) => {
|
|
20
22
|
if (dataGrid) {
|
|
21
23
|
return {
|
|
22
24
|
padding: paddings
|
|
@@ -24,9 +26,20 @@ export function ResponsivePage(props) {
|
|
|
24
26
|
}
|
|
25
27
|
else {
|
|
26
28
|
return {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
paddingTop: paddings,
|
|
30
|
+
paddingBottom: paddings
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}, elementReady: (element, isDataGrid) => {
|
|
34
|
+
setDirection(!isDataGrid);
|
|
35
|
+
setScrollContainer(element);
|
|
36
|
+
}, listBoxSx: (dataGrid, height) => {
|
|
37
|
+
if (dataGrid) {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return {
|
|
42
|
+
height: height
|
|
30
43
|
};
|
|
31
44
|
}
|
|
32
45
|
}, ...rest })));
|
|
@@ -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))
|
|
@@ -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
|
@@ -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
|
*/
|
|
@@ -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
|
*/
|
|
@@ -135,8 +145,8 @@ interface LocalRefs {
|
|
|
135
145
|
function getDefaultSearchBoxSx(paddings: {}): SxProps<Theme> {
|
|
136
146
|
const half = MUGlobal.half(paddings);
|
|
137
147
|
return {
|
|
138
|
-
paddingLeft:
|
|
139
|
-
paddingRight:
|
|
148
|
+
paddingLeft: (theme) => theme.spacing(0.5),
|
|
149
|
+
paddingRight: (theme) => theme.spacing(0.5),
|
|
140
150
|
paddingTop: half,
|
|
141
151
|
marginBottom: half
|
|
142
152
|
};
|
|
@@ -155,7 +165,9 @@ export function ResponsibleContainer<
|
|
|
155
165
|
const {
|
|
156
166
|
adjustHeight,
|
|
157
167
|
columns,
|
|
168
|
+
containerBoxSx,
|
|
158
169
|
dataGridMinWidth = DataGridExCalColumns(columns).total,
|
|
170
|
+
elementReady,
|
|
159
171
|
fields,
|
|
160
172
|
fieldTemplate,
|
|
161
173
|
height,
|
|
@@ -217,6 +229,7 @@ export function ResponsibleContainer<
|
|
|
217
229
|
const lastRect = state.rect;
|
|
218
230
|
|
|
219
231
|
// 32 = scroll bar width
|
|
232
|
+
console.log(lastRect, rect);
|
|
220
233
|
if (
|
|
221
234
|
lastRect != null &&
|
|
222
235
|
state.mounted !== true &&
|
|
@@ -252,7 +265,9 @@ export function ResponsibleContainer<
|
|
|
252
265
|
heightLocal = height;
|
|
253
266
|
} else {
|
|
254
267
|
// Auto calculation
|
|
255
|
-
heightLocal =
|
|
268
|
+
heightLocal =
|
|
269
|
+
document.documentElement.clientHeight -
|
|
270
|
+
Math.round(rect.bottom + 1);
|
|
256
271
|
|
|
257
272
|
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
258
273
|
const boxMargin = parseFloat(style.marginBottom);
|
|
@@ -281,6 +296,10 @@ export function ResponsibleContainer<
|
|
|
281
296
|
width={rect.width}
|
|
282
297
|
loadData={localLoadData}
|
|
283
298
|
mRef={mRefs}
|
|
299
|
+
outerRef={(element?: HTMLDivElement) => {
|
|
300
|
+
if (element != null && elementReady)
|
|
301
|
+
elementReady(element, true);
|
|
302
|
+
}}
|
|
284
303
|
columns={columns}
|
|
285
304
|
{...rest}
|
|
286
305
|
/>
|
|
@@ -309,10 +328,13 @@ export function ResponsibleContainer<
|
|
|
309
328
|
>
|
|
310
329
|
<ScrollerListEx<T>
|
|
311
330
|
autoLoad={!hasFields}
|
|
312
|
-
width={rect.width}
|
|
313
331
|
height={heightLocal}
|
|
314
332
|
loadData={localLoadData}
|
|
315
333
|
mRef={mRefs}
|
|
334
|
+
oRef={(element) => {
|
|
335
|
+
if (element != null && elementReady)
|
|
336
|
+
elementReady(element, false);
|
|
337
|
+
}}
|
|
316
338
|
{...rest}
|
|
317
339
|
/>
|
|
318
340
|
</Box>,
|
|
@@ -341,12 +363,17 @@ export function ResponsibleContainer<
|
|
|
341
363
|
|
|
342
364
|
// Layout
|
|
343
365
|
return (
|
|
344
|
-
<
|
|
366
|
+
<Box
|
|
367
|
+
sx={
|
|
368
|
+
containerBoxSx == null || showDataGrid == null
|
|
369
|
+
? undefined
|
|
370
|
+
: containerBoxSx(showDataGrid)
|
|
371
|
+
}
|
|
372
|
+
>
|
|
345
373
|
<Stack>
|
|
346
374
|
<Box ref={dimensions[0][0]} sx={searchBoxSx}>
|
|
347
375
|
{searchBar}
|
|
348
376
|
</Box>
|
|
349
|
-
{list}
|
|
350
377
|
</Stack>
|
|
351
378
|
{pullToRefresh && pullContainer && (
|
|
352
379
|
<PullToRefreshUI
|
|
@@ -362,6 +389,6 @@ export function ResponsibleContainer<
|
|
|
362
389
|
}}
|
|
363
390
|
/>
|
|
364
391
|
)}
|
|
365
|
-
</
|
|
392
|
+
</Box>
|
|
366
393
|
);
|
|
367
394
|
}
|
package/src/mu/SearchBar.tsx
CHANGED
|
@@ -105,12 +105,18 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
105
105
|
moreForm?: HTMLFormElement;
|
|
106
106
|
submitSeed?: number;
|
|
107
107
|
lastMaxWidth?: number;
|
|
108
|
-
|
|
108
|
+
hasMore: boolean;
|
|
109
|
+
}>({ hasMore: true }).current;
|
|
110
|
+
const lastMaxWidth = state.lastMaxWidth ?? 9999;
|
|
109
111
|
|
|
110
112
|
// Watch container
|
|
111
113
|
const { dimensions } = useDimensions(1, (target, rect) => {
|
|
112
114
|
// Same logic from resetButtonRef
|
|
113
|
-
if (
|
|
115
|
+
if (
|
|
116
|
+
rect.width === lastMaxWidth ||
|
|
117
|
+
(!state.hasMore && rect.width > lastMaxWidth)
|
|
118
|
+
)
|
|
119
|
+
return false;
|
|
114
120
|
|
|
115
121
|
// Len
|
|
116
122
|
const len = target.children.length;
|
|
@@ -143,7 +149,10 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
143
149
|
|
|
144
150
|
// Container width
|
|
145
151
|
let maxWidth = containerRect.width;
|
|
146
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
maxWidth === lastMaxWidth ||
|
|
154
|
+
(!state.hasMore && maxWidth > lastMaxWidth)
|
|
155
|
+
) {
|
|
147
156
|
return;
|
|
148
157
|
}
|
|
149
158
|
state.lastMaxWidth = maxWidth;
|
|
@@ -220,6 +229,7 @@ export function SearchBar(props: SearchBarProps) {
|
|
|
220
229
|
}
|
|
221
230
|
|
|
222
231
|
// Show or hide more button
|
|
232
|
+
state.hasMore = hasMore;
|
|
223
233
|
setElementVisible(buttonMore, hasMore);
|
|
224
234
|
setElementVisible(resetButton, true);
|
|
225
235
|
|
|
@@ -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);
|
|
@@ -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);
|
|
@@ -18,25 +18,44 @@ export function ResponsivePage<
|
|
|
18
18
|
const { pageProps = {}, ...rest } = props;
|
|
19
19
|
|
|
20
20
|
pageProps.paddings ??= MUGlobal.pagePaddings;
|
|
21
|
-
const { paddings, ...pageRest } = pageProps;
|
|
21
|
+
const { paddings, fabColumnDirection, ...pageRest } = pageProps;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
// State
|
|
24
|
+
const [scrollContainer, setScrollContainer] = React.useState<HTMLElement>();
|
|
25
|
+
const [direction, setDirection] = React.useState(fabColumnDirection);
|
|
24
26
|
|
|
25
27
|
// Layout
|
|
26
28
|
return (
|
|
27
|
-
<CommonPage
|
|
29
|
+
<CommonPage
|
|
30
|
+
{...pageRest}
|
|
31
|
+
paddings={{}}
|
|
32
|
+
scrollContainer={scrollContainer}
|
|
33
|
+
fabColumnDirection={direction}
|
|
34
|
+
>
|
|
28
35
|
<ResponsibleContainer<T, F>
|
|
29
36
|
paddings={paddings}
|
|
30
|
-
|
|
37
|
+
containerBoxSx={(dataGrid) => {
|
|
31
38
|
if (dataGrid) {
|
|
32
39
|
return {
|
|
33
40
|
padding: paddings
|
|
34
41
|
};
|
|
35
42
|
} else {
|
|
36
43
|
return {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
paddingTop: paddings,
|
|
45
|
+
paddingBottom: paddings
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
elementReady={(element, isDataGrid) => {
|
|
50
|
+
setDirection(!isDataGrid);
|
|
51
|
+
setScrollContainer(element);
|
|
52
|
+
}}
|
|
53
|
+
listBoxSx={(dataGrid, height) => {
|
|
54
|
+
if (dataGrid) {
|
|
55
|
+
return {};
|
|
56
|
+
} else {
|
|
57
|
+
return {
|
|
58
|
+
height: height
|
|
40
59
|
};
|
|
41
60
|
}
|
|
42
61
|
}}
|
|
@@ -79,7 +79,9 @@ export function TablePage<
|
|
|
79
79
|
const rect = dimensions[0][2];
|
|
80
80
|
const list = React.useMemo(() => {
|
|
81
81
|
if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
|
|
82
|
-
let maxHeight =
|
|
82
|
+
let maxHeight =
|
|
83
|
+
document.documentElement.clientHeight -
|
|
84
|
+
(rect.top + rect.height + 1);
|
|
83
85
|
|
|
84
86
|
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
85
87
|
const paddingBottom = parseFloat(style.paddingBottom);
|
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
interface ISize {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Detect window size
|
|
5
|
-
* @param miliseconds Miliseconds delayed
|
|
6
10
|
* @returns Window size
|
|
7
11
|
*/
|
|
8
|
-
export const useWindowSize = (
|
|
12
|
+
export const useWindowSize = () => {
|
|
9
13
|
// State
|
|
10
|
-
const [size, setSize] = React.useState<{
|
|
11
|
-
width: number;
|
|
12
|
-
height: number;
|
|
13
|
-
}>({
|
|
14
|
+
const [size, setSize] = React.useState<ISize>({
|
|
14
15
|
width: 0,
|
|
15
16
|
height: 0
|
|
16
17
|
});
|
|
17
|
-
const [state] = React.useState<{ seed?: number }>({});
|
|
18
|
-
|
|
19
|
-
const resizeHandler = () => {
|
|
20
|
-
if (state.seed != null) window.clearTimeout(state.seed);
|
|
21
|
-
state.seed = window.setTimeout(() => {
|
|
22
|
-
setSize({
|
|
23
|
-
width: window.innerWidth,
|
|
24
|
-
height: window.innerHeight
|
|
25
|
-
});
|
|
26
|
-
state.seed = undefined;
|
|
27
|
-
}, miliseconds);
|
|
28
|
-
};
|
|
29
18
|
|
|
30
19
|
React.useEffect(() => {
|
|
20
|
+
let ticking = false;
|
|
21
|
+
let lastKnownSize: ISize;
|
|
22
|
+
let requestAnimationFrameSeed = 0;
|
|
23
|
+
|
|
24
|
+
const resizeHandler = () => {
|
|
25
|
+
lastKnownSize = {
|
|
26
|
+
width: document.documentElement.clientWidth,
|
|
27
|
+
height: document.documentElement.clientHeight
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (!ticking) {
|
|
31
|
+
requestAnimationFrameSeed = window.requestAnimationFrame(() => {
|
|
32
|
+
setSize(lastKnownSize);
|
|
33
|
+
ticking = false;
|
|
34
|
+
requestAnimationFrameSeed = 0;
|
|
35
|
+
});
|
|
36
|
+
ticking = true;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
31
40
|
window.addEventListener('resize', resizeHandler);
|
|
32
41
|
|
|
33
42
|
return () => {
|
|
43
|
+
// Cancel animation frame
|
|
44
|
+
if (requestAnimationFrameSeed > 0)
|
|
45
|
+
window.cancelAnimationFrame(requestAnimationFrameSeed);
|
|
46
|
+
|
|
47
|
+
// Remove scroll event
|
|
34
48
|
window.removeEventListener('resize', resizeHandler);
|
|
35
|
-
if (state.seed != null) window.clearTimeout(state.seed);
|
|
36
49
|
};
|
|
37
50
|
}, []);
|
|
38
51
|
|