@revenuecat/purchases-ui-js 3.9.2 → 3.9.3

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.
@@ -23,8 +23,11 @@
23
23
  // Reactive store for input satisfaction (defaults to true if no validation context)
24
24
  const inputSatisfied = validationContext?.isSatisfied ?? readable(true);
25
25
 
26
- // Button is disabled when it's a workflow (continue) action and inputs aren't satisfied
27
- const isDisabled = $derived(action.type === "workflow" && !$inputSatisfied);
26
+ // Button is disabled when it's a workflow (continue) or complete_workflow action and inputs aren't satisfied
27
+ const isDisabled = $derived(
28
+ (action.type === "workflow" || action.type === "complete_workflow") &&
29
+ !$inputSatisfied,
30
+ );
28
31
 
29
32
  const onclick = () => {
30
33
  if (isDisabled) return;
@@ -36,6 +39,8 @@
36
39
  switch (action.type) {
37
40
  case "workflow":
38
41
  return true;
42
+ case "complete_workflow":
43
+ return true;
39
44
  case "restore_purchases":
40
45
  return false;
41
46
  case "navigate_back":
@@ -14,7 +14,10 @@
14
14
  type VariablesStore,
15
15
  } from "../../stores/variables";
16
16
  import type { ColorMode } from "../../types";
17
- import type { Action } from "../../types/components/button";
17
+ import type {
18
+ Action,
19
+ CompleteWorkflowNavigateArgs,
20
+ } from "../../types/components/button";
18
21
  import type { SheetProps } from "../../types/components/sheet";
19
22
  import type { PaywallData } from "../../types/paywall";
20
23
  import type { UIConfig } from "../../types/ui-config";
@@ -61,6 +64,13 @@
61
64
  onVisitCustomerCenterClicked?: () => void;
62
65
  onRestorePurchasesClicked?: () => void;
63
66
  onNavigateToUrlClicked?: (url: string) => void;
67
+ /**
68
+ * Called when a complete_workflow button is pressed. The URL is localized;
69
+ * the host merges `url_query_params` (e.g. `app_user_id`) if needed.
70
+ */
71
+ onCompleteWorkflowNavigate?: (
72
+ args: CompleteWorkflowNavigateArgs,
73
+ ) => void | Promise<void>;
64
74
  onActionTriggered?: (actionId: string) => void;
65
75
  onError?: (error: unknown) => void;
66
76
  hideBackButtons?: boolean;
@@ -96,6 +106,7 @@
96
106
  onVisitCustomerCenterClicked,
97
107
  onRestorePurchasesClicked,
98
108
  onNavigateToUrlClicked,
109
+ onCompleteWorkflowNavigate,
99
110
  onActionTriggered,
100
111
  onError,
101
112
  uiConfig,
@@ -140,6 +151,18 @@
140
151
  onActionTriggered?.(actionId);
141
152
  }
142
153
  return;
154
+ case "complete_workflow": {
155
+ const baseUrl = getLocalizedString(action.url.url_lid);
156
+ if (!baseUrl) {
157
+ return;
158
+ }
159
+ void onCompleteWorkflowNavigate?.({
160
+ url: baseUrl,
161
+ method: action.url.method,
162
+ url_query_params: action.url_query_params,
163
+ });
164
+ return;
165
+ }
143
166
  case "navigate_back":
144
167
  onBackClicked?.();
145
168
  return;
@@ -1,5 +1,6 @@
1
1
  import { type InitialInputSelections } from "../../stores/inputValidation";
2
2
  import type { ColorMode } from "../../types";
3
+ import type { CompleteWorkflowNavigateArgs } from "../../types/components/button";
3
4
  import type { PaywallData } from "../../types/paywall";
4
5
  import type { UIConfig } from "../../types/ui-config";
5
6
  import { type CustomVariables, type PackageInfo, type VariableDictionary } from "../../types/variables";
@@ -27,6 +28,11 @@ interface Props {
27
28
  onVisitCustomerCenterClicked?: () => void;
28
29
  onRestorePurchasesClicked?: () => void;
29
30
  onNavigateToUrlClicked?: (url: string) => void;
31
+ /**
32
+ * Called when a complete_workflow button is pressed. The URL is localized;
33
+ * the host merges `url_query_params` (e.g. `app_user_id`) if needed.
34
+ */
35
+ onCompleteWorkflowNavigate?: (args: CompleteWorkflowNavigateArgs) => void | Promise<void>;
30
36
  onActionTriggered?: (actionId: string) => void;
31
37
  onError?: (error: unknown) => void;
32
38
  hideBackButtons?: boolean;
@@ -14,6 +14,7 @@
14
14
  import {
15
15
  getActiveStateProps,
16
16
  getIntroOfferStateProps,
17
+ getPromoOfferStateProps,
17
18
  evaluateVisibilityConditions,
18
19
  } from "../../utils/style-utils";
19
20
  import { replaceVariables } from "../../utils/variable-utils";
@@ -32,6 +33,10 @@
32
33
  !!$packageInfo?.hasIntroOffer || !!$packageInfo?.hasTrial,
33
34
  props.overrides,
34
35
  ),
36
+ ...getPromoOfferStateProps(
37
+ !!$packageInfo?.hasPromoOffer,
38
+ props.overrides,
39
+ ),
35
40
  };
36
41
  });
37
42
 
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">
2
2
  import Paywall from "../paywall/Paywall.svelte";
3
+ import type { CompleteWorkflowNavigateArgs } from "../../types/components/button";
3
4
  import type { InitialInputSelections } from "../../stores/inputValidation";
4
5
  import type { WorkflowScreen } from "../../types/workflow";
5
6
  import type { VariableDictionary } from "../../types/variables";
6
7
  import type { WalletButtonRender } from "../../types/wallet";
7
8
  import type { UIConfig } from "../../types/ui-config";
8
-
9
9
  interface Props {
10
10
  paywallComponents: WorkflowScreen | null | undefined;
11
11
  selectedLocale?: string;
@@ -22,9 +22,11 @@
22
22
  variablesPerPackage?: Record<string, VariableDictionary>;
23
23
  initialInputSelections?: InitialInputSelections;
24
24
  onInputChanged?: (fieldId: string, value: string) => void;
25
+ onCompleteWorkflowNavigate?: (
26
+ args: CompleteWorkflowNavigateArgs,
27
+ ) => void | Promise<void>;
25
28
  walletButtonRender?: WalletButtonRender;
26
29
  }
27
-
28
30
  const {
29
31
  paywallComponents,
30
32
  selectedLocale = "en_US",
@@ -38,6 +40,7 @@
38
40
  variablesPerPackage,
39
41
  initialInputSelections = {},
40
42
  onInputChanged,
43
+ onCompleteWorkflowNavigate,
41
44
  walletButtonRender,
42
45
  }: Props = $props();
43
46
  </script>
@@ -55,6 +58,7 @@
55
58
  onNavigateToUrlClicked={(url: string) => {
56
59
  window.open(url, "_blank");
57
60
  }}
61
+ {onCompleteWorkflowNavigate}
58
62
  onVisitCustomerCenterClicked={() => {}}
59
63
  {onBackClicked}
60
64
  onRestorePurchasesClicked={() => {}}
@@ -1,3 +1,4 @@
1
+ import type { CompleteWorkflowNavigateArgs } from "../../types/components/button";
1
2
  import type { InitialInputSelections } from "../../stores/inputValidation";
2
3
  import type { WorkflowScreen } from "../../types/workflow";
3
4
  import type { VariableDictionary } from "../../types/variables";
@@ -16,6 +17,7 @@ interface Props {
16
17
  variablesPerPackage?: Record<string, VariableDictionary>;
17
18
  initialInputSelections?: InitialInputSelections;
18
19
  onInputChanged?: (fieldId: string, value: string) => void;
20
+ onCompleteWorkflowNavigate?: (args: CompleteWorkflowNavigateArgs) => void | Promise<void>;
19
21
  walletButtonRender?: WalletButtonRender;
20
22
  }
21
23
  declare const Screen: import("svelte").Component<Props, {}, "">;
package/dist/index.d.ts CHANGED
@@ -19,5 +19,6 @@ export { type InitialInputSelections } from "./stores/inputValidation";
19
19
  export { type UIConfig } from "./types/ui-config";
20
20
  export { type WalletButtonRender } from "./types/wallet";
21
21
  export { type CustomVariables, CustomVariableValue, type VariableDictionary, type PackageInfo, } from "./types/variables";
22
+ export type { CompleteWorkflowNavigateArgs, CompleteWorkflowUrlQueryParams, } from "./types/components/button";
22
23
  export * from "./ui/globals";
23
24
  export { default as Button } from "./ui/molecules/button.svelte";
@@ -34,7 +34,26 @@ interface NavigateToUrlAction {
34
34
  method: "deep_link" | "external_browser" | "in_app_browser";
35
35
  };
36
36
  }
37
- export type Action = WorkflowAction | RestorePurchasesAction | NavigateBackAction | NavigateToAction | NavigateToSheetAction | NavigateToWebPurchase | NavigateToUrlAction;
37
+ /** Optional query params for complete_workflow URLs (host merges values). */
38
+ export type CompleteWorkflowUrlQueryParams = {
39
+ app_user_id?: boolean;
40
+ };
41
+ /** Args passed to `onCompleteWorkflowNavigate` (host builds final URL if needed). */
42
+ export type CompleteWorkflowNavigateArgs = {
43
+ url: string;
44
+ method: "deep_link" | "external_browser" | "in_app_browser";
45
+ url_query_params?: CompleteWorkflowUrlQueryParams;
46
+ };
47
+ /** End the workflow and open a URL (optional query params, e.g. app user ID). */
48
+ interface CompleteWorkflowAction {
49
+ type: "complete_workflow";
50
+ url: {
51
+ url_lid: string;
52
+ method: "deep_link" | "external_browser" | "in_app_browser";
53
+ };
54
+ url_query_params?: CompleteWorkflowUrlQueryParams;
55
+ }
56
+ export type Action = WorkflowAction | RestorePurchasesAction | NavigateBackAction | NavigateToAction | NavigateToSheetAction | NavigateToWebPurchase | NavigateToUrlAction | CompleteWorkflowAction;
38
57
  export interface ButtonProps extends BaseComponent {
39
58
  type: "button";
40
59
  action: Action;
@@ -11,6 +11,7 @@ export declare function findSelectedPackageId({ stack, sticky_footer, }: RootPay
11
11
  export declare const getActiveStateProps: <T extends Component>(selectedState: boolean, overrides?: Overrides<T>) => Partial<T>;
12
12
  export declare const getHoverStateProps: <T extends Component>(hoverState: boolean, overrides?: Overrides<T>) => Partial<T>;
13
13
  export declare const getIntroOfferStateProps: <T extends Component>(hasIntroOffer: boolean, overrides?: Overrides<T>) => Partial<T>;
14
+ export declare const getPromoOfferStateProps: <T extends Component>(hasPromoOffer: boolean, overrides?: Overrides<T>) => Partial<T>;
14
15
  export type VisibilityContext = {
15
16
  selectedPackageId: string | undefined;
16
17
  packageInfo: PackageInfo | undefined;
@@ -58,6 +58,13 @@ export const getIntroOfferStateProps = (hasIntroOffer, overrides) => {
58
58
  const override = overrides?.find((override) => override.conditions.find((condition) => condition.type === "intro_offer"));
59
59
  return override?.properties ?? {};
60
60
  };
61
+ export const getPromoOfferStateProps = (hasPromoOffer, overrides) => {
62
+ if (!hasPromoOffer) {
63
+ return {};
64
+ }
65
+ const override = overrides?.find((override) => override.conditions.find((condition) => condition.type === "promo_offer"));
66
+ return override?.properties ?? {};
67
+ };
61
68
  const CONDITION_ORDER = [
62
69
  RuleKey.IntroOfferCondition,
63
70
  RuleKey.PromoOfferCondition,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@revenuecat/purchases-ui-js",
3
3
  "description": "Web components for Paywalls. Powered by RevenueCat",
4
4
  "private": false,
5
- "version": "3.9.2",
5
+ "version": "3.9.3",
6
6
  "author": {
7
7
  "name": "RevenueCat, Inc."
8
8
  },