Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6c9786a
fix: prevent state updates on unmounted components
JairajJangle Jun 21, 2025
de6cb59
fix: prevent race conditions during rapid mount/unmount cycles
JairajJangle Jun 21, 2025
5f640db
fix: add window dimension change listener to handle orientation changes
JairajJangle Jun 21, 2025
f5e4de7
fix: handle initial visibility state and improve measurement timing
JairajJangle Jun 21, 2025
e78fa27
feat: added percent visiblity callback requested in #44
JairajJangle Aug 23, 2025
d8a75d9
refactor: updated percent visibility change callback name - #44
JairajJangle Aug 23, 2025
6fecb32
docs: documented percent visible prop in readme - #44
JairajJangle Aug 23, 2025
25f2bc9
docs: updated example app with percent visible callback and streamlin…
JairajJangle Aug 23, 2025
81d0036
perf: conserved percent calc. if view is not visible - #44
JairajJangle Aug 23, 2025
f3e0518
ci: added beta release gh action script
JairajJangle Aug 23, 2025
0ed0689
Merge branch 'main' of github.com:JairajJangle/react-native-component…
JairajJangle Aug 23, 2025
eaf7024
chore: example app deps upgraded
JairajJangle Aug 23, 2025
1dceff5
chore(release): 1.4.0-beta.1 [skip ci]
semantic-release-bot Aug 23, 2025
af0161c
fix: added missing state dependencies in visiblity calculations
JairajJangle Aug 23, 2025
0318494
Merge branch 'beta' of github.com:JairajJangle/react-native-component…
JairajJangle Aug 23, 2025
3619b5a
chore(release): 1.4.0-beta.2 [skip ci]
semantic-release-bot Aug 23, 2025
d5cead9
docs: updated readme
JairajJangle Aug 23, 2025
f4becaa
Merge branch 'beta' of github.com:JairajJangle/react-native-component…
JairajJangle Aug 23, 2025
f5fe1b8
docs: updated readme
JairajJangle Aug 23, 2025
7ca0cdf
docs: updated readme
JairajJangle Aug 23, 2025
3f8217d
docs: updated readme
JairajJangle Aug 24, 2025
39e8aa8
fix(perf): reduced unnecessary onPercentChange callback calls when la…
JairajJangle Aug 26, 2025
2987541
chore(release): 1.4.0-beta.3 [skip ci]
semantic-release-bot Aug 26, 2025
e0e2c70
docs: updated demo gif in readme
JairajJangle Aug 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions .github/workflows/beta-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Beta Release
on:
push:
branches:
- beta
pull_request:
branches:
- beta
merge_group:
types:
- checks_requested

jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Lint files
run: yarn lint

- name: Typecheck files
run: yarn typecheck

test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Run unit tests
run: yarn test --maxWorkers=2 --coverage

build-library:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Build package
run: yarn prepack

build-web:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Build example for Web
run: |
yarn example expo export:web

publish-beta:
needs: [lint, test, build-library, build-web]
runs-on: ubuntu-latest
permissions:
contents: write # To publish a GitHub release
issues: write # To comment on released issues
pull-requests: write # To comment on released pull requests
id-token: write # To enable use of OIDC for npm provenance
if: github.ref == 'refs/heads/beta'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Ensures all tags are fetched

- name: Setup
uses: ./.github/actions/setup

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*" # Use the latest LTS version of Node.js
registry-url: 'https://registry.npmjs.org/' # Specify npm registry

- name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
run: npm audit signatures # Check the signatures to verify integrity

- name: Release Beta
run: npx semantic-release # Run semantic-release to manage versioning and publishing
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub token for authentication

# Why NODE_AUTH_TOKEN instead of NPM_TOKEN: https://github.com/semantic-release/semantic-release/issues/2313
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # npm token for publishing package

34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
# [1.4.0-beta.3](https://github.com/JairajJangle/react-native-visibility-sensor/compare/v1.4.0-beta.2...v1.4.0-beta.3) (2025-08-26)


### Bug Fixes

* **perf:** reduced unnecessary onPercentChange callback calls when last percent is already 0 ([39e8aa8](https://github.com/JairajJangle/react-native-visibility-sensor/commit/39e8aa847b42eabe9341e4bec96c35f1b8c67972))

# [1.4.0-beta.2](https://github.com/JairajJangle/react-native-visibility-sensor/compare/v1.4.0-beta.1...v1.4.0-beta.2) (2025-08-23)


### Bug Fixes

* added missing state dependencies in visiblity calculations ([af0161c](https://github.com/JairajJangle/react-native-visibility-sensor/commit/af0161c6fcfb4d72f7db97e7fb1c88cc96706c13))

# [1.4.0-beta.1](https://github.com/JairajJangle/react-native-visibility-sensor/compare/v1.3.22...v1.4.0-beta.1) (2025-08-23)


### Bug Fixes

* add window dimension change listener to handle orientation changes ([5f640db](https://github.com/JairajJangle/react-native-visibility-sensor/commit/5f640db1be9f447f9b82aece4b1e9a366df36573))
* handle initial visibility state and improve measurement timing ([f5e4de7](https://github.com/JairajJangle/react-native-visibility-sensor/commit/f5e4de7dd7802951a5654fe9ab8cf574f9f4d52d))
* prevent race conditions during rapid mount/unmount cycles ([de6cb59](https://github.com/JairajJangle/react-native-visibility-sensor/commit/de6cb59111b4b8944d3070bb826290b8941340c5))
* prevent state updates on unmounted components ([6c9786a](https://github.com/JairajJangle/react-native-visibility-sensor/commit/6c9786a1ccc46e5c48813e349a7e6aabb9b4052a))


### Features

* added percent visiblity callback requested in [#44](https://github.com/JairajJangle/react-native-visibility-sensor/issues/44) ([e78fa27](https://github.com/JairajJangle/react-native-visibility-sensor/commit/e78fa27a9fe2d8c37227f3ab6022964aeafe8b37))


### Performance Improvements

* conserved percent calc. if view is not visible - [#44](https://github.com/JairajJangle/react-native-visibility-sensor/issues/44) ([81d0036](https://github.com/JairajJangle/react-native-visibility-sensor/commit/81d003651348dcfb871d832137330d174f1f56e2))

## [1.3.22](https://github.com/JairajJangle/react-native-visibility-sensor/compare/v1.3.21...v1.3.22) (2025-08-12)


Expand Down
62 changes: 30 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
[![npm version](https://img.shields.io/npm/v/%40futurejj%2Freact-native-visibility-sensor)](https://badge.fury.io/js/%40futurejj%2Freact-native-visibility-sensor) [![License](https://img.shields.io/github/license/JairajJangle/react-native-visibility-sensor)](https://github.com/JairajJangle/react-native-visibility-sensor/blob/main/LICENSE) [![Workflow Status](https://github.com/JairajJangle/react-native-visibility-sensor/actions/workflows/ci.yml/badge.svg)](https://github.com/JairajJangle/react-native-visibility-sensor/actions/workflows/ci.yml) ![Android](https://img.shields.io/badge/-Android-555555?logo=android&logoColor=3DDC84) ![iOS](https://img.shields.io/badge/-iOS-555555?logo=apple&logoColor=white) ![Web](https://img.shields.io/badge/-Web-555555?logo=google-chrome&logoColor=0096FF) [![GitHub issues](https://img.shields.io/github/issues/JairajJangle/react-native-visibility-sensor)](https://github.com/JairajJangle/react-native-visibility-sensor/issues?q=is%3Aopen+is%3Aissue) ![TS](https://img.shields.io/badge/TypeScript-strict_💪-blue) [![Expo Snack](https://img.shields.io/badge/Expo%20Snack-555555?style=flat&logo=expo&logoColor=white)](https://snack.expo.dev/@futurejj/react-native-visibility-sensor-example) ![NPM Downloads](https://img.shields.io/npm/dm/%40futurejj%2Freact-native-visibility-sensor) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40futurejj%2Freact-native-visibility-sensor)

<div align="center">
<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYTlsaGEyaXd4ZDdicWdtYnM4d3FibWltZjJwd3RrOG80b2pzemQ4dCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/hNCfKTz7YMuDPIM7eV/giphy.gif" alt="Visibility Sensor demo" style="border: 1px solid gray;" />
<img src="https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExOXN4ZWs5ejdiYmZ5Zm5xaWw5YXZ5OGYwMmczcnFneXNiYW5hcDh6cCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/gEbrrDtgnoq6Fs8FNq/giphy.gif" alt="Visibility Sensor demo" style="border: 1px solid gray;" />
</div>



## Installation

Using yarn
Expand All @@ -26,32 +27,28 @@ npm install @futurejj/react-native-visibility-sensor

## Usage

```typescript
import React from 'react';
```tsx
import React, { useState } from 'react';
import { ScrollView, Text } from 'react-native';
import { VisibilitySensor } from '@futurejj/react-native-visibility-sensor';

export default function VisibilitySensorExample() {
const [isInView, setIsInView] = React.useState(false);

function checkVisible(isVisible: boolean) {
if (isVisible) {
setIsInView(isVisible);
} else {
setIsInView(isVisible);
}
}
const [isVisible, setIsVisible] = useState(false);
const [percentVisible, setPercentVisible] = useState<number>(0);

return (
<ScrollView>
<VisibilitySensor
onChange={(isVisible) => checkVisible(isVisible)}
threshold={{
left: 100,
right: 100,
}}
style={[styles.item, { backgroundColor: isInView ? 'green' : 'red' }]}>
<Text>This View is currently visible? {isInView ? 'yes' : 'no'}</Text>
onChange={setIsVisible}
onPercentChange={setPercentVisible} // optional callback for % change
threshold={{ top: 100, bottom: 100 }}
style={[styles.item, { backgroundColor: isVisible ? 'green' : 'red' }]}>

{/* Visibility state */}
<Text>This View is currently visible? {isVisible ? 'yes' : 'no'}</Text>

{/* Percent visibility state */}
<Text>{`Percent visible: ${percentVisible}%`}</Text>
</VisibilitySensor>
</ScrollView>
);
Expand All @@ -61,26 +58,27 @@ export default function VisibilitySensorExample() {

`VisibilitySensorProps` extends `ViewProps` from React Native, which includes common properties for all views, such as `style`, `onLayout`, etc.

| Property | Type | Required | Description |
| ----------- | ------------------------------------------------------- | -------- | ------------------------------------------------------------ |
| onChange | (visible: boolean) => void | Yes | Callback function that fires when visibility changes. |
| disabled | boolean | No | If `true`, disables the sensor. |
| triggerOnce | boolean | No | If `true`, the sensor will only trigger once. |
| delay | number \| undefined | No | The delay in milliseconds before the sensor triggers. |
| threshold | [VisibilitySensorThreshold](#visibilitysensorthreshold) | No | Defines the part of the view that must be visible for the sensor to trigger. |
| Property | Type | Required | Description |
| ----------------- | ------------------------------------------------------- | -------- | ------------------------------------------------------------ |
| `onChange` | `(visible: boolean) => void` | Yes | Callback function that fires when visibility changes. |
| `onPercentChange` | `(percentVisible: number) => void` | No | Callback function that fires when visibility % changes. |
| `disabled` | `boolean` | No | If `true`, disables the sensor. |
| `triggerOnce` | `boolean` | No | If `true`, the sensor will only trigger once. |
| `delay` | `number` or `undefined` | No | The delay in milliseconds before the sensor triggers. |
| `threshold` | [VisibilitySensorThreshold](#visibilitysensorthreshold) | No | Defines the part of the view that must be visible for the sensor to trigger. |

Additionally, all properties from `ViewProps` are also applicable.

---

### VisibilitySensorThreshold

| Property | Type | Required | Description |
| -------- | ------ | -------- | ------------------------------------------ |
| top | number | No | The top threshold value for visibility. |
| bottom | number | No | The bottom threshold value for visibility. |
| left | number | No | The left threshold value for visibility. |
| right | number | No | The right threshold value for visibility. |
| Property | Type | Required | Description |
| -------- | -------- | -------- | ------------------------------------------ |
| `top` | `number` | No | The top threshold value for visibility. |
| `bottom` | `number` | No | The bottom threshold value for visibility. |
| `left` | `number` | No | The left threshold value for visibility. |
| `right` | `number` | No | The right threshold value for visibility. |

---

Expand Down
4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"web": "expo start --web"
},
"dependencies": {
"expo": "^53.0.20",
"expo": "^53.0.22",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-native": "0.79.3",
"react-native": "0.79.5",
"react-native-web": "^0.20.0"
},
"devDependencies": {
Expand Down
Loading