react-native-screens 3.9.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +47 -7
  3. package/android/build.gradle +1 -2
  4. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +71 -0
  5. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +7 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +29 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -1
  8. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +35 -52
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +1 -1
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +83 -34
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +38 -33
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +77 -42
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +25 -9
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +8 -0
  15. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +7 -1
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +1 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +10 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +72 -11
  19. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +107 -0
  20. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +155 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +67 -0
  22. package/android/src/main/res/anim/rns_default_enter_in.xml +18 -0
  23. package/android/src/main/res/anim/rns_default_enter_out.xml +19 -0
  24. package/android/src/main/res/anim/rns_default_exit_in.xml +17 -0
  25. package/android/src/main/res/anim/rns_default_exit_out.xml +18 -0
  26. package/android/src/main/res/anim/rns_fade_in.xml +7 -0
  27. package/android/src/main/res/anim/rns_fade_out.xml +7 -0
  28. package/android/src/main/res/anim/rns_no_animation_20.xml +6 -0
  29. package/createNativeStackNavigator/README.md +12 -0
  30. package/ios/RNSScreen.h +10 -0
  31. package/ios/RNSScreen.m +38 -0
  32. package/ios/RNSScreenContainer.m +5 -0
  33. package/ios/RNSScreenStack.m +29 -13
  34. package/ios/RNSScreenStackAnimator.m +45 -14
  35. package/ios/RNSScreenStackHeaderConfig.m +4 -1
  36. package/ios/RNSScreenWindowTraits.h +1 -0
  37. package/ios/RNSScreenWindowTraits.m +20 -0
  38. package/ios/UIViewController+RNScreens.m +10 -0
  39. package/lib/commonjs/index.js +17 -1
  40. package/lib/commonjs/index.js.map +1 -1
  41. package/lib/commonjs/index.native.js +66 -18
  42. package/lib/commonjs/index.native.js.map +1 -1
  43. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +67 -0
  44. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -0
  45. package/lib/commonjs/native-stack/views/HeaderConfig.js +46 -4
  46. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  47. package/lib/commonjs/native-stack/views/NativeStackView.js +33 -4
  48. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  49. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +60 -0
  50. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  51. package/lib/commonjs/reanimated/ReanimatedScreen.js +7 -79
  52. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -1
  53. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +61 -0
  54. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -0
  55. package/lib/commonjs/reanimated/index.js +2 -2
  56. package/lib/commonjs/reanimated/index.js.map +1 -1
  57. package/lib/commonjs/utils.js +20 -0
  58. package/lib/commonjs/utils.js.map +1 -0
  59. package/lib/module/index.js +1 -0
  60. package/lib/module/index.js.map +1 -1
  61. package/lib/module/index.native.js +65 -19
  62. package/lib/module/index.native.js.map +1 -1
  63. package/lib/module/native-stack/utils/useBackPressSubscription.js +50 -0
  64. package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -0
  65. package/lib/module/native-stack/views/HeaderConfig.js +46 -5
  66. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  67. package/lib/module/native-stack/views/NativeStackView.js +33 -4
  68. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  69. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +40 -0
  70. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  71. package/lib/module/reanimated/ReanimatedScreen.js +6 -73
  72. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -1
  73. package/lib/module/reanimated/ReanimatedScreenProvider.js +49 -0
  74. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -0
  75. package/lib/module/reanimated/index.js +1 -1
  76. package/lib/module/reanimated/index.js.map +1 -1
  77. package/lib/module/utils.js +8 -0
  78. package/lib/module/utils.js.map +1 -0
  79. package/lib/typescript/index.d.ts +1 -0
  80. package/lib/typescript/native-stack/types.d.ts +34 -2
  81. package/lib/typescript/native-stack/utils/useBackPressSubscription.d.ts +16 -0
  82. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +5 -0
  83. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +5 -2
  84. package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts +2 -0
  85. package/lib/typescript/reanimated/index.d.ts +1 -1
  86. package/lib/typescript/types.d.ts +101 -1
  87. package/lib/typescript/utils.d.ts +2 -0
  88. package/native-stack/README.md +70 -8
  89. package/package.json +2 -1
  90. package/reanimated/package.json +6 -0
  91. package/src/index.native.tsx +94 -36
  92. package/src/index.tsx +4 -0
  93. package/src/native-stack/types.tsx +34 -2
  94. package/src/native-stack/utils/useBackPressSubscription.tsx +66 -0
  95. package/src/native-stack/views/HeaderConfig.tsx +46 -3
  96. package/src/native-stack/views/NativeStackView.tsx +33 -4
  97. package/src/reanimated/ReanimatedNativeStackScreen.tsx +61 -0
  98. package/src/reanimated/ReanimatedScreen.tsx +6 -84
  99. package/src/reanimated/ReanimatedScreenProvider.tsx +42 -0
  100. package/src/reanimated/index.tsx +1 -1
  101. package/src/types.tsx +101 -1
  102. package/src/utils.ts +12 -0
@@ -0,0 +1,107 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import com.facebook.react.bridge.JSApplicationIllegalArgumentException
4
+ import com.facebook.react.common.MapBuilder
5
+ import com.facebook.react.module.annotations.ReactModule
6
+ import com.facebook.react.uimanager.ThemedReactContext
7
+ import com.facebook.react.uimanager.ViewGroupManager
8
+ import com.facebook.react.uimanager.annotations.ReactProp
9
+
10
+ @ReactModule(name = SearchBarManager.REACT_CLASS)
11
+ class SearchBarManager : ViewGroupManager<SearchBarView>() {
12
+ override fun getName(): String {
13
+ return REACT_CLASS
14
+ }
15
+
16
+ override fun createViewInstance(context: ThemedReactContext): SearchBarView {
17
+ return SearchBarView(context)
18
+ }
19
+
20
+ override fun onAfterUpdateTransaction(view: SearchBarView) {
21
+ super.onAfterUpdateTransaction(view)
22
+ view.onUpdate()
23
+ }
24
+
25
+ @ReactProp(name = "autoCapitalize")
26
+ fun setAutoCapitalize(view: SearchBarView, autoCapitalize: String?) {
27
+ view.autoCapitalize = when (autoCapitalize) {
28
+ null, "none" -> SearchBarView.SearchBarAutoCapitalize.NONE
29
+ "words" -> SearchBarView.SearchBarAutoCapitalize.WORDS
30
+ "sentences" -> SearchBarView.SearchBarAutoCapitalize.SENTENCES
31
+ "characters" -> SearchBarView.SearchBarAutoCapitalize.CHARACTERS
32
+ else -> throw JSApplicationIllegalArgumentException(
33
+ "Forbidden auto capitalize value passed"
34
+ )
35
+ }
36
+ }
37
+
38
+ @ReactProp(name = "autoFocus")
39
+ fun setAutoFocus(view: SearchBarView, autoFocus: Boolean?) {
40
+ view.autoFocus = autoFocus ?: false
41
+ }
42
+
43
+ @ReactProp(name = "barTintColor", customType = "Color")
44
+ fun setTintColor(view: SearchBarView, color: Int?) {
45
+ view.tintColor = color
46
+ }
47
+
48
+ @ReactProp(name = "disableBackButtonOverride")
49
+ fun setDisableBackButtonOverride(view: SearchBarView, disableBackButtonOverride: Boolean?) {
50
+ view.shouldOverrideBackButton = disableBackButtonOverride != true
51
+ }
52
+
53
+ @ReactProp(name = "inputType")
54
+ fun setInputType(view: SearchBarView, inputType: String?) {
55
+ view.inputType = when (inputType) {
56
+ null, "text" -> SearchBarView.SearchBarInputTypes.TEXT
57
+ "phone" -> SearchBarView.SearchBarInputTypes.PHONE
58
+ "number" -> SearchBarView.SearchBarInputTypes.NUMBER
59
+ "email" -> SearchBarView.SearchBarInputTypes.EMAIL
60
+ else -> throw JSApplicationIllegalArgumentException(
61
+ "Forbidden input type value"
62
+ )
63
+ }
64
+ }
65
+
66
+ @ReactProp(name = "placeholder")
67
+ fun setPlaceholder(view: SearchBarView, placeholder: String?) {
68
+ if (placeholder != null) {
69
+ view.placeholder = placeholder
70
+ }
71
+ }
72
+
73
+ @ReactProp(name = "textColor", customType = "Color")
74
+ fun setTextColor(view: SearchBarView, color: Int?) {
75
+ view.textColor = color
76
+ }
77
+
78
+ @ReactProp(name = "headerIconColor", customType = "Color")
79
+ fun setHeaderIconColor(view: SearchBarView, color: Int?) {
80
+ view.headerIconColor = color
81
+ }
82
+
83
+ @ReactProp(name = "hintTextColor", customType = "Color")
84
+ fun setHintTextColor(view: SearchBarView, color: Int?) {
85
+ view.hintTextColor = color
86
+ }
87
+
88
+ @ReactProp(name = "shouldShowHintSearchIcon")
89
+ fun setShouldShowHintSearchIcon(view: SearchBarView, shouldShowHintSearchIcon: Boolean?) {
90
+ view.shouldShowHintSearchIcon = shouldShowHintSearchIcon ?: true
91
+ }
92
+
93
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
94
+ return MapBuilder.builder<String, Any>()
95
+ .put("onChangeText", MapBuilder.of("registrationName", "onChangeText"))
96
+ .put("onSearchButtonPress", MapBuilder.of("registrationName", "onSearchButtonPress"))
97
+ .put("onFocus", MapBuilder.of("registrationName", "onFocus"))
98
+ .put("onBlur", MapBuilder.of("registrationName", "onBlur"))
99
+ .put("onClose", MapBuilder.of("registrationName", "onClose"))
100
+ .put("onOpen", MapBuilder.of("registrationName", "onOpen"))
101
+ .build()
102
+ }
103
+
104
+ companion object {
105
+ const val REACT_CLASS = "RNSSearchBar"
106
+ }
107
+ }
@@ -0,0 +1,155 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.text.InputType
5
+ import androidx.appcompat.widget.SearchView
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.ReactContext
8
+ import com.facebook.react.bridge.WritableMap
9
+ import com.facebook.react.uimanager.events.RCTEventEmitter
10
+ import com.facebook.react.views.view.ReactViewGroup
11
+
12
+ @SuppressLint("ViewConstructor")
13
+ class SearchBarView(reactContext: ReactContext?) : ReactViewGroup(reactContext) {
14
+ var inputType: SearchBarInputTypes = SearchBarInputTypes.TEXT
15
+ var autoCapitalize: SearchBarAutoCapitalize = SearchBarAutoCapitalize.NONE
16
+ var textColor: Int? = null
17
+ var tintColor: Int? = null
18
+ var headerIconColor: Int? = null
19
+ var hintTextColor: Int? = null
20
+ var placeholder: String = ""
21
+ var shouldOverrideBackButton: Boolean = true
22
+ var autoFocus: Boolean = false
23
+ var shouldShowHintSearchIcon: Boolean = true
24
+
25
+ private var mSearchViewFormatter: SearchViewFormatter? = null
26
+
27
+ private var mAreListenersSet: Boolean = false
28
+
29
+ private val screenStackFragment: ScreenStackFragment?
30
+ get() {
31
+ val currentParent = parent
32
+ if (currentParent is ScreenStackHeaderSubview) {
33
+ return currentParent.config?.screenFragment
34
+ }
35
+ return null
36
+ }
37
+
38
+ fun onUpdate() {
39
+ setSearchViewProps()
40
+ }
41
+
42
+ private fun setSearchViewProps() {
43
+ val searchView = screenStackFragment?.searchView
44
+ if (searchView != null) {
45
+ if (!mAreListenersSet) {
46
+ setSearchViewListeners(searchView)
47
+ mAreListenersSet = true
48
+ }
49
+
50
+ searchView.inputType = inputType.toAndroidInputType(autoCapitalize)
51
+ mSearchViewFormatter?.setTextColor(textColor)
52
+ mSearchViewFormatter?.setTintColor(tintColor)
53
+ mSearchViewFormatter?.setHeaderIconColor(headerIconColor)
54
+ mSearchViewFormatter?.setHintTextColor(hintTextColor)
55
+ mSearchViewFormatter?.setPlaceholder(placeholder, shouldShowHintSearchIcon)
56
+ searchView.overrideBackAction = shouldOverrideBackButton
57
+ }
58
+ }
59
+
60
+ override fun onAttachedToWindow() {
61
+ super.onAttachedToWindow()
62
+
63
+ screenStackFragment?.onSearchViewCreate = { newSearchView ->
64
+ if (mSearchViewFormatter == null) mSearchViewFormatter =
65
+ SearchViewFormatter(newSearchView)
66
+ setSearchViewProps()
67
+ if (autoFocus) {
68
+ screenStackFragment?.searchView?.focus()
69
+ }
70
+ }
71
+ }
72
+
73
+ private fun setSearchViewListeners(searchView: SearchView) {
74
+ searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
75
+ override fun onQueryTextChange(newText: String?): Boolean {
76
+ handleTextChange(newText)
77
+ return true
78
+ }
79
+
80
+ override fun onQueryTextSubmit(query: String?): Boolean {
81
+ handleTextSubmit(query)
82
+ return true
83
+ }
84
+ })
85
+ searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
86
+ handleFocusChange(hasFocus)
87
+ }
88
+ searchView.setOnCloseListener {
89
+ handleClose()
90
+ false
91
+ }
92
+ searchView.setOnSearchClickListener {
93
+ handleOpen()
94
+ }
95
+ }
96
+
97
+ private fun handleTextChange(newText: String?) {
98
+ val event = Arguments.createMap()
99
+ event.putString("text", newText)
100
+ sendEvent("onChangeText", event)
101
+ }
102
+
103
+ private fun handleFocusChange(hasFocus: Boolean) {
104
+ sendEvent(if (hasFocus) "onFocus" else "onBlur", null)
105
+ }
106
+
107
+ private fun handleClose() {
108
+ sendEvent("onClose", null)
109
+ }
110
+
111
+ private fun handleOpen() {
112
+ sendEvent("onOpen", null)
113
+ }
114
+
115
+ private fun handleTextSubmit(newText: String?) {
116
+ val event = Arguments.createMap()
117
+ event.putString("text", newText)
118
+ sendEvent("onSearchButtonPress", event)
119
+ }
120
+
121
+ private fun sendEvent(eventName: String, eventContent: WritableMap?) {
122
+ (context as ReactContext).getJSModule(RCTEventEmitter::class.java)
123
+ ?.receiveEvent(id, eventName, eventContent)
124
+ }
125
+
126
+ enum class SearchBarAutoCapitalize {
127
+ NONE, WORDS, SENTENCES, CHARACTERS
128
+ }
129
+
130
+ enum class SearchBarInputTypes {
131
+ TEXT {
132
+ override fun toAndroidInputType(capitalize: SearchBarAutoCapitalize) =
133
+ when (capitalize) {
134
+ SearchBarAutoCapitalize.NONE -> InputType.TYPE_CLASS_TEXT
135
+ SearchBarAutoCapitalize.WORDS -> InputType.TYPE_TEXT_FLAG_CAP_WORDS
136
+ SearchBarAutoCapitalize.SENTENCES -> InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
137
+ SearchBarAutoCapitalize.CHARACTERS -> InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
138
+ }
139
+ },
140
+ PHONE {
141
+ override fun toAndroidInputType(capitalize: SearchBarAutoCapitalize) =
142
+ InputType.TYPE_CLASS_PHONE
143
+ },
144
+ NUMBER {
145
+ override fun toAndroidInputType(capitalize: SearchBarAutoCapitalize) =
146
+ InputType.TYPE_CLASS_NUMBER
147
+ },
148
+ EMAIL {
149
+ override fun toAndroidInputType(capitalize: SearchBarAutoCapitalize) =
150
+ InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
151
+ };
152
+
153
+ abstract fun toAndroidInputType(capitalize: SearchBarAutoCapitalize): Int
154
+ }
155
+ }
@@ -0,0 +1,67 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.graphics.drawable.Drawable
4
+ import android.view.View
5
+ import android.widget.EditText
6
+ import android.widget.ImageView
7
+ import androidx.appcompat.R
8
+ import androidx.appcompat.widget.SearchView
9
+
10
+ class SearchViewFormatter(var searchView: SearchView) {
11
+ private var mDefaultTextColor: Int? = null
12
+ private var mDefaultTintBackground: Drawable? = null
13
+
14
+ private val searchEditText
15
+ get() = searchView.findViewById<View>(R.id.search_src_text) as? EditText
16
+ private val searchTextPlate
17
+ get() = searchView.findViewById<View>(R.id.search_plate)
18
+ private val searchIcon
19
+ get() = searchView.findViewById<ImageView>(R.id.search_button)
20
+ private val searchCloseIcon
21
+ get() = searchView.findViewById<ImageView>(R.id.search_close_btn)
22
+
23
+ fun setTextColor(textColor: Int?) {
24
+ val currentDefaultTextColor = mDefaultTextColor
25
+ if (textColor != null) {
26
+ if (mDefaultTextColor == null) {
27
+ mDefaultTextColor = searchEditText?.textColors?.defaultColor
28
+ }
29
+ searchEditText?.setTextColor(textColor)
30
+ } else if (currentDefaultTextColor != null) {
31
+ searchEditText?.setTextColor(currentDefaultTextColor)
32
+ }
33
+ }
34
+
35
+ fun setTintColor(tintColor: Int?) {
36
+ val currentDefaultTintColor = mDefaultTintBackground
37
+ if (tintColor != null) {
38
+ if (mDefaultTintBackground == null) {
39
+ mDefaultTintBackground = searchTextPlate.background
40
+ }
41
+ searchTextPlate.setBackgroundColor(tintColor)
42
+ } else if (currentDefaultTintColor != null) {
43
+ searchTextPlate.background = currentDefaultTintColor
44
+ }
45
+ }
46
+
47
+ fun setHeaderIconColor(headerIconColor: Int?) {
48
+ headerIconColor?.let {
49
+ searchIcon.setColorFilter(it)
50
+ searchCloseIcon.setColorFilter(it)
51
+ }
52
+ }
53
+
54
+ fun setHintTextColor(hintTextColor: Int?) {
55
+ hintTextColor?.let {
56
+ searchEditText?.setHintTextColor(it)
57
+ }
58
+ }
59
+
60
+ fun setPlaceholder(placeholder: String, shouldShowHintSearchIcon: Boolean) {
61
+ if (shouldShowHintSearchIcon) {
62
+ searchView.queryHint = placeholder
63
+ } else {
64
+ searchEditText?.hint = placeholder
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <set xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <alpha
4
+ android:interpolator="@android:interpolator/accelerate_decelerate"
5
+ android:fromAlpha="0"
6
+ android:toAlpha="1.0"
7
+ android:startOffset="100"
8
+ android:duration="100"/>
9
+ <scale
10
+ android:interpolator="@android:interpolator/accelerate_decelerate"
11
+ android:fromXScale="0.85"
12
+ android:toXScale="1"
13
+ android:fromYScale="0.85"
14
+ android:toYScale="1"
15
+ android:pivotX="50%"
16
+ android:pivotY="50%"
17
+ android:duration="200"/>
18
+ </set>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <set xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <alpha
4
+ android:fromAlpha="1"
5
+ android:toAlpha="0.4"
6
+ android:startOffset="100"
7
+ android:duration="100"
8
+ android:interpolator="@android:interpolator/accelerate_decelerate" />
9
+
10
+ <scale
11
+ android:interpolator="@android:interpolator/accelerate_decelerate"
12
+ android:fromXScale="1"
13
+ android:toXScale="1.15"
14
+ android:fromYScale="1"
15
+ android:toYScale="1.15"
16
+ android:pivotX="50%"
17
+ android:pivotY="50%"
18
+ android:duration="200"/>
19
+ </set>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <set xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:shareInterpolator="false">
4
+ <alpha
5
+ android:fromAlpha="0.0"
6
+ android:toAlpha="1"
7
+ android:startOffset="50"
8
+ android:duration="100"/>
9
+ <scale
10
+ android:fromXScale="1.15"
11
+ android:toXScale="1"
12
+ android:fromYScale="1.15"
13
+ android:toYScale="1"
14
+ android:pivotX="50%"
15
+ android:pivotY="50%"
16
+ android:duration="200"/>
17
+ </set>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <set xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:shareInterpolator="false"
4
+ android:zAdjustment="top">
5
+ <alpha
6
+ android:fromAlpha="1"
7
+ android:toAlpha="0.0"
8
+ android:startOffset="50"
9
+ android:duration="100"/>
10
+ <scale
11
+ android:fromXScale="1"
12
+ android:toXScale="0.85"
13
+ android:fromYScale="1"
14
+ android:toYScale="0.85"
15
+ android:pivotX="50%"
16
+ android:pivotY="50%"
17
+ android:duration="200"/>
18
+ </set>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!--Duration taken from debugging source code-->
3
+ <alpha xmlns:android="http://schemas.android.com/apk/res/android"
4
+ android:fromAlpha="0.0"
5
+ android:toAlpha="1.0"
6
+ android:duration="150"
7
+ /> <!--Remember to change duration in the corresponding xml when modifying it-->
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!--Duration taken from debugging source code-->
3
+ <alpha xmlns:android="http://schemas.android.com/apk/res/android"
4
+ android:fromAlpha="1.0"
5
+ android:toAlpha="0.0"
6
+ android:duration="150"
7
+ /> <!--Remember to change duration in the corresponding xml when modifying it-->
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <alpha xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:fromAlpha="1.0"
4
+ android:toAlpha="1.0"
5
+ android:duration="20"
6
+ /> <!-- non-zero duration ensures transition events are triggered correctly -->
@@ -464,6 +464,18 @@ Defaults to an empty string.
464
464
 
465
465
  The search field text color.
466
466
 
467
+ #### `hintTextColor`
468
+
469
+ The search hint text color. (Android only)
470
+
471
+ #### `headerIconColor`
472
+
473
+ The search and close icon color shown in the header. (Android only)
474
+
475
+ #### `shouldShowHintSearchIcon`
476
+
477
+ Show the search hint icon when search bar is focused. (Android only)
478
+
467
479
  ### Helpers
468
480
 
469
481
  The stack navigator adds the following methods to the navigation prop:
package/ios/RNSScreen.h CHANGED
@@ -29,6 +29,11 @@ typedef NS_ENUM(NSInteger, RNSScreenReplaceAnimation) {
29
29
  RNSScreenReplaceAnimationPush,
30
30
  };
31
31
 
32
+ typedef NS_ENUM(NSInteger, RNSScreenSwipeDirection) {
33
+ RNSScreenSwipeDirectionVertical,
34
+ RNSScreenSwipeDirectionHorizontal,
35
+ };
36
+
32
37
  typedef NS_ENUM(NSInteger, RNSActivityState) {
33
38
  RNSActivityStateInactive = 0,
34
39
  RNSActivityStateTransitioningOrBelowTop = 1,
@@ -47,6 +52,7 @@ typedef NS_ENUM(NSInteger, RNSWindowTrait) {
47
52
  RNSWindowTraitAnimation,
48
53
  RNSWindowTraitHidden,
49
54
  RNSWindowTraitOrientation,
55
+ RNSWindowTraitHomeIndicatorHidden,
50
56
  };
51
57
 
52
58
  @interface RCTConvert (RNSScreen)
@@ -91,19 +97,23 @@ typedef NS_ENUM(NSInteger, RNSWindowTrait) {
91
97
  @property (nonatomic) RNSScreenStackAnimation stackAnimation;
92
98
  @property (nonatomic) RNSScreenStackPresentation stackPresentation;
93
99
  @property (nonatomic) RNSScreenReplaceAnimation replaceAnimation;
100
+ @property (nonatomic) RNSScreenSwipeDirection swipeDirection;
94
101
  @property (nonatomic) BOOL preventNativeDismiss;
95
102
  @property (nonatomic) BOOL hasOrientationSet;
96
103
  @property (nonatomic) BOOL hasStatusBarStyleSet;
97
104
  @property (nonatomic) BOOL hasStatusBarAnimationSet;
98
105
  @property (nonatomic) BOOL hasStatusBarHiddenSet;
106
+ @property (nonatomic) BOOL hasHomeIndicatorHiddenSet;
99
107
  @property (nonatomic) BOOL customAnimationOnSwipe;
100
108
  @property (nonatomic) BOOL fullScreenSwipeEnabled;
109
+ @property (nonatomic, retain) NSNumber *transitionDuration;
101
110
 
102
111
  #if !TARGET_OS_TV
103
112
  @property (nonatomic) RNSStatusBarStyle statusBarStyle;
104
113
  @property (nonatomic) UIStatusBarAnimation statusBarAnimation;
105
114
  @property (nonatomic) BOOL statusBarHidden;
106
115
  @property (nonatomic) UIInterfaceOrientationMask screenOrientation;
116
+ @property (nonatomic) BOOL homeIndicatorHidden;
107
117
  #endif
108
118
 
109
119
  - (void)notifyFinishTransitioning;
package/ios/RNSScreen.m CHANGED
@@ -34,6 +34,7 @@
34
34
  _hasStatusBarAnimationSet = NO;
35
35
  _hasStatusBarHiddenSet = NO;
36
36
  _hasOrientationSet = NO;
37
+ _hasHomeIndicatorHiddenSet = NO;
37
38
  }
38
39
 
39
40
  return self;
@@ -206,6 +207,13 @@
206
207
  _screenOrientation = screenOrientation;
207
208
  [RNSScreenWindowTraits enforceDesiredDeviceOrientation];
208
209
  }
210
+
211
+ - (void)setHomeIndicatorHidden:(BOOL)homeIndicatorHidden
212
+ {
213
+ _hasHomeIndicatorHiddenSet = YES;
214
+ _homeIndicatorHidden = homeIndicatorHidden;
215
+ [RNSScreenWindowTraits updateHomeIndicatorAutoHidden];
216
+ }
209
217
  #endif
210
218
 
211
219
  - (UIView *)reactSuperview
@@ -436,6 +444,17 @@
436
444
  return UIInterfaceOrientationMaskAllButUpsideDown;
437
445
  }
438
446
 
447
+ - (UIViewController *)childViewControllerForHomeIndicatorAutoHidden
448
+ {
449
+ UIViewController *vc = [self findChildVCForConfigAndTrait:RNSWindowTraitHomeIndicatorHidden includingModals:YES];
450
+ return vc == self ? nil : vc;
451
+ }
452
+
453
+ - (BOOL)prefersHomeIndicatorAutoHidden
454
+ {
455
+ return ((RNSScreenView *)self.view).homeIndicatorHidden;
456
+ }
457
+
439
458
  // if the returned vc is a child, it means that it can provide config;
440
459
  // if the returned vc is self, it means that there is no child for config and self has config to provide,
441
460
  // so we return self which results in asking self for preferredStatusBarStyle/Animation etc.;
@@ -495,6 +514,9 @@
495
514
  case RNSWindowTraitOrientation: {
496
515
  return ((RNSScreenView *)self.view).hasOrientationSet;
497
516
  }
517
+ case RNSWindowTraitHomeIndicatorHidden: {
518
+ return ((RNSScreenView *)self.view).hasHomeIndicatorHiddenSet;
519
+ }
498
520
  default: {
499
521
  RCTLogError(@"Unknown trait passed: %d", (int)trait);
500
522
  }
@@ -688,6 +710,10 @@
688
710
 
689
711
  - (void)traverseForScrollView:(UIView *)view
690
712
  {
713
+ if (![[self.view valueForKey:@"_bridge"] valueForKey:@"_jsThread"]) {
714
+ // we don't want to send `scrollViewDidEndDecelerating` event to JS before the JS thread is ready
715
+ return;
716
+ }
691
717
  if ([view isKindOfClass:[UIScrollView class]] &&
692
718
  ([[(UIScrollView *)view delegate] respondsToSelector:@selector(scrollViewDidEndDecelerating:)])) {
693
719
  [[(UIScrollView *)view delegate] scrollViewDidEndDecelerating:(id)view];
@@ -767,6 +793,8 @@ RCT_EXPORT_VIEW_PROPERTY(preventNativeDismiss, BOOL)
767
793
  RCT_EXPORT_VIEW_PROPERTY(replaceAnimation, RNSScreenReplaceAnimation)
768
794
  RCT_EXPORT_VIEW_PROPERTY(stackPresentation, RNSScreenStackPresentation)
769
795
  RCT_EXPORT_VIEW_PROPERTY(stackAnimation, RNSScreenStackAnimation)
796
+ RCT_EXPORT_VIEW_PROPERTY(swipeDirection, RNSScreenSwipeDirection)
797
+ RCT_EXPORT_VIEW_PROPERTY(transitionDuration, NSNumber)
770
798
 
771
799
  RCT_EXPORT_VIEW_PROPERTY(onAppear, RCTDirectEventBlock);
772
800
  RCT_EXPORT_VIEW_PROPERTY(onDisappear, RCTDirectEventBlock);
@@ -781,6 +809,7 @@ RCT_EXPORT_VIEW_PROPERTY(screenOrientation, UIInterfaceOrientationMask)
781
809
  RCT_EXPORT_VIEW_PROPERTY(statusBarAnimation, UIStatusBarAnimation)
782
810
  RCT_EXPORT_VIEW_PROPERTY(statusBarHidden, BOOL)
783
811
  RCT_EXPORT_VIEW_PROPERTY(statusBarStyle, RNSStatusBarStyle)
812
+ RCT_EXPORT_VIEW_PROPERTY(homeIndicatorHidden, BOOL)
784
813
  #endif
785
814
 
786
815
  - (UIView *)view
@@ -831,6 +860,15 @@ RCT_ENUM_CONVERTER(
831
860
  RNSScreenReplaceAnimationPop,
832
861
  integerValue)
833
862
 
863
+ RCT_ENUM_CONVERTER(
864
+ RNSScreenSwipeDirection,
865
+ (@{
866
+ @"vertical" : @(RNSScreenSwipeDirectionVertical),
867
+ @"horizontal" : @(RNSScreenSwipeDirectionHorizontal),
868
+ }),
869
+ RNSScreenSwipeDirectionHorizontal,
870
+ integerValue)
871
+
834
872
  #if !TARGET_OS_TV
835
873
  RCT_ENUM_CONVERTER(
836
874
  RNSStatusBarStyle,
@@ -23,6 +23,11 @@
23
23
  {
24
24
  return [self findActiveChildVC].supportedInterfaceOrientations;
25
25
  }
26
+
27
+ - (UIViewController *)childViewControllerForHomeIndicatorAutoHidden
28
+ {
29
+ return [self findActiveChildVC];
30
+ }
26
31
  #endif
27
32
 
28
33
  - (UIViewController *)findActiveChildVC