vk-payments 0.2.28 → 0.2.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { Injectable, ɵɵdefineInjectable, ɵɵinject, EventEmitter, Component, Input, Output, ViewChild, NgModule } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule, ReactiveFormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
3
+ import { FormsModule, ReactiveFormsModule, FormGroup, FormControl } from '@angular/forms';
4
4
  import { Router, RouterModule } from '@angular/router';
5
5
  import { __values, __awaiter, __generator } from 'tslib';
6
6
  import { HttpHeaders, HttpClient, HttpClientModule } from '@angular/common/http';
@@ -3773,25 +3773,86 @@ if (false) {
3773
3773
  var BankTransferComponent = /** @class */ (function () {
3774
3774
  function BankTransferComponent(bankTransferApi) {
3775
3775
  this.bankTransferApi = bankTransferApi;
3776
+ this.discountRate = 0.10; // Tasa de descuento (10% por defecto)
3777
+ // Tasa de descuento (10% por defecto)
3776
3778
  this.statusPay = new EventEmitter();
3777
3779
  this.isLoading = false;
3778
3780
  this.errorMessage = '';
3781
+ this.submittedSuccessfully = false;
3782
+ this.amountCopied = false;
3783
+ // CUIT no se pide al usuario por ahora — se envía valor genérico
3779
3784
  this.paymentForm = new FormGroup({
3780
- cuit: new FormControl('', [
3781
- Validators.required,
3782
- Validators.minLength(11),
3783
- Validators.maxLength(11),
3784
- Validators.pattern('^[0-9]*$')
3785
- ]),
3785
+ cuit: new FormControl('00000000000')
3786
3786
  });
3787
3787
  }
3788
+ Object.defineProperty(BankTransferComponent.prototype, "subtotalAmount", {
3789
+ // Calculados a partir de `amount` (que ya tiene el descuento aplicado)
3790
+ get:
3791
+ // Calculados a partir de `amount` (que ya tiene el descuento aplicado)
3792
+ /**
3793
+ * @return {?}
3794
+ */
3795
+ function () {
3796
+ return this.amount ? Math.round(this.amount / (1 - this.discountRate)) : 0;
3797
+ },
3798
+ enumerable: true,
3799
+ configurable: true
3800
+ });
3801
+ Object.defineProperty(BankTransferComponent.prototype, "discountAmount", {
3802
+ get: /**
3803
+ * @return {?}
3804
+ */
3805
+ function () {
3806
+ return this.subtotalAmount - (this.amount || 0);
3807
+ },
3808
+ enumerable: true,
3809
+ configurable: true
3810
+ });
3788
3811
  /**
3789
3812
  * @return {?}
3790
3813
  */
3791
3814
  BankTransferComponent.prototype.ngOnInit = /**
3792
3815
  * @return {?}
3793
3816
  */
3817
+ function () { };
3818
+ /**
3819
+ * @param {?} text
3820
+ * @return {?}
3821
+ */
3822
+ BankTransferComponent.prototype.copyToClipboard = /**
3823
+ * @param {?} text
3824
+ * @return {?}
3825
+ */
3826
+ function (text) {
3827
+ navigator.clipboard.writeText(text).catch((/**
3828
+ * @return {?}
3829
+ */
3830
+ function () {
3831
+ /** @type {?} */
3832
+ var el = document.createElement('textarea');
3833
+ el.value = text;
3834
+ document.body.appendChild(el);
3835
+ el.select();
3836
+ document.execCommand('copy');
3837
+ document.body.removeChild(el);
3838
+ }));
3839
+ };
3840
+ /**
3841
+ * @return {?}
3842
+ */
3843
+ BankTransferComponent.prototype.copyAmount = /**
3844
+ * @return {?}
3845
+ */
3794
3846
  function () {
3847
+ var _this = this;
3848
+ /** @type {?} */
3849
+ var amountStr = this.amount ? this.amount.toFixed(2) : '0';
3850
+ this.copyToClipboard(amountStr);
3851
+ this.amountCopied = true;
3852
+ setTimeout((/**
3853
+ * @return {?}
3854
+ */
3855
+ function () { return _this.amountCopied = false; }), 2000);
3795
3856
  };
3796
3857
  /**
3797
3858
  * @return {?}
@@ -3801,20 +3862,16 @@ var BankTransferComponent = /** @class */ (function () {
3801
3862
  */
3802
3863
  function () {
3803
3864
  var _this = this;
3804
- if (this.paymentForm.invalid) {
3805
- this.paymentForm.markAllAsTouched();
3865
+ if (this.submittedSuccessfully || this.isLoading)
3806
3866
  return;
3807
- }
3808
3867
  this.isLoading = true;
3809
3868
  this.errorMessage = '';
3810
3869
  /** @type {?} */
3811
- var cuitControl = this.paymentForm.get('cuit');
3812
- /** @type {?} */
3813
- var cuitValue = cuitControl ? cuitControl.value : '';
3814
- /** @type {?} */
3815
3870
  var request = {
3816
- cuit: cuitValue.toString(),
3871
+ cuit: '00000000000',
3872
+ // Valor genérico mientras no se pide al usuario
3817
3873
  checkoutId: this.checkoutId,
3874
+ checkoutAdditionalData: this.checkoutAdditionalData,
3818
3875
  storeName: this.storeName || 'Tienda VK',
3819
3876
  storeId: this.storeId
3820
3877
  };
@@ -3825,7 +3882,7 @@ var BankTransferComponent = /** @class */ (function () {
3825
3882
  function (response) {
3826
3883
  _this.isLoading = false;
3827
3884
  if (response && response.success) {
3828
- // Exito!
3885
+ _this.submittedSuccessfully = true;
3829
3886
  _this.statusPay.emit({
3830
3887
  success: true,
3831
3888
  paymentId: (response.data && response.data.bankTransferEcommId) ? response.data.bankTransferEcommId : '',
@@ -3833,8 +3890,9 @@ var BankTransferComponent = /** @class */ (function () {
3833
3890
  });
3834
3891
  }
3835
3892
  else {
3836
- // El API respondió HTTP 200 pero success: false
3837
- _this.errorMessage = (response.errorsMessages && response.errorsMessages.length > 0) ? response.errorsMessages[0] : 'Ocurrió un error al registrar la transferencia.';
3893
+ _this.errorMessage = (response.errorsMessages && response.errorsMessages.length > 0)
3894
+ ? response.errorsMessages[0]
3895
+ : 'Ocurrió un error al registrar la transferencia.';
3838
3896
  _this.statusPay.emit({
3839
3897
  success: false,
3840
3898
  paymentId: '',
@@ -3846,9 +3904,10 @@ var BankTransferComponent = /** @class */ (function () {
3846
3904
  * @return {?}
3847
3905
  */
3848
3906
  function (error) {
3849
- // Error HTTP (500, 400, etc)
3850
3907
  _this.isLoading = false;
3851
- _this.errorMessage = (error && error.error && error.error.errorsMessages && error.error.errorsMessages.length > 0) ? error.error.errorsMessages[0] : 'Ocurrió un error de conexión al registrar la transferencia.';
3908
+ _this.errorMessage = (error && error.error && error.error.errorsMessages && error.error.errorsMessages.length > 0)
3909
+ ? error.error.errorsMessages[0]
3910
+ : 'Ocurrió un error de conexión al registrar la transferencia.';
3852
3911
  _this.statusPay.emit({
3853
3912
  success: false,
3854
3913
  paymentId: '',
@@ -3858,10 +3917,7 @@ var BankTransferComponent = /** @class */ (function () {
3858
3917
  }));
3859
3918
  };
3860
3919
  Object.defineProperty(BankTransferComponent.prototype, "cuitControl", {
3861
- // Helper para validación visual en el template
3862
- get:
3863
- // Helper para validación visual en el template
3864
- /**
3920
+ get: /**
3865
3921
  * @return {?}
3866
3922
  */
3867
3923
  function () {
@@ -3873,8 +3929,8 @@ var BankTransferComponent = /** @class */ (function () {
3873
3929
  BankTransferComponent.decorators = [
3874
3930
  { type: Component, args: [{
3875
3931
  selector: 'vk-bank-transfer',
3876
- template: "<form\n [formGroup]=\"paymentForm\"\n (ngSubmit)=\"onSubmit()\"\n class=\"bt-payment\"\n id=\"formularioBT\"\n autocomplete=\"off\"\n>\n\n <div class=\"formRow\">\n <p class=\"description\">\n Complet\u00E1 tu CUIT/CUIL para registrar el pago por transferencia. \n Una vez confirmado, tu pedido quedar\u00E1 sujeto a la aprobaci\u00F3n del pago.\n </p>\n </div>\n\n <div class=\"formRow\">\n <label for=\"cuit\">CUIT / CUIL del titular de la cuenta origen *</label>\n <span>\n <input\n id=\"cuit\"\n type=\"text\"\n formControlName=\"cuit\"\n name=\"cuit\"\n required\n maxlength=\"11\"\n placeholder=\"Ej: 20112223334 (Sin guiones)\"\n [ngClass]=\"{'is-invalid': cuitControl?.invalid && (cuitControl?.dirty || cuitControl?.touched)}\"\n />\n </span>\n \n <p\n class=\"alert-text\"\n *ngIf=\"cuitControl?.invalid && (cuitControl?.dirty || cuitControl?.touched)\"\n >\n <span *ngIf=\"cuitControl?.errors?.required\">El CUIT/CUIL es obligatorio.</span>\n <span *ngIf=\"cuitControl?.errors?.pattern\">Debe contener solo n\u00FAmeros.</span>\n <span *ngIf=\"cuitControl?.errors?.minlength || cuitControl?.errors?.maxlength\">Debe tener exactamente 11 d\u00EDgitos.</span>\n </p>\n </div>\n\n <div class=\"summary-box\">\n <div class=\"summary-row total\">\n <span>Total a transferir:</span>\n <span class=\"amount\">${{ amount | number:'1.2-2' }}</span>\n </div>\n <small>* El 10% de descuento extra ya se encuentra aplicado a este total.</small>\n </div>\n\n <!-- Loading State -->\n <div *ngIf=\"isLoading\" class=\"pay-message info\">\n <i class=\"material-icons\">info</i>\n <p>Procesando informaci\u00F3n de transferencia...</p>\n </div>\n\n <!-- Error devuelto por la API -->\n <div class=\"pay-message error\" *ngIf=\"errorMessage && !isLoading\">\n <i class=\"material-icons\">error</i>\n <p>{{ errorMessage }}</p>\n </div>\n\n <div>\n <button type=\"submit\" [disabled]=\"paymentForm.invalid || isLoading\">\n Confirmar Transferencia\n </button>\n </div>\n\n</form>\n",
3877
- styles: [".bt-payment{background-color:transparent;font-family:inherit,sans-serif}.bt-payment p.description{font-size:14px;color:#888;margin-bottom:5px}.bt-payment .formRow{margin-top:10px}.bt-payment .formRow label{font-size:14px;color:#888}.bt-payment .formRow span{background-color:#fff;border:.5px solid #707070;border-radius:2px;padding:2px 10px;display:block;margin-top:4px}.bt-payment .formRow span input[type=text]{background:0 0;border:none;color:#000;font-size:15px;height:23px;width:100%;text-transform:uppercase;vertical-align:top;padding:0;margin:0}.bt-payment .formRow span input[type=text]:focus{outline:0}.bt-payment .alert-text{font-size:13px;color:#009ee3;margin-top:7px;margin-bottom:0}.bt-payment .summary-box{margin-top:20px;margin-bottom:20px;text-align:right}.bt-payment .summary-box .summary-row{display:flex;justify-content:flex-end;align-items:center;font-size:16px;color:#333}.bt-payment .summary-box .summary-row span.amount{font-weight:700;color:#000;margin-left:10px}.bt-payment .summary-box small{display:block;color:#888;font-size:12px;margin-top:5px}.bt-payment button{background-color:#009ee3;color:#fff;font-size:18px;text-align:center;padding:10px 0;width:100%;border:none;border-radius:20px;margin-top:20px;cursor:pointer}.bt-payment button:disabled{background-color:#525252;cursor:not-allowed}.bt-payment .pay-message{margin-top:10px;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:20px}.bt-payment .pay-message p{font-size:1.1rem;text-align:center;line-height:130%;margin-bottom:10px}.bt-payment .pay-message i.data{font-size:.9rem;text-align:center}.bt-payment .pay-message i.material-icons{font-size:2rem;margin-bottom:5px}.bt-payment .success{background-color:#dff2bf;color:#4f8a10}.bt-payment .error{color:#d8000c;background-color:#ffd2d2}.bt-payment .info{color:#00529b;background-color:#bde5f8}:focus{outline:0}"]
3932
+ template: "<form\n [formGroup]=\"paymentForm\"\n (ngSubmit)=\"onSubmit()\"\n class=\"bt-payment\"\n id=\"formularioBT\"\n autocomplete=\"off\"\n>\n\n <!-- Datos bancarios -->\n <div class=\"bank-info-box\">\n <div class=\"bank-info-header\">\n <i class=\"material-icons\">account_balance</i>\n <span>Datos para la transferencia</span>\n </div>\n <div class=\"bank-info-row\">\n <span class=\"bank-info-label\"><i class=\"material-icons\">tag</i>N\u00FAmero de cuenta</span>\n <span class=\"bank-info-value\">2-311972/1</span>\n </div>\n <div class=\"bank-info-row\">\n <span class=\"bank-info-label\"><i class=\"material-icons\">qr_code</i>CBU</span>\n <span class=\"bank-info-value bank-info-copy\">\n <span class=\"bank-info-copy-text\">4150002012003119720013</span>\n <button class=\"copy-btn\" type=\"button\" title=\"Copiar CBU\" (click)=\"copyToClipboard('4150002012003119720013')\">\n <i class=\"material-icons\">content_copy</i>\n </button>\n </span>\n </div>\n <div class=\"bank-info-row\">\n <span class=\"bank-info-label\"><i class=\"material-icons\">alternate_email</i>Alias</span>\n <span class=\"bank-info-value bank-info-copy\">\n <span class=\"bank-info-copy-text\">reba.vitnik</span>\n <button class=\"copy-btn\" type=\"button\" title=\"Copiar alias\" (click)=\"copyToClipboard('reba.vitnik')\">\n <i class=\"material-icons\">content_copy</i>\n </button>\n </span>\n </div>\n <div class=\"bank-info-row\">\n <span class=\"bank-info-label\"><i class=\"material-icons\">badge</i>CUIT/CUIL</span>\n <span class=\"bank-info-value\">30708777893</span>\n </div>\n <div class=\"bank-info-row\">\n <span class=\"bank-info-label\"><i class=\"material-icons\">attach_money</i>Moneda</span>\n <span class=\"bank-info-value\">Peso Argentino</span>\n </div>\n </div>\n\n <!-- Resumen con desglose del descuento -->\n <div class=\"summary-box\">\n <div class=\"summary-row\">\n <span class=\"summary-label\">Subtotal</span>\n <span class=\"summary-value\">${{ subtotalAmount | number:'1.2-2' }}</span>\n </div>\n <div class=\"summary-row discount\">\n <span class=\"summary-label\">\n <i class=\"material-icons\">local_offer</i>\n Descuento transferencia ({{ discountRate * 100 | number:'1.0-0' }}%)\n </span>\n <span class=\"summary-value discount-value\">-${{ discountAmount | number:'1.2-2' }}</span>\n </div>\n <div class=\"summary-row total\">\n <span class=\"summary-label\">Total a transferir</span>\n <span class=\"summary-value total-value\">\n ${{ amount | number:'1.2-2' }}\n <button\n class=\"copy-btn copy-amount-btn\"\n type=\"button\"\n [title]=\"amountCopied ? 'Copiado!' : 'Copiar monto'\"\n (click)=\"copyAmount()\"\n >\n <i class=\"material-icons\">{{ amountCopied ? 'check' : 'content_copy' }}</i>\n </button>\n </span>\n </div>\n </div>\n\n <!-- Leyenda de monto exacto -->\n <div class=\"exact-amount-notice\">\n <i class=\"material-icons notice-icon\">info</i>\n <p>\n <strong>\u00A1Ya casi es tuyo!</strong> Para que podamos procesar tu pedido sin demoras,\n asegurate de que el importe de la transferencia sea <strong>id\u00E9ntico</strong> al total indicado arriba.\n </p>\n </div>\n\n <!-- Error devuelto por la API -->\n <div class=\"pay-message error\" *ngIf=\"errorMessage && !isLoading\">\n <i class=\"material-icons\">error</i>\n <p>{{ errorMessage }}</p>\n </div>\n\n <!-- Loading -->\n <div *ngIf=\"isLoading\" class=\"pay-message info\">\n <i class=\"material-icons\">info</i>\n <p>Procesando informaci\u00F3n de transferencia...</p>\n </div>\n\n <!-- Bot\u00F3n confirmar (oculto tras \u00E9xito) -->\n <div *ngIf=\"!submittedSuccessfully\">\n <button type=\"submit\" [disabled]=\"paymentForm.invalid || isLoading\">\n Confirmar Transferencia\n </button>\n </div>\n\n</form>\n",
3933
+ styles: [".bt-payment{background-color:transparent;font-family:inherit,sans-serif;padding:0 12px}.bt-payment p.description{font-size:16px;color:#888;margin-bottom:5px}.bt-payment .bank-info-box{border:1px solid #c8e0f0;border-radius:8px;overflow:hidden;margin-bottom:18px}.bt-payment .bank-info-box .bank-info-header{display:flex;align-items:center;gap:8px;background-color:#009ee3;color:#fff;padding:10px 14px;font-size:18px;font-weight:600;letter-spacing:.4px;text-transform:uppercase}.bt-payment .bank-info-box .bank-info-header i.material-icons{font-size:18px}.bt-payment .bank-info-box .bank-info-row{display:flex;justify-content:space-between;align-items:center;font-size:18px;padding:8px 14px;background-color:#fff;border-bottom:1px solid #eef3f7}.bt-payment .bank-info-box .bank-info-row:last-child{border-bottom:none}.bt-payment .bank-info-box .bank-info-label{display:flex;align-items:center;gap:6px;color:#777;flex-shrink:0;margin-right:8px}.bt-payment .bank-info-box .bank-info-label i.material-icons{font-size:15px;color:#009ee3}.bt-payment .bank-info-box .bank-info-value{font-weight:600;color:#1a1a1a;text-align:right}.bt-payment .bank-info-box .bank-info-value.bank-info-copy{display:flex;align-items:center;gap:4px}.bt-payment .bank-info-box .bank-info-value .bank-info-copy-text{font-family:\"Courier New\",monospace;font-size:18px;letter-spacing:.3px}.bt-payment .bank-info-box .copy-btn{background:0 0;border:none;cursor:pointer;padding:2px 4px;border-radius:4px;color:#009ee3;display:flex;align-items:center;margin-top:0;width:auto;min-width:unset}.bt-payment .bank-info-box .copy-btn i.material-icons{font-size:16px}.bt-payment .bank-info-box .copy-btn:hover{background-color:#e8f4fb}.bt-payment .bank-info-box .copy-btn:disabled{background-color:transparent;cursor:default}.bt-payment .summary-box{margin:20px 0;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}.bt-payment .summary-box .summary-row{display:flex;justify-content:space-between;align-items:center;padding:10px 16px;font-size:16px;background-color:#fff;border-bottom:1px solid #f0f0f0}.bt-payment .summary-box .summary-row:last-child{border-bottom:none}.bt-payment .summary-box .summary-row .summary-label{display:flex;align-items:center;gap:6px;color:#555}.bt-payment .summary-box .summary-row .summary-label i.material-icons{font-size:14px}.bt-payment .summary-box .summary-row .summary-value{font-weight:600;color:#1a1a1a;display:flex;align-items:center;gap:6px}.bt-payment .summary-box .summary-row.discount{background-color:#f0fdf4}.bt-payment .summary-box .summary-row.discount .summary-label{color:#16a34a;font-weight:500}.bt-payment .summary-box .summary-row.discount .summary-label i.material-icons{color:#16a34a}.bt-payment .summary-box .summary-row.discount .discount-value{color:#16a34a;font-weight:700}.bt-payment .summary-box .summary-row.total{background-color:#f8f9fa;border-top:2px solid #009ee3}.bt-payment .summary-box .summary-row.total .summary-label{font-size:17px;font-weight:700;color:#1a1a1a}.bt-payment .summary-box .summary-row.total .total-value{font-size:20px;font-weight:800;color:#009ee3}.bt-payment .summary-box .copy-amount-btn{background:0 0;border:1px solid #009ee3;border-radius:6px;cursor:pointer;padding:2px 6px;color:#009ee3;display:flex;align-items:center;width:auto;min-width:unset;margin-top:0;transition:background-color .2s}.bt-payment .summary-box .copy-amount-btn i.material-icons{font-size:16px}.bt-payment .summary-box .copy-amount-btn:hover{background-color:#e8f4fb}.bt-payment .exact-amount-notice{display:flex;align-items:flex-start;gap:10px;background-color:#fffbeb;border:1px solid #fcd34d;border-radius:8px;padding:12px 14px;margin-bottom:20px}.bt-payment .exact-amount-notice .notice-icon{font-size:20px;color:#d97706;flex-shrink:0;margin-top:2px}.bt-payment .exact-amount-notice p{font-size:14px;color:#78350f;margin:0;line-height:1.5}.bt-payment .formRow{margin-top:10px;display:none}.bt-payment .formRow label{font-size:16px;color:#888}.bt-payment .formRow span{background-color:#fff;border:.5px solid #707070;border-radius:2px;padding:2px 10px;display:block;margin-top:4px}.bt-payment .formRow span input[type=text]{background:0 0;border:none;color:#000;font-size:16px;height:23px;width:100%;text-transform:uppercase;vertical-align:top;padding:0;margin:0}.bt-payment .formRow span input[type=text]:focus{outline:0}.bt-payment .alert-text{font-size:16px;color:#009ee3;margin-top:7px;margin-bottom:0}.bt-payment button[type=submit]{background-color:#009ee3;color:#fff;font-size:18px;text-align:center;padding:10px 0;width:100%;border:none;border-radius:20px;margin-top:20px;cursor:pointer}.bt-payment button[type=submit]:disabled{background-color:#525252;cursor:not-allowed}.bt-payment .pay-message{margin-top:10px;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:20px;border-radius:8px}.bt-payment .pay-message p{font-size:1.1rem;text-align:center;line-height:130%;margin-bottom:10px}.bt-payment .pay-message i.material-icons{font-size:2rem;margin-bottom:5px}.bt-payment .success{background-color:#dff2bf;color:#4f8a10}.bt-payment .error{color:#d8000c;background-color:#ffd2d2}.bt-payment .info{color:#00529b;background-color:#bde5f8}:focus{outline:0}"]
3878
3934
  }] }
3879
3935
  ];
3880
3936
  /** @nocollapse */
@@ -3888,6 +3944,8 @@ var BankTransferComponent = /** @class */ (function () {
3888
3944
  storeId: [{ type: Input }],
3889
3945
  storeName: [{ type: Input }],
3890
3946
  checkoutId: [{ type: Input }],
3947
+ checkoutAdditionalData: [{ type: Input }],
3948
+ discountRate: [{ type: Input }],
3891
3949
  statusPay: [{ type: Output }]
3892
3950
  };
3893
3951
  return BankTransferComponent;
@@ -3906,6 +3964,10 @@ if (false) {
3906
3964
  /** @type {?} */
3907
3965
  BankTransferComponent.prototype.checkoutId;
3908
3966
  /** @type {?} */
3967
+ BankTransferComponent.prototype.checkoutAdditionalData;
3968
+ /** @type {?} */
3969
+ BankTransferComponent.prototype.discountRate;
3970
+ /** @type {?} */
3909
3971
  BankTransferComponent.prototype.statusPay;
3910
3972
  /** @type {?} */
3911
3973
  BankTransferComponent.prototype.paymentForm;
@@ -3913,6 +3975,10 @@ if (false) {
3913
3975
  BankTransferComponent.prototype.isLoading;
3914
3976
  /** @type {?} */
3915
3977
  BankTransferComponent.prototype.errorMessage;
3978
+ /** @type {?} */
3979
+ BankTransferComponent.prototype.submittedSuccessfully;
3980
+ /** @type {?} */
3981
+ BankTransferComponent.prototype.amountCopied;
3916
3982
  /**
3917
3983
  * @type {?}
3918
3984
  * @private