ngx-vector-components 6.15.1 → 6.17.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.17.0] (26/08/2026)
4
+
5
+ ### Feat
6
+
7
+ - Added native validations with toast messages for the quantity and size of files selected in `vector-input-file`
8
+ - Fixed a box-shadow error in the CSS of the select buttons for filters used in the datatable in `filters.component.scss`
9
+
10
+ ## [6.16.0] (25/08/2026)
11
+
12
+ ### Feat
13
+
14
+ - `http-interceptor` now sends `x-client-platform: web` and `x-client: vector-<app>` (derived from the `APP_NAME` token) on every backend request, so the backend can tell web from native app (pair of the app header and the `IsFromApp()` helper on `VectioCargo.Shared`). External URLs (`external-url` header) and `/assets/` requests are skipped. Replaces the per-app `ClientHeaderInterceptor`, which has been removed from portal/fintech/marketplace/logtech/survey;
15
+
3
16
  ## [6.15.1] (25/08/2026)
4
17
 
5
18
  ### Fix
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Input, Component, Pipe, NgModule, InjectionToken, Injectable, Inject, EventEmitter, Output, ViewChild, signal, ViewEncapsulation, HostBinding, HostListener, input, output, inject } from '@angular/core';
2
+ import { Input, Component, Pipe, NgModule, InjectionToken, Injectable, Inject, EventEmitter, Output, ViewChild, signal, ViewEncapsulation, HostBinding, inject, HostListener, input, output, Optional } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2 from 'primeng/tooltip';
@@ -57,6 +57,7 @@ import { ToggleSwitchModule } from 'primeng/toggleswitch';
57
57
  import * as i1$3 from 'primeng/panel';
58
58
  import { PanelModule as PanelModule$1 } from 'primeng/panel';
59
59
  import * as i2$2 from 'primeng/api';
60
+ import { MessageService } from 'primeng/api';
60
61
  import { DateTime } from 'luxon';
61
62
  import * as i1$4 from '@angular/common/http';
62
63
  import { HttpHeaders, HttpClient, HttpResponse } from '@angular/common/http';
@@ -3943,11 +3944,11 @@ class FiltersComponent {
3943
3944
  return validators;
3944
3945
  }
3945
3946
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FiltersComponent, deps: [{ token: i1$1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
3946
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: FiltersComponent, isStandalone: false, selector: "vector-filters", inputs: { fields: "fields" }, outputs: { onSearch: "onSearch", formBuilded: "formBuilded" }, ngImport: i0, template: "<div class=\"grid filter-container\" [ngClass]=\"{ 'display-none': hideFilters }\" [formGroup]=\"formGroup\">\n <div *ngFor=\"let field of fields | notHidden\" class=\"field col-12 sm:col-8 {{ getGridClass(field) }}\">\n <label\n >{{ field.label }}\n <i\n *ngIf=\"field.tooltip\"\n class=\"fas fa-info-circle mt-1 pl-2 ch\"\n pTooltip=\"{{ field.tooltip }}\"\n tooltipPosition=\"bottom\"\n ></i\n ></label>\n <vector-text-field\n *ngIf=\"isTextFieldType(field)\"\n [control]=\"formGroup.get(field.name)\"\n [mask]=\"field.mask\"\n [label]=\"field.placeholder\"\n [isRequired]=\"field.required\"\n [numeric]=\"field.type === fieldTypes.NUMBER\"\n [class]=\"field.class\"\n ></vector-text-field>\n <vector-dropdown-field\n *ngIf=\"[fieldTypes.DYNAMIC_DROPDOWN, fieldTypes.DROPDOWN].includes(field.type)\"\n [dynamicFilters]=\"field.filterTypes\"\n [disabled]=\"field.disabled\"\n [options]=\"field.options || []\"\n [service]=\"field.service\"\n [isRequired]=\"field.required\"\n [minLengthToService]=\"field.minLengthToService || 0\"\n [control]=\"formGroup.get(field.name)\"\n [paged]=\"false\"\n [dependencies]=\"getFieldDependencies(field)\"\n [initialLoad]=\"field.initiateValue\"\n [limitScrollPage]=\"field.limitScrollPage\"\n ></vector-dropdown-field>\n <vector-currency-field\n *ngIf=\"field.type === fieldTypes.CURRENCY\"\n [control]=\"formGroup.get(field.name)\"\n [outlined]=\"true\"\n [disabled]=\"field.disabled\"\n ></vector-currency-field>\n <vector-calendar-field\n *ngIf=\"field.type === fieldTypes.DATE\"\n [control]=\"formGroup.get(field.name)\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n <vector-select-button-field\n *ngIf=\"field.type === fieldTypes.SELECT_BUTTON\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options\"\n (click)=\"search()\"\n [disabled]=\"field.disabled\"\n >\n </vector-select-button-field>\n <div *ngIf=\"field.type === fieldTypes.DATE_RANGE\" class=\"range-date-container\">\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.startDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n ></vector-calendar-field>\n At\u00E9\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.endDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n </div>\n <vector-multiselect-field\n *ngIf=\"field.type === fieldTypes.MULTISELECT\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options || []\"\n [disabled]=\"field.disabled\"\n >\n </vector-multiselect-field>\n </div>\n <div class=\"search-button sm:col-4\">\n <vector-button\n [label]=\"'app.label.search' | translate\"\n (click)=\"search()\"\n [disabled]=\"!formGroup.valid\"\n [round]=\"true\"\n type=\"default-filled\"\n ></vector-button>\n </div>\n</div>\n", styles: [".filter-container{align-items:center}.filter-container .field{display:flex;flex-direction:column}.filter-container .search-button{flex:1;padding-right:7px;display:flex;justify-content:flex-end}@media(min-width:768px){.filter-container .search-button{padding-top:36px}}.filter-container .range-date-container{display:flex;align-items:center;gap:10px}.display-none{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i1$5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: TextFieldComponent, selector: "vector-text-field", inputs: ["isRequired", "label", "maxlength", "isPassword", "numeric", "numericPositive", "numericDotComma", "decimal", "onlyText", "noSpecialCharacters", "alphaNumeric", "alphaNumericAndWhitespace", "mask", "autoClear", "readonly", "rightIcon", "centered", "_enableDocumentTypeChoice", "enableDocumentTypeChoice", "hiddenErrorMessage", "leftLabel", "control", "inputId", "slotChar", "disabled", "pattern"], outputs: ["blurEvent", "inputEvent", "enterKeyPress", "backSpaceKeyPress", "focusEvent", "onDocumentTypeChange"] }, { kind: "component", type: ButtonComponent, selector: "vector-button", inputs: ["disabled", "label", "type", "leftIcon", "rightIcon", "noShadow", "round", "style", "loading"], outputs: ["onClick"] }, { kind: "component", type: CalendarComponent, selector: "vector-calendar-field", inputs: ["isRequired", "control", "label", "showCalendarOnFocus", "min", "max", "disabledDates", "disabled", "defaultDate", "hiddenErrorMessage", "showTime", "showSeconds", "stepMinute", "stepHour", "stepSecond", "timeOnly", "hourFormat"], outputs: ["onFocus", "onBlur", "onInput", "onSelect"] }, { kind: "component", type: MultiselectFieldComponent, selector: "vector-multiselect-field", inputs: ["pagedSugestion", "isRequired", "control", "label", "options", "filter", "showSelectAllOption", "display", "paged", "disabled", "minLengthToService", "initialLoad", "service", "filterVirtualScrool", "showHeader", "showFlags", "dependencies", "limitScrollPage", "forceSelection", "showFlagsOptions"], outputs: ["onChange", "onClosePanel"] }, { kind: "component", type: DropdownFieldComponent, selector: "vector-dropdown-field", inputs: ["options", "isNgContent", "forceSelection", "isRequired", "control", "label", "service", "paged", "buttonAction", "dependencies", "hiddenErrorMessage", "dynamicFilters", "minLengthToService", "initialLoad", "disabled", "limitScrollPage", "inputId"], outputs: ["onFocus", "onChange"] }, { kind: "component", type: CurrencyFieldComponent, selector: "vector-currency-field", inputs: ["minValue", "maxValue", "placeholder", "numberOfDecimals", "control", "outlined", "rounded", "label", "isBankingField", "inputClassName", "localePrefix", "currencyPrefix", "disabled", "centered", "inputId"], outputs: ["onBlur"] }, { kind: "component", type: SelectButtonFieldComponent, selector: "vector-select-button-field", inputs: ["options", "control", "disabled", "variant"] }, { kind: "pipe", type: NotHiddenPipe, name: "notHidden" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }] }); }
3947
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: FiltersComponent, isStandalone: false, selector: "vector-filters", inputs: { fields: "fields" }, outputs: { onSearch: "onSearch", formBuilded: "formBuilded" }, ngImport: i0, template: "<div class=\"grid filter-container\" [ngClass]=\"{ 'display-none': hideFilters }\" [formGroup]=\"formGroup\">\n <div *ngFor=\"let field of fields | notHidden\" class=\"field col-12 sm:col-8 {{ getGridClass(field) }}\">\n <label\n >{{ field.label }}\n <i\n *ngIf=\"field.tooltip\"\n class=\"fas fa-info-circle mt-1 pl-2 ch\"\n pTooltip=\"{{ field.tooltip }}\"\n tooltipPosition=\"bottom\"\n ></i\n ></label>\n <vector-text-field\n *ngIf=\"isTextFieldType(field)\"\n [control]=\"formGroup.get(field.name)\"\n [mask]=\"field.mask\"\n [label]=\"field.placeholder\"\n [isRequired]=\"field.required\"\n [numeric]=\"field.type === fieldTypes.NUMBER\"\n [class]=\"field.class\"\n ></vector-text-field>\n <vector-dropdown-field\n *ngIf=\"[fieldTypes.DYNAMIC_DROPDOWN, fieldTypes.DROPDOWN].includes(field.type)\"\n [dynamicFilters]=\"field.filterTypes\"\n [disabled]=\"field.disabled\"\n [options]=\"field.options || []\"\n [service]=\"field.service\"\n [isRequired]=\"field.required\"\n [minLengthToService]=\"field.minLengthToService || 0\"\n [control]=\"formGroup.get(field.name)\"\n [paged]=\"false\"\n [dependencies]=\"getFieldDependencies(field)\"\n [initialLoad]=\"field.initiateValue\"\n [limitScrollPage]=\"field.limitScrollPage\"\n ></vector-dropdown-field>\n <vector-currency-field\n *ngIf=\"field.type === fieldTypes.CURRENCY\"\n [control]=\"formGroup.get(field.name)\"\n [outlined]=\"true\"\n [disabled]=\"field.disabled\"\n ></vector-currency-field>\n <vector-calendar-field\n *ngIf=\"field.type === fieldTypes.DATE\"\n [control]=\"formGroup.get(field.name)\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n <vector-select-button-field\n *ngIf=\"field.type === fieldTypes.SELECT_BUTTON\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options\"\n (click)=\"search()\"\n [disabled]=\"field.disabled\"\n >\n </vector-select-button-field>\n <div *ngIf=\"field.type === fieldTypes.DATE_RANGE\" class=\"range-date-container\">\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.startDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n ></vector-calendar-field>\n At\u00E9\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.endDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n </div>\n <vector-multiselect-field\n *ngIf=\"field.type === fieldTypes.MULTISELECT\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options || []\"\n [disabled]=\"field.disabled\"\n >\n </vector-multiselect-field>\n </div>\n <div class=\"search-button sm:col-4\">\n <vector-button\n [label]=\"'app.label.search' | translate\"\n (click)=\"search()\"\n [disabled]=\"!formGroup.valid\"\n [round]=\"true\"\n type=\"default-filled\"\n ></vector-button>\n </div>\n</div>\n", styles: [":host ::ng-deep vector-select-button-field .input-container p-selectbutton p-togglebutton span.p-togglebutton-content{box-shadow:none!important}.filter-container{align-items:center}.filter-container .field{display:flex;flex-direction:column}.filter-container .search-button{flex:1;padding-right:7px;display:flex;justify-content:flex-end}@media(min-width:768px){.filter-container .search-button{padding-top:36px}}.filter-container .range-date-container{display:flex;align-items:center;gap:10px}.display-none{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "directive", type: i1$5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: TextFieldComponent, selector: "vector-text-field", inputs: ["isRequired", "label", "maxlength", "isPassword", "numeric", "numericPositive", "numericDotComma", "decimal", "onlyText", "noSpecialCharacters", "alphaNumeric", "alphaNumericAndWhitespace", "mask", "autoClear", "readonly", "rightIcon", "centered", "_enableDocumentTypeChoice", "enableDocumentTypeChoice", "hiddenErrorMessage", "leftLabel", "control", "inputId", "slotChar", "disabled", "pattern"], outputs: ["blurEvent", "inputEvent", "enterKeyPress", "backSpaceKeyPress", "focusEvent", "onDocumentTypeChange"] }, { kind: "component", type: ButtonComponent, selector: "vector-button", inputs: ["disabled", "label", "type", "leftIcon", "rightIcon", "noShadow", "round", "style", "loading"], outputs: ["onClick"] }, { kind: "component", type: CalendarComponent, selector: "vector-calendar-field", inputs: ["isRequired", "control", "label", "showCalendarOnFocus", "min", "max", "disabledDates", "disabled", "defaultDate", "hiddenErrorMessage", "showTime", "showSeconds", "stepMinute", "stepHour", "stepSecond", "timeOnly", "hourFormat"], outputs: ["onFocus", "onBlur", "onInput", "onSelect"] }, { kind: "component", type: MultiselectFieldComponent, selector: "vector-multiselect-field", inputs: ["pagedSugestion", "isRequired", "control", "label", "options", "filter", "showSelectAllOption", "display", "paged", "disabled", "minLengthToService", "initialLoad", "service", "filterVirtualScrool", "showHeader", "showFlags", "dependencies", "limitScrollPage", "forceSelection", "showFlagsOptions"], outputs: ["onChange", "onClosePanel"] }, { kind: "component", type: DropdownFieldComponent, selector: "vector-dropdown-field", inputs: ["options", "isNgContent", "forceSelection", "isRequired", "control", "label", "service", "paged", "buttonAction", "dependencies", "hiddenErrorMessage", "dynamicFilters", "minLengthToService", "initialLoad", "disabled", "limitScrollPage", "inputId"], outputs: ["onFocus", "onChange"] }, { kind: "component", type: CurrencyFieldComponent, selector: "vector-currency-field", inputs: ["minValue", "maxValue", "placeholder", "numberOfDecimals", "control", "outlined", "rounded", "label", "isBankingField", "inputClassName", "localePrefix", "currencyPrefix", "disabled", "centered", "inputId"], outputs: ["onBlur"] }, { kind: "component", type: SelectButtonFieldComponent, selector: "vector-select-button-field", inputs: ["options", "control", "disabled", "variant"] }, { kind: "pipe", type: NotHiddenPipe, name: "notHidden" }, { kind: "pipe", type: i1$2.TranslatePipe, name: "translate" }] }); }
3947
3948
  }
3948
3949
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: FiltersComponent, decorators: [{
3949
3950
  type: Component,
3950
- args: [{ standalone: false, selector: 'vector-filters', template: "<div class=\"grid filter-container\" [ngClass]=\"{ 'display-none': hideFilters }\" [formGroup]=\"formGroup\">\n <div *ngFor=\"let field of fields | notHidden\" class=\"field col-12 sm:col-8 {{ getGridClass(field) }}\">\n <label\n >{{ field.label }}\n <i\n *ngIf=\"field.tooltip\"\n class=\"fas fa-info-circle mt-1 pl-2 ch\"\n pTooltip=\"{{ field.tooltip }}\"\n tooltipPosition=\"bottom\"\n ></i\n ></label>\n <vector-text-field\n *ngIf=\"isTextFieldType(field)\"\n [control]=\"formGroup.get(field.name)\"\n [mask]=\"field.mask\"\n [label]=\"field.placeholder\"\n [isRequired]=\"field.required\"\n [numeric]=\"field.type === fieldTypes.NUMBER\"\n [class]=\"field.class\"\n ></vector-text-field>\n <vector-dropdown-field\n *ngIf=\"[fieldTypes.DYNAMIC_DROPDOWN, fieldTypes.DROPDOWN].includes(field.type)\"\n [dynamicFilters]=\"field.filterTypes\"\n [disabled]=\"field.disabled\"\n [options]=\"field.options || []\"\n [service]=\"field.service\"\n [isRequired]=\"field.required\"\n [minLengthToService]=\"field.minLengthToService || 0\"\n [control]=\"formGroup.get(field.name)\"\n [paged]=\"false\"\n [dependencies]=\"getFieldDependencies(field)\"\n [initialLoad]=\"field.initiateValue\"\n [limitScrollPage]=\"field.limitScrollPage\"\n ></vector-dropdown-field>\n <vector-currency-field\n *ngIf=\"field.type === fieldTypes.CURRENCY\"\n [control]=\"formGroup.get(field.name)\"\n [outlined]=\"true\"\n [disabled]=\"field.disabled\"\n ></vector-currency-field>\n <vector-calendar-field\n *ngIf=\"field.type === fieldTypes.DATE\"\n [control]=\"formGroup.get(field.name)\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n <vector-select-button-field\n *ngIf=\"field.type === fieldTypes.SELECT_BUTTON\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options\"\n (click)=\"search()\"\n [disabled]=\"field.disabled\"\n >\n </vector-select-button-field>\n <div *ngIf=\"field.type === fieldTypes.DATE_RANGE\" class=\"range-date-container\">\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.startDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n ></vector-calendar-field>\n At\u00E9\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.endDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n </div>\n <vector-multiselect-field\n *ngIf=\"field.type === fieldTypes.MULTISELECT\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options || []\"\n [disabled]=\"field.disabled\"\n >\n </vector-multiselect-field>\n </div>\n <div class=\"search-button sm:col-4\">\n <vector-button\n [label]=\"'app.label.search' | translate\"\n (click)=\"search()\"\n [disabled]=\"!formGroup.valid\"\n [round]=\"true\"\n type=\"default-filled\"\n ></vector-button>\n </div>\n</div>\n", styles: [".filter-container{align-items:center}.filter-container .field{display:flex;flex-direction:column}.filter-container .search-button{flex:1;padding-right:7px;display:flex;justify-content:flex-end}@media(min-width:768px){.filter-container .search-button{padding-top:36px}}.filter-container .range-date-container{display:flex;align-items:center;gap:10px}.display-none{display:none!important}\n"] }]
3951
+ args: [{ standalone: false, selector: 'vector-filters', template: "<div class=\"grid filter-container\" [ngClass]=\"{ 'display-none': hideFilters }\" [formGroup]=\"formGroup\">\n <div *ngFor=\"let field of fields | notHidden\" class=\"field col-12 sm:col-8 {{ getGridClass(field) }}\">\n <label\n >{{ field.label }}\n <i\n *ngIf=\"field.tooltip\"\n class=\"fas fa-info-circle mt-1 pl-2 ch\"\n pTooltip=\"{{ field.tooltip }}\"\n tooltipPosition=\"bottom\"\n ></i\n ></label>\n <vector-text-field\n *ngIf=\"isTextFieldType(field)\"\n [control]=\"formGroup.get(field.name)\"\n [mask]=\"field.mask\"\n [label]=\"field.placeholder\"\n [isRequired]=\"field.required\"\n [numeric]=\"field.type === fieldTypes.NUMBER\"\n [class]=\"field.class\"\n ></vector-text-field>\n <vector-dropdown-field\n *ngIf=\"[fieldTypes.DYNAMIC_DROPDOWN, fieldTypes.DROPDOWN].includes(field.type)\"\n [dynamicFilters]=\"field.filterTypes\"\n [disabled]=\"field.disabled\"\n [options]=\"field.options || []\"\n [service]=\"field.service\"\n [isRequired]=\"field.required\"\n [minLengthToService]=\"field.minLengthToService || 0\"\n [control]=\"formGroup.get(field.name)\"\n [paged]=\"false\"\n [dependencies]=\"getFieldDependencies(field)\"\n [initialLoad]=\"field.initiateValue\"\n [limitScrollPage]=\"field.limitScrollPage\"\n ></vector-dropdown-field>\n <vector-currency-field\n *ngIf=\"field.type === fieldTypes.CURRENCY\"\n [control]=\"formGroup.get(field.name)\"\n [outlined]=\"true\"\n [disabled]=\"field.disabled\"\n ></vector-currency-field>\n <vector-calendar-field\n *ngIf=\"field.type === fieldTypes.DATE\"\n [control]=\"formGroup.get(field.name)\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n <vector-select-button-field\n *ngIf=\"field.type === fieldTypes.SELECT_BUTTON\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options\"\n (click)=\"search()\"\n [disabled]=\"field.disabled\"\n >\n </vector-select-button-field>\n <div *ngIf=\"field.type === fieldTypes.DATE_RANGE\" class=\"range-date-container\">\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.startDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [min]=\"field.dateMin\"\n ></vector-calendar-field>\n At\u00E9\n <vector-calendar-field\n [control]=\"formGroup.get(field.name + '.endDate')\"\n [isRequired]=\"field.required\"\n [label]=\"field.placeholder || ''\"\n [disabled]=\"field.disabled\"\n [max]=\"field.dateMax\"\n ></vector-calendar-field>\n </div>\n <vector-multiselect-field\n *ngIf=\"field.type === fieldTypes.MULTISELECT\"\n [control]=\"formGroup.get(field.name)\"\n [options]=\"field.options || []\"\n [disabled]=\"field.disabled\"\n >\n </vector-multiselect-field>\n </div>\n <div class=\"search-button sm:col-4\">\n <vector-button\n [label]=\"'app.label.search' | translate\"\n (click)=\"search()\"\n [disabled]=\"!formGroup.valid\"\n [round]=\"true\"\n type=\"default-filled\"\n ></vector-button>\n </div>\n</div>\n", styles: [":host ::ng-deep vector-select-button-field .input-container p-selectbutton p-togglebutton span.p-togglebutton-content{box-shadow:none!important}.filter-container{align-items:center}.filter-container .field{display:flex;flex-direction:column}.filter-container .search-button{flex:1;padding-right:7px;display:flex;justify-content:flex-end}@media(min-width:768px){.filter-container .search-button{padding-top:36px}}.filter-container .range-date-container{display:flex;align-items:center;gap:10px}.display-none{display:none!important}\n"] }]
3951
3952
  }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }], propDecorators: { fields: [{
3952
3953
  type: Input
3953
3954
  }], onSearch: [{
@@ -4445,6 +4446,10 @@ const UPLOAD_BUTTON_CANCEL_DEFAULTS = {
4445
4446
  leftIcon: 'fas fa-times',
4446
4447
  rightIcon: '',
4447
4448
  };
4449
+ /** Tempo em tela dos toasts de aviso emitidos pelo componente. */
4450
+ const WARNING_TOAST_LIFE_MS = 7000;
4451
+ /** Limite de arquivos suportado no modo multiple — `maxFileNumberUploaded` é limitado a este valor. */
4452
+ const MAX_FILE_NUMBER_UPLOADED = 10;
4448
4453
  const EMPTY_UPLOAD_SINGLE_VALUE = {
4449
4454
  originalFileName: '',
4450
4455
  friendlyFileName: '',
@@ -4471,6 +4476,26 @@ function createUploadMultipleForm() {
4471
4476
  return new FormArray([]);
4472
4477
  }
4473
4478
  class InputFileComponent {
4479
+ /**
4480
+ * Quantidade máxima de arquivos no modo multiple (1 à 10). Ignorado em single (sempre 1). Default: `10`.
4481
+ * Valores acima de {@link MAX_FILE_NUMBER_UPLOADED} são reduzidos ao teto do componente e geram um toast de aviso.
4482
+ */
4483
+ set maxFileNumberUploaded(value) {
4484
+ const requested = Math.trunc(Number(value));
4485
+ if (!Number.isFinite(requested) || requested < 1) {
4486
+ this._maxFileNumberUploaded = 1;
4487
+ return;
4488
+ }
4489
+ if (requested > MAX_FILE_NUMBER_UPLOADED) {
4490
+ this._maxFileNumberUploaded = MAX_FILE_NUMBER_UPLOADED;
4491
+ this.notifyConfiguredLimitExceeded(requested);
4492
+ return;
4493
+ }
4494
+ this._maxFileNumberUploaded = requested;
4495
+ }
4496
+ get maxFileNumberUploaded() {
4497
+ return this._maxFileNumberUploaded;
4498
+ }
4474
4499
  constructor(sanitizer) {
4475
4500
  this.sanitizer = sanitizer;
4476
4501
  /** Modo do upload: `'single'` = 1 arquivo (usa FormGroup) · `'multiple'` = vários (usa FormArray). Default: `'single'`. */
@@ -4481,8 +4506,7 @@ class InputFileComponent {
4481
4506
  this.acceptExtensions = [];
4482
4507
  /** Tamanho máximo por arquivo em **MB** (ex: `5` = 5MB). `null` = sem limite. Convertido internamente pra bytes. */
4483
4508
  this.maxFileSize = null;
4484
- /** Quantidade máxima de arquivos no modo multiple (1 à 10). Ignorado em single (sempre 1). Default: `10`. */
4485
- this.maxFileNumberUploaded = 10;
4509
+ this._maxFileNumberUploaded = MAX_FILE_NUMBER_UPLOADED;
4486
4510
  /** Renderiza o botão "Enviar" ao lado de "Anexar". Default: `false`. */
4487
4511
  this.uploadButtonSendEnabled = false;
4488
4512
  /** Renderiza o botão "Cancelar" (limpa todos os arquivos ao clicar). Default: `false`. */
@@ -4503,6 +4527,7 @@ class InputFileComponent {
4503
4527
  /** Multiple: arquivos originais por índice + objectURLs por índice, paralelo ao FormArray. */
4504
4528
  this._multipleFiles = [];
4505
4529
  this._multiplePreviewObjectUrls = [];
4530
+ this.messageService = inject(MessageService, { optional: true });
4506
4531
  this._uploadButtonAttach = { ...UPLOAD_BUTTON_ATTACH_DEFAULTS };
4507
4532
  this._uploadButtonSend = { ...UPLOAD_BUTTON_SEND_DEFAULTS };
4508
4533
  this._uploadButtonCancel = { ...UPLOAD_BUTTON_CANCEL_DEFAULTS };
@@ -4554,6 +4579,17 @@ class InputFileComponent {
4554
4579
  return this.hasFile;
4555
4580
  return this.uploadArray.length >= this.maxFileNumberUploaded;
4556
4581
  }
4582
+ // ─── Badge ───────────────────────────────────────────────
4583
+ /** Tooltip da badge do arquivo, no formato `nome-do-arquivo.png (1.2MB)`. */
4584
+ fileTooltip(control) {
4585
+ const name = control.controls.originalFileName.value;
4586
+ return `${name} (${this.formatFileSizeMb(control.controls.fileSize.value)})`;
4587
+ }
4588
+ /** Bytes → MB. Usa 2 casas abaixo de 0.1MB para arquivos pequenos não virarem `0.0MB`. */
4589
+ formatFileSizeMb(bytes) {
4590
+ const mb = (bytes ?? 0) / 1024 / 1024;
4591
+ return `${mb.toFixed(mb < 0.1 ? 2 : 1)}MB`;
4592
+ }
4557
4593
  // ─── Config conversion ───────────────────────────────────
4558
4594
  get acceptString() {
4559
4595
  return (this.acceptExtensions ?? []).map((ext) => `.${ext.toLowerCase()}`).join(',');
@@ -4627,7 +4663,10 @@ class InputFileComponent {
4627
4663
  }
4628
4664
  // ─── p-fileUpload handler ────────────────────────────────
4629
4665
  async onPrimeFileSelect(event) {
4630
- const files = Array.from(event?.files ?? []);
4666
+ const selected = Array.from(event?.files ?? []);
4667
+ if (selected.length === 0)
4668
+ return;
4669
+ const files = this.rejectOversizedFiles(selected);
4631
4670
  if (files.length === 0)
4632
4671
  return;
4633
4672
  if (this.uploadType === 'single') {
@@ -4639,9 +4678,10 @@ class InputFileComponent {
4639
4678
  this.fileSelected.emit(value);
4640
4679
  return;
4641
4680
  }
4642
- for (const file of files) {
4643
- if (this.uploadArray.length >= this.maxFileNumberUploaded)
4644
- break;
4681
+ const accepted = this.rejectFilesOverLimit(files);
4682
+ if (accepted.length === 0)
4683
+ return;
4684
+ for (const file of accepted) {
4645
4685
  const value = await this.buildValueFromFile(file);
4646
4686
  const fg = createUploadSingleForm();
4647
4687
  fg.setValue(value);
@@ -4724,11 +4764,57 @@ class InputFileComponent {
4724
4764
  internals.el?.nativeElement?.querySelector('input[type="file"]');
4725
4765
  if (!targetInput)
4726
4766
  return;
4727
- // Garante que o browser abra o picker em modo multi-select quando uploadType === 'multiple'.
4728
- // Sincroniza direto no DOM porque a binding [multiple] do PrimeNG pode não estar propagada no momento do click.
4729
4767
  targetInput.multiple = this.uploadType === 'multiple';
4730
4768
  targetInput.click();
4731
4769
  }
4770
+ /** Descarta os arquivos que excedem `maxFileSize` e notifica o usuário. */
4771
+ rejectOversizedFiles(files) {
4772
+ const maxBytes = this.maxFileSizeBytes;
4773
+ if (maxBytes <= 0)
4774
+ return files;
4775
+ const rejected = files.filter((file) => file.size > maxBytes);
4776
+ if (rejected.length > 0)
4777
+ this.notifyOversizedFiles(rejected);
4778
+ return files.filter((file) => file.size <= maxBytes);
4779
+ }
4780
+ notifyOversizedFiles(files) {
4781
+ this.messageService?.add({
4782
+ severity: MessageStatus.WARN,
4783
+ summary: files.length === 1 ? 'Arquivo acima do tamanho permitido' : 'Arquivos acima do tamanho permitido',
4784
+ detail: `${files.map((file) => file.name).join(', ')} — o limite é de ${this.maxFileSize}MB por arquivo.`,
4785
+ life: WARNING_TOAST_LIFE_MS,
4786
+ });
4787
+ }
4788
+ rejectFilesOverLimit(files) {
4789
+ const availableSlots = Math.max(0, this.maxFileNumberUploaded - this.uploadArray.length);
4790
+ if (files.length <= availableSlots)
4791
+ return files;
4792
+ this.notifyFileNumberExceeded(files.length, files.length - availableSlots);
4793
+ return files.slice(0, availableSlots);
4794
+ }
4795
+ notifyFileNumberExceeded(selectedCount, rejectedCount) {
4796
+ const limit = this.maxFileNumberUploaded;
4797
+ const attached = this.uploadArray.length;
4798
+ const attachedInfo = attached > 0 ? ` (${attached} já ${attached === 1 ? 'anexado' : 'anexados'})` : '';
4799
+ this.messageService?.add({
4800
+ severity: MessageStatus.WARN,
4801
+ summary: 'Limite de arquivos excedido',
4802
+ detail: `Você selecionou ${selectedCount} arquivos e o limite é de ${limit}${attachedInfo}. ` +
4803
+ `${rejectedCount} ${rejectedCount === 1 ? 'arquivo não foi anexado' : 'arquivos não foram anexados'}.`,
4804
+ life: WARNING_TOAST_LIFE_MS,
4805
+ });
4806
+ }
4807
+ notifyConfiguredLimitExceeded(requested) {
4808
+ setTimeout(() => {
4809
+ this.messageService?.add({
4810
+ severity: MessageStatus.WARN,
4811
+ summary: 'Limite de arquivos acima do suportado',
4812
+ detail: `A quantidade configurada (${requested}) excede o limite padrão do componente. ` +
4813
+ `Serão aceitos no máximo ${MAX_FILE_NUMBER_UPLOADED} arquivos.`,
4814
+ life: WARNING_TOAST_LIFE_MS,
4815
+ });
4816
+ });
4817
+ }
4732
4818
  async buildValueFromFile(file) {
4733
4819
  const { name, size, type, lastModified } = file;
4734
4820
  const extension = this.extractExtension(name);
@@ -4785,11 +4871,11 @@ class InputFileComponent {
4785
4871
  }
4786
4872
  }
4787
4873
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: InputFileComponent, deps: [{ token: i1$6.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
4788
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: InputFileComponent, isStandalone: false, selector: "vector-input-file", inputs: { uploadType: "uploadType", uploadFormat: "uploadFormat", control: "control", acceptExtensions: "acceptExtensions", maxFileSize: "maxFileSize", maxFileNumberUploaded: "maxFileNumberUploaded", uploadButtonSendEnabled: "uploadButtonSendEnabled", uploadButtonCancelEnabled: "uploadButtonCancelEnabled", uploadButtonAttachEvent: "uploadButtonAttachEvent", uploadButtonSendEvent: "uploadButtonSendEvent", uploadButtonCancelEvent: "uploadButtonCancelEvent", enableModalView: "enableModalView", uploadButtonAttach: "uploadButtonAttach", uploadButtonSend: "uploadButtonSend", uploadButtonCancel: "uploadButtonCancel" }, outputs: { fileSelected: "fileSelected", fileRemoved: "fileRemoved" }, viewQueries: [{ propertyName: "fileUploadRef", first: true, predicate: ["fileUpload"], descendants: true }], ngImport: i0, template: "<p-fileUpload\n #fileUpload\n class=\"p-fileupload-hidden\"\n mode=\"basic\"\n [multiple]=\"uploadType === 'multiple'\"\n [auto]=\"false\"\n [customUpload]=\"true\"\n [accept]=\"acceptString\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [fileLimit]=\"effectiveFileLimit\"\n [chooseLabel]=\"''\"\n (onSelect)=\"onPrimeFileSelect($event)\"\n></p-fileUpload>\n\n@if (uploadType === 'single') {\n <div class=\"box-input-file\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n @if (hasFile) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView()\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"uploadForm.controls.originalFileName.value\" tooltipPosition=\"top\">\n <span>{{ uploadForm.controls.friendlyFileName.value }}</span>\n <span>{{ uploadForm.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); resetUploadForm()\"\n ></i>\n </div>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"box-input-file mt-5\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n <div class=\"box-badge-list\">\n @if (uploadArray.length > 0) {\n <span class=\"info-selected ml-1\">\n <b>{{ uploadArray.length }}</b> {{ uploadArray.length === 1 ? 'arquivo anexado' : 'arquivos anexados' }}\n </span>\n\n <div class=\"box-badge-list-content\">\n @for (control of uploadArray.controls; track $index) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView($index)\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"control.controls.originalFileName.value\" tooltipPosition=\"top\">\n <span>{{ control.controls.friendlyFileName.value }}</span>\n <span>{{ control.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); removeUploadArrayItem($index)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}\n\n@if (enableModalView) {\n <p-dialog\n [(visible)]=\"isModalViewOpen\"\n [modal]=\"true\"\n [breakpoints]=\"{ '700px': '85%' }\"\n [style]=\"{ width: '700px' }\"\n [closable]=\"true\"\n [draggable]=\"false\"\n class=\"modal-default\"\n [header]=\"previewFileName\"\n >\n <div class=\"grid\">\n <div class=\"col-12\">\n @if (isImagePreview) {\n <img [src]=\"previewUrl\" [alt]=\"previewFileName\" class=\"w-full border-round-lg\" />\n } @else if (isPdfPreview) {\n <iframe [src]=\"safePreviewUrl\" class=\"w-full border-round-lg\" style=\"height: 500px; border: 0\"></iframe>\n } @else {\n <div class=\"box-message my-3\">\n <div class=\"flex\">\n <i class=\"fas fa-exclamation-triangle icon\"></i>\n <span>Preview n\u00E3o dispon\u00EDvel para este tipo de arquivo.</span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid justify-content-center\">\n <div class=\"col-12 md:col-4\">\n <vector-button label=\"Fechar\" [round]=\"true\" type=\"default\" (onClick)=\"closeModalView()\"></vector-button>\n </div>\n </div>\n </p-dialog>\n}\n", styles: [":host{--input-file-primary: #0046e8;--input-file-surface: #fff;--input-file-text: #434560;--input-file-border: #e5e5e5;--input-file-danger-hover: #e90800;--input-file-filename-bg: #e7e7e7;--input-file-filename-bg-hover: #dbdbe6}.p-fileupload-hidden{position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;opacity:0}.box-input-file{padding:.5rem;border:1px solid var(--surface-border);border-radius:8px;min-width:0}.box-input-file>.flex{min-width:0;flex-wrap:wrap}.box-input-file i.button-send-file{display:block;padding:.7rem;max-height:41.25px;font-size:14px;color:var(--input-file-primary);border:2px solid var(--input-file-primary);border-radius:8px;background-color:var(--input-file-surface)}.box-input-file i.button-send-file:hover{cursor:pointer;color:var(--input-file-surface);border:2px solid var(--input-file-primary);background-color:var(--input-file-primary);transition:all .2s ease-in-out}.box-input-file .box-badge-list{flex:0 0 100%;min-width:0}.box-input-file .box-badge-list span.info-selected{display:block;margin:.5rem 0;font-size:.9rem;font-weight:500;color:var(--input-file-text)}.box-input-file .box-badge-list .box-badge-list-content{display:flex;flex-wrap:wrap;gap:.5rem;padding:.5rem;max-height:140px;overflow-y:auto;border-radius:8px;border:1px solid var(--input-file-border)}.box-input-file .box-badge-list .box-badge-list-content .box-badge{width:max-content}.box-input-file .box-badge{display:flex;margin:0;height:40px;max-width:100%;min-width:0;flex:0 1 auto;align-items:center;overflow:hidden;border-radius:20px;border:2px solid var(--input-file-border)}@media(max-width:991.98px){.box-input-file .box-badge{flex:1 1 100%;max-width:min(30ch,100%);transition:all .3s ease-in-out}}.box-input-file .box-badge i.button-remove-file{display:block;padding:.5rem .3rem .5rem .2rem;flex:0 0 auto;font-size:1rem;color:var(--input-file-text)}.box-input-file .box-badge i.button-remove-file:hover{cursor:pointer;color:var(--input-file-danger-hover);transition:all .2s ease-in-out}.box-input-file .box-badge .filename{display:flex;padding:0 .7rem;align-items:center;gap:.5rem;height:40px;max-width:100%;min-width:0;flex:1 1 auto;overflow:hidden;border-radius:16px;background-color:var(--input-file-filename-bg)}.box-input-file .box-badge .filename:hover{cursor:default;background-color:var(--input-file-filename-bg-hover)}.box-input-file .box-badge .filename.cp{cursor:pointer!important}.box-input-file .box-badge .filename>.flex{min-width:0;flex:1 1 auto;overflow:hidden}.box-input-file .box-badge .filename span{display:block;min-width:0;font-size:.9rem;font-weight:400;color:var(--input-file-text)}.box-input-file .box-badge .filename span:first-child{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.box-input-file .box-badge .filename span:last-child{flex:0 0 auto;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i3$2.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "component", type: i2$5.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: ButtonComponent, selector: "vector-button", inputs: ["disabled", "label", "type", "leftIcon", "rightIcon", "noShadow", "round", "style", "loading"], outputs: ["onClick"] }] }); }
4874
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: InputFileComponent, isStandalone: false, selector: "vector-input-file", inputs: { uploadType: "uploadType", uploadFormat: "uploadFormat", control: "control", acceptExtensions: "acceptExtensions", maxFileSize: "maxFileSize", maxFileNumberUploaded: "maxFileNumberUploaded", uploadButtonSendEnabled: "uploadButtonSendEnabled", uploadButtonCancelEnabled: "uploadButtonCancelEnabled", uploadButtonAttachEvent: "uploadButtonAttachEvent", uploadButtonSendEvent: "uploadButtonSendEvent", uploadButtonCancelEvent: "uploadButtonCancelEvent", enableModalView: "enableModalView", uploadButtonAttach: "uploadButtonAttach", uploadButtonSend: "uploadButtonSend", uploadButtonCancel: "uploadButtonCancel" }, outputs: { fileSelected: "fileSelected", fileRemoved: "fileRemoved" }, viewQueries: [{ propertyName: "fileUploadRef", first: true, predicate: ["fileUpload"], descendants: true }], ngImport: i0, template: "<p-fileUpload\n #fileUpload\n class=\"p-fileupload-hidden\"\n mode=\"basic\"\n [multiple]=\"uploadType === 'multiple'\"\n [auto]=\"false\"\n [customUpload]=\"true\"\n [accept]=\"acceptString\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [fileLimit]=\"effectiveFileLimit\"\n [chooseLabel]=\"''\"\n (onSelect)=\"onPrimeFileSelect($event)\"\n></p-fileUpload>\n\n@if (uploadType === 'single') {\n <div class=\"box-input-file\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n @if (hasFile) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView()\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"fileTooltip(uploadForm)\" tooltipPosition=\"top\">\n <span>{{ uploadForm.controls.friendlyFileName.value }}</span>\n <span>{{ uploadForm.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); resetUploadForm()\"\n ></i>\n </div>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"box-input-file mt-5\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n <div class=\"box-badge-list\">\n @if (uploadArray.length > 0) {\n <span class=\"info-selected ml-1\">\n <b>{{ uploadArray.length }}</b> {{ uploadArray.length === 1 ? 'arquivo anexado' : 'arquivos anexados' }}\n </span>\n\n <div class=\"box-badge-list-content\">\n @for (control of uploadArray.controls; track $index) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView($index)\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"fileTooltip(control)\" tooltipPosition=\"top\">\n <span>{{ control.controls.friendlyFileName.value }}</span>\n <span>{{ control.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); removeUploadArrayItem($index)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}\n\n@if (enableModalView) {\n <p-dialog\n [(visible)]=\"isModalViewOpen\"\n [modal]=\"true\"\n [breakpoints]=\"{ '700px': '85%' }\"\n [style]=\"{ width: '700px' }\"\n [closable]=\"true\"\n [draggable]=\"false\"\n class=\"modal-default\"\n [header]=\"previewFileName\"\n >\n <div class=\"grid\">\n <div class=\"col-12\">\n @if (isImagePreview) {\n <img [src]=\"previewUrl\" [alt]=\"previewFileName\" class=\"w-full border-round-lg\" />\n } @else if (isPdfPreview) {\n <iframe [src]=\"safePreviewUrl\" class=\"w-full border-round-lg\" style=\"height: 500px; border: 0\"></iframe>\n } @else {\n <div class=\"box-message my-3\">\n <div class=\"flex\">\n <i class=\"fas fa-exclamation-triangle icon\"></i>\n <span>Preview n\u00E3o dispon\u00EDvel para este tipo de arquivo.</span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid justify-content-center\">\n <div class=\"col-12 md:col-4\">\n <vector-button label=\"Fechar\" [round]=\"true\" type=\"default\" (onClick)=\"closeModalView()\"></vector-button>\n </div>\n </div>\n </p-dialog>\n}\n", styles: [":host{--input-file-primary: #0046e8;--input-file-surface: #fff;--input-file-text: #434560;--input-file-border: #e5e5e5;--input-file-danger-hover: #e90800;--input-file-filename-bg: #e7e7e7;--input-file-filename-bg-hover: #dbdbe6}.p-fileupload-hidden{position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;opacity:0}.box-input-file{padding:.5rem;border:1px solid var(--surface-border);border-radius:8px;min-width:0}.box-input-file>.flex{min-width:0;flex-wrap:wrap}.box-input-file i.button-send-file{display:block;padding:.7rem;max-height:41.25px;font-size:14px;color:var(--input-file-primary);border:2px solid var(--input-file-primary);border-radius:8px;background-color:var(--input-file-surface)}.box-input-file i.button-send-file:hover{cursor:pointer;color:var(--input-file-surface);border:2px solid var(--input-file-primary);background-color:var(--input-file-primary);transition:all .2s ease-in-out}.box-input-file .box-badge-list{flex:0 0 100%;min-width:0}.box-input-file .box-badge-list span.info-selected{display:block;margin:.5rem 0;font-size:.9rem;font-weight:500;color:var(--input-file-text)}.box-input-file .box-badge-list .box-badge-list-content{display:flex;flex-wrap:wrap;gap:.5rem;padding:.5rem;max-height:140px;overflow-y:auto;border-radius:8px;border:1px solid var(--input-file-border)}.box-input-file .box-badge-list .box-badge-list-content .box-badge{width:max-content}.box-input-file .box-badge{display:flex;margin:0;height:40px;max-width:100%;min-width:0;flex:0 1 auto;align-items:center;overflow:hidden;border-radius:20px;border:2px solid var(--input-file-border)}@media(max-width:991.98px){.box-input-file .box-badge{flex:1 1 100%;max-width:min(30ch,100%);transition:all .3s ease-in-out}}.box-input-file .box-badge i.button-remove-file{display:block;padding:.5rem .3rem .5rem .2rem;flex:0 0 auto;font-size:1rem;color:var(--input-file-text)}.box-input-file .box-badge i.button-remove-file:hover{cursor:pointer;color:var(--input-file-danger-hover);transition:all .2s ease-in-out}.box-input-file .box-badge .filename{display:flex;padding:0 .7rem;align-items:center;gap:.5rem;height:40px;max-width:100%;min-width:0;flex:1 1 auto;overflow:hidden;border-radius:16px;background-color:var(--input-file-filename-bg)}.box-input-file .box-badge .filename:hover{cursor:default;background-color:var(--input-file-filename-bg-hover)}.box-input-file .box-badge .filename.cp{cursor:pointer!important}.box-input-file .box-badge .filename>.flex{min-width:0;flex:1 1 auto;overflow:hidden}.box-input-file .box-badge .filename span{display:block;min-width:0;font-size:.9rem;font-weight:400;color:var(--input-file-text)}.box-input-file .box-badge .filename span:first-child{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.box-input-file .box-badge .filename span:last-child{flex:0 0 auto;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: i2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i3$2.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "component", type: i2$5.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "component", type: ButtonComponent, selector: "vector-button", inputs: ["disabled", "label", "type", "leftIcon", "rightIcon", "noShadow", "round", "style", "loading"], outputs: ["onClick"] }] }); }
4789
4875
  }
4790
4876
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: InputFileComponent, decorators: [{
4791
4877
  type: Component,
4792
- args: [{ standalone: false, selector: 'vector-input-file', template: "<p-fileUpload\n #fileUpload\n class=\"p-fileupload-hidden\"\n mode=\"basic\"\n [multiple]=\"uploadType === 'multiple'\"\n [auto]=\"false\"\n [customUpload]=\"true\"\n [accept]=\"acceptString\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [fileLimit]=\"effectiveFileLimit\"\n [chooseLabel]=\"''\"\n (onSelect)=\"onPrimeFileSelect($event)\"\n></p-fileUpload>\n\n@if (uploadType === 'single') {\n <div class=\"box-input-file\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n @if (hasFile) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView()\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"uploadForm.controls.originalFileName.value\" tooltipPosition=\"top\">\n <span>{{ uploadForm.controls.friendlyFileName.value }}</span>\n <span>{{ uploadForm.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); resetUploadForm()\"\n ></i>\n </div>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"box-input-file mt-5\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n <div class=\"box-badge-list\">\n @if (uploadArray.length > 0) {\n <span class=\"info-selected ml-1\">\n <b>{{ uploadArray.length }}</b> {{ uploadArray.length === 1 ? 'arquivo anexado' : 'arquivos anexados' }}\n </span>\n\n <div class=\"box-badge-list-content\">\n @for (control of uploadArray.controls; track $index) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView($index)\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"control.controls.originalFileName.value\" tooltipPosition=\"top\">\n <span>{{ control.controls.friendlyFileName.value }}</span>\n <span>{{ control.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); removeUploadArrayItem($index)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}\n\n@if (enableModalView) {\n <p-dialog\n [(visible)]=\"isModalViewOpen\"\n [modal]=\"true\"\n [breakpoints]=\"{ '700px': '85%' }\"\n [style]=\"{ width: '700px' }\"\n [closable]=\"true\"\n [draggable]=\"false\"\n class=\"modal-default\"\n [header]=\"previewFileName\"\n >\n <div class=\"grid\">\n <div class=\"col-12\">\n @if (isImagePreview) {\n <img [src]=\"previewUrl\" [alt]=\"previewFileName\" class=\"w-full border-round-lg\" />\n } @else if (isPdfPreview) {\n <iframe [src]=\"safePreviewUrl\" class=\"w-full border-round-lg\" style=\"height: 500px; border: 0\"></iframe>\n } @else {\n <div class=\"box-message my-3\">\n <div class=\"flex\">\n <i class=\"fas fa-exclamation-triangle icon\"></i>\n <span>Preview n\u00E3o dispon\u00EDvel para este tipo de arquivo.</span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid justify-content-center\">\n <div class=\"col-12 md:col-4\">\n <vector-button label=\"Fechar\" [round]=\"true\" type=\"default\" (onClick)=\"closeModalView()\"></vector-button>\n </div>\n </div>\n </p-dialog>\n}\n", styles: [":host{--input-file-primary: #0046e8;--input-file-surface: #fff;--input-file-text: #434560;--input-file-border: #e5e5e5;--input-file-danger-hover: #e90800;--input-file-filename-bg: #e7e7e7;--input-file-filename-bg-hover: #dbdbe6}.p-fileupload-hidden{position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;opacity:0}.box-input-file{padding:.5rem;border:1px solid var(--surface-border);border-radius:8px;min-width:0}.box-input-file>.flex{min-width:0;flex-wrap:wrap}.box-input-file i.button-send-file{display:block;padding:.7rem;max-height:41.25px;font-size:14px;color:var(--input-file-primary);border:2px solid var(--input-file-primary);border-radius:8px;background-color:var(--input-file-surface)}.box-input-file i.button-send-file:hover{cursor:pointer;color:var(--input-file-surface);border:2px solid var(--input-file-primary);background-color:var(--input-file-primary);transition:all .2s ease-in-out}.box-input-file .box-badge-list{flex:0 0 100%;min-width:0}.box-input-file .box-badge-list span.info-selected{display:block;margin:.5rem 0;font-size:.9rem;font-weight:500;color:var(--input-file-text)}.box-input-file .box-badge-list .box-badge-list-content{display:flex;flex-wrap:wrap;gap:.5rem;padding:.5rem;max-height:140px;overflow-y:auto;border-radius:8px;border:1px solid var(--input-file-border)}.box-input-file .box-badge-list .box-badge-list-content .box-badge{width:max-content}.box-input-file .box-badge{display:flex;margin:0;height:40px;max-width:100%;min-width:0;flex:0 1 auto;align-items:center;overflow:hidden;border-radius:20px;border:2px solid var(--input-file-border)}@media(max-width:991.98px){.box-input-file .box-badge{flex:1 1 100%;max-width:min(30ch,100%);transition:all .3s ease-in-out}}.box-input-file .box-badge i.button-remove-file{display:block;padding:.5rem .3rem .5rem .2rem;flex:0 0 auto;font-size:1rem;color:var(--input-file-text)}.box-input-file .box-badge i.button-remove-file:hover{cursor:pointer;color:var(--input-file-danger-hover);transition:all .2s ease-in-out}.box-input-file .box-badge .filename{display:flex;padding:0 .7rem;align-items:center;gap:.5rem;height:40px;max-width:100%;min-width:0;flex:1 1 auto;overflow:hidden;border-radius:16px;background-color:var(--input-file-filename-bg)}.box-input-file .box-badge .filename:hover{cursor:default;background-color:var(--input-file-filename-bg-hover)}.box-input-file .box-badge .filename.cp{cursor:pointer!important}.box-input-file .box-badge .filename>.flex{min-width:0;flex:1 1 auto;overflow:hidden}.box-input-file .box-badge .filename span{display:block;min-width:0;font-size:.9rem;font-weight:400;color:var(--input-file-text)}.box-input-file .box-badge .filename span:first-child{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.box-input-file .box-badge .filename span:last-child{flex:0 0 auto;white-space:nowrap}\n"] }]
4878
+ args: [{ standalone: false, selector: 'vector-input-file', template: "<p-fileUpload\n #fileUpload\n class=\"p-fileupload-hidden\"\n mode=\"basic\"\n [multiple]=\"uploadType === 'multiple'\"\n [auto]=\"false\"\n [customUpload]=\"true\"\n [accept]=\"acceptString\"\n [maxFileSize]=\"maxFileSizeBytes\"\n [fileLimit]=\"effectiveFileLimit\"\n [chooseLabel]=\"''\"\n (onSelect)=\"onPrimeFileSelect($event)\"\n></p-fileUpload>\n\n@if (uploadType === 'single') {\n <div class=\"box-input-file\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n @if (hasFile) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView()\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"fileTooltip(uploadForm)\" tooltipPosition=\"top\">\n <span>{{ uploadForm.controls.friendlyFileName.value }}</span>\n <span>{{ uploadForm.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); resetUploadForm()\"\n ></i>\n </div>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"box-input-file mt-5\">\n <div class=\"flex gap-2\">\n <vector-button\n [label]=\"uploadButtonAttach.label\"\n [type]=\"uploadButtonAttach.type\"\n [leftIcon]=\"uploadButtonAttach.leftIcon\"\n [rightIcon]=\"uploadButtonAttach.rightIcon\"\n [round]=\"true\"\n [disabled]=\"isAttachAtLimit || internalSending\"\n (onClick)=\"handleAttachClick($event)\"\n ></vector-button>\n\n @if (uploadButtonSendEnabled) {\n <vector-button\n [label]=\"uploadButtonSend.label\"\n [type]=\"uploadButtonSend.type\"\n [leftIcon]=\"uploadButtonSend.leftIcon\"\n [rightIcon]=\"uploadButtonSend.rightIcon\"\n [round]=\"true\"\n [loading]=\"internalSending\"\n [disabled]=\"!canSend\"\n (onClick)=\"handleSendClick()\"\n ></vector-button>\n }\n\n @if (uploadButtonCancelEnabled) {\n <vector-button\n [label]=\"uploadButtonCancel.label\"\n [type]=\"uploadButtonCancel.type\"\n [leftIcon]=\"uploadButtonCancel.leftIcon\"\n [rightIcon]=\"uploadButtonCancel.rightIcon\"\n [round]=\"true\"\n [disabled]=\"!hasFile || internalSending\"\n (onClick)=\"handleCancelClick()\"\n ></vector-button>\n }\n\n <div class=\"box-badge-list\">\n @if (uploadArray.length > 0) {\n <span class=\"info-selected ml-1\">\n <b>{{ uploadArray.length }}</b> {{ uploadArray.length === 1 ? 'arquivo anexado' : 'arquivos anexados' }}\n </span>\n\n <div class=\"box-badge-list-content\">\n @for (control of uploadArray.controls; track $index) {\n <div\n class=\"box-badge\"\n [class.box-badge--clickable]=\"enableModalView\"\n (click)=\"enableModalView && openModalView($index)\"\n >\n <div class=\"filename\" [class.cp]=\"enableModalView\">\n <div class=\"flex gap-0\" [pTooltip]=\"fileTooltip(control)\" tooltipPosition=\"top\">\n <span>{{ control.controls.friendlyFileName.value }}</span>\n <span>{{ control.controls.fileExtension.value }}</span>\n </div>\n <i\n class=\"fas fa-times button-remove-file\"\n pTooltip=\"Remover\"\n tooltipPosition=\"top\"\n (click)=\"$event.stopPropagation(); removeUploadArrayItem($index)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n}\n\n@if (enableModalView) {\n <p-dialog\n [(visible)]=\"isModalViewOpen\"\n [modal]=\"true\"\n [breakpoints]=\"{ '700px': '85%' }\"\n [style]=\"{ width: '700px' }\"\n [closable]=\"true\"\n [draggable]=\"false\"\n class=\"modal-default\"\n [header]=\"previewFileName\"\n >\n <div class=\"grid\">\n <div class=\"col-12\">\n @if (isImagePreview) {\n <img [src]=\"previewUrl\" [alt]=\"previewFileName\" class=\"w-full border-round-lg\" />\n } @else if (isPdfPreview) {\n <iframe [src]=\"safePreviewUrl\" class=\"w-full border-round-lg\" style=\"height: 500px; border: 0\"></iframe>\n } @else {\n <div class=\"box-message my-3\">\n <div class=\"flex\">\n <i class=\"fas fa-exclamation-triangle icon\"></i>\n <span>Preview n\u00E3o dispon\u00EDvel para este tipo de arquivo.</span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div class=\"grid justify-content-center\">\n <div class=\"col-12 md:col-4\">\n <vector-button label=\"Fechar\" [round]=\"true\" type=\"default\" (onClick)=\"closeModalView()\"></vector-button>\n </div>\n </div>\n </p-dialog>\n}\n", styles: [":host{--input-file-primary: #0046e8;--input-file-surface: #fff;--input-file-text: #434560;--input-file-border: #e5e5e5;--input-file-danger-hover: #e90800;--input-file-filename-bg: #e7e7e7;--input-file-filename-bg-hover: #dbdbe6}.p-fileupload-hidden{position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;opacity:0}.box-input-file{padding:.5rem;border:1px solid var(--surface-border);border-radius:8px;min-width:0}.box-input-file>.flex{min-width:0;flex-wrap:wrap}.box-input-file i.button-send-file{display:block;padding:.7rem;max-height:41.25px;font-size:14px;color:var(--input-file-primary);border:2px solid var(--input-file-primary);border-radius:8px;background-color:var(--input-file-surface)}.box-input-file i.button-send-file:hover{cursor:pointer;color:var(--input-file-surface);border:2px solid var(--input-file-primary);background-color:var(--input-file-primary);transition:all .2s ease-in-out}.box-input-file .box-badge-list{flex:0 0 100%;min-width:0}.box-input-file .box-badge-list span.info-selected{display:block;margin:.5rem 0;font-size:.9rem;font-weight:500;color:var(--input-file-text)}.box-input-file .box-badge-list .box-badge-list-content{display:flex;flex-wrap:wrap;gap:.5rem;padding:.5rem;max-height:140px;overflow-y:auto;border-radius:8px;border:1px solid var(--input-file-border)}.box-input-file .box-badge-list .box-badge-list-content .box-badge{width:max-content}.box-input-file .box-badge{display:flex;margin:0;height:40px;max-width:100%;min-width:0;flex:0 1 auto;align-items:center;overflow:hidden;border-radius:20px;border:2px solid var(--input-file-border)}@media(max-width:991.98px){.box-input-file .box-badge{flex:1 1 100%;max-width:min(30ch,100%);transition:all .3s ease-in-out}}.box-input-file .box-badge i.button-remove-file{display:block;padding:.5rem .3rem .5rem .2rem;flex:0 0 auto;font-size:1rem;color:var(--input-file-text)}.box-input-file .box-badge i.button-remove-file:hover{cursor:pointer;color:var(--input-file-danger-hover);transition:all .2s ease-in-out}.box-input-file .box-badge .filename{display:flex;padding:0 .7rem;align-items:center;gap:.5rem;height:40px;max-width:100%;min-width:0;flex:1 1 auto;overflow:hidden;border-radius:16px;background-color:var(--input-file-filename-bg)}.box-input-file .box-badge .filename:hover{cursor:default;background-color:var(--input-file-filename-bg-hover)}.box-input-file .box-badge .filename.cp{cursor:pointer!important}.box-input-file .box-badge .filename>.flex{min-width:0;flex:1 1 auto;overflow:hidden}.box-input-file .box-badge .filename span{display:block;min-width:0;font-size:.9rem;font-weight:400;color:var(--input-file-text)}.box-input-file .box-badge .filename span:first-child{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.box-input-file .box-badge .filename span:last-child{flex:0 0 auto;white-space:nowrap}\n"] }]
4793
4879
  }], ctorParameters: () => [{ type: i1$6.DomSanitizer }], propDecorators: { uploadType: [{
4794
4880
  type: Input
4795
4881
  }], uploadFormat: [{
@@ -6499,19 +6585,21 @@ const tokenIsPresentGuard = (routeSnapshot) => {
6499
6585
  };
6500
6586
 
6501
6587
  class HttpInterceptorProvider {
6502
- constructor(storageService, errorMessageService, loadingService, authService, messageService, environment) {
6588
+ constructor(storageService, errorMessageService, loadingService, authService, messageService, environment, appName = null) {
6503
6589
  this.storageService = storageService;
6504
6590
  this.errorMessageService = errorMessageService;
6505
6591
  this.loadingService = loadingService;
6506
6592
  this.authService = authService;
6507
6593
  this.messageService = messageService;
6508
6594
  this.environment = environment;
6595
+ this.appName = appName;
6509
6596
  this.activeRequests = [];
6510
6597
  this.isRefreshing = false;
6511
6598
  this.refreshTokenSubject = new BehaviorSubject(null);
6512
6599
  }
6513
6600
  intercept(request, next) {
6514
6601
  const isExternalUrl = request.headers.get('external-url');
6602
+ const isAssetsRequest = request.url.startsWith('/assets/');
6515
6603
  if (!this.isRefreshTokenRequest(request.url)) {
6516
6604
  if (!isExternalUrl) {
6517
6605
  request = this.addTokenIfPresent(request);
@@ -6524,6 +6612,9 @@ class HttpInterceptorProvider {
6524
6612
  if (!isExternalUrl) {
6525
6613
  request = this.fixUrl(request);
6526
6614
  }
6615
+ if (!isExternalUrl && !isAssetsRequest) {
6616
+ request = this.addClientHeaders(request);
6617
+ }
6527
6618
  const noSpinnerHeader = request.headers.get('no-spinner');
6528
6619
  if (!noSpinnerHeader && !request.url.startsWith('/assets/')) {
6529
6620
  this.loadingService.loading$.next(true);
@@ -6622,6 +6713,28 @@ class HttpInterceptorProvider {
6622
6713
  }
6623
6714
  return request;
6624
6715
  }
6716
+ /**
6717
+ * Marca a origem da request pro backend: `x-client-platform: web` (+ `x-client` com o nome do
6718
+ * frontend), pro backend distinguir web de app nativo (ver helper IsFromApp() no VectioCargo.Shared).
6719
+ *
6720
+ * So nas chamadas do nosso backend; ignora URL externa (header `external-url`) e assets — nao
6721
+ * vaza o header p/ APIs de terceiros. Header e spoofavel: telemetria/roteamento/log, NAO
6722
+ * controle de seguranca.
6723
+ */
6724
+ addClientHeaders(request) {
6725
+ return request.clone({
6726
+ setHeaders: {
6727
+ 'x-client-platform': 'web',
6728
+ 'x-client': this.getClientName(),
6729
+ },
6730
+ });
6731
+ }
6732
+ getClientName() {
6733
+ if (!this.appName) {
6734
+ return 'vector-web';
6735
+ }
6736
+ return `vector-${this.appName.toLowerCase().replace(/_/g, '-')}`;
6737
+ }
6625
6738
  addContentType(request) {
6626
6739
  return request.clone({ setHeaders: { contentType: 'application/json' } });
6627
6740
  }
@@ -6665,7 +6778,7 @@ class HttpInterceptorProvider {
6665
6778
  }
6666
6779
  return this.refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => next.handle(this.addTokenIfPresent(request))));
6667
6780
  }
6668
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: HttpInterceptorProvider, deps: [{ token: StorageService }, { token: ErrorMessageService }, { token: LoadingService }, { token: AuthService }, { token: i2$2.MessageService }, { token: ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
6781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: HttpInterceptorProvider, deps: [{ token: StorageService }, { token: ErrorMessageService }, { token: LoadingService }, { token: AuthService }, { token: i2$2.MessageService }, { token: ENVIRONMENT }, { token: APP_NAME, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
6669
6782
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: HttpInterceptorProvider }); }
6670
6783
  }
6671
6784
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: HttpInterceptorProvider, decorators: [{
@@ -6673,6 +6786,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
6673
6786
  }], ctorParameters: () => [{ type: StorageService }, { type: ErrorMessageService }, { type: LoadingService }, { type: AuthService }, { type: i2$2.MessageService }, { type: undefined, decorators: [{
6674
6787
  type: Inject,
6675
6788
  args: [ENVIRONMENT]
6789
+ }] }, { type: AppName, decorators: [{
6790
+ type: Optional
6791
+ }, {
6792
+ type: Inject,
6793
+ args: [APP_NAME]
6676
6794
  }] }] });
6677
6795
 
6678
6796
  const getSelectedCrudItemResolver = (routeSnapshot) => {