@revenuecat/purchases-ui-js 2.0.3 → 2.0.5

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 (68) hide show
  1. package/dist/components/button/ButtonNode.stories.svelte +1 -1
  2. package/dist/components/button/ButtonNode.svelte +27 -3
  3. package/dist/components/carousel/Carousel.stories.svelte +1039 -0
  4. package/dist/components/carousel/Carousel.stories.svelte.d.ts +19 -0
  5. package/dist/components/carousel/Carousel.svelte +298 -0
  6. package/dist/components/carousel/Carousel.svelte.d.ts +4 -0
  7. package/dist/components/carousel/CarouselPage.svelte +39 -0
  8. package/dist/components/carousel/CarouselPage.svelte.d.ts +11 -0
  9. package/dist/components/carousel/PageControl.svelte +93 -0
  10. package/dist/components/carousel/PageControl.svelte.d.ts +4 -0
  11. package/dist/components/carousel/carousel-utils.d.ts +4 -0
  12. package/dist/components/carousel/carousel-utils.js +21 -0
  13. package/dist/components/package/Package.svelte +3 -1
  14. package/dist/components/paywall/Node.svelte +12 -24
  15. package/dist/components/paywall/Node.svelte.d.ts +1 -6
  16. package/dist/components/paywall/Paywall.stories.svelte +155 -0
  17. package/dist/components/paywall/Paywall.svelte +50 -59
  18. package/dist/components/paywall/Paywall.svelte.d.ts +2 -1
  19. package/dist/components/paywall/Sheet.svelte +126 -0
  20. package/dist/components/paywall/Sheet.svelte.d.ts +4 -0
  21. package/dist/components/paywall/fixtures/background-paywall.d.ts +3 -0
  22. package/dist/components/paywall/fixtures/background-paywall.js +62 -0
  23. package/dist/components/paywall/fixtures/override-paywall.d.ts +1 -1
  24. package/dist/components/paywall/fixtures/sheet-paywall.d.ts +2 -0
  25. package/dist/components/paywall/fixtures/sheet-paywall.js +325 -0
  26. package/dist/components/paywall/fixtures/stack-paywall.d.ts +1 -1
  27. package/dist/components/stack/Stack.svelte +6 -1
  28. package/dist/components/stack/Stack.svelte.d.ts +2 -0
  29. package/dist/components/tabs/TabControl.svelte +11 -0
  30. package/dist/components/tabs/TabControl.svelte.d.ts +4 -0
  31. package/dist/components/tabs/TabControlButton.svelte +19 -0
  32. package/dist/components/tabs/TabControlButton.svelte.d.ts +4 -0
  33. package/dist/components/tabs/Tabs.stories.svelte +929 -0
  34. package/dist/components/tabs/Tabs.stories.svelte.d.ts +19 -0
  35. package/dist/components/tabs/Tabs.svelte +69 -0
  36. package/dist/components/tabs/Tabs.svelte.d.ts +4 -0
  37. package/dist/components/tabs/tabs-context.d.ts +11 -0
  38. package/dist/components/tabs/tabs-context.js +12 -0
  39. package/dist/index.d.ts +2 -2
  40. package/dist/index.js +2 -2
  41. package/dist/stores/paywall.d.ts +1 -1
  42. package/dist/stores/selected.d.ts +1 -1
  43. package/dist/stores/selected.js +3 -5
  44. package/dist/stories/fixtures.d.ts +2 -1
  45. package/dist/stories/viewport-wrapper.svelte +7 -5
  46. package/dist/types/component.d.ts +5 -3
  47. package/dist/types/components/button.d.ts +4 -1
  48. package/dist/types/components/carousel.d.ts +51 -0
  49. package/dist/types/components/sheet.d.ts +16 -0
  50. package/dist/types/components/sheet.js +1 -0
  51. package/dist/types/components/tabs.d.ts +46 -0
  52. package/dist/types/components/tabs.js +1 -0
  53. package/dist/types/paywall.d.ts +26 -0
  54. package/dist/types/paywall.js +1 -0
  55. package/dist/types/ui-config.d.ts +20 -0
  56. package/dist/types/ui-config.js +1 -0
  57. package/dist/types.d.ts +6 -2
  58. package/dist/utils/base-utils.d.ts +1 -1
  59. package/dist/utils/base-utils.js +2 -17
  60. package/dist/utils/font-utils.d.ts +1 -1
  61. package/dist/utils/style-utils.d.ts +2 -9
  62. package/dist/utils/style-utils.js +7 -24
  63. package/dist/web-components/index.js +969 -942
  64. package/package.json +20 -20
  65. package/dist/components/paywall/paywall-utils.d.ts +0 -8
  66. package/dist/components/paywall/paywall-utils.js +0 -24
  67. package/dist/data/entities.d.ts +0 -46
  68. /package/dist/{data/entities.js → types/components/carousel.js} +0 -0
@@ -19,7 +19,11 @@
19
19
  uiConfigData,
20
20
  zStackTemplate,
21
21
  } from "../../stories/fixtures";
22
+ import { waitForAnimations } from "storybook/internal/preview-api";
23
+ import { viewportDecorator } from "../../stories/viewport-decorator";
24
+ import { BACKGROUND_PAYWALL } from "./fixtures/background-paywall";
22
25
  import { OVERRIDE_PAYWALL } from "./fixtures/override-paywall";
26
+ import { SHEET_PAYWALL } from "./fixtures/sheet-paywall";
23
27
  import { STACK_PAYWALL } from "./fixtures/stack-paywall";
24
28
  import { VARIABLES } from "./fixtures/variables";
25
29
 
@@ -53,6 +57,157 @@
53
57
  }}
54
58
  />
55
59
 
60
+ <Story
61
+ name="Sheet"
62
+ decorators={[viewportDecorator(500, 500, 0)]}
63
+ play={async ({ canvasElement }) => {
64
+ const button = canvasElement.querySelector("button");
65
+ button?.click();
66
+ await waitForAnimations();
67
+ }}
68
+ args={{
69
+ paywallData: SHEET_PAYWALL,
70
+ }}
71
+ />
72
+
73
+ <Story
74
+ name="Background - Color"
75
+ decorators={[viewportDecorator(500, 500, 0)]}
76
+ args={{
77
+ paywallData: BACKGROUND_PAYWALL({
78
+ type: "color",
79
+ value: {
80
+ light: {
81
+ type: "hex",
82
+ value: "#ddffddff",
83
+ },
84
+ },
85
+ }),
86
+ }}
87
+ />
88
+
89
+ <Story
90
+ name="Background - Linear gradient"
91
+ decorators={[viewportDecorator(500, 500, 0)]}
92
+ args={{
93
+ paywallData: BACKGROUND_PAYWALL({
94
+ type: "color",
95
+ value: {
96
+ light: {
97
+ type: "linear",
98
+ degrees: 0,
99
+ points: [
100
+ { percent: 0, color: "#ddffddff" },
101
+ {
102
+ percent: 100,
103
+ color: "#000000ff",
104
+ },
105
+ ],
106
+ },
107
+ },
108
+ }),
109
+ }}
110
+ />
111
+
112
+ <Story
113
+ name="Background - Radial gradient"
114
+ decorators={[viewportDecorator(500, 500, 0)]}
115
+ args={{
116
+ paywallData: BACKGROUND_PAYWALL({
117
+ type: "color",
118
+ value: {
119
+ light: {
120
+ type: "radial",
121
+ points: [
122
+ { percent: 0, color: "#ddffddff" },
123
+ {
124
+ percent: 100,
125
+ color: "#000000ff",
126
+ },
127
+ ],
128
+ },
129
+ },
130
+ }),
131
+ }}
132
+ />
133
+
134
+ <Story
135
+ name="Background - Image fit"
136
+ decorators={[viewportDecorator(500, 500, 0)]}
137
+ args={{
138
+ paywallData: BACKGROUND_PAYWALL({
139
+ type: "image",
140
+ fit_mode: "fit",
141
+ color_overlay: null,
142
+ value: {
143
+ light: {
144
+ width: 600,
145
+ height: 400,
146
+ original: "https://placehold.co/500x1000",
147
+ heic: "https://placehold.co/500x1000",
148
+ heic_low_res: "https://placehold.co/500x1000",
149
+ webp: "https://placehold.co/500x1000",
150
+ webp_low_res: "https://placehold.co/500x1000",
151
+ },
152
+ },
153
+ }),
154
+ }}
155
+ />
156
+
157
+ <Story
158
+ name="Background - Image fill"
159
+ decorators={[viewportDecorator(500, 500, 0)]}
160
+ args={{
161
+ paywallData: BACKGROUND_PAYWALL({
162
+ type: "image",
163
+ fit_mode: "fill",
164
+ color_overlay: null,
165
+ value: {
166
+ light: {
167
+ width: 600,
168
+ height: 400,
169
+ original: "https://placehold.co/500x1000",
170
+ heic: "https://placehold.co/500x1000",
171
+ heic_low_res: "https://placehold.co/500x1000",
172
+ webp: "https://placehold.co/500x1000",
173
+ webp_low_res: "https://placehold.co/500x1000",
174
+ },
175
+ },
176
+ }),
177
+ }}
178
+ />
179
+
180
+ <Story
181
+ name="Background - Image overlay"
182
+ decorators={[viewportDecorator(500, 500, 0)]}
183
+ args={{
184
+ paywallData: BACKGROUND_PAYWALL({
185
+ type: "image",
186
+ fit_mode: "fill",
187
+ color_overlay: {
188
+ light: {
189
+ type: "radial",
190
+ points: [
191
+ { percent: 0, color: "#ddffdd7f" },
192
+ { percent: 100, color: "#0000007f" },
193
+ ],
194
+ },
195
+ },
196
+ value: {
197
+ light: {
198
+ width: 600,
199
+ height: 400,
200
+ original: "https://placehold.co/500x1000",
201
+ heic: "https://placehold.co/500x1000",
202
+ heic_low_res: "https://placehold.co/500x1000",
203
+ webp: "https://placehold.co/500x1000",
204
+ webp_low_res: "https://placehold.co/500x1000",
205
+ },
206
+ },
207
+ }),
208
+ }}
209
+ />
210
+
56
211
  <Story
57
212
  name="Primary"
58
213
  args={{
@@ -1,12 +1,5 @@
1
1
  <script lang="ts">
2
- import type { PaywallData, UIConfig } from "../../data/entities";
3
-
4
2
  import Footer from "../footer/Footer.svelte";
5
- import Node from "./Node.svelte";
6
- import {
7
- getBackgroundImageSource,
8
- getBackgroundStyles,
9
- } from "./paywall-utils";
10
3
  import { setColorModeContext } from "../../stores/color-mode";
11
4
  import { setLocalizationContext } from "../../stores/localization";
12
5
  import { setPaywallContext } from "../../stores/paywall";
@@ -16,11 +9,18 @@
16
9
  } from "../../stores/variables";
17
10
  import type { ColorMode } from "../../types";
18
11
  import type { Action } from "../../types/components/button";
19
- import { findSelectedPackageId } from "../../utils/style-utils";
12
+ import type { SheetProps } from "../../types/components/sheet";
13
+ import type { PaywallData } from "../../types/paywall";
14
+ import type { UIConfig } from "../../types/ui-config";
15
+ import type { VariableDictionary } from "../../types/variables";
16
+ import { mapBackground } from "../../utils/background-utils";
17
+ import { css } from "../../utils/base-utils";
20
18
  import { registerFonts } from "../../utils/font-utils";
21
- import { derived, readable, writable } from "svelte/store";
19
+ import { findSelectedPackageId } from "../../utils/style-utils";
22
20
  import { onMount } from "svelte";
23
- import type { VariableDictionary } from "../../types/variables";
21
+ import { derived, readable, writable } from "svelte/store";
22
+ import Sheet from "./Sheet.svelte";
23
+ import Stack from "../stack/Stack.svelte";
24
24
 
25
25
  interface Props {
26
26
  paywallData: PaywallData;
@@ -53,14 +53,18 @@
53
53
  const getColorMode = setColorModeContext(() => preferredColorMode);
54
54
  const colorMode = $derived(getColorMode());
55
55
 
56
+ const { default_locale, components_config, components_localizations } =
57
+ paywallData;
58
+ const { base } = components_config;
59
+
56
60
  const { getLocalizedString } = setLocalizationContext(() => ({
57
- defaultLocale: paywallData.default_locale,
61
+ defaultLocale: default_locale,
58
62
  selectedLocale,
59
- localizations: paywallData.components_localizations!,
63
+ localizations: components_localizations!,
60
64
  }));
61
65
 
62
66
  const selectedPackageId = writable<string | undefined>(
63
- findSelectedPackageId(paywallData),
67
+ findSelectedPackageId(base),
64
68
  );
65
69
 
66
70
  const onPurchase = () => {
@@ -70,6 +74,8 @@
70
74
  }
71
75
  };
72
76
 
77
+ let sheet = $state<SheetProps>();
78
+
73
79
  const onButtonAction = (action: Action) => {
74
80
  switch (action.type) {
75
81
  case "navigate_back":
@@ -92,10 +98,12 @@
92
98
  onNavigateToUrlClicked?.(url);
93
99
  }
94
100
  return;
95
- case "offer_code":
96
101
  case "sheet":
102
+ sheet = action.sheet ?? undefined;
103
+ return;
104
+ case "offer_code":
97
105
  case "web_paywall_link":
98
- // TODO: Implement later.
106
+ // Ignored.
99
107
  return;
100
108
  }
101
109
  };
@@ -115,43 +123,37 @@
115
123
 
116
124
  setVariablesContext(variables);
117
125
 
118
- const backgroundStyles = $derived(
119
- getBackgroundStyles({
120
- background: paywallData.components_config.base?.background,
121
- colorMode,
126
+ const style = $derived(
127
+ css({
128
+ ...mapBackground(colorMode, null, base.background),
122
129
  }),
123
130
  );
124
- const backgroundImgSource = $derived(
125
- getBackgroundImageSource(paywallData, colorMode),
126
- );
127
131
 
128
132
  onMount(() => {
129
133
  registerFonts(uiConfig);
130
134
  });
135
+
136
+ const paywallClass = $derived(sheet ? "paywall blur" : "paywall");
137
+
138
+ const { stack, sticky_footer } = base;
131
139
  </script>
132
140
 
133
141
  <svelte:boundary onerror={onError}>
134
- <div class="rc-pw-paywall">
135
- <Node nodeData={paywallData.components_config.base.stack} />
136
-
137
- {#if paywallData.components_config.base.sticky_footer}
138
- <Footer
139
- {...paywallData.components_config.base.sticky_footer}
140
- stack={paywallData.components_config.base.sticky_footer.stack}
141
- />
142
- {/if}
143
- {#if paywallData.components_config.base.background?.type === "color"}
144
- <div class="rc-pw-paywall-background" style={backgroundStyles}></div>
145
- {:else if paywallData.components_config.base.background?.type === "image"}
146
- <div class="rc-pw-paywall-background rc-pw-image-container">
147
- <img class="rc-pw-image" src={backgroundImgSource} alt="" />
148
- </div>
142
+ <div id="paywall" class={paywallClass} {style}>
143
+ <Stack {...stack} />
144
+
145
+ {#if sticky_footer}
146
+ <Footer {...sticky_footer} />
149
147
  {/if}
150
148
  </div>
149
+
150
+ {#if sheet}
151
+ <Sheet {...sheet} />
152
+ {/if}
151
153
  </svelte:boundary>
152
154
 
153
155
  <style>
154
- .rc-pw-paywall {
156
+ .paywall {
155
157
  position: relative;
156
158
  display: flex;
157
159
  flex-direction: column;
@@ -159,33 +161,22 @@
159
161
  height: 100%;
160
162
  overflow: hidden;
161
163
 
164
+ transition-property: filter transform;
165
+ transition-duration: 0.1s;
166
+ transition-timing-function: ease-in-out;
167
+ transform-origin: center;
168
+
169
+ &:global(.blur) {
170
+ filter: blur(10px) brightness(0.8);
171
+ transform: scale(1.045);
172
+ }
173
+
162
174
  & > :global(*:first-child) {
163
175
  flex-grow: 1;
164
176
  overflow-y: auto;
165
177
  }
166
178
  }
167
179
 
168
- .rc-pw-paywall-background {
169
- position: absolute;
170
- top: 0;
171
- left: 0;
172
- width: 100%;
173
- height: 100%;
174
- background: var(--paywall-background, none);
175
- z-index: -1;
176
- }
177
- .rc-pw-image-container {
178
- overflow: hidden;
179
- background: none;
180
- }
181
-
182
- .rc-pw-image {
183
- width: 100%;
184
- height: 100%;
185
- object-fit: cover;
186
- display: block;
187
- }
188
-
189
180
  :global {
190
181
  *,
191
182
  *::before,
@@ -1,5 +1,6 @@
1
- import type { PaywallData, UIConfig } from "../../data/entities";
2
1
  import type { ColorMode } from "../../types";
2
+ import type { PaywallData } from "../../types/paywall";
3
+ import type { UIConfig } from "../../types/ui-config";
3
4
  import type { VariableDictionary } from "../../types/variables";
4
5
  interface Props {
5
6
  paywallData: PaywallData;
@@ -0,0 +1,126 @@
1
+ <script lang="ts">
2
+ import { getColorModeContext } from "../../stores/color-mode";
3
+ import { getPaywallContext } from "../../stores/paywall";
4
+ import { getSelectedStateContext } from "../../stores/selected";
5
+ import type { SheetProps } from "../../types/components/sheet";
6
+ import { mapBackground } from "../../utils/background-utils";
7
+ import { css, mapSize } from "../../utils/base-utils";
8
+ import { getActiveStateProps } from "../../utils/style-utils";
9
+ import { onMount } from "svelte";
10
+ import Stack from "../stack/Stack.svelte";
11
+
12
+ const props: SheetProps = $props();
13
+ const { stack } = props;
14
+
15
+ const selectedState = getSelectedStateContext();
16
+ const { size, background, background_blur, position } = $derived.by(() => {
17
+ return {
18
+ ...props,
19
+ ...getActiveStateProps($selectedState, props.overrides),
20
+ };
21
+ });
22
+
23
+ const getColorMode = getColorModeContext();
24
+ const colorMode = $derived(getColorMode());
25
+
26
+ const backdropStyle = $derived(
27
+ css({
28
+ background: background_blur ? "#0000003f" : "",
29
+ }),
30
+ );
31
+
32
+ const sheetStyle = $derived(
33
+ css({
34
+ height: mapSize(size.height),
35
+ ...mapBackground(colorMode, null, background),
36
+ }),
37
+ );
38
+
39
+ const { onButtonAction } = getPaywallContext();
40
+
41
+ let sheet: HTMLDivElement | undefined;
42
+ let visible = $state(false);
43
+
44
+ onMount(() => {
45
+ requestAnimationFrame(() => {
46
+ visible = true;
47
+ });
48
+ });
49
+
50
+ const hideSheet = () => {
51
+ visible = false;
52
+ };
53
+
54
+ const ontransitionend = () => {
55
+ if (visible) {
56
+ return;
57
+ }
58
+
59
+ onButtonAction({
60
+ type: "navigate_to",
61
+ destination: "sheet",
62
+ sheet: null,
63
+ });
64
+ };
65
+
66
+ const onclick = (event: MouseEvent) => {
67
+ if (event.target === event.currentTarget) {
68
+ hideSheet();
69
+ }
70
+ };
71
+
72
+ const onkeydown = (event: KeyboardEvent) => {
73
+ if (event.key === "Escape") {
74
+ hideSheet();
75
+ }
76
+ };
77
+
78
+ let sheetClass = $derived(`sheet ${visible ? "visible" : ""}`);
79
+ </script>
80
+
81
+ <div
82
+ class="backdrop"
83
+ style={backdropStyle}
84
+ {onclick}
85
+ {onkeydown}
86
+ role="presentation"
87
+ tabindex="-1"
88
+ aria-hidden="true"
89
+ >
90
+ <div
91
+ bind:this={sheet}
92
+ class={sheetClass}
93
+ style={sheetStyle}
94
+ role="dialog"
95
+ aria-modal="true"
96
+ {ontransitionend}
97
+ >
98
+ <Stack {...stack} />
99
+ </div>
100
+ </div>
101
+
102
+ <style>
103
+ .backdrop {
104
+ position: absolute;
105
+ inset: 0 0 0 0;
106
+ width: 100%;
107
+ height: 100%;
108
+ background-color: #0000003f;
109
+
110
+ display: flex;
111
+ flex-direction: column;
112
+ }
113
+
114
+ .sheet {
115
+ position: absolute;
116
+ inset: auto 0 0 0;
117
+ transition-property: transform;
118
+ transition-duration: 225ms;
119
+ transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
120
+ transform: translateY(100%);
121
+
122
+ &.visible {
123
+ transform: translateY(0);
124
+ }
125
+ }
126
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { SheetProps } from "../../types/components/sheet";
2
+ declare const Sheet: import("svelte").Component<SheetProps, {}, "">;
3
+ type Sheet = ReturnType<typeof Sheet>;
4
+ export default Sheet;
@@ -0,0 +1,3 @@
1
+ import type { Background } from "../../../types/background";
2
+ import type { PaywallData } from "../../../types/paywall";
3
+ export declare const BACKGROUND_PAYWALL: (background: Background) => PaywallData;
@@ -0,0 +1,62 @@
1
+ export const BACKGROUND_PAYWALL = (background) => {
2
+ return {
3
+ default_locale: "en_US",
4
+ components_localizations: {
5
+ en_US: {},
6
+ },
7
+ components_config: {
8
+ base: {
9
+ background,
10
+ stack: {
11
+ background: null,
12
+ background_color: null,
13
+ badge: null,
14
+ border: null,
15
+ components: [],
16
+ dimension: {
17
+ alignment: "center",
18
+ distribution: "start",
19
+ type: "vertical",
20
+ },
21
+ id: "rocJhuHfiP",
22
+ margin: {
23
+ bottom: 0,
24
+ leading: 0,
25
+ top: 0,
26
+ trailing: 0,
27
+ },
28
+ name: "Content",
29
+ padding: {
30
+ bottom: 0,
31
+ leading: 0,
32
+ top: 0,
33
+ trailing: 0,
34
+ },
35
+ shadow: null,
36
+ shape: {
37
+ corners: {
38
+ bottom_leading: 0,
39
+ bottom_trailing: 0,
40
+ top_leading: 0,
41
+ top_trailing: 0,
42
+ },
43
+ type: "rectangle",
44
+ },
45
+ size: {
46
+ height: {
47
+ type: "fit",
48
+ value: null,
49
+ },
50
+ width: {
51
+ type: "fill",
52
+ value: null,
53
+ },
54
+ },
55
+ spacing: 16,
56
+ type: "stack",
57
+ },
58
+ sticky_footer: null,
59
+ },
60
+ },
61
+ };
62
+ };
@@ -1,2 +1,2 @@
1
- import type { PaywallData } from "../../../data/entities";
1
+ import type { PaywallData } from "../../../types/paywall";
2
2
  export declare const OVERRIDE_PAYWALL: PaywallData;
@@ -0,0 +1,2 @@
1
+ import type { PaywallData } from "../../../types/paywall";
2
+ export declare const SHEET_PAYWALL: PaywallData;