react-native-nitro-modal 0.1.5 → 0.3.0-rc
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.
- package/README.md +65 -11
- package/android/src/main/java/com/margelo/nitro/nitromodal/BottomSheetPresenter.kt +335 -34
- package/android/src/main/java/com/margelo/nitro/nitromodal/HybridNitroModal.kt +63 -22
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalConfig.kt +31 -1
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalContentRoot.kt +48 -5
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalPresenter.kt +63 -4
- package/android/src/main/java/com/margelo/nitro/nitromodal/NitroModalHostView.kt +68 -8
- package/ios/HybridNitroModal.swift +111 -20
- package/ios/ModalConfig.swift +44 -2
- package/ios/NitroModalHostView.swift +73 -8
- package/ios/SheetView.swift +575 -0
- package/ios/SheetViewController.swift +19 -450
- package/lib/module/NitroModal.js +39 -7
- package/lib/module/NitroModal.js.map +1 -1
- package/lib/module/NitroModalView.js +4 -3
- package/lib/module/NitroModalView.js.map +1 -1
- package/lib/module/NitroModalView.native.js +3 -0
- package/lib/module/NitroModalView.native.js.map +1 -1
- package/lib/module/NitroModalView.web.js +159 -0
- package/lib/module/NitroModalView.web.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/web/AnimatedValue.js +126 -0
- package/lib/module/web/AnimatedValue.js.map +1 -0
- package/lib/module/web/ModalConfig.js +30 -0
- package/lib/module/web/ModalConfig.js.map +1 -0
- package/lib/module/web/ModalController.js +306 -0
- package/lib/module/web/ModalController.js.map +1 -0
- package/lib/module/web/ModalPresenter.js +280 -0
- package/lib/module/web/ModalPresenter.js.map +1 -0
- package/lib/module/web/PopupPresenter.js +117 -0
- package/lib/module/web/PopupPresenter.js.map +1 -0
- package/lib/module/web/SheetPresenter.js +494 -0
- package/lib/module/web/SheetPresenter.js.map +1 -0
- package/lib/module/web/dom.js +138 -0
- package/lib/module/web/dom.js.map +1 -0
- package/lib/typescript/src/NitroModal.d.ts +35 -4
- package/lib/typescript/src/NitroModal.d.ts.map +1 -1
- package/lib/typescript/src/NitroModal.nitro.d.ts +29 -2
- package/lib/typescript/src/NitroModal.nitro.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.d.ts +2 -1
- package/lib/typescript/src/NitroModalView.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.native.d.ts +1 -0
- package/lib/typescript/src/NitroModalView.native.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.web.d.ts +6 -0
- package/lib/typescript/src/NitroModalView.web.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/web/AnimatedValue.d.ts +49 -0
- package/lib/typescript/src/web/AnimatedValue.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalConfig.d.ts +30 -0
- package/lib/typescript/src/web/ModalConfig.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalController.d.ts +70 -0
- package/lib/typescript/src/web/ModalController.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalPresenter.d.ts +107 -0
- package/lib/typescript/src/web/ModalPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/PopupPresenter.d.ts +20 -0
- package/lib/typescript/src/web/PopupPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/SheetPresenter.d.ts +65 -0
- package/lib/typescript/src/web/SheetPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/dom.d.ts +42 -0
- package/lib/typescript/src/web/dom.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.cpp +60 -6
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.hpp +10 -2
- package/nitrogen/generated/android/c++/JNamedSheetDetent.hpp +64 -0
- package/nitrogen/generated/android/c++/JSheetDetent.cpp +26 -0
- package/nitrogen/generated/android/c++/JSheetDetent.hpp +42 -37
- package/nitrogen/generated/android/c++/views/JHybridNitroModalStateUpdater.cpp +20 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt +40 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/NamedSheetDetent.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/SheetDetent.kt +47 -10
- package/nitrogen/generated/android/nitromodal+autolinking.cmake +1 -0
- package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Bridge.hpp +53 -8
- package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Umbrella.hpp +4 -3
- package/nitrogen/generated/ios/c++/HybridNitroModalSpecSwift.hpp +32 -5
- package/nitrogen/generated/ios/c++/views/HybridNitroModalComponent.mm +24 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec_cxx.swift +110 -5
- package/nitrogen/generated/ios/swift/NamedSheetDetent.swift +48 -0
- package/nitrogen/generated/ios/swift/SheetDetent.swift +15 -33
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.cpp +8 -0
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.hpp +14 -5
- package/nitrogen/generated/shared/c++/{SheetDetent.hpp → NamedSheetDetent.hpp} +17 -17
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.cpp +9 -1
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.hpp +15 -2
- package/nitrogen/generated/shared/json/NitroModalConfig.json +4 -0
- package/package.json +3 -2
- package/src/NitroModal.nitro.ts +30 -2
- package/src/NitroModal.tsx +71 -8
- package/src/NitroModalView.native.tsx +4 -0
- package/src/NitroModalView.tsx +9 -4
- package/src/NitroModalView.web.tsx +180 -0
- package/src/index.tsx +2 -0
- package/src/web/AnimatedValue.ts +193 -0
- package/src/web/ModalConfig.ts +67 -0
- package/src/web/ModalController.ts +338 -0
- package/src/web/ModalPresenter.ts +333 -0
- package/src/web/PopupPresenter.ts +129 -0
- package/src/web/SheetPresenter.ts +647 -0
- package/src/web/dom.ts +171 -0
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
// Forward declaration of `ModalMode` to properly resolve imports.
|
|
17
17
|
namespace margelo::nitro::nitromodal { enum class ModalMode; }
|
|
18
|
-
// Forward declaration of `
|
|
19
|
-
namespace margelo::nitro::nitromodal { enum class
|
|
18
|
+
// Forward declaration of `NamedSheetDetent` to properly resolve imports.
|
|
19
|
+
namespace margelo::nitro::nitromodal { enum class NamedSheetDetent; }
|
|
20
20
|
// Forward declaration of `KeyboardBehavior` to properly resolve imports.
|
|
21
21
|
namespace margelo::nitro::nitromodal { enum class KeyboardBehavior; }
|
|
22
22
|
// Forward declaration of `PopupAnimation` to properly resolve imports.
|
|
@@ -27,7 +27,8 @@ namespace margelo::nitro::nitromodal { enum class DismissReason; }
|
|
|
27
27
|
namespace margelo::nitro::nitromodal { struct ModalContentArea; }
|
|
28
28
|
|
|
29
29
|
#include "ModalMode.hpp"
|
|
30
|
-
#include "
|
|
30
|
+
#include "NamedSheetDetent.hpp"
|
|
31
|
+
#include <variant>
|
|
31
32
|
#include <vector>
|
|
32
33
|
#include <optional>
|
|
33
34
|
#include "KeyboardBehavior.hpp"
|
|
@@ -67,8 +68,10 @@ namespace margelo::nitro::nitromodal {
|
|
|
67
68
|
virtual void setIsOpen(bool isOpen) = 0;
|
|
68
69
|
virtual ModalMode getMode() = 0;
|
|
69
70
|
virtual void setMode(ModalMode mode) = 0;
|
|
70
|
-
virtual
|
|
71
|
-
virtual void
|
|
71
|
+
virtual bool getIsInline() = 0;
|
|
72
|
+
virtual void setIsInline(bool isInline) = 0;
|
|
73
|
+
virtual std::vector<std::variant<NamedSheetDetent, double>> getDetents() = 0;
|
|
74
|
+
virtual void setDetents(const std::vector<std::variant<NamedSheetDetent, double>>& detents) = 0;
|
|
72
75
|
virtual double getInitialDetentIndex() = 0;
|
|
73
76
|
virtual void setInitialDetentIndex(double initialDetentIndex) = 0;
|
|
74
77
|
virtual double getBackdropColor() = 0;
|
|
@@ -93,6 +96,8 @@ namespace margelo::nitro::nitromodal {
|
|
|
93
96
|
virtual void setKeyboardBehavior(KeyboardBehavior keyboardBehavior) = 0;
|
|
94
97
|
virtual PopupAnimation getPopupAnimation() = 0;
|
|
95
98
|
virtual void setPopupAnimation(PopupAnimation popupAnimation) = 0;
|
|
99
|
+
virtual bool getPullToRefreshEnabled() = 0;
|
|
100
|
+
virtual void setPullToRefreshEnabled(bool pullToRefreshEnabled) = 0;
|
|
96
101
|
virtual std::optional<std::function<void()>> getOnPresent() = 0;
|
|
97
102
|
virtual void setOnPresent(const std::optional<std::function<void()>>& onPresent) = 0;
|
|
98
103
|
virtual std::optional<std::function<void(DismissReason /* reason */)>> getOnDismiss() = 0;
|
|
@@ -105,6 +110,10 @@ namespace margelo::nitro::nitromodal {
|
|
|
105
110
|
virtual void setOnBackButtonPress(const std::optional<std::function<void()>>& onBackButtonPress) = 0;
|
|
106
111
|
virtual std::optional<std::function<void(const ModalContentArea& /* area */)>> getOnContentAreaChange() = 0;
|
|
107
112
|
virtual void setOnContentAreaChange(const std::optional<std::function<void(const ModalContentArea& /* area */)>>& onContentAreaChange) = 0;
|
|
113
|
+
virtual std::optional<std::function<void()>> getOnPullToRefresh() = 0;
|
|
114
|
+
virtual void setOnPullToRefresh(const std::optional<std::function<void()>>& onPullToRefresh) = 0;
|
|
115
|
+
virtual std::optional<std::function<void(double /* top */)>> getOnRestingTopChange() = 0;
|
|
116
|
+
virtual void setOnRestingTopChange(const std::optional<std::function<void(double /* top */)>>& onRestingTopChange) = 0;
|
|
108
117
|
|
|
109
118
|
public:
|
|
110
119
|
// Methods
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
///
|
|
2
|
-
///
|
|
2
|
+
/// NamedSheetDetent.hpp
|
|
3
3
|
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
4
|
/// https://github.com/mrousavy/nitro
|
|
5
5
|
/// Copyright © Marc Rousavy @ Margelo
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
namespace margelo::nitro::nitromodal {
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* An enum which can be represented as a JavaScript union (
|
|
29
|
+
* An enum which can be represented as a JavaScript union (NamedSheetDetent).
|
|
30
30
|
*/
|
|
31
|
-
enum class
|
|
31
|
+
enum class NamedSheetDetent {
|
|
32
32
|
SMALL SWIFT_NAME(small) = 0,
|
|
33
33
|
MEDIUM SWIFT_NAME(medium) = 1,
|
|
34
34
|
LARGE SWIFT_NAME(large) = 2,
|
|
@@ -39,28 +39,28 @@ namespace margelo::nitro::nitromodal {
|
|
|
39
39
|
|
|
40
40
|
namespace margelo::nitro {
|
|
41
41
|
|
|
42
|
-
// C++
|
|
42
|
+
// C++ NamedSheetDetent <> JS NamedSheetDetent (union)
|
|
43
43
|
template <>
|
|
44
|
-
struct JSIConverter<margelo::nitro::nitromodal::
|
|
45
|
-
static inline margelo::nitro::nitromodal::
|
|
44
|
+
struct JSIConverter<margelo::nitro::nitromodal::NamedSheetDetent> final {
|
|
45
|
+
static inline margelo::nitro::nitromodal::NamedSheetDetent fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
46
46
|
std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
|
|
47
47
|
switch (hashString(unionValue.c_str(), unionValue.size())) {
|
|
48
|
-
case hashString("small"): return margelo::nitro::nitromodal::
|
|
49
|
-
case hashString("medium"): return margelo::nitro::nitromodal::
|
|
50
|
-
case hashString("large"): return margelo::nitro::nitromodal::
|
|
51
|
-
case hashString("fitContent"): return margelo::nitro::nitromodal::
|
|
48
|
+
case hashString("small"): return margelo::nitro::nitromodal::NamedSheetDetent::SMALL;
|
|
49
|
+
case hashString("medium"): return margelo::nitro::nitromodal::NamedSheetDetent::MEDIUM;
|
|
50
|
+
case hashString("large"): return margelo::nitro::nitromodal::NamedSheetDetent::LARGE;
|
|
51
|
+
case hashString("fitContent"): return margelo::nitro::nitromodal::NamedSheetDetent::FITCONTENT;
|
|
52
52
|
default: [[unlikely]]
|
|
53
|
-
throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum
|
|
53
|
+
throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum NamedSheetDetent - invalid value!");
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitromodal::
|
|
56
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitromodal::NamedSheetDetent arg) {
|
|
57
57
|
switch (arg) {
|
|
58
|
-
case margelo::nitro::nitromodal::
|
|
59
|
-
case margelo::nitro::nitromodal::
|
|
60
|
-
case margelo::nitro::nitromodal::
|
|
61
|
-
case margelo::nitro::nitromodal::
|
|
58
|
+
case margelo::nitro::nitromodal::NamedSheetDetent::SMALL: return JSIConverter<std::string>::toJSI(runtime, "small");
|
|
59
|
+
case margelo::nitro::nitromodal::NamedSheetDetent::MEDIUM: return JSIConverter<std::string>::toJSI(runtime, "medium");
|
|
60
|
+
case margelo::nitro::nitromodal::NamedSheetDetent::LARGE: return JSIConverter<std::string>::toJSI(runtime, "large");
|
|
61
|
+
case margelo::nitro::nitromodal::NamedSheetDetent::FITCONTENT: return JSIConverter<std::string>::toJSI(runtime, "fitContent");
|
|
62
62
|
default: [[unlikely]]
|
|
63
|
-
throw std::invalid_argument("Cannot convert
|
|
63
|
+
throw std::invalid_argument("Cannot convert NamedSheetDetent to JS - invalid value: "
|
|
64
64
|
+ std::to_string(static_cast<int>(arg)) + "!");
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -22,7 +22,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
22
22
|
react::ViewProps(context, sourceProps, rawProps, filterObjectKeys),
|
|
23
23
|
isOpen(nitro::ReactProp<bool>::fromRawValue("NitroModal", "isOpen", rawProps, sourceProps.isOpen)),
|
|
24
24
|
mode(nitro::ReactProp<ModalMode>::fromRawValue("NitroModal", "mode", rawProps, sourceProps.mode)),
|
|
25
|
-
|
|
25
|
+
isInline(nitro::ReactProp<bool>::fromRawValue("NitroModal", "isInline", rawProps, sourceProps.isInline)),
|
|
26
|
+
detents(nitro::ReactProp<std::vector<std::variant<NamedSheetDetent, double>>>::fromRawValue("NitroModal", "detents", rawProps, sourceProps.detents)),
|
|
26
27
|
initialDetentIndex(nitro::ReactProp<double>::fromRawValue("NitroModal", "initialDetentIndex", rawProps, sourceProps.initialDetentIndex)),
|
|
27
28
|
backdropColor(nitro::ReactProp<double>::fromRawValue("NitroModal", "backdropColor", rawProps, sourceProps.backdropColor)),
|
|
28
29
|
backdropOpacity(nitro::ReactProp<double>::fromRawValue("NitroModal", "backdropOpacity", rawProps, sourceProps.backdropOpacity)),
|
|
@@ -35,18 +36,22 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
35
36
|
contentBackgroundColor(nitro::ReactProp<std::optional<double>>::fromRawValue("NitroModal", "contentBackgroundColor", rawProps, sourceProps.contentBackgroundColor)),
|
|
36
37
|
keyboardBehavior(nitro::ReactProp<KeyboardBehavior>::fromRawValue("NitroModal", "keyboardBehavior", rawProps, sourceProps.keyboardBehavior)),
|
|
37
38
|
popupAnimation(nitro::ReactProp<PopupAnimation>::fromRawValue("NitroModal", "popupAnimation", rawProps, sourceProps.popupAnimation)),
|
|
39
|
+
pullToRefreshEnabled(nitro::ReactProp<bool>::fromRawValue("NitroModal", "pullToRefreshEnabled", rawProps, sourceProps.pullToRefreshEnabled)),
|
|
38
40
|
onPresent(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("NitroModal", "onPresent", rawProps, sourceProps.onPresent)),
|
|
39
41
|
onDismiss(nitro::ReactProp<std::optional<std::function<void(DismissReason /* reason */)>>>::fromRawValue("NitroModal", "onDismiss", rawProps, sourceProps.onDismiss)),
|
|
40
42
|
onDetentChange(nitro::ReactProp<std::optional<std::function<void(double /* index */)>>>::fromRawValue("NitroModal", "onDetentChange", rawProps, sourceProps.onDetentChange)),
|
|
41
43
|
onBackdropPress(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("NitroModal", "onBackdropPress", rawProps, sourceProps.onBackdropPress)),
|
|
42
44
|
onBackButtonPress(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("NitroModal", "onBackButtonPress", rawProps, sourceProps.onBackButtonPress)),
|
|
43
45
|
onContentAreaChange(nitro::ReactProp<std::optional<std::function<void(const ModalContentArea& /* area */)>>>::fromRawValue("NitroModal", "onContentAreaChange", rawProps, sourceProps.onContentAreaChange)),
|
|
46
|
+
onPullToRefresh(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("NitroModal", "onPullToRefresh", rawProps, sourceProps.onPullToRefresh)),
|
|
47
|
+
onRestingTopChange(nitro::ReactProp<std::optional<std::function<void(double /* top */)>>>::fromRawValue("NitroModal", "onRestingTopChange", rawProps, sourceProps.onRestingTopChange)),
|
|
44
48
|
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridNitroModalSpec>& /* ref */)>>>::fromRawValue("NitroModal", "hybridRef", rawProps, sourceProps.hybridRef)) { }
|
|
45
49
|
|
|
46
50
|
bool HybridNitroModalProps::filterObjectKeys(const std::string& propName) {
|
|
47
51
|
switch (hashString(propName)) {
|
|
48
52
|
case hashString("isOpen"): return true;
|
|
49
53
|
case hashString("mode"): return true;
|
|
54
|
+
case hashString("isInline"): return true;
|
|
50
55
|
case hashString("detents"): return true;
|
|
51
56
|
case hashString("initialDetentIndex"): return true;
|
|
52
57
|
case hashString("backdropColor"): return true;
|
|
@@ -60,12 +65,15 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
60
65
|
case hashString("contentBackgroundColor"): return true;
|
|
61
66
|
case hashString("keyboardBehavior"): return true;
|
|
62
67
|
case hashString("popupAnimation"): return true;
|
|
68
|
+
case hashString("pullToRefreshEnabled"): return true;
|
|
63
69
|
case hashString("onPresent"): return true;
|
|
64
70
|
case hashString("onDismiss"): return true;
|
|
65
71
|
case hashString("onDetentChange"): return true;
|
|
66
72
|
case hashString("onBackdropPress"): return true;
|
|
67
73
|
case hashString("onBackButtonPress"): return true;
|
|
68
74
|
case hashString("onContentAreaChange"): return true;
|
|
75
|
+
case hashString("onPullToRefresh"): return true;
|
|
76
|
+
case hashString("onRestingTopChange"): return true;
|
|
69
77
|
case hashString("hybridRef"): return true;
|
|
70
78
|
default: return false;
|
|
71
79
|
}
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
#include <string>
|
|
19
19
|
|
|
20
20
|
#include "ModalMode.hpp"
|
|
21
|
-
#include "
|
|
21
|
+
#include "NamedSheetDetent.hpp"
|
|
22
|
+
#include <variant>
|
|
22
23
|
#include <vector>
|
|
23
24
|
#include <optional>
|
|
24
25
|
#include "KeyboardBehavior.hpp"
|
|
@@ -51,7 +52,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
51
52
|
public:
|
|
52
53
|
nitro::ReactProp<bool> isOpen;
|
|
53
54
|
nitro::ReactProp<ModalMode> mode;
|
|
54
|
-
nitro::ReactProp<
|
|
55
|
+
nitro::ReactProp<bool> isInline;
|
|
56
|
+
nitro::ReactProp<std::vector<std::variant<NamedSheetDetent, double>>> detents;
|
|
55
57
|
nitro::ReactProp<double> initialDetentIndex;
|
|
56
58
|
nitro::ReactProp<double> backdropColor;
|
|
57
59
|
nitro::ReactProp<double> backdropOpacity;
|
|
@@ -64,18 +66,22 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
64
66
|
nitro::ReactProp<std::optional<double>> contentBackgroundColor;
|
|
65
67
|
nitro::ReactProp<KeyboardBehavior> keyboardBehavior;
|
|
66
68
|
nitro::ReactProp<PopupAnimation> popupAnimation;
|
|
69
|
+
nitro::ReactProp<bool> pullToRefreshEnabled;
|
|
67
70
|
nitro::ReactProp<std::optional<std::function<void()>>> onPresent;
|
|
68
71
|
nitro::ReactProp<std::optional<std::function<void(DismissReason /* reason */)>>> onDismiss;
|
|
69
72
|
nitro::ReactProp<std::optional<std::function<void(double /* index */)>>> onDetentChange;
|
|
70
73
|
nitro::ReactProp<std::optional<std::function<void()>>> onBackdropPress;
|
|
71
74
|
nitro::ReactProp<std::optional<std::function<void()>>> onBackButtonPress;
|
|
72
75
|
nitro::ReactProp<std::optional<std::function<void(const ModalContentArea& /* area */)>>> onContentAreaChange;
|
|
76
|
+
nitro::ReactProp<std::optional<std::function<void()>>> onPullToRefresh;
|
|
77
|
+
nitro::ReactProp<std::optional<std::function<void(double /* top */)>>> onRestingTopChange;
|
|
73
78
|
nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridNitroModalSpec>& /* ref */)>>> hybridRef;
|
|
74
79
|
|
|
75
80
|
[[nodiscard]]
|
|
76
81
|
bool hasSameProps(const HybridNitroModalProps& other) const noexcept {
|
|
77
82
|
return isOpen.hasSameValue(other.isOpen) &&
|
|
78
83
|
mode.hasSameValue(other.mode) &&
|
|
84
|
+
isInline.hasSameValue(other.isInline) &&
|
|
79
85
|
detents.hasSameValue(other.detents) &&
|
|
80
86
|
initialDetentIndex.hasSameValue(other.initialDetentIndex) &&
|
|
81
87
|
backdropColor.hasSameValue(other.backdropColor) &&
|
|
@@ -89,12 +95,15 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
89
95
|
contentBackgroundColor.hasSameValue(other.contentBackgroundColor) &&
|
|
90
96
|
keyboardBehavior.hasSameValue(other.keyboardBehavior) &&
|
|
91
97
|
popupAnimation.hasSameValue(other.popupAnimation) &&
|
|
98
|
+
pullToRefreshEnabled.hasSameValue(other.pullToRefreshEnabled) &&
|
|
92
99
|
onPresent.hasSameValue(other.onPresent) &&
|
|
93
100
|
onDismiss.hasSameValue(other.onDismiss) &&
|
|
94
101
|
onDetentChange.hasSameValue(other.onDetentChange) &&
|
|
95
102
|
onBackdropPress.hasSameValue(other.onBackdropPress) &&
|
|
96
103
|
onBackButtonPress.hasSameValue(other.onBackButtonPress) &&
|
|
97
104
|
onContentAreaChange.hasSameValue(other.onContentAreaChange) &&
|
|
105
|
+
onPullToRefresh.hasSameValue(other.onPullToRefresh) &&
|
|
106
|
+
onRestingTopChange.hasSameValue(other.onRestingTopChange) &&
|
|
98
107
|
hybridRef.hasSameValue(other.hybridRef);
|
|
99
108
|
}
|
|
100
109
|
|
|
@@ -102,6 +111,7 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
102
111
|
bool hasAnyProvidedProps() const noexcept {
|
|
103
112
|
return isOpen.isProvided() ||
|
|
104
113
|
mode.isProvided() ||
|
|
114
|
+
isInline.isProvided() ||
|
|
105
115
|
detents.isProvided() ||
|
|
106
116
|
initialDetentIndex.isProvided() ||
|
|
107
117
|
backdropColor.isProvided() ||
|
|
@@ -115,12 +125,15 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
115
125
|
contentBackgroundColor.isProvided() ||
|
|
116
126
|
keyboardBehavior.isProvided() ||
|
|
117
127
|
popupAnimation.isProvided() ||
|
|
128
|
+
pullToRefreshEnabled.isProvided() ||
|
|
118
129
|
onPresent.isProvided() ||
|
|
119
130
|
onDismiss.isProvided() ||
|
|
120
131
|
onDetentChange.isProvided() ||
|
|
121
132
|
onBackdropPress.isProvided() ||
|
|
122
133
|
onBackButtonPress.isProvided() ||
|
|
123
134
|
onContentAreaChange.isProvided() ||
|
|
135
|
+
onPullToRefresh.isProvided() ||
|
|
136
|
+
onRestingTopChange.isProvided() ||
|
|
124
137
|
hybridRef.isProvided();
|
|
125
138
|
}
|
|
126
139
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"validAttributes": {
|
|
7
7
|
"isOpen": true,
|
|
8
8
|
"mode": true,
|
|
9
|
+
"isInline": true,
|
|
9
10
|
"detents": true,
|
|
10
11
|
"initialDetentIndex": true,
|
|
11
12
|
"backdropColor": true,
|
|
@@ -19,12 +20,15 @@
|
|
|
19
20
|
"contentBackgroundColor": true,
|
|
20
21
|
"keyboardBehavior": true,
|
|
21
22
|
"popupAnimation": true,
|
|
23
|
+
"pullToRefreshEnabled": true,
|
|
22
24
|
"onPresent": true,
|
|
23
25
|
"onDismiss": true,
|
|
24
26
|
"onDetentChange": true,
|
|
25
27
|
"onBackdropPress": true,
|
|
26
28
|
"onBackButtonPress": true,
|
|
27
29
|
"onContentAreaChange": true,
|
|
30
|
+
"onPullToRefresh": true,
|
|
31
|
+
"onRestingTopChange": true,
|
|
28
32
|
"hybridRef": true
|
|
29
33
|
}
|
|
30
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-modal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-rc",
|
|
4
4
|
"description": "react native native modal",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"keywords": [
|
|
48
48
|
"react-native",
|
|
49
49
|
"ios",
|
|
50
|
-
"android"
|
|
50
|
+
"android",
|
|
51
|
+
"web"
|
|
51
52
|
],
|
|
52
53
|
"repository": {
|
|
53
54
|
"type": "git",
|
package/src/NitroModal.nitro.ts
CHANGED
|
@@ -13,13 +13,20 @@ import type {
|
|
|
13
13
|
export type ModalMode = 'bottomSheet' | 'popup';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Named resting heights of a `bottomSheet`.
|
|
17
17
|
* - `small`: ~25% of the available height.
|
|
18
18
|
* - `medium`: ~50% of the available height.
|
|
19
19
|
* - `large`: the full available height.
|
|
20
20
|
* - `fitContent`: the measured height of the React content.
|
|
21
21
|
*/
|
|
22
|
-
export type
|
|
22
|
+
export type NamedSheetDetent = 'small' | 'medium' | 'large' | 'fitContent';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A resting height of a `bottomSheet`: a named height, or the height
|
|
26
|
+
* (dp/pt) of the content above the bottom safe area, clamped to the
|
|
27
|
+
* available height.
|
|
28
|
+
*/
|
|
29
|
+
export type SheetDetent = NamedSheetDetent | number;
|
|
23
30
|
|
|
24
31
|
/**
|
|
25
32
|
* How the modal reacts to the software keyboard.
|
|
@@ -48,6 +55,12 @@ export interface NitroModalProps extends HybridViewProps {
|
|
|
48
55
|
/** Whether the modal should be presented. */
|
|
49
56
|
isOpen: boolean;
|
|
50
57
|
mode: ModalMode;
|
|
58
|
+
/**
|
|
59
|
+
* A `bottomSheet` that lives inside the host view's own bounds instead of
|
|
60
|
+
* being presented over the app: no backdrop, touches outside the sheet
|
|
61
|
+
* reach the views behind it, and the user can't dismiss it.
|
|
62
|
+
*/
|
|
63
|
+
isInline: boolean;
|
|
51
64
|
/** Detents of a `bottomSheet`, smallest first. At most 3 are used on Android. */
|
|
52
65
|
detents: SheetDetent[];
|
|
53
66
|
/** Index into `detents` that the sheet opens at. */
|
|
@@ -68,6 +81,11 @@ export interface NitroModalProps extends HybridViewProps {
|
|
|
68
81
|
contentBackgroundColor?: number;
|
|
69
82
|
keyboardBehavior: KeyboardBehavior;
|
|
70
83
|
popupAnimation: PopupAnimation;
|
|
84
|
+
/**
|
|
85
|
+
* Pulling a `bottomSheet` down past its lowest detent calls
|
|
86
|
+
* `onPullToRefresh`. Needs `dismissOnSwipe` off (always the case inline).
|
|
87
|
+
*/
|
|
88
|
+
pullToRefreshEnabled: boolean;
|
|
71
89
|
|
|
72
90
|
/** The present transition finished. */
|
|
73
91
|
onPresent?: () => void;
|
|
@@ -80,6 +98,16 @@ export interface NitroModalProps extends HybridViewProps {
|
|
|
80
98
|
onBackButtonPress?: () => void;
|
|
81
99
|
/** The area available to the content changed (rotation, keyboard, sheet sizing). */
|
|
82
100
|
onContentAreaChange?: (area: ModalContentArea) => void;
|
|
101
|
+
/**
|
|
102
|
+
* The user pulled the sheet down past its lowest detent and let go. The
|
|
103
|
+
* gesture must start with the sheet resting on that detent.
|
|
104
|
+
*/
|
|
105
|
+
onPullToRefresh?: () => void;
|
|
106
|
+
/**
|
|
107
|
+
* Inline sheets: where the sheet's top rests within the host view (or
|
|
108
|
+
* will, once it settles). Lets React lay the content out where it is shown.
|
|
109
|
+
*/
|
|
110
|
+
onRestingTopChange?: (top: number) => void;
|
|
83
111
|
}
|
|
84
112
|
|
|
85
113
|
export interface NitroModalMethods extends HybridViewMethods {
|
package/src/NitroModal.tsx
CHANGED
|
@@ -16,17 +16,26 @@ import {
|
|
|
16
16
|
type StyleProp,
|
|
17
17
|
type ViewStyle,
|
|
18
18
|
} from 'react-native';
|
|
19
|
-
import { callback } from 'react-native-nitro-modules';
|
|
20
19
|
import type {
|
|
21
20
|
DismissReason,
|
|
22
21
|
KeyboardBehavior,
|
|
23
22
|
ModalContentArea,
|
|
24
23
|
ModalMode,
|
|
24
|
+
NamedSheetDetent,
|
|
25
25
|
NitroModal as NitroModalHybridView,
|
|
26
26
|
PopupAnimation,
|
|
27
27
|
SheetDetent,
|
|
28
28
|
} from './NitroModal.nitro';
|
|
29
|
-
import { NitroModalView } from './NitroModalView';
|
|
29
|
+
import { callback, NitroModalView } from './NitroModalView';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Where a `bottomSheet` lives.
|
|
33
|
+
* - `modal`: presented over the whole app, with a backdrop.
|
|
34
|
+
* - `inline`: inside the component's own frame (`style`), as part of your
|
|
35
|
+
* screen. No backdrop, the views behind it stay interactive, and the user
|
|
36
|
+
* can't dismiss it.
|
|
37
|
+
*/
|
|
38
|
+
export type ModalPresentation = 'modal' | 'inline';
|
|
30
39
|
|
|
31
40
|
export interface NitroModalRef {
|
|
32
41
|
/** Opens the modal. Only for uncontrolled usage (no `isOpen` prop). */
|
|
@@ -46,7 +55,23 @@ export interface NitroModalProps {
|
|
|
46
55
|
isOpen?: boolean;
|
|
47
56
|
/** @default 'bottomSheet' */
|
|
48
57
|
mode?: ModalMode;
|
|
49
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* `inline` keeps a `bottomSheet` inside this component's frame, like a
|
|
60
|
+
* persistent sheet that is part of the screen. Popups are always modal.
|
|
61
|
+
* @default 'modal'
|
|
62
|
+
*/
|
|
63
|
+
presentation?: ModalPresentation;
|
|
64
|
+
/**
|
|
65
|
+
* Inline only: the frame the sheet lives in, laid out like any view.
|
|
66
|
+
* The sheet rests against its bottom edge and its largest detent reaches its
|
|
67
|
+
* top edge. @default StyleSheet.absoluteFill
|
|
68
|
+
*/
|
|
69
|
+
style?: StyleProp<ViewStyle>;
|
|
70
|
+
/**
|
|
71
|
+
* Sheet heights, smallest first: named sizes, or the content height in
|
|
72
|
+
* dp/pt above the bottom safe area. Android uses at most three.
|
|
73
|
+
* @default ['fitContent']
|
|
74
|
+
*/
|
|
50
75
|
detents?: SheetDetent[];
|
|
51
76
|
/** @default 0 */
|
|
52
77
|
initialDetentIndex?: number;
|
|
@@ -54,13 +79,13 @@ export interface NitroModalProps {
|
|
|
54
79
|
backdropColor?: ColorValue;
|
|
55
80
|
/** @default 0.4 */
|
|
56
81
|
backdropOpacity?: number;
|
|
57
|
-
/** Blur radius (dp/pt) behind the modal. Android 12+; approximated on iOS. @default 0 */
|
|
82
|
+
/** Blur radius (dp/pt/px) behind the modal. Android 12+; approximated on iOS. @default 0 */
|
|
58
83
|
backdropBlur?: number;
|
|
59
84
|
/** @default true */
|
|
60
85
|
dismissOnBackdropPress?: boolean;
|
|
61
86
|
/** Swipe down to dismiss a `bottomSheet`. @default true */
|
|
62
87
|
dismissOnSwipe?: boolean;
|
|
63
|
-
/** Android back button/gesture dismisses the modal. @default true */
|
|
88
|
+
/** Android back button/gesture (Escape on web) dismisses the modal. @default true */
|
|
64
89
|
dismissOnBackButton?: boolean;
|
|
65
90
|
/** @default false */
|
|
66
91
|
showGrabber?: boolean;
|
|
@@ -79,6 +104,13 @@ export interface NitroModalProps {
|
|
|
79
104
|
onDetentChange?: (index: number) => void;
|
|
80
105
|
onBackdropPress?: () => void;
|
|
81
106
|
onBackButtonPress?: () => void;
|
|
107
|
+
/**
|
|
108
|
+
* Pull-to-refresh: the user dragged the sheet down past its lowest detent
|
|
109
|
+
* and let go. Only for sheets that can't be swiped away (inline, or
|
|
110
|
+
* `dismissOnSwipe={false}`), and only from a gesture that starts with the
|
|
111
|
+
* sheet resting on its lowest detent.
|
|
112
|
+
*/
|
|
113
|
+
onPullToRefresh?: () => void;
|
|
82
114
|
children?: ReactNode;
|
|
83
115
|
testID?: string;
|
|
84
116
|
ref?: Ref<NitroModalRef>;
|
|
@@ -87,6 +119,13 @@ export interface NitroModalProps {
|
|
|
87
119
|
const DEFAULT_DETENTS: SheetDetent[] = ['fitContent'];
|
|
88
120
|
const BLACK = 0xff000000;
|
|
89
121
|
|
|
122
|
+
function parseDetent(value: string): SheetDetent {
|
|
123
|
+
const points = Number(value);
|
|
124
|
+
return value !== '' && Number.isFinite(points)
|
|
125
|
+
? points
|
|
126
|
+
: (value as NamedSheetDetent);
|
|
127
|
+
}
|
|
128
|
+
|
|
90
129
|
function toNativeColor(color: ColorValue | undefined): number | undefined {
|
|
91
130
|
if (color == null) return undefined;
|
|
92
131
|
const processed = processColor(color);
|
|
@@ -97,6 +136,8 @@ function toNativeColor(color: ColorValue | undefined): number | undefined {
|
|
|
97
136
|
export function NitroModal({
|
|
98
137
|
isOpen,
|
|
99
138
|
mode = 'bottomSheet',
|
|
139
|
+
presentation = 'modal',
|
|
140
|
+
style,
|
|
100
141
|
detents = DEFAULT_DETENTS,
|
|
101
142
|
initialDetentIndex = 0,
|
|
102
143
|
backdropColor = 'black',
|
|
@@ -116,11 +157,13 @@ export function NitroModal({
|
|
|
116
157
|
onDetentChange,
|
|
117
158
|
onBackdropPress,
|
|
118
159
|
onBackButtonPress,
|
|
160
|
+
onPullToRefresh,
|
|
119
161
|
children,
|
|
120
162
|
testID,
|
|
121
163
|
ref,
|
|
122
164
|
}: NitroModalProps) {
|
|
123
165
|
const isControlled = isOpen !== undefined;
|
|
166
|
+
const isInline = presentation === 'inline' && mode === 'bottomSheet';
|
|
124
167
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
125
168
|
const open = isControlled ? isOpen : internalOpen;
|
|
126
169
|
|
|
@@ -135,6 +178,10 @@ export function NitroModal({
|
|
|
135
178
|
const renderContent = open || sessionActive;
|
|
136
179
|
|
|
137
180
|
const [area, setArea] = useState<ModalContentArea | null>(null);
|
|
181
|
+
// Inline (iOS/Android): where the sheet's top rests in the host. The content
|
|
182
|
+
// is laid out there so `measure()`, which presses rely on, matches the
|
|
183
|
+
// screen; native cancels the offset out on screen.
|
|
184
|
+
const [restingTop, setRestingTop] = useState(0);
|
|
138
185
|
const hybridRef = useRef<NitroModalHybridView | null>(null);
|
|
139
186
|
|
|
140
187
|
// Native callbacks are created once (stable props, no native updates on
|
|
@@ -146,6 +193,7 @@ export function NitroModal({
|
|
|
146
193
|
onDetentChange,
|
|
147
194
|
onBackdropPress,
|
|
148
195
|
onBackButtonPress,
|
|
196
|
+
onPullToRefresh,
|
|
149
197
|
});
|
|
150
198
|
useLayoutEffect(() => {
|
|
151
199
|
latest.current = {
|
|
@@ -155,6 +203,7 @@ export function NitroModal({
|
|
|
155
203
|
onDetentChange,
|
|
156
204
|
onBackdropPress,
|
|
157
205
|
onBackButtonPress,
|
|
206
|
+
onPullToRefresh,
|
|
158
207
|
};
|
|
159
208
|
});
|
|
160
209
|
|
|
@@ -181,6 +230,12 @@ export function NitroModal({
|
|
|
181
230
|
onBackButtonPress: callback(() => {
|
|
182
231
|
latest.current.onBackButtonPress?.();
|
|
183
232
|
}),
|
|
233
|
+
onPullToRefresh: callback(() => {
|
|
234
|
+
latest.current.onPullToRefresh?.();
|
|
235
|
+
}),
|
|
236
|
+
onRestingTopChange: callback((top: number) => {
|
|
237
|
+
setRestingTop(top);
|
|
238
|
+
}),
|
|
184
239
|
onContentAreaChange: callback((next: ModalContentArea) => {
|
|
185
240
|
setArea((current) =>
|
|
186
241
|
current?.width === next.width && current.height === next.height
|
|
@@ -221,7 +276,7 @@ export function NitroModal({
|
|
|
221
276
|
// Arrays are diffed by identity, so keep one instance per distinct value.
|
|
222
277
|
const detentsKey = detents.join(',');
|
|
223
278
|
const nativeDetents = useMemo(
|
|
224
|
-
() => [...new Set(detentsKey.split(','))]
|
|
279
|
+
() => [...new Set(detentsKey.split(','))].map(parseDetent),
|
|
225
280
|
[detentsKey]
|
|
226
281
|
);
|
|
227
282
|
|
|
@@ -241,9 +296,11 @@ export function NitroModal({
|
|
|
241
296
|
|
|
242
297
|
return (
|
|
243
298
|
<NitroModalView
|
|
244
|
-
style={styles.host}
|
|
299
|
+
style={isInline ? [StyleSheet.absoluteFill, style] : styles.host}
|
|
300
|
+
pointerEvents={isInline ? 'box-none' : undefined}
|
|
245
301
|
isOpen={open}
|
|
246
302
|
mode={mode}
|
|
303
|
+
isInline={isInline}
|
|
247
304
|
detents={nativeDetents}
|
|
248
305
|
initialDetentIndex={initialDetentIndex}
|
|
249
306
|
backdropColor={toNativeColor(backdropColor) ?? BLACK}
|
|
@@ -257,13 +314,19 @@ export function NitroModal({
|
|
|
257
314
|
contentBackgroundColor={toNativeColor(backgroundColor)}
|
|
258
315
|
keyboardBehavior={keyboardBehavior}
|
|
259
316
|
popupAnimation={popupAnimation}
|
|
317
|
+
pullToRefreshEnabled={onPullToRefresh != null}
|
|
260
318
|
{...nativeCallbacks}
|
|
261
319
|
>
|
|
262
320
|
{renderContent ? (
|
|
263
321
|
<View
|
|
264
322
|
collapsable={false}
|
|
265
323
|
testID={testID}
|
|
266
|
-
style={[
|
|
324
|
+
style={[
|
|
325
|
+
styles.container,
|
|
326
|
+
containerStyle,
|
|
327
|
+
contentContainerStyle,
|
|
328
|
+
isInline && restingTop > 0 ? { top: restingTop } : null,
|
|
329
|
+
]}
|
|
267
330
|
>
|
|
268
331
|
{children}
|
|
269
332
|
</View>
|
|
@@ -4,6 +4,10 @@ import { getHostComponent } from 'react-native-nitro-modules';
|
|
|
4
4
|
const NitroModalConfig = require('react-native-nitro-modal/nitrogen/generated/shared/json/NitroModalConfig.json');
|
|
5
5
|
import type { NitroModalMethods, NitroModalProps } from './NitroModal.nitro';
|
|
6
6
|
|
|
7
|
+
// Host components need their function props wrapped. Exported from here so
|
|
8
|
+
// web bundles never import `react-native-nitro-modules`.
|
|
9
|
+
export { callback } from 'react-native-nitro-modules';
|
|
10
|
+
|
|
7
11
|
export const NitroModalView = getHostComponent<
|
|
8
12
|
NitroModalProps,
|
|
9
13
|
NitroModalMethods
|
package/src/NitroModalView.tsx
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
callback as nitroCallback,
|
|
3
|
+
ReactNativeView,
|
|
4
|
+
} from 'react-native-nitro-modules';
|
|
2
5
|
import type { NitroModalMethods, NitroModalProps } from './NitroModal.nitro';
|
|
3
6
|
|
|
4
7
|
let warned = false;
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
|
-
* Platforms without
|
|
8
|
-
*
|
|
10
|
+
* Platforms without an implementation render nothing. iOS and Android use
|
|
11
|
+
* `NitroModalView.native.tsx`, web uses `NitroModalView.web.tsx`.
|
|
9
12
|
*/
|
|
10
13
|
function UnsupportedNitroModalView() {
|
|
11
14
|
if (!warned) {
|
|
12
15
|
warned = true;
|
|
13
16
|
console.warn(
|
|
14
|
-
'react-native-nitro-modal is only implemented on iOS and
|
|
17
|
+
'react-native-nitro-modal is only implemented on iOS, Android and web.'
|
|
15
18
|
);
|
|
16
19
|
}
|
|
17
20
|
return null;
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
export const callback = ((func: unknown) => func) as typeof nitroCallback;
|
|
24
|
+
|
|
20
25
|
export const NitroModalView =
|
|
21
26
|
UnsupportedNitroModalView as unknown as ReactNativeView<
|
|
22
27
|
NitroModalProps,
|