pb-sxp-ui 1.20.14 → 1.20.16

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 (46) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +111 -111
  3. package/dist/index.cjs +959 -212
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +73 -72
  6. package/dist/index.js +959 -213
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.min.cjs +7 -7
  9. package/dist/index.min.cjs.map +1 -1
  10. package/dist/index.min.js +7 -7
  11. package/dist/index.min.js.map +1 -1
  12. package/dist/pb-ui.js +959 -212
  13. package/dist/pb-ui.js.map +1 -1
  14. package/dist/pb-ui.min.js +7 -7
  15. package/dist/pb-ui.min.js.map +1 -1
  16. package/es/core/components/DiyStoryPreview/index.js +10 -4
  17. package/es/core/components/StructurePage/index.d.ts +89 -0
  18. package/es/core/components/StructurePage/index.js +716 -0
  19. package/es/core/components/SxpPageRender/fakeData.js +1 -1
  20. package/es/core/components/SxpPageRender/index.js +10 -4
  21. package/es/core/context/SxpDataSourceProvider.js +4 -1
  22. package/es/core/hooks/useVisibleHeight.js +7 -7
  23. package/es/core/index.d.ts +2 -0
  24. package/es/core/index.js +1 -0
  25. package/es/core/utils/materials.d.ts +1 -1
  26. package/es/index.d.ts +1 -0
  27. package/es/index.js +1 -0
  28. package/es/materials/sxp/MultiPosts/index.js +4 -4
  29. package/es/materials/sxp/popup/CommodityDetail/index.js +4 -4
  30. package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +1 -1
  31. package/lib/core/components/DiyStoryPreview/index.js +10 -4
  32. package/lib/core/components/StructurePage/index.d.ts +89 -0
  33. package/lib/core/components/StructurePage/index.js +718 -0
  34. package/lib/core/components/SxpPageRender/fakeData.js +1 -1
  35. package/lib/core/components/SxpPageRender/index.js +10 -4
  36. package/lib/core/context/SxpDataSourceProvider.js +4 -1
  37. package/lib/core/hooks/useVisibleHeight.js +7 -7
  38. package/lib/core/index.d.ts +2 -0
  39. package/lib/core/index.js +6 -1
  40. package/lib/core/utils/materials.d.ts +1 -1
  41. package/lib/index.d.ts +1 -0
  42. package/lib/index.js +3 -1
  43. package/lib/materials/sxp/MultiPosts/index.js +4 -4
  44. package/lib/materials/sxp/popup/CommodityDetail/index.js +4 -4
  45. package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +1 -1
  46. package/package.json +111 -111
@@ -0,0 +1,716 @@
1
+ import { __rest } from "tslib";
2
+ import React, { useEffect, useState, useRef, useMemo, useCallback } from 'react';
3
+ import { useEditor } from '../../hooks';
4
+ import FormatImage from '../SxpPageRender/FormatImage';
5
+ const RESOLVER = {};
6
+ try {
7
+ const materialsModule = require('../../materials/sxp');
8
+ if (materialsModule && typeof materialsModule === 'object') {
9
+ Object.values(materialsModule).forEach((v) => {
10
+ var _a;
11
+ if ((_a = v === null || v === void 0 ? void 0 : v.extend) === null || _a === void 0 ? void 0 : _a.type) {
12
+ RESOLVER[v.extend.type] = v;
13
+ }
14
+ });
15
+ if (Object.keys(RESOLVER).length > 0) {
16
+ console.log('[StructurePage] Successfully loaded materials:', Object.keys(RESOLVER));
17
+ }
18
+ else {
19
+ console.warn('[StructurePage] Materials module loaded but no valid components found');
20
+ }
21
+ }
22
+ else {
23
+ console.warn('[StructurePage] Materials module is not a valid object:', materialsModule);
24
+ }
25
+ }
26
+ catch (error) {
27
+ console.error('[StructurePage] Failed to load materials for StructurePage:', error);
28
+ }
29
+ const baseStyles = {
30
+ container: {
31
+ backgroundColor: '#000',
32
+ overflowY: 'auto',
33
+ overflowX: 'hidden',
34
+ padding: 0,
35
+ boxSizing: 'border-box'
36
+ },
37
+ section: {
38
+ width: '100%',
39
+ position: 'relative',
40
+ boxSizing: 'border-box'
41
+ },
42
+ heroSection: {
43
+ width: '100%',
44
+ height: 'auto',
45
+ position: 'relative',
46
+ overflow: 'hidden',
47
+ backgroundColor: '#000'
48
+ },
49
+ heroTopText: {
50
+ width: '100%',
51
+ padding: '20px',
52
+ backgroundColor: '#fff',
53
+ color: '#000',
54
+ fontSize: '16px',
55
+ fontWeight: 'bold',
56
+ textAlign: 'center',
57
+ boxSizing: 'border-box'
58
+ },
59
+ heroImageContainer: {
60
+ width: '100%',
61
+ position: 'relative',
62
+ overflow: 'hidden'
63
+ },
64
+ heroImage: {
65
+ width: '100%',
66
+ height: 'auto',
67
+ display: 'block',
68
+ objectFit: 'cover'
69
+ },
70
+ heroVideo: {
71
+ width: '100%',
72
+ height: 'auto',
73
+ display: 'block',
74
+ objectFit: 'cover'
75
+ },
76
+ heroOverlay: {
77
+ position: 'absolute',
78
+ bottom: 0,
79
+ left: 0,
80
+ right: 0,
81
+ padding: '40px 20px',
82
+ background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%)',
83
+ color: '#fff',
84
+ display: 'flex',
85
+ justifyContent: 'center',
86
+ alignItems: 'center'
87
+ },
88
+ heroButton: {
89
+ padding: '12px 30px',
90
+ backgroundColor: '#fff',
91
+ color: '#000',
92
+ border: 'none',
93
+ fontSize: '14px',
94
+ fontWeight: 500,
95
+ cursor: 'pointer',
96
+ textTransform: 'uppercase'
97
+ },
98
+ carouselSection: {
99
+ width: '100%',
100
+ position: 'relative'
101
+ },
102
+ carouselImageContainer: {
103
+ width: '100%',
104
+ height: 'auto',
105
+ position: 'relative',
106
+ overflow: 'hidden'
107
+ },
108
+ carouselContainer: {
109
+ display: 'flex',
110
+ transition: 'transform 0.5s ease-in-out',
111
+ width: '100%'
112
+ },
113
+ carouselSlide: {
114
+ minWidth: '100%',
115
+ position: 'relative'
116
+ },
117
+ carouselImage: {
118
+ width: '100%',
119
+ height: 'auto',
120
+ display: 'block',
121
+ objectFit: 'cover'
122
+ },
123
+ carouselVideo: {
124
+ width: '100%',
125
+ height: 'auto',
126
+ display: 'block',
127
+ objectFit: 'cover'
128
+ },
129
+ carouselInfoSection: {
130
+ width: '100%',
131
+ padding: '20px',
132
+ backgroundColor: '#000',
133
+ color: '#fff',
134
+ textAlign: 'center'
135
+ },
136
+ carouselText: {
137
+ fontSize: '16px',
138
+ fontWeight: 'normal',
139
+ marginBottom: '15px',
140
+ color: '#fff'
141
+ },
142
+ carouselButton: {
143
+ padding: '10px 25px',
144
+ backgroundColor: '#fff',
145
+ color: '#000',
146
+ border: '1px solid #fff',
147
+ fontSize: '13px',
148
+ fontWeight: 500,
149
+ cursor: 'pointer',
150
+ textTransform: 'uppercase'
151
+ },
152
+ arrowButton: {
153
+ position: 'absolute',
154
+ top: '50%',
155
+ transform: 'translateY(-50%)',
156
+ width: '40px',
157
+ height: '40px',
158
+ backgroundColor: 'rgba(255,255,255,0.8)',
159
+ border: 'none',
160
+ borderRadius: '50%',
161
+ fontSize: '18px',
162
+ cursor: 'pointer',
163
+ zIndex: 10,
164
+ display: 'flex',
165
+ alignItems: 'center',
166
+ justifyContent: 'center'
167
+ },
168
+ highlightSection: {
169
+ width: '100%',
170
+ position: 'relative',
171
+ backgroundColor: '#000'
172
+ },
173
+ highlightImageContainer: {
174
+ width: '100%',
175
+ aspectRatio: '1/1',
176
+ position: 'relative',
177
+ overflow: 'hidden'
178
+ },
179
+ highlightImage: {
180
+ width: '100%',
181
+ height: '100%',
182
+ objectFit: 'cover',
183
+ display: 'block'
184
+ },
185
+ highlightInfoSection: {
186
+ width: '100%',
187
+ padding: '20px',
188
+ backgroundColor: '#000',
189
+ color: '#fff',
190
+ textAlign: 'center'
191
+ },
192
+ highlightTitle: {
193
+ fontSize: '18px',
194
+ fontWeight: 'bold',
195
+ marginBottom: '10px',
196
+ textAlign: 'center',
197
+ color: '#fff'
198
+ },
199
+ highlightDesc: {
200
+ fontSize: '14px',
201
+ marginBottom: '15px',
202
+ textAlign: 'center',
203
+ lineHeight: '1.5',
204
+ color: '#ccc'
205
+ },
206
+ highlightButton: {
207
+ padding: '10px 25px',
208
+ backgroundColor: 'transparent',
209
+ color: '#fff',
210
+ border: '1px solid #fff',
211
+ fontSize: '13px',
212
+ fontWeight: 500,
213
+ cursor: 'pointer',
214
+ textTransform: 'uppercase'
215
+ },
216
+ productGrid: {
217
+ display: 'grid',
218
+ gridTemplateColumns: '50% 50%',
219
+ gridAutoRows: 'auto',
220
+ gap: '0',
221
+ width: '100%',
222
+ backgroundColor: '#000',
223
+ boxSizing: 'border-box',
224
+ margin: 0,
225
+ padding: 0,
226
+ overflow: 'hidden'
227
+ },
228
+ productItem: {
229
+ position: 'relative',
230
+ backgroundColor: '#000',
231
+ display: 'block',
232
+ boxSizing: 'border-box',
233
+ width: '100%',
234
+ minWidth: 0,
235
+ overflow: 'hidden'
236
+ },
237
+ productImageContainer: {
238
+ width: '100%',
239
+ paddingBottom: '100%',
240
+ position: 'relative',
241
+ overflow: 'hidden'
242
+ },
243
+ productImage: {
244
+ position: 'absolute',
245
+ top: 0,
246
+ left: 0,
247
+ width: '100%',
248
+ height: '100%',
249
+ objectFit: 'cover',
250
+ display: 'block'
251
+ },
252
+ productCtaContainer: {
253
+ width: '100%',
254
+ padding: '15px',
255
+ backgroundColor: '#000',
256
+ textAlign: 'center',
257
+ boxSizing: 'border-box'
258
+ },
259
+ productText: {
260
+ width: '100%',
261
+ padding: '15px',
262
+ backgroundColor: '#000',
263
+ color: '#fff',
264
+ textAlign: 'center',
265
+ fontSize: '14px',
266
+ fontWeight: 'normal',
267
+ boxSizing: 'border-box'
268
+ },
269
+ productButton: {
270
+ padding: '8px 20px',
271
+ backgroundColor: 'transparent',
272
+ color: '#fff',
273
+ border: '1px solid #fff',
274
+ fontSize: '12px',
275
+ fontWeight: 500,
276
+ cursor: 'pointer',
277
+ textTransform: 'uppercase',
278
+ whiteSpace: 'nowrap'
279
+ },
280
+ footerSection: {
281
+ width: '100%',
282
+ position: 'relative',
283
+ backgroundColor: '#000'
284
+ },
285
+ footerInfoSection: {
286
+ width: '100%',
287
+ padding: '20px',
288
+ backgroundColor: '#000',
289
+ color: '#fff',
290
+ textAlign: 'center'
291
+ },
292
+ footerText: {
293
+ fontSize: '18px',
294
+ fontWeight: 'normal',
295
+ marginBottom: '15px',
296
+ lineHeight: '1.4',
297
+ color: '#fff'
298
+ },
299
+ footerButton: {
300
+ padding: '10px 25px',
301
+ backgroundColor: 'transparent',
302
+ color: '#fff',
303
+ border: '1px solid #fff',
304
+ fontSize: '13px',
305
+ fontWeight: 500,
306
+ cursor: 'pointer',
307
+ textTransform: 'uppercase',
308
+ marginBottom: '20px',
309
+ display: 'inline-block'
310
+ },
311
+ footerImageContainer: {
312
+ width: '100%',
313
+ aspectRatio: '1/1',
314
+ overflow: 'hidden'
315
+ },
316
+ footerImage: {
317
+ width: '100%',
318
+ height: '100%',
319
+ objectFit: 'cover',
320
+ display: 'block'
321
+ }
322
+ };
323
+ const StructurePage = (_a) => {
324
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
325
+ var { containerStyle, containerHeight = 664, containerWidth = 375, className = '', apiUrl = 'https://bff-be-dev.chatlabs.net/api/v1/recommend/list', requestBody, editorMode = false, multiCTAConfig: propMultiCTAConfig, videoPlayIcon: propVideoPlayIcon, isCmsMode = false, storyId, customHeaders } = _a, rest = __rest(_a, ["containerStyle", "containerHeight", "containerWidth", "className", "apiUrl", "requestBody", "editorMode", "multiCTAConfig", "videoPlayIcon", "isCmsMode", "storyId", "customHeaders"]);
326
+ const [data, setData] = useState(null);
327
+ const [loading, setLoading] = useState(true);
328
+ const [error, setError] = useState(null);
329
+ const [carouselIndex, setCarouselIndex] = useState(0);
330
+ const heroVideoRef = useRef(null);
331
+ const carouselVideoRefs = useRef([]);
332
+ const [isHeroVideoPaused, setIsHeroVideoPaused] = useState(false);
333
+ const [carouselVideoPausedStates, setCarouselVideoPausedStates] = useState([]);
334
+ const { schema } = useEditor();
335
+ const multiCTAConfig = useMemo(() => {
336
+ var _a;
337
+ return propMultiCTAConfig || ((_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.multiCTAConfig) || {};
338
+ }, [propMultiCTAConfig, (_b = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _b === void 0 ? void 0 : _b.multiCTAConfig]);
339
+ const DEFAULT_PAUSE_ICON = 'https://sxph5-uat.chatlabs.net/pb_static/06f28a2025c74c1cb49be6767316d827.png';
340
+ const videoPlayIcon = useMemo(() => {
341
+ var _a, _b;
342
+ if (propVideoPlayIcon)
343
+ return propVideoPlayIcon;
344
+ const configIcon = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.globalConfig) === null || _b === void 0 ? void 0 : _b.videoPlayIcon;
345
+ if (configIcon) {
346
+ if (configIcon.startsWith('http://') || configIcon.startsWith('https://')) {
347
+ return configIcon;
348
+ }
349
+ if (configIcon.startsWith('/')) {
350
+ return `${window.location.origin}${configIcon}`;
351
+ }
352
+ return configIcon;
353
+ }
354
+ return DEFAULT_PAUSE_ICON;
355
+ }, [propVideoPlayIcon, (_d = (_c = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _c === void 0 ? void 0 : _c.globalConfig) === null || _d === void 0 ? void 0 : _d.videoPlayIcon]);
356
+ const handleCtaClick = useCallback((link, interaction, productData, ctaData) => {
357
+ if (interaction) {
358
+ const { linkType, popupType, popupAni } = interaction;
359
+ if (linkType === 'popup' && popupType) {
360
+ if (productData && typeof window !== 'undefined' && window.setPopupDetailData) {
361
+ const popupData = {
362
+ video: {
363
+ bindProduct: productData,
364
+ bindProducts: [productData],
365
+ bindCta: ctaData
366
+ }
367
+ };
368
+ window.setPopupDetailData(popupData);
369
+ }
370
+ if (typeof window !== 'undefined' && window.sxpPopup) {
371
+ if (popupAni && popupAni.name) {
372
+ window.sxpPopup(popupType, popupAni);
373
+ }
374
+ else {
375
+ window.sxpPopup(popupType);
376
+ }
377
+ }
378
+ return;
379
+ }
380
+ }
381
+ if (link) {
382
+ window.open(link, '_blank');
383
+ }
384
+ }, []);
385
+ const mergeStyles = useCallback((baseStyle, configKey) => {
386
+ if (!editorMode || !multiCTAConfig[configKey]) {
387
+ return baseStyle;
388
+ }
389
+ const config = multiCTAConfig[configKey];
390
+ const styleKeys = [
391
+ 'fontSize', 'color', 'textAlign', 'fontWeight',
392
+ 'backgroundColor', 'padding', 'margin', 'borderRadius',
393
+ 'showBorder', 'borderWidth', 'borderColor',
394
+ 'buttonBackgroundColor', 'buttonTextColor', 'buttonWidth', 'buttonHeight'
395
+ ];
396
+ const styleConfig = Object.keys(config)
397
+ .filter(key => styleKeys.includes(key))
398
+ .reduce((obj, key) => {
399
+ obj[key] = config[key];
400
+ return obj;
401
+ }, {});
402
+ if (Object.keys(styleConfig).length === 0) {
403
+ return baseStyle;
404
+ }
405
+ const customStyle = {};
406
+ if (styleConfig.fontSize && typeof styleConfig.fontSize === 'number') {
407
+ customStyle.fontSize = `${styleConfig.fontSize}px`;
408
+ }
409
+ if (styleConfig.color && typeof styleConfig.color === 'string') {
410
+ customStyle.color = styleConfig.color;
411
+ }
412
+ if (styleConfig.textAlign && typeof styleConfig.textAlign === 'string') {
413
+ customStyle.textAlign = styleConfig.textAlign;
414
+ }
415
+ if (styleConfig.fontWeight && typeof styleConfig.fontWeight === 'number') {
416
+ customStyle.fontWeight = styleConfig.fontWeight;
417
+ }
418
+ if (styleConfig.backgroundColor && typeof styleConfig.backgroundColor === 'string') {
419
+ customStyle.backgroundColor = styleConfig.backgroundColor;
420
+ }
421
+ if (styleConfig.padding && typeof styleConfig.padding === 'string') {
422
+ customStyle.padding = styleConfig.padding;
423
+ }
424
+ if (styleConfig.margin && typeof styleConfig.margin === 'string') {
425
+ customStyle.margin = styleConfig.margin;
426
+ }
427
+ if (styleConfig.borderRadius && typeof styleConfig.borderRadius === 'number') {
428
+ customStyle.borderRadius = `${styleConfig.borderRadius}px`;
429
+ }
430
+ if (styleConfig.showBorder && styleConfig.borderWidth && typeof styleConfig.borderWidth === 'number') {
431
+ customStyle.border = `${styleConfig.borderWidth}px solid ${styleConfig.borderColor || '#d9d9d9'}`;
432
+ }
433
+ if (styleConfig.buttonBackgroundColor && typeof styleConfig.buttonBackgroundColor === 'string') {
434
+ customStyle.backgroundColor = styleConfig.buttonBackgroundColor;
435
+ }
436
+ if (styleConfig.buttonTextColor && typeof styleConfig.buttonTextColor === 'string') {
437
+ customStyle.color = styleConfig.buttonTextColor;
438
+ }
439
+ if (styleConfig.buttonWidth && typeof styleConfig.buttonWidth === 'number') {
440
+ customStyle.width = `${styleConfig.buttonWidth}px`;
441
+ }
442
+ if (styleConfig.buttonHeight && typeof styleConfig.buttonHeight === 'number') {
443
+ customStyle.height = `${styleConfig.buttonHeight}px`;
444
+ }
445
+ return Object.assign(Object.assign({}, baseStyle), customStyle);
446
+ }, [editorMode, multiCTAConfig]);
447
+ const renderCTA = useCallback((buttonKey, ctaData, productData, fallbackStyle) => {
448
+ var _a, _b, _c;
449
+ if (!ctaData) {
450
+ return null;
451
+ }
452
+ const config = multiCTAConfig[buttonKey];
453
+ const templateType = config === null || config === void 0 ? void 0 : config.templateType;
454
+ const interaction = config === null || config === void 0 ? void 0 : config.interaction;
455
+ if (editorMode && templateType && RESOLVER[templateType]) {
456
+ const TemplateComponent = RESOLVER[templateType];
457
+ const templateExtend = TemplateComponent === null || TemplateComponent === void 0 ? void 0 : TemplateComponent.extend;
458
+ if (templateExtend && typeof TemplateComponent === 'function') {
459
+ try {
460
+ const templateProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (_a = templateExtend.defaulSetting) === null || _a === void 0 ? void 0 : _a.props), { style: Object.assign(Object.assign(Object.assign({}, (_b = templateExtend.defaulSetting) === null || _b === void 0 ? void 0 : _b.style), mergeStyles(fallbackStyle || {}, buttonKey)), { marginBottom: 0, width: '100%' }), textStyle: (_c = templateExtend.defaulSetting) === null || _c === void 0 ? void 0 : _c.textStyle }), (productData && { bindProduct: productData })), { isTel: true }), rest);
461
+ return React.createElement(TemplateComponent, templateProps);
462
+ }
463
+ catch (error) {
464
+ console.error(`[StructurePage] Failed to render template component ${templateType}:`, error);
465
+ }
466
+ }
467
+ }
468
+ return (React.createElement("button", { style: mergeStyles(fallbackStyle || baseStyles.heroButton, buttonKey), onClick: () => handleCtaClick(ctaData === null || ctaData === void 0 ? void 0 : ctaData.link, interaction, productData, ctaData) }, ctaData.title));
469
+ }, [multiCTAConfig, editorMode, handleCtaClick, mergeStyles, rest]);
470
+ useEffect(() => {
471
+ const hasActualData = propMultiCTAConfig && (propMultiCTAConfig.heroSection ||
472
+ propMultiCTAConfig.carouselSection ||
473
+ propMultiCTAConfig.highlightRevealSection ||
474
+ propMultiCTAConfig.productGridSection ||
475
+ propMultiCTAConfig.footerSection);
476
+ if (editorMode && hasActualData && !isCmsMode) {
477
+ setLoading(false);
478
+ setError(null);
479
+ setData(propMultiCTAConfig);
480
+ return;
481
+ }
482
+ if (editorMode && data && !isCmsMode) {
483
+ return;
484
+ }
485
+ setLoading(true);
486
+ setError(null);
487
+ let finalApiUrl = apiUrl;
488
+ let bodyToSend = {};
489
+ if (isCmsMode) {
490
+ if (!storyId) {
491
+ console.error('[StructurePage CMS Mode] storyId is required but not provided');
492
+ setError('storyId is required in CMS mode');
493
+ setLoading(false);
494
+ return;
495
+ }
496
+ finalApiUrl = `${apiUrl}/api/console/ad/multiCta/rec/detail`;
497
+ bodyToSend = { storyId };
498
+ }
499
+ else {
500
+ const defaultBody = {
501
+ maxSize: 20,
502
+ defaultSize: 10,
503
+ type: 'story'
504
+ };
505
+ bodyToSend = requestBody ? Object.assign(Object.assign({}, defaultBody), requestBody) : defaultBody;
506
+ }
507
+ const headers = {
508
+ 'Content-Type': 'application/json'
509
+ };
510
+ if (isCmsMode) {
511
+ if (customHeaders) {
512
+ Object.assign(headers, customHeaders);
513
+ }
514
+ }
515
+ else {
516
+ if (bodyToSend['x-app-id']) {
517
+ headers['x-app-id'] = bodyToSend['x-app-id'];
518
+ delete bodyToSend['x-app-id'];
519
+ }
520
+ if (bodyToSend['x-user-id']) {
521
+ headers['x-user-id'] = bodyToSend['x-user-id'];
522
+ delete bodyToSend['x-user-id'];
523
+ }
524
+ if (bodyToSend['tenant-id']) {
525
+ headers['tenant-id'] = bodyToSend['tenant-id'];
526
+ delete bodyToSend['tenant-id'];
527
+ }
528
+ }
529
+ fetch(finalApiUrl, {
530
+ method: 'POST',
531
+ headers,
532
+ body: JSON.stringify(bodyToSend),
533
+ credentials: 'include'
534
+ })
535
+ .then((res) => {
536
+ if (!res.ok) {
537
+ throw new Error(`HTTP error! status: ${res.status}`);
538
+ }
539
+ return res.json();
540
+ })
541
+ .then((result) => {
542
+ var _a, _b, _c, _d;
543
+ if (result.code === '0' || result.code === '00000') {
544
+ let multiCtaData = null;
545
+ if (isCmsMode) {
546
+ multiCtaData = (_a = result.data) === null || _a === void 0 ? void 0 : _a.multiCta;
547
+ }
548
+ else {
549
+ multiCtaData = (_d = (_c = (_b = result.data) === null || _b === void 0 ? void 0 : _b.recList) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.multiCta;
550
+ }
551
+ if (multiCtaData) {
552
+ setData(multiCtaData);
553
+ }
554
+ else {
555
+ console.error('[StructurePage] No multiCta data found in response:', result);
556
+ setError(result.message || 'No multiCta data found');
557
+ }
558
+ }
559
+ else {
560
+ setError(result.message || 'Failed to load data');
561
+ }
562
+ setLoading(false);
563
+ })
564
+ .catch((err) => {
565
+ console.error('[StructurePage] Failed to fetch data:', {
566
+ error: err,
567
+ message: err.message,
568
+ url: finalApiUrl,
569
+ body: bodyToSend,
570
+ isCmsMode,
571
+ storyId
572
+ });
573
+ setError(err.message || 'Network error');
574
+ setLoading(false);
575
+ });
576
+ }, [apiUrl, isCmsMode, storyId, customHeaders]);
577
+ useEffect(() => {
578
+ var _a;
579
+ if (heroVideoRef.current && ((_a = data === null || data === void 0 ? void 0 : data.heroSection) === null || _a === void 0 ? void 0 : _a.url)) {
580
+ heroVideoRef.current.play().catch((err) => console.log('Video autoplay failed:', err));
581
+ setIsHeroVideoPaused(false);
582
+ }
583
+ }, [data === null || data === void 0 ? void 0 : data.heroSection]);
584
+ useEffect(() => {
585
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
586
+ setCarouselVideoPausedStates(new Array(data.carouselSection.length).fill(true));
587
+ }
588
+ }, [data === null || data === void 0 ? void 0 : data.carouselSection]);
589
+ const handleHeroVideoClick = useCallback(() => {
590
+ if (heroVideoRef.current) {
591
+ if (heroVideoRef.current.paused) {
592
+ heroVideoRef.current.play();
593
+ setIsHeroVideoPaused(false);
594
+ }
595
+ else {
596
+ heroVideoRef.current.pause();
597
+ setIsHeroVideoPaused(true);
598
+ }
599
+ }
600
+ }, []);
601
+ const handleCarouselVideoClick = useCallback((index) => {
602
+ const videoRef = carouselVideoRefs.current[index];
603
+ if (videoRef) {
604
+ if (videoRef.paused) {
605
+ videoRef.play();
606
+ setCarouselVideoPausedStates(prev => {
607
+ const newStates = [...prev];
608
+ newStates[index] = false;
609
+ return newStates;
610
+ });
611
+ }
612
+ else {
613
+ videoRef.pause();
614
+ setCarouselVideoPausedStates(prev => {
615
+ const newStates = [...prev];
616
+ newStates[index] = true;
617
+ return newStates;
618
+ });
619
+ }
620
+ }
621
+ }, []);
622
+ const handleCarouselPrev = () => {
623
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
624
+ setCarouselIndex((prev) => (prev === 0 ? data.carouselSection.length - 1 : prev - 1));
625
+ }
626
+ };
627
+ const handleCarouselNext = () => {
628
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
629
+ setCarouselIndex((prev) => (prev === data.carouselSection.length - 1 ? 0 : prev + 1));
630
+ }
631
+ };
632
+ if (loading) {
633
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '16px' }) }, "Loading..."));
634
+ }
635
+ if (error) {
636
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', color: '#fff', padding: '20px', textAlign: 'center' }) },
637
+ React.createElement("div", { style: { fontSize: '18px', marginBottom: '10px' } }, "\u26A0\uFE0F Error"),
638
+ React.createElement("div", { style: { fontSize: '14px', opacity: 0.8 } }, error)));
639
+ }
640
+ if (!data) {
641
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '16px' }) }, "No data available"));
642
+ }
643
+ return (React.createElement("div", { className: className, style: Object.assign(Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth }), containerStyle) },
644
+ data.heroSection && (React.createElement("div", { style: baseStyles.heroSection },
645
+ data.heroSection.text && (React.createElement("div", { style: mergeStyles(baseStyles.heroTopText, 'heroTopText') }, data.heroSection.text)),
646
+ React.createElement("div", { style: baseStyles.heroImageContainer },
647
+ data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
648
+ React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, autoPlay: true, muted: true, loop: true, playsInline: true, controls: false }),
649
+ isHeroVideoPaused && (React.createElement(FormatImage, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' })))) : ((_e = data.heroSection.imgUrls) === null || _e === void 0 ? void 0 : _e[0]) ? (React.createElement("img", { src: data.heroSection.imgUrls[0], alt: 'Hero', style: baseStyles.heroImage })) : null,
650
+ React.createElement("div", { style: baseStyles.heroOverlay }, renderCTA('heroButton', (_g = (_f = data.heroSection.bindProducts) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.bindCta, (_h = data.heroSection.bindProducts) === null || _h === void 0 ? void 0 : _h[0], baseStyles.heroButton))))),
651
+ data.carouselSection && data.carouselSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.carouselSection, 'carouselSection') },
652
+ React.createElement("div", { style: baseStyles.carouselImageContainer },
653
+ React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
654
+ var _a;
655
+ return (React.createElement("div", { key: item.itemId, style: baseStyles.carouselSlide }, item.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: () => handleCarouselVideoClick(index) },
656
+ React.createElement("video", { ref: (el) => {
657
+ carouselVideoRefs.current[index] = el;
658
+ }, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false }),
659
+ carouselVideoPausedStates[index] && (React.createElement(FormatImage, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' })))) : ((_a = item.imgUrls) === null || _a === void 0 ? void 0 : _a[0]) ? (React.createElement("img", { src: item.imgUrls[0], alt: item.text || 'Carousel', style: baseStyles.carouselImage })) : null));
660
+ })),
661
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { left: '10px' }), onClick: handleCarouselPrev }, "\u2039"),
662
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { right: '10px' }), onClick: handleCarouselNext }, "\u203A")),
663
+ React.createElement("div", { style: mergeStyles(baseStyles.carouselInfoSection, 'carouselSection') },
664
+ ((_j = data.carouselSection[carouselIndex]) === null || _j === void 0 ? void 0 : _j.text) && (React.createElement("div", { style: mergeStyles(baseStyles.carouselText, 'carouselSection') }, (_k = data.carouselSection[carouselIndex]) === null || _k === void 0 ? void 0 : _k.text)),
665
+ renderCTA('carouselButton', (_o = (_m = (_l = data.carouselSection[carouselIndex]) === null || _l === void 0 ? void 0 : _l.bindProducts) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o.bindCta, (_q = (_p = data.carouselSection[carouselIndex]) === null || _p === void 0 ? void 0 : _p.bindProducts) === null || _q === void 0 ? void 0 : _q[0], baseStyles.carouselButton)))),
666
+ data.highlightRevealSection && (React.createElement("div", { style: mergeStyles(baseStyles.highlightSection, 'highlightSection') },
667
+ React.createElement("div", { style: baseStyles.highlightImageContainer },
668
+ React.createElement("img", { src: data.highlightRevealSection.landingImageUrl || data.highlightRevealSection.cover, alt: data.highlightRevealSection.title, style: baseStyles.highlightImage })),
669
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightInfoSection, 'highlightSection') },
670
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightTitle, 'highlightSection') }, data.highlightRevealSection.title),
671
+ renderCTA('highlightButton', data.highlightRevealSection.bindCta, data.highlightRevealSection, baseStyles.highlightButton)))),
672
+ data.productGridSection && data.productGridSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.productGrid, 'productGrid') }, (() => {
673
+ const gridItems = [null, null, null, null, null, null];
674
+ const productIndexMap = {};
675
+ data.productGridSection.forEach((product, idx) => {
676
+ var _a;
677
+ const pos = (_a = product.position) === null || _a === void 0 ? void 0 : _a.toLowerCase();
678
+ let gridIndex = -1;
679
+ if (pos === 'top_right') {
680
+ gridIndex = 1;
681
+ }
682
+ else if (pos === 'top_left') {
683
+ gridIndex = 0;
684
+ }
685
+ else if (pos === 'center_left') {
686
+ gridIndex = 2;
687
+ }
688
+ else if (pos === 'center_right') {
689
+ gridIndex = 3;
690
+ }
691
+ else if (pos === 'bottom_left') {
692
+ gridIndex = 4;
693
+ }
694
+ else if (pos === 'bottom_right') {
695
+ gridIndex = 5;
696
+ }
697
+ if (gridIndex >= 0) {
698
+ gridItems[gridIndex] = product;
699
+ productIndexMap[gridIndex] = idx + 1;
700
+ }
701
+ });
702
+ return gridItems.map((product, gridIndex) => {
703
+ const productDataIndex = productIndexMap[gridIndex];
704
+ const buttonKey = `productButton${productDataIndex || gridIndex + 1}`;
705
+ return (React.createElement("div", { key: (product === null || product === void 0 ? void 0 : product.itemId) || `empty-${gridIndex}`, style: baseStyles.productItem }, product ? (React.createElement(React.Fragment, null,
706
+ React.createElement("div", { style: baseStyles.productImageContainer },
707
+ React.createElement("img", { src: product.landingImageUrl || product.cover, style: baseStyles.productImage })),
708
+ product.bindCta && (React.createElement("div", { style: baseStyles.productCtaContainer }, renderCTA(buttonKey, product.bindCta, product, baseStyles.productButton))))) : (React.createElement("div", { style: { width: '100%', paddingBottom: '100%' } }))));
709
+ });
710
+ })())),
711
+ data.footerSection && (React.createElement("div", { style: mergeStyles(baseStyles.footerSection, 'footerSection') },
712
+ React.createElement("div", { style: mergeStyles(baseStyles.footerInfoSection, 'footerSection') }, renderCTA('footerButton', data.footerSection.bindCta, data.footerSection, baseStyles.footerButton)),
713
+ React.createElement("div", { style: baseStyles.footerImageContainer },
714
+ React.createElement("img", { src: data.footerSection.landingImageUrl || data.footerSection.cover, alt: data.footerSection.title, style: baseStyles.footerImage }))))));
715
+ };
716
+ export default StructurePage;