@revenuecat/purchases-ui-js 2.0.6 → 2.1.1

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.
@@ -75,6 +75,7 @@
75
75
  id2: "Navigate back",
76
76
  id3: "Navigate to",
77
77
  id4: "URL navigation",
78
+ id5: "Workflow Action",
78
79
  },
79
80
  },
80
81
  }),
@@ -166,3 +167,22 @@
166
167
  },
167
168
  }}
168
169
  />
170
+
171
+ <Story
172
+ name="Workflow Action"
173
+ args={{
174
+ action: {
175
+ type: "workflow",
176
+ },
177
+ triggers: {
178
+ on_press: "workflow-action-id",
179
+ },
180
+ stack: {
181
+ ...stackProps(5),
182
+ background_color: {
183
+ dark: { type: "hex", value: "#9C27B0" },
184
+ light: { type: "hex", value: "#9C27B0" },
185
+ },
186
+ },
187
+ }}
188
+ />
@@ -17,10 +17,16 @@
17
17
 
18
18
  const { onButtonAction } = getPaywallContext();
19
19
 
20
- const onclick = () => onButtonAction(props.action);
20
+ const onclick = () => {
21
+ const actionId = props.triggers?.on_press;
22
+ onButtonAction(props.action, actionId);
23
+ };
21
24
 
22
25
  const visible = $derived.by(() => {
23
26
  switch (action.type) {
27
+ case "workflow":
28
+ return true;
29
+ case "restore_purchases":
24
30
  case "navigate_back":
25
31
  return false;
26
32
  case "navigate_to":
@@ -2,7 +2,6 @@
2
2
  import Package from "./Package.svelte";
3
3
  import { componentDecorator } from "../../stories/component-decorator";
4
4
  import { localizationDecorator } from "../../stories/localization-decorator";
5
- import type { PackageProps } from "../../types/components/package";
6
5
  import { defineMeta } from "@storybook/addon-svelte-csf";
7
6
 
8
7
  const defaultLocale = "en_US";
@@ -8,10 +8,15 @@
8
8
  } from "../../stores/variables";
9
9
  import type { PackageProps } from "../../types/components/package";
10
10
  import { derived } from "svelte/store";
11
+ import {
12
+ getPackageInfoContext,
13
+ setPackageInfoContext,
14
+ } from "../../stores/packageInfo";
11
15
 
12
16
  const { stack, package_id }: PackageProps = $props();
13
17
 
14
- const { selectedPackageId, variablesPerPackage } = getPaywallContext();
18
+ const { selectedPackageId, variablesPerPackage, infoPerPackage } =
19
+ getPaywallContext();
15
20
 
16
21
  setSelectedStateContext(
17
22
  derived(selectedPackageId, (value) => value === package_id),
@@ -27,6 +32,13 @@
27
32
  (fallback) => $variablesPerPackage?.[package_id] ?? fallback,
28
33
  );
29
34
  setVariablesContext(variables);
35
+
36
+ const fallbackPackageInfo = getPackageInfoContext();
37
+ const packageInfo = derived(
38
+ fallbackPackageInfo,
39
+ (fallback) => $infoPerPackage?.[package_id] ?? fallback,
40
+ );
41
+ setPackageInfoContext(packageInfo);
30
42
  </script>
31
43
 
32
44
  <Stack {...stack} onclick={onPackageClick} />
@@ -12,7 +12,7 @@
12
12
  import type { SheetProps } from "../../types/components/sheet";
13
13
  import type { PaywallData } from "../../types/paywall";
14
14
  import type { UIConfig } from "../../types/ui-config";
15
- import type { VariableDictionary } from "../../types/variables";
15
+ import type { PackageInfo, VariableDictionary } from "../../types/variables";
16
16
  import { mapBackground } from "../../utils/background-utils";
17
17
  import { css } from "../../utils/base-utils";
18
18
  import { registerFonts } from "../../utils/font-utils";
@@ -21,11 +21,16 @@
21
21
  import { derived, readable, writable } from "svelte/store";
22
22
  import Stack from "../stack/Stack.svelte";
23
23
  import Sheet from "./Sheet.svelte";
24
+ import {
25
+ type PackageInfoStore,
26
+ setPackageInfoContext,
27
+ } from "../../stores/packageInfo";
24
28
 
25
29
  interface Props {
26
30
  paywallData: PaywallData;
27
31
  selectedLocale?: string;
28
32
  variablesPerPackage?: Record<string, VariableDictionary>;
33
+ infoPerPackage?: Record<string, PackageInfo>;
29
34
  uiConfig: UIConfig;
30
35
  preferredColorMode?: ColorMode;
31
36
  onPurchaseClicked?: (selectedPackageId: string) => void;
@@ -33,6 +38,7 @@
33
38
  onVisitCustomerCenterClicked?: () => void;
34
39
  onRestorePurchasesClicked?: () => void;
35
40
  onNavigateToUrlClicked?: (url: string) => void;
41
+ onActionTriggered?: (actionId: string) => void;
36
42
  onError?: (error: unknown) => void;
37
43
  }
38
44
 
@@ -40,12 +46,14 @@
40
46
  paywallData,
41
47
  selectedLocale,
42
48
  variablesPerPackage = {},
49
+ infoPerPackage = {},
43
50
  preferredColorMode,
44
51
  onPurchaseClicked,
45
52
  onBackClicked,
46
53
  onVisitCustomerCenterClicked,
47
54
  onRestorePurchasesClicked,
48
55
  onNavigateToUrlClicked,
56
+ onActionTriggered,
49
57
  onError,
50
58
  uiConfig,
51
59
  }: Props = $props();
@@ -76,8 +84,13 @@
76
84
 
77
85
  let sheet = $state<SheetProps>();
78
86
 
79
- const onButtonAction = (action: Action) => {
87
+ const onButtonAction = (action: Action, actionId?: string) => {
80
88
  switch (action.type) {
89
+ case "workflow":
90
+ if (actionId) {
91
+ onActionTriggered?.(actionId);
92
+ }
93
+ return;
81
94
  case "navigate_back":
82
95
  onBackClicked?.();
83
96
  return;
@@ -111,6 +124,7 @@
111
124
  setPaywallContext({
112
125
  selectedPackageId,
113
126
  variablesPerPackage: readable(variablesPerPackage),
127
+ infoPerPackage: readable(infoPerPackage),
114
128
  onPurchase,
115
129
  onButtonAction,
116
130
  uiConfig,
@@ -123,6 +137,13 @@
123
137
 
124
138
  setVariablesContext(variables);
125
139
 
140
+ const packageInfo: PackageInfoStore = derived(
141
+ selectedPackageId,
142
+ (packageId) => infoPerPackage[packageId || ""],
143
+ );
144
+
145
+ setPackageInfoContext(packageInfo);
146
+
126
147
  const style = $derived(
127
148
  css({
128
149
  ...mapBackground(colorMode, null, base.background),
@@ -185,10 +206,12 @@
185
206
  padding: 0;
186
207
  font-family: sans-serif;
187
208
  }
209
+
188
210
  body {
189
211
  line-height: 1.5;
190
212
  -webkit-font-smoothing: antialiased;
191
213
  }
214
+
192
215
  img,
193
216
  picture,
194
217
  video,
@@ -204,6 +227,7 @@
204
227
  select {
205
228
  font: inherit;
206
229
  }
230
+
207
231
  p,
208
232
  h1,
209
233
  h2,
@@ -1,11 +1,12 @@
1
1
  import type { ColorMode } from "../../types";
2
2
  import type { PaywallData } from "../../types/paywall";
3
3
  import type { UIConfig } from "../../types/ui-config";
4
- import type { VariableDictionary } from "../../types/variables";
4
+ import type { PackageInfo, VariableDictionary } from "../../types/variables";
5
5
  interface Props {
6
6
  paywallData: PaywallData;
7
7
  selectedLocale?: string;
8
8
  variablesPerPackage?: Record<string, VariableDictionary>;
9
+ infoPerPackage?: Record<string, PackageInfo>;
9
10
  uiConfig: UIConfig;
10
11
  preferredColorMode?: ColorMode;
11
12
  onPurchaseClicked?: (selectedPackageId: string) => void;
@@ -13,6 +14,7 @@ interface Props {
13
14
  onVisitCustomerCenterClicked?: () => void;
14
15
  onRestorePurchasesClicked?: () => void;
15
16
  onNavigateToUrlClicked?: (url: string) => void;
17
+ onActionTriggered?: (actionId: string) => void;
16
18
  onError?: (error: unknown) => void;
17
19
  }
18
20
  declare const Paywall: import("svelte").Component<Props, {}, "">;
@@ -3,9 +3,10 @@
3
3
  import { localizationDecorator } from "../../stories/localization-decorator";
4
4
  import { variablesDecorator } from "../../stories/variables-decorator";
5
5
  import type { Localizations } from "../../types/localization";
6
- import type { VariableDictionary } from "../../types/variables";
6
+ import type { PackageInfo, VariableDictionary } from "../../types/variables";
7
7
  import { defineMeta } from "@storybook/addon-svelte-csf";
8
8
  import { VARIABLES } from "../paywall/fixtures/variables";
9
+ import { DEFAULT_SPACING } from "../../utils/constants";
9
10
 
10
11
  /*
11
12
  * Documentation for this component can be found in https://www.notion.so/revenuecat/Text-e257cb046e104351861f8364ede617be?pvs=4
@@ -32,6 +33,8 @@
32
33
  width: { type: "fill" },
33
34
  height: { type: "fill" },
34
35
  },
36
+ padding: DEFAULT_SPACING,
37
+ margin: DEFAULT_SPACING,
35
38
  },
36
39
  parameters: {
37
40
  localizations: {
@@ -49,6 +52,18 @@
49
52
  "product.price": "$39.99",
50
53
  "product.price_per_period": "$39.99/yr",
51
54
  } satisfies VariableDictionary;
55
+
56
+ const mockPackageInfoWithIntroOffer: PackageInfo = {
57
+ hasIntroOffer: true,
58
+ };
59
+
60
+ const mockPackageInfoWithTrial: PackageInfo = {
61
+ hasTrial: true,
62
+ };
63
+ </script>
64
+
65
+ <script>
66
+ import { packageInfoDecorator } from "../../stories/packageInfo-decorator";
52
67
  </script>
53
68
 
54
69
  <Story name="Default" args={{ name: "hello world!" }} />
@@ -88,6 +103,109 @@
88
103
  }}
89
104
  />
90
105
 
106
+ <Story
107
+ name="Linear gradeint"
108
+ decorators={[
109
+ localizationDecorator({
110
+ defaultLocale,
111
+ localizations: { [defaultLocale]: { [text_lid]: "Linear gradient" } },
112
+ }),
113
+ ]}
114
+ args={{
115
+ color: {
116
+ light: {
117
+ degrees: 90,
118
+ points: [
119
+ {
120
+ color: "#e81c0fFF",
121
+ percent: 0,
122
+ },
123
+ {
124
+ color: "#0029ffff",
125
+ percent: 100,
126
+ },
127
+ ],
128
+ type: "linear",
129
+ },
130
+ },
131
+ background_color: {
132
+ light: {
133
+ degrees: 90,
134
+ points: [
135
+ {
136
+ color: "#ffffffff",
137
+ percent: 0,
138
+ },
139
+ {
140
+ color: "#000000ff",
141
+ percent: 100,
142
+ },
143
+ ],
144
+ type: "linear",
145
+ },
146
+ },
147
+ font_size: 48,
148
+ font_weight: "regular",
149
+ font_weight_int: 400,
150
+ horizontal_alignment: "leading",
151
+ size: {
152
+ width: { type: "fit" },
153
+ height: { type: "fit" },
154
+ },
155
+ }}
156
+ />
157
+
158
+ <Story
159
+ name="Radial gradient"
160
+ decorators={[
161
+ localizationDecorator({
162
+ defaultLocale,
163
+ localizations: { [defaultLocale]: { [text_lid]: "Radial gradient" } },
164
+ }),
165
+ ]}
166
+ args={{
167
+ color: {
168
+ light: {
169
+ points: [
170
+ {
171
+ color: "#3bf60cff",
172
+ percent: 23,
173
+ },
174
+ {
175
+ color: "#e40fe8ff",
176
+ percent: 100,
177
+ },
178
+ ],
179
+ type: "radial",
180
+ },
181
+ },
182
+ background_color: {
183
+ light: {
184
+ degrees: 90,
185
+ points: [
186
+ {
187
+ color: "#ffffffff",
188
+ percent: 0,
189
+ },
190
+ {
191
+ color: "#000000ff",
192
+ percent: 100,
193
+ },
194
+ ],
195
+ type: "linear",
196
+ },
197
+ },
198
+ font_size: 48,
199
+ font_weight: "regular",
200
+ font_weight_int: 400,
201
+ horizontal_alignment: "leading",
202
+ size: {
203
+ width: { type: "fit" },
204
+ height: { type: "fit" },
205
+ },
206
+ }}
207
+ />
208
+
91
209
  <Story
92
210
  name="With Spacing"
93
211
  args={{
@@ -140,3 +258,35 @@
140
258
  } satisfies Localizations,
141
259
  }}
142
260
  />
261
+
262
+ <Story
263
+ name="With overrides for Intro Offers"
264
+ args={{
265
+ font_weight: "regular",
266
+ horizontal_alignment: "leading",
267
+ padding: { top: 16, trailing: 24, bottom: 16, leading: 24 },
268
+ margin: { top: 8, trailing: 0, bottom: 8, leading: 0 },
269
+ name: "hello world!",
270
+ overrides: [
271
+ {
272
+ conditions: [{ type: "intro_offer" }],
273
+ properties: { text_lid: "override_text_lid" },
274
+ },
275
+ ],
276
+ text_lid,
277
+ }}
278
+ decorators={[
279
+ variablesDecorator(mockVariableDictionary),
280
+ packageInfoDecorator(mockPackageInfoWithIntroOffer),
281
+ ]}
282
+ parameters={{
283
+ localizations: {
284
+ [defaultLocale]: {
285
+ [text_lid]:
286
+ "This is a text with variables: {{ product.store_product_name }} for {{ product.price }} per {{ product.price_per_period }} and a missing variable: {{ sub_period_abbreviated }}",
287
+ override_text_lid:
288
+ "This text is shown only when an intro offer is defined for the current package.",
289
+ },
290
+ } satisfies Localizations,
291
+ }}
292
+ />
@@ -7,27 +7,38 @@
7
7
  import Text from "./Text.svelte";
8
8
  import { getColorModeContext } from "../../stores/color-mode";
9
9
  import { getLocalizationContext } from "../../stores/localization";
10
+ import { getPaywallContext } from "../../stores/paywall";
10
11
  import { getSelectedStateContext } from "../../stores/selected";
11
12
  import { getVariablesContext } from "../../stores/variables";
12
13
  import type { TextNodeProps } from "../../types/components/text";
13
- import { getActiveStateProps } from "../../utils/style-utils";
14
+ import {
15
+ getActiveStateProps,
16
+ getIntroOfferStateProps,
17
+ } from "../../utils/style-utils";
14
18
  import { replaceVariables } from "../../utils/variable-utils";
19
+ import { getPackageInfoContext } from "../../stores/packageInfo";
15
20
 
16
21
  const props: TextNodeProps = $props();
17
22
 
18
23
  const selectedState = getSelectedStateContext();
24
+ const packageInfo = getPackageInfoContext();
19
25
  const actualProps = $derived.by(() => {
20
26
  return {
21
27
  ...props,
22
28
  ...getActiveStateProps($selectedState, props.overrides),
29
+ ...getIntroOfferStateProps(
30
+ !!$packageInfo?.hasIntroOffer,
31
+ props.overrides,
32
+ ),
23
33
  };
24
34
  });
25
35
 
26
36
  const getColorMode = getColorModeContext();
27
37
  const colorMode = $derived(getColorMode());
28
38
 
29
- const { tagToRender, textStyles } = $derived(
30
- getTextComponentStyles(colorMode, actualProps),
39
+ const { uiConfig } = getPaywallContext();
40
+ let textStyles = $derived(
41
+ getTextComponentStyles(colorMode, actualProps, uiConfig.app.fonts),
31
42
  );
32
43
 
33
44
  const wrapperStyles = $derived(
@@ -49,7 +60,7 @@
49
60
  </script>
50
61
 
51
62
  <span style={wrapperStyles}>
52
- <Text style={textStyles} component={tagToRender}>
63
+ <Text style={textStyles} component="span">
53
64
  {@html markdownParsed}
54
65
  </Text>
55
66
  </span>
@@ -1,15 +1,15 @@
1
- import type { ColorMode, SizeType } from "../../types";
1
+ import { type ColorMode, type SizeType } from "../../types";
2
2
  import type { ColorGradientScheme, ColorScheme } from "../../types/colors";
3
3
  import type { TextNodeProps } from "../../types/components/text";
4
+ import type { AppFontsConfig } from "../../types/ui-config";
5
+ import { type CSS } from "../../utils/base-utils";
4
6
  export declare const defaultColor: ColorScheme;
7
+ export declare function mapTextColor(colorMode: ColorMode, scheme: ColorGradientScheme): CSS;
5
8
  /**
6
9
  * Generates comprehensive styles for text components by combining text, component and size styles
7
10
  * @param props - Text component properties including font, color, background, spacing etc.
8
11
  * @returns Object containing text inline styles and the appropriate HTML tag to render
9
12
  */
10
- export declare const getTextComponentStyles: (colorMode: ColorMode, props: TextNodeProps) => {
11
- textStyles: string;
12
- tagToRender: string;
13
- };
13
+ export declare const getTextComponentStyles: (colorMode: ColorMode, props: TextNodeProps, fonts: AppFontsConfig) => string;
14
14
  export declare function getTextWrapperInlineStyles(colorMode: ColorMode, _restProps: Partial<TextNodeProps>, size: SizeType, background_color?: ColorGradientScheme | null): string;
15
15
  export declare function getHtmlFromMarkdown(text?: string): string;
@@ -1,38 +1,53 @@
1
+ import { FontSizes, FontWeights, TextAlignments, } from "../../types";
1
2
  import { mapBackground } from "../../utils/background-utils";
2
- import { css, mapColor, mapSize, mapSpacing } from "../../utils/base-utils";
3
+ import { css, mapColorInfo, mapColorMode, mapSize, mapSpacing, } from "../../utils/base-utils";
3
4
  import { DEFAULT_TEXT_COLOR } from "../../utils/constants";
4
- import { getTextStyles } from "../../utils/style-utils";
5
+ import { getScopedFontFamily, isFontRCFMManaged } from "../../utils/font-utils";
5
6
  export const defaultColor = {
6
7
  light: { type: "hex", value: DEFAULT_TEXT_COLOR },
7
8
  };
9
+ export function mapTextColor(colorMode, scheme) {
10
+ const info = mapColorMode(colorMode, scheme);
11
+ const color = mapColorInfo(info);
12
+ switch (info.type) {
13
+ case "alias":
14
+ case "hex":
15
+ return { color };
16
+ case "linear":
17
+ case "radial":
18
+ return {
19
+ color: "transparent",
20
+ background: color,
21
+ "-webkit-background-clip": "text",
22
+ "background-clip": "text",
23
+ };
24
+ }
25
+ }
8
26
  /**
9
27
  * Generates comprehensive styles for text components by combining text, component and size styles
10
28
  * @param props - Text component properties including font, color, background, spacing etc.
11
29
  * @returns Object containing text inline styles and the appropriate HTML tag to render
12
30
  */
13
- export const getTextComponentStyles = (colorMode, props) => {
14
- const { color = defaultColor, background_color, padding, margin, size, } = props;
15
- const textStyles = getTextStyles(props);
16
- const style = css({
31
+ export const getTextComponentStyles = (colorMode, props, fonts) => {
32
+ const { font_name, font_size, font_weight, font_weight_int, horizontal_alignment, color = defaultColor, padding, margin, size, } = props;
33
+ const font = fonts[font_name ?? ""];
34
+ const fontFamily = font?.web?.family;
35
+ return css({
17
36
  display: "block",
18
37
  width: mapSize(size.width),
19
38
  height: mapSize(size.height),
20
39
  margin: mapSpacing(margin),
21
40
  padding: mapSpacing(padding),
22
- ...mapBackground(colorMode, background_color, null),
23
- color: mapColor(colorMode, color),
24
- "text-align": textStyles["--text-align"] || "initial",
25
- "font-weight": textStyles["--font-weight"] || "initial",
26
- "font-size": textStyles["--font-size"] || "initial",
27
- "font-family": textStyles["--font-family"] || "sans-serif",
28
- "-webkit-background-clip": textStyles["--background-clip"] || "initial",
29
- "background-clip": textStyles["--background-clip"] || "initial",
30
- "-webkit-text-fill-color": textStyles["--text-fill-color"] || "initial",
41
+ ...mapTextColor(colorMode, color),
42
+ "text-align": TextAlignments[horizontal_alignment] || TextAlignments.leading,
43
+ "font-weight": font_weight_int ?? FontWeights[font_weight] ?? FontWeights.regular,
44
+ "font-size": Number.isInteger(Number(font_size))
45
+ ? `${font_size}px`
46
+ : FontSizes[font_size] || FontSizes.body_m,
47
+ "font-family": isFontRCFMManaged(font_name ?? "")
48
+ ? getScopedFontFamily(fontFamily ?? "")
49
+ : "sans-serif",
31
50
  });
32
- return {
33
- textStyles: style,
34
- tagToRender: "span",
35
- };
36
51
  };
37
52
  export function getTextWrapperInlineStyles(colorMode, _restProps, size, background_color) {
38
53
  return css({
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">
2
2
  import { getTimelineItemContentInlineStyles } from "./timeline-utils";
3
- import type { TimelineItemProps } from "../../types/components/timeline";
4
3
  import { getColorModeContext } from "../../stores/color-mode";
5
- import { getColor, getActiveStateProps } from "../../utils/style-utils";
6
4
  import { getSelectedStateContext } from "../../stores/selected";
5
+ import type { TimelineItemProps } from "../../types/components/timeline";
6
+ import { css, mapColor } from "../../utils/base-utils";
7
+ import { getActiveStateProps } from "../../utils/style-utils";
7
8
  import Icon from "../icon/Icon.svelte";
8
- import { css } from "../../utils/base-utils";
9
9
  import TextNode from "../text/TextNode.svelte";
10
10
 
11
11
  interface Props extends TimelineItemProps {
@@ -64,11 +64,7 @@
64
64
  const connectorBarStyles = $derived.by(() => {
65
65
  if (!connector) return "";
66
66
 
67
- const background = getColor({
68
- colorMap: connector.color,
69
- colorMode,
70
- fallback: "#000000",
71
- });
67
+ const background = mapColor(colorMode, connector.color);
72
68
 
73
69
  return css({
74
70
  width: "100%",
package/dist/index.d.ts CHANGED
@@ -11,6 +11,6 @@ export { default as Video } from "./components/video/Video.svelte";
11
11
  export * from "./types";
12
12
  export { type PaywallData } from "./types/paywall";
13
13
  export { type UIConfig } from "./types/ui-config";
14
- export { type VariableDictionary } from "./types/variables";
14
+ export { type VariableDictionary, type PackageInfo, } from "./types/variables";
15
15
  export * from "./ui/globals";
16
16
  export { default as Button } from "./ui/molecules/button.svelte";
@@ -0,0 +1,5 @@
1
+ import type { PackageInfo } from "../types/variables";
2
+ import { type Readable } from "svelte/store";
3
+ export type PackageInfoStore = Readable<PackageInfo | undefined>;
4
+ export declare function setPackageInfoContext(variables: PackageInfoStore): void;
5
+ export declare function getPackageInfoContext(): PackageInfoStore;
@@ -0,0 +1,13 @@
1
+ import { getContext, setContext } from "svelte";
2
+ import {} from "svelte/store";
3
+ const key = Symbol("packageInfo");
4
+ export function setPackageInfoContext(variables) {
5
+ setContext(key, variables);
6
+ }
7
+ export function getPackageInfoContext() {
8
+ const context = getContext(key);
9
+ if (context === undefined) {
10
+ throw new Error("PackageInfo context not found");
11
+ }
12
+ return context;
13
+ }
@@ -1,12 +1,13 @@
1
1
  import type { Action } from "../types/components/button";
2
2
  import type { UIConfig } from "../types/ui-config";
3
- import type { VariableDictionary } from "../types/variables";
3
+ import type { PackageInfo, VariableDictionary } from "../types/variables";
4
4
  import { type Readable, type Writable } from "svelte/store";
5
5
  type PaywallContext = Readonly<{
6
6
  selectedPackageId: Writable<string | undefined>;
7
7
  variablesPerPackage: Readable<Record<string, VariableDictionary> | undefined>;
8
+ infoPerPackage: Readable<Record<string, PackageInfo> | undefined>;
8
9
  onPurchase: () => void;
9
- onButtonAction: (action: Action) => void;
10
+ onButtonAction: (action: Action, actionId?: string) => void;
10
11
  uiConfig: UIConfig;
11
12
  }>;
12
13
  export declare function setPaywallContext(context: PaywallContext): void;
@@ -0,0 +1,3 @@
1
+ import type { PackageInfo } from "../types/variables";
2
+ import type { DecoratorFunction, Renderer } from "storybook/internal/csf";
3
+ export declare function packageInfoDecorator<TRenderer extends Renderer, TArgs>(packageInfo?: PackageInfo): DecoratorFunction<TRenderer, TArgs>;
@@ -0,0 +1,9 @@
1
+ import { readable } from "svelte/store";
2
+ import { setPackageInfoContext } from "../stores/packageInfo";
3
+ export function packageInfoDecorator(packageInfo) {
4
+ const store = readable(packageInfo);
5
+ return (Story) => {
6
+ setPackageInfoContext(store);
7
+ return Story();
8
+ };
9
+ }
@@ -16,8 +16,9 @@ export function paywallDecorator() {
16
16
  setPaywallContext({
17
17
  selectedPackageId,
18
18
  variablesPerPackage: readable(undefined),
19
+ infoPerPackage: readable(undefined),
19
20
  onPurchase: () => window.alert("Purchase clicked"),
20
- onButtonAction: (action) => window.alert(`Button clicked: ${JSON.stringify(action, undefined, 2)}`),
21
+ onButtonAction: (action, actionId) => window.alert(`Button clicked: ${JSON.stringify({ action, actionId }, undefined, 2)}`),
21
22
  uiConfig: emptyUiConfig,
22
23
  });
23
24
  return Story();
@@ -4,4 +4,5 @@ export interface BaseComponent {
4
4
  id: string;
5
5
  name: string;
6
6
  fallback?: Component;
7
+ triggers?: Record<string, string>;
7
8
  }