@revenuecat/purchases-ui-js 3.9.0 → 3.9.2

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.
@@ -50,7 +50,7 @@
50
50
  const style = $derived(
51
51
  isDisabled
52
52
  ? { opacity: "0.4", "pointer-events": "none", cursor: "not-allowed" }
53
- : {},
53
+ : undefined,
54
54
  );
55
55
  </script>
56
56
 
@@ -0,0 +1,164 @@
1
+ <script lang="ts">
2
+ import { getColorModeContext } from "../../stores/color-mode";
3
+ import { getHoverStateContext } from "../../stores/hover";
4
+ import { getLocalizationContext } from "../../stores/localization";
5
+ import { getPackageInfoContext } from "../../stores/packageInfo";
6
+ import { getPaywallContext } from "../../stores/paywall";
7
+ import { getSelectedStateContext } from "../../stores/selected";
8
+ import { getVariablesContext } from "../../stores/variables";
9
+ import { FontWeights, TextAlignments } from "../../types";
10
+ import type { InputTextProps } from "../../types/components/input-text";
11
+ import { mapBackground } from "../../utils/background-utils";
12
+ import {
13
+ css,
14
+ mapBorder,
15
+ mapBorderRadius,
16
+ mapShadow,
17
+ mapSize,
18
+ mapSpacing,
19
+ } from "../../utils/base-utils";
20
+ import {
21
+ getScopedFontFamily,
22
+ isFontRCFMManaged,
23
+ } from "../../utils/font-utils";
24
+ import {
25
+ evaluateVisibilityConditions,
26
+ getActiveStateProps,
27
+ getHoverStateProps,
28
+ } from "../../utils/style-utils";
29
+ import { replaceVariables } from "../../utils/variable-utils";
30
+ import type { HTMLInputAttributes } from "svelte/elements";
31
+ import { mapTextColor } from "../text/text-utils";
32
+
33
+ const props: InputTextProps = $props();
34
+
35
+ console.log("Hello");
36
+
37
+ const selectedState = getSelectedStateContext();
38
+ const hoverState = getHoverStateContext();
39
+ const {
40
+ placeholder_lid,
41
+ keyboard_type,
42
+ capitalize,
43
+ field_id,
44
+ required,
45
+ size,
46
+ padding,
47
+ margin,
48
+ border,
49
+ shape,
50
+ shadow,
51
+ font_name,
52
+ font_weight_int,
53
+ font_size,
54
+ horizontal_alignment,
55
+ color,
56
+ placeholder_font_name,
57
+ placeholder_font_weight_int,
58
+ placeholder_font_size,
59
+ placeholder_horizontal_alignment,
60
+ placeholder_color,
61
+ background_color,
62
+ } = $derived.by(() => {
63
+ return {
64
+ ...props,
65
+ ...getHoverStateProps($hoverState, props.overrides),
66
+ ...getActiveStateProps($selectedState, props.overrides),
67
+ };
68
+ });
69
+
70
+ const getColorMode = getColorModeContext();
71
+ const colorMode = $derived(getColorMode());
72
+ const { uiConfig, onInputChanged } = getPaywallContext();
73
+
74
+ const inputStyle = $derived.by(() => {
75
+ const font = uiConfig.app.fonts[font_name ?? ""];
76
+ const fontFamily = font?.web?.family;
77
+ const placeholderFont = uiConfig.app.fonts[placeholder_font_name ?? ""];
78
+ const placeholderFontFamily = placeholderFont?.web?.family;
79
+ const placeholderColor = mapTextColor(colorMode, placeholder_color);
80
+
81
+ return css({
82
+ display: props.visible === false ? "none" : "flex",
83
+ position: "relative",
84
+ width: mapSize(size.width),
85
+ height: mapSize(size.height),
86
+ margin: mapSpacing(margin),
87
+ padding: mapSpacing(padding),
88
+ ...mapBackground(colorMode, background_color, null),
89
+ border: mapBorder(colorMode, border),
90
+ "border-radius": mapBorderRadius(shape),
91
+ "box-shadow": mapShadow(colorMode, shadow),
92
+
93
+ ...mapTextColor(colorMode, color),
94
+ "text-align":
95
+ TextAlignments[horizontal_alignment] || TextAlignments.leading,
96
+ "font-weight": font_weight_int ?? FontWeights.regular,
97
+ "font-size": `${font_size}px`,
98
+ "font-family": isFontRCFMManaged(font_name ?? "")
99
+ ? getScopedFontFamily(fontFamily ?? "")
100
+ : "sans-serif",
101
+
102
+ "--placeholder-color": placeholderColor.color,
103
+ "--placeholder-background": placeholderColor.background,
104
+ "--placeholder-background-clip": placeholderColor["background-clip"],
105
+ "--placeholder-webkit-background-clip":
106
+ placeholderColor["-webkit-background-clip"],
107
+ "--placeholder-text-align":
108
+ TextAlignments[placeholder_horizontal_alignment] ||
109
+ TextAlignments.leading,
110
+ "--placeholder-font-weight":
111
+ placeholder_font_weight_int ?? FontWeights.regular,
112
+ "--placeholder-font-size": `${placeholder_font_size}px`,
113
+ "--placeholder-font-family": isFontRCFMManaged(
114
+ placeholder_font_name ?? "",
115
+ )
116
+ ? getScopedFontFamily(placeholderFontFamily ?? "")
117
+ : "sans-serif",
118
+ });
119
+ });
120
+
121
+ const variables = getVariablesContext();
122
+ const { getLocalizedString } = getLocalizationContext();
123
+ const placeholder = $derived(
124
+ replaceVariables(getLocalizedString(placeholder_lid), $variables),
125
+ );
126
+
127
+ const type = $derived.by((): HTMLInputAttributes["type"] => {
128
+ switch (props.keyboard_type) {
129
+ case "decimal":
130
+ case "numeric":
131
+ return "number";
132
+ case "email":
133
+ return "email";
134
+ case "tel":
135
+ return "tel";
136
+ case "text":
137
+ return "text";
138
+ }
139
+ });
140
+ </script>
141
+
142
+ <input
143
+ {type}
144
+ {placeholder}
145
+ {required}
146
+ inputmode={keyboard_type}
147
+ autocapitalize={capitalize}
148
+ style={inputStyle}
149
+ oninput={(event) => onInputChanged?.(field_id, event.currentTarget.value)}
150
+ />
151
+
152
+ <style>
153
+ input::placeholder {
154
+ color: var(--placeholder-color);
155
+ background: var(--placeholder-background);
156
+ background-clip: var(--placeholder-background-clip);
157
+ -webkit-background-clip: var(--placeholder-webkit-background-clip);
158
+
159
+ text-align: var(--placeholder-text-align);
160
+ font-weight: var(--placeholder-font-weight);
161
+ font-size: var(--placeholder-font-size);
162
+ font-family: var(--placeholder-font-family);
163
+ }
164
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { InputTextProps } from "../../types/components/input-text";
2
+ declare const InputText: import("svelte").Component<InputTextProps, {}, "">;
3
+ type InputText = ReturnType<typeof InputText>;
4
+ export default InputText;
@@ -10,6 +10,7 @@
10
10
  } from "../..";
11
11
  import ButtonNode from "../button/ButtonNode.svelte";
12
12
  import Countdown from "../countdown/Countdown.svelte";
13
+ import InputText from "../input-text/InputText.svelte";
13
14
  import InputMultipleChoice from "../options/InputMultipleChoice.svelte";
14
15
  import InputOption from "../options/InputOption.svelte";
15
16
  import InputSingleChoice from "../options/InputSingleChoice.svelte";
@@ -42,6 +43,7 @@
42
43
  input_multiple_choice: InputMultipleChoice,
43
44
  input_option: InputOption,
44
45
  input_single_choice: InputSingleChoice,
46
+ input_text: InputText,
45
47
  package: Package,
46
48
  purchase_button: PurchaseButton,
47
49
  redemption_button: RedemptionButton,
@@ -36,6 +36,7 @@
36
36
  type PackageInfoStore,
37
37
  setPackageInfoContext,
38
38
  } from "../../stores/packageInfo";
39
+ import type { WalletButtonRender } from "../../types/wallet";
39
40
 
40
41
  /**
41
42
  * Props are captured once at mount and are not reactive to subsequent changes.
@@ -63,19 +64,8 @@
63
64
  onActionTriggered?: (actionId: string) => void;
64
65
  onError?: (error: unknown) => void;
65
66
  hideBackButtons?: boolean;
66
- walletButtonRender?: (
67
- node: HTMLElement,
68
- params: {
69
- selectedPackageId: string;
70
- onReady?: (walletButtonAvailable?: boolean) => void;
71
- },
72
- ) => {
73
- destroy?: () => void;
74
- update?: (updateParams: {
75
- selectedPackageId: string;
76
- onReady?: (walletButtonAvailable?: boolean) => void;
77
- }) => void;
78
- };
67
+ walletButtonRender?: WalletButtonRender;
68
+ onInputChanged?: (fieldId: string, value: string) => void;
79
69
  maxContentWidth?: string;
80
70
  initialInputSelections?: InitialInputSelections;
81
71
  /**
@@ -110,6 +100,7 @@
110
100
  onError,
111
101
  uiConfig,
112
102
  walletButtonRender,
103
+ onInputChanged,
113
104
  hideBackButtons = false,
114
105
  maxContentWidth,
115
106
  initialInputSelections = {},
@@ -194,6 +185,7 @@
194
185
  infoPerPackage: readable(infoPerPackage),
195
186
  onPurchase,
196
187
  onButtonAction,
188
+ onInputChanged,
197
189
  walletButtonRender,
198
190
  uiConfig,
199
191
  hideBackButtons,
@@ -3,6 +3,7 @@ import type { ColorMode } from "../../types";
3
3
  import type { PaywallData } from "../../types/paywall";
4
4
  import type { UIConfig } from "../../types/ui-config";
5
5
  import { type CustomVariables, type PackageInfo, type VariableDictionary } from "../../types/variables";
6
+ import type { WalletButtonRender } from "../../types/wallet";
6
7
  /**
7
8
  * Props are captured once at mount and are not reactive to subsequent changes.
8
9
  * The paywall should be remounted to reflect new prop values.
@@ -29,16 +30,8 @@ interface Props {
29
30
  onActionTriggered?: (actionId: string) => void;
30
31
  onError?: (error: unknown) => void;
31
32
  hideBackButtons?: boolean;
32
- walletButtonRender?: (node: HTMLElement, params: {
33
- selectedPackageId: string;
34
- onReady?: (walletButtonAvailable?: boolean) => void;
35
- }) => {
36
- destroy?: () => void;
37
- update?: (updateParams: {
38
- selectedPackageId: string;
39
- onReady?: (walletButtonAvailable?: boolean) => void;
40
- }) => void;
41
- };
33
+ walletButtonRender?: WalletButtonRender;
34
+ onInputChanged?: (fieldId: string, value: string) => void;
42
35
  maxContentWidth?: string;
43
36
  initialInputSelections?: InitialInputSelections;
44
37
  /**
@@ -35,18 +35,6 @@
35
35
  };
36
36
  });
37
37
 
38
- const isVisible = $derived(
39
- evaluateVisibilityConditions(
40
- {
41
- selectedPackageId: $selectedPackageId,
42
- packageInfo: $packageInfo,
43
- variables: $variables,
44
- },
45
- props.overrides,
46
- props.visible,
47
- ),
48
- );
49
-
50
38
  const getColorMode = getColorModeContext();
51
39
  const colorMode = $derived(getColorMode());
52
40
 
@@ -69,6 +57,18 @@
69
57
  replaceVariables(getLocalizedString(actualProps.text_lid), $variables),
70
58
  );
71
59
 
60
+ const isVisible = $derived(
61
+ evaluateVisibilityConditions(
62
+ {
63
+ selectedPackageId: $selectedPackageId,
64
+ packageInfo: $packageInfo,
65
+ variables: $variables ?? {},
66
+ },
67
+ props.overrides,
68
+ props.visible,
69
+ ),
70
+ );
71
+
72
72
  const markdownParsed = $derived(getHtmlFromMarkdown(label));
73
73
  </script>
74
74
 
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import Paywall, {
3
- type UIConfig,
4
- } from "../paywall/Paywall.svelte";
2
+ import Paywall from "../paywall/Paywall.svelte";
5
3
  import type { InitialInputSelections } from "../../stores/inputValidation";
6
4
  import type { WorkflowScreen } from "../../types/workflow";
7
5
  import type { VariableDictionary } from "../../types/variables";
6
+ import type { WalletButtonRender } from "../../types/wallet";
7
+ import type { UIConfig } from "../../types/ui-config";
8
+
8
9
  interface Props {
9
10
  paywallComponents: WorkflowScreen | null | undefined;
10
11
  selectedLocale?: string;
@@ -20,7 +21,10 @@
20
21
  maxContentWidth?: string;
21
22
  variablesPerPackage?: Record<string, VariableDictionary>;
22
23
  initialInputSelections?: InitialInputSelections;
24
+ onInputChanged?: (fieldId: string, value: string) => void;
25
+ walletButtonRender?: WalletButtonRender;
23
26
  }
27
+
24
28
  const {
25
29
  paywallComponents,
26
30
  selectedLocale = "en_US",
@@ -33,6 +37,8 @@
33
37
  maxContentWidth,
34
38
  variablesPerPackage,
35
39
  initialInputSelections = {},
40
+ onInputChanged,
41
+ walletButtonRender,
36
42
  }: Props = $props();
37
43
  </script>
38
44
 
@@ -56,6 +62,8 @@
56
62
  onActionTriggered?.(actionId);
57
63
  }}
58
64
  {onPurchaseClicked}
65
+ {onInputChanged}
66
+ {walletButtonRender}
59
67
  onError={(error) => {
60
68
  console.error("Paywall error:", error);
61
69
  }}
@@ -1,7 +1,8 @@
1
- import { type UIConfig } from "../paywall/Paywall.svelte";
2
1
  import type { InitialInputSelections } from "../../stores/inputValidation";
3
2
  import type { WorkflowScreen } from "../../types/workflow";
4
3
  import type { VariableDictionary } from "../../types/variables";
4
+ import type { WalletButtonRender } from "../../types/wallet";
5
+ import type { UIConfig } from "../../types/ui-config";
5
6
  interface Props {
6
7
  paywallComponents: WorkflowScreen | null | undefined;
7
8
  selectedLocale?: string;
@@ -14,6 +15,8 @@ interface Props {
14
15
  maxContentWidth?: string;
15
16
  variablesPerPackage?: Record<string, VariableDictionary>;
16
17
  initialInputSelections?: InitialInputSelections;
18
+ onInputChanged?: (fieldId: string, value: string) => void;
19
+ walletButtonRender?: WalletButtonRender;
17
20
  }
18
21
  declare const Screen: import("svelte").Component<Props, {}, "">;
19
22
  type Screen = ReturnType<typeof Screen>;
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export * from "./types";
17
17
  export { type PaywallData } from "./types/paywall";
18
18
  export { type InitialInputSelections } from "./stores/inputValidation";
19
19
  export { type UIConfig } from "./types/ui-config";
20
+ export { type WalletButtonRender } from "./types/wallet";
20
21
  export { type CustomVariables, CustomVariableValue, type VariableDictionary, type PackageInfo, } from "./types/variables";
21
22
  export * from "./ui/globals";
22
23
  export { default as Button } from "./ui/molecules/button.svelte";
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ export * from "./types";
18
18
  export {} from "./types/paywall";
19
19
  export {} from "./stores/inputValidation";
20
20
  export {} from "./types/ui-config";
21
+ export {} from "./types/wallet";
21
22
  export { CustomVariableValue, } from "./types/variables";
22
23
  export * from "./ui/globals";
23
24
  export { default as Button } from "./ui/molecules/button.svelte";
@@ -1,6 +1,7 @@
1
1
  import type { Action } from "../types/components/button";
2
2
  import type { UIConfig } from "../types/ui-config";
3
3
  import type { PackageInfo, VariableDictionary } from "../types/variables";
4
+ import type { WalletButtonRender } from "../types/wallet";
4
5
  import { type Readable, type Writable } from "svelte/store";
5
6
  type PaywallContext = Readonly<{
6
7
  selectedPackageId: Writable<string | undefined>;
@@ -15,16 +16,8 @@ type PaywallContext = Readonly<{
15
16
  baseVariables: Readable<VariableDictionary | undefined>;
16
17
  infoPerPackage: Readable<Record<string, PackageInfo> | undefined>;
17
18
  onPurchase: (actionId?: string) => void;
18
- walletButtonRender?: (node: HTMLElement, params: {
19
- selectedPackageId: string;
20
- onReady?: (walletButtonAvailable?: boolean) => void;
21
- }) => {
22
- destroy?: () => void;
23
- update?: (params: {
24
- selectedPackageId: string;
25
- onReady?: (walletButtonAvailable?: boolean) => void;
26
- }) => void;
27
- };
19
+ onInputChanged?: (fieldId: string, value: string) => void;
20
+ walletButtonRender?: WalletButtonRender;
28
21
  onWalletButtonReady?: (walletButtonAvailable?: boolean) => void;
29
22
  onButtonAction: (action: Action, actionId?: string) => void;
30
23
  uiConfig: UIConfig;
@@ -1,11 +1,3 @@
1
+ import type { WalletButtonRender } from "../types/wallet";
1
2
  import type { DecoratorFunction, Renderer } from "storybook/internal/csf";
2
- export declare function paywallDecorator<TRenderer extends Renderer, TArgs>(walletButtonRender?: (node: HTMLElement, params: {
3
- selectedPackageId: string;
4
- onReady?: (walletButtonAvailable?: boolean) => void;
5
- }) => {
6
- destroy?: () => void;
7
- update?: (updateParams: {
8
- selectedPackageId: string;
9
- onReady?: (walletButtonAvailable?: boolean) => void;
10
- }) => void;
11
- }, selectedPackageId?: string): DecoratorFunction<TRenderer, TArgs>;
3
+ export declare function paywallDecorator<TRenderer extends Renderer, TArgs>(walletButtonRender?: WalletButtonRender, selectedPackageId?: string): DecoratorFunction<TRenderer, TArgs>;
@@ -4,6 +4,7 @@ import type { CountdownProps } from "./components/countdown";
4
4
  import type { FooterProps } from "./components/footer";
5
5
  import type { IconProps } from "./components/icon";
6
6
  import type { ImageProps } from "./components/image";
7
+ import type { InputTextProps } from "./components/input-text";
7
8
  import type { InputMultipleChoiceProps, InputOptionProps, InputSingleChoiceProps } from "./components/options";
8
9
  import type { PackageProps } from "./components/package";
9
10
  import type { PurchaseButtonProps } from "./components/purchase-button";
@@ -16,4 +17,4 @@ import type { VideoProps } from "./components/video";
16
17
  import type { WalletButtonProps } from "./components/wallet-button";
17
18
  import type { SkeletonLoaderProps } from "./components/skeleton-loader-props";
18
19
  import type { ExpressPurchaseButtonProps } from "./components/express-purchase-button-props";
19
- export type Component = ButtonProps | CarouselProps | CountdownProps | ExpressPurchaseButtonProps | FooterProps | IconProps | ImageProps | InputMultipleChoiceProps | InputOptionProps | InputSingleChoiceProps | PackageProps | PurchaseButtonProps | RedemptionButtonProps | SkeletonLoaderProps | StackProps | TabControlButtonProps | TabControlToggleProps | TabControlProps | TabsProps | TextNodeProps | TimelineProps | WalletButtonProps | VideoProps;
20
+ export type Component = ButtonProps | CarouselProps | CountdownProps | ExpressPurchaseButtonProps | FooterProps | IconProps | ImageProps | InputMultipleChoiceProps | InputOptionProps | InputSingleChoiceProps | InputTextProps | PackageProps | PurchaseButtonProps | RedemptionButtonProps | SkeletonLoaderProps | StackProps | TabControlButtonProps | TabControlToggleProps | TabControlProps | TabsProps | TextNodeProps | TimelineProps | WalletButtonProps | VideoProps;
@@ -0,0 +1,33 @@
1
+ import type { BorderType, ShapeType, ShadowType, SizeType, Spacing, TextAlignments } from "..";
2
+ import type { BaseComponent } from "../base";
3
+ import type { ColorGradientScheme } from "../colors";
4
+ import type { Overrides } from "../overrides";
5
+ export type InputTextCapitalizeType = "none" | "sentences" | "words" | "characters";
6
+ export type InputTextKeyboardType = "decimal" | "email" | "numeric" | "tel" | "text" | "url";
7
+ export interface InputTextProps extends BaseComponent {
8
+ type: "input_text";
9
+ visible?: boolean | null;
10
+ placeholder_lid: string;
11
+ keyboard_type: InputTextKeyboardType;
12
+ capitalize: InputTextCapitalizeType;
13
+ field_id: string;
14
+ required: boolean;
15
+ size: SizeType;
16
+ padding: Spacing;
17
+ margin: Spacing;
18
+ border?: BorderType | null;
19
+ shape?: ShapeType | null;
20
+ shadow?: ShadowType | null;
21
+ font_name?: string | null;
22
+ font_weight_int?: number | null;
23
+ font_size: number;
24
+ horizontal_alignment: keyof typeof TextAlignments;
25
+ color: ColorGradientScheme;
26
+ placeholder_font_name?: string | null;
27
+ placeholder_font_weight_int?: number | null;
28
+ placeholder_font_size: number;
29
+ placeholder_horizontal_alignment: keyof typeof TextAlignments;
30
+ placeholder_color: ColorGradientScheme;
31
+ background_color?: ColorGradientScheme | null;
32
+ overrides?: Overrides<InputTextProps>;
33
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export type WalletButtonRender = (node: HTMLElement, params: {
2
+ selectedPackageId: string;
3
+ onReady?: (walletButtonAvailable?: boolean) => void;
4
+ }) => {
5
+ destroy?: () => void;
6
+ update?: (updateParams: {
7
+ selectedPackageId: string;
8
+ onReady?: (walletButtonAvailable?: boolean) => void;
9
+ }) => void;
10
+ };
@@ -0,0 +1 @@
1
+ export {};