@developer_tribe/react-builder 1.2.15 → 1.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +1 -1
- package/dist/build-components/Button/ButtonProps.generated.d.ts +1 -1
- package/dist/build-components/Carousel/CarouselProps.generated.d.ts +1 -1
- package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +1 -1
- package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +1 -1
- package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +1 -1
- package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +1 -1
- package/dist/build-components/Image/ImageProps.generated.d.ts +1 -1
- package/dist/build-components/Main/MainProps.generated.d.ts +1 -1
- package/dist/build-components/Onboard/OnboardProps.generated.d.ts +1 -1
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +1 -1
- package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +1 -1
- package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +1 -1
- package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +1 -1
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +1 -1
- package/dist/build-components/PaywallCloseButton/PaywallCloseButton.d.ts +1 -1
- package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +1 -1
- package/dist/build-components/PaywallProvider/PaywallContext.d.ts +2 -1
- package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -1
- package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +1 -1
- package/dist/build-components/Text/TextProps.generated.d.ts +1 -1
- package/dist/build-components/View/ViewProps.generated.d.ts +0 -2
- package/dist/build-components/patterns.generated.d.ts +49 -41
- package/dist/index.cjs.js +3 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +3 -3
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +3 -3
- package/dist/index.web.esm.js.map +1 -1
- package/dist/mockOS/backHandler.d.ts +4 -0
- package/dist/paywall/hooks/index.d.ts +3 -3
- package/dist/paywall/hooks/useChangeDelayByPaywall.d.ts +4 -0
- package/dist/paywall/hooks/useHandleGoBack.d.ts +1 -0
- package/dist/paywall/hooks/useMockOSBackHandler.d.ts +1 -0
- package/package.json +4 -1
- package/src/RenderPage.tsx +0 -24
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/paywall-2.json +3 -2
- package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +1 -1
- package/src/build-components/Button/ButtonProps.generated.ts +1 -1
- package/src/build-components/Carousel/CarouselProps.generated.ts +1 -1
- package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +1 -1
- package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +1 -1
- package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +1 -1
- package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +1 -1
- package/src/build-components/CountDown/CountDown.tsx +9 -1
- package/src/build-components/Image/ImageProps.generated.ts +1 -1
- package/src/build-components/Main/MainProps.generated.ts +1 -1
- package/src/build-components/Onboard/OnboardProps.generated.ts +1 -1
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +1 -1
- package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +1 -1
- package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +1 -1
- package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +1 -1
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +1 -1
- package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +5 -1
- package/src/build-components/PaywallCloseButton/pattern.json +3 -0
- package/src/build-components/PaywallCounter/PaywallCounter.tsx +2 -5
- package/src/build-components/PaywallOptions/PaywallOptions.tsx +2 -2
- package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +1 -1
- package/src/build-components/PaywallProvider/PaywallContext.ts +4 -2
- package/src/build-components/PaywallProvider/PaywallProvider.tsx +45 -7
- package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +2 -1
- package/src/build-components/PaywallProvider/pattern.json +11 -1
- package/src/build-components/RadioButton/RadioButtonProps.generated.ts +1 -1
- package/src/build-components/Text/TextProps.generated.ts +1 -1
- package/src/build-components/View/ViewProps.generated.ts +0 -2
- package/src/build-components/View/pattern.json +0 -2
- package/src/build-components/patterns.generated.ts +50 -41
- package/src/components/BuilderProvider.tsx +0 -9
- package/src/components/DeviceNavigationBar.tsx +5 -0
- package/src/index.ts +1 -3
- package/src/mockOS/backHandler.ts +35 -0
- package/src/mockOS/managers/navigationManager.ts +0 -3
- package/src/pages/ProjectMigrationPage.tsx +3 -1
- package/src/paywall/hooks/index.ts +3 -3
- package/src/paywall/hooks/useChangeDelayByPaywall.ts +25 -0
- package/src/paywall/hooks/useHandleGoBack.ts +60 -0
- package/src/paywall/hooks/useMockOSBackHandler.ts +9 -0
- package/dist/paywall/hooks/useCarouselOptionsSeperator.d.ts +0 -6
- package/dist/paywall/hooks/useCloseStatusPaywall.d.ts +0 -4
- package/dist/paywall/hooks/usePaywallCounter.d.ts +0 -4
- package/src/paywall/hooks/useCarouselOptionsSeperator.ts +0 -8
- package/src/paywall/hooks/useCloseStatusPaywall.ts +0 -6
- package/src/paywall/hooks/usePaywallCounter.ts +0 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { usePaywallCounter } from './usePaywallCounter';
|
|
2
|
-
export { useCloseStatusPaywall } from './useCloseStatusPaywall';
|
|
3
|
-
export { useCarouselOptionsSeperator } from './useCarouselOptionsSeperator';
|
|
4
1
|
export { useCalculateLocalizedPrice } from './useCalculateLocalizedPrice';
|
|
5
2
|
export { useDiscountRate } from './useDiscountRate';
|
|
3
|
+
export { useChangeDelayByPaywall } from './useChangeDelayByPaywall';
|
|
4
|
+
export { useHandleGoBack } from './useHandleGoBack';
|
|
5
|
+
export { useMockOSBackHandler } from './useMockOSBackHandler';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useHandleGoBack(handleGoBack: () => boolean | null | undefined): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useMockOSBackHandler(isBackAllowed: boolean): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@developer_tribe/react-builder",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.18",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"restricted": true,
|
|
@@ -33,6 +33,9 @@
|
|
|
33
33
|
],
|
|
34
34
|
"scripts": {
|
|
35
35
|
"prebuild": "node ./scripts/prebuild/prebuild.js",
|
|
36
|
+
"prebuild:basics": "yarn builder build --name builder --components=View --components=Text --components=Button --components=Image --components=Carousel --components=CarouselProvider --components=CarouselItem --components=CarouselDots --components=CarouselButtons --components=BIcon --components=BackgroundImage --components=Main --components=RadioButton --components=Counter --components=CountDown",
|
|
37
|
+
"prebuild:onboard": "yarn builder build --name onboard/builder --components=OnboardProvider --components=Onboard --components=OnboardItem --components=OnboardImage --components=OnboardTitle --components=OnboardSubtitle --components=OnboardDot --components=OnboardButtons --components=OnboardButton --components=OnboardFooter",
|
|
38
|
+
"prebuild:paywall": "yarn builder build --name paywall/builder --components=PaywallProvider --components=PaywallBackground --components=PaywallCloseButton --components=PaywallOptions --components=PaywallSubscribeButton --components=PaywallCounter",
|
|
36
39
|
"build": "yarn prebuild && yarn rimraf dist && rollup -c",
|
|
37
40
|
"build:watch": "rollup -c -w",
|
|
38
41
|
"lint": "eslint src",
|
package/src/RenderPage.tsx
CHANGED
|
@@ -84,60 +84,37 @@ export function RenderPage({
|
|
|
84
84
|
const showEmptyState = isEmptyPreview(data);
|
|
85
85
|
|
|
86
86
|
useEffect(() => {
|
|
87
|
-
console.info('[preview] RenderPage effect', {
|
|
88
|
-
previewMode,
|
|
89
|
-
forceRender,
|
|
90
|
-
hasRoot: !!previewRootRef.current,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
87
|
if (!previewMode) {
|
|
94
88
|
return;
|
|
95
89
|
}
|
|
96
90
|
|
|
97
91
|
const root = previewRootRef.current;
|
|
98
92
|
if (!root) {
|
|
99
|
-
console.info('[preview] RenderPage effect skipped (no root)');
|
|
100
93
|
return;
|
|
101
94
|
}
|
|
102
95
|
|
|
103
|
-
console.info('[preview] RenderPage effect bound', {
|
|
104
|
-
rootTag: root.tagName,
|
|
105
|
-
rootClass: root.className,
|
|
106
|
-
});
|
|
107
|
-
|
|
108
96
|
const handleClick = (event: MouseEvent) => {
|
|
109
97
|
const target = event.target as HTMLElement | null;
|
|
110
|
-
console.info('[preview] click', {
|
|
111
|
-
target: target ? target.tagName : null,
|
|
112
|
-
className: target ? target.className : null,
|
|
113
|
-
});
|
|
114
98
|
|
|
115
99
|
if (!target) return;
|
|
116
100
|
|
|
117
101
|
// Ignore clicks on carousel dots to avoid interfering with navigation
|
|
118
102
|
if (target.closest('.embla__dot')) {
|
|
119
|
-
console.info('[preview] click ignored (embla dot)');
|
|
120
103
|
return;
|
|
121
104
|
}
|
|
122
105
|
|
|
123
106
|
const element = target.closest('[attribute-key]') as HTMLElement | null;
|
|
124
107
|
if (!element) {
|
|
125
|
-
console.info('[preview] click ignored (no attribute-key ancestor)');
|
|
126
108
|
return;
|
|
127
109
|
}
|
|
128
110
|
|
|
129
111
|
const key = element.getAttribute('attribute-key');
|
|
130
112
|
|
|
131
113
|
if (!key) {
|
|
132
|
-
console.info('[preview] click ignored (no attribute-key value)');
|
|
133
114
|
return;
|
|
134
115
|
}
|
|
135
116
|
|
|
136
117
|
const node = findNodeByKeyNested(data, key);
|
|
137
|
-
console.info('[preview] click resolved', {
|
|
138
|
-
key,
|
|
139
|
-
foundNode: !!node,
|
|
140
|
-
});
|
|
141
118
|
setCurrent(node);
|
|
142
119
|
onSelectNode?.(node);
|
|
143
120
|
};
|
|
@@ -145,7 +122,6 @@ export function RenderPage({
|
|
|
145
122
|
root.addEventListener('click', handleClick);
|
|
146
123
|
|
|
147
124
|
return () => {
|
|
148
|
-
console.info('[preview] RenderPage effect cleanup');
|
|
149
125
|
root.removeEventListener('click', handleClick);
|
|
150
126
|
};
|
|
151
127
|
}, [previewMode, data, onSelectNode, setCurrent, forceRender]); // forceRender: retrigger effect when we want to force a refresh (e.g. route change)
|
package/src/assets/meta.json
CHANGED
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"backgroundColor": "#EEF2FF"
|
|
38
38
|
},
|
|
39
39
|
"scrollable": true,
|
|
40
|
+
"delay": 5000,
|
|
40
41
|
"description": "Paywall provider container.",
|
|
41
42
|
"title": "Main Paywall"
|
|
42
43
|
},
|
|
@@ -293,14 +294,14 @@
|
|
|
293
294
|
{
|
|
294
295
|
"type": "CountDown",
|
|
295
296
|
"attributes": {
|
|
296
|
-
"count":
|
|
297
|
+
"count": 10000,
|
|
297
298
|
"style": {
|
|
298
299
|
"color": "#FF0000",
|
|
299
300
|
"fontWeight": "700",
|
|
300
301
|
"fontSize": 40,
|
|
301
302
|
"textAlign": "center"
|
|
302
303
|
},
|
|
303
|
-
"description": "Countdown timer (
|
|
304
|
+
"description": "Countdown timer (10 seconds).",
|
|
304
305
|
"title": "Countdown"
|
|
305
306
|
},
|
|
306
307
|
"children": null
|
|
@@ -59,9 +59,9 @@ export interface BackgroundImagePropsGenerated {
|
|
|
59
59
|
child: string;
|
|
60
60
|
attributes: {
|
|
61
61
|
style?: BackgroundImageStyleGenerated;
|
|
62
|
+
scrollable?: boolean;
|
|
62
63
|
title?: string;
|
|
63
64
|
description?: string;
|
|
64
|
-
scrollable?: boolean;
|
|
65
65
|
src?: string;
|
|
66
66
|
resizeMode?: ResizeModeOptionType;
|
|
67
67
|
};
|
|
@@ -59,9 +59,9 @@ export interface CarouselPropsGenerated {
|
|
|
59
59
|
child: string;
|
|
60
60
|
attributes: {
|
|
61
61
|
style?: CarouselStyleGenerated;
|
|
62
|
+
scrollable?: boolean;
|
|
62
63
|
title?: string;
|
|
63
64
|
description?: string;
|
|
64
|
-
scrollable?: boolean;
|
|
65
65
|
loop?: boolean;
|
|
66
66
|
dragFree?: boolean;
|
|
67
67
|
align?: AlignOptionType;
|
|
@@ -62,9 +62,9 @@ export interface CarouselButtonsPropsGenerated {
|
|
|
62
62
|
child: string;
|
|
63
63
|
attributes: {
|
|
64
64
|
style?: CarouselButtonsStyleGenerated;
|
|
65
|
+
scrollable?: boolean;
|
|
65
66
|
title?: string;
|
|
66
67
|
description?: string;
|
|
67
|
-
scrollable?: boolean;
|
|
68
68
|
buttonType?: ButtonTypeOptionType;
|
|
69
69
|
skipNumber?: number;
|
|
70
70
|
};
|
|
@@ -65,9 +65,9 @@ export interface CarouselDotsPropsGenerated {
|
|
|
65
65
|
child: string;
|
|
66
66
|
attributes: {
|
|
67
67
|
style?: CarouselDotsStyleGenerated;
|
|
68
|
+
scrollable?: boolean;
|
|
68
69
|
title?: string;
|
|
69
70
|
description?: string;
|
|
70
|
-
scrollable?: boolean;
|
|
71
71
|
dotType?: DotTypeOptionType;
|
|
72
72
|
};
|
|
73
73
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useId, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useId, useRef, useState } from 'react';
|
|
2
2
|
import type { CountDownComponentProps } from './CountDownProps.generated';
|
|
3
3
|
import useNode from '../useNode';
|
|
4
4
|
import { useBuilderParams } from '../../components/BuilderProvider';
|
|
@@ -7,6 +7,7 @@ import { useLogRender } from '../../utils/useLogRender';
|
|
|
7
7
|
import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
|
|
8
8
|
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
9
9
|
import { formatCountdownTime } from './formatCountdownTime';
|
|
10
|
+
import { usePaywallContext } from '../PaywallProvider/PaywallContext';
|
|
10
11
|
|
|
11
12
|
const DEFAULT_FORMAT = 'm : s';
|
|
12
13
|
|
|
@@ -20,6 +21,8 @@ export function CountDown({ node }: CountDownComponentProps) {
|
|
|
20
21
|
const attributeKey = node.key ?? generatedId;
|
|
21
22
|
|
|
22
23
|
const { previewMode, selectedKey } = useBuilderParams();
|
|
24
|
+
const { onCounterDown } = usePaywallContext();
|
|
25
|
+
const onCounterDownRef = useRef(onCounterDown);
|
|
23
26
|
const baseStyle = useExtractTextStyle(node);
|
|
24
27
|
const isSelected = isNodeSelected({
|
|
25
28
|
previewMode: !!previewMode,
|
|
@@ -39,6 +42,10 @@ export function CountDown({ node }: CountDownComponentProps) {
|
|
|
39
42
|
|
|
40
43
|
const [time, setTime] = useState<string>('');
|
|
41
44
|
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
onCounterDownRef.current = onCounterDown;
|
|
47
|
+
}, [onCounterDown]);
|
|
48
|
+
|
|
42
49
|
useEffect(() => {
|
|
43
50
|
const targetTimeMs = Date.now() + delayMs;
|
|
44
51
|
setTime(formatCountdownTime(targetTimeMs, DEFAULT_FORMAT));
|
|
@@ -53,6 +60,7 @@ export function CountDown({ node }: CountDownComponentProps) {
|
|
|
53
60
|
setTime(formatCountdownTime(targetTimeMs, DEFAULT_FORMAT, nowMs));
|
|
54
61
|
if (diffMs <= 0) {
|
|
55
62
|
clearInterval(intervalId);
|
|
63
|
+
onCounterDownRef.current?.();
|
|
56
64
|
}
|
|
57
65
|
}, 950); // Keep slightly under 1s to reduce visible drift.
|
|
58
66
|
|
|
@@ -59,9 +59,9 @@ export interface ImagePropsGenerated {
|
|
|
59
59
|
child: string;
|
|
60
60
|
attributes: {
|
|
61
61
|
style?: ImageStyleGenerated;
|
|
62
|
+
scrollable?: boolean;
|
|
62
63
|
title?: string;
|
|
63
64
|
description?: string;
|
|
64
|
-
scrollable?: boolean;
|
|
65
65
|
src?: string;
|
|
66
66
|
width?: string;
|
|
67
67
|
height?: string;
|
|
@@ -73,9 +73,9 @@ export interface OnboardButtonPropsGenerated {
|
|
|
73
73
|
child: string;
|
|
74
74
|
attributes: {
|
|
75
75
|
style?: OnboardButtonStyleGenerated;
|
|
76
|
+
scrollable?: boolean;
|
|
76
77
|
title?: string;
|
|
77
78
|
description?: string;
|
|
78
|
-
scrollable?: boolean;
|
|
79
79
|
labelKey?: string;
|
|
80
80
|
button_text_color?: string;
|
|
81
81
|
animation?: AnimationOptionType;
|
|
@@ -64,9 +64,9 @@ export interface OnboardButtonsPropsGenerated {
|
|
|
64
64
|
child: string;
|
|
65
65
|
attributes: {
|
|
66
66
|
style?: OnboardButtonsStyleGenerated;
|
|
67
|
+
scrollable?: boolean;
|
|
67
68
|
title?: string;
|
|
68
69
|
description?: string;
|
|
69
|
-
scrollable?: boolean;
|
|
70
70
|
buttonType?: ButtonTypeOptionType;
|
|
71
71
|
skipNumber?: number;
|
|
72
72
|
buttons_direction?: ButtonsDirectionOptionType;
|
|
@@ -65,9 +65,9 @@ export interface OnboardDotPropsGenerated {
|
|
|
65
65
|
child: string;
|
|
66
66
|
attributes: {
|
|
67
67
|
style?: OnboardDotStyleGenerated;
|
|
68
|
+
scrollable?: boolean;
|
|
68
69
|
title?: string;
|
|
69
70
|
description?: string;
|
|
70
|
-
scrollable?: boolean;
|
|
71
71
|
dotType?: DotTypeOptionType;
|
|
72
72
|
inactive_dot_opacity?: number;
|
|
73
73
|
expanding_dot_width?: string;
|
|
@@ -59,9 +59,9 @@ export interface OnboardItemPropsGenerated {
|
|
|
59
59
|
child: string;
|
|
60
60
|
attributes: {
|
|
61
61
|
style?: OnboardItemStyleGenerated;
|
|
62
|
+
scrollable?: boolean;
|
|
62
63
|
title?: string;
|
|
63
64
|
description?: string;
|
|
64
|
-
scrollable?: boolean;
|
|
65
65
|
display?: DisplayOptionType;
|
|
66
66
|
gap?: string;
|
|
67
67
|
flexDirection?: FlexDirectionOptionType;
|
|
@@ -59,9 +59,9 @@ export interface OnboardProviderPropsGenerated {
|
|
|
59
59
|
child: string;
|
|
60
60
|
attributes: {
|
|
61
61
|
style?: OnboardProviderStyleGenerated;
|
|
62
|
+
scrollable?: boolean;
|
|
62
63
|
title?: string;
|
|
63
64
|
description?: string;
|
|
64
|
-
scrollable?: boolean;
|
|
65
65
|
theme?: ThemeOptionType;
|
|
66
66
|
borderRadius?: never;
|
|
67
67
|
};
|
|
@@ -14,7 +14,7 @@ import { usePaywallContext } from '../PaywallProvider/PaywallContext';
|
|
|
14
14
|
function PaywallCloseButton({ node }: PaywallCloseButtonComponentProps) {
|
|
15
15
|
useLogRender('PaywallCloseButton');
|
|
16
16
|
node = useNode(node);
|
|
17
|
-
const { onClose } = usePaywallContext();
|
|
17
|
+
const { onClose, isBackAllowed } = usePaywallContext();
|
|
18
18
|
|
|
19
19
|
const generatedId = useId();
|
|
20
20
|
const attributeName = node.sourceType ?? node.type ?? 'PaywallCloseButton';
|
|
@@ -35,6 +35,10 @@ function PaywallCloseButton({ node }: PaywallCloseButtonComponentProps) {
|
|
|
35
35
|
isSelected ? SELECTED_OUTLINE_STYLE : undefined,
|
|
36
36
|
);
|
|
37
37
|
|
|
38
|
+
if (!isBackAllowed) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
38
42
|
const attrs = node.attributes;
|
|
39
43
|
const styleBag = attrs?.style;
|
|
40
44
|
const iconType = attrs?.iconType ?? 'close';
|
|
@@ -6,7 +6,6 @@ import { useExtractTextStyle } from '../../attribute-analyser/style/web/useExtra
|
|
|
6
6
|
import { useLogRender } from '../../utils/useLogRender';
|
|
7
7
|
import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
|
|
8
8
|
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
9
|
-
import { usePaywallCounter } from '../../paywall/hooks';
|
|
10
9
|
|
|
11
10
|
//Optimzation trade off by readability: skip React.memo to keep named exports.
|
|
12
11
|
export function PaywallCounter({ node }: PaywallCounterComponentProps) {
|
|
@@ -29,11 +28,9 @@ export function PaywallCounter({ node }: PaywallCounterComponentProps) {
|
|
|
29
28
|
isSelected ? SELECTED_OUTLINE_STYLE : undefined,
|
|
30
29
|
);
|
|
31
30
|
|
|
32
|
-
const paywallCount = usePaywallCounter();
|
|
33
31
|
const fallbackCount = node.attributes?.count;
|
|
34
|
-
const count =
|
|
35
|
-
|
|
36
|
-
: typeof fallbackCount === 'number' && Number.isFinite(fallbackCount)
|
|
32
|
+
const count =
|
|
33
|
+
typeof fallbackCount === 'number' && Number.isFinite(fallbackCount)
|
|
37
34
|
? fallbackCount
|
|
38
35
|
: 0;
|
|
39
36
|
|
|
@@ -52,7 +52,7 @@ function PaywallOptions({ node }: PaywallOptionsComponentProps) {
|
|
|
52
52
|
useLogRender('PaywallOptions');
|
|
53
53
|
node = useNode(node);
|
|
54
54
|
const { products } = useBuilderParams();
|
|
55
|
-
const {
|
|
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 =
|
|
70
|
+
const isSelected = selectedProduct?.productId === productId;
|
|
71
71
|
const { localizationParams, otherParams } = getParamsForProduct(p, {
|
|
72
72
|
isSelected,
|
|
73
73
|
});
|
|
@@ -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');
|
|
@@ -57,6 +61,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
57
61
|
);
|
|
58
62
|
|
|
59
63
|
const [selectedProductId, setSelectedProductId] = useState<string>('');
|
|
64
|
+
const [isBackAllowed, setIsBackAllowed] = useState<boolean>(false);
|
|
60
65
|
useEffect(() => {
|
|
61
66
|
const list = Array.isArray(products) ? products : [];
|
|
62
67
|
if (list.length === 0) {
|
|
@@ -70,6 +75,9 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
70
75
|
}
|
|
71
76
|
}, [products, selectedProductId]);
|
|
72
77
|
|
|
78
|
+
useChangeDelayByPaywall(node, setIsBackAllowed);
|
|
79
|
+
useMockOSBackHandler(isBackAllowed);
|
|
80
|
+
|
|
73
81
|
const selectedProduct = useMemo(() => {
|
|
74
82
|
const list = Array.isArray(products) ? products : [];
|
|
75
83
|
return (
|
|
@@ -79,6 +87,9 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
79
87
|
}, [products, selectedProductId]);
|
|
80
88
|
|
|
81
89
|
const handleClose = useCallback(() => {
|
|
90
|
+
if (!isBackAllowed) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
82
93
|
// Default: in MockOS go back (simulate dismissing paywall screen).
|
|
83
94
|
// TODO: at react native merge it will change
|
|
84
95
|
if (mockOS?.isEnabled) {
|
|
@@ -87,13 +98,22 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
87
98
|
mockOS.navigation('launchscreen');
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
|
-
}, [mockOS]);
|
|
101
|
+
}, [mockOS, isBackAllowed]);
|
|
102
|
+
|
|
103
|
+
const handleGoBack = useCallback(() => {
|
|
104
|
+
if (!isBackAllowed) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}, [isBackAllowed]);
|
|
109
|
+
|
|
110
|
+
useHandleGoBack(handleGoBack);
|
|
91
111
|
|
|
92
112
|
const handleSubscribe = useCallback(
|
|
93
|
-
async (product?:
|
|
113
|
+
async (product?: Product): Promise<boolean> => {
|
|
94
114
|
// Host app override wins.
|
|
95
115
|
if (onPaywallSubscribe) {
|
|
96
|
-
const result = onPaywallSubscribe(product
|
|
116
|
+
const result = onPaywallSubscribe(product);
|
|
97
117
|
const ok =
|
|
98
118
|
result instanceof Promise
|
|
99
119
|
? await result
|
|
@@ -105,7 +125,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
105
125
|
if (ok && mockOS?.isEnabled) {
|
|
106
126
|
mockOS.goBack?.();
|
|
107
127
|
}
|
|
108
|
-
return;
|
|
128
|
+
return ok;
|
|
109
129
|
}
|
|
110
130
|
|
|
111
131
|
// Default: in MockOS show a native-like subscription prompt.
|
|
@@ -122,26 +142,44 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
122
142
|
// TODO: at react native merge it will change
|
|
123
143
|
mockOS.goBack?.();
|
|
124
144
|
}
|
|
145
|
+
return ok;
|
|
125
146
|
}
|
|
147
|
+
return false;
|
|
126
148
|
},
|
|
127
149
|
[mockOS, onPaywallSubscribe],
|
|
128
150
|
);
|
|
129
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
|
+
|
|
130
166
|
const paywallContextValue = useMemo(
|
|
131
167
|
() => ({
|
|
132
168
|
products: Array.isArray(products) ? products : [],
|
|
133
|
-
selectedProductId,
|
|
134
169
|
setSelectedProductId,
|
|
135
170
|
selectedProduct,
|
|
136
171
|
onClose: handleClose,
|
|
137
|
-
onSubscribe: handleSubscribe
|
|
172
|
+
onSubscribe: handleSubscribe,
|
|
173
|
+
onCounterDown: handleCounterDown,
|
|
174
|
+
isBackAllowed,
|
|
138
175
|
}),
|
|
139
176
|
[
|
|
140
177
|
products,
|
|
141
|
-
selectedProductId,
|
|
142
178
|
selectedProduct,
|
|
143
179
|
handleClose,
|
|
144
180
|
handleSubscribe,
|
|
181
|
+
handleCounterDown,
|
|
182
|
+
isBackAllowed,
|
|
145
183
|
],
|
|
146
184
|
);
|
|
147
185
|
|
|
@@ -58,9 +58,10 @@ export interface PaywallProviderPropsGenerated {
|
|
|
58
58
|
child: string;
|
|
59
59
|
attributes: {
|
|
60
60
|
style?: PaywallProviderStyleGenerated;
|
|
61
|
+
scrollable?: boolean;
|
|
61
62
|
title?: string;
|
|
62
63
|
description?: string;
|
|
63
|
-
|
|
64
|
+
delay?: number;
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"extends": "View",
|
|
7
7
|
"attributes": {
|
|
8
8
|
"title": "title",
|
|
9
|
-
"description": "description"
|
|
9
|
+
"description": "description",
|
|
10
|
+
"delay": "number"
|
|
10
11
|
}
|
|
11
12
|
},
|
|
12
13
|
"defaults": {
|
|
@@ -21,6 +22,15 @@
|
|
|
21
22
|
],
|
|
22
23
|
"label": "Paywall Provider",
|
|
23
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
|
+
},
|
|
24
34
|
"mockableFeatures": {
|
|
25
35
|
"products": true,
|
|
26
36
|
"benefits": true
|
|
@@ -58,9 +58,9 @@ export interface RadioButtonPropsGenerated {
|
|
|
58
58
|
child: string;
|
|
59
59
|
attributes: {
|
|
60
60
|
style?: RadioButtonStyleGenerated;
|
|
61
|
+
scrollable?: boolean;
|
|
61
62
|
title?: string;
|
|
62
63
|
description?: string;
|
|
63
|
-
scrollable?: boolean;
|
|
64
64
|
selected?: boolean;
|
|
65
65
|
color?: string;
|
|
66
66
|
size?: number;
|