@everymatrix/user-login 1.94.17 → 1.94.19

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.
@@ -1,4 +1,4 @@
1
- import { r as registerInstance, h } from './index-13692399.js';
1
+ import { r as registerInstance, h, g as getElement } from './index-b943f0d9.js';
2
2
 
3
3
  const DEFAULT_LANGUAGE = 'en';
4
4
  const TRANSLATIONS = {
@@ -498,6 +498,25 @@ function getAdoptStyleSubscription(stylingContainer, domain) {
498
498
  });
499
499
  }
500
500
 
501
+ /**
502
+ * Get first assigned element from a named slot
503
+ *
504
+ * @param {HTMLElement} host
505
+ * @param {string} slotName
506
+ * @returns {HTMLElement | null}
507
+ */
508
+ const getSlottedElement = (host, slotName) => {
509
+ const slot = /** @type {HTMLSlotElement | null} */ (
510
+ host.shadowRoot?.querySelector(`slot[name="${slotName}"]`)
511
+ );
512
+
513
+ if (!slot) return null;
514
+
515
+ return /** @type {HTMLElement | null} */ (
516
+ slot.assignedElements?.()[0] ?? null
517
+ );
518
+ };
519
+
501
520
  /**
502
521
  * @name dispatchCustomEvent
503
522
  * @description dispatches the custom event CustomEventProcessor is listening for
@@ -517,6 +536,368 @@ const dispatchCustomEvent = (type, data = {}) => {
517
536
  document.dispatchEvent(event);
518
537
  };
519
538
 
539
+ const SCRIPT_SRC$1 = 'https://www.google.com/recaptcha/api.js';
540
+ let scriptPromise$1 = null;
541
+ function loadRecaptcha() {
542
+ var _a;
543
+ if (typeof window === 'undefined') {
544
+ return Promise.reject(new Error('[reCAPTCHA] SSR'));
545
+ }
546
+ if ((_a = window.grecaptcha) === null || _a === void 0 ? void 0 : _a.render) {
547
+ return Promise.resolve();
548
+ }
549
+ if (!scriptPromise$1) {
550
+ scriptPromise$1 = new Promise((resolve, reject) => {
551
+ const script = document.createElement('script');
552
+ script.src = SCRIPT_SRC$1;
553
+ script.async = true;
554
+ script.defer = true;
555
+ script.onload = () => {
556
+ const check = () => {
557
+ var _a;
558
+ if ((_a = window.grecaptcha) === null || _a === void 0 ? void 0 : _a.render) {
559
+ resolve();
560
+ }
561
+ else {
562
+ setTimeout(check, 50);
563
+ }
564
+ };
565
+ check();
566
+ };
567
+ script.onerror = () => {
568
+ scriptPromise$1 = null;
569
+ reject(new Error('[reCAPTCHA] script failed to load'));
570
+ };
571
+ document.head.appendChild(script);
572
+ });
573
+ }
574
+ return scriptPromise$1;
575
+ }
576
+ function createRecaptcha(options) {
577
+ let widgetId;
578
+ async function render(container) {
579
+ await loadRecaptcha();
580
+ if (widgetId !== undefined)
581
+ return;
582
+ widgetId = window.grecaptcha.render(container, Object.assign({ theme: 'light', size: 'normal' }, options));
583
+ }
584
+ function reset() {
585
+ if (widgetId === undefined)
586
+ return;
587
+ try {
588
+ window.grecaptcha.reset(widgetId);
589
+ }
590
+ catch (_a) { }
591
+ }
592
+ function cleanup() {
593
+ reset();
594
+ widgetId = undefined;
595
+ }
596
+ return {
597
+ render,
598
+ reset,
599
+ cleanup
600
+ };
601
+ }
602
+
603
+ const SCRIPT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
604
+ const RESET_COOL_DOWN_MS = 3000;
605
+ const RETRY_INTERVAL_MS = 3000;
606
+ const DEFAULT_RETRY_COUNT = 5;
607
+ const DUMMY_TURNSTILE_RESPONSE = 'XXXX.DUMMY.TOKEN.XXXX';
608
+ // Module-level singleton so multiple widgets share one script tag.
609
+ let scriptPromise = null;
610
+ function loadTurnstile() {
611
+ if (typeof window === 'undefined') {
612
+ return Promise.reject(new Error('[Turnstile] SSR'));
613
+ }
614
+ if (window.turnstile) {
615
+ return Promise.resolve();
616
+ }
617
+ if (!scriptPromise) {
618
+ scriptPromise = new Promise((resolve, reject) => {
619
+ const script = document.createElement('script');
620
+ script.src = SCRIPT_SRC;
621
+ script.async = true;
622
+ script.defer = true;
623
+ script.onload = () => resolve();
624
+ script.onerror = () => {
625
+ scriptPromise = null; // allow later retries
626
+ reject(new Error('[Turnstile] script failed to load'));
627
+ };
628
+ document.head.appendChild(script);
629
+ });
630
+ }
631
+ return scriptPromise;
632
+ }
633
+ /**
634
+ * Creates a self-contained Cloudflare Turnstile controller for use in any
635
+ * framework (Stencil, Vue, Svelte, vanilla TS). Mirrors the behavior of the
636
+ * React `useTurnstile` hook used in the Flash project.
637
+ *
638
+ * Typical lifecycle:
639
+ * 1. Call `render(containerEl)` in your mount/componentDidLoad — loads the
640
+ * script and renders an invisible widget.
641
+ * 2. On form submit, `await ensureToken()` to get (or obtain) a token.
642
+ * 3. Call `cleanup()` in your unmount/disconnectedCallback.
643
+ *
644
+ * @example
645
+ * ```ts
646
+ * const turnstile = createTurnstile({
647
+ * siteKey: 'YOUR_SITE_KEY',
648
+ * action: 'login',
649
+ * onLoadingChange: (loading) => { this.isTurnstileLoading = loading; },
650
+ * });
651
+ *
652
+ * // in componentDidLoad
653
+ * await turnstile.render(this.turnstileContainerEl);
654
+ *
655
+ * // in handleSubmit
656
+ * const token = await turnstile.ensureToken();
657
+ * headers['X-Captcha-Response'] = token;
658
+ *
659
+ * // in disconnectedCallback
660
+ * turnstile.cleanup();
661
+ * ```
662
+ */
663
+ function createTurnstile(options) {
664
+ const { siteKey, action, isEnabled = true, enableFallback = false, retryCount = DEFAULT_RETRY_COUNT } = options;
665
+ let token = null;
666
+ let widgetId;
667
+ let container;
668
+ let pendingRequest = null;
669
+ let currentPromise = null;
670
+ let shouldReset = false;
671
+ let lastResetAt = 0;
672
+ let errorCount = 0;
673
+ function setToken(value) {
674
+ var _a;
675
+ token = value;
676
+ (_a = options.onTokenChange) === null || _a === void 0 ? void 0 : _a.call(options, value);
677
+ }
678
+ function setLoading(value) {
679
+ var _a;
680
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, value);
681
+ }
682
+ function isWidgetReady() {
683
+ return !!window.turnstile && !!widgetId;
684
+ }
685
+ function handleVerificationSuccess(receivedToken) {
686
+ const pending = pendingRequest;
687
+ if (pending) {
688
+ if (pending.retryTimerId != null)
689
+ clearTimeout(pending.retryTimerId);
690
+ pending.resolve(receivedToken);
691
+ pendingRequest = null;
692
+ }
693
+ setToken(receivedToken);
694
+ setLoading(false);
695
+ shouldReset = false;
696
+ if (enableFallback)
697
+ errorCount = 0;
698
+ }
699
+ function scheduleNextExecute() {
700
+ const pending = pendingRequest;
701
+ if (!pending || !widgetId || !window.turnstile)
702
+ return;
703
+ pending.retryTimerId = setTimeout(() => {
704
+ if (!pendingRequest || !widgetId || !window.turnstile)
705
+ return;
706
+ errorCount += 1;
707
+ if (errorCount >= retryCount) {
708
+ if (pending.retryTimerId != null) {
709
+ clearTimeout(pending.retryTimerId);
710
+ }
711
+ try {
712
+ if (widgetId && window.turnstile) {
713
+ window.turnstile.reset(widgetId);
714
+ lastResetAt = Date.now();
715
+ }
716
+ }
717
+ catch (e) {
718
+ console.warn('[Turnstile] final reset failed', e);
719
+ }
720
+ setLoading(false);
721
+ shouldReset = false;
722
+ if (enableFallback) {
723
+ handleVerificationSuccess(DUMMY_TURNSTILE_RESPONSE);
724
+ return;
725
+ }
726
+ pendingRequest = null;
727
+ currentPromise = null;
728
+ errorCount = 0;
729
+ pending.reject(new Error('[Turnstile] Verification failed. Please try again.'));
730
+ return;
731
+ }
732
+ const now = Date.now();
733
+ if (shouldReset && now - lastResetAt >= RESET_COOL_DOWN_MS) {
734
+ try {
735
+ window.turnstile.reset(widgetId);
736
+ lastResetAt = now;
737
+ }
738
+ catch (e) {
739
+ console.warn('[Turnstile] reset error', e);
740
+ }
741
+ finally {
742
+ shouldReset = false;
743
+ }
744
+ }
745
+ try {
746
+ window.turnstile.execute(widgetId);
747
+ }
748
+ catch (e) {
749
+ console.warn('[Turnstile] execute threw -> reschedule', e);
750
+ scheduleNextExecute();
751
+ }
752
+ }, RETRY_INTERVAL_MS);
753
+ }
754
+ function renderWidget() {
755
+ if (widgetId || !container || !window.turnstile)
756
+ return;
757
+ shouldReset = false;
758
+ widgetId = window.turnstile.render(container, {
759
+ sitekey: siteKey,
760
+ retry: 'never',
761
+ action,
762
+ appearance: 'interaction-only',
763
+ execution: 'execute',
764
+ callback: handleVerificationSuccess,
765
+ 'error-callback': () => {
766
+ shouldReset = true;
767
+ if (pendingRequest)
768
+ scheduleNextExecute();
769
+ },
770
+ 'expired-callback': () => {
771
+ setToken(null);
772
+ shouldReset = true;
773
+ },
774
+ 'timeout-callback': () => {
775
+ if (pendingRequest) {
776
+ shouldReset = true;
777
+ scheduleNextExecute();
778
+ }
779
+ }
780
+ });
781
+ }
782
+ /**
783
+ * Loads the Turnstile script (once) and renders the invisible widget into
784
+ * `hostContainer`. Safe to call before the script is available.
785
+ */
786
+ async function render(hostContainer) {
787
+ var _a;
788
+ if (!isEnabled)
789
+ return;
790
+ container = hostContainer;
791
+ try {
792
+ await loadTurnstile();
793
+ renderWidget();
794
+ (_a = options.onReady) === null || _a === void 0 ? void 0 : _a.call(options);
795
+ }
796
+ catch (err) {
797
+ console.error('[Turnstile] script load error', err);
798
+ }
799
+ }
800
+ /**
801
+ * Executes the challenge and returns a token Promise. If a request is already
802
+ * in-flight the same Promise is returned (no duplicate challenges).
803
+ */
804
+ async function getToken() {
805
+ if (!isEnabled)
806
+ return undefined;
807
+ if (!isWidgetReady()) {
808
+ await loadTurnstile();
809
+ renderWidget();
810
+ if (!isWidgetReady()) {
811
+ throw new Error('[Turnstile] widget not ready');
812
+ }
813
+ }
814
+ if (currentPromise)
815
+ return currentPromise;
816
+ setLoading(true);
817
+ const promise = new Promise((resolve, reject) => {
818
+ pendingRequest = { resolve, reject, retryTimerId: null };
819
+ try {
820
+ window.turnstile.execute(widgetId);
821
+ }
822
+ catch (e) {
823
+ console.error('[Turnstile] execute error', e);
824
+ scheduleNextExecute();
825
+ }
826
+ }).finally(() => {
827
+ if (currentPromise === promise)
828
+ currentPromise = null;
829
+ });
830
+ currentPromise = promise;
831
+ return promise;
832
+ }
833
+ /**
834
+ * Returns the cached token immediately if still valid; otherwise calls
835
+ * `getToken()`. Prefer this on form submit.
836
+ */
837
+ async function ensureToken() {
838
+ if (!isEnabled)
839
+ return undefined;
840
+ if (token)
841
+ return token;
842
+ return getToken();
843
+ }
844
+ /**
845
+ * Resets the widget state and rejects any in-flight token promise.
846
+ * Call after a failed login attempt so the next submit gets a fresh token.
847
+ */
848
+ function reset() {
849
+ if (widgetId && window.turnstile) {
850
+ try {
851
+ window.turnstile.reset(widgetId);
852
+ lastResetAt = Date.now();
853
+ }
854
+ catch (_a) {
855
+ /* ignore */
856
+ }
857
+ }
858
+ if (pendingRequest) {
859
+ const pending = pendingRequest;
860
+ if (pending.retryTimerId != null)
861
+ clearTimeout(pending.retryTimerId);
862
+ pending.reject(new Error('[Turnstile] reset by caller'));
863
+ pendingRequest = null;
864
+ }
865
+ shouldReset = false;
866
+ currentPromise = null;
867
+ setLoading(false);
868
+ setToken(null);
869
+ }
870
+ /**
871
+ * Removes the widget from the DOM and rejects any pending promise.
872
+ * Call in `disconnectedCallback` / component unmount.
873
+ */
874
+ function cleanup() {
875
+ try {
876
+ if (widgetId && window.turnstile) {
877
+ window.turnstile.remove(widgetId);
878
+ }
879
+ }
880
+ catch (_a) {
881
+ /* ignore */
882
+ }
883
+ if (pendingRequest) {
884
+ const pending = pendingRequest;
885
+ if (pending.retryTimerId != null)
886
+ clearTimeout(pending.retryTimerId);
887
+ pending.reject(new Error('[Turnstile] widget destroyed'));
888
+ pendingRequest = null;
889
+ }
890
+ widgetId = undefined;
891
+ shouldReset = false;
892
+ currentPromise = null;
893
+ setLoading(false);
894
+ setToken(null);
895
+ }
896
+ return { render, getToken, ensureToken, reset, cleanup };
897
+ }
898
+
899
+ const CAPTCHA_CONTAINER_SLOT = "captchaContainer";
900
+
520
901
  var qr=Object.defineProperty,Yr=Object.defineProperties;var Kr=Object.getOwnPropertyDescriptors;var lo=Object.getOwnPropertySymbols;var Gr=Object.prototype.hasOwnProperty,Xr=Object.prototype.propertyIsEnumerable;var Mt=(s,t,e)=>t in s?qr(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e,we=(s,t)=>{for(var e in t||(t={}))Gr.call(t,e)&&Mt(s,e,t[e]);if(lo)for(var e of lo(t))Xr.call(t,e)&&Mt(s,e,t[e]);return s},Nt=(s,t)=>Yr(s,Kr(t));var k=(s,t,e)=>(Mt(s,typeof t!="symbol"?t+"":t,e),e);var Ce=(s,t,e)=>new Promise((i,o)=>{var r=l=>{try{a(e.next(l));}catch(d){o(d);}},n=l=>{try{a(e.throw(l));}catch(d){o(d);}},a=l=>l.done?i(l.value):Promise.resolve(l.value).then(r,n);a((e=e.apply(s,t)).next());});/**
521
902
  * @license
522
903
  * Copyright (c) 2021 - 2024 Vaadin Ltd.
@@ -7184,6 +7565,7 @@ const UserLogin = class {
7184
7565
  constructor(hostRef) {
7185
7566
  registerInstance(this, hostRef);
7186
7567
  this.errorCode = '';
7568
+ this.captchaInstance = null;
7187
7569
  this.messageHandler = async (e) => {
7188
7570
  var _a;
7189
7571
  if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === 'NativeAppReady') {
@@ -7200,11 +7582,11 @@ const UserLogin = class {
7200
7582
  /**
7201
7583
  * Fetch phone prefixes from the API
7202
7584
  */
7203
- this.getPhoneCodes = () => {
7585
+ this.getPhoneCodes = async () => {
7204
7586
  const url = new URL(`${this.endpoint}/v1/player/operatorSupportedPhoneCodes`);
7205
7587
  return fetch(url.href)
7206
7588
  .then(res => res.json())
7207
- .then(data => data.phoneCodes.map(code => ({ label: code, value: code })))
7589
+ .then(data => { var _a; return ((_a = data === null || data === void 0 ? void 0 : data.phoneCodes) !== null && _a !== void 0 ? _a : []).map(code => ({ label: code, value: code })); })
7208
7590
  .catch(err => console.log('Failed to fetch phone codes:', err));
7209
7591
  };
7210
7592
  /**
@@ -7222,6 +7604,7 @@ const UserLogin = class {
7222
7604
  * Login API call for Gm 1.7
7223
7605
  */
7224
7606
  this.userLoginGm17 = async () => {
7607
+ var _a, _b, _c;
7225
7608
  let headers = {
7226
7609
  'Content-Type': 'application/json'
7227
7610
  };
@@ -7229,8 +7612,15 @@ const UserLogin = class {
7229
7612
  contact: this.userNameEmail,
7230
7613
  password: this.userPassword
7231
7614
  };
7232
- if (this.captchaData.isEnabled) {
7233
- headers['X-Captcha-Response'] = this.captchaData.token;
7615
+ if (this.captchaInstance) {
7616
+ let token;
7617
+ if (typeof ((_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.ensureToken) === "function") {
7618
+ token = await ((_c = (_b = this.captchaInstance) === null || _b === void 0 ? void 0 : _b.ensureToken) === null || _c === void 0 ? void 0 : _c.call(_b));
7619
+ }
7620
+ else {
7621
+ token = this.captchaToken;
7622
+ }
7623
+ headers['cf-captcha-response'] = token !== null && token !== void 0 ? token : "";
7234
7624
  }
7235
7625
  const options = {
7236
7626
  method: 'POST',
@@ -7313,9 +7703,26 @@ const UserLogin = class {
7313
7703
  * Login API call
7314
7704
  */
7315
7705
  this.userLogin = async () => {
7706
+ var _a, _b;
7316
7707
  const url = new URL(`${this.endpoint}/v1/player/legislation/login`);
7317
7708
  const headers = new Headers();
7318
7709
  headers.append('Content-Type', 'application/json');
7710
+ if (this.turnstileSiteKey && this.captchaInstance) {
7711
+ try {
7712
+ const turnstileToken = await ((_b = (_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.ensureToken) === null || _b === void 0 ? void 0 : _b.call(_a));
7713
+ if (turnstileToken) {
7714
+ headers.append('cf-captcha-response', turnstileToken);
7715
+ headers.append('cfCaptchaIsVisible', 'false');
7716
+ }
7717
+ }
7718
+ catch (error) {
7719
+ this.hasError = true;
7720
+ this.errorMessage = translate('genericError', this.lang) || `${error}`;
7721
+ this.sendErrorNotification(this.errorMessage);
7722
+ this.isLoginLoading = false;
7723
+ return;
7724
+ }
7725
+ }
7319
7726
  const body = JSON.stringify({
7320
7727
  username: this.loginByPhoneNumber === 'true' ? `${this.userPrefix} ${this.userPhone}` : this.userNameEmail,
7321
7728
  password: this.userPassword
@@ -7483,11 +7890,11 @@ const UserLogin = class {
7483
7890
  this.clientStylingUrl = '';
7484
7891
  this.translationUrl = '';
7485
7892
  this.passwordReset = 'false';
7486
- this.userEmailRegex = undefined;
7893
+ this.userEmailRegex = '';
7487
7894
  this.userEmailRegexOptions = 'i';
7488
- this.userPhoneRegex = undefined;
7895
+ this.userPhoneRegex = '';
7489
7896
  this.userPhoneRegexOptions = '';
7490
- this.passwordRegex = undefined;
7897
+ this.passwordRegex = '';
7491
7898
  this.passwordRegexOptions = '';
7492
7899
  this.version = 'gm16';
7493
7900
  this.loginByPhoneNumber = 'false';
@@ -7497,6 +7904,9 @@ const UserLogin = class {
7497
7904
  this.biometricEnabled = 'false';
7498
7905
  this.biometricactionmode = 'switch';
7499
7906
  this.isFromLogin = true;
7907
+ this.turnstileSiteKey = undefined;
7908
+ this.turnstileEnableFallback = false;
7909
+ this.turnstileRetryCount = undefined;
7500
7910
  this.userNameEmail = '';
7501
7911
  this.userPassword = '';
7502
7912
  this.isValidUserEmail = true;
@@ -7508,16 +7918,11 @@ const UserLogin = class {
7508
7918
  this.errorMessage = '';
7509
7919
  this.errorForFields = {};
7510
7920
  this.hasError = false;
7511
- this.phoneCodes = undefined;
7921
+ this.phoneCodes = [];
7512
7922
  this.isLoginLoading = false;
7513
- this.captchaData = {
7514
- isEnabled: true,
7515
- token: '',
7516
- provider: '',
7517
- siteKey: ''
7518
- };
7519
7923
  this.isNativeApp = false;
7520
7924
  this.biometricsLoaded = false;
7925
+ this.isTurnstileLoading = false;
7521
7926
  }
7522
7927
  /**
7523
7928
  * Watch for changes in the translation URL and fetch new translations
@@ -7546,7 +7951,7 @@ const UserLogin = class {
7546
7951
  * Populate login credentials from an external caller and trigger the login process
7547
7952
  */
7548
7953
  async autofillCredentials(credentials) {
7549
- const { userNameEmail, userPassword, userPrefix, userPhone } = credentials || {};
7954
+ const { userNameEmail, userPassword, userPrefix = '', userPhone = '' } = credentials || {};
7550
7955
  this.userNameEmail = userNameEmail;
7551
7956
  this.userPassword = userPassword;
7552
7957
  this.userPrefix = userPrefix;
@@ -7558,15 +7963,16 @@ const UserLogin = class {
7558
7963
  * Lifecycle method: Fetch translations on component load
7559
7964
  */
7560
7965
  async componentWillLoad() {
7966
+ var _a, _b;
7561
7967
  if (this.loginByPhoneNumber === 'true') {
7562
7968
  if (this.defaultPrefix && this.isPrefixEditable === 'false') {
7563
7969
  this.phoneCodes = [{ label: this.defaultPrefix, value: this.defaultPrefix }];
7564
7970
  this.userPrefix = this.defaultPrefix;
7565
7971
  }
7566
7972
  else {
7567
- this.phoneCodes = await this.getPhoneCodes();
7568
- if (!this.defaultPrefix && this.isPrefixEditable === 'false') {
7569
- this.userPrefix = this.phoneCodes[0].value;
7973
+ this.phoneCodes = await (this.getPhoneCodes()) || [];
7974
+ if (((_a = this.phoneCodes) === null || _a === void 0 ? void 0 : _a.length) && !this.defaultPrefix && this.isPrefixEditable === 'false') {
7975
+ this.userPrefix = (_b = this.phoneCodes[0]) === null || _b === void 0 ? void 0 : _b.value;
7570
7976
  }
7571
7977
  else if (this.defaultPrefix && this.isPrefixEditable === 'true') {
7572
7978
  this.userPrefix = this.defaultPrefix;
@@ -7580,8 +7986,8 @@ const UserLogin = class {
7580
7986
  await getTranslations(this.translationUrl);
7581
7987
  }
7582
7988
  if (this.version === 'gm17') {
7583
- this.getLoginConfig().then(() => {
7584
- this.appendCaptchaScript();
7989
+ this.getLoginConfig().then((captchaData) => {
7990
+ this.initializeCaptcha(captchaData);
7585
7991
  }).catch((error) => {
7586
7992
  console.error(error);
7587
7993
  this.hasError = true;
@@ -7612,9 +8018,17 @@ const UserLogin = class {
7612
8018
  this.handleClientStyling();
7613
8019
  window.addEventListener('LoginCredentials', this.autofillCredentialsHandler);
7614
8020
  window.postMessage({ type: 'UserLoginDidLoad' });
8021
+ if (this.turnstileSiteKey) {
8022
+ this.initializeCaptcha({
8023
+ isEnabled: true,
8024
+ provider: "cloudflare",
8025
+ siteKey: this.turnstileSiteKey,
8026
+ enableFallback: this.turnstileEnableFallback
8027
+ });
8028
+ }
7615
8029
  }
7616
8030
  /**
7617
- * Fetches the login configuration from the backend API.
8031
+ * Fetches the login configuration from the backend API, used for gm17 only.
7618
8032
  *
7619
8033
  * @returns A Promise that resolves once the configuration is fetched and set.
7620
8034
  */
@@ -7633,8 +8047,7 @@ const UserLogin = class {
7633
8047
  if (captcha && typeof captcha.provider === 'string') {
7634
8048
  captcha.provider = captcha.provider.toLowerCase();
7635
8049
  }
7636
- this.captchaData = Object.assign({}, captcha);
7637
- resolve();
8050
+ resolve(captcha);
7638
8051
  })
7639
8052
  .catch((error) => {
7640
8053
  console.error('Error fetching login configuration:', error);
@@ -7642,70 +8055,30 @@ const UserLogin = class {
7642
8055
  });
7643
8056
  });
7644
8057
  }
7645
- /**
7646
- * Handles the integration of CAPTCHA based on the login configuration.
7647
- * Dynamically injects the necessary CAPTCHA script if enabled.
7648
- */
7649
- handleCaptcha() {
7650
- const { isEnabled, provider, siteKey } = this.captchaData;
7651
- if (!isEnabled) {
7652
- return;
7653
- }
7654
- if (!['cloudflare', 'google'].includes(provider)) {
7655
- return;
7656
- }
7657
- if (provider === 'cloudflare') {
7658
- window.turnstile.render('#turnstileContainer', {
7659
- sitekey: siteKey,
7660
- theme: 'light',
7661
- callback: this.captchaCallback.bind(this),
7662
- });
7663
- }
7664
- else if (provider === 'google') {
7665
- window.grecaptcha.ready(() => {
7666
- window.grecaptcha.render('googleContainer', {
7667
- sitekey: siteKey,
7668
- callback: this.captchaCallback.bind(this),
7669
- theme: 'light'
7670
- });
7671
- });
7672
- }
7673
- }
7674
- /**
7675
- * Common callback function for CAPTCHA response handling.
7676
- * @param token CAPTCHA response token.
7677
- */
7678
- captchaCallback(token) {
7679
- this.captchaData.token = token;
7680
- this.captchaData = Object.assign({}, this.captchaData); // Needed to tell Stencil something was changed
7681
- }
7682
- /**
7683
- * Dynamically loads the Turnstile script and renders CAPTCHA when ready.
7684
- * @param src - The URL of the CAPTCHA script to load.
7685
- * @param captcha - The CAPTCHA configuration.
7686
- */
7687
- appendCaptchaScript() {
7688
- const { isEnabled, provider } = this.captchaData;
7689
- if (!isEnabled) {
7690
- return;
7691
- }
7692
- const script = document.createElement('script');
7693
- if (provider === 'cloudflare') {
7694
- script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
7695
- }
7696
- else if (provider === 'google') {
7697
- script.src = 'https://www.google.com/recaptcha/api.js';
7698
- }
7699
- script.onload = this.handleCaptcha.bind(this);
7700
- document.head.appendChild(script);
8058
+ async initializeCaptcha({ provider, siteKey, enableFallback }) {
8059
+ const slotElement = getSlottedElement(this.host, CAPTCHA_CONTAINER_SLOT);
8060
+ this.captchaContainerEl = slotElement;
8061
+ const captchaCreator = {
8062
+ "google": createRecaptcha,
8063
+ "cloudflare": createTurnstile
8064
+ };
8065
+ this.captchaInstance = captchaCreator[provider]({
8066
+ action: 'login',
8067
+ siteKey,
8068
+ enableFallback,
8069
+ callback: provider === "google" ? (token) => { this.captchaToken = token; } : undefined
8070
+ });
8071
+ await this.captchaInstance.render(this.captchaContainerEl);
7701
8072
  }
7702
8073
  /**
7703
8074
  * Lifecycle method: Clean up event listeners when the component is removed
7704
8075
  */
7705
8076
  disconnectedCallback() {
8077
+ var _a, _b;
7706
8078
  this.stylingSubscription && this.stylingSubscription.unsubscribe();
7707
8079
  window.removeEventListener('LoginCredentials', this.autofillCredentialsHandler);
7708
8080
  window.removeEventListener('message', this.messageHandler);
8081
+ (_b = (_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
7709
8082
  }
7710
8083
  /**
7711
8084
  * Send error notification as a post message
@@ -7722,12 +8095,12 @@ const UserLogin = class {
7722
8095
  /**
7723
8096
  * Debounce function to limit API calls
7724
8097
  */
7725
- debounce(func, delay) {
8098
+ debounce(fn, delay = 500) {
7726
8099
  let timer;
7727
- return function (...args) {
8100
+ return (...args) => {
7728
8101
  clearTimeout(timer);
7729
8102
  timer = setTimeout(() => {
7730
- func.apply(this, args);
8103
+ fn(...args);
7731
8104
  }, delay);
7732
8105
  };
7733
8106
  }
@@ -7757,9 +8130,12 @@ const UserLogin = class {
7757
8130
  window.dispatchEvent(event);
7758
8131
  }
7759
8132
  checkIsDisabled() {
7760
- const isDisabled = Boolean(((this.loginByPhoneNumber !== 'true' && (!this.isValidUserEmail || !this.userNameEmail)) ||
8133
+ const isDisabled = Boolean((this.loginByPhoneNumber !== 'true' && (!this.isValidUserEmail || !this.userNameEmail)) ||
7761
8134
  (this.loginByPhoneNumber === 'true' && (!this.isValidUserPhone || !this.userPhone || !this.userPrefix)) ||
7762
- !this.userPassword || !this.isValidPassword) || this.isLoginLoading || (this.version === 'gm17' && this.captchaData.isEnabled && !this.captchaData.token));
8135
+ !this.userPassword ||
8136
+ !this.isValidPassword ||
8137
+ this.isLoginLoading ||
8138
+ (this.version === 'gm17' && this.captchaInstance && !this.captchaToken));
7763
8139
  return isDisabled;
7764
8140
  }
7765
8141
  renderVisibilityIcon() {
@@ -7777,17 +8153,16 @@ const UserLogin = class {
7777
8153
  h("p", { class: "CredentialsError" }, translate('userEmailError', this.lang))), h("div", { class: (!this.isValidPassword && this.errorForFields['password']) ? 'InputBox InputInvalidBox' : 'InputBox' }, this.renderVisibilityIcon(), h("input", { name: 'password', type: this.isPasswordVisible ? "text" : "password", placeholder: '', value: this.userPassword, onInput: this.handleInputChangePartial('password'), autocapitalize: "none", required: true }), h("label", { class: (this.userPassword ? 'FieldFilledIn' : '') + ' ' + (!this.isValidPassword && this.errorForFields['password'] ? 'FieldInvalid' : '') }, translate('password', this.lang)), !this.isValidPassword && this.errorForFields['password'] &&
7778
8154
  h("p", { class: "CredentialsError" }, translate('userPasswordError', this.lang))), this.biometricEnabled === 'true' && this.isNativeApp &&
7779
8155
  h("div", { class: "PlayerBiometricsContainer" }, h("div", { class: "PlayerBiometrics" }, h("span", null, translate('biometricLogin')), h("player-account-biometrics-action", { mode: this.biometricactionmode, isFromLogin: this.isFromLogin, isNativeApp: this.isNativeApp, lang: this.lang, translationurl: this.translationUrl, clientstyling: this.clientStyling, clientstylingurl: this.clientStylingUrl, mbsource: this.mbSource, isLoading: this.isLoginLoading }))), this.passwordReset == 'true' &&
7780
- h("div", { class: "ForgotPassword" }, h("button", { onClick: this.resetPassword }, translate('forgotPassword', this.lang))), this.captchaData.isEnabled && this.captchaData.provider === 'cloudflare' &&
7781
- h("slot", { name: "turnstile" }), this.captchaData.isEnabled && this.captchaData.provider === 'google' &&
7782
- h("slot", { name: "google" }), h("button", { disabled: this.checkIsDisabled(), class: "SubmitCredentials", onClick: this.handleLogin }, translate('login', this.lang)), this.hasError &&
8156
+ h("div", { class: "ForgotPassword" }, h("button", { onClick: this.resetPassword }, translate('forgotPassword', this.lang))), h("button", { disabled: this.checkIsDisabled(), class: "SubmitCredentials", onClick: this.handleLogin }, translate('login', this.lang)), this.hasError &&
7783
8157
  h("p", { class: "CredentialsError" }, this.errorMessage))));
7784
8158
  }
7785
8159
  /**
7786
8160
  * Render function
7787
- */
8161
+ */
7788
8162
  render() {
7789
- return h("section", { key: '6dcfae23bb6f3bb107c030d3fef3f8e32f88e12b', ref: el => this.stylingContainer = el }, this.renderUserIdentification());
8163
+ return (h("section", { key: 'c72b94ac2e6cde988ae4798402680a527e4a004e', ref: el => this.stylingContainer = el }, this.renderUserIdentification(), h("slot", { key: '36c64bfcc9d5e19ae7b22d50638bf3c720167606', name: CAPTCHA_CONTAINER_SLOT })));
7790
8164
  }
8165
+ get host() { return getElement(this); }
7791
8166
  static get watchers() { return {
7792
8167
  "translationUrl": ["handleNewTranslations"],
7793
8168
  "clientStyling": ["handleClientStylingChange"],