@namiml/expo-sdk 3.4.0-dev.202605060437
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/dist/index.cjs +4000 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.mjs +3966 -0
- package/dist/index.mjs.map +1 -0
- package/nami-expo-nami-iap.tgz +0 -0
- package/package.json +92 -0
- package/src/adapters/expo-device.adapter.ts +106 -0
- package/src/adapters/expo-purchase.adapter.ts +79 -0
- package/src/adapters/expo-storage.adapter.ts +92 -0
- package/src/adapters/expo-ui.adapter.ts +57 -0
- package/src/adapters/index.ts +33 -0
- package/src/amazon-kepler.d.ts +7 -0
- package/src/components/NamiView.tsx +1006 -0
- package/src/components/PaywallScreen.tsx +245 -0
- package/src/components/TemplateRenderer.tsx +243 -0
- package/src/components/containers/NamiBackgroundContainer.tsx +103 -0
- package/src/components/containers/NamiCarousel.tsx +217 -0
- package/src/components/containers/NamiCollapseContainer.tsx +116 -0
- package/src/components/containers/NamiContainer.tsx +315 -0
- package/src/components/containers/NamiContentContainer.tsx +140 -0
- package/src/components/containers/NamiFooter.tsx +35 -0
- package/src/components/containers/NamiHeader.tsx +45 -0
- package/src/components/containers/NamiProductContainer.tsx +248 -0
- package/src/components/containers/NamiRepeatingGrid.tsx +81 -0
- package/src/components/containers/NamiResponsiveGrid.tsx +75 -0
- package/src/components/containers/NamiStack.tsx +69 -0
- package/src/components/elements/NamiButton.tsx +285 -0
- package/src/components/elements/NamiCountdownTimer.tsx +123 -0
- package/src/components/elements/NamiImage.tsx +177 -0
- package/src/components/elements/NamiPlayPauseButton.tsx +93 -0
- package/src/components/elements/NamiProgressBar.tsx +90 -0
- package/src/components/elements/NamiProgressIndicator.tsx +41 -0
- package/src/components/elements/NamiQRCode.tsx +51 -0
- package/src/components/elements/NamiRadioButton.tsx +62 -0
- package/src/components/elements/NamiSegmentPicker.tsx +67 -0
- package/src/components/elements/NamiSegmentPickerItem.tsx +184 -0
- package/src/components/elements/NamiSpacer.tsx +23 -0
- package/src/components/elements/NamiSymbol.tsx +104 -0
- package/src/components/elements/NamiText.tsx +311 -0
- package/src/components/elements/NamiToggleButton.tsx +102 -0
- package/src/components/elements/NamiToggleSwitch.tsx +64 -0
- package/src/components/elements/NamiVideo.kepler.tsx +638 -0
- package/src/components/elements/NamiVideo.tsx +133 -0
- package/src/components/elements/NamiVolumeButton.tsx +93 -0
- package/src/context/FocusContext.tsx +169 -0
- package/src/context/PaywallContext.tsx +343 -0
- package/src/global.d.ts +5 -0
- package/src/index.ts +62 -0
- package/src/nami.ts +24 -0
- package/src/react-native-qrcode-svg.d.ts +4 -0
- package/src/utils/actionHandler.ts +281 -0
- package/src/utils/fonts.ts +359 -0
- package/src/utils/iconMap.ts +67 -0
- package/src/utils/impression.ts +39 -0
- package/src/utils/rendering.ts +197 -0
- package/src/utils/smartText.ts +148 -0
- package/src/utils/styles.ts +668 -0
- package/src/utils/tvFocus.ts +31 -0
- package/src/utils/videoControls.ts +49 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Dimensions } from 'react-native';
|
|
3
|
+
import type {
|
|
4
|
+
IPaywall, ISkuMenu, TPaywallContext, NamiPaywallLaunchContext,
|
|
5
|
+
NamiCampaign, NamiProductDetails, NamiSKU, NamiPaywallEvent,
|
|
6
|
+
TDevice, TimerState, TPaywallMedia, NamiAppSuppliedVideoDetails,
|
|
7
|
+
NamiFlow,
|
|
8
|
+
} from '@namiml/sdk-core';
|
|
9
|
+
import { PaywallState, initialState } from '@namiml/sdk-core';
|
|
10
|
+
|
|
11
|
+
type PaywallStateWithPageHistory = PaywallState & {
|
|
12
|
+
canGoBackPage(): boolean;
|
|
13
|
+
goBackPage(): boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function asMethod<TArgs extends unknown[], TResult>(
|
|
17
|
+
candidate: unknown,
|
|
18
|
+
): ((...args: TArgs) => TResult) | undefined {
|
|
19
|
+
return typeof candidate === 'function'
|
|
20
|
+
? (candidate as (...args: TArgs) => TResult)
|
|
21
|
+
: undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface PaywallContextValue {
|
|
25
|
+
state: TPaywallContext;
|
|
26
|
+
productDetails: NamiProductDetails[];
|
|
27
|
+
flow?: NamiFlow;
|
|
28
|
+
filteredSkuMenus: ISkuMenu[];
|
|
29
|
+
setPaywall(paywall: IPaywall, context: NamiPaywallLaunchContext, campaign: NamiCampaign): void;
|
|
30
|
+
notifyFirstFocusReady(paywallId: string, page: string, formFactor?: string): void;
|
|
31
|
+
setCurrentPage(page: string): void;
|
|
32
|
+
canGoBackPage(): boolean;
|
|
33
|
+
goBackPage(): boolean;
|
|
34
|
+
setCurrentGroupData(groupId: string, groupName: string): void;
|
|
35
|
+
setSelectedProducts(products: Record<string, string | null>): void;
|
|
36
|
+
setCurrentFormId(formId: string, value?: string): void;
|
|
37
|
+
setFormState(formId: string, value: boolean | string): void;
|
|
38
|
+
setTimerState(timerId: string, remainingSeconds: number, savedAt: number, hasEmittedCompletion: boolean): void;
|
|
39
|
+
getTimerState(timerId: string): TimerState | undefined;
|
|
40
|
+
setProductDetails(details: NamiProductDetails[]): void;
|
|
41
|
+
setPurchaseInProgress(inProgress: boolean): void;
|
|
42
|
+
setPurchase(inProgress: boolean, product?: NamiSKU): void;
|
|
43
|
+
setCustomerAttribute(attributes: Record<string, string>): void;
|
|
44
|
+
removeCustomerAttribute(key: string): void;
|
|
45
|
+
setIsLoggedIn(isLoggedIn: boolean): void;
|
|
46
|
+
setAppSuppliedVideoDetails(details: NamiAppSuppliedVideoDetails): void;
|
|
47
|
+
resetAppSuppliedVideoDetails(): void;
|
|
48
|
+
setMediaList(media: TPaywallMedia[]): void;
|
|
49
|
+
setSafeAreaTop(top: number): void;
|
|
50
|
+
setFullScreenPresentation(full: boolean): void;
|
|
51
|
+
setFormFactor(factor: TDevice): void;
|
|
52
|
+
setUserInteractionEnabled(enabled: boolean): void;
|
|
53
|
+
setUserTags(tags: Record<string, string>): void;
|
|
54
|
+
setLaunchDetails(value: string, type?: string): void;
|
|
55
|
+
setOpenHeaderIds(id: string, sku?: NamiSKU): void;
|
|
56
|
+
setFlow(flow: NamiFlow): void;
|
|
57
|
+
setCurrentSlideIndex(index: number): void;
|
|
58
|
+
getPaywallActionEventData(): Partial<NamiPaywallEvent>;
|
|
59
|
+
getSelectedPaywall(): IPaywall | undefined;
|
|
60
|
+
getSelectedCampaign(): NamiCampaign | undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const PaywallCtx = createContext<PaywallContextValue | null>(null);
|
|
64
|
+
const FirstFocusReadyCtx = createContext<{
|
|
65
|
+
firstFocusReadyKey: string | null;
|
|
66
|
+
notifyFirstFocusReady(paywallId: string, page: string, formFactor?: string): void;
|
|
67
|
+
} | null>(null);
|
|
68
|
+
|
|
69
|
+
export function usePaywallContext(): PaywallContextValue {
|
|
70
|
+
const ctx = useContext(PaywallCtx);
|
|
71
|
+
if (!ctx) throw new Error('usePaywallContext must be used within a PaywallProvider');
|
|
72
|
+
return ctx;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function useFirstFocusReadyContext(): {
|
|
76
|
+
firstFocusReadyKey: string | null;
|
|
77
|
+
notifyFirstFocusReady(paywallId: string, page: string, formFactor?: string): void;
|
|
78
|
+
} {
|
|
79
|
+
const ctx = useContext(FirstFocusReadyCtx);
|
|
80
|
+
if (!ctx) throw new Error('useFirstFocusReadyContext must be used within a PaywallProvider');
|
|
81
|
+
return ctx;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface PaywallProviderProps {
|
|
85
|
+
paywall: IPaywall;
|
|
86
|
+
context: NamiPaywallLaunchContext;
|
|
87
|
+
campaign: NamiCampaign;
|
|
88
|
+
flow?: NamiFlow;
|
|
89
|
+
onFirstFocusReady?: (paywallId: string, page: string, formFactor?: string) => void;
|
|
90
|
+
children: React.ReactNode;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const PaywallProvider: React.FC<PaywallProviderProps> = ({
|
|
94
|
+
paywall, context, campaign, flow, onFirstFocusReady, children,
|
|
95
|
+
}) => {
|
|
96
|
+
const providerRef = useRef<PaywallStateWithPageHistory | null>(null);
|
|
97
|
+
const pageHistoryRef = useRef<string[]>([]);
|
|
98
|
+
const [firstFocusReadyKey, setFirstFocusReadyKey] = useState<string | null>(null);
|
|
99
|
+
|
|
100
|
+
const [state, setState] = useState<TPaywallContext>(() => {
|
|
101
|
+
const provider = PaywallState.create(paywall, context, campaign) as PaywallStateWithPageHistory;
|
|
102
|
+
if (flow) provider.setFlow(flow);
|
|
103
|
+
providerRef.current = provider;
|
|
104
|
+
pageHistoryRef.current = [provider.state.currentPage ?? paywall.template?.initialState?.currentPage ?? 'page1'];
|
|
105
|
+
return cloneStateWithDynamicProps(provider.state, provider);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
const provider = providerRef.current;
|
|
110
|
+
if (!provider) return;
|
|
111
|
+
const unsubscribe = provider.subscribe(() => {
|
|
112
|
+
setState(cloneStateWithDynamicProps(provider.state, provider));
|
|
113
|
+
});
|
|
114
|
+
return () => {
|
|
115
|
+
unsubscribe();
|
|
116
|
+
PaywallState.remove(provider);
|
|
117
|
+
};
|
|
118
|
+
}, []);
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const provider = providerRef.current;
|
|
122
|
+
if (!provider) return;
|
|
123
|
+
setFirstFocusReadyKey(null);
|
|
124
|
+
provider.setPaywall(paywall, context, campaign);
|
|
125
|
+
if (flow) provider.setFlow(flow);
|
|
126
|
+
pageHistoryRef.current = [provider.state.currentPage ?? paywall.template?.initialState?.currentPage ?? 'page1'];
|
|
127
|
+
setState(cloneStateWithDynamicProps(provider.state, provider));
|
|
128
|
+
}, [paywall, context, campaign, flow]);
|
|
129
|
+
|
|
130
|
+
const methods = useMemo(() => ({
|
|
131
|
+
setPaywall: (nextPaywall: IPaywall, nextContext: NamiPaywallLaunchContext, nextCampaign: NamiCampaign) => {
|
|
132
|
+
providerRef.current?.setPaywall(nextPaywall, nextContext, nextCampaign);
|
|
133
|
+
const provider = providerRef.current;
|
|
134
|
+
pageHistoryRef.current = [provider?.state.currentPage ?? nextPaywall.template?.initialState?.currentPage ?? 'page1'];
|
|
135
|
+
},
|
|
136
|
+
setCurrentPage: (page: string) => {
|
|
137
|
+
const provider = providerRef.current;
|
|
138
|
+
const currentPage = provider?.state.currentPage ?? pageHistoryRef.current[pageHistoryRef.current.length - 1] ?? 'page1';
|
|
139
|
+
if (!page || page === currentPage) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const currentHistory = pageHistoryRef.current.length ? pageHistoryRef.current : [currentPage];
|
|
143
|
+
pageHistoryRef.current = [...currentHistory, page];
|
|
144
|
+
provider?.setCurrentPage(page);
|
|
145
|
+
},
|
|
146
|
+
canGoBackPage: () => {
|
|
147
|
+
if (pageHistoryRef.current.length > 1) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return asMethod<[], boolean>(providerRef.current?.canGoBackPage)?.call(providerRef.current) ?? false;
|
|
151
|
+
},
|
|
152
|
+
goBackPage: () => {
|
|
153
|
+
const provider = providerRef.current;
|
|
154
|
+
if (pageHistoryRef.current.length > 1) {
|
|
155
|
+
const nextHistory = [...pageHistoryRef.current];
|
|
156
|
+
nextHistory.pop();
|
|
157
|
+
const previousPage = nextHistory[nextHistory.length - 1];
|
|
158
|
+
if (!previousPage) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
pageHistoryRef.current = nextHistory;
|
|
163
|
+
const providerHandled =
|
|
164
|
+
asMethod<[], boolean>(provider?.goBackPage)?.call(provider) ?? false;
|
|
165
|
+
if (!providerHandled) {
|
|
166
|
+
provider?.setCurrentPage(previousPage);
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
return asMethod<[], boolean>(provider?.goBackPage)?.call(provider) ?? false;
|
|
171
|
+
},
|
|
172
|
+
setCurrentGroupData: (groupId: string, groupName: string) => {
|
|
173
|
+
providerRef.current?.setCurrentGroupData(groupId, groupName);
|
|
174
|
+
},
|
|
175
|
+
setSelectedProducts: (products: Record<string, string | null>) => {
|
|
176
|
+
providerRef.current?.setSelectedProducts(products);
|
|
177
|
+
},
|
|
178
|
+
setCurrentFormId: (formId: string, value?: string) => {
|
|
179
|
+
providerRef.current?.setCurrentFormId(formId, value);
|
|
180
|
+
},
|
|
181
|
+
setFormState: (formId: string, value: boolean | string) => {
|
|
182
|
+
providerRef.current?.setFormState(formId, value);
|
|
183
|
+
},
|
|
184
|
+
setTimerState: (timerId: string, remainingSeconds: number, savedAt: number, hasEmittedCompletion: boolean) => {
|
|
185
|
+
providerRef.current?.setTimerState(timerId, remainingSeconds, savedAt, hasEmittedCompletion);
|
|
186
|
+
},
|
|
187
|
+
getTimerState: (timerId: string) => {
|
|
188
|
+
return providerRef.current?.getTimerState(timerId);
|
|
189
|
+
},
|
|
190
|
+
setProductDetails: (details: NamiProductDetails[]) => {
|
|
191
|
+
providerRef.current?.setProductDetails(details);
|
|
192
|
+
},
|
|
193
|
+
setPurchaseInProgress: (inProgress: boolean) => {
|
|
194
|
+
providerRef.current?.setPurchaseInProgress(inProgress);
|
|
195
|
+
},
|
|
196
|
+
setPurchase: (inProgress: boolean, product?: NamiSKU) => {
|
|
197
|
+
providerRef.current?.setPurchase(inProgress, product);
|
|
198
|
+
},
|
|
199
|
+
setCustomerAttribute: (attributes: Record<string, string>) => {
|
|
200
|
+
providerRef.current?.setCustomerAttribute(attributes);
|
|
201
|
+
},
|
|
202
|
+
removeCustomerAttribute: (key: string) => {
|
|
203
|
+
providerRef.current?.removeCustomerAttribute(key);
|
|
204
|
+
},
|
|
205
|
+
setIsLoggedIn: (isLoggedIn: boolean) => {
|
|
206
|
+
providerRef.current?.setIsLoggedIn(isLoggedIn);
|
|
207
|
+
},
|
|
208
|
+
setAppSuppliedVideoDetails: (details: NamiAppSuppliedVideoDetails) => {
|
|
209
|
+
providerRef.current?.setAppSuppliedVideoDetails(details);
|
|
210
|
+
},
|
|
211
|
+
resetAppSuppliedVideoDetails: () => {
|
|
212
|
+
providerRef.current?.resetAppSuppliedVideoDetails();
|
|
213
|
+
},
|
|
214
|
+
setMediaList: (media: TPaywallMedia[]) => {
|
|
215
|
+
providerRef.current?.setMediaList(media);
|
|
216
|
+
},
|
|
217
|
+
setSafeAreaTop: (top: number) => {
|
|
218
|
+
providerRef.current?.setSafeAreaTop(top);
|
|
219
|
+
},
|
|
220
|
+
setFullScreenPresentation: (full: boolean) => {
|
|
221
|
+
providerRef.current?.setFullScreenPresentation(full);
|
|
222
|
+
},
|
|
223
|
+
setFormFactor: (factor: TDevice) => {
|
|
224
|
+
providerRef.current?.setFormFactor(factor);
|
|
225
|
+
},
|
|
226
|
+
setUserInteractionEnabled: (enabled: boolean) => {
|
|
227
|
+
providerRef.current?.setUserInteractionEnabled(enabled);
|
|
228
|
+
},
|
|
229
|
+
setUserTags: (tags: Record<string, string>) => {
|
|
230
|
+
providerRef.current?.setUserTags(tags);
|
|
231
|
+
},
|
|
232
|
+
setLaunchDetails: (value: string, type?: string) => {
|
|
233
|
+
providerRef.current?.setLaunchDetails(value, type);
|
|
234
|
+
},
|
|
235
|
+
setOpenHeaderIds: (id: string, sku?: NamiSKU) => {
|
|
236
|
+
providerRef.current?.setOpenHeaderIds(id, sku);
|
|
237
|
+
},
|
|
238
|
+
setFlow: (nextFlow: NamiFlow) => {
|
|
239
|
+
providerRef.current?.setFlow(nextFlow);
|
|
240
|
+
},
|
|
241
|
+
notifyFirstFocusReady: (paywallId: string, page: string, formFactor?: string) => {
|
|
242
|
+
setFirstFocusReadyKey(`${paywallId}:${page}:${formFactor ?? ''}`);
|
|
243
|
+
onFirstFocusReady?.(paywallId, page, formFactor);
|
|
244
|
+
},
|
|
245
|
+
setCurrentSlideIndex: (index: number) => {
|
|
246
|
+
providerRef.current?.setCurrentSlideIndex(index);
|
|
247
|
+
},
|
|
248
|
+
getPaywallActionEventData: () => {
|
|
249
|
+
return providerRef.current?.getPaywallActionEventData() ?? {};
|
|
250
|
+
},
|
|
251
|
+
getSelectedPaywall: () => {
|
|
252
|
+
return providerRef.current?.getSelectedPaywall();
|
|
253
|
+
},
|
|
254
|
+
getSelectedCampaign: () => {
|
|
255
|
+
return providerRef.current?.getSelectedCampaign();
|
|
256
|
+
},
|
|
257
|
+
}), [onFirstFocusReady]);
|
|
258
|
+
|
|
259
|
+
const focusReadyValue = useMemo(
|
|
260
|
+
() => ({
|
|
261
|
+
firstFocusReadyKey,
|
|
262
|
+
notifyFirstFocusReady: methods.notifyFirstFocusReady,
|
|
263
|
+
}),
|
|
264
|
+
[firstFocusReadyKey, methods],
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const value = useMemo<PaywallContextValue>(() => {
|
|
268
|
+
const provider = providerRef.current;
|
|
269
|
+
return {
|
|
270
|
+
state,
|
|
271
|
+
productDetails: provider?.getProductDetails() ?? provider?.productDetails ?? [],
|
|
272
|
+
flow: provider?.flow,
|
|
273
|
+
filteredSkuMenus: provider?.filteredSkuMenus ?? [],
|
|
274
|
+
...methods,
|
|
275
|
+
};
|
|
276
|
+
}, [methods, state]);
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<PaywallCtx.Provider value={value}>
|
|
280
|
+
<FirstFocusReadyCtx.Provider value={focusReadyValue}>
|
|
281
|
+
{children}
|
|
282
|
+
</FirstFocusReadyCtx.Provider>
|
|
283
|
+
</PaywallCtx.Provider>
|
|
284
|
+
);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
export default PaywallCtx;
|
|
288
|
+
|
|
289
|
+
function cloneStateWithDynamicProps(
|
|
290
|
+
state: TPaywallContext | undefined,
|
|
291
|
+
provider: PaywallState,
|
|
292
|
+
): TPaywallContext {
|
|
293
|
+
const nextState = { ...(state ?? initialState) } as TPaywallContext;
|
|
294
|
+
defineDynamicStateProps(nextState, provider);
|
|
295
|
+
return nextState;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function defineDynamicStateProps(state: TPaywallContext, provider: PaywallState): void {
|
|
299
|
+
Object.defineProperty(state, 'tvQuality', {
|
|
300
|
+
get: () => getTVQuality(provider),
|
|
301
|
+
enumerable: false,
|
|
302
|
+
configurable: true,
|
|
303
|
+
});
|
|
304
|
+
Object.defineProperty(state, 'viewportWidth', {
|
|
305
|
+
get: getViewportWidth,
|
|
306
|
+
enumerable: false,
|
|
307
|
+
configurable: true,
|
|
308
|
+
});
|
|
309
|
+
Object.defineProperty(state, 'viewportHeight', {
|
|
310
|
+
get: getViewportHeight,
|
|
311
|
+
enumerable: false,
|
|
312
|
+
configurable: true,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function getTVQuality(provider: PaywallState): string {
|
|
317
|
+
if (provider.getFormFactor() !== 'television') {
|
|
318
|
+
return '';
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const { width, height, scale } = Dimensions.get('window');
|
|
322
|
+
const maxDimension = Math.max(width, height) * (scale || 1);
|
|
323
|
+
const minDimension = Math.min(width, height) * (scale || 1);
|
|
324
|
+
|
|
325
|
+
if (!maxDimension || !minDimension) {
|
|
326
|
+
return '720p';
|
|
327
|
+
}
|
|
328
|
+
if (maxDimension >= 3840 || minDimension >= 2160) {
|
|
329
|
+
return '4K';
|
|
330
|
+
}
|
|
331
|
+
if (maxDimension >= 1920 || minDimension >= 1080) {
|
|
332
|
+
return '1080p';
|
|
333
|
+
}
|
|
334
|
+
return '720p';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function getViewportWidth(): number {
|
|
338
|
+
return Dimensions.get('window').width;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function getViewportHeight(): number {
|
|
342
|
+
return Dimensions.get('window').height;
|
|
343
|
+
}
|
package/src/global.d.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const runtimeGlobals = globalThis as Record<string, unknown>;
|
|
2
|
+
const sdkEnvKey = 'NAMI_SDK' + '_ENV';
|
|
3
|
+
|
|
4
|
+
if (typeof runtimeGlobals[sdkEnvKey] !== 'string' || runtimeGlobals[sdkEnvKey] === '') {
|
|
5
|
+
const devFlag = typeof __DEV__ === 'boolean' ? __DEV__ : false;
|
|
6
|
+
runtimeGlobals[sdkEnvKey] = devFlag ? 'development' : 'production';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// ─── Side-effect: register adapters ──────────────────────────────────
|
|
10
|
+
import './adapters';
|
|
11
|
+
|
|
12
|
+
// ─── Nami wrapper ────────────────────────────────────────────────────
|
|
13
|
+
export { Nami } from './nami';
|
|
14
|
+
|
|
15
|
+
// ─── Primary component ──────────────────────────────────────────────
|
|
16
|
+
export { NamiView } from './components/NamiView';
|
|
17
|
+
|
|
18
|
+
// ─── Managers (re-exported from core) ────────────────────────────────
|
|
19
|
+
export {
|
|
20
|
+
NamiCampaignManager,
|
|
21
|
+
NamiCustomerManager,
|
|
22
|
+
NamiPaywallManager,
|
|
23
|
+
NamiEntitlementManager,
|
|
24
|
+
NamiFlowManager,
|
|
25
|
+
NamiProfileManager,
|
|
26
|
+
} from '@namiml/sdk-core';
|
|
27
|
+
|
|
28
|
+
// ─── Types (re-exported from core) ──────────────────────────────────
|
|
29
|
+
export type {
|
|
30
|
+
NamiConfiguration,
|
|
31
|
+
NamiCampaign,
|
|
32
|
+
NamiSKU,
|
|
33
|
+
NamiSKUType,
|
|
34
|
+
NamiEntitlement,
|
|
35
|
+
NamiPurchase,
|
|
36
|
+
NamiPaywallEvent,
|
|
37
|
+
NamiPaywallAction,
|
|
38
|
+
NamiPaywallLaunchContext,
|
|
39
|
+
NamiLogLevel,
|
|
40
|
+
NamiLanguageCodes,
|
|
41
|
+
CustomerJourneyState,
|
|
42
|
+
NamiProductDetails,
|
|
43
|
+
NamiFlow,
|
|
44
|
+
IPurchaseAdapter,
|
|
45
|
+
PurchaseContext,
|
|
46
|
+
PurchaseResult,
|
|
47
|
+
} from '@namiml/sdk-core';
|
|
48
|
+
|
|
49
|
+
// ─── Adapters (advanced use) ────────────────────────────────────────
|
|
50
|
+
export {
|
|
51
|
+
ExpoStorageAdapter,
|
|
52
|
+
ExpoDeviceAdapter,
|
|
53
|
+
ExpoUIAdapter,
|
|
54
|
+
ExpoPurchaseAdapter,
|
|
55
|
+
} from './adapters';
|
|
56
|
+
|
|
57
|
+
// ─── Context (advanced use) ─────────────────────────────────────────
|
|
58
|
+
export { PaywallProvider, usePaywallContext } from './context/PaywallContext';
|
|
59
|
+
|
|
60
|
+
// ─── Internal components (for customization) ────────────────────────
|
|
61
|
+
export { PaywallScreen } from './components/PaywallScreen';
|
|
62
|
+
export { TemplateRenderer } from './components/TemplateRenderer';
|
package/src/nami.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import './adapters';
|
|
2
|
+
import { Nami as CoreNami } from '@namiml/sdk-core';
|
|
3
|
+
|
|
4
|
+
type ResettableCoreNami = typeof CoreNami & {
|
|
5
|
+
reset?: () => Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export class Nami {
|
|
9
|
+
static get sdkVersion(): string {
|
|
10
|
+
return CoreNami.sdkVersion();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static sdkPackageVersion(): string {
|
|
14
|
+
return CoreNami.sdkPackageVersion();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static async configure(config: Parameters<typeof CoreNami.configure>[0]) {
|
|
18
|
+
return CoreNami.configure(config);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static async reset(): Promise<void> {
|
|
22
|
+
await (CoreNami as ResettableCoreNami).reset?.();
|
|
23
|
+
}
|
|
24
|
+
}
|