@sumaris-net/ngx-components 0.26.2 → 0.26.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +136 -24
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/doc/changelog.md +1 -0
  6. package/esm2015/src/app/core/form/entity-editor.class.js +4 -5
  7. package/esm2015/src/app/core/form/form-buttons-bar.component.js +2 -1
  8. package/esm2015/src/app/core/form/form.class.js +3 -3
  9. package/esm2015/src/app/core/table/table.class.js +3 -3
  10. package/esm2015/src/app/shared/help/help.modal.js +1 -1
  11. package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +4 -2
  12. package/esm2015/src/app/shared/material/badge/badge-icon.directive.js +62 -0
  13. package/esm2015/src/app/shared/material/badge/badge-icon.module.js +23 -0
  14. package/esm2015/src/app/shared/material/badge/badge-icon.test.js +10 -0
  15. package/esm2015/src/app/shared/material/material.module.js +4 -2
  16. package/esm2015/src/app/shared/material/testing/material.testing.module.js +9 -2
  17. package/esm2015/src/app/shared/material/testing/material.testing.page.js +2 -2
  18. package/esm2015/src/app/shared/pipes/form.pipes.js +3 -3
  19. package/esm2015/src/app/shared/toolbar/modal-toolbar.js +6 -1
  20. package/esm2015/src/app/shared/validator/form-error-adapter.class.js +5 -5
  21. package/esm2015/sumaris-net.ngx-components.js +10 -7
  22. package/fesm2015/sumaris-net.ngx-components.js +115 -13
  23. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/app/core/form/entity-editor.class.d.ts +2 -2
  26. package/src/app/core/form/form.class.d.ts +2 -2
  27. package/src/app/core/table/table.class.d.ts +2 -2
  28. package/src/app/shared/help/help.modal.d.ts +7 -1
  29. package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +1 -0
  30. package/src/app/shared/material/badge/badge-icon.directive.d.ts +15 -0
  31. package/src/app/shared/material/badge/badge-icon.module.d.ts +2 -0
  32. package/src/app/shared/material/badge/badge-icon.test.d.ts +2 -0
  33. package/src/app/shared/pipes/form.pipes.d.ts +2 -2
  34. package/src/app/shared/validator/form-error-adapter.class.d.ts +1 -1
  35. package/sumaris-net.ngx-components.d.ts +9 -6
  36. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -1199,6 +1199,7 @@
1199
1199
  this.onDropButtonClick = new i0.EventEmitter(true);
1200
1200
  this.onKeydownEscape = new i0.EventEmitter();
1201
1201
  this.onKeyupEnter = new i0.EventEmitter();
1202
+ this.onKeydownTab = new i0.EventEmitter();
1202
1203
  }
1203
1204
  Object.defineProperty(MatAutocompleteField.prototype, "itemCount", {
1204
1205
  get: function () {
@@ -1832,7 +1833,7 @@
1832
1833
  { type: i0.Component, args: [{
1833
1834
  // eslint-disable-next-line @angular-eslint/component-selector
1834
1835
  selector: 'mat-autocomplete-field',
1835
- template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- readonly -->\n <ng-container>\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n </ng-container>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"onKeydownEscape.emit($event)\"\n [compareWith]=\"compareWith\"\n [multiple]=\"multiple\"\n [required]=\"required\">\n <mat-select-trigger>{{ displayWith(value) }}</mat-select-trigger>\n\n <!-- header -->\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as isLast\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n </ion-col>\n </ion-row>\n\n <!-- None option -->\n <mat-option *ngIf=\"!required\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding\">\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <ng-container *ngIf=\"$filteredItems | async; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <!-- options -->\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text>{{item | propertyGet: path }}</ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initMatSelectInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n </mat-select>\n\n\n <!--\n NOTE :\n - \"selectInputContent($event) || onFocus.emit($event)\" : call onFocus only when to the input is empty (nothing to select)\n -->\n <ng-template #searchableTemplate>\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [required]=\"required\"\n (click)=\"onClick.emit($event)\"\n (focus)=\"filterInputTextFocusInEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"onKeydownEscape.emit($event)\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\"\n (keyup.arrowdown)=\"!autocomplete.opened && onDropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [class.cdk-visually-hidden]=\"!searchable\"\n [panelWidth]=\"panelWidth\">\n\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count \" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: formControl.value, withAccent: highlightAccent }\"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n </ng-template>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('entity')\" translate>ERROR.FIELD_INVALID</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"searchable\"\n (click)=\"onDropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix type=\"button\" mat-icon-button tabindex=\"-1\"\n *ngIf=\"enabled && mobile && !searchable && !multiple\"\n [title]=\"'COMMON.BTN_SEARCH'|translate\"\n (click)=\"toggleSearch($event)\">\n <mat-icon>search</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
1836
+ template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- readonly -->\n <ng-container>\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n </ng-container>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"onKeydownEscape.emit($event)\"\n (keydown.tab)=\"onKeydownTab.emit($event)\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\"\n [compareWith]=\"compareWith\"\n [multiple]=\"multiple\"\n [required]=\"required\">\n <mat-select-trigger>{{ displayWith(value) }}</mat-select-trigger>\n\n <!-- header -->\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as isLast\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n </ion-col>\n </ion-row>\n\n <!-- None option -->\n <mat-option *ngIf=\"!required\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding\">\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <ng-container *ngIf=\"$filteredItems | async; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <!-- options -->\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text>{{item | propertyGet: path }}</ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initMatSelectInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n </mat-select>\n\n\n <!--\n NOTE :\n - \"selectInputContent($event) || onFocus.emit($event)\" : call onFocus only when to the input is empty (nothing to select)\n -->\n <ng-template #searchableTemplate>\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [required]=\"required\"\n (click)=\"onClick.emit($event)\"\n (focus)=\"filterInputTextFocusInEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"onKeydownEscape.emit($event)\"\n (keydown.tab)=\"onKeydownTab.emit($event)\"\n (keyup.enter)=\"onKeyupEnter.emit($event)\"\n (keyup.arrowdown)=\"!autocomplete.opened && onDropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [class.cdk-visually-hidden]=\"!searchable\"\n [panelWidth]=\"panelWidth\">\n\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count \" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: formControl.value, withAccent: highlightAccent }\"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n </ng-template>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('entity')\" translate>ERROR.FIELD_INVALID</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"searchable\"\n (click)=\"onDropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix type=\"button\" mat-icon-button tabindex=\"-1\"\n *ngIf=\"enabled && mobile && !searchable && !multiple\"\n [title]=\"'COMMON.BTN_SEARCH'|translate\"\n (click)=\"toggleSearch($event)\">\n <mat-icon>search</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
1836
1837
  providers: [DEFAULT_VALUE_ACCESSOR$6],
1837
1838
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
1838
1839
  styles: [":host{display:inline-block;position:relative}:host.ion-text-wrap ion-label{white-space:normal!important}button[hidden]{display:none}mat-icon.select-arrow{color:rgba(0,0,0,.47);font-size:150%}.fact-scroll-viewport{height:100%;width:100%}.fact-item{height:54px;display:flex}.fact-item .fact-date{min-width:100px;text-align:center;font-size:24pt}.fact-item .fact-date,.fact-item .fact-text{height:100%;align-items:center;justify-content:center;display:flex}.fact-item .fact-text{border-radius:10px}cdk-virtual-scroll-viewport{border:1px solid #000}cdk-virtual-scroll-viewport li{list-style:none}"]
@@ -1884,6 +1885,7 @@
1884
1885
  onDropButtonClick: [{ type: i0.Output, args: ['dropButtonClick',] }],
1885
1886
  onKeydownEscape: [{ type: i0.Output, args: ['keydown.escape',] }],
1886
1887
  onKeyupEnter: [{ type: i0.Output, args: ['keyup.enter',] }],
1888
+ onKeydownTab: [{ type: i0.Output, args: ['keydown.tab',] }],
1887
1889
  matSelect: [{ type: i0.ViewChild, args: ['matSelect',] }],
1888
1890
  matInputText: [{ type: i0.ViewChild, args: ['matInputText',] }],
1889
1891
  matAutocomplete: [{ type: i0.ViewChild, args: [autocomplete.MatAutocomplete,] }],
@@ -3983,12 +3985,12 @@
3983
3985
  }());
3984
3986
 
3985
3987
  var APP_FORM_ERROR_I18N_KEYS = new i0.InjectionToken('appFormErrorKeys');
3986
- var FormErrorAdapter = /** @class */ (function () {
3987
- function FormErrorAdapter(translate, errorI18nKeys) {
3988
+ var FormErrorTranslator = /** @class */ (function () {
3989
+ function FormErrorTranslator(translate, errorI18nKeys) {
3988
3990
  this.translate = translate;
3989
3991
  this.errorI18nKeys = Object.assign(Object.assign({}, SharedValidators.I18N_ERROR_KEYS), errorI18nKeys);
3990
3992
  }
3991
- FormErrorAdapter.prototype.translateErrors = function (control, opts) {
3993
+ FormErrorTranslator.prototype.translateErrors = function (control, opts) {
3992
3994
  var _this = this;
3993
3995
  if (!control || !control.invalid)
3994
3996
  return '';
@@ -4017,14 +4019,14 @@
4017
4019
  return res + (res.length ? separator : '') + formError;
4018
4020
  }, "");
4019
4021
  };
4020
- FormErrorAdapter.prototype.translateControlPath = function (path, opts) {
4022
+ FormErrorTranslator.prototype.translateControlPath = function (path, opts) {
4021
4023
  if (opts === null || opts === void 0 ? void 0 : opts.controlPathTranslator) {
4022
4024
  return opts === null || opts === void 0 ? void 0 : opts.controlPathTranslator.translateControlPath(path);
4023
4025
  }
4024
4026
  var i18nKey = (opts && opts.i18nPrefix || '') + changeCaseToUnderscore(path).toUpperCase();
4025
4027
  return this.translate.instant(i18nKey);
4026
4028
  };
4027
- FormErrorAdapter.prototype.translateError = function (errorKey, errorContent) {
4029
+ FormErrorTranslator.prototype.translateError = function (errorKey, errorContent) {
4028
4030
  var i18nKey = this.errorI18nKeys[errorKey]
4029
4031
  // Try to generate a standard error key, like 'ERROR.FIELD_xxx_xxx'
4030
4032
  || ('ERROR.FIELD_' + changeCaseToUnderscore(errorKey).toUpperCase());
@@ -4041,13 +4043,13 @@
4041
4043
  console.error("[form-error-adapter] Cannot translate error key '" + errorKey + "'. Please add more formErrorsKey into APP_FORM_ERROR_I18N_KEYS injection token");
4042
4044
  return errorKey;
4043
4045
  };
4044
- return FormErrorAdapter;
4046
+ return FormErrorTranslator;
4045
4047
  }());
4046
- FormErrorAdapter.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FormErrorAdapter_Factory() { return new FormErrorAdapter(i0__namespace.ɵɵinject(i1__namespace$1.TranslateService), i0__namespace.ɵɵinject(APP_FORM_ERROR_I18N_KEYS, 8)); }, token: FormErrorAdapter, providedIn: "root" });
4047
- FormErrorAdapter.decorators = [
4048
+ FormErrorTranslator.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FormErrorTranslator_Factory() { return new FormErrorTranslator(i0__namespace.ɵɵinject(i1__namespace$1.TranslateService), i0__namespace.ɵɵinject(APP_FORM_ERROR_I18N_KEYS, 8)); }, token: FormErrorTranslator, providedIn: "root" });
4049
+ FormErrorTranslator.decorators = [
4048
4050
  { type: i0.Injectable, args: [{ providedIn: 'root' },] }
4049
4051
  ];
4050
- FormErrorAdapter.ctorParameters = function () { return [
4052
+ FormErrorTranslator.ctorParameters = function () { return [
4051
4053
  { type: i1$2.TranslateService },
4052
4054
  { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [APP_FORM_ERROR_I18N_KEYS,] }] }
4053
4055
  ]; };
@@ -4067,7 +4069,7 @@
4067
4069
  },] }
4068
4070
  ];
4069
4071
  FormErrorTranslatePipe.ctorParameters = function () { return [
4070
- { type: FormErrorAdapter }
4072
+ { type: FormErrorTranslator }
4071
4073
  ]; };
4072
4074
 
4073
4075
  var SharedPipesModule = /** @class */ (function () {
@@ -7760,6 +7762,89 @@
7760
7762
  },] }
7761
7763
  ];
7762
7764
 
7765
+ var MatBadgeIconDirective = /** @class */ (function () {
7766
+ function MatBadgeIconDirective(el) {
7767
+ this.el = el;
7768
+ }
7769
+ MatBadgeIconDirective.prototype.ngOnInit = function () {
7770
+ this.size = this.size || 'medium';
7771
+ this.color = this.color || 'primary';
7772
+ if (this.color === 'warn')
7773
+ this.color = 'warning';
7774
+ var fontSize;
7775
+ switch (this.size) {
7776
+ case 'large':
7777
+ fontSize = '24px';
7778
+ break;
7779
+ case 'medium':
7780
+ fontSize = '22px';
7781
+ break;
7782
+ case 'small':
7783
+ fontSize = '16px';
7784
+ break;
7785
+ }
7786
+ var badge = this.el.nativeElement.querySelector('.mat-badge-content');
7787
+ badge.style.display = 'flex';
7788
+ badge.style.alignItems = 'center';
7789
+ badge.style.justifyContent = 'center';
7790
+ // fill: 'clear'
7791
+ if (this.fill === 'clear') {
7792
+ badge.style.color = "var(--ion-color-" + this.color + ")";
7793
+ badge.style.background = 'transparent';
7794
+ }
7795
+ // fill: 'solid' (default value)
7796
+ else {
7797
+ badge.style.background = "var(--ion-color-" + this.color + ")";
7798
+ badge.style.color = "var(--ion-color-" + this.color + "-contrast)";
7799
+ }
7800
+ if (this.matIcon) {
7801
+ badge.innerHTML = "<i class=\"material-icons\" style=\"font-size: " + fontSize + ";\">" + this.matIcon + "</i>";
7802
+ }
7803
+ else if (this.ionIcon) {
7804
+ badge.innerHTML = "<ion-icon style=\"font-size: " + fontSize + "; pointer-events: none;\" name=\"" + this.ionIcon + "\"></ion-icon>";
7805
+ }
7806
+ };
7807
+ return MatBadgeIconDirective;
7808
+ }());
7809
+ MatBadgeIconDirective.decorators = [
7810
+ { type: i0.Directive, args: [{
7811
+ selector: '[matBadgeIcon], [ionBadgeIcon]',
7812
+ inputs: [
7813
+ 'size: matBadgeSize',
7814
+ 'color: matBadgeColor',
7815
+ 'fill: matBadgeFill',
7816
+ ]
7817
+ },] }
7818
+ ];
7819
+ MatBadgeIconDirective.ctorParameters = function () { return [
7820
+ { type: i0.ElementRef }
7821
+ ]; };
7822
+ MatBadgeIconDirective.propDecorators = {
7823
+ matIcon: [{ type: i0.Input, args: ['matBadgeIcon',] }],
7824
+ ionIcon: [{ type: i0.Input, args: ['ionBadgeIcon',] }]
7825
+ };
7826
+
7827
+ var SharedMatBadgeIconModule = /** @class */ (function () {
7828
+ function SharedMatBadgeIconModule() {
7829
+ }
7830
+ return SharedMatBadgeIconModule;
7831
+ }());
7832
+ SharedMatBadgeIconModule.decorators = [
7833
+ { type: i0.NgModule, args: [{
7834
+ imports: [
7835
+ i1$4.CommonModule,
7836
+ i1$5.IonicModule,
7837
+ badge.MatBadgeModule,
7838
+ ],
7839
+ exports: [
7840
+ MatBadgeIconDirective
7841
+ ],
7842
+ declarations: [
7843
+ MatBadgeIconDirective
7844
+ ]
7845
+ },] }
7846
+ ];
7847
+
7763
7848
  var modules = [
7764
7849
  // Angular material components
7765
7850
  i1$3.MatCommonModule,
@@ -7801,7 +7886,8 @@
7801
7886
  SharedMatBooleanModule,
7802
7887
  SharedMatNumpadModule,
7803
7888
  SharedMatSwipeModule,
7804
- MaterialChipsModule
7889
+ MaterialChipsModule,
7890
+ SharedMatBadgeIconModule
7805
7891
  ];
7806
7892
  var SharedMaterialModule = /** @class */ (function () {
7807
7893
  function SharedMaterialModule() {
@@ -9234,6 +9320,10 @@
9234
9320
  ModalToolbarComponent.prototype.ngOnInit = function () {
9235
9321
  var _this = this;
9236
9322
  this.canValidate = toBoolean(this.canValidate, this.validate.observers.length > 0);
9323
+ // Ctrl+S
9324
+ this._subscription.add(this.hotkeys.addShortcut({ keys: 'control.s', description: 'COMMON.BTN_VALIDATE', elementName: this.modalName })
9325
+ .pipe(operators.filter(function () { return _this.canValidate; }))
9326
+ .subscribe(function (event) { return _this.validate.emit(event); }));
9237
9327
  // Escape
9238
9328
  this._subscription.add(this.hotkeys.addShortcut({ keys: 'escape', description: 'COMMON.BTN_CLOSE', elementName: this.modalName })
9239
9329
  .subscribe(function (event) { return _this.cancel.emit(event); }));
@@ -18462,7 +18552,7 @@
18462
18552
  MaterialTestingPage.decorators = [
18463
18553
  { type: i0.Component, args: [{
18464
18554
  selector: 'app-material-testing',
18465
- template: "\n<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Material components</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <ion-list>\n\n <ion-item-divider>Shared Material components</ion-item-divider>\n\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./datetime')\">\n Date/Time field\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./autocomplete')\">\n Autocomplete field\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./latlong')\">\n Lat/Long field\n </ion-item>\n<!-- <ion-item tappable class=\"text-1x\" (click)=\"openPage('./numpad')\">-->\n<!-- Numeric pad component-->\n<!-- </ion-item>-->\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./swipe')\">\n Swipe component\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./chips')\">\n Chips component\n </ion-item>\n\n <ng-container *ngIf=\"pages && pages.length\">\n <ion-item-divider>Other components</ion-item-divider>\n\n <ion-item *ngFor=\"let item of pages\"\n tappable class=\"text-1x\"\n (click)=\"openPage(item.page)\">{{item.label}}</ion-item>\n\n </ng-container>\n </ion-list>\n\n</ion-content>\n"
18555
+ template: "\n<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Material components</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <ion-list>\n\n <ion-item-divider>Shared Material components</ion-item-divider>\n\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./datetime')\">\n Date/Time field\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./autocomplete')\">\n Autocomplete field\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./latlong')\">\n Lat/Long field\n </ion-item>\n<!-- <ion-item tappable class=\"text-1x\" (click)=\"openPage('./numpad')\">-->\n<!-- Numeric pad component-->\n<!-- </ion-item>-->\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./swipe')\">\n Swipe component\n </ion-item>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./chips')\">\n Chips component\n </ion-item>\n\n <ion-item-divider>Directive</ion-item-divider>\n <ion-item tappable class=\"text-1x\" (click)=\"openPage('./badge-icon')\">\n Badge icon directive\n </ion-item>\n\n <ng-container *ngIf=\"pages && pages.length\">\n <ion-item-divider>Other components</ion-item-divider>\n\n <ion-item *ngFor=\"let item of pages\"\n tappable class=\"text-1x\"\n (click)=\"openPage(item.page)\">{{item.label}}</ion-item>\n\n </ng-container>\n </ion-list>\n\n</ion-content>\n"
18466
18556
  },] }
18467
18557
  ];
18468
18558
  MaterialTestingPage.ctorParameters = function () { return [
@@ -18747,6 +18837,18 @@
18747
18837
  { type: i1.FormBuilder }
18748
18838
  ]; };
18749
18839
 
18840
+ var MatBadgeIconTestPage = /** @class */ (function () {
18841
+ function MatBadgeIconTestPage() {
18842
+ }
18843
+ return MatBadgeIconTestPage;
18844
+ }());
18845
+ MatBadgeIconTestPage.decorators = [
18846
+ { type: i0.Component, args: [{
18847
+ selector: 'mat-badge-icon-test',
18848
+ template: "\n<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>matBadgeIcon directive</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <!-- small badge -->\n <p>\n <ion-text color=\"tertiary\">\n <span matBadge matIcon=\"check\"\n matBadgeSize=\"small\"\n matBadgeColor=\"accent\"\n matBadgeOverlap=\"false\">Small badge</span>\n </ion-text>\n </p>\n\n <!-- medium badge -->\n <p>\n <ion-text matBadge matBadgeIcon=\"check\"\n matBadgeSize=\"medium\"\n matBadgeColor=\"tertiary\"\n matBadgeOverlap=\"false\"\n >Medium badge</ion-text>\n </p>\n\n <!-- small badge -->\n <p>\n <ion-label matBadge matBadgeIcon=\"close\" matBadgeSize=\"large\"\n matBadgeOverlap=\"false\">Large badge</ion-label>\n </p>\n\n <!-- default size badge -->\n <p>\n <ion-label matBadge matBadgeIcon=\"check\" matBadgeColor=\"success\"\n matBadgeOverlap=\"false\">Badge (no size, no color)\n </ion-label>\n </p>\n\n <!-- ion icon -->\n <p>\n <ion-label matBadge\n ionBadgeIcon=\"checkmark\"\n matBadgeColor=\"success\"\n matBadgeOverlap=\"false\">Badge with ion-icon\n </ion-label>\n </p>\n\n <!-- ion icon clear -->\n <p>\n <ion-label matBadge\n ionBadgeIcon=\"checkmark-circle\"\n matBadgeColor=\"tertiary\"\n matBadgeFill=\"clear\"\n matBadgeOverlap=\"false\">Badge with clear icon\n </ion-label>\n </p>\n\n\n</ion-content>\n"
18849
+ },] }
18850
+ ];
18851
+
18750
18852
  var routes$1 = [
18751
18853
  {
18752
18854
  path: '',
@@ -18782,6 +18884,11 @@
18782
18884
  path: 'chips',
18783
18885
  pathMatch: 'full',
18784
18886
  component: ChipsTestPage
18887
+ },
18888
+ {
18889
+ path: 'badge-icon',
18890
+ pathMatch: 'full',
18891
+ component: MatBadgeIconTestPage
18785
18892
  }
18786
18893
  ];
18787
18894
  var MaterialTestingModule = /** @class */ (function () {
@@ -18806,7 +18913,8 @@
18806
18913
  LatLongTestPage,
18807
18914
  // NumpadTestPage,
18808
18915
  SwipeTestPage,
18809
- ChipsTestPage
18916
+ ChipsTestPage,
18917
+ MatBadgeIconTestPage
18810
18918
  ],
18811
18919
  exports: [
18812
18920
  SharedMaterialModule,
@@ -18921,7 +19029,7 @@
18921
19029
  if (form)
18922
19030
  this.setForm(form);
18923
19031
  this.settings = injector.get(LocalSettingsService);
18924
- this.errorTranslator = injector.get(FormErrorAdapter);
19032
+ this.errorTranslator = injector.get(FormErrorTranslator);
18925
19033
  this.autocompleteHelper = new MatAutocompleteConfigHolder(this.settings && {
18926
19034
  getUserAttributes: function (a, b) { return _this.settings.getFieldDisplayAttributes(a, b); }
18927
19035
  });
@@ -20235,6 +20343,7 @@
20235
20343
  this.onSave = new i0.EventEmitter();
20236
20344
  this.onNext = new i0.EventEmitter();
20237
20345
  this.onBack = new i0.EventEmitter();
20346
+ // Ctrl+S
20238
20347
  this._subscription.add(hotkeys.addShortcut({ keys: 'control.s', description: 'COMMON.BTN_SAVE' })
20239
20348
  .pipe(operators.filter(function (e) { return !_this.disabled; }))
20240
20349
  .subscribe(function (event) { return _this.onSave.emit(event); }));
@@ -23418,7 +23527,7 @@
23418
23527
  this._paginator = null;
23419
23528
  this.mobile = this.platform.is('mobile');
23420
23529
  this.translate = injector === null || injector === void 0 ? void 0 : injector.get(i1$2.TranslateService);
23421
- this.formErrorAdapter = injector === null || injector === void 0 ? void 0 : injector.get(FormErrorAdapter);
23530
+ this.formErrorAdapter = injector === null || injector === void 0 ? void 0 : injector.get(FormErrorTranslator);
23422
23531
  this.alertCtrl = injector === null || injector === void 0 ? void 0 : injector.get(i1$5.AlertController);
23423
23532
  this.toastController = injector === null || injector === void 0 ? void 0 : injector.get(i1$5.ToastController);
23424
23533
  this._autocompleteConfigHolder = new MatAutocompleteConfigHolder({
@@ -25768,7 +25877,7 @@
25768
25877
  enableListenChanges: (injector.get(ENVIRONMENT).listenRemoteChanges === true), pathIdAttribute: 'id', autoLoad: true, autoUpdateRoute: true, i18nPrefix: ''
25769
25878
  }, options);
25770
25879
  _this.settings = injector.get(LocalSettingsService);
25771
- _this.formErrorAdapter = injector.get(FormErrorAdapter);
25880
+ _this.formErrorAdapter = injector.get(FormErrorTranslator);
25772
25881
  _this.cd = injector.get(i0.ChangeDetectorRef);
25773
25882
  _this.dateFormat = injector.get(DateFormatPipe);
25774
25883
  _this.toastController = injector.get(i1$5.ToastController);
@@ -27795,8 +27904,8 @@
27795
27904
  exports.FormArrayHelper = FormArrayHelper;
27796
27905
  exports.FormButtonsBarComponent = FormButtonsBarComponent;
27797
27906
  exports.FormButtonsBarToken = FormButtonsBarToken;
27798
- exports.FormErrorAdapter = FormErrorAdapter;
27799
27907
  exports.FormErrorTranslatePipe = FormErrorTranslatePipe;
27908
+ exports.FormErrorTranslator = FormErrorTranslator;
27800
27909
  exports.FormFieldValuesHolder = FormFieldValuesHolder;
27801
27910
  exports.Fragments = Fragments;
27802
27911
  exports.GraphqlService = GraphqlService;
@@ -28049,12 +28158,15 @@
28049
28158
  exports["ɵ0"] = ɵ0$5;
28050
28159
  exports["ɵa"] = CustomReuseStrategy;
28051
28160
  exports["ɵb"] = MatNumpadDomService;
28052
- exports["ɵc"] = isFocusableElement;
28053
- exports["ɵd"] = RegisterForm;
28054
- exports["ɵe"] = AccountValidatorService;
28055
- exports["ɵf"] = RegisterModal;
28056
- exports["ɵg"] = UserSettingsValidatorService;
28057
- exports["ɵh"] = LocalSettingsValidatorService;
28161
+ exports["ɵc"] = SharedMatBadgeIconModule;
28162
+ exports["ɵd"] = MatBadgeIconDirective;
28163
+ exports["ɵe"] = isFocusableElement;
28164
+ exports["ɵf"] = MatBadgeIconTestPage;
28165
+ exports["ɵg"] = RegisterForm;
28166
+ exports["ɵh"] = AccountValidatorService;
28167
+ exports["ɵi"] = RegisterModal;
28168
+ exports["ɵj"] = UserSettingsValidatorService;
28169
+ exports["ɵk"] = LocalSettingsValidatorService;
28058
28170
 
28059
28171
  Object.defineProperty(exports, '__esModule', { value: true });
28060
28172