diff --git a/README.md b/README.md index f21bd69..25d5312 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ import {RemoveScroll} from 'react-remove-scroll'; - `[allowPinchZoom=false]` - enabled "pinch-n-zoom" behavior. By default it might be prevented. However - pinch and zoom might break "scroll isolation", and __disabled by default__. - `[noIsolation=false]` - disables outer event capturing. Event capturing is React friendly and unlikely be a problem. But if you are using _shadowbox_ of some sort - you dont need it. -- `[inert=false]` - ☠️(be careful) disables events the rest of page completely using `pointer-events` expect the Lock(+shard). +- `[inert=false]` - ☠️(be careful) disables events the rest of page completely using `pointer-events` except the Lock(+shards). React portals not friendly, might lead to production issues. Enable only for __rare__ cases, when you have to disable scrollbars somewhere on the page(except body, Lock and shards). - `[forwardProps]` - will forward all props to the `children` - `[className]` - className for an internal div diff --git a/__tests__/UI.tsx b/__tests__/UI.tsx index 2d9dc68..5bd6a98 100644 --- a/__tests__/UI.tsx +++ b/__tests__/UI.tsx @@ -16,16 +16,31 @@ describe('UI', () => { content ); await tick(); - expect(wrapper.html()).toContain('content'); + expect(wrapper.html()).toBe('
content
'); + }); + + it('smoke as style class', async () => { + const wrapper = mount( + + content + + ); + await tick(); + expect(wrapper.html()).toBe('content'); }); it('forward', async () => { const wrapper = mount( -
content
+ content
); await tick(); - expect(wrapper.html()).toContain('content'); + expect(wrapper.html()).toBe('content'); }); }); diff --git a/src/SideEffect.tsx b/src/SideEffect.tsx index 3277abe..a6287ed 100644 --- a/src/SideEffect.tsx +++ b/src/SideEffect.tsx @@ -81,7 +81,7 @@ export function RemoveScrollSideCar(props: IRemoveScrollEffectProps) { 'deltaY' in event ? event.deltaY : touchStart[1] - touch[1]; let currentAxis: Axis | undefined; - let target: HTMLElement = event.target as any; + const target: HTMLElement = event.target as any; const moveDirection: Axis = Math.abs(deltaX) > Math.abs(deltaY) ? 'h' : 'v'; @@ -128,7 +128,7 @@ export function RemoveScrollSideCar(props: IRemoveScrollEffectProps) { cancelingAxis, parent, event, - cancelingAxis == 'h' ? deltaX : deltaY, + cancelingAxis === 'h' ? deltaX : deltaY, true ); }, diff --git a/src/UI.tsx b/src/UI.tsx index e002c94..18a119b 100644 --- a/src/UI.tsx +++ b/src/UI.tsx @@ -17,6 +17,9 @@ const nothing = () => { return; }; +/** + * Removes scrollbar from the page and contain the scroll within the Lock + */ const RemoveScroll: RemoveScrollUIType = React.forwardRef< HTMLElement, IRemoveScrollUIProps @@ -42,16 +45,18 @@ const RemoveScroll: RemoveScrollUIType = React.forwardRef< noIsolation, inert, allowPinchZoom, + as: Container = 'div', ...rest } = props; const SideCar: SideCarComponent = sideCar; + const containerRef = useMergeRefs([ + ref, + parentRef as React.MutableRefObject + ]); + const containerProps = { - ref: useMergeRefs([ - ref, - parentRef as React.MutableRefObject - ]), ...rest, ...callbacks }; @@ -73,12 +78,12 @@ const RemoveScroll: RemoveScrollUIType = React.forwardRef< {forwardProps ? ( React.cloneElement( React.Children.only(children as React.ReactElement), - containerProps + { ...containerProps, ref:containerRef} ) ) : ( -
+ {children} -
+ )} ); diff --git a/src/handleScroll.ts b/src/handleScroll.ts index db1f6a4..254b141 100644 --- a/src/handleScroll.ts +++ b/src/handleScroll.ts @@ -89,8 +89,7 @@ export const handleScroll = ( (targetInLock && (endTarget.contains(target) || endTarget === target)) ); - if (0) { - } else if ( + if ( isDeltaPositive && ((noOverscroll && availableScroll === 0) || (!noOverscroll && delta > availableScroll)) diff --git a/src/types.tsx b/src/types.tsx index 71337a6..eb7f393 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -14,25 +14,67 @@ export interface RemoveScrollEffectCallbacks { } export interface ChildrenNode { + /** + * if forwardProps is false - children should be ReactNode + * and it would be wrapper with a div + * @see {@link IRemoveScrollSelfProps.as} + */ forwardProps?: false; children: React.ReactNode; } export interface ChildrenForward { + /** + * if forwardProps is true - children should be single Element + * which would NOT with a div + * @see {@link IRemoveScrollSelfProps.as} + */ forwardProps: true; children: React.ReactElement; } export interface IRemoveScrollSelfProps { + /** + * disables "event isolation" (suppressing of events happening outside of the Lock) + * @default false + */ noIsolation?: boolean; + /** + * enabled complete Lock isolation using `pointer-events:none` for anything outside the Lock + * you probably don't need it, except you do + * @default false + * @see {IRemoveScrollSelfProps.noIsolation} + */ inert?: boolean; + /** + * allows pinch-zoom, however might work not perfectly for normal scroll + */ allowPinchZoom?: boolean; + /** + * switches on/off the behavior of the component + */ enabled?: boolean; - className?: string; + + /** + * Controls the body scroll bar removal + * @default false + */ removeScrollBar?: boolean; + + className?: string; + style?: React.CSSProperties; + + /** + * array of refs to other Elements, which should be considered as a part of the Lock + */ shards?: Array | HTMLElement>; + /** + * Control host node used for the lock. + * @default 'div' + */ + as?: string | React.ElementType; } export type IRemoveScrollProps = IRemoveScrollSelfProps &