Skip to content

Commit 14a4254

Browse files
committed
Initial scaffold
1 parent efa1060 commit 14a4254

File tree

7 files changed

+215
-15
lines changed

7 files changed

+215
-15
lines changed

modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ of this software and associated documentation files (the "Software"), to deal
2525
#import <React/RCTBridgeModule.h>
2626
#import <React/RCTViewManager.h>
2727

28-
@interface RCT_EXTERN_MODULE (RCTShopifyCheckoutSheetKit, NSObject)
28+
@interface RCT_EXTERN_REMAP_MODULE (ShopifyCheckoutSheetKit, RCTShopifyCheckoutSheetKit, NSObject)
2929

3030
/**
3131
* Present checkout

modules/@shopify/checkout-sheet-kit/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,17 @@
6363
}
6464
]
6565
]
66+
},
67+
"codegenConfig": {
68+
"name": "ShopifyCheckoutSheetKitSpec",
69+
"type": "all",
70+
"jsSrcsDir": "src",
71+
"android": {
72+
"javaPackageName": "com.shopify.reactnative.checkoutsheetkit"
73+
},
74+
"ios": {
75+
"libraryName": "RNShopifyCheckoutSheetKit",
76+
"prefix": "Shopify"
77+
}
6678
}
6779
}

modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ interface NativeAcceleratedCheckoutButtonsProps {
163163
onSizeChange?: (event: {nativeEvent: {height: number}}) => void;
164164
}
165165

166-
const RCTAcceleratedCheckoutButtons =
166+
const NativeAcceleratedCheckoutButtons =
167167
requireNativeComponent<NativeAcceleratedCheckoutButtonsProps>(
168168
'RCTAcceleratedCheckoutButtons',
169169
);
@@ -304,8 +304,10 @@ export const AcceleratedCheckoutButtons: React.FC<
304304
}
305305
}
306306

307+
const NativeComponent = NativeAcceleratedCheckoutButtons;
308+
307309
return (
308-
<RCTAcceleratedCheckoutButtons
310+
<NativeComponent
309311
applePayLabel={applePayLabel}
310312
style={{...defaultStyles, height: dynamicHeight}}
311313
checkoutIdentifier={checkoutIdentifier}

modules/@shopify/checkout-sheet-kit/src/index.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2121
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2222
*/
2323

24-
import {
25-
NativeModules,
26-
NativeEventEmitter,
27-
PermissionsAndroid,
28-
Platform,
29-
} from 'react-native';
24+
import {NativeEventEmitter, PermissionsAndroid, Platform} from 'react-native';
25+
import type {NativeModule} from 'react-native';
3026
import type {
3127
EmitterSubscription,
3228
EventSubscription,
@@ -64,22 +60,27 @@ import type {
6460
RenderStateChangeEvent,
6561
} from './components/AcceleratedCheckoutButtons';
6662

67-
const RNShopifyCheckoutSheetKit = NativeModules.ShopifyCheckoutSheetKit;
63+
import {getShopifyCheckoutNativeModule} from './native/module';
64+
import type {NativeShopifyCheckoutSheetKit} from './native/module';
6865

69-
if (!('ShopifyCheckoutSheetKit' in NativeModules)) {
66+
const __maybeNative: NativeShopifyCheckoutSheetKit | undefined =
67+
getShopifyCheckoutNativeModule();
68+
if (__maybeNative == null) {
7069
throw new Error(`
7170
"@shopify/checkout-sheet-kit" is not correctly linked.
7271
7372
If you are building for iOS, make sure to run "pod install" first and restart the metro server.`);
7473
}
74+
const RNShopifyCheckoutSheetKit =
75+
__maybeNative as NativeShopifyCheckoutSheetKit;
7576

7677
const defaultFeatures: Features = {
7778
handleGeolocationRequests: true,
7879
};
7980

8081
class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
8182
private static eventEmitter: NativeEventEmitter = new NativeEventEmitter(
82-
RNShopifyCheckoutSheetKit,
83+
RNShopifyCheckoutSheetKit as unknown as NativeModule,
8384
);
8485

8586
private features: Features;
@@ -230,7 +231,7 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
230231
this.validateAcceleratedCheckoutsConfiguration(config);
231232

232233
const configured =
233-
await RNShopifyCheckoutSheetKit.configureAcceleratedCheckouts(
234+
await RNShopifyCheckoutSheetKit.configureAcceleratedCheckouts?.(
234235
config.storefrontDomain,
235236
config.storefrontAccessToken,
236237
config.customer?.email || null,
@@ -239,7 +240,7 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
239240
config.wallets?.applePay?.merchantIdentifier || null,
240241
config.wallets?.applePay?.contactFields || [],
241242
);
242-
return configured;
243+
return configured ?? false;
243244
} catch (error) {
244245
// eslint-disable-next-line no-console
245246
console.error(
@@ -260,7 +261,9 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit {
260261
return false;
261262
}
262263

263-
return RNShopifyCheckoutSheetKit.isAcceleratedCheckoutAvailable();
264+
return (
265+
RNShopifyCheckoutSheetKit.isAcceleratedCheckoutAvailable?.() ?? false
266+
);
264267
}
265268

266269
/**
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
MIT License
3+
4+
Copyright 2023 - Present, Shopify Inc.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*/
23+
24+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
25+
import type {HostComponent} from 'react-native';
26+
import type {ViewProps} from 'react-native';
27+
28+
export type AcceleratedCheckoutButtonsNativeProps = Readonly<
29+
ViewProps & {
30+
checkoutIdentifier?: {
31+
cartId?: string;
32+
variantId?: string;
33+
quantity?: number;
34+
};
35+
cornerRadius?: number;
36+
wallets?: string[];
37+
applePayLabel?: string;
38+
onFail?: (event: {nativeEvent: any}) => void;
39+
onComplete?: (event: {nativeEvent: any}) => void;
40+
onCancel?: () => void;
41+
onRenderStateChange?: (event: {
42+
nativeEvent: {state: string; reason?: string};
43+
}) => void;
44+
onWebPixelEvent?: (event: {nativeEvent: any}) => void;
45+
onClickLink?: (event: {nativeEvent: {url: string}}) => void;
46+
onSizeChange?: (event: {nativeEvent: {height: number}}) => void;
47+
}
48+
>;
49+
50+
export default codegenNativeComponent<AcceleratedCheckoutButtonsNativeProps>(
51+
'ShopifyAcceleratedCheckoutButtons',
52+
) as HostComponent<AcceleratedCheckoutButtonsNativeProps>;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
MIT License
3+
4+
Copyright 2023 - Present, Shopify Inc.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*/
23+
24+
import type {TurboModule} from 'react-native';
25+
import {TurboModuleRegistry} from 'react-native';
26+
import type {Configuration} from '../index.d';
27+
28+
export interface Spec extends TurboModule {
29+
readonly version: string;
30+
dismiss(): void;
31+
invalidateCache(): void;
32+
preload(checkoutUrl: string): void;
33+
present(checkoutUrl: string): void;
34+
getConfig(): Promise<Configuration>;
35+
setConfig(configuration: Configuration): void;
36+
configureAcceleratedCheckouts?: (
37+
storefrontDomain: string,
38+
storefrontAccessToken: string,
39+
customerEmail: string | null,
40+
customerPhoneNumber: string | null,
41+
customerAccessToken: string | null,
42+
applePayMerchantIdentifier: string | null,
43+
applePayContactFields: string[],
44+
) => Promise<boolean>;
45+
isAcceleratedCheckoutAvailable?: () => Promise<boolean>;
46+
isApplePayAvailable?: () => Promise<boolean>;
47+
initiateGeolocationRequest?: (allow: boolean) => void;
48+
addListener(eventName: string): void;
49+
removeListeners(count: number): void;
50+
}
51+
52+
export default TurboModuleRegistry.getEnforcing<Spec>(
53+
'ShopifyCheckoutSheetKit',
54+
);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
MIT License
3+
4+
Copyright 2023 - Present, Shopify Inc.
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*/
23+
24+
import {NativeModules} from 'react-native';
25+
import type {Configuration} from '../index.d';
26+
27+
type NativeShopifyCheckoutSheetKit = {
28+
readonly version: string;
29+
dismiss(): void;
30+
invalidateCache(): void;
31+
preload(checkoutUrl: string): void;
32+
present(checkoutUrl: string): void;
33+
getConfig(): Promise<Configuration>;
34+
setConfig(configuration: Configuration): void;
35+
// iOS-specific accelerated checkouts
36+
configureAcceleratedCheckouts?: (
37+
storefrontDomain: string,
38+
storefrontAccessToken: string,
39+
customerEmail: string | null,
40+
customerPhoneNumber: string | null,
41+
customerAccessToken: string | null,
42+
applePayMerchantIdentifier: string | null,
43+
applePayContactFields: string[],
44+
) => Promise<boolean>;
45+
isAcceleratedCheckoutAvailable?: () => Promise<boolean>;
46+
isApplePayAvailable?: () => Promise<boolean>;
47+
// Android-specific geolocation
48+
initiateGeolocationRequest?: (allow: boolean) => void;
49+
// RN event emitter contract for TurboModules
50+
addListener: (eventName: string) => void;
51+
removeListeners: (count: number) => void;
52+
};
53+
54+
export function getShopifyCheckoutNativeModule():
55+
| NativeShopifyCheckoutSheetKit
56+
| undefined {
57+
// Prefer TurboModule if available; fall back to classic bridge.
58+
try {
59+
// Dynamically require to avoid throwing when codegen isn't wired yet.
60+
// If the generated spec is present, default export should be the TurboModule proxy.
61+
// eslint-disable-next-line @typescript-eslint/no-var-requires
62+
const turbo: NativeShopifyCheckoutSheetKit =
63+
require('./NativeShopifyCheckoutSheetKit').default;
64+
if (turbo != null) {
65+
return turbo;
66+
}
67+
} catch {
68+
// no-op; fall back to classic bridge
69+
}
70+
71+
const legacy = (NativeModules as any).ShopifyCheckoutSheetKit as
72+
| NativeShopifyCheckoutSheetKit
73+
| undefined;
74+
return legacy;
75+
}
76+
77+
export type {NativeShopifyCheckoutSheetKit};

0 commit comments

Comments
 (0)