Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-native-intersection-observer

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-intersection-observer - npm Package Compare versions

Comparing version 0.0.9 to 0.1.0

9

lib/index.d.ts

@@ -1,6 +0,7 @@

import IntersectionObserver from './IntersectionObserver';
import InView from './InView';
import IntersectionObserver, { type IntersectionObserverEntry, type IntersectionObserverOptions, type RootMargin } from './IntersectionObserver';
import InView, { type InViewProps } from './InView';
import IOContext from './IOContext';
import IOScrollView from './IOScrollView';
import withIO from './withIO';
import IOScrollView, { type IOScrollViewProps } from './IOScrollView';
import withIO, { type IOScrollableComponentProps } from './withIO';
export type { IntersectionObserverEntry, IntersectionObserverOptions, RootMargin, InViewProps, IOScrollViewProps, IOScrollableComponentProps, };
export { IntersectionObserver, InView, IOContext, IOScrollView, withIO };

@@ -9,68 +9,6 @@ import throttle from 'lodash/throttle';

class IntersectionObserver {
callback;
options;
targets;
constructor(callback, options) {
this.measureTarget = (target) => {
const rootNode = this.options.root.node;
if (rootNode) {
target.measureLayout(rootNode, (x, y, width, height) => {
target.layout = {
x,
y,
width,
height,
};
this.handleScroll();
});
}
};
this.handleLayout = throttle(() => {
for (let index = 0; index < this.targets.length; index += 1) {
this.measureTarget(this.targets[index]);
}
}, 300, { leading: false, trailing: true });
this.handleScroll = throttle(() => {
const rootMargin = this.options?.rootMargin || defaultRootMargin;
const { horizontal, current: { contentOffset, contentSize, layoutMeasurement, }, } = this.options.root;
if (contentSize.width <= 0 ||
contentSize.height <= 0 ||
layoutMeasurement.width <= 0 ||
layoutMeasurement.height <= 0) {
return;
}
const contentOffsetWithLayout = horizontal
? contentOffset.x + layoutMeasurement.width
: contentOffset.y + layoutMeasurement.height;
const changedTargets = [];
for (let index = 0; index < this.targets.length; index += 1) {
const target = this.targets[index];
const targetLayout = target.layout;
if (!targetLayout ||
targetLayout.width === 0 ||
targetLayout.height === 0) {
continue;
}
let isIntersecting = false;
if (horizontal) {
isIntersecting =
contentOffsetWithLayout + (rootMargin.right || 0) >=
targetLayout.x &&
contentOffset.x - (rootMargin.left || 0) <=
targetLayout.x + targetLayout.width;
}
else {
isIntersecting =
contentOffsetWithLayout + (rootMargin.bottom || 0) >=
targetLayout.y &&
contentOffset.y - (rootMargin.top || 0) <=
targetLayout.y + targetLayout.height;
}
if (target.inView !== isIntersecting) {
target.inView = isIntersecting;
changedTargets.push({
target,
isIntersecting,
});
}
}
this.callback(changedTargets);
}, 100, { leading: false, trailing: true });
this.callback = callback;

@@ -82,2 +20,67 @@ this.options = options;

}
measureTarget = (target) => {
const rootNode = this.options.root.node;
if (rootNode) {
target.measureLayout(rootNode, (x, y, width, height) => {
target.layout = {
x,
y,
width,
height,
};
this.handleScroll();
});
}
};
handleLayout = throttle(() => {
for (let index = 0; index < this.targets.length; index += 1) {
this.measureTarget(this.targets[index]);
}
}, 300, { leading: false, trailing: true });
handleScroll = throttle(() => {
const rootMargin = this.options?.rootMargin || defaultRootMargin;
const { horizontal, current: { contentOffset, contentSize, layoutMeasurement, }, } = this.options.root;
if (contentSize.width <= 0 ||
contentSize.height <= 0 ||
layoutMeasurement.width <= 0 ||
layoutMeasurement.height <= 0) {
return;
}
const contentOffsetWithLayout = horizontal
? contentOffset.x + layoutMeasurement.width
: contentOffset.y + layoutMeasurement.height;
const changedTargets = [];
for (let index = 0; index < this.targets.length; index += 1) {
const target = this.targets[index];
const targetLayout = target.layout;
if (!targetLayout ||
targetLayout.width === 0 ||
targetLayout.height === 0) {
continue;
}
let isIntersecting = false;
if (horizontal) {
isIntersecting =
contentOffsetWithLayout + (rootMargin.right || 0) >=
targetLayout.x &&
contentOffset.x - (rootMargin.left || 0) <=
targetLayout.x + targetLayout.width;
}
else {
isIntersecting =
contentOffsetWithLayout + (rootMargin.bottom || 0) >=
targetLayout.y &&
contentOffset.y - (rootMargin.top || 0) <=
targetLayout.y + targetLayout.height;
}
if (target.inView !== isIntersecting) {
target.inView = isIntersecting;
changedTargets.push({
target,
isIntersecting,
});
}
}
this.callback(changedTargets);
}, 100, { leading: false, trailing: true });
observe(target) {

@@ -84,0 +87,0 @@ const index = this.targets.indexOf(target);

@@ -5,49 +5,14 @@ import React, { PureComponent, } from 'react';

class InView extends PureComponent {
static contextType = IOContext;
static defaultProps = {
triggerOnce: false,
as: View,
};
context = undefined;
mounted = false;
element;
instance;
view;
constructor(props) {
super(props);
this.mounted = false;
this.handleChange = (inView) => {
if (this.mounted) {
const { triggerOnce, onChange } = this.props;
if (inView && triggerOnce) {
if (this.context?.manager) {
this.context?.manager.unobserve(this.element);
}
}
if (onChange) {
onChange(inView);
}
}
};
this.handleRef = (ref) => {
this.view = ref;
};
this.handleLayout = (event) => {
const { nativeEvent: { layout }, } = event;
if (layout.width !== this.element.layout.width ||
layout.height !== this.element.layout.height) {
if (this.element.onLayout) {
this.element.onLayout();
}
}
const { onLayout } = this.props;
if (onLayout) {
onLayout(event);
}
};
this.measureInWindow = (...args) => {
this.view.measureInWindow(...args);
};
this.measureLayout = (...args) => {
this.view.measureLayout(...args);
};
this.setNativeProps = (...args) => {
this.view.setNativeProps(...args);
};
this.focus = (...args) => {
this.view.focus(...args);
};
this.blur = (...args) => {
this.view.blur(...args);
};
this.element = {

@@ -76,2 +41,46 @@ inView: false,

}
handleChange = (inView) => {
if (this.mounted) {
const { triggerOnce, onChange } = this.props;
if (inView && triggerOnce) {
if (this.context?.manager) {
this.context?.manager.unobserve(this.element);
}
}
if (onChange) {
onChange(inView);
}
}
};
handleRef = (ref) => {
this.view = ref;
};
handleLayout = (event) => {
const { nativeEvent: { layout }, } = event;
if (layout.width !== this.element.layout.width ||
layout.height !== this.element.layout.height) {
if (this.element.onLayout) {
this.element.onLayout();
}
}
const { onLayout } = this.props;
if (onLayout) {
onLayout(event);
}
};
measureInWindow = (...args) => {
this.view.measureInWindow(...args);
};
measureLayout = (...args) => {
this.view.measureLayout(...args);
};
setNativeProps = (...args) => {
this.view.setNativeProps(...args);
};
focus = (...args) => {
this.view.focus(...args);
};
blur = (...args) => {
this.view.blur(...args);
};
render() {

@@ -83,10 +92,5 @@ const { as, children, ...props } = this.props;

const ViewComponent = (as || View);
return (React.createElement(ViewComponent, Object.assign({}, props, { ref: this.handleRef, onLayout: this.handleLayout }), children));
return (React.createElement(ViewComponent, { ...props, ref: this.handleRef, onLayout: this.handleLayout }, children));
}
}
InView.contextType = IOContext;
InView.defaultProps = {
triggerOnce: false,
as: View,
};
export default InView;
import IntersectionObserver from './IntersectionObserver';
class IOManager {
io;
observerId;
instanceMap = new Map();
constructor(options) {
this.instanceMap = new Map();
this.handleChange = (entries) => {
for (let index = 0; index < entries.length; index += 1) {
const { target, isIntersecting } = entries[index];
const instance = this.instanceMap.get(target);
if (instance) {
instance.callback(isIntersecting);
}
}
};
this.io = new IntersectionObserver(this.handleChange, options);
this.observerId = 0;
}
handleChange = (entries) => {
for (let index = 0; index < entries.length; index += 1) {
const { target, isIntersecting } = entries[index];
const instance = this.instanceMap.get(target);
if (instance) {
instance.callback(isIntersecting);
}
}
};
observe(element, callback) {

@@ -18,0 +20,0 @@ const existInstance = this.instanceMap.get(element);

@@ -1,3 +0,4 @@

import { IOScrollView } from './withIO';
declare const _default: typeof IOScrollView;
import { type IOScrollableComponent, type IOScrollableComponentProps } from './withIO';
export declare type IOScrollViewProps = IOScrollableComponentProps;
declare const _default: typeof IOScrollableComponent;
export default _default;
import { PureComponent } from 'react';
import { ScrollView, ScrollViewComponent, ScrollViewProps } from 'react-native';
import { ScrollResponderMixin, ScrollView, ScrollViewComponent, ScrollViewProps } from 'react-native';
import { RootMargin } from './IntersectionObserver';
interface IOScrollViewProps extends ScrollViewProps {
export interface IOScrollableComponentProps extends ScrollViewProps {
rootMargin?: RootMargin;
}
export declare class IOScrollViewComponent extends PureComponent<IOScrollViewProps> {
}
export declare class IOScrollView extends IOScrollViewComponent {
export declare class IOScrollableComponent extends PureComponent<IOScrollableComponentProps> {
scrollTo: ScrollView['scrollTo'];
scrollToEnd: ScrollView['scrollToEnd'];
getScrollResponder: ScrollView['getScrollResponder'];
getScrollResponder(): ScrollResponderMixin | undefined;
getScrollableNode: ScrollView['getScrollableNode'];
getInnerViewNode: ScrollView['getInnerViewNode'];
}
declare const withIO: (ScrollableComponent: typeof ScrollViewComponent) => typeof IOScrollView;
declare const withIO: (ScrollableComponent: typeof ScrollViewComponent) => typeof IOScrollableComponent;
export default withIO;

@@ -6,52 +6,10 @@ import React, { PureComponent, createRef } from 'react';

const withIO = (ScrollableComponent) => {
class IOScrollableComponent extends PureComponent {
class IOScrollView extends PureComponent {
node;
scroller;
root;
manager;
contextValue;
constructor(props) {
super(props);
this.handleContentSizeChange = (width, height) => {
const { contentSize } = this.root.current;
if (width !== contentSize.width || height !== contentSize.height) {
this.root.current.contentSize = { width, height };
if (width > 0 && height > 0 && this.root.onLayout) {
this.root.onLayout();
}
}
const { onContentSizeChange } = this.props;
if (onContentSizeChange) {
onContentSizeChange(width, height);
}
};
this.handleLayout = (event) => {
const { nativeEvent: { layout }, } = event;
const { layoutMeasurement } = this.root.current;
if (layoutMeasurement.width !== layout.width ||
layoutMeasurement.height !== layout.height) {
this.root.current.layoutMeasurement = layout;
}
const { onLayout } = this.props;
if (onLayout) {
onLayout(event);
}
};
this.handleScroll = (event) => {
this.root.current = event.nativeEvent;
if (this.root.onScroll) {
this.root.onScroll(this.root.current);
}
const { onScroll } = this.props;
if (onScroll) {
onScroll(event);
}
};
this.scrollToEnd = (options) => {
this.scroller.current?.scrollToEnd(options);
};
this.getScrollResponder = () => {
return this.scroller.current?.getScrollResponder();
};
this.getScrollableNode = () => {
return this.scroller.current?.getScrollableNode();
};
this.getInnerViewNode = () => {
return this.scroller.current?.getInnerViewNode();
};
const self = this;

@@ -102,12 +60,59 @@ this.scroller = createRef();

}
handleContentSizeChange = (width, height) => {
const { contentSize } = this.root.current;
if (width !== contentSize.width || height !== contentSize.height) {
this.root.current.contentSize = { width, height };
if (width > 0 && height > 0 && this.root.onLayout) {
this.root.onLayout();
}
}
const { onContentSizeChange } = this.props;
if (onContentSizeChange) {
onContentSizeChange(width, height);
}
};
handleLayout = (event) => {
const { nativeEvent: { layout }, } = event;
const { layoutMeasurement } = this.root.current;
if (layoutMeasurement.width !== layout.width ||
layoutMeasurement.height !== layout.height) {
this.root.current.layoutMeasurement = layout;
}
const { onLayout } = this.props;
if (onLayout) {
onLayout(event);
}
};
handleScroll = (event) => {
this.root.current = event.nativeEvent;
if (this.root.onScroll) {
this.root.onScroll(this.root.current);
}
const { onScroll } = this.props;
if (onScroll) {
onScroll(event);
}
};
scrollTo(y, x, animated) {
this.scroller.current?.scrollTo(y, x, animated);
}
scrollToEnd = (options) => {
this.scroller.current?.scrollToEnd(options);
};
getScrollResponder = () => {
return this.scroller.current?.getScrollResponder();
};
getScrollableNode = () => {
return this.scroller.current?.getScrollableNode();
};
getInnerViewNode = () => {
return this.scroller.current?.getInnerViewNode();
};
render() {
return (React.createElement(IOContext.Provider, { value: this.contextValue },
React.createElement(ScrollableComponent, Object.assign({ scrollEventThrottle: 16 }, this.props, { ref: this.scroller, onContentSizeChange: this.handleContentSizeChange, onLayout: this.handleLayout, onScroll: this.handleScroll }))));
React.createElement(ScrollableComponent, { scrollEventThrottle: 16, ...this.props, ref: this.scroller, onContentSizeChange: this.handleContentSizeChange, onLayout: this.handleLayout, onScroll: this.handleScroll })));
}
}
return IOScrollableComponent;
return IOScrollView;
};
export default withIO;
{
"name": "react-native-intersection-observer",
"version": "0.0.9",
"version": "0.1.0",
"description": "react native intersection observer",

@@ -5,0 +5,0 @@ "keywords": [

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc