react-native-glance-chat 0.1.9 → 0.1.13

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.
@@ -9,7 +9,9 @@ buildscript {
9
9
  // example/android/settings.gradle and the README integration section. During local
10
10
  // development, publish with `./gradlew publishToMavenLocal -Psdk.version=1.0.0`
11
11
  // (produces 1.0.0-local) and set sdkVersion to "1.0.0-local" to resolve from mavenLocal().
12
- sdkVersion: "1.0.15"
12
+ // 1.0.16 is the first SDK release with `GlanceChatSDK.setUser`; it must be published
13
+ // before this wrapper version can build or ship.
14
+ sdkVersion: "1.0.18"
13
15
  ]
14
16
 
15
17
  ext.getExtOrDefault = { prop ->
@@ -11,6 +11,7 @@ import com.facebook.react.bridge.ReadableMap
11
11
  import com.facebook.react.modules.core.DeviceEventManagerModule
12
12
  import com.glance.chat.GlanceChatSDK
13
13
  import com.glance.chat.core.config.GlanceChatConfig
14
+ import com.glance.chat.core.config.GlanceTheme
14
15
  import kotlinx.coroutines.CoroutineScope
15
16
  import kotlinx.coroutines.Dispatchers
16
17
  import kotlinx.coroutines.SupervisorJob
@@ -54,11 +55,37 @@ class GlanceChatModuleImpl(private val reactContext: ReactApplicationContext) {
54
55
  Arguments.createMap().apply {
55
56
  putString("productId", product.id)
56
57
  putString("name", product.name)
58
+ // The host may navigate from the click alone: the deeplink is blank for some
59
+ // catalogue entries, and the merchant variant id is what the host's product
60
+ // page needs when there is no URL to parse.
61
+ putString("deeplinkUrl", product.deeplinkUrl)
62
+ putString("merchantVariantId", product.merchantVariantId)
57
63
  }
58
64
  )
59
65
  product.deeplinkUrl.takeIf { it.isNotBlank() }?.let { emit(EVENT_DEEPLINK_CLICK, it) }
60
66
  }
61
67
 
68
+ // The host owns the cart. The shopper's confirmed size selection arrives here and JS
69
+ // adds it through the host's own cart action (Appmaker's ADD_TO_CART_V2).
70
+ GlanceChatSDK.addToCartHandler = { item ->
71
+ emit(
72
+ EVENT_ADD_TO_CART,
73
+ Arguments.createMap().apply {
74
+ putString("productId", item.productId)
75
+ putString("productName", item.productName)
76
+ putString("productImageUrl", item.productImageUrl)
77
+ putString("productPrice", item.productPrice)
78
+ putString("deeplinkUrl", item.deeplinkUrl)
79
+ putString("merchantVariantId", item.merchantVariantId)
80
+ putString("sizeId", item.sizeId)
81
+ putString("sizeLabel", item.sizeLabel)
82
+ putInt("quantity", item.quantity)
83
+ }
84
+ )
85
+ }
86
+
87
+ GlanceChatSDK.viewCartHandler = { emit(EVENT_VIEW_CART, Arguments.createMap()) }
88
+
62
89
  // Auth token cannot be fetched/refreshed — host should re-authenticate.
63
90
  GlanceChatSDK.onSessionExpired = {
64
91
  emit(EVENT_SESSION_EXPIRED, Arguments.createMap())
@@ -68,11 +95,30 @@ class GlanceChatModuleImpl(private val reactContext: ReactApplicationContext) {
68
95
  }
69
96
  }
70
97
 
98
+ /**
99
+ * Follows the host's login/logout without tearing the SDK down. Requires a Glance SDK
100
+ * that exposes `setUser`; against an older AAR this is a logged no-op so the host keeps
101
+ * the identity it initialized with instead of crashing.
102
+ */
103
+ fun setUser(userId: String) {
104
+ runOnMain {
105
+ try {
106
+ GlanceChatSDK.setUser(userId)
107
+ } catch (error: NoSuchMethodError) {
108
+ Log.w(TAG, "Glance SDK ${BuildConfig.SDK_VERSION} has no setUser(); identity unchanged", error)
109
+ } catch (error: NoClassDefFoundError) {
110
+ Log.w(TAG, "Glance SDK ${BuildConfig.SDK_VERSION} has no setUser(); identity unchanged", error)
111
+ }
112
+ }
113
+ }
114
+
71
115
  fun destroy() {
72
116
  runOnMain {
73
117
  scope?.cancel()
74
118
  scope = null
75
119
  GlanceChatSDK.productNavigationHandler = null
120
+ GlanceChatSDK.addToCartHandler = null
121
+ GlanceChatSDK.viewCartHandler = null
76
122
  GlanceChatSDK.onSessionExpired = null
77
123
  GlanceChatSDK.destroy()
78
124
  }
@@ -113,12 +159,36 @@ class GlanceChatModuleImpl(private val reactContext: ReactApplicationContext) {
113
159
  .userId(resolvedUserId)
114
160
  .environment(parseEnvironment(config.getString("environment")))
115
161
  .storeHandle(config.getString("storeHandle") ?: "")
162
+ // The catalogue tenant id differs from the Shopify handle when the merchant sells on a
163
+ // custom domain; mix-and-match and similar-products resolve by this id.
164
+ .catalogId(config.getString("catalogId") ?: "")
165
+ .storefrontBaseUrl(config.getString("storefrontBaseUrl") ?: "")
166
+ // X-Store-Region: the backend filters mix-and-match recommendations by it.
167
+ .countryCode(config.getString("countryCode") ?: "")
116
168
  .showTryOnProgressPill(
117
169
  if (config.hasKey("showTryOnProgressPill")) config.getBoolean("showTryOnProgressPill") else true
118
170
  )
171
+ // Appearance settings for the SDK's own composables. Each is optional: GlanceTheme's
172
+ // defaults reproduce the hardcoded values the SDK shipped with, so an older host config
173
+ // (or a field the merchant never set) renders exactly as before.
174
+ .theme(
175
+ GlanceTheme(
176
+ brandAccentColor = config.optString("brandAccentColor", ""),
177
+ mnmStyleOnMeRadius = config.optString("mnmStyleOnMeRadius", ""),
178
+ mnmAddToCartRadius = config.optString("mnmAddToCartRadius", ""),
179
+ mnmCartIconRadius = config.optString("mnmCartIconRadius", ""),
180
+ onboardingContinueRadius = config.optString("onboardingContinueRadius", ""),
181
+ onboardingGenderRadius = config.optString("onboardingGenderRadius", "")
182
+ )
183
+ )
119
184
  .build()
120
185
  }
121
186
 
187
+ // ReadableMap has no generic "string or default" helper across the old/new arch impls, and
188
+ // a missing key must not throw — a blank string lets GlanceTheme apply its own default.
189
+ private fun ReadableMap.optString(key: String, fallback: String): String =
190
+ if (hasKey(key) && !isNull(key)) getString(key) ?: fallback else fallback
191
+
122
192
  @Suppress("HardwareIds")
123
193
  private fun androidId(): String =
124
194
  Settings.Secure.getString(reactContext.contentResolver, Settings.Secure.ANDROID_ID) ?: "anonymous"
@@ -162,6 +232,8 @@ class GlanceChatModuleImpl(private val reactContext: ReactApplicationContext) {
162
232
  private const val EVENT_TRY_ON_STATES = "onTryOnStatesChanged"
163
233
  private const val EVENT_PRODUCT_CLICK = "onProductClick"
164
234
  private const val EVENT_DEEPLINK_CLICK = "onDeeplinkClick"
235
+ private const val EVENT_ADD_TO_CART = "onAddToCart"
236
+ private const val EVENT_VIEW_CART = "onViewCart"
165
237
  private const val EVENT_SESSION_EXPIRED = "onSessionExpired"
166
238
  }
167
239
  }
@@ -53,6 +53,12 @@ class GlanceMixAndMatchWidgetViewManager :
53
53
  "bubbled" to "onAddToCartClick",
54
54
  "captured" to "onAddToCartClickCapture"
55
55
  )
56
+ ),
57
+ "onContentStateChange" to mapOf(
58
+ "phasedRegistrationNames" to mapOf(
59
+ "bubbled" to "onContentStateChange",
60
+ "captured" to "onContentStateChangeCapture"
61
+ )
56
62
  )
57
63
  )
58
64
  }
@@ -61,26 +67,59 @@ class GlanceMixAndMatchWidgetViewManager :
61
67
  surfaceId: Int,
62
68
  viewId: Int,
63
69
  private val productId: String,
64
- private val size: String
70
+ private val productTitle: String,
71
+ private val productImageUrl: String,
72
+ private val productPrice: String?,
73
+ private val productDeeplinkUrl: String?,
74
+ private val merchantVariantId: String?,
75
+ private val sizeId: String,
76
+ private val sizeLabel: String
65
77
  ) : Event<AddToCartEvent>(surfaceId, viewId) {
66
78
  override fun getEventName() = "onAddToCartClick"
67
79
  override fun getEventData() = Arguments.createMap().apply {
68
80
  putString("productId", productId)
69
- putString("size", size)
81
+ putString("productTitle", productTitle)
82
+ putString("productImageUrl", productImageUrl)
83
+ putString("productPrice", productPrice)
84
+ putString("productDeeplinkUrl", productDeeplinkUrl)
85
+ putString("merchantVariantId", merchantVariantId)
86
+ // `sizeId` is the purchasable merchant variant id; `sizeLabel` is the
87
+ // display label ("M"). `size` is kept for older extension builds only.
88
+ putString("sizeId", sizeId)
89
+ putString("sizeLabel", sizeLabel)
90
+ putString("size", sizeLabel)
91
+ }
92
+ }
93
+
94
+ private class ContentStateEvent(
95
+ surfaceId: Int,
96
+ viewId: Int,
97
+ private val status: String,
98
+ private val itemCount: Int
99
+ ) : Event<ContentStateEvent>(surfaceId, viewId) {
100
+ override fun getEventName() = "onContentStateChange"
101
+ override fun getEventData() = Arguments.createMap().apply {
102
+ putString("status", status)
103
+ putInt("itemCount", itemCount)
70
104
  }
71
105
  }
72
106
 
73
107
  private class WidgetHostLayout(context: ThemedReactContext) : FrameLayout(context) {
74
108
  private var composeView: ComposeView? = null
75
109
 
110
+ // Fabric commits every prop on each React render, changed or not. Without these guards
111
+ // each commit called renderContent() → setContent{}, which restarted the widget's
112
+ // fetch effect — one recommendations request per parent re-render.
76
113
  var variantId: String = ""
77
114
  set(value) {
115
+ if (field == value) return
78
116
  field = value
79
117
  if (isAttachedToWindow) renderContent()
80
118
  }
81
119
 
82
120
  var widgetEnabled: Boolean = true
83
121
  set(value) {
122
+ if (field == value) return
84
123
  field = value
85
124
  if (isAttachedToWindow) renderContent()
86
125
  }
@@ -111,7 +150,19 @@ class GlanceMixAndMatchWidgetViewManager :
111
150
  MixAndMatchWidget(
112
151
  merchantVariantId = currentVariantId,
113
152
  onAddToCartClick = { product, size ->
114
- emitAddToCart(product.id, size.value)
153
+ emitAddToCart(
154
+ productId = product.id,
155
+ productTitle = product.name,
156
+ productImageUrl = product.imageUrl,
157
+ productPrice = product.price,
158
+ productDeeplinkUrl = product.deeplinkUrl,
159
+ merchantVariantId = product.merchantVariantId,
160
+ sizeId = size.id,
161
+ sizeLabel = size.value
162
+ )
163
+ },
164
+ onContentStateChange = { status, itemCount ->
165
+ emitContentState(status?.name ?: "", itemCount)
115
166
  }
116
167
  )
117
168
  }
@@ -128,11 +179,40 @@ class GlanceMixAndMatchWidgetViewManager :
128
179
  child.layout(0, 0, width, height)
129
180
  }
130
181
 
131
- private fun emitAddToCart(productId: String, size: String) {
182
+ private fun emitAddToCart(
183
+ productId: String,
184
+ productTitle: String,
185
+ productImageUrl: String,
186
+ productPrice: String?,
187
+ productDeeplinkUrl: String?,
188
+ merchantVariantId: String?,
189
+ sizeId: String,
190
+ sizeLabel: String
191
+ ) {
192
+ val reactContext = context as? ThemedReactContext ?: return
193
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
194
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
195
+ dispatcher?.dispatchEvent(
196
+ AddToCartEvent(
197
+ surfaceId,
198
+ id,
199
+ productId,
200
+ productTitle,
201
+ productImageUrl,
202
+ productPrice,
203
+ productDeeplinkUrl,
204
+ merchantVariantId,
205
+ sizeId,
206
+ sizeLabel
207
+ )
208
+ )
209
+ }
210
+
211
+ private fun emitContentState(status: String, itemCount: Int) {
132
212
  val reactContext = context as? ThemedReactContext ?: return
133
213
  val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
134
214
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
135
- dispatcher?.dispatchEvent(AddToCartEvent(surfaceId, id, productId, size))
215
+ dispatcher?.dispatchEvent(ContentStateEvent(surfaceId, id, status, itemCount))
136
216
  }
137
217
  }
138
218
 
@@ -18,6 +18,8 @@ class GlanceChatModule(reactContext: ReactApplicationContext) :
18
18
  override fun initialize(partnerId: String, config: ReadableMap, userId: String?) =
19
19
  impl.initialize(partnerId, config, userId)
20
20
 
21
+ override fun setUser(userId: String) = impl.setUser(userId)
22
+
21
23
  override fun destroy() = impl.destroy()
22
24
 
23
25
  override fun isInitialized() = impl.isInitialized()
@@ -21,6 +21,9 @@ class GlanceChatModule(reactContext: ReactApplicationContext) :
21
21
  fun initialize(partnerId: String, config: ReadableMap, userId: String?) =
22
22
  impl.initialize(partnerId, config, userId)
23
23
 
24
+ @ReactMethod
25
+ fun setUser(userId: String) = impl.setUser(userId)
26
+
24
27
  @ReactMethod
25
28
  fun destroy() = impl.destroy()
26
29
 
@@ -1,12 +1,39 @@
1
1
  import type { ViewProps, HostComponent } from 'react-native';
2
- import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypesNamespace';
2
+ import type {
3
+ BubblingEventHandler,
4
+ Int32,
5
+ } from 'react-native/Libraries/Types/CodegenTypesNamespace';
3
6
  import { codegenNativeComponent } from 'react-native';
4
7
 
5
8
  export type AddToCartEvent = Readonly<{
6
9
  productId: string;
10
+ productTitle: string;
11
+ productImageUrl: string;
12
+ productPrice: string | null;
13
+ productDeeplinkUrl: string | null;
14
+ /** Product-level merchant variant id the catalogue was keyed by. */
15
+ merchantVariantId: string | null;
16
+ /** Purchasable size-specific merchant variant id (what goes in the cart). */
17
+ sizeId: string;
18
+ /** Display label, e.g. "M". */
19
+ sizeLabel: string;
20
+ /** Same as sizeLabel — kept for older consumers. */
7
21
  size: string;
8
22
  }>;
9
23
 
24
+ /**
25
+ * Payload for {@link NativeProps.onContentStateChange}: how much the widget will render.
26
+ *
27
+ * `status` is the recommendation fetch status ('NONE' | 'LOADING' | 'LOADED' | 'FAILED'), or
28
+ * an empty string when the widget is not rendering at all (feature disabled, module absent).
29
+ * `itemCount` is the number of look groups the tray will actually show — a group needs at
30
+ * least two products to render.
31
+ */
32
+ export type ContentStateEvent = Readonly<{
33
+ status: string;
34
+ itemCount: Int32;
35
+ }>;
36
+
10
37
  export interface NativeProps extends ViewProps {
11
38
  /** Merchant variant id of the anchor product the tray recommends for. */
12
39
  variantId: string;
@@ -14,6 +41,11 @@ export interface NativeProps extends ViewProps {
14
41
  enabled?: boolean;
15
42
  /** Fired when a size is confirmed in the add-to-cart sheet. */
16
43
  onAddToCartClick?: BubblingEventHandler<AddToCartEvent> | null;
44
+ /**
45
+ * Fired whenever the rendered amount changes, so a host that sizes this widget from its own
46
+ * layout box can collapse to nothing instead of leaving a blank band when the tray is empty.
47
+ */
48
+ onContentStateChange?: BubblingEventHandler<ContentStateEvent> | null;
17
49
  }
18
50
 
19
51
  export default codegenNativeComponent<NativeProps>(
@@ -10,6 +10,14 @@ import { TurboModuleRegistry } from 'react-native';
10
10
 
11
11
  /** Payload for the {@link Spec.onProductClick} event. */
12
12
 
13
+ /**
14
+ * Payload for {@link Spec.onAddToCart}: one shopper-confirmed size selection from an
15
+ * SDK surface. The SDK owns no cart — the host adds this through its own cart action.
16
+ *
17
+ * `sizeId` is the purchasable merchant variant id; `sizeLabel` is display text only and
18
+ * must never be sent as a variant id.
19
+ */
20
+
13
21
  /**
14
22
  * Payload for {@link Spec.onTryOnStatesChanged}: a map of variantId -> status
15
23
  * string (e.g. 'IDLE' | 'GENERATING' | 'READY' | 'FAILED'). Codegen does not
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeGlanceChat.ts"],"mappings":";;AAEA,SAASA,mBAAmB,QAAQ,cAAc;;AAElD;AACA;AACA;AACA;AACA;;AAWA;;AAMA;AACA;AACA;AACA;AACA;;AAoEA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeGlanceChat.ts"],"mappings":";;AAEA,SAASA,mBAAmB,QAAQ,cAAc;;AAElD;AACA;AACA;AACA;AACA;;AA2BA;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;;AAaA;AACA;AACA;AACA;AACA;;AAqFA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
@@ -21,6 +21,9 @@ export const Glance = {
21
21
  initialize(partnerId, config, userId) {
22
22
  GlanceChat.initialize(partnerId, config, userId ?? null);
23
23
  },
24
+ setUser(userId) {
25
+ GlanceChat.setUser(userId);
26
+ },
24
27
  destroy() {
25
28
  GlanceChat.destroy();
26
29
  },
@@ -55,6 +58,12 @@ export const Glance = {
55
58
  onDeeplinkClick(listener) {
56
59
  return GlanceChat.onDeeplinkClick(listener);
57
60
  },
61
+ onAddToCart(listener) {
62
+ return GlanceChat.onAddToCart(listener);
63
+ },
64
+ onViewCart(listener) {
65
+ return GlanceChat.onViewCart(listener);
66
+ },
58
67
  onTryOnStatesChanged(listener) {
59
68
  return GlanceChat.onTryOnStatesChanged(listener);
60
69
  },
@@ -1 +1 @@
1
- {"version":3,"names":["GlanceChat","default","GlanceChatOverlay","GlanceProductTryOnWidget","GlanceMixAndMatchWidget","GlancePdpSuggestions","GlanceEnvironment","DEVELOPMENT","UAT","PRODUCTION","Glance","initialize","partnerId","config","userId","destroy","isInitialized","isLoggedIn","setPageContext","context","metadata","clearPageContext","closeChat","openChatWithSuggestion","suggestion","handleDeepLink","uri","startOnboarding","variantId","onProductClick","listener","onDeeplinkClick","onTryOnStatesChanged","onSessionExpired"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,uBAAoB;AAS3C;AACA,SAASC,OAAO,IAAIC,iBAAiB,QAAQ,oCAAoC;AACjF,SAASD,OAAO,IAAIE,wBAAwB,QAAQ,2CAA2C;AAC/F,SAASF,OAAO,IAAIG,uBAAuB,QAAQ,0CAA0C;AAC7F,SAASH,OAAO,IAAII,oBAAoB,QAAQ,uCAAuC;;AAEvF;AACA,OAAO,MAAMC,iBAAiB,GAAG;EAC/BC,WAAW,EAAE,aAAa;EAC1BC,GAAG,EAAE,KAAK;EACVC,UAAU,EAAE;AACd,CAAU;AAIV;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAM,GAAG;EACpBC,UAAUA,CACRC,SAAiB,EACjBC,MAAwB,EACxBC,MAAsB,EAChB;IACNd,UAAU,CAACW,UAAU,CAACC,SAAS,EAAEC,MAAM,EAAEC,MAAM,IAAI,IAAI,CAAC;EAC1D,CAAC;EACDC,OAAOA,CAAA,EAAS;IACdf,UAAU,CAACe,OAAO,CAAC,CAAC;EACtB,CAAC;EACDC,aAAaA,CAAA,EAAY;IACvB,OAAOhB,UAAU,CAACgB,aAAa,CAAC,CAAC;EACnC,CAAC;EACDC,UAAUA,CAAA,EAAY;IACpB,OAAOjB,UAAU,CAACiB,UAAU,CAAC,CAAC;EAChC,CAAC;EACDC,cAAcA,CAACC,OAAe,EAAEC,QAAgC,GAAG,CAAC,CAAC,EAAQ;IAC3EpB,UAAU,CAACkB,cAAc,CAACC,OAAO,EAAEC,QAAQ,CAAC;EAC9C,CAAC;EACDC,gBAAgBA,CAAA,EAAS;IACvBrB,UAAU,CAACqB,gBAAgB,CAAC,CAAC;EAC/B,CAAC;EACDC,SAASA,CAAA,EAAS;IAChBtB,UAAU,CAACsB,SAAS,CAAC,CAAC;EACxB,CAAC;EACDC,sBAAsBA,CAACC,UAAkB,EAAQ;IAC/CxB,UAAU,CAACuB,sBAAsB,CAACC,UAAU,CAAC;EAC/C,CAAC;EACDC,cAAcA,CAACC,GAAW,EAAW;IACnC,OAAO1B,UAAU,CAACyB,cAAc,CAACC,GAAG,CAAC;EACvC,CAAC;EACDC,eAAeA,CAACC,SAAkB,EAAQ;IACxC5B,UAAU,CAAC2B,eAAe,CAACC,SAAS,CAAC;EACvC,CAAC;EAED;EACAC,cAAcA,CAACC,QAA4C,EAAE;IAC3D,OAAO9B,UAAU,CAAC6B,cAAc,CAACC,QAAQ,CAAC;EAC5C,CAAC;EACDC,eAAeA,CAACD,QAA+B,EAAE;IAC/C,OAAO9B,UAAU,CAAC+B,eAAe,CAACD,QAAQ,CAAC;EAC7C,CAAC;EACDE,oBAAoBA,CAACF,QAA2C,EAAE;IAChE,OAAO9B,UAAU,CAACgC,oBAAoB,CAACF,QAAQ,CAAC;EAClD,CAAC;EACDG,gBAAgBA,CAACH,QAAoB,EAAE;IACrC,OAAO9B,UAAU,CAACiC,gBAAgB,CAACH,QAAQ,CAAC;EAC9C;AACF,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["GlanceChat","default","GlanceChatOverlay","GlanceProductTryOnWidget","GlanceMixAndMatchWidget","GlancePdpSuggestions","GlanceEnvironment","DEVELOPMENT","UAT","PRODUCTION","Glance","initialize","partnerId","config","userId","setUser","destroy","isInitialized","isLoggedIn","setPageContext","context","metadata","clearPageContext","closeChat","openChatWithSuggestion","suggestion","handleDeepLink","uri","startOnboarding","variantId","onProductClick","listener","onDeeplinkClick","onAddToCart","onViewCart","onTryOnStatesChanged","onSessionExpired"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,UAAU,MAAM,uBAAoB;AAe3C;AACA,SAASC,OAAO,IAAIC,iBAAiB,QAAQ,oCAAoC;AACjF,SAASD,OAAO,IAAIE,wBAAwB,QAAQ,2CAA2C;AAC/F,SAASF,OAAO,IAAIG,uBAAuB,QAAQ,0CAA0C;AAC7F,SAASH,OAAO,IAAII,oBAAoB,QAAQ,uCAAuC;;AAEvF;AACA,OAAO,MAAMC,iBAAiB,GAAG;EAC/BC,WAAW,EAAE,aAAa;EAC1BC,GAAG,EAAE,KAAK;EACVC,UAAU,EAAE;AACd,CAAU;AAIV;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAM,GAAG;EACpBC,UAAUA,CACRC,SAAiB,EACjBC,MAAwB,EACxBC,MAAsB,EAChB;IACNd,UAAU,CAACW,UAAU,CAACC,SAAS,EAAEC,MAAM,EAAEC,MAAM,IAAI,IAAI,CAAC;EAC1D,CAAC;EACDC,OAAOA,CAACD,MAAc,EAAQ;IAC5Bd,UAAU,CAACe,OAAO,CAACD,MAAM,CAAC;EAC5B,CAAC;EACDE,OAAOA,CAAA,EAAS;IACdhB,UAAU,CAACgB,OAAO,CAAC,CAAC;EACtB,CAAC;EACDC,aAAaA,CAAA,EAAY;IACvB,OAAOjB,UAAU,CAACiB,aAAa,CAAC,CAAC;EACnC,CAAC;EACDC,UAAUA,CAAA,EAAY;IACpB,OAAOlB,UAAU,CAACkB,UAAU,CAAC,CAAC;EAChC,CAAC;EACDC,cAAcA,CAACC,OAAe,EAAEC,QAAgC,GAAG,CAAC,CAAC,EAAQ;IAC3ErB,UAAU,CAACmB,cAAc,CAACC,OAAO,EAAEC,QAAQ,CAAC;EAC9C,CAAC;EACDC,gBAAgBA,CAAA,EAAS;IACvBtB,UAAU,CAACsB,gBAAgB,CAAC,CAAC;EAC/B,CAAC;EACDC,SAASA,CAAA,EAAS;IAChBvB,UAAU,CAACuB,SAAS,CAAC,CAAC;EACxB,CAAC;EACDC,sBAAsBA,CAACC,UAAkB,EAAQ;IAC/CzB,UAAU,CAACwB,sBAAsB,CAACC,UAAU,CAAC;EAC/C,CAAC;EACDC,cAAcA,CAACC,GAAW,EAAW;IACnC,OAAO3B,UAAU,CAAC0B,cAAc,CAACC,GAAG,CAAC;EACvC,CAAC;EACDC,eAAeA,CAACC,SAAkB,EAAQ;IACxC7B,UAAU,CAAC4B,eAAe,CAACC,SAAS,CAAC;EACvC,CAAC;EAED;EACAC,cAAcA,CAACC,QAA4C,EAAE;IAC3D,OAAO/B,UAAU,CAAC8B,cAAc,CAACC,QAAQ,CAAC;EAC5C,CAAC;EACDC,eAAeA,CAACD,QAA+B,EAAE;IAC/C,OAAO/B,UAAU,CAACgC,eAAe,CAACD,QAAQ,CAAC;EAC7C,CAAC;EACDE,WAAWA,CAACF,QAAyC,EAAE;IACrD,OAAO/B,UAAU,CAACiC,WAAW,CAACF,QAAQ,CAAC;EACzC,CAAC;EACDG,UAAUA,CAACH,QAAoB,EAAE;IAC/B,OAAO/B,UAAU,CAACkC,UAAU,CAACH,QAAQ,CAAC;EACxC,CAAC;EACDI,oBAAoBA,CAACJ,QAA2C,EAAE;IAChE,OAAO/B,UAAU,CAACmC,oBAAoB,CAACJ,QAAQ,CAAC;EAClD,CAAC;EACDK,gBAAgBA,CAACL,QAAoB,EAAE;IACrC,OAAO/B,UAAU,CAACoC,gBAAgB,CAACL,QAAQ,CAAC;EAC9C;AACF,CAAC","ignoreList":[]}
@@ -1,9 +1,32 @@
1
1
  import type { ViewProps, HostComponent } from 'react-native';
2
- import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypesNamespace';
2
+ import type { BubblingEventHandler, Int32 } from 'react-native/Libraries/Types/CodegenTypesNamespace';
3
3
  export type AddToCartEvent = Readonly<{
4
4
  productId: string;
5
+ productTitle: string;
6
+ productImageUrl: string;
7
+ productPrice: string | null;
8
+ productDeeplinkUrl: string | null;
9
+ /** Product-level merchant variant id the catalogue was keyed by. */
10
+ merchantVariantId: string | null;
11
+ /** Purchasable size-specific merchant variant id (what goes in the cart). */
12
+ sizeId: string;
13
+ /** Display label, e.g. "M". */
14
+ sizeLabel: string;
15
+ /** Same as sizeLabel — kept for older consumers. */
5
16
  size: string;
6
17
  }>;
18
+ /**
19
+ * Payload for {@link NativeProps.onContentStateChange}: how much the widget will render.
20
+ *
21
+ * `status` is the recommendation fetch status ('NONE' | 'LOADING' | 'LOADED' | 'FAILED'), or
22
+ * an empty string when the widget is not rendering at all (feature disabled, module absent).
23
+ * `itemCount` is the number of look groups the tray will actually show — a group needs at
24
+ * least two products to render.
25
+ */
26
+ export type ContentStateEvent = Readonly<{
27
+ status: string;
28
+ itemCount: Int32;
29
+ }>;
7
30
  export interface NativeProps extends ViewProps {
8
31
  /** Merchant variant id of the anchor product the tray recommends for. */
9
32
  variantId: string;
@@ -11,6 +34,11 @@ export interface NativeProps extends ViewProps {
11
34
  enabled?: boolean;
12
35
  /** Fired when a size is confirmed in the add-to-cart sheet. */
13
36
  onAddToCartClick?: BubblingEventHandler<AddToCartEvent> | null;
37
+ /**
38
+ * Fired whenever the rendered amount changes, so a host that sizes this widget from its own
39
+ * layout box can collapse to nothing instead of leaving a blank band when the tray is empty.
40
+ */
41
+ onContentStateChange?: BubblingEventHandler<ContentStateEvent> | null;
14
42
  }
15
43
  declare const _default: HostComponent<NativeProps>;
16
44
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"GlanceMixAndMatchWidgetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/GlanceMixAndMatchWidgetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAG/F,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;CAChE;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
1
+ {"version":3,"file":"GlanceMixAndMatchWidgetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/GlanceMixAndMatchWidgetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EACV,oBAAoB,EACpB,KAAK,EACN,MAAM,oDAAoD,CAAC;AAG5D,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,KAAK,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAC/D;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;CACvE;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
@@ -8,16 +8,54 @@ import type { EventEmitter } from 'react-native/Libraries/Types/CodegenTypesName
8
8
  export type GlanceChatConfig = {
9
9
  environment: string;
10
10
  storeHandle: string;
11
+ /** Catalogue tenant id Glance indexes products under; falls back to storeHandle. */
12
+ catalogId?: string;
13
+ /** Public storefront origin, e.g. "https://thebearhouse.com", for absolute product URLs. */
14
+ storefrontBaseUrl?: string;
15
+ /** ISO 3166-1 alpha-2 store region (e.g. "IN", "US"), sent as X-Store-Region. */
16
+ countryCode?: string;
11
17
  brandName?: string;
12
18
  brandLogoUrl?: string;
13
19
  productDeeplinkBaseUrl?: string;
14
20
  /** Host-configurable floating "Generating…" pill during try-on; default true. */
15
21
  showTryOnProgressPill?: boolean;
22
+ /**
23
+ * Appearance for the SDK's own composables. Each value falls back to the SDK's
24
+ * original hardcoded look when omitted or unrecognised.
25
+ */
26
+ brandAccentColor?: string;
27
+ mnmStyleOnMeRadius?: string;
28
+ mnmAddToCartRadius?: string;
29
+ mnmCartIconRadius?: string;
30
+ onboardingContinueRadius?: string;
31
+ onboardingGenderRadius?: string;
16
32
  };
17
33
  /** Payload for the {@link Spec.onProductClick} event. */
18
34
  export type ProductClickEvent = {
19
35
  productId: string;
20
36
  name: string;
37
+ /** Empty when the catalogue entry has no merchant URL. */
38
+ deeplinkUrl: string;
39
+ /** The purchasable merchant variant id, when the SDK has one. */
40
+ merchantVariantId: string | null;
41
+ };
42
+ /**
43
+ * Payload for {@link Spec.onAddToCart}: one shopper-confirmed size selection from an
44
+ * SDK surface. The SDK owns no cart — the host adds this through its own cart action.
45
+ *
46
+ * `sizeId` is the purchasable merchant variant id; `sizeLabel` is display text only and
47
+ * must never be sent as a variant id.
48
+ */
49
+ export type AddToCartEvent = {
50
+ productId: string;
51
+ productName: string;
52
+ productImageUrl: string;
53
+ productPrice: string | null;
54
+ deeplinkUrl: string | null;
55
+ merchantVariantId: string | null;
56
+ sizeId: string;
57
+ sizeLabel: string;
58
+ quantity: number;
21
59
  };
22
60
  /**
23
61
  * Payload for {@link Spec.onTryOnStatesChanged}: a map of variantId -> status
@@ -41,6 +79,13 @@ export interface Spec extends TurboModule {
41
79
  * When omitted, the SDK falls back to the device id.
42
80
  */
43
81
  initialize(partnerId: string, config: GlanceChatConfig, userId?: string | null): void;
82
+ /**
83
+ * Switch the shopper the SDK acts as, without re-initializing it — call on host
84
+ * login/logout. The bearer token is re-minted for the new id and identity-scoped
85
+ * state (avatar, profile, trial quota, conversation) is cleared. Re-sending the
86
+ * current id is a no-op.
87
+ */
88
+ setUser(userId: string): void;
44
89
  /** Tear down the SDK and release resources. */
45
90
  destroy(): void;
46
91
  /** Whether {@link initialize} has completed. */
@@ -71,6 +116,13 @@ export interface Spec extends TurboModule {
71
116
  readonly onProductClick: EventEmitter<ProductClickEvent>;
72
117
  /** Emitted when the SDK requests the host to open a deeplink URL. */
73
118
  readonly onDeeplinkClick: EventEmitter<string>;
119
+ /**
120
+ * Emitted when the shopper confirms a size in an SDK add-to-cart sheet. The host
121
+ * adds the item to its own cart; the SDK's surfaces assume no cart.
122
+ */
123
+ readonly onAddToCart: EventEmitter<AddToCartEvent>;
124
+ /** Emitted when the shopper taps "View Cart" inside an SDK surface. */
125
+ readonly onViewCart: EventEmitter<void>;
74
126
  /** Emitted whenever the try-on state map changes. */
75
127
  readonly onTryOnStatesChanged: EventEmitter<TryOnStatesEvent>;
76
128
  /** Emitted when the auth session expires and the host should re-authenticate. */
@@ -1 +1 @@
1
- {"version":3,"file":"NativeGlanceChat.d.ts","sourceRoot":"","sources":["../../../src/NativeGlanceChat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oDAAoD,CAAC;AAGvF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;;;;;;;;OASG;IACH,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,EACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,IAAI,CAAC;IAER,+CAA+C;IAC/C,OAAO,IAAI,IAAI,CAAC;IAEhB,gDAAgD;IAChD,aAAa,IAAI,OAAO,CAAC;IAEzB,+CAA+C;IAC/C,UAAU,IAAI,OAAO,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAE3E,sCAAsC;IACtC,gBAAgB,IAAI,IAAI,CAAC;IAEzB,sCAAsC;IACtC,SAAS,IAAI,IAAI,CAAC;IAElB,kDAAkD;IAClD,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjD,+DAA+D;IAC/D,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAErC;;;OAGG;IACH,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjD,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAEzD,qEAAqE;IACrE,QAAQ,CAAC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAE/C,qDAAqD;IACrD,QAAQ,CAAC,oBAAoB,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAE9D,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;CAC/C;;AAED,wBAAoE"}
1
+ {"version":3,"file":"NativeGlanceChat.d.ts","sourceRoot":"","sources":["../../../src/NativeGlanceChat.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { GlanceChatConfig, ProductClickEvent, TryOnStatesEvent } from './NativeGlanceChat';
2
- export type { GlanceChatConfig, ProductClickEvent, TryOnStatesEvent };
1
+ import type { AddToCartEvent, GlanceChatConfig, ProductClickEvent, TryOnStatesEvent } from './NativeGlanceChat';
2
+ export type { AddToCartEvent, GlanceChatConfig, ProductClickEvent, TryOnStatesEvent, };
3
3
  export { default as GlanceChatOverlay } from './GlanceChatOverlayNativeComponent';
4
4
  export { default as GlanceProductTryOnWidget } from './GlanceProductTryOnWidgetNativeComponent';
5
5
  export { default as GlanceMixAndMatchWidget } from './GlanceMixAndMatchWidgetNativeComponent';
@@ -17,6 +17,7 @@ export type GlanceEnvironment = (typeof GlanceEnvironment)[keyof typeof GlanceEn
17
17
  */
18
18
  export declare const Glance: {
19
19
  initialize(partnerId: string, config: GlanceChatConfig, userId?: string | null): void;
20
+ setUser(userId: string): void;
20
21
  destroy(): void;
21
22
  isInitialized(): boolean;
22
23
  isLoggedIn(): boolean;
@@ -28,6 +29,8 @@ export declare const Glance: {
28
29
  startOnboarding(variantId?: string): void;
29
30
  onProductClick(listener: (event: ProductClickEvent) => void): import("react-native").EventSubscription;
30
31
  onDeeplinkClick(listener: (uri: string) => void): import("react-native").EventSubscription;
32
+ onAddToCart(listener: (event: AddToCartEvent) => void): import("react-native").EventSubscription;
33
+ onViewCart(listener: () => void): import("react-native").EventSubscription;
31
34
  onTryOnStatesChanged(listener: (event: TryOnStatesEvent) => void): import("react-native").EventSubscription;
32
35
  onSessionExpired(listener: () => void): import("react-native").EventSubscription;
33
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAChG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAExF,qCAAqC;AACrC,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,MAAM;0BAEJ,MAAM,UACT,gBAAgB,WACf,MAAM,GAAG,IAAI,GACrB,IAAI;eAGI,IAAI;qBAGE,OAAO;kBAGV,OAAO;4BAGG,MAAM,aAAY,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAQ,IAAI;wBAGxD,IAAI;iBAGX,IAAI;uCAGkB,MAAM,GAAG,IAAI;wBAG5B,MAAM,GAAG,OAAO;gCAGR,MAAM,GAAG,IAAI;6BAKhB,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI;8BAGjC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;mCAGhB,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI;+BAGrC,MAAM,IAAI;CAGtC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACjB,CAAC;AAGF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAChG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAExF,qCAAqC;AACrC,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAC3B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,MAAM;0BAEJ,MAAM,UACT,gBAAgB,WACf,MAAM,GAAG,IAAI,GACrB,IAAI;oBAGS,MAAM,GAAG,IAAI;eAGlB,IAAI;qBAGE,OAAO;kBAGV,OAAO;4BAGG,MAAM,aAAY,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAQ,IAAI;wBAGxD,IAAI;iBAGX,IAAI;uCAGkB,MAAM,GAAG,IAAI;wBAG5B,MAAM,GAAG,OAAO;gCAGR,MAAM,GAAG,IAAI;6BAKhB,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI;8BAGjC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI;0BAGzB,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI;yBAGhC,MAAM,IAAI;mCAGA,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI;+BAGrC,MAAM,IAAI;CAGtC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-glance-chat",
3
- "version": "0.1.9",
3
+ "version": "0.1.13",
4
4
  "description": "React Native wrapper for the Glance Chat SDK (Android + iOS)",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -125,4 +125,4 @@
125
125
  ],
126
126
  "version": "0.63.0"
127
127
  }
128
- }
128
+ }
@@ -1,12 +1,39 @@
1
1
  import type { ViewProps, HostComponent } from 'react-native';
2
- import type { BubblingEventHandler } from 'react-native/Libraries/Types/CodegenTypesNamespace';
2
+ import type {
3
+ BubblingEventHandler,
4
+ Int32,
5
+ } from 'react-native/Libraries/Types/CodegenTypesNamespace';
3
6
  import { codegenNativeComponent } from 'react-native';
4
7
 
5
8
  export type AddToCartEvent = Readonly<{
6
9
  productId: string;
10
+ productTitle: string;
11
+ productImageUrl: string;
12
+ productPrice: string | null;
13
+ productDeeplinkUrl: string | null;
14
+ /** Product-level merchant variant id the catalogue was keyed by. */
15
+ merchantVariantId: string | null;
16
+ /** Purchasable size-specific merchant variant id (what goes in the cart). */
17
+ sizeId: string;
18
+ /** Display label, e.g. "M". */
19
+ sizeLabel: string;
20
+ /** Same as sizeLabel — kept for older consumers. */
7
21
  size: string;
8
22
  }>;
9
23
 
24
+ /**
25
+ * Payload for {@link NativeProps.onContentStateChange}: how much the widget will render.
26
+ *
27
+ * `status` is the recommendation fetch status ('NONE' | 'LOADING' | 'LOADED' | 'FAILED'), or
28
+ * an empty string when the widget is not rendering at all (feature disabled, module absent).
29
+ * `itemCount` is the number of look groups the tray will actually show — a group needs at
30
+ * least two products to render.
31
+ */
32
+ export type ContentStateEvent = Readonly<{
33
+ status: string;
34
+ itemCount: Int32;
35
+ }>;
36
+
10
37
  export interface NativeProps extends ViewProps {
11
38
  /** Merchant variant id of the anchor product the tray recommends for. */
12
39
  variantId: string;
@@ -14,6 +41,11 @@ export interface NativeProps extends ViewProps {
14
41
  enabled?: boolean;
15
42
  /** Fired when a size is confirmed in the add-to-cart sheet. */
16
43
  onAddToCartClick?: BubblingEventHandler<AddToCartEvent> | null;
44
+ /**
45
+ * Fired whenever the rendered amount changes, so a host that sizes this widget from its own
46
+ * layout box can collapse to nothing instead of leaving a blank band when the tray is empty.
47
+ */
48
+ onContentStateChange?: BubblingEventHandler<ContentStateEvent> | null;
17
49
  }
18
50
 
19
51
  export default codegenNativeComponent<NativeProps>(
@@ -10,17 +10,56 @@ import { TurboModuleRegistry } from 'react-native';
10
10
  export type GlanceChatConfig = {
11
11
  environment: string; // 'DEVELOPMENT' | 'UAT' | 'PRODUCTION'
12
12
  storeHandle: string;
13
+ /** Catalogue tenant id Glance indexes products under; falls back to storeHandle. */
14
+ catalogId?: string;
15
+ /** Public storefront origin, e.g. "https://thebearhouse.com", for absolute product URLs. */
16
+ storefrontBaseUrl?: string;
17
+ /** ISO 3166-1 alpha-2 store region (e.g. "IN", "US"), sent as X-Store-Region. */
18
+ countryCode?: string;
13
19
  brandName?: string;
14
20
  brandLogoUrl?: string;
15
21
  productDeeplinkBaseUrl?: string;
16
22
  /** Host-configurable floating "Generating…" pill during try-on; default true. */
17
23
  showTryOnProgressPill?: boolean;
24
+ /**
25
+ * Appearance for the SDK's own composables. Each value falls back to the SDK's
26
+ * original hardcoded look when omitted or unrecognised.
27
+ */
28
+ brandAccentColor?: string; // '#RRGGBB'
29
+ mnmStyleOnMeRadius?: string; // '0' | '4' | '8' | '12' | 'pill'
30
+ mnmAddToCartRadius?: string;
31
+ mnmCartIconRadius?: string;
32
+ onboardingContinueRadius?: string;
33
+ onboardingGenderRadius?: string;
18
34
  };
19
35
 
20
36
  /** Payload for the {@link Spec.onProductClick} event. */
21
37
  export type ProductClickEvent = {
22
38
  productId: string;
23
39
  name: string;
40
+ /** Empty when the catalogue entry has no merchant URL. */
41
+ deeplinkUrl: string;
42
+ /** The purchasable merchant variant id, when the SDK has one. */
43
+ merchantVariantId: string | null;
44
+ };
45
+
46
+ /**
47
+ * Payload for {@link Spec.onAddToCart}: one shopper-confirmed size selection from an
48
+ * SDK surface. The SDK owns no cart — the host adds this through its own cart action.
49
+ *
50
+ * `sizeId` is the purchasable merchant variant id; `sizeLabel` is display text only and
51
+ * must never be sent as a variant id.
52
+ */
53
+ export type AddToCartEvent = {
54
+ productId: string;
55
+ productName: string;
56
+ productImageUrl: string;
57
+ productPrice: string | null;
58
+ deeplinkUrl: string | null;
59
+ merchantVariantId: string | null;
60
+ sizeId: string;
61
+ sizeLabel: string;
62
+ quantity: number;
24
63
  };
25
64
 
26
65
  /**
@@ -49,6 +88,14 @@ export interface Spec extends TurboModule {
49
88
  userId?: string | null
50
89
  ): void;
51
90
 
91
+ /**
92
+ * Switch the shopper the SDK acts as, without re-initializing it — call on host
93
+ * login/logout. The bearer token is re-minted for the new id and identity-scoped
94
+ * state (avatar, profile, trial quota, conversation) is cleared. Re-sending the
95
+ * current id is a no-op.
96
+ */
97
+ setUser(userId: string): void;
98
+
52
99
  /** Tear down the SDK and release resources. */
53
100
  destroy(): void;
54
101
 
@@ -88,6 +135,15 @@ export interface Spec extends TurboModule {
88
135
  /** Emitted when the SDK requests the host to open a deeplink URL. */
89
136
  readonly onDeeplinkClick: EventEmitter<string>;
90
137
 
138
+ /**
139
+ * Emitted when the shopper confirms a size in an SDK add-to-cart sheet. The host
140
+ * adds the item to its own cart; the SDK's surfaces assume no cart.
141
+ */
142
+ readonly onAddToCart: EventEmitter<AddToCartEvent>;
143
+
144
+ /** Emitted when the shopper taps "View Cart" inside an SDK surface. */
145
+ readonly onViewCart: EventEmitter<void>;
146
+
91
147
  /** Emitted whenever the try-on state map changes. */
92
148
  readonly onTryOnStatesChanged: EventEmitter<TryOnStatesEvent>;
93
149
 
package/src/index.tsx CHANGED
@@ -1,11 +1,17 @@
1
1
  import GlanceChat from './NativeGlanceChat';
2
2
  import type {
3
+ AddToCartEvent,
3
4
  GlanceChatConfig,
4
5
  ProductClickEvent,
5
6
  TryOnStatesEvent,
6
7
  } from './NativeGlanceChat';
7
8
 
8
- export type { GlanceChatConfig, ProductClickEvent, TryOnStatesEvent };
9
+ export type {
10
+ AddToCartEvent,
11
+ GlanceChatConfig,
12
+ ProductClickEvent,
13
+ TryOnStatesEvent,
14
+ };
9
15
 
10
16
  // Native UI components (Fabric). Each hosts the corresponding SDK Composable.
11
17
  export { default as GlanceChatOverlay } from './GlanceChatOverlayNativeComponent';
@@ -34,6 +40,9 @@ export const Glance = {
34
40
  ): void {
35
41
  GlanceChat.initialize(partnerId, config, userId ?? null);
36
42
  },
43
+ setUser(userId: string): void {
44
+ GlanceChat.setUser(userId);
45
+ },
37
46
  destroy(): void {
38
47
  GlanceChat.destroy();
39
48
  },
@@ -69,6 +78,12 @@ export const Glance = {
69
78
  onDeeplinkClick(listener: (uri: string) => void) {
70
79
  return GlanceChat.onDeeplinkClick(listener);
71
80
  },
81
+ onAddToCart(listener: (event: AddToCartEvent) => void) {
82
+ return GlanceChat.onAddToCart(listener);
83
+ },
84
+ onViewCart(listener: () => void) {
85
+ return GlanceChat.onViewCart(listener);
86
+ },
72
87
  onTryOnStatesChanged(listener: (event: TryOnStatesEvent) => void) {
73
88
  return GlanceChat.onTryOnStatesChanged(listener);
74
89
  },