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.
Files changed (99) hide show
  1. package/README.md +65 -11
  2. package/android/src/main/java/com/margelo/nitro/nitromodal/BottomSheetPresenter.kt +335 -34
  3. package/android/src/main/java/com/margelo/nitro/nitromodal/HybridNitroModal.kt +63 -22
  4. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalConfig.kt +31 -1
  5. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalContentRoot.kt +48 -5
  6. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalPresenter.kt +63 -4
  7. package/android/src/main/java/com/margelo/nitro/nitromodal/NitroModalHostView.kt +68 -8
  8. package/ios/HybridNitroModal.swift +111 -20
  9. package/ios/ModalConfig.swift +44 -2
  10. package/ios/NitroModalHostView.swift +73 -8
  11. package/ios/SheetView.swift +575 -0
  12. package/ios/SheetViewController.swift +19 -450
  13. package/lib/module/NitroModal.js +39 -7
  14. package/lib/module/NitroModal.js.map +1 -1
  15. package/lib/module/NitroModalView.js +4 -3
  16. package/lib/module/NitroModalView.js.map +1 -1
  17. package/lib/module/NitroModalView.native.js +3 -0
  18. package/lib/module/NitroModalView.native.js.map +1 -1
  19. package/lib/module/NitroModalView.web.js +159 -0
  20. package/lib/module/NitroModalView.web.js.map +1 -0
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/module/web/AnimatedValue.js +126 -0
  23. package/lib/module/web/AnimatedValue.js.map +1 -0
  24. package/lib/module/web/ModalConfig.js +30 -0
  25. package/lib/module/web/ModalConfig.js.map +1 -0
  26. package/lib/module/web/ModalController.js +306 -0
  27. package/lib/module/web/ModalController.js.map +1 -0
  28. package/lib/module/web/ModalPresenter.js +280 -0
  29. package/lib/module/web/ModalPresenter.js.map +1 -0
  30. package/lib/module/web/PopupPresenter.js +117 -0
  31. package/lib/module/web/PopupPresenter.js.map +1 -0
  32. package/lib/module/web/SheetPresenter.js +494 -0
  33. package/lib/module/web/SheetPresenter.js.map +1 -0
  34. package/lib/module/web/dom.js +138 -0
  35. package/lib/module/web/dom.js.map +1 -0
  36. package/lib/typescript/src/NitroModal.d.ts +35 -4
  37. package/lib/typescript/src/NitroModal.d.ts.map +1 -1
  38. package/lib/typescript/src/NitroModal.nitro.d.ts +29 -2
  39. package/lib/typescript/src/NitroModal.nitro.d.ts.map +1 -1
  40. package/lib/typescript/src/NitroModalView.d.ts +2 -1
  41. package/lib/typescript/src/NitroModalView.d.ts.map +1 -1
  42. package/lib/typescript/src/NitroModalView.native.d.ts +1 -0
  43. package/lib/typescript/src/NitroModalView.native.d.ts.map +1 -1
  44. package/lib/typescript/src/NitroModalView.web.d.ts +6 -0
  45. package/lib/typescript/src/NitroModalView.web.d.ts.map +1 -0
  46. package/lib/typescript/src/index.d.ts +2 -2
  47. package/lib/typescript/src/index.d.ts.map +1 -1
  48. package/lib/typescript/src/web/AnimatedValue.d.ts +49 -0
  49. package/lib/typescript/src/web/AnimatedValue.d.ts.map +1 -0
  50. package/lib/typescript/src/web/ModalConfig.d.ts +30 -0
  51. package/lib/typescript/src/web/ModalConfig.d.ts.map +1 -0
  52. package/lib/typescript/src/web/ModalController.d.ts +70 -0
  53. package/lib/typescript/src/web/ModalController.d.ts.map +1 -0
  54. package/lib/typescript/src/web/ModalPresenter.d.ts +107 -0
  55. package/lib/typescript/src/web/ModalPresenter.d.ts.map +1 -0
  56. package/lib/typescript/src/web/PopupPresenter.d.ts +20 -0
  57. package/lib/typescript/src/web/PopupPresenter.d.ts.map +1 -0
  58. package/lib/typescript/src/web/SheetPresenter.d.ts +65 -0
  59. package/lib/typescript/src/web/SheetPresenter.d.ts.map +1 -0
  60. package/lib/typescript/src/web/dom.d.ts +42 -0
  61. package/lib/typescript/src/web/dom.d.ts.map +1 -0
  62. package/nitrogen/generated/android/c++/JHybridNitroModalSpec.cpp +60 -6
  63. package/nitrogen/generated/android/c++/JHybridNitroModalSpec.hpp +10 -2
  64. package/nitrogen/generated/android/c++/JNamedSheetDetent.hpp +64 -0
  65. package/nitrogen/generated/android/c++/JSheetDetent.cpp +26 -0
  66. package/nitrogen/generated/android/c++/JSheetDetent.hpp +42 -37
  67. package/nitrogen/generated/android/c++/views/JHybridNitroModalStateUpdater.cpp +20 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt +40 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/NamedSheetDetent.kt +25 -0
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/SheetDetent.kt +47 -10
  71. package/nitrogen/generated/android/nitromodal+autolinking.cmake +1 -0
  72. package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Bridge.hpp +53 -8
  73. package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Umbrella.hpp +4 -3
  74. package/nitrogen/generated/ios/c++/HybridNitroModalSpecSwift.hpp +32 -5
  75. package/nitrogen/generated/ios/c++/views/HybridNitroModalComponent.mm +24 -0
  76. package/nitrogen/generated/ios/swift/HybridNitroModalSpec.swift +4 -0
  77. package/nitrogen/generated/ios/swift/HybridNitroModalSpec_cxx.swift +110 -5
  78. package/nitrogen/generated/ios/swift/NamedSheetDetent.swift +48 -0
  79. package/nitrogen/generated/ios/swift/SheetDetent.swift +15 -33
  80. package/nitrogen/generated/shared/c++/HybridNitroModalSpec.cpp +8 -0
  81. package/nitrogen/generated/shared/c++/HybridNitroModalSpec.hpp +14 -5
  82. package/nitrogen/generated/shared/c++/{SheetDetent.hpp → NamedSheetDetent.hpp} +17 -17
  83. package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.cpp +9 -1
  84. package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.hpp +15 -2
  85. package/nitrogen/generated/shared/json/NitroModalConfig.json +4 -0
  86. package/package.json +3 -2
  87. package/src/NitroModal.nitro.ts +30 -2
  88. package/src/NitroModal.tsx +71 -8
  89. package/src/NitroModalView.native.tsx +4 -0
  90. package/src/NitroModalView.tsx +9 -4
  91. package/src/NitroModalView.web.tsx +180 -0
  92. package/src/index.tsx +2 -0
  93. package/src/web/AnimatedValue.ts +193 -0
  94. package/src/web/ModalConfig.ts +67 -0
  95. package/src/web/ModalController.ts +338 -0
  96. package/src/web/ModalPresenter.ts +333 -0
  97. package/src/web/PopupPresenter.ts +129 -0
  98. package/src/web/SheetPresenter.ts +647 -0
  99. 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 `SheetDetent` to properly resolve imports.
19
- namespace margelo::nitro::nitromodal { enum class SheetDetent; }
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 "SheetDetent.hpp"
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 std::vector<SheetDetent> getDetents() = 0;
71
- virtual void setDetents(const std::vector<SheetDetent>& detents) = 0;
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
- /// SheetDetent.hpp
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 (SheetDetent).
29
+ * An enum which can be represented as a JavaScript union (NamedSheetDetent).
30
30
  */
31
- enum class SheetDetent {
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++ SheetDetent <> JS SheetDetent (union)
42
+ // C++ NamedSheetDetent <> JS NamedSheetDetent (union)
43
43
  template <>
44
- struct JSIConverter<margelo::nitro::nitromodal::SheetDetent> final {
45
- static inline margelo::nitro::nitromodal::SheetDetent fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
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::SheetDetent::SMALL;
49
- case hashString("medium"): return margelo::nitro::nitromodal::SheetDetent::MEDIUM;
50
- case hashString("large"): return margelo::nitro::nitromodal::SheetDetent::LARGE;
51
- case hashString("fitContent"): return margelo::nitro::nitromodal::SheetDetent::FITCONTENT;
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 SheetDetent - invalid value!");
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::SheetDetent arg) {
56
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitromodal::NamedSheetDetent arg) {
57
57
  switch (arg) {
58
- case margelo::nitro::nitromodal::SheetDetent::SMALL: return JSIConverter<std::string>::toJSI(runtime, "small");
59
- case margelo::nitro::nitromodal::SheetDetent::MEDIUM: return JSIConverter<std::string>::toJSI(runtime, "medium");
60
- case margelo::nitro::nitromodal::SheetDetent::LARGE: return JSIConverter<std::string>::toJSI(runtime, "large");
61
- case margelo::nitro::nitromodal::SheetDetent::FITCONTENT: return JSIConverter<std::string>::toJSI(runtime, "fitContent");
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 SheetDetent to JS - invalid value: "
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
- detents(nitro::ReactProp<std::vector<SheetDetent>>::fromRawValue("NitroModal", "detents", rawProps, sourceProps.detents)),
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 "SheetDetent.hpp"
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<std::vector<SheetDetent>> detents;
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.1.5",
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",
@@ -13,13 +13,20 @@ import type {
13
13
  export type ModalMode = 'bottomSheet' | 'popup';
14
14
 
15
15
  /**
16
- * Resting heights of a `bottomSheet`.
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 SheetDetent = 'small' | 'medium' | 'large' | 'fitContent';
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 {
@@ -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
- /** Sheet heights, smallest first. Android uses at most three. @default ['fitContent'] */
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(','))] as SheetDetent[],
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={[styles.container, containerStyle, contentContainerStyle]}
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
@@ -1,22 +1,27 @@
1
- import type { ReactNativeView } from 'react-native-nitro-modules';
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 a native implementation (e.g. web) render nothing.
8
- * iOS and Android use `NitroModalView.native.tsx`.
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 Android.'
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,