@yuuvis/client-framework 2.3.0 → 2.3.2

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 (26) hide show
  1. package/fesm2022/yuuvis-client-framework-forms.mjs +22 -12
  2. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  3. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +2 -2
  4. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +55 -22
  6. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-object-details.mjs +139 -52
  8. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-object-form.mjs +1 -1
  10. package/fesm2022/yuuvis-client-framework-object-preview.mjs +4 -26
  11. package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -1
  12. package/fesm2022/yuuvis-client-framework-tile-list.mjs +8 -3
  13. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  14. package/forms/index.d.ts +1 -0
  15. package/forms/lib/elements/data-grid/data-grid/data-grid.component.d.ts +3 -1
  16. package/forms/lib/forms.utils.d.ts +4 -0
  17. package/metadata-form/lib/object-metadata-element-label.directive.d.ts +16 -5
  18. package/object-details/lib/object-details-shell/object-details-shell.component.d.ts +1 -1
  19. package/object-details/lib/object-details-shell/object-details-shell.service.d.ts +2 -1
  20. package/object-details/lib/object-details.component.d.ts +4 -3
  21. package/object-details/lib/object-metadata/object-metadata-section/object-metadata-section.component.d.ts +8 -4
  22. package/object-details/lib/object-metadata/object-metadata.component.d.ts +16 -5
  23. package/object-form/index.d.ts +0 -1
  24. package/object-preview/lib/services/object-preview.service.d.ts +1 -22
  25. package/package.json +8 -8
  26. package/tile-list/lib/tile-list/tile-list.component.d.ts +3 -1
@@ -19,7 +19,7 @@ import { YmtButtonDirective, YmtIconButtonDirective } from '@yuuvis/material';
19
19
  import { map, timer, take, of, forkJoin } from 'rxjs';
20
20
  import { MatFormFieldModule, MatFormFieldControl } from '@angular/material/form-field';
21
21
  import { FormTranslateService, DialogComponent, AbstractMatFormField, injectNgControl } from '@yuuvis/client-framework/common';
22
- import { MetadataFormFieldComponent } from '@yuuvis/client-framework/metadata-form';
22
+ import { MetadataFormFieldComponent, ObjectMetadataElementLabelDirective } from '@yuuvis/client-framework/metadata-form';
23
23
  import { MatDatepickerModule } from '@angular/material/datepicker';
24
24
  import { MatInputModule } from '@angular/material/input';
25
25
  import { TranslateService as TranslateService$1, TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
@@ -167,6 +167,8 @@ class DataGridComponent {
167
167
  this.formControl = input(undefined);
168
168
  this.classifications = input([]);
169
169
  this.readonly = input(false);
170
+ // context to also apply form labels state (e.g. dirty, error) to the data grid label
171
+ this.formFieldContext = input();
170
172
  this.size = input(DataGridSizeType.AUTO);
171
173
  this.displayedColumns = signal([]);
172
174
  this.displayedColumnsWithActions = signal([]);
@@ -320,7 +322,7 @@ class DataGridComponent {
320
322
  this.onTouched();
321
323
  }
322
324
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
323
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DataGridComponent, isStandalone: true, selector: "yuv-data-grid", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, formElement: { classPropertyName: "formElement", publicName: "formElement", isSignal: true, isRequired: false, transformFunction: null }, formControl: { classPropertyName: "formControl", publicName: "formControl", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusout": "onHostFocusOut($event)" }, classAttribute: "yuv-data-grid" }, providers: [
325
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DataGridComponent, isStandalone: true, selector: "yuv-data-grid", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, formElement: { classPropertyName: "formElement", publicName: "formElement", isSignal: true, isRequired: false, transformFunction: null }, formControl: { classPropertyName: "formControl", publicName: "formControl", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, formFieldContext: { classPropertyName: "formFieldContext", publicName: "formFieldContext", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusout": "onHostFocusOut($event)" }, classAttribute: "yuv-data-grid" }, providers: [
324
326
  {
325
327
  provide: NG_VALUE_ACCESSOR,
326
328
  useExisting: forwardRef(() => DataGridComponent),
@@ -333,11 +335,13 @@ class DataGridComponent {
333
335
  },
334
336
  DecimalPipe,
335
337
  DatePipe
336
- ], ngImport: i0, template: "\n<fieldset [attr.aria-required]=\"isRequired\" [attr.aria-invalid]=\"isInvalid\" >\n <legend class=\"ymt-hide-sr\">{{ tableLabel() }} @if(isRequired) {*}</legend>\n <header class=\"yuv-data-grid__header\">\n <span class=\"yuv-data-grid__header-title\" [ngClass]=\"{'yuv-data-grid__header-title--invalid' : isInvalid}\" aria-hidden=\"true\">\n {{ tableLabel() }} @if(isRequired) {*}\n </span>\n\n @if (!readonly()) {\n <button ymtIconButton (click)=\"addRow()\" class=\"yuv-data-grid__header-action\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </header>\n\n @let displayedCol = displayedColumns();\n @let displayedColActions = displayedColumnsWithActions();\n\n <div class=\"yuv-data-grid__table\" [ngClass]=\"size()\">\n <table mat-table [dataSource]=\"dataSource()\" class=\"mat-elevation-z8\">\n <caption class=\"ymt-hide-sr\">{{ tableLabel() }}</caption>\n\n @for (column of displayedCol; track column) {\n <ng-container [matColumnDef]=\"column.columnDef\">\n <th mat-header-cell *matHeaderCellDef [attr.aria-label]=\"column.header\" [title]=\"column.header\">{{ column.header }}</th>\n <td [ngClass]=\"{'number-cell': column.type === 'integer' || column.type === 'decimal', 'yuv-data-grid__cell--editable': !readonly()}\" mat-cell *matCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n @if (!readonly()) {\n <ng-container matColumnDef=\"actions\" stickyEnd>\n <th mat-header-cell *matHeaderCellDef aria-label=\"row actions\"></th>\n <td class=\"yuv-data-grid__cell--editable\" mat-cell *matCellDef=\"let element\">\n <div class=\"yuv-data-grid__table-actions\">\n <!-- Only show the button in the last (empty) row -->\n <button ymtIconButton icon-button-size=\"small\" class=\"table-options-menu-bar-item\" [matMenuTriggerFor]=\"menu\" (click)=\"onMenuTrigger(element)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColActions; sticky: ['header-1']\"></tr>\n\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n\n </table>\n </div>\n</fieldset>\n<mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"copyLine(selectedRow())\">{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button mat-menu-item (click)=\"editRow(selectedRow())\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button mat-menu-item (click)=\"removeRow(selectedRow())\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n</mat-menu>\n", styles: [":host{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px;max-width:100%;width:100%}:host .yuv-data-grid__header{display:flex;justify-content:space-between;margin-block-end:var(--ymt-spacing-m)}:host .yuv-data-grid__header-title--invalid{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);align-self:baseline}:host .yuv-data-grid__cell--editable{-webkit-user-select:none;user-select:none}:host .yuv-data-grid__table{overflow:auto;white-space:nowrap}:host .yuv-data-grid__table.small{height:var(--table-size-small)}:host .yuv-data-grid__table.medium{height:var(--table-size-medium)}:host .yuv-data-grid__table.large{height:var(--table-size-large)}:host .yuv-data-grid__table.extra-large{height:var(--table-size-extra-large)}:host .yuv-data-grid__table-actions{display:flex;align-items:center;justify-content:flex-end}:host.yuv-data-grid{display:block}:host.yuv-data-grid ::ng-deep tr.cdk-row td.number-cell{text-align:right}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
338
+ ], ngImport: i0, template: "\n<fieldset [attr.aria-required]=\"isRequired\" [attr.aria-invalid]=\"isInvalid\" >\n <legend class=\"ymt-hide-sr\">{{ tableLabel() }} @if(isRequired) {*}</legend>\n <header class=\"yuv-data-grid__header\">\n <span [yuvObjectMetadataElementLabel]=\"formFieldContext()\"class=\"yuv-data-grid__header-title label\" [ngClass]=\"{'yuv-data-grid__header-title--invalid' : isInvalid}\" aria-hidden=\"true\">\n {{ tableLabel() }} @if(isRequired) {*}\n </span>\n\n @if (!readonly()) {\n <button ymtIconButton (click)=\"addRow()\" class=\"yuv-data-grid__header-action\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </header>\n\n @let displayedCol = displayedColumns();\n @let displayedColActions = displayedColumnsWithActions();\n\n <div class=\"yuv-data-grid__table\" [ngClass]=\"size()\">\n <table mat-table [dataSource]=\"dataSource()\" class=\"mat-elevation-z8\">\n <caption class=\"ymt-hide-sr\">{{ tableLabel() }}</caption>\n\n @for (column of displayedCol; track column) {\n <ng-container [matColumnDef]=\"column.columnDef\">\n <th mat-header-cell *matHeaderCellDef [attr.aria-label]=\"column.header\" [title]=\"column.header\">{{ column.header }}</th>\n <td [ngClass]=\"{'number-cell': column.type === 'integer' || column.type === 'decimal', 'yuv-data-grid__cell--editable': !readonly()}\" mat-cell *matCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n @if (!readonly()) {\n <ng-container matColumnDef=\"actions\" stickyEnd>\n <th mat-header-cell *matHeaderCellDef aria-label=\"row actions\"></th>\n <td class=\"yuv-data-grid__cell--editable\" mat-cell *matCellDef=\"let element\">\n <div class=\"yuv-data-grid__table-actions\">\n <!-- Only show the button in the last (empty) row -->\n <button ymtIconButton icon-button-size=\"small\" class=\"table-options-menu-bar-item\" [matMenuTriggerFor]=\"menu\" (click)=\"onMenuTrigger(element)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColActions; sticky: ['header-1']\"></tr>\n\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n\n </table>\n </div>\n</fieldset>\n<mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"copyLine(selectedRow())\">{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button mat-menu-item (click)=\"editRow(selectedRow())\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button mat-menu-item (click)=\"removeRow(selectedRow())\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n</mat-menu>\n", styles: [":host{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px;max-width:100%;width:100%}:host .yuv-data-grid__header{display:flex;justify-content:space-between;align-items:center;margin-block-end:var(--ymt-spacing-m)}:host .yuv-data-grid__header-title{transform:scale(var(--mat-mdc-form-field-floating-label-scale, .75))}:host .yuv-data-grid__header-title--invalid{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);align-self:baseline}:host .yuv-data-grid__cell--editable{-webkit-user-select:none;user-select:none}:host .yuv-data-grid__table{overflow:auto;white-space:nowrap}:host .yuv-data-grid__table.small{height:var(--table-size-small)}:host .yuv-data-grid__table.medium{height:var(--table-size-medium)}:host .yuv-data-grid__table.large{height:var(--table-size-large)}:host .yuv-data-grid__table.extra-large{height:var(--table-size-extra-large)}:host .yuv-data-grid__table-actions{display:flex;align-items:center;justify-content:flex-end}:host.yuv-data-grid{display:block}:host.yuv-data-grid ::ng-deep tr.cdk-row td.number-cell{text-align:right}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: ObjectMetadataElementLabelDirective, selector: "[yuvObjectMetadataElementLabel]", inputs: ["yuvObjectMetadataElementLabel"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
337
339
  }
338
340
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataGridComponent, decorators: [{
339
341
  type: Component,
340
- args: [{ selector: 'yuv-data-grid', standalone: true, imports: [NgClass, TranslateModule, ...MATERIAL, YmtIconButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
342
+ args: [{ selector: 'yuv-data-grid', standalone: true, imports: [NgClass, TranslateModule, ...MATERIAL,
343
+ ObjectMetadataElementLabelDirective,
344
+ YmtIconButtonDirective], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
341
345
  {
342
346
  provide: NG_VALUE_ACCESSOR,
343
347
  useExisting: forwardRef(() => DataGridComponent),
@@ -353,7 +357,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
353
357
  ], host: {
354
358
  class: 'yuv-data-grid',
355
359
  '(focusout)': 'onHostFocusOut($event)'
356
- }, template: "\n<fieldset [attr.aria-required]=\"isRequired\" [attr.aria-invalid]=\"isInvalid\" >\n <legend class=\"ymt-hide-sr\">{{ tableLabel() }} @if(isRequired) {*}</legend>\n <header class=\"yuv-data-grid__header\">\n <span class=\"yuv-data-grid__header-title\" [ngClass]=\"{'yuv-data-grid__header-title--invalid' : isInvalid}\" aria-hidden=\"true\">\n {{ tableLabel() }} @if(isRequired) {*}\n </span>\n\n @if (!readonly()) {\n <button ymtIconButton (click)=\"addRow()\" class=\"yuv-data-grid__header-action\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </header>\n\n @let displayedCol = displayedColumns();\n @let displayedColActions = displayedColumnsWithActions();\n\n <div class=\"yuv-data-grid__table\" [ngClass]=\"size()\">\n <table mat-table [dataSource]=\"dataSource()\" class=\"mat-elevation-z8\">\n <caption class=\"ymt-hide-sr\">{{ tableLabel() }}</caption>\n\n @for (column of displayedCol; track column) {\n <ng-container [matColumnDef]=\"column.columnDef\">\n <th mat-header-cell *matHeaderCellDef [attr.aria-label]=\"column.header\" [title]=\"column.header\">{{ column.header }}</th>\n <td [ngClass]=\"{'number-cell': column.type === 'integer' || column.type === 'decimal', 'yuv-data-grid__cell--editable': !readonly()}\" mat-cell *matCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n @if (!readonly()) {\n <ng-container matColumnDef=\"actions\" stickyEnd>\n <th mat-header-cell *matHeaderCellDef aria-label=\"row actions\"></th>\n <td class=\"yuv-data-grid__cell--editable\" mat-cell *matCellDef=\"let element\">\n <div class=\"yuv-data-grid__table-actions\">\n <!-- Only show the button in the last (empty) row -->\n <button ymtIconButton icon-button-size=\"small\" class=\"table-options-menu-bar-item\" [matMenuTriggerFor]=\"menu\" (click)=\"onMenuTrigger(element)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColActions; sticky: ['header-1']\"></tr>\n\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n\n </table>\n </div>\n</fieldset>\n<mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"copyLine(selectedRow())\">{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button mat-menu-item (click)=\"editRow(selectedRow())\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button mat-menu-item (click)=\"removeRow(selectedRow())\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n</mat-menu>\n", styles: [":host{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px;max-width:100%;width:100%}:host .yuv-data-grid__header{display:flex;justify-content:space-between;margin-block-end:var(--ymt-spacing-m)}:host .yuv-data-grid__header-title--invalid{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);align-self:baseline}:host .yuv-data-grid__cell--editable{-webkit-user-select:none;user-select:none}:host .yuv-data-grid__table{overflow:auto;white-space:nowrap}:host .yuv-data-grid__table.small{height:var(--table-size-small)}:host .yuv-data-grid__table.medium{height:var(--table-size-medium)}:host .yuv-data-grid__table.large{height:var(--table-size-large)}:host .yuv-data-grid__table.extra-large{height:var(--table-size-extra-large)}:host .yuv-data-grid__table-actions{display:flex;align-items:center;justify-content:flex-end}:host.yuv-data-grid{display:block}:host.yuv-data-grid ::ng-deep tr.cdk-row td.number-cell{text-align:right}\n"] }]
360
+ }, template: "\n<fieldset [attr.aria-required]=\"isRequired\" [attr.aria-invalid]=\"isInvalid\" >\n <legend class=\"ymt-hide-sr\">{{ tableLabel() }} @if(isRequired) {*}</legend>\n <header class=\"yuv-data-grid__header\">\n <span [yuvObjectMetadataElementLabel]=\"formFieldContext()\"class=\"yuv-data-grid__header-title label\" [ngClass]=\"{'yuv-data-grid__header-title--invalid' : isInvalid}\" aria-hidden=\"true\">\n {{ tableLabel() }} @if(isRequired) {*}\n </span>\n\n @if (!readonly()) {\n <button ymtIconButton (click)=\"addRow()\" class=\"yuv-data-grid__header-action\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </header>\n\n @let displayedCol = displayedColumns();\n @let displayedColActions = displayedColumnsWithActions();\n\n <div class=\"yuv-data-grid__table\" [ngClass]=\"size()\">\n <table mat-table [dataSource]=\"dataSource()\" class=\"mat-elevation-z8\">\n <caption class=\"ymt-hide-sr\">{{ tableLabel() }}</caption>\n\n @for (column of displayedCol; track column) {\n <ng-container [matColumnDef]=\"column.columnDef\">\n <th mat-header-cell *matHeaderCellDef [attr.aria-label]=\"column.header\" [title]=\"column.header\">{{ column.header }}</th>\n <td [ngClass]=\"{'number-cell': column.type === 'integer' || column.type === 'decimal', 'yuv-data-grid__cell--editable': !readonly()}\" mat-cell *matCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n @if (!readonly()) {\n <ng-container matColumnDef=\"actions\" stickyEnd>\n <th mat-header-cell *matHeaderCellDef aria-label=\"row actions\"></th>\n <td class=\"yuv-data-grid__cell--editable\" mat-cell *matCellDef=\"let element\">\n <div class=\"yuv-data-grid__table-actions\">\n <!-- Only show the button in the last (empty) row -->\n <button ymtIconButton icon-button-size=\"small\" class=\"table-options-menu-bar-item\" [matMenuTriggerFor]=\"menu\" (click)=\"onMenuTrigger(element)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColActions; sticky: ['header-1']\"></tr>\n\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr mat-row *matRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n\n </table>\n </div>\n</fieldset>\n<mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"copyLine(selectedRow())\">{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button mat-menu-item (click)=\"editRow(selectedRow())\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button mat-menu-item (click)=\"removeRow(selectedRow())\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n</mat-menu>\n", styles: [":host{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px;max-width:100%;width:100%}:host .yuv-data-grid__header{display:flex;justify-content:space-between;align-items:center;margin-block-end:var(--ymt-spacing-m)}:host .yuv-data-grid__header-title{transform:scale(var(--mat-mdc-form-field-floating-label-scale, .75))}:host .yuv-data-grid__header-title--invalid{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);align-self:baseline}:host .yuv-data-grid__cell--editable{-webkit-user-select:none;user-select:none}:host .yuv-data-grid__table{overflow:auto;white-space:nowrap}:host .yuv-data-grid__table.small{height:var(--table-size-small)}:host .yuv-data-grid__table.medium{height:var(--table-size-medium)}:host .yuv-data-grid__table.large{height:var(--table-size-large)}:host .yuv-data-grid__table.extra-large{height:var(--table-size-extra-large)}:host .yuv-data-grid__table-actions{display:flex;align-items:center;justify-content:flex-end}:host.yuv-data-grid{display:block}:host.yuv-data-grid ::ng-deep tr.cdk-row td.number-cell{text-align:right}\n"] }]
357
361
  }] });
358
362
 
359
363
  class DatetimeComponent extends AbstractMatFormField {
@@ -609,6 +613,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
609
613
  type: Input
610
614
  }] } });
611
615
 
616
+ class FormUtils {
617
+ static getErrorState(control) {
618
+ return control.invalid && (control.dirty || control.touched);
619
+ }
620
+ }
621
+
612
622
  var _a;
613
623
  /**
614
624
  * Creates form input for number values.
@@ -764,7 +774,7 @@ class NumberComponent extends AbstractMatFormField {
764
774
  validators.push(Validators.required);
765
775
  this.innerCtrl.setValidators(validators);
766
776
  this.innerCtrl.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
767
- this.errorState = this.innerCtrl.invalid;
777
+ this.errorState = FormUtils.getErrorState(this.innerCtrl);
768
778
  if (this.ngControl?.control) {
769
779
  this.ngControl.control.setErrors(this.innerCtrl.errors);
770
780
  }
@@ -955,7 +965,7 @@ class NumberRangeComponent extends AbstractMatFormField {
955
965
  ngOnInit() {
956
966
  this.rangeForm.setValidators(this.#getValidator());
957
967
  this.rangeForm.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
958
- this.errorState = this.rangeForm.invalid;
968
+ this.errorState = FormUtils.getErrorState(this.rangeForm);
959
969
  if (this.ngControl?.control) {
960
970
  this.ngControl.control.setErrors(this.rangeForm.errors);
961
971
  }
@@ -1163,7 +1173,7 @@ class OrganizationComponent extends AbstractMatFormField {
1163
1173
  if (this.required)
1164
1174
  this.acFormControl.setValidators(Validators.required);
1165
1175
  this.acFormControl.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
1166
- this.errorState = this.acFormControl.invalid;
1176
+ this.errorState = FormUtils.getErrorState(this.acFormControl);
1167
1177
  if (this.ngControl?.control) {
1168
1178
  this.ngControl.control.setErrors(this.acFormControl.errors);
1169
1179
  }
@@ -1320,7 +1330,7 @@ class OrganizationSetComponent extends AbstractMatFormField {
1320
1330
  if (this.required)
1321
1331
  this.acFormControl.setValidators(Validators.required);
1322
1332
  this.acFormControl.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
1323
- this.errorState = this.acFormControl.invalid;
1333
+ this.errorState = FormUtils.getErrorState(this.acFormControl);
1324
1334
  if (this.ngControl?.control) {
1325
1335
  this.ngControl.control.setErrors(this.acFormControl.errors);
1326
1336
  }
@@ -1871,7 +1881,7 @@ class StringComponent extends AbstractMatFormField {
1871
1881
  validators.push(Validators.required);
1872
1882
  this.fc.setValidators(validators);
1873
1883
  this.fc.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
1874
- this.errorState = this.fc.invalid;
1884
+ this.errorState = FormUtils.getErrorState(this.fc);
1875
1885
  if (this.ngControl?.control) {
1876
1886
  this.ngControl.control.setErrors(this.fc.errors);
1877
1887
  }
@@ -1977,7 +1987,7 @@ class CatalogComponent extends AbstractMatFormField {
1977
1987
  if (this.required)
1978
1988
  this.fc.setValidators(Validators.required);
1979
1989
  this.fc.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
1980
- this.errorState = this.fc.invalid;
1990
+ this.errorState = FormUtils.getErrorState(this.fc);
1981
1991
  if (this.ngControl?.control) {
1982
1992
  this.ngControl.control.setErrors(this.fc.errors);
1983
1993
  }
@@ -2042,5 +2052,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2042
2052
  * Generated bundle index. Do not edit.
2043
2053
  */
2044
2054
 
2045
- export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
2055
+ export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, FormUtils, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
2046
2056
  //# sourceMappingURL=yuuvis-client-framework-forms.mjs.map