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