webs-sdk 0.14.45 → 0.15.0

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 (64) hide show
  1. package/README.md +398 -398
  2. package/dist/components/ARFilters/ARFilters.js +52 -52
  3. package/dist/components/AvatarAI.js +4 -4
  4. package/dist/components/CookieConsent/constants.js +31 -31
  5. package/dist/components/CreativeFaceSwap.js +12 -12
  6. package/dist/components/MemeGenerator.js +12 -12
  7. package/dist/components/Quiz.d.ts +91 -0
  8. package/dist/components/Quiz.d.ts.map +1 -0
  9. package/dist/components/Quiz.js +748 -0
  10. package/dist/components/Quiz.js.map +1 -0
  11. package/dist/components/SpinningWheel/SpinningWheel.js +7 -7
  12. package/dist/components/Stickers.d.ts +68 -0
  13. package/dist/components/Stickers.d.ts.map +1 -0
  14. package/dist/components/Stickers.js +303 -0
  15. package/dist/components/Stickers.js.map +1 -0
  16. package/dist/components/esports/news/EsportsNews.d.ts.map +1 -1
  17. package/dist/components/esports/news/EsportsNews.js +5 -12
  18. package/dist/components/esports/news/EsportsNews.js.map +1 -1
  19. package/dist/components/esports/news/index.d.ts +0 -2
  20. package/dist/components/esports/news/index.d.ts.map +1 -1
  21. package/dist/components/esports/news/index.js +1 -3
  22. package/dist/components/esports/news/index.js.map +1 -1
  23. package/dist/components/esports/news/types.d.ts +1 -4
  24. package/dist/components/esports/news/types.d.ts.map +1 -1
  25. package/dist/components/esports/utils.d.ts +0 -1
  26. package/dist/components/esports/utils.d.ts.map +1 -1
  27. package/dist/components/esports/utils.js +0 -23
  28. package/dist/components/esports/utils.js.map +1 -1
  29. package/dist/components/esports/videos/EsportsVideos.d.ts.map +1 -1
  30. package/dist/components/esports/videos/EsportsVideos.js +5 -12
  31. package/dist/components/esports/videos/EsportsVideos.js.map +1 -1
  32. package/dist/components/esports/videos/types.d.ts +1 -4
  33. package/dist/components/esports/videos/types.d.ts.map +1 -1
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +8 -1
  37. package/dist/index.js.map +1 -1
  38. package/package.json +43 -42
  39. package/public/spin2win/assets/border-afristream.svg +26 -26
  40. package/public/spin2win/assets/border-efc.svg +23 -23
  41. package/public/spin2win/assets/border-totalgym.svg +27 -27
  42. package/public/spin2win/assets/border-womantoday.svg +26 -26
  43. package/public/spin2win/assets/indicator-afristream.svg +28 -28
  44. package/public/spin2win/assets/indicator-efc.svg +29 -29
  45. package/public/spin2win/assets/indicator-totalgym.svg +29 -29
  46. package/public/spin2win/fonts/switzer/README.md +22 -22
  47. package/dist/client.d.ts +0 -2
  48. package/dist/client.d.ts.map +0 -1
  49. package/dist/client.js +0 -7
  50. package/dist/client.js.map +0 -1
  51. package/dist/components/esports/news/EsportsNewsDetail.d.ts +0 -12
  52. package/dist/components/esports/news/EsportsNewsDetail.d.ts.map +0 -1
  53. package/dist/components/esports/news/EsportsNewsDetail.js +0 -99
  54. package/dist/components/esports/news/EsportsNewsDetail.js.map +0 -1
  55. package/dist/components/ui/VideoPlayer.d.ts +0 -11
  56. package/dist/components/ui/VideoPlayer.d.ts.map +0 -1
  57. package/dist/components/ui/VideoPlayer.js +0 -171
  58. package/dist/components/ui/VideoPlayer.js.map +0 -1
  59. package/dist/context/TranslationContext.d.ts +0 -12
  60. package/dist/context/TranslationContext.d.ts.map +0 -1
  61. package/dist/context/TranslationContext.js +0 -60
  62. package/dist/context/TranslationContext.js.map +0 -1
  63. package/index.js +0 -83
  64. package/types/index.d.ts +0 -415
@@ -0,0 +1,748 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Quiz = Quiz;
37
+ exports.QuizForYouCard = QuizForYouCard;
38
+ const react_1 = __importStar(require("react"));
39
+ function parseMeta(raw) {
40
+ if (!raw)
41
+ return {};
42
+ if (typeof raw === 'object')
43
+ return raw;
44
+ try {
45
+ return JSON.parse(raw);
46
+ }
47
+ catch (_a) {
48
+ return {};
49
+ }
50
+ }
51
+ function formatLabel(template, vars) {
52
+ return Object.entries(vars).reduce((acc, [key, val]) => acc.replace(`{${key}}`, String(val)), template);
53
+ }
54
+ function toQuizItem(item) {
55
+ var _a, _b;
56
+ const title = (item.title || item.name || '');
57
+ if (!title)
58
+ return null;
59
+ const contentsId = String(item.contents || '');
60
+ if (!contentsId)
61
+ return null;
62
+ const thumbnail = item.thumbnail ||
63
+ item.image ||
64
+ ((_b = (_a = item.files) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) ||
65
+ '';
66
+ return {
67
+ id: item.id,
68
+ title,
69
+ description: item.description,
70
+ thumbnail: thumbnail || undefined,
71
+ contentsId,
72
+ };
73
+ }
74
+ function extractResults(item, locale) {
75
+ const meta = parseMeta(item.metadata);
76
+ let quizConfig = meta.quiz_configuration;
77
+ if (!quizConfig && 'quiz_configuration' in item) {
78
+ quizConfig = item.quiz_configuration;
79
+ }
80
+ if (!quizConfig)
81
+ return [];
82
+ const langs = quizConfig.langs;
83
+ if (!langs)
84
+ return [];
85
+ const localeUpper = locale.toUpperCase();
86
+ const localeUpper2 = locale.substring(0, 2).toUpperCase();
87
+ let langData = langs[localeUpper];
88
+ if (!langData)
89
+ langData = langs[localeUpper2];
90
+ if (!langData)
91
+ langData = langs[locale];
92
+ if (!langData)
93
+ return [];
94
+ const resultados = langData.resultados;
95
+ if (!Array.isArray(resultados))
96
+ return [];
97
+ return resultados
98
+ .map(r => ({
99
+ title: String(r.titulo || ''),
100
+ description: String(r.titulo || ''),
101
+ minPoints: typeof r.puntos_ini === 'number' ? r.puntos_ini : 0,
102
+ maxPoints: typeof r.puntos_fin === 'number' ? r.puntos_fin : 0,
103
+ }))
104
+ .filter(r => r.description);
105
+ }
106
+ function extractQuestions(item, locale) {
107
+ const meta = parseMeta(item.metadata);
108
+ let quizConfig = meta.quiz_configuration;
109
+ if (!quizConfig && 'quiz_configuration' in item) {
110
+ quizConfig = item.quiz_configuration;
111
+ }
112
+ if (!quizConfig)
113
+ return [];
114
+ const langs = quizConfig.langs;
115
+ if (!langs)
116
+ return [];
117
+ const localeUpper = locale.toUpperCase();
118
+ const localeUpper2 = locale.substring(0, 2).toUpperCase();
119
+ let langData = langs[localeUpper];
120
+ if (!langData)
121
+ langData = langs[localeUpper2];
122
+ if (!langData)
123
+ langData = langs[locale];
124
+ if (!langData)
125
+ return [];
126
+ const preguntas = langData.preguntas;
127
+ if (!Array.isArray(preguntas))
128
+ return [];
129
+ return preguntas
130
+ .map((pregunta, idx) => {
131
+ const titulo = String(pregunta.titulo || '');
132
+ if (!titulo)
133
+ return null;
134
+ const respuestas = pregunta.respuestas;
135
+ if (!Array.isArray(respuestas) || respuestas.length < 2)
136
+ return null;
137
+ const options = respuestas
138
+ .map(r => ({
139
+ text: String(r.titulo || ''),
140
+ points: typeof r.puntos === 'number' ? r.puntos : 0,
141
+ }))
142
+ .filter(o => o.text);
143
+ if (options.length < 2)
144
+ return null;
145
+ return {
146
+ id: `${item.id}_q${idx}`,
147
+ question: titulo,
148
+ options,
149
+ };
150
+ })
151
+ .filter(Boolean);
152
+ }
153
+ function normalizeResponse(json) {
154
+ const j = json;
155
+ if (Array.isArray(j))
156
+ return j;
157
+ if (j === null || j === void 0 ? void 0 : j.data) {
158
+ const data = j.data;
159
+ if (data.data && typeof data.data === 'object') {
160
+ const dataData = data.data;
161
+ if (dataData.data && typeof dataData.data === 'object') {
162
+ const datDataData = dataData.data;
163
+ if ('quiz_configuration' in datDataData) {
164
+ return [datDataData];
165
+ }
166
+ if (Array.isArray(datDataData))
167
+ return datDataData;
168
+ }
169
+ if (Array.isArray(dataData))
170
+ return dataData;
171
+ if (typeof dataData === 'object' && dataData !== null)
172
+ return [dataData];
173
+ }
174
+ if (Array.isArray(data.data))
175
+ return data.data;
176
+ if (Array.isArray(data.contents))
177
+ return data.contents;
178
+ if (Array.isArray(data))
179
+ return data;
180
+ if (typeof data === 'object' && data !== null)
181
+ return [data];
182
+ }
183
+ if (Array.isArray(j.contents))
184
+ return j.contents;
185
+ return [];
186
+ }
187
+ function QuizCard({ quiz, index, theme, texts, onClick }) {
188
+ const [hovered, setHovered] = (0, react_1.useState)(false);
189
+ return (react_1.default.createElement("div", { onClick: onClick, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), style: {
190
+ backgroundColor: theme.cardBackground,
191
+ border: `1.5px solid ${hovered ? theme.primaryColor : theme.cardBorderColor}`,
192
+ borderRadius: '16px',
193
+ overflow: 'hidden',
194
+ cursor: 'pointer',
195
+ transition: 'border-color 0.2s, transform 0.2s, box-shadow 0.2s',
196
+ transform: hovered ? 'translateY(-2px)' : 'none',
197
+ boxShadow: hovered ? '0 8px 24px rgba(0,0,0,0.12)' : '0 2px 8px rgba(0,0,0,0.06)',
198
+ display: 'flex',
199
+ flexDirection: 'column',
200
+ } },
201
+ react_1.default.createElement("div", { style: {
202
+ width: '100%',
203
+ aspectRatio: '16/9',
204
+ backgroundColor: theme.backgroundColor,
205
+ overflow: 'hidden',
206
+ position: 'relative',
207
+ display: 'flex',
208
+ alignItems: 'center',
209
+ justifyContent: 'center',
210
+ } }, quiz.thumbnail ? (react_1.default.createElement("img", { src: quiz.thumbnail, alt: quiz.title, style: { width: '100%', height: '100%', objectFit: 'cover' } })) : (react_1.default.createElement("div", { style: {
211
+ width: '56px',
212
+ height: '56px',
213
+ borderRadius: '50%',
214
+ backgroundColor: theme.primaryColor,
215
+ display: 'flex',
216
+ alignItems: 'center',
217
+ justifyContent: 'center',
218
+ color: theme.buttonTextColor,
219
+ fontSize: '24px',
220
+ fontWeight: 700,
221
+ } }, index + 1))),
222
+ react_1.default.createElement("div", { style: { padding: '16px', flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' } },
223
+ react_1.default.createElement("p", { style: {
224
+ color: theme.textColor,
225
+ fontSize: '15px',
226
+ lineHeight: 1.4,
227
+ margin: 0,
228
+ fontWeight: 700,
229
+ display: '-webkit-box',
230
+ WebkitLineClamp: 2,
231
+ WebkitBoxOrient: 'vertical',
232
+ overflow: 'hidden',
233
+ } }, quiz.title),
234
+ quiz.description && (react_1.default.createElement("p", { style: {
235
+ color: theme.neutralMid,
236
+ fontSize: '13px',
237
+ lineHeight: 1.4,
238
+ margin: 0,
239
+ display: '-webkit-box',
240
+ WebkitLineClamp: 2,
241
+ WebkitBoxOrient: 'vertical',
242
+ overflow: 'hidden',
243
+ } }, quiz.description)),
244
+ react_1.default.createElement("button", { style: {
245
+ marginTop: 'auto',
246
+ padding: '8px 16px',
247
+ borderRadius: '20px',
248
+ border: 'none',
249
+ backgroundColor: theme.buttonColor,
250
+ color: theme.buttonTextColor,
251
+ fontSize: '13px',
252
+ fontWeight: 600,
253
+ cursor: 'pointer',
254
+ transition: 'opacity 0.2s',
255
+ }, onMouseEnter: (e) => { e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { e.currentTarget.style.opacity = '1'; } }, texts.startQuiz))));
256
+ }
257
+ function QuizModal({ questions, results, startIndex, theme, texts, onClose }) {
258
+ var _a;
259
+ const [currentIndex, setCurrentIndex] = (0, react_1.useState)(startIndex);
260
+ const [answers, setAnswers] = (0, react_1.useState)(new Map());
261
+ const [finished, setFinished] = (0, react_1.useState)(false);
262
+ const current = questions[currentIndex];
263
+ const total = questions.length;
264
+ const isPointsBased = current.correctIndex === undefined;
265
+ const selectedOption = (_a = answers.get(currentIndex)) !== null && _a !== void 0 ? _a : null;
266
+ function handleSelect(optionIndex) {
267
+ setAnswers(prev => new Map(prev).set(currentIndex, optionIndex));
268
+ }
269
+ function handlePrevious() {
270
+ if (currentIndex > 0) {
271
+ setCurrentIndex(i => i - 1);
272
+ }
273
+ }
274
+ function handleNext() {
275
+ if (currentIndex + 1 >= total) {
276
+ setFinished(true);
277
+ }
278
+ else {
279
+ setCurrentIndex((i) => i + 1);
280
+ }
281
+ }
282
+ function handleRetry() {
283
+ setCurrentIndex(startIndex);
284
+ setAnswers(new Map());
285
+ setFinished(false);
286
+ }
287
+ function handleOverlayClick(e) {
288
+ if (e.target === e.currentTarget)
289
+ onClose();
290
+ }
291
+ (0, react_1.useEffect)(() => {
292
+ function handleKey(e) {
293
+ if (e.key === 'Escape')
294
+ onClose();
295
+ }
296
+ window.addEventListener('keydown', handleKey);
297
+ return () => window.removeEventListener('keydown', handleKey);
298
+ }, [onClose]);
299
+ (0, react_1.useEffect)(() => {
300
+ document.body.style.overflow = 'hidden';
301
+ return () => { document.body.style.overflow = ''; };
302
+ }, []);
303
+ const overlayStyle = {
304
+ position: 'fixed',
305
+ inset: 0,
306
+ zIndex: 9999,
307
+ backgroundColor: 'rgba(0,0,0,0.6)',
308
+ display: 'flex',
309
+ alignItems: 'center',
310
+ justifyContent: 'center',
311
+ padding: '16px',
312
+ };
313
+ const modalStyle = {
314
+ backgroundColor: theme.cardBackground,
315
+ borderRadius: '20px',
316
+ width: '100%',
317
+ maxWidth: '560px',
318
+ maxHeight: '90vh',
319
+ overflowY: 'auto',
320
+ padding: '32px 28px',
321
+ position: 'relative',
322
+ display: 'flex',
323
+ flexDirection: 'column',
324
+ gap: '20px',
325
+ };
326
+ if (finished) {
327
+ let score = 0;
328
+ answers.forEach((optionIdx, questionIdx) => {
329
+ const question = questions[questionIdx];
330
+ if (question.correctIndex === undefined) {
331
+ score += question.options[optionIdx].points;
332
+ }
333
+ else {
334
+ if (optionIdx === question.correctIndex) {
335
+ score += 1;
336
+ }
337
+ }
338
+ });
339
+ let resultMessage;
340
+ const firstQuestion = questions[0];
341
+ const isQuizPointsBased = firstQuestion.correctIndex === undefined;
342
+ if (isQuizPointsBased && results && results.length > 0) {
343
+ const matchedResult = results.find(r => score >= r.minPoints && score <= r.maxPoints);
344
+ resultMessage = matchedResult === null || matchedResult === void 0 ? void 0 : matchedResult.description;
345
+ }
346
+ return (react_1.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick },
347
+ react_1.default.createElement("div", { style: modalStyle },
348
+ react_1.default.createElement("button", { onClick: onClose, "aria-label": texts.closeButton, style: {
349
+ position: 'absolute',
350
+ top: '16px',
351
+ right: '16px',
352
+ background: 'none',
353
+ border: 'none',
354
+ cursor: 'pointer',
355
+ color: theme.neutralMid,
356
+ fontSize: '20px',
357
+ lineHeight: 1,
358
+ } }, "\u2715"),
359
+ react_1.default.createElement("div", { style: { textAlign: 'center', paddingTop: '8px' } },
360
+ react_1.default.createElement("div", { style: {
361
+ width: '80px',
362
+ height: '80px',
363
+ borderRadius: '50%',
364
+ backgroundColor: theme.primaryColor,
365
+ margin: '0 auto 20px',
366
+ display: 'flex',
367
+ alignItems: 'center',
368
+ justifyContent: 'center',
369
+ fontSize: '32px',
370
+ color: theme.buttonTextColor,
371
+ } }, "\uD83C\uDFC6"),
372
+ isQuizPointsBased ? (react_1.default.createElement(react_1.default.Fragment, null,
373
+ react_1.default.createElement("p", { style: {
374
+ fontSize: '18px',
375
+ fontWeight: 600,
376
+ color: theme.textColor,
377
+ margin: '0 0 16px',
378
+ } }, formatLabel(texts.scoreLabel, { score, total: score })),
379
+ resultMessage && (react_1.default.createElement("p", { style: {
380
+ fontSize: '15px',
381
+ lineHeight: 1.6,
382
+ color: theme.neutralMid,
383
+ margin: 0,
384
+ textAlign: 'left',
385
+ } }, resultMessage)))) : (react_1.default.createElement("p", { style: {
386
+ fontSize: '22px',
387
+ fontWeight: 700,
388
+ color: theme.textColor,
389
+ margin: '0 0 8px',
390
+ } }, formatLabel(texts.scoreLabel, { score, total })))),
391
+ react_1.default.createElement("div", { style: { display: 'flex', gap: '12px', marginTop: '8px' } },
392
+ react_1.default.createElement("button", { onClick: handleRetry, style: {
393
+ flex: 1,
394
+ padding: '12px',
395
+ borderRadius: '12px',
396
+ border: `1.5px solid ${theme.primaryColor}`,
397
+ backgroundColor: 'transparent',
398
+ color: theme.primaryColor,
399
+ fontWeight: 600,
400
+ cursor: 'pointer',
401
+ fontSize: '14px',
402
+ } }, texts.retryButton),
403
+ react_1.default.createElement("button", { onClick: onClose, style: {
404
+ flex: 1,
405
+ padding: '12px',
406
+ borderRadius: '12px',
407
+ border: 'none',
408
+ backgroundColor: theme.primaryColor,
409
+ color: theme.buttonTextColor,
410
+ fontWeight: 600,
411
+ cursor: 'pointer',
412
+ fontSize: '14px',
413
+ } }, texts.closeButton)))));
414
+ }
415
+ const isCorrect = !isPointsBased && selectedOption !== null && selectedOption === current.correctIndex;
416
+ return (react_1.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick },
417
+ react_1.default.createElement("div", { style: modalStyle },
418
+ react_1.default.createElement("button", { onClick: onClose, "aria-label": texts.closeButton, style: {
419
+ position: 'absolute',
420
+ top: '16px',
421
+ right: '16px',
422
+ background: 'none',
423
+ border: 'none',
424
+ cursor: 'pointer',
425
+ color: theme.neutralMid,
426
+ fontSize: '20px',
427
+ lineHeight: 1,
428
+ } }, "\u2715"),
429
+ react_1.default.createElement("div", { style: { paddingTop: '4px' } },
430
+ react_1.default.createElement("div", { style: {
431
+ display: 'flex',
432
+ justifyContent: 'space-between',
433
+ alignItems: 'center',
434
+ marginBottom: '8px',
435
+ } },
436
+ react_1.default.createElement("span", { style: { fontSize: '12px', color: theme.neutralMid } }, formatLabel(texts.questionLabel, { current: currentIndex + 1, total }))),
437
+ react_1.default.createElement("div", { style: {
438
+ height: '4px',
439
+ borderRadius: '2px',
440
+ backgroundColor: theme.cardBorderColor,
441
+ overflow: 'hidden',
442
+ } },
443
+ react_1.default.createElement("div", { style: {
444
+ height: '100%',
445
+ width: `${((currentIndex + 1) / total) * 100}%`,
446
+ backgroundColor: theme.primaryColor,
447
+ transition: 'width 0.3s',
448
+ } }))),
449
+ current.thumbnail && (react_1.default.createElement("div", { style: {
450
+ borderRadius: '12px',
451
+ overflow: 'hidden',
452
+ aspectRatio: '16/9',
453
+ } },
454
+ react_1.default.createElement("img", { src: current.thumbnail, alt: current.question, style: { width: '100%', height: '100%', objectFit: 'cover' } }))),
455
+ react_1.default.createElement("p", { style: {
456
+ fontSize: '18px',
457
+ fontWeight: 700,
458
+ color: theme.textColor,
459
+ margin: 0,
460
+ lineHeight: 1.45,
461
+ } }, current.question),
462
+ react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' } }, current.options.map((option, idx) => {
463
+ let bg = theme.cardBackground;
464
+ let border = theme.cardBorderColor;
465
+ let color = theme.textColor;
466
+ const hasAnswer = selectedOption !== null;
467
+ if (hasAnswer && !isPointsBased) {
468
+ if (idx === current.correctIndex) {
469
+ bg = '#E8F5E9';
470
+ border = '#4CAF50';
471
+ color = '#1B5E20';
472
+ }
473
+ else if (idx === selectedOption) {
474
+ bg = '#FFEBEE';
475
+ border = '#F44336';
476
+ color = '#B71C1C';
477
+ }
478
+ }
479
+ else if (idx === selectedOption) {
480
+ bg = theme.primaryColor;
481
+ color = theme.buttonTextColor;
482
+ border = theme.primaryColor;
483
+ }
484
+ return (react_1.default.createElement("button", { key: idx, onClick: () => handleSelect(idx), style: {
485
+ padding: '12px 16px',
486
+ borderRadius: '12px',
487
+ border: `1.5px solid ${border}`,
488
+ backgroundColor: bg,
489
+ color,
490
+ fontSize: '14px',
491
+ fontWeight: 500,
492
+ textAlign: 'left',
493
+ cursor: 'pointer',
494
+ transition: 'all 0.2s',
495
+ lineHeight: 1.5,
496
+ } }, option.text));
497
+ })),
498
+ selectedOption !== null && !isPointsBased && (react_1.default.createElement("p", { style: {
499
+ fontSize: '14px',
500
+ fontWeight: 600,
501
+ color: isCorrect ? '#2E7D32' : '#C62828',
502
+ margin: 0,
503
+ } },
504
+ isCorrect ? texts.correctAnswer : texts.wrongAnswer,
505
+ current.explanation && (react_1.default.createElement("span", { style: { fontWeight: 400, display: 'block', marginTop: 4 } }, current.explanation)))),
506
+ react_1.default.createElement("div", { style: { display: 'flex', gap: '12px' } },
507
+ currentIndex > 0 && (react_1.default.createElement("button", { onClick: handlePrevious, style: {
508
+ flex: 1,
509
+ padding: '14px',
510
+ borderRadius: '12px',
511
+ border: `1.5px solid ${theme.primaryColor}`,
512
+ backgroundColor: 'transparent',
513
+ color: theme.primaryColor,
514
+ fontWeight: 700,
515
+ fontSize: '15px',
516
+ cursor: 'pointer',
517
+ transition: 'opacity 0.2s',
518
+ }, onMouseEnter: (e) => { e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { e.currentTarget.style.opacity = '1'; } },
519
+ "\u2190 ",
520
+ texts.previousButton)),
521
+ react_1.default.createElement("button", { onClick: handleNext, disabled: selectedOption === null, style: {
522
+ flex: currentIndex > 0 ? 1 : 'auto',
523
+ width: currentIndex === 0 ? '100%' : 'auto',
524
+ padding: '14px',
525
+ borderRadius: '12px',
526
+ border: 'none',
527
+ backgroundColor: selectedOption === null ? theme.neutralMid : theme.primaryColor,
528
+ color: theme.buttonTextColor,
529
+ fontWeight: 700,
530
+ fontSize: '15px',
531
+ cursor: selectedOption === null ? 'not-allowed' : 'pointer',
532
+ transition: 'opacity 0.2s',
533
+ opacity: selectedOption === null ? 0.5 : 1,
534
+ }, onMouseEnter: (e) => { if (selectedOption !== null)
535
+ e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { if (selectedOption !== null)
536
+ e.currentTarget.style.opacity = '1'; } }, currentIndex + 1 >= total ? texts.submitButton : texts.nextButton)))));
537
+ }
538
+ const DEFAULT_THEME = {
539
+ primaryColor: '#FF2273',
540
+ primaryHoverColor: '#E81F69',
541
+ textColor: '#0F1F35',
542
+ backgroundColor: '#F5F5F5',
543
+ cardBackground: '#FFFFFF',
544
+ buttonColor: '#FF2273',
545
+ buttonTextColor: '#FFFFFF',
546
+ neutralMid: '#8C8C8C',
547
+ cardBorderColor: 'rgba(15,31,53,0.1)',
548
+ titleDarkColor: '#210F5C',
549
+ };
550
+ const DEFAULT_TEXTS = {
551
+ title: 'Quizzes',
552
+ subtitle: 'Test your knowledge',
553
+ loading: 'Loading quizzes...',
554
+ noItems: 'No quizzes available',
555
+ loadMore: 'Load More',
556
+ startQuiz: 'Start Quiz',
557
+ questionLabel: 'Question {current} of {total}',
558
+ nextButton: 'Next',
559
+ previousButton: 'Previous',
560
+ submitButton: 'Submit',
561
+ correctAnswer: 'Correct!',
562
+ wrongAnswer: 'Incorrect',
563
+ retryButton: 'Retry',
564
+ closeButton: 'Close',
565
+ scoreLabel: 'You got {score}/{total} correct',
566
+ loadingQuestions: 'Loading questions...',
567
+ };
568
+ function Quiz({ config, theme: themeP, texts: textsP, onQuizStart, onQuizComplete }) {
569
+ const theme = Object.assign(Object.assign({}, DEFAULT_THEME), themeP);
570
+ const texts = Object.assign(Object.assign({}, DEFAULT_TEXTS), textsP);
571
+ const { apiUrl, questionsApiUrl, tags, includeIds, locale, initialCount = 12, loadMoreCount = 8 } = config;
572
+ const [quizItems, setQuizItems] = (0, react_1.useState)([]);
573
+ const [loading, setLoading] = (0, react_1.useState)(true);
574
+ const [visibleCount, setVisibleCount] = (0, react_1.useState)(initialCount);
575
+ const [activeQuiz, setActiveQuiz] = (0, react_1.useState)(null);
576
+ const [activeQuestions, setActiveQuestions] = (0, react_1.useState)([]);
577
+ const [activeResults, setActiveResults] = (0, react_1.useState)([]);
578
+ const [loadingQuestions, setLoadingQuestions] = (0, react_1.useState)(false);
579
+ const fetchList = (0, react_1.useCallback)(async () => {
580
+ setLoading(true);
581
+ try {
582
+ const res = await fetch(apiUrl, {
583
+ method: 'POST',
584
+ headers: { 'Content-Type': 'application/json' },
585
+ body: JSON.stringify(Object.assign({ language: locale || 'en', tags: tags || [] }, (includeIds && includeIds.length > 0 ? { includeIds } : {}))),
586
+ });
587
+ if (!res.ok)
588
+ throw new Error(`API error ${res.status}`);
589
+ const json = await res.json();
590
+ const raw = normalizeResponse(json);
591
+ const parsed = raw.map(toQuizItem).filter((q) => q !== null);
592
+ const uniqueIds = new Set();
593
+ const unique = parsed.filter(item => {
594
+ if (uniqueIds.has(item.id))
595
+ return false;
596
+ uniqueIds.add(item.id);
597
+ return true;
598
+ });
599
+ setQuizItems(unique);
600
+ }
601
+ catch (err) {
602
+ console.error('[Quiz] fetch error:', err);
603
+ setQuizItems([]);
604
+ }
605
+ finally {
606
+ setLoading(false);
607
+ }
608
+ }, [apiUrl, locale, tags, includeIds]);
609
+ (0, react_1.useEffect)(() => {
610
+ fetchList();
611
+ }, [fetchList]);
612
+ const handleCardClick = (0, react_1.useCallback)(async (quiz) => {
613
+ setActiveQuiz(quiz);
614
+ setLoadingQuestions(true);
615
+ if (onQuizStart) {
616
+ onQuizStart(quiz);
617
+ }
618
+ try {
619
+ const url = questionsApiUrl || apiUrl;
620
+ const res = await fetch(url, {
621
+ method: 'POST',
622
+ headers: { 'Content-Type': 'application/json' },
623
+ body: JSON.stringify({
624
+ preset: 'getQuiz',
625
+ params: {
626
+ quiz_id: quiz.contentsId,
627
+ language: locale || 'en',
628
+ },
629
+ }),
630
+ });
631
+ if (!res.ok)
632
+ throw new Error(`API error ${res.status}`);
633
+ const json = await res.json();
634
+ const raw = normalizeResponse(json);
635
+ if (raw.length === 0) {
636
+ console.error('[Quiz] No data returned from questions API');
637
+ setLoadingQuestions(false);
638
+ return;
639
+ }
640
+ const item = raw[0];
641
+ const questions = extractQuestions(item, locale || 'en');
642
+ const results = extractResults(item, locale || 'en');
643
+ if (questions.length === 0) {
644
+ console.error('[Quiz] No questions found');
645
+ }
646
+ setActiveQuestions(questions);
647
+ setActiveResults(results);
648
+ }
649
+ catch (err) {
650
+ console.error('[Quiz] fetch questions error:', err);
651
+ setActiveQuestions([]);
652
+ setActiveResults([]);
653
+ }
654
+ finally {
655
+ setLoadingQuestions(false);
656
+ }
657
+ }, [apiUrl, questionsApiUrl, locale, onQuizStart]);
658
+ const handleCloseModal = (0, react_1.useCallback)(() => {
659
+ setActiveQuiz(null);
660
+ setActiveQuestions([]);
661
+ setActiveResults([]);
662
+ }, []);
663
+ const visible = quizItems.slice(0, visibleCount);
664
+ const hasMore = visibleCount < quizItems.length;
665
+ return (react_1.default.createElement("div", { style: { backgroundColor: theme.backgroundColor, minHeight: '100vh' } },
666
+ react_1.default.createElement("div", { style: { padding: '40px 16px', maxWidth: '1200px', margin: '0 auto' } },
667
+ react_1.default.createElement("div", { style: { textAlign: 'center', marginBottom: '32px' } },
668
+ react_1.default.createElement("h2", { style: {
669
+ fontSize: '28px',
670
+ fontWeight: 700,
671
+ color: theme.titleDarkColor,
672
+ margin: '0 0 8px',
673
+ } }, texts.title),
674
+ texts.subtitle && (react_1.default.createElement("p", { style: {
675
+ fontSize: '16px',
676
+ color: theme.neutralMid,
677
+ margin: 0,
678
+ } }, texts.subtitle))),
679
+ loading ? (react_1.default.createElement("div", { style: { textAlign: 'center', padding: '40px', color: theme.neutralMid } }, texts.loading)) : quizItems.length === 0 ? (react_1.default.createElement("div", { style: { textAlign: 'center', padding: '40px', color: theme.neutralMid } }, texts.noItems)) : (react_1.default.createElement(react_1.default.Fragment, null,
680
+ react_1.default.createElement("div", { style: {
681
+ display: 'grid',
682
+ gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
683
+ gap: '20px',
684
+ marginBottom: '32px',
685
+ } }, visible.map((quiz, idx) => (react_1.default.createElement(QuizCard, { key: quiz.id, quiz: quiz, index: idx, theme: theme, texts: texts, onClick: () => handleCardClick(quiz) })))),
686
+ hasMore && (react_1.default.createElement("div", { style: { textAlign: 'center' } },
687
+ react_1.default.createElement("button", { onClick: () => setVisibleCount(v => v + loadMoreCount), style: {
688
+ padding: '12px 32px',
689
+ borderRadius: '24px',
690
+ border: `1.5px solid ${theme.primaryColor}`,
691
+ backgroundColor: 'transparent',
692
+ color: theme.primaryColor,
693
+ fontWeight: 600,
694
+ fontSize: '15px',
695
+ cursor: 'pointer',
696
+ transition: 'all 0.2s',
697
+ }, onMouseEnter: (e) => {
698
+ e.currentTarget.style.backgroundColor = theme.primaryColor;
699
+ e.currentTarget.style.color = theme.buttonTextColor;
700
+ }, onMouseLeave: (e) => {
701
+ e.currentTarget.style.backgroundColor = 'transparent';
702
+ e.currentTarget.style.color = theme.primaryColor;
703
+ } }, texts.loadMore)))))),
704
+ activeQuiz && loadingQuestions && (react_1.default.createElement("div", { style: {
705
+ position: 'fixed',
706
+ inset: 0,
707
+ zIndex: 9999,
708
+ backgroundColor: 'rgba(0,0,0,0.6)',
709
+ display: 'flex',
710
+ alignItems: 'center',
711
+ justifyContent: 'center',
712
+ } },
713
+ react_1.default.createElement("div", { style: {
714
+ backgroundColor: theme.cardBackground,
715
+ borderRadius: '20px',
716
+ padding: '40px',
717
+ textAlign: 'center',
718
+ color: theme.textColor,
719
+ } }, texts.loadingQuestions))),
720
+ activeQuiz && !loadingQuestions && activeQuestions.length > 0 && (react_1.default.createElement(QuizModal, { questions: activeQuestions, results: activeResults, startIndex: 0, theme: theme, texts: texts, onClose: handleCloseModal }))));
721
+ }
722
+ function QuizForYouCard({ title, description, ctaText, ctaHref, desktopImage, mobileImage, imageAlt = '', imageOnRight = false, titleColor = '#210F5C', descriptionColor = '#0F1F35', ctaColor = '#FF2273', ctaHoverColor = '#E81F69', backgroundColor = '#FFFFFF', paddingClass = '', }) {
723
+ return (react_1.default.createElement("div", { style: { backgroundColor, width: '100%' }, className: paddingClass },
724
+ react_1.default.createElement("div", { style: {
725
+ display: 'flex',
726
+ flexDirection: imageOnRight ? 'row-reverse' : 'row',
727
+ minHeight: '420px',
728
+ alignItems: 'stretch',
729
+ } },
730
+ react_1.default.createElement("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '40px' } },
731
+ react_1.default.createElement("div", { style: { maxWidth: '400px', textAlign: 'center' } },
732
+ react_1.default.createElement("h2", { style: { color: titleColor, fontSize: '32px', fontWeight: 700, marginBottom: '16px' } }, title),
733
+ react_1.default.createElement("p", { style: { color: descriptionColor, fontSize: '16px', marginBottom: '24px' } }, description),
734
+ react_1.default.createElement("a", { href: ctaHref, style: {
735
+ display: 'inline-block',
736
+ padding: '12px 32px',
737
+ borderRadius: '24px',
738
+ backgroundColor: ctaColor,
739
+ color: '#fff',
740
+ textDecoration: 'none',
741
+ fontWeight: 600,
742
+ transition: 'background-color 0.2s',
743
+ }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = ctaHoverColor; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = ctaColor; } }, ctaText))),
744
+ react_1.default.createElement("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px' } },
745
+ react_1.default.createElement("img", { src: desktopImage, alt: imageAlt, style: { maxWidth: '100%', height: 'auto' } })))));
746
+ }
747
+ exports.default = Quiz;
748
+ //# sourceMappingURL=Quiz.js.map