@revenuecat/purchases-ui-js 2.0.1 → 2.0.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 (138) hide show
  1. package/dist/components/button/ButtonNode.stories.svelte +66 -108
  2. package/dist/components/button/ButtonNode.svelte +3 -31
  3. package/dist/components/footer/Footer.stories.svelte +112 -106
  4. package/dist/components/footer/Footer.svelte +10 -6
  5. package/dist/components/icon/Icon.stories.svelte +100 -0
  6. package/dist/components/icon/Icon.stories.svelte.d.ts +19 -0
  7. package/dist/components/icon/Icon.svelte +73 -0
  8. package/dist/components/icon/Icon.svelte.d.ts +4 -0
  9. package/dist/components/image/ClipPath.svelte +49 -0
  10. package/dist/components/image/ClipPath.svelte.d.ts +9 -0
  11. package/dist/components/image/Image.stories.svelte +83 -199
  12. package/dist/components/image/Image.svelte +152 -137
  13. package/dist/components/image/Image.svelte.d.ts +1 -1
  14. package/dist/components/image/Overlay.svelte +36 -0
  15. package/dist/components/image/Overlay.svelte.d.ts +8 -0
  16. package/dist/components/package/Package.stories.svelte +12 -27
  17. package/dist/components/package/Package.svelte +10 -44
  18. package/dist/components/paywall/Node.svelte +45 -43
  19. package/dist/components/paywall/Node.svelte.d.ts +10 -12
  20. package/dist/components/paywall/Paywall.stories.svelte +36 -140
  21. package/dist/components/paywall/Paywall.svelte +38 -20
  22. package/dist/components/paywall/Paywall.svelte.d.ts +3 -2
  23. package/dist/components/paywall/fixtures/override-paywall.d.ts +2 -0
  24. package/dist/components/paywall/fixtures/override-paywall.js +1310 -0
  25. package/dist/components/paywall/fixtures/stack-paywall.d.ts +2 -0
  26. package/dist/components/paywall/fixtures/stack-paywall.js +5223 -0
  27. package/dist/components/paywall/fixtures/variables.d.ts +261 -0
  28. package/dist/components/paywall/fixtures/variables.js +262 -0
  29. package/dist/components/purchase-button/PurchaseButton.stories.svelte +10 -29
  30. package/dist/components/purchase-button/PurchaseButton.svelte +2 -34
  31. package/dist/components/stack/Stack.stories.svelte +2364 -1020
  32. package/dist/components/stack/Stack.svelte +108 -151
  33. package/dist/components/stack/Stack.svelte.d.ts +6 -2
  34. package/dist/components/stack/stack-utils.d.ts +10 -30
  35. package/dist/components/stack/stack-utils.js +77 -257
  36. package/dist/components/text/Text.svelte +3 -37
  37. package/dist/components/text/Text.svelte.d.ts +1 -2
  38. package/dist/components/text/TextNode.stories.svelte +10 -48
  39. package/dist/components/text/TextNode.svelte +25 -37
  40. package/dist/components/text/TextNode.svelte.d.ts +1 -1
  41. package/dist/components/text/text-utils.d.ts +4 -9
  42. package/dist/components/text/text-utils.js +32 -117
  43. package/dist/components/timeline/Timeline.stories.svelte +640 -256
  44. package/dist/components/timeline/Timeline.svelte +42 -30
  45. package/dist/components/timeline/Timeline.svelte.d.ts +1 -1
  46. package/dist/components/timeline/TimelineItem.svelte +80 -112
  47. package/dist/components/timeline/TimelineItem.svelte.d.ts +6 -2
  48. package/dist/components/timeline/timeline-utils.d.ts +24 -6
  49. package/dist/components/timeline/timeline-utils.js +21 -114
  50. package/dist/data/entities.d.ts +23 -169
  51. package/dist/index.d.ts +11 -10
  52. package/dist/index.js +11 -10
  53. package/dist/stores/color-mode.d.ts +1 -1
  54. package/dist/stores/localization.d.ts +1 -1
  55. package/dist/stores/localization.js +3 -2
  56. package/dist/stores/paywall.d.ts +7 -3
  57. package/dist/stores/selected.d.ts +5 -0
  58. package/dist/stores/selected.js +12 -0
  59. package/dist/stores/variables.d.ts +2 -3
  60. package/dist/stores/variables.js +0 -1
  61. package/dist/stories/component-decorator.d.ts +2 -0
  62. package/dist/stories/component-decorator.js +12 -0
  63. package/dist/stories/fixtures.d.ts +6 -4
  64. package/dist/stories/fixtures.js +6241 -5485
  65. package/dist/stories/localization-decorator.js +1 -1
  66. package/dist/stories/paywall-decorator.js +8 -1
  67. package/dist/stories/variables-decorator.d.ts +1 -1
  68. package/dist/stories/viewport-decorator.d.ts +2 -0
  69. package/dist/stories/viewport-decorator.js +8 -0
  70. package/dist/stories/viewport-wrapper.svelte +53 -0
  71. package/dist/stories/viewport-wrapper.svelte.d.ts +10 -0
  72. package/dist/stories/with-layout.d.ts +2 -10
  73. package/dist/stories/with-layout.js +3 -5
  74. package/dist/stories/with-layout.svelte +3 -3
  75. package/dist/types/alignment.d.ts +5 -3
  76. package/dist/types/background.d.ts +6 -5
  77. package/dist/types/base.d.ts +7 -0
  78. package/dist/types/colors.d.ts +4 -4
  79. package/dist/types/component.d.ts +10 -0
  80. package/dist/types/component.js +1 -0
  81. package/dist/types/components/button.d.ts +5 -2
  82. package/dist/types/components/footer.d.ts +3 -2
  83. package/dist/types/components/icon.d.ts +28 -0
  84. package/dist/types/components/icon.js +1 -0
  85. package/dist/types/components/image.d.ts +20 -0
  86. package/dist/types/components/image.js +1 -0
  87. package/dist/types/components/package.d.ts +3 -2
  88. package/dist/types/components/purchase-button.d.ts +3 -2
  89. package/dist/types/components/stack.d.ts +32 -0
  90. package/dist/types/components/stack.js +1 -0
  91. package/dist/types/components/text.d.ts +20 -0
  92. package/dist/types/components/text.js +1 -0
  93. package/dist/types/components/timeline.d.ts +35 -0
  94. package/dist/types/components/timeline.js +1 -0
  95. package/dist/types/localization.d.ts +2 -1
  96. package/dist/types/media.d.ts +4 -3
  97. package/dist/types/overrides.d.ts +48 -0
  98. package/dist/types/overrides.js +1 -0
  99. package/dist/types/variables.d.ts +13 -0
  100. package/dist/types/variables.js +10 -0
  101. package/dist/types.d.ts +17 -9
  102. package/dist/ui/atoms/typography.stories.svelte +3 -29
  103. package/dist/ui/atoms/typography.stories.svelte.d.ts +1 -1
  104. package/dist/ui/layout/main-block.svelte +2 -2
  105. package/dist/ui/molecules/button.stories.svelte +5 -10
  106. package/dist/ui/molecules/button.svelte +1 -1
  107. package/dist/ui/theme/colors.d.ts +0 -6
  108. package/dist/ui/theme/colors.js +1 -1
  109. package/dist/ui/theme/text.d.ts +3 -4
  110. package/dist/ui/theme/theme.d.ts +2 -2
  111. package/dist/ui/theme/theme.js +2 -2
  112. package/dist/ui/theme/utils.d.ts +2 -12
  113. package/dist/ui/theme/utils.js +5 -5
  114. package/dist/utils/background-utils.d.ts +4 -0
  115. package/dist/utils/background-utils.js +39 -0
  116. package/dist/utils/base-utils.d.ts +18 -0
  117. package/dist/utils/base-utils.js +124 -0
  118. package/dist/utils/constants.d.ts +2 -2
  119. package/dist/utils/constants.js +6 -1
  120. package/dist/utils/font-utils.d.ts +4 -0
  121. package/dist/utils/font-utils.js +47 -0
  122. package/dist/utils/style-utils.d.ts +7 -120
  123. package/dist/utils/style-utils.js +35 -314
  124. package/dist/utils/variable-utils.d.ts +1 -22
  125. package/dist/utils/variable-utils.js +28 -24
  126. package/dist/web-components/index.css +1 -1
  127. package/dist/web-components/index.js +1415 -987
  128. package/package.json +34 -24
  129. package/dist/components/button/button-utils.d.ts +0 -2
  130. package/dist/components/button/button-utils.js +0 -19
  131. package/dist/components/image/image-utils.d.ts +0 -19
  132. package/dist/components/image/image-utils.js +0 -33
  133. package/dist/components/purchase-button/purchase-button-utils.d.ts +0 -2
  134. package/dist/components/purchase-button/purchase-button-utils.js +0 -20
  135. package/dist/data/state.d.ts +0 -4
  136. package/dist/stories/meta-templates.d.ts +0 -12
  137. package/dist/stories/meta-templates.js +0 -155
  138. /package/dist/{data/state.js → types/base.js} +0 -0
@@ -1,164 +1,179 @@
1
1
  <script lang="ts">
2
- import { getImageComponentStyles } from "./image-utils";
3
- import type { ImageProps } from "../../data/entities";
4
2
  import { getColorModeContext } from "../../stores/color-mode";
5
- import { DEFAULT_COLOR_MODE } from "../../utils/constants";
3
+ import { getSelectedStateContext } from "../../stores/selected";
4
+ import type { ImageProps } from "../../types/components/image";
5
+ import {
6
+ css,
7
+ mapColor,
8
+ mapColorMode,
9
+ mapFitMode,
10
+ mapSize,
11
+ mapSpacing,
12
+ } from "../../utils/base-utils";
13
+ import { getActiveStateProps } from "../../utils/style-utils";
14
+ import ClipPath from "./ClipPath.svelte";
15
+ import Overlay from "./Overlay.svelte";
6
16
 
7
- const { id, source, purchaseState, ...restProps }: ImageProps = $props();
17
+ const props: ImageProps = $props();
18
+
19
+ const selectedState = getSelectedStateContext();
20
+ const {
21
+ id,
22
+ source,
23
+ size,
24
+ mask_shape,
25
+ fit_mode,
26
+ padding,
27
+ margin,
28
+ color_overlay,
29
+ border,
30
+ shadow,
31
+ } = $derived.by(() => {
32
+ return {
33
+ ...props,
34
+ ...getActiveStateProps($selectedState, props.overrides),
35
+ };
36
+ });
8
37
 
9
38
  const getColorMode = getColorModeContext();
10
39
  const colorMode = $derived(getColorMode());
40
+ const image = $derived(mapColorMode(colorMode, source));
11
41
 
12
- let imageAspectRatio = $state(0);
13
- let imageElement: HTMLImageElement | null;
42
+ let wrapperWidth = $state(0);
43
+ let imageSize = $state({
44
+ height: 0,
45
+ width: 0,
46
+ });
14
47
 
15
- // Calculate aspect ratio once image loads
16
- function onImageLoad() {
17
- if (imageElement) {
18
- imageAspectRatio = imageElement.naturalHeight / imageElement.naturalWidth;
48
+ // TODO: Not needed if width/height are set. Remove once paywall stories are fixed or removed.
49
+ $effect(() => {
50
+ if (image.width || image.height) {
51
+ imageSize = {
52
+ height: image.height,
53
+ width: image.width,
54
+ };
55
+ return;
19
56
  }
20
- }
21
57
 
22
- const { imageStyles, maskPath, linearGradientAngle } = $derived(
23
- getImageComponentStyles(colorMode, {
24
- id,
25
- source,
26
- purchaseState,
27
- ...restProps,
28
- imageAspectRatio,
58
+ const img = new window.Image();
59
+ img.src = image.original;
60
+
61
+ const onImageLoad = () => {
62
+ imageSize = {
63
+ height: img.height,
64
+ width: img.width,
65
+ };
66
+ };
67
+
68
+ img.addEventListener("load", onImageLoad);
69
+ return () => {
70
+ img.removeEventListener("load", onImageLoad);
71
+ };
72
+ });
73
+
74
+ const height = $derived.by(() => {
75
+ if (size.height.type === "fixed") {
76
+ return size.height.value;
77
+ }
78
+ return Math.round(wrapperWidth * (imageSize.height / imageSize.width));
79
+ });
80
+
81
+ const style = $derived(
82
+ css({
83
+ width: mapSize(size.width),
84
+ height: `${height}px`,
85
+ margin: mapSpacing(margin),
86
+ padding: mapSpacing(padding),
87
+ "line-height": 0,
88
+ "flex-shrink": size.width.type === "fixed" ? 0 : 1,
29
89
  }),
30
90
  );
31
91
 
32
- const imageSource = $derived.by(() => {
33
- if (source[colorMode]?.original) {
34
- return source[colorMode].original;
35
- } else {
36
- return source[DEFAULT_COLOR_MODE]?.original as string;
92
+ let svgRect = $state<DOMRect | null>(null);
93
+
94
+ const [svgWidth, svgHeight] = $derived.by(() => {
95
+ return [svgRect?.width ?? 0, svgRect?.height ?? 0];
96
+ });
97
+
98
+ const viewBox = $derived.by(() => {
99
+ return `0 0 ${svgWidth} ${svgHeight}`;
100
+ });
101
+
102
+ const svgStyle = $derived.by(() => {
103
+ if (!shadow?.color) {
104
+ return "";
37
105
  }
106
+
107
+ const { x, y, radius, color } = shadow;
108
+ const shadowColor = mapColor(colorMode, color);
109
+ return `filter: drop-shadow(${x}px ${y}px ${radius}px ${shadowColor})`;
38
110
  });
39
111
 
40
- const colorOverlay = $derived(restProps.color_overlay);
41
- const colorInfo = $derived(
42
- colorOverlay?.[colorMode] ?? colorOverlay?.[DEFAULT_COLOR_MODE],
112
+ const overlay = $derived(
113
+ color_overlay && mapColorMode(colorMode, color_overlay),
43
114
  );
44
115
  </script>
45
116
 
46
- <img
47
- src={imageSource}
48
- bind:this={imageElement}
49
- onload={onImageLoad}
50
- style="display: none;"
51
- alt=""
52
- />
53
-
54
- <svg
55
- class="rc-pw-image-container"
56
- id={`rc-pw-image-container-${id}`}
57
- style={imageStyles}
58
- preserveAspectRatio="xMidYMid slice"
59
- viewBox={`0 0 100 ${imageAspectRatio * 100}`}
60
- >
61
- <defs>
62
- <clipPath id={`clip-path-${id}`}>
63
- {#if restProps.mask_shape?.type === "circle"}
64
- <ellipse
65
- cx="50"
66
- cy={imageAspectRatio * 50}
67
- rx="50"
68
- ry={imageAspectRatio * 50}
117
+ <div {style} bind:clientWidth={wrapperWidth}>
118
+ <svg
119
+ bind:contentRect={svgRect}
120
+ width="100%"
121
+ height="100%"
122
+ {viewBox}
123
+ style={svgStyle}
124
+ >
125
+ <defs>
126
+ <clipPath id={`${id}-path`}>
127
+ <ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
128
+ </clipPath>
129
+
130
+ <g id={`${id}-border`}>
131
+ <ClipPath shape={mask_shape} width={svgWidth} height={svgHeight} />
132
+ </g>
133
+
134
+ <Overlay id={`${id}-overlay`} {overlay} />
135
+ </defs>
136
+
137
+ {#if border && border.width > 0}
138
+ <use href={`#${id}-border`} fill="transparent" />
139
+ {/if}
140
+
141
+ <g clip-path={`url(#${id}-path)`}>
142
+ <foreignObject x="0" y="0" width="100%" height="100%">
143
+ <img
144
+ src={image.original}
145
+ style="object-fit:{mapFitMode(fit_mode)}"
146
+ alt=""
147
+ />
148
+ </foreignObject>
149
+
150
+ {#if overlay}
151
+ <rect
152
+ x="0"
153
+ y="0"
154
+ height="100%"
155
+ width="100%"
156
+ fill={`url(#${id}-overlay)`}
69
157
  />
70
- {:else}
71
- <path d={maskPath} />
72
158
  {/if}
73
- </clipPath>
74
-
75
- {#if colorInfo?.type === "linear"}
76
- <linearGradient
77
- id={`gradient-${id}`}
78
- x1={linearGradientAngle.x1}
79
- y1={linearGradientAngle.y1}
80
- x2={linearGradientAngle.x2}
81
- y2={linearGradientAngle.y2}
82
- >
83
- {#each colorInfo?.points || [] as stop}
84
- <stop
85
- offset={`${stop.percent}%`}
86
- style={`stop-color: ${stop.color}`}
87
- />
88
- {/each}
89
- </linearGradient>
90
- {:else if colorInfo?.type === "radial"}
91
- <radialGradient
92
- id={`gradient-${id}`}
93
- cx="50%"
94
- cy="50%"
95
- r="50%"
96
- fx="50%"
97
- fy="50%"
98
- >
99
- {#each colorInfo?.points || [] as stop}
100
- <stop
101
- offset={`${stop.percent}%`}
102
- style={`stop-color: ${stop.color}`}
103
- />
104
- {/each}
105
- </radialGradient>
106
- {:else if colorInfo?.type === "hex"}
107
- <linearGradient id={`gradient-${id}`}>
108
- <stop offset="0%" style={`stop-color: ${colorInfo?.value}`} />
109
- </linearGradient>
110
- {/if}
111
- </defs>
112
-
113
- <image
114
- class="rc-pw-image"
115
- href={imageSource}
116
- x="0"
117
- y="0"
118
- width="100"
119
- height={imageAspectRatio * 100}
120
- clip-path={`url(#clip-path-${id})`}
121
- preserveAspectRatio="xMidYMid slice"
122
- {id}
123
- />
124
-
125
- <rect
126
- class="rc-pw-image-overlay"
127
- x="0"
128
- y="0"
129
- width="100"
130
- height={imageAspectRatio * 100}
131
- clip-path={`url(#clip-path-${id})`}
132
- fill={`url(#gradient-${id})`}
133
- />
134
- </svg>
135
159
 
136
- <style>
137
- .rc-pw-image-container {
138
- border-end-start-radius: var(--image-border-end-start-radius, 0px);
139
- border-end-end-radius: var(--image-border-end-end-radius, 0px);
140
- border-start-start-radius: var(--image-border-start-start-radius, 0px);
141
- border-start-end-radius: var(--image-border-start-end-radius, 0px);
142
- position: relative;
143
- overflow: hidden;
144
- display: flex;
145
- flex: var(--image-flex, 1 1 auto);
146
- position: var(--image-position, relative);
147
- inset: var(--image-inset, 0);
148
- transform: var(--image-transform, initial);
149
- height: var(--image-height, initial);
150
- width: var(--image-width, initial);
151
- }
160
+ {#if border && border.width > 0}
161
+ <use
162
+ href={`#${id}-border`}
163
+ fill="none"
164
+ stroke={mapColor(colorMode, border.color)}
165
+ stroke-width={border.width}
166
+ />
167
+ {/if}
168
+ </g>
169
+ </svg>
170
+ </div>
152
171
 
153
- .rc-pw-image {
172
+ <style>
173
+ img {
154
174
  width: 100%;
155
175
  height: 100%;
156
- object-fit: cover;
157
- display: block;
158
- }
159
-
160
- .rc-pw-image-overlay {
161
- position: absolute;
162
- inset: 0;
176
+ object-fit: contain;
177
+ object-position: center;
163
178
  }
164
179
  </style>
@@ -1,4 +1,4 @@
1
- import type { ImageProps } from "../../data/entities";
1
+ import type { ImageProps } from "../../types/components/image";
2
2
  declare const Image: import("svelte").Component<ImageProps, {}, "">;
3
3
  type Image = ReturnType<typeof Image>;
4
4
  export default Image;
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import type { ColorGradientInfo } from "../../types/colors";
3
+
4
+ interface OverlayProps {
5
+ id: string;
6
+ overlay: ColorGradientInfo | null | undefined;
7
+ }
8
+
9
+ const { id, overlay }: OverlayProps = $props();
10
+ </script>
11
+
12
+ {#if overlay?.type === "hex"}
13
+ <linearGradient {id} x1="0" y1="0" x2="100%" y2="100%">
14
+ <stop offset="0%" stop-color={overlay.value} />
15
+ <stop offset="100%" stop-color={overlay.value} />
16
+ </linearGradient>
17
+ {/if}
18
+
19
+ {#if overlay?.type === "linear"}
20
+ <linearGradient
21
+ {id}
22
+ gradientTransform={`rotate(${overlay.degrees - 90}, 0.5, 0.5)`}
23
+ >
24
+ {#each overlay.points as point}
25
+ <stop offset={`${point.percent}%`} stop-color={point.color} />
26
+ {/each}
27
+ </linearGradient>
28
+ {/if}
29
+
30
+ {#if overlay?.type === "radial"}
31
+ <radialGradient {id}>
32
+ {#each overlay.points as point}
33
+ <stop offset={`${point.percent}%`} stop-color={point.color} />
34
+ {/each}
35
+ </radialGradient>
36
+ {/if}
@@ -0,0 +1,8 @@
1
+ import type { ColorGradientInfo } from "../../types/colors";
2
+ interface OverlayProps {
3
+ id: string;
4
+ overlay: ColorGradientInfo | null | undefined;
5
+ }
6
+ declare const Overlay: import("svelte").Component<OverlayProps, {}, "">;
7
+ type Overlay = ReturnType<typeof Overlay>;
8
+ export default Overlay;
@@ -1,19 +1,19 @@
1
1
  <script module lang="ts">
2
2
  import Package from "./Package.svelte";
3
- import type { PurchaseState } from "../../data/state";
3
+ import { componentDecorator } from "../../stories/component-decorator";
4
4
  import { localizationDecorator } from "../../stories/localization-decorator";
5
+ import type { PackageProps } from "../../types/components/package";
5
6
  import { defineMeta } from "@storybook/addon-svelte-csf";
6
7
 
7
8
  const defaultLocale = "en_US";
8
9
  const priceLid = "QZ4ZmYsqjN";
9
10
  const nameLid = "BcX-6YwhoV";
10
- const purchaseState: PurchaseState = {};
11
11
 
12
12
  const { Story } = defineMeta({
13
13
  title: "Components/Package",
14
14
  component: Package,
15
- tags: ["autodocs"],
16
15
  decorators: [
16
+ componentDecorator(),
17
17
  localizationDecorator({
18
18
  defaultLocale,
19
19
  localizations: {
@@ -24,32 +24,21 @@
24
24
  },
25
25
  }),
26
26
  ],
27
- args: { purchaseState },
28
- argTypes: {
29
- stack: {
30
- control: { type: "object" },
31
- description: "Stack configuration for package content",
32
- table: {
33
- type: {
34
- summary: "object",
35
- detail: "StackProps",
36
- },
37
- },
38
- },
39
- },
40
27
  });
41
28
  </script>
42
29
 
43
- <!-- Default -->
44
30
  <Story
45
31
  name="Default Package"
46
32
  args={{
47
- id: "6rQSD5e2Kz",
48
- is_selected_by_default: false,
33
+ type: "package",
34
+ id: "package",
49
35
  name: "Package - Monthly",
50
36
  package_id: "$rc_monthly",
37
+ is_selected_by_default: true,
51
38
  stack: {
52
- purchaseState,
39
+ type: "stack",
40
+ id: "stack",
41
+ name: "Stack",
53
42
  background_color: {
54
43
  light: {
55
44
  type: "hex",
@@ -83,7 +72,6 @@
83
72
  value: "#ffffff",
84
73
  },
85
74
  },
86
- components: [],
87
75
  font_name: null,
88
76
  font_size: "heading_s",
89
77
  font_weight: "bold",
@@ -122,6 +110,8 @@
122
110
  value: "#292631",
123
111
  },
124
112
  },
113
+ background: null,
114
+ shadow: null,
125
115
  border: null,
126
116
  components: [
127
117
  {
@@ -132,7 +122,6 @@
132
122
  value: "#ffffff",
133
123
  },
134
124
  },
135
- components: [],
136
125
  font_name: null,
137
126
  font_size: "body_m",
138
127
  font_weight: "extra_bold",
@@ -212,14 +201,12 @@
212
201
  distribution: "space_between",
213
202
  type: "horizontal",
214
203
  },
215
- id: "u0KZLUZTQT",
216
204
  margin: {
217
205
  bottom: 0,
218
206
  leading: 16,
219
207
  top: 16,
220
208
  trailing: 16,
221
209
  },
222
- name: "Stack",
223
210
  padding: {
224
211
  bottom: 16,
225
212
  leading: 16,
@@ -245,9 +232,7 @@
245
232
  },
246
233
  },
247
234
  spacing: 8,
248
- type: "stack",
249
235
  shadow: null,
250
236
  },
251
- type: "package",
252
- }}
237
+ } satisfies PackageProps}
253
238
  />
@@ -1,64 +1,30 @@
1
1
  <script lang="ts">
2
2
  import Stack from "../stack/Stack.svelte";
3
3
  import { getPaywallContext } from "../../stores/paywall";
4
+ import { setSelectedStateContext } from "../../stores/selected";
4
5
  import {
5
6
  getVariablesContext,
6
7
  setVariablesContext,
7
8
  } from "../../stores/variables";
8
9
  import type { PackageProps } from "../../types/components/package";
9
- import { prefixObject, stringifyStyles } from "../../utils/style-utils";
10
10
  import { derived } from "svelte/store";
11
11
 
12
- const {
13
- stack,
14
- package_id,
15
- labels,
16
- id,
17
- purchaseState,
18
- zStackChildStyles,
19
- }: PackageProps = $props();
12
+ const { stack, package_id }: PackageProps = $props();
20
13
 
21
- const { selectedPackageId } = getPaywallContext();
14
+ const { selectedPackageId, variablesPerPackage } = getPaywallContext();
22
15
 
23
- const onPackageClick = () => ($selectedPackageId = package_id);
16
+ setSelectedStateContext(package_id);
17
+
18
+ const onPackageClick = () => {
19
+ $selectedPackageId = package_id;
20
+ };
24
21
 
25
22
  const fallbackVariables = getVariablesContext();
26
23
  const variables = derived(
27
24
  fallbackVariables,
28
- (fallback) => purchaseState.variablesPerPackage?.[package_id] ?? fallback,
25
+ (fallback) => $variablesPerPackage?.[package_id] ?? fallback,
29
26
  );
30
27
  setVariablesContext(variables);
31
-
32
- const componentState = $derived({
33
- selected: $selectedPackageId === package_id,
34
- });
35
-
36
- const styles = $derived(
37
- stringifyStyles(prefixObject(zStackChildStyles, "package")),
38
- );
39
28
  </script>
40
29
 
41
- <button
42
- class="rc-pw-package"
43
- class:selected={componentState.selected}
44
- {id}
45
- onclick={onPackageClick}
46
- style={styles}
47
- >
48
- <Stack {...stack} {labels} {purchaseState} {componentState} />
49
- </button>
50
-
51
- <style>
52
- .rc-pw-package {
53
- width: 100%;
54
- display: flex;
55
- margin: 0;
56
- padding: 0;
57
- background: initial;
58
- border: initial;
59
- text-align: initial;
60
- position: var(--package-position, relative);
61
- inset: var(--package-inset, 0);
62
- transform: var(--package-transform, initial);
63
- }
64
- </style>
30
+ <Stack {...stack} onclick={onPackageClick} />
@@ -8,41 +8,41 @@
8
8
  Timeline,
9
9
  } from "../..";
10
10
  import ButtonNode from "../button/ButtonNode.svelte";
11
- import type { ZStackChildStyles } from "../stack/stack-utils";
12
11
  import TextNode from "../text/TextNode.svelte";
13
- import {
14
- type ComponentState,
15
- type PaywallComponent,
16
- type PurchaseStateProps,
17
- } from "../../data/entities";
18
- import type { Component } from "svelte";
12
+ import type { Component } from "../../types/component";
13
+ import type { Component as SvelteComponent } from "svelte";
14
+ import Icon from "../icon/Icon.svelte";
19
15
  import Self from "./Node.svelte";
20
16
 
21
17
  type SupportedComponents =
22
- | TextNode
23
- | Stack
24
- | Image
25
18
  | ButtonNode
26
- | PurchaseButton
27
- | Package
28
19
  | Footer
20
+ | Icon
21
+ | Image
22
+ | Package
23
+ | PurchaseButton
24
+ | Stack
25
+ | TextNode
29
26
  | Timeline;
30
27
 
31
- interface Props extends PurchaseStateProps {
32
- nodeData: PaywallComponent;
33
- zStackChildStyles?: ZStackChildStyles;
34
- componentState?: ComponentState;
28
+ interface Props {
29
+ nodeData: Component;
35
30
  }
36
31
 
37
32
  const ComponentTypes = {
38
- stack: Stack,
39
- text: TextNode,
40
- image: Image,
41
33
  button: ButtonNode,
42
- purchase_button: PurchaseButton,
43
- package: Package,
44
34
  footer: Footer,
35
+ icon: Icon,
36
+ image: Image,
37
+ package: Package,
38
+ purchase_button: PurchaseButton,
39
+ stack: Stack,
40
+ text: TextNode,
45
41
  timeline: Timeline,
42
+ } satisfies {
43
+ [key in Component["type"]]: SvelteComponent<
44
+ Extract<Component, { type: key }>
45
+ >;
46
46
  };
47
47
 
48
48
  /**
@@ -50,18 +50,18 @@
50
50
  * It first checks if the component type is supported and returns the corresponding component class.
51
51
  * If not supported, it checks if the fallback component type is supported and returns the corresponding component class,
52
52
  * finally it throws an error if the component type is not supported and the fallback component type is not supported.
53
- * @param nodeData:PaywallComponent - the PaywallComponent object representing a Node in the paywall
54
- * @returns [Component<SupportedComponents>, PaywallComponent] - a tuple containing the component class and the node data
53
+ * @param nodeData:Component - the Component object representing a Node in the paywall
54
+ * @returns [Component<SupportedComponents>, Component] - a tuple containing the component class and the node data
55
55
  * @throws Error - if the component type and the fallback component type are not supported
56
56
  */
57
57
  export const getComponentClass: (
58
- nodeData: PaywallComponent,
59
- ) => [Component<SupportedComponents>, PaywallComponent] = (
60
- nodeData: PaywallComponent,
58
+ nodeData: Component,
59
+ ) => [SvelteComponent<SupportedComponents>, Component] | undefined = (
60
+ nodeData: Component,
61
61
  ) => {
62
62
  if (ComponentTypes[nodeData.type]) {
63
63
  return [
64
- ComponentTypes[nodeData.type] as Component<SupportedComponents>,
64
+ ComponentTypes[nodeData.type] as SvelteComponent<SupportedComponents>,
65
65
  nodeData,
66
66
  ];
67
67
  }
@@ -69,29 +69,31 @@
69
69
  const { fallback } = nodeData;
70
70
  if (fallback && ComponentTypes[fallback?.type]) {
71
71
  return [
72
- ComponentTypes[fallback.type] as Component<SupportedComponents>,
72
+ ComponentTypes[fallback.type] as SvelteComponent<SupportedComponents>,
73
73
  fallback,
74
74
  ];
75
75
  }
76
76
 
77
- // manually throwing error for this specific case until
77
+ // Manually throwing error for this specific case until
78
78
  // it's handled with fallback components
79
- throw new Error(`Invalid component type: ${nodeData.type}`);
79
+ // throw new Error(`Invalid component type: ${nodeData.type}`);
80
80
  };
81
81
 
82
- const { nodeData, purchaseState, zStackChildStyles, ...restProps }: Props =
83
- $props();
82
+ const { nodeData, ...restProps }: Props = $props();
83
+
84
+ const [ComponentToRender, dataToUse] = $derived(
85
+ getComponentClass(nodeData) ?? [],
86
+ );
84
87
 
85
- const [ComponentToRender, dataToUse] = $derived(getComponentClass(nodeData));
88
+ const components = $derived(
89
+ ("components" in nodeData ? nodeData.components : undefined) ?? [],
90
+ );
86
91
  </script>
87
92
 
88
- <ComponentToRender
89
- {...(dataToUse as any) || {}}
90
- {purchaseState}
91
- {zStackChildStyles}
92
- {...restProps}
93
- >
94
- {#each nodeData.components as PaywallComponent[] as childData}
95
- <Self nodeData={childData} {purchaseState} {...restProps} />
96
- {/each}
97
- </ComponentToRender>
93
+ {#if ComponentToRender}
94
+ <ComponentToRender {...(dataToUse as any) || {}} {...restProps}>
95
+ {#each components as childData}
96
+ <Self nodeData={childData} {...restProps} />
97
+ {/each}
98
+ </ComponentToRender>
99
+ {/if}