@everymatrix/player-step-up-auth 1.76.7 → 1.76.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/cjs/index.cjs.js +1 -1
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/{player-step-up-auth-80ad5fa5.js → player-step-up-auth-d5d44be3.js} +85 -65
  4. package/dist/cjs/player-step-up-auth.cjs.entry.js +1 -1
  5. package/dist/cjs/player-step-up-auth.cjs.js +1 -1
  6. package/dist/collection/components/player-step-up-auth/player-step-up-auth.js +87 -66
  7. package/dist/esm/index.js +1 -1
  8. package/dist/esm/loader.js +1 -1
  9. package/dist/esm/{player-step-up-auth-045726cf.js → player-step-up-auth-e624c40c.js} +85 -65
  10. package/dist/esm/player-step-up-auth.entry.js +1 -1
  11. package/dist/esm/player-step-up-auth.js +1 -1
  12. package/dist/player-step-up-auth/index.esm.js +1 -1
  13. package/dist/player-step-up-auth/{player-step-up-auth-045726cf.js → player-step-up-auth-e624c40c.js} +1 -1
  14. package/dist/player-step-up-auth/player-step-up-auth.entry.js +1 -1
  15. package/dist/player-step-up-auth/player-step-up-auth.esm.js +1 -1
  16. package/dist/types/Users/adrian.pripon/Documents/Work/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.d.ts +2 -0
  17. package/dist/types/Users/adrian.pripon/Documents/Work/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.dev.d.ts +2 -0
  18. package/dist/types/components/player-step-up-auth/player-step-up-auth.d.ts +14 -11
  19. package/package.json +1 -1
  20. package/dist/types/builds/emfe-widgets/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.d.ts +0 -2
  21. package/dist/types/builds/emfe-widgets/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/stencil.config.dev.d.ts +0 -2
  22. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/libs/common/src/storybook/storybook-utils.d.ts +0 -0
  23. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/storybook/main.d.ts +0 -0
  24. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/packages/stencil/player-step-up-auth/storybook/preview.d.ts +0 -0
  25. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/index.d.ts +0 -0
  26. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/stencil-clean-deps-plugin.d.ts +0 -0
  27. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/vite-chunk-plugin.d.ts +0 -0
  28. /package/dist/types/{builds/emfe-widgets → Users/adrian.pripon/Documents/Work}/widgets-monorepo/packages/stencil/player-step-up-auth/.stencil/tools/plugins/vite-clean-deps-plugin.d.ts +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const playerStepUpAuth = require('./player-step-up-auth-80ad5fa5.js');
5
+ const playerStepUpAuth = require('./player-step-up-auth-d5d44be3.js');
6
6
  require('./index-bf4d774c.js');
7
7
 
8
8
 
@@ -8,7 +8,7 @@ const appGlobals = require('./app-globals-3a1e7e63.js');
8
8
  const defineCustomElements = async (win, options) => {
9
9
  if (typeof window === 'undefined') return undefined;
10
10
  await appGlobals.globalScripts();
11
- return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
11
+ return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
12
12
  };
13
13
 
14
14
  exports.setNonce = index.setNonce;
@@ -368,16 +368,17 @@ const PlayerStepUpAuth = class {
368
368
  this.flow = '';
369
369
  this.showResendOtp = false;
370
370
  this.isLastWarning = false;
371
+ this.inputDisabled = false;
371
372
  this.handleResendOtp = this.handleResendOtp.bind(this);
372
373
  this.submitOtp = this.submitOtp.bind(this);
373
- this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
374
374
  this.handleCloseWidget = this.handleCloseWidget.bind(this);
375
375
  this.manualClosePopup = this.manualClosePopup.bind(this);
376
376
  }
377
377
  /**
378
- * Fetches OTP configuration from the endpoint.
379
- * Updates the OTP state, expiration time, and starts the countdown timer.
380
- */
378
+ * Fetches OTP configuration from the endpoint.
379
+ * Updates the OTP state, expiration time, and starts the countdown timer.
380
+ * Handles specific errors like max attempts exceeded by closing the widget.
381
+ */
381
382
  async getConfig() {
382
383
  if (!this.endpoint)
383
384
  return;
@@ -385,29 +386,41 @@ const PlayerStepUpAuth = class {
385
386
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
386
387
  this.isLoading = true;
387
388
  const response = await fetch(url.href);
388
- if (!response.ok)
389
- throw new Error(`HTTP error! Status: ${response.status}`);
390
- this.config = await response.json();
391
- this.otp = new Array(this.config.inputLength).fill('');
392
- this.isLoading = false;
393
- this.showResendOtp = false;
394
- this.expirationTime = this.config.expirationTime;
395
- this.serverTime = this.config.serverTime;
396
- /**
397
- * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
398
- * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
399
- */
400
- if (this.config.numberOfValidateAttempts !== 0) {
401
- this.hasErrors = true;
402
- this.errorMessage = translate('invalidOtp', this.language);
389
+ const result = await response.json(); // Parse JSON regardless of status
390
+ if (response.ok) {
391
+ //--- Success Path (2xx status) ---
392
+ this.config = result;
393
+ this.otp = Array(this.config.inputLength).fill('');
394
+ this.isLoading = false;
395
+ this.showResendOtp = false;
396
+ this.expirationTime = this.config.expirationTime;
397
+ this.serverTime = this.config.serverTime;
398
+ if (this.config.numberOfValidateAttempts !== 0) {
399
+ this.hasErrors = true;
400
+ this.errorMessage = translate('invalidOtp', this.language);
401
+ }
402
+ if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
403
+ this.isLastWarning = true;
404
+ }
405
+ this.calculateTimeLeft();
406
+ this.startCountdown();
403
407
  }
404
- if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
405
- this.isLastWarning = true;
408
+ else {
409
+ //--- Error Path (non-2xx status) ---
410
+ // Check for result existence before accessing properties for compatibility.
411
+ if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
412
+ // Specific "max attempts" error: close the widget.
413
+ this.handleCloseWidget();
414
+ }
415
+ else {
416
+ // Any other configuration error: throw to be handled by the catch block.
417
+ const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
418
+ throw new Error(errorMessage);
419
+ }
406
420
  }
407
- this.calculateTimeLeft();
408
- this.startCountdown();
409
421
  }
410
422
  catch (error) {
423
+ //--- Catch block for network errors or thrown exceptions ---
411
424
  this.isLoading = false;
412
425
  this.hasConfigErrors = true;
413
426
  this.errorMessage = translate('configError', this.language);
@@ -440,6 +453,7 @@ const PlayerStepUpAuth = class {
440
453
  const now = Date.now();
441
454
  const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
442
455
  this.timeLeft = timeRemaining;
456
+ this.inputDisabled = timeRemaining <= 0;
443
457
  if (timeRemaining <= 0) {
444
458
  clearInterval(this.countdownTimer);
445
459
  this.countdownTimer = null;
@@ -460,15 +474,6 @@ const PlayerStepUpAuth = class {
460
474
  const remainingSeconds = seconds % 60;
461
475
  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
462
476
  }
463
- /**
464
- * Sets a reference to the OTP input container.
465
- *
466
- * @param el - The OTP input container element.
467
- */
468
- setOtpContainerRef(el) {
469
- if (el)
470
- this.otpContainer = el;
471
- }
472
477
  /**
473
478
  * Sets a reference to the OTP inputs.
474
479
  *
@@ -479,6 +484,18 @@ const PlayerStepUpAuth = class {
479
484
  this.otpInputs[index] = el;
480
485
  }
481
486
  }
487
+ /**
488
+ * update otp state
489
+ * by creating new array and assign to state, to make the UI trigger
490
+ *
491
+ * @param index - The index of the input field being updated.
492
+ * @param value - The inputted value.
493
+ */
494
+ updateOtpState(index, value) {
495
+ const updated = [...this.otp];
496
+ updated[index] = value.toUpperCase();
497
+ this.otp = updated;
498
+ }
482
499
  /**
483
500
  * Handles pasting an OTP directly into the input fields.
484
501
  * Extracts characters from the clipboard and populates the OTP fields.
@@ -486,24 +503,15 @@ const PlayerStepUpAuth = class {
486
503
  * @param e - The clipboard event containing pasted data.
487
504
  */
488
505
  handleOnPasteOtp(e) {
489
- var _a;
506
+ var _a, _b, _c;
490
507
  e.preventDefault();
491
- const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
492
- if (!data)
493
- return;
494
- const value = data.slice(0, this.config.inputLength).split(""); // Limit to OTP length
495
- this.otp = [...value, ...new Array(this.config.inputLength - value.length).fill('')];
496
- const inputs = Array.from(this.otpContainer.children);
497
- if (inputs) {
498
- value.forEach((char, index) => {
499
- inputs[index].value = char;
500
- });
501
- // Move focus to the last input or trigger submit
502
- const lastInput = inputs[value.length - 1];
503
- lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
504
- if (value.length === this.config.inputLength) {
505
- this.submitOtp();
506
- }
508
+ const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
509
+ const values = data.slice(0, this.config.inputLength).split('');
510
+ this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
511
+ // Move focus to the one after last input or trigger submit
512
+ (_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
513
+ if (values.length === this.config.inputLength) {
514
+ this.submitOtp();
507
515
  }
508
516
  }
509
517
  /**
@@ -515,14 +523,14 @@ const PlayerStepUpAuth = class {
515
523
  */
516
524
  handleOtpInput(e, index) {
517
525
  const input = e.target;
518
- let value = input.value.replace(/[^0-9a-zA-Z]/gi, '').toUpperCase();
519
- input.value = value.charAt(0);
520
- if (!value)
521
- return;
522
- this.otp[index] = value[0];
523
- // Move focus using stored refs
524
- const nextInput = this.otpInputs[index + 1];
525
- nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
526
+ const value = input.value;
527
+ if (/^[a-z0-9]$/i.test(value)) {
528
+ this.updateOtpState(index, value);
529
+ // Move focus using stored refs
530
+ const nextInput = this.otpInputs[index + 1];
531
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
532
+ }
533
+ input.value = '';
526
534
  }
527
535
  /**
528
536
  * Handles key press events for OTP inputs.
@@ -532,9 +540,21 @@ const PlayerStepUpAuth = class {
532
540
  * @param index - The index of the input field.
533
541
  */
534
542
  handleKeyDown(e, index) {
535
- if (e.key === "Backspace") {
536
- this.otp[index] = '';
537
- this.otpInputs[index].value = ''; // Clear input field
543
+ const key = e.key;
544
+ const isCommandOrControlKey = e.ctrlKey || e.metaKey;
545
+ if (/^[a-z0-9]$/i.test(key)) {
546
+ if (isCommandOrControlKey && key.toLowerCase() === 'v')
547
+ return;
548
+ e.preventDefault();
549
+ this.updateOtpState(index, key);
550
+ const nextInput = this.otpInputs[index + 1];
551
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
552
+ }
553
+ else if (key === 'Backspace') {
554
+ e.preventDefault();
555
+ if (this.otp[index] !== '') {
556
+ this.updateOtpState(index, '');
557
+ }
538
558
  const prevInput = this.otpInputs[index - 1];
539
559
  prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
540
560
  }
@@ -601,7 +621,7 @@ const PlayerStepUpAuth = class {
601
621
  throw new Error(result.message);
602
622
  }
603
623
  catch (error) {
604
- if (error.message === 'gm.multifactorauthentication.challenge') {
624
+ if (error.message === 'gm.multifactorauthentication.internal_server_error') {
605
625
  if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
606
626
  window.dispatchEvent(new CustomEvent('otpSetTimeout'));
607
627
  //Trigger notification
@@ -656,8 +676,8 @@ const PlayerStepUpAuth = class {
656
676
  (_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
657
677
  }
658
678
  /**
659
- * Lifecycle method: Fetch translations on component load
660
- */
679
+ * Lifecycle method: Fetch translations on component load
680
+ */
661
681
  async componentWillLoad() {
662
682
  if (this.translationUrl.length > 2) {
663
683
  await getTranslations(this.translationUrl);
@@ -684,9 +704,9 @@ const PlayerStepUpAuth = class {
684
704
  * Displays the OTP popup, input fields, timer, and action buttons.
685
705
  */
686
706
  render() {
687
- return (index.h("div", { key: '9afac9d2e248a06828ce17dcb8dc6902fe4ec8cf', ref: el => this.stylingContainer = el }, this.showPopup && (index.h("div", { key: '48bab2747dcba4c64cb97a973a5f9961856126b8', class: "OtpPopupOverlay" }, index.h("div", { key: '89c38b7dbeb7a151f3c172d6913ea2e6884f2c40', class: "OtpPopupContent" }, this.isLoading ? (index.h("div", { class: "OtpLoaderContainer" }, index.h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (index.h("div", { class: "OtpError" }, index.h("div", { class: "OtpErrorHeader" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, index.h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), index.h("h2", null, translate('errorHeader', this.language))), index.h("p", null, this.errorMessage), index.h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (index.h(index.Fragment, null, index.h("div", { class: "otp-description" }, this.showResendOtp ? (index.h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (index.h(index.Fragment, null, index.h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (index.h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), index.h("div", { class: "OtpFieldWrapper" }, index.h("h2", null, translate('otpHeading', this.language)), index.h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index$1) => {
707
+ return (index.h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (index.h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, index.h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (index.h("div", { class: "OtpLoaderContainer" }, index.h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (index.h("div", { class: "OtpError" }, index.h("div", { class: "OtpErrorHeader" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, index.h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), index.h("h2", null, translate('errorHeader', this.language))), index.h("p", null, this.errorMessage), index.h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (index.h(index.Fragment, null, index.h("div", { class: "otp-description" }, this.showResendOtp ? (index.h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (index.h(index.Fragment, null, index.h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (index.h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), index.h("div", { class: "OtpFieldWrapper" }, index.h("h2", null, translate('otpHeading', this.language)), index.h("div", { class: "OtpField" }, this.otp.map((char, index$1) => {
688
708
  const isHalfway = this.config.inputLength % 2 === 0 && index$1 === (this.config.inputLength / 2) - 1;
689
- return (index.h("input", { key: index$1, ref: el => this.setOtpInputRef(el, index$1), id: `otp-input-${index$1}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index$1), onKeyDown: (event) => this.handleKeyDown(event, index$1), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
709
+ return (index.h("input", { key: index$1, ref: el => this.setOtpInputRef(el, index$1), id: `otp-input-${index$1}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index$1), onKeyDown: (event) => this.handleKeyDown(event, index$1), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
690
710
  })), index.h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), index.h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (index.h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (index.h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), index.h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
691
711
  }
692
712
  get el() { return index.getElement(this); }
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const playerStepUpAuth = require('./player-step-up-auth-80ad5fa5.js');
5
+ const playerStepUpAuth = require('./player-step-up-auth-d5d44be3.js');
6
6
  require('./index-bf4d774c.js');
7
7
 
8
8
 
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
22
+ return index.bootstrapLazy([["player-step-up-auth.cjs",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -104,16 +104,17 @@ export class PlayerStepUpAuth {
104
104
  this.flow = '';
105
105
  this.showResendOtp = false;
106
106
  this.isLastWarning = false;
107
+ this.inputDisabled = false;
107
108
  this.handleResendOtp = this.handleResendOtp.bind(this);
108
109
  this.submitOtp = this.submitOtp.bind(this);
109
- this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
110
110
  this.handleCloseWidget = this.handleCloseWidget.bind(this);
111
111
  this.manualClosePopup = this.manualClosePopup.bind(this);
112
112
  }
113
113
  /**
114
- * Fetches OTP configuration from the endpoint.
115
- * Updates the OTP state, expiration time, and starts the countdown timer.
116
- */
114
+ * Fetches OTP configuration from the endpoint.
115
+ * Updates the OTP state, expiration time, and starts the countdown timer.
116
+ * Handles specific errors like max attempts exceeded by closing the widget.
117
+ */
117
118
  async getConfig() {
118
119
  if (!this.endpoint)
119
120
  return;
@@ -121,29 +122,41 @@ export class PlayerStepUpAuth {
121
122
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
122
123
  this.isLoading = true;
123
124
  const response = await fetch(url.href);
124
- if (!response.ok)
125
- throw new Error(`HTTP error! Status: ${response.status}`);
126
- this.config = await response.json();
127
- this.otp = new Array(this.config.inputLength).fill('');
128
- this.isLoading = false;
129
- this.showResendOtp = false;
130
- this.expirationTime = this.config.expirationTime;
131
- this.serverTime = this.config.serverTime;
132
- /**
133
- * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
134
- * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
135
- */
136
- if (this.config.numberOfValidateAttempts !== 0) {
137
- this.hasErrors = true;
138
- this.errorMessage = translate('invalidOtp', this.language);
125
+ const result = await response.json(); // Parse JSON regardless of status
126
+ if (response.ok) {
127
+ //--- Success Path (2xx status) ---
128
+ this.config = result;
129
+ this.otp = Array(this.config.inputLength).fill('');
130
+ this.isLoading = false;
131
+ this.showResendOtp = false;
132
+ this.expirationTime = this.config.expirationTime;
133
+ this.serverTime = this.config.serverTime;
134
+ if (this.config.numberOfValidateAttempts !== 0) {
135
+ this.hasErrors = true;
136
+ this.errorMessage = translate('invalidOtp', this.language);
137
+ }
138
+ if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
139
+ this.isLastWarning = true;
140
+ }
141
+ this.calculateTimeLeft();
142
+ this.startCountdown();
139
143
  }
140
- if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
141
- this.isLastWarning = true;
144
+ else {
145
+ //--- Error Path (non-2xx status) ---
146
+ // Check for result existence before accessing properties for compatibility.
147
+ if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
148
+ // Specific "max attempts" error: close the widget.
149
+ this.handleCloseWidget();
150
+ }
151
+ else {
152
+ // Any other configuration error: throw to be handled by the catch block.
153
+ const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
154
+ throw new Error(errorMessage);
155
+ }
142
156
  }
143
- this.calculateTimeLeft();
144
- this.startCountdown();
145
157
  }
146
158
  catch (error) {
159
+ //--- Catch block for network errors or thrown exceptions ---
147
160
  this.isLoading = false;
148
161
  this.hasConfigErrors = true;
149
162
  this.errorMessage = translate('configError', this.language);
@@ -176,6 +189,7 @@ export class PlayerStepUpAuth {
176
189
  const now = Date.now();
177
190
  const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
178
191
  this.timeLeft = timeRemaining;
192
+ this.inputDisabled = timeRemaining <= 0;
179
193
  if (timeRemaining <= 0) {
180
194
  clearInterval(this.countdownTimer);
181
195
  this.countdownTimer = null;
@@ -196,15 +210,6 @@ export class PlayerStepUpAuth {
196
210
  const remainingSeconds = seconds % 60;
197
211
  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
198
212
  }
199
- /**
200
- * Sets a reference to the OTP input container.
201
- *
202
- * @param el - The OTP input container element.
203
- */
204
- setOtpContainerRef(el) {
205
- if (el)
206
- this.otpContainer = el;
207
- }
208
213
  /**
209
214
  * Sets a reference to the OTP inputs.
210
215
  *
@@ -215,6 +220,18 @@ export class PlayerStepUpAuth {
215
220
  this.otpInputs[index] = el;
216
221
  }
217
222
  }
223
+ /**
224
+ * update otp state
225
+ * by creating new array and assign to state, to make the UI trigger
226
+ *
227
+ * @param index - The index of the input field being updated.
228
+ * @param value - The inputted value.
229
+ */
230
+ updateOtpState(index, value) {
231
+ const updated = [...this.otp];
232
+ updated[index] = value.toUpperCase();
233
+ this.otp = updated;
234
+ }
218
235
  /**
219
236
  * Handles pasting an OTP directly into the input fields.
220
237
  * Extracts characters from the clipboard and populates the OTP fields.
@@ -222,24 +239,15 @@ export class PlayerStepUpAuth {
222
239
  * @param e - The clipboard event containing pasted data.
223
240
  */
224
241
  handleOnPasteOtp(e) {
225
- var _a;
242
+ var _a, _b, _c;
226
243
  e.preventDefault();
227
- const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
228
- if (!data)
229
- return;
230
- const value = data.slice(0, this.config.inputLength).split(""); // Limit to OTP length
231
- this.otp = [...value, ...new Array(this.config.inputLength - value.length).fill('')];
232
- const inputs = Array.from(this.otpContainer.children);
233
- if (inputs) {
234
- value.forEach((char, index) => {
235
- inputs[index].value = char;
236
- });
237
- // Move focus to the last input or trigger submit
238
- const lastInput = inputs[value.length - 1];
239
- lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
240
- if (value.length === this.config.inputLength) {
241
- this.submitOtp();
242
- }
244
+ const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
245
+ const values = data.slice(0, this.config.inputLength).split('');
246
+ this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
247
+ // Move focus to the one after last input or trigger submit
248
+ (_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
249
+ if (values.length === this.config.inputLength) {
250
+ this.submitOtp();
243
251
  }
244
252
  }
245
253
  /**
@@ -251,14 +259,14 @@ export class PlayerStepUpAuth {
251
259
  */
252
260
  handleOtpInput(e, index) {
253
261
  const input = e.target;
254
- let value = input.value.replace(/[^0-9a-zA-Z]/gi, '').toUpperCase();
255
- input.value = value.charAt(0);
256
- if (!value)
257
- return;
258
- this.otp[index] = value[0];
259
- // Move focus using stored refs
260
- const nextInput = this.otpInputs[index + 1];
261
- nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
262
+ const value = input.value;
263
+ if (/^[a-z0-9]$/i.test(value)) {
264
+ this.updateOtpState(index, value);
265
+ // Move focus using stored refs
266
+ const nextInput = this.otpInputs[index + 1];
267
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
268
+ }
269
+ input.value = '';
262
270
  }
263
271
  /**
264
272
  * Handles key press events for OTP inputs.
@@ -268,9 +276,21 @@ export class PlayerStepUpAuth {
268
276
  * @param index - The index of the input field.
269
277
  */
270
278
  handleKeyDown(e, index) {
271
- if (e.key === "Backspace") {
272
- this.otp[index] = '';
273
- this.otpInputs[index].value = ''; // Clear input field
279
+ const key = e.key;
280
+ const isCommandOrControlKey = e.ctrlKey || e.metaKey;
281
+ if (/^[a-z0-9]$/i.test(key)) {
282
+ if (isCommandOrControlKey && key.toLowerCase() === 'v')
283
+ return;
284
+ e.preventDefault();
285
+ this.updateOtpState(index, key);
286
+ const nextInput = this.otpInputs[index + 1];
287
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
288
+ }
289
+ else if (key === 'Backspace') {
290
+ e.preventDefault();
291
+ if (this.otp[index] !== '') {
292
+ this.updateOtpState(index, '');
293
+ }
274
294
  const prevInput = this.otpInputs[index - 1];
275
295
  prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
276
296
  }
@@ -337,7 +357,7 @@ export class PlayerStepUpAuth {
337
357
  throw new Error(result.message);
338
358
  }
339
359
  catch (error) {
340
- if (error.message === 'gm.multifactorauthentication.challenge') {
360
+ if (error.message === 'gm.multifactorauthentication.internal_server_error') {
341
361
  if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
342
362
  window.dispatchEvent(new CustomEvent('otpSetTimeout'));
343
363
  //Trigger notification
@@ -392,8 +412,8 @@ export class PlayerStepUpAuth {
392
412
  (_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
393
413
  }
394
414
  /**
395
- * Lifecycle method: Fetch translations on component load
396
- */
415
+ * Lifecycle method: Fetch translations on component load
416
+ */
397
417
  async componentWillLoad() {
398
418
  if (this.translationUrl.length > 2) {
399
419
  await getTranslations(this.translationUrl);
@@ -420,9 +440,9 @@ export class PlayerStepUpAuth {
420
440
  * Displays the OTP popup, input fields, timer, and action buttons.
421
441
  */
422
442
  render() {
423
- return (h("div", { key: '9afac9d2e248a06828ce17dcb8dc6902fe4ec8cf', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: '48bab2747dcba4c64cb97a973a5f9961856126b8', class: "OtpPopupOverlay" }, h("div", { key: '89c38b7dbeb7a151f3c172d6913ea2e6884f2c40', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
443
+ return (h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField" }, this.otp.map((char, index) => {
424
444
  const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
425
- return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
445
+ return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
426
446
  })), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
427
447
  }
428
448
  static get is() { return "player-step-up-auth"; }
@@ -577,7 +597,8 @@ export class PlayerStepUpAuth {
577
597
  "token": {},
578
598
  "flow": {},
579
599
  "showResendOtp": {},
580
- "isLastWarning": {}
600
+ "isLastWarning": {},
601
+ "inputDisabled": {}
581
602
  };
582
603
  }
583
604
  static get elementRef() { return "el"; }
package/dist/esm/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { P as PlayerStepUpAuth } from './player-step-up-auth-045726cf.js';
1
+ export { P as PlayerStepUpAuth } from './player-step-up-auth-e624c40c.js';
2
2
  import './index-c6eee6d8.js';
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-0f993ce5.js';
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await globalScripts();
8
- return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
8
+ return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
9
9
  };
10
10
 
11
11
  export { defineCustomElements };
@@ -366,16 +366,17 @@ const PlayerStepUpAuth = class {
366
366
  this.flow = '';
367
367
  this.showResendOtp = false;
368
368
  this.isLastWarning = false;
369
+ this.inputDisabled = false;
369
370
  this.handleResendOtp = this.handleResendOtp.bind(this);
370
371
  this.submitOtp = this.submitOtp.bind(this);
371
- this.setOtpContainerRef = this.setOtpContainerRef.bind(this);
372
372
  this.handleCloseWidget = this.handleCloseWidget.bind(this);
373
373
  this.manualClosePopup = this.manualClosePopup.bind(this);
374
374
  }
375
375
  /**
376
- * Fetches OTP configuration from the endpoint.
377
- * Updates the OTP state, expiration time, and starts the countdown timer.
378
- */
376
+ * Fetches OTP configuration from the endpoint.
377
+ * Updates the OTP state, expiration time, and starts the countdown timer.
378
+ * Handles specific errors like max attempts exceeded by closing the widget.
379
+ */
379
380
  async getConfig() {
380
381
  if (!this.endpoint)
381
382
  return;
@@ -383,29 +384,41 @@ const PlayerStepUpAuth = class {
383
384
  const url = new URL(`/api/v1/mfa/challenge/${this.token}/config`, this.endpoint);
384
385
  this.isLoading = true;
385
386
  const response = await fetch(url.href);
386
- if (!response.ok)
387
- throw new Error(`HTTP error! Status: ${response.status}`);
388
- this.config = await response.json();
389
- this.otp = new Array(this.config.inputLength).fill('');
390
- this.isLoading = false;
391
- this.showResendOtp = false;
392
- this.expirationTime = this.config.expirationTime;
393
- this.serverTime = this.config.serverTime;
394
- /**
395
- * `numberOfValidateAttempts` indicates how many times the user has previously attempted to enter the OTP.
396
- * A non-zero value means at least one failed attempt occurred, so an error message should be displayed.
397
- */
398
- if (this.config.numberOfValidateAttempts !== 0) {
399
- this.hasErrors = true;
400
- this.errorMessage = translate('invalidOtp', this.language);
387
+ const result = await response.json(); // Parse JSON regardless of status
388
+ if (response.ok) {
389
+ //--- Success Path (2xx status) ---
390
+ this.config = result;
391
+ this.otp = Array(this.config.inputLength).fill('');
392
+ this.isLoading = false;
393
+ this.showResendOtp = false;
394
+ this.expirationTime = this.config.expirationTime;
395
+ this.serverTime = this.config.serverTime;
396
+ if (this.config.numberOfValidateAttempts !== 0) {
397
+ this.hasErrors = true;
398
+ this.errorMessage = translate('invalidOtp', this.language);
399
+ }
400
+ if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
401
+ this.isLastWarning = true;
402
+ }
403
+ this.calculateTimeLeft();
404
+ this.startCountdown();
401
405
  }
402
- if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
403
- this.isLastWarning = true;
406
+ else {
407
+ //--- Error Path (non-2xx status) ---
408
+ // Check for result existence before accessing properties for compatibility.
409
+ if (result && result.details === 'gm.twofa.token_max_attempts_exceeded') {
410
+ // Specific "max attempts" error: close the widget.
411
+ this.handleCloseWidget();
412
+ }
413
+ else {
414
+ // Any other configuration error: throw to be handled by the catch block.
415
+ const errorMessage = (result && result.message) || `Failed to load config. Status: ${response.status}`;
416
+ throw new Error(errorMessage);
417
+ }
404
418
  }
405
- this.calculateTimeLeft();
406
- this.startCountdown();
407
419
  }
408
420
  catch (error) {
421
+ //--- Catch block for network errors or thrown exceptions ---
409
422
  this.isLoading = false;
410
423
  this.hasConfigErrors = true;
411
424
  this.errorMessage = translate('configError', this.language);
@@ -438,6 +451,7 @@ const PlayerStepUpAuth = class {
438
451
  const now = Date.now();
439
452
  const timeRemaining = Math.max(0, Math.floor((this.expirationTimestamp - now) / 1000));
440
453
  this.timeLeft = timeRemaining;
454
+ this.inputDisabled = timeRemaining <= 0;
441
455
  if (timeRemaining <= 0) {
442
456
  clearInterval(this.countdownTimer);
443
457
  this.countdownTimer = null;
@@ -458,15 +472,6 @@ const PlayerStepUpAuth = class {
458
472
  const remainingSeconds = seconds % 60;
459
473
  return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
460
474
  }
461
- /**
462
- * Sets a reference to the OTP input container.
463
- *
464
- * @param el - The OTP input container element.
465
- */
466
- setOtpContainerRef(el) {
467
- if (el)
468
- this.otpContainer = el;
469
- }
470
475
  /**
471
476
  * Sets a reference to the OTP inputs.
472
477
  *
@@ -477,6 +482,18 @@ const PlayerStepUpAuth = class {
477
482
  this.otpInputs[index] = el;
478
483
  }
479
484
  }
485
+ /**
486
+ * update otp state
487
+ * by creating new array and assign to state, to make the UI trigger
488
+ *
489
+ * @param index - The index of the input field being updated.
490
+ * @param value - The inputted value.
491
+ */
492
+ updateOtpState(index, value) {
493
+ const updated = [...this.otp];
494
+ updated[index] = value.toUpperCase();
495
+ this.otp = updated;
496
+ }
480
497
  /**
481
498
  * Handles pasting an OTP directly into the input fields.
482
499
  * Extracts characters from the clipboard and populates the OTP fields.
@@ -484,24 +501,15 @@ const PlayerStepUpAuth = class {
484
501
  * @param e - The clipboard event containing pasted data.
485
502
  */
486
503
  handleOnPasteOtp(e) {
487
- var _a;
504
+ var _a, _b, _c;
488
505
  e.preventDefault();
489
- const data = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text').trim();
490
- if (!data)
491
- return;
492
- const value = data.slice(0, this.config.inputLength).split(""); // Limit to OTP length
493
- this.otp = [...value, ...new Array(this.config.inputLength - value.length).fill('')];
494
- const inputs = Array.from(this.otpContainer.children);
495
- if (inputs) {
496
- value.forEach((char, index) => {
497
- inputs[index].value = char;
498
- });
499
- // Move focus to the last input or trigger submit
500
- const lastInput = inputs[value.length - 1];
501
- lastInput === null || lastInput === void 0 ? void 0 : lastInput.focus();
502
- if (value.length === this.config.inputLength) {
503
- this.submitOtp();
504
- }
506
+ const data = ((_b = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) === null || _b === void 0 ? void 0 : _b.trim()) || '';
507
+ const values = data.slice(0, this.config.inputLength).split('');
508
+ this.otp = [...values, ...Array(this.config.inputLength - values.length).fill('')];
509
+ // Move focus to the one after last input or trigger submit
510
+ (_c = this.otpInputs[values.length]) === null || _c === void 0 ? void 0 : _c.focus();
511
+ if (values.length === this.config.inputLength) {
512
+ this.submitOtp();
505
513
  }
506
514
  }
507
515
  /**
@@ -513,14 +521,14 @@ const PlayerStepUpAuth = class {
513
521
  */
514
522
  handleOtpInput(e, index) {
515
523
  const input = e.target;
516
- let value = input.value.replace(/[^0-9a-zA-Z]/gi, '').toUpperCase();
517
- input.value = value.charAt(0);
518
- if (!value)
519
- return;
520
- this.otp[index] = value[0];
521
- // Move focus using stored refs
522
- const nextInput = this.otpInputs[index + 1];
523
- nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
524
+ const value = input.value;
525
+ if (/^[a-z0-9]$/i.test(value)) {
526
+ this.updateOtpState(index, value);
527
+ // Move focus using stored refs
528
+ const nextInput = this.otpInputs[index + 1];
529
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
530
+ }
531
+ input.value = '';
524
532
  }
525
533
  /**
526
534
  * Handles key press events for OTP inputs.
@@ -530,9 +538,21 @@ const PlayerStepUpAuth = class {
530
538
  * @param index - The index of the input field.
531
539
  */
532
540
  handleKeyDown(e, index) {
533
- if (e.key === "Backspace") {
534
- this.otp[index] = '';
535
- this.otpInputs[index].value = ''; // Clear input field
541
+ const key = e.key;
542
+ const isCommandOrControlKey = e.ctrlKey || e.metaKey;
543
+ if (/^[a-z0-9]$/i.test(key)) {
544
+ if (isCommandOrControlKey && key.toLowerCase() === 'v')
545
+ return;
546
+ e.preventDefault();
547
+ this.updateOtpState(index, key);
548
+ const nextInput = this.otpInputs[index + 1];
549
+ nextInput === null || nextInput === void 0 ? void 0 : nextInput.focus();
550
+ }
551
+ else if (key === 'Backspace') {
552
+ e.preventDefault();
553
+ if (this.otp[index] !== '') {
554
+ this.updateOtpState(index, '');
555
+ }
536
556
  const prevInput = this.otpInputs[index - 1];
537
557
  prevInput === null || prevInput === void 0 ? void 0 : prevInput.focus();
538
558
  }
@@ -599,7 +619,7 @@ const PlayerStepUpAuth = class {
599
619
  throw new Error(result.message);
600
620
  }
601
621
  catch (error) {
602
- if (error.message === 'gm.multifactorauthentication.challenge') {
622
+ if (error.message === 'gm.multifactorauthentication.internal_server_error') {
603
623
  if (this.config.numberOfValidateAttempts === (this.config.maxValidationAttempts - 1)) {
604
624
  window.dispatchEvent(new CustomEvent('otpSetTimeout'));
605
625
  //Trigger notification
@@ -654,8 +674,8 @@ const PlayerStepUpAuth = class {
654
674
  (_a = this.stylingSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
655
675
  }
656
676
  /**
657
- * Lifecycle method: Fetch translations on component load
658
- */
677
+ * Lifecycle method: Fetch translations on component load
678
+ */
659
679
  async componentWillLoad() {
660
680
  if (this.translationUrl.length > 2) {
661
681
  await getTranslations(this.translationUrl);
@@ -682,9 +702,9 @@ const PlayerStepUpAuth = class {
682
702
  * Displays the OTP popup, input fields, timer, and action buttons.
683
703
  */
684
704
  render() {
685
- return (h("div", { key: '9afac9d2e248a06828ce17dcb8dc6902fe4ec8cf', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: '48bab2747dcba4c64cb97a973a5f9961856126b8', class: "OtpPopupOverlay" }, h("div", { key: '89c38b7dbeb7a151f3c172d6913ea2e6884f2c40', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField", ref: this.setOtpContainerRef }, this.otp.map((char, index) => {
705
+ return (h("div", { key: '481fb2d579925de2fb472f3d715712625fb7aba9', ref: el => this.stylingContainer = el }, this.showPopup && (h("div", { key: 'd9d55ab487c8bd11ed72d18e7eed49fdb59bab8b', class: "OtpPopupOverlay" }, h("div", { key: 'c42458b9f43f03dd88cb9ec8706826739cb2ee4c', class: "OtpPopupContent" }, this.isLoading ? (h("div", { class: "OtpLoaderContainer" }, h("span", { class: "OtpLoader" }))) : (this.hasConfigErrors ? (h("div", { class: "OtpError" }, h("div", { class: "OtpErrorHeader" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512" }, h("path", { d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z" })), h("h2", null, translate('errorHeader', this.language))), h("p", null, this.errorMessage), h("button", { class: "OtpButton error", onClick: this.manualClosePopup }, translate('close', this.language)))) : (h(Fragment, null, h("div", { class: "otp-description" }, this.showResendOtp ? (h("p", { class: "OtpNoticeMessage", role: "alert" }, translate('otpExpiredMessage', this.language))) : (h(Fragment, null, h("p", { class: this.isLastWarning ? 'LastWarningMessage' : '' }, translate(this.isLastWarning ? 'popupMessageLastWarning' : 'popupMessage', this.language)), this.hasErrors && (h("p", { class: "OtpErrorMessage", role: "alert" }, this.errorMessage))))), h("div", { class: "OtpFieldWrapper" }, h("h2", null, translate('otpHeading', this.language)), h("div", { class: "OtpField" }, this.otp.map((char, index) => {
686
706
  const isHalfway = this.config.inputLength % 2 === 0 && index === (this.config.inputLength / 2) - 1;
687
- return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.timeLeft <= 0 }));
707
+ return (h("input", { key: index, ref: el => this.setOtpInputRef(el, index), id: `otp-input-${index}`, type: "text", class: `otp-box ${isHalfway ? 'space' : ''}`, maxLength: 1, value: char, onInput: (event) => this.handleOtpInput(event, index), onKeyDown: (event) => this.handleKeyDown(event, index), onPaste: (event) => this.handleOnPasteOtp(event), disabled: this.inputDisabled, autoComplete: 'off' }));
688
708
  })), h("div", { class: "otp-timer" }, this.formatTime(this.timeLeft), " ", translate('minutes', this.language))), h("div", { class: "OtpActionButtons" }, this.showResendOtp ? (h("button", { class: "OtpButton", onClick: this.handleResendOtp }, translate('resendOtp', this.language))) : (h("button", { class: "OtpButton", onClick: this.submitOtp, disabled: this.otp.join('').length !== this.config.inputLength }, translate('submit', this.language))), h("button", { class: "OtpButton", onClick: this.manualClosePopup }, translate('close', this.language)))))))))));
689
709
  }
690
710
  get el() { return getElement(this); }
@@ -1,2 +1,2 @@
1
- export { P as player_step_up_auth } from './player-step-up-auth-045726cf.js';
1
+ export { P as player_step_up_auth } from './player-step-up-auth-e624c40c.js';
2
2
  import './index-c6eee6d8.js';
@@ -16,5 +16,5 @@ var patchBrowser = () => {
16
16
 
17
17
  patchBrowser().then(async (options) => {
18
18
  await globalScripts();
19
- return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
19
+ return bootstrapLazy([["player-step-up-auth",[[1,"player-step-up-auth",{"mbSource":[513,"mb-source"],"clientStyling":[513,"client-styling"],"clientStylingUrl":[513,"client-styling-url"],"language":[513],"endpoint":[513],"userSession":[513,"user-session"],"translationUrl":[513,"translation-url"],"showPopup":[32],"otp":[32],"isLoading":[32],"config":[32],"timeLeft":[32],"expirationTime":[32],"serverTime":[32],"hasErrors":[32],"hasConfigErrors":[32],"errorMessage":[32],"token":[32],"flow":[32],"showResendOtp":[32],"isLastWarning":[32],"inputDisabled":[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{"translationUrl":["handleNewTranslations"],"clientStyling":["handleClientStylingChange"],"clientStylingUrl":["handleClientStylingUrlChange"]}]]]], options);
20
20
  });
@@ -1 +1 @@
1
- export{P as PlayerStepUpAuth}from"./player-step-up-auth-045726cf.js";import"./index-c6eee6d8.js";
1
+ export{P as PlayerStepUpAuth}from"./player-step-up-auth-e624c40c.js";import"./index-c6eee6d8.js";
@@ -1 +1 @@
1
- import{r as e,h as t,F as i,g as r}from"./index-c6eee6d8.js";function o(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function a(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const s={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",popupMessageLastWarning:"If the next validation attempt is failed, you will be logged out and blocked temporarily.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again.",otpExpiredMessage:"Validation code has expired, please request a new one to continue."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",popupMessageLastWarning:"Dacă următoarea încercare de validare eșuează, veți fi delogat și blocat temporar.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou.",otpExpiredMessage:"Codul de validare a expirat, vă rugăm să solicitați unul nou pentru a continua."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",popupMessageLastWarning:"Si la prochaine tentative de validation échoue, vous serez déconnecté et temporairement bloqué.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer.",otpExpiredMessage:"Le code de validation a expiré, veuillez en demander un nouveau pour continuer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",popupMessageLastWarning:"Ha a következő érvényesítési kísérlet sikertelen, ki lesz jelentkeztetve és ideiglenesen letiltva.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra.",otpExpiredMessage:"A megerősítő kód lejárt, kérjük, kérjen egy újat a folytatáshoz."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",popupMessageLastWarning:"Bir sonraki doğrulama girişimi başarısız olursa, oturumunuz kapatılacak ve geçici olarak engelleneceksiniz.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin.",otpExpiredMessage:"Doğrulama kodunun süresi doldu, devam etmek için lütfen yeni bir tane isteyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",popupMessageLastWarning:"Αν η επόμενη προσπάθεια επικύρωσης αποτύχει, θα αποσυνδεθείτε και θα αποκλειστείτε προσωρινά.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά.",otpExpiredMessage:"Ο κωδικός επαλήθευσης έχει λήξει, παρακαλώ ζητήστε έναν νέο για να συνεχίσετε."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, será desconectado e temporariamente bloqueado.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",popupMessageLastWarning:"Ako sljedeći pokušaj provjere ne uspije, bit ćete odjavljeni i privremeno blokirani.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo.",otpExpiredMessage:"Kod za potvrdu je istekao, molimo zatražite novi kako biste nastavili."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",popupMessageLastWarning:"Wenn der nächste Validierungsversuch fehlschlägt, werden Sie abgemeldet und vorübergehend gesperrt.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.",otpExpiredMessage:"Der Bestätigungscode ist abgelaufen, bitte fordern Sie einen neuen an, um fortzufahren."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, você será desconectado e bloqueado temporariamente.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."}},n=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])s[t][i]=e[t][i]})),t(!0)}))})),l=(e,t)=>s[void 0!==t?t:"en"][e],d=class{handleNewTranslations(){n(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&o(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;if(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"]){if(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],this.flow=e.detail.flow,!this.token||!this.flow)return this.isLoading=!1,this.hasConfigErrors=!0,void(this.errorMessage=l("configError",this.language));await this.getConfig()}}handleCloseWidget(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.showPopup=!1,this.isLastWarning=!1}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.expirationTimestamp=0,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.flow="",this.showResendOtp=!1,this.isLastWarning=!1,this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.setOtpContainerRef=this.setOtpContainerRef.bind(this),this.handleCloseWidget=this.handleCloseWidget.bind(this),this.manualClosePopup=this.manualClosePopup.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href);if(!t.ok)throw new Error(`HTTP error! Status: ${t.status}`);this.config=await t.json(),this.otp=new Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,0!==this.config.numberOfValidateAttempts&&(this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language)),this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1&&(this.isLastWarning=!0),this.calculateTimeLeft(),this.startCountdown()}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=l("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime),i=new Date,r=t.getTime()-i.getTime();this.expirationTimestamp=e.getTime()-r;const o=Date.now(),a=Math.max(0,Math.floor((this.expirationTimestamp-o)/1e3));this.timeLeft=a}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{const e=Date.now(),t=Math.max(0,Math.floor((this.expirationTimestamp-e)/1e3));this.timeLeft=t,t<=0&&(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0,this.hasErrors=!1,this.isLastWarning=!1)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpContainerRef(e){e&&(this.otpContainer=e)}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}handleOnPasteOtp(e){var t;e.preventDefault();const i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text").trim();if(!i)return;const r=i.slice(0,this.config.inputLength).split("");this.otp=[...r,...new Array(this.config.inputLength-r.length).fill("")];const o=Array.from(this.otpContainer.children);if(o){r.forEach(((e,t)=>{o[t].value=e}));const e=o[r.length-1];null==e||e.focus(),r.length===this.config.inputLength&&this.submitOtp()}}handleOtpInput(e,t){const i=e.target;let r=i.value.replace(/[^0-9a-zA-Z]/gi,"").toUpperCase();if(i.value=r.charAt(0),!r)return;this.otp[t]=r[0];const o=this.otpInputs[t+1];null==o||o.focus()}handleKeyDown(e,t){if("Backspace"===e.key){this.otp[t]="",this.otpInputs[t].value="";const e=this.otpInputs[t-1];null==e||e.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested");window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=l("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join("");"stateless"===this.flow&&this.handleOtpStateless(e),"stateful"===this.flow&&await this.handleOtpStateful(e)}handleOtpStateless(e){window.dispatchEvent(new CustomEvent("otpSubmitted",{detail:{code:e,maxAttempts:this.config.maxValidationAttempts,validatedAttempts:this.config.numberOfValidateAttempts}}))}async handleOtpStateful(e){const t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.challenge"===e.message)return this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1?(window.dispatchEvent(new CustomEvent("otpSetTimeout")),window.postMessage({type:"WidgetNotification",data:{type:"error",message:l("accountBlocked",this.language)}},window.location.href),void this.handleCloseWidget()):(this.hasErrors=!0,this.errorMessage=l("invalidOtp",this.language),void this.getConfig());console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=l("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.handleCloseWidget()}manualClosePopup(){window.dispatchEvent(new CustomEvent("manualClosePopup")),this.handleCloseWidget()}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await n(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&o(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"9afac9d2e248a06828ce17dcb8dc6902fe4ec8cf",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"48bab2747dcba4c64cb97a973a5f9961856126b8",class:"OtpPopupOverlay"},t("div",{key:"89c38b7dbeb7a151f3c172d6913ea2e6884f2c40",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,l("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.manualClosePopup},l("close",this.language))):t(i,null,t("div",{class:"otp-description"},this.showResendOtp?t("p",{class:"OtpNoticeMessage",role:"alert"},l("otpExpiredMessage",this.language)):t(i,null,t("p",{class:this.isLastWarning?"LastWarningMessage":""},l(this.isLastWarning?"popupMessageLastWarning":"popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage",role:"alert"},this.errorMessage))),t("div",{class:"OtpFieldWrapper"},t("h2",null,l("otpHeading",this.language)),t("div",{class:"OtpField",ref:this.setOtpContainerRef},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.timeLeft<=0})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",l("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},l("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},l("submit",this.language)),t("button",{class:"OtpButton",onClick:this.manualClosePopup},l("close",this.language)))))))}get el(){return r(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};d.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{d as P}
1
+ import{r as e,h as t,F as i,g as o}from"./index-c6eee6d8.js";function r(e,t){if(e){const i=document.createElement("style");i.innerHTML=t,e.appendChild(i)}}function a(e,t){const i=new URL(t);fetch(i.href).then((e=>e.text())).then((t=>{const i=document.createElement("style");i.innerHTML=t,e&&e.appendChild(i)})).catch((e=>{console.error("There was an error while trying to load client styling from URL",e)}))}const s={en:{popupMessage:"Please enter the security code received on your email address to perform the update.",popupMessageLastWarning:"If the next validation attempt is failed, you will be logged out and blocked temporarily.",minutes:"minutes",errorHeader:"Error",configError:"Unable to load OTP data. Please try again later.",otpHeading:"Enter OTP",resendOtp:"Resent OTP",submit:"Submit",close:"Close",invalidOtp:"The code you've sent is not valid. Please try again.",accountBlocked:"Too many attempts for OTP. Your account has been blocked for one hour.",submissionError:"Something went wrong. Please try again.",otpExpiredMessage:"Validation code has expired, please request a new one to continue."},ro:{popupMessage:"Introduceți codul de securitate primit pe adresa dvs. de e-mail pentru a efectua actualizarea.",popupMessageLastWarning:"Dacă următoarea încercare de validare eșuează, veți fi delogat și blocat temporar.",minutes:"minute",errorHeader:"Eroare",configError:"Nu s-a putut încărca datele OTP. Vă rugăm să încercați din nou mai târziu.",otpHeading:"Introduceți OTP",resendOtp:"Retrimitere OTP",submit:"Trimite",close:"Închide",invalidOtp:"Codul introdus nu este valid. Vă rugăm să încercați din nou.",accountBlocked:"Prea multe încercări de OTP. Contul dvs. a fost blocat timp de o oră.",submissionError:"Ceva a mers prost. Vă rugăm să încercați din nou.",otpExpiredMessage:"Codul de validare a expirat, vă rugăm să solicitați unul nou pentru a continua."},fr:{popupMessage:"Veuillez entrer le code de sécurité reçu sur votre adresse e-mail pour effectuer la mise à jour.",popupMessageLastWarning:"Si la prochaine tentative de validation échoue, vous serez déconnecté et temporairement bloqué.",minutes:"minutes",errorHeader:"Erreur",configError:"Impossible de charger les données OTP. Veuillez réessayer plus tard.",otpHeading:"Entrez OTP",resendOtp:"Renvoyer OTP",submit:"Soumettre",close:"Fermer",invalidOtp:"Le code que vous avez saisi n’est pas valide. Veuillez réessayer.",accountBlocked:"Trop de tentatives OTP. Votre compte a été bloqué pendant une heure.",submissionError:"Quelque chose s'est mal passé. Veuillez réessayer.",otpExpiredMessage:"Le code de validation a expiré, veuillez en demander un nouveau pour continuer."},hu:{popupMessage:"Kérjük, adja meg az e-mail címére küldött biztonsági kódot a frissítés végrehajtásához.",popupMessageLastWarning:"Ha a következő érvényesítési kísérlet sikertelen, ki lesz jelentkeztetve és ideiglenesen letiltva.",minutes:"perc",errorHeader:"Hiba",configError:"Nem sikerült betölteni az OTP adatokat. Kérjük, próbálja újra később.",otpHeading:"OTP megadása",resendOtp:"Újraküldés",submit:"Beküldés",close:"Bezárás",invalidOtp:"A megadott kód érvénytelen. Kérjük, próbálja újra.",accountBlocked:"Túl sok OTP próbálkozás. A fiókja egy órára zárolva lett.",submissionError:"Valami hiba történt. Kérjük, próbálja újra.",otpExpiredMessage:"A megerősítő kód lejárt, kérjük, kérjen egy újat a folytatáshoz."},tr:{popupMessage:"Güncellemeyi gerçekleştirmek için e-posta adresinize gelen güvenlik kodunu girin.",popupMessageLastWarning:"Bir sonraki doğrulama girişimi başarısız olursa, oturumunuz kapatılacak ve geçici olarak engelleneceksiniz.",minutes:"dakika",errorHeader:"Hata",configError:"OTP verisi yüklenemedi. Lütfen daha sonra tekrar deneyin.",otpHeading:"OTP Girin",resendOtp:"OTP'yi Yeniden Gönder",submit:"Gönder",close:"Kapat",invalidOtp:"Gönderdiğiniz kod geçersiz. Lütfen tekrar deneyin.",accountBlocked:"Çok fazla OTP denemesi yapıldı. Hesabınız bir saat boyunca kilitlendi.",submissionError:"Bir şeyler yanlış gitti. Lütfen tekrar deneyin.",otpExpiredMessage:"Doğrulama kodunun süresi doldu, devam etmek için lütfen yeni bir tane isteyin."},el:{popupMessage:"Παρακαλώ εισάγετε τον κωδικό ασφαλείας που λάβατε στο email σας για να ολοκληρώσετε την ενημέρωση.",popupMessageLastWarning:"Αν η επόμενη προσπάθεια επικύρωσης αποτύχει, θα αποσυνδεθείτε και θα αποκλειστείτε προσωρινά.",minutes:"λεπτά",errorHeader:"Σφάλμα",configError:"Δεν ήταν δυνατή η φόρτωση των δεδομένων OTP. Παρακαλούμε προσπαθήστε ξανά αργότερα.",otpHeading:"Εισαγωγή OTP",resendOtp:"Αποστολή ξανά OTP",submit:"Υποβολή",close:"Κλείσιμο",invalidOtp:"Ο κωδικός που εισαγάγατε δεν είναι έγκυρος. Παρακαλώ προσπαθήστε ξανά.",accountBlocked:"Πάρα πολλές προσπάθειες OTP. Ο λογαριασμός σας έχει αποκλειστεί για μία ώρα.",submissionError:"Κάτι πήγε στραβά. Παρακαλώ προσπαθήστε ξανά.",otpExpiredMessage:"Ο κωδικός επαλήθευσης έχει λήξει, παρακαλώ ζητήστε έναν νέο για να συνεχίσετε."},es:{popupMessage:"Por favor, introduzca el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudo cargar los datos del OTP. Por favor, inténtelo de nuevo más tarde.",otpHeading:"Introducir OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresaste no es válido. Por favor, inténtalo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},pt:{popupMessage:"Por favor, insira o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, será desconectado e temporariamente bloqueado.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Insira o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código inserido não é válido. Por favor, tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."},hr:{popupMessage:"Unesite sigurnosni kod primljen na vašu e-mail adresu kako biste izvršili ažuriranje.",popupMessageLastWarning:"Ako sljedeći pokušaj provjere ne uspije, bit ćete odjavljeni i privremeno blokirani.",minutes:"minute",errorHeader:"Greška",configError:"Nije moguće učitati OTP podatke. Pokušajte ponovno kasnije.",otpHeading:"Unesite OTP",resendOtp:"Ponovno pošalji OTP",submit:"Pošalji",close:"Zatvori",invalidOtp:"Uneseni kod nije valjan. Molimo pokušajte ponovo.",accountBlocked:"Previše pokušaja unosa OTP-a. Vaš račun je blokiran na jedan sat.",submissionError:"Nešto je pošlo po zlu. Molimo pokušajte ponovo.",otpExpiredMessage:"Kod za potvrdu je istekao, molimo zatražite novi kako biste nastavili."},de:{popupMessage:"Bitte geben Sie den Sicherheitscode ein, den Sie an Ihre E-Mail-Adresse erhalten haben, um das Update durchzuführen.",popupMessageLastWarning:"Wenn der nächste Validierungsversuch fehlschlägt, werden Sie abgemeldet und vorübergehend gesperrt.",minutes:"Minuten",errorHeader:"Fehler",configError:"OTP-Daten konnten nicht geladen werden. Bitte versuchen Sie es später erneut.",otpHeading:"OTP eingeben",resendOtp:"OTP erneut senden",submit:"Absenden",close:"Schließen",invalidOtp:"Der eingegebene Code ist ungültig. Bitte versuchen Sie es erneut.",accountBlocked:"Zu viele OTP-Versuche. Ihr Konto wurde für eine Stunde gesperrt.",submissionError:"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.",otpExpiredMessage:"Der Bestätigungscode ist abgelaufen, bitte fordern Sie einen neuen an, um fortzufahren."},"es-mx":{popupMessage:"Por favor, ingrese el código de seguridad recibido en su correo electrónico para realizar la actualización.",popupMessageLastWarning:"Si el siguiente intento de validación falla, se cerrará tu sesión y serás bloqueado temporalmente.",minutes:"minutos",errorHeader:"Error",configError:"No se pudieron cargar los datos del OTP. Inténtelo de nuevo más tarde.",otpHeading:"Ingrese OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Cerrar",invalidOtp:"El código que ingresó no es válido. Inténtelo de nuevo.",accountBlocked:"Demasiados intentos de OTP. Su cuenta ha sido bloqueada por una hora.",submissionError:"Algo salió mal. Por favor, inténtelo de nuevo.",otpExpiredMessage:"El código de validación ha expirado, por favor solicite uno nuevo para continuar."},"pt-br":{popupMessage:"Por favor, digite o código de segurança recebido no seu e-mail para realizar a atualização.",popupMessageLastWarning:"Se a próxima tentativa de validação falhar, você será desconectado e bloqueado temporariamente.",minutes:"minutos",errorHeader:"Erro",configError:"Não foi possível carregar os dados do OTP. Tente novamente mais tarde.",otpHeading:"Digite o OTP",resendOtp:"Reenviar OTP",submit:"Enviar",close:"Fechar",invalidOtp:"O código informado não é válido. Tente novamente.",accountBlocked:"Muitas tentativas de OTP. Sua conta foi bloqueada por uma hora.",submissionError:"Algo deu errado. Por favor, tente novamente.",otpExpiredMessage:"O código de validação expirou, por favor solicite um novo para continuar."}},n=e=>new Promise((t=>{fetch(e).then((e=>e.json())).then((e=>{Object.keys(e).forEach((t=>{for(let i in e[t])s[t][i]=e[t][i]})),t(!0)}))})),d=(e,t)=>s[void 0!==t?t:"en"][e],l=class{handleNewTranslations(){n(this.translationUrl)}handleClientStylingChange(e,t){e!==t&&r(this.el,this.clientStyling)}handleClientStylingUrlChange(e,t){e!=t&&this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)}async handleStepUpAuthEvent(e){var t;if(null===(t=e.detail)||void 0===t?void 0:t["x-step-up-required"]){if(this.hasConfigErrors=!1,this.hasErrors=!1,this.errorMessage="",this.showPopup=!0,this.token=e.detail["x-step-up-token"],this.flow=e.detail.flow,!this.token||!this.flow)return this.isLoading=!1,this.hasConfigErrors=!0,void(this.errorMessage=d("configError",this.language));await this.getConfig()}}handleCloseWidget(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.showPopup=!1,this.isLastWarning=!1}constructor(t){e(this,t),this.otpInputs=[],this.countdownTimer=null,this.expirationTimestamp=0,this.mbSource=void 0,this.clientStyling=void 0,this.clientStylingUrl=void 0,this.language="en",this.endpoint=void 0,this.userSession=void 0,this.translationUrl="",this.showPopup=!1,this.otp=void 0,this.isLoading=!0,this.config=null,this.timeLeft=0,this.expirationTime="",this.serverTime="",this.hasErrors=!1,this.hasConfigErrors=!1,this.errorMessage="",this.token="",this.flow="",this.showResendOtp=!1,this.isLastWarning=!1,this.inputDisabled=!1,this.handleResendOtp=this.handleResendOtp.bind(this),this.submitOtp=this.submitOtp.bind(this),this.handleCloseWidget=this.handleCloseWidget.bind(this),this.manualClosePopup=this.manualClosePopup.bind(this)}async getConfig(){if(this.endpoint)try{const e=new URL(`/api/v1/mfa/challenge/${this.token}/config`,this.endpoint);this.isLoading=!0;const t=await fetch(e.href),i=await t.json();if(t.ok)this.config=i,this.otp=Array(this.config.inputLength).fill(""),this.isLoading=!1,this.showResendOtp=!1,this.expirationTime=this.config.expirationTime,this.serverTime=this.config.serverTime,0!==this.config.numberOfValidateAttempts&&(this.hasErrors=!0,this.errorMessage=d("invalidOtp",this.language)),this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1&&(this.isLastWarning=!0),this.calculateTimeLeft(),this.startCountdown();else{if(!i||"gm.twofa.token_max_attempts_exceeded"!==i.details){const e=i&&i.message||`Failed to load config. Status: ${t.status}`;throw new Error(e)}this.handleCloseWidget()}}catch(e){this.isLoading=!1,this.hasConfigErrors=!0,this.errorMessage=d("configError",this.language),console.error("Error loading 2FA config:",e)}}calculateTimeLeft(){const e=new Date(this.expirationTime),t=new Date(this.serverTime),i=new Date,o=t.getTime()-i.getTime();this.expirationTimestamp=e.getTime()-o;const r=Date.now(),a=Math.max(0,Math.floor((this.expirationTimestamp-r)/1e3));this.timeLeft=a}startCountdown(){this.countdownTimer&&clearInterval(this.countdownTimer),this.countdownTimer=setInterval((()=>{const e=Date.now(),t=Math.max(0,Math.floor((this.expirationTimestamp-e)/1e3));this.timeLeft=t,this.inputDisabled=t<=0,t<=0&&(clearInterval(this.countdownTimer),this.countdownTimer=null,this.showResendOtp=!0,this.hasErrors=!1,this.isLastWarning=!1)}),1e3)}formatTime(e){const t=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${t.toString().padStart(2,"0")}`}setOtpInputRef(e,t){e&&(this.otpInputs[t]=e)}updateOtpState(e,t){const i=[...this.otp];i[e]=t.toUpperCase(),this.otp=i}handleOnPasteOtp(e){var t,i,o;e.preventDefault();const r=((null===(i=null===(t=e.clipboardData)||void 0===t?void 0:t.getData("text"))||void 0===i?void 0:i.trim())||"").slice(0,this.config.inputLength).split("");this.otp=[...r,...Array(this.config.inputLength-r.length).fill("")],null===(o=this.otpInputs[r.length])||void 0===o||o.focus(),r.length===this.config.inputLength&&this.submitOtp()}handleOtpInput(e,t){const i=e.target,o=i.value;if(/^[a-z0-9]$/i.test(o)){this.updateOtpState(t,o);const e=this.otpInputs[t+1];null==e||e.focus()}i.value=""}handleKeyDown(e,t){const i=e.key,o=e.ctrlKey||e.metaKey;if(/^[a-z0-9]$/i.test(i)){if(o&&"v"===i.toLowerCase())return;e.preventDefault(),this.updateOtpState(t,i);const r=this.otpInputs[t+1];null==r||r.focus()}else if("Backspace"===i){e.preventDefault(),""!==this.otp[t]&&this.updateOtpState(t,"");const i=this.otpInputs[t-1];null==i||i.focus()}}handleResendOtp(){const e=new CustomEvent("otpResendRequested");window.dispatchEvent(e)}async submitOtp(){if(this.otp.join("").length!==this.config.inputLength)return this.hasErrors=!0,void(this.errorMessage=d("invalidOtp",this.language));this.isLoading=!0,this.hasErrors=!1,this.errorMessage="";const e=this.otp.join("");"stateless"===this.flow&&this.handleOtpStateless(e),"stateful"===this.flow&&await this.handleOtpStateful(e)}handleOtpStateless(e){window.dispatchEvent(new CustomEvent("otpSubmitted",{detail:{code:e,maxAttempts:this.config.maxValidationAttempts,validatedAttempts:this.config.numberOfValidateAttempts}}))}async handleOtpStateful(e){const t=new URL(`/api/v1/mfa/challenge/${this.token}/validate`,this.endpoint);t.searchParams.append("input",e);try{const e=await fetch(t.href,{method:"POST"});if(200===e.status)return void this.handleSuccess();const i=await e.json();throw new Error(i.message)}catch(e){if("gm.multifactorauthentication.internal_server_error"===e.message)return this.config.numberOfValidateAttempts===this.config.maxValidationAttempts-1?(window.dispatchEvent(new CustomEvent("otpSetTimeout")),window.postMessage({type:"WidgetNotification",data:{type:"error",message:d("accountBlocked",this.language)}},window.location.href),void this.handleCloseWidget()):(this.hasErrors=!0,this.errorMessage=d("invalidOtp",this.language),void this.getConfig());console.error("OTP submission failed:",e),this.hasErrors=!0,this.errorMessage=d("submissionError",this.language)}finally{this.isLoading=!1}}handleSuccess(){window.dispatchEvent(new CustomEvent("otpSuccess",{detail:{message:"User successfully authenticated"}})),this.handleCloseWidget()}manualClosePopup(){window.dispatchEvent(new CustomEvent("manualClosePopup")),this.handleCloseWidget()}disconnectedCallback(){var e;this.countdownTimer&&clearInterval(this.countdownTimer),null===(e=this.stylingSubscription)||void 0===e||e.unsubscribe()}async componentWillLoad(){this.translationUrl.length>2&&await n(this.translationUrl)}componentDidLoad(){this.stylingContainer&&(null!=window.emMessageBuss?function(e,t){if(window.emMessageBus){const i=document.createElement("style");window.emMessageBus.subscribe(t,(t=>{i.innerHTML=t,e&&e.appendChild(i)}))}}(this.stylingContainer,`${this.mbSource}.Style`):(this.clientStyling&&r(this.stylingContainer,this.clientStyling),this.clientStylingUrl&&a(this.stylingContainer,this.clientStylingUrl)))}render(){return t("div",{key:"481fb2d579925de2fb472f3d715712625fb7aba9",ref:e=>this.stylingContainer=e},this.showPopup&&t("div",{key:"d9d55ab487c8bd11ed72d18e7eed49fdb59bab8b",class:"OtpPopupOverlay"},t("div",{key:"c42458b9f43f03dd88cb9ec8706826739cb2ee4c",class:"OtpPopupContent"},this.isLoading?t("div",{class:"OtpLoaderContainer"},t("span",{class:"OtpLoader"})):this.hasConfigErrors?t("div",{class:"OtpError"},t("div",{class:"OtpErrorHeader"},t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"})),t("h2",null,d("errorHeader",this.language))),t("p",null,this.errorMessage),t("button",{class:"OtpButton error",onClick:this.manualClosePopup},d("close",this.language))):t(i,null,t("div",{class:"otp-description"},this.showResendOtp?t("p",{class:"OtpNoticeMessage",role:"alert"},d("otpExpiredMessage",this.language)):t(i,null,t("p",{class:this.isLastWarning?"LastWarningMessage":""},d(this.isLastWarning?"popupMessageLastWarning":"popupMessage",this.language)),this.hasErrors&&t("p",{class:"OtpErrorMessage",role:"alert"},this.errorMessage))),t("div",{class:"OtpFieldWrapper"},t("h2",null,d("otpHeading",this.language)),t("div",{class:"OtpField"},this.otp.map(((e,i)=>t("input",{key:i,ref:e=>this.setOtpInputRef(e,i),id:`otp-input-${i}`,type:"text",class:"otp-box "+(this.config.inputLength%2==0&&i===this.config.inputLength/2-1?"space":""),maxLength:1,value:e,onInput:e=>this.handleOtpInput(e,i),onKeyDown:e=>this.handleKeyDown(e,i),onPaste:e=>this.handleOnPasteOtp(e),disabled:this.inputDisabled,autoComplete:"off"})))),t("div",{class:"otp-timer"},this.formatTime(this.timeLeft)," ",d("minutes",this.language))),t("div",{class:"OtpActionButtons"},this.showResendOtp?t("button",{class:"OtpButton",onClick:this.handleResendOtp},d("resendOtp",this.language)):t("button",{class:"OtpButton",onClick:this.submitOtp,disabled:this.otp.join("").length!==this.config.inputLength},d("submit",this.language)),t("button",{class:"OtpButton",onClick:this.manualClosePopup},d("close",this.language)))))))}get el(){return o(this)}static get watchers(){return{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}}};l.style=".OtpPopupOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--emw--color-overlay, rgba(0, 0, 0, 0.5));display:flex;align-items:center;justify-content:center}.OtpButton{font-family:var(--emw--button-typography);border:var(--emw--button-border, none);border-radius:var(--emw--button-border-radius, 3px);border-color:var(--emw--button-border-color);background-color:var(--emw--button-background-color, var(--emw--color-primary, #007bff));color:var(--emw--button-typography, var(--emw--color-white, #fff));padding:10px 20px;cursor:pointer;font-size:16px}.OtpButton.error{background:var(--emw--color-error, #dd3434)}.OtpPopupContent{position:relative;background:var(--emw--color-white, #fff);padding:20px;border-radius:5px;text-align:center;min-width:25%;min-height:200px;display:flex;flex-direction:column;justify-content:center;gap:20px}.OtpPopupContent .OtpError{display:flex;flex-direction:column;gap:20px;align-items:center}.OtpPopupContent .OtpError .OtpErrorHeader{display:flex;justify-content:center;gap:5px}.OtpPopupContent .OtpError h2{margin:0}.OtpPopupContent .OtpError svg{width:25px;fill:var(--emw--color-error, #dd3434)}.OtpFieldWrapper{display:flex;flex-direction:column;gap:10px}.OtpFieldWrapper h2{margin:0}.OtpField{display:flex;justify-content:center}.OtpField input{width:24px;font-size:32px;padding:10px;text-align:center;border-radius:5px;margin:2px;border:2px solid var(--emw--otp-border-color, #55525c);font-weight:bold;outline:none;transition:all 0.1s}.OtpField input.space{margin-right:1rem !important}.OtpField input:focus{border:2px solid var(--emw--color-primary, #007bff);box-shadow:0 0 2px 2px var(--emw--color-primary, #007bff)}.OtpActionButtons{display:flex;justify-content:space-between}.OtpErrorMessage{color:var(--emw--color-error, #dd3434);font-weight:bold}.OtpLoaderContainer{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.OtpLoader{width:48px;height:48px;border:5px solid var(--emw--color-secondary, #b3d8ff);border-bottom-color:var(--emw--color-primary, #007bff);border-radius:50%;display:inline-block;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";export{l as P}
@@ -1 +1 @@
1
- export{P as player_step_up_auth}from"./player-step-up-auth-045726cf.js";import"./index-c6eee6d8.js";
1
+ export{P as player_step_up_auth}from"./player-step-up-auth-e624c40c.js";import"./index-c6eee6d8.js";
@@ -1 +1 @@
1
- import{p as e,b as n}from"./index-c6eee6d8.js";export{s as setNonce}from"./index-c6eee6d8.js";import{g as t}from"./app-globals-0f993ce5.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["player-step-up-auth",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],flow:[32],showResendOtp:[32],isLastWarning:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
1
+ import{p as e,b as n}from"./index-c6eee6d8.js";export{s as setNonce}from"./index-c6eee6d8.js";import{g as t}from"./app-globals-0f993ce5.js";(()=>{const n=import.meta.url,t={};return""!==n&&(t.resourcesUrl=new URL(".",n).href),e(t)})().then((async e=>(await t(),n([["player-step-up-auth",[[1,"player-step-up-auth",{mbSource:[513,"mb-source"],clientStyling:[513,"client-styling"],clientStylingUrl:[513,"client-styling-url"],language:[513],endpoint:[513],userSession:[513,"user-session"],translationUrl:[513,"translation-url"],showPopup:[32],otp:[32],isLoading:[32],config:[32],timeLeft:[32],expirationTime:[32],serverTime:[32],hasErrors:[32],hasConfigErrors:[32],errorMessage:[32],token:[32],flow:[32],showResendOtp:[32],isLastWarning:[32],inputDisabled:[32]},[[8,"stepUpAuthRequired","handleStepUpAuthEvent"],[8,"closePopup","handleCloseWidget"]],{translationUrl:["handleNewTranslations"],clientStyling:["handleClientStylingChange"],clientStylingUrl:["handleClientStylingUrlChange"]}]]]],e))));
@@ -0,0 +1,2 @@
1
+ import { Config } from '../../../../../../../../../../../../stencil-public-runtime';
2
+ export declare const config: Config;
@@ -0,0 +1,2 @@
1
+ import { Config } from '../../../../../../../../../../../../stencil-public-runtime';
2
+ export declare const config: Config;
@@ -42,9 +42,9 @@ export declare class PlayerStepUpAuth {
42
42
  flow: string;
43
43
  showResendOtp: boolean;
44
44
  isLastWarning: boolean;
45
+ inputDisabled: boolean;
45
46
  private stylingContainer;
46
47
  private stylingSubscription;
47
- private otpContainer;
48
48
  private otpInputs;
49
49
  private countdownTimer;
50
50
  private expirationTimestamp;
@@ -89,9 +89,10 @@ export declare class PlayerStepUpAuth {
89
89
  */
90
90
  constructor();
91
91
  /**
92
- * Fetches OTP configuration from the endpoint.
93
- * Updates the OTP state, expiration time, and starts the countdown timer.
94
- */
92
+ * Fetches OTP configuration from the endpoint.
93
+ * Updates the OTP state, expiration time, and starts the countdown timer.
94
+ * Handles specific errors like max attempts exceeded by closing the widget.
95
+ */
95
96
  getConfig(): Promise<void>;
96
97
  /**
97
98
  * Calculates the remaining time for OTP expiration.
@@ -111,17 +112,19 @@ export declare class PlayerStepUpAuth {
111
112
  */
112
113
  formatTime(seconds: number): string;
113
114
  /**
114
- * Sets a reference to the OTP input container.
115
+ * Sets a reference to the OTP inputs.
115
116
  *
116
117
  * @param el - The OTP input container element.
117
118
  */
118
- setOtpContainerRef(el: HTMLDivElement | null): void;
119
+ setOtpInputRef(el: HTMLInputElement | null, index: number): void;
119
120
  /**
120
- * Sets a reference to the OTP inputs.
121
+ * update otp state
122
+ * by creating new array and assign to state, to make the UI trigger
121
123
  *
122
- * @param el - The OTP input container element.
124
+ * @param index - The index of the input field being updated.
125
+ * @param value - The inputted value.
123
126
  */
124
- setOtpInputRef(el: HTMLInputElement | null, index: number): void;
127
+ updateOtpState(index: number, value: string): void;
125
128
  /**
126
129
  * Handles pasting an OTP directly into the input fields.
127
130
  * Extracts characters from the clipboard and populates the OTP fields.
@@ -181,8 +184,8 @@ export declare class PlayerStepUpAuth {
181
184
  */
182
185
  disconnectedCallback(): void;
183
186
  /**
184
- * Lifecycle method: Fetch translations on component load
185
- */
187
+ * Lifecycle method: Fetch translations on component load
188
+ */
186
189
  componentWillLoad(): Promise<void>;
187
190
  /**
188
191
  * Lifecycle method: Set up event listeners after the component is rendered
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everymatrix/player-step-up-auth",
3
- "version": "1.76.7",
3
+ "version": "1.76.9",
4
4
  "main": "./dist/index.cjs.js",
5
5
  "module": "./dist/index.js",
6
6
  "es2015": "./dist/esm/index.mjs",
@@ -1,2 +0,0 @@
1
- import { Config } from '../../../../../../../../../../stencil-public-runtime';
2
- export declare const config: Config;
@@ -1,2 +0,0 @@
1
- import { Config } from '../../../../../../../../../../stencil-public-runtime';
2
- export declare const config: Config;