@developer_tribe/react-builder 1.2.27 → 1.2.29
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/assets/samples/getSamples.d.ts +0 -3
- package/dist/build-components/BIcon/BIconProps.generated.d.ts +1 -2
- package/dist/build-components/CountDown/CountDownProps.generated.d.ts +2 -1
- package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +1 -2
- package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +1 -2
- package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +1 -2
- package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +1 -2
- package/dist/build-components/PaywallOptions/usePaywallOptionParamsFactory.d.ts +1 -1
- package/dist/build-components/PriceTag/PriceTag.d.ts +5 -0
- package/dist/build-components/PriceTag/PriceTagProps.generated.d.ts +63 -0
- package/dist/build-components/Pricing/Pricing.d.ts +5 -0
- package/dist/build-components/Pricing/PricingProps.generated.d.ts +59 -0
- package/dist/build-components/Promo/Promo.d.ts +5 -0
- package/dist/build-components/Promo/PromoProps.generated.d.ts +59 -0
- package/dist/build-components/Text/TextProps.generated.d.ts +1 -2
- package/dist/build-components/index.d.ts +4 -1
- package/dist/build-components/patterns.generated.d.ts +1405 -202
- package/dist/components/BuilderProvider.d.ts +5 -3
- package/dist/components/ParamsProvider.d.ts +16 -8
- package/dist/hooks/useSyncHtmlThemeClass.d.ts +1 -1
- package/dist/index.cjs.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +4 -4
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +4 -4
- package/dist/index.web.esm.js.map +1 -1
- package/dist/logger.d.ts +18 -0
- package/dist/modals/InspectModal.d.ts +5 -0
- package/dist/modals/index.d.ts +1 -1
- package/dist/pages/ProjectPage.d.ts +3 -3
- package/dist/paywall/hooks/useCalculateLocalizedPrice.d.ts +4 -2
- package/dist/paywall/hooks/useDiscountRate.d.ts +3 -2
- package/dist/paywall/types/paywall-types.d.ts +7 -32
- package/dist/product-base/buildPaywallLocalizationParams.d.ts +16 -0
- package/dist/product-base/calculations.d.ts +29 -0
- package/dist/product-base/extractAndroidParams.d.ts +24 -0
- package/dist/product-base/extractIOSParams.d.ts +24 -0
- package/dist/product-base/index.d.ts +51 -0
- package/dist/product-base/periodLocalizationKeys.d.ts +44 -0
- package/dist/product-base/types.d.ts +155 -0
- package/dist/product-base/usePaywallLocalizationParams.d.ts +29 -0
- package/dist/store.d.ts +7 -1
- package/dist/styles.css +1 -1
- package/dist/types/PreviewConfig.d.ts +10 -16
- package/dist/utils/extractTextStyle/extractTextStyle.d.ts +2 -2
- package/dist/utils/extractTextStyle/extractTextStyleNative.d.ts +2 -2
- package/dist/utils/replaceLocalizationParams.d.ts +1 -1
- package/package.json +2 -2
- package/scripts/migrate-samples-to-current.ts +3 -3
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +28 -12
- package/src/DeviceMockFrame.tsx +15 -10
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/carousel-sample.json +6 -5
- package/src/assets/samples/getSamples.ts +16 -49
- package/src/assets/samples/paywall-1.json +64 -22
- package/src/assets/samples/paywall-2.json +0 -15
- package/src/assets/samples/paywall-app-delete-offer.json +0 -15
- package/src/assets/samples/paywall-app-open-offer.json +0 -15
- package/src/assets/samples/paywall-back-offer.json +0 -15
- package/src/assets/samples/paywall-notification-offer.json +0 -15
- package/src/assets/samples/simple-1.json +1 -16
- package/src/assets/samples/simple-2.json +0 -15
- package/src/assets/samples/unmigrated-builder-1.1.1.json +0 -3
- package/src/assets/samples/unmigrated-builder1.json +0 -3
- package/src/assets/samples/unvalidated-builder1.json +0 -3
- package/src/assets/samples/unvalidated-crash1.json +0 -3
- package/src/assets/samples/unvalidated-crashcomponent1.json +0 -3
- package/src/assets/samples/vpn-onboard-1.json +1 -34
- package/src/assets/samples/vpn-onboard-2.json +1 -34
- package/src/assets/samples/vpn-onboard-3.json +1 -42
- package/src/assets/samples/vpn-onboard-4.json +0 -73
- package/src/assets/samples/vpn-onboard-5.json +0 -73
- package/src/assets/samples/vpn-onboard-6.json +0 -73
- package/src/assets/samples/vpn-onboard-7.json +529 -0
- package/src/attribute-analyser/style/native/useExtractImageStyle.ts +1 -4
- package/src/attribute-analyser/style/native/useExtractTextStyle.ts +3 -12
- package/src/attribute-analyser/style/native/useExtractViewStyle.ts +1 -4
- package/src/attribute-analyser/style/web/useExtractImageStyle.ts +1 -4
- package/src/attribute-analyser/style/web/useExtractTextStyle.ts +3 -12
- package/src/attribute-analyser/style/web/useExtractViewStyle.ts +1 -4
- package/src/attributes-editor/useAttributesEditorModel.ts +5 -52
- package/src/build-components/BIcon/BIconProps.generated.ts +1 -2
- package/src/build-components/CarouselDots/CarouselDots.tsx +6 -13
- package/src/build-components/CountDown/CountDownProps.generated.ts +2 -1
- package/src/build-components/NavigationBarColor/NavigationBarColor.tsx +2 -2
- package/src/build-components/OnboardButton/OnboardButton.tsx +1 -2
- package/src/build-components/OnboardDot/OnboardDot.tsx +6 -18
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +5 -3
- package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +1 -2
- package/src/build-components/OnboardFooter/pattern.json +1 -1
- package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +1 -2
- package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +1 -2
- package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +1 -2
- package/src/build-components/PaywallOptions/PaywallOptions.tsx +3 -3
- package/src/build-components/PaywallOptions/usePaywallOptionParamsFactory.ts +26 -13
- package/src/build-components/PaywallProvider/PaywallProvider.tsx +51 -12
- package/src/build-components/PriceTag/PriceTag.tsx +25 -0
- package/src/build-components/PriceTag/PriceTagProps.generated.ts +83 -0
- package/src/build-components/PriceTag/pattern.json +53 -0
- package/src/build-components/Pricing/Pricing.tsx +13 -0
- package/src/build-components/Pricing/PricingProps.generated.ts +76 -0
- package/src/build-components/Pricing/pattern.json +25 -0
- package/src/build-components/Promo/Promo.tsx +13 -0
- package/src/build-components/Promo/PromoProps.generated.ts +76 -0
- package/src/build-components/Promo/pattern.json +25 -0
- package/src/build-components/RadioButton/RadioButton.tsx +3 -5
- package/src/build-components/RenderNode.generated.tsx +15 -0
- package/src/build-components/StatusBarColor/StatusBarColor.tsx +2 -2
- package/src/build-components/Text/Text.tsx +12 -5
- package/src/build-components/Text/TextProps.generated.ts +1 -2
- package/src/build-components/Text/pattern.json +3 -2
- package/src/build-components/index.ts +15 -0
- package/src/build-components/patterns.generated.ts +1454 -181
- package/src/components/BottomBar.tsx +42 -39
- package/src/components/BuilderProvider.tsx +41 -14
- package/src/components/LocalizationParamsProvider.tsx +1 -1
- package/src/components/ParamsProvider.tsx +36 -11
- package/src/hooks/useLocalize.ts +7 -4
- package/src/hooks/useParams.ts +1 -1
- package/src/hooks/useSyncHtmlThemeClass.ts +2 -2
- package/src/index.ts +54 -8
- package/src/logger.ts +39 -0
- package/src/modals/InspectModal.tsx +331 -0
- package/src/modals/ProductPresetsModal.tsx +7 -14
- package/src/modals/index.ts +1 -1
- package/src/pages/DebugJsonPage.tsx +9 -22
- package/src/pages/ProjectDebug.tsx +1 -1
- package/src/pages/ProjectPage.tsx +29 -11
- package/src/pages/tabs/SideTool.tsx +28 -104
- package/src/paywall/hooks/useCalculateLocalizedPrice.ts +8 -3
- package/src/paywall/hooks/useDiscountRate.ts +11 -3
- package/src/paywall/types/paywall-types.ts +7 -38
- package/src/product-base/buildPaywallLocalizationParams.ts +100 -0
- package/src/product-base/calculations.ts +93 -0
- package/src/product-base/extractAndroidParams.ts +207 -0
- package/src/product-base/extractIOSParams.ts +199 -0
- package/src/product-base/index.ts +64 -0
- package/src/product-base/mockProducts.json +489 -0
- package/src/product-base/periodLocalizationKeys.ts +114 -0
- package/src/product-base/types.ts +183 -0
- package/src/product-base/usePaywallLocalizationParams.ts +61 -0
- package/src/store.ts +18 -1
- package/src/styles/index.scss +1 -0
- package/src/styles/modals/_inspect-modal.scss +155 -0
- package/src/types/PreviewConfig.ts +157 -16
- package/src/utils/extractTextStyle/extractTextStyle.ts +14 -6
- package/src/utils/extractTextStyle/extractTextStyleNative.ts +8 -6
- package/src/utils/logRenderStore.ts +6 -10
- package/src/utils/parseColor.ts +0 -1
- package/src/utils/replaceLocalizationParams.ts +8 -4
- package/dist/modals/ScreenColorsModal.d.ts +0 -8
- package/src/assets/products.json +0 -98
- package/src/modals/ScreenColorsModal.tsx +0 -121
|
@@ -14,6 +14,9 @@ import { useMockOSContext } from '../../mockOS/context/MockOSContextBase';
|
|
|
14
14
|
import type { Product } from '../../paywall/types/paywall-types';
|
|
15
15
|
import { useChangeDelayByPaywall } from '../../paywall/hooks/useChangeDelayByPaywall';
|
|
16
16
|
import { useMockOSBackHandler } from '../../paywall/hooks/useMockOSBackHandler';
|
|
17
|
+
import { usePaywallLocalizationParams } from '../../product-base';
|
|
18
|
+
import { useRenderStore } from '../../store';
|
|
19
|
+
import { useLocalize } from '../../hooks/useLocalize';
|
|
17
20
|
|
|
18
21
|
function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
19
22
|
useLogRender('PaywallProvider');
|
|
@@ -23,13 +26,20 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
23
26
|
const attributeName = node.sourceType ?? node.type ?? 'PaywallProvider';
|
|
24
27
|
const attributeKey = node.key ?? generatedId;
|
|
25
28
|
|
|
26
|
-
const {
|
|
27
|
-
|
|
29
|
+
const {
|
|
30
|
+
mockBenefits,
|
|
31
|
+
mockProducts,
|
|
32
|
+
onPaywallSubscribe,
|
|
33
|
+
previewMode,
|
|
34
|
+
selectedKey,
|
|
35
|
+
} = useBuilderParams();
|
|
28
36
|
const mockOS = useMockOSContext();
|
|
29
37
|
const benefitLocalizationParams = useMemo(() => {
|
|
30
38
|
const raw =
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
mockBenefits &&
|
|
40
|
+
typeof mockBenefits === 'object' &&
|
|
41
|
+
!Array.isArray(mockBenefits)
|
|
42
|
+
? (mockBenefits as Record<string, unknown>)
|
|
33
43
|
: {};
|
|
34
44
|
|
|
35
45
|
const entries = Object.entries(raw).filter(([k]) => k.trim().length > 0);
|
|
@@ -45,7 +55,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
45
55
|
params[`benefit${idx}`] = value;
|
|
46
56
|
}
|
|
47
57
|
return params;
|
|
48
|
-
}, [
|
|
58
|
+
}, [mockBenefits]);
|
|
49
59
|
|
|
50
60
|
const baseStyle = useExtractViewStyle(node);
|
|
51
61
|
|
|
@@ -64,7 +74,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
64
74
|
useChangeDelayByPaywall(node, setIsBackAllowed);
|
|
65
75
|
useMockOSBackHandler(isBackAllowed);
|
|
66
76
|
useEffect(() => {
|
|
67
|
-
const list = Array.isArray(
|
|
77
|
+
const list = Array.isArray(mockProducts) ? mockProducts : [];
|
|
68
78
|
if (list.length === 0) {
|
|
69
79
|
if (selectedProductId) setSelectedProductId('');
|
|
70
80
|
return;
|
|
@@ -74,15 +84,38 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
74
84
|
if (!selectedProductId || !exists) {
|
|
75
85
|
setSelectedProductId(list[0]?.productId ?? '');
|
|
76
86
|
}
|
|
77
|
-
}, [
|
|
87
|
+
}, [mockProducts, selectedProductId]);
|
|
78
88
|
|
|
79
89
|
const selectedProduct = useMemo(() => {
|
|
80
|
-
const list = Array.isArray(
|
|
90
|
+
const list = Array.isArray(mockProducts) ? mockProducts : [];
|
|
81
91
|
return (
|
|
82
92
|
list.find((p) => p?.productId === selectedProductId) ??
|
|
83
93
|
(list.length > 0 ? list[0] : undefined)
|
|
84
94
|
);
|
|
85
|
-
}, [
|
|
95
|
+
}, [mockProducts, selectedProductId]);
|
|
96
|
+
|
|
97
|
+
const device = useRenderStore((s) => s.device);
|
|
98
|
+
const localize = useLocalize();
|
|
99
|
+
const platformForExtraction = (
|
|
100
|
+
device.platform === 'ios' ? 'ios' : 'android'
|
|
101
|
+
) as 'ios' | 'android';
|
|
102
|
+
const detailedProductParams = usePaywallLocalizationParams(
|
|
103
|
+
selectedProduct,
|
|
104
|
+
selectedProductId,
|
|
105
|
+
{
|
|
106
|
+
platform: platformForExtraction,
|
|
107
|
+
localize,
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
console.log('[PaywallProvider] extraction debug', {
|
|
112
|
+
platform: platformForExtraction,
|
|
113
|
+
selectedProductId,
|
|
114
|
+
hasSubscriptionOffers: !!selectedProduct?.subscriptionOffers?.length,
|
|
115
|
+
subscriptionOffersCount: selectedProduct?.subscriptionOffers?.length ?? 0,
|
|
116
|
+
detailedProductParams,
|
|
117
|
+
selectedProduct,
|
|
118
|
+
});
|
|
86
119
|
|
|
87
120
|
const handleClose = useCallback(() => {
|
|
88
121
|
if (!isBackAllowed) {
|
|
@@ -154,7 +187,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
154
187
|
|
|
155
188
|
const paywallContextValue = useMemo(
|
|
156
189
|
() => ({
|
|
157
|
-
products: Array.isArray(
|
|
190
|
+
products: Array.isArray(mockProducts) ? mockProducts : [],
|
|
158
191
|
setSelectedProductId,
|
|
159
192
|
selectedProduct,
|
|
160
193
|
onClose: handleClose,
|
|
@@ -163,7 +196,7 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
163
196
|
isBackAllowed,
|
|
164
197
|
}),
|
|
165
198
|
[
|
|
166
|
-
|
|
199
|
+
mockProducts,
|
|
167
200
|
selectedProduct,
|
|
168
201
|
handleClose,
|
|
169
202
|
handleSubscribe,
|
|
@@ -179,7 +212,13 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
|
|
|
179
212
|
style={style}
|
|
180
213
|
>
|
|
181
214
|
<PaywallContext.Provider value={paywallContextValue}>
|
|
182
|
-
<LocalizationParamsProvider
|
|
215
|
+
<LocalizationParamsProvider
|
|
216
|
+
params={{
|
|
217
|
+
...benefitLocalizationParams,
|
|
218
|
+
...detailedProductParams,
|
|
219
|
+
platform: platformForExtraction,
|
|
220
|
+
}}
|
|
221
|
+
>
|
|
183
222
|
<RenderNode node={node.children as Node} />
|
|
184
223
|
</LocalizationParamsProvider>
|
|
185
224
|
</PaywallContext.Provider>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PriceTagComponentProps } from './PriceTagProps.generated';
|
|
3
|
+
import Text from '../Text/Text';
|
|
4
|
+
import useNode from '../useNode';
|
|
5
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
6
|
+
import { useLocalizationParams } from '../../hooks/useLocalizationParams';
|
|
7
|
+
|
|
8
|
+
function PriceTag({ node }: PriceTagComponentProps) {
|
|
9
|
+
useLogRender('PriceTag');
|
|
10
|
+
node = useNode(node);
|
|
11
|
+
|
|
12
|
+
const params = useLocalizationParams();
|
|
13
|
+
const hasDiscount = !!params?.promoPrice;
|
|
14
|
+
|
|
15
|
+
const hideIfItsNotDiscount =
|
|
16
|
+
(node.attributes as Record<string, unknown>)?.hideIfItsNotDiscount ?? false;
|
|
17
|
+
|
|
18
|
+
if (hideIfItsNotDiscount && !hasDiscount) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return <Text node={node} />;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default React.memo(PriceTag);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
|
|
3
|
+
import type { NodeData } from '../../types/Node';
|
|
4
|
+
|
|
5
|
+
export type FlexDirectionOptionType = 'row' | 'column';
|
|
6
|
+
export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
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
|
+
export type TextDecorationLineOptionType =
|
|
22
|
+
| 'none'
|
|
23
|
+
| 'underline'
|
|
24
|
+
| 'line-through';
|
|
25
|
+
|
|
26
|
+
export interface PriceTagStyleGenerated {
|
|
27
|
+
color?: string;
|
|
28
|
+
fontSize?: string;
|
|
29
|
+
fontFamily?: string;
|
|
30
|
+
fontWeight?: string;
|
|
31
|
+
flexDirection?: FlexDirectionOptionType;
|
|
32
|
+
flexWrap?: FlexWrapOptionType;
|
|
33
|
+
alignItems?: AlignItemsOptionType;
|
|
34
|
+
justifyContent?: JustifyContentOptionType;
|
|
35
|
+
gap?: string;
|
|
36
|
+
padding?: string;
|
|
37
|
+
paddingHorizontal?: string;
|
|
38
|
+
paddingVertical?: string;
|
|
39
|
+
paddingTop?: string;
|
|
40
|
+
paddingBottom?: string;
|
|
41
|
+
paddingLeft?: string;
|
|
42
|
+
paddingRight?: string;
|
|
43
|
+
margin?: string;
|
|
44
|
+
marginHorizontal?: string;
|
|
45
|
+
marginVertical?: string;
|
|
46
|
+
marginTop?: string;
|
|
47
|
+
marginBottom?: string;
|
|
48
|
+
marginLeft?: string;
|
|
49
|
+
marginRight?: string;
|
|
50
|
+
backgroundColor?: string;
|
|
51
|
+
borderRadius?: string;
|
|
52
|
+
width?: string;
|
|
53
|
+
minWidth?: string;
|
|
54
|
+
maxWidth?: string;
|
|
55
|
+
height?: string;
|
|
56
|
+
minHeight?: string;
|
|
57
|
+
maxHeight?: string;
|
|
58
|
+
flex?: number;
|
|
59
|
+
position?: PositionOptionType;
|
|
60
|
+
top?: string;
|
|
61
|
+
bottom?: string;
|
|
62
|
+
left?: string;
|
|
63
|
+
right?: string;
|
|
64
|
+
zIndex?: number;
|
|
65
|
+
textDecorationLine?: TextDecorationLineOptionType;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PriceTagPropsGenerated {
|
|
69
|
+
child: string;
|
|
70
|
+
attributes: {
|
|
71
|
+
style?: PriceTagStyleGenerated;
|
|
72
|
+
adjustsFontSizeToFit?: boolean;
|
|
73
|
+
showEllipsis?: boolean;
|
|
74
|
+
translateCounter?: number;
|
|
75
|
+
scrollable?: boolean;
|
|
76
|
+
showOriginalPricePossible?: boolean;
|
|
77
|
+
hideIfItsNotDiscount?: boolean;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface PriceTagComponentProps {
|
|
82
|
+
node: NodeData<PriceTagPropsGenerated['attributes']>;
|
|
83
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"pattern": {
|
|
4
|
+
"type": "PriceTag",
|
|
5
|
+
"title": "title",
|
|
6
|
+
"description": "description",
|
|
7
|
+
"children": "string",
|
|
8
|
+
"extends": "Text",
|
|
9
|
+
"attributes": {
|
|
10
|
+
"showOriginalPricePossible": "boolean",
|
|
11
|
+
"hideIfItsNotDiscount": "boolean",
|
|
12
|
+
"style": {
|
|
13
|
+
"textDecorationLine": ["none", "underline", "line-through"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"defaults": {
|
|
18
|
+
"style": {
|
|
19
|
+
"fontSize": "16@fs",
|
|
20
|
+
"fontWeight": "700"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"meta": {
|
|
24
|
+
"desiredParent": [">PaywallProvider"],
|
|
25
|
+
"label": "Price Tag",
|
|
26
|
+
"description": "Displays a price tag text. Extends Text.",
|
|
27
|
+
"styles": {
|
|
28
|
+
"textDecorationLine": {
|
|
29
|
+
"label": "Text Decoration",
|
|
30
|
+
"description": "Text decoration line style (e.g. line-through for strikethrough).",
|
|
31
|
+
"category": "style",
|
|
32
|
+
"specialCategory": null,
|
|
33
|
+
"sort": 6
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"attributes": {
|
|
37
|
+
"showOriginalPricePossible": {
|
|
38
|
+
"label": "Show Original Price Possible",
|
|
39
|
+
"description": "When enabled, shows the original price if available.",
|
|
40
|
+
"category": "other",
|
|
41
|
+
"specialCategory": null,
|
|
42
|
+
"sort": 1
|
|
43
|
+
},
|
|
44
|
+
"hideIfItsNotDiscount": {
|
|
45
|
+
"label": "Hide If No Discount",
|
|
46
|
+
"description": "Hides this element when there is no active discount/promo.",
|
|
47
|
+
"category": "other",
|
|
48
|
+
"specialCategory": null,
|
|
49
|
+
"sort": 2
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PricingComponentProps } from './PricingProps.generated';
|
|
3
|
+
import Text from '../Text/Text';
|
|
4
|
+
import useNode from '../useNode';
|
|
5
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
6
|
+
|
|
7
|
+
function Pricing({ node }: PricingComponentProps) {
|
|
8
|
+
useLogRender('Pricing');
|
|
9
|
+
node = useNode(node);
|
|
10
|
+
return <Text node={node} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default React.memo(Pricing);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
|
|
3
|
+
import type { NodeData } from '../../types/Node';
|
|
4
|
+
|
|
5
|
+
export type FlexDirectionOptionType = 'row' | 'column';
|
|
6
|
+
export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
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 PricingStyleGenerated {
|
|
23
|
+
color?: string;
|
|
24
|
+
fontSize?: string;
|
|
25
|
+
fontFamily?: string;
|
|
26
|
+
fontWeight?: string;
|
|
27
|
+
flexDirection?: FlexDirectionOptionType;
|
|
28
|
+
flexWrap?: FlexWrapOptionType;
|
|
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 PricingPropsGenerated {
|
|
64
|
+
child: string;
|
|
65
|
+
attributes: {
|
|
66
|
+
style?: PricingStyleGenerated;
|
|
67
|
+
adjustsFontSizeToFit?: boolean;
|
|
68
|
+
showEllipsis?: boolean;
|
|
69
|
+
translateCounter?: number;
|
|
70
|
+
scrollable?: boolean;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PricingComponentProps {
|
|
75
|
+
node: NodeData<PricingPropsGenerated['attributes']>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"pattern": {
|
|
4
|
+
"type": "Pricing",
|
|
5
|
+
"title": "title",
|
|
6
|
+
"description": "base.builder.paywall.pricing.default.text",
|
|
7
|
+
"children": "string",
|
|
8
|
+
"extends": "Text"
|
|
9
|
+
},
|
|
10
|
+
"defaults": {
|
|
11
|
+
"translateCounter": 2,
|
|
12
|
+
"style": {
|
|
13
|
+
"textAlign": "center",
|
|
14
|
+
"fontSize": "12@fs",
|
|
15
|
+
"fontWeight": "400",
|
|
16
|
+
"color": "rgba(255,255,255,0.6)"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"meta": {
|
|
20
|
+
"desiredParent": [">PaywallProvider"],
|
|
21
|
+
"label": "Pricing",
|
|
22
|
+
"description": "Displays pricing details (e.g. promo/trial breakdown). Extends Text.",
|
|
23
|
+
"styles": {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PromoComponentProps } from './PromoProps.generated';
|
|
3
|
+
import Text from '../Text/Text';
|
|
4
|
+
import useNode from '../useNode';
|
|
5
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
6
|
+
|
|
7
|
+
function Promo({ node }: PromoComponentProps) {
|
|
8
|
+
useLogRender('Promo');
|
|
9
|
+
node = useNode(node);
|
|
10
|
+
return <Text node={node} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default React.memo(Promo);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
|
|
3
|
+
import type { NodeData } from '../../types/Node';
|
|
4
|
+
|
|
5
|
+
export type FlexDirectionOptionType = 'row' | 'column';
|
|
6
|
+
export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
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 PromoStyleGenerated {
|
|
23
|
+
color?: string;
|
|
24
|
+
fontSize?: string;
|
|
25
|
+
fontFamily?: string;
|
|
26
|
+
fontWeight?: string;
|
|
27
|
+
flexDirection?: FlexDirectionOptionType;
|
|
28
|
+
flexWrap?: FlexWrapOptionType;
|
|
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 PromoPropsGenerated {
|
|
64
|
+
child: string;
|
|
65
|
+
attributes: {
|
|
66
|
+
style?: PromoStyleGenerated;
|
|
67
|
+
adjustsFontSizeToFit?: boolean;
|
|
68
|
+
showEllipsis?: boolean;
|
|
69
|
+
translateCounter?: number;
|
|
70
|
+
scrollable?: boolean;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PromoComponentProps {
|
|
75
|
+
node: NodeData<PromoPropsGenerated['attributes']>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"pattern": {
|
|
4
|
+
"type": "Promo",
|
|
5
|
+
"title": "title",
|
|
6
|
+
"description": "base.builder.paywall.promo.default.text",
|
|
7
|
+
"children": "string",
|
|
8
|
+
"extends": "Text"
|
|
9
|
+
},
|
|
10
|
+
"defaults": {
|
|
11
|
+
"translateCounter": 2,
|
|
12
|
+
"style": {
|
|
13
|
+
"textAlign": "center",
|
|
14
|
+
"fontSize": "12@fs",
|
|
15
|
+
"fontWeight": "600",
|
|
16
|
+
"color": "#34D399"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"meta": {
|
|
20
|
+
"desiredParent": [">PaywallProvider"],
|
|
21
|
+
"label": "Promo",
|
|
22
|
+
"description": "Displays promotional badge/text (e.g. discount percentage). Extends Text.",
|
|
23
|
+
"styles": {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -35,11 +35,9 @@ export function RadioButtonBase({
|
|
|
35
35
|
const sizeHalf = Math.round(size * 0.5);
|
|
36
36
|
|
|
37
37
|
const paramsContext = useContext(ParamsContext);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
? String(otherParams.isSelected).toLowerCase() === 'true'
|
|
42
|
-
: selected;
|
|
38
|
+
const { singleProductIsSelected: contextIsSelected } =
|
|
39
|
+
paramsContext?.otherParams ?? {};
|
|
40
|
+
const newSelected = contextIsSelected ?? selected;
|
|
43
41
|
return (
|
|
44
42
|
<div style={{ marginLeft: 8, marginRight: 16 }}>
|
|
45
43
|
<div
|
|
@@ -40,6 +40,9 @@ import type { PaywallCloseButtonComponentProps } from './PaywallCloseButton/Payw
|
|
|
40
40
|
import type { PaywallOptionsComponentProps } from './PaywallOptions/PaywallOptionsProps.generated';
|
|
41
41
|
import type { PaywallProviderComponentProps } from './PaywallProvider/PaywallProviderProps.generated';
|
|
42
42
|
import type { PaywallSubscribeButtonComponentProps } from './PaywallSubscribeButton/PaywallSubscribeButtonProps.generated';
|
|
43
|
+
import type { PriceTagComponentProps } from './PriceTag/PriceTagProps.generated';
|
|
44
|
+
import type { PricingComponentProps } from './Pricing/PricingProps.generated';
|
|
45
|
+
import type { PromoComponentProps } from './Promo/PromoProps.generated';
|
|
43
46
|
import type { RadioButtonComponentProps } from './RadioButton/RadioButtonProps.generated';
|
|
44
47
|
import type { SeparatorComponentProps } from './Separator/SeparatorProps.generated';
|
|
45
48
|
import type { StatusBarColorComponentProps } from './StatusBarColor/StatusBarColorProps.generated';
|
|
@@ -72,6 +75,9 @@ import PaywallCloseButton from './PaywallCloseButton/PaywallCloseButton';
|
|
|
72
75
|
import PaywallOptions from './PaywallOptions/PaywallOptions';
|
|
73
76
|
import PaywallProvider from './PaywallProvider/PaywallProvider';
|
|
74
77
|
import PaywallSubscribeButton from './PaywallSubscribeButton/PaywallSubscribeButton';
|
|
78
|
+
import PriceTag from './PriceTag/PriceTag';
|
|
79
|
+
import Pricing from './Pricing/Pricing';
|
|
80
|
+
import Promo from './Promo/Promo';
|
|
75
81
|
import RadioButton from './RadioButton/RadioButton';
|
|
76
82
|
import Separator from './Separator/Separator';
|
|
77
83
|
import StatusBarColor from './StatusBarColor/StatusBarColor';
|
|
@@ -108,6 +114,9 @@ type BuilderNode =
|
|
|
108
114
|
| (PaywallSubscribeButtonComponentProps['node'] & {
|
|
109
115
|
type: 'PaywallSubscribeButton';
|
|
110
116
|
})
|
|
117
|
+
| (PriceTagComponentProps['node'] & { type: 'PriceTag' })
|
|
118
|
+
| (PricingComponentProps['node'] & { type: 'Pricing' })
|
|
119
|
+
| (PromoComponentProps['node'] & { type: 'Promo' })
|
|
111
120
|
| (RadioButtonComponentProps['node'] & { type: 'RadioButton' })
|
|
112
121
|
| (SeparatorComponentProps['node'] & { type: 'Separator' })
|
|
113
122
|
| (StatusBarColorComponentProps['node'] & { type: 'StatusBarColor' })
|
|
@@ -198,6 +207,12 @@ function RenderNode({ node }: { node: Node }) {
|
|
|
198
207
|
return <PaywallProvider node={normalizedNode} />;
|
|
199
208
|
case 'PaywallSubscribeButton':
|
|
200
209
|
return <PaywallSubscribeButton node={normalizedNode} />;
|
|
210
|
+
case 'PriceTag':
|
|
211
|
+
return <PriceTag node={normalizedNode} />;
|
|
212
|
+
case 'Pricing':
|
|
213
|
+
return <Pricing node={normalizedNode} />;
|
|
214
|
+
case 'Promo':
|
|
215
|
+
return <Promo node={normalizedNode} />;
|
|
201
216
|
case 'RadioButton':
|
|
202
217
|
return <RadioButton node={normalizedNode} />;
|
|
203
218
|
case 'Separator':
|
|
@@ -11,7 +11,7 @@ function StatusBarColor({ node }: StatusBarColorComponentProps) {
|
|
|
11
11
|
useLogRender('StatusBarColor');
|
|
12
12
|
node = useNode(node);
|
|
13
13
|
|
|
14
|
-
const {
|
|
14
|
+
const { theme, projectColors } = useBuilderParams();
|
|
15
15
|
const setStatusBarOverrideColor = useRenderStore(
|
|
16
16
|
(s) => s.setStatusBarOverrideColor,
|
|
17
17
|
);
|
|
@@ -21,7 +21,7 @@ function StatusBarColor({ node }: StatusBarColorComponentProps) {
|
|
|
21
21
|
| undefined;
|
|
22
22
|
const resolvedColor = parseColor(rawBg, {
|
|
23
23
|
projectColors,
|
|
24
|
-
theme
|
|
24
|
+
theme,
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
useEffect(() => {
|
|
@@ -26,11 +26,18 @@ function Text({ node }: TextComponentProps) {
|
|
|
26
26
|
node,
|
|
27
27
|
});
|
|
28
28
|
const localize = useLocalize({ appConfig });
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const translateCounter = (node.attributes as Record<string, unknown>)
|
|
30
|
+
?.translateCounter as number | undefined;
|
|
31
|
+
|
|
32
|
+
const localizedText = useMemo(() => {
|
|
33
|
+
let text = localize(keyOrText);
|
|
34
|
+
const passes = translateCounter ?? 1;
|
|
35
|
+
for (let i = 1; i < passes; i++) {
|
|
36
|
+
text = localize(text);
|
|
37
|
+
}
|
|
38
|
+
return text;
|
|
39
|
+
//Optimzation trade off by readability: could avoid dict lookup on subsequent passes
|
|
40
|
+
}, [localize, keyOrText, translateCounter]);
|
|
34
41
|
|
|
35
42
|
const styleBag = node.attributes?.style as unknown as
|
|
36
43
|
| { adjustsFontSizeToFit?: boolean; showEllipsis?: boolean }
|
|
@@ -18,7 +18,6 @@ export type JustifyContentOptionType =
|
|
|
18
18
|
| 'space-around'
|
|
19
19
|
| 'space-evenly';
|
|
20
20
|
export type PositionOptionType = 'relative' | 'absolute';
|
|
21
|
-
export type TextAlignOptionType = 'left' | 'center' | 'right' | 'justify';
|
|
22
21
|
|
|
23
22
|
export interface TextStyleGenerated {
|
|
24
23
|
flexDirection?: FlexDirectionOptionType;
|
|
@@ -59,7 +58,6 @@ export interface TextStyleGenerated {
|
|
|
59
58
|
fontSize?: string;
|
|
60
59
|
fontFamily?: string;
|
|
61
60
|
fontWeight?: string;
|
|
62
|
-
textAlign?: TextAlignOptionType;
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
export interface TextPropsGenerated {
|
|
@@ -69,6 +67,7 @@ export interface TextPropsGenerated {
|
|
|
69
67
|
scrollable?: boolean;
|
|
70
68
|
adjustsFontSizeToFit?: boolean;
|
|
71
69
|
showEllipsis?: boolean;
|
|
70
|
+
translateCounter?: number;
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -9,15 +9,16 @@
|
|
|
9
9
|
"attributes": {
|
|
10
10
|
"adjustsFontSizeToFit": "boolean",
|
|
11
11
|
"showEllipsis": "boolean",
|
|
12
|
+
"translateCounter": "number",
|
|
12
13
|
"style": {
|
|
13
14
|
"color": "color",
|
|
14
15
|
"fontSize": "size",
|
|
15
16
|
"fontFamily": "fontFamily",
|
|
16
|
-
"fontWeight": "fontWeight"
|
|
17
|
-
"textAlign": ["left", "center", "right", "justify"]
|
|
17
|
+
"fontWeight": "fontWeight"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"defaults": {
|
|
21
|
+
"translateCounter": 1,
|
|
21
22
|
"style": {
|
|
22
23
|
"color": "THEME_COLORS.TEXT",
|
|
23
24
|
"fontSize": "16@fs",
|