Skip to content

Commit 7d6bfb5

Browse files
authored
fix: table not responding to parent size change (#1516)
* fix: table not responding to parent size change * chore: cleanup not used packages * chore: cleanup more not used packages
1 parent 96a7eff commit 7d6bfb5

File tree

4 files changed

+147
-10
lines changed

4 files changed

+147
-10
lines changed

packages/gatsby-theme-aio/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,15 @@
138138
"redoc-cli": "^0.13.20",
139139
"rehype-slug-custom-id": "^1.1.0",
140140
"request": "^2.88.2",
141+
"resize-observer-polyfill": "^1.5.1",
141142
"sharp": "^0.31.0",
142143
"stream-http": "^3.2.0",
143144
"styled-components": "^5.3.5",
144145
"swiper": "^8.3.2",
145146
"to-arraybuffer": "^1.0.1",
146147
"tty-browserify": "^0.0.1",
147148
"unist-util-select": "3.0.4",
149+
"use-debounce": "^9.0.4",
148150
"uuid": "^9.0.0"
149151
}
150152
}

packages/gatsby-theme-aio/src/components/Table/index.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,33 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import React, { useEffect, useRef, useState } from 'react';
13+
import React, { useRef, useState } from 'react';
1414
import { css } from '@emotion/react';
1515
import PropTypes from 'prop-types';
1616
import '@spectrum-css/table';
17-
import { MOBILE_SCREEN_WIDTH } from '../../utils';
17+
import { MOBILE_SCREEN_WIDTH, useParentSize } from '../../utils';
1818

1919
const Table = ({ children, css: cssOverrides, columnWidths, ...props }) => {
20-
const [width, setWidth] = useState(MOBILE_SCREEN_WIDTH);
2120
const tableRef = useRef(null);
21+
const [width, setWidth] = useState(parseInt(MOBILE_SCREEN_WIDTH, 10));
22+
23+
useParentSize(tableRef, {
24+
debounceDelay: 500,
25+
initialValues: { width: parseInt(MOBILE_SCREEN_WIDTH, 10) },
26+
callback: size => {
27+
if (size.width) {
28+
setWidth(size.width);
29+
}
30+
},
31+
});
32+
2233
const columnWidthDistribution = columnWidths
2334
? columnWidths
2435
.split(',')
2536
.map(num => (width * Number(num)) / 100)
2637
.filter(width => !isNaN(width))
2738
: [];
2839

29-
useEffect(() => {
30-
if (tableRef.current.parentNode) {
31-
setWidth(Number(tableRef.current.parentNode.offsetWidth));
32-
}
33-
}, [width]);
34-
3540
return (
3641
<table
3742
ref={tableRef}

packages/gatsby-theme-aio/src/utils/index.js

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import React, { Children, cloneElement } from 'react';
13+
import React, {
14+
Children,
15+
cloneElement,
16+
useCallback,
17+
useMemo,
18+
useRef,
19+
useState,
20+
useLayoutEffect,
21+
} from 'react';
22+
import ResizeObserver from 'resize-observer-polyfill';
23+
import { useDebouncedCallback } from 'use-debounce';
1424
import { withPrefix } from 'gatsby';
1525
import globals from '../../conf/globals';
1626

@@ -265,6 +275,107 @@ const cloneChildren = (children, changeProps) => {
265275
});
266276
};
267277

278+
// Modified to actually grab the parent size https://github.com/dagda1/cuttingedge/blob/main/packages/use-get-parent-size/src/useParentSize/useParentSize.ts
279+
280+
const initialContentRect = {
281+
bottom: undefined,
282+
height: undefined,
283+
left: undefined,
284+
width: undefined,
285+
right: undefined,
286+
top: undefined,
287+
x: undefined,
288+
y: undefined,
289+
};
290+
291+
const isNil = val => typeof val === 'undefined' || val === null;
292+
293+
const useParentSize = (
294+
ref,
295+
{
296+
debounceDelay = 500,
297+
initialValues = initialContentRect,
298+
transformFunc = o => o,
299+
maxDifference = 10,
300+
callback = o => o,
301+
}
302+
) => {
303+
const [contentRect, setContentRect] = useState({
304+
...initialContentRect,
305+
...initialValues,
306+
});
307+
const rerenderCount = useRef(0);
308+
const previousContentRect = useRef(initialValues);
309+
310+
const transformer = useCallback(transformFunc, [transformFunc]);
311+
312+
if (!ref) console.error('You must pass a valid ref to useParentSize');
313+
314+
const debouncedCallback = useDebouncedCallback(
315+
value => {
316+
setContentRect(value);
317+
callback(value);
318+
},
319+
debounceDelay,
320+
{
321+
leading: true,
322+
}
323+
);
324+
325+
const refElement = ref.current;
326+
327+
useLayoutEffect(() => {
328+
if (isNil(refElement)) {
329+
if (rerenderCount.current > 10) {
330+
throw new Error('Maximum rerender count and no refElement Found');
331+
}
332+
333+
setContentRect({ ...contentRect });
334+
rerenderCount.current++;
335+
return;
336+
}
337+
338+
if (isNil(refElement.parentNode)) {
339+
if (rerenderCount.parentNode > 10) {
340+
throw new Error('Maximum rerender count and no parentNode Found');
341+
}
342+
343+
setContentRect({ ...contentRect });
344+
rerenderCount.parentNode++;
345+
return;
346+
}
347+
348+
const resizeObserver = new ResizeObserver(entries => {
349+
if (!Array.isArray(entries) || entries.length !== 1) {
350+
return;
351+
}
352+
353+
const entry = entries[0];
354+
const newWidth = Math.round(entry.contentRect.width);
355+
const newHeight = Math.round(entry.contentRect.height);
356+
357+
const widthDiff = Math.abs(newWidth - (previousContentRect.current.width ?? 0));
358+
const heightDiff = Math.abs(newHeight - (previousContentRect.current.height ?? 0));
359+
360+
if (widthDiff > maxDifference || heightDiff > maxDifference) {
361+
previousContentRect.current.height = newHeight;
362+
previousContentRect.current.width = newWidth;
363+
debouncedCallback(entry.contentRect);
364+
}
365+
});
366+
367+
requestAnimationFrame(() => resizeObserver?.observe(refElement.parentNode));
368+
369+
return () => {
370+
if (!!refElement.parentNode) {
371+
resizeObserver?.unobserve(refElement.parentNode);
372+
}
373+
};
374+
}, [maxDifference, debouncedCallback, refElement, initialValues, contentRect]);
375+
376+
return useMemo(() => transformer(contentRect), [contentRect, transformer]);
377+
};
378+
268379
const DEFAULT_HOME = {
269380
title: 'Products',
270381
href: '/apis/',
@@ -303,6 +414,7 @@ export {
303414
getExternalLinkProps,
304415
getElementChild,
305416
cloneChildren,
417+
useParentSize,
306418
DEFAULT_HOME,
307419
SEARCH_PARAMS,
308420
SIDENAV_WIDTH,

yarn.lock

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,15 @@ __metadata:
118118
redoc-cli: ^0.13.20
119119
rehype-slug-custom-id: ^1.1.0
120120
request: ^2.88.2
121+
resize-observer-polyfill: ^1.5.1
121122
sharp: ^0.31.0
122123
stream-http: ^3.2.0
123124
styled-components: ^5.3.5
124125
swiper: ^8.3.2
125126
to-arraybuffer: ^1.0.1
126127
tty-browserify: ^0.0.1
127128
unist-util-select: 3.0.4
129+
use-debounce: ^9.0.4
128130
uuid: ^9.0.0
129131
peerDependencies:
130132
gatsby: ^4.22.0
@@ -20737,6 +20739,13 @@ __metadata:
2073720739
languageName: node
2073820740
linkType: hard
2073920741

20742+
"resize-observer-polyfill@npm:^1.5.1":
20743+
version: 1.5.1
20744+
resolution: "resize-observer-polyfill@npm:1.5.1"
20745+
checksum: 57e7f79489867b00ba43c9c051524a5c8f162a61d5547e99333549afc23e15c44fd43f2f318ea0261ea98c0eb3158cca261e6f48d66e1ed1cd1f340a43977094
20746+
languageName: node
20747+
linkType: hard
20748+
2074020749
"resolve-alpn@npm:^1.0.0":
2074120750
version: 1.2.1
2074220751
resolution: "resolve-alpn@npm:1.2.1"
@@ -23809,6 +23818,15 @@ __metadata:
2380923818
languageName: node
2381023819
linkType: hard
2381123820

23821+
"use-debounce@npm:^9.0.4":
23822+
version: 9.0.4
23823+
resolution: "use-debounce@npm:9.0.4"
23824+
peerDependencies:
23825+
react: ">=16.8.0"
23826+
checksum: 37da4ecbe4e10a6230580cac03a8cae1788ea3e417dfdd92fcf654325458cf1b4567fd57bebf888edab62701a6abe47059a585008fd04228784f223f94d66ce4
23827+
languageName: node
23828+
linkType: hard
23829+
2381223830
"utif@npm:^2.0.1":
2381323831
version: 2.0.1
2381423832
resolution: "utif@npm:2.0.1"

0 commit comments

Comments
 (0)