react-native-firework-sdk 2.15.3 → 2.16.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.
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +1 -2
- package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCustomCta.kt +7 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModel.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelDeserializer.kt +3 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelSerializer.kt +2 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +5 -1
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt +2 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWEventName.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +10 -2
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +20 -1
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +7 -0
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWModelUtils.kt +18 -1
- package/ios/Components/StoryBlock.swift +1 -1
- package/ios/Components/VideoFeed.swift +1 -1
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +1 -0
- package/ios/Modules/Shopping/ShoppingModule.swift +12 -0
- package/lib/typescript/models/FWEvents.d.ts +18 -0
- package/lib/typescript/models/VideoPlayerConfiguration.d.ts +0 -1
- package/package.json +1 -1
- package/react-native-firework-sdk.podspec +2 -2
- package/src/models/FWEvents.ts +22 -0
- package/src/models/VideoPlayerConfiguration.ts +0 -1
|
@@ -2,7 +2,6 @@ package com.fireworksdk.bridge.components.videofeed
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.util.AttributeSet
|
|
5
|
-
import android.view.ViewGroup
|
|
6
5
|
import android.widget.FrameLayout
|
|
7
6
|
import com.firework.error.FwErrorListener
|
|
8
7
|
import com.firework.videofeed.FeedViewStateListener
|
|
@@ -29,7 +28,7 @@ class FWVideoFeed(
|
|
|
29
28
|
init {
|
|
30
29
|
FWLanguageUtil.getInstance(context).updateBaseContextLocale(context)
|
|
31
30
|
videoFeedView.layoutDirection = LAYOUT_DIRECTION_LOCALE
|
|
32
|
-
addView(videoFeedView, LayoutParams(
|
|
31
|
+
addView(videoFeedView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
fun setVideoFeedLayoutParams(l: LayoutParams?) {
|
package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelDeserializer.kt
CHANGED
|
@@ -7,6 +7,7 @@ object FWVideoFeedConfigModelDeserializer {
|
|
|
7
7
|
|
|
8
8
|
private const val BACKGROUND_COLOR_KEY = "backgroundColor"
|
|
9
9
|
private const val CORNER_RADIUS_KEY = "cornerRadius"
|
|
10
|
+
private const val ASPECT_RATIO_KEY = "aspectRatio"
|
|
10
11
|
private const val TITLE_KEY = "title"
|
|
11
12
|
private const val TITLE_POSITION_KEY = "titlePosition"
|
|
12
13
|
private const val PLAY_ICON_KEY = "playIcon"
|
|
@@ -29,6 +30,7 @@ object FWVideoFeedConfigModelDeserializer {
|
|
|
29
30
|
|
|
30
31
|
val backgroundColor = if (responseJson.has(BACKGROUND_COLOR_KEY)) responseJson.optString(BACKGROUND_COLOR_KEY) else null
|
|
31
32
|
val cornerRadius = if (!responseJson.isNull(CORNER_RADIUS_KEY)) responseJson.optInt(CORNER_RADIUS_KEY) else null
|
|
33
|
+
val aspectRatio = if (!responseJson.isNull(ASPECT_RATIO_KEY)) responseJson.optDouble(ASPECT_RATIO_KEY) else null
|
|
32
34
|
val title = if (responseJson.has(TITLE_KEY)) deserializeTitle(responseJson.optJSONObject(TITLE_KEY)) else null
|
|
33
35
|
val titlePosition = if (responseJson.has(TITLE_POSITION_KEY)) responseJson.optString(TITLE_POSITION_KEY) else null
|
|
34
36
|
val playIcon = if (responseJson.has(PLAY_ICON_KEY)) deserializePlayIcon(responseJson.optJSONObject(PLAY_ICON_KEY)) else null
|
|
@@ -47,6 +49,7 @@ object FWVideoFeedConfigModelDeserializer {
|
|
|
47
49
|
enableAutoplay = enableAutoplay,
|
|
48
50
|
gridColumns = gridColumns,
|
|
49
51
|
itemSpacing = itemSpacing,
|
|
52
|
+
aspectRatio = aspectRatio,
|
|
50
53
|
)
|
|
51
54
|
}
|
|
52
55
|
|
package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelSerializer.kt
CHANGED
|
@@ -7,6 +7,7 @@ object FWVideoFeedConfigModelSerializer {
|
|
|
7
7
|
|
|
8
8
|
private const val BACKGROUND_COLOR_KEY = "backgroundColor"
|
|
9
9
|
private const val CORNER_RADIUS_KEY = "cornerRadius"
|
|
10
|
+
private const val ASPECT_RATIO_KEY = "aspectRatio"
|
|
10
11
|
private const val TITLE_KEY = "title"
|
|
11
12
|
private const val TITLE_POSITION_KEY = "titlePosition"
|
|
12
13
|
private const val PLAY_ICON_KEY = "playIcon"
|
|
@@ -29,6 +30,7 @@ object FWVideoFeedConfigModelSerializer {
|
|
|
29
30
|
val jsonObject = JSONObject()
|
|
30
31
|
jsonObject.put(BACKGROUND_COLOR_KEY, model.backgroundColor)
|
|
31
32
|
jsonObject.put(CORNER_RADIUS_KEY, model.cornerRadius)
|
|
33
|
+
jsonObject.put(ASPECT_RATIO_KEY, model.aspectRatio)
|
|
32
34
|
jsonObject.put(TITLE_KEY, serializeTitle(model.title))
|
|
33
35
|
jsonObject.put(TITLE_POSITION_KEY, FWVideoFeedTitlePosition.serialize(model.titlePosition))
|
|
34
36
|
jsonObject.put(PLAY_ICON_KEY, serializePlayIcon(model.playIcon))
|
package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt
CHANGED
|
@@ -38,6 +38,7 @@ object FWVideoPlayerConfigModelDeserializer {
|
|
|
38
38
|
private const val SHOW_FULL_SCREEN_ICON = "enableFullScreen"
|
|
39
39
|
private const val ENABLE_AUTOPLAY = "enableAutoplay"
|
|
40
40
|
private const val ENABLE_AUTOPAUSE = "enableAutopause"
|
|
41
|
+
private const val ENABLE_SMALL_SIZE_IN_COMPACT = "enableSmallSizeInCompact"
|
|
41
42
|
|
|
42
43
|
fun deserialize(responseJson: JSONObject?): FWVideoPlayerConfigModel? {
|
|
43
44
|
responseJson ?: return null
|
|
@@ -66,6 +67,8 @@ object FWVideoPlayerConfigModelDeserializer {
|
|
|
66
67
|
if (responseJson.has(ENABLE_AUTOPLAY)) responseJson.optBoolean(ENABLE_AUTOPLAY) else null
|
|
67
68
|
val enableAutoPause =
|
|
68
69
|
if (responseJson.has(ENABLE_AUTOPAUSE)) responseJson.optBoolean(ENABLE_AUTOPAUSE) else null
|
|
70
|
+
val enableSmallSizeInCompact =
|
|
71
|
+
if (responseJson.has(ENABLE_SMALL_SIZE_IN_COMPACT)) responseJson.optBoolean(ENABLE_SMALL_SIZE_IN_COMPACT) else null
|
|
69
72
|
|
|
70
73
|
return FWVideoPlayerConfigModel(
|
|
71
74
|
playerStyle = if (!playerStyle.isNullOrBlank()) FWPlayerStyle.deserialize(playerStyle) else null,
|
|
@@ -88,7 +91,8 @@ object FWVideoPlayerConfigModelDeserializer {
|
|
|
88
91
|
cancelButtonStyle = FWActionButtonDeserializer.deserialize(cancelButtonStyleJsonObject),
|
|
89
92
|
showFullScreenIcon = showFullScreenIcon,
|
|
90
93
|
enableAutoPlay = enableAutoPlay,
|
|
91
|
-
enableAutoPause = enableAutoPause
|
|
94
|
+
enableAutoPause = enableAutoPause,
|
|
95
|
+
enableSmallSizeInCompact = enableSmallSizeInCompact
|
|
92
96
|
)
|
|
93
97
|
}
|
|
94
98
|
|
package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt
CHANGED
|
@@ -38,6 +38,7 @@ object FWVideoPlayerConfigModelSerializer {
|
|
|
38
38
|
private const val SHOW_FULL_SCREEN_ICON = "enableFullScreen"
|
|
39
39
|
private const val ENABLE_AUTOPLAY = "enableAutoplay"
|
|
40
40
|
private const val ENABLE_AUTOPAUSE = "enableAutopause"
|
|
41
|
+
private const val ENABLE_SMALL_SIZE_IN_COMPACT = "enableSmallSizeInCompact"
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
fun serialize(model: FWVideoPlayerConfigModel?): JSONObject? {
|
|
@@ -64,6 +65,7 @@ object FWVideoPlayerConfigModelSerializer {
|
|
|
64
65
|
jsonObject.put(SHOW_FULL_SCREEN_ICON, model.showFullScreenIcon)
|
|
65
66
|
jsonObject.put(ENABLE_AUTOPLAY, model.enableAutoPlay)
|
|
66
67
|
jsonObject.put(ENABLE_AUTOPAUSE, model.enableAutoPause)
|
|
68
|
+
jsonObject.put(ENABLE_SMALL_SIZE_IN_COMPACT, model.enableSmallSizeInCompact)
|
|
67
69
|
return jsonObject
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -7,6 +7,7 @@ enum class FWEventName(val rawValue: String) {
|
|
|
7
7
|
VideoFeedClick("fw:video-feed-click"),
|
|
8
8
|
LiveStream("fw:livestream"),
|
|
9
9
|
LiveStreamChat("fw:livestream-chat"),
|
|
10
|
+
LiveStreamLinkInteractionClick("fw:livestream:custom-link-interaction-click"),
|
|
10
11
|
LogMessage("fw:log-message"),
|
|
11
12
|
CustomShareURL("fw:custom-share-url")
|
|
12
13
|
}
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt
CHANGED
|
@@ -289,8 +289,16 @@ class FWVideoShoppingModule(
|
|
|
289
289
|
ctaHandler = Triple(callbackId, productId, unitId)
|
|
290
290
|
|
|
291
291
|
val videoPlaybackDetails = FWModelUtils.convertVideoInfo2PlaybackDetails(videoInfo)
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
val customCtaDetails = FWModelUtils.convertVideoInfo2CustomCta(product)
|
|
293
|
+
|
|
294
|
+
FWEventUtils.sendShoppingCtaButtonClickEvent(
|
|
295
|
+
reactContext = reactApplicationContext,
|
|
296
|
+
productId = productId,
|
|
297
|
+
unitId = unitId,
|
|
298
|
+
url = productWebUrl,
|
|
299
|
+
info = videoPlaybackDetails,
|
|
300
|
+
customCta = customCtaDetails,
|
|
301
|
+
callbackId = callbackId)
|
|
294
302
|
}
|
|
295
303
|
|
|
296
304
|
FireworkSdk.shopping.setOnShoppingErrorListener(
|
|
@@ -90,6 +90,14 @@ object FWEventUtils {
|
|
|
90
90
|
return contentMap
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
private fun convertCustomCta2Map(info: FWShoppingCustomCta): WritableMap {
|
|
94
|
+
val contentMap = Arguments.createMap()
|
|
95
|
+
contentMap.putString("url", info.url)
|
|
96
|
+
contentMap.putString("titleKey", info.titleKey)
|
|
97
|
+
contentMap.putString("title", info.title)
|
|
98
|
+
return contentMap
|
|
99
|
+
}
|
|
100
|
+
|
|
93
101
|
private fun convertVideoPlaybackDetails2Map(info: FWVideoPlaybackDetails?): WritableMap {
|
|
94
102
|
val contentMap = Arguments.createMap()
|
|
95
103
|
if (!info?.id.isNullOrBlank()) {
|
|
@@ -129,13 +137,24 @@ object FWEventUtils {
|
|
|
129
137
|
return contentMap;
|
|
130
138
|
}
|
|
131
139
|
|
|
132
|
-
fun sendShoppingCtaButtonClickEvent(
|
|
140
|
+
fun sendShoppingCtaButtonClickEvent(
|
|
141
|
+
reactContext: ReactContext,
|
|
142
|
+
productId: String?,
|
|
143
|
+
unitId: String?,
|
|
144
|
+
url: String?,
|
|
145
|
+
info: FWVideoPlaybackDetails?,
|
|
146
|
+
customCta: FWShoppingCustomCta?,
|
|
147
|
+
callbackId: Int?
|
|
148
|
+
) {
|
|
133
149
|
val eventMap = Arguments.createMap()
|
|
134
150
|
eventMap.putString("productId", productId)
|
|
135
151
|
eventMap.putString("unitId", unitId)
|
|
136
152
|
eventMap.putString("url", url)
|
|
137
153
|
eventMap.putInt("callbackId", callbackId?:0)
|
|
138
154
|
eventMap.putMap("video", convertVideoPlaybackDetails2Map(info))
|
|
155
|
+
customCta?.let {
|
|
156
|
+
eventMap.putMap("customCTA", convertCustomCta2Map(it))
|
|
157
|
+
}
|
|
139
158
|
sendEvent(reactContext, FWVideoShoppingEventName.CtaButtonClick.rawValue, eventMap)
|
|
140
159
|
}
|
|
141
160
|
|
|
@@ -151,6 +151,11 @@ object FWConfigUtil {
|
|
|
151
151
|
.roundedCornerRadius(FWCommonUtil.dpToPx(cornerRadius.toFloat(), context))
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
val aspectRatio = videoFeedPropsModel.videoFeedConfiguration?.aspectRatio
|
|
155
|
+
if (aspectRatio != null && aspectRatio > 0) {
|
|
156
|
+
layoutOptionBuilder.aspectRatio(aspectRatio)
|
|
157
|
+
}
|
|
158
|
+
|
|
154
159
|
val title = videoFeedPropsModel.videoFeedConfiguration?.title
|
|
155
160
|
if (title != null) {
|
|
156
161
|
val titleHidden = title.hidden
|
|
@@ -563,6 +568,8 @@ object FWConfigUtil {
|
|
|
563
568
|
storyblockOptionBuilder.showFullScreenIcon(showFullScreenIcon)}
|
|
564
569
|
videoFeedPropsModel.videoPlayerConfiguration?.enableAutoPause?.let { enableAutoPause ->
|
|
565
570
|
storyblockOptionBuilder.enableAutoPause(enableAutoPause)}
|
|
571
|
+
videoFeedPropsModel.videoPlayerConfiguration?.enableSmallSizeInCompact?.let { enableSmallSizeInCompact ->
|
|
572
|
+
storyblockOptionBuilder.enableSmallSizeInCompact(enableSmallSizeInCompact)}
|
|
566
573
|
|
|
567
574
|
playerOptionBuilder.shareUrlCustomCallBack(FWGlobalDataUtil.customShareUrlCallback)
|
|
568
575
|
|
|
@@ -5,7 +5,9 @@ import com.firework.analyticsevents.VideoType
|
|
|
5
5
|
import com.firework.analyticsevents.cta.CtaButtonClickAnalyticsEvent
|
|
6
6
|
import com.firework.analyticsevents.player.PlayerLifecycleAnalyticsEvent
|
|
7
7
|
import com.firework.analyticsevents.share.ShareButtonAnalyticsEvent
|
|
8
|
+
import com.firework.common.product.Product
|
|
8
9
|
import com.fireworksdk.bridge.models.FWLiveStreamEventDetailsModel
|
|
10
|
+
import com.fireworksdk.bridge.models.FWShoppingCustomCta
|
|
9
11
|
import com.fireworksdk.bridge.models.FWVideoPlaybackDetails
|
|
10
12
|
|
|
11
13
|
object FWModelUtils {
|
|
@@ -45,6 +47,21 @@ object FWModelUtils {
|
|
|
45
47
|
)
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
fun convertVideoInfo2CustomCta(product: Product?): FWShoppingCustomCta? {
|
|
51
|
+
val url = product?.customCTAUrl
|
|
52
|
+
val title = product?.customCTATitleTranslation
|
|
53
|
+
val titleKey = product?.customCTATitle
|
|
54
|
+
return if (!url.isNullOrBlank() && !titleKey.isNullOrBlank() && !title.isNullOrBlank() && product.isCustomCtaPrimary) {
|
|
55
|
+
FWShoppingCustomCta(
|
|
56
|
+
url = url,
|
|
57
|
+
titleKey = titleKey,
|
|
58
|
+
title = title,
|
|
59
|
+
)
|
|
60
|
+
} else {
|
|
61
|
+
null
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
48
65
|
fun convertVideoInfo2LivestreamDetails(videoInfo: VideoInfo): FWLiveStreamEventDetailsModel {
|
|
49
66
|
return FWLiveStreamEventDetailsModel(
|
|
50
67
|
id = videoInfo.id,
|
|
@@ -101,4 +118,4 @@ object FWModelUtils {
|
|
|
101
118
|
)
|
|
102
119
|
}
|
|
103
120
|
|
|
104
|
-
}
|
|
121
|
+
}
|
|
@@ -79,7 +79,7 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate, PictureInPict
|
|
|
79
79
|
case .sku:
|
|
80
80
|
return .skuPlaylist(channelID: channel, productIDs: (productIds as? [String]) ?? [])
|
|
81
81
|
case .singleContent:
|
|
82
|
-
return .singleContent(
|
|
82
|
+
return .singleContent(contentID: contentId)
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
private var isInPip: Bool = false
|
|
@@ -105,7 +105,7 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate, PictureInPictur
|
|
|
105
105
|
case .sku:
|
|
106
106
|
return .skuPlaylist(channelID: channel, productIDs: (productIds as? [String]) ?? [])
|
|
107
107
|
case .singleContent:
|
|
108
|
-
return .singleContent(
|
|
108
|
+
return .singleContent(contentID: contentId)
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -230,6 +230,18 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate {
|
|
|
230
230
|
var body = item.jsObject
|
|
231
231
|
body["callbackId"] = callbackId
|
|
232
232
|
body["video"] = video.jsObject
|
|
233
|
+
if let product = item.product,
|
|
234
|
+
product.hasCustomPrimaryCTA,
|
|
235
|
+
let customCTA = product.customCTA,
|
|
236
|
+
let url = customCTA.url,
|
|
237
|
+
let title = customCTA.title,
|
|
238
|
+
let titleTranslation = customCTA.titleTranslation {
|
|
239
|
+
body["customCTA"] = [
|
|
240
|
+
"url": url,
|
|
241
|
+
"titleKey": title,
|
|
242
|
+
"title": titleTranslation
|
|
243
|
+
]
|
|
244
|
+
}
|
|
233
245
|
sendEvent(
|
|
234
246
|
withName: ShoppingEventName.ctaButtonClick.rawValue,
|
|
235
247
|
body: body)
|
|
@@ -46,6 +46,20 @@ export interface VideoPlaybackEvent {
|
|
|
46
46
|
export interface VideoFeedClickEvent {
|
|
47
47
|
info: FeedItemDetails;
|
|
48
48
|
}
|
|
49
|
+
export interface CustomCTA {
|
|
50
|
+
/**
|
|
51
|
+
* Action URL that is associated with this CTA
|
|
52
|
+
*/
|
|
53
|
+
url: string;
|
|
54
|
+
/**
|
|
55
|
+
* The title key of the CTA, such as buy_now.
|
|
56
|
+
*/
|
|
57
|
+
titleKey: string;
|
|
58
|
+
/**
|
|
59
|
+
* The title of the CTA, such as "Buy Now".
|
|
60
|
+
*/
|
|
61
|
+
title: string;
|
|
62
|
+
}
|
|
49
63
|
export interface ShoppingCTAEvent {
|
|
50
64
|
/**
|
|
51
65
|
* The url for the product unit
|
|
@@ -63,6 +77,10 @@ export interface ShoppingCTAEvent {
|
|
|
63
77
|
* The video playback details for the event.
|
|
64
78
|
*/
|
|
65
79
|
video: VideoPlaybackDetails;
|
|
80
|
+
/**
|
|
81
|
+
* This property only has value when configuring a custom product primary CTA in the business portal.
|
|
82
|
+
*/
|
|
83
|
+
customCTA?: CustomCTA;
|
|
66
84
|
}
|
|
67
85
|
export interface UpdateProductDetailsEvent {
|
|
68
86
|
/**
|
package/package.json
CHANGED
package/src/models/FWEvents.ts
CHANGED
|
@@ -55,6 +55,23 @@ export interface VideoFeedClickEvent {
|
|
|
55
55
|
info: FeedItemDetails;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
export interface CustomCTA {
|
|
59
|
+
/**
|
|
60
|
+
* Action URL that is associated with this CTA
|
|
61
|
+
*/
|
|
62
|
+
url: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The title key of the CTA, such as buy_now.
|
|
66
|
+
*/
|
|
67
|
+
titleKey: string;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The title of the CTA, such as "Buy Now".
|
|
71
|
+
*/
|
|
72
|
+
title: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
58
75
|
export interface ShoppingCTAEvent {
|
|
59
76
|
/**
|
|
60
77
|
* The url for the product unit
|
|
@@ -72,6 +89,11 @@ export interface ShoppingCTAEvent {
|
|
|
72
89
|
* The video playback details for the event.
|
|
73
90
|
*/
|
|
74
91
|
video: VideoPlaybackDetails;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* This property only has value when configuring a custom product primary CTA in the business portal.
|
|
95
|
+
*/
|
|
96
|
+
customCTA?: CustomCTA;
|
|
75
97
|
}
|
|
76
98
|
|
|
77
99
|
export interface UpdateProductDetailsEvent {
|