@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
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product types for IAP.
|
|
3
|
+
*
|
|
4
|
+
* All platform-specific fields (iOS/Android) are included.
|
|
5
|
+
*
|
|
6
|
+
* See: `https://www.npmjs.com/package/react-native-iap`
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Purchase type: subscription or one-time in-app purchase. */
|
|
10
|
+
export type PurchaseType = 'in-app' | 'subs';
|
|
11
|
+
|
|
12
|
+
/** Subscription offer type */
|
|
13
|
+
export type SubscriptionOfferType = 'introductory' | 'promotional';
|
|
14
|
+
|
|
15
|
+
/** Payment mode */
|
|
16
|
+
export type PaymentMode = 'pay-as-you-go' | 'pay-up-front' | 'free-trial';
|
|
17
|
+
|
|
18
|
+
/** recurrenceMode values from Google Play Billing */
|
|
19
|
+
export type RecurrenceMode = 1 | 2 | 3;
|
|
20
|
+
// 1 = INFINITE_RECURRING (normal subscription)
|
|
21
|
+
// 2 = FINITE_RECURRING (limited cycles, e.g. promo)
|
|
22
|
+
// 3 = NON_RECURRING (one-time, e.g. trial)
|
|
23
|
+
|
|
24
|
+
/** iOS subscription period unit */
|
|
25
|
+
export type IOSPeriodUnit = 'DAY' | 'WEEK' | 'MONTH' | 'YEAR';
|
|
26
|
+
|
|
27
|
+
/** Normalized period unit */
|
|
28
|
+
export type PeriodUnit = 'day' | 'week' | 'month' | 'year';
|
|
29
|
+
|
|
30
|
+
/** A single billing phase (Google Play Billing) */
|
|
31
|
+
export interface PricingPhase {
|
|
32
|
+
/** ISO 8601 duration (e.g. "P1M", "P1Y", "P7D") */
|
|
33
|
+
billingPeriod: string;
|
|
34
|
+
/** How many times this phase repeats (0 = infinite) */
|
|
35
|
+
billingCycleCount: number;
|
|
36
|
+
/** Human-readable price (e.g. "$4.99") */
|
|
37
|
+
formattedPrice: string;
|
|
38
|
+
/** Price in micros (e.g. "4990000"). "0" = free (trial) */
|
|
39
|
+
priceAmountMicros: string;
|
|
40
|
+
/** Currency code (e.g. "USD") */
|
|
41
|
+
priceCurrencyCode: string;
|
|
42
|
+
/** Recurrence mode: 1=infinite, 2=finite/promo, 3=one-time/trial */
|
|
43
|
+
recurrenceMode: RecurrenceMode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Android raw offer details (from Google Play Billing API) */
|
|
47
|
+
export interface AndroidOfferDetails {
|
|
48
|
+
basePlanId: string;
|
|
49
|
+
offerId?: string;
|
|
50
|
+
offerToken: string;
|
|
51
|
+
offerTags: string[];
|
|
52
|
+
pricingPhases: {
|
|
53
|
+
pricingPhaseList: PricingPhase[];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Normalized subscription offer (cross-platform) */
|
|
58
|
+
export interface SubscriptionOffer {
|
|
59
|
+
id: string;
|
|
60
|
+
displayPrice: string;
|
|
61
|
+
price: number;
|
|
62
|
+
type: SubscriptionOfferType;
|
|
63
|
+
currency: string;
|
|
64
|
+
paymentMode?: PaymentMode;
|
|
65
|
+
periodCount?: number;
|
|
66
|
+
period?: {
|
|
67
|
+
unit: PeriodUnit;
|
|
68
|
+
value: number;
|
|
69
|
+
};
|
|
70
|
+
// Android specific
|
|
71
|
+
basePlanIdAndroid?: string;
|
|
72
|
+
offerTokenAndroid?: string;
|
|
73
|
+
offerTagsAndroid?: string[];
|
|
74
|
+
pricingPhasesAndroid?: {
|
|
75
|
+
pricingPhaseList: PricingPhase[];
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** iOS introductory price */
|
|
80
|
+
export interface IOSIntroductoryPrice {
|
|
81
|
+
price: string;
|
|
82
|
+
priceIOS?: string;
|
|
83
|
+
type: 'free_trial' | 'pay_as_you_go' | 'pay_up_front';
|
|
84
|
+
numberOfPeriods: number;
|
|
85
|
+
subscriptionPeriod?: IOSPeriodUnit;
|
|
86
|
+
subscriptionPeriodUnitIOS?: IOSPeriodUnit;
|
|
87
|
+
subscriptionPeriodNumberIOS?: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** iOS promotional discount */
|
|
91
|
+
export interface IOSDiscount {
|
|
92
|
+
identifier: string;
|
|
93
|
+
price: string;
|
|
94
|
+
numberOfPeriods: number;
|
|
95
|
+
subscriptionPeriod: IOSPeriodUnit;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Product input coming from builder for membership initialization. */
|
|
99
|
+
export interface ProductInput {
|
|
100
|
+
store_package_id: string;
|
|
101
|
+
offer_id?: string;
|
|
102
|
+
type?: string;
|
|
103
|
+
is_consumable?: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Unified product representation for IAP */
|
|
107
|
+
export interface Product {
|
|
108
|
+
/** iOS: `productId`, Android: `id` (normalized to productId) */
|
|
109
|
+
productId: string;
|
|
110
|
+
/** Android raw id */
|
|
111
|
+
id?: string;
|
|
112
|
+
|
|
113
|
+
title?: string;
|
|
114
|
+
description?: string;
|
|
115
|
+
displayName?: string;
|
|
116
|
+
displayPrice?: string;
|
|
117
|
+
localizedPrice?: string;
|
|
118
|
+
price?: string;
|
|
119
|
+
currency?: string;
|
|
120
|
+
currencyCode?: string;
|
|
121
|
+
platform?: 'android' | 'ios';
|
|
122
|
+
debugDescription?: string | null;
|
|
123
|
+
|
|
124
|
+
/** Offer identifier from builder (Android offer token) */
|
|
125
|
+
offerId?: string;
|
|
126
|
+
type?: PurchaseType;
|
|
127
|
+
isConsumable?: boolean;
|
|
128
|
+
|
|
129
|
+
// Android specific
|
|
130
|
+
nameAndroid?: string;
|
|
131
|
+
productStatusAndroid?: unknown | null;
|
|
132
|
+
oneTimePurchaseOfferDetailsAndroid?: unknown | null;
|
|
133
|
+
discountOffers?: unknown | null;
|
|
134
|
+
/** Raw Google Play offer details */
|
|
135
|
+
subscriptionOfferDetailsAndroid?: AndroidOfferDetails[];
|
|
136
|
+
/** Normalized cross-platform offers */
|
|
137
|
+
subscriptionOffers?: SubscriptionOffer[];
|
|
138
|
+
|
|
139
|
+
// iOS specific
|
|
140
|
+
introductoryPrice?: IOSIntroductoryPrice;
|
|
141
|
+
introductoryPriceIOS?: IOSIntroductoryPrice;
|
|
142
|
+
discounts?: IOSDiscount[];
|
|
143
|
+
subscriptionPeriodUnitIOS?: IOSPeriodUnit;
|
|
144
|
+
subscriptionPeriodNumberIOS?: number;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Product params exposed as localization variables (e.g. @price, @promoPrice). */
|
|
148
|
+
export interface ProductParams {
|
|
149
|
+
price: string;
|
|
150
|
+
promoPrice: string;
|
|
151
|
+
currency: string;
|
|
152
|
+
localizedPrice: string;
|
|
153
|
+
period: string;
|
|
154
|
+
promoPeriod: string;
|
|
155
|
+
promoPeriodUnit: string;
|
|
156
|
+
hasTrial: string;
|
|
157
|
+
trialPeriod: string;
|
|
158
|
+
trialPeriodUnit: string;
|
|
159
|
+
discountPercentage: string;
|
|
160
|
+
localizedPeriod: string;
|
|
161
|
+
localizedPromoPeriod: string;
|
|
162
|
+
localizedPromoPrice: string;
|
|
163
|
+
localizedCalculatedPrice: string;
|
|
164
|
+
localizedCalculatedPeriod: string;
|
|
165
|
+
baseLocalizedPricingText: string;
|
|
166
|
+
baseLocalizedPromoText: string;
|
|
167
|
+
productTitle: string;
|
|
168
|
+
productDescription: string;
|
|
169
|
+
productCurreny: string;
|
|
170
|
+
productId: string;
|
|
171
|
+
productSelected: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Keys excluded from single (per-option) params — these are global/context-level. */
|
|
175
|
+
type SingleExcludedKeys = 'productId' | 'productSelected';
|
|
176
|
+
|
|
177
|
+
/** Per-option (single product) params — same keys as ProductParams prefixed with `single`. */
|
|
178
|
+
export type SingleProductParams = {
|
|
179
|
+
[K in keyof Omit<
|
|
180
|
+
ProductParams,
|
|
181
|
+
SingleExcludedKeys
|
|
182
|
+
> as `single${Capitalize<K>}`]: ProductParams[K];
|
|
183
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic React hook for extracting paywall localization params.
|
|
3
|
+
*
|
|
4
|
+
* All runtime dependencies (platform, localize, builderProducts) are injected
|
|
5
|
+
* via the `config` parameter — no hard-coded imports to any specific project.
|
|
6
|
+
*
|
|
7
|
+
* Usage (React Native / core):
|
|
8
|
+
* usePaywallLocalizationParams(product, productId, {
|
|
9
|
+
* platform: Platform.OS,
|
|
10
|
+
* localize: (key) => localize(key),
|
|
11
|
+
* builderProducts: builder.products,
|
|
12
|
+
* })
|
|
13
|
+
*
|
|
14
|
+
* Usage (Web builder):
|
|
15
|
+
* usePaywallLocalizationParams(product, productId, {
|
|
16
|
+
* platform: device.platform,
|
|
17
|
+
* localize,
|
|
18
|
+
* })
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { useMemo } from 'react';
|
|
22
|
+
import { buildPaywallLocalizationParams } from './buildPaywallLocalizationParams';
|
|
23
|
+
import type { Product, ProductInput, ProductParams } from './types';
|
|
24
|
+
|
|
25
|
+
export type PaywallLocalizationConfig = {
|
|
26
|
+
/** 'ios' | 'android' — RN: Platform.OS, Web: device.platform */
|
|
27
|
+
platform: 'ios' | 'android';
|
|
28
|
+
/** Translates a localization key to a display string. Falls back to identity. */
|
|
29
|
+
localize?: (key: string) => string;
|
|
30
|
+
/** Builder product definitions — used to resolve offer_id for a product. */
|
|
31
|
+
builderProducts?: ProductInput[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function usePaywallLocalizationParams(
|
|
35
|
+
selectedProduct?: Product,
|
|
36
|
+
selectedProductId?: string,
|
|
37
|
+
config?: PaywallLocalizationConfig,
|
|
38
|
+
): Partial<ProductParams> {
|
|
39
|
+
return useMemo(() => {
|
|
40
|
+
if (!selectedProduct || !config?.platform) {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const builderProduct = config.builderProducts?.find(
|
|
46
|
+
(p) => p.store_package_id === selectedProductId,
|
|
47
|
+
);
|
|
48
|
+
const offerId = builderProduct?.offer_id;
|
|
49
|
+
|
|
50
|
+
return buildPaywallLocalizationParams(
|
|
51
|
+
selectedProduct,
|
|
52
|
+
config.platform,
|
|
53
|
+
offerId,
|
|
54
|
+
config.localize,
|
|
55
|
+
);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('[usePaywallLocalizationParams] Error:', error);
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}, [selectedProduct, selectedProductId, config]);
|
|
61
|
+
}
|
package/src/store.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
2
2
|
import { shallow } from 'zustand/shallow';
|
|
3
3
|
import type { Device } from './types/Device';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
defaultAppConfig,
|
|
6
|
+
defaultTheme,
|
|
7
|
+
type AppConfig,
|
|
8
|
+
type Theme,
|
|
9
|
+
} from './types/PreviewConfig';
|
|
5
10
|
import { getDefaultDevice } from './utils/getDevices';
|
|
6
11
|
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
7
12
|
import { Node } from './types/Node';
|
|
@@ -28,6 +33,12 @@ type RenderStore = {
|
|
|
28
33
|
setAppConfig: (appConfig: AppConfig) => void;
|
|
29
34
|
projectColors?: ProjectColors;
|
|
30
35
|
setProjectColors: (projectColors?: ProjectColors) => void;
|
|
36
|
+
theme: Theme;
|
|
37
|
+
setTheme: (theme: Theme) => void;
|
|
38
|
+
defaultLanguage: string;
|
|
39
|
+
setDefaultLanguage: (lang: string) => void;
|
|
40
|
+
isRtl: boolean;
|
|
41
|
+
setIsRtl: (isRtl: boolean) => void;
|
|
31
42
|
previewMode: boolean;
|
|
32
43
|
setPreviewMode: (previewMode: boolean) => void;
|
|
33
44
|
// Mockable: products (persisted)
|
|
@@ -99,6 +110,12 @@ export const useRenderStore = createWithEqualityFn<RenderStore>()(
|
|
|
99
110
|
setAppConfig: (appConfig) => set({ appConfig }),
|
|
100
111
|
projectColors: undefined,
|
|
101
112
|
setProjectColors: (projectColors) => set({ projectColors }),
|
|
113
|
+
theme: defaultTheme,
|
|
114
|
+
setTheme: (theme) => set({ theme }),
|
|
115
|
+
defaultLanguage: 'en',
|
|
116
|
+
setDefaultLanguage: (lang) => set({ defaultLanguage: lang }),
|
|
117
|
+
isRtl: false,
|
|
118
|
+
setIsRtl: (isRtl) => set({ isRtl }),
|
|
102
119
|
previewMode: false,
|
|
103
120
|
setPreviewMode: (previewMode) => set({ previewMode }),
|
|
104
121
|
products: [],
|
package/src/styles/index.scss
CHANGED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
@use '../foundation/colors' as colors;
|
|
2
|
+
@use '../foundation/sizes' as sizes;
|
|
3
|
+
|
|
4
|
+
.inspect-modal__content {
|
|
5
|
+
width: calc(100vw - 32px);
|
|
6
|
+
height: calc(100vh - 64px);
|
|
7
|
+
max-width: 900px;
|
|
8
|
+
max-height: calc(100vh - 64px);
|
|
9
|
+
padding: 0;
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.inspect-modal__header {
|
|
15
|
+
padding: sizes.$spaceComfy sizes.$spaceRoomy;
|
|
16
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.inspect-modal__tabs {
|
|
20
|
+
display: flex;
|
|
21
|
+
gap: 0;
|
|
22
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
23
|
+
padding: 0 sizes.$spaceRoomy;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.inspect-modal__tab {
|
|
27
|
+
all: unset;
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
padding: sizes.$spaceCompact sizes.$spaceComfy;
|
|
30
|
+
font-size: sizes.$fontSizeSmPlus;
|
|
31
|
+
font-weight: 500;
|
|
32
|
+
color: colors.$mutedTextColor;
|
|
33
|
+
border-bottom: 2px solid transparent;
|
|
34
|
+
transition: color 0.15s, border-color 0.15s;
|
|
35
|
+
|
|
36
|
+
&:hover {
|
|
37
|
+
color: colors.$textColor;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&.is-active {
|
|
41
|
+
color: colors.$accentColor;
|
|
42
|
+
border-bottom-color: colors.$accentColor;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.inspect-modal__body {
|
|
47
|
+
flex: 1;
|
|
48
|
+
min-height: 0;
|
|
49
|
+
overflow: auto;
|
|
50
|
+
padding: sizes.$spaceRoomy;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.inspect-modal__empty {
|
|
54
|
+
margin: 0;
|
|
55
|
+
font-size: sizes.$fontSizeSmPlus;
|
|
56
|
+
color: colors.$mutedTextColor;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.inspect-modal__section-title {
|
|
60
|
+
margin: sizes.$spaceComfy 0 sizes.$spaceCompact;
|
|
61
|
+
font-size: sizes.$fontSizeSmPlus;
|
|
62
|
+
font-weight: 600;
|
|
63
|
+
color: colors.$textColor;
|
|
64
|
+
|
|
65
|
+
&:first-child {
|
|
66
|
+
margin-top: 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.inspect-modal__table-wrap {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.inspect-modal__table {
|
|
76
|
+
width: 100%;
|
|
77
|
+
border-collapse: collapse;
|
|
78
|
+
font-size: sizes.$fontSizeSm;
|
|
79
|
+
|
|
80
|
+
th {
|
|
81
|
+
text-align: left;
|
|
82
|
+
padding: sizes.$spaceSnug sizes.$spaceCompact;
|
|
83
|
+
font-weight: 600;
|
|
84
|
+
color: colors.$mutedTextColor;
|
|
85
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
86
|
+
white-space: nowrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
td {
|
|
90
|
+
padding: sizes.$spaceSnug sizes.$spaceCompact;
|
|
91
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
92
|
+
vertical-align: top;
|
|
93
|
+
color: colors.$textColor;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
tr:last-child td {
|
|
97
|
+
border-bottom: none;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.inspect-modal__cell-key {
|
|
102
|
+
font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'Segoe UI Mono', monospace;
|
|
103
|
+
font-size: sizes.$fontSizeXs;
|
|
104
|
+
word-break: break-all;
|
|
105
|
+
max-width: 320px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.inspect-modal__cell-key--nested {
|
|
109
|
+
padding-left: sizes.$spaceRoomy;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.inspect-modal__cell-value {
|
|
113
|
+
font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'Segoe UI Mono', monospace;
|
|
114
|
+
font-size: sizes.$fontSizeXs;
|
|
115
|
+
word-break: break-all;
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
gap: sizes.$spaceTight;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.inspect-modal__badge {
|
|
122
|
+
display: inline-block;
|
|
123
|
+
font-size: sizes.$fontSizeXs;
|
|
124
|
+
padding: 1px 6px;
|
|
125
|
+
border-radius: sizes.$radiusSoft;
|
|
126
|
+
font-weight: 500;
|
|
127
|
+
white-space: nowrap;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.inspect-modal__badge--default {
|
|
131
|
+
background: colors.$muted;
|
|
132
|
+
color: colors.$mutedTextColor;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.inspect-modal__badge--custom {
|
|
136
|
+
background: colors.$primary;
|
|
137
|
+
color: colors.$primaryForeground;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.inspect-modal__color-swatch {
|
|
141
|
+
display: inline-block;
|
|
142
|
+
width: 14px;
|
|
143
|
+
height: 14px;
|
|
144
|
+
border-radius: 3px;
|
|
145
|
+
border: 1px solid colors.$borderColor;
|
|
146
|
+
flex-shrink: 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.inspect-modal__separator-row td {
|
|
150
|
+
font-weight: 600;
|
|
151
|
+
font-size: sizes.$fontSizeSmPlus;
|
|
152
|
+
color: colors.$mutedTextColor;
|
|
153
|
+
padding-top: sizes.$spaceComfy;
|
|
154
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
155
|
+
}
|
|
@@ -1,24 +1,165 @@
|
|
|
1
|
+
export type Theme = 'light' | 'dark';
|
|
2
|
+
|
|
1
3
|
export interface AppConfig {
|
|
2
|
-
theme: 'light' | 'dark';
|
|
3
|
-
isRtl: boolean; //This could be device in future
|
|
4
|
-
screenStyle: {
|
|
5
|
-
light: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
6
|
-
dark: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
7
|
-
};
|
|
8
4
|
localication: Localication;
|
|
9
|
-
defaultLanguage?: string;
|
|
10
5
|
baseSize: { width: number; height: number };
|
|
11
6
|
}
|
|
12
7
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
export type LocalizationKey =
|
|
9
|
+
// paywall – period
|
|
10
|
+
| 'base.builder.paywall.period.monthly'
|
|
11
|
+
| 'base.builder.paywall.period.annual'
|
|
12
|
+
| 'base.builder.paywall.period.weekly'
|
|
13
|
+
| 'base.builder.paywall.period.daily'
|
|
14
|
+
| 'base.builder.paywall.period.monthlyPromo'
|
|
15
|
+
| 'base.builder.paywall.period.annualPromo'
|
|
16
|
+
// paywall – default texts
|
|
17
|
+
| 'base.builder.paywall.pricing.default.text'
|
|
18
|
+
| 'base.builder.paywall.pricing.freeTrial.text'
|
|
19
|
+
| 'base.builder.paywall.pricing.regular.text'
|
|
20
|
+
| 'base.builder.paywall.promo.default.text'
|
|
21
|
+
| 'base.builder.paywall.promo.freeTrial.text'
|
|
22
|
+
| 'base.builder.paywall.promo.regular.text'
|
|
23
|
+
// onboard – titles
|
|
24
|
+
| 'onboard.title.one-page'
|
|
25
|
+
| 'onboard.title.two-page'
|
|
26
|
+
| 'onboard.title.three-page'
|
|
27
|
+
| 'onboard.title.four-page'
|
|
28
|
+
| 'onboard.title.one-page2'
|
|
29
|
+
| 'onboard.title.two-page2'
|
|
30
|
+
| 'onboard.title.three-page2'
|
|
31
|
+
| 'onboard.title.four-page2'
|
|
32
|
+
// onboard – subtitles
|
|
33
|
+
| 'onboard.subtitle.one-page'
|
|
34
|
+
| 'onboard.subtitle.two-page'
|
|
35
|
+
| 'onboard.subtitle.three-page'
|
|
36
|
+
| 'onboard.subtitle.four-page'
|
|
37
|
+
| 'onboard.subtitle.one-page2'
|
|
38
|
+
| 'onboard.subtitle.two-page2'
|
|
39
|
+
| 'onboard.subtitle.three-page2'
|
|
40
|
+
| 'onboard.subtitle.four-page2'
|
|
41
|
+
// onboard – actions
|
|
42
|
+
| 'onboard.next.one-page'
|
|
43
|
+
| 'onboard.next.two-page'
|
|
44
|
+
| 'onboard.next.three-page'
|
|
45
|
+
| 'onboard.skip.one-page'
|
|
46
|
+
| 'onboard.skip.two-page'
|
|
47
|
+
| 'onboard.skip.three-page'
|
|
48
|
+
| 'onboard.allow.four-page'
|
|
49
|
+
// onboard – footer
|
|
50
|
+
| 'view.onboarding.footer.description'
|
|
51
|
+
| 'view.onboarding.btnPrivacy'
|
|
52
|
+
| 'view.onboarding.btnTerms'
|
|
53
|
+
| (string & {});
|
|
54
|
+
|
|
55
|
+
export type Localication = Record<
|
|
56
|
+
string,
|
|
57
|
+
Partial<Record<LocalizationKey, string>>
|
|
58
|
+
>;
|
|
59
|
+
|
|
60
|
+
export const defaultLocalization: Localication = {
|
|
61
|
+
en: {
|
|
62
|
+
// paywall – period
|
|
63
|
+
'base.builder.paywall.period.monthly': 'per month',
|
|
64
|
+
'base.builder.paywall.period.annual': 'per year',
|
|
65
|
+
'base.builder.paywall.period.weekly': 'per week',
|
|
66
|
+
'base.builder.paywall.period.daily': 'per day',
|
|
67
|
+
'base.builder.paywall.period.monthlyPromo': 'per month',
|
|
68
|
+
'base.builder.paywall.period.annualPromo': 'per year',
|
|
69
|
+
// paywall – default texts
|
|
70
|
+
'base.builder.paywall.pricing.default.text':
|
|
71
|
+
'@promoPrice for the first @promoPeriod, then @localizedPrice @localizedPeriod',
|
|
72
|
+
'base.builder.paywall.pricing.freeTrial.text':
|
|
73
|
+
'@trialPeriod-@trialPeriodUnit free trial, then @localizedPrice @localizedPeriod',
|
|
74
|
+
'base.builder.paywall.pricing.regular.text':
|
|
75
|
+
'@localizedPrice @localizedPeriod',
|
|
76
|
+
'base.builder.paywall.promo.default.text': 'Save @discountPercentage%!',
|
|
77
|
+
'base.builder.paywall.promo.freeTrial.text':
|
|
78
|
+
'@trialPeriod-@trialPeriodUnit free trial',
|
|
79
|
+
'base.builder.paywall.promo.regular.text':
|
|
80
|
+
'@localizedPrice @localizedPeriod',
|
|
81
|
+
// onboard – titles
|
|
82
|
+
'onboard.title.one-page': 'Secure your connection',
|
|
83
|
+
'onboard.title.two-page': 'Access content worldwide',
|
|
84
|
+
'onboard.title.three-page': 'Fast and reliable',
|
|
85
|
+
'onboard.title.four-page': 'Stay notified and safe',
|
|
86
|
+
'onboard.title.one-page2': 'Secure your connection',
|
|
87
|
+
'onboard.title.two-page2': 'Access content worldwide',
|
|
88
|
+
'onboard.title.three-page2': 'Fast and reliable',
|
|
89
|
+
'onboard.title.four-page2': 'Stay notified and safe',
|
|
90
|
+
// onboard – subtitles
|
|
91
|
+
'onboard.subtitle.one-page':
|
|
92
|
+
'Encrypt your traffic and protect your privacy on public Wi\u2011Fi.',
|
|
93
|
+
'onboard.subtitle.two-page':
|
|
94
|
+
'Connect to high\u2011speed servers in many countries with one tap.',
|
|
95
|
+
'onboard.subtitle.three-page':
|
|
96
|
+
'Auto\u2011connect to the best server for speed and stability.',
|
|
97
|
+
'onboard.subtitle.four-page':
|
|
98
|
+
'Enable notifications for connection status and security tips.',
|
|
99
|
+
'onboard.subtitle.one-page2':
|
|
100
|
+
'Encrypt your traffic and protect your privacy on public Wi\u2011Fi.',
|
|
101
|
+
'onboard.subtitle.two-page2':
|
|
102
|
+
'Connect to high\u2011speed servers in many countries with one tap.',
|
|
103
|
+
'onboard.subtitle.three-page2':
|
|
104
|
+
'Auto\u2011connect to the best server for speed and stability.',
|
|
105
|
+
'onboard.subtitle.four-page2':
|
|
106
|
+
'Enable notifications for connection status and security tips.',
|
|
107
|
+
// onboard – actions
|
|
108
|
+
'onboard.next.one-page': 'Next',
|
|
109
|
+
'onboard.next.two-page': 'Next',
|
|
110
|
+
'onboard.next.three-page': 'Next',
|
|
111
|
+
'onboard.skip.one-page': 'Skip',
|
|
112
|
+
'onboard.skip.two-page': 'Skip',
|
|
113
|
+
'onboard.skip.three-page': 'Skip',
|
|
114
|
+
'onboard.allow.four-page': 'Allow',
|
|
115
|
+
// onboard – footer
|
|
116
|
+
'view.onboarding.footer.description':
|
|
117
|
+
'By clicking continue, you will be accepting the Terms of service and privacy policy',
|
|
118
|
+
'view.onboarding.btnPrivacy': 'Privacy Policy',
|
|
119
|
+
'view.onboarding.btnTerms': 'Terms of Service',
|
|
120
|
+
},
|
|
121
|
+
tr: {
|
|
122
|
+
// paywall – period
|
|
123
|
+
'base.builder.paywall.period.monthly': 'aylık',
|
|
124
|
+
'base.builder.paywall.period.annual': 'yıllık',
|
|
125
|
+
'base.builder.paywall.period.weekly': 'haftalık',
|
|
126
|
+
'base.builder.paywall.period.daily': 'günlük',
|
|
127
|
+
'base.builder.paywall.period.monthlyPromo': 'aylık',
|
|
128
|
+
'base.builder.paywall.period.annualPromo': 'yıllık',
|
|
129
|
+
// paywall – default texts
|
|
130
|
+
'base.builder.paywall.pricing.default.text':
|
|
131
|
+
'İlk @promoPeriod için @promoPrice, sonra @localizedPrice @localizedPeriod',
|
|
132
|
+
'base.builder.paywall.pricing.freeTrial.text':
|
|
133
|
+
'@trialPeriod @trialPeriodUnit ücretsiz deneme, sonra @localizedPrice @localizedPeriod',
|
|
134
|
+
'base.builder.paywall.pricing.regular.text':
|
|
135
|
+
'@localizedPrice @localizedPeriod',
|
|
136
|
+
'base.builder.paywall.promo.default.text': '%@discountPercentage indirim!',
|
|
137
|
+
'base.builder.paywall.promo.freeTrial.text':
|
|
138
|
+
'@trialPeriod @trialPeriodUnit ücretsiz deneme',
|
|
139
|
+
'base.builder.paywall.promo.regular.text':
|
|
140
|
+
'@localizedPrice @localizedPeriod',
|
|
19
141
|
},
|
|
20
|
-
localication: {},
|
|
21
|
-
baseSize: { width: 375, height: 812 },
|
|
22
142
|
};
|
|
23
143
|
|
|
24
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Merges custom localization with base localization.
|
|
146
|
+
* Custom values override base values on a per-language, per-key basis.
|
|
147
|
+
*/
|
|
148
|
+
export function mergeLocalization(
|
|
149
|
+
base: Localication,
|
|
150
|
+
custom: Localication,
|
|
151
|
+
): Localication {
|
|
152
|
+
const allLanguages = new Set([...Object.keys(base), ...Object.keys(custom)]);
|
|
153
|
+
const merged: Localication = {};
|
|
154
|
+
for (const lang of allLanguages) {
|
|
155
|
+
merged[lang] = { ...(base[lang] || {}), ...(custom[lang] || {}) };
|
|
156
|
+
}
|
|
157
|
+
return merged;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const defaultTheme: Theme = 'light';
|
|
161
|
+
|
|
162
|
+
export const defaultAppConfig: AppConfig = {
|
|
163
|
+
localication: defaultLocalization,
|
|
164
|
+
baseSize: { width: 375, height: 812 },
|
|
165
|
+
};
|
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
TextPropsGenerated,
|
|
4
4
|
TextStyleGenerated,
|
|
5
5
|
} from '../../build-components/Text/TextProps.generated';
|
|
6
|
-
import type {
|
|
7
|
-
import {
|
|
6
|
+
import type { Theme } from '../../types/PreviewConfig';
|
|
7
|
+
import { defaultTheme } from '../../types/PreviewConfig';
|
|
8
8
|
import type { ProjectColors } from '../../types/Project';
|
|
9
9
|
import type { Fonts } from '../../types/Fonts';
|
|
10
10
|
import { fs, parseSize } from '../../size-matters';
|
|
@@ -85,7 +85,7 @@ function ensureFontWeightLoaded(
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
export type ExtractTextStyleOptions = {
|
|
88
|
-
|
|
88
|
+
theme?: Theme;
|
|
89
89
|
projectColors?: ProjectColors;
|
|
90
90
|
fonts?: Fonts;
|
|
91
91
|
onFontLoaded?: (fontFamily: string) => void;
|
|
@@ -105,10 +105,12 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
105
105
|
if (direct !== undefined && direct !== null) return direct;
|
|
106
106
|
return styleBag?.[key as keyof TextStyleGenerated];
|
|
107
107
|
};
|
|
108
|
-
const
|
|
109
|
-
const { screenStyle, theme } = resolvedAppConfig;
|
|
108
|
+
const theme = options.theme ?? defaultTheme;
|
|
110
109
|
const fallbackColor =
|
|
111
|
-
|
|
110
|
+
parseColor('THEME_COLORS.TEXT', {
|
|
111
|
+
projectColors: options.projectColors,
|
|
112
|
+
theme,
|
|
113
|
+
}) ?? 'THEME_COLORS.TEXT';
|
|
112
114
|
|
|
113
115
|
const style: React.CSSProperties = {};
|
|
114
116
|
|
|
@@ -178,6 +180,11 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
178
180
|
if (textAlign) {
|
|
179
181
|
style.textAlign = textAlign;
|
|
180
182
|
}
|
|
183
|
+
const textDecorationLine = get('textDecorationLine') as string | undefined;
|
|
184
|
+
if (textDecorationLine && textDecorationLine !== 'none') {
|
|
185
|
+
style.textDecorationLine =
|
|
186
|
+
textDecorationLine as React.CSSProperties['textDecorationLine'];
|
|
187
|
+
}
|
|
181
188
|
|
|
182
189
|
const viewStyle = extractViewStyle(node, {
|
|
183
190
|
projectColors: options.projectColors,
|
|
@@ -196,6 +203,7 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
196
203
|
'lineHeight',
|
|
197
204
|
'letterSpacing',
|
|
198
205
|
'textDecoration',
|
|
206
|
+
'textDecorationLine',
|
|
199
207
|
'textTransform',
|
|
200
208
|
]);
|
|
201
209
|
|