@revenuecat/purchases-ui-js 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/components/button/ButtonNode.stories.svelte +1 -1
  2. package/dist/components/button/ButtonNode.svelte +11 -4
  3. package/dist/components/package/Package.svelte +3 -1
  4. package/dist/components/paywall/Node.svelte +9 -15
  5. package/dist/components/paywall/Node.svelte.d.ts +1 -7
  6. package/dist/components/paywall/Paywall.stories.svelte +155 -0
  7. package/dist/components/paywall/Paywall.svelte +45 -54
  8. package/dist/components/paywall/Sheet.svelte +126 -0
  9. package/dist/components/paywall/Sheet.svelte.d.ts +4 -0
  10. package/dist/components/paywall/fixtures/background-paywall.d.ts +3 -0
  11. package/dist/components/paywall/fixtures/background-paywall.js +62 -0
  12. package/dist/components/paywall/fixtures/sheet-paywall.d.ts +2 -0
  13. package/dist/components/paywall/fixtures/sheet-paywall.js +325 -0
  14. package/dist/components/tabs/TabControl.svelte +11 -0
  15. package/dist/components/tabs/TabControl.svelte.d.ts +4 -0
  16. package/dist/components/tabs/TabControlButton.svelte +19 -0
  17. package/dist/components/tabs/TabControlButton.svelte.d.ts +4 -0
  18. package/dist/components/tabs/Tabs.stories.svelte +929 -0
  19. package/dist/components/tabs/Tabs.stories.svelte.d.ts +19 -0
  20. package/dist/components/tabs/Tabs.svelte +69 -0
  21. package/dist/components/tabs/Tabs.svelte.d.ts +4 -0
  22. package/dist/components/tabs/tabs-context.d.ts +11 -0
  23. package/dist/components/tabs/tabs-context.js +12 -0
  24. package/dist/stores/selected.d.ts +1 -1
  25. package/dist/stores/selected.js +3 -5
  26. package/dist/types/component.d.ts +5 -4
  27. package/dist/types/components/button.d.ts +2 -1
  28. package/dist/types/components/sheet.d.ts +16 -0
  29. package/dist/types/components/sheet.js +1 -0
  30. package/dist/types/components/tabs.d.ts +46 -0
  31. package/dist/types/components/tabs.js +1 -0
  32. package/dist/types/paywall.d.ts +1 -2
  33. package/dist/types.d.ts +6 -2
  34. package/dist/utils/base-utils.d.ts +1 -1
  35. package/dist/utils/base-utils.js +2 -17
  36. package/dist/utils/style-utils.d.ts +2 -9
  37. package/dist/utils/style-utils.js +1 -23
  38. package/package.json +1 -1
  39. package/dist/components/paywall/paywall-utils.d.ts +0 -8
  40. package/dist/components/paywall/paywall-utils.js +0 -24
@@ -0,0 +1,19 @@
1
+ import Tabs from "./Tabs.svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const Tabs: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, string>;
18
+ type Tabs = InstanceType<typeof Tabs>;
19
+ export default Tabs;
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ import { getColorModeContext } from "../../stores/color-mode";
3
+ import { getSelectedStateContext } from "../../stores/selected";
4
+ import type { TabsProps } from "../../types/components/tabs";
5
+ import { mapBackground } from "../../utils/background-utils";
6
+ import {
7
+ css,
8
+ mapBorder,
9
+ mapBorderRadius,
10
+ mapShadow,
11
+ mapSize,
12
+ mapSpacing,
13
+ } from "../../utils/base-utils";
14
+ import { getActiveStateProps } from "../../utils/style-utils";
15
+ import { derived, readable, writable } from "svelte/store";
16
+ import Stack from "../stack/Stack.svelte";
17
+ import { setTabsContext, type SelectTab } from "./tabs-context";
18
+
19
+ const props: TabsProps = $props();
20
+ const { control, tabs, default_tab_id } = props;
21
+
22
+ const selectedState = getSelectedStateContext();
23
+ const { size, padding, margin, background, shape, border, shadow } =
24
+ $derived.by(() => {
25
+ return {
26
+ ...props,
27
+ ...getActiveStateProps($selectedState, props.overrides),
28
+ };
29
+ });
30
+
31
+ const getColorMode = getColorModeContext();
32
+ const colorMode = $derived(getColorMode());
33
+
34
+ const styles = $derived(
35
+ css({
36
+ width: mapSize(size.width),
37
+ height: mapSize(size.height),
38
+ margin: mapSpacing(margin),
39
+ padding: mapSpacing(padding),
40
+ ...mapBackground(colorMode, null, background),
41
+ border: mapBorder(colorMode, border),
42
+ "border-radius": mapBorderRadius(shape),
43
+ "box-shadow": mapShadow(colorMode, shadow),
44
+ }),
45
+ );
46
+
47
+ const tab = writable(
48
+ tabs.find((tab) => tab.id === default_tab_id) ?? tabs.at(0),
49
+ );
50
+
51
+ const selectTab: SelectTab = (tabId, tabIndex) => {
52
+ const nextTab = tabs.find((tab) => tab.id === tabId) ?? tabs.at(tabIndex);
53
+ if (nextTab !== undefined) {
54
+ tab.set(nextTab);
55
+ }
56
+ };
57
+
58
+ setTabsContext({
59
+ control: readable(control),
60
+ selectedTabId: derived(tab, (tab) => tab.id),
61
+ selectTab,
62
+ });
63
+ </script>
64
+
65
+ <div style={styles}>
66
+ {#if $tab !== undefined}
67
+ <Stack {...$tab.stack} />
68
+ {/if}
69
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { TabsProps } from "../../types/components/tabs";
2
+ declare const Tabs: import("svelte").Component<TabsProps, {}, "">;
3
+ type Tabs = ReturnType<typeof Tabs>;
4
+ export default Tabs;
@@ -0,0 +1,11 @@
1
+ import type { TabControl, TabProps } from "../../types/components/tabs";
2
+ import type { Readable } from "svelte/store";
3
+ export type SelectTab = (tabId: string, tabIndex: number) => void;
4
+ interface TabsContext {
5
+ control: Readable<TabControl>;
6
+ selectedTabId: Readable<TabProps["id"]>;
7
+ selectTab: SelectTab;
8
+ }
9
+ export declare function setTabsContext(context: TabsContext): void;
10
+ export declare function getTabsContext(): TabsContext;
11
+ export {};
@@ -0,0 +1,12 @@
1
+ import { getContext, setContext } from "svelte";
2
+ const key = Symbol("selected");
3
+ export function setTabsContext(context) {
4
+ setContext(key, context);
5
+ }
6
+ export function getTabsContext() {
7
+ const context = getContext(key);
8
+ if (context === undefined) {
9
+ throw new Error("Tabs context not found");
10
+ }
11
+ return context;
12
+ }
@@ -1,5 +1,5 @@
1
1
  import { type Readable } from "svelte/store";
2
2
  type SelectedContext = Readable<boolean>;
3
- export declare function setSelectedStateContext(packageId: string): void;
3
+ export declare function setSelectedStateContext(context: SelectedContext): void;
4
4
  export declare function getSelectedStateContext(): SelectedContext;
5
5
  export {};
@@ -1,10 +1,8 @@
1
1
  import { getContext, setContext } from "svelte";
2
- import { derived, readable } from "svelte/store";
3
- import { getPaywallContext } from "./paywall";
2
+ import { readable } from "svelte/store";
4
3
  const key = Symbol("selected");
5
- export function setSelectedStateContext(packageId) {
6
- const { selectedPackageId } = getPaywallContext();
7
- setContext(key, derived(selectedPackageId, (value) => value === packageId));
4
+ export function setSelectedStateContext(context) {
5
+ setContext(key, context);
8
6
  }
9
7
  export function getSelectedStateContext() {
10
8
  const context = getContext(key);
@@ -1,11 +1,12 @@
1
- import type { TimelineProps } from "./components/timeline";
2
- import type { TextNodeProps } from "./components/text";
3
1
  import type { ButtonProps } from "./components/button";
2
+ import type { CarouselProps } from "./components/carousel";
4
3
  import type { FooterProps } from "./components/footer";
5
4
  import type { IconProps } from "./components/icon";
6
5
  import type { ImageProps } from "./components/image";
7
6
  import type { PackageProps } from "./components/package";
8
7
  import type { PurchaseButtonProps } from "./components/purchase-button";
9
8
  import type { StackProps } from "./components/stack";
10
- import type { CarouselProps } from "./components/carousel";
11
- export type Component = ButtonProps | CarouselProps | FooterProps | IconProps | ImageProps | PackageProps | PurchaseButtonProps | StackProps | TextNodeProps | TimelineProps;
9
+ import type { TabControlButtonProps, TabControlProps, TabsProps } from "./components/tabs";
10
+ import type { TextNodeProps } from "./components/text";
11
+ import type { TimelineProps } from "./components/timeline";
12
+ export type Component = ButtonProps | CarouselProps | FooterProps | IconProps | ImageProps | PackageProps | PurchaseButtonProps | StackProps | TabControlButtonProps | TabControlProps | TabsProps | TextNodeProps | TimelineProps;
@@ -1,5 +1,6 @@
1
1
  import type { BaseComponent } from "../base";
2
2
  import type { Overrides } from "../overrides";
3
+ import type { SheetProps } from "./sheet";
3
4
  import type { StackProps } from "./stack";
4
5
  interface RestorePurchasesAction {
5
6
  type: "restore_purchases";
@@ -14,7 +15,7 @@ interface NavigateToAction {
14
15
  interface NavigateToSheetAction {
15
16
  type: "navigate_to";
16
17
  destination: "sheet";
17
- sheet?: unknown;
18
+ sheet?: SheetProps | null;
18
19
  }
19
20
  interface NavigateToWebPurchase {
20
21
  type: "navigate_to";
@@ -0,0 +1,16 @@
1
+ import type { SizeType } from "..";
2
+ import type { Background } from "../background";
3
+ import type { BaseComponent } from "../base";
4
+ import type { Overrides } from "../overrides";
5
+ import type { StackProps } from "./stack";
6
+ type SheetPosition = "bottom" | "top" | "center" | "left" | "right";
7
+ export interface SheetProps extends BaseComponent {
8
+ type: "sheet";
9
+ stack: StackProps;
10
+ size: SizeType;
11
+ background?: Background | null;
12
+ background_blur: boolean;
13
+ position?: SheetPosition;
14
+ overrides?: Overrides<SheetProps>;
15
+ }
16
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import type { BorderType, ShadowType, ShapeType, SizeType, Spacing } from "..";
2
+ import type { Background } from "../background";
3
+ import type { BaseComponent } from "../base";
4
+ import type { Overrides } from "../overrides";
5
+ import type { StackProps } from "./stack";
6
+ type TabControlType = "buttons" | "toggle";
7
+ export interface TabControl {
8
+ type: TabControlType;
9
+ stack: StackProps;
10
+ }
11
+ export interface TabProps extends BaseComponent {
12
+ type: "tab";
13
+ stack: StackProps;
14
+ overrides?: Overrides<TabProps>;
15
+ }
16
+ export interface TabsProps extends BaseComponent {
17
+ type: "tabs";
18
+ visible?: boolean | null;
19
+ size: SizeType;
20
+ padding: Spacing;
21
+ margin: Spacing;
22
+ control: TabControl;
23
+ tabs: TabProps[];
24
+ default_tab_id: string;
25
+ background?: Background | null;
26
+ shape?: ShapeType | null;
27
+ border?: BorderType | null;
28
+ shadow?: ShadowType | null;
29
+ overrides?: Overrides<TabsProps>;
30
+ }
31
+ export interface TabControlProps extends BaseComponent {
32
+ type: "tab_control";
33
+ overrides?: Overrides<TabControlProps>;
34
+ }
35
+ export interface TabControlButtonProps extends BaseComponent {
36
+ type: "tab_control_button";
37
+ tab_id: string;
38
+ stack: StackProps;
39
+ overrides?: Overrides<TabControlButtonProps>;
40
+ /**
41
+ * @deprecated Use `tab_id` instead. This stores the index of the tab the control is related to,
42
+ * we'll utilize the `tab_id` field instead but need this for backwards compatibility
43
+ */
44
+ tab_index: number;
45
+ }
46
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -2,7 +2,7 @@ import type { Background } from "./background";
2
2
  import type { FooterProps } from "./components/footer";
3
3
  import type { StackProps } from "./components/stack";
4
4
  import type { Localizations } from "./localization";
5
- interface RootPaywall {
5
+ export interface RootPaywall {
6
6
  background?: Background;
7
7
  stack: StackProps;
8
8
  sticky_footer?: FooterProps | null;
@@ -24,4 +24,3 @@ export interface PaywallData {
24
24
  components_config: ComponentConfig;
25
25
  components_localizations: Localizations;
26
26
  }
27
- export {};
package/dist/types.d.ts CHANGED
@@ -45,10 +45,14 @@ type FixedSize = {
45
45
  value: number;
46
46
  };
47
47
  type RelativeSize = {
48
- type: "fit" | "fill" | "relative";
48
+ type: "relative";
49
+ value: number;
50
+ };
51
+ type FitFillSize = {
52
+ type: "fit" | "fill";
49
53
  value?: null;
50
54
  };
51
- export type Size = FixedSize | RelativeSize;
55
+ export type Size = FixedSize | RelativeSize | FitFillSize;
52
56
  export type SizeType = {
53
57
  width: Size;
54
58
  height: Size;
@@ -8,7 +8,7 @@ export declare function mapColorMode<T>(colorMode: ColorMode, value: {
8
8
  light: T;
9
9
  dark?: T | null;
10
10
  }): T;
11
- export declare function mapSize(size: Size, deviceFrameElement?: HTMLElement | null): string;
11
+ export declare function mapSize(size: Size): string;
12
12
  export declare function mapSpacing(spacing?: Spacing | null): string;
13
13
  export declare function mapColor(colorMode: ColorMode, scheme: ColorScheme | ColorGradientScheme | null | undefined): string;
14
14
  export declare function mapOverlay(colorMode: ColorMode, colorOverlay: ColorGradientScheme | null | undefined): string;
@@ -14,7 +14,7 @@ export function mapColorMode(colorMode, value) {
14
14
  const result = value[colorMode];
15
15
  return result ?? value.light;
16
16
  }
17
- export function mapSize(size, deviceFrameElement) {
17
+ export function mapSize(size) {
18
18
  switch (size.type) {
19
19
  case "fill":
20
20
  // Support both webkit and mozilla browsers
@@ -29,22 +29,7 @@ export function mapSize(size, deviceFrameElement) {
29
29
  case "fixed":
30
30
  return px(size.value);
31
31
  case "relative": {
32
- // TODO(marek): Good enough for now.
33
- if (!deviceFrameElement) {
34
- console.error("[mapSizeConstraint] Device frame element is not available");
35
- return `${(size.value ?? 0) * 100}%`;
36
- }
37
- // getBoundingClientRect returns device pixel values that may be affected by CSS transforms
38
- // due to phone preview scaling.
39
- // We need to account for any scaling that may be applied to the element
40
- const rect = deviceFrameElement.getBoundingClientRect();
41
- const computedStyle = window.getComputedStyle(
42
- // Need to go up two levels to get the transformed viewport element.
43
- deviceFrameElement.parentNode?.parentNode);
44
- const { transform } = computedStyle;
45
- const scale = transform === "none" ? 1 : parseFloat(transform.split("(")[1]);
46
- const height = rect.height / (scale || 1);
47
- return px((size.value ?? 0) * height);
32
+ return `${size.value * 100}%`;
48
33
  }
49
34
  }
50
35
  }
@@ -2,7 +2,7 @@ import type { ColorGradientScheme } from "../types/colors.js";
2
2
  import type { Component } from "../types/component.js";
3
3
  import type { TextNodeProps } from "../types/components/text";
4
4
  import type { Overrides } from "../types/overrides.js";
5
- import type { PaywallData } from "../types/paywall.js";
5
+ import type { RootPaywall } from "../types/paywall.js";
6
6
  import { type ColorMode } from "../types.js";
7
7
  /**
8
8
  * Gets color value based on color mode with fallback
@@ -30,18 +30,11 @@ type TextStyleVariables = {
30
30
  * @returns CSS style object with text formatting properties
31
31
  */
32
32
  export declare function getTextStyles(props: TextNodeProps): TextStyleVariables;
33
- /**
34
- * Converts a style object to a CSS string
35
- * @param styles - Object containing CSS properties and values
36
- * @returns CSS string
37
- */
38
- export declare function stringifyStyles(styles: Record<string, string | number>): string;
39
33
  /**
40
34
  * Given an instance of PaywallData, returns the id of the first package marked as `is_selected_by_default` if any.
41
35
  * @param paywallData
42
36
  * @returns the id of the first package marked as `is_selected_by_default` or undefined
43
37
  */
44
- export declare function findSelectedPackageId(paywallData: PaywallData): string | undefined;
38
+ export declare function findSelectedPackageId({ stack, sticky_footer, }: RootPaywall): string | undefined;
45
39
  export declare const getActiveStateProps: <T extends Component>(selectedState: boolean, overrides?: Overrides<T>) => Partial<T>;
46
- export declare function prefixObject(object?: Record<string, string | number>, prefix?: string): Record<string, string | number>;
47
40
  export {};
@@ -64,22 +64,12 @@ export function getTextStyles(props) {
64
64
  });
65
65
  return styles;
66
66
  }
67
- /**
68
- * Converts a style object to a CSS string
69
- * @param styles - Object containing CSS properties and values
70
- * @returns CSS string
71
- */
72
- export function stringifyStyles(styles) {
73
- return Object.entries(styles)
74
- .map(([key, value]) => `${key}: ${value}`)
75
- .join("; ");
76
- }
77
67
  /**
78
68
  * Given an instance of PaywallData, returns the id of the first package marked as `is_selected_by_default` if any.
79
69
  * @param paywallData
80
70
  * @returns the id of the first package marked as `is_selected_by_default` or undefined
81
71
  */
82
- export function findSelectedPackageId(paywallData) {
72
+ export function findSelectedPackageId({ stack, sticky_footer, }) {
83
73
  const traverseNode = (node) => {
84
74
  if (node.type === "package" && node.is_selected_by_default) {
85
75
  return node;
@@ -100,7 +90,6 @@ export function findSelectedPackageId(paywallData) {
100
90
  }
101
91
  return undefined;
102
92
  };
103
- const { stack, sticky_footer } = paywallData.components_config.base;
104
93
  const pkg = traverseNode(stack);
105
94
  if (pkg !== undefined) {
106
95
  return pkg?.package_id;
@@ -120,14 +109,3 @@ export const getActiveStateProps = (selectedState, overrides) => {
120
109
  const override = overrides?.find((override) => override.conditions.find((condition) => condition.type === "selected"));
121
110
  return override?.properties ?? {};
122
111
  };
123
- export function prefixObject(object, prefix) {
124
- if (!object)
125
- return {};
126
- if (!prefix)
127
- return object;
128
- return Object.entries(object).reduce((acc, [key, value]) => {
129
- const replacedKey = key.replace(/^--/, `${prefix}-`);
130
- acc[`--${replacedKey}`] = value;
131
- return acc;
132
- }, {});
133
- }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@revenuecat/purchases-ui-js",
3
3
  "description": "Web components for Paywalls. Powered by RevenueCat",
4
4
  "private": false,
5
- "version": "2.0.4",
5
+ "version": "2.0.5",
6
6
  "author": {
7
7
  "name": "RevenueCat, Inc."
8
8
  },
@@ -1,8 +0,0 @@
1
- import type { ColorMode } from "../../types";
2
- import type { Background } from "../../types/background";
3
- import type { PaywallData } from "../../types/paywall";
4
- export declare function getBackgroundStyles({ background, colorMode, }: {
5
- background?: Background;
6
- colorMode: ColorMode;
7
- }): string;
8
- export declare function getBackgroundImageSource(paywallData: PaywallData, colorMode: ColorMode): string | undefined;
@@ -1,24 +0,0 @@
1
- import { DEFAULT_COLOR_MODE } from "../../utils/constants";
2
- import { getColor, prefixObject, stringifyStyles, } from "../../utils/style-utils";
3
- export function getBackgroundStyles({ background, colorMode, }) {
4
- const styles = { "--background": "initial" };
5
- if (background?.type === "color") {
6
- Object.assign(styles, {
7
- "--background": getColor({
8
- colorMap: background.value,
9
- colorMode,
10
- fallback: "transparent",
11
- }),
12
- });
13
- }
14
- const prefixedStyles = prefixObject(styles, "paywall");
15
- return stringifyStyles(prefixedStyles);
16
- }
17
- export function getBackgroundImageSource(paywallData, colorMode) {
18
- const { background } = paywallData.components_config.base;
19
- if (background?.type !== "image") {
20
- return "";
21
- }
22
- const { value } = background;
23
- return value[colorMode]?.original ?? value[DEFAULT_COLOR_MODE]?.original;
24
- }