@everymatrix/user-actions 1.90.27 → 1.90.28

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.
@@ -0,0 +1,631 @@
1
+ import { r as registerInstance, h } from './index-ec24e8d4.js';
2
+
3
+ const actionsMapping = {
4
+ "verification-popup": {
5
+ "emit": "openKycVerificationModal",
6
+ "listen": "closeKycVerificationModal"
7
+ },
8
+ "get-temporary-account-consents": {
9
+ "emit": "openTemporaryConsentsModal",
10
+ "listen": "closeTemporaryConsentsModal"
11
+ },
12
+ "limits-popup": {
13
+ "emit": "openLugasPopup",
14
+ "listen": "closeLugasPopup"
15
+ },
16
+ "video-verification-popup": {
17
+ "emit": "openKycVerificationModal",
18
+ "listen": "closeKycVerificationModal"
19
+ },
20
+ "unverified-phone-number": {
21
+ "emit": "openSmsVerificationModal",
22
+ "listen": "closeSmsVerificationModal"
23
+ },
24
+ "expired-consents": {
25
+ "emit": "openExpiredConsentsModal",
26
+ "listen": "closeExpiredConsentsModal"
27
+ },
28
+ "financial-limit-notification": {
29
+ "emit": "openLimitNotificationModal",
30
+ "listen": "closeLimitNotificationModal"
31
+ },
32
+ "account-review-notification": {
33
+ "emit": "openAccountReviewModal",
34
+ "listen": "closeAccountReviewModal"
35
+ },
36
+ "accept-tax-consent": {
37
+ "emit": "openStakeModal",
38
+ "listen": "closeStakeModal"
39
+ }
40
+ };
41
+
42
+ const userActionsCss = ":host{display:block}";
43
+ const UserActionsStyle0 = userActionsCss;
44
+
45
+ const UserActions = class {
46
+ constructor(hostRef) {
47
+ registerInstance(this, hostRef);
48
+ this.emitCurrentActionEvent = () => {
49
+ window.postMessage({ type: actionsMapping[this.actionStack[0].action].emit });
50
+ };
51
+ this.shiftActionStack = () => {
52
+ this.actionStack = this.actionStack.slice(1);
53
+ };
54
+ this.mbSource = undefined;
55
+ this.endpoint = undefined;
56
+ this.userid = undefined;
57
+ this.operatorid = undefined;
58
+ this.playercurrency = 'EUR';
59
+ this.hasfundsacknowledgment = 'false';
60
+ this.session = "";
61
+ this.language = 'en';
62
+ this.clientStyling = undefined;
63
+ this.clientStylingUrl = undefined;
64
+ this.translationUrl = '';
65
+ this.currencylocale = 'en';
66
+ this.currencydisplay = 'symbol';
67
+ this.maximumfractiondigits = '2';
68
+ this.minimumfractiondigits = '0';
69
+ this.customdisplayformat = '';
70
+ this.alwaysshowdecimals = 'true';
71
+ this.actionStack = [];
72
+ this.customerFundsProtectionActive = false;
73
+ }
74
+ handleEvent(e) {
75
+ var _a, _b;
76
+ if (((_b = actionsMapping[(_a = this.actionStack[0]) === null || _a === void 0 ? void 0 : _a.action]) === null || _b === void 0 ? void 0 : _b.listen) === e.data.type) {
77
+ this.shiftActionStack();
78
+ if (this.actionStack.length > 0)
79
+ this.emitCurrentActionEvent();
80
+ }
81
+ }
82
+ fetchUserActions() {
83
+ const url = new URL(`${this.endpoint}/v1/player/${this.userid}/legislation/actions`);
84
+ return fetch(url.href)
85
+ .then((response) => response.json())
86
+ .then(data => {
87
+ var _a, _b;
88
+ // filtering necessary to prevent widget from throwing "cannot read properties of 'undefined'"
89
+ // when the actions received are not part of actionsMapping
90
+ this.actionStack = data.actions.filter(action => actionsMapping[action.action]);
91
+ if (this.actionStack.length > 0)
92
+ this.emitCurrentActionEvent();
93
+ this.customerFundsProtectionActive = (_b = (_a = data.actions) === null || _a === void 0 ? void 0 : _a.some((item) => item.action === "customer-funds-protection")) !== null && _b !== void 0 ? _b : false;
94
+ // signal to prompt modal
95
+ if (this.customerFundsProtectionActive) {
96
+ window.postMessage({ type: 'ProtectionFundsActive' }, window.location.href);
97
+ }
98
+ });
99
+ }
100
+ componentWillLoad() {
101
+ return this.fetchUserActions();
102
+ }
103
+ render() {
104
+ if (!this.customerFundsProtectionActive || this.hasfundsacknowledgment === 'false') {
105
+ return;
106
+ }
107
+ else {
108
+ return (h("user-funds-acknowledgment", { endpoint: this.endpoint, session: this.session, operatorid: this.operatorid, language: this.language, "mb-source": this.mbSource, "client-styling": this.clientStyling, "client-styling-url": this.clientStylingUrl, "translation-url": this.translationUrl, currencylocale: this.currencylocale, currencydisplay: this.currencydisplay, maximumfractiondigits: this.maximumfractiondigits, minimumfractiondigits: this.minimumfractiondigits, playercurrency: this.playercurrency }));
109
+ }
110
+ }
111
+ };
112
+ UserActions.style = UserActionsStyle0;
113
+
114
+ const StyleCacheKey = '__WIDGET_GLOBAL_STYLE_CACHE__';
115
+
116
+ /**
117
+ * @name setClientStyling
118
+ * @description Method used to create and append to the passed element of the widget a style element with the content received
119
+ * @param {HTMLElement} stylingContainer The reference element of the widget
120
+ * @param {string} clientStyling The style content
121
+ */
122
+ function setClientStyling(stylingContainer, clientStyling) {
123
+ if (stylingContainer) {
124
+ const sheet = document.createElement('style');
125
+ sheet.innerHTML = clientStyling;
126
+ stylingContainer.appendChild(sheet);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * @name setClientStylingURL
132
+ * @description Method used to create and append to the passed element of the widget a style element with the content fetched from a given URL
133
+ * @param {HTMLElement} stylingContainer The reference element of the widget
134
+ * @param {string} clientStylingUrl The URL of the style content
135
+ */
136
+ function setClientStylingURL(stylingContainer, clientStylingUrl) {
137
+ if (!stylingContainer || !clientStylingUrl) return;
138
+
139
+ const url = new URL(clientStylingUrl);
140
+
141
+ fetch(url.href)
142
+ .then((res) => res.text())
143
+ .then((data) => {
144
+ const cssFile = document.createElement('style');
145
+ cssFile.innerHTML = data;
146
+ if (stylingContainer) {
147
+ stylingContainer.appendChild(cssFile);
148
+ }
149
+ })
150
+ .catch((err) => {
151
+ console.error('There was an error while trying to load client styling from URL', err);
152
+ });
153
+ }
154
+
155
+ /**
156
+ * @name setStreamLibrary
157
+ * @description Method used to create and append to the passed element of the widget a style element with content fetched from the MessageBus
158
+ * @param {HTMLElement} stylingContainer The highest element of the widget
159
+ * @param {string} domain The domain from where the content should be fetched (e.g. 'Casino.Style', 'App.Style', 'casino-footer.style', etc.)
160
+ * @param {ref} subscription A reference to a variable where the subscription should be saved for unsubscribing when no longer needed
161
+ * @param {boolean} useAdoptedStyleSheets A flag to gradually enable testing of adoptedStyleSheets
162
+ */
163
+ function setStreamStyling(stylingContainer, domain, subscription, useAdoptedStyleSheets = false) {
164
+ if (!window.emMessageBus) return;
165
+
166
+ const supportAdoptStyle = 'adoptedStyleSheets' in Document.prototype;
167
+
168
+ if (!supportAdoptStyle || !useAdoptedStyleSheets) {
169
+ subscription = getStyleTagSubscription(stylingContainer, domain);
170
+
171
+ return subscription;
172
+ }
173
+
174
+ if (!window[StyleCacheKey]) {
175
+ window[StyleCacheKey] = {};
176
+ }
177
+ subscription = getAdoptStyleSubscription(stylingContainer, domain);
178
+
179
+ const originalUnsubscribe = subscription.unsubscribe.bind(subscription);
180
+ const wrappedUnsubscribe = () => {
181
+ if (window[StyleCacheKey][domain]) {
182
+ const cachedObject = window[StyleCacheKey][domain];
183
+ cachedObject.refCount > 1
184
+ ? (cachedObject.refCount = cachedObject.refCount - 1)
185
+ : delete window[StyleCacheKey][domain];
186
+ }
187
+
188
+ originalUnsubscribe();
189
+ };
190
+ subscription.unsubscribe = wrappedUnsubscribe;
191
+
192
+ return subscription;
193
+ }
194
+
195
+ function getStyleTagSubscription(stylingContainer, domain) {
196
+ const sheet = document.createElement('style');
197
+
198
+ return window.emMessageBus.subscribe(domain, (data) => {
199
+ if (stylingContainer) {
200
+ sheet.innerHTML = data;
201
+ stylingContainer.appendChild(sheet);
202
+ }
203
+ });
204
+ }
205
+
206
+ function getAdoptStyleSubscription(stylingContainer, domain) {
207
+ return window.emMessageBus.subscribe(domain, (data) => {
208
+ if (!stylingContainer) return;
209
+
210
+ const shadowRoot = stylingContainer.getRootNode();
211
+ const cacheStyleObject = window[StyleCacheKey];
212
+ let cachedStyle = cacheStyleObject[domain] && cacheStyleObject[domain].sheet;
213
+
214
+ if (!cachedStyle) {
215
+ cachedStyle = new CSSStyleSheet();
216
+ cachedStyle.replaceSync(data);
217
+ cacheStyleObject[domain] = {
218
+ sheet: cachedStyle,
219
+ refCount: 1
220
+ };
221
+ } else {
222
+ cacheStyleObject[domain].refCount = cacheStyleObject[domain].refCount + 1;
223
+ }
224
+
225
+ const currentSheets = shadowRoot.adoptedStyleSheets || [];
226
+ if (!currentSheets.includes(cachedStyle)) {
227
+ shadowRoot.adoptedStyleSheets = [...currentSheets, cachedStyle];
228
+ }
229
+ });
230
+ }
231
+
232
+ const DEFAULT_LANGUAGE = 'en';
233
+ const TRANSLATIONS = {
234
+ en: {
235
+ protectionTitle: 'Protection of Customer Funds',
236
+ protectionContent: '<p>We hold customer funds separate from company funds.<sup class="note"><a href="https://www.gamblingcommission.gov.uk/guidance/customer-funds-segregation-disclosure-to-customers-and-reporting/example-statements-that-might-be-used-in-terms-and-conditions-for-each-of#ref-2" target="_blank">12</a></sup> These funds ar <b>not protected</b> in the event of insolvency: <b>not protected segregation.</b></p><p>For more information, please see the <a href="https://www.gamblingcommission.gov.uk/guidance/customer-funds-segregation-disclosure-to-customers-and-reporting/the-customer-funds-insolvency-ratings-system" target="_blank">customer funds insolvency ratings system</a>.</p>',
237
+ balanceArea: 'Your current balance:',
238
+ protectionCheckboxLabel: 'I understand that my funds are <b>not protected</b> if the operator becomes insolvent.',
239
+ userNoticeText: 'Before you can proceed you must consent to the following',
240
+ submitButtonText: 'Confirm',
241
+ serverNotResponding: 'Server might not be responding',
242
+ apiCallError: 'Request failed with status '
243
+ },
244
+ 'en-us': {
245
+ protectionTitle: 'Terms and Conditions',
246
+ protectionContent: 'We hold customer funds separate from company funds.',
247
+ balanceArea: 'Email marketing',
248
+ privacyPolicyTitle: 'Privacy Policy',
249
+ userNoticeText: 'Before you can proceed you must consent to the following',
250
+ submitButtonText: 'Submit',
251
+ rejectButtonText: 'Reject',
252
+ rejectText: 'Rejecting new consents will result in the inability to continue the login process and you will be logged out.',
253
+ consentUpdateSuccess: 'Consent update successful!',
254
+ serverNotResponding: 'Server might not be responding'
255
+ },
256
+ ro: {
257
+ protectionTitle: 'Termeni și Condiții',
258
+ protectionContent: 'We hold customer funds separate from company funds.',
259
+ balanceArea: 'Marketing prin Email',
260
+ privacyPolicyTitle: 'Politica de Confidențialitate',
261
+ userNoticeText: 'Înainte de a continua, trebuie să vă dați consimțământul pentru următoarele',
262
+ submitButtonText: 'Trimite',
263
+ rejectButtonText: 'Respinge',
264
+ rejectText: 'Respingerea noilor consimțăminte va duce la imposibilitatea de a continua procesul de autentificare și veți fi deconectat.',
265
+ consentUpdateSuccess: 'Actualizare consimțământ reușită!',
266
+ serverNotResponding: 'Serverul s-ar putea să nu răspundă'
267
+ },
268
+ hr: {
269
+ protectionTitle: 'Opći uvjeti i odredbe',
270
+ protectionContent: 'We hold customer funds separate from company funds.',
271
+ balanceArea: 'E-mail makretinški sadržaj',
272
+ privacyPolicyTitle: 'Politika Privatnosti',
273
+ userNoticeText: 'Prije nego što možete nastaviti, morate pristati na sljedeće',
274
+ submitButtonText: 'Pošalji',
275
+ rejectButtonText: 'Odbij',
276
+ rejectText: 'Odbijanje novih pristanka rezultirat će nemogućnošću nastavka procesa prijave i bit ćete odjavljeni.',
277
+ consentUpdateSuccess: 'Ažuriranje pristanka uspješno!',
278
+ serverNotResponding: 'Poslužitelj možda ne odgovara'
279
+ },
280
+ fr: {
281
+ protectionTitle: 'Termes et Conditions',
282
+ protectionContent: 'We hold customer funds separate from company funds.',
283
+ balanceArea: 'Marketing par Email',
284
+ privacyPolicyTitle: 'Politique de Confidentialité',
285
+ userNoticeText: 'Avant de continuer, vous devez consentir aux éléments suivants',
286
+ submitButtonText: 'Soumettre',
287
+ rejectButtonText: 'Rejeter',
288
+ rejectText: 'Le rejet des nouveaux consentements entraînera l\'impossibilité de continuer le processus de connexion et vous serez déconnecté.',
289
+ consentUpdateSuccess: 'Mise à jour du consentement réussie!',
290
+ serverNotResponding: 'Le serveur ne répond peut-être pas'
291
+ },
292
+ cs: {
293
+ protectionTitle: 'Podmínky a ujednání',
294
+ protectionContent: 'We hold customer funds separate from company funds.',
295
+ balanceArea: 'Emailový marketing',
296
+ privacyPolicyTitle: 'Zásady ochrany osobních údajů',
297
+ userNoticeText: 'Než budete moci pokračovat, musíte souhlasit s následujícím',
298
+ submitButtonText: 'Odeslat',
299
+ rejectButtonText: 'Odmítnout',
300
+ rejectText: 'Odmítnutí nových souhlasů povede k nemožnosti pokračovat v procesu přihlášení a budete odhlášeni.',
301
+ consentUpdateSuccess: 'Aktualizace souhlasu proběhla úspěšně!',
302
+ serverNotResponding: 'Server možná neodpovídá'
303
+ },
304
+ de: {
305
+ protectionTitle: 'Allgemeine Geschäftsbedingungen',
306
+ protectionContent: 'We hold customer funds separate from company funds.',
307
+ balanceArea: 'E-Mail-Marketing',
308
+ privacyPolicyTitle: 'Datenschutzrichtlinie',
309
+ userNoticeText: 'Bevor Sie fortfahren können, müssen Sie den folgenden Punkten zustimmen',
310
+ submitButtonText: 'Absenden',
311
+ rejectButtonText: 'Ablehnen',
312
+ rejectText: 'Das Ablehnen neuer Zustimmungen führt dazu, dass der Anmeldevorgang nicht fortgesetzt werden kann und Sie abgemeldet werden.',
313
+ consentUpdateSuccess: 'Zustimmung erfolgreich aktualisiert!',
314
+ serverNotResponding: 'Der Server antwortet möglicherweise nicht'
315
+ },
316
+ es: {
317
+ protectionTitle: 'Términos y Condiciones',
318
+ protectionContent: 'We hold customer funds separate from company funds.',
319
+ balanceArea: 'Marketing por Email',
320
+ privacyPolicyTitle: 'Política de Privacidad',
321
+ userNoticeText: 'Antes de continuar, debe dar su consentimiento a lo siguiente',
322
+ submitButtonText: 'Enviar',
323
+ rejectButtonText: 'Rechazar',
324
+ rejectText: 'Rechazar nuevos consentimientos resultará en la imposibilidad de continuar el proceso de inicio de sesión y se cerrará la sesión.',
325
+ consentUpdateSuccess: '¡Actualización del consentimiento exitosa!',
326
+ serverNotResponding: 'El servidor podría no estar respondiendo'
327
+ },
328
+ pt: {
329
+ protectionTitle: 'Termos e Condições',
330
+ protectionContent: 'We hold customer funds separate from company funds.',
331
+ balanceArea: 'Marketing por Email',
332
+ privacyPolicyTitle: 'Política de Privacidade',
333
+ userNoticeText: 'Antes de continuar, você deve consentir com o seguinte',
334
+ submitButtonText: 'Enviar',
335
+ rejectButtonText: 'Rejeitar',
336
+ rejectText: 'Rejeitar novos consentimentos resultará na impossibilidade de continuar o processo de login e você será desconectado.',
337
+ consentUpdateSuccess: 'Atualização de consentimento bem-sucedida!',
338
+ serverNotResponding: 'O servidor pode não estar respondendo'
339
+ },
340
+ 'es-mx': {
341
+ protectionTitle: 'Términos y Condiciones',
342
+ protectionContent: 'We hold customer funds separate from company funds.',
343
+ balanceArea: 'Marketing por Email',
344
+ privacyPolicyTitle: 'Política de Privacidad',
345
+ userNoticeText: 'Antes de continuar, debe dar su consentimiento a lo siguiente',
346
+ submitButtonText: 'Enviar',
347
+ rejectButtonText: 'Rechazar',
348
+ rejectText: 'Rechazar nuevos consentimientos resultará en la imposibilidad de continuar el proceso de inicio de sesión y se cerrará la sesión.',
349
+ consentUpdateSuccess: '¡Actualización del consentimiento exitosa!',
350
+ serverNotResponding: 'El servidor podría no estar respondiendo'
351
+ },
352
+ 'pt-br': {
353
+ protectionTitle: 'Termos e Condições',
354
+ protectionContent: 'We hold customer funds separate from company funds.',
355
+ balanceArea: 'Marketing por Email',
356
+ privacyPolicyTitle: 'Política de Privacidade',
357
+ userNoticeText: 'Antes de continuar, você deve consentir com o seguinte',
358
+ submitButtonText: 'Enviar',
359
+ rejectButtonText: 'Rejeitar',
360
+ rejectText: 'Rejeitar novos consentimentos resultará na impossibilidade de continuar o processo de login e você será desconectado.',
361
+ consentUpdateSuccess: 'Atualização de consentimento bem-sucedida!',
362
+ serverNotResponding: 'O servidor pode não estar respondendo'
363
+ }
364
+ };
365
+ const getTranslations = (url) => {
366
+ return new Promise((resolve) => {
367
+ fetch(url)
368
+ .then((res) => res.json())
369
+ .then((data) => {
370
+ Object.keys(data).forEach((lang) => {
371
+ if (!TRANSLATIONS[lang]) {
372
+ TRANSLATIONS[lang] = {};
373
+ }
374
+ for (let key in data[lang]) {
375
+ TRANSLATIONS[lang][key] = data[lang][key];
376
+ }
377
+ });
378
+ resolve(true);
379
+ });
380
+ });
381
+ };
382
+ const translate = (key, customLang, values) => {
383
+ const lang = customLang;
384
+ let translation = TRANSLATIONS[(lang !== undefined) && (lang in TRANSLATIONS) ? lang : DEFAULT_LANGUAGE][key];
385
+ if (values !== undefined) {
386
+ for (const [key, value] of Object.entries(values.values)) {
387
+ const regex = new RegExp(`{${key}}`, 'g');
388
+ translation = translation.replace(regex, value);
389
+ }
390
+ }
391
+ return translation;
392
+ };
393
+
394
+ const userFundsAcknowledgmentCss = ":host{display:block}.QueryReferenceContainer{height:100%;width:100%}.UserProtectionFundsTitle{font-size:1.2rem;font-weight:200;text-align:center}.CloseButton{width:25px;height:25px;align-self:flex-end}.UserProtectionFundsContainer{font-family:inherit;font-weight:100;height:100%;padding:1rem 1.5rem;background-color:var(--emw--color-white, #FFFFFF);display:flex;flex-direction:column;justify-content:space-between;border-radius:var(--emw--border-radius-large, 20px);max-width:fit-content}.ConsentSubmitButton{font-size:1rem;font-family:var(--emw--button-typography);padding:0.4rem 1.4rem;background:var(--emw--button-background-color, #FFFFFF);border:var(--emw--button-border, 2px solid #000000);color:var(--emw--button-text-color, #000000);border-radius:var(--emw--button-border-radius, 10px);align-self:center;cursor:pointer}.ConsentSubmitButton:disabled{border:2px solid #ccc;color:#ccc;cursor:unset}.ButtonsWrapper{display:flex;flex-direction:column;margin-top:10px;gap:40px}.ButtonsWrapper button:only-child{margin-left:auto}.UserProtectionError{color:var(--emw--color-error, #FD2839);text-align:center;height:22px}@media screen and (max-width: 320px){.QueryReferenceContainer{font-size:0.8rem;color:var(--emw--button-text-color, #000000)}}.spinner{animation:rotate 2s linear infinite;z-index:2;position:absolute;top:50%;left:50%;margin:-25px 0 0 -25px;width:50px;height:50px}.spinner .path{stroke:var(--emw--login-color-primary, var(--emw--color-primary, #22B04E));stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{100%{transform:rotate(360deg)}}@keyframes dash{0%{stroke-dasharray:1, 150;stroke-dashoffset:0}50%{stroke-dasharray:90, 150;stroke-dashoffset:-35}100%{stroke-dasharray:90, 150;stroke-dashoffset:-124}}";
395
+ const UserFundsAcknowledgmentStyle0 = userFundsAcknowledgmentCss;
396
+
397
+ const UserFundsAcknowledgment = class {
398
+ constructor(hostRef) {
399
+ registerInstance(this, hostRef);
400
+ this.abortController = null;
401
+ this.TIMEOUT_MS = 10000; // 10 seconds
402
+ /**
403
+ * Returns the formatted balance
404
+ * @param balance -> the balance value to be formatted
405
+ */
406
+ this.formatBalance = (balance) => {
407
+ if (this.customdisplayformat) {
408
+ return this.formatFromCustom(balance);
409
+ }
410
+ const locales = this.currencylocale || this.language;
411
+ const formatOptions = {
412
+ style: 'currency',
413
+ currency: this.playercurrency,
414
+ useGrouping: true,
415
+ currencyDisplay: this.currencydisplay,
416
+ maximumFractionDigits: this.maximumfractiondigits === '' || isNaN(Number(this.maximumfractiondigits)) ? 2 : Number(this.maximumfractiondigits),
417
+ minimumFractionDigits: this.minimumfractiondigits === '' || isNaN(Number(this.minimumfractiondigits)) ? 0 : Number(this.minimumfractiondigits),
418
+ };
419
+ return new Intl.NumberFormat(locales, formatOptions).format(balance);
420
+ };
421
+ /**
422
+ * Parses customdisplayformat and returns the formatted balance accordingly.
423
+ * Example:
424
+ * if customdisplayformat = '{amount|,.1} {currency}', currency = 'EUR'
425
+ * then formatFromCustom(123123.199) = '123,123.1 EUR'
426
+ * @param balance
427
+ */
428
+ this.formatFromCustom = (balance) => {
429
+ const tokens = [];
430
+ let acc = '';
431
+ for (const char of this.customdisplayformat) {
432
+ switch (char) {
433
+ default:
434
+ acc += char;
435
+ break;
436
+ case '{':
437
+ acc && tokens.push(acc);
438
+ acc = '';
439
+ break;
440
+ case '}':
441
+ const [variable, args] = acc.split('|');
442
+ acc = '';
443
+ if (variable.toLowerCase() === 'currency') {
444
+ acc = this.playercurrency;
445
+ }
446
+ else if (variable.toLowerCase() === 'amount') {
447
+ // defaults
448
+ let sepThousands = ',';
449
+ let sepDecimal = '.';
450
+ let decimals = 2;
451
+ // override defaults if args provided (' ' is considered empty so default is used)
452
+ if (args) {
453
+ args[0] !== ' ' && (sepThousands = args[0]);
454
+ args[1] !== ' ' && (sepDecimal = args[1]);
455
+ args[2] !== ' ' && !isNaN(Number(args[2])) && (decimals = Number(args[2]));
456
+ }
457
+ // separate int and fractional part, also round down to desired precision
458
+ let [integerPart, fractionalPart] = String(Math.floor(balance * 10 ** decimals) / 10 ** decimals).split('.');
459
+ // format int part by adding thousands separators
460
+ acc += integerPart[0];
461
+ for (let i = 1; i < integerPart.length; ++i) {
462
+ if ((integerPart.length - i) % 3 === 0) {
463
+ acc += (sepThousands + integerPart[i]);
464
+ }
465
+ else {
466
+ acc += integerPart[i];
467
+ }
468
+ }
469
+ let finalFraction = fractionalPart || '';
470
+ const forceDecimals = this.alwaysshowdecimals === 'true';
471
+ const maxFractionDigits = Number(this.maximumfractiondigits);
472
+ if (forceDecimals) {
473
+ // Always show exactly maxFractionDigits decimals
474
+ finalFraction = finalFraction.padEnd(maxFractionDigits || 2, '0').substring(0, maxFractionDigits);
475
+ }
476
+ else {
477
+ // Default behavior: only show decimals if they exist
478
+ if (!finalFraction) {
479
+ break;
480
+ }
481
+ }
482
+ // Append decimals
483
+ acc += sepDecimal + finalFraction;
484
+ }
485
+ acc && tokens.push(acc);
486
+ acc = '';
487
+ break;
488
+ }
489
+ }
490
+ tokens.push(acc);
491
+ return tokens.join('');
492
+ };
493
+ this.handleSubmit = () => {
494
+ var _a;
495
+ this.consentsSubmitted = true;
496
+ // Abort any in-flight request before starting a new one
497
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
498
+ this.abortController = new AbortController();
499
+ const timeoutId = setTimeout(() => {
500
+ var _a;
501
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort('Request timed out');
502
+ }, this.TIMEOUT_MS);
503
+ const url = `${this.endpoint}/api/pam/v1/actions/customer-funds-protection`;
504
+ const headers = new Headers();
505
+ headers.append('Content-Type', 'application/json');
506
+ headers.append('X-SessionId', `${this.session}`);
507
+ headers.append('X-Tenant-ID', `${this.operatorid}`);
508
+ return fetch(url, {
509
+ method: 'POST',
510
+ headers: headers,
511
+ body: JSON.stringify({ accepted: true }),
512
+ signal: this.abortController.signal,
513
+ })
514
+ .then((res) => {
515
+ if (!res.ok) {
516
+ this.errorMessage = `${translate('apiCallError', this.language)} ${res.status}`;
517
+ throw new Error(`Request failed with status ${res.status}`);
518
+ }
519
+ // 202 Accepted has no body, skip res.json()
520
+ if (res.status === 202) {
521
+ this.errorMessage = '';
522
+ localStorage.removeItem("totalCashAmount");
523
+ window.postMessage({ type: 'ProtectionFundsAccepted' }, window.location.href);
524
+ return;
525
+ }
526
+ return res.json();
527
+ })
528
+ .catch((error) => {
529
+ var _a;
530
+ if (error.name === 'AbortError') {
531
+ // Validate between timeout/unmount
532
+ const reason = (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.reason;
533
+ if (reason === 'Request timed out') {
534
+ this.errorMessage = translate('serverNotResponding', this.language);
535
+ }
536
+ return;
537
+ }
538
+ console.error('Customer funds protection request failed:', error.message);
539
+ this.errorMessage = translate('serverNotResponding', this.language);
540
+ })
541
+ .finally(() => {
542
+ clearTimeout(timeoutId); // clear timer
543
+ this.abortController = null;
544
+ });
545
+ };
546
+ this.session = undefined;
547
+ this.operatorid = undefined;
548
+ this.mbSource = undefined;
549
+ this.clientStyling = undefined;
550
+ this.clientStylingUrl = undefined;
551
+ this.endpoint = undefined;
552
+ this.language = 'en';
553
+ this.translationUrl = '';
554
+ this.currencylocale = 'en';
555
+ this.currencydisplay = 'symbol';
556
+ this.maximumfractiondigits = '2';
557
+ this.minimumfractiondigits = '0';
558
+ this.customdisplayformat = '';
559
+ this.alwaysshowdecimals = 'true';
560
+ this.playercurrency = 'EUR';
561
+ this.isLoading = false;
562
+ this.isConsentChecked = false;
563
+ this.totalCashAmount = 0;
564
+ this.errorMessage = '';
565
+ this.consentsSubmitted = false;
566
+ }
567
+ handleNewTranslations() {
568
+ getTranslations(this.translationUrl);
569
+ }
570
+ handleClientStylingChange(newValue, oldValue) {
571
+ if (newValue != oldValue) {
572
+ setClientStyling(this.stylingContainer, this.clientStyling);
573
+ }
574
+ }
575
+ handleClientStylingUrlChange(newValue, oldValue) {
576
+ if (newValue != oldValue) {
577
+ setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
578
+ }
579
+ }
580
+ handleMbSourceChange(newValue, oldValue) {
581
+ if (newValue != oldValue) {
582
+ setStreamStyling(this.stylingContainer, `${this.mbSource}.Style`, this.stylingSubscription);
583
+ }
584
+ }
585
+ async componentWillLoad() {
586
+ if (this.translationUrl.length > 2) {
587
+ await getTranslations(this.translationUrl);
588
+ }
589
+ this.totalCashAmount = parseFloat(localStorage.getItem('totalCashAmount')) || 0;
590
+ }
591
+ componentDidLoad() {
592
+ if (this.stylingContainer) {
593
+ if (this.mbSource)
594
+ setStreamStyling(this.stylingContainer, `${this.mbSource}.Style`, this.stylingSubscription);
595
+ if (this.clientStyling)
596
+ setClientStyling(this.stylingContainer, this.clientStyling);
597
+ if (this.clientStylingUrl)
598
+ setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
599
+ }
600
+ }
601
+ disconnectedCallback() {
602
+ var _a;
603
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort('Component unmounted');
604
+ this.stylingSubscription && this.stylingSubscription.unsubscribe();
605
+ }
606
+ userLegislationConsentHandler() {
607
+ if (this.checkboxInput) {
608
+ this.isConsentChecked = this.checkboxInput.checked;
609
+ }
610
+ // In case of a network error, permit the user to retry consents submission
611
+ if (this.isConsentChecked) {
612
+ this.consentsSubmitted = false;
613
+ this.errorMessage = '';
614
+ }
615
+ }
616
+ consentsArea() {
617
+ return (h("div", { class: "UserProtectionFundsCheckboxArea" }, h("label", { class: "UserProtectionFundsCheckboxContent", htmlFor: "userProtectionFunds" }, h("input", { ref: el => this.checkboxInput = el, id: "userProtectionFunds", type: "checkbox", onInput: () => this.userLegislationConsentHandler() }), h("span", { innerHTML: `${translate('protectionCheckboxLabel', this.language)}` }))));
618
+ }
619
+ render() {
620
+ return (h("div", { key: 'e6361dbe3338fd1bbf9b54eb41b3fddf0f8829c7', class: "QueryReferenceContainer", ref: el => this.stylingContainer = el }, this.isLoading ? (h("div", null, h("slot", { name: 'spinner' }), h("svg", { class: "spinner", viewBox: "0 0 50 50" }, h("circle", { class: "path", cx: "25", cy: "25", r: "20", fill: "none", "stroke-width": "5" })))) : (h("div", { class: "UserProtectionFundsContainer" }, h("div", { class: "UserProtectionFundsTitle" }, h("h2", null, translate('protectionTitle', this.language))), h("div", { class: "UserProtectionFundsWrapper" }, h("p", { innerHTML: `${translate('protectionContent', this.language)}` })), h("div", { class: "UserProtectionFundsBalance" }, h("p", null, translate('balanceArea', this.language), " ", h("span", null, this.formatBalance(this.totalCashAmount)))), h("div", { class: "UserProtectionFundsButtonsWrapper" }, h("div", null, this.consentsArea()), h("div", null, h("button", { class: "UserProtectionFundsSubmitButton", disabled: !this.isConsentChecked || this.errorMessage != '' || this.consentsSubmitted, onClick: this.handleSubmit }, translate('submitButtonText', this.language))), h("div", { class: "UserProtectionError" }, this.errorMessage != '' && this.errorMessage))))));
621
+ }
622
+ static get watchers() { return {
623
+ "translationUrl": ["handleNewTranslations"],
624
+ "clientStyling": ["handleClientStylingChange"],
625
+ "clientStylingUrl": ["handleClientStylingUrlChange"],
626
+ "mbSource": ["handleMbSourceChange"]
627
+ }; }
628
+ };
629
+ UserFundsAcknowledgment.style = UserFundsAcknowledgmentStyle0;
630
+
631
+ export { UserActions as user_actions, UserFundsAcknowledgment as user_funds_acknowledgment };