@developer_tribe/react-builder 1.0.4 → 1.0.5

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 (499) hide show
  1. package/README.md +6 -0
  2. package/dist/assets/samples/getSamples.d.ts +1 -0
  3. package/dist/background.jpg +0 -0
  4. package/dist/build-components/BIcon/BIcon.d.ts +5 -0
  5. package/dist/build-components/BIcon/BIconProps.generated.d.ts +55 -0
  6. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +4 -0
  7. package/dist/build-components/Button/ButtonProps.generated.d.ts +4 -0
  8. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +4 -0
  9. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +4 -0
  10. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +4 -0
  11. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +4 -0
  12. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +4 -0
  13. package/dist/build-components/Image/ImageProps.generated.d.ts +4 -0
  14. package/dist/build-components/Main/Main.d.ts +5 -0
  15. package/dist/build-components/Main/MainProps.generated.d.ts +48 -0
  16. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +4 -0
  17. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +4 -0
  18. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +4 -0
  19. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +4 -0
  20. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +4 -0
  21. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +4 -0
  22. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +4 -0
  23. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +4 -1
  24. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +4 -0
  25. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +4 -0
  26. package/dist/build-components/PaywallBackground/PaywallBackground.d.ts +5 -0
  27. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +47 -0
  28. package/dist/build-components/PaywallCloseButton/PaywallCloseButton.d.ts +5 -0
  29. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +56 -0
  30. package/dist/build-components/PaywallOptions/PaywallOptionButton.d.ts +9 -0
  31. package/dist/build-components/PaywallOptions/PaywallOptions.d.ts +5 -0
  32. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +47 -0
  33. package/dist/build-components/PaywallOptions/usePaywallOptionParamsFactory.d.ts +10 -0
  34. package/dist/build-components/PaywallProvider/PaywallProvider.d.ts +5 -0
  35. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +47 -0
  36. package/dist/build-components/PaywallSubscriButton/PaywallSubscriButton.d.ts +5 -0
  37. package/dist/build-components/PaywallSubscriButton/PaywallSubscriButtonProps.generated.d.ts +50 -0
  38. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButton.d.ts +5 -0
  39. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +50 -0
  40. package/dist/build-components/RadioButton/RadioButton.d.ts +11 -0
  41. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +50 -0
  42. package/dist/build-components/RenderNode.generated.d.ts +1 -1
  43. package/dist/build-components/Text/TextProps.generated.d.ts +4 -0
  44. package/dist/build-components/View/ViewProps.generated.d.ts +4 -0
  45. package/dist/build-components/index.d.ts +10 -1
  46. package/dist/build-components/patterns.generated.d.ts +4831 -661
  47. package/dist/components/AttributesEditorPanel.d.ts +2 -1
  48. package/dist/components/Builder.d.ts +1 -1
  49. package/dist/components/BuilderButton.d.ts +1 -1
  50. package/dist/components/BuilderProvider.d.ts +15 -0
  51. package/dist/components/EditorHeader.d.ts +1 -1
  52. package/dist/components/Icon.generated.d.ts +11 -0
  53. package/dist/components/LocalizationParamsProvider.d.ts +11 -0
  54. package/dist/components/ParamsProvider.d.ts +14 -0
  55. package/dist/hooks/useLocalizationParams.d.ts +1 -0
  56. package/dist/hooks/useLocalize.d.ts +2 -0
  57. package/dist/hooks/useParams.d.ts +1 -0
  58. package/dist/hooks/useSafeAreaViewStyle.d.ts +1 -0
  59. package/dist/index.cjs.js +5 -5
  60. package/dist/index.cjs.js.map +1 -1
  61. package/dist/index.d.ts +8 -0
  62. package/dist/index.esm.js +5 -5
  63. package/dist/index.esm.js.map +1 -1
  64. package/dist/index.native.cjs.js +29 -0
  65. package/dist/index.native.cjs.js.map +1 -0
  66. package/dist/index.native.d.ts +31 -0
  67. package/dist/index.native.esm.js +29 -0
  68. package/dist/index.native.esm.js.map +1 -0
  69. package/dist/mockOS/components/MockOSRouter.d.ts +1 -1
  70. package/dist/mockOS/context/MockOSContext.d.ts +4 -18
  71. package/dist/mockOS/context/MockOSContextBase.d.ts +21 -0
  72. package/dist/mockOS/index.d.ts +3 -2
  73. package/dist/modals/BenefitEditModal.d.ts +13 -0
  74. package/dist/modals/BenefitPresetsModal.d.ts +9 -0
  75. package/dist/modals/IconPickerModal.d.ts +9 -0
  76. package/dist/modals/MockableFeatureModal.d.ts +6 -0
  77. package/dist/modals/ProductEditModal.d.ts +9 -0
  78. package/dist/modals/ProductPresetsModal.d.ts +9 -0
  79. package/dist/modals/index.d.ts +6 -0
  80. package/dist/pages/ProjectPage.d.ts +3 -2
  81. package/dist/pages/tabs/BuilderPanel.d.ts +1 -1
  82. package/dist/pages/tabs/SideTool.d.ts +1 -1
  83. package/dist/paywall/hooks/index.d.ts +5 -0
  84. package/dist/paywall/hooks/useCalculateLocalizedPrice.d.ts +4 -0
  85. package/dist/paywall/hooks/useCarouselOptionsSeperator.d.ts +6 -0
  86. package/dist/paywall/hooks/useCloseStatusPaywall.d.ts +4 -0
  87. package/dist/paywall/hooks/useDiscountRate.d.ts +4 -0
  88. package/dist/paywall/hooks/usePaywallCounter.d.ts +4 -0
  89. package/dist/paywall/types/benefits.d.ts +14 -0
  90. package/dist/paywall/types/paywall-types.d.ts +43 -0
  91. package/dist/store.d.ts +29 -1
  92. package/dist/styles.css +1 -1
  93. package/dist/types/Icons.d.ts +2 -0
  94. package/dist/types/Project.d.ts +5 -0
  95. package/dist/utils/analyseNode.d.ts +1 -4
  96. package/dist/utils/analyseNodeByPatterns.d.ts +16 -0
  97. package/dist/utils/analyseNodeStructural.d.ts +11 -0
  98. package/dist/utils/findNodeByKeyNested.d.ts +2 -0
  99. package/dist/utils/nodeGuards.d.ts +5 -0
  100. package/dist/utils/novaToJson.d.ts +5 -0
  101. package/dist/utils/patterns.d.ts +14 -0
  102. package/dist/utils/replaceLocalizationParams.d.ts +1 -0
  103. package/package.json +33 -3
  104. package/scripts/prebuild/assets/icon.template +71 -0
  105. package/scripts/prebuild/build-components.js +5 -0
  106. package/scripts/prebuild/icon-generator.js +206 -0
  107. package/scripts/prebuild/prebuild.js +10 -1
  108. package/scripts/prebuild/utils/createComponentTsx.js +6 -3
  109. package/scripts/prebuild/utils/createGeneratedProps.js +4 -2
  110. package/scripts/prebuild/utils/createRenderNodeGenerated.js +43 -8
  111. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +20 -9
  112. package/scripts/prebuild/utils/validatePatternJson.js +3 -2
  113. package/src/AttributesEditor.tsx +178 -34
  114. package/src/DeviceMockFrame.tsx +41 -43
  115. package/src/RenderPage.tsx +8 -49
  116. package/src/assets/benefits.json +24 -0
  117. package/src/assets/iconset/activity-heart.svg +3 -0
  118. package/src/assets/iconset/activity.svg +3 -0
  119. package/src/assets/iconset/alert-circle.svg +3 -0
  120. package/src/assets/iconset/alert-triangle.svg +3 -0
  121. package/src/assets/iconset/anchor.svg +3 -0
  122. package/src/assets/iconset/archive.svg +3 -0
  123. package/src/assets/iconset/arrow-down.svg +3 -0
  124. package/src/assets/iconset/arrow-left.svg +3 -0
  125. package/src/assets/iconset/arrow-narrow-down-left.svg +3 -0
  126. package/src/assets/iconset/arrow-narrow-up-right.svg +3 -0
  127. package/src/assets/iconset/arrow-right-smooth.svg +4 -0
  128. package/src/assets/iconset/arrow-right.svg +7 -0
  129. package/src/assets/iconset/asterisk-01.svg +3 -0
  130. package/src/assets/iconset/asterisk-02.svg +3 -0
  131. package/src/assets/iconset/at-sign.svg +3 -0
  132. package/src/assets/iconset/award.svg +4 -0
  133. package/src/assets/iconset/battery-charging.svg +6 -0
  134. package/src/assets/iconset/bell-01.svg +5 -0
  135. package/src/assets/iconset/bell-02.svg +3 -0
  136. package/src/assets/iconset/bell-ringing-02.svg +3 -0
  137. package/src/assets/iconset/bookmark-add.svg +3 -0
  138. package/src/assets/iconset/bookmark-check.svg +3 -0
  139. package/src/assets/iconset/bookmark-minus.svg +3 -0
  140. package/src/assets/iconset/bookmark-x.svg +3 -0
  141. package/src/assets/iconset/bookmark.svg +3 -0
  142. package/src/assets/iconset/bubble.svg +5 -0
  143. package/src/assets/iconset/building-01.svg +3 -0
  144. package/src/assets/iconset/building-02.svg +3 -0
  145. package/src/assets/iconset/building-03.svg +3 -0
  146. package/src/assets/iconset/building-04.svg +3 -0
  147. package/src/assets/iconset/building-05.svg +3 -0
  148. package/src/assets/iconset/building-06.svg +3 -0
  149. package/src/assets/iconset/building-07.svg +3 -0
  150. package/src/assets/iconset/building-08.svg +3 -0
  151. package/src/assets/iconset/building-09.svg +3 -0
  152. package/src/assets/iconset/camera-01.svg +8 -0
  153. package/src/assets/iconset/camera-steel.svg +4 -0
  154. package/src/assets/iconset/camera.svg +4 -0
  155. package/src/assets/iconset/check-circle-bold.svg +3 -0
  156. package/src/assets/iconset/check-circle-broken.svg +3 -0
  157. package/src/assets/iconset/check-circle.svg +3 -0
  158. package/src/assets/iconset/check-done-01.svg +3 -0
  159. package/src/assets/iconset/check-done-02.svg +3 -0
  160. package/src/assets/iconset/check-heart.svg +3 -0
  161. package/src/assets/iconset/check-square-broken.svg +3 -0
  162. package/src/assets/iconset/check-square.svg +3 -0
  163. package/src/assets/iconset/check-verified-01.svg +3 -0
  164. package/src/assets/iconset/check-verified-02.svg +3 -0
  165. package/src/assets/iconset/check-verified-03.svg +3 -0
  166. package/src/assets/iconset/check.svg +3 -0
  167. package/src/assets/iconset/checkbox.svg +4 -0
  168. package/src/assets/iconset/checkv.svg +3 -0
  169. package/src/assets/iconset/chevron-down.svg +3 -0
  170. package/src/assets/iconset/chevron-down2.svg +3 -0
  171. package/src/assets/iconset/chevron-left-2.svg +3 -0
  172. package/src/assets/iconset/chevron-left.svg +3 -0
  173. package/src/assets/iconset/chevron-right-empty.svg +3 -0
  174. package/src/assets/iconset/chevron-right-smooth.svg +3 -0
  175. package/src/assets/iconset/chevron-right.svg +3 -0
  176. package/src/assets/iconset/chevron-up.svg +3 -0
  177. package/src/assets/iconset/circle.svg +32 -0
  178. package/src/assets/iconset/clock-fast-forward.svg +10 -0
  179. package/src/assets/iconset/clock.svg +3 -0
  180. package/src/assets/iconset/close-circle.svg +3 -0
  181. package/src/assets/iconset/close.svg +3 -0
  182. package/src/assets/iconset/cloud-01.svg +5 -0
  183. package/src/assets/iconset/cloud-blank-01.svg +3 -0
  184. package/src/assets/iconset/cloud-blank-02.svg +3 -0
  185. package/src/assets/iconset/coin.svg +5 -0
  186. package/src/assets/iconset/coins-02.svg +3 -0
  187. package/src/assets/iconset/colors.svg +3 -0
  188. package/src/assets/iconset/copy-01.svg +3 -0
  189. package/src/assets/iconset/copy-02.svg +3 -0
  190. package/src/assets/iconset/copy-03.svg +3 -0
  191. package/src/assets/iconset/copy-04.svg +3 -0
  192. package/src/assets/iconset/copy-05.svg +3 -0
  193. package/src/assets/iconset/copy-06.svg +3 -0
  194. package/src/assets/iconset/copy-07.svg +3 -0
  195. package/src/assets/iconset/corner-down-right.svg +3 -0
  196. package/src/assets/iconset/crypto-bold.svg +4 -0
  197. package/src/assets/iconset/delete-icon.svg +5 -0
  198. package/src/assets/iconset/diamond.svg +3 -0
  199. package/src/assets/iconset/dice-3.svg +3 -0
  200. package/src/assets/iconset/divide-01.svg +3 -0
  201. package/src/assets/iconset/divide-02.svg +3 -0
  202. package/src/assets/iconset/divide-03.svg +3 -0
  203. package/src/assets/iconset/document-check-bold.svg +4 -0
  204. package/src/assets/iconset/dots-circle.svg +10 -0
  205. package/src/assets/iconset/dots-grid.svg +11 -0
  206. package/src/assets/iconset/dots-horizontal.svg +5 -0
  207. package/src/assets/iconset/dots-vertical.svg +5 -0
  208. package/src/assets/iconset/download-01.svg +3 -0
  209. package/src/assets/iconset/download-02.svg +3 -0
  210. package/src/assets/iconset/download-03.svg +3 -0
  211. package/src/assets/iconset/edit-03.svg +3 -0
  212. package/src/assets/iconset/edit-04.svg +3 -0
  213. package/src/assets/iconset/edit-05.svg +3 -0
  214. package/src/assets/iconset/element-3.svg +6 -0
  215. package/src/assets/iconset/ellipse-127.svg +3 -0
  216. package/src/assets/iconset/exclaimation-circle.svg +8 -0
  217. package/src/assets/iconset/eye-off-line.svg +5 -0
  218. package/src/assets/iconset/face-smile.svg +5 -0
  219. package/src/assets/iconset/file-04.svg +3 -0
  220. package/src/assets/iconset/file-05.svg +3 -0
  221. package/src/assets/iconset/file-check-02.svg +3 -0
  222. package/src/assets/iconset/file-plus-01.svg +5 -0
  223. package/src/assets/iconset/file-shield-02.svg +5 -0
  224. package/src/assets/iconset/filter-funnel-01.svg +3 -0
  225. package/src/assets/iconset/flag-03.svg +3 -0
  226. package/src/assets/iconset/flash.svg +3 -0
  227. package/src/assets/iconset/folder-plus.svg +3 -0
  228. package/src/assets/iconset/folder.svg +3 -0
  229. package/src/assets/iconset/gallery.svg +3 -0
  230. package/src/assets/iconset/globe-01.svg +3 -0
  231. package/src/assets/iconset/globe-04.svg +5 -0
  232. package/src/assets/iconset/globe-bold.svg +4 -0
  233. package/src/assets/iconset/guard.svg +3 -0
  234. package/src/assets/iconset/headphones-01.svg +3 -0
  235. package/src/assets/iconset/headphones-02.svg +5 -0
  236. package/src/assets/iconset/headset-bold.svg +4 -0
  237. package/src/assets/iconset/heart-bold.svg +3 -0
  238. package/src/assets/iconset/heart.svg +3 -0
  239. package/src/assets/iconset/help-circle.svg +5 -0
  240. package/src/assets/iconset/home-2.svg +4 -0
  241. package/src/assets/iconset/home-line.svg +3 -0
  242. package/src/assets/iconset/hourglass-02.svg +5 -0
  243. package/src/assets/iconset/image-01.svg +5 -0
  244. package/src/assets/iconset/image-03.svg +3 -0
  245. package/src/assets/iconset/image.svg +4 -0
  246. package/src/assets/iconset/inbox-01.svg +3 -0
  247. package/src/assets/iconset/inbox-arrow-down.svg +3 -0
  248. package/src/assets/iconset/info-circle.svg +3 -0
  249. package/src/assets/iconset/keyboard-line.svg +9 -0
  250. package/src/assets/iconset/lamp-charge.svg +5 -0
  251. package/src/assets/iconset/layer.svg +3 -0
  252. package/src/assets/iconset/light.svg +6 -0
  253. package/src/assets/iconset/like-dislike.svg +6 -0
  254. package/src/assets/iconset/lock-03.svg +3 -0
  255. package/src/assets/iconset/logout.svg +3 -0
  256. package/src/assets/iconset/magicpen.svg +7 -0
  257. package/src/assets/iconset/mail-01.svg +5 -0
  258. package/src/assets/iconset/mail.svg +3 -0
  259. package/src/assets/iconset/marker.svg +3 -0
  260. package/src/assets/iconset/medal-star.svg +5 -0
  261. package/src/assets/iconset/menu-04.svg +3 -0
  262. package/src/assets/iconset/menu.svg +5 -0
  263. package/src/assets/iconset/message-circle-01.svg +5 -0
  264. package/src/assets/iconset/message-plus-circle.svg +3 -0
  265. package/src/assets/iconset/message-question-circle.svg +5 -0
  266. package/src/assets/iconset/message-text-circle-01.svg +5 -0
  267. package/src/assets/iconset/message-text-square-02.svg +3 -0
  268. package/src/assets/iconset/message-x-square.svg +3 -0
  269. package/src/assets/iconset/microphone-02.svg +3 -0
  270. package/src/assets/iconset/microphone-slash.svg +8 -0
  271. package/src/assets/iconset/mirror.svg +4 -0
  272. package/src/assets/iconset/moon-01.svg +3 -0
  273. package/src/assets/iconset/moon-bold.svg +3 -0
  274. package/src/assets/iconset/mouse-circle.svg +4 -0
  275. package/src/assets/iconset/move.svg +5 -0
  276. package/src/assets/iconset/notification-fill.svg +3 -0
  277. package/src/assets/iconset/notification-text.svg +3 -0
  278. package/src/assets/iconset/notification.svg +5 -0
  279. package/src/assets/iconset/pdf-01.svg +6 -0
  280. package/src/assets/iconset/pencil-01.svg +5 -0
  281. package/src/assets/iconset/phone-01.svg +3 -0
  282. package/src/assets/iconset/phone-arrow-down-left.svg +4 -0
  283. package/src/assets/iconset/phone-arrow-up-right.svg +8 -0
  284. package/src/assets/iconset/phone-hang-up.svg +5 -0
  285. package/src/assets/iconset/phone-hangup2.svg +8 -0
  286. package/src/assets/iconset/phone-incoming-01.svg +3 -0
  287. package/src/assets/iconset/phone-outgoing-01.svg +3 -0
  288. package/src/assets/iconset/phone-plus.svg +3 -0
  289. package/src/assets/iconset/phone-x.svg +3 -0
  290. package/src/assets/iconset/phone.svg +3 -0
  291. package/src/assets/iconset/plus-circle.svg +3 -0
  292. package/src/assets/iconset/plus.svg +4 -0
  293. package/src/assets/iconset/printer.svg +3 -0
  294. package/src/assets/iconset/question-mark-circle.svg +5 -0
  295. package/src/assets/iconset/refresh-ccw-01.svg +3 -0
  296. package/src/assets/iconset/refresh-cw-01.svg +3 -0
  297. package/src/assets/iconset/refresh-cw-04.svg +3 -0
  298. package/src/assets/iconset/refresh-right-square-bold.svg +3 -0
  299. package/src/assets/iconset/remove-circle.svg +12 -0
  300. package/src/assets/iconset/repeat-04.svg +3 -0
  301. package/src/assets/iconset/repeat-bold.svg +3 -0
  302. package/src/assets/iconset/ruler-pen.svg +4 -0
  303. package/src/assets/iconset/search-lg.svg +3 -0
  304. package/src/assets/iconset/search-md.svg +5 -0
  305. package/src/assets/iconset/search-refraction.svg +5 -0
  306. package/src/assets/iconset/search.svg +3 -0
  307. package/src/assets/iconset/send-01.svg +3 -0
  308. package/src/assets/iconset/send-02.svg +5 -0
  309. package/src/assets/iconset/send-diagonal.svg +3 -0
  310. package/src/assets/iconset/setting-2.svg +4 -0
  311. package/src/assets/iconset/settings-02.svg +4 -0
  312. package/src/assets/iconset/settings-04.svg +5 -0
  313. package/src/assets/iconset/settings-2.svg +4 -0
  314. package/src/assets/iconset/settings-cog.svg +3 -0
  315. package/src/assets/iconset/settings.svg +4 -0
  316. package/src/assets/iconset/share-01.svg +4 -0
  317. package/src/assets/iconset/share-03.svg +3 -0
  318. package/src/assets/iconset/share-04.svg +3 -0
  319. package/src/assets/iconset/share-05.svg +5 -0
  320. package/src/assets/iconset/share-06.svg +3 -0
  321. package/src/assets/iconset/share-bold.svg +3 -0
  322. package/src/assets/iconset/shield-01.svg +3 -0
  323. package/src/assets/iconset/shield-bold.svg +3 -0
  324. package/src/assets/iconset/solar-check.svg +3 -0
  325. package/src/assets/iconset/speaker-wave.svg +9 -0
  326. package/src/assets/iconset/speaker.svg +5 -0
  327. package/src/assets/iconset/speedometer-03.svg +3 -0
  328. package/src/assets/iconset/star-rounded.svg +3 -0
  329. package/src/assets/iconset/star.svg +3 -0
  330. package/src/assets/iconset/sun.svg +5 -0
  331. package/src/assets/iconset/target-03.svg +3 -0
  332. package/src/assets/iconset/text-input.svg +3 -0
  333. package/src/assets/iconset/translate.svg +7 -0
  334. package/src/assets/iconset/trash-02.svg +3 -0
  335. package/src/assets/iconset/trash-03.svg +5 -0
  336. package/src/assets/iconset/trash-04.svg +3 -0
  337. package/src/assets/iconset/trash.svg +7 -0
  338. package/src/assets/iconset/trush-square-bold.svg +3 -0
  339. package/src/assets/iconset/unlimited.svg +3 -0
  340. package/src/assets/iconset/user-circle.svg +3 -0
  341. package/src/assets/iconset/user-jogging.svg +3 -0
  342. package/src/assets/iconset/user-plus-01.svg +5 -0
  343. package/src/assets/iconset/user-square.svg +5 -0
  344. package/src/assets/iconset/user-x-01.svg +5 -0
  345. package/src/assets/iconset/user-x-02.svg +3 -0
  346. package/src/assets/iconset/user2.svg +3 -0
  347. package/src/assets/iconset/users-02.svg +5 -0
  348. package/src/assets/iconset/users-speaker.svg +7 -0
  349. package/src/assets/iconset/verify.svg +3 -0
  350. package/src/assets/iconset/voice-cricle.svg +8 -0
  351. package/src/assets/iconset/x-circle.svg +3 -0
  352. package/src/assets/iconset/x-close.svg +3 -0
  353. package/src/assets/iconset/x-sm.svg +3 -0
  354. package/src/assets/iconset/zap.svg +3 -0
  355. package/src/assets/images/background.jpg +0 -0
  356. package/src/assets/loading_animation.json +1 -0
  357. package/src/assets/products.json +98 -0
  358. package/src/assets/samples/carousel-sample.json +1 -0
  359. package/src/assets/samples/getSamples.ts +39 -66
  360. package/src/assets/samples/paywall-1.json +220 -0
  361. package/src/assets/samples/simple-1.json +1 -0
  362. package/src/assets/samples/simple-2.json +1 -0
  363. package/src/assets/samples/vpn-onboard-1.json +324 -720
  364. package/src/assets/samples/vpn-onboard-2.json +299 -683
  365. package/src/assets/samples/vpn-onboard-3.json +270 -680
  366. package/src/assets/samples/vpn-onboard-4.json +270 -681
  367. package/src/assets/samples/vpn-onboard-5.json +408 -893
  368. package/src/assets/samples/vpn-onboard-6.json +279 -594
  369. package/src/attributes-editor/SpecialCategorySection.tsx +1 -1
  370. package/src/build-components/BIcon/BIcon.tsx +56 -0
  371. package/src/build-components/BIcon/BIconProps.generated.ts +82 -0
  372. package/src/build-components/BIcon/pattern.json +47 -0
  373. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +4 -0
  374. package/src/build-components/BackgroundImage/pattern.json +2 -2
  375. package/src/build-components/Button/Button.tsx +14 -1
  376. package/src/build-components/Button/ButtonProps.generated.ts +4 -0
  377. package/src/build-components/Button/pattern.json +4 -1
  378. package/src/build-components/Carousel/CarouselProps.generated.ts +4 -0
  379. package/src/build-components/Carousel/pattern.json +2 -2
  380. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +4 -0
  381. package/src/build-components/CarouselButtons/pattern.json +1 -1
  382. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +4 -0
  383. package/src/build-components/CarouselDots/pattern.json +1 -1
  384. package/src/build-components/CarouselItem/CarouselItem.tsx +1 -1
  385. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +4 -0
  386. package/src/build-components/CarouselItem/pattern.json +1 -1
  387. package/src/build-components/CarouselProvider/CarouselProvider.tsx +1 -1
  388. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +4 -0
  389. package/src/build-components/CarouselProvider/pattern.json +1 -1
  390. package/src/build-components/Image/ImageProps.generated.ts +4 -0
  391. package/src/build-components/Image/pattern.json +1 -1
  392. package/src/build-components/Main/Main.tsx +61 -0
  393. package/src/build-components/Main/MainProps.generated.ts +64 -0
  394. package/src/build-components/Main/pattern.json +35 -0
  395. package/src/build-components/Onboard/OnboardProps.generated.ts +4 -0
  396. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +4 -0
  397. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +4 -0
  398. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +4 -0
  399. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +4 -0
  400. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +4 -0
  401. package/src/build-components/OnboardItem/OnboardItem.tsx +1 -1
  402. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +4 -0
  403. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +4 -1
  404. package/src/build-components/OnboardProvider/pattern.json +6 -16
  405. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +4 -0
  406. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +4 -0
  407. package/src/build-components/PaywallBackground/PaywallBackground.tsx +47 -0
  408. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +63 -0
  409. package/src/build-components/PaywallBackground/pattern.json +16 -0
  410. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +62 -0
  411. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +83 -0
  412. package/src/build-components/PaywallCloseButton/pattern.json +23 -0
  413. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +64 -0
  414. package/src/build-components/PaywallOptions/PaywallOptions.tsx +92 -0
  415. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +63 -0
  416. package/src/build-components/PaywallOptions/pattern.json +22 -0
  417. package/src/build-components/PaywallOptions/usePaywallOptionParamsFactory.ts +42 -0
  418. package/src/build-components/PaywallProvider/PaywallProvider.tsx +78 -0
  419. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +63 -0
  420. package/src/build-components/PaywallProvider/pattern.json +24 -0
  421. package/src/build-components/PaywallSubscriButton/PaywallSubscriButton.tsx +10 -0
  422. package/src/build-components/PaywallSubscriButton/PaywallSubscriButtonProps.generated.ts +77 -0
  423. package/src/build-components/PaywallSubscriButton/pattern.json +27 -0
  424. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +60 -0
  425. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +77 -0
  426. package/src/build-components/PaywallSubscribeButton/pattern.json +27 -0
  427. package/src/build-components/RadioButton/RadioButton.tsx +123 -0
  428. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +66 -0
  429. package/src/build-components/RadioButton/pattern.json +42 -0
  430. package/src/build-components/RenderNode.generated.tsx +140 -37
  431. package/src/build-components/Text/Text.tsx +3 -3
  432. package/src/build-components/Text/TextProps.generated.ts +4 -0
  433. package/src/build-components/Text/pattern.json +1 -1
  434. package/src/build-components/View/ViewProps.generated.ts +4 -0
  435. package/src/build-components/View/pattern.json +42 -4
  436. package/src/build-components/index.ts +55 -10
  437. package/src/build-components/patterns.generated.ts +4909 -706
  438. package/src/components/AttributesEditorPanel.tsx +3 -1
  439. package/src/components/Builder.tsx +3 -5
  440. package/src/components/BuilderButton.tsx +2 -7
  441. package/src/components/BuilderProvider.tsx +45 -0
  442. package/src/components/DeviceNavigationBar.tsx +1 -1
  443. package/src/components/EditorHeader.tsx +4 -1
  444. package/src/components/Icon.generated.tsx +540 -0
  445. package/src/components/LocalizationParamsProvider.tsx +22 -0
  446. package/src/components/ParamsProvider.tsx +38 -0
  447. package/src/hooks/useLocalizationParams.ts +5 -0
  448. package/src/hooks/useLocalize.ts +23 -0
  449. package/src/hooks/useParams.ts +8 -0
  450. package/src/hooks/useSafeAreaViewStyle.ts +67 -0
  451. package/src/index.native.ts +75 -0
  452. package/src/index.ts +26 -0
  453. package/src/mockOS/components/MockOSRouter.tsx +9 -14
  454. package/src/mockOS/context/MockOSContext.tsx +12 -36
  455. package/src/mockOS/context/MockOSContextBase.ts +35 -0
  456. package/src/mockOS/index.ts +3 -2
  457. package/src/modals/AddComponentModal.tsx +1 -0
  458. package/src/modals/BenefitEditModal.tsx +160 -0
  459. package/src/modals/BenefitPresetsModal.tsx +166 -0
  460. package/src/modals/IconPickerModal.tsx +109 -0
  461. package/src/modals/MockableFeatureModal.tsx +292 -0
  462. package/src/modals/ProductEditModal.tsx +215 -0
  463. package/src/modals/ProductPresetsModal.tsx +151 -0
  464. package/src/modals/index.ts +6 -0
  465. package/src/pages/ProjectPage.tsx +72 -15
  466. package/src/pages/tabs/BuilderPanel.tsx +1 -1
  467. package/src/pages/tabs/SideTool.tsx +3 -10
  468. package/src/paywall/hooks/index.ts +5 -0
  469. package/src/paywall/hooks/useCalculateLocalizedPrice.ts +6 -0
  470. package/src/paywall/hooks/useCarouselOptionsSeperator.ts +8 -0
  471. package/src/paywall/hooks/useCloseStatusPaywall.ts +6 -0
  472. package/src/paywall/hooks/useDiscountRate.ts +6 -0
  473. package/src/paywall/hooks/usePaywallCounter.ts +6 -0
  474. package/src/paywall/types/benefits.ts +44 -0
  475. package/src/paywall/types/paywall-types.ts +51 -0
  476. package/src/store.ts +155 -41
  477. package/src/styles/base/_global.scss +49 -41
  478. package/src/styles/components/_attributes-editor.scss +40 -5
  479. package/src/styles/components/_editor-shell.scss +5 -11
  480. package/src/styles/components/_ui-components.scss +2 -1
  481. package/src/styles/index.scss +5 -0
  482. package/src/styles/modals/_benefit-edit-modal.scss +17 -0
  483. package/src/styles/modals/_benefit-presets-modal.scss +79 -0
  484. package/src/styles/modals/_mockable-feature-modal.scss +15 -0
  485. package/src/styles/modals/_product-edit-modal.scss +23 -0
  486. package/src/styles/modals/_product-presets-modal.scss +81 -0
  487. package/src/types/Icons.ts +244 -0
  488. package/src/types/Project.ts +5 -0
  489. package/src/types/jest-globals.d.ts +13 -0
  490. package/src/utils/analyseNode.ts +22 -109
  491. package/src/utils/analyseNodeByPatterns.ts +438 -0
  492. package/src/utils/analyseNodeStructural.ts +52 -0
  493. package/src/utils/extractViewStyle.ts +19 -0
  494. package/src/utils/findNodeByKeyNested.ts +32 -0
  495. package/src/utils/isCarousel.ts +21 -5
  496. package/src/utils/nodeGuards.ts +26 -0
  497. package/src/utils/novaToJson.ts +21 -9
  498. package/src/utils/patterns.ts +62 -3
  499. package/src/utils/replaceLocalizationParams.ts +15 -0
@@ -0,0 +1,438 @@
1
+ import type { Node, NodeData, NodeDefaultAttribute } from '../types/Node';
2
+ import {
3
+ getArrayItemType,
4
+ getAttributeSchema,
5
+ getPatternByType,
6
+ getTypeSchema,
7
+ isPrimitiveType,
8
+ normalizeComponentType,
9
+ } from './patterns';
10
+ import {
11
+ isEmptyObject,
12
+ isNodeArray,
13
+ isNodeNullOrUndefined,
14
+ isNodeString,
15
+ } from './nodeGuards';
16
+
17
+ export type AnalyseResultWithPath = {
18
+ valid: boolean;
19
+ message?: string;
20
+ path?: string;
21
+ };
22
+
23
+ type AttributeTypeSpec = string | string[];
24
+ type AttributeSchema = Record<string, AttributeTypeSpec>;
25
+
26
+ type PatternLike = {
27
+ allowUnknownAttributes: boolean;
28
+ pattern: {
29
+ type: string;
30
+ children: unknown;
31
+ attributes?: AttributeSchema;
32
+ };
33
+ };
34
+
35
+ function ok(): AnalyseResultWithPath {
36
+ return { valid: true };
37
+ }
38
+
39
+ function fail(message: string, path?: string): AnalyseResultWithPath {
40
+ return { valid: false, message, path };
41
+ }
42
+
43
+ function joinPath(base: string, next: string): string {
44
+ if (!base) return next;
45
+ if (!next) return base;
46
+ // next may already include brackets (e.g. [0])
47
+ return next.startsWith('[') ? `${base}${next}` : `${base}.${next}`;
48
+ }
49
+
50
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
51
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
52
+ }
53
+
54
+ function isNodeDataLike(
55
+ value: unknown,
56
+ ): value is NodeData<NodeDefaultAttribute> {
57
+ if (!isPlainObject(value)) return false;
58
+ const maybeType = (value as Record<string, unknown>).type;
59
+ return typeof maybeType === 'string' && 'children' in value;
60
+ }
61
+
62
+ function normalizeTypeOrFallback(type: string): string {
63
+ return normalizeComponentType(type) ?? type;
64
+ }
65
+
66
+ function getChildrenSpecTokens(pattern: PatternLike): string[] {
67
+ const raw = pattern?.pattern?.children;
68
+ if (typeof raw === 'string') return [raw];
69
+ if (Array.isArray(raw)) return raw.filter((x) => typeof x === 'string');
70
+ return [];
71
+ }
72
+
73
+ function splitChildrenSpec(tokens: string[]): {
74
+ baseKinds: Set<'never' | 'string' | 'node' | 'array'>;
75
+ allowedComponentTypes: Set<string>;
76
+ } {
77
+ const baseKinds = new Set<'never' | 'string' | 'node' | 'array'>();
78
+ const allowedComponentTypes = new Set<string>();
79
+ for (const t of tokens) {
80
+ if (t === 'never' || t === 'string' || t === 'node' || t === 'array') {
81
+ baseKinds.add(t);
82
+ } else if (typeof t === 'string' && t) {
83
+ allowedComponentTypes.add(normalizeTypeOrFallback(t));
84
+ }
85
+ }
86
+ return { baseKinds, allowedComponentTypes };
87
+ }
88
+
89
+ function validateChildrenNeverRule(
90
+ children: Node<NodeDefaultAttribute>,
91
+ baseKinds: Set<'never' | 'string' | 'node' | 'array'>,
92
+ path: string,
93
+ ): AnalyseResultWithPath {
94
+ if (!baseKinds.has('never')) return ok();
95
+ if (isNodeNullOrUndefined(children) || isEmptyObject(children)) return ok();
96
+ return fail(`Children not allowed (pattern.children = "never")`, path);
97
+ }
98
+
99
+ function validateChildrenKindRule(
100
+ children: Node<NodeDefaultAttribute>,
101
+ baseKinds: Set<'never' | 'string' | 'node' | 'array'>,
102
+ allowedComponentTypes: Set<string>,
103
+ path: string,
104
+ ): AnalyseResultWithPath {
105
+ if (isNodeNullOrUndefined(children) || isEmptyObject(children)) return ok();
106
+
107
+ // Component-type specs allow either a single node or an array of nodes.
108
+ if (allowedComponentTypes.size > 0) {
109
+ if (isNodeArray(children)) return ok();
110
+ if (isNodeDataLike(children)) return ok();
111
+ return fail(
112
+ `Children must be a node or array of nodes (allowed: ${Array.from(
113
+ allowedComponentTypes,
114
+ ).join(', ')})`,
115
+ path,
116
+ );
117
+ }
118
+
119
+ if (isNodeString(children)) {
120
+ return baseKinds.has('string')
121
+ ? ok()
122
+ : fail(`Children must not be a string`, path);
123
+ }
124
+ if (isNodeArray(children)) {
125
+ return baseKinds.has('array')
126
+ ? ok()
127
+ : fail(`Children must not be an array`, path);
128
+ }
129
+ if (isNodeDataLike(children)) {
130
+ return baseKinds.has('node')
131
+ ? ok()
132
+ : fail(`Children must not be a node`, path);
133
+ }
134
+
135
+ // Unknown object shape
136
+ return fail(`Children has invalid shape`, path);
137
+ }
138
+
139
+ function validateChildrenAllowedComponentTypesRule(
140
+ children: Node<NodeDefaultAttribute>,
141
+ allowedComponentTypes: Set<string>,
142
+ path: string,
143
+ ): AnalyseResultWithPath {
144
+ if (allowedComponentTypes.size === 0) return ok();
145
+ if (isNodeNullOrUndefined(children) || isEmptyObject(children)) return ok();
146
+
147
+ const allowed = Array.from(allowedComponentTypes);
148
+
149
+ const validateChildType = (child: unknown, childPath: string) => {
150
+ if (!isNodeDataLike(child)) {
151
+ return fail(`Child must be an object node`, childPath);
152
+ }
153
+ const actual = normalizeTypeOrFallback(child.type);
154
+ if (!allowedComponentTypes.has(actual)) {
155
+ return fail(
156
+ `Child type "${child.type}" is not allowed here (allowed: ${allowed.join(
157
+ ', ',
158
+ )})`,
159
+ joinPath(childPath, 'type'),
160
+ );
161
+ }
162
+ return ok();
163
+ };
164
+
165
+ if (isNodeArray(children)) {
166
+ const arr = children as unknown[];
167
+ for (let i = 0; i < arr.length; i++) {
168
+ const res = validateChildType(arr[i], `${path}[${i}]`);
169
+ if (!res.valid) return res;
170
+ }
171
+ return ok();
172
+ }
173
+
174
+ return validateChildType(children, path);
175
+ }
176
+
177
+ function validateChildrenByPattern(
178
+ nodeData: NodeData<NodeDefaultAttribute>,
179
+ pattern: PatternLike,
180
+ path: string,
181
+ ): AnalyseResultWithPath {
182
+ const tokens = getChildrenSpecTokens(pattern);
183
+ const { baseKinds, allowedComponentTypes } = splitChildrenSpec(tokens);
184
+
185
+ const neverRes = validateChildrenNeverRule(
186
+ nodeData.children,
187
+ baseKinds,
188
+ path,
189
+ );
190
+ if (!neverRes.valid) return neverRes;
191
+
192
+ const kindRes = validateChildrenKindRule(
193
+ nodeData.children,
194
+ baseKinds,
195
+ allowedComponentTypes,
196
+ path,
197
+ );
198
+ if (!kindRes.valid) return kindRes;
199
+
200
+ return validateChildrenAllowedComponentTypesRule(
201
+ nodeData.children,
202
+ allowedComponentTypes,
203
+ path,
204
+ );
205
+ }
206
+
207
+ function validatePrimitiveValue(
208
+ value: unknown,
209
+ primitiveType: string,
210
+ path: string,
211
+ ): AnalyseResultWithPath {
212
+ switch (primitiveType) {
213
+ case 'string':
214
+ return typeof value === 'string' ? ok() : fail(`Expected string`, path);
215
+ case 'number':
216
+ return typeof value === 'number' ? ok() : fail(`Expected number`, path);
217
+ case 'boolean':
218
+ return typeof value === 'boolean' ? ok() : fail(`Expected boolean`, path);
219
+ case 'color':
220
+ return typeof value === 'string'
221
+ ? ok()
222
+ : fail(`Expected color (string)`, path);
223
+ case 'size':
224
+ // Sizes can be numbers or strings like "16@fs" / "100%" / "20px"
225
+ return typeof value === 'number' || typeof value === 'string'
226
+ ? ok()
227
+ : fail(`Expected size (string or number)`, path);
228
+ case 'iconType':
229
+ return typeof value === 'string'
230
+ ? ok()
231
+ : fail(`Expected iconType (string)`, path);
232
+ default:
233
+ return fail(`Unknown primitive type "${primitiveType}"`, path);
234
+ }
235
+ }
236
+
237
+ function validateEnumValue(
238
+ value: unknown,
239
+ options: string[],
240
+ path: string,
241
+ ): AnalyseResultWithPath {
242
+ if (typeof value === 'string') {
243
+ return options.includes(value)
244
+ ? ok()
245
+ : fail(`Expected one of: ${options.join(', ')}`, path);
246
+ }
247
+ if (Array.isArray(value)) {
248
+ for (let i = 0; i < value.length; i++) {
249
+ const v = value[i];
250
+ if (typeof v !== 'string' || !options.includes(v)) {
251
+ return fail(
252
+ `Expected an array of: ${options.join(', ')}`,
253
+ `${path}[${i}]`,
254
+ );
255
+ }
256
+ }
257
+ return ok();
258
+ }
259
+ return fail(`Expected a string or string[] enum value`, path);
260
+ }
261
+
262
+ function validateCustomObjectValue(
263
+ componentType: string,
264
+ value: unknown,
265
+ typeName: string,
266
+ path: string,
267
+ ): AnalyseResultWithPath {
268
+ const schema = getTypeSchema(componentType, typeName);
269
+ if (!schema) {
270
+ return fail(`Unknown custom type "${typeName}"`, path);
271
+ }
272
+ if (!isPlainObject(value)) {
273
+ return fail(`Expected object for type "${typeName}"`, path);
274
+ }
275
+
276
+ for (const [fieldName, fieldSpec] of Object.entries(schema)) {
277
+ if (!(fieldName in value)) continue;
278
+ const fieldValue = (value as Record<string, unknown>)[fieldName];
279
+ const fieldPath = joinPath(path, fieldName);
280
+ const res = validateAttributeValue(
281
+ componentType,
282
+ fieldValue,
283
+ fieldSpec,
284
+ fieldPath,
285
+ );
286
+ if (!res.valid) return res;
287
+ }
288
+
289
+ return ok();
290
+ }
291
+
292
+ function validateAttributeValue(
293
+ componentType: string,
294
+ value: unknown,
295
+ spec: AttributeTypeSpec,
296
+ path: string,
297
+ ): AnalyseResultWithPath {
298
+ if (Array.isArray(spec)) {
299
+ return validateEnumValue(value, spec, path);
300
+ }
301
+
302
+ const arrayItemType = getArrayItemType(spec);
303
+ if (arrayItemType) {
304
+ if (!Array.isArray(value)) {
305
+ return fail(`Expected array for type "${spec}"`, path);
306
+ }
307
+ for (let i = 0; i < value.length; i++) {
308
+ const item = value[i];
309
+ const itemPath = `${path}[${i}]`;
310
+ const res = validateAttributeValue(
311
+ componentType,
312
+ item,
313
+ arrayItemType,
314
+ itemPath,
315
+ );
316
+ if (!res.valid) return res;
317
+ }
318
+ return ok();
319
+ }
320
+
321
+ if (isPrimitiveType(spec)) {
322
+ return validatePrimitiveValue(value, spec, path);
323
+ }
324
+
325
+ return validateCustomObjectValue(componentType, value, spec, path);
326
+ }
327
+
328
+ function validateAttributesByPattern(
329
+ nodeData: NodeData<NodeDefaultAttribute>,
330
+ pattern: PatternLike,
331
+ path: string,
332
+ ): AnalyseResultWithPath {
333
+ const attrs = nodeData.attributes;
334
+ if (attrs == null) return ok();
335
+ if (!isPlainObject(attrs)) return fail(`attributes must be an object`, path);
336
+
337
+ const schema: AttributeSchema = (getAttributeSchema(pattern.pattern.type) ??
338
+ pattern.pattern.attributes ??
339
+ {}) as AttributeSchema;
340
+
341
+ for (const [attrName, attrValue] of Object.entries(attrs)) {
342
+ const attrSpec = schema?.[attrName];
343
+ if (!attrSpec) {
344
+ if (pattern.allowUnknownAttributes) continue;
345
+ return fail(`Unknown attribute "${attrName}"`, joinPath(path, attrName));
346
+ }
347
+ const res = validateAttributeValue(
348
+ pattern.pattern.type,
349
+ attrValue,
350
+ attrSpec,
351
+ joinPath(path, attrName),
352
+ );
353
+ if (!res.valid) return res;
354
+ }
355
+
356
+ return ok();
357
+ }
358
+
359
+ function validateNodeDataByPatterns(
360
+ nodeData: NodeData<NodeDefaultAttribute>,
361
+ path: string,
362
+ ): AnalyseResultWithPath {
363
+ const normalizedType = normalizeTypeOrFallback(nodeData.type);
364
+ const pattern = getPatternByType(normalizedType) as unknown as
365
+ | PatternLike
366
+ | undefined;
367
+ if (!pattern) {
368
+ return fail(
369
+ `Unknown component type "${nodeData.type}"`,
370
+ joinPath(path, 'type'),
371
+ );
372
+ }
373
+
374
+ const attrRes = validateAttributesByPattern(
375
+ { ...nodeData, type: normalizedType },
376
+ pattern,
377
+ joinPath(path, 'attributes'),
378
+ );
379
+ if (!attrRes.valid) return attrRes;
380
+
381
+ const childrenRes = validateChildrenByPattern(
382
+ { ...nodeData, type: normalizedType },
383
+ pattern,
384
+ joinPath(path, 'children'),
385
+ );
386
+ if (!childrenRes.valid) return childrenRes;
387
+
388
+ return ok();
389
+ }
390
+
391
+ function validateAnyNodeByPatterns(
392
+ node: Node<NodeDefaultAttribute>,
393
+ path: string,
394
+ ): AnalyseResultWithPath {
395
+ if (
396
+ isNodeNullOrUndefined(node) ||
397
+ isNodeString(node) ||
398
+ isEmptyObject(node)
399
+ ) {
400
+ return ok();
401
+ }
402
+
403
+ if (isNodeArray(node)) {
404
+ const arr = node as unknown as Node<NodeDefaultAttribute>[];
405
+ for (let i = 0; i < arr.length; i++) {
406
+ const res = validateAnyNodeByPatterns(arr[i], `${path}[${i}]`);
407
+ if (!res.valid) return res;
408
+ }
409
+ return ok();
410
+ }
411
+
412
+ if (!isNodeDataLike(node)) {
413
+ return fail(`Invalid node shape`, path);
414
+ }
415
+
416
+ const selfRes = validateNodeDataByPatterns(node, path);
417
+ if (!selfRes.valid) return selfRes;
418
+
419
+ return validateAnyNodeByPatterns(
420
+ node.children as Node<NodeDefaultAttribute>,
421
+ joinPath(path, 'children'),
422
+ );
423
+ }
424
+
425
+ /**
426
+ * Validates a Node tree against the generated component patterns:
427
+ * - Enforces `pattern.children` including "never"
428
+ * - Validates `attributes` against `pattern.attributes` (+ custom `types`)
429
+ *
430
+ * Notes:
431
+ * - Null/undefined children are considered "no children" and are allowed even
432
+ * when patterns expect some kind of children.
433
+ */
434
+ export function analyseNodeByPatterns(
435
+ node: Node<NodeDefaultAttribute>,
436
+ ): AnalyseResultWithPath {
437
+ return validateAnyNodeByPatterns(node, 'root');
438
+ }
@@ -0,0 +1,52 @@
1
+ import type { Node, NodeData, NodeDefaultAttribute } from '../types/Node';
2
+ import {
3
+ isEmptyObject,
4
+ isNodeArray,
5
+ isNodeNullOrUndefined,
6
+ isNodeString,
7
+ } from './nodeGuards';
8
+
9
+ export type AnalyseResult = {
10
+ valid: boolean;
11
+ message?: string;
12
+ };
13
+
14
+ /**
15
+ * Structural validation only:
16
+ * - Ensures the input is a valid Node union recursively (null/string/array/object)
17
+ * - Does NOT validate against component patterns.
18
+ */
19
+ export function analyseNodeStructural(
20
+ node: Node<NodeDefaultAttribute>,
21
+ ): AnalyseResult {
22
+ if (isNodeNullOrUndefined(node)) {
23
+ return { valid: true, message: 'null or undefined is valid' };
24
+ }
25
+
26
+ if (isNodeString(node)) {
27
+ return { valid: true, message: 'string is valid' };
28
+ }
29
+
30
+ if (isNodeArray(node)) {
31
+ const nodeArray = node as unknown as Node[];
32
+ for (const value of nodeArray) {
33
+ const res = analyseNodeStructural(value as Node<NodeDefaultAttribute>);
34
+ if (!res.valid) return res;
35
+ }
36
+ return { valid: true, message: 'Array is valid' };
37
+ }
38
+
39
+ const recordData = node as NodeData;
40
+ if (isEmptyObject(recordData)) {
41
+ return { valid: true, message: 'empty object is valid' };
42
+ }
43
+
44
+ if (recordData.children) {
45
+ const res = analyseNodeStructural(
46
+ recordData.children as Node<NodeDefaultAttribute>,
47
+ );
48
+ if (!res.valid) return res;
49
+ }
50
+
51
+ return { valid: true, message: 'everything is structurally valid' };
52
+ }
@@ -26,6 +26,9 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
26
26
  value === null ||
27
27
  (typeof value === 'string' && value.trim() === '');
28
28
  if (scrollable) {
29
+ // Important for flex children: allow the element to shrink so overflow scroll can work.
30
+ style.minWidth = 0;
31
+ style.minHeight = 0;
29
32
  if (attributes.flexDirection === 'row') {
30
33
  style.overflowX = 'auto';
31
34
  style.overflowY = 'hidden';
@@ -102,7 +105,23 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
102
105
  }
103
106
  setParsedSize('borderRadius', attributes.borderRadius);
104
107
  setParsedSize('width', attributes.width);
108
+ setParsedSize(
109
+ 'minWidth',
110
+ (attributes as ViewPropsGenerated['attributes']).minWidth,
111
+ );
112
+ setParsedSize(
113
+ 'maxWidth',
114
+ (attributes as ViewPropsGenerated['attributes']).maxWidth,
115
+ );
105
116
  setParsedSize('height', attributes.height);
117
+ setParsedSize(
118
+ 'minHeight',
119
+ (attributes as ViewPropsGenerated['attributes']).minHeight,
120
+ );
121
+ setParsedSize(
122
+ 'maxHeight',
123
+ (attributes as ViewPropsGenerated['attributes']).maxHeight,
124
+ );
106
125
  if (attributes.flex !== undefined)
107
126
  style.flex = attributes.flex as React.CSSProperties['flex'];
108
127
  if (attributes.position)
@@ -0,0 +1,32 @@
1
+ import type { Node, NodeData } from '../types/Node';
2
+
3
+ export function findNodeByKeyNested(node: Node, key: string): NodeData | null {
4
+ if (node === null || node === undefined) {
5
+ return null;
6
+ }
7
+
8
+ if (typeof node === 'string') {
9
+ return null;
10
+ }
11
+
12
+ if (Array.isArray(node)) {
13
+ for (const child of node) {
14
+ const found = findNodeByKeyNested(child, key);
15
+ if (found) {
16
+ return found;
17
+ }
18
+ }
19
+ return null;
20
+ }
21
+
22
+ const recordData = node as NodeData;
23
+ if (recordData.key === key) {
24
+ return recordData;
25
+ }
26
+
27
+ if (recordData.children) {
28
+ return findNodeByKeyNested(recordData.children as Node, key);
29
+ }
30
+
31
+ return null;
32
+ }
@@ -1,28 +1,44 @@
1
1
  import { Node, NodeData } from '../types/Node';
2
+ import { normalizeComponentType } from './patterns';
2
3
 
3
4
  export const isCarouselProvider = (node: Node): node is NodeData => {
4
5
  if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
5
- return 'type' in node && node.type === 'carouselProvider';
6
+ return (
7
+ 'type' in node &&
8
+ normalizeComponentType((node as NodeData).type) === 'CarouselProvider'
9
+ );
6
10
  };
7
11
 
8
12
  export const isCarousel = (node: Node): node is NodeData => {
9
13
  if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
10
- return 'type' in node && node.type === 'carousel';
14
+ return (
15
+ 'type' in node &&
16
+ normalizeComponentType((node as NodeData).type) === 'Carousel'
17
+ );
11
18
  };
12
19
 
13
20
  export const isCarouselItem = (node: Node): node is NodeData => {
14
21
  if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
15
- return 'type' in node && node.type === 'carouselItem';
22
+ return (
23
+ 'type' in node &&
24
+ normalizeComponentType((node as NodeData).type) === 'CarouselItem'
25
+ );
16
26
  };
17
27
 
18
28
  export const isCarouselDots = (node: Node): node is NodeData => {
19
29
  if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
20
- return 'type' in node && node.type === 'carouselDots';
30
+ return (
31
+ 'type' in node &&
32
+ normalizeComponentType((node as NodeData).type) === 'CarouselDots'
33
+ );
21
34
  };
22
35
 
23
36
  export const isCarouselButtons = (node: Node): node is NodeData => {
24
37
  if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
25
- return 'type' in node && node.type === 'carouselButtons';
38
+ return (
39
+ 'type' in node &&
40
+ normalizeComponentType((node as NodeData).type) === 'CarouselButtons'
41
+ );
26
42
  };
27
43
 
28
44
  export const isCarouselComponent = (node: Node): boolean => {
@@ -0,0 +1,26 @@
1
+ import type { Node, NodeDefaultAttribute } from '../types/Node';
2
+
3
+ export function isNodeNullOrUndefined<T = NodeDefaultAttribute>(
4
+ node: Node<T>,
5
+ ): boolean {
6
+ return node === null || node === undefined;
7
+ }
8
+
9
+ export function isNodeString<T = NodeDefaultAttribute>(node: Node<T>): boolean {
10
+ return typeof node === 'string';
11
+ }
12
+
13
+ export function isNodeArray<T = NodeDefaultAttribute>(node: Node<T>): boolean {
14
+ return node instanceof Array;
15
+ }
16
+
17
+ export function isEmptyObject<T = NodeDefaultAttribute>(
18
+ node: Node<T>,
19
+ ): boolean {
20
+ return (
21
+ typeof node === 'object' &&
22
+ node !== null &&
23
+ !Array.isArray(node) &&
24
+ Object.keys(node as object).length === 0
25
+ );
26
+ }
@@ -1,9 +1,13 @@
1
1
  import { Node, NodeData } from '../types/Node';
2
2
  import { Project, ProjectBase } from '../types/Project';
3
-
3
+ //TODO: deprecated olmasına rağmen snapshot testi ekle
4
+ /**
5
+ * @deprecated Legacy converter for old "nova" onboard JSON formats.
6
+ * The built-in samples are now shipped in the new `Project<Node>` format,
7
+ * so this should no longer be needed in normal usage.
8
+ */
4
9
  export function novaToJson(nova: ProjectBase<unknown>): Node {
5
10
  const layout = (nova.data as any).data?.layout;
6
- console.info('layout', layout);
7
11
  if (layout === 'onboard-layout') {
8
12
  return onboardNovaToJson(nova);
9
13
  }
@@ -26,7 +30,6 @@ function onboardNovaToJson(nova: ProjectBase<unknown>): Node {
26
30
 
27
31
  const providerNode: NodeData = {
28
32
  type: 'OnboardProvider',
29
- isMain: true,
30
33
  key: (nova?.data as any)?.data?.key,
31
34
  children: [
32
35
  carouselNode,
@@ -37,15 +40,24 @@ function onboardNovaToJson(nova: ProjectBase<unknown>): Node {
37
40
  ],
38
41
  attributes: {
39
42
  theme: (nova?.data as any)?.theme,
40
- // forward safe area inset preference; default to true when absent
41
- use_safe_area_inset:
42
- (attributes as any)?.use_safe_area_inset !== undefined
43
- ? (attributes as any)?.use_safe_area_inset
44
- : true,
45
43
  },
46
44
  };
47
45
 
48
- return providerNode;
46
+ const mainNode: NodeData = {
47
+ type: 'Main',
48
+ isMain: true,
49
+ key: (nova?.data as any)?.data?.key,
50
+ children: [providerNode],
51
+ attributes: {
52
+ // default safe area view on; can be overridden in the editor
53
+ useSafeAreaView: true,
54
+ },
55
+ };
56
+
57
+ // Provider should have its own key if needed; avoid duplicating root key on child.
58
+ delete (providerNode as any).key;
59
+
60
+ return mainNode;
49
61
  }
50
62
  //@eslint-disable-next-line @typescript-eslint/no-explicit-any
51
63
  function buildCarouselFromPages(pages: any[]): {