@developer_tribe/react-builder 1.2.14 → 1.2.17

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 (183) hide show
  1. package/dist/build-components/BIcon/BIconProps.generated.d.ts +2 -0
  2. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +2 -0
  3. package/dist/build-components/Button/ButtonProps.generated.d.ts +2 -0
  4. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +2 -0
  5. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +2 -0
  6. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +2 -0
  7. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +2 -0
  8. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +2 -0
  9. package/dist/build-components/CountDown/CountDown.d.ts +2 -0
  10. package/dist/build-components/CountDown/CountDownProps.generated.d.ts +61 -0
  11. package/dist/build-components/CountDown/formatCountdownTime.d.ts +1 -0
  12. package/dist/build-components/Counter/Counter.d.ts +2 -0
  13. package/dist/build-components/Counter/CounterProps.generated.d.ts +61 -0
  14. package/dist/build-components/Image/ImageProps.generated.d.ts +2 -0
  15. package/dist/build-components/Main/MainProps.generated.d.ts +2 -0
  16. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +2 -0
  17. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +2 -0
  18. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +2 -0
  19. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +2 -0
  20. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +2 -0
  21. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +2 -0
  22. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +2 -0
  23. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
  24. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +2 -0
  25. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +2 -0
  26. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +2 -0
  27. package/dist/build-components/PaywallCloseButton/PaywallCloseButton.d.ts +1 -1
  28. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +2 -0
  29. package/dist/build-components/PaywallCounter/PaywallCounter.d.ts +2 -0
  30. package/dist/build-components/PaywallCounter/PaywallCounterProps.generated.d.ts +61 -0
  31. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +2 -0
  32. package/dist/build-components/PaywallProvider/PaywallContext.d.ts +2 -1
  33. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +3 -0
  34. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +2 -0
  35. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +2 -0
  36. package/dist/build-components/Text/TextProps.generated.d.ts +2 -0
  37. package/dist/build-components/View/ViewProps.generated.d.ts +2 -0
  38. package/dist/build-components/index.d.ts +4 -1
  39. package/dist/build-components/patterns.generated.d.ts +2969 -1550
  40. package/dist/components/BuilderProvider.d.ts +0 -1
  41. package/dist/index.cjs.js +4 -4
  42. package/dist/index.cjs.js.map +1 -1
  43. package/dist/index.d.ts +2 -1
  44. package/dist/index.esm.js +4 -4
  45. package/dist/index.esm.js.map +1 -1
  46. package/dist/index.native.d.ts +7 -0
  47. package/dist/index.web.cjs.js +7 -5
  48. package/dist/index.web.cjs.js.map +1 -1
  49. package/dist/index.web.esm.js +7 -5
  50. package/dist/index.web.esm.js.map +1 -1
  51. package/dist/mockOS/backHandler.d.ts +4 -0
  52. package/dist/paywall/hooks/index.d.ts +3 -3
  53. package/dist/paywall/hooks/useChangeDelayByPaywall.d.ts +4 -0
  54. package/dist/paywall/hooks/useHandleGoBack.d.ts +1 -0
  55. package/dist/paywall/hooks/useMockOSBackHandler.d.ts +1 -0
  56. package/dist/utils/getDefaultProject.d.ts +4 -0
  57. package/dist/utils/patterns.d.ts +3 -0
  58. package/package.json +5 -1
  59. package/scripts/prebuild/utils/createComponentTsx.js +1 -1
  60. package/scripts/prebuild/utils/createGeneratedProps.js +6 -2
  61. package/scripts/prebuild/utils/createRenderNodeGenerated.js +26 -5
  62. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +17 -5
  63. package/scripts/prebuild/utils/validateExistingComponentTsx.js +12 -8
  64. package/src/AttributesEditor.tsx +7 -2
  65. package/src/RenderPage.tsx +34 -3
  66. package/src/assets/meta.json +1 -1
  67. package/src/assets/samples/carousel-sample.json +44 -14
  68. package/src/assets/samples/getSamples.ts +3 -1
  69. package/src/assets/samples/paywall-1.json +73 -29
  70. package/src/assets/samples/paywall-2.json +339 -0
  71. package/src/assets/samples/simple-1.json +9 -3
  72. package/src/assets/samples/simple-2.json +72 -24
  73. package/src/assets/samples/unmigrated-builder-1.1.1.json +19 -7
  74. package/src/assets/samples/unmigrated-builder1.json +10 -4
  75. package/src/assets/samples/unvalidated-builder1.json +10 -4
  76. package/src/assets/samples/unvalidated-crash1.json +3 -1
  77. package/src/assets/samples/unvalidated-crashcomponent1.json +3 -1
  78. package/src/assets/samples/vpn-onboard-1.json +88 -40
  79. package/src/assets/samples/vpn-onboard-2.json +85 -37
  80. package/src/assets/samples/vpn-onboard-3.json +93 -45
  81. package/src/assets/samples/vpn-onboard-4.json +93 -45
  82. package/src/assets/samples/vpn-onboard-5.json +121 -53
  83. package/src/assets/samples/vpn-onboard-6.json +93 -45
  84. package/src/attributes-editor/AttributesEditorView.tsx +39 -1
  85. package/src/attributes-editor/Field.tsx +30 -0
  86. package/src/build-components/BIcon/BIconProps.generated.ts +2 -0
  87. package/src/build-components/BIcon/pattern.json +2 -0
  88. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +2 -0
  89. package/src/build-components/BackgroundImage/pattern.json +2 -0
  90. package/src/build-components/Button/ButtonProps.generated.ts +2 -0
  91. package/src/build-components/Button/pattern.json +2 -0
  92. package/src/build-components/Carousel/CarouselProps.generated.ts +2 -0
  93. package/src/build-components/Carousel/pattern.json +2 -0
  94. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +2 -0
  95. package/src/build-components/CarouselButtons/pattern.json +2 -0
  96. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +2 -0
  97. package/src/build-components/CarouselDots/pattern.json +2 -0
  98. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +2 -0
  99. package/src/build-components/CarouselItem/pattern.json +4 -1
  100. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +2 -0
  101. package/src/build-components/CarouselProvider/pattern.json +4 -1
  102. package/src/build-components/CountDown/CountDown.tsx +81 -0
  103. package/src/build-components/CountDown/CountDownProps.generated.ts +78 -0
  104. package/src/build-components/CountDown/formatCountdownTime.ts +10 -0
  105. package/src/build-components/CountDown/pattern.json +24 -0
  106. package/src/build-components/Counter/Counter.tsx +44 -0
  107. package/src/build-components/Counter/CounterProps.generated.ts +78 -0
  108. package/src/build-components/Counter/pattern.json +26 -0
  109. package/src/build-components/Image/ImageProps.generated.ts +2 -0
  110. package/src/build-components/Image/pattern.json +2 -0
  111. package/src/build-components/Main/MainProps.generated.ts +2 -0
  112. package/src/build-components/Main/pattern.json +2 -0
  113. package/src/build-components/Onboard/OnboardProps.generated.ts +2 -0
  114. package/src/build-components/Onboard/pattern.json +4 -1
  115. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +2 -0
  116. package/src/build-components/OnboardButton/pattern.json +2 -0
  117. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +2 -0
  118. package/src/build-components/OnboardButtons/pattern.json +2 -0
  119. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +2 -0
  120. package/src/build-components/OnboardDot/pattern.json +2 -0
  121. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +2 -0
  122. package/src/build-components/OnboardFooter/pattern.json +2 -0
  123. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +2 -0
  124. package/src/build-components/OnboardImage/pattern.json +2 -0
  125. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +2 -0
  126. package/src/build-components/OnboardItem/pattern.json +2 -0
  127. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +2 -0
  128. package/src/build-components/OnboardProvider/pattern.json +2 -0
  129. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +2 -0
  130. package/src/build-components/OnboardSubtitle/pattern.json +4 -1
  131. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +2 -0
  132. package/src/build-components/OnboardTitle/pattern.json +4 -1
  133. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +2 -0
  134. package/src/build-components/PaywallBackground/pattern.json +4 -1
  135. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +12 -6
  136. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +2 -0
  137. package/src/build-components/PaywallCloseButton/pattern.json +7 -1
  138. package/src/build-components/PaywallCounter/PaywallCounter.tsx +46 -0
  139. package/src/build-components/PaywallCounter/PaywallCounterProps.generated.ts +78 -0
  140. package/src/build-components/PaywallCounter/pattern.json +24 -0
  141. package/src/build-components/PaywallOptions/PaywallOptions.tsx +2 -2
  142. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +2 -0
  143. package/src/build-components/PaywallOptions/pattern.json +4 -1
  144. package/src/build-components/PaywallProvider/PaywallContext.ts +4 -2
  145. package/src/build-components/PaywallProvider/PaywallProvider.tsx +51 -21
  146. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +3 -0
  147. package/src/build-components/PaywallProvider/pattern.json +14 -1
  148. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +2 -0
  149. package/src/build-components/PaywallSubscribeButton/pattern.json +4 -1
  150. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +2 -0
  151. package/src/build-components/RadioButton/pattern.json +2 -0
  152. package/src/build-components/RenderNode.generated.tsx +17 -2
  153. package/src/build-components/Text/TextProps.generated.ts +2 -0
  154. package/src/build-components/Text/pattern.json +3 -1
  155. package/src/build-components/View/View.tsx +1 -1
  156. package/src/build-components/View/ViewProps.generated.ts +2 -0
  157. package/src/build-components/View/pattern.json +35 -38
  158. package/src/build-components/index.ts +15 -0
  159. package/src/build-components/patterns.generated.ts +3094 -1569
  160. package/src/components/BuilderButton.tsx +23 -6
  161. package/src/components/BuilderProvider.tsx +10 -7
  162. package/src/components/DeviceNavigationBar.tsx +5 -0
  163. package/src/index.native.ts +7 -0
  164. package/src/index.ts +2 -3
  165. package/src/mockOS/backHandler.ts +35 -0
  166. package/src/mockOS/context/MockOSContext.tsx +22 -8
  167. package/src/mockOS/managers/navigationManager.ts +4 -0
  168. package/src/pages/ProjectMigrationPage.tsx +10 -1
  169. package/src/pages/ProjectPage.tsx +7 -0
  170. package/src/pages/projectPageUtils.ts +3 -2
  171. package/src/paywall/hooks/index.ts +3 -3
  172. package/src/paywall/hooks/useChangeDelayByPaywall.ts +25 -0
  173. package/src/paywall/hooks/useHandleGoBack.ts +60 -0
  174. package/src/paywall/hooks/useMockOSBackHandler.ts +9 -0
  175. package/src/utils/analyseNodeByPatterns.ts +21 -0
  176. package/src/utils/getDefaultProject.ts +34 -0
  177. package/src/utils/patterns.ts +6 -7
  178. package/dist/paywall/hooks/useCarouselOptionsSeperator.d.ts +0 -6
  179. package/dist/paywall/hooks/useCloseStatusPaywall.d.ts +0 -4
  180. package/dist/paywall/hooks/usePaywallCounter.d.ts +0 -4
  181. package/src/paywall/hooks/useCarouselOptionsSeperator.ts +0 -8
  182. package/src/paywall/hooks/useCloseStatusPaywall.ts +0 -6
  183. package/src/paywall/hooks/usePaywallCounter.ts +0 -6
@@ -0,0 +1,46 @@
1
+ import React, { useId } from 'react';
2
+ import type { PaywallCounterComponentProps } from './PaywallCounterProps.generated';
3
+ import useNode from '../useNode';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
+ import { useExtractTextStyle } from '../../attribute-analyser/style/web/useExtractTextStyle';
6
+ import { useLogRender } from '../../utils/useLogRender';
7
+ import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
+ import { useMergedStyle } from '../../utils/useMergedStyle';
9
+
10
+ //Optimzation trade off by readability: skip React.memo to keep named exports.
11
+ export function PaywallCounter({ node }: PaywallCounterComponentProps) {
12
+ useLogRender('PaywallCounter');
13
+ node = useNode(node);
14
+
15
+ const generatedId = useId();
16
+ const attributeName = node.sourceType ?? node.type ?? 'PaywallCounter';
17
+ const attributeKey = node.key ?? generatedId;
18
+
19
+ const { previewMode, selectedKey } = useBuilderParams();
20
+ const baseStyle = useExtractTextStyle(node);
21
+ const isSelected = isNodeSelected({
22
+ previewMode: !!previewMode,
23
+ current: selectedKey ? { key: selectedKey } : undefined,
24
+ node,
25
+ });
26
+ const style = useMergedStyle(
27
+ baseStyle,
28
+ isSelected ? SELECTED_OUTLINE_STYLE : undefined,
29
+ );
30
+
31
+ const fallbackCount = node.attributes?.count;
32
+ const count =
33
+ typeof fallbackCount === 'number' && Number.isFinite(fallbackCount)
34
+ ? fallbackCount
35
+ : 0;
36
+
37
+ return (
38
+ <p
39
+ attribute-name={attributeName}
40
+ attribute-key={attributeKey}
41
+ style={style}
42
+ >
43
+ {String(count)}
44
+ </p>
45
+ );
46
+ }
@@ -0,0 +1,78 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type TextAlignOptionType = 'left' | 'center' | 'right' | 'justify';
6
+ export type FlexDirectionOptionType = 'row' | 'column';
7
+ export type AlignItemsOptionType =
8
+ | 'flex-start'
9
+ | 'center'
10
+ | 'flex-end'
11
+ | 'stretch'
12
+ | 'baseline';
13
+ export type JustifyContentOptionType =
14
+ | 'flex-start'
15
+ | 'center'
16
+ | 'flex-end'
17
+ | 'space-between'
18
+ | 'space-around'
19
+ | 'space-evenly';
20
+ export type PositionOptionType = 'relative' | 'absolute';
21
+
22
+ export interface PaywallCounterStyleGenerated {
23
+ color?: string;
24
+ fontSize?: string;
25
+ fontFamily?: string;
26
+ fontWeight?: string;
27
+ textAlign?: TextAlignOptionType;
28
+ flexDirection?: FlexDirectionOptionType;
29
+ alignItems?: AlignItemsOptionType;
30
+ justifyContent?: JustifyContentOptionType;
31
+ gap?: string;
32
+ padding?: string;
33
+ paddingHorizontal?: string;
34
+ paddingVertical?: string;
35
+ paddingTop?: string;
36
+ paddingBottom?: string;
37
+ paddingLeft?: string;
38
+ paddingRight?: string;
39
+ margin?: string;
40
+ marginHorizontal?: string;
41
+ marginVertical?: string;
42
+ marginTop?: string;
43
+ marginBottom?: string;
44
+ marginLeft?: string;
45
+ marginRight?: string;
46
+ backgroundColor?: string;
47
+ borderRadius?: string;
48
+ width?: string;
49
+ minWidth?: string;
50
+ maxWidth?: string;
51
+ height?: string;
52
+ minHeight?: string;
53
+ maxHeight?: string;
54
+ flex?: number;
55
+ position?: PositionOptionType;
56
+ top?: string;
57
+ bottom?: string;
58
+ left?: string;
59
+ right?: string;
60
+ zIndex?: number;
61
+ }
62
+
63
+ export interface PaywallCounterPropsGenerated {
64
+ child: string;
65
+ attributes: {
66
+ style?: PaywallCounterStyleGenerated;
67
+ count?: number;
68
+ title?: string;
69
+ description?: string;
70
+ adjustsFontSizeToFit?: boolean;
71
+ showEllipsis?: boolean;
72
+ scrollable?: boolean;
73
+ };
74
+ }
75
+
76
+ export interface PaywallCounterComponentProps {
77
+ node: NodeData<PaywallCounterPropsGenerated['attributes']>;
78
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "PaywallCounter",
5
+ "children": "never",
6
+ "extends": "Counter",
7
+ "attributes": {}
8
+ },
9
+ "meta": {
10
+ "desiredParent": ["all"],
11
+ "label": "Paywall Counter",
12
+ "description": "Displays the paywall counter value.",
13
+ "attributes": {
14
+ "count": {
15
+ "label": "Fallback Count",
16
+ "description": "Used only when the paywall counter hook returns no value.",
17
+ "category": "other",
18
+ "specialCategory": null,
19
+ "sort": 1
20
+ }
21
+ }
22
+ }
23
+ }
24
+
@@ -52,7 +52,7 @@ function PaywallOptions({ node }: PaywallOptionsComponentProps) {
52
52
  useLogRender('PaywallOptions');
53
53
  node = useNode(node);
54
54
  const { products } = useBuilderParams();
55
- const { selectedProductId, setSelectedProductId } = usePaywallContext();
55
+ const { selectedProduct, setSelectedProductId } = usePaywallContext();
56
56
  const getParamsForProduct = usePaywallOptionParamsFactory();
57
57
 
58
58
  const sortedProducts = useMemo(() => {
@@ -67,7 +67,7 @@ function PaywallOptions({ node }: PaywallOptionsComponentProps) {
67
67
  <>
68
68
  {sortedProducts.map((p, index) => {
69
69
  const productId = p.productId || `${index}`;
70
- const isSelected = selectedProductId === productId;
70
+ const isSelected = selectedProduct?.productId === productId;
71
71
  const { localizationParams, otherParams } = getParamsForProduct(p, {
72
72
  isSelected,
73
73
  });
@@ -58,6 +58,8 @@ export interface PaywallOptionsPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: PaywallOptionsStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
62
64
  };
63
65
  }
@@ -4,7 +4,10 @@
4
4
  "type": "PaywallOptions",
5
5
  "extends": "View",
6
6
  "children": "node",
7
- "attributes": {}
7
+ "attributes": {
8
+ "title": "title",
9
+ "description": "description"
10
+ }
8
11
  },
9
12
  "meta": {
10
13
  "desiredParent": [
@@ -3,11 +3,12 @@ import type { Product } from '../../paywall/types/paywall-types';
3
3
 
4
4
  export type PaywallContextValue = {
5
5
  products: Product[];
6
- selectedProductId: string;
7
6
  setSelectedProductId: (productId: string) => void;
8
7
  selectedProduct?: Product;
9
8
  onClose?: () => void;
10
9
  onSubscribe?: (product?: Product) => void | boolean | Promise<boolean>;
10
+ onCounterDown?: () => void;
11
+ isBackAllowed: boolean;
11
12
  };
12
13
 
13
14
  export const PaywallContext = createContext<PaywallContextValue | undefined>(
@@ -18,8 +19,9 @@ export function usePaywallContext(): PaywallContextValue {
18
19
  return (
19
20
  useContext(PaywallContext) ?? {
20
21
  products: [],
21
- selectedProductId: '',
22
22
  setSelectedProductId: () => {},
23
+ onCounterDown: () => {},
24
+ isBackAllowed: true,
23
25
  }
24
26
  );
25
27
  }
@@ -11,6 +11,10 @@ import { LocalizationParamsProvider } from '../../components/LocalizationParamsP
11
11
  import { useBuilderParams } from '../../components/BuilderProvider';
12
12
  import { PaywallContext } from './PaywallContext';
13
13
  import { useMockOSContext } from '../../mockOS/context/MockOSContextBase';
14
+ import type { Product } from '../../paywall/types/paywall-types';
15
+ import { useChangeDelayByPaywall } from '../../paywall/hooks/useChangeDelayByPaywall';
16
+ import { useHandleGoBack } from '../../paywall/hooks/useHandleGoBack';
17
+ import { useMockOSBackHandler } from '../../paywall/hooks/useMockOSBackHandler';
14
18
 
15
19
  function PaywallProvider({ node }: PaywallProviderComponentProps) {
16
20
  useLogRender('PaywallProvider');
@@ -20,14 +24,8 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
20
24
  const attributeName = node.sourceType ?? node.type ?? 'PaywallProvider';
21
25
  const attributeKey = node.key ?? generatedId;
22
26
 
23
- const {
24
- benefits,
25
- products,
26
- onPaywallClose,
27
- onPaywallSubscribe,
28
- previewMode,
29
- selectedKey,
30
- } = useBuilderParams();
27
+ const { benefits, products, onPaywallSubscribe, previewMode, selectedKey } =
28
+ useBuilderParams();
31
29
  const mockOS = useMockOSContext();
32
30
  const benefitLocalizationParams = useMemo(() => {
33
31
  const raw =
@@ -63,6 +61,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
63
61
  );
64
62
 
65
63
  const [selectedProductId, setSelectedProductId] = useState<string>('');
64
+ const [isBackAllowed, setIsBackAllowed] = useState<boolean>(false);
66
65
  useEffect(() => {
67
66
  const list = Array.isArray(products) ? products : [];
68
67
  if (list.length === 0) {
@@ -76,6 +75,9 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
76
75
  }
77
76
  }, [products, selectedProductId]);
78
77
 
78
+ useChangeDelayByPaywall(node, setIsBackAllowed);
79
+ useMockOSBackHandler(isBackAllowed);
80
+
79
81
  const selectedProduct = useMemo(() => {
80
82
  const list = Array.isArray(products) ? products : [];
81
83
  return (
@@ -85,23 +87,33 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
85
87
  }, [products, selectedProductId]);
86
88
 
87
89
  const handleClose = useCallback(() => {
88
- // Host app override wins.
89
- if (onPaywallClose) {
90
- onPaywallClose();
90
+ if (!isBackAllowed) {
91
+ return;
91
92
  }
92
-
93
93
  // Default: in MockOS go back (simulate dismissing paywall screen).
94
94
  // TODO: at react native merge it will change
95
- if (mockOS?.isEnabled && mockOS.goBack) {
96
- mockOS.goBack();
95
+ if (mockOS?.isEnabled) {
96
+ const canGoBack = mockOS.goBack();
97
+ if (!canGoBack) {
98
+ mockOS.navigation('launchscreen');
99
+ }
97
100
  }
98
- }, [mockOS, onPaywallClose]);
101
+ }, [mockOS, isBackAllowed]);
102
+
103
+ const handleGoBack = useCallback(() => {
104
+ if (!isBackAllowed) {
105
+ return false;
106
+ }
107
+ return true;
108
+ }, [isBackAllowed]);
109
+
110
+ useHandleGoBack(handleGoBack);
99
111
 
100
112
  const handleSubscribe = useCallback(
101
- async (product?: { productId?: string }) => {
113
+ async (product?: Product): Promise<boolean> => {
102
114
  // Host app override wins.
103
115
  if (onPaywallSubscribe) {
104
- const result = onPaywallSubscribe(product as any);
116
+ const result = onPaywallSubscribe(product);
105
117
  const ok =
106
118
  result instanceof Promise
107
119
  ? await result
@@ -113,7 +125,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
113
125
  if (ok && mockOS?.isEnabled) {
114
126
  mockOS.goBack?.();
115
127
  }
116
- return;
128
+ return ok;
117
129
  }
118
130
 
119
131
  // Default: in MockOS show a native-like subscription prompt.
@@ -130,26 +142,44 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
130
142
  // TODO: at react native merge it will change
131
143
  mockOS.goBack?.();
132
144
  }
145
+ return ok;
133
146
  }
147
+ return false;
134
148
  },
135
149
  [mockOS, onPaywallSubscribe],
136
150
  );
137
151
 
152
+ const handleCounterDown = useCallback(() => {
153
+ if (!isBackAllowed) {
154
+ return;
155
+ }
156
+ // Default: in MockOS go back (simulate dismissing paywall screen).
157
+ // TODO: at react native merge it will change
158
+ if (mockOS?.isEnabled) {
159
+ const canGoBack = mockOS.goBack();
160
+ if (!canGoBack) {
161
+ mockOS.navigation('launchscreen');
162
+ }
163
+ }
164
+ }, [isBackAllowed, mockOS]);
165
+
138
166
  const paywallContextValue = useMemo(
139
167
  () => ({
140
168
  products: Array.isArray(products) ? products : [],
141
- selectedProductId,
142
169
  setSelectedProductId,
143
170
  selectedProduct,
144
171
  onClose: handleClose,
145
- onSubscribe: handleSubscribe as any,
172
+ onSubscribe: handleSubscribe,
173
+ onCounterDown: handleCounterDown,
174
+ isBackAllowed,
146
175
  }),
147
176
  [
148
177
  products,
149
- selectedProductId,
150
178
  selectedProduct,
151
179
  handleClose,
152
180
  handleSubscribe,
181
+ handleCounterDown,
182
+ isBackAllowed,
153
183
  ],
154
184
  );
155
185
 
@@ -58,7 +58,10 @@ export interface PaywallProviderPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: PaywallProviderStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
64
+ delay?: number;
62
65
  };
63
66
  }
64
67
 
@@ -4,7 +4,11 @@
4
4
  "type": "PaywallProvider",
5
5
  "children": "node",
6
6
  "extends": "View",
7
- "attributes": {}
7
+ "attributes": {
8
+ "title": "title",
9
+ "description": "description",
10
+ "delay": "number"
11
+ }
8
12
  },
9
13
  "defaults": {
10
14
  "style": {
@@ -18,6 +22,15 @@
18
22
  ],
19
23
  "label": "Paywall Provider",
20
24
  "description": "Provider/wrapper for paywall screen components.",
25
+ "attributes": {
26
+ "delay": {
27
+ "label": "Back Delay (ms)",
28
+ "description": "Milliseconds before the paywall can be dismissed via back/close.",
29
+ "category": "other",
30
+ "specialCategory": null,
31
+ "sort": 1
32
+ }
33
+ },
21
34
  "mockableFeatures": {
22
35
  "products": true,
23
36
  "benefits": true
@@ -73,6 +73,8 @@ export interface PaywallSubscribeButtonPropsGenerated {
73
73
  child: string;
74
74
  attributes: {
75
75
  style?: PaywallSubscribeButtonStyleGenerated;
76
+ title?: string;
77
+ description?: string;
76
78
  scrollable?: boolean;
77
79
  };
78
80
  }
@@ -4,7 +4,10 @@
4
4
  "type": "PaywallSubscribeButton",
5
5
  "children": "string",
6
6
  "extends": "Button",
7
- "attributes": {}
7
+ "attributes": {
8
+ "title": "title",
9
+ "description": "description"
10
+ }
8
11
  },
9
12
  "defaults": {
10
13
  "style": {
@@ -58,6 +58,8 @@ export interface RadioButtonPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: RadioButtonStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
62
64
  selected?: boolean;
63
65
  color?: string;
@@ -5,6 +5,8 @@
5
5
  "children": "never",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "selected": "boolean",
9
11
  "color": "color",
10
12
  "size": "number"
@@ -21,6 +21,8 @@ import type { CarouselButtonsComponentProps } from './CarouselButtons/CarouselBu
21
21
  import type { CarouselDotsComponentProps } from './CarouselDots/CarouselDotsProps.generated';
22
22
  import type { CarouselItemComponentProps } from './CarouselItem/CarouselItemProps.generated';
23
23
  import type { CarouselProviderComponentProps } from './CarouselProvider/CarouselProviderProps.generated';
24
+ import type { CountDownComponentProps } from './CountDown/CountDownProps.generated';
25
+ import type { CounterComponentProps } from './Counter/CounterProps.generated';
24
26
  import type { ImageComponentProps } from './Image/ImageProps.generated';
25
27
  import type { MainComponentProps } from './Main/MainProps.generated';
26
28
  import type { OnboardComponentProps } from './Onboard/OnboardProps.generated';
@@ -35,6 +37,7 @@ import type { OnboardSubtitleComponentProps } from './OnboardSubtitle/OnboardSub
35
37
  import type { OnboardTitleComponentProps } from './OnboardTitle/OnboardTitleProps.generated';
36
38
  import type { PaywallBackgroundComponentProps } from './PaywallBackground/PaywallBackgroundProps.generated';
37
39
  import type { PaywallCloseButtonComponentProps } from './PaywallCloseButton/PaywallCloseButtonProps.generated';
40
+ import type { PaywallCounterComponentProps } from './PaywallCounter/PaywallCounterProps.generated';
38
41
  import type { PaywallOptionsComponentProps } from './PaywallOptions/PaywallOptionsProps.generated';
39
42
  import type { PaywallProviderComponentProps } from './PaywallProvider/PaywallProviderProps.generated';
40
43
  import type { PaywallSubscribeButtonComponentProps } from './PaywallSubscribeButton/PaywallSubscribeButtonProps.generated';
@@ -47,8 +50,10 @@ import Button from './Button/Button';
47
50
  import Carousel from './Carousel/Carousel';
48
51
  import CarouselButtons from './CarouselButtons/CarouselButtons';
49
52
  import CarouselDots from './CarouselDots/CarouselDots';
50
- import CarouselItem from './CarouselItem/CarouselItem';
53
+ import { CarouselItem } from './CarouselItem/CarouselItem';
51
54
  import CarouselProvider from './CarouselProvider/CarouselProvider';
55
+ import { CountDown } from './CountDown/CountDown';
56
+ import { Counter } from './Counter/Counter';
52
57
  import Image from './Image/Image';
53
58
  import Main from './Main/Main';
54
59
  import Onboard from './Onboard/Onboard';
@@ -63,12 +68,13 @@ import OnboardSubtitle from './OnboardSubtitle/OnboardSubtitle';
63
68
  import OnboardTitle from './OnboardTitle/OnboardTitle';
64
69
  import PaywallBackground from './PaywallBackground/PaywallBackground';
65
70
  import PaywallCloseButton from './PaywallCloseButton/PaywallCloseButton';
71
+ import { PaywallCounter } from './PaywallCounter/PaywallCounter';
66
72
  import PaywallOptions from './PaywallOptions/PaywallOptions';
67
73
  import PaywallProvider from './PaywallProvider/PaywallProvider';
68
74
  import PaywallSubscribeButton from './PaywallSubscribeButton/PaywallSubscribeButton';
69
75
  import RadioButton from './RadioButton/RadioButton';
70
76
  import Text from './Text/Text';
71
- import View from './View/View';
77
+ import { View } from './View/View';
72
78
 
73
79
  type BuilderNode =
74
80
  | (BIconComponentProps['node'] & { type: 'BIcon' })
@@ -79,6 +85,8 @@ type BuilderNode =
79
85
  | (CarouselDotsComponentProps['node'] & { type: 'CarouselDots' })
80
86
  | (CarouselItemComponentProps['node'] & { type: 'CarouselItem' })
81
87
  | (CarouselProviderComponentProps['node'] & { type: 'CarouselProvider' })
88
+ | (CountDownComponentProps['node'] & { type: 'CountDown' })
89
+ | (CounterComponentProps['node'] & { type: 'Counter' })
82
90
  | (ImageComponentProps['node'] & { type: 'Image' })
83
91
  | (MainComponentProps['node'] & { type: 'Main' })
84
92
  | (OnboardComponentProps['node'] & { type: 'Onboard' })
@@ -93,6 +101,7 @@ type BuilderNode =
93
101
  | (OnboardTitleComponentProps['node'] & { type: 'OnboardTitle' })
94
102
  | (PaywallBackgroundComponentProps['node'] & { type: 'PaywallBackground' })
95
103
  | (PaywallCloseButtonComponentProps['node'] & { type: 'PaywallCloseButton' })
104
+ | (PaywallCounterComponentProps['node'] & { type: 'PaywallCounter' })
96
105
  | (PaywallOptionsComponentProps['node'] & { type: 'PaywallOptions' })
97
106
  | (PaywallProviderComponentProps['node'] & { type: 'PaywallProvider' })
98
107
  | (PaywallSubscribeButtonComponentProps['node'] & {
@@ -148,6 +157,10 @@ function RenderNode({ node }: { node: Node }) {
148
157
  return <CarouselItem node={normalizedNode} />;
149
158
  case 'CarouselProvider':
150
159
  return <CarouselProvider node={normalizedNode} />;
160
+ case 'CountDown':
161
+ return <CountDown node={normalizedNode} />;
162
+ case 'Counter':
163
+ return <Counter node={normalizedNode} />;
151
164
  case 'Image':
152
165
  return <Image node={normalizedNode} />;
153
166
  case 'Main':
@@ -176,6 +189,8 @@ function RenderNode({ node }: { node: Node }) {
176
189
  return <PaywallBackground node={normalizedNode} />;
177
190
  case 'PaywallCloseButton':
178
191
  return <PaywallCloseButton node={normalizedNode} />;
192
+ case 'PaywallCounter':
193
+ return <PaywallCounter node={normalizedNode} />;
179
194
  case 'PaywallOptions':
180
195
  return <PaywallOptions node={normalizedNode} />;
181
196
  case 'PaywallProvider':
@@ -64,6 +64,8 @@ export interface TextPropsGenerated {
64
64
  child: string;
65
65
  attributes: {
66
66
  style?: TextStyleGenerated;
67
+ title?: string;
68
+ description?: string;
67
69
  scrollable?: boolean;
68
70
  adjustsFontSizeToFit?: boolean;
69
71
  showEllipsis?: boolean;
@@ -5,6 +5,8 @@
5
5
  "children": "string",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "adjustsFontSizeToFit": "boolean",
9
11
  "showEllipsis": "boolean",
10
12
  "style": {
@@ -36,7 +38,7 @@
36
38
  "category": "style",
37
39
  "specialCategory": null,
38
40
  "sort": 2,
39
- "preferedScale": "s"
41
+ "preferredScale": "s"
40
42
  },
41
43
  "fontFamily": {
42
44
  "label": "Font Family",
@@ -30,7 +30,7 @@ export function View({ node }: ViewComponentProps) {
30
30
  <div
31
31
  attribute-name={attributeName}
32
32
  attribute-key={attributeKey}
33
- style={viewStyle}
33
+ style={{ ...viewStyle, boxSizing: 'border-box' }}
34
34
  className="scroll-container"
35
35
  >
36
36
  <RenderNode node={node.children as Node} />
@@ -58,6 +58,8 @@ export interface ViewPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: ViewStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
62
64
  };
63
65
  }