@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.
@@ -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 = window.innerHeight, width = '100%', mRef, oRef, style = {}, itemRenderer, itemSize, loadBatchSize = calculateBatchSize(height, itemSize), loadData, threshold = GridSizeGet(loadBatchSize, height) / 2, onItemsRendered, ...rest } = props;
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: half,
16
- paddingRight: half,
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 = window.innerHeight - Math.round(rect.bottom + 1);
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, columns: columns, ...rest })),
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, width: rect.width, height: heightLocal, loadData: localLoadData, mRef: mRefs, ...rest })),
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(React.Fragment, null,
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);
@@ -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 === state.lastMaxWidth)
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 === state.lastMaxWidth) {
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 = window.innerHeight - Math.round(rect.top + rect.height + 1);
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 = window.innerHeight - Math.round(rect.top + rect.height + 1);
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
- const halfPadding = MUGlobal.half(paddings);
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, listBoxSx: (dataGrid, height) => {
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
- height,
28
- paddingTop: halfPadding,
29
- paddingBottom: halfPadding
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 = window.innerHeight - (rect.top + rect.height + 1);
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: (miliseconds?: number) => {
7
- width: number;
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 = (miliseconds = 50) => {
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.25",
3
+ "version": "1.4.29",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -106,7 +106,7 @@ export const ScrollerList = <T extends Record<string, any>>(
106
106
  autoLoad = true,
107
107
  defaultOrderBy,
108
108
  defaultOrderByAsc,
109
- height = window.innerHeight,
109
+ height = document.documentElement.clientHeight,
110
110
  width = '100%',
111
111
  mRef,
112
112
  oRef,
@@ -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: half,
139
- paddingRight: half,
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 = window.innerHeight - Math.round(rect.bottom + 1);
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
- <React.Fragment>
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
- </React.Fragment>
392
+ </Box>
366
393
  );
367
394
  }
@@ -105,12 +105,18 @@ export function SearchBar(props: SearchBarProps) {
105
105
  moreForm?: HTMLFormElement;
106
106
  submitSeed?: number;
107
107
  lastMaxWidth?: number;
108
- }>({}).current;
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 (rect.width === state.lastMaxWidth) return false;
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 (maxWidth === state.lastMaxWidth) {
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
- window.innerHeight - Math.round(rect.top + rect.height + 1);
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
- window.innerHeight - Math.round(rect.top + rect.height + 1);
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
- const halfPadding = MUGlobal.half(paddings);
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 {...pageRest} paddings={{}}>
29
+ <CommonPage
30
+ {...pageRest}
31
+ paddings={{}}
32
+ scrollContainer={scrollContainer}
33
+ fabColumnDirection={direction}
34
+ >
28
35
  <ResponsibleContainer<T, F>
29
36
  paddings={paddings}
30
- listBoxSx={(dataGrid, height) => {
37
+ containerBoxSx={(dataGrid) => {
31
38
  if (dataGrid) {
32
39
  return {
33
40
  padding: paddings
34
41
  };
35
42
  } else {
36
43
  return {
37
- height,
38
- paddingTop: halfPadding,
39
- paddingBottom: halfPadding
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 = window.innerHeight - (rect.top + rect.height + 1);
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 = (miliseconds: number = 50) => {
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