@ezoic/react-native-sdk 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,7 @@ Pod::Spec.new do |s|
20
20
 
21
21
  # Native Ezoic Ads SDK (vends the `EzoicAdsSDKBinary` module). Brings in
22
22
  # PrebidMobile + Google-Mobile-Ads-SDK transitively.
23
- s.dependency "EzoicAdsSDK", "~> 1.7"
23
+ s.dependency "EzoicAdsSDK", "~> 1.9"
24
24
  # The native-ad host imports GoogleMobileAds directly (NativeAdView,
25
25
  # MediaView, NativeAd). Pin GMA 12 so the module is on the compile path.
26
26
  s.dependency "Google-Mobile-Ads-SDK", "~> 12.0"
package/README.md CHANGED
@@ -52,11 +52,15 @@ EzoicAds.setSubjectToCOPPA(false);
52
52
  // Track a pageview.
53
53
  const tracked = await EzoicAds.trackPageview();
54
54
 
55
- // Render a banner.
55
+ // Render a banner. A hard-coded height is optional: on no-fill the view
56
+ // collapses to height 0 (default), and `onSizeChange` reports the creative
57
+ // size (or `{ width: 0, height: 0 }` when collapsed).
56
58
  <EzoicBannerView
57
59
  adUnitIdentifier="123456"
58
60
  size="300x250"
59
- style={{ width: 300, height: 250 }}
61
+ style={{ width: 300 }}
62
+ collapseOnNoFill
63
+ onSizeChange={({ width, height }) => console.log('size', width, height)}
60
64
  onLoad={() => console.log('loaded')}
61
65
  onError={(e) => console.log('error', e.message, e.code)}
62
66
  onImpression={() => console.log('impression')}
@@ -68,6 +72,9 @@ const tracked = await EzoicAds.trackPageview();
68
72
 
69
73
  `adUnitIdentifier` is a string coerced to a native integer. `size` is a `"WxH"`
70
74
  string or comma-separated list (e.g. `"300x250"`, `"300x250,320x50"`).
75
+ `collapseOnNoFill` (default `true`) collapses the view to height 0 when a load
76
+ fails and nothing is displayed. `onSizeChange` receives `{ width, height }` in
77
+ dp/pt after a fill, or `{ width: 0, height: 0 }` on collapse.
71
78
 
72
79
  ### Native ads
73
80
 
@@ -96,7 +103,8 @@ import { EzoicAds, EzoicNativeAdView } from '@ezoic/react-native-sdk';
96
103
  `EzoicOutstreamAdView` loads and renders a self-contained outstream video ad.
97
104
  Like the native ad it has no `size` prop — size it with `style` and the native
98
105
  view lays the player out inside those bounds. It is view-managed: mounting the
99
- component loads the ad, unmounting destroys it.
106
+ component loads the ad, unmounting destroys it. Same `collapseOnNoFill`
107
+ (default `true`) and `onSizeChange` props as the banner.
100
108
 
101
109
  ```tsx
102
110
  import { EzoicAds, EzoicOutstreamAdView } from '@ezoic/react-native-sdk';
@@ -104,6 +112,8 @@ import { EzoicAds, EzoicOutstreamAdView } from '@ezoic/react-native-sdk';
104
112
  <EzoicOutstreamAdView
105
113
  adUnitIdentifier="123456"
106
114
  style={{ width: '100%', height: 250 }}
115
+ collapseOnNoFill
116
+ onSizeChange={({ width, height }) => console.log('size', width, height)}
107
117
  onLoad={() => console.log('loaded')}
108
118
  onError={(e) => console.log('error', e.message, e.code)}
109
119
  onImpression={() => console.log('impression')}
@@ -152,9 +162,9 @@ resolves. `contentUrl` and `revenueUsd` are optional.
152
162
  - `EzoicAds.setGPPConsent(gppString?, sectionIds?)` → `void`
153
163
  - `EzoicAds.setSubjectToCOPPA(value)` → `void`
154
164
  - `EzoicAds.trackPageview()` → `Promise<boolean>`
155
- - `<EzoicBannerView adUnitIdentifier size onLoad onError onImpression onClick onOpen onClose />`
165
+ - `<EzoicBannerView adUnitIdentifier size collapseOnNoFill onSizeChange onLoad onError onImpression onClick onOpen onClose />`
156
166
  - `<EzoicNativeAdView adUnitIdentifier onLoad onError onImpression onClick onOpen onClose />`
157
- - `<EzoicOutstreamAdView adUnitIdentifier onLoad onError onImpression onClick onOpen onClose />`
167
+ - `<EzoicOutstreamAdView adUnitIdentifier collapseOnNoFill onSizeChange onLoad onError onImpression onClick onOpen onClose />`
158
168
  - `new EzoicInstreamAd(adUnitIdentifier)`
159
169
  - `.load({ contentUrl? })` → `Promise<string>` (GAM VAST ad-tag URL)
160
170
  - `.getNextAdTagUrl()` → `Promise<string | null>`
@@ -68,7 +68,7 @@ dependencies {
68
68
  // Native Ezoic Ads SDK (resolved from Maven Central). Brings in Google Mobile
69
69
  // Ads + Prebid transitively. Requires mavenCentral() + google() in the
70
70
  // consuming app's repositories (the RN template provides both).
71
- implementation "com.ezoic.sdk:ezoic-ads-sdk:1.7.0"
71
+ implementation "com.ezoic.sdk:ezoic-ads-sdk:1.9.0"
72
72
 
73
73
  // The native-ad wrapper references GMA's NativeAdView/MediaView/NativeAd
74
74
  // types at compile time. The Ezoic SDK POM scopes Google Mobile Ads at
@@ -1,5 +1,7 @@
1
1
  package com.ezoic.reactnative
2
2
 
3
+ import android.content.Context
4
+ import android.view.View
3
5
  import android.view.ViewGroup
4
6
  import android.widget.FrameLayout
5
7
  import com.facebook.react.bridge.Arguments
@@ -16,36 +18,44 @@ import com.ezoic.ads.sdk.core.EzoicError
16
18
 
17
19
  @ReactModule(name = EzoicBannerViewManager.NAME)
18
20
  class EzoicBannerViewManager(private val ctx: ReactApplicationContext) :
19
- SimpleViewManager<FrameLayout>() {
21
+ SimpleViewManager<EzoicBannerViewManager.BannerContainer>() {
20
22
 
21
23
  override fun getName() = NAME
22
24
 
23
- override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
24
- val container = FrameLayout(reactContext)
25
+ override fun createViewInstance(reactContext: ThemedReactContext): BannerContainer {
26
+ val container = BannerContainer(reactContext)
25
27
  container.layoutParams = ViewGroup.LayoutParams(
26
28
  ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
27
29
  )
28
- container.tag = BannerState()
29
30
  return container
30
31
  }
31
32
 
32
33
  @ReactProp(name = "adUnitIdentifier")
33
- fun setAdUnitIdentifier(view: FrameLayout, value: String?) {
34
- (view.tag as BannerState).adUnitId = value?.toIntOrNull() ?: 0
34
+ fun setAdUnitIdentifier(view: BannerContainer, value: String?) {
35
+ view.adUnitId = value?.toIntOrNull() ?: 0
35
36
  maybeLoad(view)
36
37
  }
37
38
 
38
39
  @ReactProp(name = "size")
39
- fun setSize(view: FrameLayout, value: String?) {
40
- (view.tag as BannerState).size = value ?: ""
40
+ fun setSize(view: BannerContainer, value: String?) {
41
+ view.size = value ?: ""
41
42
  maybeLoad(view)
42
43
  }
43
44
 
44
- private fun maybeLoad(view: FrameLayout) {
45
- val state = view.tag as BannerState
46
- if (state.loaded || state.adUnitId <= 0) return
47
- state.loaded = true
48
- val banner = EzoicBannerView(view.context, state.adUnitId)
45
+ // Forwarded to the native view's `collapseOnNoFill` property. Applied to an
46
+ // already-created banner too, so a prop change after load takes effect on
47
+ // the next load outcome.
48
+ @ReactProp(name = "collapseOnNoFill", defaultBoolean = true)
49
+ fun setCollapseOnNoFill(view: BannerContainer, value: Boolean) {
50
+ view.collapseOnNoFill = value
51
+ view.banner?.collapseOnNoFill = value
52
+ }
53
+
54
+ private fun maybeLoad(view: BannerContainer) {
55
+ if (view.loaded || view.adUnitId <= 0) return
56
+ view.loaded = true
57
+ val banner = EzoicBannerView(view.context, view.adUnitId)
58
+ banner.collapseOnNoFill = view.collapseOnNoFill
49
59
  banner.listener = object : EzoicBannerViewListener {
50
60
  override fun onBannerLoaded(b: EzoicBannerView) = emit(view, "topLoad", Arguments.createMap())
51
61
  override fun onBannerLoadFailed(b: EzoicBannerView, error: EzoicError) {
@@ -58,14 +68,24 @@ class EzoicBannerViewManager(private val ctx: ReactApplicationContext) :
58
68
  override fun onBannerClicked(b: EzoicBannerView) = emit(view, "topAdClick", Arguments.createMap())
59
69
  override fun onBannerOpened(b: EzoicBannerView) = emit(view, "topOpen", Arguments.createMap())
60
70
  override fun onBannerClosed(b: EzoicBannerView) = emit(view, "topClose", Arguments.createMap())
71
+ // The native view collapses itself (GONE) or resizes to the loaded
72
+ // creative, but this container is MATCH_PARENT inside the Yoga box, so
73
+ // the JS component applies the height from this event.
74
+ override fun onBannerSizeChanged(bannerView: EzoicBannerView, widthDp: Int, heightDp: Int) {
75
+ val map = Arguments.createMap()
76
+ map.putDouble("width", widthDp.toDouble())
77
+ map.putDouble("height", heightDp.toDouble())
78
+ emit(view, "topSizeChange", map)
79
+ }
61
80
  }
81
+ view.banner = banner
62
82
  view.removeAllViews()
63
83
  view.addView(banner)
64
- val sizes = state.size.split(",").map { it.trim() }.filter { it.isNotEmpty() }
84
+ val sizes = view.size.split(",").map { it.trim() }.filter { it.isNotEmpty() }
65
85
  if (sizes.isEmpty()) banner.loadAd() else banner.loadAd(sizes)
66
86
  }
67
87
 
68
- private fun emit(view: FrameLayout, event: String, payload: WritableMap) {
88
+ private fun emit(view: BannerContainer, event: String, payload: WritableMap) {
69
89
  ctx.getJSModule(RCTEventEmitter::class.java).receiveEvent(view.id, event, payload)
70
90
  }
71
91
 
@@ -81,10 +101,39 @@ class EzoicBannerViewManager(private val ctx: ReactApplicationContext) :
81
101
  )
82
102
  }
83
103
 
84
- private class BannerState {
104
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
105
+ return mapOf(
106
+ "topSizeChange" to mapOf("registrationName" to "onSizeChange")
107
+ )
108
+ }
109
+
110
+ /**
111
+ * Container for the native banner. RN lays out only Yoga-managed views; the
112
+ * native [EzoicBannerView] is added from native code, so when JS changes the
113
+ * Yoga box height (collapse to 0 / restore after a fill) the child must be
114
+ * re-measured against the new bounds. Overriding [requestLayout] to post a
115
+ * manual measure(EXACTLY)+layout of the current bounds is the same fix used
116
+ * by [EzoicOutstreamAdViewManager] and [EzoicNativeAdViewManager].
117
+ */
118
+ class BannerContainer(context: Context) : FrameLayout(context) {
85
119
  var adUnitId: Int = 0
86
120
  var size: String = ""
87
121
  var loaded: Boolean = false
122
+ var collapseOnNoFill: Boolean = true
123
+ var banner: EzoicBannerView? = null
124
+
125
+ private val measureAndLayout = Runnable {
126
+ measure(
127
+ View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
128
+ View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
129
+ )
130
+ layout(left, top, right, bottom)
131
+ }
132
+
133
+ override fun requestLayout() {
134
+ super.requestLayout()
135
+ post(measureAndLayout)
136
+ }
88
137
  }
89
138
 
90
139
  companion object {
@@ -56,6 +56,12 @@ class EzoicOutstreamAdViewManager(private val ctx: ReactApplicationContext) :
56
56
  view.rawAdUnitId = value ?: ""
57
57
  }
58
58
 
59
+ @ReactProp(name = "collapseOnNoFill", defaultBoolean = true)
60
+ fun setCollapseOnNoFill(view: OutstreamAdContainer, value: Boolean) {
61
+ view.collapseOnNoFill = value
62
+ view.ezoicOutstreamAd?.collapseOnNoFill = value
63
+ }
64
+
59
65
  // Fabric sets every prop for the mount transaction before this runs, so the
60
66
  // ad unit id is final here. `view.post` escapes the mount transaction so the
61
67
  // synchronous native-SDK failure path (uninitialized) can't reenter the
@@ -83,6 +89,7 @@ class EzoicOutstreamAdViewManager(private val ctx: ReactApplicationContext) :
83
89
  // loadAd() so no early lifecycle callback is missed, add it to the
84
90
  // container, then load.
85
91
  val outstreamAd = EzoicOutstreamAdView(view.context, view.adUnitId)
92
+ outstreamAd.collapseOnNoFill = view.collapseOnNoFill
86
93
  outstreamAd.listener = object : EzoicOutstreamAdViewListener {
87
94
  override fun onOutstreamLoaded(adView: EzoicOutstreamAdView) {
88
95
  // dispose() and this callback both arrive on the main thread, so the
@@ -97,6 +104,15 @@ class EzoicOutstreamAdViewManager(private val ctx: ReactApplicationContext) :
97
104
  emit(view, "topError", errorMap(error.message, error.code))
98
105
  }
99
106
 
107
+ override fun onOutstreamSizeChanged(adView: EzoicOutstreamAdView, widthDp: Int, heightDp: Int) {
108
+ if (view.disposed || view.loadGeneration != generation) return
109
+ val map = Arguments.createMap()
110
+ map.putDouble("width", widthDp.toDouble())
111
+ map.putDouble("height", heightDp.toDouble())
112
+ emit(view, "topSizeChange", map)
113
+ view.requestLayout()
114
+ }
115
+
100
116
  override fun onOutstreamImpression(adView: EzoicOutstreamAdView) {
101
117
  if (view.disposed || view.loadGeneration != generation) return
102
118
  emit(view, "topImpression", Arguments.createMap())
@@ -156,6 +172,12 @@ class EzoicOutstreamAdViewManager(private val ctx: ReactApplicationContext) :
156
172
  )
157
173
  }
158
174
 
175
+ override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
176
+ return mapOf(
177
+ "topSizeChange" to mapOf("registrationName" to "onSizeChange")
178
+ )
179
+ }
180
+
159
181
  /**
160
182
  * Container for the native outstream view. RN lays out only Yoga-managed
161
183
  * views; the native [EzoicOutstreamAdView] is added from native code and stays
@@ -169,6 +191,7 @@ class EzoicOutstreamAdViewManager(private val ctx: ReactApplicationContext) :
169
191
  var loadStarted: Boolean = false
170
192
  var disposed: Boolean = false
171
193
  var loadGeneration: Int = 0
194
+ var collapseOnNoFill: Boolean = true
172
195
  var ezoicOutstreamAd: EzoicOutstreamAdView? = null
173
196
 
174
197
  private val measureAndLayout = Runnable {
@@ -4,6 +4,7 @@ import EzoicAdsSDKBinary
4
4
  @objc public protocol EzoicBannerHostViewDelegate: AnyObject {
5
5
  func bannerDidLoad()
6
6
  func bannerDidFail(_ message: String, code: Int)
7
+ func bannerDidChangeSize(_ width: Double, height: Double)
7
8
  func bannerDidRecordImpression()
8
9
  func bannerDidRecordClick()
9
10
  func bannerWillPresentScreen()
@@ -13,6 +14,9 @@ import EzoicAdsSDKBinary
13
14
  @objc public class EzoicBannerHostView: UIView, EzoicBannerViewDelegate {
14
15
 
15
16
  @objc public weak var hostDelegate: EzoicBannerHostViewDelegate?
17
+ @objc public var collapseOnNoFill: Bool = true {
18
+ didSet { banner?.collapseOnNoFill = collapseOnNoFill }
19
+ }
16
20
  private var banner: EzoicBannerView?
17
21
  private var adUnitId: Int = 0
18
22
  private var sizes: [String] = []
@@ -26,6 +30,7 @@ import EzoicAdsSDKBinary
26
30
  private func rebuildAndLoad() {
27
31
  banner?.removeFromSuperview()
28
32
  let view = EzoicBannerView(adUnitIdentifier: adUnitId)
33
+ view.collapseOnNoFill = collapseOnNoFill
29
34
  view.delegate = self
30
35
  view.translatesAutoresizingMaskIntoConstraints = false
31
36
  addSubview(view)
@@ -42,6 +47,9 @@ import EzoicAdsSDKBinary
42
47
  public func bannerView(_ bannerView: EzoicBannerView, didFailToLoadWithError error: EzoicError) {
43
48
  hostDelegate?.bannerDidFail(error.localizedDescription, code: error.code)
44
49
  }
50
+ public func bannerView(_ bannerView: EzoicBannerView, didChangeSize size: CGSize) {
51
+ hostDelegate?.bannerDidChangeSize(Double(size.width), height: Double(size.height))
52
+ }
45
53
  public func bannerViewDidRecordImpression(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidRecordImpression() }
46
54
  public func bannerViewDidRecordClick(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidRecordClick() }
47
55
  public func bannerViewWillPresentScreen(_ bannerView: EzoicBannerView) { hostDelegate?.bannerWillPresentScreen() }
@@ -33,6 +33,7 @@ using namespace facebook::react;
33
33
  const auto &newProps = *std::static_pointer_cast<EzoicBannerViewProps const>(props);
34
34
  NSString *adUnit = [NSString stringWithUTF8String:newProps.adUnitIdentifier.c_str()];
35
35
  NSString *size = [NSString stringWithUTF8String:newProps.size.c_str()];
36
+ _host.collapseOnNoFill = newProps.collapseOnNoFill;
36
37
  if (![adUnit isEqualToString:_lastAdUnit] || ![size isEqualToString:_lastSize]) {
37
38
  _lastAdUnit = adUnit;
38
39
  _lastSize = size;
@@ -49,6 +50,11 @@ using namespace facebook::react;
49
50
  std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)
50
51
  ->onError({.message = std::string([message UTF8String]), .code = (int)code});
51
52
  }
53
+ - (void)bannerDidChangeSize:(double)width height:(double)height {
54
+ if (_eventEmitter)
55
+ std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)
56
+ ->onSizeChange({.width = width, .height = height});
57
+ }
52
58
  - (void)bannerDidRecordImpression {
53
59
  if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onImpression({});
54
60
  }
@@ -61,7 +67,6 @@ using namespace facebook::react;
61
67
  - (void)bannerDidDismissScreen {
62
68
  if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onClose({});
63
69
  }
64
-
65
70
  Class<RCTComponentViewProtocol> EzoicBannerViewCls(void) { return EzoicBannerView.class; }
66
71
 
67
72
  @end
@@ -7,6 +7,7 @@ import EzoicAdsSDKBinary
7
7
  @objc public protocol EzoicOutstreamAdHostViewDelegate: AnyObject {
8
8
  func outstreamAdDidLoad()
9
9
  func outstreamAdDidFail(_ message: String, code: Int)
10
+ func outstreamAdDidChangeSize(_ width: Double, height: Double)
10
11
  func outstreamAdDidRecordImpression()
11
12
  func outstreamAdDidRecordClick()
12
13
  func outstreamAdWillPresentScreen()
@@ -26,6 +27,10 @@ import EzoicAdsSDKBinary
26
27
 
27
28
  @objc public weak var hostDelegate: EzoicOutstreamAdHostViewDelegate?
28
29
 
30
+ @objc public var collapseOnNoFill: Bool = true {
31
+ didSet { outstreamView?.collapseOnNoFill = collapseOnNoFill }
32
+ }
33
+
29
34
  private var adUnitId: Int = 0
30
35
  private var outstreamView: EzoicOutstreamAdView?
31
36
  private var loadStarted = false
@@ -44,6 +49,7 @@ import EzoicAdsSDKBinary
44
49
  loadStarted = true
45
50
 
46
51
  let view = EzoicOutstreamAdView(adUnitIdentifier: adUnitId)
52
+ view.collapseOnNoFill = collapseOnNoFill
47
53
  // Delegate before loadAd so no early lifecycle callback is missed.
48
54
  view.delegate = self
49
55
  view.translatesAutoresizingMaskIntoConstraints = false
@@ -65,6 +71,9 @@ import EzoicAdsSDKBinary
65
71
  public func outstreamView(_ outstreamView: EzoicOutstreamAdView, didFailToLoadWithError error: EzoicError) {
66
72
  hostDelegate?.outstreamAdDidFail(error.localizedDescription, code: error.code)
67
73
  }
74
+ public func outstreamView(_ outstreamView: EzoicOutstreamAdView, didChangeSize size: CGSize) {
75
+ hostDelegate?.outstreamAdDidChangeSize(Double(size.width), height: Double(size.height))
76
+ }
68
77
  public func outstreamViewDidRecordImpression(_ outstreamView: EzoicOutstreamAdView) {
69
78
  hostDelegate?.outstreamAdDidRecordImpression()
70
79
  }
@@ -49,6 +49,7 @@ using namespace facebook::react;
49
49
  _lastAdUnit = adUnit;
50
50
  [_host configureWithAdUnitIdentifier:adUnit];
51
51
  }
52
+ _host.collapseOnNoFill = newProps.collapseOnNoFill;
52
53
  [super updateProps:props oldProps:oldProps];
53
54
  }
54
55
 
@@ -72,6 +73,11 @@ using namespace facebook::react;
72
73
  std::static_pointer_cast<EzoicOutstreamAdViewEventEmitter const>(_eventEmitter)
73
74
  ->onError({.message = std::string([message UTF8String]), .code = (int)code});
74
75
  }
76
+ - (void)outstreamAdDidChangeSize:(double)width height:(double)height {
77
+ if (_eventEmitter)
78
+ std::static_pointer_cast<EzoicOutstreamAdViewEventEmitter const>(_eventEmitter)
79
+ ->onSizeChange({.width = width, .height = height});
80
+ }
75
81
  - (void)outstreamAdDidRecordImpression {
76
82
  if (_eventEmitter) std::static_pointer_cast<EzoicOutstreamAdViewEventEmitter const>(_eventEmitter)->onImpression({});
77
83
  }
@@ -3,12 +3,21 @@ import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
3
3
 
4
4
  type LoadEvent = Readonly<{}>;
5
5
  type ErrorEvent = Readonly<{ message: string; code: CodegenTypes.Int32 }>;
6
+ type SizeChangeEvent = Readonly<{
7
+ width: CodegenTypes.Double;
8
+ height: CodegenTypes.Double;
9
+ }>;
6
10
 
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
9
13
  size?: string;
14
+ // Collapse the native view when a load fails and no ad is displayed.
15
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
10
16
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
17
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
18
+ // Displayed ad size changed (dp/pt): the creative size after a successful
19
+ // load, or 0x0 when the native view collapses on a terminal no-fill.
20
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
12
21
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
22
  // `onClick` is reserved by core ViewProps (a gesture handler), so the native
14
23
  // banner-click event is exposed as `onAdClick`. The public `EzoicBannerView`
@@ -3,11 +3,20 @@ import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
3
3
 
4
4
  type LoadEvent = Readonly<{}>;
5
5
  type ErrorEvent = Readonly<{ message: string; code: CodegenTypes.Int32 }>;
6
+ type SizeChangeEvent = Readonly<{
7
+ width: CodegenTypes.Double;
8
+ height: CodegenTypes.Double;
9
+ }>;
6
10
 
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
13
+ // Collapse the native view when a load fails and no ad is displayed.
14
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
9
15
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
10
16
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
17
+ // Displayed ad size changed (dp/pt): the creative size after a successful
18
+ // load, or 0x0 when the native view collapses on a terminal no-fill.
19
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
11
20
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
12
21
  // `onClick` is reserved by core ViewProps (a gesture handler), so the native
13
22
  // outstream-click event is exposed as `onAdClick`. The public
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ import { useState } from 'react';
3
4
  import NativeEzoicAds from "./NativeEzoicAds.js";
4
5
  import EzoicBannerNative from './EzoicBannerViewNativeComponent';
5
6
  import EzoicNativeAdNative from './EzoicNativeAdViewNativeComponent';
@@ -26,28 +27,71 @@ export const EzoicAds = {
26
27
  return NativeEzoicAds.trackPageview();
27
28
  }
28
29
  };
30
+
31
+ /**
32
+ * Displayed ad size in dp (Android) / points (iOS). `{ width: 0, height: 0 }`
33
+ * means the native view collapsed after a terminal no-fill.
34
+ */
35
+
36
+ /**
37
+ * Tracks the collapsed state of an ad view from the native `onSizeChange`
38
+ * event (height 0 ⇒ collapsed) and returns the style to render with plus the
39
+ * handler to attach to the native component. While collapsed and
40
+ * `collapseOnNoFill` is on, the host style is overridden with `height: 0` so
41
+ * the Yoga box shrinks along with the native view; a non-zero size restores
42
+ * the host style. The user's `onSizeChange` always receives the plain
43
+ * `{ width, height }` payload.
44
+ */
45
+ function useCollapsibleAdStyle(style, collapseOnNoFill, onSizeChange) {
46
+ const [collapsed, setCollapsed] = useState(false);
47
+ const handleSizeChange = e => {
48
+ const {
49
+ width,
50
+ height
51
+ } = e.nativeEvent;
52
+ setCollapsed(height === 0);
53
+ onSizeChange?.({
54
+ width,
55
+ height
56
+ });
57
+ };
58
+ const resolvedStyle = collapseOnNoFill !== false && collapsed ? [style, {
59
+ height: 0
60
+ }] : style;
61
+ return {
62
+ style: resolvedStyle,
63
+ onSizeChange: handleSizeChange
64
+ };
65
+ }
29
66
  export function EzoicBannerView(props) {
30
67
  const {
31
68
  adUnitIdentifier,
32
69
  size,
70
+ style,
71
+ collapseOnNoFill = true,
33
72
  onLoad,
34
73
  onError,
35
74
  onImpression,
36
75
  onClick,
37
76
  onOpen,
38
77
  onClose,
78
+ onSizeChange,
39
79
  ...rest
40
80
  } = props;
81
+ const collapsible = useCollapsibleAdStyle(style, collapseOnNoFill, onSizeChange);
41
82
  return /*#__PURE__*/_jsx(EzoicBannerNative, {
42
83
  ...rest,
84
+ style: collapsible.style,
43
85
  adUnitIdentifier: coerceAdUnitId(adUnitIdentifier),
44
86
  size: normalizeSize(size),
87
+ collapseOnNoFill: collapseOnNoFill,
45
88
  onLoad: onLoad ? () => onLoad() : undefined,
46
89
  onError: onError ? e => onError(e.nativeEvent) : undefined,
47
90
  onImpression: onImpression ? () => onImpression() : undefined,
48
91
  onAdClick: onClick ? () => onClick() : undefined,
49
92
  onOpen: onOpen ? () => onOpen() : undefined,
50
- onClose: onClose ? () => onClose() : undefined
93
+ onClose: onClose ? () => onClose() : undefined,
94
+ onSizeChange: collapsible.onSizeChange
51
95
  });
52
96
  }
53
97
  /**
@@ -81,28 +125,36 @@ export function EzoicNativeAdView(props) {
81
125
  * Renders an outstream video ad in an SDK-built player. Outstream video runs on
82
126
  * its own (not inside host video content), so the SDK owns the player and this
83
127
  * component only needs a size. Fills the bounds it is given by its RN style, so
84
- * size it with `style` (e.g. `{ width: '100%', height: 200 }`).
128
+ * size it with `style` (e.g. `{ width: '100%', height: 200 }`). While collapsed
129
+ * after a no-fill (see `collapseOnNoFill`) the height is forced to 0.
85
130
  */
86
131
  export function EzoicOutstreamAdView(props) {
87
132
  const {
88
133
  adUnitIdentifier,
134
+ style,
135
+ collapseOnNoFill = true,
89
136
  onLoad,
90
137
  onError,
91
138
  onImpression,
92
139
  onClick,
93
140
  onOpen,
94
141
  onClose,
142
+ onSizeChange,
95
143
  ...rest
96
144
  } = props;
145
+ const collapsible = useCollapsibleAdStyle(style, collapseOnNoFill, onSizeChange);
97
146
  return /*#__PURE__*/_jsx(EzoicOutstreamNative, {
98
147
  ...rest,
148
+ style: collapsible.style,
99
149
  adUnitIdentifier: coerceAdUnitId(adUnitIdentifier),
150
+ collapseOnNoFill: collapseOnNoFill,
100
151
  onLoad: onLoad ? () => onLoad() : undefined,
101
152
  onError: onError ? e => onError(e.nativeEvent) : undefined,
102
153
  onImpression: onImpression ? () => onImpression() : undefined,
103
154
  onAdClick: onClick ? () => onClick() : undefined,
104
155
  onOpen: onOpen ? () => onOpen() : undefined,
105
- onClose: onClose ? () => onClose() : undefined
156
+ onClose: onClose ? () => onClose() : undefined,
157
+ onSizeChange: collapsible.onSizeChange
106
158
  });
107
159
  }
108
160
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeEzoicAds","EzoicBannerNative","EzoicNativeAdNative","EzoicOutstreamNative","coerceAdUnitId","normalizeConfig","normalizeSize","jsx","_jsx","EzoicRewardedAd","EzoicInterstitialAd","EzoicInstreamAd","EzoicAds","initialize","config","setGDPRConsent","applies","consentString","setGPPConsent","gppString","sectionIds","setSubjectToCOPPA","value","trackPageview","EzoicBannerView","props","adUnitIdentifier","size","onLoad","onError","onImpression","onClick","onOpen","onClose","rest","undefined","e","nativeEvent","onAdClick","EzoicNativeAdView","EzoicOutstreamAdView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useState","NativeEzoicAds","EzoicBannerNative","EzoicNativeAdNative","EzoicOutstreamNative","coerceAdUnitId","normalizeConfig","normalizeSize","jsx","_jsx","EzoicRewardedAd","EzoicInterstitialAd","EzoicInstreamAd","EzoicAds","initialize","config","setGDPRConsent","applies","consentString","setGPPConsent","gppString","sectionIds","setSubjectToCOPPA","value","trackPageview","useCollapsibleAdStyle","style","collapseOnNoFill","onSizeChange","collapsed","setCollapsed","handleSizeChange","e","width","height","nativeEvent","resolvedStyle","EzoicBannerView","props","adUnitIdentifier","size","onLoad","onError","onImpression","onClick","onOpen","onClose","rest","collapsible","undefined","onAdClick","EzoicNativeAdView","EzoicOutstreamAdView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,OAAO;AAEhC,OAAOC,cAAc,MAA4B,qBAAkB;AACnE,OAAOC,iBAAiB,MAAM,kCAAkC;AAChE,OAAOC,mBAAmB,MAAM,oCAAoC;AACpE,OAAOC,oBAAoB,MAAM,uCAAuC;AACxE,SAASC,cAAc,EAAEC,eAAe,EAAEC,aAAa,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAG3E,SACEC,eAAe,QAGV,sBAAmB;AAC1B,SACEC,mBAAmB,QAEd,0BAAuB;AAC9B,SACEC,eAAe,QAGV,sBAAmB;AAE1B,OAAO,MAAMC,QAAQ,GAAG;EACtBC,UAAUA,CAACC,MAAmB,EAAiB;IAC7C,OAAOd,cAAc,CAACa,UAAU,CAACR,eAAe,CAACS,MAAM,CAAC,CAAC;EAC3D,CAAC;EACDC,cAAcA,CAACC,OAAgB,EAAEC,aAAsB,EAAQ;IAC7DjB,cAAc,CAACe,cAAc,CAACC,OAAO,EAAEC,aAAa,CAAC;EACvD,CAAC;EACDC,aAAaA,CAACC,SAAkB,EAAEC,UAAmB,EAAQ;IAC3DpB,cAAc,CAACkB,aAAa,CAACC,SAAS,EAAEC,UAAU,CAAC;EACrD,CAAC;EACDC,iBAAiBA,CAACC,KAAc,EAAQ;IACtCtB,cAAc,CAACqB,iBAAiB,CAACC,KAAK,CAAC;EACzC,CAAC;EACDC,aAAaA,CAAA,EAAqB;IAChC,OAAOvB,cAAc,CAACuB,aAAa,CAAC,CAAC;EACvC;AACF,CAAC;;AAOD;AACA;AACA;AACA;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,qBAAqBA,CAC5BC,KAA2B,EAC3BC,gBAAyB,EACzBC,YAA0C,EAC1C;EACA,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAG9B,QAAQ,CAAC,KAAK,CAAC;EACjD,MAAM+B,gBAAgB,GAAIC,CAAoC,IAAK;IACjE,MAAM;MAAEC,KAAK;MAAEC;IAAO,CAAC,GAAGF,CAAC,CAACG,WAAW;IACvCL,YAAY,CAACI,MAAM,KAAK,CAAC,CAAC;IAC1BN,YAAY,GAAG;MAAEK,KAAK;MAAEC;IAAO,CAAC,CAAC;EACnC,CAAC;EACD,MAAME,aAAmC,GACvCT,gBAAgB,KAAK,KAAK,IAAIE,SAAS,GAAG,CAACH,KAAK,EAAE;IAAEQ,MAAM,EAAE;EAAE,CAAC,CAAC,GAAGR,KAAK;EAC1E,OAAO;IAAEA,KAAK,EAAEU,aAAa;IAAER,YAAY,EAAEG;EAAiB,CAAC;AACjE;AAkBA,OAAO,SAASM,eAAeA,CAACC,KAA2B,EAAE;EAC3D,MAAM;IACJC,gBAAgB;IAChBC,IAAI;IACJd,KAAK;IACLC,gBAAgB,GAAG,IAAI;IACvBc,MAAM;IACNC,OAAO;IACPC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,OAAO;IACPlB,YAAY;IACZ,GAAGmB;EACL,CAAC,GAAGT,KAAK;EACT,MAAMU,WAAW,GAAGvB,qBAAqB,CACvCC,KAAK,EACLC,gBAAgB,EAChBC,YACF,CAAC;EACD,oBACEnB,IAAA,CAACP,iBAAiB;IAAA,GACZ6C,IAAI;IACRrB,KAAK,EAAEsB,WAAW,CAACtB,KAAM;IACzBa,gBAAgB,EAAElC,cAAc,CAACkC,gBAAgB,CAAE;IACnDC,IAAI,EAAEjC,aAAa,CAACiC,IAAI,CAAE;IAC1Bb,gBAAgB,EAAEA,gBAAiB;IACnCc,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGQ,SAAU;IAC5CP,OAAO,EAAEA,OAAO,GAAIV,CAAC,IAAKU,OAAO,CAACV,CAAC,CAACG,WAAW,CAAC,GAAGc,SAAU;IAC7DN,YAAY,EAAEA,YAAY,GAAG,MAAMA,YAAY,CAAC,CAAC,GAAGM,SAAU;IAC9DC,SAAS,EAAEN,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGK,SAAU;IACjDJ,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGI,SAAU;IAC5CH,OAAO,EAAEA,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGG,SAAU;IAC/CrB,YAAY,EAAEoB,WAAW,CAACpB;EAAa,CACxC,CAAC;AAEN;AAkBA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASuB,iBAAiBA,CAACb,KAA6B,EAAE;EAC/D,MAAM;IACJC,gBAAgB;IAChBE,MAAM;IACNC,OAAO;IACPC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,OAAO;IACP,GAAGC;EACL,CAAC,GAAGT,KAAK;EACT,oBACE7B,IAAA,CAACN,mBAAmB;IAAA,GACd4C,IAAI;IACRR,gBAAgB,EAAElC,cAAc,CAACkC,gBAAgB,CAAE;IACnDE,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGQ,SAAU;IAC5CP,OAAO,EAAEA,OAAO,GAAIV,CAAC,IAAKU,OAAO,CAACV,CAAC,CAACG,WAAW,CAAC,GAAGc,SAAU;IAC7DN,YAAY,EAAEA,YAAY,GAAG,MAAMA,YAAY,CAAC,CAAC,GAAGM,SAAU;IAC9DC,SAAS,EAAEN,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGK,SAAU;IACjDJ,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGI,SAAU;IAC5CH,OAAO,EAAEA,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGG;EAAU,CAChD,CAAC;AAEN;AAsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,oBAAoBA,CAACd,KAAgC,EAAE;EACrE,MAAM;IACJC,gBAAgB;IAChBb,KAAK;IACLC,gBAAgB,GAAG,IAAI;IACvBc,MAAM;IACNC,OAAO;IACPC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,OAAO;IACPlB,YAAY;IACZ,GAAGmB;EACL,CAAC,GAAGT,KAAK;EACT,MAAMU,WAAW,GAAGvB,qBAAqB,CACvCC,KAAK,EACLC,gBAAgB,EAChBC,YACF,CAAC;EACD,oBACEnB,IAAA,CAACL,oBAAoB;IAAA,GACf2C,IAAI;IACRrB,KAAK,EAAEsB,WAAW,CAACtB,KAAM;IACzBa,gBAAgB,EAAElC,cAAc,CAACkC,gBAAgB,CAAE;IACnDZ,gBAAgB,EAAEA,gBAAiB;IACnCc,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGQ,SAAU;IAC5CP,OAAO,EAAEA,OAAO,GAAIV,CAAC,IAAKU,OAAO,CAACV,CAAC,CAACG,WAAW,CAAC,GAAGc,SAAU;IAC7DN,YAAY,EAAEA,YAAY,GAAG,MAAMA,YAAY,CAAC,CAAC,GAAGM,SAAU;IAC9DC,SAAS,EAAEN,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGK,SAAU;IACjDJ,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGI,SAAU;IAC5CH,OAAO,EAAEA,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGG,SAAU;IAC/CrB,YAAY,EAAEoB,WAAW,CAACpB;EAAa,CACxC,CAAC;AAEN","ignoreList":[]}
@@ -4,11 +4,17 @@ type ErrorEvent = Readonly<{
4
4
  message: string;
5
5
  code: CodegenTypes.Int32;
6
6
  }>;
7
+ type SizeChangeEvent = Readonly<{
8
+ width: CodegenTypes.Double;
9
+ height: CodegenTypes.Double;
10
+ }>;
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
9
13
  size?: string;
14
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
10
15
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
16
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
17
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
12
18
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
19
  onAdClick?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
14
20
  onOpen?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"EzoicBannerViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/EzoicBannerViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3E,KAAK,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9B,KAAK,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAA;CAAE,CAAC,CAAC;AAE1E,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAInE,SAAS,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;CAC/D;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
1
+ {"version":3,"file":"EzoicBannerViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/EzoicBannerViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3E,KAAK,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9B,KAAK,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAA;CAAE,CAAC,CAAC;AAC1E,KAAK,eAAe,GAAG,QAAQ,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,gBAAgB,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAG/D,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;IACvE,YAAY,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAInE,SAAS,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;CAC/D;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
@@ -4,10 +4,16 @@ type ErrorEvent = Readonly<{
4
4
  message: string;
5
5
  code: CodegenTypes.Int32;
6
6
  }>;
7
+ type SizeChangeEvent = Readonly<{
8
+ width: CodegenTypes.Double;
9
+ height: CodegenTypes.Double;
10
+ }>;
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
13
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
9
14
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
10
15
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
16
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
11
17
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
12
18
  onAdClick?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
19
  onOpen?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"EzoicOutstreamAdViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/EzoicOutstreamAdViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3E,KAAK,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9B,KAAK,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAA;CAAE,CAAC,CAAC;AAE1E,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAKnE,SAAS,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;CAC/D;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
1
+ {"version":3,"file":"EzoicOutstreamAdViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/EzoicOutstreamAdViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3E,KAAK,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9B,KAAK,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAA;CAAE,CAAC,CAAC;AAC1E,KAAK,eAAe,GAAG,QAAQ,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC;CAC7B,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IAEzB,gBAAgB,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAG/D,YAAY,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;IACvE,YAAY,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAKnE,SAAS,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;CAC/D;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
@@ -15,16 +15,28 @@ export interface EzoicBannerError {
15
15
  message: string;
16
16
  code: number;
17
17
  }
18
+ /**
19
+ * Displayed ad size in dp (Android) / points (iOS). `{ width: 0, height: 0 }`
20
+ * means the native view collapsed after a terminal no-fill.
21
+ */
22
+ export interface EzoicAdSize {
23
+ width: number;
24
+ height: number;
25
+ }
18
26
  export interface EzoicBannerViewProps {
19
27
  adUnitIdentifier: string;
20
28
  size?: string;
21
29
  style?: StyleProp<ViewStyle>;
30
+ /** Collapse the view (height 0) when a load fails and no ad is displayed. Default `true`. */
31
+ collapseOnNoFill?: boolean;
22
32
  onLoad?: () => void;
23
33
  onError?: (error: EzoicBannerError) => void;
24
34
  onImpression?: () => void;
25
35
  onClick?: () => void;
26
36
  onOpen?: () => void;
27
37
  onClose?: () => void;
38
+ /** Displayed ad size changed: the creative size after a load, or 0x0 on collapse. */
39
+ onSizeChange?: (size: EzoicAdSize) => void;
28
40
  }
29
41
  export declare function EzoicBannerView(props: EzoicBannerViewProps): import("react").JSX.Element;
30
42
  export interface EzoicNativeAdError {
@@ -54,18 +66,23 @@ export interface EzoicOutstreamAdError {
54
66
  export interface EzoicOutstreamAdViewProps {
55
67
  adUnitIdentifier: string | number;
56
68
  style?: StyleProp<ViewStyle>;
69
+ /** Collapse the view (height 0) when a load fails and no ad is displayed. Default `true`. */
70
+ collapseOnNoFill?: boolean;
57
71
  onLoad?: () => void;
58
72
  onError?: (error: EzoicOutstreamAdError) => void;
59
73
  onImpression?: () => void;
60
74
  onClick?: () => void;
61
75
  onOpen?: () => void;
62
76
  onClose?: () => void;
77
+ /** Displayed ad size changed: the creative size after a load, or 0x0 on collapse. */
78
+ onSizeChange?: (size: EzoicAdSize) => void;
63
79
  }
64
80
  /**
65
81
  * Renders an outstream video ad in an SDK-built player. Outstream video runs on
66
82
  * its own (not inside host video content), so the SDK owns the player and this
67
83
  * component only needs a size. Fills the bounds it is given by its RN style, so
68
- * size it with `style` (e.g. `{ width: '100%', height: 200 }`).
84
+ * size it with `style` (e.g. `{ width: '100%', height: 200 }`). While collapsed
85
+ * after a no-fill (see `collapseOnNoFill`) the height is forced to 0.
69
86
  */
70
87
  export declare function EzoicOutstreamAdView(props: EzoicOutstreamAdViewProps): import("react").JSX.Element;
71
88
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezoic/react-native-sdk",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Ezoic Ads SDK for React Native (Prebid + Google Ad Manager banner, native, interstitial, rewarded, outstream and instream video ads).",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -3,12 +3,21 @@ import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
3
3
 
4
4
  type LoadEvent = Readonly<{}>;
5
5
  type ErrorEvent = Readonly<{ message: string; code: CodegenTypes.Int32 }>;
6
+ type SizeChangeEvent = Readonly<{
7
+ width: CodegenTypes.Double;
8
+ height: CodegenTypes.Double;
9
+ }>;
6
10
 
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
9
13
  size?: string;
14
+ // Collapse the native view when a load fails and no ad is displayed.
15
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
10
16
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
17
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
18
+ // Displayed ad size changed (dp/pt): the creative size after a successful
19
+ // load, or 0x0 when the native view collapses on a terminal no-fill.
20
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
12
21
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
22
  // `onClick` is reserved by core ViewProps (a gesture handler), so the native
14
23
  // banner-click event is exposed as `onAdClick`. The public `EzoicBannerView`
@@ -3,11 +3,20 @@ import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
3
3
 
4
4
  type LoadEvent = Readonly<{}>;
5
5
  type ErrorEvent = Readonly<{ message: string; code: CodegenTypes.Int32 }>;
6
+ type SizeChangeEvent = Readonly<{
7
+ width: CodegenTypes.Double;
8
+ height: CodegenTypes.Double;
9
+ }>;
6
10
 
7
11
  export interface NativeProps extends ViewProps {
8
12
  adUnitIdentifier: string;
13
+ // Collapse the native view when a load fails and no ad is displayed.
14
+ collapseOnNoFill?: CodegenTypes.WithDefault<boolean, true>;
9
15
  onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
10
16
  onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
17
+ // Displayed ad size changed (dp/pt): the creative size after a successful
18
+ // load, or 0x0 when the native view collapses on a terminal no-fill.
19
+ onSizeChange?: CodegenTypes.DirectEventHandler<SizeChangeEvent> | null;
11
20
  onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
12
21
  // `onClick` is reserved by core ViewProps (a gesture handler), so the native
13
22
  // outstream-click event is exposed as `onAdClick`. The public
package/src/index.tsx CHANGED
@@ -1,4 +1,5 @@
1
- import type { StyleProp, ViewStyle } from 'react-native';
1
+ import { useState } from 'react';
2
+ import type { NativeSyntheticEvent, StyleProp, ViewStyle } from 'react-native';
2
3
  import NativeEzoicAds, { type EzoicConfig } from './NativeEzoicAds';
3
4
  import EzoicBannerNative from './EzoicBannerViewNativeComponent';
4
5
  import EzoicNativeAdNative from './EzoicNativeAdViewNativeComponent';
@@ -44,41 +45,90 @@ export interface EzoicBannerError {
44
45
  code: number;
45
46
  }
46
47
 
48
+ /**
49
+ * Displayed ad size in dp (Android) / points (iOS). `{ width: 0, height: 0 }`
50
+ * means the native view collapsed after a terminal no-fill.
51
+ */
52
+ export interface EzoicAdSize {
53
+ width: number;
54
+ height: number;
55
+ }
56
+
57
+ /**
58
+ * Tracks the collapsed state of an ad view from the native `onSizeChange`
59
+ * event (height 0 ⇒ collapsed) and returns the style to render with plus the
60
+ * handler to attach to the native component. While collapsed and
61
+ * `collapseOnNoFill` is on, the host style is overridden with `height: 0` so
62
+ * the Yoga box shrinks along with the native view; a non-zero size restores
63
+ * the host style. The user's `onSizeChange` always receives the plain
64
+ * `{ width, height }` payload.
65
+ */
66
+ function useCollapsibleAdStyle(
67
+ style: StyleProp<ViewStyle>,
68
+ collapseOnNoFill: boolean,
69
+ onSizeChange?: (size: EzoicAdSize) => void
70
+ ) {
71
+ const [collapsed, setCollapsed] = useState(false);
72
+ const handleSizeChange = (e: NativeSyntheticEvent<EzoicAdSize>) => {
73
+ const { width, height } = e.nativeEvent;
74
+ setCollapsed(height === 0);
75
+ onSizeChange?.({ width, height });
76
+ };
77
+ const resolvedStyle: StyleProp<ViewStyle> =
78
+ collapseOnNoFill !== false && collapsed ? [style, { height: 0 }] : style;
79
+ return { style: resolvedStyle, onSizeChange: handleSizeChange };
80
+ }
81
+
47
82
  export interface EzoicBannerViewProps {
48
83
  adUnitIdentifier: string;
49
84
  size?: string;
50
85
  style?: StyleProp<ViewStyle>;
86
+ /** Collapse the view (height 0) when a load fails and no ad is displayed. Default `true`. */
87
+ collapseOnNoFill?: boolean;
51
88
  onLoad?: () => void;
52
89
  onError?: (error: EzoicBannerError) => void;
53
90
  onImpression?: () => void;
54
91
  onClick?: () => void;
55
92
  onOpen?: () => void;
56
93
  onClose?: () => void;
94
+ /** Displayed ad size changed: the creative size after a load, or 0x0 on collapse. */
95
+ onSizeChange?: (size: EzoicAdSize) => void;
57
96
  }
58
97
 
59
98
  export function EzoicBannerView(props: EzoicBannerViewProps) {
60
99
  const {
61
100
  adUnitIdentifier,
62
101
  size,
102
+ style,
103
+ collapseOnNoFill = true,
63
104
  onLoad,
64
105
  onError,
65
106
  onImpression,
66
107
  onClick,
67
108
  onOpen,
68
109
  onClose,
110
+ onSizeChange,
69
111
  ...rest
70
112
  } = props;
113
+ const collapsible = useCollapsibleAdStyle(
114
+ style,
115
+ collapseOnNoFill,
116
+ onSizeChange
117
+ );
71
118
  return (
72
119
  <EzoicBannerNative
73
120
  {...rest}
121
+ style={collapsible.style}
74
122
  adUnitIdentifier={coerceAdUnitId(adUnitIdentifier)}
75
123
  size={normalizeSize(size)}
124
+ collapseOnNoFill={collapseOnNoFill}
76
125
  onLoad={onLoad ? () => onLoad() : undefined}
77
126
  onError={onError ? (e) => onError(e.nativeEvent) : undefined}
78
127
  onImpression={onImpression ? () => onImpression() : undefined}
79
128
  onAdClick={onClick ? () => onClick() : undefined}
80
129
  onOpen={onOpen ? () => onOpen() : undefined}
81
130
  onClose={onClose ? () => onClose() : undefined}
131
+ onSizeChange={collapsible.onSizeChange}
82
132
  />
83
133
  );
84
134
  }
@@ -137,41 +187,57 @@ export interface EzoicOutstreamAdError {
137
187
  export interface EzoicOutstreamAdViewProps {
138
188
  adUnitIdentifier: string | number;
139
189
  style?: StyleProp<ViewStyle>;
190
+ /** Collapse the view (height 0) when a load fails and no ad is displayed. Default `true`. */
191
+ collapseOnNoFill?: boolean;
140
192
  onLoad?: () => void;
141
193
  onError?: (error: EzoicOutstreamAdError) => void;
142
194
  onImpression?: () => void;
143
195
  onClick?: () => void;
144
196
  onOpen?: () => void;
145
197
  onClose?: () => void;
198
+ /** Displayed ad size changed: the creative size after a load, or 0x0 on collapse. */
199
+ onSizeChange?: (size: EzoicAdSize) => void;
146
200
  }
147
201
 
148
202
  /**
149
203
  * Renders an outstream video ad in an SDK-built player. Outstream video runs on
150
204
  * its own (not inside host video content), so the SDK owns the player and this
151
205
  * component only needs a size. Fills the bounds it is given by its RN style, so
152
- * size it with `style` (e.g. `{ width: '100%', height: 200 }`).
206
+ * size it with `style` (e.g. `{ width: '100%', height: 200 }`). While collapsed
207
+ * after a no-fill (see `collapseOnNoFill`) the height is forced to 0.
153
208
  */
154
209
  export function EzoicOutstreamAdView(props: EzoicOutstreamAdViewProps) {
155
210
  const {
156
211
  adUnitIdentifier,
212
+ style,
213
+ collapseOnNoFill = true,
157
214
  onLoad,
158
215
  onError,
159
216
  onImpression,
160
217
  onClick,
161
218
  onOpen,
162
219
  onClose,
220
+ onSizeChange,
163
221
  ...rest
164
222
  } = props;
223
+ const collapsible = useCollapsibleAdStyle(
224
+ style,
225
+ collapseOnNoFill,
226
+ onSizeChange
227
+ );
165
228
  return (
166
229
  <EzoicOutstreamNative
167
230
  {...rest}
231
+ style={collapsible.style}
168
232
  adUnitIdentifier={coerceAdUnitId(adUnitIdentifier)}
233
+ collapseOnNoFill={collapseOnNoFill}
169
234
  onLoad={onLoad ? () => onLoad() : undefined}
170
235
  onError={onError ? (e) => onError(e.nativeEvent) : undefined}
171
236
  onImpression={onImpression ? () => onImpression() : undefined}
172
237
  onAdClick={onClick ? () => onClick() : undefined}
173
238
  onOpen={onOpen ? () => onOpen() : undefined}
174
239
  onClose={onClose ? () => onClose() : undefined}
240
+ onSizeChange={collapsible.onSizeChange}
175
241
  />
176
242
  );
177
243
  }