@developer_tribe/react-builder 1.2.7 → 1.2.9

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 (204) hide show
  1. package/dist/AttributesEditor.d.ts +2 -11
  2. package/dist/attribute-analyser/style/native/useExtractImageStyle.d.ts +10 -0
  3. package/dist/attribute-analyser/style/native/useExtractTextStyle.d.ts +9 -0
  4. package/dist/attribute-analyser/style/native/useExtractViewStyle.d.ts +8 -0
  5. package/dist/attribute-analyser/style/web/useExtractImageStyle.d.ts +4 -0
  6. package/dist/attribute-analyser/style/web/useExtractTextStyle.d.ts +4 -0
  7. package/dist/attribute-analyser/style/web/useExtractViewStyle.d.ts +4 -0
  8. package/dist/attributes-editor/AttributesEditorFields.d.ts +18 -0
  9. package/dist/attributes-editor/AttributesEditorView.d.ts +4 -0
  10. package/dist/attributes-editor/attributesEditorModelTypes.d.ts +67 -0
  11. package/dist/attributes-editor/attributesEditorUtils.d.ts +19 -0
  12. package/dist/attributes-editor/useAttributesEditorModel.d.ts +2 -0
  13. package/dist/build-components/BIcon/BIconProps.generated.d.ts +41 -38
  14. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +37 -34
  15. package/dist/build-components/Button/ButtonProps.generated.d.ts +39 -36
  16. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +37 -34
  17. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +37 -34
  18. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +37 -34
  19. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +36 -33
  20. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +36 -33
  21. package/dist/build-components/Image/ImageProps.generated.d.ts +38 -33
  22. package/dist/build-components/Main/MainProps.generated.d.ts +36 -33
  23. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +36 -33
  24. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +38 -34
  25. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +39 -36
  26. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +43 -34
  27. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +41 -38
  28. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +36 -31
  29. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +39 -33
  30. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +38 -34
  31. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +41 -38
  32. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +41 -38
  33. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +36 -33
  34. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +41 -38
  35. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +36 -33
  36. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +36 -33
  37. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +39 -36
  38. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +36 -33
  39. package/dist/build-components/Text/TextProps.generated.d.ts +41 -38
  40. package/dist/build-components/View/ViewProps.generated.d.ts +36 -33
  41. package/dist/build-components/patterns.generated.d.ts +2673 -5787
  42. package/dist/components/BuilderProvider.d.ts +6 -0
  43. package/dist/index.cjs.js +5 -5
  44. package/dist/index.cjs.js.map +1 -1
  45. package/dist/index.d.ts +5 -26
  46. package/dist/index.esm.js +5 -5
  47. package/dist/index.esm.js.map +1 -1
  48. package/dist/index.native.cjs.js +6 -4
  49. package/dist/index.native.cjs.js.map +1 -1
  50. package/dist/index.native.d.ts +6 -3
  51. package/dist/index.native.esm.js +6 -4
  52. package/dist/index.native.esm.js.map +1 -1
  53. package/dist/migrations/migratePipe.d.ts +1 -1
  54. package/dist/migrations/migrations/1.1.2_extract_component_attributes_from_style.d.ts +2 -0
  55. package/dist/mockOS/components/PermissionModal.d.ts +1 -2
  56. package/dist/styles.css +1 -1
  57. package/dist/types/PreviewConfig.d.ts +1 -5
  58. package/dist/utils/extractImageStyle.d.ts +3 -0
  59. package/dist/utils/extractTextStyle/extractTextStyleNative.d.ts +17 -0
  60. package/dist/utils/extractTextStyle.d.ts +2 -0
  61. package/dist/utils/extractViewStyle/extractViewStyleNative.d.ts +12 -0
  62. package/dist/utils/extractViewStyle.d.ts +2 -0
  63. package/dist/utils/getMeta.d.ts +5 -0
  64. package/dist/utils/patterns.d.ts +14 -1
  65. package/package.json +2 -1
  66. package/scripts/prebuild/prebuild.js +14 -0
  67. package/scripts/prebuild/utils/createGeneratedProps.js +51 -3
  68. package/scripts/prebuild/utils/index.js +1 -0
  69. package/scripts/prebuild/utils/updateMetaJson.js +66 -0
  70. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +37 -3
  71. package/scripts/prebuild/utils/validatePatternJson.js +27 -2
  72. package/scripts/public/scripts/build/index.js +20 -3
  73. package/scripts/public/scripts/build/info.json +6 -0
  74. package/scripts/public/scripts/build/utils/createComponentsIndex.js +9 -3
  75. package/scripts/public/scripts/build/utils/createRenderNodeGenerated.js +66 -8
  76. package/src/AttributesEditor.tsx +8 -944
  77. package/src/assets/meta.json +4 -0
  78. package/src/assets/samples/carousel-sample.json +1 -1
  79. package/src/assets/samples/getSamples.ts +2 -0
  80. package/src/assets/samples/paywall-1.json +11 -7
  81. package/src/assets/samples/simple-1.json +3 -3
  82. package/src/assets/samples/simple-2.json +3 -3
  83. package/src/assets/samples/unmigrated-builder-1.1.1.json +87 -0
  84. package/src/assets/samples/unmigrated-builder1.json +1 -1
  85. package/src/assets/samples/unvalidated-builder1.json +3 -3
  86. package/src/assets/samples/unvalidated-crash1.json +1 -1
  87. package/src/assets/samples/unvalidated-crashcomponent1.json +1 -1
  88. package/src/assets/samples/vpn-onboard-1.json +1 -1
  89. package/src/assets/samples/vpn-onboard-2.json +1 -1
  90. package/src/assets/samples/vpn-onboard-3.json +1 -1
  91. package/src/assets/samples/vpn-onboard-4.json +1 -1
  92. package/src/assets/samples/vpn-onboard-5.json +1 -1
  93. package/src/assets/samples/vpn-onboard-6.json +1 -1
  94. package/src/attribute-analyser/style/native/useExtractImageStyle.ts +46 -0
  95. package/src/attribute-analyser/style/native/useExtractTextStyle.ts +50 -0
  96. package/src/attribute-analyser/style/native/useExtractViewStyle.ts +32 -0
  97. package/src/attribute-analyser/style/web/useExtractImageStyle.ts +20 -0
  98. package/src/{hooks → attribute-analyser/style/web}/useExtractTextStyle.ts +7 -6
  99. package/src/{hooks → attribute-analyser/style/web}/useExtractViewStyle.ts +7 -6
  100. package/src/attributes-editor/AttributesEditorFields.tsx +248 -0
  101. package/src/attributes-editor/AttributesEditorView.tsx +360 -0
  102. package/src/attributes-editor/LayoutPreviewPicker.tsx +4 -3
  103. package/src/attributes-editor/attributesEditorModelTypes.ts +86 -0
  104. package/src/attributes-editor/attributesEditorUtils.ts +102 -0
  105. package/src/attributes-editor/useAttributesEditorModel.ts +477 -0
  106. package/src/build-components/BIcon/BIcon.tsx +4 -3
  107. package/src/build-components/BIcon/BIconProps.generated.ts +42 -38
  108. package/src/build-components/BIcon/pattern.json +5 -6
  109. package/src/build-components/BackgroundImage/BackgroundImage.tsx +7 -4
  110. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +38 -34
  111. package/src/build-components/BackgroundImage/pattern.json +9 -17
  112. package/src/build-components/Button/Button.tsx +7 -6
  113. package/src/build-components/Button/ButtonProps.generated.ts +40 -36
  114. package/src/build-components/Button/pattern.json +17 -15
  115. package/src/build-components/Carousel/Carousel.tsx +1 -1
  116. package/src/build-components/Carousel/CarouselProps.generated.ts +38 -34
  117. package/src/build-components/CarouselButtons/CarouselButtons.tsx +4 -6
  118. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +41 -37
  119. package/src/build-components/CarouselButtons/pattern.json +2 -1
  120. package/src/build-components/CarouselDots/CarouselDots.tsx +2 -2
  121. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +44 -40
  122. package/src/build-components/CarouselItem/CarouselItem.tsx +1 -1
  123. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +37 -33
  124. package/src/build-components/CarouselProvider/CarouselProvider.tsx +1 -1
  125. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +37 -33
  126. package/src/build-components/Image/Image.tsx +4 -3
  127. package/src/build-components/Image/ImageProps.generated.ts +39 -33
  128. package/src/build-components/Image/pattern.json +5 -11
  129. package/src/build-components/Main/Main.tsx +1 -1
  130. package/src/build-components/Main/MainProps.generated.ts +37 -33
  131. package/src/build-components/Main/pattern.json +2 -1
  132. package/src/build-components/Onboard/OnboardProps.generated.ts +37 -33
  133. package/src/build-components/OnboardButton/OnboardButton.tsx +8 -6
  134. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +44 -39
  135. package/src/build-components/OnboardButton/pattern.json +9 -7
  136. package/src/build-components/OnboardButtons/OnboardButtons.tsx +31 -31
  137. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +43 -39
  138. package/src/build-components/OnboardButtons/pattern.json +9 -7
  139. package/src/build-components/OnboardDot/OnboardDot.tsx +7 -5
  140. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +55 -34
  141. package/src/build-components/OnboardFooter/OnboardFooter.tsx +19 -23
  142. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +42 -38
  143. package/src/build-components/OnboardFooter/pattern.json +16 -14
  144. package/src/build-components/OnboardImage/OnboardImage.tsx +8 -7
  145. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +37 -31
  146. package/src/build-components/OnboardImage/pattern.json +2 -1
  147. package/src/build-components/OnboardItem/OnboardItem.tsx +1 -1
  148. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +40 -33
  149. package/src/build-components/OnboardItem/pattern.json +2 -1
  150. package/src/build-components/OnboardProvider/OnboardProvider.tsx +1 -1
  151. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +39 -34
  152. package/src/build-components/OnboardProvider/pattern.json +2 -1
  153. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +42 -38
  154. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +42 -38
  155. package/src/build-components/PaywallBackground/PaywallBackground.tsx +1 -1
  156. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +37 -33
  157. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +6 -5
  158. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +42 -38
  159. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +1 -1
  160. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +37 -33
  161. package/src/build-components/PaywallProvider/PaywallProvider.tsx +1 -1
  162. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +37 -33
  163. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +1 -1
  164. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +40 -36
  165. package/src/build-components/RadioButton/RadioButton.tsx +5 -4
  166. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +37 -33
  167. package/src/build-components/RadioButton/pattern.json +9 -7
  168. package/src/build-components/Text/Text.tsx +6 -8
  169. package/src/build-components/Text/TextProps.generated.ts +42 -38
  170. package/src/build-components/Text/pattern.json +15 -11
  171. package/src/build-components/View/View.tsx +1 -1
  172. package/src/build-components/View/ViewProps.generated.ts +37 -33
  173. package/src/build-components/View/pattern.json +71 -66
  174. package/src/build-components/patterns.generated.ts +3022 -5971
  175. package/src/components/AttributesEditorPanel.tsx +2 -2
  176. package/src/components/BuilderProvider.tsx +15 -1
  177. package/src/index.native.ts +7 -4
  178. package/src/index.ts +6 -77
  179. package/src/migrations/migratePipe.ts +7 -3
  180. package/src/migrations/migrations/1.1.2_extract_component_attributes_from_style.ts +211 -0
  181. package/src/mockOS/components/MockOSRouter.tsx +3 -1
  182. package/src/mockOS/components/PermissionModal.tsx +20 -160
  183. package/src/mockOS/components/SubscriptionModal.tsx +41 -278
  184. package/src/pages/ProjectPage.tsx +12 -6
  185. package/src/styles/components/_attributes-editor.scss +122 -0
  186. package/src/styles/components/_mockos-router.scss +388 -0
  187. package/src/styles/components/_onboard.scss +23 -0
  188. package/src/styles/index.scss +1 -0
  189. package/src/types/PreviewConfig.ts +1 -5
  190. package/src/utils/analyseNodeByPatterns.ts +39 -4
  191. package/src/utils/extractImageStyle.ts +34 -5
  192. package/src/utils/extractTextStyle/extractTextStyle.ts +7 -6
  193. package/src/utils/extractTextStyle/extractTextStyleNative.ts +106 -0
  194. package/src/utils/extractTextStyle.ts +2 -0
  195. package/src/utils/extractViewStyle/extractViewStyle.ts +2 -4
  196. package/src/utils/extractViewStyle/extractViewStyleNative.ts +111 -0
  197. package/src/utils/extractViewStyle.ts +2 -0
  198. package/src/utils/getMeta.ts +15 -0
  199. package/src/utils/patterns.ts +100 -3
  200. package/dist/hooks/useExtractImageStyle.d.ts +0 -3
  201. package/dist/hooks/useExtractTextStyle.d.ts +0 -3
  202. package/dist/hooks/useExtractViewStyle.d.ts +0 -3
  203. package/src/hooks/useExtractImageStyle.ts +0 -19
  204. package/src/migrations/migrations/1.1.0_normalize_style_attributes.ts +0 -80
@@ -141,3 +141,391 @@
141
141
  text-overflow: ellipsis;
142
142
  white-space: nowrap;
143
143
  }
144
+
145
+ // ------------------------------------------------------------
146
+ // MockOS "OS alert" modals (Permission + Subscription)
147
+ // - Theme-aware via builder tokens (see `foundation/_colors.scss`)
148
+ // ------------------------------------------------------------
149
+
150
+ .mockos-modal-overlay {
151
+ position: absolute;
152
+ inset: 0;
153
+ display: flex;
154
+ z-index: 9999;
155
+ background-color: rgba(0, 0, 0, var(--mockos-overlay-alpha, 0.5));
156
+ }
157
+
158
+ .mockos-modal-overlay--ios {
159
+ --mockos-overlay-alpha: 0.4;
160
+ }
161
+
162
+ .mockos-modal-overlay--android {
163
+ --mockos-overlay-alpha: 0.5;
164
+ }
165
+
166
+ .mockos-modal-overlay--center {
167
+ align-items: center;
168
+ justify-content: center;
169
+ padding: 20px;
170
+ }
171
+
172
+ .mockos-modal-overlay--bottom {
173
+ align-items: flex-end;
174
+ justify-content: stretch;
175
+ padding: 0;
176
+ }
177
+
178
+ .mockos-permission-modal {
179
+ width: 100%;
180
+ }
181
+
182
+ .mockos-permission-modal--ios {
183
+ max-width: 270px;
184
+ overflow: hidden;
185
+ border-radius: 14px;
186
+ background-color: hsl(var(--card, var(--rb-card, 0 0% 100%)) / 0.95);
187
+ backdrop-filter: blur(20px);
188
+ }
189
+
190
+ .mockos-permission-modal--android {
191
+ max-width: 280px;
192
+ border-radius: 4px;
193
+ background-color: colors.$surfaceColor;
194
+ box-shadow:
195
+ 0 11px 15px -7px rgba(0, 0, 0, 0.2),
196
+ 0 24px 38px 3px rgba(0, 0, 0, 0.14);
197
+ }
198
+
199
+ .mockos-permission-modal__content {
200
+ padding: 20px 16px;
201
+ }
202
+
203
+ .mockos-permission-modal__content--center {
204
+ text-align: center;
205
+ }
206
+
207
+ .mockos-permission-modal__title {
208
+ font-size: 17px;
209
+ font-weight: 600;
210
+ color: colors.$textColor;
211
+ margin-bottom: 8px;
212
+ line-height: 1.3;
213
+ }
214
+
215
+ .mockos-permission-modal__title--android {
216
+ font-size: 20px;
217
+ font-weight: 500;
218
+ margin-bottom: 16px;
219
+ line-height: 1.2;
220
+ }
221
+
222
+ .mockos-permission-modal__message {
223
+ font-size: 13px;
224
+ line-height: 1.4;
225
+ color: hsl(
226
+ var(--muted-foreground, var(--rb-muted-foreground, 220 8.9% 46.1%))
227
+ );
228
+ }
229
+
230
+ .mockos-permission-modal__message--android {
231
+ font-size: 16px;
232
+ line-height: 1.5;
233
+ }
234
+
235
+ .mockos-permission-modal__actions {
236
+ display: flex;
237
+ }
238
+
239
+ .mockos-permission-modal__actions--ios {
240
+ border-top: 0.5px solid
241
+ hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.65);
242
+ }
243
+
244
+ .mockos-permission-modal__actions--android {
245
+ padding: 8px 8px 8px 0;
246
+ justify-content: flex-end;
247
+ gap: 8px;
248
+ }
249
+
250
+ .mockos-permission-modal__button {
251
+ background: transparent;
252
+ border: none;
253
+ cursor: pointer;
254
+ font: inherit;
255
+ }
256
+
257
+ .mockos-permission-modal__button--ios {
258
+ flex: 1;
259
+ padding: 11px 0;
260
+ font-size: 17px;
261
+ font-weight: 400;
262
+ color: hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)));
263
+ }
264
+
265
+ .mockos-permission-modal__actions--ios
266
+ .mockos-permission-modal__button--ios:first-child {
267
+ border-right: 0.5px solid
268
+ hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.65);
269
+ }
270
+
271
+ .mockos-permission-modal__button--bold {
272
+ font-weight: 600;
273
+ }
274
+
275
+ .mockos-permission-modal__button--android {
276
+ padding: 8px 16px;
277
+ font-size: 14px;
278
+ font-weight: 500;
279
+ border-radius: 4px;
280
+ text-transform: uppercase;
281
+ letter-spacing: 0.5px;
282
+ }
283
+
284
+ .mockos-permission-modal__button--deny {
285
+ color: hsl(
286
+ var(--muted-foreground, var(--rb-muted-foreground, 220 8.9% 46.1%))
287
+ );
288
+ }
289
+
290
+ .mockos-permission-modal__button--allow {
291
+ color: hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)));
292
+ }
293
+
294
+ .mockos-subscription-sheet {
295
+ width: 100%;
296
+ border-top-left-radius: 16px;
297
+ border-top-right-radius: 16px;
298
+ overflow: hidden;
299
+ padding-bottom: max(12px, env(safe-area-inset-bottom));
300
+ transform: translateY(0);
301
+ background-color: colors.$surfaceColor;
302
+ }
303
+
304
+ .mockos-subscription-sheet--ios {
305
+ background-color: hsl(var(--card, var(--rb-card, 0 0% 100%)) / 0.96);
306
+ backdrop-filter: blur(20px);
307
+ box-shadow:
308
+ 0 -12px 30px rgba(0, 0, 0, 0.18),
309
+ 0 -2px 6px rgba(0, 0, 0, 0.08);
310
+ }
311
+
312
+ .mockos-subscription-sheet--android {
313
+ box-shadow:
314
+ 0 -10px 20px rgba(0, 0, 0, 0.22),
315
+ 0 -2px 6px rgba(0, 0, 0, 0.14);
316
+ }
317
+
318
+ .mockos-subscription-sheet__handle {
319
+ width: 44px;
320
+ height: 5px;
321
+ border-radius: 999px;
322
+ background-color: hsl(
323
+ var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.18
324
+ );
325
+ margin: 10px auto 0;
326
+ }
327
+
328
+ .mockos-subscription-sheet__content {
329
+ padding: 14px 16px 10px;
330
+ }
331
+
332
+ .mockos-subscription-sheet__content--ios {
333
+ padding: 10px 16px 10px;
334
+ text-align: center;
335
+ }
336
+
337
+ .mockos-subscription-sheet__top-actions {
338
+ display: flex;
339
+ justify-content: flex-end;
340
+ margin-bottom: 6px;
341
+ }
342
+
343
+ .mockos-subscription-sheet__android-header {
344
+ display: flex;
345
+ justify-content: space-between;
346
+ align-items: center;
347
+ gap: 12px;
348
+ }
349
+
350
+ .mockos-subscription-sheet__close {
351
+ width: 28px;
352
+ height: 28px;
353
+ border-radius: 999px;
354
+ border: none;
355
+ background: hsl(
356
+ var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.06
357
+ );
358
+ color: hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.55);
359
+ font-size: 18px;
360
+ line-height: 28px;
361
+ cursor: pointer;
362
+ }
363
+
364
+ .mockos-subscription-sheet__title {
365
+ font-weight: 600;
366
+ color: colors.$textColor;
367
+ }
368
+
369
+ .mockos-subscription-sheet__title--ios {
370
+ font-size: 15px;
371
+ margin-bottom: 8px;
372
+ line-height: 1.3;
373
+ letter-spacing: 0.2px;
374
+ }
375
+
376
+ .mockos-subscription-sheet__title--android {
377
+ font-size: 16px;
378
+ }
379
+
380
+ .mockos-subscription-sheet__subtitle {
381
+ color: hsl(
382
+ var(--muted-foreground, var(--rb-muted-foreground, 220 8.9% 46.1%))
383
+ );
384
+ line-height: 1.5;
385
+ }
386
+
387
+ .mockos-subscription-sheet__subtitle--ios {
388
+ font-size: 13px;
389
+ line-height: 1.4;
390
+ }
391
+
392
+ .mockos-subscription-sheet__subtitle--android {
393
+ margin-top: 8px;
394
+ font-size: 14px;
395
+ }
396
+
397
+ .mockos-subscription-sheet__card {
398
+ margin-top: 12px;
399
+ padding: 10px 12px;
400
+ background: hsl(
401
+ var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.04
402
+ );
403
+ text-align: left;
404
+ }
405
+
406
+ .mockos-subscription-sheet__card--ios {
407
+ border-radius: 12px;
408
+ }
409
+
410
+ .mockos-subscription-sheet__card--android {
411
+ margin-top: 14px;
412
+ border-radius: 10px;
413
+ border: 1px solid hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.7);
414
+ }
415
+
416
+ .mockos-subscription-sheet__row {
417
+ display: flex;
418
+ align-items: center;
419
+ gap: 10px;
420
+ }
421
+
422
+ .mockos-subscription-sheet__row--space-between {
423
+ justify-content: space-between;
424
+ }
425
+
426
+ .mockos-subscription-sheet__icon {
427
+ width: 38px;
428
+ height: 38px;
429
+ border-radius: 10px;
430
+ background: linear-gradient(
431
+ 135deg,
432
+ rgba(0, 122, 255, 0.25),
433
+ rgba(88, 86, 214, 0.22)
434
+ );
435
+ border: 1px solid hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.7);
436
+ }
437
+
438
+ .mockos-subscription-sheet__meta {
439
+ flex: 1;
440
+ min-width: 0;
441
+ }
442
+
443
+ .mockos-subscription-sheet__meta--android {
444
+ min-width: 0;
445
+ }
446
+
447
+ .mockos-subscription-sheet__product-id {
448
+ font-size: 14px;
449
+ font-weight: 600;
450
+ color: hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.9);
451
+ line-height: 1.2;
452
+ white-space: nowrap;
453
+ overflow: hidden;
454
+ text-overflow: ellipsis;
455
+ }
456
+
457
+ .mockos-subscription-sheet__meta-subtitle {
458
+ margin-top: 2px;
459
+ font-size: 12px;
460
+ color: hsl(
461
+ var(--muted-foreground, var(--rb-muted-foreground, 220 8.9% 46.1%)) / 0.95
462
+ );
463
+ }
464
+
465
+ .mockos-subscription-sheet__price {
466
+ font-size: 13px;
467
+ font-weight: 700;
468
+ color: hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.86);
469
+ }
470
+
471
+ .mockos-subscription-sheet__actions {
472
+ display: flex;
473
+ }
474
+
475
+ .mockos-subscription-sheet__actions--ios {
476
+ border-top: 0.5px solid
477
+ hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.6);
478
+ }
479
+
480
+ .mockos-subscription-sheet__actions--android {
481
+ padding: 10px 12px 12px;
482
+ justify-content: flex-end;
483
+ gap: 8px;
484
+ }
485
+
486
+ .mockos-subscription-sheet__action {
487
+ background: transparent;
488
+ border: none;
489
+ cursor: pointer;
490
+ font: inherit;
491
+ }
492
+
493
+ .mockos-subscription-sheet__action--ios {
494
+ flex: 1;
495
+ padding: 13px 0;
496
+ font-size: 17px;
497
+ font-weight: 400;
498
+ color: hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)));
499
+ }
500
+
501
+ .mockos-subscription-sheet__actions--ios
502
+ .mockos-subscription-sheet__action--ios:first-child {
503
+ border-right: 0.5px solid
504
+ hsl(var(--border, var(--rb-border, 220 13% 91%)) / 0.6);
505
+ }
506
+
507
+ .mockos-subscription-sheet__action--bold {
508
+ font-weight: 600;
509
+ }
510
+
511
+ .mockos-subscription-sheet__action--android {
512
+ padding: 10px 16px;
513
+ font-size: 14px;
514
+ font-weight: 600;
515
+ border-radius: 4px;
516
+ text-transform: uppercase;
517
+ letter-spacing: 0.5px;
518
+ }
519
+
520
+ .mockos-subscription-sheet__action--cancel {
521
+ color: hsl(
522
+ var(--muted-foreground, var(--rb-muted-foreground, 220 8.9% 46.1%))
523
+ );
524
+ }
525
+
526
+ .mockos-subscription-sheet__action--primary {
527
+ color: hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)));
528
+ background: hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)) / 0.12);
529
+ border-radius: 999px;
530
+ font-weight: 700;
531
+ }
@@ -0,0 +1,23 @@
1
+ /* Onboard components */
2
+
3
+ .onboard__separator {
4
+ height: 1px;
5
+ width: 100%;
6
+ }
7
+
8
+ .onboard__buttons {
9
+ display: flex;
10
+ height: 40px;
11
+ gap: 12px;
12
+ align-items: center;
13
+ justify-content: center;
14
+ margin: 12px 24px;
15
+ }
16
+
17
+ .onboard__buttons--row {
18
+ flex-direction: row;
19
+ }
20
+
21
+ .onboard__buttons--column {
22
+ flex-direction: column;
23
+ }
@@ -15,6 +15,7 @@
15
15
  @use './components/attributes-editor';
16
16
  @use './components/mockos-router';
17
17
  @use './components/bottom-bar';
18
+ @use './components/onboard';
18
19
 
19
20
  @use './modals/modal-shell';
20
21
  @use './modals/add-component';
@@ -21,8 +21,4 @@ export const defaultAppConfig: AppConfig = {
21
21
  baseSize: { width: 375, height: 812 },
22
22
  };
23
23
 
24
- export type Localication = {
25
- [key: string]: {
26
- [key: string]: string;
27
- };
28
- };
24
+ export type Localication = Record<string, Record<string, string>>;
@@ -22,7 +22,12 @@ export type AnalyseResultWithPath = {
22
22
  };
23
23
 
24
24
  type AttributeTypeSpec = string | string[];
25
- type AttributeSchema = Record<string, AttributeTypeSpec>;
25
+ // schema v2 supports nesting style specs under `attributes.style` (one level deep)
26
+ type NestedAttributeSchema = Record<string, AttributeTypeSpec>;
27
+ type AttributeSchema = Record<
28
+ string,
29
+ AttributeTypeSpec | NestedAttributeSchema
30
+ >;
26
31
 
27
32
  type PatternLike = {
28
33
  pattern: {
@@ -51,6 +56,16 @@ function isPlainObject(value: unknown): value is Record<string, unknown> {
51
56
  return typeof value === 'object' && value !== null && !Array.isArray(value);
52
57
  }
53
58
 
59
+ function getStyleSubSchema(
60
+ schema: AttributeSchema | undefined,
61
+ ): AttributeSchema {
62
+ if (!schema) return {};
63
+ const maybe = schema.style;
64
+ if (!maybe) return {};
65
+ if (typeof maybe === 'string' || Array.isArray(maybe)) return {};
66
+ return (maybe ?? {}) as AttributeSchema;
67
+ }
68
+
54
69
  function isNodeDataLike(
55
70
  value: unknown,
56
71
  ): value is NodeData<NodeDefaultAttribute> {
@@ -359,6 +374,7 @@ function validateAttributesByPattern(
359
374
  const schema: AttributeSchema = (getAttributeSchema(pattern.pattern.type) ??
360
375
  pattern.pattern.attributes ??
361
376
  {}) as AttributeSchema;
377
+ const styleSchema = getStyleSubSchema(schema);
362
378
 
363
379
  // Validate nested `attributes.style` as an object; validate any style keys that also exist in schema.
364
380
  const maybeStyle = (attrs as Record<string, unknown>).style;
@@ -369,7 +385,9 @@ function validateAttributesByPattern(
369
385
  for (const [styleKey, styleValue] of Object.entries(
370
386
  maybeStyle as Record<string, unknown>,
371
387
  )) {
372
- const spec = schema?.[styleKey];
388
+ const spec = (styleSchema?.[styleKey] ?? schema?.[styleKey]) as
389
+ | AttributeTypeSpec
390
+ | undefined;
373
391
  if (!spec) continue; // allow unknown style keys (free-form CSSProperties)
374
392
  const res = validateAttributeValue(
375
393
  pattern.pattern.type,
@@ -383,9 +401,26 @@ function validateAttributesByPattern(
383
401
 
384
402
  for (const [attrName, attrValue] of Object.entries(attrs)) {
385
403
  if (attrName === 'style') continue;
386
- const attrSpec = schema?.[attrName];
404
+ const attrSpec = schema?.[attrName] as AttributeTypeSpec | undefined;
387
405
  if (!attrSpec) {
388
- return fail(`Unknown attribute "${attrName}"`, joinPath(path, attrName));
406
+ // Back-compat: allow legacy flat style keys even when the schema nests them.
407
+ const legacyStyleSpec = styleSchema?.[attrName] as
408
+ | AttributeTypeSpec
409
+ | undefined;
410
+ if (!legacyStyleSpec) {
411
+ return fail(
412
+ `Unknown attribute "${attrName}"`,
413
+ joinPath(path, attrName),
414
+ );
415
+ }
416
+ const res = validateAttributeValue(
417
+ pattern.pattern.type,
418
+ attrValue,
419
+ legacyStyleSpec,
420
+ joinPath(path, attrName),
421
+ );
422
+ if (!res.valid) return res;
423
+ continue;
389
424
  }
390
425
  const res = validateAttributeValue(
391
426
  pattern.pattern.type,
@@ -1,21 +1,50 @@
1
1
  import { ImagePropsGenerated } from '../build-components/Image/ImageProps.generated';
2
2
  import type { NodeData } from '../types/Node';
3
- import { extractViewStyle, ExtractViewStyleOptions } from './extractViewStyle';
3
+ import {
4
+ extractViewStyle,
5
+ extractViewStyleNative,
6
+ ExtractViewStyleOptions,
7
+ } from './extractViewStyle';
4
8
 
5
9
  export function extractImageStyle<T extends ImagePropsGenerated['attributes']>(
6
10
  node: NodeData<T>,
7
11
  options: ExtractViewStyleOptions = {},
8
12
  ) {
9
13
  const attributes = node.attributes;
14
+ const styleBag = (attributes as any)?.style as
15
+ | Record<string, unknown>
16
+ | undefined;
10
17
  const style: React.CSSProperties = {};
11
18
 
12
19
  if (!attributes) return style;
13
20
 
14
21
  // Map resizeMode to CSS object-fit
15
- if (attributes.resizeMode === 'cover') style.objectFit = 'cover';
16
- else if (attributes.resizeMode === 'contain') style.objectFit = 'contain';
17
- else if (attributes.resizeMode === 'stretch') style.objectFit = 'fill';
18
- else if (attributes.resizeMode === 'center') style.objectFit = 'none';
22
+ const resizeMode = ((attributes as any)?.resizeMode ??
23
+ styleBag?.resizeMode) as any;
24
+ if (resizeMode === 'cover') style.objectFit = 'cover';
25
+ else if (resizeMode === 'contain') style.objectFit = 'contain';
26
+ else if (resizeMode === 'stretch') style.objectFit = 'fill';
27
+ else if (resizeMode === 'center') style.objectFit = 'none';
19
28
 
20
29
  return { ...extractViewStyle(node, options), ...style };
21
30
  }
31
+
32
+ export function extractImageStyleNative<
33
+ T extends ImagePropsGenerated['attributes'],
34
+ >(node: NodeData<T>, options: ExtractViewStyleOptions = {}) {
35
+ const attributes = node.attributes;
36
+ const styleBag = (attributes as any)?.style as
37
+ | Record<string, unknown>
38
+ | undefined;
39
+ if (!attributes) return {};
40
+
41
+ const resizeMode = ((attributes as any)?.resizeMode ??
42
+ styleBag?.resizeMode) as any;
43
+
44
+ // In RN, resizeMode is usually an Image prop, but many codebases also accept it on ImageStyle.
45
+ // We return it here so consumers can pass it through as they prefer.
46
+ const nativeStyle: Record<string, unknown> = {};
47
+ if (resizeMode) nativeStyle.resizeMode = resizeMode;
48
+
49
+ return { ...extractViewStyleNative(node, options as any), ...nativeStyle };
50
+ }
@@ -15,7 +15,10 @@ import {
15
15
  } from '../loadFontFamily';
16
16
  import { fontsDebug } from '../fontsDebug';
17
17
 
18
- const inFlightFontLoads: Map<string, Promise<void>> = new Map();
18
+ const inFlightFontLoads: Map<string, Promise<void>> = new Map<
19
+ string,
20
+ Promise<void>
21
+ >();
19
22
 
20
23
  function weightToNumericKey(weight: unknown): string | undefined {
21
24
  const normalized = normalizeFontWeight(weight);
@@ -93,12 +96,10 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
93
96
  const styleBag = (attributes as any)?.style as
94
97
  | Record<string, unknown>
95
98
  | undefined;
96
- const get = <K extends keyof TextPropsGenerated['attributes']>(
97
- key: K,
98
- ): TextPropsGenerated['attributes'][K] | undefined => {
99
+ const get = (key: string): unknown => {
99
100
  const direct = (attributes as any)?.[key];
100
101
  if (direct !== undefined && direct !== null) return direct;
101
- return styleBag?.[key as unknown as string] as any;
102
+ return styleBag?.[key];
102
103
  };
103
104
  const resolvedAppConfig = options.appConfig ?? defaultAppConfig;
104
105
  const { screenStyle, theme } = resolvedAppConfig;
@@ -162,7 +163,7 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
162
163
  // If no fontFamily is set, keep previous behavior.
163
164
  if (!normalizedFontFamily && normalizedFontWeight)
164
165
  style.fontWeight = normalizedFontWeight;
165
- const resolvedTextColor = parseColor(get('color'), {
166
+ const resolvedTextColor = parseColor(get('color') as any, {
166
167
  projectColors: options.projectColors,
167
168
  theme,
168
169
  });
@@ -0,0 +1,106 @@
1
+ import type { NodeData } from '../../types/Node';
2
+ import type { TextPropsGenerated } from '../../build-components/Text/TextProps.generated';
3
+ import type { AppConfig } from '../../types/PreviewConfig';
4
+ import { defaultAppConfig } from '../../types/PreviewConfig';
5
+ import type { ProjectColors } from '../../types/Project';
6
+ import type { Fonts } from '../../types/Fonts';
7
+ import { fs, parseSize } from '../../size-matters';
8
+ import { parseColor } from '../parseColor';
9
+ import { extractViewStyleNative } from '../extractViewStyle';
10
+ import { normalizeFontWeight } from '../fontWeight';
11
+ import {
12
+ findFontDefinition,
13
+ resolveClosestFontWeightKey,
14
+ } from '../loadFontFamily';
15
+
16
+ export type ExtractTextStyleNativeOptions = {
17
+ appConfig?: AppConfig;
18
+ projectColors?: ProjectColors;
19
+ fonts?: Fonts;
20
+ };
21
+
22
+ function weightToNumericKey(weight: unknown): string | undefined {
23
+ const normalized = normalizeFontWeight(weight);
24
+ if (!normalized) return undefined;
25
+ if (normalized === 'normal') return '400';
26
+ if (normalized === 'bold') return '700';
27
+ return normalized;
28
+ }
29
+
30
+ /**
31
+ * React Native-friendly text style extraction.
32
+ * - Avoids web-only quoting of fontFamily.
33
+ * - Returns numeric fontSize (dp) when possible.
34
+ * - Merges with extractViewStyleNative so padding/margin/etc still work in RN.
35
+ */
36
+ export function extractTextStyleNative<
37
+ T extends TextPropsGenerated['attributes'],
38
+ >(node: NodeData<T>, options: ExtractTextStyleNativeOptions = {}) {
39
+ const attributes = node.attributes;
40
+ const styleBag = (attributes as any)?.style as
41
+ | Record<string, unknown>
42
+ | undefined;
43
+ const get = (key: string): unknown => {
44
+ const direct = (attributes as any)?.[key];
45
+ if (direct !== undefined && direct !== null) return direct;
46
+ return styleBag?.[key];
47
+ };
48
+
49
+ const resolvedAppConfig = options.appConfig ?? defaultAppConfig;
50
+ const { screenStyle, theme } = resolvedAppConfig;
51
+ const fallbackColor =
52
+ theme === 'light' ? screenStyle.light.color : screenStyle.dark.color;
53
+
54
+ const style: Record<string, unknown> = {};
55
+ if (!attributes) {
56
+ style.fontSize = fs(14);
57
+ style.color = fallbackColor;
58
+ return style;
59
+ }
60
+
61
+ const rawFontSize = get('fontSize') as any;
62
+ const parsedFontSize = parseSize(rawFontSize);
63
+ if (typeof parsedFontSize === 'number') style.fontSize = parsedFontSize;
64
+ else style.fontSize = fs(14);
65
+
66
+ const fontFamily = get('fontFamily') as any;
67
+ const fontWeight = get('fontWeight') as any;
68
+ const requestedWeight = weightToNumericKey(fontWeight);
69
+ const normalizedFontFamily =
70
+ typeof fontFamily === 'string' && fontFamily.trim().length > 0
71
+ ? fontFamily.trim()
72
+ : undefined;
73
+
74
+ if (normalizedFontFamily) {
75
+ const def = findFontDefinition(options.fonts ?? [], normalizedFontFamily);
76
+ const resolvedWeightKey =
77
+ def?.family && typeof def.family === 'object'
78
+ ? resolveClosestFontWeightKey(
79
+ def.family as Record<string, string>,
80
+ requestedWeight,
81
+ )
82
+ : requestedWeight;
83
+
84
+ style.fontFamily = normalizedFontFamily;
85
+ if (resolvedWeightKey) style.fontWeight = resolvedWeightKey;
86
+ }
87
+
88
+ const normalizedFontWeight = normalizeFontWeight(fontWeight);
89
+ if (!normalizedFontFamily && normalizedFontWeight)
90
+ style.fontWeight = normalizedFontWeight;
91
+
92
+ const resolvedTextColor = parseColor(get('color') as any, {
93
+ projectColors: options.projectColors,
94
+ theme,
95
+ });
96
+ style.color = resolvedTextColor ?? fallbackColor;
97
+
98
+ const textAlign = get('textAlign');
99
+ if (textAlign) style.textAlign = textAlign as any;
100
+
101
+ const viewStyle = extractViewStyleNative(node, {
102
+ projectColors: options.projectColors,
103
+ theme,
104
+ });
105
+ return { ...viewStyle, ...style };
106
+ }