@everymatrix/user-login 1.94.20 → 1.94.22

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.
@@ -510,11 +510,21 @@ const getSlottedElement = (host, slotName) => {
510
510
  host.shadowRoot?.querySelector(`slot[name="${slotName}"]`)
511
511
  );
512
512
 
513
- if (!slot) return null;
513
+ if (!slot) {
514
+ console.error(`[${host.tagName.toLowerCase()}] slot "${slotName}" not found.`);
515
+ return null;
516
+ }
514
517
 
515
- return /** @type {HTMLElement | null} */ (
518
+ const assignedElement = /** @type {HTMLElement | null} */ (
516
519
  slot.assignedElements?.()[0] ?? null
517
520
  );
521
+
522
+ if (!assignedElement) {
523
+ console.error( `[${host.tagName.toLowerCase()}] no element assigned to slot "${slotName}".`);
524
+ return null;
525
+ }
526
+
527
+ return assignedElement;
518
528
  };
519
529
 
520
530
  /**
@@ -537,6 +547,8 @@ const dispatchCustomEvent = (type, data = {}) => {
537
547
  };
538
548
 
539
549
  const SCRIPT_SRC$1 = 'https://www.google.com/recaptcha/api.js';
550
+ const SCRIPT_LOAD_TIMEOUT_MS$1 = 5000;
551
+ const RECAPTCHA_TOKEN_RESPONSE_HEADER = 'g-recaptcha-response';
540
552
  let scriptPromise$1 = null;
541
553
  function loadRecaptcha() {
542
554
  var _a;
@@ -553,11 +565,16 @@ function loadRecaptcha() {
553
565
  script.async = true;
554
566
  script.defer = true;
555
567
  script.onload = () => {
568
+ const deadline = Date.now() + SCRIPT_LOAD_TIMEOUT_MS$1;
556
569
  const check = () => {
557
570
  var _a;
558
571
  if ((_a = window.grecaptcha) === null || _a === void 0 ? void 0 : _a.render) {
559
572
  resolve();
560
573
  }
574
+ else if (Date.now() > deadline) {
575
+ scriptPromise$1 = null;
576
+ reject(new Error('[reCAPTCHA] timed out waiting for grecaptcha'));
577
+ }
561
578
  else {
562
579
  setTimeout(check, 50);
563
580
  }
@@ -601,28 +618,37 @@ function createRecaptcha(options) {
601
618
  }
602
619
 
603
620
  const SCRIPT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
604
- const RESET_COOL_DOWN_MS = 3000;
605
621
  const RETRY_INTERVAL_MS = 3000;
606
622
  const DEFAULT_RETRY_COUNT = 5;
623
+ const SCRIPT_LOAD_TIMEOUT_MS = 10000;
624
+ const TURNSTILE_TOKEN_EXPIRY_MS = 5 * 60 * 1000;
607
625
  const DUMMY_TURNSTILE_RESPONSE = 'XXXX.DUMMY.TOKEN.XXXX';
608
- // Module-level singleton so multiple widgets share one script tag.
626
+ const TURNSTILE_TOKEN_RESPONSE_HEADER = 'cf-captcha-response';
627
+ const TURNSTILE_IS_VISIBLE_HEADER = 'cfCaptchaIsVisible';
609
628
  let scriptPromise = null;
610
629
  function loadTurnstile() {
611
630
  if (typeof window === 'undefined') {
612
631
  return Promise.reject(new Error('[Turnstile] SSR'));
613
632
  }
614
- if (window.turnstile) {
633
+ if (window.turnstile)
615
634
  return Promise.resolve();
616
- }
617
635
  if (!scriptPromise) {
618
636
  scriptPromise = new Promise((resolve, reject) => {
637
+ const timeout = setTimeout(() => {
638
+ scriptPromise = null;
639
+ reject(new Error('[Turnstile] script load timeout'));
640
+ }, SCRIPT_LOAD_TIMEOUT_MS);
619
641
  const script = document.createElement('script');
620
642
  script.src = SCRIPT_SRC;
621
643
  script.async = true;
622
644
  script.defer = true;
623
- script.onload = () => resolve();
645
+ script.onload = () => {
646
+ clearTimeout(timeout);
647
+ resolve();
648
+ };
624
649
  script.onerror = () => {
625
- scriptPromise = null; // allow later retries
650
+ clearTimeout(timeout);
651
+ scriptPromise = null;
626
652
  reject(new Error('[Turnstile] script failed to load'));
627
653
  };
628
654
  document.head.appendChild(script);
@@ -630,159 +656,78 @@ function loadTurnstile() {
630
656
  }
631
657
  return scriptPromise;
632
658
  }
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
659
  function createTurnstile(options) {
664
660
  const { siteKey, action, isEnabled = true, enableFallback = false, retryCount = DEFAULT_RETRY_COUNT } = options;
665
661
  let token = null;
662
+ let tokenIssuedAt = 0;
666
663
  let widgetId;
667
664
  let container;
668
- let pendingRequest = null;
669
- let currentPromise = null;
670
- let shouldReset = false;
671
- let lastResetAt = 0;
665
+ let isDestroyed = false;
672
666
  let errorCount = 0;
667
+ let resolveToken = null;
668
+ let rejectToken = null;
673
669
  function setToken(value) {
674
670
  var _a;
675
671
  token = value;
672
+ if (value)
673
+ tokenIssuedAt = Date.now();
676
674
  (_a = options.onTokenChange) === null || _a === void 0 ? void 0 : _a.call(options, value);
677
675
  }
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
676
  function renderWidget() {
755
677
  if (widgetId || !container || !window.turnstile)
756
678
  return;
757
- shouldReset = false;
758
679
  widgetId = window.turnstile.render(container, {
759
680
  sitekey: siteKey,
760
- retry: 'never',
681
+ retry: 'auto',
761
682
  action,
762
683
  appearance: 'interaction-only',
763
684
  execution: 'execute',
764
- callback: handleVerificationSuccess,
765
- 'error-callback': () => {
766
- shouldReset = true;
767
- if (pendingRequest)
768
- scheduleNextExecute();
685
+ theme: 'light',
686
+ 'retry-interval': RETRY_INTERVAL_MS,
687
+ callback: (receivedToken) => {
688
+ var _a;
689
+ if (isDestroyed)
690
+ return;
691
+ errorCount = 0;
692
+ setToken(receivedToken);
693
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, false);
694
+ resolveToken === null || resolveToken === void 0 ? void 0 : resolveToken(receivedToken);
695
+ resolveToken = null;
696
+ rejectToken = null;
697
+ },
698
+ 'error-callback': (errorCode) => {
699
+ var _a;
700
+ if (isDestroyed)
701
+ return true;
702
+ errorCount += 1;
703
+ if (errorCount <= retryCount) {
704
+ return false;
705
+ }
706
+ errorCount = 0;
707
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, false);
708
+ if (widgetId && window.turnstile) {
709
+ try {
710
+ window.turnstile.reset(widgetId);
711
+ }
712
+ catch (_b) { }
713
+ }
714
+ if (enableFallback) {
715
+ resolveToken === null || resolveToken === void 0 ? void 0 : resolveToken(DUMMY_TURNSTILE_RESPONSE);
716
+ }
717
+ else {
718
+ const error = `[Turnstile] Verification failed (${errorCode}). Please try again.`;
719
+ console.error(error);
720
+ rejectToken === null || rejectToken === void 0 ? void 0 : rejectToken(new Error(error));
721
+ }
722
+ resolveToken = null;
723
+ rejectToken = null;
724
+ return true;
769
725
  },
770
726
  'expired-callback': () => {
771
727
  setToken(null);
772
- shouldReset = true;
773
- },
774
- 'timeout-callback': () => {
775
- if (pendingRequest) {
776
- shouldReset = true;
777
- scheduleNextExecute();
778
- }
779
728
  }
780
729
  });
781
730
  }
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
731
  async function render(hostContainer) {
787
732
  var _a;
788
733
  if (!isEnabled)
@@ -797,101 +742,71 @@ function createTurnstile(options) {
797
742
  console.error('[Turnstile] script load error', err);
798
743
  }
799
744
  }
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
745
  async function getToken() {
746
+ var _a;
805
747
  if (!isEnabled)
806
748
  return undefined;
807
- if (!isWidgetReady()) {
749
+ if (!widgetId) {
808
750
  await loadTurnstile();
809
751
  renderWidget();
810
- if (!isWidgetReady()) {
752
+ if (!widgetId)
811
753
  throw new Error('[Turnstile] widget not ready');
812
- }
813
754
  }
814
- if (currentPromise)
815
- return currentPromise;
816
- setLoading(true);
817
- const promise = new Promise((resolve, reject) => {
818
- pendingRequest = { resolve, reject, retryTimerId: null };
755
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, true);
756
+ return new Promise((resolve, reject) => {
757
+ var _a;
758
+ resolveToken = resolve;
759
+ rejectToken = reject;
819
760
  try {
820
761
  window.turnstile.execute(widgetId);
821
762
  }
822
763
  catch (e) {
823
764
  console.error('[Turnstile] execute error', e);
824
- scheduleNextExecute();
765
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, false);
766
+ resolveToken = null;
767
+ rejectToken = null;
768
+ reject(e);
825
769
  }
826
- }).finally(() => {
827
- if (currentPromise === promise)
828
- currentPromise = null;
829
770
  });
830
- currentPromise = promise;
831
- return promise;
832
771
  }
833
- /**
834
- * Returns the cached token immediately if still valid; otherwise calls
835
- * `getToken()`. Prefer this on form submit.
836
- */
837
772
  async function ensureToken() {
838
773
  if (!isEnabled)
839
774
  return undefined;
840
- if (token)
775
+ if (token && Date.now() - tokenIssuedAt < TURNSTILE_TOKEN_EXPIRY_MS)
841
776
  return token;
842
777
  return getToken();
843
778
  }
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
779
  function reset() {
780
+ var _a;
849
781
  if (widgetId && window.turnstile) {
850
782
  try {
851
783
  window.turnstile.reset(widgetId);
852
- lastResetAt = Date.now();
853
- }
854
- catch (_a) {
855
- /* ignore */
856
784
  }
785
+ catch (_b) { }
857
786
  }
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);
787
+ errorCount = 0;
868
788
  setToken(null);
789
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, false);
790
+ rejectToken === null || rejectToken === void 0 ? void 0 : rejectToken(new Error('[Turnstile] reset by caller'));
791
+ resolveToken = null;
792
+ rejectToken = null;
869
793
  }
870
- /**
871
- * Removes the widget from the DOM and rejects any pending promise.
872
- * Call in `disconnectedCallback` / component unmount.
873
- */
874
794
  function cleanup() {
875
- try {
876
- if (widgetId && window.turnstile) {
795
+ var _a;
796
+ isDestroyed = true;
797
+ if (widgetId && window.turnstile) {
798
+ try {
877
799
  window.turnstile.remove(widgetId);
878
800
  }
801
+ catch (_b) { }
879
802
  }
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
- }
803
+ errorCount = 0;
804
+ rejectToken === null || rejectToken === void 0 ? void 0 : rejectToken(null);
805
+ resolveToken = null;
806
+ rejectToken = null;
890
807
  widgetId = undefined;
891
- shouldReset = false;
892
- currentPromise = null;
893
- setLoading(false);
894
808
  setToken(null);
809
+ (_a = options.onLoadingChange) === null || _a === void 0 ? void 0 : _a.call(options, false);
895
810
  }
896
811
  return { render, getToken, ensureToken, reset, cleanup };
897
812
  }
@@ -7604,7 +7519,7 @@ const UserLogin = class {
7604
7519
  * Login API call for Gm 1.7
7605
7520
  */
7606
7521
  this.userLoginGm17 = async () => {
7607
- var _a, _b, _c;
7522
+ var _a, _b, _c, _d, _e;
7608
7523
  let headers = {
7609
7524
  'Content-Type': 'application/json'
7610
7525
  };
@@ -7616,11 +7531,13 @@ const UserLogin = class {
7616
7531
  let token;
7617
7532
  if (typeof ((_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.ensureToken) === "function") {
7618
7533
  token = await ((_c = (_b = this.captchaInstance) === null || _b === void 0 ? void 0 : _b.ensureToken) === null || _c === void 0 ? void 0 : _c.call(_b));
7534
+ headers[TURNSTILE_TOKEN_RESPONSE_HEADER] = token !== null && token !== void 0 ? token : "";
7535
+ headers[TURNSTILE_IS_VISIBLE_HEADER] = "false";
7619
7536
  }
7620
7537
  else {
7621
7538
  token = this.captchaToken;
7539
+ headers[RECAPTCHA_TOKEN_RESPONSE_HEADER] = token !== null && token !== void 0 ? token : "";
7622
7540
  }
7623
- headers['cf-captcha-response'] = token !== null && token !== void 0 ? token : "";
7624
7541
  }
7625
7542
  const options = {
7626
7543
  method: 'POST',
@@ -7649,6 +7566,7 @@ const UserLogin = class {
7649
7566
  }
7650
7567
  finally {
7651
7568
  this.isLoginLoading = false;
7569
+ (_e = (_d = this.captchaInstance) === null || _d === void 0 ? void 0 : _d.reset) === null || _e === void 0 ? void 0 : _e.call(_d);
7652
7570
  }
7653
7571
  };
7654
7572
  /**
@@ -7711,15 +7629,17 @@ const UserLogin = class {
7711
7629
  try {
7712
7630
  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
7631
  if (turnstileToken) {
7714
- headers.append('cf-captcha-response', turnstileToken);
7715
- headers.append('cfCaptchaIsVisible', 'false');
7632
+ headers.append(TURNSTILE_TOKEN_RESPONSE_HEADER, turnstileToken);
7633
+ headers.append(TURNSTILE_IS_VISIBLE_HEADER, 'false');
7716
7634
  }
7717
7635
  }
7718
7636
  catch (error) {
7719
7637
  this.hasError = true;
7720
- this.errorMessage = translate('genericError', this.lang) || `${error}`;
7721
- this.sendErrorNotification(this.errorMessage);
7722
7638
  this.isLoginLoading = false;
7639
+ if (error !== null) {
7640
+ this.errorMessage = translate('genericError', this.lang) || `${error}`;
7641
+ this.sendErrorNotification(this.errorMessage);
7642
+ }
7723
7643
  return;
7724
7644
  }
7725
7645
  }
@@ -7784,7 +7704,9 @@ const UserLogin = class {
7784
7704
  this.sendErrorNotification(this.errorMessage);
7785
7705
  })
7786
7706
  .finally(() => {
7707
+ var _a, _b;
7787
7708
  this.isLoginLoading = false;
7709
+ (_b = (_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.reset) === null || _b === void 0 ? void 0 : _b.call(_a);
7788
7710
  });
7789
7711
  };
7790
7712
  /**
@@ -7905,8 +7827,6 @@ const UserLogin = class {
7905
7827
  this.biometricactionmode = 'switch';
7906
7828
  this.isFromLogin = true;
7907
7829
  this.turnstileSiteKey = undefined;
7908
- this.turnstileEnableFallback = false;
7909
- this.turnstileRetryCount = undefined;
7910
7830
  this.userNameEmail = '';
7911
7831
  this.userPassword = '';
7912
7832
  this.isValidUserEmail = true;
@@ -7922,7 +7842,6 @@ const UserLogin = class {
7922
7842
  this.isLoginLoading = false;
7923
7843
  this.isNativeApp = false;
7924
7844
  this.biometricsLoaded = false;
7925
- this.isTurnstileLoading = false;
7926
7845
  }
7927
7846
  /**
7928
7847
  * Watch for changes in the translation URL and fetch new translations
@@ -8023,7 +7942,6 @@ const UserLogin = class {
8023
7942
  isEnabled: true,
8024
7943
  provider: "cloudflare",
8025
7944
  siteKey: this.turnstileSiteKey,
8026
- enableFallback: this.turnstileEnableFallback
8027
7945
  });
8028
7946
  }
8029
7947
  }
@@ -8056,8 +7974,7 @@ const UserLogin = class {
8056
7974
  });
8057
7975
  }
8058
7976
  async initializeCaptcha({ provider, siteKey, enableFallback }) {
8059
- const slotElement = getSlottedElement(this.host, CAPTCHA_CONTAINER_SLOT);
8060
- this.captchaContainerEl = slotElement;
7977
+ const captchaContainerEl = getSlottedElement(this.host, CAPTCHA_CONTAINER_SLOT);
8061
7978
  const captchaCreator = {
8062
7979
  "google": createRecaptcha,
8063
7980
  "cloudflare": createTurnstile
@@ -8068,7 +7985,7 @@ const UserLogin = class {
8068
7985
  enableFallback,
8069
7986
  callback: provider === "google" ? (token) => { this.captchaToken = token; } : undefined
8070
7987
  });
8071
- await this.captchaInstance.render(this.captchaContainerEl);
7988
+ await this.captchaInstance.render(captchaContainerEl);
8072
7989
  }
8073
7990
  /**
8074
7991
  * Lifecycle method: Clean up event listeners when the component is removed
@@ -8078,7 +7995,8 @@ const UserLogin = class {
8078
7995
  this.stylingSubscription && this.stylingSubscription.unsubscribe();
8079
7996
  window.removeEventListener('LoginCredentials', this.autofillCredentialsHandler);
8080
7997
  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);
7998
+ if (this.turnstileSiteKey)
7999
+ (_b = (_a = this.captchaInstance) === null || _a === void 0 ? void 0 : _a.cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
8082
8000
  }
8083
8001
  /**
8084
8002
  * Send error notification as a post message
@@ -8160,7 +8078,7 @@ const UserLogin = class {
8160
8078
  * Render function
8161
8079
  */
8162
8080
  render() {
8163
- return (h("section", { key: 'c72b94ac2e6cde988ae4798402680a527e4a004e', ref: el => this.stylingContainer = el }, this.renderUserIdentification(), h("slot", { key: '36c64bfcc9d5e19ae7b22d50638bf3c720167606', name: CAPTCHA_CONTAINER_SLOT })));
8081
+ return (h("section", { key: 'd53f60a484827fbb28b2ec8a907ac21e0781427a', ref: el => this.stylingContainer = el }, this.renderUserIdentification(), h("slot", { key: '8b42ec462b580ffb0d1448bbe185febada0bcd22', name: CAPTCHA_CONTAINER_SLOT })));
8164
8082
  }
8165
8083
  get host() { return getElement(this); }
8166
8084
  static get watchers() { return {
@@ -16,5 +16,5 @@ var patchBrowser = () => {
16
16
 
17
17
  patchBrowser().then(async (options) => {
18
18
  await globalScripts();
19
- return bootstrapLazy([["user-login",[[1,"user-login",{"endpoint":[513],"minPassLength":[514,"min-pass-length"],"lang":[1537],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"translationUrl":[513,"translation-url"],"passwordReset":[513,"password-reset"],"userEmailRegex":[513,"user-email-regex"],"userEmailRegexOptions":[513,"user-email-regex-options"],"userPhoneRegex":[513,"user-phone-regex"],"userPhoneRegexOptions":[513,"user-phone-regex-options"],"passwordRegex":[513,"password-regex"],"passwordRegexOptions":[513,"password-regex-options"],"version":[513],"loginByPhoneNumber":[513,"login-by-phone-number"],"defaultPrefix":[513,"default-prefix"],"isPrefixEditable":[513,"is-prefix-editable"],"mbSource":[513,"mb-source"],"biometricEnabled":[513,"biometric-enabled"],"biometricactionmode":[1],"isFromLogin":[4,"is-from-login"],"turnstileSiteKey":[1,"turnstile-site-key"],"turnstileEnableFallback":[4,"turnstile-enable-fallback"],"turnstileRetryCount":[2,"turnstile-retry-count"],"userNameEmail":[32],"userPassword":[32],"isValidUserEmail":[32],"userPhone":[32],"userPrefix":[32],"isValidPassword":[32],"isValidUserPhone":[32],"isPasswordVisible":[32],"errorMessage":[32],"errorForFields":[32],"hasError":[32],"phoneCodes":[32],"isLoginLoading":[32],"isNativeApp":[32],"biometricsLoaded":[32],"isTurnstileLoading":[32],"autofillCredentials":[64]},null,{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingChangeURL"]}]]]], options);
19
+ return bootstrapLazy([["user-login",[[1,"user-login",{"endpoint":[513],"minPassLength":[514,"min-pass-length"],"lang":[1537],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"translationUrl":[513,"translation-url"],"passwordReset":[513,"password-reset"],"userEmailRegex":[513,"user-email-regex"],"userEmailRegexOptions":[513,"user-email-regex-options"],"userPhoneRegex":[513,"user-phone-regex"],"userPhoneRegexOptions":[513,"user-phone-regex-options"],"passwordRegex":[513,"password-regex"],"passwordRegexOptions":[513,"password-regex-options"],"version":[513],"loginByPhoneNumber":[513,"login-by-phone-number"],"defaultPrefix":[513,"default-prefix"],"isPrefixEditable":[513,"is-prefix-editable"],"mbSource":[513,"mb-source"],"biometricEnabled":[513,"biometric-enabled"],"biometricactionmode":[1],"isFromLogin":[4,"is-from-login"],"turnstileSiteKey":[1,"turnstile-site-key"],"userNameEmail":[32],"userPassword":[32],"isValidUserEmail":[32],"userPhone":[32],"userPrefix":[32],"isValidPassword":[32],"isValidUserPhone":[32],"isPasswordVisible":[32],"errorMessage":[32],"errorForFields":[32],"hasError":[32],"phoneCodes":[32],"isLoginLoading":[32],"isNativeApp":[32],"biometricsLoaded":[32],"autofillCredentials":[64]},null,{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingChangeURL"]}]]]], options);
20
20
  });
@@ -1,3 +1,4 @@
1
+ export declare const RECAPTCHA_TOKEN_RESPONSE_HEADER = "g-recaptcha-response";
1
2
  export type RenderRecaptchaOptions = {
2
3
  siteKey: string;
3
4
  theme?: 'light' | 'dark';
@@ -1,8 +1,9 @@
1
- import { createRecaptcha } from './google';
2
- import { createTurnstile } from './turnstile';
1
+ import { createRecaptcha, RECAPTCHA_TOKEN_RESPONSE_HEADER } from './google';
2
+ import { createTurnstile, TURNSTILE_TOKEN_RESPONSE_HEADER, TURNSTILE_IS_VISIBLE_HEADER } from './turnstile';
3
+ declare const CAPTCHA_CONTAINER_SLOT = "captchaContainer";
3
4
  type CaptchaProvider = 'google' | 'cloudflare';
4
5
  type GM17CaptchaData = {
5
- isEnabled: boolean;
6
+ isEnabled?: boolean;
6
7
  provider: CaptchaProvider;
7
8
  siteKey: string;
8
9
  };
@@ -12,4 +13,4 @@ type CaptchaOption = GM17CaptchaData & {
12
13
  type RecaptchaInstance = ReturnType<typeof createRecaptcha>;
13
14
  type TurnstileInstance = ReturnType<typeof createTurnstile>;
14
15
  type CaptchaInstance = RecaptchaInstance | TurnstileInstance;
15
- export { createRecaptcha, createTurnstile, RecaptchaInstance, TurnstileInstance, CaptchaInstance, CaptchaProvider, CaptchaOption, GM17CaptchaData };
16
+ export { createRecaptcha, createTurnstile, RECAPTCHA_TOKEN_RESPONSE_HEADER, TURNSTILE_TOKEN_RESPONSE_HEADER, TURNSTILE_IS_VISIBLE_HEADER, CAPTCHA_CONTAINER_SLOT, RecaptchaInstance, TurnstileInstance, CaptchaInstance, CaptchaProvider, CaptchaOption, GM17CaptchaData };
@@ -1,51 +1,15 @@
1
+ export declare const TURNSTILE_TOKEN_RESPONSE_HEADER = "cf-captcha-response";
2
+ export declare const TURNSTILE_IS_VISIBLE_HEADER = "cfCaptchaIsVisible";
1
3
  export type CreateTurnstileOptions = {
2
4
  siteKey: string;
3
5
  action?: string;
4
- /** When false every method is a no-op; getToken/ensureToken resolve to undefined. */
5
6
  isEnabled?: boolean;
6
- /**
7
- * Resolve with DUMMY_TURNSTILE_RESPONSE after DEFAULT_RETRY_COUNT consecutive
8
- * retries. Only enable when the backend is configured to accept it (e.g. login only).
9
- */
10
7
  enableFallback?: boolean;
11
8
  retryCount?: number;
12
- /** Fired once the script has loaded and the widget is rendered. */
13
9
  onReady?: () => void;
14
- /** Fired whenever the cached token changes (new value or null on expiry/reset). */
15
10
  onTokenChange?: (token: string | null) => void;
16
- /** Fired when an async token fetch starts (true) or finishes (false). */
17
11
  onLoadingChange?: (isLoading: boolean) => void;
18
12
  };
19
- /**
20
- * Creates a self-contained Cloudflare Turnstile controller for use in any
21
- * framework (Stencil, Vue, Svelte, vanilla TS). Mirrors the behavior of the
22
- * React `useTurnstile` hook used in the Flash project.
23
- *
24
- * Typical lifecycle:
25
- * 1. Call `render(containerEl)` in your mount/componentDidLoad — loads the
26
- * script and renders an invisible widget.
27
- * 2. On form submit, `await ensureToken()` to get (or obtain) a token.
28
- * 3. Call `cleanup()` in your unmount/disconnectedCallback.
29
- *
30
- * @example
31
- * ```ts
32
- * const turnstile = createTurnstile({
33
- * siteKey: 'YOUR_SITE_KEY',
34
- * action: 'login',
35
- * onLoadingChange: (loading) => { this.isTurnstileLoading = loading; },
36
- * });
37
- *
38
- * // in componentDidLoad
39
- * await turnstile.render(this.turnstileContainerEl);
40
- *
41
- * // in handleSubmit
42
- * const token = await turnstile.ensureToken();
43
- * headers['X-Captcha-Response'] = token;
44
- *
45
- * // in disconnectedCallback
46
- * turnstile.cleanup();
47
- * ```
48
- */
49
13
  export declare function createTurnstile(options: CreateTurnstileOptions): {
50
14
  render: (hostContainer: HTMLElement) => Promise<void>;
51
15
  getToken: () => Promise<string | undefined>;
@@ -92,14 +92,6 @@ export declare class UserLogin {
92
92
  * Acts as the enable/disable flag for Turnstile.
93
93
  */
94
94
  turnstileSiteKey?: string;
95
- /**
96
- * Enable Turnstile fallback behavior.
97
- */
98
- turnstileEnableFallback?: boolean;
99
- /**
100
- * Number of retry attempts for Turnstile.
101
- */
102
- turnstileRetryCount?: number;
103
95
  userNameEmail: string;
104
96
  userPassword: string;
105
97
  isValidUserEmail: boolean;
@@ -118,13 +110,11 @@ export declare class UserLogin {
118
110
  isLoginLoading: boolean;
119
111
  isNativeApp: boolean;
120
112
  biometricsLoaded: boolean;
121
- isTurnstileLoading: boolean;
122
113
  host: HTMLElement;
123
114
  private errorCode;
124
115
  private stylingContainer?;
125
116
  private stylingSubscription;
126
117
  private captchaInstance;
127
- private captchaContainerEl;
128
118
  private captchaToken?;
129
119
  updateLoginCredentialsEvent?: CustomEvent;
130
120
  inputUserPhoneReference?: HTMLInputElement;