@revenuecat/purchases-ui-js 0.0.17 → 0.0.18
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.
- package/dist/components/button/Button.svelte +0 -13
- package/dist/components/button/ButtonNode.stories.svelte +16 -9
- package/dist/components/button/ButtonNode.svelte +26 -1
- package/dist/components/button/button-utils.d.ts +2 -0
- package/dist/components/button/button-utils.js +19 -0
- package/dist/components/footer/Footer.stories.svelte +2 -0
- package/dist/components/footer/Footer.svelte +5 -5
- package/dist/components/image/Image.stories.svelte +6 -2
- package/dist/components/image/Image.svelte +20 -17
- package/dist/components/image/image-utils.d.ts +2 -12
- package/dist/components/image/image-utils.js +27 -10
- package/dist/components/package/Package.stories.svelte +5 -3
- package/dist/components/package/Package.svelte +15 -6
- package/dist/components/paywall/Node.svelte +72 -19
- package/dist/components/paywall/Node.svelte.d.ts +18 -1
- package/dist/components/paywall/Paywall.stories.svelte +14 -0
- package/dist/components/paywall/Paywall.svelte +73 -70
- package/dist/components/paywall/paywall-utils.d.ts +1 -1
- package/dist/components/paywall/paywall-utils.js +11 -9
- package/dist/components/purchase-button/PurchaseButton.stories.svelte +7 -6
- package/dist/components/purchase-button/PurchaseButton.svelte +24 -10
- package/dist/components/purchase-button/purchase-button-utils.d.ts +2 -0
- package/dist/components/purchase-button/purchase-button-utils.js +20 -0
- package/dist/components/stack/Stack.stories.svelte +1138 -4
- package/dist/components/stack/Stack.svelte +160 -45
- package/dist/components/stack/stack-utils.d.ts +24 -24
- package/dist/components/stack/stack-utils.js +244 -11
- package/dist/components/text/Text.svelte +24 -19
- package/dist/components/text/TextNode.stories.svelte +12 -11
- package/dist/components/text/TextNode.svelte +21 -24
- package/dist/components/text/text-utils.d.ts +9 -15
- package/dist/components/text/text-utils.js +121 -6
- package/dist/components/timeline/Timeline.svelte +10 -10
- package/dist/components/timeline/TimelineItem.svelte +45 -33
- package/dist/components/timeline/timeline-utils.d.ts +3 -20
- package/dist/components/timeline/timeline-utils.js +46 -11
- package/dist/data/entities.d.ts +33 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/stories/fixtures.d.ts +2 -0
- package/dist/stories/fixtures.js +5346 -1412
- package/dist/types.d.ts +4 -3
- package/dist/utils/style-utils.d.ts +66 -59
- package/dist/utils/style-utils.js +114 -96
- package/dist/utils/variable-utils.d.ts +27 -0
- package/dist/utils/variable-utils.js +37 -0
- package/package.json +3 -2
- package/dist/components/paywall/global-styles.css +0 -9
|
@@ -18,16 +18,3 @@
|
|
|
18
18
|
<button onclick={handleClick} class={clz} disabled={!onclick} {style}>
|
|
19
19
|
{@render children?.()}
|
|
20
20
|
</button>
|
|
21
|
-
|
|
22
|
-
<style>
|
|
23
|
-
button {
|
|
24
|
-
border: none;
|
|
25
|
-
cursor: pointer;
|
|
26
|
-
background: transparent;
|
|
27
|
-
padding: 0;
|
|
28
|
-
width: 100%;
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
justify-content: center;
|
|
32
|
-
}
|
|
33
|
-
</style>
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
3
|
import ButtonNode from "./ButtonNode.svelte";
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ComponentTypes,
|
|
6
|
+
StackProps,
|
|
7
|
+
SupportedActions,
|
|
8
|
+
} from "../../data/entities";
|
|
9
|
+
import type { PurchaseState } from "../../data/state";
|
|
10
|
+
import type { ColorMode } from "../../types";
|
|
5
11
|
|
|
6
12
|
const onAction = (action: SupportedActions) => {
|
|
7
13
|
alert(action.type);
|
|
@@ -42,10 +48,10 @@
|
|
|
42
48
|
},
|
|
43
49
|
});
|
|
44
50
|
|
|
45
|
-
const purchaseState = {
|
|
51
|
+
const purchaseState: PurchaseState = {
|
|
46
52
|
locale: "en_US",
|
|
47
53
|
defaultLocale: "en_US",
|
|
48
|
-
colorMode: "light",
|
|
54
|
+
colorMode: "light" as ColorMode,
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
export const labelsData = {
|
|
@@ -58,7 +64,7 @@
|
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
const textProps = (id: number) => ({
|
|
61
|
-
type: "text",
|
|
67
|
+
type: "text" as ComponentTypes,
|
|
62
68
|
name: "Button Text",
|
|
63
69
|
components: [],
|
|
64
70
|
id: "button-text-1",
|
|
@@ -83,7 +89,7 @@
|
|
|
83
89
|
},
|
|
84
90
|
});
|
|
85
91
|
|
|
86
|
-
const baseStackProps = {
|
|
92
|
+
const baseStackProps: Partial<StackProps> = {
|
|
87
93
|
type: "stack",
|
|
88
94
|
size: { width: { type: "fill" }, height: { type: "fill" } },
|
|
89
95
|
labels: labelsData,
|
|
@@ -116,7 +122,8 @@
|
|
|
116
122
|
stack: {
|
|
117
123
|
...baseStackProps,
|
|
118
124
|
components: [textProps(1)],
|
|
119
|
-
|
|
125
|
+
purchaseState,
|
|
126
|
+
} as StackProps,
|
|
120
127
|
purchaseState: purchaseState,
|
|
121
128
|
onAction,
|
|
122
129
|
}}
|
|
@@ -146,7 +153,7 @@
|
|
|
146
153
|
light: { type: "hex", value: "#2E7D32" },
|
|
147
154
|
},
|
|
148
155
|
components: [textProps(2)],
|
|
149
|
-
},
|
|
156
|
+
} as StackProps,
|
|
150
157
|
purchaseState: purchaseState,
|
|
151
158
|
}}
|
|
152
159
|
/>
|
|
@@ -178,7 +185,7 @@
|
|
|
178
185
|
light: { type: "hex", value: "#D32F2F" },
|
|
179
186
|
},
|
|
180
187
|
components: [textProps(3)],
|
|
181
|
-
},
|
|
188
|
+
} as StackProps,
|
|
182
189
|
purchaseState: purchaseState,
|
|
183
190
|
}}
|
|
184
191
|
/>
|
|
@@ -205,7 +212,7 @@
|
|
|
205
212
|
light: { type: "hex", value: "#4A90E2" },
|
|
206
213
|
},
|
|
207
214
|
components: [textProps(4)],
|
|
208
|
-
},
|
|
215
|
+
} as StackProps,
|
|
209
216
|
purchaseState: purchaseState,
|
|
210
217
|
}}
|
|
211
218
|
/>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import Button from "./Button.svelte";
|
|
3
3
|
import type { ButtonNodeProps } from "../../data/entities";
|
|
4
4
|
import Stack from "../stack/Stack.svelte";
|
|
5
|
+
import { getButtonStyles } from "./button-utils";
|
|
5
6
|
|
|
6
7
|
const {
|
|
7
8
|
stack,
|
|
@@ -10,12 +11,36 @@
|
|
|
10
11
|
labels,
|
|
11
12
|
purchaseState,
|
|
12
13
|
variableDictionary,
|
|
14
|
+
...restProps
|
|
13
15
|
}: ButtonNodeProps = $props();
|
|
14
16
|
const onClick = () => {
|
|
15
17
|
onAction && onAction(action);
|
|
16
18
|
};
|
|
19
|
+
|
|
20
|
+
const buttonStyles = $derived(
|
|
21
|
+
getButtonStyles({
|
|
22
|
+
stack,
|
|
23
|
+
action,
|
|
24
|
+
onAction,
|
|
25
|
+
labels,
|
|
26
|
+
purchaseState,
|
|
27
|
+
variableDictionary,
|
|
28
|
+
...restProps,
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
17
31
|
</script>
|
|
18
32
|
|
|
19
|
-
<Button onclick={onClick}>
|
|
33
|
+
<Button onclick={onClick} style={buttonStyles} class={"rc-pw-button"}>
|
|
20
34
|
<Stack {...stack} {labels} {purchaseState} {variableDictionary} />
|
|
21
35
|
</Button>
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
.rc-pw-button {
|
|
39
|
+
display: flex;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0;
|
|
42
|
+
background: initial;
|
|
43
|
+
border: initial;
|
|
44
|
+
text-align: initial;
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { prefixObject, stringifyStyles } from "../../utils/style-utils";
|
|
2
|
+
export function getButtonStyles({ stack, zStackChildStyles }) {
|
|
3
|
+
// Get the width of the inner stack to adjust to the outer button wrapper
|
|
4
|
+
const width = stack?.size?.width?.type === "fill" ? "100%" : "fit-content";
|
|
5
|
+
// Define set of variables to be assigned to the button
|
|
6
|
+
// Define width as an inline style
|
|
7
|
+
const prefixedObject = prefixObject(zStackChildStyles || {}, "button");
|
|
8
|
+
const assignedVariables = {
|
|
9
|
+
position: "var(--button-position, relative)",
|
|
10
|
+
inset: "var(--button-inset, 0)",
|
|
11
|
+
transform: "var(--button-transform, initial)",
|
|
12
|
+
width,
|
|
13
|
+
};
|
|
14
|
+
const buttonInlineStyles = stringifyStyles({
|
|
15
|
+
...prefixedObject,
|
|
16
|
+
...assignedVariables,
|
|
17
|
+
});
|
|
18
|
+
return buttonInlineStyles;
|
|
19
|
+
}
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
$props();
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
|
-
<div class="footer" {id}>
|
|
9
|
+
<div class="rc-pw-footer" {id}>
|
|
10
10
|
<Stack {...stack} {labels} {purchaseState} {variableDictionary} />
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
13
|
<style>
|
|
14
|
-
.footer {
|
|
15
|
-
position:
|
|
14
|
+
.rc-pw-footer {
|
|
15
|
+
position: sticky;
|
|
16
16
|
bottom: 0;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
transform: translateY(50%);
|
|
18
|
+
width: 100%;
|
|
19
19
|
}
|
|
20
20
|
</style>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
3
|
import Image from "./Image.svelte";
|
|
4
|
+
import type { PurchaseState } from "../../data/state";
|
|
5
|
+
import type { ColorMode } from "../../types";
|
|
4
6
|
|
|
5
|
-
const purchaseState = {
|
|
6
|
-
colorMode: "light",
|
|
7
|
+
const purchaseState: PurchaseState = {
|
|
8
|
+
colorMode: "light" as ColorMode,
|
|
9
|
+
locale: "en_US",
|
|
10
|
+
defaultLocale: "en_US",
|
|
7
11
|
};
|
|
8
12
|
|
|
9
13
|
const { Story } = defineMeta({
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getImageComponentStyles } from "./image-utils";
|
|
3
|
-
import { stringifyStyles } from "../../utils/style-utils";
|
|
4
3
|
import type { ImageProps } from "../../data/entities";
|
|
5
4
|
|
|
6
5
|
const { id, source, purchaseState, ...restProps }: ImageProps = $props();
|
|
@@ -14,8 +13,6 @@
|
|
|
14
13
|
...restProps,
|
|
15
14
|
}),
|
|
16
15
|
);
|
|
17
|
-
const gradientStylesString = $derived(stringifyStyles(gradientStyles));
|
|
18
|
-
const imageStylesString = $derived(stringifyStyles(imageStyles));
|
|
19
16
|
|
|
20
17
|
const imageSource = $derived.by(() => {
|
|
21
18
|
const colorMode = purchaseState.colorMode;
|
|
@@ -28,36 +25,42 @@
|
|
|
28
25
|
</script>
|
|
29
26
|
|
|
30
27
|
<div
|
|
31
|
-
class="image-container"
|
|
32
|
-
id={`image-container-${id}`}
|
|
33
|
-
style={
|
|
28
|
+
class="rc-pw-image-container"
|
|
29
|
+
id={`rc-pw-image-container-${id}`}
|
|
30
|
+
style={imageStyles}
|
|
34
31
|
>
|
|
35
|
-
<img class="image" src={imageSource} alt="" {id} />
|
|
36
|
-
<span class="image-overlay" style={
|
|
32
|
+
<img class="rc-pw-image" src={imageSource} alt="" {id} />
|
|
33
|
+
<span class="rc-pw-image-overlay" style={gradientStyles}></span>
|
|
37
34
|
</div>
|
|
38
35
|
|
|
39
36
|
<style>
|
|
40
|
-
.image-container {
|
|
37
|
+
.rc-pw-image-container {
|
|
41
38
|
position: relative;
|
|
42
|
-
height: var(--height, unset);
|
|
43
|
-
width: var(--width, unset);
|
|
44
39
|
overflow: hidden;
|
|
45
|
-
border-radius: var(--
|
|
46
|
-
|
|
40
|
+
border-end-start-radius: var(--image-border-end-start-radius, 0px);
|
|
41
|
+
border-end-end-radius: var(--image-border-end-end-radius, 0px);
|
|
42
|
+
border-start-start-radius: var(--image-border-start-start-radius, 0px);
|
|
43
|
+
border-start-end-radius: var(--image-border-start-end-radius, 0px);
|
|
44
|
+
clip-path: var(--image-clip-path, initial);
|
|
47
45
|
display: flex;
|
|
48
|
-
flex: var(--flex, 1 1 auto);
|
|
46
|
+
flex: var(--image-flex, 1 1 auto);
|
|
47
|
+
position: var(--image-position, relative);
|
|
48
|
+
inset: var(--image-inset, 0);
|
|
49
|
+
transform: var(--image-transform, initial);
|
|
50
|
+
height: var(--image-height, initial);
|
|
51
|
+
width: var(--image-width, initial);
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
.image {
|
|
54
|
+
.rc-pw-image {
|
|
52
55
|
width: 100%;
|
|
53
56
|
height: 100%;
|
|
54
57
|
object-fit: cover;
|
|
55
58
|
display: block;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
.image-overlay {
|
|
61
|
+
.rc-pw-image-overlay {
|
|
59
62
|
position: absolute;
|
|
60
63
|
inset: 0;
|
|
61
|
-
background: var(--background, none);
|
|
64
|
+
background: var(--image-background, none);
|
|
62
65
|
}
|
|
63
66
|
</style>
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import type { ImageProps } from "../../data/entities";
|
|
2
|
-
type ImageStyleVariables = {
|
|
3
|
-
"--height": string;
|
|
4
|
-
"--width": string;
|
|
5
|
-
"--clip-path": string;
|
|
6
|
-
"--corner-radius": string;
|
|
7
|
-
};
|
|
8
|
-
type GradientStyleVariables = {
|
|
9
|
-
"--background": string;
|
|
10
|
-
};
|
|
11
2
|
/**
|
|
12
3
|
* Generates comprehensive styles for image components by combining gradient and size styles
|
|
13
4
|
* @param props - Image component properties including gradient, mask and size
|
|
14
5
|
* @returns Object containing image style variables and gradient style variables
|
|
15
6
|
*/
|
|
16
7
|
export declare const getImageComponentStyles: (props: ImageProps) => {
|
|
17
|
-
imageStyles:
|
|
18
|
-
gradientStyles:
|
|
8
|
+
imageStyles: string;
|
|
9
|
+
gradientStyles: string;
|
|
19
10
|
};
|
|
20
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getActiveStateProps, getGradientStyle, getMaskStyle, getSizeStyle, } from "../../utils/style-utils";
|
|
1
|
+
import { getActiveStateProps, getGradientStyle, getMaskStyle, getSizeStyle, prefixObject, stringifyStyles, } from "../../utils/style-utils";
|
|
2
2
|
/**
|
|
3
3
|
* Generates comprehensive styles for image components by combining gradient and size styles
|
|
4
4
|
* @param props - Image component properties including gradient, mask and size
|
|
@@ -8,17 +8,34 @@ export const getImageComponentStyles = (props) => {
|
|
|
8
8
|
const { gradient_colors, mask_shape, size,
|
|
9
9
|
// max_height, // TODO: implement this. still waiting on spec
|
|
10
10
|
// override_source_lid, // TODO: Implement this once structure is defined
|
|
11
|
-
overrides, componentState, purchaseState, } = props;
|
|
11
|
+
overrides, componentState, purchaseState, zStackChildStyles, } = props;
|
|
12
|
+
const imageStyles = {
|
|
13
|
+
"--height": "unset",
|
|
14
|
+
"--width": "unset",
|
|
15
|
+
"--clip-path": "none",
|
|
16
|
+
"--border-end-start-radius": "unset",
|
|
17
|
+
"--border-end-end-radius": "unset",
|
|
18
|
+
"--border-start-start-radius": "unset",
|
|
19
|
+
"--border-start-end-radius": "unset",
|
|
20
|
+
"--position": "relative",
|
|
21
|
+
"--inset": "0",
|
|
22
|
+
"--transform": "initial",
|
|
23
|
+
};
|
|
24
|
+
Object.assign(imageStyles, zStackChildStyles);
|
|
25
|
+
const backgroundStyles = {
|
|
26
|
+
"--background": "none",
|
|
27
|
+
};
|
|
12
28
|
const activeStateProps = getActiveStateProps(overrides, componentState);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
Object.assign(backgroundStyles, getGradientStyle(purchaseState.colorMode, activeStateProps?.gradient_colors || gradient_colors));
|
|
30
|
+
Object.assign(imageStyles, getSizeStyle({ ...size, ...activeStateProps }));
|
|
31
|
+
Object.assign(imageStyles, getMaskStyle({
|
|
16
32
|
...mask_shape,
|
|
17
33
|
...activeStateProps,
|
|
18
|
-
});
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
}));
|
|
35
|
+
const prefixedImageStyles = prefixObject(imageStyles, "image");
|
|
36
|
+
const prefixedGradientStyles = prefixObject(backgroundStyles, "image");
|
|
37
|
+
return {
|
|
38
|
+
imageStyles: stringifyStyles(prefixedImageStyles),
|
|
39
|
+
gradientStyles: stringifyStyles(prefixedGradientStyles),
|
|
22
40
|
};
|
|
23
|
-
return { imageStyles: imageStylesObject, gradientStyles };
|
|
24
41
|
};
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
3
|
import Package from "./Package.svelte";
|
|
4
4
|
import type { Extra, SupportedActions } from "../../data/entities";
|
|
5
|
+
import type { PurchaseState } from "../../data/state";
|
|
6
|
+
import type { ColorMode } from "../../types";
|
|
5
7
|
|
|
6
|
-
const onAction = (action: SupportedActions, data
|
|
8
|
+
const onAction = (action: SupportedActions, data?: Extra) => {
|
|
7
9
|
alert(`${action.type} ${JSON.stringify(data)}`);
|
|
8
10
|
};
|
|
9
11
|
|
|
@@ -31,7 +33,8 @@
|
|
|
31
33
|
QZ4ZmYsqjN: "$1.99",
|
|
32
34
|
},
|
|
33
35
|
};
|
|
34
|
-
const purchaseState = {
|
|
36
|
+
const purchaseState: PurchaseState = {
|
|
37
|
+
colorMode: "light" as ColorMode,
|
|
35
38
|
locale: "en_US",
|
|
36
39
|
defaultLocale: "en_US",
|
|
37
40
|
};
|
|
@@ -230,7 +233,6 @@
|
|
|
230
233
|
size: {
|
|
231
234
|
height: {
|
|
232
235
|
type: "fit",
|
|
233
|
-
value: null,
|
|
234
236
|
},
|
|
235
237
|
width: {
|
|
236
238
|
type: "fixed",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { PackageProps, SelectPackageAction } from "../../data/entities";
|
|
3
3
|
import Stack from "../stack/Stack.svelte";
|
|
4
|
+
import { prefixObject, stringifyStyles } from "../../utils/style-utils";
|
|
4
5
|
|
|
5
6
|
const {
|
|
6
7
|
stack,
|
|
@@ -10,8 +11,8 @@
|
|
|
10
11
|
onAction,
|
|
11
12
|
purchaseState,
|
|
12
13
|
variableDictionary,
|
|
14
|
+
zStackChildStyles,
|
|
13
15
|
}: PackageProps = $props();
|
|
14
|
-
|
|
15
16
|
const onPackageClick = (evt: MouseEvent) => {
|
|
16
17
|
evt.preventDefault();
|
|
17
18
|
evt.stopPropagation();
|
|
@@ -28,13 +29,18 @@
|
|
|
28
29
|
const componentState = $derived({
|
|
29
30
|
selected: purchaseState?.selectedPackageId === package_id,
|
|
30
31
|
});
|
|
32
|
+
|
|
33
|
+
const styles = $derived(
|
|
34
|
+
stringifyStyles(prefixObject(zStackChildStyles, "package")),
|
|
35
|
+
);
|
|
31
36
|
</script>
|
|
32
37
|
|
|
33
38
|
<button
|
|
34
|
-
class="package"
|
|
39
|
+
class="rc-pw-package"
|
|
35
40
|
class:selected={componentState.selected}
|
|
36
41
|
{id}
|
|
37
42
|
onclick={onPackageClick}
|
|
43
|
+
style={styles}
|
|
38
44
|
>
|
|
39
45
|
<Stack
|
|
40
46
|
{...stack}
|
|
@@ -47,13 +53,16 @@
|
|
|
47
53
|
</button>
|
|
48
54
|
|
|
49
55
|
<style>
|
|
50
|
-
.package {
|
|
56
|
+
.rc-pw-package {
|
|
51
57
|
width: 100%;
|
|
52
58
|
display: flex;
|
|
53
59
|
margin: 0;
|
|
54
60
|
padding: 0;
|
|
55
|
-
background:
|
|
56
|
-
border:
|
|
57
|
-
text-align:
|
|
61
|
+
background: initial;
|
|
62
|
+
border: initial;
|
|
63
|
+
text-align: initial;
|
|
64
|
+
position: var(--package-position, relative);
|
|
65
|
+
inset: var(--package-inset, 0);
|
|
66
|
+
transform: var(--package-transform, initial);
|
|
58
67
|
}
|
|
59
68
|
</style>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Stack, Image, PurchaseButton, Package, Footer } from "../..";
|
|
3
2
|
import Self from "./Node.svelte";
|
|
4
3
|
import {
|
|
5
4
|
type ActionsProps,
|
|
@@ -10,29 +9,41 @@
|
|
|
10
9
|
type SupportedActions,
|
|
11
10
|
} from "../../data/entities";
|
|
12
11
|
import { prefersDarkMode } from "../../stores/theme";
|
|
13
|
-
import ButtonNode from "../button/ButtonNode.svelte";
|
|
14
|
-
import TextNode from "../text/TextNode.svelte";
|
|
15
12
|
import type { VariableDictionary } from "../../utils/variable-utils";
|
|
16
|
-
import
|
|
13
|
+
import type { ZStackChildStyles } from "../stack/stack-utils";
|
|
14
|
+
import TextNode from "../text/TextNode.svelte";
|
|
15
|
+
import {
|
|
16
|
+
Footer,
|
|
17
|
+
Image,
|
|
18
|
+
Package,
|
|
19
|
+
PurchaseButton,
|
|
20
|
+
Stack,
|
|
21
|
+
Timeline,
|
|
22
|
+
} from "../..";
|
|
23
|
+
import ButtonNode from "../button/ButtonNode.svelte";
|
|
24
|
+
import type { Component } from "svelte";
|
|
25
|
+
|
|
26
|
+
type SupportedComponents =
|
|
27
|
+
| TextNode
|
|
28
|
+
| Stack
|
|
29
|
+
| Image
|
|
30
|
+
| ButtonNode
|
|
31
|
+
| PurchaseButton
|
|
32
|
+
| Package
|
|
33
|
+
| Footer
|
|
34
|
+
| Timeline;
|
|
17
35
|
|
|
18
36
|
interface Props extends ActionsProps, PurchaseStateProps {
|
|
19
37
|
nodeData: PaywallComponent;
|
|
20
38
|
labels: ComponentLocalizations;
|
|
21
39
|
onAction?: (action: SupportedActions, data?: Extra) => void;
|
|
22
40
|
variableDictionary?: VariableDictionary;
|
|
41
|
+
zStackChildStyles?: ZStackChildStyles;
|
|
23
42
|
}
|
|
24
43
|
|
|
25
|
-
const {
|
|
26
|
-
nodeData,
|
|
27
|
-
labels,
|
|
28
|
-
onAction,
|
|
29
|
-
purchaseState,
|
|
30
|
-
variableDictionary,
|
|
31
|
-
}: Props = $props();
|
|
32
|
-
|
|
33
44
|
const ComponentTypes = {
|
|
34
|
-
text: TextNode,
|
|
35
45
|
stack: Stack,
|
|
46
|
+
text: TextNode,
|
|
36
47
|
image: Image,
|
|
37
48
|
button: ButtonNode,
|
|
38
49
|
purchase_button: PurchaseButton,
|
|
@@ -40,21 +51,63 @@
|
|
|
40
51
|
footer: Footer,
|
|
41
52
|
timeline: Timeline,
|
|
42
53
|
};
|
|
43
|
-
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* This function returns the component class and the node data for a given paywall component.
|
|
57
|
+
* It first checks if the component type is supported and returns the corresponding component class.
|
|
58
|
+
* If not supported, it checks if the fallback component type is supported and returns the corresponding component class,
|
|
59
|
+
* finally it throws an error if the component type is not supported and the fallback component type is not supported.
|
|
60
|
+
* @param nodeData:PaywallComponent - the PaywallComponent object representing a Node in the paywall
|
|
61
|
+
* @returns [Component<SupportedComponents>, PaywallComponent] - a tuple containing the component class and the node data
|
|
62
|
+
* @throws Error - if the component type and the fallback component type are not supported
|
|
63
|
+
*/
|
|
64
|
+
export const getComponentClass: (
|
|
65
|
+
nodeData: PaywallComponent,
|
|
66
|
+
) => [Component<SupportedComponents>, PaywallComponent] = (
|
|
67
|
+
nodeData: PaywallComponent,
|
|
68
|
+
) => {
|
|
69
|
+
if (ComponentTypes[nodeData.type]) {
|
|
70
|
+
return [
|
|
71
|
+
ComponentTypes[nodeData.type] as Component<SupportedComponents>,
|
|
72
|
+
nodeData,
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { fallback } = nodeData;
|
|
77
|
+
if (fallback && ComponentTypes[fallback?.type]) {
|
|
78
|
+
return [
|
|
79
|
+
ComponentTypes[fallback.type] as Component<SupportedComponents>,
|
|
80
|
+
fallback,
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
|
|
44
84
|
// manually throwing error for this specific case until
|
|
45
85
|
// it's handled with fallback components
|
|
46
86
|
throw new Error(`Invalid component type: ${nodeData.type}`);
|
|
47
|
-
}
|
|
48
|
-
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const {
|
|
90
|
+
nodeData,
|
|
91
|
+
labels,
|
|
92
|
+
onAction,
|
|
93
|
+
purchaseState,
|
|
94
|
+
variableDictionary,
|
|
95
|
+
zStackChildStyles,
|
|
96
|
+
...restProps
|
|
97
|
+
}: Props = $props();
|
|
98
|
+
|
|
99
|
+
const [ComponentToRender, dataToUse] = $derived(getComponentClass(nodeData));
|
|
49
100
|
</script>
|
|
50
101
|
|
|
51
|
-
<
|
|
52
|
-
{...(
|
|
102
|
+
<ComponentToRender
|
|
103
|
+
{...(dataToUse as any) || {}}
|
|
53
104
|
{labels}
|
|
54
105
|
prefersDarkMode={$prefersDarkMode}
|
|
55
106
|
{onAction}
|
|
56
107
|
{purchaseState}
|
|
57
108
|
{variableDictionary}
|
|
109
|
+
{zStackChildStyles}
|
|
110
|
+
{...restProps}
|
|
58
111
|
>
|
|
59
112
|
{#each nodeData.components as PaywallComponent[] as childData}
|
|
60
113
|
<Self
|
|
@@ -65,4 +118,4 @@
|
|
|
65
118
|
{variableDictionary}
|
|
66
119
|
/>
|
|
67
120
|
{/each}
|
|
68
|
-
</
|
|
121
|
+
</ComponentToRender>
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { type ActionsProps, type ComponentLocalizations, type Extra, type PaywallComponent, type PurchaseStateProps, type SupportedActions } from "../../data/entities";
|
|
2
2
|
import type { VariableDictionary } from "../../utils/variable-utils";
|
|
3
|
+
import type { ZStackChildStyles } from "../stack/stack-utils";
|
|
4
|
+
import TextNode from "../text/TextNode.svelte";
|
|
5
|
+
import { Footer, Image, Package, PurchaseButton, Stack, Timeline } from "../..";
|
|
6
|
+
import ButtonNode from "../button/ButtonNode.svelte";
|
|
7
|
+
import type { Component } from "svelte";
|
|
8
|
+
type SupportedComponents = TextNode | Stack | Image | ButtonNode | PurchaseButton | Package | Footer | Timeline;
|
|
3
9
|
interface Props extends ActionsProps, PurchaseStateProps {
|
|
4
10
|
nodeData: PaywallComponent;
|
|
5
11
|
labels: ComponentLocalizations;
|
|
6
12
|
onAction?: (action: SupportedActions, data?: Extra) => void;
|
|
7
13
|
variableDictionary?: VariableDictionary;
|
|
14
|
+
zStackChildStyles?: ZStackChildStyles;
|
|
8
15
|
}
|
|
9
|
-
declare const Node:
|
|
16
|
+
declare const Node: Component<Props, {
|
|
17
|
+
/**
|
|
18
|
+
* This function returns the component class and the node data for a given paywall component.
|
|
19
|
+
* It first checks if the component type is supported and returns the corresponding component class.
|
|
20
|
+
* If not supported, it checks if the fallback component type is supported and returns the corresponding component class,
|
|
21
|
+
* finally it throws an error if the component type is not supported and the fallback component type is not supported.
|
|
22
|
+
* @param nodeData:PaywallComponent - the PaywallComponent object representing a Node in the paywall
|
|
23
|
+
* @returns [Component<SupportedComponents>, PaywallComponent] - a tuple containing the component class and the node data
|
|
24
|
+
* @throws Error - if the component type and the fallback component type are not supported
|
|
25
|
+
*/ getComponentClass: (nodeData: PaywallComponent) => [Component<SupportedComponents>, PaywallComponent];
|
|
26
|
+
}, "">;
|
|
10
27
|
type Node = ReturnType<typeof Node>;
|
|
11
28
|
export default Node;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
colorModeOverrideTemplate,
|
|
18
18
|
errorPaywallData,
|
|
19
19
|
paywallWithFooter,
|
|
20
|
+
fallbackPaywallData,
|
|
20
21
|
} from "../../stories/fixtures";
|
|
21
22
|
import { fn } from "@storybook/test";
|
|
22
23
|
import type { VariableDictionary } from "../../utils/variable-utils";
|
|
@@ -243,6 +244,19 @@
|
|
|
243
244
|
}}
|
|
244
245
|
/>
|
|
245
246
|
|
|
247
|
+
<Story
|
|
248
|
+
name="Fallback Paywall"
|
|
249
|
+
args={{
|
|
250
|
+
paywallData: fallbackPaywallData,
|
|
251
|
+
onPurchaseClicked: fn(),
|
|
252
|
+
onBackClicked: fn(),
|
|
253
|
+
onNavigateToUrlClicked: fn(),
|
|
254
|
+
onRestorePurchasesClicked: fn(),
|
|
255
|
+
preferredColorMode: "dark",
|
|
256
|
+
onError: (error: unknown) => console.error(`Error - ${error}`),
|
|
257
|
+
}}
|
|
258
|
+
/>
|
|
259
|
+
|
|
246
260
|
<Story
|
|
247
261
|
name="Sticky Footer"
|
|
248
262
|
args={{
|