@developer_tribe/react-builder 1.2.14 → 1.2.15

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 (160) hide show
  1. package/dist/build-components/BIcon/BIconProps.generated.d.ts +2 -0
  2. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +2 -0
  3. package/dist/build-components/Button/ButtonProps.generated.d.ts +2 -0
  4. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +2 -0
  5. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +2 -0
  6. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +2 -0
  7. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +2 -0
  8. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +2 -0
  9. package/dist/build-components/CountDown/CountDown.d.ts +2 -0
  10. package/dist/build-components/CountDown/CountDownProps.generated.d.ts +61 -0
  11. package/dist/build-components/CountDown/formatCountdownTime.d.ts +1 -0
  12. package/dist/build-components/Counter/Counter.d.ts +2 -0
  13. package/dist/build-components/Counter/CounterProps.generated.d.ts +61 -0
  14. package/dist/build-components/Image/ImageProps.generated.d.ts +2 -0
  15. package/dist/build-components/Main/MainProps.generated.d.ts +2 -0
  16. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +2 -0
  17. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +2 -0
  18. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +2 -0
  19. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +2 -0
  20. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +2 -0
  21. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +2 -0
  22. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +2 -0
  23. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
  24. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +2 -0
  25. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +2 -0
  26. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +2 -0
  27. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +2 -0
  28. package/dist/build-components/PaywallCounter/PaywallCounter.d.ts +2 -0
  29. package/dist/build-components/PaywallCounter/PaywallCounterProps.generated.d.ts +61 -0
  30. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +2 -0
  31. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -0
  32. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +2 -0
  33. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +2 -0
  34. package/dist/build-components/Text/TextProps.generated.d.ts +2 -0
  35. package/dist/build-components/View/ViewProps.generated.d.ts +2 -0
  36. package/dist/build-components/index.d.ts +4 -1
  37. package/dist/build-components/patterns.generated.d.ts +2961 -1552
  38. package/dist/components/BuilderProvider.d.ts +0 -1
  39. package/dist/index.cjs.js +4 -4
  40. package/dist/index.cjs.js.map +1 -1
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.esm.js +4 -4
  43. package/dist/index.esm.js.map +1 -1
  44. package/dist/index.native.d.ts +7 -0
  45. package/dist/index.web.cjs.js +7 -5
  46. package/dist/index.web.cjs.js.map +1 -1
  47. package/dist/index.web.esm.js +7 -5
  48. package/dist/index.web.esm.js.map +1 -1
  49. package/dist/utils/getDefaultProject.d.ts +4 -0
  50. package/dist/utils/patterns.d.ts +3 -0
  51. package/package.json +2 -1
  52. package/scripts/prebuild/utils/createComponentTsx.js +1 -1
  53. package/scripts/prebuild/utils/createGeneratedProps.js +6 -2
  54. package/scripts/prebuild/utils/createRenderNodeGenerated.js +26 -5
  55. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +17 -5
  56. package/scripts/prebuild/utils/validateExistingComponentTsx.js +12 -8
  57. package/src/AttributesEditor.tsx +7 -2
  58. package/src/RenderPage.tsx +34 -3
  59. package/src/assets/meta.json +1 -1
  60. package/src/assets/samples/carousel-sample.json +44 -14
  61. package/src/assets/samples/getSamples.ts +3 -1
  62. package/src/assets/samples/paywall-1.json +73 -29
  63. package/src/assets/samples/paywall-2.json +338 -0
  64. package/src/assets/samples/simple-1.json +9 -3
  65. package/src/assets/samples/simple-2.json +72 -24
  66. package/src/assets/samples/unmigrated-builder-1.1.1.json +19 -7
  67. package/src/assets/samples/unmigrated-builder1.json +10 -4
  68. package/src/assets/samples/unvalidated-builder1.json +10 -4
  69. package/src/assets/samples/unvalidated-crash1.json +3 -1
  70. package/src/assets/samples/unvalidated-crashcomponent1.json +3 -1
  71. package/src/assets/samples/vpn-onboard-1.json +88 -40
  72. package/src/assets/samples/vpn-onboard-2.json +85 -37
  73. package/src/assets/samples/vpn-onboard-3.json +93 -45
  74. package/src/assets/samples/vpn-onboard-4.json +93 -45
  75. package/src/assets/samples/vpn-onboard-5.json +121 -53
  76. package/src/assets/samples/vpn-onboard-6.json +93 -45
  77. package/src/attributes-editor/AttributesEditorView.tsx +39 -1
  78. package/src/attributes-editor/Field.tsx +30 -0
  79. package/src/build-components/BIcon/BIconProps.generated.ts +2 -0
  80. package/src/build-components/BIcon/pattern.json +2 -0
  81. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +2 -0
  82. package/src/build-components/BackgroundImage/pattern.json +2 -0
  83. package/src/build-components/Button/ButtonProps.generated.ts +2 -0
  84. package/src/build-components/Button/pattern.json +2 -0
  85. package/src/build-components/Carousel/CarouselProps.generated.ts +2 -0
  86. package/src/build-components/Carousel/pattern.json +2 -0
  87. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +2 -0
  88. package/src/build-components/CarouselButtons/pattern.json +2 -0
  89. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +2 -0
  90. package/src/build-components/CarouselDots/pattern.json +2 -0
  91. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +2 -0
  92. package/src/build-components/CarouselItem/pattern.json +4 -1
  93. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +2 -0
  94. package/src/build-components/CarouselProvider/pattern.json +4 -1
  95. package/src/build-components/CountDown/CountDown.tsx +73 -0
  96. package/src/build-components/CountDown/CountDownProps.generated.ts +78 -0
  97. package/src/build-components/CountDown/formatCountdownTime.ts +10 -0
  98. package/src/build-components/CountDown/pattern.json +24 -0
  99. package/src/build-components/Counter/Counter.tsx +44 -0
  100. package/src/build-components/Counter/CounterProps.generated.ts +78 -0
  101. package/src/build-components/Counter/pattern.json +26 -0
  102. package/src/build-components/Image/ImageProps.generated.ts +2 -0
  103. package/src/build-components/Image/pattern.json +2 -0
  104. package/src/build-components/Main/MainProps.generated.ts +2 -0
  105. package/src/build-components/Main/pattern.json +2 -0
  106. package/src/build-components/Onboard/OnboardProps.generated.ts +2 -0
  107. package/src/build-components/Onboard/pattern.json +4 -1
  108. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +2 -0
  109. package/src/build-components/OnboardButton/pattern.json +2 -0
  110. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +2 -0
  111. package/src/build-components/OnboardButtons/pattern.json +2 -0
  112. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +2 -0
  113. package/src/build-components/OnboardDot/pattern.json +2 -0
  114. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +2 -0
  115. package/src/build-components/OnboardFooter/pattern.json +2 -0
  116. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +2 -0
  117. package/src/build-components/OnboardImage/pattern.json +2 -0
  118. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +2 -0
  119. package/src/build-components/OnboardItem/pattern.json +2 -0
  120. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +2 -0
  121. package/src/build-components/OnboardProvider/pattern.json +2 -0
  122. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +2 -0
  123. package/src/build-components/OnboardSubtitle/pattern.json +4 -1
  124. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +2 -0
  125. package/src/build-components/OnboardTitle/pattern.json +4 -1
  126. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +2 -0
  127. package/src/build-components/PaywallBackground/pattern.json +4 -1
  128. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +7 -5
  129. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +2 -0
  130. package/src/build-components/PaywallCloseButton/pattern.json +4 -1
  131. package/src/build-components/PaywallCounter/PaywallCounter.tsx +49 -0
  132. package/src/build-components/PaywallCounter/PaywallCounterProps.generated.ts +78 -0
  133. package/src/build-components/PaywallCounter/pattern.json +24 -0
  134. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +2 -0
  135. package/src/build-components/PaywallOptions/pattern.json +4 -1
  136. package/src/build-components/PaywallProvider/PaywallProvider.tsx +8 -16
  137. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +2 -0
  138. package/src/build-components/PaywallProvider/pattern.json +4 -1
  139. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +2 -0
  140. package/src/build-components/PaywallSubscribeButton/pattern.json +4 -1
  141. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +2 -0
  142. package/src/build-components/RadioButton/pattern.json +2 -0
  143. package/src/build-components/RenderNode.generated.tsx +17 -2
  144. package/src/build-components/Text/TextProps.generated.ts +2 -0
  145. package/src/build-components/Text/pattern.json +3 -1
  146. package/src/build-components/View/View.tsx +1 -1
  147. package/src/build-components/View/ViewProps.generated.ts +2 -0
  148. package/src/build-components/View/pattern.json +35 -38
  149. package/src/build-components/index.ts +15 -0
  150. package/src/build-components/patterns.generated.ts +3084 -1570
  151. package/src/components/BuilderButton.tsx +23 -6
  152. package/src/components/BuilderProvider.tsx +10 -7
  153. package/src/index.native.ts +7 -0
  154. package/src/index.ts +1 -0
  155. package/src/mockOS/context/MockOSContext.tsx +22 -8
  156. package/src/mockOS/managers/navigationManager.ts +4 -0
  157. package/src/pages/projectPageUtils.ts +3 -2
  158. package/src/utils/analyseNodeByPatterns.ts +21 -0
  159. package/src/utils/getDefaultProject.ts +34 -0
  160. package/src/utils/patterns.ts +6 -7
@@ -45,32 +45,32 @@
45
45
  "view.onboarding.btnTerms": "Terms"
46
46
  },
47
47
  "ar": {
48
- "onboard.title.one-page": " العربية",
49
- "onboard.title.one-page2": " العربية",
50
- "onboard.title.two-page": " العربية",
51
- "onboard.title.two-page2": " العربية",
52
- "onboard.title.three-page": " العربية",
53
- "onboard.title.three-page2": " العربية",
54
- "onboard.title.four-page": " العربية",
55
- "onboard.title.four-page2": " العربية",
56
- "onboard.subtitle.one-page": " العربية",
57
- "onboard.subtitle.one-page2": " العربية",
58
- "onboard.subtitle.two-page": " العربية",
59
- "onboard.subtitle.two-page2": " العربية",
60
- "onboard.subtitle.three-page": " العربية",
61
- "onboard.subtitle.three-page2": " العربية",
62
- "onboard.subtitle.four-page": " العربية",
63
- "onboard.subtitle.four-page2": " العربية",
64
- "onboard.next.one-page": "التالي",
65
- "onboard.next.two-page": "التالي",
66
- "onboard.next.three-page": "التالي",
67
- "onboard.skip.one-page": "تخطي",
68
- "onboard.skip.two-page": "تخطي",
69
- "onboard.skip.three-page": "تخطي",
70
- "onboard.allow.four-page": "السماح",
71
- "view.onboarding.footer.description": "بالمتابعة فإنك توافق على",
72
- "view.onboarding.btnPrivacy": "الخصوصية",
73
- "view.onboarding.btnTerms": "الشروط"
48
+ "onboard.title.one-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
49
+ "onboard.title.one-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
50
+ "onboard.title.two-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
51
+ "onboard.title.two-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
52
+ "onboard.title.three-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
53
+ "onboard.title.three-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
54
+ "onboard.title.four-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
55
+ "onboard.title.four-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
56
+ "onboard.subtitle.one-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
57
+ "onboard.subtitle.one-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
58
+ "onboard.subtitle.two-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
59
+ "onboard.subtitle.two-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
60
+ "onboard.subtitle.three-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
61
+ "onboard.subtitle.three-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
62
+ "onboard.subtitle.four-page": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
63
+ "onboard.subtitle.four-page2": " \u0627\u0644\u0639\u0631\u0628\u064a\u0629",
64
+ "onboard.next.one-page": "\u0627\u0644\u062a\u0627\u0644\u064a",
65
+ "onboard.next.two-page": "\u0627\u0644\u062a\u0627\u0644\u064a",
66
+ "onboard.next.three-page": "\u0627\u0644\u062a\u0627\u0644\u064a",
67
+ "onboard.skip.one-page": "\u062a\u062e\u0637\u064a",
68
+ "onboard.skip.two-page": "\u062a\u062e\u0637\u064a",
69
+ "onboard.skip.three-page": "\u062a\u062e\u0637\u064a",
70
+ "onboard.allow.four-page": "\u0627\u0644\u0633\u0645\u0627\u062d",
71
+ "view.onboarding.footer.description": "\u0628\u0627\u0644\u0645\u062a\u0627\u0628\u0639\u0629 \u0641\u0625\u0646\u0643 \u062a\u0648\u0627\u0641\u0642 \u0639\u0644\u0649",
72
+ "view.onboarding.btnPrivacy": "\u0627\u0644\u062e\u0635\u0648\u0635\u064a\u0629",
73
+ "view.onboarding.btnTerms": "\u0627\u0644\u0634\u0631\u0648\u0637"
74
74
  }
75
75
  },
76
76
  "defaultLanguage": "en"
@@ -80,7 +80,9 @@
80
80
  "isMain": true,
81
81
  "key": "cJVVSS7q9Qe1trnb",
82
82
  "attributes": {
83
- "useSafeAreaView": true
83
+ "useSafeAreaView": true,
84
+ "description": "Ekran\u0131n ana kapsay\u0131c\u0131s\u0131. (#1)",
85
+ "title": "Main 1"
84
86
  },
85
87
  "children": [
86
88
  {
@@ -108,7 +110,9 @@
108
110
  "attributes": {
109
111
  "style": {
110
112
  "color": "#F4F5FF"
111
- }
113
+ },
114
+ "description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#1)",
115
+ "title": "OnboardTitle 1"
112
116
  },
113
117
  "children": "onboard.title.one-page"
114
118
  },
@@ -117,11 +121,17 @@
117
121
  "attributes": {
118
122
  "style": {
119
123
  "color": "#DBDDEB"
120
- }
124
+ },
125
+ "description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#1)",
126
+ "title": "OnboardSubtitle 1"
121
127
  },
122
128
  "children": "onboard.subtitle.one-page"
123
129
  }
124
- ]
130
+ ],
131
+ "attributes": {
132
+ "description": "Onboarding sayfas\u0131. (#1)",
133
+ "title": "OnboardItem 1"
134
+ }
125
135
  },
126
136
  {
127
137
  "type": "OnboardItem",
@@ -142,7 +152,9 @@
142
152
  "attributes": {
143
153
  "style": {
144
154
  "color": "#F4F5FF"
145
- }
155
+ },
156
+ "description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#2)",
157
+ "title": "OnboardTitle 2"
146
158
  },
147
159
  "children": "onboard.title.two-page"
148
160
  },
@@ -151,11 +163,17 @@
151
163
  "attributes": {
152
164
  "style": {
153
165
  "color": "#DBDDEB"
154
- }
166
+ },
167
+ "description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#2)",
168
+ "title": "OnboardSubtitle 2"
155
169
  },
156
170
  "children": "onboard.subtitle.two-page"
157
171
  }
158
- ]
172
+ ],
173
+ "attributes": {
174
+ "description": "Onboarding sayfas\u0131. (#2)",
175
+ "title": "OnboardItem 2"
176
+ }
159
177
  },
160
178
  {
161
179
  "type": "OnboardItem",
@@ -176,7 +194,9 @@
176
194
  "attributes": {
177
195
  "style": {
178
196
  "color": "#F4F5FF"
179
- }
197
+ },
198
+ "description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#3)",
199
+ "title": "OnboardTitle 3"
180
200
  },
181
201
  "children": "onboard.title.three-page"
182
202
  },
@@ -185,11 +205,17 @@
185
205
  "attributes": {
186
206
  "style": {
187
207
  "color": "#DBDDEB"
188
- }
208
+ },
209
+ "description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#3)",
210
+ "title": "OnboardSubtitle 3"
189
211
  },
190
212
  "children": "onboard.subtitle.three-page"
191
213
  }
192
- ]
214
+ ],
215
+ "attributes": {
216
+ "description": "Onboarding sayfas\u0131. (#3)",
217
+ "title": "OnboardItem 3"
218
+ }
193
219
  },
194
220
  {
195
221
  "type": "OnboardItem",
@@ -210,7 +236,9 @@
210
236
  "attributes": {
211
237
  "style": {
212
238
  "color": "#F4F5FF"
213
- }
239
+ },
240
+ "description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#4)",
241
+ "title": "OnboardTitle 4"
214
242
  },
215
243
  "children": "onboard.title.four-page"
216
244
  },
@@ -219,13 +247,23 @@
219
247
  "attributes": {
220
248
  "style": {
221
249
  "color": "#DBDDEB"
222
- }
250
+ },
251
+ "description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#4)",
252
+ "title": "OnboardSubtitle 4"
223
253
  },
224
254
  "children": "onboard.subtitle.four-page"
225
255
  }
226
- ]
256
+ ],
257
+ "attributes": {
258
+ "description": "Onboarding sayfas\u0131. (#4)",
259
+ "title": "OnboardItem 4"
260
+ }
227
261
  }
228
- ]
262
+ ],
263
+ "attributes": {
264
+ "description": "Onboarding ana yap\u0131s\u0131. (#1)",
265
+ "title": "Onboard 1"
266
+ }
229
267
  },
230
268
  {
231
269
  "type": "OnboardDot",
@@ -239,7 +277,9 @@
239
277
  "attributes": {
240
278
  "buttons_direction": "row",
241
279
  "condition": "carousel-index",
242
- "conditionVariable": 0
280
+ "conditionVariable": 0,
281
+ "description": "Sayfa buton grubu. (#1)",
282
+ "title": "OnboardButtons 1"
243
283
  },
244
284
  "children": [
245
285
  {
@@ -285,7 +325,9 @@
285
325
  "attributes": {
286
326
  "buttons_direction": "row",
287
327
  "condition": "carousel-index",
288
- "conditionVariable": 1
328
+ "conditionVariable": 1,
329
+ "description": "Sayfa buton grubu. (#2)",
330
+ "title": "OnboardButtons 2"
289
331
  },
290
332
  "children": [
291
333
  {
@@ -331,7 +373,9 @@
331
373
  "attributes": {
332
374
  "buttons_direction": "row",
333
375
  "condition": "carousel-index",
334
- "conditionVariable": 2
376
+ "conditionVariable": 2,
377
+ "description": "Sayfa buton grubu. (#3)",
378
+ "title": "OnboardButtons 3"
335
379
  },
336
380
  "children": [
337
381
  {
@@ -381,7 +425,9 @@
381
425
  "attributes": {
382
426
  "buttons_direction": "row",
383
427
  "condition": "carousel-index",
384
- "conditionVariable": 3
428
+ "conditionVariable": 3,
429
+ "description": "Sayfa buton grubu. (#4)",
430
+ "title": "OnboardButtons 4"
385
431
  },
386
432
  "children": [
387
433
  {
@@ -425,7 +471,9 @@
425
471
  }
426
472
  ],
427
473
  "attributes": {
428
- "theme": "dark"
474
+ "theme": "dark",
475
+ "description": "Onboarding sa\u011flay\u0131c\u0131s\u0131. (#1)",
476
+ "title": "OnboardProvider 1"
429
477
  }
430
478
  }
431
479
  ]
@@ -92,6 +92,42 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
92
92
  </div>
93
93
  );
94
94
 
95
+ const titleValue = getAttributeValue('title');
96
+ const descriptionValue = getAttributeValue('description');
97
+ const topFieldsSection = !isInvalidNode ? (
98
+ <section className="attributes-editor__top-fields">
99
+ <div className="attributes-editor__field-wrapper">
100
+ <label className="attributes-editor__field-label" htmlFor="title">
101
+ Title (max 20 characters for display purposes)
102
+ </label>
103
+ <input
104
+ id="title"
105
+ className="input"
106
+ type="text"
107
+ maxLength={20}
108
+ value={typeof titleValue === 'string' ? titleValue : ''}
109
+ onChange={(event) =>
110
+ handleAttributeChange('title', event.target.value)
111
+ }
112
+ />
113
+ </div>
114
+ <div className="attributes-editor__field-wrapper">
115
+ <label className="attributes-editor__field-label" htmlFor="description">
116
+ Description (for display purposes)
117
+ </label>
118
+ <input
119
+ id="description"
120
+ className="input"
121
+ type="text"
122
+ value={typeof descriptionValue === 'string' ? descriptionValue : ''}
123
+ onChange={(event) =>
124
+ handleAttributeChange('description', event.target.value)
125
+ }
126
+ />
127
+ </div>
128
+ </section>
129
+ ) : null;
130
+
95
131
  const mockableSection =
96
132
  mockableFeatureKeys.length > 0 ? (
97
133
  <section className="attributes-editor__mockable">
@@ -173,7 +209,8 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
173
209
  const label = attributeMeta?.[name]?.label ?? name;
174
210
  const description = attributeMeta?.[name]?.description;
175
211
  const preferredScale = toPreferredScale(
176
- attributeMeta?.[name]?.preferedScale,
212
+ attributeMeta?.[name]?.preferredScale ??
213
+ attributeMeta?.[name]?.preferedScale,
177
214
  );
178
215
  const isBoolean = isBooleanFieldType(type);
179
216
  const wrapperClassNames = [
@@ -336,6 +373,7 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
336
373
  return (
337
374
  <div className="attributes-editor">
338
375
  {headerSection}
376
+ {topFieldsSection}
339
377
  {mockableSection}
340
378
  {tabsSection}
341
379
  {childrenSection}
@@ -116,6 +116,7 @@ export function Field({
116
116
  />
117
117
  );
118
118
  case 'string':
119
+ case 'description':
119
120
  return (
120
121
  <input
121
122
  type="text"
@@ -130,6 +131,22 @@ export function Field({
130
131
  style={{ flex: 1 }}
131
132
  />
132
133
  );
134
+ case 'title':
135
+ return (
136
+ <input
137
+ type="text"
138
+ value={itemValue ?? ''}
139
+ maxLength={20}
140
+ onChange={(e) => {
141
+ const next = [...arr];
142
+ next[idx] =
143
+ e.target.value === '' ? undefined : e.target.value;
144
+ onChange(next);
145
+ }}
146
+ className="input"
147
+ style={{ flex: 1 }}
148
+ />
149
+ );
133
150
  case 'color':
134
151
  return (
135
152
  <ColorPickerButton
@@ -479,10 +496,23 @@ export function Field({
479
496
  />
480
497
  );
481
498
  case 'string':
499
+ case 'description':
500
+ return (
501
+ <input
502
+ type="text"
503
+ value={value ?? ''}
504
+ onChange={(e) =>
505
+ onChange(e.target.value === '' ? undefined : e.target.value)
506
+ }
507
+ className="input"
508
+ />
509
+ );
510
+ case 'title':
482
511
  return (
483
512
  <input
484
513
  type="text"
485
514
  value={value ?? ''}
515
+ maxLength={20}
486
516
  onChange={(e) =>
487
517
  onChange(e.target.value === '' ? undefined : e.target.value)
488
518
  }
@@ -64,6 +64,8 @@ export interface BIconPropsGenerated {
64
64
  child: string;
65
65
  attributes: {
66
66
  style?: BIconStyleGenerated;
67
+ title?: string;
68
+ description?: string;
67
69
  adjustsFontSizeToFit?: boolean;
68
70
  showEllipsis?: boolean;
69
71
  scrollable?: boolean;
@@ -5,6 +5,8 @@
5
5
  "children": "never",
6
6
  "extends": "Text",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "iconType": "iconType",
9
11
  "size": "number",
10
12
  "strokeWidth": "number"
@@ -59,6 +59,8 @@ export interface BackgroundImagePropsGenerated {
59
59
  child: string;
60
60
  attributes: {
61
61
  style?: BackgroundImageStyleGenerated;
62
+ title?: string;
63
+ description?: string;
62
64
  scrollable?: boolean;
63
65
  src?: string;
64
66
  resizeMode?: ResizeModeOptionType;
@@ -5,6 +5,8 @@
5
5
  "children": "never",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "src": "string",
9
11
  "resizeMode": ["cover", "contain", "stretch", "center"]
10
12
  },
@@ -73,6 +73,8 @@ export interface ButtonPropsGenerated {
73
73
  child: string;
74
74
  attributes: {
75
75
  style?: ButtonStyleGenerated;
76
+ title?: string;
77
+ description?: string;
76
78
  scrollable?: boolean;
77
79
  };
78
80
  }
@@ -5,6 +5,8 @@
5
5
  "children": "string",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "style": {
9
11
  "color": "color",
10
12
  "fontSize": "size",
@@ -59,6 +59,8 @@ export interface CarouselPropsGenerated {
59
59
  child: string;
60
60
  attributes: {
61
61
  style?: CarouselStyleGenerated;
62
+ title?: string;
63
+ description?: string;
62
64
  scrollable?: boolean;
63
65
  loop?: boolean;
64
66
  dragFree?: boolean;
@@ -5,6 +5,8 @@
5
5
  "type": "Carousel",
6
6
  "children": "node",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "loop": "boolean",
9
11
  "dragFree": "boolean",
10
12
  "align": [
@@ -62,6 +62,8 @@ export interface CarouselButtonsPropsGenerated {
62
62
  child: string;
63
63
  attributes: {
64
64
  style?: CarouselButtonsStyleGenerated;
65
+ title?: string;
66
+ description?: string;
65
67
  scrollable?: boolean;
66
68
  buttonType?: ButtonTypeOptionType;
67
69
  skipNumber?: number;
@@ -5,6 +5,8 @@
5
5
  "children": "never",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "buttonType": [
9
11
  "previous_button",
10
12
  "next_button",
@@ -65,6 +65,8 @@ export interface CarouselDotsPropsGenerated {
65
65
  child: string;
66
66
  attributes: {
67
67
  style?: CarouselDotsStyleGenerated;
68
+ title?: string;
69
+ description?: string;
68
70
  scrollable?: boolean;
69
71
  dotType?: DotTypeOptionType;
70
72
  };
@@ -5,6 +5,8 @@
5
5
  "children": "never",
6
6
  "extends": "View",
7
7
  "attributes": {
8
+ "title": "title",
9
+ "description": "description",
8
10
  "dotType": [
9
11
  "expanding_dot",
10
12
  "normal_dot",
@@ -58,6 +58,8 @@ export interface CarouselItemPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: CarouselItemStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
62
64
  };
63
65
  }
@@ -4,7 +4,10 @@
4
4
  "type": "CarouselItem",
5
5
  "children": "node",
6
6
  "extends": "View",
7
- "attributes": {}
7
+ "attributes": {
8
+ "title": "title",
9
+ "description": "description"
10
+ }
8
11
  },
9
12
  "meta": {
10
13
  "desiredParent": [
@@ -58,6 +58,8 @@ export interface CarouselProviderPropsGenerated {
58
58
  child: string;
59
59
  attributes: {
60
60
  style?: CarouselProviderStyleGenerated;
61
+ title?: string;
62
+ description?: string;
61
63
  scrollable?: boolean;
62
64
  };
63
65
  }
@@ -5,7 +5,10 @@
5
5
  "type": "CarouselProvider",
6
6
  "children": "node",
7
7
  "extends": "View",
8
- "attributes": {}
8
+ "attributes": {
9
+ "title": "title",
10
+ "description": "description"
11
+ }
9
12
  },
10
13
  "meta": {
11
14
  "desiredParent": ["root", ">View"],
@@ -0,0 +1,73 @@
1
+ import React, { useEffect, useId, useState } from 'react';
2
+ import type { CountDownComponentProps } from './CountDownProps.generated';
3
+ import useNode from '../useNode';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
+ import { useExtractTextStyle } from '../../attribute-analyser/style/web/useExtractTextStyle';
6
+ import { useLogRender } from '../../utils/useLogRender';
7
+ import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
+ import { useMergedStyle } from '../../utils/useMergedStyle';
9
+ import { formatCountdownTime } from './formatCountdownTime';
10
+
11
+ const DEFAULT_FORMAT = 'm : s';
12
+
13
+ //Optimzation trade off by readability: skip React.memo to keep named exports.
14
+ export function CountDown({ node }: CountDownComponentProps) {
15
+ useLogRender('CountDown');
16
+ node = useNode(node);
17
+
18
+ const generatedId = useId();
19
+ const attributeName = node.sourceType ?? node.type ?? 'CountDown';
20
+ const attributeKey = node.key ?? generatedId;
21
+
22
+ const { previewMode, selectedKey } = useBuilderParams();
23
+ const baseStyle = useExtractTextStyle(node);
24
+ const isSelected = isNodeSelected({
25
+ previewMode: !!previewMode,
26
+ current: selectedKey ? { key: selectedKey } : undefined,
27
+ node,
28
+ });
29
+ const style = useMergedStyle(
30
+ baseStyle,
31
+ isSelected ? SELECTED_OUTLINE_STYLE : undefined,
32
+ );
33
+
34
+ const rawCount = node.attributes?.count;
35
+ const delayMs =
36
+ typeof rawCount === 'number' && Number.isFinite(rawCount)
37
+ ? Math.max(0, rawCount)
38
+ : 0;
39
+
40
+ const [time, setTime] = useState<string>('');
41
+
42
+ useEffect(() => {
43
+ const targetTimeMs = Date.now() + delayMs;
44
+ setTime(formatCountdownTime(targetTimeMs, DEFAULT_FORMAT));
45
+
46
+ if (delayMs <= 0) {
47
+ return;
48
+ }
49
+
50
+ const intervalId = setInterval(() => {
51
+ const nowMs = Date.now();
52
+ const diffMs = targetTimeMs - nowMs;
53
+ setTime(formatCountdownTime(targetTimeMs, DEFAULT_FORMAT, nowMs));
54
+ if (diffMs <= 0) {
55
+ clearInterval(intervalId);
56
+ }
57
+ }, 950); // Keep slightly under 1s to reduce visible drift.
58
+
59
+ return () => {
60
+ clearInterval(intervalId);
61
+ };
62
+ }, [delayMs]);
63
+
64
+ return (
65
+ <p
66
+ attribute-name={attributeName}
67
+ attribute-key={attributeKey}
68
+ style={style}
69
+ >
70
+ {time}
71
+ </p>
72
+ );
73
+ }