@yuuvis/client-framework 0.8.0 → 0.9.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.
Files changed (72) hide show
  1. package/actions/lib/actions/delete-action/delete-action.d.ts +1 -0
  2. package/common/index.d.ts +1 -0
  3. package/common/lib/services/error-messages/error-messages.service.d.ts +7 -0
  4. package/common/lib/services/index.d.ts +1 -0
  5. package/esm2022/actions/lib/actions/delete-action/delete-action.mjs +4 -10
  6. package/esm2022/common/index.mjs +2 -1
  7. package/esm2022/common/lib/directives/drag-select.directive.mjs +2 -2
  8. package/esm2022/common/lib/services/error-messages/error-messages.service.mjs +68 -0
  9. package/esm2022/common/lib/services/index.mjs +2 -0
  10. package/esm2022/forms/index.mjs +9 -8
  11. package/esm2022/forms/lib/elements/data-grid/data-grid/data-grid.component.mjs +172 -0
  12. package/esm2022/forms/lib/elements/data-grid/edit-table-data/edit-data.component.mjs +95 -0
  13. package/esm2022/forms/lib/elements/data-grid/model/data-grid.interface.mjs +9 -0
  14. package/esm2022/forms/lib/elements/index.mjs +11 -0
  15. package/esm2022/forms/lib/elements/organization/organization.component.mjs +47 -29
  16. package/esm2022/icons/lib/icons.mjs +3 -2
  17. package/esm2022/metadata-form/lib/metadata-default-templates/metadata-default-templates.component.mjs +5 -4
  18. package/esm2022/metadata-form/lib/metadata-form-element-registry.service.mjs +1 -1
  19. package/esm2022/metadata-form/lib/metadata-form-field/metadata-form-field.component.mjs +7 -52
  20. package/esm2022/object-details/index.mjs +2 -1
  21. package/esm2022/object-details/lib/object-metadata/object-metadata.component.mjs +5 -4
  22. package/esm2022/object-details/lib/retention-badge/retention-badge.component.mjs +27 -0
  23. package/esm2022/object-form/index.mjs +1 -1
  24. package/esm2022/object-form/lib/object-form.component.mjs +2 -1
  25. package/esm2022/object-form/lib/object-form.service.mjs +5 -2
  26. package/esm2022/object-summary/lib/object-summary/object-summary.component.mjs +15 -13
  27. package/esm2022/pagination/lib/pagination.component.mjs +4 -6
  28. package/esm2022/sequence-list/index.mjs +1 -3
  29. package/esm2022/sequence-list/lib/sequence-list.component.mjs +11 -16
  30. package/esm2022/sequence-list/lib/sequence-list.interface.mjs +1 -1
  31. package/esm2022/tile-list/lib/tile/tile.component.mjs +3 -3
  32. package/esm2022/tile-list/lib/tile-extension/extensions/email.extension.mjs +1 -1
  33. package/fesm2022/yuuvis-client-framework-actions.mjs +3 -9
  34. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  35. package/fesm2022/yuuvis-client-framework-common.mjs +69 -4
  36. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  37. package/fesm2022/yuuvis-client-framework-forms.mjs +1194 -909
  38. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  39. package/fesm2022/yuuvis-client-framework-icons.mjs +2 -1
  40. package/fesm2022/yuuvis-client-framework-icons.mjs.map +1 -1
  41. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +10 -55
  42. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
  43. package/fesm2022/yuuvis-client-framework-object-details.mjs +26 -5
  44. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  45. package/fesm2022/yuuvis-client-framework-object-form.mjs +5 -1
  46. package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
  47. package/fesm2022/yuuvis-client-framework-object-summary.mjs +14 -12
  48. package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -1
  49. package/fesm2022/yuuvis-client-framework-pagination.mjs +3 -5
  50. package/fesm2022/yuuvis-client-framework-pagination.mjs.map +1 -1
  51. package/fesm2022/yuuvis-client-framework-sequence-list.mjs +17 -296
  52. package/fesm2022/yuuvis-client-framework-sequence-list.mjs.map +1 -1
  53. package/fesm2022/yuuvis-client-framework-tile-list.mjs +2 -2
  54. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  55. package/forms/index.d.ts +1 -7
  56. package/forms/lib/elements/data-grid/data-grid/data-grid.component.d.ts +38 -0
  57. package/forms/lib/elements/data-grid/edit-table-data/edit-data.component.d.ts +21 -0
  58. package/forms/lib/elements/data-grid/model/data-grid.interface.d.ts +14 -0
  59. package/forms/lib/elements/index.d.ts +10 -0
  60. package/forms/lib/elements/organization/organization.component.d.ts +13 -4
  61. package/metadata-form/lib/metadata-form-field/metadata-form-field.component.d.ts +0 -1
  62. package/object-details/index.d.ts +1 -0
  63. package/object-details/lib/retention-badge/retention-badge.component.d.ts +12 -0
  64. package/package.json +10 -10
  65. package/sequence-list/index.d.ts +0 -2
  66. package/sequence-list/lib/sequence-list.component.d.ts +2 -2
  67. package/sequence-list/lib/sequence-list.interface.d.ts +5 -4
  68. package/styles/client-framework.scss +55 -18
  69. package/esm2022/sequence-list/lib/sequence-list-template-manage/sequence-list-template-manage.component.mjs +0 -183
  70. package/esm2022/sequence-list/lib/sequence-list-templates/sequence-list-templates.component.mjs +0 -114
  71. package/sequence-list/lib/sequence-list-template-manage/sequence-list-template-manage.component.d.ts +0 -52
  72. package/sequence-list/lib/sequence-list-templates/sequence-list-templates.component.d.ts +0 -36
@@ -1,31 +1,118 @@
1
+ import * as i1$2 from '@angular/common';
2
+ import { CommonModule, DecimalPipe, NgClass } from '@angular/common';
1
3
  import * as i0 from '@angular/core';
2
- import { forwardRef, Component, Input, inject, input, EventEmitter, ViewChild, HostListener, HostBinding, Output, ElementRef, Renderer2, ViewEncapsulation, NgModule, output, effect, signal } from '@angular/core';
4
+ import { inject, Renderer2, Component, ViewEncapsulation, ViewChild, Input, HostBinding, forwardRef, ElementRef, signal, input, ChangeDetectionStrategy, computed, effect, untracked, EventEmitter, HostListener, Output, output, NgModule } from '@angular/core';
5
+ import { FocusWithinDirective, ErrorMessagesService } from '@yuuvis/client-framework/common';
3
6
  import * as i2 from '@angular/forms';
4
- import { NG_VALUE_ACCESSOR, FormsModule, FormBuilder, Validators, NG_VALIDATORS, ReactiveFormsModule, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
7
+ import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS, FormBuilder, Validators, ReactiveFormsModule, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
5
8
  import * as i1 from '@yuuvis/client-core';
6
- import { Classification, OperatorLabel, Operator, Situation, FileSizePipe, LocaleNumberPipe, Utils, SystemService, UserService, YuvUser, TranslateModule, ClassificationPrefix, TranslateService as TranslateService$1, SearchUtils, LocaleDatePipe } from '@yuuvis/client-core';
9
+ import { Classification, FileSizePipe, LocaleNumberPipe, Utils, ClassificationPrefix, Situation, TranslateModule, ClipboardService, TranslateService, OperatorLabel, Operator, SystemService, UserService, YuvUser, SearchUtils, LocaleDatePipe } from '@yuuvis/client-core';
7
10
  import * as i1$1 from '@yuuvis/components/dropdown';
8
11
  import { YvcDropdownModule } from '@yuuvis/components/dropdown';
9
- import { TranslateService, TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
10
- import * as i2$1 from '@yuuvis/components/datepicker';
11
- import { YvcDatepickerModule } from '@yuuvis/components/datepicker';
12
- import * as i1$2 from '@angular/common';
13
- import { CommonModule } from '@angular/common';
14
- import { YUV_ICONS, IconService } from '@yuuvis/client-framework/icons';
15
- import * as i2$2 from '@yuuvis/components/autocomplete';
16
- import { YvcAutocompleteModule } from '@yuuvis/components/autocomplete';
12
+ import { CdkMenu, CdkMenuTrigger, CdkMenuItem } from '@angular/cdk/menu';
13
+ import * as i4 from '@angular/cdk/table';
14
+ import { CdkTableModule } from '@angular/cdk/table';
15
+ import { IconService, YUV_ICONS } from '@yuuvis/client-framework/icons';
17
16
  import * as i3 from '@yuuvis/components/icon';
18
17
  import { YvcIconModule } from '@yuuvis/components/icon';
19
- import { of, forkJoin } from 'rxjs';
20
- import { catchError } from 'rxjs/operators';
21
- import * as i2$3 from '@yuuvis/components/chips';
18
+ import { YvcOverlayRef, YvcOverlayService } from '@yuuvis/components/overlay';
19
+ import { map, of, forkJoin } from 'rxjs';
20
+ import * as i2$1 from '@yuuvis/components/chips';
22
21
  import { YvcChipsModule } from '@yuuvis/components/chips';
23
- import { FocusWithinDirective } from '@yuuvis/client-framework/common';
24
- import { YvcCheckboxModule } from '@yuuvis/components/checkbox';
25
- import { YvcFocusWithin } from '@yuuvis/components/common';
22
+ import { TranslateService as TranslateService$1, TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
23
+ import * as i2$2 from '@yuuvis/components/datepicker';
24
+ import { YvcDatepickerModule } from '@yuuvis/components/datepicker';
25
+ import * as i3$1 from '@yuuvis/components/autocomplete';
26
+ import { YvcAutocompleteModule } from '@yuuvis/components/autocomplete';
27
+ import { map as map$1, catchError } from 'rxjs/operators';
26
28
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
27
29
  import { marker } from '@colsen1991/ngx-translate-extract-marker';
28
- import { YvcOverlayRef, YvcOverlayService } from '@yuuvis/components/overlay';
30
+ import { YvcCheckboxModule } from '@yuuvis/components/checkbox';
31
+ import { YvcFocusWithin } from '@yuuvis/components/common';
32
+
33
+ /**
34
+ * Component for wrapping a form element. Provides a label and focus behaviour.
35
+ *
36
+ * @example
37
+ * <yuv-form-input [label]="'my form element'">
38
+ * <!-- form element to be wrapped -->
39
+ * </yuv-form-input>
40
+ */
41
+ class FormInputComponent {
42
+ constructor() {
43
+ this.renderer = inject(Renderer2);
44
+ this.isDisabled = false;
45
+ this.isInvalid = false;
46
+ this.isRequired = false;
47
+ }
48
+ /**
49
+ * A label string for the wrapped form element
50
+ */
51
+ set label(val) {
52
+ this._label = val;
53
+ }
54
+ /**
55
+ * Indicator that the wrapped form element is invalid. Will then render appropriate styles.
56
+ * You may also provide an array of error messages.
57
+ */
58
+ set invalid(iv) {
59
+ if (iv === null || iv === undefined) {
60
+ this.isInvalid = false;
61
+ this.renderer.removeAttribute(this.labelEl.nativeElement, 'title');
62
+ }
63
+ else if (Array.isArray(iv)) {
64
+ this.isInvalid = iv.length > 0;
65
+ if (this.isInvalid) {
66
+ this.renderer.setAttribute(this.labelEl.nativeElement, 'title', iv.join(';'));
67
+ }
68
+ }
69
+ else {
70
+ this.isInvalid = iv;
71
+ }
72
+ }
73
+ /**
74
+ * Indicator that the wrapped form element is disabled. Will then render appropriate styles.
75
+ */
76
+ set disabled(d) {
77
+ this.isDisabled = d;
78
+ }
79
+ /**
80
+ * Indicator that the wrapped form element is mandatory. Will then render appropriate styles.
81
+ */
82
+ set required(d) {
83
+ this.isRequired = d;
84
+ }
85
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
86
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FormInputComponent, isStandalone: true, selector: "yuv-form-input", inputs: { label: "label", tag: "tag", description: "description", invalid: "invalid", disabled: "disabled", required: "required" }, host: { properties: { "class.disabled": "this.isDisabled", "class.invalid": "this.isInvalid", "class.required": "this.isRequired" } }, viewQueries: [{ propertyName: "labelEl", first: true, predicate: ["label"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: FocusWithinDirective, selector: "[yuvFocusWithin]", outputs: ["yuvFocusWithin", "yuvFocusWithinBlur"] }], encapsulation: i0.ViewEncapsulation.None }); }
87
+ }
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, decorators: [{
89
+ type: Component,
90
+ args: [{ selector: 'yuv-form-input', standalone: true, imports: [CommonModule, FocusWithinDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"] }]
91
+ }], propDecorators: { labelEl: [{
92
+ type: ViewChild,
93
+ args: ['label', { static: true }]
94
+ }], label: [{
95
+ type: Input
96
+ }], tag: [{
97
+ type: Input
98
+ }], description: [{
99
+ type: Input
100
+ }], invalid: [{
101
+ type: Input
102
+ }], disabled: [{
103
+ type: Input
104
+ }], required: [{
105
+ type: Input
106
+ }], isDisabled: [{
107
+ type: HostBinding,
108
+ args: ['class.disabled']
109
+ }], isInvalid: [{
110
+ type: HostBinding,
111
+ args: ['class.invalid']
112
+ }], isRequired: [{
113
+ type: HostBinding,
114
+ args: ['class.required']
115
+ }] } });
29
116
 
30
117
  /**
31
118
  * Component rendering a simple catalog as form element.
@@ -137,310 +224,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
137
224
  type: Input
138
225
  }] } });
139
226
 
140
- class DatetimeComponent {
141
- constructor() {
142
- this.translate = inject(TranslateService);
143
- this.value = null;
144
- this.locale = this.translate.currentLang;
145
- /**
146
- * Whether or not to allow only values in the future (default: false)
147
- */
148
- this.onlyFutureDates = false;
149
- /**
150
- * Will prevent the input from being changed (default: false)
151
- */
152
- this.readonly = false;
153
- /**
154
- * Enables setting time as well (default: false)
155
- */
156
- this.withTime = false;
157
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
158
- this.propagateChange = (fn) => { };
159
- // eslint-disable-next-line @typescript-eslint/no-empty-function
160
- this.validationChange = () => { };
161
- this._setLabels();
162
- this.translate.onLangChange.subscribe((e) => (this.locale = e.lang));
227
+ /**
228
+ * Creates form input for number values.
229
+ *
230
+ * Implements `ControlValueAccessor` so it can be used within Angular forms.
231
+ *
232
+ * @example
233
+ * <yuv-number [scale]="2"></yuv-number>
234
+ *
235
+ */
236
+ class NumberComponent {
237
+ /**
238
+ * Number of decimal places
239
+ */
240
+ set scale(val) {
241
+ this._scale = Math.min(val || 0, 30);
163
242
  }
164
- _setLabels() {
165
- this.labels = {
166
- calendarApply: this.translate.instant('yuv.form.element.datetime.calendar.select'),
167
- calendarCancel: this.translate.instant('yuv.form.element.datetime.calendar.cancel'),
168
- shortcut: { today: this.translate.instant('yuv.form.element.datetime.calendar.today') }
169
- };
243
+ get scale() {
244
+ return this._scale;
170
245
  }
171
- writeValue(value) {
172
- if (typeof value === 'string') {
173
- value = new Date(value);
174
- this.propagateChange(value);
175
- }
176
- this.value = value || null;
246
+ /**
247
+ * Overall amount of digits allowed (including decimal places)
248
+ */
249
+ set precision(val) {
250
+ this._precision = Math.min(val || 100, 100);
177
251
  }
178
- registerOnChange(fn) {
179
- this.propagateChange = fn;
252
+ get precision() {
253
+ return this._precision;
180
254
  }
181
- registerOnValidatorChange(fn) {
182
- this.validationChange = fn;
255
+ /**
256
+ * Set to true to group number by pattern
257
+ */
258
+ set grouping(val) {
259
+ this._grouping = val ?? true;
183
260
  }
184
- // eslint-disable-next-line @typescript-eslint/no-empty-function
185
- registerOnTouched() { }
186
- onValueChange(e) {
187
- this.propagateChange(e);
261
+ get grouping() {
262
+ return this._grouping;
188
263
  }
189
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
190
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DatetimeComponent, isStandalone: true, selector: "yuv-datetime", inputs: { onlyFutureDates: "onlyFutureDates", readonly: "readonly", withTime: "withTime" }, providers: [
191
- {
192
- provide: NG_VALUE_ACCESSOR,
193
- useExisting: forwardRef(() => DatetimeComponent),
194
- multi: true
195
- }
196
- ], ngImport: i0, template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDatepickerModule }, { kind: "component", type: i2$1.Datepicker, selector: "yvc-datepicker", inputs: ["calendar", "readonly", "hour12", "locale", "labels", "withTime", "onlyFutureDates", "minDate", "maxDate", "disabled"] }] }); }
197
- }
198
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, decorators: [{
199
- type: Component,
200
- args: [{ selector: 'yuv-datetime', standalone: true, imports: [FormsModule, YvcDatepickerModule, DatetimeComponent], providers: [
201
- {
202
- provide: NG_VALUE_ACCESSOR,
203
- useExisting: forwardRef(() => DatetimeComponent),
204
- multi: true
205
- }
206
- ], template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"] }]
207
- }], ctorParameters: () => [], propDecorators: { onlyFutureDates: [{
208
- type: Input
209
- }], readonly: [{
210
- type: Input
211
- }], withTime: [{
212
- type: Input
213
- }] } });
214
-
215
- class DatetimeRangeComponent {
216
- constructor() {
217
- this.fb = inject(FormBuilder);
218
- /**
219
- * Enables setting time as well (default: false)
220
- */
221
- this.withTime = false;
264
+ /**
265
+ * The pattern to group number value by
266
+ */
267
+ set groupPattern(val) {
268
+ this._pattern = val;
269
+ }
270
+ get groupPattern() {
271
+ return this._pattern;
272
+ }
273
+ /**
274
+ * classification property adds some semantics to the value of this component.
275
+ * If you provide a value of `filesize` numbers typed into the control will be
276
+ * handled like file sizes (calculates differnt units)
277
+ */
278
+ set classifications(classifications) {
279
+ this.numberPipe =
280
+ classifications && classifications.includes(Classification.NUMBER_FILESIZE) ? new FileSizePipe(this.translate) : new LocaleNumberPipe(this.translate);
281
+ }
282
+ static betweenTwoNumbers(val, minVal, maxVal) {
283
+ const min = !Utils.isEmpty(minVal) ? minVal : -Infinity;
284
+ const max = !Utils.isEmpty(maxVal) ? maxVal : Infinity;
285
+ return val >= min && val <= max;
286
+ }
287
+ constructor(translate) {
288
+ this.translate = translate;
289
+ this.innerValue = null;
290
+ this._grouping = false;
291
+ this.validationErrors = [];
222
292
  /**
223
293
  * Will prevent the input from being changed (default: false)
224
294
  */
225
295
  this.readonly = false;
226
- this.operator = 'eq';
227
- this.rangeForm = this.fb.group({
228
- dateValue: [undefined, Validators.required],
229
- dateValueFrom: []
230
- });
231
- this._isValid = true;
232
- // options for search situation
233
- this.availableSearchOptions = [
234
- { label: OperatorLabel.EQUAL, value: Operator.EQUAL },
235
- { label: OperatorLabel.GREATER_OR_EQUAL, value: Operator.GREATER_OR_EQUAL },
236
- { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
237
- { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
238
- ];
239
- // the selected search option
240
- this.searchOption = this.availableSearchOptions[1].value;
241
296
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
242
297
  this.propagateChange = (_) => { };
243
- }
244
- writeValue(value) {
245
- if (value && (value.firstValue || value.secondValue)) {
246
- const match = this.availableSearchOptions.find((o) => o.value === value.operator);
247
- this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
248
- this.value = value;
249
- this.rangeForm.patchValue({
250
- dateValueFrom: value.secondValue && value.firstValue,
251
- dateValue: value.secondValue || value.firstValue
252
- });
253
- }
254
- else {
255
- this.searchOption = this.availableSearchOptions[0].value;
256
- this.value = undefined;
257
- this.rangeForm.reset();
258
- }
259
- }
260
- registerOnChange(fn) {
261
- this.propagateChange = fn;
262
- }
263
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
264
- registerOnTouched(fn) { }
265
- onValueChange() {
266
- const dateValue = this.rangeForm.value.dateValue || undefined;
267
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
268
- const dateValueFrom = this.rangeForm.value.dateValueFrom || undefined;
269
- if (dateValueFrom || dateValue) {
270
- this._isValid = this.rangeForm.valid && !!dateValueFrom && !!dateValue;
271
- this.value = !this._isValid
272
- ? // {
273
- // operator: this.searchOption,
274
- // firstValue: undefined,
275
- // secondValue: undefined
276
- // }
277
- undefined
278
- : {
279
- operator: this.searchOption,
280
- firstValue: dateValueFrom,
281
- secondValue: dateValue
282
- };
283
- }
284
- }
285
- else {
286
- this._isValid = this.rangeForm.valid;
287
- this.value = !this._isValid
288
- ? // {
289
- // operator: this.searchOption,
290
- // firstValue: undefined,
291
- // secondValue: undefined
292
- // }
293
- undefined
294
- : {
295
- operator: this.searchOption,
296
- firstValue: dateValue,
297
- secondValue: undefined
298
- };
299
- }
300
- this.propagateChange(this.value);
301
- }
302
- validate() {
303
- let err;
304
- if (this.searchOption === Operator.EQUAL) {
305
- err = {
306
- datecontrol: {
307
- valid: false
308
- }
309
- };
310
- }
311
- else {
312
- // make sure that on ranges, the first value is earlier than the last
313
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value && this.value.firstValue && this.value.secondValue) {
314
- this._isValid = new Date(this.value.firstValue).getTime() < new Date(this.value.secondValue).getTime();
315
- err = {
316
- daterangeorder: {
317
- valid: false
318
- }
319
- };
320
- }
321
- else {
322
- err = {
323
- daterange: {
324
- valid: false
325
- }
326
- };
327
- }
328
- }
329
- return this.situation === Situation.SEARCH || this._isValid ? null : err;
330
- }
331
- ngOnInit() {
332
- this.rangeForm.valueChanges.subscribe(() => this.onValueChange());
333
- }
334
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
335
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DatetimeRangeComponent, isStandalone: true, selector: "yuv-datetime-range", inputs: { withTime: "withTime", readonly: "readonly", operator: "operator", situation: "situation" }, providers: [
336
- {
337
- provide: NG_VALUE_ACCESSOR,
338
- useExisting: forwardRef(() => DatetimeRangeComponent),
339
- multi: true
340
- },
341
- {
342
- provide: NG_VALIDATORS,
343
- useExisting: forwardRef(() => DatetimeRangeComponent),
344
- multi: true
345
- }
346
- ], ngImport: i0, template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DatetimeComponent, selector: "yuv-datetime", inputs: ["onlyFutureDates", "readonly", "withTime"] }] }); }
347
- }
348
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, decorators: [{
349
- type: Component,
350
- args: [{ selector: 'yuv-datetime-range', standalone: true, imports: [CommonModule, FormsModule, YvcDropdownModule, ReactiveFormsModule, DatetimeComponent], providers: [
351
- {
352
- provide: NG_VALUE_ACCESSOR,
353
- useExisting: forwardRef(() => DatetimeRangeComponent),
354
- multi: true
355
- },
356
- {
357
- provide: NG_VALIDATORS,
358
- useExisting: forwardRef(() => DatetimeRangeComponent),
359
- multi: true
360
- }
361
- ], template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
362
- }], propDecorators: { withTime: [{
363
- type: Input
364
- }], readonly: [{
365
- type: Input
366
- }], operator: [{
367
- type: Input
368
- }], situation: [{
369
- type: Input
370
- }] } });
371
-
372
- /**
373
- * Creates form input for number values.
374
- *
375
- * Implements `ControlValueAccessor` so it can be used within Angular forms.
376
- *
377
- * @example
378
- * <yuv-number [scale]="2"></yuv-number>
379
- *
380
- */
381
- class NumberComponent {
382
- /**
383
- * Number of decimal places
384
- */
385
- set scale(val) {
386
- this._scale = Math.min(val || 0, 30);
387
- }
388
- get scale() {
389
- return this._scale;
390
- }
391
- /**
392
- * Overall amount of digits allowed (including decimal places)
393
- */
394
- set precision(val) {
395
- this._precision = Math.min(val || 100, 100);
396
- }
397
- get precision() {
398
- return this._precision;
399
- }
400
- /**
401
- * Set to true to group number by pattern
402
- */
403
- set grouping(val) {
404
- this._grouping = val ?? true;
405
- }
406
- get grouping() {
407
- return this._grouping;
408
- }
409
- /**
410
- * The pattern to group number value by
411
- */
412
- set groupPattern(val) {
413
- this._pattern = val;
414
- }
415
- get groupPattern() {
416
- return this._pattern;
417
- }
418
- /**
419
- * classification property adds some semantics to the value of this component.
420
- * If you provide a value of `filesize` numbers typed into the control will be
421
- * handled like file sizes (calculates differnt units)
422
- */
423
- set classifications(classifications) {
424
- this.numberPipe =
425
- classifications && classifications.includes(Classification.NUMBER_FILESIZE) ? new FileSizePipe(this.translate) : new LocaleNumberPipe(this.translate);
426
- }
427
- static betweenTwoNumbers(val, minVal, maxVal) {
428
- const min = !Utils.isEmpty(minVal) ? minVal : -Infinity;
429
- const max = !Utils.isEmpty(maxVal) ? maxVal : Infinity;
430
- return val >= min && val <= max;
431
- }
432
- constructor(translate) {
433
- this.translate = translate;
434
- this.innerValue = null;
435
- this._grouping = false;
436
- this.validationErrors = [];
437
- /**
438
- * Will prevent the input from being changed (default: false)
439
- */
440
- this.readonly = false;
441
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
442
- this.propagateChange = (_) => { };
443
- this.numberPipe = new LocaleNumberPipe(this.translate);
298
+ this.numberPipe = new LocaleNumberPipe(this.translate);
444
299
  }
445
300
  writeValue(value) {
446
301
  this.value = value != null ? value : null;
@@ -558,453 +413,924 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
558
413
  }] } });
559
414
 
560
415
  /**
561
- * Creates form input for ranges of numeric values.
416
+ * Creates form input for strings. Based on the input values different kinds of inputs will be generated.
562
417
  *
563
418
  * Implements `ControlValueAccessor` so it can be used within Angular forms.
564
419
  *
565
420
  * @example
566
- * <yuv-number-range [scale]="2"></yuv-number-range>
421
+ * <!-- string input validating input to be between 5 and 10 characters -->
422
+ * <yuv-string [minLength]="5" [maxLength]="10"></yuv-string>
423
+ *
424
+ * <!-- string input that only allow digits -->
425
+ * <yuv-string [regex]="[0-9]*"></yuv-string>
426
+ *
427
+ * <!-- string input rendering a large textarea -->
428
+ * <yuv-string [rows]="10"></yuv-string>
567
429
  *
568
430
  */
569
- class NumberRangeComponent {
431
+ class StringComponent {
570
432
  constructor() {
433
+ this.iconsService = inject(IconService);
434
+ this.elementRef = inject(ElementRef);
435
+ this.classifiytionIcons = {
436
+ email: this.iconsService.getIcon(ClassificationPrefix.EMAIL_ICON) || '',
437
+ url: this.iconsService.getIcon(ClassificationPrefix.URL_ICON) || '',
438
+ phone: this.iconsService.getIcon(ClassificationPrefix.PHONE_ICON) || ''
439
+ };
440
+ // provides all css variables defined by |yuuvis/comonents
441
+ this.fe = true;
571
442
  /**
572
- * Set to true to group number by pattern
443
+ * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
573
444
  */
574
- this.grouping = false;
445
+ this.multiselect = false;
575
446
  /**
576
447
  * Will prevent the input from being changed (default: false)
577
448
  */
578
449
  this.readonly = false;
579
450
  /**
580
- * classification property adds some semantics to the value of this component.
581
- * If you provide a value of `filesize` numbers typed into the control will be
582
- * handled like file sizes (calculates differnt units)
451
+ * Enable autofucus for the input (default: false)
583
452
  */
584
- this.classifications = [];
585
- this.rangeForm = new UntypedFormGroup({
586
- numberValue: new UntypedFormControl(),
587
- numberValueFrom: new UntypedFormControl()
588
- });
589
- this.isValid = true;
590
- // options for search situation
591
- this.availableSearchOptions = [
592
- { label: OperatorLabel.EQUAL, value: Operator.EQUAL },
593
- { label: OperatorLabel.GREATER_OR_EQUAL, value: Operator.GREATER_OR_EQUAL },
594
- { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
595
- { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
596
- ];
597
- // the selected search option
598
- this.searchOption = this.availableSearchOptions[1].value;
599
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
453
+ this.autofocus = false;
454
+ this.valid = false;
455
+ this.validationErrors = [];
456
+ this._classifications = [];
600
457
  this.propagateChange = (_) => { };
601
- this.rangeForm.valueChanges.forEach(() => {
602
- this.onValueChange();
603
- });
604
458
  }
605
- writeValue(value) {
606
- if (value && (value.firstValue != null || value.secondValue != null)) {
607
- const match = this.availableSearchOptions.find((o) => o.value === value.operator);
608
- this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
609
- this.value = value;
610
- if (value.secondValue == null) {
611
- this.rangeForm.setValue({
612
- numberValueFrom: null,
613
- numberValue: value.firstValue != null ? value.firstValue : null
614
- });
615
- }
616
- else {
617
- this.rangeForm.setValue({
618
- numberValueFrom: value.firstValue != null ? value.firstValue : null,
619
- numberValue: value.secondValue
620
- });
459
+ /**
460
+ * Additional semantics for the form element. Possible values are
461
+ * `email` (validates and creates a link to send an email once there
462
+ * is a valid email address) and `url` (validates and creates a link
463
+ * to an URL typed into the form element).
464
+ */
465
+ set classifications(c) {
466
+ this._classifications = c;
467
+ if (c && c.length) {
468
+ if (c.includes(Classification.STRING_EMAIL)) {
469
+ this.classify = {
470
+ hrefPrefix: ClassificationPrefix.EMAIL,
471
+ icon: this.classifiytionIcons.email
472
+ };
473
+ }
474
+ else if (c.includes(Classification.STRING_URL)) {
475
+ this.classify = {
476
+ hrefPrefix: ClassificationPrefix.URL,
477
+ icon: this.classifiytionIcons.url
478
+ };
479
+ }
480
+ else if (c.includes(Classification.STRING_PHONE)) {
481
+ this.classify = {
482
+ hrefPrefix: ClassificationPrefix.PHONE,
483
+ icon: this.classifiytionIcons.phone
484
+ };
621
485
  }
622
486
  }
623
- else {
624
- this.searchOption = this.availableSearchOptions[0].value;
625
- this.value = undefined;
626
- this.rangeForm.reset();
487
+ }
488
+ get classifications() {
489
+ return this._classifications;
490
+ }
491
+ propagate() {
492
+ this.propagateChange(this.value);
493
+ }
494
+ writeValue(value) {
495
+ if (Array.isArray(value)) {
496
+ value = value.filter((v) => typeof v === 'string' && v.trim().length > 0);
627
497
  }
498
+ this.formatedValue = Utils.formatMailTo(value, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
499
+ this.value = value || null;
628
500
  }
629
501
  registerOnChange(fn) {
630
502
  this.propagateChange = fn;
631
503
  }
632
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
633
- registerOnTouched(fn) { }
634
- onValueChange() {
635
- this.isValid = this.rangeForm.valid;
636
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
637
- this.isValid = this.rangeForm.valid && this.rangeForm.value.numberValueFrom != null && this.rangeForm.value.numberValue != null;
638
- this.value = !this.isValid
639
- ? {
640
- operator: this.searchOption,
641
- firstValue: undefined,
642
- secondValue: undefined
504
+ registerOnTouched() { }
505
+ onValueChange(val) {
506
+ this.maxEntryCountIfInvalid = undefined;
507
+ this.validationErrors = [];
508
+ if (Utils.isEmpty(val)) {
509
+ this.value = null;
510
+ this.propagate();
511
+ return;
512
+ }
513
+ const multiCheck = (check) => !!(this.multiselect ? val : [val]).find((v) => check(v));
514
+ // validate regular expression
515
+ if (this.regex && multiCheck((v) => !RegExp(this.regex).test(v))) {
516
+ this.validationErrors.push({ key: 'regex' });
517
+ }
518
+ // validate classification settings
519
+ if (this.classifications && this.classifications.length) {
520
+ this.classifications.forEach((c) => {
521
+ if (multiCheck((v) => !this.validateClassification(v, c))) {
522
+ this.validationErrors.push({ key: 'classification' + c });
643
523
  }
644
- : {
645
- operator: this.searchOption,
646
- firstValue: this.rangeForm.value.numberValueFrom,
647
- secondValue: this.rangeForm.value.numberValue
648
- };
524
+ });
525
+ }
526
+ // validate min length
527
+ if (!Utils.isEmpty(this.minLength) && multiCheck((v) => v.length < this.minLength)) {
528
+ this.validationErrors.push({ key: 'minlength', params: { minLength: this.minLength } });
529
+ }
530
+ // validate max length
531
+ if (!Utils.isEmpty(this.maxLength) && multiCheck((v) => v.length > this.maxLength)) {
532
+ this.validationErrors.push({ key: 'maxlength', params: { maxLength: this.maxLength } });
533
+ }
534
+ // validate invalid if only whitespaces
535
+ if (multiCheck((v) => v.length > 0 && !v.trim().length)) {
536
+ this.validationErrors.push({ key: 'onlyWhitespaces' });
537
+ }
538
+ if (this.validationErrors.length && this.multiselect && this.value) {
539
+ // Setting maxEntryCountIfInvalid to the actual length of the value array to prevent the user to add more entries.
540
+ this.maxEntryCountIfInvalid = this.value.length;
541
+ }
542
+ this.formatedValue = Utils.formatMailTo(val, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
543
+ this.propagate();
544
+ }
545
+ onBlur() {
546
+ if (this.multiselect) {
547
+ // add on blur
548
+ this.value.push('');
549
+ }
550
+ if (this.trimValue()) {
551
+ this.propagate();
552
+ }
553
+ }
554
+ /**
555
+ * Trims the current value and returns wether or not it has been trimmed
556
+ */
557
+ trimValue() {
558
+ if (this.value) {
559
+ if (this.multiselect) {
560
+ const lengthBefore = this.value.join('').length;
561
+ this.value = this.value.map((v) => v.trim());
562
+ return this.value.join('').length !== lengthBefore;
563
+ }
564
+ else {
565
+ const lengthBefore = this.value.length;
566
+ this.value = this.value.trim();
567
+ return this.value.length !== lengthBefore;
568
+ }
569
+ }
570
+ return false;
571
+ }
572
+ validateClassification(string, classification) {
573
+ if (this.situation === Situation.SEARCH) {
574
+ return true;
649
575
  }
650
576
  else {
651
- this.value = !this.isValid
652
- ? {
653
- operator: this.searchOption,
654
- firstValue: undefined,
655
- secondValue: undefined
656
- }
657
- : {
658
- operator: this.searchOption,
659
- firstValue: this.rangeForm.value.numberValue,
660
- secondValue: undefined
661
- };
577
+ let pattern;
578
+ if (classification === Classification.STRING_EMAIL) {
579
+ pattern =
580
+ /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
581
+ }
582
+ else if (classification === Classification.STRING_URL) {
583
+ pattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)?([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
584
+ }
585
+ else if (classification === Classification.STRING_PHONE) {
586
+ pattern = /^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-x\s\./0-9]*$/g;
587
+ }
588
+ return pattern ? pattern.test(string) : true;
662
589
  }
663
- this.propagateChange(this.value);
664
590
  }
665
- // returns null when valid else the validation object
591
+ /**
592
+ * returns null when valid else the validation object
593
+ */
666
594
  validate() {
667
- let err;
668
- if (this.searchOption === Operator.EQUAL) {
669
- err = { number: { valid: false } };
670
- }
671
- else if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value?.firstValue && this.value?.secondValue) {
672
- // make sure that on ranges, the first value is earlier than the last
673
- this.isValid = this.value.firstValue < this.value.secondValue;
674
- err = { numberrangeorder: { valid: false } };
595
+ if (this.validationErrors.length) {
596
+ this.valid = false;
597
+ return Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err }));
675
598
  }
676
599
  else {
677
- err = { numberrange: { valid: false } };
600
+ this.valid = true;
601
+ return null;
678
602
  }
679
- return this.isValid ? null : err;
680
603
  }
681
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
682
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NumberRangeComponent, isStandalone: true, selector: "yuv-number-range", inputs: { scale: "scale", precision: "precision", grouping: "grouping", pattern: "pattern", readonly: "readonly", classifications: "classifications", minValue: "minValue", maxValue: "maxValue" }, providers: [
604
+ ngAfterViewInit() {
605
+ if (this.autofocus) {
606
+ if (!this.multiselect) {
607
+ const el = this.elementRef.nativeElement.querySelector(this.rows && this.rows > 1 ? 'textarea' : 'input');
608
+ if (el)
609
+ el.focus();
610
+ }
611
+ }
612
+ }
613
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
614
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: StringComponent, isStandalone: true, selector: "yuv-string", inputs: { multiselect: "multiselect", rows: "rows", readonly: "readonly", autofocus: "autofocus", classifications: "classifications", situation: "situation", regex: "regex", minLength: "minLength", maxLength: "maxLength" }, host: { properties: { "class.yvc-form-element": "this.fe" } }, providers: [
683
615
  {
684
616
  provide: NG_VALUE_ACCESSOR,
685
- useExisting: forwardRef(() => NumberRangeComponent),
617
+ useExisting: forwardRef(() => StringComponent),
686
618
  multi: true
687
619
  },
688
620
  {
689
621
  provide: NG_VALIDATORS,
690
- useExisting: forwardRef(() => NumberRangeComponent),
622
+ useExisting: forwardRef(() => StringComponent),
691
623
  multi: true
692
624
  }
693
- ], ngImport: i0, template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
625
+ ], ngImport: i0, template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: YvcChipsModule }, { kind: "component", type: i2$1.Chips, selector: "yvc-chips", inputs: ["field", "placeholder", "max", "disabled", "addOnBlur"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
694
626
  }
695
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, decorators: [{
627
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, decorators: [{
696
628
  type: Component,
697
- args: [{ selector: 'yuv-number-range', standalone: true, imports: [CommonModule, NumberComponent, YvcDropdownModule, FormsModule, ReactiveFormsModule], providers: [
629
+ args: [{ selector: 'yuv-string', standalone: true, imports: [CommonModule, YvcChipsModule, YvcIconModule, FormsModule], providers: [
698
630
  {
699
631
  provide: NG_VALUE_ACCESSOR,
700
- useExisting: forwardRef(() => NumberRangeComponent),
632
+ useExisting: forwardRef(() => StringComponent),
701
633
  multi: true
702
634
  },
703
635
  {
704
636
  provide: NG_VALIDATORS,
705
- useExisting: forwardRef(() => NumberRangeComponent),
637
+ useExisting: forwardRef(() => StringComponent),
706
638
  multi: true
707
639
  }
708
- ], template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
709
- }], ctorParameters: () => [], propDecorators: { scale: [{
710
- type: Input
711
- }], precision: [{
712
- type: Input
713
- }], grouping: [{
640
+ ], template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"] }]
641
+ }], propDecorators: { fe: [{
642
+ type: HostBinding,
643
+ args: ['class.yvc-form-element']
644
+ }], multiselect: [{
714
645
  type: Input
715
- }], pattern: [{
646
+ }], rows: [{
716
647
  type: Input
717
648
  }], readonly: [{
718
649
  type: Input
650
+ }], autofocus: [{
651
+ type: Input
719
652
  }], classifications: [{
720
653
  type: Input
721
- }], minValue: [{
654
+ }], situation: [{
722
655
  type: Input
723
- }], maxValue: [{
656
+ }], regex: [{
657
+ type: Input
658
+ }], minLength: [{
659
+ type: Input
660
+ }], maxLength: [{
724
661
  type: Input
725
662
  }] } });
726
663
 
727
- /**
728
- * Creates form input for organisation values.
729
- * Implements `ControlValueAccessor` so it can be used within Angular forms.
730
- *
731
- * [Screenshot](../assets/images/yuv-organization.gif)
732
- *
733
- * @example
734
- * <yuv-organization [multiselect]="true"></yuv-organization>
735
- */
736
- class OrganizationComponent {
664
+ class EditTableDataComponent {
737
665
  constructor() {
738
- this.system = inject(SystemService);
739
- this.userService = inject(UserService);
740
- this.minLength = 2;
741
- this.icons = {
742
- organizationMulti: YUV_ICONS['group'],
743
- organization: YUV_ICONS['user']
666
+ this.#oRef = inject((YvcOverlayRef));
667
+ this.#fb = inject(FormBuilder);
668
+ this.#errorMassge = inject(ErrorMessagesService);
669
+ this.errorMassage = signal(null);
670
+ this.tableForm = this.#fb.group({});
671
+ this.isInnerTableForm = input(true);
672
+ this.formElement = this.#oRef.data?.formElement || {};
673
+ this.#elementData = this.#oRef.data?.elementData || {};
674
+ this.situation = this.#oRef.data?.situation || Situation.EDIT;
675
+ this.header = this.#oRef.data?.label || '';
676
+ this.adding = this.#oRef.data?.adding;
677
+ }
678
+ #oRef;
679
+ #fb;
680
+ #errorMassge;
681
+ #elementData;
682
+ cancel() {
683
+ if (this.#oRef)
684
+ this.#oRef.close();
685
+ }
686
+ submit() {
687
+ if (this.tableForm.valid && this.#oRef)
688
+ this.#oRef.close(this.tableForm.getRawValue());
689
+ }
690
+ ngOnInit() {
691
+ Object.values(this.formElement['elements']).forEach((element) => {
692
+ return this.tableForm.addControl(element.name, this.#fb.control({ value: '', disabled: element.readonly }, element.required ? Validators.required : null));
693
+ });
694
+ this.tableForm.setValidators(this.#globalErrorValidator());
695
+ this.#elementData && this.tableForm.patchValue(this.#elementData);
696
+ this.tableForm.valueChanges.subscribe((v) => {
697
+ this.errorMassage.set(this.tableForm.errors
698
+ ? Object.keys(this.tableForm.errors).map((key) => this.tableForm.errors && this.tableForm.errors[key]
699
+ ? Object.keys(this.tableForm.errors[key]).map((k) => ({ [key]: this.#errorMassge.getErrorLabel(k, key) }))
700
+ : null)
701
+ : null);
702
+ });
703
+ }
704
+ #globalErrorValidator() {
705
+ return (control) => {
706
+ const formGroup = control;
707
+ const errors = {};
708
+ Object.keys(formGroup.controls).forEach((key) => {
709
+ const control = formGroup.get(key);
710
+ if (control && control.invalid && control.dirty) {
711
+ const controlErrors = control.errors;
712
+ if (controlErrors) {
713
+ // Ignore 'required' error if there are more errors
714
+ if (Object.keys(controlErrors).length > 1 && controlErrors['required']) {
715
+ const { required, ...otherErrors } = controlErrors;
716
+ errors[key] = otherErrors;
717
+ }
718
+ else {
719
+ errors[key] = controlErrors;
720
+ }
721
+ }
722
+ }
723
+ });
724
+ return Object.keys(errors).length ? errors : null;
744
725
  };
745
- this.isValidInput = true;
726
+ }
727
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditTableDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
728
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: EditTableDataComponent, isStandalone: true, selector: "yuv-edit-table-data", inputs: { isInnerTableForm: { classPropertyName: "isInnerTableForm", publicName: "isInnerTableForm", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
729
+ {
730
+ provide: NG_VALUE_ACCESSOR,
731
+ useExisting: forwardRef(() => EditTableDataComponent),
732
+ multi: true
733
+ }
734
+ ], ngImport: i0, template: "<header>\n <h2>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n</header>\n\n<div [formGroup]=\"tableForm\">\n @for (element of formElement['elements']; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-form-input\n [label]=\"element.label\"\n [required]=\"element.required\"\n [invalid]=\"false\"\n [disabled]=\"element.readonly\"\n [invalid]=\"!tableForm.get(element.label)?.valid && tableForm.get(element.label)?.dirty\"\n >\n @switch (element.type) {\n @case ('string') {\n <yuv-string\n [situation]=\"situation\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n [multiselect]=\"element.cardinality === 'multi' || situation === 'SEARCH'\"\n [rows]=\"element.rows\"\n [classifications]=\"element.classifications\"\n [regex]=\"element.regex\"\n [readonly]=\"element.readonly\"\n [minLength]=\"element.minLength\"\n [maxLength]=\"element.maxLength\"\n >\n </yuv-string>\n }\n @case ('decimal') {\n <yuv-number\n [readonly]=\"element.readonly\"\n [precision]=\"element.precision\"\n [scale]=\"element.scale\"\n [pattern]=\"element.pattern\"\n [grouping]=\"element.grouping\"\n [minValue]=\"element.minValue\"\n [maxValue]=\"element.maxValue\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n ></yuv-number>\n }\n @default {\n <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" />\n }\n }\n <!-- <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" /> -->\n </yuv-form-input>\n @let errorsGroup = errorMassage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.label] }}\n }\n }\n </div>\n }\n </div>\n }\n <footer>\n <button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;padding:var(--app-pane-padding)}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}:host footer{display:flex;justify-content:end;gap:var(--app-pane-padding);margin-block-start:var(--app-pane-padding)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormInputComponent, selector: "yuv-form-input", inputs: ["label", "tag", "description", "invalid", "disabled", "required"] }, { kind: "component", type: StringComponent, selector: "yuv-string", inputs: ["multiselect", "rows", "readonly", "autofocus", "classifications", "situation", "regex", "minLength", "maxLength"] }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
735
+ }
736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditTableDataComponent, decorators: [{
737
+ type: Component,
738
+ args: [{ selector: 'yuv-edit-table-data', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormInputComponent, StringComponent, NumberComponent, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
739
+ {
740
+ provide: NG_VALUE_ACCESSOR,
741
+ useExisting: forwardRef(() => EditTableDataComponent),
742
+ multi: true
743
+ }
744
+ ], template: "<header>\n <h2>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n</header>\n\n<div [formGroup]=\"tableForm\">\n @for (element of formElement['elements']; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-form-input\n [label]=\"element.label\"\n [required]=\"element.required\"\n [invalid]=\"false\"\n [disabled]=\"element.readonly\"\n [invalid]=\"!tableForm.get(element.label)?.valid && tableForm.get(element.label)?.dirty\"\n >\n @switch (element.type) {\n @case ('string') {\n <yuv-string\n [situation]=\"situation\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n [multiselect]=\"element.cardinality === 'multi' || situation === 'SEARCH'\"\n [rows]=\"element.rows\"\n [classifications]=\"element.classifications\"\n [regex]=\"element.regex\"\n [readonly]=\"element.readonly\"\n [minLength]=\"element.minLength\"\n [maxLength]=\"element.maxLength\"\n >\n </yuv-string>\n }\n @case ('decimal') {\n <yuv-number\n [readonly]=\"element.readonly\"\n [precision]=\"element.precision\"\n [scale]=\"element.scale\"\n [pattern]=\"element.pattern\"\n [grouping]=\"element.grouping\"\n [minValue]=\"element.minValue\"\n [maxValue]=\"element.maxValue\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n ></yuv-number>\n }\n @default {\n <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" />\n }\n }\n <!-- <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" /> -->\n </yuv-form-input>\n @let errorsGroup = errorMassage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.label] }}\n }\n }\n </div>\n }\n </div>\n }\n <footer>\n <button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;padding:var(--app-pane-padding)}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}:host footer{display:flex;justify-content:end;gap:var(--app-pane-padding);margin-block-start:var(--app-pane-padding)}\n"] }]
745
+ }] });
746
+
747
+ var DataGridSizeType;
748
+ (function (DataGridSizeType) {
749
+ DataGridSizeType["SMALL"] = "small";
750
+ DataGridSizeType["MEDIUM"] = "medium";
751
+ DataGridSizeType["LARGE"] = "large";
752
+ DataGridSizeType["XLARGE"] = "extra-large";
753
+ DataGridSizeType["AUTO"] = "auto";
754
+ })(DataGridSizeType || (DataGridSizeType = {}));
755
+
756
+ const CDK_IMPORT = [CdkMenu, CdkTableModule, CdkMenuTrigger, CdkMenuItem];
757
+ class DataGridComponent {
758
+ constructor() {
759
+ this.#overlay = inject(YvcOverlayService);
760
+ this.#clipboardService = inject(ClipboardService);
761
+ this.#decimalPipe = inject(DecimalPipe);
762
+ this.trnaslate = inject(TranslateService);
763
+ this.situation = input(Situation.EDIT);
764
+ this.formElement = input(undefined);
765
+ this.formControl = input(undefined);
766
+ this.classifications = input([]);
767
+ this.readonly = input(false);
768
+ this.size = input(DataGridSizeType.AUTO);
769
+ this.displayedColumns = signal([]);
770
+ this.displayedColumnsWithActions = signal([]);
771
+ this.dataSource = signal([]);
772
+ this.tableLabel = computed(() => this.formElement()?.['label'] ?? '');
773
+ this.selectedRow = signal(null);
774
+ this.initalTableUpdate = true;
775
+ this.icons = {
776
+ add: YUV_ICONS.add,
777
+ more: YUV_ICONS.more
778
+ };
779
+ this.#loadData = effect(() => {
780
+ const formElement = this.formElement();
781
+ untracked(() => formElement && this.#updateTable(formElement['elements'], formElement['value'] || []));
782
+ });
783
+ this.#sourceData = effect(() => {
784
+ const dataSource = this.dataSource();
785
+ !this.initalTableUpdate && this.writeValue(dataSource.filter((row) => !row.isAddRow));
786
+ this.initalTableUpdate = false;
787
+ });
788
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
789
+ this.propagateChange = (fn) => { };
790
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
791
+ this.validationChange = () => { };
792
+ }
793
+ #overlay;
794
+ #clipboardService;
795
+ #decimalPipe;
796
+ #loadData;
797
+ #sourceData;
798
+ #openEditOverlay(elementData, adding = false) {
799
+ return this.#overlay
800
+ .open(EditTableDataComponent, {
801
+ formElement: {
802
+ ...this.formElement()
803
+ },
804
+ elementData,
805
+ situation: this.situation(),
806
+ adding,
807
+ label: this.tableLabel()
808
+ })
809
+ .afterClosed$.pipe(map((result) => result.data));
810
+ }
811
+ copyLine(element) {
812
+ this.#clipboardService.addToNavigatorClipBoard(JSON.stringify(element));
813
+ }
814
+ onMenuTriggert(element) {
815
+ this.selectedRow.set(element);
816
+ }
817
+ editRow(element) {
818
+ this.selectedRow.set(element);
819
+ this.#openEditOverlay(element).subscribe((result) => {
820
+ if (result) {
821
+ const updatedData = this.dataSource().map((item) => (JSON.stringify(item) === JSON.stringify(element) ? result : item));
822
+ const formElement = this.formElement();
823
+ formElement && this.#updateTable(formElement['elements'], [...updatedData]);
824
+ }
825
+ this.selectedRow.set(null);
826
+ });
827
+ }
828
+ addRow() {
829
+ this.#openEditOverlay(null, true).subscribe((result) => {
830
+ const currentData = this.dataSource();
831
+ const data = [...currentData];
832
+ result && data.push(result);
833
+ const formElement = this.formElement();
834
+ formElement && this.#updateTable(formElement['elements'], data);
835
+ });
836
+ }
837
+ removeRow(element) {
838
+ const updatedData = this.dataSource().filter((item) => JSON.stringify(item) !== JSON.stringify(element));
839
+ const formElement = this.formElement();
840
+ formElement && this.#updateTable(formElement['elements'], updatedData);
841
+ }
842
+ #cellor(element, value) {
843
+ switch (element.type) {
844
+ case 'string':
845
+ return value;
846
+ break;
847
+ case 'decimal':
848
+ return this.#decimalPipe.transform(value, '1.2-4', this.trnaslate.currentLang);
849
+ break;
850
+ default:
851
+ return value;
852
+ break;
853
+ }
854
+ }
855
+ #updateTable(elements, data = []) {
856
+ if (elements.length > 0) {
857
+ this.displayedColumns.set(elements.reduce((acc, el) => {
858
+ acc.push({
859
+ columnDef: el.label,
860
+ header: el.label,
861
+ cell: (element) => (element.isAddRow ? '' : this.#cellor(el, element[el.label]))
862
+ });
863
+ return acc;
864
+ }, []));
865
+ }
866
+ else {
867
+ this.displayedColumns.set([]);
868
+ }
869
+ this.displayedColumnsWithActions.set([...this.displayedColumns().map((col) => col.columnDef), 'actions']);
870
+ this.dataSource.set(data);
871
+ }
872
+ writeValue(obj) {
873
+ this.propagateChange(obj);
874
+ }
875
+ registerOnChange(fn) {
876
+ this.propagateChange = fn;
877
+ }
878
+ registerOnTouched(fn) {
879
+ this.validationChange = fn;
880
+ }
881
+ setDisabledState(isDisabled) {
882
+ // console.log('setDisabledState: ', isDisabled);
883
+ }
884
+ onValueChange(e) {
885
+ this.propagateChange(e);
886
+ }
887
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
888
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", 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: { classAttribute: "yuv-data-grid" }, providers: [
889
+ {
890
+ provide: NG_VALUE_ACCESSOR,
891
+ useExisting: forwardRef(() => DataGridComponent),
892
+ multi: true
893
+ },
894
+ DecimalPipe
895
+ ], ngImport: i0, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button (click)=\"addRow()\" aria-label=\"Add Row\" class=\"table-options-add-row\">\n <yvc-icon [svg]=\"icons.add\"></yvc-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n aria-label=\"Edit Row\"\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <yvc-icon [svg]=\"icons.more\"></yvc-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--panel-divider-color)}:host header{display:flex;justify-content:space-between;background-color:var(--panel-background-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--panel-divider-color);border-right:1px solid var(--panel-divider-color);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--panel-background-grey);border-bottom:1px solid var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--text-color-hint)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;z-index:1;background-color:var(--panel-background-grey)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--panel-background);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--panel-background);border:1px solid var(--panel-divider-color);padding:calc(var(--app-pane-padding) / 6) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--panel-divider-color)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}.table-options-menu .table-options-menu-item:active{background-color:var(--item-focus-border-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "directive", type: CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "ngmodule", type: CdkTableModule }, { kind: "component", type: i4.CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: i4.CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "directive", type: i4.CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: i4.CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: i4.CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: i4.CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "component", type: i4.CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: i4.CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "component", type: i4.CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "directive", type: i4.CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
896
+ }
897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataGridComponent, decorators: [{
898
+ type: Component,
899
+ args: [{ selector: 'yuv-data-grid', standalone: true, imports: [CommonModule, NgClass, TranslateModule, YvcIconModule, ...CDK_IMPORT], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
900
+ {
901
+ provide: NG_VALUE_ACCESSOR,
902
+ useExisting: forwardRef(() => DataGridComponent),
903
+ multi: true
904
+ },
905
+ DecimalPipe
906
+ ], host: {
907
+ class: 'yuv-data-grid'
908
+ }, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button (click)=\"addRow()\" aria-label=\"Add Row\" class=\"table-options-add-row\">\n <yvc-icon [svg]=\"icons.add\"></yvc-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n aria-label=\"Edit Row\"\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <yvc-icon [svg]=\"icons.more\"></yvc-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--panel-divider-color)}:host header{display:flex;justify-content:space-between;background-color:var(--panel-background-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--panel-divider-color);border-right:1px solid var(--panel-divider-color);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--panel-background-grey);border-bottom:1px solid var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--text-color-hint)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;z-index:1;background-color:var(--panel-background-grey)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--panel-background);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--panel-background);border:1px solid var(--panel-divider-color);padding:calc(var(--app-pane-padding) / 6) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--panel-divider-color)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}.table-options-menu .table-options-menu-item:active{background-color:var(--item-focus-border-color)}\n"] }]
909
+ }] });
910
+
911
+ class DatetimeComponent {
912
+ constructor() {
913
+ this.translate = inject(TranslateService$1);
746
914
  this.value = null;
747
- this._innerValue = [];
748
- this.autocompleteRes = [];
749
- this.filterRoles = [];
915
+ this.locale = this.translate.currentLang;
916
+ /**
917
+ * Whether or not to allow only values in the future (default: false)
918
+ */
919
+ this.onlyFutureDates = false;
920
+ /**
921
+ * Will prevent the input from being changed (default: false)
922
+ */
923
+ this.readonly = false;
924
+ /**
925
+ * Enables setting time as well (default: false)
926
+ */
927
+ this.withTime = false;
928
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
929
+ this.propagateChange = (fn) => { };
930
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
931
+ this.validationChange = () => { };
932
+ this._setLabels();
933
+ this.translate.onLangChange.subscribe((e) => (this.locale = e.lang));
934
+ }
935
+ _setLabels() {
936
+ this.labels = {
937
+ calendarApply: this.translate.instant('yuv.form.element.datetime.calendar.select'),
938
+ calendarCancel: this.translate.instant('yuv.form.element.datetime.calendar.cancel'),
939
+ shortcut: { today: this.translate.instant('yuv.form.element.datetime.calendar.today') }
940
+ };
941
+ }
942
+ writeValue(value) {
943
+ if (typeof value === 'string') {
944
+ value = new Date(value);
945
+ this.propagateChange(value);
946
+ }
947
+ this.value = value || null;
948
+ }
949
+ registerOnChange(fn) {
950
+ this.propagateChange = fn;
951
+ }
952
+ registerOnValidatorChange(fn) {
953
+ this.validationChange = fn;
954
+ }
955
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
956
+ registerOnTouched() { }
957
+ onValueChange(e) {
958
+ this.propagateChange(e);
959
+ }
960
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
961
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DatetimeComponent, isStandalone: true, selector: "yuv-datetime", inputs: { onlyFutureDates: "onlyFutureDates", readonly: "readonly", withTime: "withTime" }, providers: [
962
+ {
963
+ provide: NG_VALUE_ACCESSOR,
964
+ useExisting: forwardRef(() => DatetimeComponent),
965
+ multi: true
966
+ }
967
+ ], ngImport: i0, template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDatepickerModule }, { kind: "component", type: i2$2.Datepicker, selector: "yvc-datepicker", inputs: ["calendar", "readonly", "hour12", "locale", "labels", "withTime", "onlyFutureDates", "minDate", "maxDate", "disabled"] }] }); }
968
+ }
969
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, decorators: [{
970
+ type: Component,
971
+ args: [{ selector: 'yuv-datetime', standalone: true, imports: [FormsModule, YvcDatepickerModule, DatetimeComponent], providers: [
972
+ {
973
+ provide: NG_VALUE_ACCESSOR,
974
+ useExisting: forwardRef(() => DatetimeComponent),
975
+ multi: true
976
+ }
977
+ ], template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"] }]
978
+ }], ctorParameters: () => [], propDecorators: { onlyFutureDates: [{
979
+ type: Input
980
+ }], readonly: [{
981
+ type: Input
982
+ }], withTime: [{
983
+ type: Input
984
+ }] } });
985
+
986
+ class DatetimeRangeComponent {
987
+ constructor() {
988
+ this.fb = inject(FormBuilder);
989
+ /**
990
+ * Enables setting time as well (default: false)
991
+ */
992
+ this.withTime = false;
993
+ /**
994
+ * Will prevent the input from being changed (default: false)
995
+ */
996
+ this.readonly = false;
997
+ this.operator = 'eq';
998
+ this.rangeForm = this.fb.group({
999
+ dateValue: [undefined, Validators.required],
1000
+ dateValueFrom: []
1001
+ });
1002
+ this._isValid = true;
1003
+ // options for search situation
1004
+ this.availableSearchOptions = [
1005
+ { label: OperatorLabel.EQUAL, value: Operator.EQUAL },
1006
+ { label: OperatorLabel.GREATER_OR_EQUAL, value: Operator.GREATER_OR_EQUAL },
1007
+ { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
1008
+ { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
1009
+ ];
1010
+ // the selected search option
1011
+ this.searchOption = this.availableSearchOptions[1].value;
1012
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1013
+ this.propagateChange = (_) => { };
1014
+ }
1015
+ writeValue(value) {
1016
+ if (value && (value.firstValue || value.secondValue)) {
1017
+ const match = this.availableSearchOptions.find((o) => o.value === value.operator);
1018
+ this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
1019
+ this.value = value;
1020
+ this.rangeForm.patchValue({
1021
+ dateValueFrom: value.secondValue && value.firstValue,
1022
+ dateValue: value.secondValue || value.firstValue
1023
+ });
1024
+ }
1025
+ else {
1026
+ this.searchOption = this.availableSearchOptions[0].value;
1027
+ this.value = undefined;
1028
+ this.rangeForm.reset();
1029
+ }
1030
+ }
1031
+ registerOnChange(fn) {
1032
+ this.propagateChange = fn;
1033
+ }
1034
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1035
+ registerOnTouched(fn) { }
1036
+ onValueChange() {
1037
+ const dateValue = this.rangeForm.value.dateValue || undefined;
1038
+ if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
1039
+ const dateValueFrom = this.rangeForm.value.dateValueFrom || undefined;
1040
+ if (dateValueFrom || dateValue) {
1041
+ this._isValid = this.rangeForm.valid && !!dateValueFrom && !!dateValue;
1042
+ this.value = !this._isValid
1043
+ ? // {
1044
+ // operator: this.searchOption,
1045
+ // firstValue: undefined,
1046
+ // secondValue: undefined
1047
+ // }
1048
+ undefined
1049
+ : {
1050
+ operator: this.searchOption,
1051
+ firstValue: dateValueFrom,
1052
+ secondValue: dateValue
1053
+ };
1054
+ }
1055
+ }
1056
+ else {
1057
+ this._isValid = this.rangeForm.valid;
1058
+ this.value = !this._isValid
1059
+ ? // {
1060
+ // operator: this.searchOption,
1061
+ // firstValue: undefined,
1062
+ // secondValue: undefined
1063
+ // }
1064
+ undefined
1065
+ : {
1066
+ operator: this.searchOption,
1067
+ firstValue: dateValue,
1068
+ secondValue: undefined
1069
+ };
1070
+ }
1071
+ this.propagateChange(this.value);
1072
+ }
1073
+ validate() {
1074
+ let err;
1075
+ if (this.searchOption === Operator.EQUAL) {
1076
+ err = {
1077
+ datecontrol: {
1078
+ valid: false
1079
+ }
1080
+ };
1081
+ }
1082
+ else {
1083
+ // make sure that on ranges, the first value is earlier than the last
1084
+ if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value && this.value.firstValue && this.value.secondValue) {
1085
+ this._isValid = new Date(this.value.firstValue).getTime() < new Date(this.value.secondValue).getTime();
1086
+ err = {
1087
+ daterangeorder: {
1088
+ valid: false
1089
+ }
1090
+ };
1091
+ }
1092
+ else {
1093
+ err = {
1094
+ daterange: {
1095
+ valid: false
1096
+ }
1097
+ };
1098
+ }
1099
+ }
1100
+ return this.situation === Situation.SEARCH || this._isValid ? null : err;
1101
+ }
1102
+ ngOnInit() {
1103
+ this.rangeForm.valueChanges.subscribe(() => this.onValueChange());
1104
+ }
1105
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1106
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DatetimeRangeComponent, isStandalone: true, selector: "yuv-datetime-range", inputs: { withTime: "withTime", readonly: "readonly", operator: "operator", situation: "situation" }, providers: [
1107
+ {
1108
+ provide: NG_VALUE_ACCESSOR,
1109
+ useExisting: forwardRef(() => DatetimeRangeComponent),
1110
+ multi: true
1111
+ },
1112
+ {
1113
+ provide: NG_VALIDATORS,
1114
+ useExisting: forwardRef(() => DatetimeRangeComponent),
1115
+ multi: true
1116
+ }
1117
+ ], ngImport: i0, template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DatetimeComponent, selector: "yuv-datetime", inputs: ["onlyFutureDates", "readonly", "withTime"] }] }); }
1118
+ }
1119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, decorators: [{
1120
+ type: Component,
1121
+ args: [{ selector: 'yuv-datetime-range', standalone: true, imports: [CommonModule, FormsModule, YvcDropdownModule, ReactiveFormsModule, DatetimeComponent], providers: [
1122
+ {
1123
+ provide: NG_VALUE_ACCESSOR,
1124
+ useExisting: forwardRef(() => DatetimeRangeComponent),
1125
+ multi: true
1126
+ },
1127
+ {
1128
+ provide: NG_VALIDATORS,
1129
+ useExisting: forwardRef(() => DatetimeRangeComponent),
1130
+ multi: true
1131
+ }
1132
+ ], template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
1133
+ }], propDecorators: { withTime: [{
1134
+ type: Input
1135
+ }], readonly: [{
1136
+ type: Input
1137
+ }], operator: [{
1138
+ type: Input
1139
+ }], situation: [{
1140
+ type: Input
1141
+ }] } });
1142
+
1143
+ /**
1144
+ * Creates form input for ranges of numeric values.
1145
+ *
1146
+ * Implements `ControlValueAccessor` so it can be used within Angular forms.
1147
+ *
1148
+ * @example
1149
+ * <yuv-number-range [scale]="2"></yuv-number-range>
1150
+ *
1151
+ */
1152
+ class NumberRangeComponent {
1153
+ constructor() {
750
1154
  /**
751
- * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
1155
+ * Set to true to group number by pattern
752
1156
  */
753
- this.multiselect = false;
1157
+ this.grouping = false;
754
1158
  /**
755
1159
  * Will prevent the input from being changed (default: false)
756
1160
  */
757
1161
  this.readonly = false;
758
1162
  /**
759
- * Set this to true and the component will try to gain focus once it has been rendered.
760
- * Notice that this is not reliable. If there are any other components that are rendered
761
- * later and also try to be focused, they will 'win', because there can only be one focus.
762
- */
763
- this.autofocus = false;
764
- /**
765
- * Will attch the overlay to this HTMLelement
766
- */
767
- this.appendTo = null;
768
- /**
769
- * Whether or not to exclude the current user from autocomplete result
770
- */
771
- this.excludeMe = false;
772
- /**
773
- * Whether or not the emitted value should be an object containing id and title
774
- * or, if set to false only the ID
1163
+ * classification property adds some semantics to the value of this component.
1164
+ * If you provide a value of `filesize` numbers typed into the control will be
1165
+ * handled like file sizes (calculates differnt units)
775
1166
  */
776
- this.withMetadata = input(false);
777
- this.userSelect = new EventEmitter();
778
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1167
+ this.classifications = [];
1168
+ this.rangeForm = new UntypedFormGroup({
1169
+ numberValue: new UntypedFormControl(),
1170
+ numberValueFrom: new UntypedFormControl()
1171
+ });
1172
+ this.isValid = true;
1173
+ // options for search situation
1174
+ this.availableSearchOptions = [
1175
+ { label: OperatorLabel.EQUAL, value: Operator.EQUAL },
1176
+ { label: OperatorLabel.GREATER_OR_EQUAL, value: Operator.GREATER_OR_EQUAL },
1177
+ { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
1178
+ { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
1179
+ ];
1180
+ // the selected search option
1181
+ this.searchOption = this.availableSearchOptions[1].value;
1182
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
779
1183
  this.propagateChange = (_) => { };
780
- }
781
- set innerValue(iv) {
782
- this._innerValue = iv || [];
783
- this.userSelect.emit(this._innerValue);
784
- }
785
- get innerValue() {
786
- return this._innerValue;
787
- }
788
- // prevent ENTER from being propagated, because the component could be located
789
- // inside some other component that also relys on ENTER
790
- onKeydownHandler(event) {
791
- event.stopPropagation();
792
- }
793
- get _inputDisabled() {
794
- return !this.multiselect && this.innerValue?.length === 1;
795
- }
796
- set classifications(c) {
797
- this._classifications = c;
798
- if (c?.length) {
799
- const classifications = this.system.getClassifications(c);
800
- if (classifications.has(Classification.STRING_ORGANIZATION)) {
801
- const options = classifications.get(Classification.STRING_ORGANIZATION).options;
802
- this.filterRoles = options;
803
- }
804
- }
805
- else {
806
- this.filterRoles = [];
807
- }
808
- }
809
- get classifications() {
810
- return this._classifications;
1184
+ this.rangeForm.valueChanges.forEach(() => {
1185
+ this.onValueChange();
1186
+ });
811
1187
  }
812
1188
  writeValue(value) {
813
- if (value) {
1189
+ if (value && (value.firstValue != null || value.secondValue != null)) {
1190
+ const match = this.availableSearchOptions.find((o) => o.value === value.operator);
1191
+ this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
814
1192
  this.value = value;
815
- this.resolveFn(value);
1193
+ if (value.secondValue == null) {
1194
+ this.rangeForm.setValue({
1195
+ numberValueFrom: null,
1196
+ numberValue: value.firstValue != null ? value.firstValue : null
1197
+ });
1198
+ }
1199
+ else {
1200
+ this.rangeForm.setValue({
1201
+ numberValueFrom: value.firstValue != null ? value.firstValue : null,
1202
+ numberValue: value.secondValue
1203
+ });
1204
+ }
816
1205
  }
817
1206
  else {
818
- this.value = null;
819
- this.innerValue = [];
1207
+ this.searchOption = this.availableSearchOptions[0].value;
1208
+ this.value = undefined;
1209
+ this.rangeForm.reset();
820
1210
  }
821
1211
  }
822
1212
  registerOnChange(fn) {
823
1213
  this.propagateChange = fn;
824
1214
  }
825
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1215
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
826
1216
  registerOnTouched(fn) { }
827
- propagate() {
828
- this.propagateChange(this.#getPropagateValue());
829
- }
830
- #getPropagateValue() {
831
- return this.multiselect
832
- ? this.withMetadata()
833
- ? this.value
834
- ? this._innerValue.map((v) => ({
835
- id: v.id,
836
- title: v.title
837
- }))
838
- : this.value
839
- : this.value
840
- : this.withMetadata()
841
- ? this.value
842
- ? {
843
- id: this._innerValue[0].id,
844
- title: this._innerValue[0].title
845
- }
846
- : this.value
847
- : this.value;
848
- }
849
- focusInput() {
850
- this.autoCompleteInput.focusInput();
851
- }
852
- resolveFn(value) {
853
- const map = (value instanceof Array ? value : [value]).map((v) => {
854
- const match = this.innerValue.find((iv) => iv.id === v);
855
- return match
856
- ? of(match)
857
- : this.userService.getUserById(v).pipe(catchError(() => of(new YuvUser({
858
- id: v,
859
- title: v,
860
- image: null
861
- }, undefined))));
862
- });
863
- return forkJoin(map).subscribe((data) => {
864
- this.innerValue = data;
865
- // setTimeout(() => this.autoCompleteInput.cd.markForCheck());
866
- });
867
- }
868
- autocompleteFn(query) {
869
- if (query.length >= this.minLength) {
870
- this.userService.queryUser(query, this.excludeMe, this.filterRoles).subscribe({
871
- next: (users) => {
872
- this.autocompleteRes = users.filter((user) => !this.innerValue.some((value) => value.id === user.id));
873
- this.propagateValidity(this.autocompleteRes.length > 0);
874
- },
875
- error: () => {
876
- this.autocompleteRes = [];
877
- this.propagateValidity(this.autocompleteRes.length > 0);
1217
+ onValueChange() {
1218
+ this.isValid = this.rangeForm.valid;
1219
+ if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
1220
+ this.isValid = this.rangeForm.valid && this.rangeForm.value.numberValueFrom != null && this.rangeForm.value.numberValue != null;
1221
+ this.value = !this.isValid
1222
+ ? {
1223
+ operator: this.searchOption,
1224
+ firstValue: undefined,
1225
+ secondValue: undefined
878
1226
  }
879
- });
1227
+ : {
1228
+ operator: this.searchOption,
1229
+ firstValue: this.rangeForm.value.numberValueFrom,
1230
+ secondValue: this.rangeForm.value.numberValue
1231
+ };
880
1232
  }
881
1233
  else {
882
- this.autocompleteRes = [];
1234
+ this.value = !this.isValid
1235
+ ? {
1236
+ operator: this.searchOption,
1237
+ firstValue: undefined,
1238
+ secondValue: undefined
1239
+ }
1240
+ : {
1241
+ operator: this.searchOption,
1242
+ firstValue: this.rangeForm.value.numberValue,
1243
+ secondValue: undefined
1244
+ };
883
1245
  }
1246
+ this.propagateChange(this.value);
884
1247
  }
885
1248
  // returns null when valid else the validation object
886
1249
  validate() {
887
- return this.isValidInput ? null : { empty: { valid: false } };
888
- }
889
- propagateValidity(valid = true) {
890
- if (this.isValidInput !== valid) {
891
- this.isValidInput = valid;
892
- this.propagate();
1250
+ let err;
1251
+ if (this.searchOption === Operator.EQUAL) {
1252
+ err = { number: { valid: false } };
893
1253
  }
894
- }
895
- // handle selection changes to the model
896
- onSelect() {
897
- if (this.multiselect) {
898
- this.value = this.innerValue.map((v) => v.id);
1254
+ else if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value?.firstValue && this.value?.secondValue) {
1255
+ // make sure that on ranges, the first value is earlier than the last
1256
+ this.isValid = this.value.firstValue < this.value.secondValue;
1257
+ err = { numberrangeorder: { valid: false } };
899
1258
  }
900
1259
  else {
901
- // internal autocomplete control is always set to multiselect
902
- // so the resolved value is always an array
903
- this.innerValue = this.innerValue.slice(-1);
904
- this.value = this.innerValue[0].id;
905
- }
906
- this.propagate();
907
- }
908
- // handle selection changes to the model
909
- onUnselect(value) {
910
- this.innerValue = this.innerValue.filter((v) => v.id !== value.id);
911
- const _value = this.innerValue.map((v) => v.id);
912
- this.value = this.multiselect ? _value : null;
913
- if (!this.multiselect) {
914
- this.clearInnerInput();
1260
+ err = { numberrange: { valid: false } };
915
1261
  }
916
- this.propagate();
917
- }
918
- onAutoCompleteBlur() {
919
- this.clearInnerInput();
920
- }
921
- clearInnerInput() {
922
- this.autoCompleteInput.clearInput();
1262
+ return this.isValid ? null : err;
923
1263
  }
924
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
925
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: OrganizationComponent, isStandalone: true, selector: "yuv-organization", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, situation: { classPropertyName: "situation", publicName: "situation", isSignal: false, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: false, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: false, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: false, isRequired: false, transformFunction: null }, excludeMe: { classPropertyName: "excludeMe", publicName: "excludeMe", isSignal: false, isRequired: false, transformFunction: null }, withMetadata: { classPropertyName: "withMetadata", publicName: "withMetadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userSelect: "userSelect" }, host: { listeners: { "keydown.enter": "onKeydownHandler($event)" }, properties: { "class.inputDisabled": "this._inputDisabled" } }, providers: [
1264
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1265
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NumberRangeComponent, isStandalone: true, selector: "yuv-number-range", inputs: { scale: "scale", precision: "precision", grouping: "grouping", pattern: "pattern", readonly: "readonly", classifications: "classifications", minValue: "minValue", maxValue: "maxValue" }, providers: [
926
1266
  {
927
1267
  provide: NG_VALUE_ACCESSOR,
928
- useExisting: forwardRef(() => OrganizationComponent),
1268
+ useExisting: forwardRef(() => NumberRangeComponent),
929
1269
  multi: true
930
1270
  },
931
1271
  {
932
1272
  provide: NG_VALIDATORS,
933
- useExisting: forwardRef(() => OrganizationComponent),
1273
+ useExisting: forwardRef(() => NumberRangeComponent),
934
1274
  multi: true
935
1275
  }
936
- ], viewQueries: [{ propertyName: "autoCompleteInput", first: true, predicate: ["autocomplete"], descendants: true }], ngImport: i0, template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.title }}</span>\n </ng-template>\n \n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\">{{ item.title }}</span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon\n class=\"classify\"\n [title]=\"'yuv.form.element.organization.classify.icon.title' | translate\"\n [svg]=\"multiselect ? icons.organizationMulti : icons.organization\"\n (click)=\"focusInput()\"\n></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host ::ng-deep .chip{--yvc-form-element-border-color: var(--text-color-hint)}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcAutocompleteModule }, { kind: "component", type: i2$2.AutoComplete, selector: "yvc-autocomplete", inputs: ["field", "placeholder", "minLength", "multiple", "typeahead", "distinctValues", "forceSelection", "autocompleteValues", "disabled"], outputs: ["autocompleteFnc", "blur", "focus", "suggestionUnselect", "suggestionSelect"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] }); }
1276
+ ], ngImport: i0, template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
937
1277
  }
938
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, decorators: [{
1278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, decorators: [{
939
1279
  type: Component,
940
- args: [{ selector: 'yuv-organization', standalone: true, imports: [CommonModule, FormsModule, YvcAutocompleteModule, YvcIconModule, TranslateModule], providers: [
1280
+ args: [{ selector: 'yuv-number-range', standalone: true, imports: [CommonModule, NumberComponent, YvcDropdownModule, FormsModule, ReactiveFormsModule], providers: [
941
1281
  {
942
1282
  provide: NG_VALUE_ACCESSOR,
943
- useExisting: forwardRef(() => OrganizationComponent),
1283
+ useExisting: forwardRef(() => NumberRangeComponent),
944
1284
  multi: true
945
1285
  },
946
1286
  {
947
1287
  provide: NG_VALIDATORS,
948
- useExisting: forwardRef(() => OrganizationComponent),
1288
+ useExisting: forwardRef(() => NumberRangeComponent),
949
1289
  multi: true
950
1290
  }
951
- ], template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.title }}</span>\n </ng-template>\n \n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\">{{ item.title }}</span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon\n class=\"classify\"\n [title]=\"'yuv.form.element.organization.classify.icon.title' | translate\"\n [svg]=\"multiselect ? icons.organizationMulti : icons.organization\"\n (click)=\"focusInput()\"\n></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host ::ng-deep .chip{--yvc-form-element-border-color: var(--text-color-hint)}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"] }]
952
- }], propDecorators: { autoCompleteInput: [{
953
- type: ViewChild,
954
- args: ['autocomplete']
955
- }], onKeydownHandler: [{
956
- type: HostListener,
957
- args: ['keydown.enter', ['$event']]
958
- }], _inputDisabled: [{
959
- type: HostBinding,
960
- args: ['class.inputDisabled']
961
- }], placeholder: [{
1291
+ ], template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
1292
+ }], ctorParameters: () => [], propDecorators: { scale: [{
962
1293
  type: Input
963
- }], situation: [{
1294
+ }], precision: [{
964
1295
  type: Input
965
- }], multiselect: [{
1296
+ }], grouping: [{
966
1297
  type: Input
967
- }], classifications: [{
1298
+ }], pattern: [{
968
1299
  type: Input
969
1300
  }], readonly: [{
970
1301
  type: Input
971
- }], autofocus: [{
972
- type: Input
973
- }], appendTo: [{
1302
+ }], classifications: [{
974
1303
  type: Input
975
- }], excludeMe: [{
1304
+ }], minValue: [{
1305
+ type: Input
1306
+ }], maxValue: [{
976
1307
  type: Input
977
- }], userSelect: [{
978
- type: Output
979
1308
  }] } });
980
1309
 
981
1310
  /**
982
- * Creates form input for strings. Based on the input values different kinds of inputs will be generated.
983
- *
1311
+ * Creates form input for organisation values.
984
1312
  * Implements `ControlValueAccessor` so it can be used within Angular forms.
985
1313
  *
986
- * @example
987
- * <!-- string input validating input to be between 5 and 10 characters -->
988
- * <yuv-string [minLength]="5" [maxLength]="10"></yuv-string>
989
- *
990
- * <!-- string input that only allow digits -->
991
- * <yuv-string [regex]="[0-9]*"></yuv-string>
992
- *
993
- * <!-- string input rendering a large textarea -->
994
- * <yuv-string [rows]="10"></yuv-string>
1314
+ * [Screenshot](../assets/images/yuv-organization.gif)
995
1315
  *
1316
+ * @example
1317
+ * <yuv-organization [multiselect]="true"></yuv-organization>
996
1318
  */
997
- class StringComponent {
1319
+ class OrganizationComponent {
998
1320
  constructor() {
999
- this.iconsService = inject(IconService);
1000
- this.elementRef = inject(ElementRef);
1001
- this.classifiytionIcons = {
1002
- email: this.iconsService.getIcon(ClassificationPrefix.EMAIL_ICON) || '',
1003
- url: this.iconsService.getIcon(ClassificationPrefix.URL_ICON) || '',
1004
- phone: this.iconsService.getIcon(ClassificationPrefix.PHONE_ICON) || ''
1321
+ this.system = inject(SystemService);
1322
+ this.userService = inject(UserService);
1323
+ this.translate = inject(TranslateService);
1324
+ this.minLength = 2;
1325
+ this.icons = {
1326
+ organizationMulti: YUV_ICONS['group'],
1327
+ organization: YUV_ICONS['user']
1005
1328
  };
1006
- // provides all css variables defined by |yuuvis/comonents
1007
- this.fe = true;
1329
+ this.isValidInput = true;
1330
+ this.value = null;
1331
+ this._innerValue = [];
1332
+ this.autocompleteRes = [];
1333
+ this.filterRoles = [];
1008
1334
  /**
1009
1335
  * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
1010
1336
  */
@@ -1014,349 +1340,245 @@ class StringComponent {
1014
1340
  */
1015
1341
  this.readonly = false;
1016
1342
  /**
1017
- * Enable autofucus for the input (default: false)
1343
+ * Set this to true and the component will try to gain focus once it has been rendered.
1344
+ * Notice that this is not reliable. If there are any other components that are rendered
1345
+ * later and also try to be focused, they will 'win', because there can only be one focus.
1018
1346
  */
1019
1347
  this.autofocus = false;
1020
- this.valid = false;
1021
- this.validationErrors = [];
1022
- this._classifications = [];
1348
+ /**
1349
+ * Will attch the overlay to this HTMLelement
1350
+ */
1351
+ this.appendTo = null;
1352
+ /**
1353
+ * Whether or not to exclude the current user from autocomplete result
1354
+ */
1355
+ this.excludeMe = false;
1356
+ /**
1357
+ * Whether or not the emitted value should be an object containing id and title
1358
+ * or, if set to false only the ID
1359
+ */
1360
+ this.withMetadata = input(false);
1361
+ this.userSelect = new EventEmitter();
1362
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1023
1363
  this.propagateChange = (_) => { };
1024
1364
  }
1025
- /**
1026
- * Additional semantics for the form element. Possible values are
1027
- * `email` (validates and creates a link to send an email once there
1028
- * is a valid email address) and `url` (validates and creates a link
1029
- * to an URL typed into the form element).
1030
- */
1365
+ set innerValue(iv) {
1366
+ this._innerValue = iv || [];
1367
+ this.userSelect.emit(this._innerValue.map((v) => v.user));
1368
+ }
1369
+ get innerValue() {
1370
+ return this._innerValue;
1371
+ }
1372
+ // prevent ENTER from being propagated, because the component could be located
1373
+ // inside some other component that also relys on ENTER
1374
+ onKeydownHandler(event) {
1375
+ event.stopPropagation();
1376
+ }
1377
+ get _inputDisabled() {
1378
+ return !this.multiselect && this.innerValue?.length === 1;
1379
+ }
1031
1380
  set classifications(c) {
1032
1381
  this._classifications = c;
1033
- if (c && c.length) {
1034
- if (c.includes(Classification.STRING_EMAIL)) {
1035
- this.classify = {
1036
- hrefPrefix: ClassificationPrefix.EMAIL,
1037
- icon: this.classifiytionIcons.email
1038
- };
1039
- }
1040
- else if (c.includes(Classification.STRING_URL)) {
1041
- this.classify = {
1042
- hrefPrefix: ClassificationPrefix.URL,
1043
- icon: this.classifiytionIcons.url
1044
- };
1045
- }
1046
- else if (c.includes(Classification.STRING_PHONE)) {
1047
- this.classify = {
1048
- hrefPrefix: ClassificationPrefix.PHONE,
1049
- icon: this.classifiytionIcons.phone
1050
- };
1382
+ if (c?.length) {
1383
+ const classifications = this.system.getClassifications(c);
1384
+ if (classifications.has(Classification.STRING_ORGANIZATION)) {
1385
+ const options = classifications.get(Classification.STRING_ORGANIZATION).options;
1386
+ this.filterRoles = options;
1051
1387
  }
1052
1388
  }
1389
+ else {
1390
+ this.filterRoles = [];
1391
+ }
1053
1392
  }
1054
1393
  get classifications() {
1055
1394
  return this._classifications;
1056
1395
  }
1057
- propagate() {
1058
- this.propagateChange(this.value);
1059
- }
1060
1396
  writeValue(value) {
1061
- if (Array.isArray(value)) {
1062
- value = value.filter((v) => typeof v === 'string' && v.trim().length > 0);
1397
+ if (value) {
1398
+ this.value = value;
1399
+ this.resolveFn(value);
1400
+ }
1401
+ else {
1402
+ this.value = null;
1403
+ this.innerValue = [];
1063
1404
  }
1064
- this.formatedValue = Utils.formatMailTo(value, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
1065
- this.value = value || null;
1066
1405
  }
1067
1406
  registerOnChange(fn) {
1068
1407
  this.propagateChange = fn;
1069
1408
  }
1070
- registerOnTouched() { }
1071
- onValueChange(val) {
1072
- this.maxEntryCountIfInvalid = undefined;
1073
- this.validationErrors = [];
1074
- if (Utils.isEmpty(val)) {
1075
- this.value = null;
1076
- this.propagate();
1077
- return;
1078
- }
1079
- const multiCheck = (check) => !!(this.multiselect ? val : [val]).find((v) => check(v));
1080
- // validate regular expression
1081
- if (this.regex && multiCheck((v) => !RegExp(this.regex).test(v))) {
1082
- this.validationErrors.push({ key: 'regex' });
1083
- }
1084
- // validate classification settings
1085
- if (this.classifications && this.classifications.length) {
1086
- this.classifications.forEach((c) => {
1087
- if (multiCheck((v) => !this.validateClassification(v, c))) {
1088
- this.validationErrors.push({ key: 'classification' + c });
1089
- }
1090
- });
1091
- }
1092
- // validate min length
1093
- if (!Utils.isEmpty(this.minLength) && multiCheck((v) => v.length < this.minLength)) {
1094
- this.validationErrors.push({ key: 'minlength', params: { minLength: this.minLength } });
1095
- }
1096
- // validate max length
1097
- if (!Utils.isEmpty(this.maxLength) && multiCheck((v) => v.length > this.maxLength)) {
1098
- this.validationErrors.push({ key: 'maxlength', params: { maxLength: this.maxLength } });
1099
- }
1100
- // validate invalid if only whitespaces
1101
- if (multiCheck((v) => v.length > 0 && !v.trim().length)) {
1102
- this.validationErrors.push({ key: 'onlyWhitespaces' });
1103
- }
1104
- if (this.validationErrors.length && this.multiselect && this.value) {
1105
- // Setting maxEntryCountIfInvalid to the actual length of the value array to prevent the user to add more entries.
1106
- this.maxEntryCountIfInvalid = this.value.length;
1107
- }
1108
- this.formatedValue = Utils.formatMailTo(val, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
1109
- this.propagate();
1409
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1410
+ registerOnTouched(fn) { }
1411
+ propagate() {
1412
+ this.propagateChange(this.#getPropagateValue());
1110
1413
  }
1111
- onBlur() {
1112
- if (this.multiselect) {
1113
- // add on blur
1114
- this.value.push('');
1115
- }
1116
- if (this.trimValue()) {
1117
- this.propagate();
1118
- }
1414
+ #getPropagateValue() {
1415
+ return this.multiselect
1416
+ ? this.withMetadata()
1417
+ ? this.value
1418
+ ? this._innerValue.map((v) => ({
1419
+ id: v.user.id,
1420
+ title: v.user.title
1421
+ }))
1422
+ : this.value
1423
+ : this.value
1424
+ : this.withMetadata()
1425
+ ? this.value
1426
+ ? {
1427
+ id: this._innerValue[0].user.id,
1428
+ title: this._innerValue[0].user.title
1429
+ }
1430
+ : this.value
1431
+ : this.value;
1119
1432
  }
1120
- /**
1121
- * Trims the current value and returns wether or not it has been trimmed
1122
- */
1123
- trimValue() {
1124
- if (this.value) {
1125
- if (this.multiselect) {
1126
- const lengthBefore = this.value.join('').length;
1127
- this.value = this.value.map((v) => v.trim());
1128
- return this.value.join('').length !== lengthBefore;
1129
- }
1130
- else {
1131
- const lengthBefore = this.value.length;
1132
- this.value = this.value.trim();
1133
- return this.value.length !== lengthBefore;
1134
- }
1135
- }
1136
- return false;
1433
+ focusInput() {
1434
+ this.autoCompleteInput.focusInput();
1137
1435
  }
1138
- validateClassification(string, classification) {
1139
- if (this.situation === Situation.SEARCH) {
1140
- return true;
1436
+ resolveFn(value) {
1437
+ const obs = (value instanceof Array ? value : [value]).map((v) => {
1438
+ const valueID = typeof v === 'string' ? v : v.id;
1439
+ const match = this.innerValue.find((iv) => iv.user.id === valueID);
1440
+ return match
1441
+ ? of(match)
1442
+ : this.userService.getUserById(valueID).pipe(map$1((res) => ({
1443
+ user: res,
1444
+ state: {}
1445
+ })), catchError((e) => {
1446
+ const user = new YuvUser({
1447
+ id: typeof v === 'string' ? v : v.id
1448
+ });
1449
+ user.title = typeof v === 'string' ? v : v.title;
1450
+ return of({
1451
+ user,
1452
+ state: {
1453
+ notFound: e.status === 404
1454
+ },
1455
+ titleString: e.status === 404 ? this.translate.instant('yuv.form.element.organization.user.not-found') : undefined
1456
+ });
1457
+ }));
1458
+ });
1459
+ return forkJoin(obs).subscribe((data) => {
1460
+ this.innerValue = data;
1461
+ // setTimeout(() => this.autoCompleteInput.cd.markForCheck());
1462
+ });
1463
+ }
1464
+ autocompleteFn(query) {
1465
+ if (query.length >= this.minLength) {
1466
+ this.userService.queryUser(query, this.excludeMe, this.filterRoles).subscribe({
1467
+ next: (users) => {
1468
+ this.autocompleteRes = users
1469
+ .filter((user) => !this.innerValue.some((value) => value.user.id === user.id))
1470
+ .map((user) => ({
1471
+ user: user,
1472
+ state: {}
1473
+ }));
1474
+ this.propagateValidity(this.autocompleteRes.length > 0);
1475
+ },
1476
+ error: () => {
1477
+ this.autocompleteRes = [];
1478
+ this.propagateValidity(this.autocompleteRes.length > 0);
1479
+ }
1480
+ });
1141
1481
  }
1142
1482
  else {
1143
- let pattern;
1144
- if (classification === Classification.STRING_EMAIL) {
1145
- pattern =
1146
- /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
1147
- }
1148
- else if (classification === Classification.STRING_URL) {
1149
- pattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)?([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
1150
- }
1151
- else if (classification === Classification.STRING_PHONE) {
1152
- pattern = /^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-x\s\./0-9]*$/g;
1153
- }
1154
- return pattern ? pattern.test(string) : true;
1483
+ this.autocompleteRes = [];
1155
1484
  }
1156
1485
  }
1157
- /**
1158
- * returns null when valid else the validation object
1159
- */
1486
+ // returns null when valid else the validation object
1160
1487
  validate() {
1161
- if (this.validationErrors.length) {
1162
- this.valid = false;
1163
- return Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err }));
1488
+ return this.isValidInput ? null : { empty: { valid: false } };
1489
+ }
1490
+ propagateValidity(valid = true) {
1491
+ if (this.isValidInput !== valid) {
1492
+ this.isValidInput = valid;
1493
+ this.propagate();
1494
+ }
1495
+ }
1496
+ // handle selection changes to the model
1497
+ onSelect() {
1498
+ if (this.multiselect) {
1499
+ this.value = this.innerValue.map((v) => v.user.id);
1164
1500
  }
1165
1501
  else {
1166
- this.valid = true;
1167
- return null;
1502
+ // internal autocomplete control is always set to multiselect
1503
+ // so the resolved value is always an array
1504
+ this.innerValue = this.innerValue.slice(-1);
1505
+ this.value = this.innerValue[0].user.id;
1168
1506
  }
1507
+ this.propagate();
1169
1508
  }
1170
- ngAfterViewInit() {
1171
- if (this.autofocus) {
1172
- if (!this.multiselect) {
1173
- const el = this.elementRef.nativeElement.querySelector(this.rows && this.rows > 1 ? 'textarea' : 'input');
1174
- if (el)
1175
- el.focus();
1176
- }
1509
+ // handle selection changes to the model
1510
+ onUnselect(value) {
1511
+ this.innerValue = this.innerValue.filter((v) => v.user.id !== value.id);
1512
+ const _value = this.innerValue.map((v) => v.user.id);
1513
+ this.value = this.multiselect ? _value : null;
1514
+ if (!this.multiselect) {
1515
+ this.clearInnerInput();
1177
1516
  }
1517
+ this.propagate();
1178
1518
  }
1179
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1180
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: StringComponent, isStandalone: true, selector: "yuv-string", inputs: { multiselect: "multiselect", rows: "rows", readonly: "readonly", autofocus: "autofocus", classifications: "classifications", situation: "situation", regex: "regex", minLength: "minLength", maxLength: "maxLength" }, host: { properties: { "class.yvc-form-element": "this.fe" } }, providers: [
1519
+ onAutoCompleteBlur() {
1520
+ this.clearInnerInput();
1521
+ }
1522
+ clearInnerInput() {
1523
+ this.autoCompleteInput.clearInput();
1524
+ }
1525
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1526
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: OrganizationComponent, isStandalone: true, selector: "yuv-organization", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, situation: { classPropertyName: "situation", publicName: "situation", isSignal: false, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: false, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: false, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: false, isRequired: false, transformFunction: null }, excludeMe: { classPropertyName: "excludeMe", publicName: "excludeMe", isSignal: false, isRequired: false, transformFunction: null }, withMetadata: { classPropertyName: "withMetadata", publicName: "withMetadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userSelect: "userSelect" }, host: { listeners: { "keydown.enter": "onKeydownHandler($event)" }, properties: { "class.inputDisabled": "this._inputDisabled" } }, providers: [
1181
1527
  {
1182
1528
  provide: NG_VALUE_ACCESSOR,
1183
- useExisting: forwardRef(() => StringComponent),
1529
+ useExisting: forwardRef(() => OrganizationComponent),
1184
1530
  multi: true
1185
1531
  },
1186
1532
  {
1187
1533
  provide: NG_VALIDATORS,
1188
- useExisting: forwardRef(() => StringComponent),
1534
+ useExisting: forwardRef(() => OrganizationComponent),
1189
1535
  multi: true
1190
1536
  }
1191
- ], ngImport: i0, template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: YvcChipsModule }, { kind: "component", type: i2$3.Chips, selector: "yvc-chips", inputs: ["field", "placeholder", "max", "disabled", "addOnBlur"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
1537
+ ], viewQueries: [{ propertyName: "autoCompleteInput", first: true, predicate: ["autocomplete"], descendants: true }], ngImport: i0, template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.state.notFound }\" [title]=\"item.titleString\">\n {{ item.user.title }}\n </span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon class=\"classify\" aria-hidden=\"true\" [svg]=\"multiselect ? icons.organizationMulti : icons.organization\" (click)=\"focusInput()\"></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--color-error);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--color-error);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcAutocompleteModule }, { kind: "component", type: i3$1.AutoComplete, selector: "yvc-autocomplete", inputs: ["field", "placeholder", "minLength", "multiple", "typeahead", "distinctValues", "forceSelection", "autocompleteValues", "disabled"], outputs: ["autocompleteFnc", "blur", "focus", "suggestionUnselect", "suggestionSelect"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: TranslateModule }] }); }
1192
1538
  }
1193
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, decorators: [{
1539
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, decorators: [{
1194
1540
  type: Component,
1195
- args: [{ selector: 'yuv-string', standalone: true, imports: [CommonModule, YvcChipsModule, YvcIconModule, FormsModule], providers: [
1541
+ args: [{ selector: 'yuv-organization', standalone: true, imports: [CommonModule, FormsModule, YvcAutocompleteModule, YvcIconModule, TranslateModule], providers: [
1196
1542
  {
1197
1543
  provide: NG_VALUE_ACCESSOR,
1198
- useExisting: forwardRef(() => StringComponent),
1544
+ useExisting: forwardRef(() => OrganizationComponent),
1199
1545
  multi: true
1200
1546
  },
1201
1547
  {
1202
1548
  provide: NG_VALIDATORS,
1203
- useExisting: forwardRef(() => StringComponent),
1549
+ useExisting: forwardRef(() => OrganizationComponent),
1204
1550
  multi: true
1205
1551
  }
1206
- ], template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"] }]
1207
- }], propDecorators: { fe: [{
1552
+ ], template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.state.notFound }\" [title]=\"item.titleString\">\n {{ item.user.title }}\n </span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon class=\"classify\" aria-hidden=\"true\" [svg]=\"multiselect ? icons.organizationMulti : icons.organization\" (click)=\"focusInput()\"></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--color-error);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--color-error);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"] }]
1553
+ }], propDecorators: { autoCompleteInput: [{
1554
+ type: ViewChild,
1555
+ args: ['autocomplete']
1556
+ }], onKeydownHandler: [{
1557
+ type: HostListener,
1558
+ args: ['keydown.enter', ['$event']]
1559
+ }], _inputDisabled: [{
1208
1560
  type: HostBinding,
1209
- args: ['class.yvc-form-element']
1210
- }], multiselect: [{
1211
- type: Input
1212
- }], rows: [{
1213
- type: Input
1214
- }], readonly: [{
1215
- type: Input
1216
- }], autofocus: [{
1217
- type: Input
1218
- }], classifications: [{
1561
+ args: ['class.inputDisabled']
1562
+ }], placeholder: [{
1219
1563
  type: Input
1220
1564
  }], situation: [{
1221
1565
  type: Input
1222
- }], regex: [{
1223
- type: Input
1224
- }], minLength: [{
1225
- type: Input
1226
- }], maxLength: [{
1227
- type: Input
1228
- }] } });
1229
-
1230
- /**
1231
- * Component for wrapping a form element. Provides a label and focus behaviour.
1232
- *
1233
- * @example
1234
- * <yuv-form-input [label]="'my form element'">
1235
- * <!-- form element to be wrapped -->
1236
- * </yuv-form-input>
1237
- */
1238
- class FormInputComponent {
1239
- constructor() {
1240
- this.renderer = inject(Renderer2);
1241
- this.isDisabled = false;
1242
- this.isInvalid = false;
1243
- this.isRequired = false;
1244
- }
1245
- /**
1246
- * A label string for the wrapped form element
1247
- */
1248
- set label(val) {
1249
- this._label = val;
1250
- }
1251
- /**
1252
- * Indicator that the wrapped form element is invalid. Will then render appropriate styles.
1253
- * You may also provide an array of error messages.
1254
- */
1255
- set invalid(iv) {
1256
- if (iv === null || iv === undefined) {
1257
- this.isInvalid = false;
1258
- this.renderer.removeAttribute(this.labelEl.nativeElement, 'title');
1259
- }
1260
- else if (Array.isArray(iv)) {
1261
- this.isInvalid = iv.length > 0;
1262
- if (this.isInvalid) {
1263
- this.renderer.setAttribute(this.labelEl.nativeElement, 'title', iv.join(';'));
1264
- }
1265
- }
1266
- else {
1267
- this.isInvalid = iv;
1268
- }
1269
- }
1270
- /**
1271
- * Indicator that the wrapped form element is disabled. Will then render appropriate styles.
1272
- */
1273
- set disabled(d) {
1274
- this.isDisabled = d;
1275
- }
1276
- /**
1277
- * Indicator that the wrapped form element is mandatory. Will then render appropriate styles.
1278
- */
1279
- set required(d) {
1280
- this.isRequired = d;
1281
- }
1282
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1283
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FormInputComponent, isStandalone: true, selector: "yuv-form-input", inputs: { label: "label", tag: "tag", description: "description", invalid: "invalid", disabled: "disabled", required: "required" }, host: { properties: { "class.disabled": "this.isDisabled", "class.invalid": "this.isInvalid", "class.required": "this.isRequired" } }, viewQueries: [{ propertyName: "labelEl", first: true, predicate: ["label"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: FocusWithinDirective, selector: "[yuvFocusWithin]", outputs: ["yuvFocusWithin", "yuvFocusWithinBlur"] }], encapsulation: i0.ViewEncapsulation.None }); }
1284
- }
1285
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, decorators: [{
1286
- type: Component,
1287
- args: [{ selector: 'yuv-form-input', standalone: true, imports: [CommonModule, FocusWithinDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"] }]
1288
- }], propDecorators: { labelEl: [{
1289
- type: ViewChild,
1290
- args: ['label', { static: true }]
1291
- }], label: [{
1566
+ }], multiselect: [{
1292
1567
  type: Input
1293
- }], tag: [{
1568
+ }], classifications: [{
1294
1569
  type: Input
1295
- }], description: [{
1570
+ }], readonly: [{
1296
1571
  type: Input
1297
- }], invalid: [{
1572
+ }], autofocus: [{
1298
1573
  type: Input
1299
- }], disabled: [{
1574
+ }], appendTo: [{
1300
1575
  type: Input
1301
- }], required: [{
1576
+ }], excludeMe: [{
1302
1577
  type: Input
1303
- }], isDisabled: [{
1304
- type: HostBinding,
1305
- args: ['class.disabled']
1306
- }], isInvalid: [{
1307
- type: HostBinding,
1308
- args: ['class.invalid']
1309
- }], isRequired: [{
1310
- type: HostBinding,
1311
- args: ['class.required']
1578
+ }], userSelect: [{
1579
+ type: Output
1312
1580
  }] } });
1313
1581
 
1314
- class YuvFormsModule {
1315
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1316
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1317
- FormsModule,
1318
- TranslateModule$1,
1319
- ReactiveFormsModule,
1320
- YvcFocusWithin,
1321
- YvcAutocompleteModule,
1322
- YvcDatepickerModule,
1323
- FormsModule,
1324
- YvcCheckboxModule,
1325
- YvcIconModule,
1326
- YvcChipsModule,
1327
- YvcDropdownModule] }); }
1328
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1329
- FormsModule,
1330
- TranslateModule$1,
1331
- ReactiveFormsModule,
1332
- YvcAutocompleteModule,
1333
- YvcDatepickerModule,
1334
- FormsModule,
1335
- YvcCheckboxModule,
1336
- YvcIconModule,
1337
- YvcChipsModule,
1338
- YvcDropdownModule] }); }
1339
- }
1340
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, decorators: [{
1341
- type: NgModule,
1342
- args: [{
1343
- imports: [
1344
- CommonModule,
1345
- FormsModule,
1346
- TranslateModule$1,
1347
- ReactiveFormsModule,
1348
- YvcFocusWithin,
1349
- YvcAutocompleteModule,
1350
- YvcDatepickerModule,
1351
- FormsModule,
1352
- YvcCheckboxModule,
1353
- YvcIconModule,
1354
- YvcChipsModule,
1355
- YvcDropdownModule,
1356
- ]
1357
- }]
1358
- }] });
1359
-
1360
1582
  class DateRangePickerComponent {
1361
1583
  constructor() {
1362
1584
  this.#oRef = inject(YvcOverlayRef);
@@ -1409,7 +1631,7 @@ class RangeSelectDateComponent {
1409
1631
  #CUSTOM_OPTION;
1410
1632
  #customDateRange;
1411
1633
  constructor() {
1412
- this.translate = inject(TranslateService$1);
1634
+ this.translate = inject(TranslateService);
1413
1635
  this.#overlay = inject(YvcOverlayService);
1414
1636
  this.#fb = inject(FormBuilder);
1415
1637
  this.#ANY_OPTION = 'any';
@@ -1569,7 +1791,7 @@ class RangeSelectFilesizeComponent {
1569
1791
  #fb;
1570
1792
  #ANY_OPTION;
1571
1793
  constructor() {
1572
- this.translate = inject(TranslateService);
1794
+ this.translate = inject(TranslateService$1);
1573
1795
  this.#fb = inject(FormBuilder);
1574
1796
  this.#ANY_OPTION = 'any';
1575
1797
  this.options = signal([]);
@@ -1642,9 +1864,72 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1642
1864
  ], template: "<form [formGroup]=\"innerForm\">\n <yvc-dropdown formControlName=\"range\" [options]=\"options()\" [disableClearButton]=\"true\"></yvc-dropdown>\n</form>\n", styles: [":host form{display:flex}:host form yvc-dropdown{flex:1;outline-offset:0px;color:currentColor}\n"] }]
1643
1865
  }], ctorParameters: () => [] });
1644
1866
 
1867
+ class YuvFormsModule {
1868
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1869
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1870
+ FormsModule,
1871
+ TranslateModule$1,
1872
+ ReactiveFormsModule,
1873
+ YvcFocusWithin,
1874
+ YvcAutocompleteModule,
1875
+ YvcDatepickerModule,
1876
+ FormsModule,
1877
+ YvcCheckboxModule,
1878
+ YvcIconModule,
1879
+ YvcChipsModule,
1880
+ YvcDropdownModule] }); }
1881
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1882
+ FormsModule,
1883
+ TranslateModule$1,
1884
+ ReactiveFormsModule,
1885
+ YvcAutocompleteModule,
1886
+ YvcDatepickerModule,
1887
+ FormsModule,
1888
+ YvcCheckboxModule,
1889
+ YvcIconModule,
1890
+ YvcChipsModule,
1891
+ YvcDropdownModule] }); }
1892
+ }
1893
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, decorators: [{
1894
+ type: NgModule,
1895
+ args: [{
1896
+ imports: [
1897
+ CommonModule,
1898
+ FormsModule,
1899
+ TranslateModule$1,
1900
+ ReactiveFormsModule,
1901
+ YvcFocusWithin,
1902
+ YvcAutocompleteModule,
1903
+ YvcDatepickerModule,
1904
+ FormsModule,
1905
+ YvcCheckboxModule,
1906
+ YvcIconModule,
1907
+ YvcChipsModule,
1908
+ YvcDropdownModule,
1909
+ ]
1910
+ }]
1911
+ }] });
1912
+
1913
+ // export { CatalogComponent } from './lib/elements/catalog/catalog.component';
1914
+ // export { CheckboxComponent } from './lib/elements/checkbox/checkbox.component';
1915
+ // export { DatetimeRangeComponent } from './lib/elements/datetime-range/datetime-range.component';
1916
+ // export { DatepickerComponent } from './lib/elements/datetime/datepicker/datepicker.component';
1917
+ // export { DatetimeComponent } from './lib/elements/datetime/datetime.component';
1918
+ // export { YearRangeDirective } from './lib/elements/datetime/year-range/year-range.directive';
1919
+ // export { DynamicCatalogManagementComponent } from './lib/elements/dynamic-catalog/dynamic-catalog-management/dynamic-catalog-management.component';
1920
+ // export { DynamicCatalogComponent } from './lib/elements/dynamic-catalog/dynamic-catalog.component';
1921
+ // export { NumberRangeComponent } from './lib/elements/number-range/number-range.component';
1922
+ // export { NumberComponent } from './lib/elements/number/number.component';
1923
+ // export { OrganizationSetComponent } from './lib/elements/organization-set/organization-set.component';
1924
+ // export { OrganizationComponent } from './lib/elements/organization/organization.component';
1925
+ // export { ReferenceItemComponent } from './lib/elements/reference/reference-item/reference-item.component';
1926
+ // export { ReferenceComponent } from './lib/elements/reference/reference.component';
1927
+ // export * from './lib/elements/reference/reference.interface';
1928
+ // export { StringComponent } from './lib/elements/string/string.component';
1929
+
1645
1930
  /**
1646
1931
  * Generated bundle index. Do not edit.
1647
1932
  */
1648
1933
 
1649
- export { CatalogComponent, DatetimeComponent, DatetimeRangeComponent, FormInputComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
1934
+ export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, FormInputComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
1650
1935
  //# sourceMappingURL=yuuvis-client-framework-forms.mjs.map