Improved namespace conflicted attribute check performance. It was
too slow for deep elements.
Reported by l33thaxor.
Fixes
Fixed a bug that default entity expansions are counted for
security check. Default entity expansions should not be counted
because they don't have a security risk.
Improved namespace conflicted attribute check performance. It was
too slow for deep elements.
Reported by l33thaxor.
Fixes
Fixed a bug that default entity expansions are counted for
security check. Default entity expansions should not be counted
because they don't have a security risk.
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rexml&package-manager=bundler&previous-version=3.2.9&new-version=3.3.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/software-mansion/react-native-screens/network/alerts).
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Example/Gemfile.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Example/Gemfile.lock b/Example/Gemfile.lock
index 87401e9531..8da5212e64 100644
--- a/Example/Gemfile.lock
+++ b/Example/Gemfile.lock
@@ -84,7 +84,7 @@ GEM
netrc (0.11.0)
nkf (0.2.0)
public_suffix (4.0.7)
- rexml (3.2.9)
+ rexml (3.3.6)
strscan
ruby-macho (2.5.1)
strscan (3.1.0)
@@ -92,13 +92,13 @@ GEM
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
- xcodeproj (1.24.0)
+ xcodeproj (1.25.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
- rexml (~> 3.2.4)
+ rexml (>= 3.3.2, < 4.0)
PLATFORMS
ruby
From b7a51fc6703565a789eb647b0a8cca3ded660819 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrycja=20Kali=C5=84ska?=
<59940332+patrycjakalinska@users.noreply.github.com>
Date: Thu, 29 Aug 2024 11:52:09 +0200
Subject: [PATCH 02/38] docs: Fix placement of Hero on big screens (#2305)
Before:
![image](https://github.com/user-attachments/assets/2cfbec89-ddd2-46b0-ac1f-aadd7a8271d9)
After:
---
.../Hero/ScreenSequence/styles.module.css | 20 +++++++++++++++++++
.../Hero/StartScreen/styles.module.css | 16 +--------------
2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/docs/src/components/Hero/ScreenSequence/styles.module.css b/docs/src/components/Hero/ScreenSequence/styles.module.css
index 2651a9ebfd..271678ed76 100644
--- a/docs/src/components/Hero/ScreenSequence/styles.module.css
+++ b/docs/src/components/Hero/ScreenSequence/styles.module.css
@@ -8,6 +8,26 @@
align-items: center;
}
+@media (min-width: 2920px) {
+ .screens {
+ top: 3rem;
+ min-height: 70%;
+ }
+}
+@media (min-width: 3000px) and (min-height: 1500px) {
+ .screens {
+ top: -3vh;
+ min-height: 50%;
+ }
+}
+
+@media (min-width: 3000px) and (min-height: 2000px) {
+ .screens {
+ top: -3vh;
+ min-height: 50%;
+ }
+}
+
@media (max-width: 2000px) {
.screens {
top: 4rem;
diff --git a/docs/src/components/Hero/StartScreen/styles.module.css b/docs/src/components/Hero/StartScreen/styles.module.css
index 6804223a85..b5c1c1e8e0 100644
--- a/docs/src/components/Hero/StartScreen/styles.module.css
+++ b/docs/src/components/Hero/StartScreen/styles.module.css
@@ -25,7 +25,7 @@
color: var(--swm-blue-light-80);
}
-[data-theme='dark'] .headingLabel :nth-child(2) {
+[data-theme="dark"] .headingLabel :nth-child(2) {
color: var(--swm-blue-dark-80);
}
@@ -55,20 +55,6 @@
justify-content: flex-start;
}
-@media (min-width: 2920px) {
- .hero {
- flex-direction: row-reverse;
- margin-bottom: 0;
- align-items: center;
- }
- .subheadingLabel {
- width: 100%;
- }
- .heading {
- margin: 0;
- }
-}
-
@media (max-width: 996px) {
.hero {
margin-bottom: 1rem;
From fcee5e15f871a0054018119ad2e2bf9425d85c5e Mon Sep 17 00:00:00 2001
From: Ilia Kurganskii
Date: Mon, 2 Sep 2024 10:22:31 +0200
Subject: [PATCH 03/38] docs(readme): update FullWindowOverlay example path
(#2326)
## Description
Update path for FullWindowOverlay example
## Changes
- Updated `README.md` docs
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 47c9fb4300..b75cb3c413 100644
--- a/README.md
+++ b/README.md
@@ -188,7 +188,7 @@ To take advantage of the native stack navigator primitive for React Navigation t
## `FullWindowOverlay`
-Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/TestsExample/src/Test1096.tsx
+Native `iOS` component for rendering views straight under the `Window`. Based on `RCTPerfMonitor`. You should treat it as a wrapper, providing full-screen, transparent view which receives no props and should ideally render one child `View`, being the root of its view hierarchy. For the example usage, see https://github.com/software-mansion/react-native-screens/blob/main/apps/src/tests/Test1096.tsx
## Interop with [react-native-navigation](https://github.com/wix/react-native-navigation)
From ee7915f2c92157368029187c16fc313a6f6ab28b Mon Sep 17 00:00:00 2001
From: Kirill Zyusko
Date: Mon, 2 Sep 2024 10:28:12 +0200
Subject: [PATCH 04/38] fix: do not force set `translucent` nav bar (until it's
explicitly specified) (#2301)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Description
I have next navigator structure:
- JS
- native-stack
`native-stack` navigator customizes options as:
```ts
{
headerShown: false,
statusBarTranslucent: true,
navigationBarColor: "#FFFFFF",
navigationBarTranslucent: true,
},
```
When I go to `native-stack` - everything works well: the nav bar changes
color. However, when I go back, then I'm getting a gray space in the
bottom of my screen.
It happens because we disable mode `edge-to-edge` by calling
`WindowCompat.setDecorFitsSystemWindows(window, true)` (the gray space
appears because before we were already in edge-to-edge mode, because I
had `KeyboardProvider` mounted in `App.tsx`).
So to fix this problem I decided explicitly check for boolean value for
`navigationBarTranslucent` and set `decorFitsSystemWindows` only when we
have an actual boolean value.
If you think that it's a problem in my project, then, please, let me
know the way to fix it 😊
## Changes
- call `WindowCompat.setDecorFitsSystemWindows(window, true)` only if
`isNavigationBarTranslucent` has a boolean value;
## Screenshots / GIFs
### Before
![telegram-cloud-photo-size-2-5321328488650760881-y](https://github.com/user-attachments/assets/4c1ef654-3146-44bd-aa00-6a810c2aa0aa)
### After
![telegram-cloud-photo-size-2-5321328488650760882-y](https://github.com/user-attachments/assets/7920cf2c-e5b7-46e9-bb75-a581ce2dab2a)
## Test code and steps to reproduce
I tested in `react-native-keyboard-controller` example app, but if you
need to test it in your code - let me know, and I'll try to prepare a
reproduction code.
## Checklist
- [x] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [x] Ensured that CI passes
---
.../src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt
index cbdb5478df..37aefe87b5 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt
@@ -225,7 +225,7 @@ object ScreenWindowTraits {
val window = activity.window
val screenForNavBarTranslucent = findScreenForTrait(screen, WindowTraits.NAVIGATION_BAR_TRANSLUCENT)
- val translucent = screenForNavBarTranslucent?.isNavigationBarTranslucent ?: false
+ val translucent = screenForNavBarTranslucent?.isNavigationBarTranslucent ?: return
// Following method controls whether to display edge-to-edge content that draws behind the navigation bar
WindowCompat.setDecorFitsSystemWindows(window, !translucent)
From d424e1a20fe55688ec9b15ec74d21b2a93dc8bb6 Mon Sep 17 00:00:00 2001
From: ben
Date: Tue, 3 Sep 2024 11:21:32 +0100
Subject: [PATCH 05/38] fix(Android): getChildDrawingOrder when using
refreshcontrol (#2330)
## Description
Fixes #2329
## Changes
- Changes how we check if the child is a CircleImageView to be
minification safe
## Test code and steps to reproduce
Build
`[this](https://github.com/BenIrving/refreshcontrolrepro/tree/main)`
repro using this changeset, observe no crash when navigating between
screens.
You can also check `Test640.tsx` test by going into the second screen
(by button), then try to manually refresh list by swiping down (until
the refresh control will show). During the refresh, try to go back to
the first screen - application shouldn't crash.
## Checklist
- [x] Ensured that CI passes
Co-authored-by: Ben Irving
---
android/src/main/java/com/swmansion/rnscreens/Screen.kt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index 6bbfda09cc..4ae30f5538 100644
--- a/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -9,9 +9,11 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.webkit.WebView
+import android.widget.ImageView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.children
import androidx.fragment.app.Fragment
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.facebook.react.bridge.GuardedRunnable
import com.facebook.react.bridge.ReactContext
import com.facebook.react.uimanager.UIManagerHelper
@@ -363,7 +365,7 @@ class Screen(
parent?.let {
for (i in 0 until it.childCount) {
val child = it.getChildAt(i)
- if (child.javaClass.simpleName.equals("CircleImageView")) {
+ if (parent is SwipeRefreshLayout && child is ImageView) {
// SwipeRefreshLayout class which has CircleImageView as a child,
// does not handle `startViewTransition` properly.
// It has a custom `getChildDrawingOrder` method which returns
From ef475388882abd74f545b91a8d3bddffc87481f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrycja=20Kali=C5=84ska?=
<59940332+patrycjakalinska@users.noreply.github.com>
Date: Mon, 9 Sep 2024 13:22:57 +0200
Subject: [PATCH 06/38] docs: add Testimonials (#2333)
This PR adds gathered Testimonials to Screens landing page
---
.../Testimonials/TestimonialList/index.tsx | 75 +++++++++++++------
docs/src/pages/index.js | 4 +-
2 files changed, 54 insertions(+), 25 deletions(-)
diff --git a/docs/src/components/Testimonials/TestimonialList/index.tsx b/docs/src/components/Testimonials/TestimonialList/index.tsx
index 2a008f021c..c8ffa85156 100644
--- a/docs/src/components/Testimonials/TestimonialList/index.tsx
+++ b/docs/src/components/Testimonials/TestimonialList/index.tsx
@@ -5,33 +5,62 @@ import TestimonialItem from '@site/src/components/Testimonials/TestimonialItem';
const items = [
{
- author: 'Test author',
- company: 'Test',
- body: 'Screens are the best ever and ever - I love using it!',
- link: 'https://test.com/',
+ author: 'Satyajit Sahoo',
+ company: 'Callstack',
+ body: "React Navigation wouldn't be the same today without React Native Screens. Gotta give kudos to the Screens team for bringing native navigation with a nice API. And they are always hard at work to bring more native features as well!",
+ link: 'https://x.com/satya164/status/1826694902660694028',
image: {
- alt: 'test',
- src: '/img/logo.svg',
+ alt: 'satya',
+ src: 'https://pbs.twimg.com/profile_images/1426585051379159040/RG8CUmff_400x400.jpg',
},
},
{
- author: 'Test author',
- company: 'Test',
- body: 'Screens are the best ever and ever - I love using it!',
- link: 'https://test.com/',
+ author: 'Ferran Negre Pizzaro',
+ company: 'FitHero',
+ body: 'I would never build a serious React Native app without it.',
+ link: 'https://x.com/ferrannp/status/1826734343571796317',
image: {
- alt: 'test',
- src: '/img/logo.svg',
+ alt: 'ferran',
+ src: 'https://pbs.twimg.com/profile_images/1225546442917515264/OBZyRYWO_400x400.jpg',
},
},
{
- author: 'Test author',
- company: 'Test',
- body: 'Screens are the best ever and ever - I love using it!',
- link: 'https://test.com/',
+ author: 'Sébastien Lorber',
+ company: 'This Week In React',
+ body: 'React Native Screens is what makes React Native navigation truly competitive against native apps',
+ link: 'https://x.com/sebastienlorber/status/1828760445106466959',
image: {
- alt: 'test',
- src: '/img/logo.svg',
+ alt: 'seb',
+ src: 'https://pbs.twimg.com/profile_images/573206276819140608/gKAusMeX_400x400.jpeg',
+ },
+ },
+ {
+ author: 'Jamon Holmgren',
+ company: 'Infinite Red',
+ body: 'React Native Screens is one of the most underrated React Native libraries!',
+ link: 'https://x.com/jamonholmgren/status/1826713786797228166',
+ image: {
+ alt: 'jamon',
+ src: 'https://pbs.twimg.com/profile_images/1712505856905170944/LDFMYGSQ_400x400.jpg',
+ },
+ },
+ {
+ author: 'Kwesi Kay',
+ body: "React Native Screens has been a game-changer for me! It optimizes performance by reducing memory usage and makes navigation smoother, especially in large apps. Couldn't imagine building without it now! 😍",
+ link: 'https://x.com/EiiKwesiKay/status/1826282042965000267',
+ image: {
+ alt: 'kwesikay',
+ src: 'https://pbs.twimg.com/profile_images/1823345356794449920/UVMh-ABt_400x400.jpg',
+ },
+ },
+ {
+ author: 'Brent Vatne',
+ company: 'Expo',
+ body: "react-native-screens is one of the most essential libraries in the ecosystem. it's a crucial building block for react-navigation and expo-router, and therefore nearly all react-native apps! native stack in particular does tons of heavy lifting to make your apps feel fantastic.",
+ link: 'https://x.com/notbrent/status/1826699409738137796',
+ image: {
+ alt: 'brent',
+ src: 'https://pbs.twimg.com/profile_images/1509282922498428929/gV2uTCff_400x400.jpg',
},
},
];
@@ -42,7 +71,7 @@ const TestimonialList = () => {
useEffect(() => {
const updateHeight = () => {
const testimonialContainer = document.querySelector(
- `.testimonialContainer-${activeIndex}`
+ `.testimonialContainer-${activeIndex}`,
);
const testimonialSlides =
document.querySelector('.testimonialSlides');
@@ -73,7 +102,7 @@ const TestimonialList = () => {
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=express&package-manager=npm_and_yarn&previous-version=4.19.2&new-version=4.21.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/software-mansion/react-native-screens/network/alerts).
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
docs/yarn.lock | 97 +++++++++++++++++++++++++++-----------------------
1 file changed, 52 insertions(+), 45 deletions(-)
diff --git a/docs/yarn.lock b/docs/yarn.lock
index 63b02bdec4..c6be251c77 100644
--- a/docs/yarn.lock
+++ b/docs/yarn.lock
@@ -4122,9 +4122,9 @@ __metadata:
languageName: node
linkType: hard
-"body-parser@npm:1.20.2":
- version: 1.20.2
- resolution: "body-parser@npm:1.20.2"
+"body-parser@npm:1.20.3":
+ version: 1.20.3
+ resolution: "body-parser@npm:1.20.3"
dependencies:
bytes: "npm:3.1.2"
content-type: "npm:~1.0.5"
@@ -4134,11 +4134,11 @@ __metadata:
http-errors: "npm:2.0.0"
iconv-lite: "npm:0.4.24"
on-finished: "npm:2.4.1"
- qs: "npm:6.11.0"
+ qs: "npm:6.13.0"
raw-body: "npm:2.5.2"
type-is: "npm:~1.6.18"
unpipe: "npm:1.0.0"
- checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9
+ checksum: 10c0/0a9a93b7518f222885498dcecaad528cf010dd109b071bf471c93def4bfe30958b83e03496eb9c1ad4896db543d999bb62be1a3087294162a88cfa1b42c16310
languageName: node
linkType: hard
@@ -5486,6 +5486,13 @@ __metadata:
languageName: node
linkType: hard
+"encodeurl@npm:~2.0.0":
+ version: 2.0.0
+ resolution: "encodeurl@npm:2.0.0"
+ checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb
+ languageName: node
+ linkType: hard
+
"encoding@npm:^0.1.13":
version: 0.1.13
resolution: "encoding@npm:0.1.13"
@@ -5722,41 +5729,41 @@ __metadata:
linkType: hard
"express@npm:^4.17.3":
- version: 4.19.2
- resolution: "express@npm:4.19.2"
+ version: 4.21.0
+ resolution: "express@npm:4.21.0"
dependencies:
accepts: "npm:~1.3.8"
array-flatten: "npm:1.1.1"
- body-parser: "npm:1.20.2"
+ body-parser: "npm:1.20.3"
content-disposition: "npm:0.5.4"
content-type: "npm:~1.0.4"
cookie: "npm:0.6.0"
cookie-signature: "npm:1.0.6"
debug: "npm:2.6.9"
depd: "npm:2.0.0"
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
etag: "npm:~1.8.1"
- finalhandler: "npm:1.2.0"
+ finalhandler: "npm:1.3.1"
fresh: "npm:0.5.2"
http-errors: "npm:2.0.0"
- merge-descriptors: "npm:1.0.1"
+ merge-descriptors: "npm:1.0.3"
methods: "npm:~1.1.2"
on-finished: "npm:2.4.1"
parseurl: "npm:~1.3.3"
- path-to-regexp: "npm:0.1.7"
+ path-to-regexp: "npm:0.1.10"
proxy-addr: "npm:~2.0.7"
- qs: "npm:6.11.0"
+ qs: "npm:6.13.0"
range-parser: "npm:~1.2.1"
safe-buffer: "npm:5.2.1"
- send: "npm:0.18.0"
- serve-static: "npm:1.15.0"
+ send: "npm:0.19.0"
+ serve-static: "npm:1.16.2"
setprototypeof: "npm:1.2.0"
statuses: "npm:2.0.1"
type-is: "npm:~1.6.18"
utils-merge: "npm:1.0.1"
vary: "npm:~1.1.2"
- checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb
+ checksum: 10c0/4cf7ca328f3fdeb720f30ccb2ea7708bfa7d345f9cc460b64a82bf1b2c91e5b5852ba15a9a11b2a165d6089acf83457fc477dc904d59cd71ed34c7a91762c6cc
languageName: node
linkType: hard
@@ -5898,18 +5905,18 @@ __metadata:
languageName: node
linkType: hard
-"finalhandler@npm:1.2.0":
- version: 1.2.0
- resolution: "finalhandler@npm:1.2.0"
+"finalhandler@npm:1.3.1":
+ version: 1.3.1
+ resolution: "finalhandler@npm:1.3.1"
dependencies:
debug: "npm:2.6.9"
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
on-finished: "npm:2.4.1"
parseurl: "npm:~1.3.3"
statuses: "npm:2.0.1"
unpipe: "npm:~1.0.0"
- checksum: 10c0/64b7e5ff2ad1fcb14931cd012651631b721ce657da24aedb5650ddde9378bf8e95daa451da43398123f5de161a81e79ff5affe4f9f2a6d2df4a813d6d3e254b7
+ checksum: 10c0/d38035831865a49b5610206a3a9a9aae4e8523cbbcd01175d0480ffbf1278c47f11d89be3ca7f617ae6d94f29cf797546a4619cd84dd109009ef33f12f69019f
languageName: node
linkType: hard
@@ -7698,10 +7705,10 @@ __metadata:
languageName: node
linkType: hard
-"merge-descriptors@npm:1.0.1":
- version: 1.0.1
- resolution: "merge-descriptors@npm:1.0.1"
- checksum: 10c0/b67d07bd44cfc45cebdec349bb6e1f7b077ee2fd5beb15d1f7af073849208cb6f144fe403e29a36571baf3f4e86469ac39acf13c318381e958e186b2766f54ec
+"merge-descriptors@npm:1.0.3":
+ version: 1.0.3
+ resolution: "merge-descriptors@npm:1.0.3"
+ checksum: 10c0/866b7094afd9293b5ea5dcd82d71f80e51514bed33b4c4e9f516795dc366612a4cbb4dc94356e943a8a6914889a914530badff27f397191b9b75cda20b6bae93
languageName: node
linkType: hard
@@ -8460,10 +8467,10 @@ __metadata:
languageName: node
linkType: hard
-"path-to-regexp@npm:0.1.7":
- version: 0.1.7
- resolution: "path-to-regexp@npm:0.1.7"
- checksum: 10c0/50a1ddb1af41a9e68bd67ca8e331a705899d16fb720a1ea3a41e310480948387daf603abb14d7b0826c58f10146d49050a1291ba6a82b78a382d1c02c0b8f905
+"path-to-regexp@npm:0.1.10":
+ version: 0.1.10
+ resolution: "path-to-regexp@npm:0.1.10"
+ checksum: 10c0/34196775b9113ca6df88e94c8d83ba82c0e1a2063dd33bfe2803a980da8d49b91db8104f49d5191b44ea780d46b8670ce2b7f4a5e349b0c48c6779b653f1afe4
languageName: node
linkType: hard
@@ -9136,12 +9143,12 @@ __metadata:
languageName: node
linkType: hard
-"qs@npm:6.11.0":
- version: 6.11.0
- resolution: "qs@npm:6.11.0"
+"qs@npm:6.13.0":
+ version: 6.13.0
+ resolution: "qs@npm:6.13.0"
dependencies:
- side-channel: "npm:^1.0.4"
- checksum: 10c0/4e4875e4d7c7c31c233d07a448e7e4650f456178b9dd3766b7cfa13158fdb24ecb8c4f059fa91e820dc6ab9f2d243721d071c9c0378892dcdad86e9e9a27c68f
+ side-channel: "npm:^1.0.6"
+ checksum: 10c0/62372cdeec24dc83a9fb240b7533c0fdcf0c5f7e0b83343edd7310f0ab4c8205a5e7c56406531f2e47e1b4878a3821d652be4192c841de5b032ca83619d8f860
languageName: node
linkType: hard
@@ -9960,9 +9967,9 @@ __metadata:
languageName: node
linkType: hard
-"send@npm:0.18.0":
- version: 0.18.0
- resolution: "send@npm:0.18.0"
+"send@npm:0.19.0":
+ version: 0.19.0
+ resolution: "send@npm:0.19.0"
dependencies:
debug: "npm:2.6.9"
depd: "npm:2.0.0"
@@ -9977,7 +9984,7 @@ __metadata:
on-finished: "npm:2.4.1"
range-parser: "npm:~1.2.1"
statuses: "npm:2.0.1"
- checksum: 10c0/0eb134d6a51fc13bbcb976a1f4214ea1e33f242fae046efc311e80aff66c7a43603e26a79d9d06670283a13000e51be6e0a2cb80ff0942eaf9f1cd30b7ae736a
+ checksum: 10c0/ea3f8a67a8f0be3d6bf9080f0baed6d2c51d11d4f7b4470de96a5029c598a7011c497511ccc28968b70ef05508675cebff27da9151dd2ceadd60be4e6cf845e3
languageName: node
linkType: hard
@@ -10021,15 +10028,15 @@ __metadata:
languageName: node
linkType: hard
-"serve-static@npm:1.15.0":
- version: 1.15.0
- resolution: "serve-static@npm:1.15.0"
+"serve-static@npm:1.16.2":
+ version: 1.16.2
+ resolution: "serve-static@npm:1.16.2"
dependencies:
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
parseurl: "npm:~1.3.3"
- send: "npm:0.18.0"
- checksum: 10c0/fa9f0e21a540a28f301258dfe1e57bb4f81cd460d28f0e973860477dd4acef946a1f41748b5bd41c73b621bea2029569c935faa38578fd34cd42a9b4947088ba
+ send: "npm:0.19.0"
+ checksum: 10c0/528fff6f5e12d0c5a391229ad893910709bc51b5705962b09404a1d813857578149b8815f35d3ee5752f44cd378d0f31669d4b1d7e2d11f41e08283d5134bd1f
languageName: node
linkType: hard
@@ -10120,7 +10127,7 @@ __metadata:
languageName: node
linkType: hard
-"side-channel@npm:^1.0.4":
+"side-channel@npm:^1.0.6":
version: 1.0.6
resolution: "side-channel@npm:1.0.6"
dependencies:
From d01f9604ded46204ea48f74fd1b69f2fde6c8ff7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 25 Sep 2024 10:29:18 +0200
Subject: [PATCH 10/38] chore(deps): bump serve-static from 1.15.0 to 1.16.2 in
/Example (#2343)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
[//]: # (dependabot-start)
⚠️ **Dependabot is rebasing this PR** ⚠️
Rebasing might not happen immediately, so don't worry if this takes some
time.
Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.
---
[//]: # (dependabot-end)
Bumps [serve-static](https://github.com/expressjs/serve-static) from
1.15.0 to 1.16.2.
Release notes
This version was pushed to npm by wesleytodd, a new releaser
for serve-static since your current version.
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=serve-static&package-manager=npm_and_yarn&previous-version=1.15.0&new-version=1.16.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/software-mansion/react-native-screens/network/alerts).
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Example/yarn.lock | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/Example/yarn.lock b/Example/yarn.lock
index eb58dfbda5..e20b7d37b2 100644
--- a/Example/yarn.lock
+++ b/Example/yarn.lock
@@ -5505,6 +5505,13 @@ __metadata:
languageName: node
linkType: hard
+"encodeurl@npm:~2.0.0":
+ version: 2.0.0
+ resolution: "encodeurl@npm:2.0.0"
+ checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb
+ languageName: node
+ linkType: hard
+
"encoding@npm:^0.1.13":
version: 0.1.13
resolution: "encoding@npm:0.1.13"
@@ -10963,9 +10970,9 @@ __metadata:
languageName: node
linkType: hard
-"send@npm:0.18.0":
- version: 0.18.0
- resolution: "send@npm:0.18.0"
+"send@npm:0.19.0":
+ version: 0.19.0
+ resolution: "send@npm:0.19.0"
dependencies:
debug: "npm:2.6.9"
depd: "npm:2.0.0"
@@ -10980,7 +10987,7 @@ __metadata:
on-finished: "npm:2.4.1"
range-parser: "npm:~1.2.1"
statuses: "npm:2.0.1"
- checksum: 10c0/0eb134d6a51fc13bbcb976a1f4214ea1e33f242fae046efc311e80aff66c7a43603e26a79d9d06670283a13000e51be6e0a2cb80ff0942eaf9f1cd30b7ae736a
+ checksum: 10c0/ea3f8a67a8f0be3d6bf9080f0baed6d2c51d11d4f7b4470de96a5029c598a7011c497511ccc28968b70ef05508675cebff27da9151dd2ceadd60be4e6cf845e3
languageName: node
linkType: hard
@@ -11001,14 +11008,14 @@ __metadata:
linkType: hard
"serve-static@npm:^1.13.1":
- version: 1.15.0
- resolution: "serve-static@npm:1.15.0"
+ version: 1.16.2
+ resolution: "serve-static@npm:1.16.2"
dependencies:
- encodeurl: "npm:~1.0.2"
+ encodeurl: "npm:~2.0.0"
escape-html: "npm:~1.0.3"
parseurl: "npm:~1.3.3"
- send: "npm:0.18.0"
- checksum: 10c0/fa9f0e21a540a28f301258dfe1e57bb4f81cd460d28f0e973860477dd4acef946a1f41748b5bd41c73b621bea2029569c935faa38578fd34cd42a9b4947088ba
+ send: "npm:0.19.0"
+ checksum: 10c0/528fff6f5e12d0c5a391229ad893910709bc51b5705962b09404a1d813857578149b8815f35d3ee5752f44cd378d0f31669d4b1d7e2d11f41e08283d5134bd1f
languageName: node
linkType: hard
From f80281bf6785aea0c65ec12832d187ff582e3790 Mon Sep 17 00:00:00 2001
From: Christoph Pader
Date: Wed, 25 Sep 2024 10:31:22 +0200
Subject: [PATCH 11/38] feat(Android): add ios like `ios_from_left` slide
animation (#2328)
## Description
This PR is based on
https://github.com/software-mansion/react-native-screens/pull/1945 and
implements the `ios` animation in the reverse direction (slide in from
left to right, slide out from right to left)
## Changes
## Test code and steps to reproduce
## Checklist
- [x] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [x] Ensured that CI passes
---
.../src/main/java/com/swmansion/rnscreens/Screen.kt | 2 ++
.../main/java/com/swmansion/rnscreens/ScreenStack.kt | 12 +++++++++---
.../com/swmansion/rnscreens/ScreenViewManager.kt | 2 ++
.../base/anim/rns_ios_from_left_background_close.xml | 5 +++++
...ios.xml => rns_ios_from_left_background_open.xml} | 2 +-
.../base/anim/rns_ios_from_left_foreground_close.xml | 6 ++++++
.../base/anim/rns_ios_from_left_foreground_open.xml | 6 ++++++
...s.xml => rns_ios_from_right_background_close.xml} | 0
.../base/anim/rns_ios_from_right_background_open.xml | 5 +++++
...s.xml => rns_ios_from_right_foreground_close.xml} | 0
...os.xml => rns_ios_from_right_foreground_open.xml} | 0
apps/src/screens/Animations.tsx | 2 ++
apps/src/screens/Events.tsx | 2 ++
guides/GUIDE_FOR_LIBRARY_AUTHORS.md | 4 +++-
ios/RNSConvert.mm | 5 ++++-
ios/RNSScreen.mm | 2 ++
native-stack/README.md | 4 +++-
src/fabric/ScreenNativeComponent.ts | 4 +++-
src/native-stack/types.tsx | 4 +++-
src/types.tsx | 8 ++++++--
windows/RNScreens/Screen.h | 4 +++-
21 files changed, 67 insertions(+), 12 deletions(-)
create mode 100644 android/src/main/res/base/anim/rns_ios_from_left_background_close.xml
rename android/src/main/res/base/anim/{rns_slide_out_to_left_ios.xml => rns_ios_from_left_background_open.xml} (86%)
create mode 100644 android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml
create mode 100644 android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml
rename android/src/main/res/base/anim/{rns_slide_in_from_left_ios.xml => rns_ios_from_right_background_close.xml} (100%)
create mode 100644 android/src/main/res/base/anim/rns_ios_from_right_background_open.xml
rename android/src/main/res/base/anim/{rns_slide_out_to_right_ios.xml => rns_ios_from_right_foreground_close.xml} (100%)
rename android/src/main/res/base/anim/{rns_slide_in_from_right_ios.xml => rns_ios_from_right_foreground_open.xml} (100%)
diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index 4ae30f5538..a6cb8c7501 100644
--- a/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -436,6 +436,8 @@ class Screen(
SLIDE_FROM_LEFT,
FADE_FROM_BOTTOM,
IOS,
+ IOS_FROM_RIGHT,
+ IOS_FROM_LEFT,
}
enum class ReplaceAnimation {
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
index 27624fdf70..b700bffffd 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
@@ -182,7 +182,9 @@ class ScreenStack(
R.anim.rns_no_animation_medium,
)
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_right_ios, R.anim.rns_slide_out_to_left_ios)
+ StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
+ StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
+ StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_foreground_open, R.anim.rns_ios_from_left_background_open)
}
} else {
when (stackAnimation) {
@@ -220,7 +222,9 @@ class ScreenStack(
R.anim.rns_slide_out_to_bottom,
)
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_slide_in_from_left_ios, R.anim.rns_slide_out_to_right_ios)
+ StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_close, R.anim.rns_ios_from_right_background_close)
+ StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_background_close, R.anim.rns_ios_from_right_foreground_close)
+ StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_background_close, R.anim.rns_ios_from_left_foreground_close)
}
}
}
@@ -413,6 +417,8 @@ class ScreenStack(
Build.VERSION.SDK_INT >= 33 ||
fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
- fragmentWrapper.screen.stackAnimation === StackAnimation.IOS
+ fragmentWrapper.screen.stackAnimation === StackAnimation.IOS ||
+ fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
+ fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_LEFT
}
}
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
index 9f0f0ab94c..de5be092b5 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
@@ -143,6 +143,8 @@ open class ScreenViewManager :
"slide_from_bottom" -> Screen.StackAnimation.SLIDE_FROM_BOTTOM
"fade_from_bottom" -> Screen.StackAnimation.FADE_FROM_BOTTOM
"ios" -> Screen.StackAnimation.IOS
+ "ios_from_right" -> Screen.StackAnimation.IOS_FROM_RIGHT
+ "ios_from_left" -> Screen.StackAnimation.IOS_FROM_LEFT
else -> throw JSApplicationIllegalArgumentException("Unknown animation type $animation")
}
}
diff --git a/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml b/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml
new file mode 100644
index 0000000000..5d75e0b6b9
--- /dev/null
+++ b/android/src/main/res/base/anim/rns_ios_from_left_background_close.xml
@@ -0,0 +1,5 @@
+
+
diff --git a/android/src/main/res/base/anim/rns_slide_out_to_left_ios.xml b/android/src/main/res/base/anim/rns_ios_from_left_background_open.xml
similarity index 86%
rename from android/src/main/res/base/anim/rns_slide_out_to_left_ios.xml
rename to android/src/main/res/base/anim/rns_ios_from_left_background_open.xml
index 0789fbed24..11a8d45d36 100644
--- a/android/src/main/res/base/anim/rns_slide_out_to_left_ios.xml
+++ b/android/src/main/res/base/anim/rns_ios_from_left_background_open.xml
@@ -2,4 +2,4 @@
+ android:toXDelta="30%" />
diff --git a/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml b/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml
new file mode 100644
index 0000000000..2cb62377d0
--- /dev/null
+++ b/android/src/main/res/base/anim/rns_ios_from_left_foreground_close.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml b/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml
new file mode 100644
index 0000000000..394ac6655d
--- /dev/null
+++ b/android/src/main/res/base/anim/rns_ios_from_left_foreground_open.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/android/src/main/res/base/anim/rns_slide_in_from_left_ios.xml b/android/src/main/res/base/anim/rns_ios_from_right_background_close.xml
similarity index 100%
rename from android/src/main/res/base/anim/rns_slide_in_from_left_ios.xml
rename to android/src/main/res/base/anim/rns_ios_from_right_background_close.xml
diff --git a/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml b/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml
new file mode 100644
index 0000000000..1d92c95470
--- /dev/null
+++ b/android/src/main/res/base/anim/rns_ios_from_right_background_open.xml
@@ -0,0 +1,5 @@
+
+
diff --git a/android/src/main/res/base/anim/rns_slide_out_to_right_ios.xml b/android/src/main/res/base/anim/rns_ios_from_right_foreground_close.xml
similarity index 100%
rename from android/src/main/res/base/anim/rns_slide_out_to_right_ios.xml
rename to android/src/main/res/base/anim/rns_ios_from_right_foreground_close.xml
diff --git a/android/src/main/res/base/anim/rns_slide_in_from_right_ios.xml b/android/src/main/res/base/anim/rns_ios_from_right_foreground_open.xml
similarity index 100%
rename from android/src/main/res/base/anim/rns_slide_in_from_right_ios.xml
rename to android/src/main/res/base/anim/rns_ios_from_right_foreground_open.xml
diff --git a/apps/src/screens/Animations.tsx b/apps/src/screens/Animations.tsx
index 0f969b6aed..10097a5d23 100644
--- a/apps/src/screens/Animations.tsx
+++ b/apps/src/screens/Animations.tsx
@@ -53,6 +53,8 @@ const MainScreen = ({
'slide_from_right',
'slide_from_left',
'ios',
+ 'ios_from_right',
+ 'ios_from_left',
'none',
]}
/>
diff --git a/apps/src/screens/Events.tsx b/apps/src/screens/Events.tsx
index 819efd18d7..9996d9e979 100644
--- a/apps/src/screens/Events.tsx
+++ b/apps/src/screens/Events.tsx
@@ -84,6 +84,8 @@ const MainScreen = ({
'slide_from_right',
'slide_from_left',
'ios',
+ 'ios_from_right',
+ 'ios_from_left',
'none',
]}
/>
diff --git a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
index 4b7fd05577..0f0a72d4b1 100644
--- a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
+++ b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
@@ -210,7 +210,9 @@ Allows for the customization of how the given screen should appear/disappear whe
- `"slide_from_bottom"` - slide in the new screen from bottom to top
- `"slide_from_right"` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
- `"slide_from_left"` - slide in the new screen from left to right
-- `"ios"` - iOS like slide in animation (Android only, resolves to default transition on iOS)
+- `"ios"` - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
+- `"ios_from_right"` - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
+- `"ios_from_left"` - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
- `"none"` – the screen appears/disappears without an animation
### `stackPresentation`
diff --git a/ios/RNSConvert.mm b/ios/RNSConvert.mm
index 011964ed52..eb13f1fc70 100644
--- a/ios/RNSConvert.mm
+++ b/ios/RNSConvert.mm
@@ -51,12 +51,15 @@ + (RNSScreenStackPresentation)RNSScreenStackPresentationFromCppEquivalent:
+ (RNSScreenStackAnimation)RNSScreenStackAnimationFromCppEquivalent:(react::RNSScreenStackAnimation)stackAnimation
{
switch (stackAnimation) {
- // these three are intentionally grouped
+ // these four are intentionally grouped
case react::RNSScreenStackAnimation::Slide_from_right:
case react::RNSScreenStackAnimation::Ios:
+ case react::RNSScreenStackAnimation::Ios_from_right:
case react::RNSScreenStackAnimation::Default:
return RNSScreenStackAnimationDefault;
+ // these two are intentionally grouped
case react::RNSScreenStackAnimation::Slide_from_left:
+ case react::RNSScreenStackAnimation::Ios_from_left:
return RNSScreenStackAnimationSlideFromLeft;
case react::RNSScreenStackAnimation::Flip:
return RNSScreenStackAnimationFlip;
diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm
index a207074d17..b91f83cc89 100644
--- a/ios/RNSScreen.mm
+++ b/ios/RNSScreen.mm
@@ -1937,6 +1937,8 @@ @implementation RCTConvert (RNSScreen)
@"slide_from_right" : @(RNSScreenStackAnimationDefault),
@"slide_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
@"ios" : @(RNSScreenStackAnimationDefault),
+ @"ios_from_right" : @(RNSScreenStackAnimationDefault),
+ @"ios_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
}),
RNSScreenStackAnimationDefault,
integerValue)
diff --git a/native-stack/README.md b/native-stack/README.md
index ee04adc601..d0a6563da2 100644
--- a/native-stack/README.md
+++ b/native-stack/README.md
@@ -304,7 +304,9 @@ How the given screen should appear/disappear when pushed or popped at the top of
- `slide_from_bottom` – performs a slide from bottom animation
- `slide_from_right` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
- `slide_from_left` - slide in the new screen from left to right
-- `ios` - iOS like slide in animation (Android only, resolves to default transition on iOS)
+- `"ios"` - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
+- `"ios_from_right"` - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
+- `"ios_from_left"` - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
- `none` - the screen appears/disappears without an animation.
Defaults to `default`.
diff --git a/src/fabric/ScreenNativeComponent.ts b/src/fabric/ScreenNativeComponent.ts
index 48ef882d3a..d552cd6bb4 100644
--- a/src/fabric/ScreenNativeComponent.ts
+++ b/src/fabric/ScreenNativeComponent.ts
@@ -56,7 +56,9 @@ type StackAnimation =
| 'slide_from_left'
| 'slide_from_bottom'
| 'fade_from_bottom'
- | 'ios';
+ | 'ios'
+ | 'ios_from_right'
+ | 'ios_from_left';
type SwipeDirection = 'vertical' | 'horizontal';
diff --git a/src/native-stack/types.tsx b/src/native-stack/types.tsx
index 6f9d252e76..fadde7ee47 100644
--- a/src/native-stack/types.tsx
+++ b/src/native-stack/types.tsx
@@ -440,7 +440,9 @@ export type NativeStackNavigationOptions = {
* - "slide_from_bottom" – performs a slide from bottom animation
* - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "slide_from_left" - slide in the new screen from left to right
- * - "ios" - iOS like slide in animation (Android only, resolves to default transition on iOS)
+ * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
+ * - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
+ * - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
* - "none" – the screen appears/dissapears without an animation
*/
stackAnimation?: ScreenProps['stackAnimation'];
diff --git a/src/types.tsx b/src/types.tsx
index 6e8c8b343b..1ccd801e66 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -39,7 +39,9 @@ export type StackAnimationTypes =
| 'slide_from_bottom'
| 'slide_from_right'
| 'slide_from_left'
- | 'ios';
+ | 'ios'
+ | 'ios_from_right'
+ | 'ios_from_left';
export type BlurEffectTypes =
| 'extraLight'
| 'light'
@@ -365,7 +367,9 @@ export interface ScreenProps extends ViewProps {
* - `slide_from_bottom` – performs a slide from bottom animation
* - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "slide_from_left" - slide in the new screen from left to right
- * - "ios" - iOS like slide in animation (Android only, resolves to default transition on iOS)
+ * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
+ * - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
+ * - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
* - "none" – the screen appears/dissapears without an animation
*/
stackAnimation?: StackAnimationTypes;
diff --git a/windows/RNScreens/Screen.h b/windows/RNScreens/Screen.h
index fd0264129d..564b173f5b 100644
--- a/windows/RNScreens/Screen.h
+++ b/windows/RNScreens/Screen.h
@@ -11,7 +11,9 @@ enum class StackAnimation {
SIMPLE_FROM_BOTTOM,
SLIDE_FROM_RIGHT,
SLIDE_FROM_LEFT,
- IOS
+ IOS,
+ IOS_FROM_RIGHT,
+ IOS_FROM_LEFT
};
enum class ReplaceAnimation { PUSH, POP };
From 98d6ca64a6e5627a95619878abcd930173e8d4ab Mon Sep 17 00:00:00 2001
From: Adrian Ryt <72470330+adrianryt@users.noreply.github.com>
Date: Wed, 25 Sep 2024 10:55:44 +0200
Subject: [PATCH 12/38] fix(Android): minSdkVersion fallback to default 21 but
RN 0.74 require minSdkVersion 23 (#2346)
## Description
This PR is a potential fix for
[#2295](https://github.com/software-mansion/react-native-screens/issues/2295).
Following suggestions in
[PR#2251](https://github.com/software-mansion/react-native-screens/pull/2251#issuecomment-2236771857)
and Android Gradle Plugin version 7.0.0 changes: `minSdkVersion` was
renamed to `minSdk`, `targetSdkVersion` was renamed to `targetSdk`,
`compileSdkVersion` was renamed to `compileSdk`, this PR ensures
compatibility with react native integrated with newest Android projects.
Fixes #2295
## Changes
In `adroid/build.gradle` file to get value for `minSdkVersion` in
`defaultConfig` it will look for `minSdkVersion` in rootProject then
look for `minSdk` and then fallback to default. Previously it looked for
`minSdkVersion` and fallback if not found.
Similar logic for `targetSdkVersion` and `compileSdkVersion`
## Test code and steps to reproduce
## Checklist
- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation:
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
---
android/build.gradle | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/android/build.gradle b/android/build.gradle
index b8683ee4e1..03f63baafc 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -9,7 +9,11 @@ buildscript {
rnsDefaultKotlinVersion = '1.8.0'
}
ext.safeExtGet = {prop, fallback ->
- rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
+ def props = (prop instanceof String) ? [prop] : prop
+ def result = props.find { key ->
+ return rootProject.ext.has(key)
+ }
+ return result ? rootProject.ext.get(result) : fallback
}
repositories {
google()
@@ -77,8 +81,8 @@ android {
}
defaultConfig {
- minSdkVersion safeExtGet('minSdkVersion', rnsDefaultMinSdkVersion)
- targetSdkVersion safeExtGet('targetSdkVersion', rnsDefaultTargetSdkVersion)
+ minSdkVersion safeExtGet(['minSdkVersion', 'minSdk'], rnsDefaultMinSdkVersion)
+ targetSdkVersion safeExtGet(['targetSdkVersion', 'targetSdk'], rnsDefaultTargetSdkVersion)
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString()
@@ -136,7 +140,7 @@ android {
}
}
res {
- if (safeExtGet('compileSdkVersion', rnsDefaultCompileSdkVersion) >= 33) {
+ if (safeExtGet(['compileSdkVersion', 'compileSdk'], rnsDefaultCompileSdkVersion) >= 33) {
srcDirs = ["${androidResDir}/base", "${androidResDir}/v33"]
} else {
srcDirs = ["${androidResDir}/base"]
From 75c15c1facbae598b463477d7d0e3cebd2aacdc6 Mon Sep 17 00:00:00 2001
From: Evan Bacon
Date: Wed, 25 Sep 2024 16:56:50 +0200
Subject: [PATCH 13/38] feat: add basic React Server Component support (#2170)
## Description
Add basic support for React Server Components support.
Related PRs for more context:
- https://github.com/necolas/react-native-web/pull/2678
- https://github.com/th3rdwave/react-native-safe-area-context/pull/502
- https://github.com/software-mansion/react-native-svg/pull/2287
## Changes
- Added basic React Server Component support
## Test code and steps to reproduce
- It's kinda hard to test this E2E. I wrote a small jest runner in
jest-expo which executes in RSC mode, but it requires React 19 to work.
Here's where I tested this patch https://github.com/expo/expo/pull/29404
- It will likely break between now and the full release, but this should
at least reduce the number of patches required to work on Expo Router
support.
- There's pretty good compilation on web:
```
2:I["../../node_modules/react-native-web/dist/exports/View/index.js",[],""]
3:I["../../node_modules/react-native-web/dist/exports/Image/index.js",[],""]
1:{"name":"ScreenStackHeaderBackButtonImage","env":"Server","owner":null}
0:D"$1"
0:["$","$L2",null,{"children":["$","$L3",null,{"resizeMode":"center","fadeDuration":0},"$1"]},"$1"]
```
- And more opaque compilation on native platforms:
```
1:I["../../node_modules/react-native-screens/src/components/ScreenStackHeaderConfig.tsx",[],"ScreenStackHeaderBackButtonImage"]
0:["$","$L1",null,{},null]
```
## Checklist
- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation:
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
---
src/TransitionProgressContext.tsx | 2 ++
src/components/Screen.tsx | 2 ++
src/components/Screen.web.tsx | 3 +++
src/components/ScreenContainer.tsx | 2 ++
src/components/ScreenStack.tsx | 2 ++
src/components/ScreenStackHeaderConfig.tsx | 2 ++
src/components/SearchBar.tsx | 2 ++
src/core.ts | 2 ++
src/fabric/FullWindowOverlayNativeComponent.ts | 2 ++
src/fabric/ModalScreenNativeComponent.ts | 2 ++
src/fabric/NativeScreensModule.ts | 2 ++
src/fabric/ScreenContainerNativeComponent.ts | 2 ++
src/fabric/ScreenNativeComponent.ts | 2 ++
src/fabric/ScreenNavigationContainerNativeComponent.ts | 2 ++
src/fabric/ScreenStackHeaderConfigNativeComponent.ts | 2 ++
src/fabric/ScreenStackHeaderSubviewNativeComponent.ts | 2 ++
src/fabric/ScreenStackNativeComponent.ts | 2 ++
src/fabric/SearchBarNativeComponent.ts | 2 ++
src/native-stack/contexts/GHContext.tsx | 2 ++
19 files changed, 39 insertions(+)
diff --git a/src/TransitionProgressContext.tsx b/src/TransitionProgressContext.tsx
index 30cfd6a94f..6382473fbc 100644
--- a/src/TransitionProgressContext.tsx
+++ b/src/TransitionProgressContext.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import * as React from 'react';
import { Animated } from 'react-native';
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index 122a9042b2..b553763834 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React from 'react';
import { Animated, View, Platform } from 'react-native';
diff --git a/src/components/Screen.web.tsx b/src/components/Screen.web.tsx
index c624a49eaf..183b6f8512 100644
--- a/src/components/Screen.web.tsx
+++ b/src/components/Screen.web.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import { ScreenProps } from 'react-native-screens';
import { Animated, View } from 'react-native';
import React from 'react';
@@ -8,6 +10,7 @@ export const InnerScreen = View;
// We're using class component here because of the error from reanimated:
// createAnimatedComponent` does not support stateless functional components; use a class component instead.
+// NOTE: React Server Components do not support class components.
export class NativeScreen extends React.Component {
render(): JSX.Element {
let {
diff --git a/src/components/ScreenContainer.tsx b/src/components/ScreenContainer.tsx
index 1a968b2e8a..65c907a1f6 100644
--- a/src/components/ScreenContainer.tsx
+++ b/src/components/ScreenContainer.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import { Platform, View } from 'react-native';
import React from 'react';
import { ScreenContainerProps } from 'react-native-screens';
diff --git a/src/components/ScreenStack.tsx b/src/components/ScreenStack.tsx
index 46043b6359..310b6a6938 100644
--- a/src/components/ScreenStack.tsx
+++ b/src/components/ScreenStack.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React from 'react';
import { ScreenStackProps, freezeEnabled } from 'react-native-screens';
import DelayedFreeze from './helpers/DelayedFreeze';
diff --git a/src/components/ScreenStackHeaderConfig.tsx b/src/components/ScreenStackHeaderConfig.tsx
index e65799092b..f3339fa5bd 100644
--- a/src/components/ScreenStackHeaderConfig.tsx
+++ b/src/components/ScreenStackHeaderConfig.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React from 'react';
import {
HeaderSubviewTypes,
diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx
index 981f67dc00..0874531679 100644
--- a/src/components/SearchBar.tsx
+++ b/src/components/SearchBar.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React from 'react';
import {
isSearchBarAvailableForCurrentPlatform,
diff --git a/src/core.ts b/src/core.ts
index 7a5f3971bc..0a28fdf9e7 100644
--- a/src/core.ts
+++ b/src/core.ts
@@ -1,3 +1,5 @@
+'use client';
+
import { Platform, UIManager } from 'react-native';
// const that tells if the library should use new implementation, will be undefined for older versions
diff --git a/src/fabric/FullWindowOverlayNativeComponent.ts b/src/fabric/FullWindowOverlayNativeComponent.ts
index 9d1c662e16..dcbd10d259 100644
--- a/src/fabric/FullWindowOverlayNativeComponent.ts
+++ b/src/fabric/FullWindowOverlayNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
diff --git a/src/fabric/ModalScreenNativeComponent.ts b/src/fabric/ModalScreenNativeComponent.ts
index ab8a5e889d..979dddeeeb 100644
--- a/src/fabric/ModalScreenNativeComponent.ts
+++ b/src/fabric/ModalScreenNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps, ColorValue } from 'react-native';
import type {
diff --git a/src/fabric/NativeScreensModule.ts b/src/fabric/NativeScreensModule.ts
index 23c2bc767c..bc334ff35f 100644
--- a/src/fabric/NativeScreensModule.ts
+++ b/src/fabric/NativeScreensModule.ts
@@ -1,3 +1,5 @@
+'use client';
+
/* eslint-disable @typescript-eslint/ban-types */
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
diff --git a/src/fabric/ScreenContainerNativeComponent.ts b/src/fabric/ScreenContainerNativeComponent.ts
index 290375c6d5..b8f0c7b250 100644
--- a/src/fabric/ScreenContainerNativeComponent.ts
+++ b/src/fabric/ScreenContainerNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
diff --git a/src/fabric/ScreenNativeComponent.ts b/src/fabric/ScreenNativeComponent.ts
index d552cd6bb4..bf7242cfd5 100644
--- a/src/fabric/ScreenNativeComponent.ts
+++ b/src/fabric/ScreenNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps, ColorValue } from 'react-native';
import type {
diff --git a/src/fabric/ScreenNavigationContainerNativeComponent.ts b/src/fabric/ScreenNavigationContainerNativeComponent.ts
index 89fb72f164..906ae64047 100644
--- a/src/fabric/ScreenNavigationContainerNativeComponent.ts
+++ b/src/fabric/ScreenNavigationContainerNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
diff --git a/src/fabric/ScreenStackHeaderConfigNativeComponent.ts b/src/fabric/ScreenStackHeaderConfigNativeComponent.ts
index de0574aa1b..9bf6634e24 100644
--- a/src/fabric/ScreenStackHeaderConfigNativeComponent.ts
+++ b/src/fabric/ScreenStackHeaderConfigNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps, ColorValue } from 'react-native';
import type {
diff --git a/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts b/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts
index 625e578459..189702dc13 100644
--- a/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts
+++ b/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
import type { WithDefault } from 'react-native/Libraries/Types/CodegenTypes';
diff --git a/src/fabric/ScreenStackNativeComponent.ts b/src/fabric/ScreenStackNativeComponent.ts
index fbf56654ec..3400cfe099 100644
--- a/src/fabric/ScreenStackNativeComponent.ts
+++ b/src/fabric/ScreenStackNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
diff --git a/src/fabric/SearchBarNativeComponent.ts b/src/fabric/SearchBarNativeComponent.ts
index c10dc70e44..467442aa2a 100644
--- a/src/fabric/SearchBarNativeComponent.ts
+++ b/src/fabric/SearchBarNativeComponent.ts
@@ -1,3 +1,5 @@
+'use client';
+
/* eslint-disable */
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps, ColorValue, HostComponent } from 'react-native';
diff --git a/src/native-stack/contexts/GHContext.tsx b/src/native-stack/contexts/GHContext.tsx
index 6b8b29096b..3e2a5cdd07 100644
--- a/src/native-stack/contexts/GHContext.tsx
+++ b/src/native-stack/contexts/GHContext.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React, { PropsWithChildren } from 'react';
import { GestureProviderProps } from '../types';
From 408112ab8d3b48e0e22cea0efee4955d1f7700e5 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Wed, 25 Sep 2024 18:05:41 +0200
Subject: [PATCH 14/38] feat: add monorepo support for Android builds (#2352)
## Description
Based on:
https://github.com/software-mansion/react-native-screens/pull/2337 by
@morganick.
Please see the original PR and its description for details.
See:
https://github.com/software-mansion/react-native-screens/pull/2337#pullrequestreview-2328416182
for discussion why new PR has been created.
## Changes
- **Using node resolver to find react native package for better monorepo
support**
- **Using rootDir instead of projectDir**
- **Change the order of path lookup**
## Test code and steps to reproduce
I've tested it using our both example apps and additionally I've created
fresh RN app
and tested the Android build there.
## Checklist
- [x] Ensured that CI passes
---------
Co-authored-by: Nick Morgan
---
android/build.gradle | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/android/build.gradle b/android/build.gradle
index 03f63baafc..81c29a720a 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -152,10 +152,26 @@ android {
repositories {
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
- // Matches the RN Hello World template
+
+ // First look for the standard location of react-native, as in RN Hello World template
// https://github.com/facebook/react-native/blob/1e8f3b11027fe0a7514b4fc97d0798d3c64bc895/local-cli/templates/HelloWorld/android/build.gradle#L21
- url "$projectDir/../node_modules/react-native/android"
+ // TODO(kkafar): Note, that in latest template app https://github.com/react-native-community/template/blob/0f4745b7a9d84232aeedec2def8d75ab9b050d11/template/android/build.gradle
+ // this is not specified at all.
+ File standardRnAndroidDirLocation = file("$rootDir/../node_modules/react-native/android")
+ if (standardRnAndroidDirLocation.exists()) {
+ url standardRnAndroidDirLocation
+ } else {
+ // We're in non standard setup - try to use node resolver to locate the react-native package.
+ File reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
+ def rnAndroidDirLocation = "$reactNativePackage.parentFile/android"
+ if (reactNativePackage.exists()) {
+ url rnAndroidDirLocation
+ } else {
+ println "[RNScreens] Failed to resolve react-native directory. Attempted locations: ${standardRnAndroidDirLocation}, ${rnAndroidDirLocation}"
+ }
+ }
}
+
mavenCentral()
mavenLocal()
google()
From 82d4a04d8b0059eee27d87db596b8564ab956301 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Wed, 25 Sep 2024 18:59:33 +0200
Subject: [PATCH 15/38] chore(deps): aggregate updates from dependabot (#2354)
## Description
Aggregating dependabot updates
* #2321
* #2322
* #2323
## Checklist
- [x] Ensured that CI passes
---------
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
FabricExample/Gemfile.lock | 2 +-
FabricExample/yarn.lock | 20 +++++--------------
docs/yarn.lock | 41 ++++++++++----------------------------
3 files changed, 16 insertions(+), 47 deletions(-)
diff --git a/FabricExample/Gemfile.lock b/FabricExample/Gemfile.lock
index a7f485ef2c..c3dd70283f 100644
--- a/FabricExample/Gemfile.lock
+++ b/FabricExample/Gemfile.lock
@@ -75,7 +75,7 @@ GEM
netrc (0.11.0)
nkf (0.2.0)
public_suffix (4.0.7)
- rexml (3.3.3)
+ rexml (3.3.6)
strscan
ruby-macho (2.5.1)
strscan (3.1.0)
diff --git a/FabricExample/yarn.lock b/FabricExample/yarn.lock
index e7402b0c20..c073d5d916 100644
--- a/FabricExample/yarn.lock
+++ b/FabricExample/yarn.lock
@@ -3879,7 +3879,7 @@ __metadata:
languageName: node
linkType: hard
-"braces@npm:^3.0.2, braces@npm:^3.0.3":
+"braces@npm:^3.0.3":
version: 3.0.3
resolution: "braces@npm:3.0.3"
dependencies:
@@ -7550,23 +7550,13 @@ __metadata:
languageName: node
linkType: hard
-"micromatch@npm:^4.0.2":
- version: 4.0.7
- resolution: "micromatch@npm:4.0.7"
+"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4":
+ version: 4.0.8
+ resolution: "micromatch@npm:4.0.8"
dependencies:
braces: "npm:^3.0.3"
picomatch: "npm:^2.3.1"
- checksum: 10c0/58fa99bc5265edec206e9163a1d2cec5fabc46a5b473c45f4a700adce88c2520456ae35f2b301e4410fb3afb27e9521fb2813f6fc96be0a48a89430e0916a772
- languageName: node
- linkType: hard
-
-"micromatch@npm:^4.0.4":
- version: 4.0.5
- resolution: "micromatch@npm:4.0.5"
- dependencies:
- braces: "npm:^3.0.2"
- picomatch: "npm:^2.3.1"
- checksum: 10c0/3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff
+ checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8
languageName: node
linkType: hard
diff --git a/docs/yarn.lock b/docs/yarn.lock
index c6be251c77..9d69743b77 100644
--- a/docs/yarn.lock
+++ b/docs/yarn.lock
@@ -3162,27 +3162,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/eslint-scope@npm:^3.7.3":
- version: 3.7.7
- resolution: "@types/eslint-scope@npm:3.7.7"
- dependencies:
- "@types/eslint": "npm:*"
- "@types/estree": "npm:*"
- checksum: 10c0/a0ecbdf2f03912679440550817ff77ef39a30fa8bfdacaf6372b88b1f931828aec392f52283240f0d648cf3055c5ddc564544a626bcf245f3d09fcb099ebe3cc
- languageName: node
- linkType: hard
-
-"@types/eslint@npm:*":
- version: 8.56.10
- resolution: "@types/eslint@npm:8.56.10"
- dependencies:
- "@types/estree": "npm:*"
- "@types/json-schema": "npm:*"
- checksum: 10c0/674349d6c342c3864d70f4d5a9965f96fb253801532752c8c500ad6a1c2e8b219e01ccff5dc8791dcb58b5483012c495708bb9f3ff929f5c9322b3da126c15d3
- languageName: node
- linkType: hard
-
-"@types/estree@npm:*, @types/estree@npm:^1.0.5":
+"@types/estree@npm:^1.0.5":
version: 1.0.5
resolution: "@types/estree@npm:1.0.5"
checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d
@@ -3277,7 +3257,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
+"@types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
@@ -5511,13 +5491,13 @@ __metadata:
languageName: node
linkType: hard
-"enhanced-resolve@npm:^5.17.0":
- version: 5.17.0
- resolution: "enhanced-resolve@npm:5.17.0"
+"enhanced-resolve@npm:^5.17.1":
+ version: 5.17.1
+ resolution: "enhanced-resolve@npm:5.17.1"
dependencies:
graceful-fs: "npm:^4.2.4"
tapable: "npm:^2.2.0"
- checksum: 10c0/90065e58e4fd08e77ba47f827eaa17d60c335e01e4859f6e644bb3b8d0e32b203d33894aee92adfa5121fa262f912b48bdf0d0475e98b4a0a1132eea1169ad37
+ checksum: 10c0/81a0515675eca17efdba2cf5bad87abc91a528fc1191aad50e275e74f045b41506167d420099022da7181c8d787170ea41e4a11a0b10b7a16f6237daecb15370
languageName: node
linkType: hard
@@ -11294,10 +11274,9 @@ __metadata:
linkType: hard
"webpack@npm:^5.73.0":
- version: 5.92.1
- resolution: "webpack@npm:5.92.1"
+ version: 5.94.0
+ resolution: "webpack@npm:5.94.0"
dependencies:
- "@types/eslint-scope": "npm:^3.7.3"
"@types/estree": "npm:^1.0.5"
"@webassemblyjs/ast": "npm:^1.12.1"
"@webassemblyjs/wasm-edit": "npm:^1.12.1"
@@ -11306,7 +11285,7 @@ __metadata:
acorn-import-attributes: "npm:^1.9.5"
browserslist: "npm:^4.21.10"
chrome-trace-event: "npm:^1.0.2"
- enhanced-resolve: "npm:^5.17.0"
+ enhanced-resolve: "npm:^5.17.1"
es-module-lexer: "npm:^1.2.1"
eslint-scope: "npm:5.1.1"
events: "npm:^3.2.0"
@@ -11326,7 +11305,7 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
- checksum: 10c0/43ca7c76b9c1005bd85f05303d048f918bac10276a209e3ef5e359353fbfef4e5fcee876265e6bc305bf5ef326576e02df63bc7e5af878fb7f06d7e1795b811a
+ checksum: 10c0/b4d1b751f634079bd177a89eef84d80fa5bb8d6fc15d72ab40fc2b9ca5167a79b56585e1a849e9e27e259803ee5c4365cb719e54af70a43c06358ec268ff4ebf
languageName: node
linkType: hard
From 53695c36b37d9b31f2450fe33ee7f5df07387b64 Mon Sep 17 00:00:00 2001
From: Adrian Ryt <72470330+adrianryt@users.noreply.github.com>
Date: Thu, 26 Sep 2024 16:30:55 +0200
Subject: [PATCH 16/38] fix!: always set Zindex to undefined for InnerScreen
(#2351)
## Description
Together with @kkafar we noticed that when switching back between
BottomTabsView (A -> B -> A) , React is calling removeScreenAt and
addScreen for tab we are leaving - in the same transaction! Because of
that and asynchronous nature of react-native-screens, error described in
#2345 exist. We also noticed that this weir behaviour is related to
setting ZIndex in InnerScreen.
Fixes #2345
Test 2232 was failing due to change in headerBackTitleVisible property.
> [!Caution]
@kkafar:
Note that this change might be potentially breaking since we're
effectively removing possibility of managing `Screen` components through
"z indices", breaking public API.
@kkafar:
The error mechanism is as follows:
1. `zIndex` being set causes RN diffing mechanism to include two
mutations on the same view in the same transaction - effectively
detaching and attaching it,
2. Thus when we navigate from tab B to A, react first detaches B from
screen container and in the same transaction it attaches it again -
however at the moment of reattach react expects B to be detached. This
is not case due to the fact, that we don't execute updates
synchronously, but rather we just schedule them in another block on UI
thread;
3. React asserts the invariant from point 2., and when we violate it,
its internal state gets corrupted later leading to crash.
We detected that getting rid of setting `zIndex` on screens prevents the
two consecutive operations on the same screen to appear, thus
effectively solving the problem.
Note, however, that we still won't support such cases with multiple
mount/unmount mutations related to the same component in single
transaction.
## Changes
- For every InnerScreen created we set/override ZIndex style to
undefined.
- Use headerBackButtonDisplayMode instead of headerBackTitleVisible.
## Test code and steps to reproduce
## Checklist
- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation:
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
---------
Co-authored-by: Kacper Kafara
---
apps/src/tests/Test2232.tsx | 2 +-
src/components/Screen.tsx | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/apps/src/tests/Test2232.tsx b/apps/src/tests/Test2232.tsx
index 7cc4d2020d..4ad2eaf79a 100644
--- a/apps/src/tests/Test2232.tsx
+++ b/apps/src/tests/Test2232.tsx
@@ -35,7 +35,7 @@ const App = () => (
component={SettingsScreen}
options={{
headerTintColor: 'hotpink',
- headerBackTitleVisible: false,
+ headerBackButtonDisplayMode: 'minimal',
headerTitle: () => (
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index b553763834..dec294fa2d 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -97,6 +97,7 @@ export const InnerScreen = React.forwardRef(
isNativeStack,
gestureResponseDistance,
onGestureCancel,
+ style,
...props
} = rest;
@@ -127,6 +128,11 @@ export const InnerScreen = React.forwardRef(
Date: Fri, 27 Sep 2024 16:11:25 +0200
Subject: [PATCH 17/38] fix(iOS): right header incorrect position (#2316)
## Description
This PR fixes the incorrect position of the custom header items when
updating more than one option at the same time. The proposed solution
let us remove the previous fix for a similar problem:
https://github.com/software-mansion/react-native-screens/pull/2248 which
only fixed the issue on fabric.
Fixes #432, #2231.
## Changes
- forced re-layout of the navigation controller when subviews are
updated
- removed previous fix
- updated `Test432` repro
## Test code and steps to reproduce
- use `Test432` and `Test2231` to test this fix on both architectures.
## Checklist
- [x] Included code example that can be used to test this change
- [x] Ensured that CI passes
---
apps/src/tests/Test432.tsx | 28 ++++++++++++++++++++++------
ios/RNSScreenStackHeaderConfig.mm | 3 +++
ios/RNSScreenStackHeaderSubview.mm | 3 ---
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/apps/src/tests/Test432.tsx b/apps/src/tests/Test432.tsx
index 5a0843dbc0..8274bfd299 100644
--- a/apps/src/tests/Test432.tsx
+++ b/apps/src/tests/Test432.tsx
@@ -13,18 +13,34 @@ type RootStackParamList = {
};
type RootStackScreenProps =
NativeStackScreenProps;
+
const HomeScreen = ({ navigation }: RootStackScreenProps<'Home'>) => {
- const showSettings = useCallback(() => {
- navigation.navigate('Settings');
- }, [navigation]);
+ const [x, setX] = React.useState(false);
+ React.useEffect(() => {
+ navigation.setOptions({
+ headerBackVisible: !x,
+ headerRight: x
+ ? () => (
+
+ )
+ : () => (
+
+ ),
+ });
+ }, [navigation, x]);
+
return (
-
+ setX(!x)} />
+ navigation.navigate('Settings')}
+ />
);
};
-const SettingsScreen = ({ navigation }: RootStackScreenProps<'Settings'>) => {
+const SettingsScreen = () => {
return (
Settings
@@ -47,7 +63,7 @@ const RootNavigator = () => {
[navigation],
);
return (
-
+
Date: Mon, 30 Sep 2024 08:29:40 +0200
Subject: [PATCH 18/38] feat: add compat mode for previously removed formSheet
prop values (#2356)
## Description
This PR intends to add support for previously removed
`sheetAllowedDetents` and `sheetLargestUndimmedDetent` props values:
`medium`, `large` and `all`.
With addition of custom detents for iOS I've changed the API of
NativeScreen component to receive `number[]` as the detent list and
removed the old options. This removal was unnecessary. I've restored
these options on the `Screen` component abstraction layer, where old
options are translated to the new API w/o need for additional support in
downstream packages such as react-navigation.
Corresponding PR in `react-navigation`:
* https://github.com/react-navigation/react-navigation/pull/12032
## Changes
* updated the types,
* added "translation layer" in InnerScreen.
## Test code and steps to reproduce
Test1649 is great for testing all sheet related props.
## Checklist
- [x] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [x] Ensured that CI passes
---
guides/GUIDE_FOR_LIBRARY_AUTHORS.md | 30 +++++++-----
native-stack/README.md | 21 ++++++++-
react-navigation | 2 +-
src/components/Screen.tsx | 55 +++++++++++++++++++++-
src/native-stack/types.tsx | 2 +-
src/native-stack/views/NativeStackView.tsx | 13 ++---
src/types.tsx | 27 +++++++++--
7 files changed, 124 insertions(+), 26 deletions(-)
diff --git a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
index 0f0a72d4b1..4689105491 100644
--- a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
+++ b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
@@ -150,17 +150,23 @@ Sets the current screen's available orientations and forces rotation if current
Defaults to `default` on iOS.
-### `sheetAllowedDetents` (iOS only)
+### `sheetAllowedDetents`
Describes heights where a sheet can rest.
-Works only when `stackPresentation` is set to `formSheet`.
+Works only when `presentation` is set to `formSheet`.
Heights should be described as fraction (a number from `[0, 1]` interval) of screen height / maximum detent height.
-There is also possibility to specify `[-1]` literal array with single element, which intets to set the sheet height
+There is also possibility to specify `fitToContents` literal, which intents to set the sheet height
to the height of its contents.
Please note that the array **must** be sorted in ascending order.
+There are also legacy & **deprecated** options available:
+
+* `medium` - corresponds to `[0.5]` detent value, around half of the screen height,
+* `large` - corresponds to `[1.0]` detent value, maximum height,
+* `all` - corresponds to `[0.5, 1.0]` value, the name is deceiving due to compatibility reasons.
+
Defaults to `[1.0]` literal.
### `sheetExpandsWhenScrolledToEdge` (iOS only)
@@ -170,7 +176,7 @@ Works only when `stackPresentation` is set to `formSheet`.
Defaults to `true`.
-### `sheetCornerRadius (iOS only)
+### `sheetCornerRadius`
The corner radius that the sheet will try to render with.
Works only when `stackPresentation` is set to `formSheet`.
@@ -188,15 +194,15 @@ Defaults to `false`.
### `sheetLargestUndimmedDetent` (iOS only)
The largest sheet detent for which a view underneath won't be dimmed.
-Works only when `stackPresentation` is set to `formSheet`.
+Works only when `presentation` is set to `formSheet`.
-If this prop is set to:
+This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
+there won't be a dimming view beneath the sheet.
-- `large` - the view underneath won't be dimmed at any detent level
-- `medium` - the view underneath will be dimmed only when detent level is `large`
-- `all` - the view underneath will be dimmed for any detent level
+There also legacy & **deprecated** prop values available, which work in tandem with
+corresponding legacy proop values for `sheetAllowedDetents` prop.
-Defaults to `all`.
+Defaults to `-1`, indicating that the dimming view should be always present.
### `stackAnimation`
@@ -365,7 +371,7 @@ function Home() {
}
```
-### unstable_footerComponent
+### unstable_sheetFooter (Android only)
Footer component that can be used alongside form sheet stack presentation style.
@@ -375,6 +381,8 @@ to implement such layout with JS-only code.
Please note that this prop is marked as unstable and might be subject of breaking changes,
even removal.
+Currently supported on Android only.
+
## ``
diff --git a/native-stack/README.md b/native-stack/README.md
index d0a6563da2..9c8f6429d0 100644
--- a/native-stack/README.md
+++ b/native-stack/README.md
@@ -247,14 +247,28 @@ Defaults to `pop`.
Describes heights where a sheet can rest.
Works only when `stackPresentation` is set to `formSheet`.
-Heights should be described as fraction (a number from [0, 1] interval) of screen height / maximum detent height.
-There is also possibility to specify `fitToContents` literal, which intents to set the sheet height
+Heights should be described as fraction (a number from `[0, 1]` interval) of screen height / maximum detent height.
+There is also possibility to specify `[-1]` literal array with single element, which intets to set the sheet height
to the height of its contents.
Please note that the array **must** be sorted in ascending order.
+There are also legacy & **deprecated** options available:
+
+* 'medium' - corresponds to `[0.5]` detent value, around half of the screen height,
+* 'large' - corresponds to `[1.0]` detent value, maximum height,
+* 'all' - corresponds to `[0.5, 1.0]` value, the name is deceiving due to compatibility reasons.
+
Defaults to `[1.0]` literal.
+#### `sheetElevation` (Android only)
+
+Integer value describing elevation of the sheet, impacting shadow on the top edge of the sheet.
+
+Not dynamic - changing it after the component is rendered won't have an effect.
+
+Defaults to `24`.
+
#### `sheetExpandsWhenScrolledToEdge` (iOS only)
Whether the sheet should expand to larger detent when scrolling.
@@ -290,6 +304,9 @@ Works only when `stackPresentation` is set to `formSheet`.
This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
there won't be a dimming view beneath the sheet.
+There also legacy & **deprecated** prop values available, which work in tandem with
+corresponding legacy prop values for `sheetAllowedDetents` prop.
+
Defaults to `-1`, indicating that the dimming view should be always present.
#### `stackAnimation`
diff --git a/react-navigation b/react-navigation
index 248fcf7d32..c7cbe96430 160000
--- a/react-navigation
+++ b/react-navigation
@@ -1 +1 @@
-Subproject commit 248fcf7d328b7a813106f5306a78ffd7eef5bcb3
+Subproject commit c7cbe9643091a9a91dbed6b18fd579166d34107a
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index dec294fa2d..aa1c1440d0 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -43,6 +43,50 @@ interface ViewConfig extends View {
};
}
+// This value must be kept in sync with native side.
+const SHEET_FIT_TO_CONTENTS = [-1];
+const SHEET_COMPAT_LARGE = [1.0];
+const SHEET_COMPAT_MEDIUM = [0.5];
+const SHEET_COMPAT_ALL = [0.5, 1.0];
+
+// These exist to transform old 'legacy' values used by the formsheet API to the new API shape.
+// We can get rid of it, once we get rid of support for legacy values: 'large', 'medium', 'all'.
+function resolveSheetAllowedDetents(
+ allowedDetentsCompat: ScreenProps['sheetAllowedDetents'],
+): number[] {
+ if (Array.isArray(allowedDetentsCompat)) {
+ return allowedDetentsCompat;
+ } else if (allowedDetentsCompat === 'fitToContents') {
+ return SHEET_FIT_TO_CONTENTS;
+ } else if (allowedDetentsCompat === 'large') {
+ return SHEET_COMPAT_LARGE;
+ } else if (allowedDetentsCompat === 'medium') {
+ return SHEET_COMPAT_MEDIUM;
+ } else if (allowedDetentsCompat === 'all') {
+ return SHEET_COMPAT_ALL;
+ } else {
+ // Safe default, only large detent is allowed.
+ return [1.0];
+ }
+}
+
+function resolveSheetLargestUndimmedDetent(
+ lud: ScreenProps['sheetLargestUndimmedDetent'],
+): number {
+ if (typeof lud === 'number') {
+ return lud;
+ } else if (lud === 'large') {
+ return 1;
+ } else if (lud === 'medium') {
+ return 0;
+ } else if (lud === 'all') {
+ return -1;
+ } else {
+ // Safe default, every detent is dimmed
+ return -1;
+ }
+}
+
export const InnerScreen = React.forwardRef(
function InnerScreen(props, ref) {
const innerRef = React.useRef(null);
@@ -66,6 +110,7 @@ export const InnerScreen = React.forwardRef(
// To maintain default behavior of formSheet stack presentation style and to have reasonable
// defaults for new medium-detent iOS API we need to set defaults here
const {
+ // formSheet presentation related props
sheetAllowedDetents = [1.0],
sheetLargestUndimmedDetent = -1,
sheetGrabberVisible = false,
@@ -73,10 +118,16 @@ export const InnerScreen = React.forwardRef(
sheetExpandsWhenScrolledToEdge = true,
sheetElevation = 24,
sheetInitialDetent = 0,
+
+ // Other
stackPresentation,
} = rest;
if (enabled && isNativePlatformSupported) {
+ const resolvedSheetAllowedDetents =
+ resolveSheetAllowedDetents(sheetAllowedDetents);
+ const resolvedSheetLargestUndimmedDetent =
+ resolveSheetLargestUndimmedDetent(sheetLargestUndimmedDetent);
// Due to how Yoga resolves layout, we need to have different components for modal nad non-modal screens
const AnimatedScreen =
Platform.OS === 'android' ||
@@ -134,8 +185,8 @@ export const InnerScreen = React.forwardRef(
// Detailed information can be found here https://github.com/software-mansion/react-native-screens/pull/2351
style={[style, { zIndex: undefined }]}
activityState={activityState}
- sheetAllowedDetents={sheetAllowedDetents}
- sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
+ sheetAllowedDetents={resolvedSheetAllowedDetents}
+ sheetLargestUndimmedDetent={resolvedSheetLargestUndimmedDetent}
sheetElevation={sheetElevation}
sheetGrabberVisible={sheetGrabberVisible}
sheetCornerRadius={sheetCornerRadius}
diff --git a/src/native-stack/types.tsx b/src/native-stack/types.tsx
index fadde7ee47..12ff6f82a3 100644
--- a/src/native-stack/types.tsx
+++ b/src/native-stack/types.tsx
@@ -517,7 +517,7 @@ export type NativeStackNavigationOptions = {
*
* @platform android
*/
- unstable_footerComponent?: React.ReactNode;
+ unstable_sheetFooter?: () => React.ReactNode;
};
export type NativeStackNavigatorProps =
diff --git a/src/native-stack/views/NativeStackView.tsx b/src/native-stack/views/NativeStackView.tsx
index 0f4717121a..dec52bb618 100644
--- a/src/native-stack/views/NativeStackView.tsx
+++ b/src/native-stack/views/NativeStackView.tsx
@@ -215,7 +215,7 @@ const RouteView = ({
swipeDirection = 'horizontal',
transitionDuration,
freezeOnBlur,
- unstable_footerComponent = null,
+ unstable_sheetFooter = null,
} = options;
let {
@@ -229,9 +229,10 @@ const RouteView = ({
} = options;
// We only want to allow backgroundColor for now
- unstable_screenStyle = unstable_screenStyle
- ? { backgroundColor: unstable_screenStyle.backgroundColor }
- : null;
+ unstable_screenStyle =
+ stackPresentation === 'formSheet' && unstable_screenStyle
+ ? { backgroundColor: unstable_screenStyle.backgroundColor }
+ : null;
if (sheetAllowedDetents === 'fitToContents') {
sheetAllowedDetents = [-1];
@@ -450,8 +451,8 @@ const RouteView = ({
route={route}
headerShown={isHeaderInPush}
/>
- {unstable_footerComponent && (
- {unstable_footerComponent}
+ {stackPresentation === 'formSheet' && unstable_sheetFooter && (
+ {unstable_sheetFooter()}
)}
diff --git a/src/types.tsx b/src/types.tsx
index 1ccd801e66..ceb580ccb7 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -104,7 +104,6 @@ export interface ScreenProps extends ViewProps {
active?: 0 | 1 | Animated.AnimatedInterpolation;
activityState?: 0 | 1 | 2 | Animated.AnimatedInterpolation;
children?: React.ReactNode;
- unstable_footer?: React.ReactNode;
/**
* Boolean indicating that swipe dismissal should trigger animation provided by `stackAnimation`. Defaults to `false`.
*
@@ -299,9 +298,15 @@ export interface ScreenProps extends ViewProps {
*
* Please note that the array **must** be sorted in ascending order.
*
+ * There are also legacy & **deprecated** options available:
+ *
+ * * 'medium' - corresponds to `[0.5]` detent value, around half of the screen height,
+ * * 'large' - corresponds to `[1.0]` detent value, maximum height,
+ * * 'all' - corresponds to `[0.5, 1.0]` value, the name is deceiving due to compatibility reasons.
+ *
* Defaults to `[1.0]` literal.
*/
- sheetAllowedDetents?: number[];
+ sheetAllowedDetents?: number[] | 'fitToContents' | 'medium' | 'large' | 'all';
/**
* Integer value describing elevation of the sheet, impacting shadow on the top edge of the sheet.
*
@@ -346,9 +351,12 @@ export interface ScreenProps extends ViewProps {
* This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
* there won't be a dimming view beneath the sheet.
*
+ * There also legacy & **deprecated** prop values available, which work in tandem with
+ * corresponding legacy prop values for `sheetAllowedDetents` prop.
+ *
* Defaults to `-1`, indicating that the dimming view should be always present.
*/
- sheetLargestUndimmedDetent?: number;
+ sheetLargestUndimmedDetent?: number | 'medium' | 'large' | 'all';
/**
* Index of the detent the sheet should expand to after being opened.
* Works only when `stackPresentation` is set to `formSheet`.
@@ -426,6 +434,19 @@ export interface ScreenProps extends ViewProps {
* @platform ios
*/
transitionDuration?: number;
+ /**
+ * Footer component that can be used alongside formSheet stack presentation style.
+ *
+ * This option is provided, because due to implementation details it might be problematic
+ * to implement such layout with JS-only code.
+ *
+ * Please note that this prop is marked as unstable and might be subject of breaking changes,
+ * including removal, in particular when we find solution that will make implementing it with JS
+ * straightforward.
+ *
+ * @platform android
+ */
+ unstable_sheetFooter?: () => React.ReactNode;
}
export interface ScreenContainerProps extends ViewProps {
From 261b7ddb50dd7ee96797e4e989692c8884bc456c Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Mon, 30 Sep 2024 11:41:32 +0200
Subject: [PATCH 19/38] feat: expose `none` & `largest` values for
`sheetLargestUndimmedDetent` prop (#2359)
## Description
I'm exposing two new options for `sheetLargestUndimmedDetent` prop:
* `none` - denoting that dimming view will be always present,
* `largest` - denoting that dimming view will never be present.
Previously to achieve the effect of `none` you had to either rely on
default or pass `-1` raw value.
Similarly achieving the effect of `largest` required user to set a
numeric value and update it everytime new detent was added / removed.
> [!note]
~~As I wrote this description, new idea popped out - instead of exposing
numeric constant just add some string options, as with
`sheetAllowedDetents` (it is an array or some predefined string
constants).
> What would be the API though? `sheetLargestUndimmedDetent: 'none'`?
What's the wording here?~~
>
> *Done! ^^^*
`react-navigation` PR:
* https://github.com/react-navigation/react-navigation/pull/12032
## Changes
Replaced raw `-1` with constants `none` and `largest`.
## Test code and steps to reproduce
`Test1649`
## Checklist
- [x] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [x] Ensured that CI passes
---
apps/src/tests/Test1649/state.tsx | 2 +-
guides/GUIDE_FOR_LIBRARY_AUTHORS.md | 15 ++++++++++-----
native-stack/README.md | 9 +++++++--
react-navigation | 2 +-
src/components/Screen.tsx | 19 ++++++++++++++-----
src/index.tsx | 12 ++++++------
src/native-stack/types.tsx | 10 +++++++++-
src/native-stack/views/NativeStackView.tsx | 2 +-
src/types.tsx | 17 ++++++++++++++---
9 files changed, 63 insertions(+), 25 deletions(-)
diff --git a/apps/src/tests/Test1649/state.tsx b/apps/src/tests/Test1649/state.tsx
index fe5aec1169..5e9af4294d 100644
--- a/apps/src/tests/Test1649/state.tsx
+++ b/apps/src/tests/Test1649/state.tsx
@@ -6,7 +6,7 @@ export const sheetInitialOptions: SheetOptions = {
sheetAllowedDetents: [0.4, 0.6, 0.9],
// sheetAllowedDetents: [0.6],
// sheetAllowedDetents: 'fitToContents',
- sheetLargestUndimmedDetent: 2,
+ sheetLargestUndimmedDetent: 'none',
sheetGrabberVisible: false,
sheetCornerRadius: 24,
sheetExpandsWhenScrolledToEdge: true,
diff --git a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
index 4689105491..2ed6bcf9ef 100644
--- a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
+++ b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
@@ -191,18 +191,23 @@ Boolean indicating whether the sheet shows a grabber at the top.
Works only when `stackPresentation` is set to `formSheet`.
Defaults to `false`.
-### `sheetLargestUndimmedDetent` (iOS only)
+### `sheetLargestUndimmedDetent`
The largest sheet detent for which a view underneath won't be dimmed.
-Works only when `presentation` is set to `formSheet`.
+Works only when `stackPresentation` is set to `formSheet`.
This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
there won't be a dimming view beneath the sheet.
-There also legacy & **deprecated** prop values available, which work in tandem with
-corresponding legacy proop values for `sheetAllowedDetents` prop.
+Additionaly there are following options available:
+
+* `none` - there will be dimming view for all detents levels,
+* `largest` - there won't be a dimming view for any detent level.
+
+There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
+corresponding legacy prop values for `sheetAllowedDetents` prop.
-Defaults to `-1`, indicating that the dimming view should be always present.
+Defaults to `none`, indicating that the dimming view should be always present.
### `stackAnimation`
diff --git a/native-stack/README.md b/native-stack/README.md
index 9c8f6429d0..c6649591e6 100644
--- a/native-stack/README.md
+++ b/native-stack/README.md
@@ -304,10 +304,15 @@ Works only when `stackPresentation` is set to `formSheet`.
This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
there won't be a dimming view beneath the sheet.
-There also legacy & **deprecated** prop values available, which work in tandem with
+Additionaly there are following options available:
+
+* `none` - there will be dimming view for all detents levels,
+* `largest` - there won't be a dimming view for any detent level.
+
+There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
corresponding legacy prop values for `sheetAllowedDetents` prop.
-Defaults to `-1`, indicating that the dimming view should be always present.
+Defaults to `none`, indicating that the dimming view should be always present.
#### `stackAnimation`
diff --git a/react-navigation b/react-navigation
index c7cbe96430..782248d992 160000
--- a/react-navigation
+++ b/react-navigation
@@ -1 +1 @@
-Subproject commit c7cbe9643091a9a91dbed6b18fd579166d34107a
+Subproject commit 782248d9922c9e71ba65ea1d93b09abd6f84fe5c
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index aa1c1440d0..ab2bfaf1a6 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -49,6 +49,9 @@ const SHEET_COMPAT_LARGE = [1.0];
const SHEET_COMPAT_MEDIUM = [0.5];
const SHEET_COMPAT_ALL = [0.5, 1.0];
+const SHEET_DIMMED_ALWAYS = -1;
+// const SHEET_DIMMED_NEVER = 9999;
+
// These exist to transform old 'legacy' values used by the formsheet API to the new API shape.
// We can get rid of it, once we get rid of support for legacy values: 'large', 'medium', 'all'.
function resolveSheetAllowedDetents(
@@ -72,18 +75,21 @@ function resolveSheetAllowedDetents(
function resolveSheetLargestUndimmedDetent(
lud: ScreenProps['sheetLargestUndimmedDetent'],
+ largestDetentIndex: number,
): number {
if (typeof lud === 'number') {
return lud;
+ } else if (lud === 'largest') {
+ return largestDetentIndex;
+ } else if (lud === 'none' || lud === 'all') {
+ return SHEET_DIMMED_ALWAYS;
} else if (lud === 'large') {
return 1;
} else if (lud === 'medium') {
return 0;
- } else if (lud === 'all') {
- return -1;
} else {
// Safe default, every detent is dimmed
- return -1;
+ return SHEET_DIMMED_ALWAYS;
}
}
@@ -112,7 +118,7 @@ export const InnerScreen = React.forwardRef(
const {
// formSheet presentation related props
sheetAllowedDetents = [1.0],
- sheetLargestUndimmedDetent = -1,
+ sheetLargestUndimmedDetent = SHEET_DIMMED_ALWAYS,
sheetGrabberVisible = false,
sheetCornerRadius = -1.0,
sheetExpandsWhenScrolledToEdge = true,
@@ -127,7 +133,10 @@ export const InnerScreen = React.forwardRef(
const resolvedSheetAllowedDetents =
resolveSheetAllowedDetents(sheetAllowedDetents);
const resolvedSheetLargestUndimmedDetent =
- resolveSheetLargestUndimmedDetent(sheetLargestUndimmedDetent);
+ resolveSheetLargestUndimmedDetent(
+ sheetLargestUndimmedDetent,
+ resolvedSheetAllowedDetents.length - 1,
+ );
// Due to how Yoga resolves layout, we need to have different components for modal nad non-modal screens
const AnimatedScreen =
Platform.OS === 'android' ||
diff --git a/src/index.tsx b/src/index.tsx
index 0e2a7dc5bb..b344112232 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,6 +1,6 @@
export * from './types';
-/*
+/**
* Core
*/
export {
@@ -11,7 +11,7 @@ export {
shouldUseActivityState,
} from './core';
-/*
+/**
* RNS Components
*/
export {
@@ -57,17 +57,17 @@ export {
NativeScreenContentWrapper,
} from './components/ScreenContentWrapper';
-/*
+/**
* Modules
*/
export { default as NativeScreensModule } from './fabric/NativeScreensModule';
-/*
+/**
* Contexts
*/
export { GHContext } from './native-stack/contexts/GHContext';
-/*
+/**
* Utils
*/
export {
@@ -76,7 +76,7 @@ export {
executeNativeBackPress,
} from './utils';
-/*
+/**
* Hooks
*/
export { default as useTransitionProgress } from './useTransitionProgress';
diff --git a/src/native-stack/types.tsx b/src/native-stack/types.tsx
index 12ff6f82a3..4c3f342625 100644
--- a/src/native-stack/types.tsx
+++ b/src/native-stack/types.tsx
@@ -426,7 +426,15 @@ export type NativeStackNavigationOptions = {
* This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
* there won't be a dimming view beneath the sheet.
*
- * Defaults to `-1`, indicating that the dimming view should be always present.
+ * Additionaly there are following options available:
+ *
+ * * `none` - there will be dimming view for all detents levels,
+ * * `largest` - there won't be a dimming view for any detent level.
+ *
+ * There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
+ * corresponding legacy prop values for `sheetAllowedDetents` prop.
+ *
+ * Defaults to `none`, indicating that the dimming view should be always present.
*/
sheetLargestUndimmedDetent?: ScreenProps['sheetLargestUndimmedDetent'];
/**
diff --git a/src/native-stack/views/NativeStackView.tsx b/src/native-stack/views/NativeStackView.tsx
index dec52bb618..9f00561282 100644
--- a/src/native-stack/views/NativeStackView.tsx
+++ b/src/native-stack/views/NativeStackView.tsx
@@ -195,7 +195,7 @@ const RouteView = ({
headerShown,
hideKeyboardOnSwipe,
homeIndicatorHidden,
- sheetLargestUndimmedDetent = -1,
+ sheetLargestUndimmedDetent = 'none',
sheetGrabberVisible = false,
sheetCornerRadius = -1.0,
sheetElevation = 24,
diff --git a/src/types.tsx b/src/types.tsx
index ceb580ccb7..5c11e9556b 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -351,12 +351,23 @@ export interface ScreenProps extends ViewProps {
* This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
* there won't be a dimming view beneath the sheet.
*
- * There also legacy & **deprecated** prop values available, which work in tandem with
+ * Additionaly there are following options available:
+ *
+ * * `none` - there will be dimming view for all detents levels,
+ * * `largest` - there won't be a dimming view for any detent level.
+ *
+ * There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
* corresponding legacy prop values for `sheetAllowedDetents` prop.
*
- * Defaults to `-1`, indicating that the dimming view should be always present.
+ * Defaults to `none`, indicating that the dimming view should be always present.
*/
- sheetLargestUndimmedDetent?: number | 'medium' | 'large' | 'all';
+ sheetLargestUndimmedDetent?:
+ | number
+ | 'none'
+ | 'largest'
+ | 'medium'
+ | 'large'
+ | 'all';
/**
* Index of the detent the sheet should expand to after being opened.
* Works only when `stackPresentation` is set to `formSheet`.
From 8fc934f88ef99ca303fc52cfc0d5569a9b6cb112 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Tue, 1 Oct 2024 12:24:54 +0200
Subject: [PATCH 20/38] Release 4.0.0-beta.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2ab746c8a8..deff3c6de3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
- "version": "4.0.0-beta.0",
+ "version": "4.0.0-beta.1",
"description": "Native navigation primitives for your React Native app.",
"scripts": {
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
From 108d85dd7f8de143dfe02f5029770e65b551ec95 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Tue, 1 Oct 2024 16:40:00 +0200
Subject: [PATCH 21/38] feat: add stub implementations for
`ScreenContentWrapper` for web (#2368)
## Description
Missing stubs for web.
## Changes
See the changes, no additional description is needed.
## Checklist
- [-] Ensured that CI passes
---
src/components/ScreenContentWrapper.web.tsx | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 src/components/ScreenContentWrapper.web.tsx
diff --git a/src/components/ScreenContentWrapper.web.tsx b/src/components/ScreenContentWrapper.web.tsx
new file mode 100644
index 0000000000..97eee625cb
--- /dev/null
+++ b/src/components/ScreenContentWrapper.web.tsx
@@ -0,0 +1,4 @@
+import { View } from 'react-native';
+
+export const NativeScreenContentWrapper = View;
+export const ScreenContentWrapper = View;
From 5da303e669e3efb3bbe3cb4f753d9c602b3b8e62 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Tue, 1 Oct 2024 16:41:18 +0200
Subject: [PATCH 22/38] Release 4.0.0-beta.2
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index deff3c6de3..cb914e9632 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
- "version": "4.0.0-beta.1",
+ "version": "4.0.0-beta.2",
"description": "Native navigation primitives for your React Native app.",
"scripts": {
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
From f9c491e9408875f3febbbda502d1a63aa139e05d Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Tue, 1 Oct 2024 17:18:04 +0200
Subject: [PATCH 23/38] feat: add stub implementations for `ScreenFooter` for
web (#2369)
## Description
Adding stub implmentation for web.
## Changes
See files. No more description needed.
## Checklist
- [-] Ensured that CI passes
---
src/components/ScreenContentWrapper.web.tsx | 4 +++-
src/components/ScreenFooter.web.tsx | 6 ++++++
2 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 src/components/ScreenFooter.web.tsx
diff --git a/src/components/ScreenContentWrapper.web.tsx b/src/components/ScreenContentWrapper.web.tsx
index 97eee625cb..93474d280b 100644
--- a/src/components/ScreenContentWrapper.web.tsx
+++ b/src/components/ScreenContentWrapper.web.tsx
@@ -1,4 +1,6 @@
import { View } from 'react-native';
export const NativeScreenContentWrapper = View;
-export const ScreenContentWrapper = View;
+
+const ScreenContentWrapper = View;
+export default ScreenContentWrapper;
diff --git a/src/components/ScreenFooter.web.tsx b/src/components/ScreenFooter.web.tsx
new file mode 100644
index 0000000000..b8dd6df383
--- /dev/null
+++ b/src/components/ScreenFooter.web.tsx
@@ -0,0 +1,6 @@
+import { View } from 'react-native';
+
+export const NativeScreenFooter = View;
+
+const ScreenFooter = View;
+export default ScreenFooter;
From 04997380a58b9482bb24b836ce93b689bc82b569 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Tue, 1 Oct 2024 17:19:06 +0200
Subject: [PATCH 24/38] Release 4.0.0-beta.3
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index cb914e9632..1b0253d964 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
- "version": "4.0.0-beta.2",
+ "version": "4.0.0-beta.3",
"description": "Native navigation primitives for your React Native app.",
"scripts": {
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
From 606cd4bb495c9403138514ab5dc0042c16048b3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Du=C5=BCy?=
<91994767+alduzy@users.noreply.github.com>
Date: Wed, 2 Oct 2024 12:38:10 +0200
Subject: [PATCH 25/38] feat(iOS): sheetInitialDetent support (#2367)
## Description
This PR adds `sheetInitialDetent` support to iOS and fixes detents logic
on iOS < 16.
This functionality depends on changes made in this PR:
https://github.com/react-navigation/react-navigation/pull/12032
## Changes
- supporting `sheetInitialDetent` on iOS
- modified `Test2002.tsx` repro
- updated README definition to match types
- fixed `sheetAllowedDetents` on iOS < 16
## Test code and steps to reproduce
- Use `Test2002.tsx` repro
## Checklist
- [x] Included code example that can be used to test this change
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x] Ensured that CI passes
---
apps/src/tests/Test2002.tsx | 31 ++++++++++++++++++++----
ios/RNSScreen.h | 1 +
ios/RNSScreen.mm | 29 ++++++++++++++++++++--
native-stack/README.md | 4 ++-
src/fabric/ModalScreenNativeComponent.ts | 1 +
5 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/apps/src/tests/Test2002.tsx b/apps/src/tests/Test2002.tsx
index 55a5a39979..098813c201 100644
--- a/apps/src/tests/Test2002.tsx
+++ b/apps/src/tests/Test2002.tsx
@@ -5,9 +5,22 @@ import {
DefaultTheme,
NavigationContainer,
} from '@react-navigation/native';
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
+import {
+ createNativeStackNavigator,
+ NativeStackNavigationProp,
+} from '@react-navigation/native-stack';
+
+type StackParamList = {
+ Home: undefined;
+ formSheet: undefined;
+ fullScreenModal: undefined;
+};
-function HomeScreen({ navigation }) {
+function HomeScreen({
+ navigation,
+}: {
+ navigation: NativeStackNavigationProp;
+}) {
return (
;
+}) {
return (
navigation.goBack()} title="Dismiss" />
@@ -30,7 +47,7 @@ function ModalScreen({ navigation }) {
);
}
-const RootStack = createNativeStackNavigator();
+const RootStack = createNativeStackNavigator();
export default function App() {
const scheme = useColorScheme();
@@ -42,7 +59,11 @@ export default function App() {
= __IPHONE_16_0
- if (_sheetAllowedDetents.count > 0) {
- if (@available(iOS 16.0, *)) {
+ if (@available(iOS 16.0, *)) {
+ if (_sheetAllowedDetents.count > 0) {
if (_sheetAllowedDetents.count == 1 && [_sheetAllowedDetents[0] integerValue] == SHEET_FIT_TO_CONTENTS) {
// This is `fitToContents` case, where sheet should be just high to display its contents.
// Paper: we do not set anything here, we will set once React computed layout of our React's children, namely
@@ -944,6 +944,26 @@ - (void)updateFormSheetPresentationStyle
}
}
+ if (_sheetInitialDetent > 0 && _sheetInitialDetent < _sheetAllowedDetents.count) {
+#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_16_0) && \
+ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0
+ if (@available(iOS 16.0, *)) {
+ UISheetPresentationControllerDetent *detent = sheet.detents[_sheetInitialDetent];
+ [self setSelectedDetentForSheet:sheet to:detent.identifier animate:YES];
+ } else
+#endif // Check for iOS >= 16
+ {
+ if (_sheetInitialDetent < 2) {
+ [self setSelectedDetentForSheet:sheet to:UISheetPresentationControllerDetentIdentifierLarge animate:YES];
+ } else {
+ RCTLogError(
+ @"[RNScreens] sheetInitialDetent out of bounds, on iOS versions below 16 sheetAllowedDetents is ignored in favor of an array of two system-defined detents");
+ }
+ }
+ } else if (_sheetInitialDetent != 0) {
+ RCTLogError(@"[RNScreens] sheetInitialDetent out of bounds for sheetAllowedDetents array");
+ }
+
sheet.prefersScrollingExpandsWhenScrolledToEdge = _sheetExpandsWhenScrolledToEdge;
[self setGrabberVisibleForSheet:sheet to:_sheetGrabberVisible animate:YES];
[self setCornerRadiusForSheet:sheet to:_sheetCornerRadius animate:YES];
@@ -1151,6 +1171,10 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
[self setSheetAllowedDetents:[RNSConvert detentFractionsArrayFromVector:newScreenProps.sheetAllowedDetents]];
}
+ if (newScreenProps.sheetInitialDetent != oldScreenProps.sheetInitialDetent) {
+ [self setSheetInitialDetent:newScreenProps.sheetInitialDetent];
+ }
+
if (newScreenProps.sheetLargestUndimmedDetent != oldScreenProps.sheetLargestUndimmedDetent) {
[self setSheetLargestUndimmedDetent:[NSNumber numberWithInt:newScreenProps.sheetLargestUndimmedDetent]];
}
@@ -1864,6 +1888,7 @@ @implementation RNSScreenManager
RCT_EXPORT_VIEW_PROPERTY(sheetLargestUndimmedDetent, NSNumber *);
RCT_EXPORT_VIEW_PROPERTY(sheetGrabberVisible, BOOL);
RCT_EXPORT_VIEW_PROPERTY(sheetCornerRadius, CGFloat);
+RCT_EXPORT_VIEW_PROPERTY(sheetInitialDetent, NSInteger);
RCT_EXPORT_VIEW_PROPERTY(sheetExpandsWhenScrolledToEdge, BOOL);
#endif
diff --git a/native-stack/README.md b/native-stack/README.md
index c6649591e6..20f8734077 100644
--- a/native-stack/README.md
+++ b/native-stack/README.md
@@ -287,9 +287,11 @@ Defaults to system default.
#### `sheetInitialDetent`
-Initial detent for the sheet.
+Index of the detent the sheet should expand to after being opened.
Works only when `presentation` is set to `formSheet`.
+Defaults to `0` - which represents first detent in the detents array.
+
#### `sheetGrabberVisible` (iOS only)
Boolean indicating whether the sheet shows a grabber at the top.
diff --git a/src/fabric/ModalScreenNativeComponent.ts b/src/fabric/ModalScreenNativeComponent.ts
index 979dddeeeb..1a675c2c84 100644
--- a/src/fabric/ModalScreenNativeComponent.ts
+++ b/src/fabric/ModalScreenNativeComponent.ts
@@ -75,6 +75,7 @@ export interface NativeProps extends ViewProps {
sheetGrabberVisible?: WithDefault;
sheetCornerRadius?: WithDefault;
sheetExpandsWhenScrolledToEdge?: WithDefault;
+ sheetInitialDetent?: WithDefault;
customAnimationOnSwipe?: boolean;
fullScreenSwipeEnabled?: boolean;
fullScreenSwipeShadowEnabled?: boolean;
From c711d3c67644a22080c16514076a15028267716b Mon Sep 17 00:00:00 2001
From: Maciej Stosio
Date: Wed, 2 Oct 2024 15:55:55 +0200
Subject: [PATCH 26/38] refactor!: remove deprecated ios stack animation
(#2361)
## Description
Removes stackAnimation "ios" option in v4 after making it deprecated in
3.x.
## Checklist
- [ ] Included code example that can be used to test this change
- [x] Updated TS types
- [x] Updated documentation:
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
---
android/src/main/java/com/swmansion/rnscreens/Screen.kt | 1 -
android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt | 3 ---
.../src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt | 1 -
apps/src/screens/Animations.tsx | 1 -
apps/src/screens/Events.tsx | 1 -
guides/GUIDE_FOR_LIBRARY_AUTHORS.md | 1 -
ios/RNSConvert.mm | 1 -
ios/RNSScreen.mm | 1 -
native-stack/README.md | 1 -
src/fabric/ScreenNativeComponent.ts | 1 -
src/native-stack/types.tsx | 1 -
src/types.tsx | 2 --
windows/RNScreens/Screen.h | 1 -
13 files changed, 16 deletions(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index a6cb8c7501..0f91f963fd 100644
--- a/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -435,7 +435,6 @@ class Screen(
SLIDE_FROM_RIGHT,
SLIDE_FROM_LEFT,
FADE_FROM_BOTTOM,
- IOS,
IOS_FROM_RIGHT,
IOS_FROM_LEFT,
}
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
index b700bffffd..a4e6fea83e 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt
@@ -182,7 +182,6 @@ class ScreenStack(
R.anim.rns_no_animation_medium,
)
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_open, R.anim.rns_ios_from_right_background_open)
StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_foreground_open, R.anim.rns_ios_from_left_background_open)
}
@@ -222,7 +221,6 @@ class ScreenStack(
R.anim.rns_slide_out_to_bottom,
)
StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
- StackAnimation.IOS -> it.setCustomAnimations(R.anim.rns_ios_from_right_foreground_close, R.anim.rns_ios_from_right_background_close)
StackAnimation.IOS_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_ios_from_right_background_close, R.anim.rns_ios_from_right_foreground_close)
StackAnimation.IOS_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_ios_from_left_background_close, R.anim.rns_ios_from_left_foreground_close)
}
@@ -417,7 +415,6 @@ class ScreenStack(
Build.VERSION.SDK_INT >= 33 ||
fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
- fragmentWrapper.screen.stackAnimation === StackAnimation.IOS ||
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_LEFT
}
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
index de5be092b5..2b752266b9 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
@@ -142,7 +142,6 @@ open class ScreenViewManager :
"slide_from_left" -> Screen.StackAnimation.SLIDE_FROM_LEFT
"slide_from_bottom" -> Screen.StackAnimation.SLIDE_FROM_BOTTOM
"fade_from_bottom" -> Screen.StackAnimation.FADE_FROM_BOTTOM
- "ios" -> Screen.StackAnimation.IOS
"ios_from_right" -> Screen.StackAnimation.IOS_FROM_RIGHT
"ios_from_left" -> Screen.StackAnimation.IOS_FROM_LEFT
else -> throw JSApplicationIllegalArgumentException("Unknown animation type $animation")
diff --git a/apps/src/screens/Animations.tsx b/apps/src/screens/Animations.tsx
index 10097a5d23..608e939746 100644
--- a/apps/src/screens/Animations.tsx
+++ b/apps/src/screens/Animations.tsx
@@ -52,7 +52,6 @@ const MainScreen = ({
'slide_from_bottom',
'slide_from_right',
'slide_from_left',
- 'ios',
'ios_from_right',
'ios_from_left',
'none',
diff --git a/apps/src/screens/Events.tsx b/apps/src/screens/Events.tsx
index 9996d9e979..03ddace791 100644
--- a/apps/src/screens/Events.tsx
+++ b/apps/src/screens/Events.tsx
@@ -83,7 +83,6 @@ const MainScreen = ({
'slide_from_bottom',
'slide_from_right',
'slide_from_left',
- 'ios',
'ios_from_right',
'ios_from_left',
'none',
diff --git a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
index 2ed6bcf9ef..d86bd10c9a 100644
--- a/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
+++ b/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
@@ -221,7 +221,6 @@ Allows for the customization of how the given screen should appear/disappear whe
- `"slide_from_bottom"` - slide in the new screen from bottom to top
- `"slide_from_right"` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
- `"slide_from_left"` - slide in the new screen from left to right
-- `"ios"` - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
- `"ios_from_right"` - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
- `"ios_from_left"` - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
- `"none"` – the screen appears/disappears without an animation
diff --git a/ios/RNSConvert.mm b/ios/RNSConvert.mm
index eb13f1fc70..67c6519b90 100644
--- a/ios/RNSConvert.mm
+++ b/ios/RNSConvert.mm
@@ -53,7 +53,6 @@ + (RNSScreenStackAnimation)RNSScreenStackAnimationFromCppEquivalent:(react::RNSS
switch (stackAnimation) {
// these four are intentionally grouped
case react::RNSScreenStackAnimation::Slide_from_right:
- case react::RNSScreenStackAnimation::Ios:
case react::RNSScreenStackAnimation::Ios_from_right:
case react::RNSScreenStackAnimation::Default:
return RNSScreenStackAnimationDefault;
diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm
index dba3b4fef7..9b1cc543a0 100644
--- a/ios/RNSScreen.mm
+++ b/ios/RNSScreen.mm
@@ -1961,7 +1961,6 @@ @implementation RCTConvert (RNSScreen)
@"slide_from_bottom" : @(RNSScreenStackAnimationSlideFromBottom),
@"slide_from_right" : @(RNSScreenStackAnimationDefault),
@"slide_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
- @"ios" : @(RNSScreenStackAnimationDefault),
@"ios_from_right" : @(RNSScreenStackAnimationDefault),
@"ios_from_left" : @(RNSScreenStackAnimationSlideFromLeft),
}),
diff --git a/native-stack/README.md b/native-stack/README.md
index 20f8734077..3b619e130b 100644
--- a/native-stack/README.md
+++ b/native-stack/README.md
@@ -328,7 +328,6 @@ How the given screen should appear/disappear when pushed or popped at the top of
- `slide_from_bottom` – performs a slide from bottom animation
- `slide_from_right` - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
- `slide_from_left` - slide in the new screen from left to right
-- `"ios"` - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
- `"ios_from_right"` - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
- `"ios_from_left"` - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
- `none` - the screen appears/disappears without an animation.
diff --git a/src/fabric/ScreenNativeComponent.ts b/src/fabric/ScreenNativeComponent.ts
index bf7242cfd5..1eb9071ac3 100644
--- a/src/fabric/ScreenNativeComponent.ts
+++ b/src/fabric/ScreenNativeComponent.ts
@@ -58,7 +58,6 @@ type StackAnimation =
| 'slide_from_left'
| 'slide_from_bottom'
| 'fade_from_bottom'
- | 'ios'
| 'ios_from_right'
| 'ios_from_left';
diff --git a/src/native-stack/types.tsx b/src/native-stack/types.tsx
index 4c3f342625..d9f9f10290 100644
--- a/src/native-stack/types.tsx
+++ b/src/native-stack/types.tsx
@@ -448,7 +448,6 @@ export type NativeStackNavigationOptions = {
* - "slide_from_bottom" – performs a slide from bottom animation
* - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "slide_from_left" - slide in the new screen from left to right
- * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
* - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
* - "none" – the screen appears/dissapears without an animation
diff --git a/src/types.tsx b/src/types.tsx
index 5c11e9556b..684a21b0c3 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -39,7 +39,6 @@ export type StackAnimationTypes =
| 'slide_from_bottom'
| 'slide_from_right'
| 'slide_from_left'
- | 'ios'
| 'ios_from_right'
| 'ios_from_left';
export type BlurEffectTypes =
@@ -386,7 +385,6 @@ export interface ScreenProps extends ViewProps {
* - `slide_from_bottom` – performs a slide from bottom animation
* - "slide_from_right" - slide in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "slide_from_left" - slide in the new screen from left to right
- * - "ios" - @deprecated iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS) (will be removed in v4.0.0 in favor of `ios_from_right`)
* - "ios_from_right" - iOS like slide in animation. pushes in the new screen from right to left (Android only, resolves to default transition on iOS)
* - "ios_from_left" - iOS like slide in animation. pushes in the new screen from left to right (Android only, resolves to default transition on iOS)
* - "none" – the screen appears/dissapears without an animation
diff --git a/windows/RNScreens/Screen.h b/windows/RNScreens/Screen.h
index 564b173f5b..7abf42672c 100644
--- a/windows/RNScreens/Screen.h
+++ b/windows/RNScreens/Screen.h
@@ -11,7 +11,6 @@ enum class StackAnimation {
SIMPLE_FROM_BOTTOM,
SLIDE_FROM_RIGHT,
SLIDE_FROM_LEFT,
- IOS,
IOS_FROM_RIGHT,
IOS_FROM_LEFT
};
From 64d2d64de5b0959850ca2d73d5e5de4f6e385cf0 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Wed, 2 Oct 2024 20:26:36 +0200
Subject: [PATCH 27/38] chore: fix crash in example app due to typo in export
(#2374)
## Description
The `Test2332` was wrongly exported as `Test2232` from `index`,
resulting in two exports with the same name => leading to crash.
## Changes
Renamed the export appropriately.
## Test code and steps to reproduce
Run any example app.
## Checklist
- [ ] Ensured that CI passes
---
apps/src/tests/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/src/tests/index.ts b/apps/src/tests/index.ts
index 7b6fe91b30..eea1285008 100644
--- a/apps/src/tests/index.ts
+++ b/apps/src/tests/index.ts
@@ -111,7 +111,7 @@ export { default as Test2235 } from './Test2235';
export { default as Test2252 } from './Test2252';
export { default as Test2271 } from './Test2271';
export { default as Test2282 } from './Test2282';
-export { default as Test2232 } from './Test2332';
+export { default as Test2332 } from './Test2332';
export { default as TestScreenAnimation } from './TestScreenAnimation';
export { default as TestHeader } from './TestHeader';
export { default as TestModalNavigation } from './TestModalNavigation';
From b3f189d573f54c73be756b38c7624605bb8b1304 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 10:05:27 +0200
Subject: [PATCH 28/38] fix: bring back headers when using "modal" presentation
on Android (#2372)
## Description
Recently, when adding formSheets I've also merged some code for future
modals implementation.
When detaching the yet-unused code for modals from being used I've
forgotten about one code place,
causing the header to not be created.
`modal` presentation is rather not widely used on Android, because it
has no real differences from `push`,
however I'm restoring the old behavior for the sake of backward
compatibility.
Kudos to @alduzy for noticing the issue.
## Changes
* Fixed the condition that prevents the header from being created on
Android, right now header
is not created only for `formSheet` stack presentation.
## Test code and steps to reproduce
`Test1649` - set 'modal' stack presentation to any screen and do not
disable the header. See that it now works.
## Checklist
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
Co-authored-by: Alex Duzy
---
.../swmansion/rnscreens/ScreenStackFragment.kt | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
index 1c06c7f3a0..f58c88d043 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
@@ -142,7 +142,11 @@ class ScreenStackFragment :
// once it is hidden by user gesture.
private val bottomSheetStateCallback =
object : BottomSheetCallback() {
- private var lastStableState: Int = SheetUtils.sheetStateFromDetentIndex(screen.sheetInitialDetentIndex, screen.sheetDetents.count())
+ private var lastStableState: Int =
+ SheetUtils.sheetStateFromDetentIndex(
+ screen.sheetInitialDetentIndex,
+ screen.sheetDetents.count(),
+ )
override fun onStateChanged(
bottomSheet: View,
@@ -152,7 +156,10 @@ class ScreenStackFragment :
lastStableState = newState
screen.notifySheetDetentChange(SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()), true)
} else if (newState == BottomSheetBehavior.STATE_DRAGGING) {
- screen.notifySheetDetentChange(SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()), false)
+ screen.notifySheetDetentChange(
+ SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()),
+ false,
+ )
}
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
@@ -232,9 +239,7 @@ class ScreenStackFragment :
coordinatorLayout.addView(screen.recycle())
- if (screen.stackPresentation != Screen.StackPresentation.MODAL &&
- screen.stackPresentation != Screen.StackPresentation.FORM_SHEET
- ) {
+ if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) {
appBarLayout =
context?.let { AppBarLayout(it) }?.apply {
// By default AppBarLayout will have a background color set but since we cover the whole layout
From bf83e4b5df497e9419e0197405a232447361d580 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 10:13:05 +0200
Subject: [PATCH 29/38] fix: prevent crash when there is no appearance model
built (#2375)
## Description
I haven't investigated it carefully, but there were case when updating
`sheetCornerRadius` the appearance
model has not been built yet leading to a crash when casting to a
non-null type.
Additionally, this PR prevents calls to `onSheetCornerRadiusUpdate` when
not in `formSheet` presentation
or not in native stack.
## Changes
* Prevent calls to `onSheetCornerRadiusUpdate` when not in `formSheet`
presentation.
* Check for nullish view background before attempt to set the corner
radius.
* Update the corner radius after all updates are applied, so that the
`stackPresentation` has change of being updated.
## Test code and steps to reproduce
`Test1649`. Try setting the corner radius now, should work properly.
## Checklist
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
---
.../java/com/swmansion/rnscreens/Screen.kt | 35 +++++++++++++++++--
.../rnscreens/ScreenStackFragment.kt | 8 +----
.../swmansion/rnscreens/ScreenViewManager.kt | 6 ++++
3 files changed, 40 insertions(+), 9 deletions(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index 0f91f963fd..b556d115ac 100644
--- a/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -21,6 +21,9 @@ import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.scroll.ReactScrollView
import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.shape.CornerFamily
+import com.google.android.material.shape.MaterialShapeDrawable
+import com.google.android.material.shape.ShapeAppearanceModel
import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
import com.swmansion.rnscreens.events.SheetDetentChangedEvent
@@ -54,10 +57,16 @@ class Screen(
// Props for controlling modal presentation
var isSheetGrabberVisible: Boolean = false
+
+ // corner radius must be updated after all props prop updates from a single transaction
+ // have been applied, because it depends on the presentation type.
+ private var shouldUpdateSheetCornerRadius = false
var sheetCornerRadius: Float = 0F
set(value) {
- field = value
- (fragment as? ScreenStackFragment)?.onSheetCornerRadiusChange()
+ if (field != value) {
+ field = value
+ shouldUpdateSheetCornerRadius = true
+ }
}
var sheetExpandsWhenScrolledToEdge: Boolean = true
@@ -420,6 +429,28 @@ class Screen(
)
}
+ internal fun onFinalizePropsUpdate() {
+ if (shouldUpdateSheetCornerRadius) {
+ shouldUpdateSheetCornerRadius = false
+ onSheetCornerRadiusChange()
+ }
+ }
+
+ internal fun onSheetCornerRadiusChange() {
+ if (stackPresentation !== StackPresentation.FORM_SHEET || background == null) {
+ return
+ }
+ (background as MaterialShapeDrawable?)?.let {
+ it.shapeAppearanceModel =
+ ShapeAppearanceModel
+ .Builder()
+ .apply {
+ setTopLeftCorner(CornerFamily.ROUNDED, sheetCornerRadius)
+ setTopRightCorner(CornerFamily.ROUNDED, sheetCornerRadius)
+ }.build()
+ }
+ }
+
enum class StackPresentation {
PUSH,
MODAL,
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
index f58c88d043..8fc46a9aea 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
@@ -198,13 +198,7 @@ class ScreenStackFragment :
}
internal fun onSheetCornerRadiusChange() {
- (screen.background as MaterialShapeDrawable).shapeAppearanceModel =
- ShapeAppearanceModel
- .Builder()
- .apply {
- setTopLeftCorner(CornerFamily.ROUNDED, screen.sheetCornerRadius)
- setTopRightCorner(CornerFamily.ROUNDED, screen.sheetCornerRadius)
- }.build()
+ screen.onSheetCornerRadiusChange()
}
override fun onCreateView(
diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
index 2b752266b9..48f82b9511 100644
--- a/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt
@@ -92,6 +92,12 @@ open class ScreenViewManager :
return super.updateState(view, props, stateWrapper)
}
+ // Called after all props are updated for given view
+ override fun onAfterUpdateTransaction(view: Screen) {
+ super.onAfterUpdateTransaction(view)
+ view.onFinalizePropsUpdate()
+ }
+
@ReactProp(name = "activityState")
fun setActivityState(
view: Screen,
From 9075f4279ae3e6a1c5735f6bf2a96b9b968f94c9 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 10:19:17 +0200
Subject: [PATCH 30/38] fix: align units of sheet corner radius in different
callsites (#2378)
## Description
Before this PR, when updating corner size after initial render different
unit (pixel) has been used opposed to
`dp` used during initial render. This PR align this behaviour so that
`dp` is always used.
## Changes
* Calculate appropriate value in `Screen.onSheetDetentChange` function
## Test code and steps to reproduce
`Test1649`
## Checklist
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
---
android/src/main/java/com/swmansion/rnscreens/Screen.kt | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/android/src/main/java/com/swmansion/rnscreens/Screen.kt b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
index b556d115ac..68956f02bc 100644
--- a/android/src/main/java/com/swmansion/rnscreens/Screen.kt
+++ b/android/src/main/java/com/swmansion/rnscreens/Screen.kt
@@ -16,6 +16,7 @@ import androidx.fragment.app.Fragment
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.facebook.react.bridge.GuardedRunnable
import com.facebook.react.bridge.ReactContext
+import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.events.EventDispatcher
@@ -441,12 +442,13 @@ class Screen(
return
}
(background as MaterialShapeDrawable?)?.let {
+ val resolvedCornerRadius = PixelUtil.toDIPFromPixel(sheetCornerRadius)
it.shapeAppearanceModel =
ShapeAppearanceModel
.Builder()
.apply {
- setTopLeftCorner(CornerFamily.ROUNDED, sheetCornerRadius)
- setTopRightCorner(CornerFamily.ROUNDED, sheetCornerRadius)
+ setTopLeftCorner(CornerFamily.ROUNDED, resolvedCornerRadius)
+ setTopRightCorner(CornerFamily.ROUNDED, resolvedCornerRadius)
}.build()
}
}
From 253ddade5b0a9b9547fc727e80c211fc357a3cae Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 14:31:16 +0200
Subject: [PATCH 31/38] feat: assert that detents array is sorted in dev mode
(#2381)
## Description
Verify the invariant specified in `sheetAllowedDetents` prop
documentation in dev mode.
## Test code and steps to reproduce
`Test1649`
## Checklist
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
---
src/components/Screen.tsx | 19 +++++++++++++++++++
src/types.tsx | 5 ++++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index ab2bfaf1a6..4e78287931 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -52,12 +52,31 @@ const SHEET_COMPAT_ALL = [0.5, 1.0];
const SHEET_DIMMED_ALWAYS = -1;
// const SHEET_DIMMED_NEVER = 9999;
+function assertDetentsArrayIsSorted(array: number[]) {
+ for (let i = 1; i < array.length; i++) {
+ if (array[i - 1] > array[i]) {
+ throw new Error(
+ '[RNScreens] The detent array is not sorted in ascending order!',
+ );
+ }
+ }
+}
+
// These exist to transform old 'legacy' values used by the formsheet API to the new API shape.
// We can get rid of it, once we get rid of support for legacy values: 'large', 'medium', 'all'.
function resolveSheetAllowedDetents(
allowedDetentsCompat: ScreenProps['sheetAllowedDetents'],
): number[] {
if (Array.isArray(allowedDetentsCompat)) {
+ if (__DEV__) {
+ assertDetentsArrayIsSorted(allowedDetentsCompat);
+ if (Platform.OS === 'android' && allowedDetentsCompat.length > 3) {
+ console.warn(
+ '[RNScreens] Sheets API on Android do accept only up to 3 values. Any surplus value are ignored.',
+ );
+ allowedDetentsCompat = allowedDetentsCompat.slice(0, 3);
+ }
+ }
return allowedDetentsCompat;
} else if (allowedDetentsCompat === 'fitToContents') {
return SHEET_FIT_TO_CONTENTS;
diff --git a/src/types.tsx b/src/types.tsx
index 684a21b0c3..e244cfa1c8 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -295,7 +295,10 @@ export interface ScreenProps extends ViewProps {
* There is also possibility to specify `[-1]` literal array with single element, which intets to set the sheet height
* to the height of its contents.
*
- * Please note that the array **must** be sorted in ascending order.
+ * Please note that the array **must** be sorted in ascending order. This invariant is verified only in developement mode,
+ * where violation results in error.
+ *
+ * **Android is limited to up 3 values in the array** -- any surplus values, beside first three are ignored.
*
* There are also legacy & **deprecated** options available:
*
From d87062aa9705cdafeaa3cb7279f1a6bae53cc036 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 14:36:17 +0200
Subject: [PATCH 32/38] refactor!: add "index" suffix to selected sheet props &
add better error handling (#2380)
## Description
This PR aims to improve prop naming by following renames:
* `sheetInitialDetent` -> `sheetInitialDetentIndex`,
* `sheetLargestUndimmedDetent` -> `sheetLargestUndimmedDetentIndex`
In case of `sheetInitialDetentIndex` prop additional value is handled:
`last`, which indicates that the
sheet should be opened initially at largest detent.
In case of `sheetLargestUndimmedDetent` the `largest` variant has been
changed to `last`, so there is no discrepancy between these two props.
Additionally, error handling has been improved for both of these props.
Now if they are out of bounds, in production environment default value
is used,
in developement mode an descriptive error is thrown.
## Changes
^^^
## Test code and steps to reproduce
Test1649
## Checklist
- [ ] Included code example that can be used to test this change
- [x] Updated TS types
- [ ] Updated documentation:
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [x]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
---
src/components/Screen.tsx | 74 ++++++++++++++++++----
src/native-stack/types.tsx | 4 +-
src/native-stack/views/NativeStackView.tsx | 8 +--
src/types.tsx | 35 +++++++---
4 files changed, 93 insertions(+), 28 deletions(-)
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index 4e78287931..e49b249d63 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -17,11 +17,19 @@ import {
import ScreenNativeComponent from '../fabric/ScreenNativeComponent';
import ModalScreenNativeComponent from '../fabric/ModalScreenNativeComponent';
-export const NativeScreen: React.ComponentType =
- ScreenNativeComponent as React.ComponentType;
+type NativeScreenProps = Omit<
+ ScreenProps,
+ 'sheetInitialDetentIndex' | 'sheetLargestUndimmedDetentIndex'
+> & {
+ sheetInitialDetent: number;
+ sheetLargestUndimmedDetent: number;
+};
+
+export const NativeScreen: React.ComponentType =
+ ScreenNativeComponent as React.ComponentType;
const AnimatedNativeScreen = Animated.createAnimatedComponent(NativeScreen);
const AnimatedNativeModalScreen = Animated.createAnimatedComponent(
- ModalScreenNativeComponent as React.ComponentType,
+ ModalScreenNativeComponent as React.ComponentType,
);
// Incomplete type, all accessible properties available at:
@@ -93,13 +101,22 @@ function resolveSheetAllowedDetents(
}
function resolveSheetLargestUndimmedDetent(
- lud: ScreenProps['sheetLargestUndimmedDetent'],
- largestDetentIndex: number,
+ lud: ScreenProps['sheetLargestUndimmedDetentIndex'],
+ lastDetentIndex: number,
): number {
if (typeof lud === 'number') {
+ if (!isIndexInClosedRange(lud, SHEET_DIMMED_ALWAYS, lastDetentIndex)) {
+ if (__DEV__) {
+ throw new Error(
+ "[RNScreens] Provided value of 'sheetLargestUndimmedDetentIndex' prop is out of bounds of 'sheetAllowedDetents' array.",
+ );
+ }
+ // Return default in production
+ return SHEET_DIMMED_ALWAYS;
+ }
return lud;
- } else if (lud === 'largest') {
- return largestDetentIndex;
+ } else if (lud === 'last') {
+ return lastDetentIndex;
} else if (lud === 'none' || lud === 'all') {
return SHEET_DIMMED_ALWAYS;
} else if (lud === 'large') {
@@ -112,6 +129,36 @@ function resolveSheetLargestUndimmedDetent(
}
}
+function resolveSheetInitialDetentIndex(
+ index: ScreenProps['sheetInitialDetentIndex'],
+ lastDetentIndex: number,
+): number {
+ if (index === 'last') {
+ index = lastDetentIndex;
+ } else if (index == null) {
+ // Intentional check for undefined & null ^
+ index = 0;
+ }
+ if (!isIndexInClosedRange(index, 0, lastDetentIndex)) {
+ if (__DEV__) {
+ throw new Error(
+ "[RNScreens] Provided value of 'sheetInitialDetentIndex' prop is out of bounds of 'sheetAllowedDetents' array.",
+ );
+ }
+ // Return default in production
+ return 0;
+ }
+ return index;
+}
+
+function isIndexInClosedRange(
+ value: number,
+ lowerBound: number,
+ upperBound: number,
+): boolean {
+ return Number.isInteger(value) && value >= lowerBound && value <= upperBound;
+}
+
export const InnerScreen = React.forwardRef(
function InnerScreen(props, ref) {
const innerRef = React.useRef(null);
@@ -137,13 +184,12 @@ export const InnerScreen = React.forwardRef(
const {
// formSheet presentation related props
sheetAllowedDetents = [1.0],
- sheetLargestUndimmedDetent = SHEET_DIMMED_ALWAYS,
+ sheetLargestUndimmedDetentIndex = SHEET_DIMMED_ALWAYS,
sheetGrabberVisible = false,
sheetCornerRadius = -1.0,
sheetExpandsWhenScrolledToEdge = true,
sheetElevation = 24,
- sheetInitialDetent = 0,
-
+ sheetInitialDetentIndex = 0,
// Other
stackPresentation,
} = rest;
@@ -153,9 +199,13 @@ export const InnerScreen = React.forwardRef(
resolveSheetAllowedDetents(sheetAllowedDetents);
const resolvedSheetLargestUndimmedDetent =
resolveSheetLargestUndimmedDetent(
- sheetLargestUndimmedDetent,
+ sheetLargestUndimmedDetentIndex,
resolvedSheetAllowedDetents.length - 1,
);
+ const resolvedSheetInitialDetentIndex = resolveSheetInitialDetentIndex(
+ sheetInitialDetentIndex,
+ resolvedSheetAllowedDetents.length - 1,
+ );
// Due to how Yoga resolves layout, we need to have different components for modal nad non-modal screens
const AnimatedScreen =
Platform.OS === 'android' ||
@@ -219,7 +269,7 @@ export const InnerScreen = React.forwardRef(
sheetGrabberVisible={sheetGrabberVisible}
sheetCornerRadius={sheetCornerRadius}
sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
- sheetInitialDetent={sheetInitialDetent}
+ sheetInitialDetent={resolvedSheetInitialDetentIndex}
gestureResponseDistance={{
start: gestureResponseDistance?.start ?? -1,
end: gestureResponseDistance?.end ?? -1,
diff --git a/src/native-stack/types.tsx b/src/native-stack/types.tsx
index d9f9f10290..b9b57a403c 100644
--- a/src/native-stack/types.tsx
+++ b/src/native-stack/types.tsx
@@ -418,7 +418,7 @@ export type NativeStackNavigationOptions = {
*
* Defaults to `0` - which represents first detent in the detents array.
*/
- sheetInitialDetent?: ScreenProps['sheetInitialDetent'];
+ sheetInitialDetentIndex?: ScreenProps['sheetInitialDetentIndex'];
/**
* The largest sheet detent for which a view underneath won't be dimmed.
* Works only when `stackPresentation` is set to `formSheet`.
@@ -436,7 +436,7 @@ export type NativeStackNavigationOptions = {
*
* Defaults to `none`, indicating that the dimming view should be always present.
*/
- sheetLargestUndimmedDetent?: ScreenProps['sheetLargestUndimmedDetent'];
+ sheetLargestUndimmedDetentIndex?: ScreenProps['sheetLargestUndimmedDetentIndex'];
/**
* How the screen should appear/disappear when pushed or popped at the top of the stack.
* The following values are currently supported:
diff --git a/src/native-stack/views/NativeStackView.tsx b/src/native-stack/views/NativeStackView.tsx
index 9f00561282..3e0f244ae1 100644
--- a/src/native-stack/views/NativeStackView.tsx
+++ b/src/native-stack/views/NativeStackView.tsx
@@ -195,12 +195,12 @@ const RouteView = ({
headerShown,
hideKeyboardOnSwipe,
homeIndicatorHidden,
- sheetLargestUndimmedDetent = 'none',
+ sheetLargestUndimmedDetentIndex = 'none',
sheetGrabberVisible = false,
sheetCornerRadius = -1.0,
sheetElevation = 24,
sheetExpandsWhenScrolledToEdge = true,
- sheetInitialDetent = 0,
+ sheetInitialDetentIndex = 0,
nativeBackButtonDismissalEnabled = false,
navigationBarColor,
navigationBarTranslucent,
@@ -318,9 +318,9 @@ const RouteView = ({
hasLargeHeader={hasLargeHeader}
style={[StyleSheet.absoluteFill, unstable_screenStyle]}
sheetAllowedDetents={sheetAllowedDetents}
- sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
+ sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
sheetGrabberVisible={sheetGrabberVisible}
- sheetInitialDetent={sheetInitialDetent}
+ sheetInitialDetentIndex={sheetInitialDetentIndex}
sheetCornerRadius={sheetCornerRadius}
sheetElevation={sheetElevation}
sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
diff --git a/src/types.tsx b/src/types.tsx
index e244cfa1c8..a40cbdeb76 100644
--- a/src/types.tsx
+++ b/src/types.tsx
@@ -289,10 +289,13 @@ export interface ScreenProps extends ViewProps {
unstable_screenStyle?: Pick;
/**
* Describes heights where a sheet can rest.
- * Works only when `stackPresentation` is set to `formSheet`.
+ * Works only when `presentation` is set to `formSheet`.
*
* Heights should be described as fraction (a number from `[0, 1]` interval) of screen height / maximum detent height.
- * There is also possibility to specify `[-1]` literal array with single element, which intets to set the sheet height
+ * You can pass an array of ascending values each defining allowed sheet detent. iOS accepts any number of detents,
+ * while **Android is limited to three**.
+ *
+ * There is also possibility to specify `fitToContents` literal, which intents to set the sheet height
* to the height of its contents.
*
* Please note that the array **must** be sorted in ascending order. This invariant is verified only in developement mode,
@@ -306,7 +309,9 @@ export interface ScreenProps extends ViewProps {
* * 'large' - corresponds to `[1.0]` detent value, maximum height,
* * 'all' - corresponds to `[0.5, 1.0]` value, the name is deceiving due to compatibility reasons.
*
- * Defaults to `[1.0]` literal.
+ * These are provided solely for **temporary** backward compatibility and are destined for removal in future versions.
+ *
+ * Defaults to `[1.0]`.
*/
sheetAllowedDetents?: number[] | 'fitToContents' | 'medium' | 'large' | 'all';
/**
@@ -353,30 +358,40 @@ export interface ScreenProps extends ViewProps {
* This prop can be set to an number, which indicates index of detent in `sheetAllowedDetents` array for which
* there won't be a dimming view beneath the sheet.
*
+ * If the specified index is out of bounds of `sheetAllowedDetents` array, in dev environment mode error will be thrown,
+ * in production the value will be reset to default value.
+ *
* Additionaly there are following options available:
*
* * `none` - there will be dimming view for all detents levels,
- * * `largest` - there won't be a dimming view for any detent level.
+ * * `last` - there won't be a dimming view for any detent level.
*
* There also legacy & **deprecated** prop values available: `medium`, `large` (don't confuse with `largest`), `all`, which work in tandem with
* corresponding legacy prop values for `sheetAllowedDetents` prop.
*
+ * These are provided solely for **temporary** backward compatibility and are destined for removal in future versions.
+ *
* Defaults to `none`, indicating that the dimming view should be always present.
*/
- sheetLargestUndimmedDetent?:
+ sheetLargestUndimmedDetentIndex?:
| number
| 'none'
- | 'largest'
- | 'medium'
- | 'large'
- | 'all';
+ | 'last'
+ | 'medium' // deprecated
+ | 'large' // deprecated
+ | 'all'; // deprecated
/**
* Index of the detent the sheet should expand to after being opened.
* Works only when `stackPresentation` is set to `formSheet`.
*
+ * If the specified index is out of bounds of `sheetAllowedDetents` array, in dev environment more error will be thrown,
+ * in production the value will be reset to default value.
+ *
+ * Additionaly there is `last` value available, when set the sheet will expand initially to last (largest) detent.
+ *
* Defaults to `0` - which represents first detent in the detents array.
*/
- sheetInitialDetent?: number;
+ sheetInitialDetentIndex?: number | 'last';
/**
* How the screen should appear/disappear when pushed or popped at the top of the stack.
* The following values are currently supported:
From 486ce07c80105665200eb953207b69de498f4f97 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 14:38:10 +0200
Subject: [PATCH 33/38] Release 4.0.0-beta.4
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 1b0253d964..4bec347d4f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
- "version": "4.0.0-beta.3",
+ "version": "4.0.0-beta.4",
"description": "Native navigation primitives for your React Native app.",
"scripts": {
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
From 7719eb1ded7362af13475d1b25a90fdbfa5f891f Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 14:43:47 +0200
Subject: [PATCH 34/38] chore: remove unnecessary logs from native-stack v5
(#2382)
## Description
Remove leftover logs
## Checklist
- [ ] Ensured that CI passes
---
src/native-stack/views/NativeStackView.tsx | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/native-stack/views/NativeStackView.tsx b/src/native-stack/views/NativeStackView.tsx
index 3e0f244ae1..5a50bc8949 100644
--- a/src/native-stack/views/NativeStackView.tsx
+++ b/src/native-stack/views/NativeStackView.tsx
@@ -355,7 +355,6 @@ const RouteView = ({
});
}}
onWillAppear={() => {
- console.log(`onWillAppear/transitionStart route: ${route.key}`);
navigation.emit({
type: 'transitionStart',
data: { closing: false },
@@ -363,7 +362,6 @@ const RouteView = ({
});
}}
onWillDisappear={() => {
- console.log(`onWillDisappear/transitionStart route: ${route.key}`);
navigation.emit({
type: 'transitionStart',
data: { closing: true },
@@ -371,12 +369,10 @@ const RouteView = ({
});
}}
onAppear={() => {
- console.log(`onAppear/appear route: ${route.key}`);
navigation.emit({
type: 'appear',
target: route.key,
});
- console.log(`onAppear/transitionEnd route: ${route.key}`);
navigation.emit({
type: 'transitionEnd',
data: { closing: false },
@@ -384,7 +380,6 @@ const RouteView = ({
});
}}
onDisappear={() => {
- console.log(`onDisappear/transitionEnd route: ${route.key}`);
navigation.emit({
type: 'transitionEnd',
data: { closing: true },
@@ -404,7 +399,6 @@ const RouteView = ({
}
}}
onDismissed={e => {
- console.log(`onDismissed/dismiss route: ${route.key}`);
navigation.emit({
type: 'dismiss',
target: route.key,
From 9ea05927cfafd4dd10c9834f1c9c8c99a1353989 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Thu, 3 Oct 2024 14:44:56 +0200
Subject: [PATCH 35/38] Release 4.0.0-beta.5
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 4bec347d4f..918b5471f8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
- "version": "4.0.0-beta.4",
+ "version": "4.0.0-beta.5",
"description": "Native navigation primitives for your React Native app.",
"scripts": {
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn)",
From 6502d52af715e71122465d8c5f4875b80f8108d9 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Fri, 4 Oct 2024 11:54:47 +0200
Subject: [PATCH 36/38] chore: bump react-navigation to current main (#2386)
## Description
Bumping react-navigation since the sheet API PR:
* https://github.com/react-navigation/react-navigation/pull/12032
landed on main & we no longer need to use off-trunk branches.
## Checklist
- [ ] Ensured that CI passes
---
react-navigation | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/react-navigation b/react-navigation
index 782248d992..af20d57b1a 160000
--- a/react-navigation
+++ b/react-navigation
@@ -1 +1 @@
-Subproject commit 782248d9922c9e71ba65ea1d93b09abd6f84fe5c
+Subproject commit af20d57b1a12d0d79a51425e2a7088efe140ae57
From af3048964d59e83d0ad4d99e4f4dd07611ec8bad Mon Sep 17 00:00:00 2001
From: Maksymilian Galas
Date: Fri, 4 Oct 2024 12:15:20 +0200
Subject: [PATCH 37/38] fix(iOS): full screen modal crash on paper (#2336)
## Description
Full screen modal was crashing sometimes on Paper.
Fixes #2317.
## Test code and steps to reproduce
Added `Test2317` to tests.
## Checklist
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
---------
Co-authored-by: Kacper Kafara
---
apps/src/tests/Test2317.tsx | 85 +++++++++++++++++++++++++++++++
apps/src/tests/index.ts | 1 +
ios/RNSScreenStackHeaderConfig.mm | 8 +++
3 files changed, 94 insertions(+)
create mode 100644 apps/src/tests/Test2317.tsx
diff --git a/apps/src/tests/Test2317.tsx b/apps/src/tests/Test2317.tsx
new file mode 100644
index 0000000000..799e46519f
--- /dev/null
+++ b/apps/src/tests/Test2317.tsx
@@ -0,0 +1,85 @@
+import * as React from 'react';
+import { NavigationContainer } from '@react-navigation/native';
+import { createNativeStackNavigator, NativeStackScreenProps } from '@react-navigation/native-stack';
+import { DarkTheme, DefaultTheme } from '@react-navigation/native';
+import { Button, StyleSheet, Text, useColorScheme } from 'react-native';
+import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
+import { Colors } from 'react-native/Libraries/NewAppScreen';
+
+const Stack = createNativeStackNavigator();
+
+const App = (): React.JSX.Element => {
+ const isDarkMode = useColorScheme();
+
+ return (
+
+
+
+
+ ({
+ presentation: 'fullScreenModal',
+ headerTitle: () => (
+
+ Header Title
+
+ )
+ })}
+ />
+
+
+
+ );
+};
+
+const FullScreenModal = ({ navigation }: NativeStackScreenProps<{}>) => {
+ const isDarkMode = useColorScheme() === 'dark';
+
+ return (
+
+ FullScreenModal
+
+
+ );
+};
+
+const MainScreen = ({
+ navigation
+}: NativeStackScreenProps>) => {
+ const isDarkMode = useColorScheme() === 'dark';
+
+ return (
+
+
+ Main Screen
+
+ navigation.navigate('modal')} />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center'
+ }
+});
+
+export default App;
diff --git a/apps/src/tests/index.ts b/apps/src/tests/index.ts
index eea1285008..94199a0fe4 100644
--- a/apps/src/tests/index.ts
+++ b/apps/src/tests/index.ts
@@ -111,6 +111,7 @@ export { default as Test2235 } from './Test2235';
export { default as Test2252 } from './Test2252';
export { default as Test2271 } from './Test2271';
export { default as Test2282 } from './Test2282';
+export { default as Test2317 } from './Test2317';
export { default as Test2332 } from './Test2332';
export { default as TestScreenAnimation } from './TestScreenAnimation';
export { default as TestHeader } from './TestHeader';
diff --git a/ios/RNSScreenStackHeaderConfig.mm b/ios/RNSScreenStackHeaderConfig.mm
index 04abae0cfb..a6dbb1a041 100644
--- a/ios/RNSScreenStackHeaderConfig.mm
+++ b/ios/RNSScreenStackHeaderConfig.mm
@@ -471,6 +471,14 @@ + (void)updateViewController:(UIViewController *)vc
UINavigationItem *navitem = vc.navigationItem;
UINavigationController *navctr = (UINavigationController *)vc.parentViewController;
+ // When modal is shown the underlying RNSScreen isn't attached to any navigation controller.
+ // During the modal dismissal transition this update method is called on this RNSScreen resulting in nil navctr.
+ // After the transition is completed it will be called again and will configure the navigation controller correctly.
+ // Also see: https://github.com/software-mansion/react-native-screens/pull/2336
+ if (navctr == nil) {
+ return;
+ }
+
NSUInteger currentIndex = [navctr.viewControllers indexOfObject:vc];
UINavigationItem *prevItem =
currentIndex > 0 ? [navctr.viewControllers objectAtIndex:currentIndex - 1].navigationItem : nil;
From e864aafc65e2630a4f8fbdba1bed1b9361239df7 Mon Sep 17 00:00:00 2001
From: Kacper Kafara
Date: Fri, 4 Oct 2024 14:02:35 +0200
Subject: [PATCH 38/38] fix: check for surplus values in sheet detents array
not only in dev mode (#2387)
## Description
Previous code reduced detent array to three values on Android only in
dev mode - this is undesired.
We want to always do it.
## Changes
Moved the slicing operation out of check for dev mode.
## Test code and steps to reproduce
`Test1649`, pass more than 3 values on Android, see that it works.
## Checklist
- [ ] Ensured that CI passes
---
src/components/Screen.tsx | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index e49b249d63..2dd3dfd8f7 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -76,14 +76,16 @@ function resolveSheetAllowedDetents(
allowedDetentsCompat: ScreenProps['sheetAllowedDetents'],
): number[] {
if (Array.isArray(allowedDetentsCompat)) {
- if (__DEV__) {
- assertDetentsArrayIsSorted(allowedDetentsCompat);
- if (Platform.OS === 'android' && allowedDetentsCompat.length > 3) {
+ if (Platform.OS === 'android' && allowedDetentsCompat.length > 3) {
+ if (__DEV__) {
console.warn(
'[RNScreens] Sheets API on Android do accept only up to 3 values. Any surplus value are ignored.',
);
- allowedDetentsCompat = allowedDetentsCompat.slice(0, 3);
}
+ allowedDetentsCompat = allowedDetentsCompat.slice(0, 3);
+ }
+ if (__DEV__) {
+ assertDetentsArrayIsSorted(allowedDetentsCompat);
}
return allowedDetentsCompat;
} else if (allowedDetentsCompat === 'fitToContents') {