@revenuecat/purchases-ui-js 0.0.13 → 0.0.14

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,7 +23,7 @@
23
23
  button {
24
24
  border: none;
25
25
  cursor: pointer;
26
- background-color: transparent;
26
+ background: transparent;
27
27
  padding: 0;
28
28
  width: 100%;
29
29
  display: flex;
@@ -3,13 +3,19 @@
3
3
  import type { ButtonNodeProps } from "../../data/entities";
4
4
  import Stack from "../stack/Stack.svelte";
5
5
 
6
- const { stack, action, labels, onAction, purchaseState }: ButtonNodeProps =
7
- $props();
6
+ const {
7
+ stack,
8
+ action,
9
+ onAction,
10
+ labels,
11
+ purchaseState,
12
+ variableDictionary,
13
+ }: ButtonNodeProps = $props();
8
14
  const onClick = () => {
9
15
  onAction && onAction(action);
10
16
  };
11
17
  </script>
12
18
 
13
19
  <Button onclick={onClick}>
14
- <Stack {...stack} {labels} {purchaseState} />
20
+ <Stack {...stack} {labels} {purchaseState} {variableDictionary} />
15
21
  </Button>
@@ -2,10 +2,10 @@
2
2
  import type { FooterProps } from "../../data/entities";
3
3
  import Stack from "../stack/Stack.svelte";
4
4
 
5
- const props: FooterProps = $props();
6
- const { stack, labels, id } = $derived(props);
5
+ const { stack, id, labels, purchaseState, variableDictionary }: FooterProps =
6
+ $props();
7
7
  </script>
8
8
 
9
9
  <div class="footer" {id}>
10
- <Stack {...stack} {labels} />
10
+ <Stack {...stack} {labels} {purchaseState} {variableDictionary} />
11
11
  </div>
@@ -32,15 +32,17 @@
32
32
  display: flex;
33
33
  flex: var(--flex, 1 0 auto);
34
34
  }
35
+
35
36
  .image {
36
37
  width: 100%;
37
38
  height: 100%;
38
39
  object-fit: cover;
39
40
  display: block;
40
41
  }
42
+
41
43
  .image-overlay {
42
44
  position: absolute;
43
45
  inset: 0;
44
- background: var(--background, unset);
46
+ background: var(--background, none);
45
47
  }
46
48
  </style>
@@ -9,6 +9,7 @@
9
9
  id,
10
10
  onAction,
11
11
  purchaseState,
12
+ variableDictionary,
12
13
  }: PackageProps = $props();
13
14
 
14
15
  const onPackageClick = (evt: MouseEvent) => {
@@ -20,20 +21,35 @@
20
21
  });
21
22
  };
22
23
 
24
+ const packageVariables = $derived(
25
+ purchaseState.variablesPerPackage?.[package_id] || variableDictionary,
26
+ );
23
27
  const isSelected = $derived(purchaseState?.selectedPackageId === package_id);
24
28
  </script>
25
29
 
26
- <div class="package" class:selected={isSelected} {id} onclick={onPackageClick}>
27
- <Stack {...stack} {labels} {onAction} {purchaseState} />
28
- </div>
30
+ <button
31
+ class="package"
32
+ class:selected={isSelected}
33
+ {id}
34
+ onclick={onPackageClick}
35
+ >
36
+ <Stack
37
+ {...stack}
38
+ {labels}
39
+ {onAction}
40
+ {purchaseState}
41
+ variableDictionary={packageVariables}
42
+ />
43
+ </button>
29
44
 
30
45
  <style>
31
46
  .package {
32
47
  width: 100%;
33
48
  display: flex;
34
- cursor: pointer;
35
- }
36
-
37
- .selected {
49
+ margin: 0;
50
+ padding: 0;
51
+ background: unset;
52
+ border: unset;
53
+ text-align: unset;
38
54
  }
39
55
  </style>
@@ -12,14 +12,22 @@
12
12
  import { prefersDarkMode } from "../../stores/theme";
13
13
  import ButtonNode from "../button/ButtonNode.svelte";
14
14
  import TextNode from "../text/TextNode.svelte";
15
+ import type { VariableDictionary } from "../../utils/variable-utils";
15
16
 
16
17
  interface Props extends ActionsProps, PurchaseStateProps {
17
18
  nodeData: PaywallComponent;
18
19
  labels: ComponentLocalizations;
19
20
  onAction?: (action: SupportedActions, data?: Extra) => void;
21
+ variableDictionary?: VariableDictionary;
20
22
  }
21
23
 
22
- const { nodeData, labels, onAction, purchaseState }: Props = $props();
24
+ const {
25
+ nodeData,
26
+ labels,
27
+ onAction,
28
+ purchaseState,
29
+ variableDictionary,
30
+ }: Props = $props();
23
31
 
24
32
  const ComponentTypes = {
25
33
  text: TextNode,
@@ -39,8 +47,15 @@
39
47
  prefersDarkMode={$prefersDarkMode}
40
48
  {onAction}
41
49
  {purchaseState}
50
+ {variableDictionary}
42
51
  >
43
52
  {#each nodeData.components as childData}
44
- <Self nodeData={childData} {labels} {onAction} {purchaseState} />
53
+ <Self
54
+ nodeData={childData}
55
+ {labels}
56
+ {onAction}
57
+ {purchaseState}
58
+ {variableDictionary}
59
+ />
45
60
  {/each}
46
61
  </MyComponent>
@@ -1,7 +1,9 @@
1
1
  import { type ActionsProps, type ComponentLocalizations, type Extra, type PaywallComponent, type PurchaseStateProps, type SupportedActions } from "../../data/entities";
2
+ import type { VariableDictionary } from "../../utils/variable-utils";
2
3
  declare const Node: import("svelte").Component<ActionsProps & PurchaseStateProps & {
3
4
  nodeData: PaywallComponent;
4
5
  labels: ComponentLocalizations;
5
6
  onAction?: (action: SupportedActions, data?: Extra) => void;
7
+ variableDictionary?: VariableDictionary;
6
8
  }, {}, "">;
7
9
  export default Node;
@@ -8,6 +8,8 @@
8
8
  fontsPaywallData,
9
9
  pastaPaywallData,
10
10
  paywallData,
11
+ gradientPaywallData,
12
+ variablesPastaPaywallData,
11
13
  } from "../../stories/fixtures";
12
14
  import { fn } from "@storybook/test";
13
15
 
@@ -31,7 +33,7 @@
31
33
  onRestorePurchasesClicked: fn(),
32
34
  }}
33
35
  />
34
- <!-- Italian missing labels story -->
36
+
35
37
  <Story
36
38
  name="Italian Missing Labels"
37
39
  args={{
@@ -79,6 +81,34 @@
79
81
  onRestorePurchasesClicked: fn(),
80
82
  }}
81
83
  />
84
+ <Story
85
+ name="Pasta paywall example(with variables)"
86
+ args={{
87
+ paywallData: variablesPastaPaywallData,
88
+ selectedLocale: "en_US",
89
+ onPurchaseClicked: fn(),
90
+ onBackClicked: fn(),
91
+ onNavigateToClicked: fn(),
92
+ onRestorePurchasesClicked: fn(),
93
+ variablesPerPackage: {
94
+ trial: {
95
+ product_name: "This was a variable: Product A",
96
+ price: "$19.99",
97
+ price_per_period: "$19.99/yr",
98
+ },
99
+ $rc_weekly: {
100
+ product_name: "This was a variable: Product B",
101
+ price: "$29.99",
102
+ price_per_period: "$29.99/yr",
103
+ },
104
+ $rc_daily: {
105
+ product_name: "This was a variable: Product C",
106
+ price: "$39.99",
107
+ price_per_period: "$39.99/yr",
108
+ },
109
+ },
110
+ }}
111
+ />
82
112
 
83
113
  <Story
84
114
  name="Calm paywall example"
@@ -91,3 +121,14 @@
91
121
  onRestorePurchasesClicked: fn(),
92
122
  }}
93
123
  />
124
+
125
+ <Story
126
+ name="Healthy Cat (Gradient)"
127
+ args={{
128
+ paywallData: gradientPaywallData,
129
+ onPurchaseClicked: fn(),
130
+ onBackClicked: fn(),
131
+ onNavigateToClicked: fn(),
132
+ onRestorePurchasesClicked: fn(),
133
+ }}
134
+ />
@@ -9,6 +9,7 @@
9
9
  import Node from "./Node.svelte";
10
10
  import type { PurchaseState } from "../../data/state";
11
11
  import { findSelectedPackageId, getLabelById } from "../../utils/style-utils";
12
+ import { type VariableDictionary } from "../../utils/variable-utils";
12
13
 
13
14
  interface Props {
14
15
  paywallData: PaywallData;
@@ -18,6 +19,7 @@
18
19
  onRestorePurchasesClicked?: () => void;
19
20
  onNavigateToUrlClicked?: (url: string) => void;
20
21
  selectedLocale?: string;
22
+ variablesPerPackage?: Record<string, VariableDictionary>;
21
23
  }
22
24
 
23
25
  const {
@@ -28,14 +30,20 @@
28
30
  onBackClicked,
29
31
  onVisitCustomerCenterClicked,
30
32
  selectedLocale,
33
+ variablesPerPackage = {},
31
34
  }: Props = $props();
32
35
 
33
36
  let purchaseState: PurchaseState = $state({
34
37
  selectedPackageId: findSelectedPackageId(paywallData),
35
38
  locale: selectedLocale || paywallData.default_locale,
36
39
  defaultLocale: paywallData.default_locale,
40
+ variablesPerPackage,
37
41
  });
38
42
 
43
+ let variableDictionary = $state(
44
+ variablesPerPackage[purchaseState.selectedPackageId || ""],
45
+ );
46
+
39
47
  const onRestorePurchasesAction = (_: SupportedActions, _2?: Extra) => {
40
48
  onRestorePurchasesClicked?.();
41
49
  };
@@ -68,6 +76,9 @@
68
76
 
69
77
  const onSelectPackageAction = (_: SupportedActions, data?: Extra) => {
70
78
  purchaseState.selectedPackageId = data?.packageId;
79
+ if (data?.packageId) {
80
+ variableDictionary = variablesPerPackage[data.packageId];
81
+ }
71
82
  };
72
83
 
73
84
  const onPurchaseAction = (_: SupportedActions, _2?: Extra) => {
@@ -104,6 +115,7 @@
104
115
  nodeData={paywallData.components_config.base.stack}
105
116
  labels={paywallData.components_localizations}
106
117
  {purchaseState}
118
+ {variableDictionary}
107
119
  />
108
120
  </div>
109
121
 
@@ -1,4 +1,5 @@
1
1
  import type { PaywallData } from "../../data/entities";
2
+ import { type VariableDictionary } from "../../utils/variable-utils";
2
3
  declare const Paywall: import("svelte").Component<{
3
4
  paywallData: PaywallData;
4
5
  onPurchaseClicked?: (selectedPackageId: string) => void;
@@ -7,5 +8,6 @@ declare const Paywall: import("svelte").Component<{
7
8
  onRestorePurchasesClicked?: () => void;
8
9
  onNavigateToUrlClicked?: (url: string) => void;
9
10
  selectedLocale?: string;
11
+ variablesPerPackage?: Record<string, VariableDictionary>;
10
12
  }, {}, "">;
11
13
  export default Paywall;
@@ -3,22 +3,27 @@
3
3
  import Stack from "../stack/Stack.svelte";
4
4
  import { Button } from "../../index";
5
5
 
6
- const { stack, labels, onAction, purchaseState }: PurchaseButtonProps =
7
- $props();
6
+ const {
7
+ stack,
8
+ labels,
9
+ onAction,
10
+ purchaseState,
11
+ variableDictionary,
12
+ }: PurchaseButtonProps = $props();
8
13
  const handleClick = () => {
9
14
  onAction && onAction({ type: "purchase" });
10
15
  };
11
16
  </script>
12
17
 
13
18
  <Button onclick={handleClick} class="purchase-button">
14
- <Stack {...stack} {labels} {purchaseState} />
19
+ <Stack {...stack} {labels} {purchaseState} {variableDictionary} />
15
20
  </Button>
16
21
 
17
22
  <style>
18
23
  .purchase-button {
19
24
  border: none;
20
25
  cursor: pointer;
21
- background-color: transparent;
26
+ background: transparent;
22
27
  padding: 0;
23
28
  width: 100%;
24
29
  display: flex;
@@ -10,6 +10,7 @@
10
10
  labels,
11
11
  onAction,
12
12
  purchaseState,
13
+ variableDictionary,
13
14
  ...restProps
14
15
  }: StackProps = $props();
15
16
 
@@ -29,7 +30,13 @@
29
30
 
30
31
  <div {id} style={stackStyles} class="stack">
31
32
  {#each components as component}
32
- <Node nodeData={component} {labels} {onAction} {purchaseState} />
33
+ <Node
34
+ nodeData={component}
35
+ {labels}
36
+ {onAction}
37
+ {purchaseState}
38
+ {variableDictionary}
39
+ />
33
40
  {/each}
34
41
  </div>
35
42
 
@@ -41,7 +48,7 @@
41
48
  width: var(--width, unset);
42
49
  height: var(--height, unset);
43
50
  gap: var(--spacing, 0);
44
- background-color: var(--background-color, unset);
51
+ background: var(--background, none);
45
52
  border: var(--border, none);
46
53
  border-radius: var(--border-radius, 0);
47
54
  box-shadow: var(--shadow, none);
@@ -15,7 +15,7 @@ type StackStyleVariables = {
15
15
  "--padding-inline-end": string;
16
16
  "--padding-block-end": string;
17
17
  "--padding-inline-start": string;
18
- "--background-color": string;
18
+ "--background": string;
19
19
  "--text-color": string;
20
20
  "--border": string;
21
21
  "--border-radius": string;
@@ -32,7 +32,7 @@
32
32
  margin-block-end: var(--margin-block-end, unset);
33
33
  margin-inline-start: var(--margin-inline-start, unset);
34
34
  color: var(--text-color, #ffffff);
35
- background-color: var(--background-color, #ffffff);
35
+ background: var(--background, none);
36
36
  font-size: var(--font-size, 1rem);
37
37
  font-weight: var(--font-weight, normal);
38
38
  text-align: var(--text-align, center);
@@ -36,7 +36,7 @@
36
36
  const parsedLabel = $derived(
37
37
  replaceVariables({
38
38
  value: label,
39
- dictionary: variableDictionary,
39
+ variableDictionary,
40
40
  }),
41
41
  );
42
42
  </script>
@@ -48,6 +48,7 @@ interface SharedComponentProps extends PaywallComponent, ActionsProps, PurchaseS
48
48
  id: string;
49
49
  colorMode: ColorMode;
50
50
  name: string;
51
+ variableDictionary?: VariableDictionary;
51
52
  }
52
53
  interface Action {
53
54
  type: "restore_purchases" | "navigate_to" | "navigate_back" | "purchase" | "select_package";
@@ -1,5 +1,7 @@
1
+ import type { VariableDictionary } from "../utils/variable-utils";
1
2
  export interface PurchaseState {
2
3
  selectedPackageId?: string;
3
4
  locale: string;
4
5
  defaultLocale: string;
6
+ variablesPerPackage?: Record<string, VariableDictionary>;
5
7
  }
package/dist/index.d.ts CHANGED
@@ -8,3 +8,4 @@ export { default as Image } from "./components/image/Image.svelte";
8
8
  export { default as PurchaseButton } from "./components/purchase-button/PurchaseButton.svelte";
9
9
  export { default as Package } from "./components/package/Package.svelte";
10
10
  export { default as Footer } from "./components/footer/Footer.svelte";
11
+ export { type VariableDictionary } from "./utils/variable-utils";
package/dist/index.js CHANGED
@@ -9,3 +9,4 @@ export { default as Image } from "./components/image/Image.svelte";
9
9
  export { default as PurchaseButton } from "./components/purchase-button/PurchaseButton.svelte";
10
10
  export { default as Package } from "./components/package/Package.svelte";
11
11
  export { default as Footer } from "./components/footer/Footer.svelte";
12
+ export {} from "./utils/variable-utils";
@@ -3,6 +3,8 @@ export declare const paywallData: PaywallData;
3
3
  export declare const alignmentPaywallData: PaywallData;
4
4
  export declare const fontsPaywallData: PaywallData;
5
5
  export declare const pastaPaywallData: PaywallData;
6
+ export declare const variablesPastaPaywallData: PaywallData;
7
+ export declare const gradientPaywallData: PaywallData;
6
8
  export declare const calmPaywallData: PaywallData;
7
9
  export declare const labelsData: {
8
10
  en_US: {