diff --git a/package.json b/package.json index c027722..d7e4eeb 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./lib/index.js", "types": "./lib/index.d.ts", "scripts": { - "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", + "format": "prettier --write \"src/**/*.ts*\"", "lint": "tslint -p tsconfig.json", "test-jest": "jest --config jestconfig.json", "test": "echo \"No tests to execute\" && exit 0", diff --git a/src/__tests__/test.tsx b/src/__tests__/test.tsx index fbd28de..3b55fdc 100644 --- a/src/__tests__/test.tsx +++ b/src/__tests__/test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; -import { MorefinityListLoader, MorefinityContainer, IMorefinityProps } from '../index'; +import { MorefinityListLoader, Morefinity, IMorefinityProps } from '../index'; import { useState } from 'react'; const mockedItemHeight = 30; @@ -36,8 +36,8 @@ const fetchItems = async ( }); }; -describe('', () => { - const MorefinityContainerTest = () => { +describe('', () => { + const MorefinityTest = () => { const [items, setItems] = useState<{ id: number; text: string }[]>([ { id: 0, @@ -53,18 +53,18 @@ describe('', () => { }; return (
- {items.map(itemRenderer)} - +
); }; - const container = shallow(); + const container = shallow(); let wrapper: ShallowWrapper; const useEffect = jest.spyOn(React, 'useEffect'); @@ -84,21 +84,21 @@ describe('', () => { }; test('should pass scrollOffset prop', () => { - expect(container.find(MorefinityContainer).props().scrollOffset).toBe(100); + expect(container.find(Morefinity).props().scrollOffset).toBe(100); }); test('should request items with start offset and limit from props', () => { mockUseEffect(); - wrapper = shallow(); + wrapper = shallow(); expect(props.onScrollEnd).toBeCalledTimes(0); }); test('container height should be equal to passed property', () => { - wrapper = shallow(); + wrapper = shallow(); expect(wrapper.find('div').props().height).toBe(props.height); }); - test('should render ', () => { + test('should render ', () => { expect(wrapper.length).toBe(1); }); diff --git a/src/index.tsx b/src/index.tsx index ded1025..26cc042 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -23,6 +23,7 @@ function useDebouncedState(initialValue: T, delay: number = 50): [T, (newValu export interface IMorefinityProps { isLoading?: boolean; loader?: React.ReactElement; + maxHeight?: number; height?: number; notAllLoaded?: boolean; scrollOffset?: number; @@ -88,10 +89,24 @@ export const MorefinityListLoader = ({ return isLoading ?
{element}
: null; }; -export const MorefinityContainer: React.FC = React.memo( - ({ isLoading, height, notAllLoaded, onScrollEnd, scrollOffset = 0, loader, children }) => { +export const Morefinity: React.FC = React.memo( + ({ + isLoading, + height, + notAllLoaded, + maxHeight, + onScrollEnd, + scrollOffset = 0, + loader, + children, + }) => { const [offsetHeight, setOffsetHeight] = useState(0); + const { ref, size: contentSize } = useObservedSize() as { + ref: RefObject; + size: IObservableSize; + }; + const [scrollTop, setScrollTop] = useDebouncedState(0, 50); const { ref: containerRef, size } = useObservedSize() as { @@ -211,7 +226,16 @@ export const MorefinityContainer: React.FC = React.memo( }); }, [listHeight, children, minPredicted, maxPredicted]); - const pageWrapperStyles: React.CSSProperties = useMemo(() => { + const wrapperStyles: React.CSSProperties = useMemo(() => { + return { + position: 'relative', + height: maxHeight ? contentSize.height : height ?? 'inherit', + overflow: 'auto', + maxHeight, + }; + }, [contentSize.height, maxHeight, height]); + + const containerStyles: React.CSSProperties = useMemo(() => { const offset = Math.max(minPredicted - 1, 0) * avgItemHeight; return { position: 'absolute', @@ -226,12 +250,10 @@ export const MorefinityContainer: React.FC = React.memo( }; return ( -
-
{renderItems()}
+
+
+ {renderItems()} +