react-native-nitro-modal 0.3.0-rc → 0.3.1-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 +5 -1
- package/android/src/main/java/com/margelo/nitro/nitromodal/BottomSheetPresenter.kt +73 -9
- package/android/src/main/java/com/margelo/nitro/nitromodal/HybridNitroModal.kt +4 -0
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalConfig.kt +4 -0
- package/ios/HybridNitroModal.swift +5 -1
- package/ios/ModalConfig.swift +4 -0
- package/ios/SheetView.swift +82 -10
- package/lib/module/NitroModal.js +16 -1
- package/lib/module/NitroModal.js.map +1 -1
- package/lib/module/NitroModalView.web.js +32 -2
- package/lib/module/NitroModalView.web.js.map +1 -1
- package/lib/module/web/ModalConfig.js +3 -1
- package/lib/module/web/ModalConfig.js.map +1 -1
- package/lib/module/web/ModalPresenter.js.map +1 -1
- package/lib/module/web/SheetPresenter.js +66 -7
- package/lib/module/web/SheetPresenter.js.map +1 -1
- package/lib/module/web/dom.js +3 -0
- package/lib/module/web/dom.js.map +1 -1
- package/lib/typescript/src/NitroModal.d.ts +10 -1
- package/lib/typescript/src/NitroModal.d.ts.map +1 -1
- package/lib/typescript/src/NitroModal.nitro.d.ts +8 -0
- package/lib/typescript/src/NitroModal.nitro.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.web.d.ts.map +1 -1
- package/lib/typescript/src/web/ModalConfig.d.ts +4 -0
- package/lib/typescript/src/web/ModalConfig.d.ts.map +1 -1
- package/lib/typescript/src/web/ModalPresenter.d.ts +4 -0
- package/lib/typescript/src/web/ModalPresenter.d.ts.map +1 -1
- package/lib/typescript/src/web/SheetPresenter.d.ts +12 -1
- package/lib/typescript/src/web/SheetPresenter.d.ts.map +1 -1
- package/lib/typescript/src/web/dom.d.ts +2 -0
- package/lib/typescript/src/web/dom.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.cpp +18 -0
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.hpp +4 -0
- package/nitrogen/generated/android/c++/views/JHybridNitroModalStateUpdater.cpp +10 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt +12 -0
- package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Bridge.hpp +15 -0
- package/nitrogen/generated/ios/c++/HybridNitroModalSpecSwift.hpp +14 -0
- package/nitrogen/generated/ios/c++/views/HybridNitroModalComponent.mm +12 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec.swift +2 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec_cxx.swift +48 -0
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.cpp +4 -0
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.hpp +6 -0
- package/nitrogen/generated/shared/json/NitroModalConfig.json +2 -0
- package/package.json +1 -1
- package/src/NitroModal.nitro.ts +8 -0
- package/src/NitroModal.tsx +25 -0
- package/src/NitroModalView.web.tsx +26 -1
- package/src/web/ModalConfig.ts +6 -0
- package/src/web/ModalPresenter.ts +4 -0
- package/src/web/SheetPresenter.ts +72 -5
- package/src/web/dom.ts +3 -0
|
@@ -16,6 +16,9 @@ export declare class SheetPresenter extends ModalPresenter {
|
|
|
16
16
|
private drag;
|
|
17
17
|
/** Vertical velocity of the swipe that requested the dismissal. */
|
|
18
18
|
private releaseVelocity;
|
|
19
|
+
/** The sheet rests below its lowest detent, the indicator spinning above it. */
|
|
20
|
+
private refreshing;
|
|
21
|
+
private refreshSpin;
|
|
19
22
|
/** The sheet's top edge in the viewport. */
|
|
20
23
|
private readonly top;
|
|
21
24
|
constructor(config: ModalConfig, listener: PresenterListener);
|
|
@@ -23,7 +26,7 @@ export declare class SheetPresenter extends ModalPresenter {
|
|
|
23
26
|
protected didShow(): void;
|
|
24
27
|
protected animateIn(): void;
|
|
25
28
|
protected animateOut(onEnd: () => void): void;
|
|
26
|
-
protected configDidChange(): void;
|
|
29
|
+
protected configDidChange(previous: ModalConfig): void;
|
|
27
30
|
protected viewportDidChange(): void;
|
|
28
31
|
protected contentSizeDidChange(): void;
|
|
29
32
|
protected stopAnimations(): void;
|
|
@@ -35,8 +38,16 @@ export declare class SheetPresenter extends ModalPresenter {
|
|
|
35
38
|
/** Sheet top when resting on `detents[index]`. The bottom safe area is added below the content. */
|
|
36
39
|
private restingTop;
|
|
37
40
|
private get detentTops();
|
|
41
|
+
/** Where the sheet settles on `detents[index]`: held below the lowest detent while refreshing. */
|
|
42
|
+
private settledTop;
|
|
43
|
+
private get settledTops();
|
|
38
44
|
private layout;
|
|
39
45
|
private render;
|
|
46
|
+
/**
|
|
47
|
+
* Centered in the gap a pull uncovers below the lowest detent, fading in
|
|
48
|
+
* as the pull nears the threshold.
|
|
49
|
+
*/
|
|
50
|
+
private renderRefreshIndicator;
|
|
40
51
|
/** Fully dimmed at every detent; fades out below the lowest one. */
|
|
41
52
|
private backdropAlpha;
|
|
42
53
|
private motion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SheetPresenter.d.ts","sourceRoot":"","sources":["../../../../src/web/SheetPresenter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAqB,CAAC;AAEvD,OAAO,
|
|
1
|
+
{"version":3,"file":"SheetPresenter.d.ts","sourceRoot":"","sources":["../../../../src/web/SheetPresenter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAqB,CAAC;AAEvD,OAAO,EAOL,KAAK,MAAM,EACX,KAAK,IAAI,EACV,MAAM,UAAO,CAAC;AACf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAe,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAkB,CAAC;AAmG1E,oEAAoE;AACpE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,IAAI,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAChB,IAAI,CAQN;AAcD;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,cAAc;IAChD,OAAO,CAAC,aAAa,CAAK;IAC1B,gFAAgF;IAChF,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,IAAI,CAAqB;IACjC,mEAAmE;IACnE,OAAO,CAAC,eAAe,CAAK;IAC5B,gFAAgF;IAChF,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAA0B;IAC7C,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAElB;gBAEU,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB;IAS5D,YAAY,CAAC,KAAK,EAAE,MAAM;IAO1B,SAAS,CAAC,OAAO;IAejB,SAAS,CAAC,SAAS;IAKnB,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,IAAI;IAYtC,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,WAAW;IAS/C,SAAS,CAAC,iBAAiB;IAK3B,SAAS,CAAC,oBAAoB;IAM9B,SAAS,CAAC,cAAc;IAIxB,SAAS,CAAC,QAAQ;IAelB,OAAO,KAAK,OAAO,GAIlB;IAED,OAAO,KAAK,kBAAkB,GAM7B;IAED,OAAO,KAAK,YAAY,GAIvB;IAED,OAAO,CAAC,MAAM;IAQd,mGAAmG;IACnG,OAAO,CAAC,UAAU;IAelB,OAAO,KAAK,UAAU,GAErB;IAED,kGAAkG;IAClG,OAAO,CAAC,UAAU;IAOlB,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,CAAC,MAAM;IA8Bd,OAAO,CAAC,MAAM;IAOd;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA2B9B,oEAAoE;IACpE,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,SAAS;IAwBjB,6GAA6G;IAC7G,OAAO,CAAC,KAAK;IAoBb,OAAO,CAAC,QAAQ;IAsBhB,OAAO,CAAC,QAAQ;IA4ChB,OAAO,CAAC,OAAO;IA+Cf,kFAAkF;IAClF,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,QAAQ;IAWhB,kGAAkG;IAClG,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,gBAAgB,CAiBtB;IAEF,OAAO,CAAC,eAAe,CAqBrB;IAEF,OAAO,CAAC,cAAc,CAKpB;IAIF,OAAO,CAAC,iBAAiB,CAqBvB;IAEF,OAAO,CAAC,iBAAiB,CAkBvB;IAEF,OAAO,CAAC,eAAe,CAIrB;CACH"}
|
|
@@ -10,6 +10,8 @@ export interface Insets {
|
|
|
10
10
|
}
|
|
11
11
|
export declare const ZERO_INSETS: Insets;
|
|
12
12
|
export declare const canUseDOM: boolean;
|
|
13
|
+
/** Width and height of the pull-to-refresh indicator. */
|
|
14
|
+
export declare const REFRESH_INDICATOR_SIZE = 24;
|
|
13
15
|
/** Converts a color from `processColor` (0xAARRGGBB) to CSS, scaling its alpha by `opacity`. */
|
|
14
16
|
export declare function toCSSColor(argb: number, opacity?: number): string;
|
|
15
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../../src/web/dom.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,WAAW,EAAE,MAAiD,CAAC;AAE5E,eAAO,MAAM,SAAS,SAC4C,CAAC;AAEnE,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,MAAM,CAM5D;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAmB3C;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAcrD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AASD,gGAAgG;AAChG,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,IAAI,EAAE,OAAO,GACZ,WAAW,GAAG,IAAI,CAMpB;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAWT;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAO/D;AAED,oGAAoG;AACpG,wBAAgB,iBAAiB,SAUhC;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAK9C;AAID;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../../src/web/dom.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,WAAW,EAAE,MAAiD,CAAC;AAE5E,eAAO,MAAM,SAAS,SAC4C,CAAC;AAEnE,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,MAAM,CAM5D;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAmB3C;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAcrD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AASD,gGAAgG;AAChG,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,IAAI,EAAE,OAAO,GACZ,WAAW,GAAG,IAAI,CAMpB;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAWT;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAO/D;AAED,oGAAoG;AACpG,wBAAgB,iBAAiB,SAUhC;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAK9C;AAID;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
|
|
@@ -244,6 +244,24 @@ namespace margelo::nitro::nitromodal {
|
|
|
244
244
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* pullToRefreshEnabled */)>("setPullToRefreshEnabled");
|
|
245
245
|
method(_javaPart, pullToRefreshEnabled);
|
|
246
246
|
}
|
|
247
|
+
std::optional<bool> JHybridNitroModalSpec::getRefreshing() {
|
|
248
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JBoolean>()>("getRefreshing");
|
|
249
|
+
auto __result = method(_javaPart);
|
|
250
|
+
return __result != nullptr ? std::make_optional(static_cast<bool>(__result->value())) : std::nullopt;
|
|
251
|
+
}
|
|
252
|
+
void JHybridNitroModalSpec::setRefreshing(std::optional<bool> refreshing) {
|
|
253
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JBoolean> /* refreshing */)>("setRefreshing");
|
|
254
|
+
method(_javaPart, refreshing.has_value() ? jni::JBoolean::valueOf(refreshing.value()) : nullptr);
|
|
255
|
+
}
|
|
256
|
+
std::optional<double> JHybridNitroModalSpec::getRefreshIndicatorColor() {
|
|
257
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getRefreshIndicatorColor");
|
|
258
|
+
auto __result = method(_javaPart);
|
|
259
|
+
return __result != nullptr ? std::make_optional(__result->value()) : std::nullopt;
|
|
260
|
+
}
|
|
261
|
+
void JHybridNitroModalSpec::setRefreshIndicatorColor(std::optional<double> refreshIndicatorColor) {
|
|
262
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JDouble> /* refreshIndicatorColor */)>("setRefreshIndicatorColor");
|
|
263
|
+
method(_javaPart, refreshIndicatorColor.has_value() ? jni::JDouble::valueOf(refreshIndicatorColor.value()) : nullptr);
|
|
264
|
+
}
|
|
247
265
|
std::optional<std::function<void()>> JHybridNitroModalSpec::getOnPresent() {
|
|
248
266
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_void::javaobject>()>("getOnPresent_cxx");
|
|
249
267
|
auto __result = method(_javaPart);
|
|
@@ -84,6 +84,10 @@ namespace margelo::nitro::nitromodal {
|
|
|
84
84
|
void setPopupAnimation(PopupAnimation popupAnimation) override;
|
|
85
85
|
bool getPullToRefreshEnabled() override;
|
|
86
86
|
void setPullToRefreshEnabled(bool pullToRefreshEnabled) override;
|
|
87
|
+
std::optional<bool> getRefreshing() override;
|
|
88
|
+
void setRefreshing(std::optional<bool> refreshing) override;
|
|
89
|
+
std::optional<double> getRefreshIndicatorColor() override;
|
|
90
|
+
void setRefreshIndicatorColor(std::optional<double> refreshIndicatorColor) override;
|
|
87
91
|
std::optional<std::function<void()>> getOnPresent() override;
|
|
88
92
|
void setOnPresent(const std::optional<std::function<void()>>& onPresent) override;
|
|
89
93
|
std::optional<std::function<void(DismissReason /* reason */)>> getOnDismiss() override;
|
|
@@ -138,6 +138,16 @@ void JHybridNitroModalStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
|
|
|
138
138
|
: !newProps->pullToRefreshEnabled.hasSameValue(oldProps->pullToRefreshEnabled)) {
|
|
139
139
|
hybridView->setPullToRefreshEnabled(newProps->pullToRefreshEnabled.get());
|
|
140
140
|
}
|
|
141
|
+
if (oldProps == nullptr
|
|
142
|
+
? newProps->refreshing.isProvided()
|
|
143
|
+
: !newProps->refreshing.hasSameValue(oldProps->refreshing)) {
|
|
144
|
+
hybridView->setRefreshing(newProps->refreshing.get());
|
|
145
|
+
}
|
|
146
|
+
if (oldProps == nullptr
|
|
147
|
+
? newProps->refreshIndicatorColor.isProvided()
|
|
148
|
+
: !newProps->refreshIndicatorColor.hasSameValue(oldProps->refreshIndicatorColor)) {
|
|
149
|
+
hybridView->setRefreshIndicatorColor(newProps->refreshIndicatorColor.get());
|
|
150
|
+
}
|
|
141
151
|
if (oldProps == nullptr
|
|
142
152
|
? newProps->onPresent.isProvided()
|
|
143
153
|
: !newProps->onPresent.hasSameValue(oldProps->onPresent)) {
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt
CHANGED
|
@@ -129,6 +129,18 @@ abstract class HybridNitroModalSpec: HybridView() {
|
|
|
129
129
|
@set:Keep
|
|
130
130
|
abstract var pullToRefreshEnabled: Boolean
|
|
131
131
|
|
|
132
|
+
@get:DoNotStrip
|
|
133
|
+
@get:Keep
|
|
134
|
+
@set:DoNotStrip
|
|
135
|
+
@set:Keep
|
|
136
|
+
abstract var refreshing: Boolean?
|
|
137
|
+
|
|
138
|
+
@get:DoNotStrip
|
|
139
|
+
@get:Keep
|
|
140
|
+
@set:DoNotStrip
|
|
141
|
+
@set:Keep
|
|
142
|
+
abstract var refreshIndicatorColor: Double?
|
|
143
|
+
|
|
132
144
|
abstract var onPresent: (() -> Unit)?
|
|
133
145
|
|
|
134
146
|
private var onPresent_cxx: Func_void?
|
|
@@ -95,6 +95,21 @@ namespace margelo::nitro::nitromodal::bridge::swift {
|
|
|
95
95
|
return optional.value();
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
// pragma MARK: std::optional<bool>
|
|
99
|
+
/**
|
|
100
|
+
* Specialized version of `std::optional<bool>`.
|
|
101
|
+
*/
|
|
102
|
+
using std__optional_bool_ = std::optional<bool>;
|
|
103
|
+
inline std::optional<bool> create_std__optional_bool_(const bool& value) noexcept {
|
|
104
|
+
return std::optional<bool>(value);
|
|
105
|
+
}
|
|
106
|
+
inline bool has_value_std__optional_bool_(const std::optional<bool>& optional) noexcept {
|
|
107
|
+
return optional.has_value();
|
|
108
|
+
}
|
|
109
|
+
inline bool get_std__optional_bool_(const std::optional<bool>& optional) noexcept {
|
|
110
|
+
return optional.value();
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
// pragma MARK: std::function<void()>
|
|
99
114
|
/**
|
|
100
115
|
* Specialized version of `std::function<void()>`.
|
|
@@ -189,6 +189,20 @@ namespace margelo::nitro::nitromodal {
|
|
|
189
189
|
inline void setPullToRefreshEnabled(bool pullToRefreshEnabled) noexcept override {
|
|
190
190
|
_swiftPart.setPullToRefreshEnabled(std::forward<decltype(pullToRefreshEnabled)>(pullToRefreshEnabled));
|
|
191
191
|
}
|
|
192
|
+
inline std::optional<bool> getRefreshing() noexcept override {
|
|
193
|
+
auto __result = _swiftPart.getRefreshing();
|
|
194
|
+
return __result;
|
|
195
|
+
}
|
|
196
|
+
inline void setRefreshing(std::optional<bool> refreshing) noexcept override {
|
|
197
|
+
_swiftPart.setRefreshing(refreshing);
|
|
198
|
+
}
|
|
199
|
+
inline std::optional<double> getRefreshIndicatorColor() noexcept override {
|
|
200
|
+
auto __result = _swiftPart.getRefreshIndicatorColor();
|
|
201
|
+
return __result;
|
|
202
|
+
}
|
|
203
|
+
inline void setRefreshIndicatorColor(std::optional<double> refreshIndicatorColor) noexcept override {
|
|
204
|
+
_swiftPart.setRefreshIndicatorColor(refreshIndicatorColor);
|
|
205
|
+
}
|
|
192
206
|
inline std::optional<std::function<void()>> getOnPresent() noexcept override {
|
|
193
207
|
auto __result = _swiftPart.getOnPresent();
|
|
194
208
|
return __result;
|
|
@@ -200,6 +200,18 @@ using namespace margelo::nitro::nitromodal::views;
|
|
|
200
200
|
: !newViewProps.pullToRefreshEnabled.hasSameValue(oldViewProps->pullToRefreshEnabled)) {
|
|
201
201
|
swiftPart.setPullToRefreshEnabled(newViewProps.pullToRefreshEnabled.get());
|
|
202
202
|
}
|
|
203
|
+
// refreshing: optional
|
|
204
|
+
if (oldViewProps == nullptr
|
|
205
|
+
? newViewProps.refreshing.isProvided()
|
|
206
|
+
: !newViewProps.refreshing.hasSameValue(oldViewProps->refreshing)) {
|
|
207
|
+
swiftPart.setRefreshing(newViewProps.refreshing.get());
|
|
208
|
+
}
|
|
209
|
+
// refreshIndicatorColor: optional
|
|
210
|
+
if (oldViewProps == nullptr
|
|
211
|
+
? newViewProps.refreshIndicatorColor.isProvided()
|
|
212
|
+
: !newViewProps.refreshIndicatorColor.hasSameValue(oldViewProps->refreshIndicatorColor)) {
|
|
213
|
+
swiftPart.setRefreshIndicatorColor(newViewProps.refreshIndicatorColor.get());
|
|
214
|
+
}
|
|
203
215
|
// onPresent: optional
|
|
204
216
|
if (oldViewProps == nullptr
|
|
205
217
|
? newViewProps.onPresent.isProvided()
|
|
@@ -27,6 +27,8 @@ public protocol HybridNitroModalSpec_protocol: HybridObject, HybridView {
|
|
|
27
27
|
var keyboardBehavior: KeyboardBehavior { get set }
|
|
28
28
|
var popupAnimation: PopupAnimation { get set }
|
|
29
29
|
var pullToRefreshEnabled: Bool { get set }
|
|
30
|
+
var refreshing: Bool? { get set }
|
|
31
|
+
var refreshIndicatorColor: Double? { get set }
|
|
30
32
|
var onPresent: (() -> Void)? { get set }
|
|
31
33
|
var onDismiss: ((_ reason: DismissReason) -> Void)? { get set }
|
|
32
34
|
var onDetentChange: ((_ index: Double) -> Void)? { get set }
|
|
@@ -346,6 +346,54 @@ open class HybridNitroModalSpec_cxx {
|
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
public final var refreshing: bridge.std__optional_bool_ {
|
|
350
|
+
@inline(__always)
|
|
351
|
+
get {
|
|
352
|
+
return { () -> bridge.std__optional_bool_ in
|
|
353
|
+
if let __unwrappedValue = self.__implementation.refreshing {
|
|
354
|
+
return bridge.create_std__optional_bool_(__unwrappedValue)
|
|
355
|
+
} else {
|
|
356
|
+
return .init()
|
|
357
|
+
}
|
|
358
|
+
}()
|
|
359
|
+
}
|
|
360
|
+
@inline(__always)
|
|
361
|
+
set {
|
|
362
|
+
self.__implementation.refreshing = { () -> Bool? in
|
|
363
|
+
if bridge.has_value_std__optional_bool_(newValue) {
|
|
364
|
+
let __unwrapped = bridge.get_std__optional_bool_(newValue)
|
|
365
|
+
return __unwrapped
|
|
366
|
+
} else {
|
|
367
|
+
return nil
|
|
368
|
+
}
|
|
369
|
+
}()
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
public final var refreshIndicatorColor: bridge.std__optional_double_ {
|
|
374
|
+
@inline(__always)
|
|
375
|
+
get {
|
|
376
|
+
return { () -> bridge.std__optional_double_ in
|
|
377
|
+
if let __unwrappedValue = self.__implementation.refreshIndicatorColor {
|
|
378
|
+
return bridge.create_std__optional_double_(__unwrappedValue)
|
|
379
|
+
} else {
|
|
380
|
+
return .init()
|
|
381
|
+
}
|
|
382
|
+
}()
|
|
383
|
+
}
|
|
384
|
+
@inline(__always)
|
|
385
|
+
set {
|
|
386
|
+
self.__implementation.refreshIndicatorColor = { () -> Double? in
|
|
387
|
+
if bridge.has_value_std__optional_double_(newValue) {
|
|
388
|
+
let __unwrapped = bridge.get_std__optional_double_(newValue)
|
|
389
|
+
return __unwrapped
|
|
390
|
+
} else {
|
|
391
|
+
return nil
|
|
392
|
+
}
|
|
393
|
+
}()
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
349
397
|
public final var onPresent: bridge.std__optional_std__function_void____ {
|
|
350
398
|
@inline(__always)
|
|
351
399
|
get {
|
|
@@ -48,6 +48,10 @@ namespace margelo::nitro::nitromodal {
|
|
|
48
48
|
prototype.registerHybridSetter("popupAnimation", &HybridNitroModalSpec::setPopupAnimation);
|
|
49
49
|
prototype.registerHybridGetter("pullToRefreshEnabled", &HybridNitroModalSpec::getPullToRefreshEnabled);
|
|
50
50
|
prototype.registerHybridSetter("pullToRefreshEnabled", &HybridNitroModalSpec::setPullToRefreshEnabled);
|
|
51
|
+
prototype.registerHybridGetter("refreshing", &HybridNitroModalSpec::getRefreshing);
|
|
52
|
+
prototype.registerHybridSetter("refreshing", &HybridNitroModalSpec::setRefreshing);
|
|
53
|
+
prototype.registerHybridGetter("refreshIndicatorColor", &HybridNitroModalSpec::getRefreshIndicatorColor);
|
|
54
|
+
prototype.registerHybridSetter("refreshIndicatorColor", &HybridNitroModalSpec::setRefreshIndicatorColor);
|
|
51
55
|
prototype.registerHybridGetter("onPresent", &HybridNitroModalSpec::getOnPresent);
|
|
52
56
|
prototype.registerHybridSetter("onPresent", &HybridNitroModalSpec::setOnPresent);
|
|
53
57
|
prototype.registerHybridGetter("onDismiss", &HybridNitroModalSpec::getOnDismiss);
|
|
@@ -98,6 +98,10 @@ namespace margelo::nitro::nitromodal {
|
|
|
98
98
|
virtual void setPopupAnimation(PopupAnimation popupAnimation) = 0;
|
|
99
99
|
virtual bool getPullToRefreshEnabled() = 0;
|
|
100
100
|
virtual void setPullToRefreshEnabled(bool pullToRefreshEnabled) = 0;
|
|
101
|
+
virtual std::optional<bool> getRefreshing() = 0;
|
|
102
|
+
virtual void setRefreshing(std::optional<bool> refreshing) = 0;
|
|
103
|
+
virtual std::optional<double> getRefreshIndicatorColor() = 0;
|
|
104
|
+
virtual void setRefreshIndicatorColor(std::optional<double> refreshIndicatorColor) = 0;
|
|
101
105
|
virtual std::optional<std::function<void()>> getOnPresent() = 0;
|
|
102
106
|
virtual void setOnPresent(const std::optional<std::function<void()>>& onPresent) = 0;
|
|
103
107
|
virtual std::optional<std::function<void(DismissReason /* reason */)>> getOnDismiss() = 0;
|
|
@@ -37,6 +37,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
37
37
|
keyboardBehavior(nitro::ReactProp<KeyboardBehavior>::fromRawValue("NitroModal", "keyboardBehavior", rawProps, sourceProps.keyboardBehavior)),
|
|
38
38
|
popupAnimation(nitro::ReactProp<PopupAnimation>::fromRawValue("NitroModal", "popupAnimation", rawProps, sourceProps.popupAnimation)),
|
|
39
39
|
pullToRefreshEnabled(nitro::ReactProp<bool>::fromRawValue("NitroModal", "pullToRefreshEnabled", rawProps, sourceProps.pullToRefreshEnabled)),
|
|
40
|
+
refreshing(nitro::ReactProp<std::optional<bool>>::fromRawValue("NitroModal", "refreshing", rawProps, sourceProps.refreshing)),
|
|
41
|
+
refreshIndicatorColor(nitro::ReactProp<std::optional<double>>::fromRawValue("NitroModal", "refreshIndicatorColor", rawProps, sourceProps.refreshIndicatorColor)),
|
|
40
42
|
onPresent(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("NitroModal", "onPresent", rawProps, sourceProps.onPresent)),
|
|
41
43
|
onDismiss(nitro::ReactProp<std::optional<std::function<void(DismissReason /* reason */)>>>::fromRawValue("NitroModal", "onDismiss", rawProps, sourceProps.onDismiss)),
|
|
42
44
|
onDetentChange(nitro::ReactProp<std::optional<std::function<void(double /* index */)>>>::fromRawValue("NitroModal", "onDetentChange", rawProps, sourceProps.onDetentChange)),
|
|
@@ -66,6 +68,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
66
68
|
case hashString("keyboardBehavior"): return true;
|
|
67
69
|
case hashString("popupAnimation"): return true;
|
|
68
70
|
case hashString("pullToRefreshEnabled"): return true;
|
|
71
|
+
case hashString("refreshing"): return true;
|
|
72
|
+
case hashString("refreshIndicatorColor"): return true;
|
|
69
73
|
case hashString("onPresent"): return true;
|
|
70
74
|
case hashString("onDismiss"): return true;
|
|
71
75
|
case hashString("onDetentChange"): return true;
|
|
@@ -67,6 +67,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
67
67
|
nitro::ReactProp<KeyboardBehavior> keyboardBehavior;
|
|
68
68
|
nitro::ReactProp<PopupAnimation> popupAnimation;
|
|
69
69
|
nitro::ReactProp<bool> pullToRefreshEnabled;
|
|
70
|
+
nitro::ReactProp<std::optional<bool>> refreshing;
|
|
71
|
+
nitro::ReactProp<std::optional<double>> refreshIndicatorColor;
|
|
70
72
|
nitro::ReactProp<std::optional<std::function<void()>>> onPresent;
|
|
71
73
|
nitro::ReactProp<std::optional<std::function<void(DismissReason /* reason */)>>> onDismiss;
|
|
72
74
|
nitro::ReactProp<std::optional<std::function<void(double /* index */)>>> onDetentChange;
|
|
@@ -96,6 +98,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
96
98
|
keyboardBehavior.hasSameValue(other.keyboardBehavior) &&
|
|
97
99
|
popupAnimation.hasSameValue(other.popupAnimation) &&
|
|
98
100
|
pullToRefreshEnabled.hasSameValue(other.pullToRefreshEnabled) &&
|
|
101
|
+
refreshing.hasSameValue(other.refreshing) &&
|
|
102
|
+
refreshIndicatorColor.hasSameValue(other.refreshIndicatorColor) &&
|
|
99
103
|
onPresent.hasSameValue(other.onPresent) &&
|
|
100
104
|
onDismiss.hasSameValue(other.onDismiss) &&
|
|
101
105
|
onDetentChange.hasSameValue(other.onDetentChange) &&
|
|
@@ -126,6 +130,8 @@ namespace margelo::nitro::nitromodal::views {
|
|
|
126
130
|
keyboardBehavior.isProvided() ||
|
|
127
131
|
popupAnimation.isProvided() ||
|
|
128
132
|
pullToRefreshEnabled.isProvided() ||
|
|
133
|
+
refreshing.isProvided() ||
|
|
134
|
+
refreshIndicatorColor.isProvided() ||
|
|
129
135
|
onPresent.isProvided() ||
|
|
130
136
|
onDismiss.isProvided() ||
|
|
131
137
|
onDetentChange.isProvided() ||
|
package/package.json
CHANGED
package/src/NitroModal.nitro.ts
CHANGED
|
@@ -86,6 +86,14 @@ export interface NitroModalProps extends HybridViewProps {
|
|
|
86
86
|
* `onPullToRefresh`. Needs `dismissOnSwipe` off (always the case inline).
|
|
87
87
|
*/
|
|
88
88
|
pullToRefreshEnabled: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* A refresh is in progress: the sheet rests pulled down below its lowest
|
|
91
|
+
* detent with an activity indicator above it. Native starts refreshing on
|
|
92
|
+
* its own when a pull is released. `undefined` shows no indicator.
|
|
93
|
+
*/
|
|
94
|
+
refreshing?: boolean;
|
|
95
|
+
/** Refresh indicator color as a processed ARGB color. Omit for the platform default. */
|
|
96
|
+
refreshIndicatorColor?: number;
|
|
89
97
|
|
|
90
98
|
/** The present transition finished. */
|
|
91
99
|
onPresent?: () => void;
|
package/src/NitroModal.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
useEffect,
|
|
2
3
|
useImperativeHandle,
|
|
3
4
|
useLayoutEffect,
|
|
4
5
|
useMemo,
|
|
@@ -111,6 +112,15 @@ export interface NitroModalProps {
|
|
|
111
112
|
* sheet resting on its lowest detent.
|
|
112
113
|
*/
|
|
113
114
|
onPullToRefresh?: () => void;
|
|
115
|
+
/**
|
|
116
|
+
* Whether a refresh is in progress, like `RefreshControl`'s `refreshing`.
|
|
117
|
+
* While true, the sheet stays pulled down below its lowest detent with an
|
|
118
|
+
* activity indicator above it. Set it to `true` in `onPullToRefresh` and
|
|
119
|
+
* back to `false` when done. Leave undefined to show no indicator.
|
|
120
|
+
*/
|
|
121
|
+
refreshing?: boolean;
|
|
122
|
+
/** Color of the refresh indicator. Defaults to the platform style. */
|
|
123
|
+
refreshIndicatorColor?: ColorValue;
|
|
114
124
|
children?: ReactNode;
|
|
115
125
|
testID?: string;
|
|
116
126
|
ref?: Ref<NitroModalRef>;
|
|
@@ -158,6 +168,8 @@ export function NitroModal({
|
|
|
158
168
|
onBackdropPress,
|
|
159
169
|
onBackButtonPress,
|
|
160
170
|
onPullToRefresh,
|
|
171
|
+
refreshing,
|
|
172
|
+
refreshIndicatorColor,
|
|
161
173
|
children,
|
|
162
174
|
testID,
|
|
163
175
|
ref,
|
|
@@ -182,12 +194,21 @@ export function NitroModal({
|
|
|
182
194
|
// is laid out there so `measure()`, which presses rely on, matches the
|
|
183
195
|
// screen; native cancels the offset out on screen.
|
|
184
196
|
const [restingTop, setRestingTop] = useState(0);
|
|
197
|
+
// Native starts refreshing as soon as a pull is released. Reporting `true`
|
|
198
|
+
// for the render that follows, then `refreshing` again, stops it if the
|
|
199
|
+
// handler didn't start a refresh (unchanged props never reach native).
|
|
200
|
+
const isRefreshControlled = refreshing !== undefined;
|
|
201
|
+
const [pullPending, setPullPending] = useState(false);
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (pullPending) setPullPending(false);
|
|
204
|
+
}, [pullPending]);
|
|
185
205
|
const hybridRef = useRef<NitroModalHybridView | null>(null);
|
|
186
206
|
|
|
187
207
|
// Native callbacks are created once (stable props, no native updates on
|
|
188
208
|
// re-render) and read the latest handlers from this ref.
|
|
189
209
|
const latest = useRef({
|
|
190
210
|
isControlled,
|
|
211
|
+
isRefreshControlled,
|
|
191
212
|
onPresent,
|
|
192
213
|
onDismiss,
|
|
193
214
|
onDetentChange,
|
|
@@ -198,6 +219,7 @@ export function NitroModal({
|
|
|
198
219
|
useLayoutEffect(() => {
|
|
199
220
|
latest.current = {
|
|
200
221
|
isControlled,
|
|
222
|
+
isRefreshControlled,
|
|
201
223
|
onPresent,
|
|
202
224
|
onDismiss,
|
|
203
225
|
onDetentChange,
|
|
@@ -231,6 +253,7 @@ export function NitroModal({
|
|
|
231
253
|
latest.current.onBackButtonPress?.();
|
|
232
254
|
}),
|
|
233
255
|
onPullToRefresh: callback(() => {
|
|
256
|
+
if (latest.current.isRefreshControlled) setPullPending(true);
|
|
234
257
|
latest.current.onPullToRefresh?.();
|
|
235
258
|
}),
|
|
236
259
|
onRestingTopChange: callback((top: number) => {
|
|
@@ -315,6 +338,8 @@ export function NitroModal({
|
|
|
315
338
|
keyboardBehavior={keyboardBehavior}
|
|
316
339
|
popupAnimation={popupAnimation}
|
|
317
340
|
pullToRefreshEnabled={onPullToRefresh != null}
|
|
341
|
+
refreshing={isRefreshControlled ? refreshing || pullPending : undefined}
|
|
342
|
+
refreshIndicatorColor={toNativeColor(refreshIndicatorColor)}
|
|
318
343
|
{...nativeCallbacks}
|
|
319
344
|
>
|
|
320
345
|
{renderContent ? (
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { Modal, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
12
12
|
import type { ReactNativeView } from 'react-native-nitro-modules';
|
|
13
13
|
import type { NitroModalMethods, NitroModalProps } from './NitroModal.nitro';
|
|
14
|
-
import { clipOverflow } from './web/dom';
|
|
14
|
+
import { clipOverflow, REFRESH_INDICATOR_SIZE } from './web/dom';
|
|
15
15
|
import { ModalController } from './web/ModalController';
|
|
16
16
|
|
|
17
17
|
interface WebNitroModalViewProps extends NitroModalProps {
|
|
@@ -45,6 +45,8 @@ function WebNitroModalView(props: WebNitroModalViewProps) {
|
|
|
45
45
|
const surface = useRef<HTMLDivElement>(null);
|
|
46
46
|
const content = useRef<HTMLDivElement>(null);
|
|
47
47
|
const grabber = useRef<HTMLDivElement>(null);
|
|
48
|
+
const refreshIndicator = useRef<HTMLDivElement>(null);
|
|
49
|
+
const refreshSpinner = useRef<HTMLDivElement>(null);
|
|
48
50
|
|
|
49
51
|
useLayoutEffect(() => {
|
|
50
52
|
controller.attach();
|
|
@@ -67,6 +69,8 @@ function WebNitroModalView(props: WebNitroModalViewProps) {
|
|
|
67
69
|
surface: surface.current!,
|
|
68
70
|
content: content.current!,
|
|
69
71
|
grabber: grabber.current!,
|
|
72
|
+
refreshIndicator: refreshIndicator.current!,
|
|
73
|
+
refreshSpinner: refreshSpinner.current!,
|
|
70
74
|
});
|
|
71
75
|
return () => controller.elementsWillUnmount();
|
|
72
76
|
}, [controller, mounted]);
|
|
@@ -98,6 +102,9 @@ function WebNitroModalView(props: WebNitroModalViewProps) {
|
|
|
98
102
|
}
|
|
99
103
|
>
|
|
100
104
|
<div ref={backdrop} aria-hidden style={styles.backdrop} />
|
|
105
|
+
<div ref={refreshIndicator} aria-hidden style={styles.refreshIndicator}>
|
|
106
|
+
<div ref={refreshSpinner} style={styles.refreshSpinner} />
|
|
107
|
+
</div>
|
|
101
108
|
<div ref={surface} style={styles.surface}>
|
|
102
109
|
<div ref={content} style={styles.content}>
|
|
103
110
|
{children}
|
|
@@ -172,6 +179,24 @@ const styles = {
|
|
|
172
179
|
backgroundColor: 'rgba(127, 127, 127, 0.4)',
|
|
173
180
|
pointerEvents: 'none',
|
|
174
181
|
},
|
|
182
|
+
refreshIndicator: {
|
|
183
|
+
position: 'absolute',
|
|
184
|
+
left: 0,
|
|
185
|
+
top: 0,
|
|
186
|
+
width: REFRESH_INDICATOR_SIZE,
|
|
187
|
+
height: REFRESH_INDICATOR_SIZE,
|
|
188
|
+
opacity: 0,
|
|
189
|
+
pointerEvents: 'none',
|
|
190
|
+
},
|
|
191
|
+
// Colored through `color` by the presenter.
|
|
192
|
+
refreshSpinner: {
|
|
193
|
+
width: '100%',
|
|
194
|
+
height: '100%',
|
|
195
|
+
boxSizing: 'border-box',
|
|
196
|
+
borderRadius: '50%',
|
|
197
|
+
border: '2.5px solid currentColor',
|
|
198
|
+
borderTopColor: 'transparent',
|
|
199
|
+
},
|
|
175
200
|
} satisfies Record<string, CSSProperties>;
|
|
176
201
|
|
|
177
202
|
export const NitroModalView = WebNitroModalView as unknown as ReactNativeView<
|
package/src/web/ModalConfig.ts
CHANGED
|
@@ -31,6 +31,10 @@ export interface ModalConfig {
|
|
|
31
31
|
keyboardBehavior: KeyboardBehavior;
|
|
32
32
|
popupAnimation: PopupAnimation;
|
|
33
33
|
pullToRefreshEnabled: boolean;
|
|
34
|
+
/** A refresh is in progress; `null` shows no refresh indicator. */
|
|
35
|
+
refreshing: boolean | null;
|
|
36
|
+
/** 0xAARRGGBB; `null` uses the default. */
|
|
37
|
+
refreshIndicatorColor: number | null;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export function makeConfig(props: NitroModalProps): ModalConfig {
|
|
@@ -55,6 +59,8 @@ export function makeConfig(props: NitroModalProps): ModalConfig {
|
|
|
55
59
|
keyboardBehavior: props.keyboardBehavior,
|
|
56
60
|
popupAnimation: props.popupAnimation,
|
|
57
61
|
pullToRefreshEnabled: props.pullToRefreshEnabled,
|
|
62
|
+
refreshing: props.refreshing ?? null,
|
|
63
|
+
refreshIndicatorColor: props.refreshIndicatorColor ?? null,
|
|
58
64
|
};
|
|
59
65
|
}
|
|
60
66
|
|
|
@@ -23,6 +23,10 @@ export interface ModalElements {
|
|
|
23
23
|
/** Hosts the React content. */
|
|
24
24
|
content: HTMLElement;
|
|
25
25
|
grabber: HTMLElement;
|
|
26
|
+
/** Behind the sheet, uncovered as it's pulled down to refresh. */
|
|
27
|
+
refreshIndicator: HTMLElement;
|
|
28
|
+
/** The spinning ring inside `refreshIndicator`. */
|
|
29
|
+
refreshSpinner: HTMLElement;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface PresenterListener {
|