@revenuecat/purchases-ui-js 4.11.1 → 4.12.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/dist/components/paywall/Paywall.svelte +32 -7
- package/dist/components/paywall/Paywall.svelte.d.ts +4 -0
- package/dist/components/purchase-button/PurchaseButton.svelte +29 -19
- package/dist/components/purchase-button/custom-web-checkout-url.d.ts +18 -0
- package/dist/components/purchase-button/custom-web-checkout-url.js +33 -0
- package/dist/components/workflows/Screen.svelte +12 -0
- package/dist/components/workflows/Screen.svelte.d.ts +4 -0
- package/dist/components/workflows/Workflow.svelte +12 -0
- package/dist/components/workflows/Workflow.svelte.d.ts +4 -0
- package/dist/stores/paywall.d.ts +6 -0
- package/dist/types/components/purchase-button.d.ts +3 -1
- package/package.json +1 -1
|
@@ -117,6 +117,10 @@
|
|
|
117
117
|
walletButtonRender?: WalletButtonRender;
|
|
118
118
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
119
119
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
120
|
+
appUserId?: string;
|
|
121
|
+
isSandbox?: boolean;
|
|
122
|
+
rcSource?: string;
|
|
123
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
120
124
|
onInputChanged?: (
|
|
121
125
|
fieldId: string,
|
|
122
126
|
value: string,
|
|
@@ -181,6 +185,10 @@
|
|
|
181
185
|
walletButtonRender,
|
|
182
186
|
prepareWalletPurchase,
|
|
183
187
|
onWalletPurchaseClicked,
|
|
188
|
+
appUserId,
|
|
189
|
+
isSandbox,
|
|
190
|
+
rcSource,
|
|
191
|
+
onCustomWebCheckout,
|
|
184
192
|
onInputChanged,
|
|
185
193
|
onSensitiveInputChanged,
|
|
186
194
|
onReservedAttributeChanged,
|
|
@@ -398,6 +406,10 @@
|
|
|
398
406
|
walletButtonRender,
|
|
399
407
|
prepareWalletPurchase,
|
|
400
408
|
onWalletPurchaseClicked,
|
|
409
|
+
appUserId,
|
|
410
|
+
isSandbox,
|
|
411
|
+
rcSource,
|
|
412
|
+
onCustomWebCheckout,
|
|
401
413
|
uiConfig,
|
|
402
414
|
hideBackButtons,
|
|
403
415
|
});
|
|
@@ -468,18 +480,26 @@
|
|
|
468
480
|
<Stack
|
|
469
481
|
{...stack}
|
|
470
482
|
class="paywall-content-scroll"
|
|
471
|
-
padding={sticky_footer
|
|
472
|
-
? {
|
|
473
|
-
...stack.padding,
|
|
474
|
-
bottom: (stack.padding?.bottom ?? 0) + footerHeight,
|
|
475
|
-
}
|
|
476
|
-
: stack.padding}
|
|
477
483
|
style={mapPaywallContentStackStyle(
|
|
478
484
|
stack.size.height,
|
|
479
485
|
pullContentUnderHeader,
|
|
480
486
|
headerHeight,
|
|
481
487
|
)}
|
|
482
|
-
|
|
488
|
+
>
|
|
489
|
+
{#if sticky_footer}
|
|
490
|
+
<!-- Adds a real flex item rather than bottom padding to clear
|
|
491
|
+
a footer because iOS Safari ignores the padding if the content
|
|
492
|
+
still fits on screen leaving content stuck behind the footer. -->
|
|
493
|
+
<div
|
|
494
|
+
class="footer-scroll-spacer"
|
|
495
|
+
aria-hidden="true"
|
|
496
|
+
style="height: {Math.max(
|
|
497
|
+
0,
|
|
498
|
+
footerHeight - (stack.spacing ?? 0),
|
|
499
|
+
)}px;"
|
|
500
|
+
></div>
|
|
501
|
+
{/if}
|
|
502
|
+
</Stack>
|
|
483
503
|
</div>
|
|
484
504
|
{#if sticky_footer}
|
|
485
505
|
<!-- Overlaps the content so translucent footers show it; sticky rather than
|
|
@@ -536,6 +556,11 @@
|
|
|
536
556
|
flex-shrink: 0;
|
|
537
557
|
}
|
|
538
558
|
|
|
559
|
+
.footer-scroll-spacer {
|
|
560
|
+
width: 100%;
|
|
561
|
+
flex-shrink: 0;
|
|
562
|
+
}
|
|
563
|
+
|
|
539
564
|
.paywall-content {
|
|
540
565
|
z-index: 2;
|
|
541
566
|
width: 100%;
|
|
@@ -47,6 +47,10 @@ interface Props {
|
|
|
47
47
|
walletButtonRender?: WalletButtonRender;
|
|
48
48
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
49
49
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
50
|
+
appUserId?: string;
|
|
51
|
+
isSandbox?: boolean;
|
|
52
|
+
rcSource?: string;
|
|
53
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
50
54
|
onInputChanged?: (fieldId: string, value: string, actionId?: string) => void;
|
|
51
55
|
/**
|
|
52
56
|
* Called for sensitive inputs (keyboard_type: "password") instead of
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { PurchaseButtonProps } from "../../types/components/purchase-button";
|
|
7
7
|
import type { PurchaseButtonInteractionData } from "../../types/paywall-component-interaction";
|
|
8
8
|
import { get } from "svelte/store";
|
|
9
|
+
import { buildCustomWebCheckoutURL } from "./custom-web-checkout-url";
|
|
9
10
|
|
|
10
11
|
const props: PurchaseButtonProps = $props();
|
|
11
12
|
const { stack } = props;
|
|
@@ -13,41 +14,42 @@
|
|
|
13
14
|
const {
|
|
14
15
|
emitComponentInteraction,
|
|
15
16
|
onPurchase,
|
|
17
|
+
onCustomWebCheckout,
|
|
16
18
|
selectedPackageId,
|
|
17
19
|
infoPerPackage,
|
|
20
|
+
appUserId,
|
|
21
|
+
isSandbox,
|
|
22
|
+
rcSource,
|
|
18
23
|
} = getPaywallContext();
|
|
19
24
|
const { getLocalizedString } = getLocalizationContext();
|
|
20
25
|
|
|
21
26
|
// Set when embedded in a package; standalone buttons fall back to the store.
|
|
22
27
|
const enclosingPackageId = getOptionalPackageIdContext();
|
|
23
28
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const getCustomWebCheckoutURL = (packageId: string) => {
|
|
30
|
+
if (props.method?.type !== "custom_web_checkout") {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const url = getLocalizedString(props.method.custom_url.url_lid);
|
|
34
|
+
return url
|
|
35
|
+
? buildCustomWebCheckoutURL(url, props.method.custom_url, {
|
|
36
|
+
packageId,
|
|
37
|
+
appUserId,
|
|
38
|
+
isSandbox,
|
|
39
|
+
rcSource,
|
|
40
|
+
})
|
|
41
|
+
: undefined;
|
|
31
42
|
};
|
|
32
43
|
|
|
33
44
|
const getPurchaseButtonInteractionData = (
|
|
34
45
|
packageId: string,
|
|
46
|
+
customWebCheckoutURL: string | undefined,
|
|
35
47
|
): PurchaseButtonInteractionData => {
|
|
36
|
-
let componentURL
|
|
48
|
+
let componentURL = customWebCheckoutURL;
|
|
37
49
|
const resolvedMethodType =
|
|
38
50
|
props.method?.type === "unknown" ? undefined : props.method?.type;
|
|
39
51
|
const webCheckoutURL = $infoPerPackage?.[packageId]?.webCheckoutURL;
|
|
40
52
|
|
|
41
|
-
if (props.method?.type === "custom_web_checkout") {
|
|
42
|
-
const url = getLocalizedString(props.method.custom_url.url_lid);
|
|
43
|
-
if (url) {
|
|
44
|
-
const packageParam = props.method.custom_url.package_param;
|
|
45
|
-
componentURL = packageParam
|
|
46
|
-
? appendQueryParam(url, packageParam, packageId)
|
|
47
|
-
: url;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
53
|
if (componentURL === undefined) {
|
|
52
54
|
const interactionValue = resolvedMethodType ?? props.action;
|
|
53
55
|
if (
|
|
@@ -75,7 +77,15 @@
|
|
|
75
77
|
if (packageId !== undefined) {
|
|
76
78
|
// Sync before purchasing so onPurchase reads this package, not a stale one.
|
|
77
79
|
$selectedPackageId = packageId;
|
|
78
|
-
|
|
80
|
+
const customWebCheckoutURL = getCustomWebCheckoutURL(packageId);
|
|
81
|
+
emitComponentInteraction(
|
|
82
|
+
getPurchaseButtonInteractionData(packageId, customWebCheckoutURL),
|
|
83
|
+
);
|
|
84
|
+
// Hosts without the callback keep the purchase flow.
|
|
85
|
+
if (customWebCheckoutURL !== undefined && onCustomWebCheckout) {
|
|
86
|
+
onCustomWebCheckout(customWebCheckoutURL);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
onPurchase(props.triggers?.on_purchase_press);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PurchaseButtonMethod } from "../../types/components/purchase-button";
|
|
2
|
+
type CustomURLConfig = Extract<PurchaseButtonMethod, {
|
|
3
|
+
type: "custom_web_checkout";
|
|
4
|
+
}>["custom_url"];
|
|
5
|
+
type CustomWebCheckoutContext = {
|
|
6
|
+
packageId: string;
|
|
7
|
+
appUserId?: string;
|
|
8
|
+
isSandbox?: boolean;
|
|
9
|
+
rcSource?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Mirrors the native SDKs: source, then app user ID, env and package when
|
|
13
|
+
* configured. The source is the host's own, so it survives a same-tab hop.
|
|
14
|
+
* Same-named params are replaced; an unparseable URL is returned unchanged.
|
|
15
|
+
* Script-capable URLs resolve to undefined, so the button purchases instead.
|
|
16
|
+
*/
|
|
17
|
+
export declare const buildCustomWebCheckoutURL: (url: string, config: CustomURLConfig, { packageId, appUserId, isSandbox, rcSource }: CustomWebCheckoutContext) => string | undefined;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const SCRIPT_PROTOCOLS = new Set(["javascript:", "data:", "vbscript:"]);
|
|
2
|
+
/**
|
|
3
|
+
* Mirrors the native SDKs: source, then app user ID, env and package when
|
|
4
|
+
* configured. The source is the host's own, so it survives a same-tab hop.
|
|
5
|
+
* Same-named params are replaced; an unparseable URL is returned unchanged.
|
|
6
|
+
* Script-capable URLs resolve to undefined, so the button purchases instead.
|
|
7
|
+
*/
|
|
8
|
+
export const buildCustomWebCheckoutURL = (url, config, { packageId, appUserId, isSandbox, rcSource }) => {
|
|
9
|
+
let parsed;
|
|
10
|
+
try {
|
|
11
|
+
parsed = new URL(url);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return url;
|
|
15
|
+
}
|
|
16
|
+
if (SCRIPT_PROTOCOLS.has(parsed.protocol)) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const { searchParams } = parsed;
|
|
20
|
+
if (rcSource !== undefined) {
|
|
21
|
+
searchParams.set("rc_source", rcSource);
|
|
22
|
+
}
|
|
23
|
+
if (config.app_user_id_param && appUserId !== undefined) {
|
|
24
|
+
searchParams.set(config.app_user_id_param, appUserId);
|
|
25
|
+
}
|
|
26
|
+
if (config.env_param && isSandbox !== undefined) {
|
|
27
|
+
searchParams.set(config.env_param, isSandbox ? "sandbox" : "production");
|
|
28
|
+
}
|
|
29
|
+
if (config.package_param) {
|
|
30
|
+
searchParams.set(config.package_param, packageId);
|
|
31
|
+
}
|
|
32
|
+
return parsed.toString();
|
|
33
|
+
};
|
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
walletButtonRender?: WalletButtonRender;
|
|
65
65
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
66
66
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
67
|
+
appUserId?: string;
|
|
68
|
+
isSandbox?: boolean;
|
|
69
|
+
rcSource?: string;
|
|
70
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
67
71
|
safeAreaFallbackColor?: ColorScheme | null;
|
|
68
72
|
hideBackButtons?: boolean;
|
|
69
73
|
offering?: PaywallOffering | null;
|
|
@@ -98,6 +102,10 @@
|
|
|
98
102
|
walletButtonRender,
|
|
99
103
|
prepareWalletPurchase,
|
|
100
104
|
onWalletPurchaseClicked,
|
|
105
|
+
appUserId,
|
|
106
|
+
isSandbox,
|
|
107
|
+
rcSource,
|
|
108
|
+
onCustomWebCheckout,
|
|
101
109
|
safeAreaFallbackColor,
|
|
102
110
|
hideBackButtons,
|
|
103
111
|
offering,
|
|
@@ -147,6 +155,10 @@
|
|
|
147
155
|
{walletButtonRender}
|
|
148
156
|
{prepareWalletPurchase}
|
|
149
157
|
{onWalletPurchaseClicked}
|
|
158
|
+
{appUserId}
|
|
159
|
+
{isSandbox}
|
|
160
|
+
{rcSource}
|
|
161
|
+
{onCustomWebCheckout}
|
|
150
162
|
{safeAreaFallbackColor}
|
|
151
163
|
{hideBackButtons}
|
|
152
164
|
{offering}
|
|
@@ -38,6 +38,10 @@ interface Props {
|
|
|
38
38
|
walletButtonRender?: WalletButtonRender;
|
|
39
39
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
40
40
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
41
|
+
appUserId?: string;
|
|
42
|
+
isSandbox?: boolean;
|
|
43
|
+
rcSource?: string;
|
|
44
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
41
45
|
safeAreaFallbackColor?: ColorScheme | null;
|
|
42
46
|
hideBackButtons?: boolean;
|
|
43
47
|
offering?: PaywallOffering | null;
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
walletButtonRender?: WalletButtonRender;
|
|
58
58
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
59
59
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
60
|
+
appUserId?: string;
|
|
61
|
+
isSandbox?: boolean;
|
|
62
|
+
rcSource?: string;
|
|
63
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
60
64
|
safeAreaFallbackColor?: ColorScheme | null;
|
|
61
65
|
hideBackButtons?: boolean;
|
|
62
66
|
onPurchaseClicked?: (
|
|
@@ -113,6 +117,10 @@
|
|
|
113
117
|
walletButtonRender,
|
|
114
118
|
prepareWalletPurchase,
|
|
115
119
|
onWalletPurchaseClicked,
|
|
120
|
+
appUserId,
|
|
121
|
+
isSandbox,
|
|
122
|
+
rcSource,
|
|
123
|
+
onCustomWebCheckout,
|
|
116
124
|
safeAreaFallbackColor,
|
|
117
125
|
hideBackButtons,
|
|
118
126
|
onPurchaseClicked,
|
|
@@ -378,6 +386,10 @@
|
|
|
378
386
|
{walletButtonRender}
|
|
379
387
|
{prepareWalletPurchase}
|
|
380
388
|
{onWalletPurchaseClicked}
|
|
389
|
+
{appUserId}
|
|
390
|
+
{isSandbox}
|
|
391
|
+
{rcSource}
|
|
392
|
+
{onCustomWebCheckout}
|
|
381
393
|
{safeAreaFallbackColor}
|
|
382
394
|
{hideBackButtons}
|
|
383
395
|
{onPurchaseClicked}
|
|
@@ -23,6 +23,10 @@ interface Props {
|
|
|
23
23
|
walletButtonRender?: WalletButtonRender;
|
|
24
24
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
25
25
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
26
|
+
appUserId?: string;
|
|
27
|
+
isSandbox?: boolean;
|
|
28
|
+
rcSource?: string;
|
|
29
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
26
30
|
safeAreaFallbackColor?: ColorScheme | null;
|
|
27
31
|
hideBackButtons?: boolean;
|
|
28
32
|
onPurchaseClicked?: (packageId: string, actionId: string) => void | Promise<void>;
|
package/dist/stores/paywall.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ type PaywallContext = Readonly<{
|
|
|
32
32
|
typedCustom?: BridgeCustomValues;
|
|
33
33
|
bridgeInputs?: Writable<BridgeInputs>;
|
|
34
34
|
onPurchase: (actionId?: string) => void;
|
|
35
|
+
/** Opens a custom checkout URL in place of purchasing. */
|
|
36
|
+
onCustomWebCheckout?: (url: string) => void;
|
|
35
37
|
emitComponentInteraction: (data: ComponentInteractionData) => void;
|
|
36
38
|
onNavigateToUrl?: (url: string) => void;
|
|
37
39
|
onInputChanged?: (fieldId: string, value: string, actionId?: string) => void;
|
|
@@ -47,6 +49,10 @@ type PaywallContext = Readonly<{
|
|
|
47
49
|
prepareWalletPurchase?: WalletPurchasePrepare;
|
|
48
50
|
onWalletPurchaseClicked?: WalletPurchaseStart;
|
|
49
51
|
onButtonAction: (action: Action, actionId?: string) => void;
|
|
52
|
+
/** Forwarded on custom checkout URLs. */
|
|
53
|
+
appUserId?: string;
|
|
54
|
+
isSandbox?: boolean;
|
|
55
|
+
rcSource?: string;
|
|
50
56
|
uiConfig: UIConfig;
|
|
51
57
|
hideBackButtons: boolean;
|
|
52
58
|
}>;
|
|
@@ -16,7 +16,9 @@ export type PurchaseButtonMethod = {
|
|
|
16
16
|
type: "custom_web_checkout";
|
|
17
17
|
custom_url: {
|
|
18
18
|
url_lid: string;
|
|
19
|
-
package_param?: string;
|
|
19
|
+
package_param?: string | null;
|
|
20
|
+
app_user_id_param?: string | null;
|
|
21
|
+
env_param?: string | null;
|
|
20
22
|
};
|
|
21
23
|
} & PurchaseButtonWebMethod) | {
|
|
22
24
|
type: "unknown";
|