Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.

Add initial test for observeScrollArea

Changed files
+67 -8
src
+58
src/utils/__tests__/observeScrollArea.test.tsx
···
+
import React, { useState, useRef, useLayoutEffect } from 'react';
+
import { mount } from '@cypress/react';
+
import { observeScrollArea } from '../observeScrollArea';
+
+
it('reports changes to the scroll area sizes', () => {
+
const Resizeable = () => {
+
const [minHeight, setMinHeight] = useState(50);
+
const toggleHeight = () => setMinHeight(prev => prev === 50 ? 200 : 50);
+
return (
+
<div style={{ border: '1px solid palevioletred', minHeight }}>
+
<button id="increase" onClick={toggleHeight}>Increase Height</button>
+
</div>
+
);
+
};
+
+
const Main = () => {
+
const [elements, setElements] = useState<number[]>([]);
+
const [height, setHeight] = useState(-1);
+
const ref = useRef<HTMLDivElement>(null);
+
+
useLayoutEffect(() => {
+
return observeScrollArea(ref.current!, (_width, height) => {
+
setHeight(height);
+
});
+
});
+
+
const addElement = () => setElements(prev => [...prev, prev.length]);
+
+
return (
+
<div
+
style={{ border: '1px solid red', overflowY: 'scroll', maxHeight: 100 }}
+
ref={ref}
+
>
+
<Resizeable />
+
<div style={{ display: 'flex', flexDirection: 'column', minHeight: 40 }}>
+
<span id="size">{height}</span>
+
<button id="add" onClick={addElement}>Add Element</button>
+
</div>
+
{elements.map(num => (
+
<div style={{ height: 10, width: 10 }} key={num} />
+
))}
+
</div>
+
);
+
};
+
+
mount(<Main />);
+
+
cy.get('#size').contains('92');
+
cy.get('#increase').first().click();
+
cy.get('#size').contains('242');
+
cy.get('#increase').first().click();
+
cy.get('#size').contains('92');
+
cy.get('#increase').first().click();
+
cy.get('#add').first().click();
+
cy.get('#size').contains('252');
+
cy.get('#add').first().click();
+
cy.get('#size').contains('262');
+
});
+9 -8
src/utils/observeScrollArea.ts
···
+
const resizeOptions: ResizeObserverOptions = { box: 'border-box' };
const mutationObservers: Map<HTMLElement, MutationObserver> = new Map();
const resizeListeners: Map<HTMLElement, Array<() => void>> = new Map();
···
for (let j = 0; j < entry.addedNodes.length; j++) {
const node = entry.addedNodes[j];
if (node.nodeType === Node.ELEMENT_NODE) {
-
resizeObserver.observe(node as Element);
+
resizeObserver.observe(node as Element, resizeOptions);
}
}
···
}
});
-
const childNodes = element.childNodes;
-
for (let i = 0; i < childNodes.length; i++)
-
if (childNodes[i].nodeType === Node.ELEMENT_NODE)
-
resizeObserver.observe(childNodes[i] as Element);
+
requestAnimationFrame(() => {
+
const childNodes = element.childNodes;
+
for (let i = 0; i < childNodes.length; i++)
+
if (childNodes[i].nodeType === Node.ELEMENT_NODE)
+
resizeObserver.observe(childNodes[i] as Element, resizeOptions);
+
mutationObserver.observe(element, { childList: true });
+
});
-
mutationObserver.observe(element, { childList: true });
mutationObservers.set(element, mutationObserver);
}
-
-
requestAnimationFrame(onResize);
return () => {
const listeners = resizeListeners.get(element) || [];