@revenuecat/purchases-ui-js 3.5.2 → 3.5.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.
Files changed (30) hide show
  1. package/dist/components/express-purchase-button/ExpressPurchaseButton.stories.svelte +368 -0
  2. package/dist/components/express-purchase-button/ExpressPurchaseButton.stories.svelte.d.ts +19 -0
  3. package/dist/components/express-purchase-button/ExpressPurchaseButton.svelte +43 -0
  4. package/dist/components/express-purchase-button/ExpressPurchaseButton.svelte.d.ts +4 -0
  5. package/dist/components/options/InputOption.svelte +5 -2
  6. package/dist/components/paywall/Node.svelte +6 -0
  7. package/dist/components/paywall/Paywall.stories.svelte +46 -2
  8. package/dist/components/paywall/Paywall.svelte +2 -2
  9. package/dist/components/paywall/Paywall.svelte.d.ts +2 -2
  10. package/dist/components/paywall/fixtures/express-purchase-button-paywall.d.ts +1786 -0
  11. package/dist/components/paywall/fixtures/express-purchase-button-paywall.js +1819 -0
  12. package/dist/components/purchase-button/PurchaseButton.svelte +2 -145
  13. package/dist/components/skeleton-loader/SkeletonLoader.svelte +127 -0
  14. package/dist/components/skeleton-loader/SkeletonLoader.svelte.d.ts +8 -0
  15. package/dist/components/stack/Stack.svelte +2 -2
  16. package/dist/components/wallet-button/WalletButton.svelte +75 -0
  17. package/dist/components/wallet-button/WalletButton.svelte.d.ts +8 -0
  18. package/dist/stores/paywall.d.ts +3 -2
  19. package/dist/stories/paywall-decorator.d.ts +3 -3
  20. package/dist/stories/paywall-decorator.js +5 -5
  21. package/dist/stories/selected-package-id-decorator.d.ts +2 -0
  22. package/dist/stories/selected-package-id-decorator.js +12 -0
  23. package/dist/types/component.d.ts +4 -1
  24. package/dist/types/components/express-purchase-button-props.d.ts +8 -0
  25. package/dist/types/components/express-purchase-button-props.js +1 -0
  26. package/dist/types/components/skeleton-loader-props.d.ts +13 -0
  27. package/dist/types/components/skeleton-loader-props.js +1 -0
  28. package/dist/types/components/wallet-button.d.ts +14 -0
  29. package/dist/types/components/wallet-button.js +1 -0
  30. package/package.json +1 -1
@@ -0,0 +1,368 @@
1
+ <script module lang="ts">
2
+ import ExpressPurchaseButton from "./ExpressPurchaseButton.svelte";
3
+ import { componentDecorator } from "../../stories/component-decorator";
4
+ import { localizations } from "../../stories/fixtures";
5
+ import { localizationDecorator } from "../../stories/localization-decorator";
6
+ import { paywallDecorator } from "../../stories/paywall-decorator";
7
+ import { variablesDecorator } from "../../stories/variables-decorator";
8
+ import type { ExpressPurchaseButtonProps } from "../../types/components/express-purchase-button-props";
9
+ import type { SkeletonLoaderProps } from "../../types/components/skeleton-loader-props";
10
+ import type { WalletButtonProps } from "../../types/components/wallet-button";
11
+ import { defineMeta } from "@storybook/addon-svelte-csf";
12
+ import { mockDateDecorator } from "storybook-mock-date-decorator";
13
+ import type { PurchaseButtonProps } from "../../types/components/purchase-button";
14
+
15
+ const defaultLocale = "en_US";
16
+ const textLidWhenAvailable = "purchase_wallet_available_text";
17
+ const textLidWhenUnavailable = "purchase_wallet_unavailable_text";
18
+ const loc = {
19
+ en_US: {
20
+ ...localizations["en_US"],
21
+ [textLidWhenAvailable]: "Purchase with Wallet",
22
+ [textLidWhenUnavailable]: "Wallet Unavailable",
23
+ },
24
+ };
25
+
26
+ const createWalletButtonRender =
27
+ ({ available, delay }: { available: boolean; delay?: number }) =>
28
+ (
29
+ element: HTMLElement,
30
+ {
31
+ selectedPackageId,
32
+ onReady,
33
+ }: {
34
+ selectedPackageId: string;
35
+ onReady?: (isAvailable?: boolean) => void;
36
+ },
37
+ ) => {
38
+ const mockButton = document.createElement("button");
39
+ mockButton.innerHTML = `Wallet for ${selectedPackageId}`;
40
+ mockButton.style.width = "100%";
41
+ mockButton.style.padding = "12px 16px";
42
+ mockButton.style.borderRadius = "12px";
43
+ mockButton.style.border = "1px solid rgba(0,0,0,0.12)";
44
+ mockButton.style.background = available ? "#0b8f4d" : "#ccc";
45
+ mockButton.style.color = "#fff";
46
+
47
+ setTimeout(() => {
48
+ element.replaceChildren(mockButton);
49
+ onReady?.(available);
50
+ }, delay);
51
+
52
+ return {
53
+ destroy: () => {
54
+ element.replaceChildren();
55
+ },
56
+ };
57
+ };
58
+
59
+ const skeletonLoaderProps: SkeletonLoaderProps = {
60
+ type: "skeleton_loader",
61
+ id: "wallet-loader",
62
+ name: "Wallet Loader",
63
+ size: {
64
+ width: { type: "fill" },
65
+ height: { type: "fit" },
66
+ },
67
+ margin: { top: 0, trailing: 0, bottom: 0, leading: 0 },
68
+ border: null,
69
+ shape: {
70
+ type: "rectangle",
71
+ corners: {
72
+ top_leading: 12,
73
+ top_trailing: 12,
74
+ bottom_leading: 12,
75
+ bottom_trailing: 12,
76
+ },
77
+ },
78
+ shadow: null,
79
+ };
80
+
81
+ const walletProps: WalletButtonProps = {
82
+ type: "wallet_button",
83
+ id: "wallet_button",
84
+ name: "Wallet Button",
85
+ size: {
86
+ width: { type: "fill" },
87
+ height: { type: "fit" },
88
+ },
89
+ dimension: {
90
+ type: "vertical",
91
+ alignment: "center",
92
+ distribution: "center",
93
+ },
94
+ spacing: 8,
95
+ margin: { top: 0, trailing: 0, bottom: 0, leading: 0 },
96
+ border: null,
97
+ shape: {
98
+ type: "rectangle",
99
+ corners: {
100
+ top_leading: 8,
101
+ top_trailing: 8,
102
+ bottom_leading: 8,
103
+ bottom_trailing: 8,
104
+ },
105
+ },
106
+ shadow: null,
107
+ };
108
+
109
+ const purchaseButtonWhenAvailableProps = {
110
+ type: "purchase_button",
111
+ id: "purchase-button",
112
+ name: "Purchase button",
113
+ stack: {
114
+ type: "stack",
115
+ id: "pbvAUBvilP",
116
+ name: "Stack",
117
+ background_color: {
118
+ light: {
119
+ type: "hex",
120
+ value: "#a229f3",
121
+ },
122
+ },
123
+ background: {
124
+ type: "color",
125
+ value: {
126
+ light: {
127
+ type: "hex",
128
+ value: "#a229f3",
129
+ },
130
+ },
131
+ },
132
+ components: [
133
+ {
134
+ background_color: null,
135
+ color: {
136
+ light: {
137
+ type: "hex",
138
+ value: "#ffffff",
139
+ },
140
+ },
141
+ font_name: null,
142
+ font_size: "heading_m",
143
+ font_weight: "extra_bold",
144
+ horizontal_alignment: "center",
145
+ id: "MI_dDBpD4z",
146
+ margin: {
147
+ bottom: 0,
148
+ leading: 0,
149
+ top: 0,
150
+ trailing: 0,
151
+ },
152
+ name: "Text",
153
+ padding: {
154
+ bottom: 0,
155
+ leading: 0,
156
+ top: 0,
157
+ trailing: 0,
158
+ },
159
+ size: {
160
+ height: {
161
+ type: "fit",
162
+ value: null,
163
+ },
164
+ width: {
165
+ type: "fill",
166
+ value: null,
167
+ },
168
+ },
169
+ text_lid: textLidWhenAvailable,
170
+ type: "text",
171
+ },
172
+ ],
173
+ dimension: {
174
+ type: "vertical",
175
+ alignment: "center",
176
+ distribution: "center",
177
+ },
178
+ margin: {
179
+ bottom: 0,
180
+ leading: 0,
181
+ top: 0,
182
+ trailing: 0,
183
+ },
184
+ padding: {
185
+ bottom: 16,
186
+ leading: 16,
187
+ top: 16,
188
+ trailing: 16,
189
+ },
190
+ border: null,
191
+ shadow: null,
192
+ shape: {
193
+ corners: {
194
+ bottom_leading: 8,
195
+ bottom_trailing: 8,
196
+ top_leading: 8,
197
+ top_trailing: 8,
198
+ },
199
+ type: "rectangle",
200
+ },
201
+ size: {
202
+ height: {
203
+ type: "fit",
204
+ },
205
+ width: {
206
+ type: "fill",
207
+ },
208
+ },
209
+ spacing: 8,
210
+ },
211
+ } satisfies PurchaseButtonProps;
212
+
213
+ const purchaseButtonWhenUnavailableProps = {
214
+ ...purchaseButtonWhenAvailableProps,
215
+ } satisfies PurchaseButtonProps;
216
+ purchaseButtonWhenUnavailableProps.stack.components[0].text_lid =
217
+ textLidWhenUnavailable;
218
+
219
+ const { Story } = defineMeta({
220
+ title: "Components/ExpressPurchaseButton",
221
+ component: ExpressPurchaseButton,
222
+ decorators: [
223
+ mockDateDecorator,
224
+ componentDecorator(),
225
+ localizationDecorator({
226
+ defaultLocale,
227
+ localizations: loc,
228
+ }),
229
+ variablesDecorator(undefined),
230
+ ],
231
+
232
+ args: {
233
+ type: "express_purchase_button",
234
+ id: "express_purchase_button",
235
+ name: "ExpressPurchaseButton",
236
+
237
+ wallet_available_stack: {
238
+ type: "stack",
239
+ id: "wallet-available-stack",
240
+ name: "Wallet Available Stack",
241
+ components: [walletProps, purchaseButtonWhenAvailableProps],
242
+ size: {
243
+ width: { type: "fill" },
244
+ height: { type: "fit" },
245
+ },
246
+ dimension: {
247
+ type: "vertical",
248
+ alignment: "center",
249
+ distribution: "center",
250
+ },
251
+ spacing: 8,
252
+ margin: { top: 0, trailing: 0, bottom: 0, leading: 0 },
253
+ padding: { top: 16, trailing: 16, bottom: 16, leading: 16 },
254
+ background_color: null,
255
+ background: null,
256
+ border: null,
257
+ shape: {
258
+ type: "rectangle",
259
+ corners: {
260
+ top_leading: 8,
261
+ top_trailing: 8,
262
+ bottom_leading: 8,
263
+ bottom_trailing: 8,
264
+ },
265
+ },
266
+ shadow: null,
267
+ badge: null,
268
+ },
269
+ wallet_unavailable_stack: {
270
+ type: "stack",
271
+ id: "wallet-unavailable-stack",
272
+ name: "Wallet Unavailable Stack",
273
+ components: [purchaseButtonWhenUnavailableProps],
274
+ size: {
275
+ width: { type: "fill" },
276
+ height: { type: "fit" },
277
+ },
278
+ dimension: {
279
+ type: "vertical",
280
+ alignment: "center",
281
+ distribution: "center",
282
+ },
283
+ spacing: 8,
284
+ margin: { top: 0, trailing: 0, bottom: 0, leading: 0 },
285
+ padding: { top: 16, trailing: 16, bottom: 16, leading: 16 },
286
+ background_color: null,
287
+ background: null,
288
+ border: null,
289
+ shape: {
290
+ type: "rectangle",
291
+ corners: {
292
+ top_leading: 8,
293
+ top_trailing: 8,
294
+ bottom_leading: 8,
295
+ bottom_trailing: 8,
296
+ },
297
+ },
298
+ shadow: null,
299
+ badge: null,
300
+ },
301
+ wallet_unknown_stack: {
302
+ type: "stack",
303
+ id: "wallet-unknown-stack",
304
+ name: "Wallet Unknown Stack",
305
+ components: [skeletonLoaderProps],
306
+ size: {
307
+ width: { type: "fill" },
308
+ height: { type: "fit" },
309
+ },
310
+ dimension: {
311
+ type: "vertical",
312
+ alignment: "center",
313
+ distribution: "center",
314
+ },
315
+ spacing: 8,
316
+ margin: { top: 0, trailing: 0, bottom: 0, leading: 0 },
317
+ padding: { top: 16, trailing: 16, bottom: 16, leading: 16 },
318
+ background_color: null,
319
+ background: null,
320
+ border: null,
321
+ shape: {
322
+ type: "rectangle",
323
+ corners: {
324
+ top_leading: 8,
325
+ top_trailing: 8,
326
+ bottom_leading: 8,
327
+ bottom_trailing: 8,
328
+ },
329
+ },
330
+ shadow: null,
331
+ badge: null,
332
+ },
333
+ } satisfies ExpressPurchaseButtonProps,
334
+ });
335
+ </script>
336
+
337
+ <Story
338
+ name="Wallets Available"
339
+ decorators={[
340
+ paywallDecorator(
341
+ createWalletButtonRender({ available: true, delay: 1000 }),
342
+ "some-package-id",
343
+ ),
344
+ ]}
345
+ args={{}}
346
+ />
347
+
348
+ <Story
349
+ name="Wallets Unavailable"
350
+ decorators={[
351
+ paywallDecorator(
352
+ createWalletButtonRender({ available: false, delay: 1000 }),
353
+ "some-package-id",
354
+ ),
355
+ ]}
356
+ args={{}}
357
+ />
358
+
359
+ <Story
360
+ name="Wallets Unknown"
361
+ decorators={[
362
+ paywallDecorator(
363
+ createWalletButtonRender({ available: false, delay: 1000 }),
364
+ "some-package-id",
365
+ ),
366
+ ]}
367
+ args={{}}
368
+ />
@@ -0,0 +1,19 @@
1
+ import ExpressPurchaseButton from "./ExpressPurchaseButton.svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const ExpressPurchaseButton: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type ExpressPurchaseButton = InstanceType<typeof ExpressPurchaseButton>;
19
+ export default ExpressPurchaseButton;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import Stack from "../stack/Stack.svelte";
3
+ import { getPaywallContext, setPaywallContext } from "../../stores/paywall";
4
+ import type { ExpressPurchaseButtonProps } from "../../types/components/express-purchase-button-props";
5
+
6
+ const props: ExpressPurchaseButtonProps = $props();
7
+ const {
8
+ wallet_unknown_stack,
9
+ wallet_available_stack,
10
+ wallet_unavailable_stack,
11
+ } = props;
12
+
13
+ const { walletButtonRender, ...rest } = getPaywallContext();
14
+
15
+ let walletButtonAvailable = $state<boolean | undefined>(undefined);
16
+ let shouldShowWalletSkeleton = $state(!!walletButtonRender);
17
+
18
+ const onWalletButtonReady = (isAvailable?: boolean) => {
19
+ walletButtonAvailable = isAvailable;
20
+ shouldShowWalletSkeleton = false;
21
+ };
22
+
23
+ setPaywallContext({ walletButtonRender, ...rest, onWalletButtonReady });
24
+
25
+ const shouldShowUnavailableStack = $derived(
26
+ !walletButtonAvailable || !wallet_available_stack,
27
+ );
28
+ const shouldShowAvailableStack = $derived(
29
+ Boolean(
30
+ wallet_available_stack &&
31
+ walletButtonAvailable &&
32
+ !shouldShowWalletSkeleton,
33
+ ),
34
+ );
35
+ </script>
36
+
37
+ <Stack {...{ ...wallet_available_stack, visible: shouldShowAvailableStack }} />
38
+
39
+ {#if shouldShowWalletSkeleton}
40
+ <Stack {...wallet_unknown_stack} />
41
+ {:else if shouldShowUnavailableStack}
42
+ <Stack {...wallet_unavailable_stack} />
43
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { ExpressPurchaseButtonProps } from "../../types/components/express-purchase-button-props";
2
+ declare const ExpressPurchaseButton: import("svelte").Component<ExpressPurchaseButtonProps, {}, "">;
3
+ type ExpressPurchaseButton = ReturnType<typeof ExpressPurchaseButton>;
4
+ export default ExpressPurchaseButton;
@@ -27,9 +27,12 @@
27
27
 
28
28
  const onclick = () => {
29
29
  const actionId = props.triggers?.on_press;
30
- // Create a workflow action to pass up through the callback
31
- onButtonAction({ type: "workflow" }, actionId);
30
+
31
+ // Update selection state
32
32
  inputChoiceContext?.selectOption(option_id);
33
+
34
+ // Trigger navigation
35
+ onButtonAction({ type: "workflow" }, actionId);
33
36
  };
34
37
  </script>
35
38
 
@@ -23,6 +23,9 @@
23
23
  import TabControlButton from "../tabs/TabControlButton.svelte";
24
24
  import TabControlToggle from "../tabs/TabControlToggle.svelte";
25
25
  import Tabs from "../tabs/Tabs.svelte";
26
+ import WalletButton from "../wallet-button/WalletButton.svelte";
27
+ import SkeletonLoader from "../skeleton-loader/SkeletonLoader.svelte";
28
+ import ExpressPurchaseButton from "../express-purchase-button/ExpressPurchaseButton.svelte";
26
29
 
27
30
  interface Props {
28
31
  nodeData: Component;
@@ -32,6 +35,7 @@
32
35
  button: ButtonNode,
33
36
  carousel: Carousel,
34
37
  countdown: Countdown,
38
+ express_purchase_button: ExpressPurchaseButton,
35
39
  footer: Footer,
36
40
  icon: Icon,
37
41
  image: Image,
@@ -41,6 +45,7 @@
41
45
  package: Package,
42
46
  purchase_button: PurchaseButton,
43
47
  redemption_button: RedemptionButton,
48
+ skeleton_loader: SkeletonLoader,
44
49
  stack: Stack,
45
50
  tab_control_button: TabControlButton,
46
51
  tab_control_toggle: TabControlToggle,
@@ -49,6 +54,7 @@
49
54
  text: TextNode,
50
55
  timeline: Timeline,
51
56
  video: Video,
57
+ wallet_button: WalletButton,
52
58
  } satisfies {
53
59
  [key in Component["type"]]: SvelteComponent<
54
60
  Extract<Component, { type: key }>
@@ -47,6 +47,10 @@
47
47
  });
48
48
  </script>
49
49
 
50
+ <script>
51
+ import { DUELINGUE_PAYWALL } from "./fixtures/express-purchase-button-paywall";
52
+ </script>
53
+
50
54
  <Story
51
55
  name="Stack paywall"
52
56
  args={{
@@ -354,7 +358,7 @@
354
358
 
355
359
  setTimeout(() => {
356
360
  element.append(newDiv);
357
- onReady && onReady();
361
+ onReady && onReady(true);
358
362
  }, 3000);
359
363
  return {};
360
364
  },
@@ -378,7 +382,47 @@
378
382
 
379
383
  setTimeout(() => {
380
384
  element.append(newDiv);
381
- onReady && onReady();
385
+ onReady && onReady(true);
386
+ }, 3000);
387
+ return {};
388
+ },
389
+ }}
390
+ />
391
+
392
+ <Story
393
+ name="Duelinuge Paywall Wallet Button available"
394
+ args={{
395
+ paywallData: DUELINGUE_PAYWALL,
396
+ walletButtonRender: (
397
+ element: HTMLElement,
398
+ { selectedPackageId, onReady },
399
+ ) => {
400
+ const newDiv = document.createElement("div");
401
+ newDiv.innerText = "Hi! I was injected from the walletButtonRender";
402
+ newDiv.style.width = "100%";
403
+ newDiv.style.textAlign = "center";
404
+ newDiv.style.color = "black";
405
+ newDiv.style.border = "1px solid black";
406
+
407
+ setTimeout(() => {
408
+ element.append(newDiv);
409
+ onReady && onReady(true);
410
+ }, 3000);
411
+ return {};
412
+ },
413
+ }}
414
+ />
415
+
416
+ <Story
417
+ name="Duelinuge Paywall Wallet Button Unavailable"
418
+ args={{
419
+ paywallData: DUELINGUE_PAYWALL,
420
+ walletButtonRender: (
421
+ element: HTMLElement,
422
+ { selectedPackageId, onReady },
423
+ ) => {
424
+ setTimeout(() => {
425
+ onReady && onReady(false);
382
426
  }, 3000);
383
427
  return {};
384
428
  },
@@ -52,13 +52,13 @@
52
52
  node: HTMLElement,
53
53
  params: {
54
54
  selectedPackageId: string;
55
- onReady?: () => void;
55
+ onReady?: (walletButtonAvailable?: boolean) => void;
56
56
  },
57
57
  ) => {
58
58
  destroy?: () => void;
59
59
  update?: (updateParams: {
60
60
  selectedPackageId: string;
61
- onReady?: () => void;
61
+ onReady?: (walletButtonAvailable?: boolean) => void;
62
62
  }) => void;
63
63
  };
64
64
  maxContentWidth?: string;
@@ -26,12 +26,12 @@ interface Props {
26
26
  hideBackButtons?: boolean;
27
27
  walletButtonRender?: (node: HTMLElement, params: {
28
28
  selectedPackageId: string;
29
- onReady?: () => void;
29
+ onReady?: (walletButtonAvailable?: boolean) => void;
30
30
  }) => {
31
31
  destroy?: () => void;
32
32
  update?: (updateParams: {
33
33
  selectedPackageId: string;
34
- onReady?: () => void;
34
+ onReady?: (walletButtonAvailable?: boolean) => void;
35
35
  }) => void;
36
36
  };
37
37
  maxContentWidth?: string;