framepayments-react-native 2.0.5 → 2.0.8
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 +80 -0
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameOnboardingActivity.kt +4 -1
- package/android/src/main/java/com/framepayments/reactnativeframe/FrameSDKModule.kt +2 -0
- package/ios/FrameRNTheme.swift +119 -0
- package/ios/FrameSDKBridge.m +8 -0
- package/ios/FrameSDKBridge.swift +38 -23
- package/lib/index.d.ts +5 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -3
- package/lib/native.d.ts +11 -1
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +20 -1
- package/lib/types.d.ts +55 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/native.test.ts +11 -4
- package/src/index.ts +10 -1
- package/src/native.ts +28 -1
- package/src/types.ts +62 -0
package/README.md
CHANGED
|
@@ -299,6 +299,86 @@ On non-Android platforms `Frame.presentGooglePay` rejects synchronously with a n
|
|
|
299
299
|
|
|
300
300
|
---
|
|
301
301
|
|
|
302
|
+
### `Frame.setTheme(theme)` (iOS)
|
|
303
|
+
|
|
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
|
+
|
|
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.
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
import Frame from 'framepayments-react-native';
|
|
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 },
|
|
322
|
+
},
|
|
323
|
+
radii: { medium: 16 },
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Android**: `setTheme()` resolves immediately and has no effect — `frame-android` does not yet have a matching theme API.
|
|
328
|
+
|
|
329
|
+
#### Tokens
|
|
330
|
+
|
|
331
|
+
**Colors** — hex strings (`#RGB`, `#RRGGBB`, or `#RRGGBBAA`, with or without leading `#`):
|
|
332
|
+
|
|
333
|
+
| Key | Used by |
|
|
334
|
+
|-----|---------|
|
|
335
|
+
| `primaryButton` / `primaryButtonText` | Primary CTAs |
|
|
336
|
+
| `secondaryButton` / `secondaryButtonText` | Secondary CTAs |
|
|
337
|
+
| `disabledButton` / `disabledButtonStroke` / `disabledButtonText` | Disabled CTAs |
|
|
338
|
+
| `surface` / `surfaceStroke` | Cards, sheets, input backgrounds |
|
|
339
|
+
| `textPrimary` / `textSecondary` | Body and supporting text |
|
|
340
|
+
| `error` | Validation messages |
|
|
341
|
+
| `onboardingHeaderBackground` | Onboarding header bar |
|
|
342
|
+
| `onboardingProgressFilledOnBrand` / `onboardingProgressEmptyOnBrand` | Onboarding progress indicator |
|
|
343
|
+
|
|
344
|
+
**Fonts** — `{ name: string; size: number }` objects. `name` must match a PostScript font name registered in your app's `Info.plist` (`UIAppFonts`) and bundled as a resource. Use `name: 'system'` for the system font.
|
|
345
|
+
|
|
346
|
+
| Key | Default | Used by |
|
|
347
|
+
|-----|---------|---------|
|
|
348
|
+
| `title` | `.title` | Page titles |
|
|
349
|
+
| `heading` | 18pt semibold | Section headers |
|
|
350
|
+
| `headline` | `.headline` | Card headlines |
|
|
351
|
+
| `body` | `.body` | Body text |
|
|
352
|
+
| `bodySmall` | 14pt | Smaller body |
|
|
353
|
+
| `label` | `.subheadline` | Field labels |
|
|
354
|
+
| `caption` | `.caption` | Captions, footnotes |
|
|
355
|
+
| `button` | `.headline` | Button text |
|
|
356
|
+
|
|
357
|
+
**Radii** — numbers (in points):
|
|
358
|
+
|
|
359
|
+
| Key | Default | Used by |
|
|
360
|
+
|-----|---------|---------|
|
|
361
|
+
| `small` | 8 | Small chips |
|
|
362
|
+
| `medium` | 10 | Buttons, inputs |
|
|
363
|
+
| `large` | 16 | Cards, sheets |
|
|
364
|
+
|
|
365
|
+
#### Custom fonts
|
|
366
|
+
|
|
367
|
+
Custom fonts are passed through to SwiftUI's `Font.custom(name:size:)`. Two requirements on the host iOS app:
|
|
368
|
+
|
|
369
|
+
1. Add the font file to your app's bundle (Xcode → Build Phases → Copy Bundle Resources).
|
|
370
|
+
2. Register it in your app's `Info.plist`:
|
|
371
|
+
```xml
|
|
372
|
+
<key>UIAppFonts</key>
|
|
373
|
+
<array>
|
|
374
|
+
<string>Inter-Bold.ttf</string>
|
|
375
|
+
</array>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
If a font name doesn't resolve, iOS silently falls back to the system font.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
302
382
|
### Rendering wallet buttons
|
|
303
383
|
|
|
304
384
|
Apple and Google both require their official button artwork (with light/dark variants) — custom-styled buttons can be rejected. Download the assets from [Apple's marketing page](https://developer.apple.com/apple-pay/marketing/) and [Google's brand guidelines page](https://developers.google.com/pay/api/android/guides/brand-guidelines), bundle them in your app, and pick a variant based on the active color scheme:
|
package/android/build.gradle
CHANGED
|
@@ -31,9 +31,9 @@ android {
|
|
|
31
31
|
dependencies {
|
|
32
32
|
implementation 'com.facebook.react:react-native:+'
|
|
33
33
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.0"
|
|
34
|
-
implementation 'com.framepayments:framesdk:2.0.
|
|
35
|
-
implementation 'com.framepayments:framesdk_ui:2.0.
|
|
36
|
-
implementation 'com.framepayments:framesdk_onboarding:2.0.
|
|
34
|
+
implementation 'com.framepayments:framesdk:2.0.4'
|
|
35
|
+
implementation 'com.framepayments:framesdk_ui:2.0.4'
|
|
36
|
+
implementation 'com.framepayments:framesdk_onboarding:2.0.4'
|
|
37
37
|
// Required by FrameGooglePayButton (PaymentsClient, WalletConstants).
|
|
38
38
|
// framesdk_ui declares this as `implementation`, so it is not exposed transitively.
|
|
39
39
|
implementation 'com.google.android.gms:play-services-wallet:19.4.0'
|
|
@@ -18,10 +18,12 @@ class FrameOnboardingActivity : ComponentActivity() {
|
|
|
18
18
|
val accountId = intent.getStringExtra(EXTRA_ACCOUNT_ID)
|
|
19
19
|
val capabilitiesJson = intent.getStringExtra(EXTRA_CAPABILITIES_JSON) ?: "[]"
|
|
20
20
|
val capabilities = parseCapabilities(capabilitiesJson)
|
|
21
|
+
val googlePayMerchantId = intent.getStringExtra(EXTRA_GOOGLE_PAY_MERCHANT_ID)
|
|
21
22
|
|
|
22
23
|
val config = OnboardingConfig(
|
|
23
24
|
accountId = accountId,
|
|
24
|
-
requiredCapabilities = capabilities
|
|
25
|
+
requiredCapabilities = capabilities,
|
|
26
|
+
googlePayMerchantId = googlePayMerchantId
|
|
25
27
|
)
|
|
26
28
|
|
|
27
29
|
setContent {
|
|
@@ -62,6 +64,7 @@ class FrameOnboardingActivity : ComponentActivity() {
|
|
|
62
64
|
companion object {
|
|
63
65
|
const val EXTRA_ACCOUNT_ID = "account_id"
|
|
64
66
|
const val EXTRA_CAPABILITIES_JSON = "capabilities_json"
|
|
67
|
+
const val EXTRA_GOOGLE_PAY_MERCHANT_ID = "google_pay_merchant_id"
|
|
65
68
|
const val EXTRA_PAYMENT_METHOD_ID = "payment_method_id"
|
|
66
69
|
const val REQUEST_CODE = 9003
|
|
67
70
|
}
|
|
@@ -119,6 +119,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
119
119
|
fun presentOnboarding(
|
|
120
120
|
accountId: String?,
|
|
121
121
|
capabilities: com.facebook.react.bridge.ReadableArray,
|
|
122
|
+
googlePayMerchantId: String?,
|
|
122
123
|
promise: Promise
|
|
123
124
|
) {
|
|
124
125
|
val activity = reactApplicationContext.currentActivity ?: run {
|
|
@@ -131,6 +132,7 @@ class FrameSDKModule(reactContext: ReactApplicationContext) :
|
|
|
131
132
|
val intent = Intent(activity, FrameOnboardingActivity::class.java).apply {
|
|
132
133
|
putExtra(FrameOnboardingActivity.EXTRA_ACCOUNT_ID, accountId)
|
|
133
134
|
putExtra(FrameOnboardingActivity.EXTRA_CAPABILITIES_JSON, capabilitiesJson)
|
|
135
|
+
putExtra(FrameOnboardingActivity.EXTRA_GOOGLE_PAY_MERCHANT_ID, googlePayMerchantId)
|
|
134
136
|
}
|
|
135
137
|
activity.startActivityForResult(intent, FrameOnboardingActivity.REQUEST_CODE)
|
|
136
138
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
//
|
|
2
|
+
// FrameRNTheme.swift
|
|
3
|
+
// FrameReactNative
|
|
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.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import SwiftUI
|
|
11
|
+
import Frame
|
|
12
|
+
|
|
13
|
+
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
|
+
static func parse(_ dict: [String: Any]) -> FrameTheme {
|
|
21
|
+
var theme = FrameTheme.default
|
|
22
|
+
|
|
23
|
+
if let colorsDict = dict["colors"] as? [String: Any] {
|
|
24
|
+
applyColor(colorsDict, "primaryButton") { theme.colors.primaryButton = $0 }
|
|
25
|
+
applyColor(colorsDict, "primaryButtonText") { theme.colors.primaryButtonText = $0 }
|
|
26
|
+
applyColor(colorsDict, "secondaryButton") { theme.colors.secondaryButton = $0 }
|
|
27
|
+
applyColor(colorsDict, "secondaryButtonText") { theme.colors.secondaryButtonText = $0 }
|
|
28
|
+
applyColor(colorsDict, "disabledButton") { theme.colors.disabledButton = $0 }
|
|
29
|
+
applyColor(colorsDict, "disabledButtonStroke") { theme.colors.disabledButtonStroke = $0 }
|
|
30
|
+
applyColor(colorsDict, "disabledButtonText") { theme.colors.disabledButtonText = $0 }
|
|
31
|
+
applyColor(colorsDict, "surface") { theme.colors.surface = $0 }
|
|
32
|
+
applyColor(colorsDict, "surfaceStroke") { theme.colors.surfaceStroke = $0 }
|
|
33
|
+
applyColor(colorsDict, "textPrimary") { theme.colors.textPrimary = $0 }
|
|
34
|
+
applyColor(colorsDict, "textSecondary") { theme.colors.textSecondary = $0 }
|
|
35
|
+
applyColor(colorsDict, "error") { theme.colors.error = $0 }
|
|
36
|
+
applyColor(colorsDict, "onboardingHeaderBackground") { theme.colors.onboardingHeaderBackground = $0 }
|
|
37
|
+
applyColor(colorsDict, "onboardingProgressFilledOnBrand") { theme.colors.onboardingProgressFilledOnBrand = $0 }
|
|
38
|
+
applyColor(colorsDict, "onboardingProgressEmptyOnBrand") { theme.colors.onboardingProgressEmptyOnBrand = $0 }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if let fontsDict = dict["fonts"] as? [String: Any] {
|
|
42
|
+
applyFont(fontsDict, "title") { theme.fonts.title = $0 }
|
|
43
|
+
applyFont(fontsDict, "heading") { theme.fonts.heading = $0 }
|
|
44
|
+
applyFont(fontsDict, "headline") { theme.fonts.headline = $0 }
|
|
45
|
+
applyFont(fontsDict, "body") { theme.fonts.body = $0 }
|
|
46
|
+
applyFont(fontsDict, "bodySmall") { theme.fonts.bodySmall = $0 }
|
|
47
|
+
applyFont(fontsDict, "label") { theme.fonts.label = $0 }
|
|
48
|
+
applyFont(fontsDict, "caption") { theme.fonts.caption = $0 }
|
|
49
|
+
applyFont(fontsDict, "button") { theme.fonts.button = $0 }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if let radiiDict = dict["radii"] as? [String: Any] {
|
|
53
|
+
if let v = radiiDict["small"] as? Double { theme.radii.small = CGFloat(v) }
|
|
54
|
+
if let v = radiiDict["medium"] as? Double { theme.radii.medium = CGFloat(v) }
|
|
55
|
+
if let v = radiiDict["large"] as? Double { theme.radii.large = CGFloat(v) }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return theme
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private static func applyColor(_ dict: [String: Any], _ key: String, _ set: (Color) -> Void) {
|
|
62
|
+
guard let hex = dict[key] as? String, let color = Color(rnHex: hex) else { return }
|
|
63
|
+
set(color)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private static func applyFont(_ dict: [String: Any], _ key: String, _ set: (Font) -> Void) {
|
|
67
|
+
guard let entry = dict[key] as? [String: Any],
|
|
68
|
+
let name = entry["name"] as? String,
|
|
69
|
+
let size = entry["size"] as? Double else { return }
|
|
70
|
+
if name.lowercased() == "system" {
|
|
71
|
+
set(.system(size: CGFloat(size)))
|
|
72
|
+
} else {
|
|
73
|
+
set(.custom(name, size: CGFloat(size)))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
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
|
+
extension Color {
|
|
95
|
+
// Accepts "#RGB", "#RRGGBB", "#RRGGBBAA" with or without the leading '#'.
|
|
96
|
+
init?(rnHex hex: String) {
|
|
97
|
+
var s = hex.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
98
|
+
if s.hasPrefix("#") { s.removeFirst() }
|
|
99
|
+
if s.count == 3 {
|
|
100
|
+
s = s.map { "\($0)\($0)" }.joined()
|
|
101
|
+
}
|
|
102
|
+
guard s.count == 6 || s.count == 8 else { return nil }
|
|
103
|
+
var v: UInt64 = 0
|
|
104
|
+
guard Scanner(string: s).scanHexInt64(&v) else { return nil }
|
|
105
|
+
let r, g, b, a: Double
|
|
106
|
+
if s.count == 6 {
|
|
107
|
+
r = Double((v >> 16) & 0xff) / 255
|
|
108
|
+
g = Double((v >> 8) & 0xff) / 255
|
|
109
|
+
b = Double( v & 0xff) / 255
|
|
110
|
+
a = 1
|
|
111
|
+
} else {
|
|
112
|
+
r = Double((v >> 24) & 0xff) / 255
|
|
113
|
+
g = Double((v >> 16) & 0xff) / 255
|
|
114
|
+
b = Double((v >> 8) & 0xff) / 255
|
|
115
|
+
a = Double( v & 0xff) / 255
|
|
116
|
+
}
|
|
117
|
+
self = Color(.sRGB, red: r, green: g, blue: b, opacity: a)
|
|
118
|
+
}
|
|
119
|
+
}
|
package/ios/FrameSDKBridge.m
CHANGED
|
@@ -31,6 +31,10 @@ RCT_EXTERN_METHOD(initialize:(NSString *)secretKey
|
|
|
31
31
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
32
32
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
33
33
|
|
|
34
|
+
RCT_EXTERN_METHOD(setTheme:(NSDictionary *)theme
|
|
35
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
36
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
37
|
+
|
|
34
38
|
RCT_EXTERN_METHOD(presentCheckout:(id)customerId
|
|
35
39
|
amount:(nonnull NSNumber *)amount
|
|
36
40
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
@@ -76,6 +80,10 @@ RCT_EXTERN_METHOD(presentApplePay:(NSString *)ownerType
|
|
|
76
80
|
[[[ObjCFrameSDKBridge alloc] init] initialize:secretKey publishableKey:publishableKey debugMode:debugMode resolver:resolve rejecter:reject];
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
- (void)setTheme:(NSDictionary *)theme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
84
|
+
[[[ObjCFrameSDKBridge alloc] init] setTheme:theme resolver:resolve rejecter:reject];
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
- (void)presentCheckout:(id)customerId amount:(NSNumber *)amount resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
80
88
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
81
89
|
UIViewController *topVC = FrameGetTopViewController();
|
package/ios/FrameSDKBridge.swift
CHANGED
|
@@ -27,6 +27,15 @@ public class FrameSDKBridge: NSObject {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
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)
|
|
35
|
+
resolve(nil)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
@objc public
|
|
31
40
|
func presentCheckout(from viewController: UIViewController, customerId: String?, amount: Int, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
32
41
|
presentCheckoutOnMain(from: viewController, customerId: customerId, amount: amount, resolve: resolve, reject: reject)
|
|
@@ -104,20 +113,23 @@ public class FrameSDKBridge: NSObject {
|
|
|
104
113
|
|
|
105
114
|
private func presentCheckoutOnMain(from top: UIViewController, customerId: String?, amount: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
106
115
|
var hosting: CheckoutHostingController!
|
|
107
|
-
hosting = CheckoutHostingController(rootView:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
hosting
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
hosting = CheckoutHostingController(rootView: ThemedRoot(
|
|
117
|
+
FrameCheckoutView(
|
|
118
|
+
customerId: customerId,
|
|
119
|
+
paymentAmount: amount,
|
|
120
|
+
checkoutCallback: { [weak hosting] chargeIntent in
|
|
121
|
+
hosting?.didComplete = true
|
|
122
|
+
top.dismiss(animated: true)
|
|
123
|
+
DispatchQueue.main.async {
|
|
124
|
+
if let dict = Self.encodeChargeIntent(chargeIntent) {
|
|
125
|
+
resolve(dict)
|
|
126
|
+
} else {
|
|
127
|
+
reject("ENCODE_ERROR", "Failed to encode charge intent", nil)
|
|
128
|
+
}
|
|
118
129
|
}
|
|
119
130
|
}
|
|
120
|
-
|
|
131
|
+
),
|
|
132
|
+
theme: FrameRNTheme.resolved()
|
|
121
133
|
))
|
|
122
134
|
hosting.onCancel = {
|
|
123
135
|
DispatchQueue.main.async {
|
|
@@ -174,7 +186,7 @@ public class FrameSDKBridge: NSObject {
|
|
|
174
186
|
cartItems: cartItems,
|
|
175
187
|
shippingAmountInCents: shippingAmountInCents
|
|
176
188
|
)
|
|
177
|
-
let hosting = UIHostingController(rootView: cartView)
|
|
189
|
+
let hosting = UIHostingController(rootView: ThemedRoot(cartView, theme: FrameRNTheme.resolved()))
|
|
178
190
|
hosting.modalPresentationStyle = UIModalPresentationStyle.pageSheet
|
|
179
191
|
if let sheet = hosting.sheetPresentationController {
|
|
180
192
|
sheet.detents = [UISheetPresentationController.Detent.large()]
|
|
@@ -188,17 +200,20 @@ public class FrameSDKBridge: NSObject {
|
|
|
188
200
|
}
|
|
189
201
|
|
|
190
202
|
private func presentOnboardingOnMain(from top: UIViewController, accountId: String?, capabilities: [FrameObjects.Capabilities], applePayMerchantId: String?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
191
|
-
var hosting: OnboardingHostingController<OnboardingContainerView
|
|
203
|
+
var hosting: OnboardingHostingController<ThemedRoot<OnboardingContainerView>>!
|
|
192
204
|
var delegate: OnboardingDismissDelegate!
|
|
193
205
|
hosting = OnboardingHostingController(
|
|
194
|
-
rootView:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
206
|
+
rootView: ThemedRoot(
|
|
207
|
+
OnboardingContainerView(
|
|
208
|
+
accountId: accountId,
|
|
209
|
+
requiredCapabilities: capabilities,
|
|
210
|
+
applePayMerchantId: applePayMerchantId,
|
|
211
|
+
onComplete: { [weak hosting] in
|
|
212
|
+
delegate?.finish(completed: true)
|
|
213
|
+
hosting?.dismiss(animated: true)
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
theme: FrameRNTheme.resolved()
|
|
202
217
|
)
|
|
203
218
|
)
|
|
204
219
|
// Embed in a UINavigationController so the outer sheet is a UIKit container,
|
|
@@ -227,7 +242,7 @@ public class FrameSDKBridge: NSObject {
|
|
|
227
242
|
|
|
228
243
|
// MARK: - CheckoutHostingController
|
|
229
244
|
|
|
230
|
-
private final class CheckoutHostingController: UIHostingController<FrameCheckoutView
|
|
245
|
+
private final class CheckoutHostingController: UIHostingController<ThemedRoot<FrameCheckoutView>>, UIAdaptivePresentationControllerDelegate {
|
|
231
246
|
var didComplete = false
|
|
232
247
|
var onCancel: (() -> Void)?
|
|
233
248
|
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 } from './native';
|
|
11
|
-
export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
|
|
12
|
-
export type { FrameCartItem, ChargeIntent, ChargeIntentStatus, AuthorizationMode, FrameError, BillingAddress, PaymentCard, BankAccount, PaymentMethod, OnboardingCapability, OnboardingResult, OnboardingResultStatus, ApplePayOwner, PresentApplePayOptions, PresentGooglePayOptions, } from './types';
|
|
10
|
+
import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme } from './native';
|
|
11
|
+
export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
|
|
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() */
|
|
15
|
+
/** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
|
|
16
16
|
declare const _default: {
|
|
17
17
|
initialize: typeof initialize;
|
|
18
18
|
presentCheckout: typeof presentCheckout;
|
|
@@ -20,6 +20,7 @@ declare const _default: {
|
|
|
20
20
|
presentOnboarding: typeof presentOnboarding;
|
|
21
21
|
presentApplePay: typeof presentApplePay;
|
|
22
22
|
presentGooglePay: typeof presentGooglePay;
|
|
23
|
+
setTheme: typeof setTheme;
|
|
23
24
|
};
|
|
24
25
|
export default _default;
|
|
25
26
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
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, } from './native';
|
|
11
|
-
export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, } from './native';
|
|
10
|
+
import { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
|
|
11
|
+
export { initialize, presentCheckout, presentCart, presentOnboarding, presentApplePay, presentGooglePay, setTheme, } from './native';
|
|
12
12
|
export { ErrorCodes } from './errors';
|
|
13
|
-
/** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
|
|
13
|
+
/** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
|
|
14
14
|
export default {
|
|
15
15
|
initialize,
|
|
16
16
|
presentCheckout,
|
|
@@ -18,4 +18,5 @@ export default {
|
|
|
18
18
|
presentOnboarding,
|
|
19
19
|
presentApplePay,
|
|
20
20
|
presentGooglePay,
|
|
21
|
+
setTheme,
|
|
21
22
|
};
|
package/lib/native.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Native module bridge. Uses NativeModules for classic React Native bridge.
|
|
3
3
|
*/
|
|
4
|
-
import type { ChargeIntent, FrameCartItem, OnboardingCapability, OnboardingResult, PresentApplePayOptions, PresentGooglePayOptions } from './types';
|
|
4
|
+
import type { ChargeIntent, FrameCartItem, FrameTheme, OnboardingCapability, OnboardingResult, PresentApplePayOptions, PresentGooglePayOptions } from './types';
|
|
5
5
|
export declare function initialize(options: {
|
|
6
6
|
secretKey: string;
|
|
7
7
|
publishableKey: string;
|
|
@@ -20,7 +20,17 @@ export declare function presentOnboarding(options: {
|
|
|
20
20
|
accountId?: string | null;
|
|
21
21
|
capabilities?: OnboardingCapability[];
|
|
22
22
|
applePayMerchantId?: string | null;
|
|
23
|
+
googlePayMerchantId?: string | null;
|
|
23
24
|
}): Promise<OnboardingResult>;
|
|
24
25
|
export declare function presentApplePay(options: PresentApplePayOptions): Promise<ChargeIntent>;
|
|
25
26
|
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>;
|
|
26
36
|
//# sourceMappingURL=native.d.ts.map
|
package/lib/native.d.ts.map
CHANGED
|
@@ -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,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;
|
|
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,CA0B5B;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"}
|
package/lib/native.js
CHANGED
|
@@ -56,7 +56,10 @@ export function presentOnboarding(options) {
|
|
|
56
56
|
if (Platform.OS === 'ios' && options.applePayMerchantId) {
|
|
57
57
|
return wrapPromise(FrameSDK.presentOnboardingWithApplePay(options.accountId ?? null, options.capabilities ?? [], options.applePayMerchantId));
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
if (Platform.OS === 'ios') {
|
|
60
|
+
return wrapPromise(FrameSDK.presentOnboarding(options.accountId ?? null, options.capabilities ?? []));
|
|
61
|
+
}
|
|
62
|
+
return wrapPromise(FrameSDK.presentOnboarding(options.accountId ?? null, options.capabilities ?? [], options.googlePayMerchantId ?? null));
|
|
60
63
|
}
|
|
61
64
|
export function presentApplePay(options) {
|
|
62
65
|
guardInitialized();
|
|
@@ -75,3 +78,19 @@ export function presentGooglePay(options) {
|
|
|
75
78
|
guardInitialized();
|
|
76
79
|
return wrapPromise(FrameSDK.presentGooglePay(options.amountCents, options.customerId ?? null, options.currencyCode ?? 'USD', options.googlePayMerchantId ?? null));
|
|
77
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Configure colors, fonts, and corner radii for Frame's reusable iOS
|
|
83
|
+
* components. Applied to every subsequent `present*` call; an in-flight modal
|
|
84
|
+
* is not re-themed mid-flow.
|
|
85
|
+
*
|
|
86
|
+
* Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
|
|
87
|
+
* frame-android ships a matching theme API.
|
|
88
|
+
*/
|
|
89
|
+
export function setTheme(theme) {
|
|
90
|
+
if (theme !== null && (typeof theme !== 'object' || Array.isArray(theme))) {
|
|
91
|
+
throw new Error('Frame.setTheme requires a theme object or null');
|
|
92
|
+
}
|
|
93
|
+
if (Platform.OS !== 'ios')
|
|
94
|
+
return Promise.resolve();
|
|
95
|
+
return wrapPromise(FrameSDK.setTheme(theme ?? {}));
|
|
96
|
+
}
|
package/lib/types.d.ts
CHANGED
|
@@ -128,4 +128,59 @@ export interface PresentGooglePayOptions {
|
|
|
128
128
|
/** Optional override for the Google Pay merchant ID. */
|
|
129
129
|
googlePayMerchantId?: string;
|
|
130
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Theming for Frame's reusable iOS components (checkout, cart, onboarding).
|
|
133
|
+
* iOS-only: on Android, Frame.setTheme() resolves immediately and has no effect
|
|
134
|
+
* until frame-android ships a matching theme API.
|
|
135
|
+
*
|
|
136
|
+
* Pass any subset — unspecified tokens fall back to SDK defaults.
|
|
137
|
+
*/
|
|
138
|
+
/** Hex color: '#RGB', '#RRGGBB', or '#RRGGBBAA' (with or without leading '#'). */
|
|
139
|
+
export type FrameThemeColor = string;
|
|
140
|
+
/**
|
|
141
|
+
* Custom font reference. `name` must be a PostScript font name registered in
|
|
142
|
+
* the host app's Info.plist `UIAppFonts` and bundled as a resource. Pass
|
|
143
|
+
* `name: 'system'` to use the system font at the given size.
|
|
144
|
+
*/
|
|
145
|
+
export interface FrameThemeFont {
|
|
146
|
+
name: string;
|
|
147
|
+
size: number;
|
|
148
|
+
}
|
|
149
|
+
export interface FrameThemeColors {
|
|
150
|
+
primaryButton?: FrameThemeColor;
|
|
151
|
+
primaryButtonText?: FrameThemeColor;
|
|
152
|
+
secondaryButton?: FrameThemeColor;
|
|
153
|
+
secondaryButtonText?: FrameThemeColor;
|
|
154
|
+
disabledButton?: FrameThemeColor;
|
|
155
|
+
disabledButtonStroke?: FrameThemeColor;
|
|
156
|
+
disabledButtonText?: FrameThemeColor;
|
|
157
|
+
surface?: FrameThemeColor;
|
|
158
|
+
surfaceStroke?: FrameThemeColor;
|
|
159
|
+
textPrimary?: FrameThemeColor;
|
|
160
|
+
textSecondary?: FrameThemeColor;
|
|
161
|
+
error?: FrameThemeColor;
|
|
162
|
+
onboardingHeaderBackground?: FrameThemeColor;
|
|
163
|
+
onboardingProgressFilledOnBrand?: FrameThemeColor;
|
|
164
|
+
onboardingProgressEmptyOnBrand?: FrameThemeColor;
|
|
165
|
+
}
|
|
166
|
+
export interface FrameThemeFonts {
|
|
167
|
+
title?: FrameThemeFont;
|
|
168
|
+
heading?: FrameThemeFont;
|
|
169
|
+
headline?: FrameThemeFont;
|
|
170
|
+
body?: FrameThemeFont;
|
|
171
|
+
bodySmall?: FrameThemeFont;
|
|
172
|
+
label?: FrameThemeFont;
|
|
173
|
+
caption?: FrameThemeFont;
|
|
174
|
+
button?: FrameThemeFont;
|
|
175
|
+
}
|
|
176
|
+
export interface FrameThemeRadii {
|
|
177
|
+
small?: number;
|
|
178
|
+
medium?: number;
|
|
179
|
+
large?: number;
|
|
180
|
+
}
|
|
181
|
+
export interface FrameTheme {
|
|
182
|
+
colors?: FrameThemeColors;
|
|
183
|
+
fonts?: FrameThemeFonts;
|
|
184
|
+
radii?: FrameThemeRadii;
|
|
185
|
+
}
|
|
131
186
|
//# sourceMappingURL=types.d.ts.map
|
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@ let presentCart: (opts: {
|
|
|
32
32
|
items: Array<{ id: string; title: string; amountInCents: number; imageUrl: string }>;
|
|
33
33
|
shippingAmountInCents: number;
|
|
34
34
|
}) => Promise<unknown>;
|
|
35
|
-
let presentOnboarding: (opts: { accountId?: string | null; capabilities?: string[]; applePayMerchantId?: string | null }) => Promise<unknown>;
|
|
35
|
+
let presentOnboarding: (opts: { accountId?: string | null; capabilities?: string[]; applePayMerchantId?: string | null; googlePayMerchantId?: string | null }) => Promise<unknown>;
|
|
36
36
|
|
|
37
37
|
beforeEach(() => {
|
|
38
38
|
jest.resetModules();
|
|
@@ -148,14 +148,14 @@ describe('presentOnboarding', () => {
|
|
|
148
148
|
it('calls native presentOnboarding with accountId and capabilities after initialize', async () => {
|
|
149
149
|
await initialize({ secretKey: 'sk_xxx', publishableKey: 'pk_xxx' });
|
|
150
150
|
const result = await presentOnboarding({ accountId: 'acct_1', capabilities: ['kyc', 'bank_account_verification'] });
|
|
151
|
-
expect(mockPresentOnboarding).toHaveBeenCalledWith('acct_1', ['kyc', 'bank_account_verification']);
|
|
151
|
+
expect(mockPresentOnboarding).toHaveBeenCalledWith('acct_1', ['kyc', 'bank_account_verification'], null);
|
|
152
152
|
expect(result).toEqual({ status: 'completed', paymentMethodId: 'pm_1' });
|
|
153
153
|
});
|
|
154
154
|
|
|
155
155
|
it('passes null for accountId and empty array for capabilities when not provided', async () => {
|
|
156
156
|
await initialize({ secretKey: 'sk_xxx', publishableKey: 'pk_xxx' });
|
|
157
157
|
await presentOnboarding({});
|
|
158
|
-
expect(mockPresentOnboarding).toHaveBeenCalledWith(null, []);
|
|
158
|
+
expect(mockPresentOnboarding).toHaveBeenCalledWith(null, [], null);
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
it('routes to presentOnboardingWithApplePay on iOS when applePayMerchantId is set', async () => {
|
|
@@ -170,7 +170,14 @@ describe('presentOnboarding', () => {
|
|
|
170
170
|
mockPlatform.OS = 'android';
|
|
171
171
|
await initialize({ secretKey: 'sk_xxx', publishableKey: 'pk_xxx' });
|
|
172
172
|
await presentOnboarding({ accountId: 'acct_1', capabilities: ['kyc'], applePayMerchantId: 'merchant.com.example' });
|
|
173
|
-
expect(mockPresentOnboarding).toHaveBeenCalledWith('acct_1', ['kyc']);
|
|
173
|
+
expect(mockPresentOnboarding).toHaveBeenCalledWith('acct_1', ['kyc'], null);
|
|
174
174
|
expect(mockPresentOnboardingWithApplePay).not.toHaveBeenCalled();
|
|
175
175
|
});
|
|
176
|
+
|
|
177
|
+
it('forwards googlePayMerchantId to native presentOnboarding on Android', async () => {
|
|
178
|
+
mockPlatform.OS = 'android';
|
|
179
|
+
await initialize({ secretKey: 'sk_xxx', publishableKey: 'pk_xxx' });
|
|
180
|
+
await presentOnboarding({ accountId: 'acct_1', capabilities: ['kyc'], googlePayMerchantId: 'BCR2DN4T...' });
|
|
181
|
+
expect(mockPresentOnboarding).toHaveBeenCalledWith('acct_1', ['kyc'], 'BCR2DN4T...');
|
|
182
|
+
});
|
|
176
183
|
});
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
presentOnboarding,
|
|
16
16
|
presentApplePay,
|
|
17
17
|
presentGooglePay,
|
|
18
|
+
setTheme,
|
|
18
19
|
} from './native';
|
|
19
20
|
|
|
20
21
|
export {
|
|
@@ -24,6 +25,7 @@ export {
|
|
|
24
25
|
presentOnboarding,
|
|
25
26
|
presentApplePay,
|
|
26
27
|
presentGooglePay,
|
|
28
|
+
setTheme,
|
|
27
29
|
} from './native';
|
|
28
30
|
export type {
|
|
29
31
|
FrameCartItem,
|
|
@@ -41,11 +43,17 @@ export type {
|
|
|
41
43
|
ApplePayOwner,
|
|
42
44
|
PresentApplePayOptions,
|
|
43
45
|
PresentGooglePayOptions,
|
|
46
|
+
FrameTheme,
|
|
47
|
+
FrameThemeColor,
|
|
48
|
+
FrameThemeFont,
|
|
49
|
+
FrameThemeColors,
|
|
50
|
+
FrameThemeFonts,
|
|
51
|
+
FrameThemeRadii,
|
|
44
52
|
} from './types';
|
|
45
53
|
export { ErrorCodes } from './errors';
|
|
46
54
|
export type { FrameErrorShape, FrameErrorCode } from './errors';
|
|
47
55
|
|
|
48
|
-
/** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay() */
|
|
56
|
+
/** Default export for Frame.initialize(), Frame.presentCheckout(), Frame.presentCart(), Frame.presentOnboarding(), Frame.presentApplePay(), Frame.presentGooglePay(), Frame.setTheme() */
|
|
49
57
|
export default {
|
|
50
58
|
initialize,
|
|
51
59
|
presentCheckout,
|
|
@@ -53,4 +61,5 @@ export default {
|
|
|
53
61
|
presentOnboarding,
|
|
54
62
|
presentApplePay,
|
|
55
63
|
presentGooglePay,
|
|
64
|
+
setTheme,
|
|
56
65
|
};
|
package/src/native.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { NativeModules, Platform } from 'react-native';
|
|
|
6
6
|
import type {
|
|
7
7
|
ChargeIntent,
|
|
8
8
|
FrameCartItem,
|
|
9
|
+
FrameTheme,
|
|
9
10
|
OnboardingCapability,
|
|
10
11
|
OnboardingResult,
|
|
11
12
|
PresentApplePayOptions,
|
|
@@ -102,6 +103,7 @@ export function presentOnboarding(options: {
|
|
|
102
103
|
accountId?: string | null;
|
|
103
104
|
capabilities?: OnboardingCapability[];
|
|
104
105
|
applePayMerchantId?: string | null;
|
|
106
|
+
googlePayMerchantId?: string | null;
|
|
105
107
|
}): Promise<OnboardingResult> {
|
|
106
108
|
guardInitialized();
|
|
107
109
|
if (Platform.OS === 'ios' && options.applePayMerchantId) {
|
|
@@ -113,10 +115,19 @@ export function presentOnboarding(options: {
|
|
|
113
115
|
)
|
|
114
116
|
);
|
|
115
117
|
}
|
|
118
|
+
if (Platform.OS === 'ios') {
|
|
119
|
+
return wrapPromise(
|
|
120
|
+
FrameSDK.presentOnboarding(
|
|
121
|
+
options.accountId ?? null,
|
|
122
|
+
options.capabilities ?? []
|
|
123
|
+
)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
116
126
|
return wrapPromise(
|
|
117
127
|
FrameSDK.presentOnboarding(
|
|
118
128
|
options.accountId ?? null,
|
|
119
|
-
options.capabilities ?? []
|
|
129
|
+
options.capabilities ?? [],
|
|
130
|
+
options.googlePayMerchantId ?? null
|
|
120
131
|
)
|
|
121
132
|
);
|
|
122
133
|
}
|
|
@@ -154,3 +165,19 @@ export function presentGooglePay(options: PresentGooglePayOptions): Promise<Char
|
|
|
154
165
|
)
|
|
155
166
|
);
|
|
156
167
|
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Configure colors, fonts, and corner radii for Frame's reusable iOS
|
|
171
|
+
* components. Applied to every subsequent `present*` call; an in-flight modal
|
|
172
|
+
* is not re-themed mid-flow.
|
|
173
|
+
*
|
|
174
|
+
* Pass `null` or `{}` to reset to SDK defaults. Android is a no-op until
|
|
175
|
+
* frame-android ships a matching theme API.
|
|
176
|
+
*/
|
|
177
|
+
export function setTheme(theme: FrameTheme | null): Promise<void> {
|
|
178
|
+
if (theme !== null && (typeof theme !== 'object' || Array.isArray(theme))) {
|
|
179
|
+
throw new Error('Frame.setTheme requires a theme object or null');
|
|
180
|
+
}
|
|
181
|
+
if (Platform.OS !== 'ios') return Promise.resolve();
|
|
182
|
+
return wrapPromise(FrameSDK.setTheme(theme ?? {}));
|
|
183
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -162,3 +162,65 @@ export interface PresentGooglePayOptions {
|
|
|
162
162
|
/** Optional override for the Google Pay merchant ID. */
|
|
163
163
|
googlePayMerchantId?: string;
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Theming for Frame's reusable iOS components (checkout, cart, onboarding).
|
|
168
|
+
* iOS-only: on Android, Frame.setTheme() resolves immediately and has no effect
|
|
169
|
+
* until frame-android ships a matching theme API.
|
|
170
|
+
*
|
|
171
|
+
* Pass any subset — unspecified tokens fall back to SDK defaults.
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
/** Hex color: '#RGB', '#RRGGBB', or '#RRGGBBAA' (with or without leading '#'). */
|
|
175
|
+
export type FrameThemeColor = string;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Custom font reference. `name` must be a PostScript font name registered in
|
|
179
|
+
* the host app's Info.plist `UIAppFonts` and bundled as a resource. Pass
|
|
180
|
+
* `name: 'system'` to use the system font at the given size.
|
|
181
|
+
*/
|
|
182
|
+
export interface FrameThemeFont {
|
|
183
|
+
name: string;
|
|
184
|
+
size: number;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface FrameThemeColors {
|
|
188
|
+
primaryButton?: FrameThemeColor;
|
|
189
|
+
primaryButtonText?: FrameThemeColor;
|
|
190
|
+
secondaryButton?: FrameThemeColor;
|
|
191
|
+
secondaryButtonText?: FrameThemeColor;
|
|
192
|
+
disabledButton?: FrameThemeColor;
|
|
193
|
+
disabledButtonStroke?: FrameThemeColor;
|
|
194
|
+
disabledButtonText?: FrameThemeColor;
|
|
195
|
+
surface?: FrameThemeColor;
|
|
196
|
+
surfaceStroke?: FrameThemeColor;
|
|
197
|
+
textPrimary?: FrameThemeColor;
|
|
198
|
+
textSecondary?: FrameThemeColor;
|
|
199
|
+
error?: FrameThemeColor;
|
|
200
|
+
onboardingHeaderBackground?: FrameThemeColor;
|
|
201
|
+
onboardingProgressFilledOnBrand?: FrameThemeColor;
|
|
202
|
+
onboardingProgressEmptyOnBrand?: FrameThemeColor;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface FrameThemeFonts {
|
|
206
|
+
title?: FrameThemeFont;
|
|
207
|
+
heading?: FrameThemeFont;
|
|
208
|
+
headline?: FrameThemeFont;
|
|
209
|
+
body?: FrameThemeFont;
|
|
210
|
+
bodySmall?: FrameThemeFont;
|
|
211
|
+
label?: FrameThemeFont;
|
|
212
|
+
caption?: FrameThemeFont;
|
|
213
|
+
button?: FrameThemeFont;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface FrameThemeRadii {
|
|
217
|
+
small?: number;
|
|
218
|
+
medium?: number;
|
|
219
|
+
large?: number;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface FrameTheme {
|
|
223
|
+
colors?: FrameThemeColors;
|
|
224
|
+
fonts?: FrameThemeFonts;
|
|
225
|
+
radii?: FrameThemeRadii;
|
|
226
|
+
}
|