@developer_tribe/react-builder 1.2.27 → 1.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/assets/samples/getSamples.d.ts +0 -3
  2. package/dist/build-components/BIcon/BIconProps.generated.d.ts +1 -2
  3. package/dist/build-components/CountDown/CountDownProps.generated.d.ts +2 -1
  4. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +1 -2
  5. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +1 -2
  6. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +1 -2
  7. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +1 -2
  8. package/dist/build-components/PaywallOptions/usePaywallOptionParamsFactory.d.ts +1 -1
  9. package/dist/build-components/PriceTag/PriceTag.d.ts +5 -0
  10. package/dist/build-components/PriceTag/PriceTagProps.generated.d.ts +63 -0
  11. package/dist/build-components/Pricing/Pricing.d.ts +5 -0
  12. package/dist/build-components/Pricing/PricingProps.generated.d.ts +59 -0
  13. package/dist/build-components/Promo/Promo.d.ts +5 -0
  14. package/dist/build-components/Promo/PromoProps.generated.d.ts +59 -0
  15. package/dist/build-components/Text/TextProps.generated.d.ts +1 -2
  16. package/dist/build-components/index.d.ts +4 -1
  17. package/dist/build-components/patterns.generated.d.ts +1405 -202
  18. package/dist/components/BuilderProvider.d.ts +5 -3
  19. package/dist/components/ParamsProvider.d.ts +16 -8
  20. package/dist/hooks/useSyncHtmlThemeClass.d.ts +1 -1
  21. package/dist/index.cjs.js +4 -4
  22. package/dist/index.cjs.js.map +1 -1
  23. package/dist/index.d.ts +14 -3
  24. package/dist/index.esm.js +4 -4
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/index.web.cjs.js +4 -4
  27. package/dist/index.web.cjs.js.map +1 -1
  28. package/dist/index.web.esm.js +4 -4
  29. package/dist/index.web.esm.js.map +1 -1
  30. package/dist/logger.d.ts +18 -0
  31. package/dist/modals/InspectModal.d.ts +5 -0
  32. package/dist/modals/index.d.ts +1 -1
  33. package/dist/pages/ProjectPage.d.ts +3 -3
  34. package/dist/paywall/hooks/useCalculateLocalizedPrice.d.ts +4 -2
  35. package/dist/paywall/hooks/useDiscountRate.d.ts +3 -2
  36. package/dist/paywall/types/paywall-types.d.ts +7 -32
  37. package/dist/product-base/buildPaywallLocalizationParams.d.ts +16 -0
  38. package/dist/product-base/calculations.d.ts +29 -0
  39. package/dist/product-base/extractAndroidParams.d.ts +24 -0
  40. package/dist/product-base/extractIOSParams.d.ts +24 -0
  41. package/dist/product-base/index.d.ts +27 -0
  42. package/dist/product-base/periodLocalizationKeys.d.ts +44 -0
  43. package/dist/product-base/types.d.ts +155 -0
  44. package/dist/product-base/usePaywallLocalizationParams.d.ts +29 -0
  45. package/dist/store.d.ts +7 -1
  46. package/dist/styles.css +1 -1
  47. package/dist/types/PreviewConfig.d.ts +10 -16
  48. package/dist/utils/extractTextStyle/extractTextStyle.d.ts +2 -2
  49. package/dist/utils/extractTextStyle/extractTextStyleNative.d.ts +2 -2
  50. package/dist/utils/replaceLocalizationParams.d.ts +1 -1
  51. package/package.json +2 -2
  52. package/scripts/migrate-samples-to-current.ts +3 -3
  53. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +28 -12
  54. package/src/DeviceMockFrame.tsx +15 -10
  55. package/src/assets/meta.json +1 -1
  56. package/src/assets/samples/carousel-sample.json +6 -5
  57. package/src/assets/samples/getSamples.ts +16 -49
  58. package/src/assets/samples/paywall-1.json +64 -22
  59. package/src/assets/samples/paywall-2.json +0 -15
  60. package/src/assets/samples/paywall-app-delete-offer.json +0 -15
  61. package/src/assets/samples/paywall-app-open-offer.json +0 -15
  62. package/src/assets/samples/paywall-back-offer.json +0 -15
  63. package/src/assets/samples/paywall-notification-offer.json +0 -15
  64. package/src/assets/samples/simple-1.json +1 -16
  65. package/src/assets/samples/simple-2.json +0 -15
  66. package/src/assets/samples/unmigrated-builder-1.1.1.json +0 -3
  67. package/src/assets/samples/unmigrated-builder1.json +0 -3
  68. package/src/assets/samples/unvalidated-builder1.json +0 -3
  69. package/src/assets/samples/unvalidated-crash1.json +0 -3
  70. package/src/assets/samples/unvalidated-crashcomponent1.json +0 -3
  71. package/src/assets/samples/vpn-onboard-1.json +1 -34
  72. package/src/assets/samples/vpn-onboard-2.json +1 -34
  73. package/src/assets/samples/vpn-onboard-3.json +1 -42
  74. package/src/assets/samples/vpn-onboard-4.json +0 -73
  75. package/src/assets/samples/vpn-onboard-5.json +0 -73
  76. package/src/assets/samples/vpn-onboard-6.json +0 -73
  77. package/src/assets/samples/vpn-onboard-7.json +529 -0
  78. package/src/attribute-analyser/style/native/useExtractImageStyle.ts +1 -4
  79. package/src/attribute-analyser/style/native/useExtractTextStyle.ts +3 -12
  80. package/src/attribute-analyser/style/native/useExtractViewStyle.ts +1 -4
  81. package/src/attribute-analyser/style/web/useExtractImageStyle.ts +1 -4
  82. package/src/attribute-analyser/style/web/useExtractTextStyle.ts +3 -12
  83. package/src/attribute-analyser/style/web/useExtractViewStyle.ts +1 -4
  84. package/src/attributes-editor/useAttributesEditorModel.ts +5 -52
  85. package/src/build-components/BIcon/BIconProps.generated.ts +1 -2
  86. package/src/build-components/CarouselDots/CarouselDots.tsx +6 -13
  87. package/src/build-components/CountDown/CountDownProps.generated.ts +2 -1
  88. package/src/build-components/NavigationBarColor/NavigationBarColor.tsx +2 -2
  89. package/src/build-components/OnboardButton/OnboardButton.tsx +1 -2
  90. package/src/build-components/OnboardDot/OnboardDot.tsx +6 -18
  91. package/src/build-components/OnboardFooter/OnboardFooter.tsx +5 -3
  92. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +1 -2
  93. package/src/build-components/OnboardFooter/pattern.json +1 -1
  94. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +1 -2
  95. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +1 -2
  96. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +1 -2
  97. package/src/build-components/PaywallOptions/PaywallOptions.tsx +3 -3
  98. package/src/build-components/PaywallOptions/usePaywallOptionParamsFactory.ts +26 -13
  99. package/src/build-components/PaywallProvider/PaywallProvider.tsx +51 -12
  100. package/src/build-components/PriceTag/PriceTag.tsx +25 -0
  101. package/src/build-components/PriceTag/PriceTagProps.generated.ts +83 -0
  102. package/src/build-components/PriceTag/pattern.json +53 -0
  103. package/src/build-components/Pricing/Pricing.tsx +13 -0
  104. package/src/build-components/Pricing/PricingProps.generated.ts +76 -0
  105. package/src/build-components/Pricing/pattern.json +25 -0
  106. package/src/build-components/Promo/Promo.tsx +13 -0
  107. package/src/build-components/Promo/PromoProps.generated.ts +76 -0
  108. package/src/build-components/Promo/pattern.json +25 -0
  109. package/src/build-components/RadioButton/RadioButton.tsx +3 -5
  110. package/src/build-components/RenderNode.generated.tsx +15 -0
  111. package/src/build-components/StatusBarColor/StatusBarColor.tsx +2 -2
  112. package/src/build-components/Text/Text.tsx +12 -5
  113. package/src/build-components/Text/TextProps.generated.ts +1 -2
  114. package/src/build-components/Text/pattern.json +3 -2
  115. package/src/build-components/index.ts +15 -0
  116. package/src/build-components/patterns.generated.ts +1454 -181
  117. package/src/components/BottomBar.tsx +42 -39
  118. package/src/components/BuilderProvider.tsx +41 -14
  119. package/src/components/LocalizationParamsProvider.tsx +1 -1
  120. package/src/components/ParamsProvider.tsx +36 -11
  121. package/src/hooks/useLocalize.ts +7 -4
  122. package/src/hooks/useParams.ts +1 -1
  123. package/src/hooks/useSyncHtmlThemeClass.ts +2 -2
  124. package/src/index.ts +52 -8
  125. package/src/logger.ts +39 -0
  126. package/src/modals/InspectModal.tsx +331 -0
  127. package/src/modals/ProductPresetsModal.tsx +6 -13
  128. package/src/modals/index.ts +1 -1
  129. package/src/pages/DebugJsonPage.tsx +9 -22
  130. package/src/pages/ProjectDebug.tsx +1 -1
  131. package/src/pages/ProjectPage.tsx +29 -11
  132. package/src/pages/tabs/SideTool.tsx +28 -104
  133. package/src/paywall/hooks/useCalculateLocalizedPrice.ts +8 -3
  134. package/src/paywall/hooks/useDiscountRate.ts +11 -3
  135. package/src/paywall/types/paywall-types.ts +7 -38
  136. package/src/product-base/buildPaywallLocalizationParams.ts +100 -0
  137. package/src/product-base/calculations.ts +93 -0
  138. package/src/product-base/extractAndroidParams.ts +207 -0
  139. package/src/product-base/extractIOSParams.ts +199 -0
  140. package/src/product-base/index.ts +28 -0
  141. package/src/product-base/mockProducts.json +489 -0
  142. package/src/product-base/periodLocalizationKeys.ts +114 -0
  143. package/src/product-base/types.ts +183 -0
  144. package/src/product-base/usePaywallLocalizationParams.ts +61 -0
  145. package/src/store.ts +18 -1
  146. package/src/styles/index.scss +1 -0
  147. package/src/styles/modals/_inspect-modal.scss +155 -0
  148. package/src/types/PreviewConfig.ts +157 -16
  149. package/src/utils/extractTextStyle/extractTextStyle.ts +14 -6
  150. package/src/utils/extractTextStyle/extractTextStyleNative.ts +8 -6
  151. package/src/utils/logRenderStore.ts +6 -10
  152. package/src/utils/parseColor.ts +0 -1
  153. package/src/utils/replaceLocalizationParams.ts +8 -4
  154. package/dist/modals/ScreenColorsModal.d.ts +0 -8
  155. package/src/assets/products.json +0 -98
  156. package/src/modals/ScreenColorsModal.tsx +0 -121
@@ -0,0 +1,331 @@
1
+ import React, { useMemo, useState } from 'react';
2
+ import Modal from './Modal';
3
+ import { useRenderStore } from '../store';
4
+ import { defaultLocalization, type Localication } from '../types/PreviewConfig';
5
+ import { defaultProjectColors } from '../utils/projectColors';
6
+ import { getLastParamsSnapshot } from '../components/ParamsProvider';
7
+ import type { ProjectColors } from '../types/Project';
8
+
9
+ type InspectTab = 'localizations' | 'params' | 'colors';
10
+
11
+ type InspectModalProps = {
12
+ onClose: () => void;
13
+ };
14
+
15
+ export function InspectModal({ onClose }: InspectModalProps) {
16
+ const [activeTab, setActiveTab] = useState<InspectTab>('localizations');
17
+
18
+ const { appConfig, projectColors, theme, defaultLanguage } = useRenderStore(
19
+ (s) => ({
20
+ appConfig: s.appConfig,
21
+ projectColors: s.projectColors,
22
+ theme: s.theme,
23
+ defaultLanguage: s.defaultLanguage,
24
+ }),
25
+ );
26
+
27
+ const paramsSnapshot = useMemo(() => getLastParamsSnapshot(), []);
28
+
29
+ return (
30
+ <Modal
31
+ onClose={onClose}
32
+ ariaLabelledBy="inspect-modal-title"
33
+ className="modal--large modal--scrollable"
34
+ contentClassName="inspect-modal__content"
35
+ >
36
+ <div className="modal__header inspect-modal__header">
37
+ <h3 id="inspect-modal-title" className="modal__title">
38
+ Inspect
39
+ </h3>
40
+ <button type="button" className="editor-button" onClick={onClose}>
41
+ Close
42
+ </button>
43
+ </div>
44
+
45
+ <div className="inspect-modal__tabs">
46
+ <button
47
+ type="button"
48
+ className={`inspect-modal__tab${activeTab === 'localizations' ? ' is-active' : ''}`}
49
+ onClick={() => setActiveTab('localizations')}
50
+ >
51
+ Localizations
52
+ </button>
53
+ <button
54
+ type="button"
55
+ className={`inspect-modal__tab${activeTab === 'params' ? ' is-active' : ''}`}
56
+ onClick={() => setActiveTab('params')}
57
+ >
58
+ Params
59
+ </button>
60
+ <button
61
+ type="button"
62
+ className={`inspect-modal__tab${activeTab === 'colors' ? ' is-active' : ''}`}
63
+ onClick={() => setActiveTab('colors')}
64
+ >
65
+ Colors
66
+ </button>
67
+ </div>
68
+
69
+ <div className="inspect-modal__body">
70
+ {activeTab === 'localizations' && (
71
+ <LocalizationsTab
72
+ localication={appConfig.localication ?? {}}
73
+ language={defaultLanguage}
74
+ />
75
+ )}
76
+ {activeTab === 'params' && (
77
+ <ParamsTab
78
+ localizationParams={paramsSnapshot.localizationParams}
79
+ nestedLocalizationParams={paramsSnapshot.nestedLocalizationParams}
80
+ />
81
+ )}
82
+ {activeTab === 'colors' && (
83
+ <ColorsTab projectColors={projectColors} theme={theme} />
84
+ )}
85
+ </div>
86
+ </Modal>
87
+ );
88
+ }
89
+
90
+ /* ------------------------------------------------------------------ */
91
+ /* Tab 1 – Localizations */
92
+ /* ------------------------------------------------------------------ */
93
+
94
+ function LocalizationsTab({
95
+ localication,
96
+ language,
97
+ }: {
98
+ localication: Localication;
99
+ language: string;
100
+ }) {
101
+ const langKeys = localication[language] ?? {};
102
+ const defaultLangKeys =
103
+ defaultLocalization[language] ?? defaultLocalization['en'] ?? {};
104
+
105
+ const entries = Object.entries(langKeys);
106
+
107
+ if (entries.length === 0) {
108
+ return (
109
+ <p className="inspect-modal__empty">
110
+ No localization keys found for "{language}".
111
+ </p>
112
+ );
113
+ }
114
+
115
+ return (
116
+ <div className="inspect-modal__table-wrap">
117
+ <table className="inspect-modal__table">
118
+ <thead>
119
+ <tr>
120
+ <th>Key</th>
121
+ <th>Value</th>
122
+ <th>Source</th>
123
+ </tr>
124
+ </thead>
125
+ <tbody>
126
+ {entries.map(([key, value]) => {
127
+ const isDefault = defaultLangKeys[key] === value;
128
+ return (
129
+ <tr key={key}>
130
+ <td className="inspect-modal__cell-key">{key}</td>
131
+ <td className="inspect-modal__cell-value">{value}</td>
132
+ <td>
133
+ <span
134
+ className={`inspect-modal__badge${isDefault ? ' inspect-modal__badge--default' : ' inspect-modal__badge--custom'}`}
135
+ >
136
+ {isDefault ? 'default' : 'custom'}
137
+ </span>
138
+ </td>
139
+ </tr>
140
+ );
141
+ })}
142
+ </tbody>
143
+ </table>
144
+ </div>
145
+ );
146
+ }
147
+
148
+ /* ------------------------------------------------------------------ */
149
+ /* Tab 2 – Params */
150
+ /* ------------------------------------------------------------------ */
151
+
152
+ function ParamsTab({
153
+ localizationParams,
154
+ nestedLocalizationParams,
155
+ }: {
156
+ localizationParams: Record<string, unknown>;
157
+ nestedLocalizationParams: Record<string, unknown>;
158
+ }) {
159
+ const flatEntries = Object.entries(localizationParams);
160
+ const nestedEntries = Object.entries(nestedLocalizationParams);
161
+ const hasAny = flatEntries.length > 0 || nestedEntries.length > 0;
162
+
163
+ if (!hasAny) {
164
+ return (
165
+ <p className="inspect-modal__empty">
166
+ No params available. Params are populated inside a PaywallProvider.
167
+ </p>
168
+ );
169
+ }
170
+
171
+ return (
172
+ <div className="inspect-modal__table-wrap">
173
+ <table className="inspect-modal__table">
174
+ <thead>
175
+ <tr>
176
+ <th>Param</th>
177
+ <th>Value</th>
178
+ </tr>
179
+ </thead>
180
+ <tbody>
181
+ {flatEntries.map(([key, value]) => (
182
+ <tr key={key}>
183
+ <td className="inspect-modal__cell-key">{key}</td>
184
+ <td className="inspect-modal__cell-value">
185
+ {formatValue(value)}
186
+ </td>
187
+ </tr>
188
+ ))}
189
+ {nestedEntries.length > 0 && (
190
+ <>
191
+ <tr className="inspect-modal__separator-row">
192
+ <td colSpan={2}>Nested (per-product)</td>
193
+ </tr>
194
+ {nestedEntries.map(([key, value]) => (
195
+ <tr key={`nested-${key}`}>
196
+ <td className="inspect-modal__cell-key inspect-modal__cell-key--nested">
197
+ - {key}
198
+ </td>
199
+ <td className="inspect-modal__cell-value">
200
+ {formatValue(value)}
201
+ </td>
202
+ </tr>
203
+ ))}
204
+ </>
205
+ )}
206
+ </tbody>
207
+ </table>
208
+ </div>
209
+ );
210
+ }
211
+
212
+ /* ------------------------------------------------------------------ */
213
+ /* Tab 3 – Colors */
214
+ /* ------------------------------------------------------------------ */
215
+
216
+ function ColorsTab({
217
+ projectColors,
218
+ theme,
219
+ }: {
220
+ projectColors?: ProjectColors;
221
+ theme: string;
222
+ }) {
223
+ const staticColors = projectColors?.STATIC_COLORS ?? {};
224
+ const themeColors = projectColors?.THEME_COLORS?.[theme] ?? {};
225
+
226
+ const defaultStatic = defaultProjectColors.STATIC_COLORS ?? {};
227
+ const defaultThemeMap = defaultProjectColors.THEME_COLORS?.[theme] ?? {};
228
+
229
+ const staticEntries = Object.entries(staticColors);
230
+ const themeEntries = Object.entries(themeColors);
231
+
232
+ if (staticEntries.length === 0 && themeEntries.length === 0) {
233
+ return <p className="inspect-modal__empty">No project colors defined.</p>;
234
+ }
235
+
236
+ return (
237
+ <div className="inspect-modal__table-wrap">
238
+ {staticEntries.length > 0 && (
239
+ <>
240
+ <h4 className="inspect-modal__section-title">Static Colors</h4>
241
+ <table className="inspect-modal__table">
242
+ <thead>
243
+ <tr>
244
+ <th>Token</th>
245
+ <th>Value</th>
246
+ <th>Source</th>
247
+ </tr>
248
+ </thead>
249
+ <tbody>
250
+ {staticEntries.map(([token, hex]) => {
251
+ const isDefault = defaultStatic[token] === hex;
252
+ return (
253
+ <tr key={token}>
254
+ <td className="inspect-modal__cell-key">{token}</td>
255
+ <td className="inspect-modal__cell-value">
256
+ <span
257
+ className="inspect-modal__color-swatch"
258
+ style={{ backgroundColor: hex }}
259
+ />
260
+ {hex}
261
+ </td>
262
+ <td>
263
+ <span
264
+ className={`inspect-modal__badge${isDefault ? ' inspect-modal__badge--default' : ' inspect-modal__badge--custom'}`}
265
+ >
266
+ {isDefault ? 'default' : 'custom'}
267
+ </span>
268
+ </td>
269
+ </tr>
270
+ );
271
+ })}
272
+ </tbody>
273
+ </table>
274
+ </>
275
+ )}
276
+
277
+ {themeEntries.length > 0 && (
278
+ <>
279
+ <h4 className="inspect-modal__section-title">
280
+ Theme Colors ({theme})
281
+ </h4>
282
+ <table className="inspect-modal__table">
283
+ <thead>
284
+ <tr>
285
+ <th>Token</th>
286
+ <th>Value</th>
287
+ <th>Source</th>
288
+ </tr>
289
+ </thead>
290
+ <tbody>
291
+ {themeEntries.map(([token, hex]) => {
292
+ const isDefault = defaultThemeMap[token] === hex;
293
+ return (
294
+ <tr key={token}>
295
+ <td className="inspect-modal__cell-key">{token}</td>
296
+ <td className="inspect-modal__cell-value">
297
+ <span
298
+ className="inspect-modal__color-swatch"
299
+ style={{ backgroundColor: hex }}
300
+ />
301
+ {hex}
302
+ </td>
303
+ <td>
304
+ <span
305
+ className={`inspect-modal__badge${isDefault ? ' inspect-modal__badge--default' : ' inspect-modal__badge--custom'}`}
306
+ >
307
+ {isDefault ? 'default' : 'custom'}
308
+ </span>
309
+ </td>
310
+ </tr>
311
+ );
312
+ })}
313
+ </tbody>
314
+ </table>
315
+ </>
316
+ )}
317
+ </div>
318
+ );
319
+ }
320
+
321
+ /* ------------------------------------------------------------------ */
322
+ /* Helpers */
323
+ /* ------------------------------------------------------------------ */
324
+
325
+ function formatValue(v: unknown): string {
326
+ if (v === undefined) return '—';
327
+ if (v === null) return 'null';
328
+ if (typeof v === 'string') return v;
329
+ if (typeof v === 'number' || typeof v === 'boolean') return String(v);
330
+ return JSON.stringify(v);
331
+ }
@@ -1,10 +1,10 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import Modal from './Modal';
3
3
  import type { Product } from '../paywall/types/paywall-types';
4
- import presetsJson from '../assets/products.json';
4
+ import presetsJson from '../product-base/mockProducts.json';
5
5
 
6
6
  type PresetMap = Record<string, Product[]>;
7
- const DEFAULT_PRESET_KEY = 'Embeded Paywall';
7
+ const DEFAULT_PRESET_KEY = 'preset-1';
8
8
 
9
9
  type ProductPresetsModalProps = {
10
10
  current: Product[];
@@ -13,15 +13,8 @@ type ProductPresetsModalProps = {
13
13
  onClose: () => void;
14
14
  };
15
15
 
16
- function normalizeProduct(p: Product): Product {
17
- return {
18
- productId: p?.productId ?? '',
19
- title: p?.title ?? '',
20
- description: p?.description ?? '',
21
- localizedPrice: p?.localizedPrice ?? '',
22
- price: p?.price ?? '',
23
- currency: p?.currency ?? '',
24
- };
16
+ function ensureProductId(p: Product): Product {
17
+ return { ...p, productId: p?.productId ?? '' };
25
18
  }
26
19
 
27
20
  function getPresetMap(): PresetMap {
@@ -32,8 +25,8 @@ function getPresetMap(): PresetMap {
32
25
  if (!Array.isArray(list)) return;
33
26
  safe[key] = list
34
27
  .filter(Boolean)
35
- .map((p) => normalizeProduct(p as Product))
36
- .filter((p) => typeof p.productId === 'string');
28
+ .map((p) => ensureProductId(p as Product))
29
+ .filter((p) => typeof p.productId === 'string' && p.productId.length > 0);
37
30
  });
38
31
  return safe;
39
32
  }
@@ -4,9 +4,9 @@ export { DeviceSelectorModal } from './DeviceSelectorModal';
4
4
  export { ColorModal } from './ColorModal';
5
5
  export { IconPickerModal } from './IconPickerModal';
6
6
  export { LocalicationModal } from './LocalicationModal';
7
- export { ScreenColorsModal } from './ScreenColorsModal';
8
7
  export { MockableFeatureModal } from './MockableFeatureModal';
9
8
  export { ProductEditModal } from './ProductEditModal';
10
9
  export { ProductPresetsModal } from './ProductPresetsModal';
11
10
  export { BenefitEditModal } from './BenefitEditModal';
12
11
  export { BenefitPresetsModal } from './BenefitPresetsModal';
12
+ export { InspectModal } from './InspectModal';
@@ -46,16 +46,16 @@ export function DebugJsonPage({
46
46
  const setCurrent = useRenderStore((s) => s.setCurrent);
47
47
  const listMaxNested = useRenderStore((s) => s.listMaxNested);
48
48
  const setListMaxNested = useRenderStore((s) => s.setListMaxNested);
49
+ const theme = useRenderStore((s) => s.theme);
50
+ const setTheme = useRenderStore((s) => s.setTheme);
51
+ const isRtl = useRenderStore((s) => s.isRtl);
52
+ const setIsRtl = useRenderStore((s) => s.setIsRtl);
49
53
  const [listMaxNestedInput, setListMaxNestedInput] = useState(
50
54
  String(listMaxNested),
51
55
  );
52
56
  const canTogglePreviewMode = typeof setPreviewMode === 'function';
53
- const canToggleTheme =
54
- typeof setAppConfig === 'function' && typeof appConfig?.theme === 'string';
55
- const canToggleRtl =
56
- typeof setAppConfig === 'function' &&
57
- appConfig != null &&
58
- 'isRtl' in appConfig;
57
+ const canToggleTheme = true;
58
+ const canToggleRtl = true;
59
59
 
60
60
  const isRecord = (v: unknown): v is Record<string, unknown> =>
61
61
  typeof v === 'object' && v !== null && !Array.isArray(v);
@@ -210,26 +210,13 @@ export function DebugJsonPage({
210
210
  {canToggleTheme ? (
211
211
  <Checkbox
212
212
  label="Dark Mode"
213
- checked={(appConfig?.theme ?? 'light') === 'dark'}
214
- onChange={(checked) =>
215
- setAppConfig!({
216
- ...(appConfig as AppConfig),
217
- theme: checked ? 'dark' : 'light',
218
- })
219
- }
213
+ checked={theme === 'dark'}
214
+ onChange={(checked) => setTheme(checked ? 'dark' : 'light')}
220
215
  />
221
216
  ) : null}
222
217
 
223
218
  {canToggleRtl ? (
224
- <Checkbox
225
- label="Is RTL"
226
- checked={Boolean(
227
- (appConfig as AppConfig & { isRtl?: boolean })?.isRtl,
228
- )}
229
- onChange={(checked) =>
230
- setAppConfig!({ ...(appConfig as AppConfig), isRtl: checked })
231
- }
232
- />
219
+ <Checkbox label="Is RTL" checked={isRtl} onChange={setIsRtl} />
233
220
  ) : null}
234
221
  </div>
235
222
  ) : null}
@@ -316,7 +316,7 @@ export function ProjectDebug({
316
316
  <RenderPage
317
317
  data={previewData}
318
318
  name={name}
319
- params={{ products, benefits }}
319
+ params={{ mockProducts: products, mockBenefits: benefits }}
320
320
  />
321
321
  </RenderErrorBoundary>
322
322
  </section>
@@ -7,7 +7,13 @@ import { EditorHeader } from '../components/EditorHeader';
7
7
  import { AttributesEditorPanel } from '../components/AttributesEditorPanel';
8
8
  import { BuilderPanel } from './tabs/BuilderPanel';
9
9
  import { BottomBar } from '../components/BottomBar';
10
- import { AppConfig, defaultAppConfig } from '../types/PreviewConfig';
10
+ import {
11
+ type AppConfig,
12
+ defaultAppConfig,
13
+ defaultLocalization,
14
+ mergeLocalization,
15
+ type Localication,
16
+ } from '../types/PreviewConfig';
11
17
  import { useRenderStore } from '../store';
12
18
  import { logger } from '../utils/logger';
13
19
  import { useLogRender } from '../utils/useLogRender';
@@ -41,7 +47,7 @@ export type ProjectPageProps = {
41
47
  project: Project;
42
48
  // TODO: Tüm onSaveProject call-site'ları toProjectMeta kullanacak şekilde migrate et
43
49
  onSaveProject: (project: ProjectMeta) => void;
44
- appConfig?: AppConfig;
50
+ localization?: Localication;
45
51
  logLevel?: LogLevel;
46
52
  projectColors?: ProjectColors;
47
53
  onSaveProjectColors?: (colors: ProjectColors) => void;
@@ -61,7 +67,7 @@ const MOBILE_BREAKPOINT = 1000;
61
67
 
62
68
  export function ProjectPage({
63
69
  project,
64
- appConfig,
70
+ localization,
65
71
  onSaveProject,
66
72
  logLevel,
67
73
  projectColors,
@@ -85,6 +91,8 @@ export function ProjectPage({
85
91
  setProjectName,
86
92
  setAppConfig,
87
93
  storeAppConfig,
94
+ storeTheme,
95
+ storeDefaultLanguage,
88
96
  products,
89
97
  benefits,
90
98
  previewMode,
@@ -95,11 +103,18 @@ export function ProjectPage({
95
103
  setProjectName: s.setProjectName,
96
104
  setAppConfig: s.setAppConfig,
97
105
  storeAppConfig: s.appConfig,
106
+ storeTheme: s.theme,
107
+ storeDefaultLanguage: s.defaultLanguage,
98
108
  products: s.products,
99
109
  benefits: s.benefits,
100
110
  previewMode: s.previewMode,
101
111
  }));
102
- const resolvedAppConfig = appConfig ?? storeAppConfig ?? defaultAppConfig;
112
+ const resolvedAppConfig: AppConfig = localization
113
+ ? {
114
+ ...defaultAppConfig,
115
+ localication: mergeLocalization(defaultLocalization, localization),
116
+ }
117
+ : (storeAppConfig ?? defaultAppConfig);
103
118
  const [overrideProject, setOverrideProject] = useState<Project | null>(null);
104
119
  const activeProject = overrideProject ?? project;
105
120
  const resolvedName = name ?? activeProject.name;
@@ -169,14 +184,15 @@ export function ProjectPage({
169
184
  useEffect(() => {
170
185
  logger.info('ProjectPage', 'mount', { projectName: project.name });
171
186
  setOverrideProject(null);
172
- if (appConfig) {
173
- setAppConfig(appConfig);
174
- logger.verbose('ProjectPage', 'appConfig applied', appConfig);
187
+ if (localization) {
188
+ const merged = mergeLocalization(defaultLocalization, localization);
189
+ setAppConfig({ ...defaultAppConfig, localication: merged });
190
+ logger.verbose('ProjectPage', 'localization applied', merged);
175
191
  }
176
192
  return () => {
177
193
  logger.info('ProjectPage', 'unmount');
178
194
  };
179
- }, [appConfig, project.name, setAppConfig]);
195
+ }, [localization, project.name, setAppConfig]);
180
196
 
181
197
  useEffect(() => {
182
198
  setProjectName(resolvedName);
@@ -643,12 +659,14 @@ export function ProjectPage({
643
659
  data={editorData}
644
660
  name={resolvedName}
645
661
  params={{
646
- products,
647
- benefits:
662
+ mockProducts: products,
663
+ mockBenefits:
648
664
  benefits && typeof benefits === 'object'
649
665
  ? (benefits as PaywallBenefits)
650
666
  : {},
651
- // Theme/colors/fonts must be passed via BuilderProvider params so build-components never touch useRenderStore.
667
+ // Colors/fonts/theme must be passed via BuilderProvider params so build-components never touch useRenderStore.
668
+ theme: storeTheme,
669
+ defaultLanguage: storeDefaultLanguage,
652
670
  appConfig: resolvedAppConfig,
653
671
  projectColors: resolvedProjectColors,
654
672
  fonts: typography.fonts,