@developer_tribe/react-builder 1.2.18 → 1.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +2 -1
- package/dist/build-components/patterns.generated.d.ts +23 -8
- package/dist/index.cjs.js +3 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +4 -4
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +3 -3
- package/dist/index.web.esm.js.map +1 -1
- package/dist/pages/ProjectDebug.d.ts +9 -1
- package/dist/pages/ProjectMigrationPage.d.ts +3 -1
- package/dist/pages/ProjectValidationPage.d.ts +3 -2
- package/dist/styles.css +1 -1
- package/dist/utils/applyJsonTransform.d.ts +13 -0
- package/dist/utils/repairNodeKeys.d.ts +11 -0
- package/dist/utils/safeJsonStringify.d.ts +1 -0
- package/dist/utils/wrapNodeInMain.d.ts +2 -0
- package/package.json +1 -1
- package/src/RenderPage.tsx +17 -46
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/carousel-sample.json +51 -51
- package/src/assets/samples/paywall-1.json +77 -77
- package/src/assets/samples/paywall-2.json +76 -76
- package/src/assets/samples/simple-1.json +13 -13
- package/src/assets/samples/simple-2.json +97 -97
- package/src/assets/samples/unmigrated-builder-1.1.1.json +25 -25
- package/src/assets/samples/unmigrated-builder1.json +1 -1
- package/src/assets/samples/unvalidated-builder1.json +15 -15
- package/src/assets/samples/unvalidated-crash1.json +4 -4
- package/src/assets/samples/vpn-onboard-1.json +100 -78
- package/src/assets/samples/vpn-onboard-2.json +97 -75
- package/src/assets/samples/vpn-onboard-3.json +103 -79
- package/src/assets/samples/vpn-onboard-4.json +103 -79
- package/src/assets/samples/vpn-onboard-5.json +139 -108
- package/src/assets/samples/vpn-onboard-6.json +100 -81
- package/src/build-components/CarouselDots/CarouselDots.tsx +112 -12
- package/src/build-components/OnboardDot/OnboardDot.tsx +74 -40
- package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +2 -1
- package/src/build-components/OnboardDot/pattern.json +28 -10
- package/src/build-components/PaywallProvider/PaywallProvider.tsx +2 -3
- package/src/build-components/Text/Text.tsx +4 -9
- package/src/build-components/patterns.generated.ts +23 -8
- package/src/build-components/useNode.ts +20 -4
- package/src/components/AttributesEditorPanel.tsx +13 -1
- package/src/components/Builder.tsx +19 -5
- package/src/components/EditorHeader.tsx +16 -6
- package/src/components/JsonTextEditor.tsx +41 -0
- package/src/pages/DebugJsonPage.tsx +104 -4
- package/src/pages/ProjectDebug.tsx +66 -28
- package/src/pages/ProjectMigrationPage.tsx +15 -0
- package/src/pages/ProjectPage.tsx +160 -23
- package/src/pages/ProjectValidationPage.tsx +64 -1
- package/src/styles/layout/_project-validation.scss +29 -0
- package/src/styles/utilities/_carousel.scss +0 -32
- package/src/utils/__special_exceptions.ts +9 -3
- package/src/utils/analyseNodeByPatterns.ts +16 -6
- package/src/utils/applyJsonTransform.ts +19 -0
- package/src/utils/novaToJson.ts +7 -3
- package/src/utils/repairNodeKeys.ts +90 -0
- package/src/utils/safeJsonStringify.ts +18 -0
- package/src/utils/wrapNodeInMain.ts +67 -0
|
@@ -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": " العربية",
|
|
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": "الشروط"
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
"defaultLanguage": "en"
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"key": "cJVVSS7q9Qe1trnb",
|
|
82
82
|
"attributes": {
|
|
83
83
|
"useSafeAreaView": true,
|
|
84
|
-
"description": "
|
|
84
|
+
"description": "Ekranın ana kapsayıcısı. (#1)",
|
|
85
85
|
"title": "Main 1"
|
|
86
86
|
},
|
|
87
87
|
"children": [
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"attributes": {
|
|
101
101
|
"src": "https://vpn111-stage.s3.eu-central-1.amazonaws.com/onboard/high/9cb1d668b3724655f93a91e5eee771c5.png",
|
|
102
102
|
"resizeMode": "contain",
|
|
103
|
-
"
|
|
103
|
+
"styles": {
|
|
104
104
|
"height": 400
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -108,28 +108,28 @@
|
|
|
108
108
|
{
|
|
109
109
|
"type": "OnboardTitle",
|
|
110
110
|
"attributes": {
|
|
111
|
-
"
|
|
111
|
+
"description": "Sayfa başlığı. (#1)",
|
|
112
|
+
"title": "OnboardTitle 1",
|
|
113
|
+
"styles": {
|
|
112
114
|
"color": "#F4F5FF"
|
|
113
|
-
}
|
|
114
|
-
"description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#1)",
|
|
115
|
-
"title": "OnboardTitle 1"
|
|
115
|
+
}
|
|
116
116
|
},
|
|
117
117
|
"children": "onboard.title.one-page"
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
"type": "OnboardSubtitle",
|
|
121
121
|
"attributes": {
|
|
122
|
-
"
|
|
122
|
+
"description": "Sayfa alt başlığı. (#1)",
|
|
123
|
+
"title": "OnboardSubtitle 1",
|
|
124
|
+
"styles": {
|
|
123
125
|
"color": "#DBDDEB"
|
|
124
|
-
}
|
|
125
|
-
"description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#1)",
|
|
126
|
-
"title": "OnboardSubtitle 1"
|
|
126
|
+
}
|
|
127
127
|
},
|
|
128
128
|
"children": "onboard.subtitle.one-page"
|
|
129
129
|
}
|
|
130
130
|
],
|
|
131
131
|
"attributes": {
|
|
132
|
-
"description": "Onboarding sayfas
|
|
132
|
+
"description": "Onboarding sayfası. (#1)",
|
|
133
133
|
"title": "OnboardItem 1"
|
|
134
134
|
}
|
|
135
135
|
},
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"attributes": {
|
|
143
143
|
"src": "https://vpn111-stage.s3.eu-central-1.amazonaws.com/onboard/high/f8d0c64bf89cc5f2f14126d0544ba174.png",
|
|
144
144
|
"resizeMode": "contain",
|
|
145
|
-
"
|
|
145
|
+
"styles": {
|
|
146
146
|
"height": 400
|
|
147
147
|
}
|
|
148
148
|
}
|
|
@@ -150,28 +150,28 @@
|
|
|
150
150
|
{
|
|
151
151
|
"type": "OnboardTitle",
|
|
152
152
|
"attributes": {
|
|
153
|
-
"
|
|
153
|
+
"description": "Sayfa başlığı. (#2)",
|
|
154
|
+
"title": "OnboardTitle 2",
|
|
155
|
+
"styles": {
|
|
154
156
|
"color": "#F4F5FF"
|
|
155
|
-
}
|
|
156
|
-
"description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#2)",
|
|
157
|
-
"title": "OnboardTitle 2"
|
|
157
|
+
}
|
|
158
158
|
},
|
|
159
159
|
"children": "onboard.title.two-page"
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
"type": "OnboardSubtitle",
|
|
163
163
|
"attributes": {
|
|
164
|
-
"
|
|
164
|
+
"description": "Sayfa alt başlığı. (#2)",
|
|
165
|
+
"title": "OnboardSubtitle 2",
|
|
166
|
+
"styles": {
|
|
165
167
|
"color": "#DBDDEB"
|
|
166
|
-
}
|
|
167
|
-
"description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#2)",
|
|
168
|
-
"title": "OnboardSubtitle 2"
|
|
168
|
+
}
|
|
169
169
|
},
|
|
170
170
|
"children": "onboard.subtitle.two-page"
|
|
171
171
|
}
|
|
172
172
|
],
|
|
173
173
|
"attributes": {
|
|
174
|
-
"description": "Onboarding sayfas
|
|
174
|
+
"description": "Onboarding sayfası. (#2)",
|
|
175
175
|
"title": "OnboardItem 2"
|
|
176
176
|
}
|
|
177
177
|
},
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"attributes": {
|
|
185
185
|
"src": "https://vpn111-stage.s3.eu-central-1.amazonaws.com/onboard/high/ad823809885c1a2a8e4632039f35a94e.png",
|
|
186
186
|
"resizeMode": "contain",
|
|
187
|
-
"
|
|
187
|
+
"styles": {
|
|
188
188
|
"height": 400
|
|
189
189
|
}
|
|
190
190
|
}
|
|
@@ -192,28 +192,28 @@
|
|
|
192
192
|
{
|
|
193
193
|
"type": "OnboardTitle",
|
|
194
194
|
"attributes": {
|
|
195
|
-
"
|
|
195
|
+
"description": "Sayfa başlığı. (#3)",
|
|
196
|
+
"title": "OnboardTitle 3",
|
|
197
|
+
"styles": {
|
|
196
198
|
"color": "#F4F5FF"
|
|
197
|
-
}
|
|
198
|
-
"description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#3)",
|
|
199
|
-
"title": "OnboardTitle 3"
|
|
199
|
+
}
|
|
200
200
|
},
|
|
201
201
|
"children": "onboard.title.three-page"
|
|
202
202
|
},
|
|
203
203
|
{
|
|
204
204
|
"type": "OnboardSubtitle",
|
|
205
205
|
"attributes": {
|
|
206
|
-
"
|
|
206
|
+
"description": "Sayfa alt başlığı. (#3)",
|
|
207
|
+
"title": "OnboardSubtitle 3",
|
|
208
|
+
"styles": {
|
|
207
209
|
"color": "#DBDDEB"
|
|
208
|
-
}
|
|
209
|
-
"description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#3)",
|
|
210
|
-
"title": "OnboardSubtitle 3"
|
|
210
|
+
}
|
|
211
211
|
},
|
|
212
212
|
"children": "onboard.subtitle.three-page"
|
|
213
213
|
}
|
|
214
214
|
],
|
|
215
215
|
"attributes": {
|
|
216
|
-
"description": "Onboarding sayfas
|
|
216
|
+
"description": "Onboarding sayfası. (#3)",
|
|
217
217
|
"title": "OnboardItem 3"
|
|
218
218
|
}
|
|
219
219
|
},
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
"attributes": {
|
|
227
227
|
"src": "https://vpn111-stage.s3.eu-central-1.amazonaws.com/onboard/high/ede1705c51f3434ae9053ed5f29bf5dd.png",
|
|
228
228
|
"resizeMode": "contain",
|
|
229
|
-
"
|
|
229
|
+
"styles": {
|
|
230
230
|
"height": 400
|
|
231
231
|
}
|
|
232
232
|
}
|
|
@@ -234,34 +234,34 @@
|
|
|
234
234
|
{
|
|
235
235
|
"type": "OnboardTitle",
|
|
236
236
|
"attributes": {
|
|
237
|
-
"
|
|
237
|
+
"description": "Sayfa başlığı. (#4)",
|
|
238
|
+
"title": "OnboardTitle 4",
|
|
239
|
+
"styles": {
|
|
238
240
|
"color": "#F4F5FF"
|
|
239
|
-
}
|
|
240
|
-
"description": "Sayfa ba\u015fl\u0131\u011f\u0131. (#4)",
|
|
241
|
-
"title": "OnboardTitle 4"
|
|
241
|
+
}
|
|
242
242
|
},
|
|
243
243
|
"children": "onboard.title.four-page"
|
|
244
244
|
},
|
|
245
245
|
{
|
|
246
246
|
"type": "OnboardSubtitle",
|
|
247
247
|
"attributes": {
|
|
248
|
-
"
|
|
248
|
+
"description": "Sayfa alt başlığı. (#4)",
|
|
249
|
+
"title": "OnboardSubtitle 4",
|
|
250
|
+
"styles": {
|
|
249
251
|
"color": "#DBDDEB"
|
|
250
|
-
}
|
|
251
|
-
"description": "Sayfa alt ba\u015fl\u0131\u011f\u0131. (#4)",
|
|
252
|
-
"title": "OnboardSubtitle 4"
|
|
252
|
+
}
|
|
253
253
|
},
|
|
254
254
|
"children": "onboard.subtitle.four-page"
|
|
255
255
|
}
|
|
256
256
|
],
|
|
257
257
|
"attributes": {
|
|
258
|
-
"description": "Onboarding sayfas
|
|
258
|
+
"description": "Onboarding sayfası. (#4)",
|
|
259
259
|
"title": "OnboardItem 4"
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
],
|
|
263
263
|
"attributes": {
|
|
264
|
-
"description": "Onboarding ana
|
|
264
|
+
"description": "Onboarding ana yapısı. (#1)",
|
|
265
265
|
"title": "Onboard 1"
|
|
266
266
|
}
|
|
267
267
|
},
|
|
@@ -269,7 +269,13 @@
|
|
|
269
269
|
"type": "OnboardDot",
|
|
270
270
|
"attributes": {
|
|
271
271
|
"dotType": "expanding_dot",
|
|
272
|
-
"
|
|
272
|
+
"dot_thickness": 20,
|
|
273
|
+
"inactive_dot_opacity": 0.3,
|
|
274
|
+
"inactive_dot_color": "#E4E5E7",
|
|
275
|
+
"active_dot_color": "#007AFF",
|
|
276
|
+
"styles": {
|
|
277
|
+
"flex": 2
|
|
278
|
+
}
|
|
273
279
|
}
|
|
274
280
|
},
|
|
275
281
|
{
|
|
@@ -279,7 +285,11 @@
|
|
|
279
285
|
"condition": "carousel-index",
|
|
280
286
|
"conditionVariable": 0,
|
|
281
287
|
"description": "Sayfa buton grubu. (#1)",
|
|
282
|
-
"title": "OnboardButtons 1"
|
|
288
|
+
"title": "OnboardButtons 1",
|
|
289
|
+
"styles": {
|
|
290
|
+
"flex": 2,
|
|
291
|
+
"justifyContent": "flex-end"
|
|
292
|
+
}
|
|
283
293
|
},
|
|
284
294
|
"children": [
|
|
285
295
|
{
|
|
@@ -295,7 +305,7 @@
|
|
|
295
305
|
"targetIndex": 3
|
|
296
306
|
}
|
|
297
307
|
],
|
|
298
|
-
"
|
|
308
|
+
"styles": {
|
|
299
309
|
"flex": 1
|
|
300
310
|
}
|
|
301
311
|
}
|
|
@@ -313,7 +323,7 @@
|
|
|
313
323
|
"targetIndex": 1
|
|
314
324
|
}
|
|
315
325
|
],
|
|
316
|
-
"
|
|
326
|
+
"styles": {
|
|
317
327
|
"flex": 1
|
|
318
328
|
}
|
|
319
329
|
}
|
|
@@ -327,7 +337,11 @@
|
|
|
327
337
|
"condition": "carousel-index",
|
|
328
338
|
"conditionVariable": 1,
|
|
329
339
|
"description": "Sayfa buton grubu. (#2)",
|
|
330
|
-
"title": "OnboardButtons 2"
|
|
340
|
+
"title": "OnboardButtons 2",
|
|
341
|
+
"styles": {
|
|
342
|
+
"flex": 2,
|
|
343
|
+
"justifyContent": "flex-end"
|
|
344
|
+
}
|
|
331
345
|
},
|
|
332
346
|
"children": [
|
|
333
347
|
{
|
|
@@ -343,7 +357,7 @@
|
|
|
343
357
|
"targetIndex": 3
|
|
344
358
|
}
|
|
345
359
|
],
|
|
346
|
-
"
|
|
360
|
+
"styles": {
|
|
347
361
|
"flex": 1
|
|
348
362
|
}
|
|
349
363
|
}
|
|
@@ -361,7 +375,7 @@
|
|
|
361
375
|
"targetIndex": 2
|
|
362
376
|
}
|
|
363
377
|
],
|
|
364
|
-
"
|
|
378
|
+
"styles": {
|
|
365
379
|
"flex": 1
|
|
366
380
|
}
|
|
367
381
|
}
|
|
@@ -375,7 +389,11 @@
|
|
|
375
389
|
"condition": "carousel-index",
|
|
376
390
|
"conditionVariable": 2,
|
|
377
391
|
"description": "Sayfa buton grubu. (#3)",
|
|
378
|
-
"title": "OnboardButtons 3"
|
|
392
|
+
"title": "OnboardButtons 3",
|
|
393
|
+
"styles": {
|
|
394
|
+
"flex": 2,
|
|
395
|
+
"justifyContent": "flex-end"
|
|
396
|
+
}
|
|
379
397
|
},
|
|
380
398
|
"children": [
|
|
381
399
|
{
|
|
@@ -391,7 +409,7 @@
|
|
|
391
409
|
"targetIndex": 3
|
|
392
410
|
}
|
|
393
411
|
],
|
|
394
|
-
"
|
|
412
|
+
"styles": {
|
|
395
413
|
"flex": 1
|
|
396
414
|
}
|
|
397
415
|
}
|
|
@@ -413,7 +431,7 @@
|
|
|
413
431
|
"targetIndex": 3
|
|
414
432
|
}
|
|
415
433
|
],
|
|
416
|
-
"
|
|
434
|
+
"styles": {
|
|
417
435
|
"flex": 1
|
|
418
436
|
}
|
|
419
437
|
}
|
|
@@ -446,7 +464,7 @@
|
|
|
446
464
|
"navigate_to": "subscriptions"
|
|
447
465
|
}
|
|
448
466
|
],
|
|
449
|
-
"
|
|
467
|
+
"styles": {
|
|
450
468
|
"flex": 1
|
|
451
469
|
}
|
|
452
470
|
}
|
|
@@ -463,7 +481,8 @@
|
|
|
463
481
|
"linkedWordSecondLocalizationKey": "view.onboarding.btnTerms",
|
|
464
482
|
"linkedWordSecondColor": "#0450E2",
|
|
465
483
|
"linkedWordSecondPage": "terms",
|
|
466
|
-
"
|
|
484
|
+
"styles": {
|
|
485
|
+
"flex": 2,
|
|
467
486
|
"gap": 8,
|
|
468
487
|
"color": "#81838F"
|
|
469
488
|
}
|
|
@@ -472,7 +491,7 @@
|
|
|
472
491
|
],
|
|
473
492
|
"attributes": {
|
|
474
493
|
"theme": "dark",
|
|
475
|
-
"description": "Onboarding
|
|
494
|
+
"description": "Onboarding sağlayıcısı. (#1)",
|
|
476
495
|
"title": "OnboardProvider 1"
|
|
477
496
|
}
|
|
478
497
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useId, useState } from 'react';
|
|
1
|
+
import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
|
|
2
2
|
import type { CarouselDotsComponentProps } from './CarouselDotsProps.generated';
|
|
3
3
|
import { carouselContext } from '../CarouselProvider/CarouselProvider';
|
|
4
4
|
import { onboardContext } from '../OnboardProvider/OnboardProvider';
|
|
5
5
|
import useNode from '../useNode';
|
|
6
6
|
import { useLogRender } from '../../utils/useLogRender';
|
|
7
7
|
import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
|
|
8
|
+
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
9
|
+
import { parseColor } from '../../utils/parseColor';
|
|
10
|
+
import { parseSize } from '../../size-matters';
|
|
11
|
+
import { useBuilderParams } from '../../components/BuilderProvider';
|
|
12
|
+
import { defaultAppConfig } from '../../types/PreviewConfig';
|
|
8
13
|
|
|
9
14
|
function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
10
15
|
useLogRender('CarouselDots');
|
|
@@ -15,7 +20,13 @@ function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
|
15
20
|
const attributeName = node.sourceType ?? node.type ?? 'carouselDots';
|
|
16
21
|
const attributeKey = node.key ?? generatedId;
|
|
17
22
|
|
|
18
|
-
const
|
|
23
|
+
const attrsAny = node.attributes as any;
|
|
24
|
+
const stylesBag =
|
|
25
|
+
(attrsAny?.styles as Record<string, unknown> | undefined) ??
|
|
26
|
+
(attrsAny?.style as Record<string, unknown> | undefined) ??
|
|
27
|
+
undefined;
|
|
28
|
+
const dotType =
|
|
29
|
+
(stylesBag?.dotType as any) ?? (attrsAny?.dotType as any) ?? 'normal_dot';
|
|
19
30
|
const style = useExtractViewStyle(node);
|
|
20
31
|
|
|
21
32
|
// Use the appropriate context based on sourceType
|
|
@@ -24,6 +35,71 @@ function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
|
24
35
|
const onboardApi = useContext(onboardContext);
|
|
25
36
|
const emblaApi = isOnboard ? onboardApi?.emblaApi : carouselApi;
|
|
26
37
|
|
|
38
|
+
// When used as OnboardDot (sourceType), support OnboardDot-specific attributes too.
|
|
39
|
+
const GHOST_DOT_DARK_COLOR = '#E4E5E7';
|
|
40
|
+
const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
|
|
41
|
+
const inactiveDotOpacity =
|
|
42
|
+
(stylesBag?.inactive_dot_opacity as number | undefined) ??
|
|
43
|
+
attrsAny?.inactive_dot_opacity ??
|
|
44
|
+
0.3;
|
|
45
|
+
const inactiveDotColorOverride =
|
|
46
|
+
(stylesBag?.inactive_dot_color as string | undefined) ??
|
|
47
|
+
attrsAny?.inactive_dot_color;
|
|
48
|
+
const activeDotColor =
|
|
49
|
+
(stylesBag?.active_dot_color as string | undefined) ??
|
|
50
|
+
attrsAny?.active_dot_color;
|
|
51
|
+
const dotThicknessRaw =
|
|
52
|
+
(stylesBag?.dot_thickness as any) ?? attrsAny?.dot_thickness;
|
|
53
|
+
|
|
54
|
+
const { appConfig: builderAppConfig, projectColors } = useBuilderParams();
|
|
55
|
+
const appConfig = builderAppConfig ?? defaultAppConfig;
|
|
56
|
+
const isDark = appConfig.theme === 'dark';
|
|
57
|
+
const inactiveDotColorBase = isDark
|
|
58
|
+
? GHOST_DOT_DARK_COLOR
|
|
59
|
+
: GHOST_DOT_LIGHT_COLOR;
|
|
60
|
+
|
|
61
|
+
const resolvedActiveDotColor = useMemo(
|
|
62
|
+
() => parseColor(activeDotColor, { theme: appConfig.theme, projectColors }),
|
|
63
|
+
[activeDotColor, appConfig.theme, projectColors],
|
|
64
|
+
);
|
|
65
|
+
const resolvedInactiveDotColor = useMemo(() => {
|
|
66
|
+
const parsed = parseColor(inactiveDotColorOverride, {
|
|
67
|
+
theme: appConfig.theme,
|
|
68
|
+
projectColors,
|
|
69
|
+
});
|
|
70
|
+
return parsed ?? inactiveDotColorBase;
|
|
71
|
+
}, [
|
|
72
|
+
inactiveDotColorBase,
|
|
73
|
+
inactiveDotColorOverride,
|
|
74
|
+
appConfig.theme,
|
|
75
|
+
projectColors,
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const dotSizeCss = useMemo(() => {
|
|
79
|
+
const parsed = parseSize(dotThicknessRaw);
|
|
80
|
+
if (parsed === undefined) return '10px';
|
|
81
|
+
if (typeof parsed === 'number') return `${parsed}px`;
|
|
82
|
+
if (typeof parsed === 'string' && parsed.trim()) return parsed;
|
|
83
|
+
return '10px';
|
|
84
|
+
}, [dotThicknessRaw]);
|
|
85
|
+
|
|
86
|
+
const dotGapCss = useMemo((): string => {
|
|
87
|
+
const px =
|
|
88
|
+
typeof dotSizeCss === 'string' && dotSizeCss.trim().endsWith('px')
|
|
89
|
+
? Number.parseFloat(dotSizeCss)
|
|
90
|
+
: Number.NaN;
|
|
91
|
+
const n = Number.isFinite(px) ? px : 10;
|
|
92
|
+
return `${Math.max(0, n / 3)}px`;
|
|
93
|
+
}, [dotSizeCss]);
|
|
94
|
+
|
|
95
|
+
const gapValue = (style as any)?.gap ?? dotGapCss;
|
|
96
|
+
const containerStyle = useMergedStyle(style, {
|
|
97
|
+
display: 'flex',
|
|
98
|
+
flexWrap: 'wrap',
|
|
99
|
+
gap: gapValue,
|
|
100
|
+
alignItems: 'center',
|
|
101
|
+
});
|
|
102
|
+
|
|
27
103
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
28
104
|
const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
|
|
29
105
|
|
|
@@ -53,17 +129,41 @@ function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
|
53
129
|
attribute-name={attributeName}
|
|
54
130
|
attribute-key={attributeKey}
|
|
55
131
|
className={`embla__dots embla__dots--${dotType}`}
|
|
56
|
-
style={
|
|
132
|
+
style={containerStyle}
|
|
57
133
|
>
|
|
58
|
-
{scrollSnaps.map((snap, index) =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
134
|
+
{scrollSnaps.map((snap, index) => {
|
|
135
|
+
const isDotSelected = selectedIndex === index;
|
|
136
|
+
const dotSize = dotSizeCss;
|
|
137
|
+
const resolvedColor =
|
|
138
|
+
isDotSelected && resolvedActiveDotColor
|
|
139
|
+
? resolvedActiveDotColor
|
|
140
|
+
: resolvedInactiveDotColor;
|
|
141
|
+
const activeFallback = '#007AFF';
|
|
142
|
+
const dotColor = resolvedColor ?? activeFallback;
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<button
|
|
146
|
+
key={index}
|
|
147
|
+
onClick={() => emblaApi?.scrollTo(snap)}
|
|
148
|
+
className="embla__dot"
|
|
149
|
+
style={{
|
|
150
|
+
width: dotSize,
|
|
151
|
+
height: dotSize,
|
|
152
|
+
backgroundColor: dotColor,
|
|
153
|
+
opacity: isDotSelected ? 1 : inactiveDotOpacity,
|
|
154
|
+
borderRadius: '9999px',
|
|
155
|
+
border: 0,
|
|
156
|
+
padding: 0,
|
|
157
|
+
margin: 0,
|
|
158
|
+
display: 'inline-block',
|
|
159
|
+
cursor: 'pointer',
|
|
160
|
+
boxSizing: 'border-box',
|
|
161
|
+
}}
|
|
162
|
+
aria-label={`Go to slide ${index + 1}`}
|
|
163
|
+
aria-current={isDotSelected ? 'true' : undefined}
|
|
164
|
+
/>
|
|
165
|
+
);
|
|
166
|
+
})}
|
|
67
167
|
</div>
|
|
68
168
|
);
|
|
69
169
|
}
|