framepayments-react-native 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -299,32 +299,37 @@ On non-Android platforms `Frame.presentGooglePay` rejects synchronously with a n
299
299
 
300
300
  ---
301
301
 
302
- ### `Frame.setTheme(theme)` (iOS)
302
+ ### Theming (iOS)
303
303
 
304
304
  Customizes colors, fonts, and corner radii on Frame's reusable components — checkout, cart, and the onboarding flow. Backed by `FrameTheme` introduced in Frame-iOS 2.1.2.
305
305
 
306
- Call once at app startup (after `Frame.initialize`). The theme applies to every subsequent `present*` call. Modals already on screen are not re-themed mid-flow. Pass `null` or `{}` to reset to defaults; pass a partial dict to override only specific tokens.
306
+ Pass an optional `theme` to `Frame.initialize`. It's stored on `FrameNetworking.shared` and read by every Frame view at present time, so all subsequent `present*` calls render with it. Modals already on screen are not re-themed if the theme is changed mid-flow. Omit the field, or pass `{}`, to use SDK defaults; pass a partial dict to override only specific tokens.
307
307
 
308
308
  ```ts
309
309
  import Frame from 'framepayments-react-native';
310
310
 
311
- await Frame.setTheme({
312
- colors: {
313
- primaryButton: '#5B2DFF',
314
- primaryButtonText: '#FFFFFF',
315
- surface: '#0A0A0A',
316
- textPrimary: '#FFFFFF',
317
- error: '#E53935',
318
- },
319
- fonts: {
320
- title: { name: 'Inter-Bold', size: 24 },
321
- button: { name: 'Inter-SemiBold', size: 16 },
311
+ await Frame.initialize({
312
+ secretKey: 'sk_sandbox_...',
313
+ publishableKey: 'pk_sandbox_...',
314
+ debugMode: __DEV__,
315
+ theme: {
316
+ colors: {
317
+ primaryButton: '#5B2DFF',
318
+ primaryButtonText: '#FFFFFF',
319
+ surface: '#0A0A0A',
320
+ textPrimary: '#FFFFFF',
321
+ error: '#E53935',
322
+ },
323
+ fonts: {
324
+ title: { name: 'Inter-Bold', size: 24 },
325
+ button: { name: 'Inter-SemiBold', size: 16 },
326
+ },
327
+ radii: { medium: 16 },
322
328
  },
323
- radii: { medium: 16 },
324
329
  });
325
330
  ```
326
331
 
327
- **Android**: `setTheme()` resolves immediately and has no effect — `frame-android` does not yet have a matching theme API.
332
+ **Android**: the `theme` field is accepted for cross-platform parity but currently has no effect — `frame-android` does not yet have a matching theme API.
328
333
 
329
334
  #### Tokens
330
335
 
@@ -31,7 +31,15 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
31
31
  }
32
32
 
33
33
  @ReactMethod
34
- fun initialize(secretKey: String, publishableKey: String, debugMode: Boolean, promise: Promise) {
34
+ fun initialize(
35
+ secretKey: String,
36
+ publishableKey: String,
37
+ debugMode: Boolean,
38
+ @Suppress("UNUSED_PARAMETER") theme: com.facebook.react.bridge.ReadableMap?,
39
+ promise: Promise
40
+ ) {
41
+ // theme is accepted for cross-platform parity with iOS but is currently a
42
+ // no-op on Android — frame-android does not yet have a matching theme API.
35
43
  try {
36
44
  val ctx = reactApplicationContext.applicationContext
37
45
  FrameNetworking.initializeWithAPIKey(ctx, secretKey, publishableKey, debugMode)
@@ -2,8 +2,9 @@
2
2
  // FrameRNTheme.swift
3
3
  // FrameReactNative
4
4
  //
5
- // Bridges JS theme dictionaries to Frame-iOS's FrameTheme and applies it to
6
- // every SwiftUI root view we present. Read/written only on the main thread.
5
+ // Parses JS theme dictionaries into Frame-iOS's FrameTheme. The parsed
6
+ // theme is handed to FrameNetworking.shared.configureTheme(_:); the SDK
7
+ // owns storage and applies it via its FrameThemeKey environment default.
7
8
  //
8
9
 
9
10
  import Foundation
@@ -11,12 +12,6 @@ import SwiftUI
11
12
  import Frame
12
13
 
13
14
  enum FrameRNTheme {
14
- // Main-thread only: written by FrameSDKBridge.setTheme (dispatched to main),
15
- // read by present* methods (already on main).
16
- static var current: FrameTheme? = nil
17
-
18
- static func resolved() -> FrameTheme { current ?? .default }
19
-
20
15
  static func parse(_ dict: [String: Any]) -> FrameTheme {
21
16
  var theme = FrameTheme.default
22
17
 
@@ -75,22 +70,6 @@ enum FrameRNTheme {
75
70
  }
76
71
  }
77
72
 
78
- // Applies the supplied FrameTheme to a single root view. Captured at present
79
- // time so each UIHostingController has a stable, concrete rootView type.
80
- struct ThemedRoot<Content: View>: View {
81
- let theme: FrameTheme
82
- let content: Content
83
-
84
- init(_ content: Content, theme: FrameTheme) {
85
- self.content = content
86
- self.theme = theme
87
- }
88
-
89
- var body: some View {
90
- content.frameTheme(theme)
91
- }
92
- }
93
-
94
73
  extension Color {
95
74
  // Accepts "#RGB", "#RRGGBB", "#RRGGBBAA" with or without the leading '#'.
96
75
  init?(rnHex hex: String) {
@@ -28,10 +28,7 @@
28
28
  RCT_EXTERN_METHOD(initialize:(NSString *)secretKey
29
29
  publishableKey:(NSString *)publishableKey
30
30
  debugMode:(BOOL)debugMode
31
- resolver:(RCTPromiseResolveBlock)resolve
32
- rejecter:(RCTPromiseRejectBlock)reject)
33
-
34
- RCT_EXTERN_METHOD(setTheme:(NSDictionary *)theme
31
+ theme:(NSDictionary *)theme
35
32
  resolver:(RCTPromiseResolveBlock)resolve
36
33
  rejecter:(RCTPromiseRejectBlock)reject)
37
34
 
@@ -71,12 +68,8 @@ RCT_EXTERN_METHOD(presentApplePay:(NSString *)ownerType
71
68
  return YES;
72
69
  }
73
70
 
74
- - (void)initialize:(NSString *)secretKey publishableKey:(NSString *)publishableKey debugMode:(BOOL)debugMode resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
75
- [[[ObjCFrameSDKBridge alloc] init] initialize:secretKey publishableKey:publishableKey debugMode:debugMode resolver:resolve rejecter:reject];
76
- }
77
-
78
- - (void)setTheme:(NSDictionary *)theme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
79
- [[[ObjCFrameSDKBridge alloc] init] setTheme:theme resolver:resolve rejecter:reject];
71
+ - (void)initialize:(NSString *)secretKey publishableKey:(NSString *)publishableKey debugMode:(BOOL)debugMode theme:(NSDictionary *)theme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
72
+ [[[ObjCFrameSDKBridge alloc] init] initialize:secretKey publishableKey:publishableKey debugMode:debugMode theme:theme resolver:resolve rejecter:reject];
80
73
  }
81
74
 
82
75
  - (void)presentCheckout:(id)customerId amount:(NSNumber *)amount resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
@@ -20,18 +20,11 @@ public class FrameSDKBridge: NSObject {
20
20
  }
21
21
 
22
22
  @objc public
23
- func initialize(_ secretKey: String, publishableKey: String, debugMode: Bool, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
23
+ func initialize(_ secretKey: String, publishableKey: String, debugMode: Bool, theme: NSDictionary?, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
24
24
  DispatchQueue.main.async {
25
- FrameNetworking.shared.initializeWithAPIKey(secretKey, publishableKey: publishableKey, debugMode: debugMode)
26
- resolve(nil)
27
- }
28
- }
29
-
30
- @objc public
31
- func setTheme(_ theme: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
32
- DispatchQueue.main.async {
33
- let dict = theme as? [String: Any] ?? [:]
34
- FrameRNTheme.current = dict.isEmpty ? nil : FrameRNTheme.parse(dict)
25
+ let themeDict = theme as? [String: Any] ?? [:]
26
+ let resolvedTheme = themeDict.isEmpty ? FrameTheme.default : FrameRNTheme.parse(themeDict)
27
+ FrameNetworking.shared.initializeWithAPIKey(secretKey, publishableKey: publishableKey, theme: resolvedTheme, debugMode: debugMode)
35
28
  resolve(nil)
36
29
  }
37
30
  }
@@ -106,23 +99,20 @@ public class FrameSDKBridge: NSObject {
106
99
 
107
100
  private func presentCheckoutOnMain(from top: UIViewController, customerId: String?, amount: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
108
101
  var hosting: CheckoutHostingController!
109
- hosting = CheckoutHostingController(rootView: ThemedRoot(
110
- FrameCheckoutView(
111
- customerId: customerId,
112
- paymentAmount: amount,
113
- checkoutCallback: { [weak hosting] chargeIntent in
114
- hosting?.didComplete = true
115
- top.dismiss(animated: true)
116
- DispatchQueue.main.async {
117
- if let dict = Self.encodeChargeIntent(chargeIntent) {
118
- resolve(dict)
119
- } else {
120
- reject("ENCODE_ERROR", "Failed to encode charge intent", nil)
121
- }
102
+ hosting = CheckoutHostingController(rootView: FrameCheckoutView(
103
+ customerId: customerId,
104
+ paymentAmount: amount,
105
+ checkoutCallback: { [weak hosting] chargeIntent in
106
+ hosting?.didComplete = true
107
+ top.dismiss(animated: true)
108
+ DispatchQueue.main.async {
109
+ if let dict = Self.encodeChargeIntent(chargeIntent) {
110
+ resolve(dict)
111
+ } else {
112
+ reject("ENCODE_ERROR", "Failed to encode charge intent", nil)
122
113
  }
123
114
  }
124
- ),
125
- theme: FrameRNTheme.resolved()
115
+ }
126
116
  ))
127
117
  hosting.onCancel = {
128
118
  DispatchQueue.main.async {
@@ -179,7 +169,7 @@ public class FrameSDKBridge: NSObject {
179
169
  cartItems: cartItems,
180
170
  shippingAmountInCents: shippingAmountInCents
181
171
  )
182
- let hosting = UIHostingController(rootView: ThemedRoot(cartView, theme: FrameRNTheme.resolved()))
172
+ let hosting = UIHostingController(rootView: cartView)
183
173
  hosting.modalPresentationStyle = UIModalPresentationStyle.pageSheet
184
174
  if let sheet = hosting.sheetPresentationController {
185
175
  sheet.detents = [UISheetPresentationController.Detent.large()]
@@ -193,20 +183,22 @@ public class FrameSDKBridge: NSObject {
193
183
  }
194
184
 
195
185
  private func presentOnboardingOnMain(from top: UIViewController, accountId: String?, capabilities: [FrameObjects.Capabilities], applePayMerchantId: String?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
196
- var hosting: OnboardingHostingController<ThemedRoot<OnboardingContainerView>>!
197
- var delegate: OnboardingDismissDelegate!
198
- hosting = OnboardingHostingController(
199
- rootView: ThemedRoot(
200
- OnboardingContainerView(
201
- accountId: accountId,
202
- requiredCapabilities: capabilities,
203
- applePayMerchantId: applePayMerchantId,
204
- onComplete: { [weak top] in
205
- delegate?.finish(completed: true)
206
- top?.dismiss(animated: true)
207
- }
208
- ),
209
- theme: FrameRNTheme.resolved()
186
+ // Build the dismiss delegate up-front so onComplete captures a non-nil
187
+ // instance directly. Earlier shape declared `var delegate: …!` and assigned
188
+ // it AFTER constructing OnboardingContainerView; the onComplete closure
189
+ // captured the local by reference, so any path that fired the callback
190
+ // before assignment landed on a nil delegate and silently no-op'd via `?.`.
191
+ let delegate = OnboardingDismissDelegate(resolve: resolve)
192
+
193
+ let hosting = OnboardingHostingController(
194
+ rootView: OnboardingContainerView(
195
+ accountId: accountId,
196
+ requiredCapabilities: capabilities,
197
+ applePayMerchantId: applePayMerchantId,
198
+ onComplete: { [delegate, weak top] in
199
+ delegate.finish(completed: true)
200
+ top?.dismiss(animated: true)
201
+ }
210
202
  )
211
203
  )
212
204
  // Embed in a UINavigationController so the outer sheet is a UIKit container,
@@ -222,7 +214,6 @@ public class FrameSDKBridge: NSObject {
222
214
  if let sheet = nav.sheetPresentationController {
223
215
  sheet.detents = [UISheetPresentationController.Detent.large()]
224
216
  }
225
- delegate = OnboardingDismissDelegate(resolve: resolve)
226
217
  delegate.hostingController = nav
227
218
  objc_setAssociatedObject(nav, &onboardingDismissKey, delegate, .OBJC_ASSOCIATION_RETAIN)
228
219
  NSLog("[FrameRN][onb] presenting OnboardingHostingController (wrapped in UINavigationController) from \(type(of: top))")
@@ -235,7 +226,7 @@ public class FrameSDKBridge: NSObject {
235
226
 
236
227
  // MARK: - CheckoutHostingController
237
228
 
238
- private final class CheckoutHostingController: UIHostingController<ThemedRoot<FrameCheckoutView>>, UIAdaptivePresentationControllerDelegate {
229
+ private final class CheckoutHostingController: UIHostingController<FrameCheckoutView>, UIAdaptivePresentationControllerDelegate {
239
230
  var didComplete = false
240
231
  var onCancel: (() -> Void)?
241
232
  private var cancelled = false
package/lib/index.d.ts CHANGED
@@ -7,12 +7,12 @@
7
7
  * - Use presentApplePay / presentGooglePay to launch the platform wallet sheet from your own button UI.
8
8
  * - For API calls (customers, charge intents, refunds), use the framepayments (frame-node) package from JS.
9
9
  */
10
- import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme } from './native';
11
- export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
10
+ import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay } from './native';
11
+ export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
12
12
  export type { FrameCartItem, ChargeIntent, ChargeIntentStatus, AuthorizationMode, FrameError, BillingAddress, PaymentCard, BankAccount, PaymentMethod, OnboardingCapability, OnboardingResult, OnboardingResultStatus, ApplePayOwner, PresentApplePayOptions, PresentGooglePayOptions, FrameTheme, FrameThemeColor, FrameThemeFont, FrameThemeColors, FrameThemeFonts, FrameThemeRadii, } from './types';
13
13
  export { ErrorCodes } from './errors';
14
14
  export type { FrameErrorShape, FrameErrorCode } from './errors';
15
- /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
15
+ /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
16
16
  declare const _default: {
17
17
  initialize: typeof initialize;
18
18
  presentCheckout: typeof presentCheckout;
@@ -20,7 +20,6 @@ declare const _default: {
20
20
  presentOnboarding: typeof presentOnboarding;
21
21
  presentApplePay: typeof presentApplePay;
22
22
  presentGooglePay: typeof presentGooglePay;
23
- setTheme: typeof setTheme;
24
23
  };
25
24
  export default _default;
26
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhE,0LAA0L;;;;;;;;;;AAC1L,wBAQE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhE,wKAAwK;;;;;;;;;AACxK,wBAOE"}
package/lib/index.js CHANGED
@@ -7,10 +7,10 @@
7
7
  * - Use presentApplePay / presentGooglePay to launch the platform wallet sheet from your own button UI.
8
8
  * - For API calls (customers, charge intents, refunds), use the framepayments (frame-node) package from JS.
9
9
  */
10
- import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
11
- export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
10
+ import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
11
+ export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
12
12
  export { ErrorCodes } from './errors';
13
- /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
13
+ /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
14
14
  export default {
15
15
  initialize,
16
16
  presentCheckout,
@@ -18,5 +18,4 @@ export default {
18
18
  presentOnboarding,
19
19
  presentApplePay,
20
20
  presentGooglePay,
21
- setTheme,
22
21
  };
package/lib/native.d.ts CHANGED
@@ -6,6 +6,13 @@ export declare function initialize(options: {
6
6
  secretKey: string;
7
7
  publishableKey: string;
8
8
  debugMode?: boolean;
9
+ /**
10
+ * Optional theme applied SDK-wide to Frame's reusable iOS components
11
+ * (checkout, cart, onboarding). Pass any subset — unspecified tokens fall
12
+ * back to SDK defaults. No-op on Android until frame-android ships a
13
+ * matching theme API.
14
+ */
15
+ theme?: FrameTheme;
9
16
  }): Promise<void>;
10
17
  export declare function presentCheckout(options: {
11
18
  customerId?: string | null;
@@ -24,13 +31,4 @@ export declare function presentOnboarding(options: {
24
31
  }): Promise<OnboardingResult>;
25
32
  export declare function presentApplePay(options: PresentApplePayOptions): Promise<ChargeIntent>;
26
33
  export declare function presentGooglePay(options: PresentGooglePayOptions): Promise<ChargeIntent>;
27
- /**
28
- * Configure colors, fonts, and corner radii for Frame's reusable iOS
29
- * components. Applied to every subsequent `present*` call; an in-flight modal
30
- * is not re-themed mid-flow.
31
- *
32
- * Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
33
- * frame-android ships a matching theme API.
34
- */
35
- export declare function setTheme(theme: FrameTheme | null): Promise<void>;
36
34
  //# sourceMappingURL=native.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAmBjB,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhB;AAwBD,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKxB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,YAAY,CAAC,CASxB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkB5B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBtF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAUxF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhE"}
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAsBjB,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB;AAwBD,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKxB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,YAAY,CAAC,CASxB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkB5B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBtF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAUxF"}
package/lib/native.js CHANGED
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import { NativeModules, Platform } from 'react-native';
5
5
  import { ErrorCodes } from './errors';
6
+ // theme is iOS-only today: frame-android does not yet have a matching theme API,
7
+ // so the field is accepted on both platforms but ignored on Android until it does.
6
8
  const LINKING_ERROR = `The package 'framepayments-react-native' doesn't seem to be linked. Make sure you have run 'pod install' (iOS) or rebuilt the app (Android).`;
7
9
  const FrameSDK = NativeModules.FrameSDK
8
10
  ? NativeModules.FrameSDK
@@ -19,7 +21,10 @@ export function initialize(options) {
19
21
  if (!options?.publishableKey) {
20
22
  throw new Error('Frame.initialize requires publishableKey');
21
23
  }
22
- return wrapPromise(FrameSDK.initialize(options.secretKey, options.publishableKey, options.debugMode ?? false)).then(() => {
24
+ if (options.theme !== undefined && (typeof options.theme !== 'object' || Array.isArray(options.theme))) {
25
+ throw new Error('Frame.initialize: theme must be an object');
26
+ }
27
+ return wrapPromise(FrameSDK.initialize(options.secretKey, options.publishableKey, options.debugMode ?? false, options.theme ?? null)).then(() => {
23
28
  isInitialized = true;
24
29
  });
25
30
  }
@@ -75,19 +80,3 @@ export function presentGooglePay(options) {
75
80
  guardInitialized();
76
81
  return wrapPromise(FrameSDK.presentGooglePay(options.amountCents, options.customerId ?? null, options.currencyCode ?? 'USD', options.googlePayMerchantId ?? null));
77
82
  }
78
- /**
79
- * Configure colors, fonts, and corner radii for Frame's reusable iOS
80
- * components. Applied to every subsequent `present*` call; an in-flight modal
81
- * is not re-themed mid-flow.
82
- *
83
- * Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
84
- * frame-android ships a matching theme API.
85
- */
86
- export function setTheme(theme) {
87
- if (theme !== null && (typeof theme !== 'object' || Array.isArray(theme))) {
88
- throw new Error('Frame.setTheme requires a theme object or null');
89
- }
90
- if (Platform.OS !== 'ios')
91
- return Promise.resolve();
92
- return wrapPromise(FrameSDK.setTheme(theme ?? {}));
93
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framepayments-react-native",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "React Native SDK for Frame Payments - modal checkout and cart, with API usage via frame-node.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
package/src/index.ts CHANGED
@@ -15,7 +15,6 @@ import {
15
15
  presentOnboarding,
16
16
  presentApplePay,
17
17
  presentGooglePay,
18
- setTheme,
19
18
  } from './native';
20
19
 
21
20
  export {
@@ -25,7 +24,6 @@ export {
25
24
  presentOnboarding,
26
25
  presentApplePay,
27
26
  presentGooglePay,
28
- setTheme,
29
27
  } from './native';
30
28
  export type {
31
29
  FrameCartItem,
@@ -53,7 +51,7 @@ export type {
53
51
  export { ErrorCodes } from './errors';
54
52
  export type { FrameErrorShape, FrameErrorCode } from './errors';
55
53
 
56
- /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
54
+ /** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
57
55
  export default {
58
56
  initialize,
59
57
  presentCheckout,
@@ -61,5 +59,4 @@ export default {
61
59
  presentOnboarding,
62
60
  presentApplePay,
63
61
  presentGooglePay,
64
- setTheme,
65
62
  };
package/src/native.ts CHANGED
@@ -14,6 +14,9 @@ import type {
14
14
  } from './types';
15
15
  import { ErrorCodes } from './errors';
16
16
 
17
+ // theme is iOS-only today: frame-android does not yet have a matching theme API,
18
+ // so the field is accepted on both platforms but ignored on Android until it does.
19
+
17
20
  const LINKING_ERROR =
18
21
  `The package 'framepayments-react-native' doesn't seem to be linked. Make sure you have run 'pod install' (iOS) or rebuilt the app (Android).`;
19
22
 
@@ -34,6 +37,13 @@ export function initialize(options: {
34
37
  secretKey: string;
35
38
  publishableKey: string;
36
39
  debugMode?: boolean;
40
+ /**
41
+ * Optional theme applied SDK-wide to Frame's reusable iOS components
42
+ * (checkout, cart, onboarding). Pass any subset — unspecified tokens fall
43
+ * back to SDK defaults. No-op on Android until frame-android ships a
44
+ * matching theme API.
45
+ */
46
+ theme?: FrameTheme;
37
47
  }): Promise<void> {
38
48
  if (!options?.secretKey) {
39
49
  throw new Error('Frame.initialize requires secretKey');
@@ -41,11 +51,15 @@ export function initialize(options: {
41
51
  if (!options?.publishableKey) {
42
52
  throw new Error('Frame.initialize requires publishableKey');
43
53
  }
54
+ if (options.theme !== undefined && (typeof options.theme !== 'object' || Array.isArray(options.theme))) {
55
+ throw new Error('Frame.initialize: theme must be an object');
56
+ }
44
57
  return wrapPromise(
45
58
  FrameSDK.initialize(
46
59
  options.secretKey,
47
60
  options.publishableKey,
48
- options.debugMode ?? false
61
+ options.debugMode ?? false,
62
+ options.theme ?? null
49
63
  )
50
64
  ).then(() => {
51
65
  isInitialized = true;
@@ -158,18 +172,3 @@ export function presentGooglePay(options: PresentGooglePayOptions): Promise<Char
158
172
  );
159
173
  }
160
174
 
161
- /**
162
- * Configure colors, fonts, and corner radii for Frame's reusable iOS
163
- * components. Applied to every subsequent `present*` call; an in-flight modal
164
- * is not re-themed mid-flow.
165
- *
166
- * Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
167
- * frame-android ships a matching theme API.
168
- */
169
- export function setTheme(theme: FrameTheme | null): Promise<void> {
170
- if (theme !== null && (typeof theme !== 'object' || Array.isArray(theme))) {
171
- throw new Error('Frame.setTheme requires a theme object or null');
172
- }
173
- if (Platform.OS !== 'ios') return Promise.resolve();
174
- return wrapPromise(FrameSDK.setTheme(theme ?? {}));
175
- }