@myrmidon/cadmus-ui 15.0.0 → 15.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,35 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, Component, signal, effect, ViewChild, Injectable, Inject, model, computed, inject } from '@angular/core';
3
- import { MatButton, MatIconButton, MatAnchor } from '@angular/material/button';
4
- import { MatIcon } from '@angular/material/icon';
2
+ import { input, output, Component, signal, effect, ViewChild, Injectable, Inject, inject, model, computed, untracked } from '@angular/core';
3
+ import * as i2$1 from '@angular/material/button';
4
+ import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button';
5
+ import * as i5 from '@angular/material/icon';
6
+ import { MatIcon, MatIconModule } from '@angular/material/icon';
5
7
  import { SafeHtmlPipe, deepCopy } from '@myrmidon/ngx-tools';
6
8
  import * as i1 from '@myrmidon/cadmus-core';
7
- import { MatTooltip } from '@angular/material/tooltip';
9
+ import * as i6 from '@angular/material/tooltip';
10
+ import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
8
11
  import * as i1$1 from '@angular/forms';
9
- import { FormsModule, ReactiveFormsModule, PristineChangeEvent } from '@angular/forms';
10
- import { MatCheckbox } from '@angular/material/checkbox';
12
+ import { FormsModule, ReactiveFormsModule, FormBuilder, FormControl, FormGroup, Validators, PristineChangeEvent } from '@angular/forms';
13
+ import * as i3 from '@angular/material/checkbox';
14
+ import { MatCheckbox, MatCheckboxModule } from '@angular/material/checkbox';
11
15
  import * as i2 from '@myrmidon/ngx-mat-tools';
12
- import { AsyncPipe, NgClass } from '@angular/common';
16
+ import { AsyncPipe } from '@angular/common';
13
17
  import { of, BehaviorSubject, map as map$1, Subject } from 'rxjs';
14
18
  import { debounceTime, distinctUntilChanged, switchMap, map, take } from 'rxjs/operators';
15
19
  import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
16
20
  import { MatOption } from '@angular/material/core';
17
- import { MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field';
18
- import { MatInput } from '@angular/material/input';
21
+ import * as i4 from '@angular/material/form-field';
22
+ import { MatFormField, MatFormFieldModule } from '@angular/material/form-field';
23
+ import * as i4$1 from '@angular/material/input';
24
+ import { MatInput, MatInputModule } from '@angular/material/input';
19
25
  import * as i1$2 from '@myrmidon/cadmus-api';
20
- import { NestedTreeControl } from '@angular/cdk/tree';
21
- import { MatTreeNestedDataSource, MatTree, MatTreeNodeDef, MatTreeNode, MatTreeNodeToggle, MatNestedTreeNode, MatTreeNodeOutlet } from '@angular/material/tree';
26
+ import { moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
27
+ import { MatChipListbox, MatChipOption, MatChipRemove } from '@angular/material/chips';
28
+ import { MatExpansionPanel } from '@angular/material/expansion';
29
+ import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
30
+ import * as i7 from '@angular/material/progress-bar';
31
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
32
+ import { PagedTreeStore, BrowserTreeNodeComponent } from '@myrmidon/paged-data-browsers';
22
33
  import { AppRepository } from '@myrmidon/cadmus-state';
23
34
  import * as i1$3 from '@myrmidon/auth-jwt-login';
24
35
 
@@ -29,10 +40,10 @@ class CloseSaveButtonsComponent {
29
40
  close() {
30
41
  this.closeRequest.emit();
31
42
  }
32
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: CloseSaveButtonsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: CloseSaveButtonsComponent, isStandalone: true, selector: "cadmus-close-save-buttons", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, noSave: { classPropertyName: "noSave", publicName: "noSave", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeRequest: "closeRequest" }, ngImport: i0, template: "@if (form()) {\n<div class=\"form-row\">\n <button type=\"button\" mat-flat-button class=\"mat-warn\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n close\n </button>\n @if (!noSave()) {\n <button\n type=\"submit\"\n [disabled]=\"form()?.invalid\"\n mat-flat-button\n class=\"mat-primary\"\n >\n <mat-icon>check_circle</mat-icon>\n save\n </button>\n }\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
43
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: CloseSaveButtonsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
44
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: CloseSaveButtonsComponent, isStandalone: true, selector: "cadmus-close-save-buttons", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, noSave: { classPropertyName: "noSave", publicName: "noSave", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeRequest: "closeRequest" }, ngImport: i0, template: "@if (form()) {\n<div class=\"form-row\">\n <button type=\"button\" mat-flat-button class=\"mat-warn\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n close\n </button>\n @if (!noSave()) {\n <button\n type=\"submit\"\n [disabled]=\"form()?.invalid\"\n mat-flat-button\n class=\"mat-primary\"\n >\n <mat-icon>check_circle</mat-icon>\n save\n </button>\n }\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
34
45
  }
35
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: CloseSaveButtonsComponent, decorators: [{
46
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: CloseSaveButtonsComponent, decorators: [{
36
47
  type: Component,
37
48
  args: [{ selector: 'cadmus-close-save-buttons', imports: [MatButton, MatIcon], template: "@if (form()) {\n<div class=\"form-row\">\n <button type=\"button\" mat-flat-button class=\"mat-warn\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n close\n </button>\n @if (!noSave()) {\n <button\n type=\"submit\"\n [disabled]=\"form()?.invalid\"\n mat-flat-button\n class=\"mat-primary\"\n >\n <mat-icon>check_circle</mat-icon>\n save\n </button>\n }\n</div>\n}\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
38
49
  }] });
@@ -69,10 +80,10 @@ class DecoratedTokenTextComponent {
69
80
  decorate(text, locations, selectedLocation) {
70
81
  this.text.set(this._textLayerService.render(text, locations, selectedLocation));
71
82
  }
72
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: DecoratedTokenTextComponent, deps: [{ token: i1.TextLayerService }], target: i0.ɵɵFactoryTarget.Component });
73
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: DecoratedTokenTextComponent, isStandalone: true, selector: "cadmus-decorated-token-text", inputs: { baseText: { classPropertyName: "baseText", publicName: "baseText", isSignal: true, isRequired: false, transformFunction: null }, locations: { classPropertyName: "locations", publicName: "locations", isSignal: true, isRequired: false, transformFunction: null }, selectedLocation: { classPropertyName: "selectedLocation", publicName: "selectedLocation", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_textElement", first: true, predicate: ["textElem"], descendants: true }], ngImport: i0, template: "<div [innerHtml]=\"text() | safeHtml : 'html'\" id=\"text\" #textElem></div>\r\n", styles: [":host ::ng-deep div#text{counter-reset:text-y-counter}:host ::ng-deep div#text p:before{content:counter(text-y-counter);counter-increment:text-y-counter;margin-right:6px;color:#a0a0a0}:host ::ng-deep span.fr{background-color:#ff0;border:1px solid silver;border-radius:6px;padding:0 4px}:host ::ng-deep span.fr-sel{background-color:orange;font-weight:700;border:1px solid #404040}\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
83
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: DecoratedTokenTextComponent, deps: [{ token: i1.TextLayerService }], target: i0.ɵɵFactoryTarget.Component });
84
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: DecoratedTokenTextComponent, isStandalone: true, selector: "cadmus-decorated-token-text", inputs: { baseText: { classPropertyName: "baseText", publicName: "baseText", isSignal: true, isRequired: false, transformFunction: null }, locations: { classPropertyName: "locations", publicName: "locations", isSignal: true, isRequired: false, transformFunction: null }, selectedLocation: { classPropertyName: "selectedLocation", publicName: "selectedLocation", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_textElement", first: true, predicate: ["textElem"], descendants: true }], ngImport: i0, template: "<div [innerHtml]=\"text() | safeHtml : 'html'\" id=\"text\" #textElem></div>\r\n", styles: [":host ::ng-deep div#text{counter-reset:text-y-counter}:host ::ng-deep div#text p:before{content:counter(text-y-counter);counter-increment:text-y-counter;margin-right:6px;color:#a0a0a0}:host ::ng-deep span.fr{background-color:#ff0;border:1px solid silver;border-radius:6px;padding:0 4px}:host ::ng-deep span.fr-sel{background-color:orange;font-weight:700;border:1px solid #404040}\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
74
85
  }
75
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: DecoratedTokenTextComponent, decorators: [{
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: DecoratedTokenTextComponent, decorators: [{
76
87
  type: Component,
77
88
  args: [{ selector: 'cadmus-decorated-token-text', imports: [SafeHtmlPipe], template: "<div [innerHtml]=\"text() | safeHtml : 'html'\" id=\"text\" #textElem></div>\r\n", styles: [":host ::ng-deep div#text{counter-reset:text-y-counter}:host ::ng-deep div#text p:before{content:counter(text-y-counter);counter-increment:text-y-counter;margin-right:6px;color:#a0a0a0}:host ::ng-deep span.fr{background-color:#ff0;border:1px solid silver;border-radius:6px;padding:0 4px}:host ::ng-deep span.fr-sel{background-color:orange;font-weight:700;border:1px solid #404040}\n"] }]
78
89
  }], ctorParameters: () => [{ type: i1.TextLayerService }], propDecorators: { _textElement: [{
@@ -82,10 +93,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
82
93
 
83
94
  class ErrorListComponent {
84
95
  errors = input(...(ngDevMode ? [undefined, { debugName: "errors" }] : []));
85
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ErrorListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
86
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ErrorListComponent, isStandalone: true, selector: "cadmus-error-list", inputs: { errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (errors()?.length) {\n <ul>\n @for (error of errors(); track error) {\n <li class=\"error\">{{error}}</li>\n }\n </ul>\n}\n", styles: [".error{color:red}\n"] });
96
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ErrorListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
97
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ErrorListComponent, isStandalone: true, selector: "cadmus-error-list", inputs: { errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (errors()?.length) {\n <ul>\n @for (error of errors(); track error) {\n <li class=\"error\">{{error}}</li>\n }\n </ul>\n}\n", styles: [".error{color:red}\n"] });
87
98
  }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ErrorListComponent, decorators: [{
99
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ErrorListComponent, decorators: [{
89
100
  type: Component,
90
101
  args: [{ selector: 'cadmus-error-list', template: "@if (errors()?.length) {\n <ul>\n @for (error of errors(); track error) {\n <li class=\"error\">{{error}}</li>\n }\n </ul>\n}\n", styles: [".error{color:red}\n"] }]
91
102
  }] });
@@ -233,10 +244,10 @@ class ColorService {
233
244
  const rgb = this.hslToRgb(h, s, l);
234
245
  return this.rgbToString(rgb.r, rgb.g, rgb.b);
235
246
  }
236
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ColorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
237
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ColorService, providedIn: 'root' });
247
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
248
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, providedIn: 'root' });
238
249
  }
239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ColorService, decorators: [{
250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ColorService, decorators: [{
240
251
  type: Injectable,
241
252
  args: [{
242
253
  providedIn: 'root',
@@ -317,10 +328,10 @@ class FacetBadgeComponent {
317
328
  this.contrastColor.set(this._colorService.getContrastColor(this.color()));
318
329
  this.tip.set(this.getFacetTip(data?.facetId || '') ?? undefined);
319
330
  }
320
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: FacetBadgeComponent, deps: [{ token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
321
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: FacetBadgeComponent, isStandalone: true, selector: "cadmus-facet-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<span\r\n class=\"model-type\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n matTooltip=\"{{ tip() }}\"\r\n >{{ data().facetId }}\r\n</span>\r\n", styles: ["span.model-type{padding:4px;border-radius:6px}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
331
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FacetBadgeComponent, deps: [{ token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
332
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: FacetBadgeComponent, isStandalone: true, selector: "cadmus-facet-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<span\r\n class=\"model-type\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n matTooltip=\"{{ tip() }}\"\r\n >{{ data().facetId }}\r\n</span>\r\n", styles: ["span.model-type{padding:4px;border-radius:6px}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
322
333
  }
323
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: FacetBadgeComponent, decorators: [{
334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FacetBadgeComponent, decorators: [{
324
335
  type: Component,
325
336
  args: [{ selector: 'cadmus-facet-badge', imports: [MatTooltip], template: "<span\r\n class=\"model-type\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n matTooltip=\"{{ tip() }}\"\r\n >{{ data().facetId }}\r\n</span>\r\n", styles: ["span.model-type{padding:4px;border-radius:6px}\n"] }]
326
337
  }], ctorParameters: () => [{ type: ColorService }] });
@@ -346,10 +357,10 @@ class FlagsBadgeComponent {
346
357
  return def.id & data.flags;
347
358
  }));
348
359
  }
349
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: FlagsBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
350
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: FlagsBadgeComponent, isStandalone: true, selector: "cadmus-flags-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\r\n @for (def of badgeFlags(); track def.id) {\r\n <span\r\n class=\"badge-flag\"\r\n [style.color]=\"'#' + def.colorKey\"\r\n [matTooltip]=\"def.label\"\r\n >\r\n @if (def.isAdmin) { &#x25c6; } @else { &#x2b24; }\r\n </span>\r\n }\r\n</div>\r\n", styles: ["span.badge-flag{font-size:1rem;cursor:default}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FlagsBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
361
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: FlagsBadgeComponent, isStandalone: true, selector: "cadmus-flags-badge", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\r\n @for (def of badgeFlags(); track def.id) {\r\n <span\r\n class=\"badge-flag\"\r\n [style.color]=\"'#' + def.colorKey\"\r\n [matTooltip]=\"def.label\"\r\n >\r\n @if (def.isAdmin) { &#x25c6; } @else { &#x2b24; }\r\n </span>\r\n }\r\n</div>\r\n", styles: ["span.badge-flag{font-size:1rem;cursor:default}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
351
362
  }
352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: FlagsBadgeComponent, decorators: [{
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: FlagsBadgeComponent, decorators: [{
353
364
  type: Component,
354
365
  args: [{ selector: 'cadmus-flags-badge', imports: [MatTooltip], template: "<div>\r\n @for (def of badgeFlags(); track def.id) {\r\n <span\r\n class=\"badge-flag\"\r\n [style.color]=\"'#' + def.colorKey\"\r\n [matTooltip]=\"def.label\"\r\n >\r\n @if (def.isAdmin) { &#x25c6; } @else { &#x2b24; }\r\n </span>\r\n }\r\n</div>\r\n", styles: ["span.badge-flag{font-size:1rem;cursor:default}\n"] }]
355
366
  }], ctorParameters: () => [] });
@@ -426,10 +437,10 @@ class LayerHintsComponent {
426
437
  }
427
438
  });
428
439
  }
429
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LayerHintsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
430
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: LayerHintsComponent, isStandalone: true, selector: "cadmus-layer-hints", inputs: { hints: { classPropertyName: "hints", publicName: "hints", isSignal: true, isRequired: false, transformFunction: null }, targetLocation: { classPropertyName: "targetLocation", publicName: "targetLocation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { requestEdit: "requestEdit", requestDelete: "requestDelete", requestMove: "requestMove", requestPatch: "requestPatch" }, ngImport: i0, template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [disabled]=\"disabled() || false\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
440
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LayerHintsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2.DialogService }], target: i0.ɵɵFactoryTarget.Component });
441
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: LayerHintsComponent, isStandalone: true, selector: "cadmus-layer-hints", inputs: { hints: { classPropertyName: "hints", publicName: "hints", isSignal: true, isRequired: false, transformFunction: null }, targetLocation: { classPropertyName: "targetLocation", publicName: "targetLocation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { requestEdit: "requestEdit", requestDelete: "requestDelete", requestMove: "requestMove", requestPatch: "requestPatch" }, ngImport: i0, template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
431
442
  }
432
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LayerHintsComponent, decorators: [{
443
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LayerHintsComponent, decorators: [{
433
444
  type: Component,
434
445
  args: [{ selector: 'cadmus-layer-hints', imports: [
435
446
  FormsModule,
@@ -439,7 +450,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
439
450
  MatIcon,
440
451
  MatCheckbox,
441
452
  MatButton,
442
- ], template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [disabled]=\"disabled() || false\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"] }]
453
+ ], template: "@if (hints().length) {\r\n<form [formGroup]=\"form\" (submit)=\"emitRequestPatch()\">\r\n <table class=\"patches\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>location</th>\r\n <th>description</th>\r\n <th>patch</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (hint of hints(); track hint; let i = $index) {\r\n <tr>\r\n @if (!readonly()) {\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Edit this fragment\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Move this fragment to {{ targetLocation() }}\"\r\n [disabled]=\"\r\n disabled() ||\r\n !targetLocation() ||\r\n targetLocation() === hint.location\r\n \"\r\n (click)=\"emitRequestMove(hint)\"\r\n >\r\n <mat-icon>arrow_forward</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Delete this fragment\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"emitRequestDelete(hint)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n }\r\n <td>{{ hint.location }}</td>\r\n <td>{{ hint.description }}</td>\r\n <td>\r\n @if (hint.patchOperation) {\r\n <mat-checkbox\r\n matTooltip=\"Apply this patch\"\r\n [formControl]=\"checks.at(i)\"\r\n >\r\n {{ hint.patchOperation }}\r\n </mat-checkbox>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (targetLocation()) {\r\n <div>move target: {{ targetLocation() }}</div>\r\n }\r\n <button\r\n type=\"submit\"\r\n mat-flat-button\r\n [disabled]=\"readonly() || disabled() || form.invalid\"\r\n >\r\n apply patches\r\n </button>\r\n</form>\r\n}\r\n", styles: ["table.patches th{font-weight:400;color:#bdbdbd}\n"] }]
443
454
  }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2.DialogService }] });
444
455
 
445
456
  /**
@@ -566,10 +577,10 @@ class LookupPinComponent {
566
577
  this.clear();
567
578
  }
568
579
  }
569
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LookupPinComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i1$2.ItemService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
570
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: LookupPinComponent, isStandalone: true, selector: "cadmus-lookup-pin", inputs: { initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, limit: { classPropertyName: "limit", publicName: "limit", isSignal: true, isRequired: false, transformFunction: null }, resetOnPick: { classPropertyName: "resetOnPick", publicName: "resetOnPick", isSignal: true, isRequired: false, transformFunction: null }, lookupKey: { classPropertyName: "lookupKey", publicName: "lookupKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <mat-autocomplete #lookupAuto=\"matAutocomplete\" [displayWith]=\"entryToName\">\r\n @for (entry of entries$ | async; track entry) {\r\n <mat-option [value]=\"entry\" (onSelectionChange)=\"pickEntry(entry)\">\r\n {{ entry?.value }}\r\n </mat-option>\r\n }\r\n </mat-autocomplete>\r\n\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [placeholder]=\"label()\"\r\n [formControl]=\"lookup\"\r\n [matAutocomplete]=\"lookupAuto\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"clear()\"\r\n [disabled]=\"!entry()\"\r\n matTooltip=\"Clear\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n</form>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
580
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LookupPinComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i1$2.ItemService }, { token: 'indexLookupDefinitions' }], target: i0.ɵɵFactoryTarget.Component });
581
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: LookupPinComponent, isStandalone: true, selector: "cadmus-lookup-pin", inputs: { initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, limit: { classPropertyName: "limit", publicName: "limit", isSignal: true, isRequired: false, transformFunction: null }, resetOnPick: { classPropertyName: "resetOnPick", publicName: "resetOnPick", isSignal: true, isRequired: false, transformFunction: null }, lookupKey: { classPropertyName: "lookupKey", publicName: "lookupKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <mat-autocomplete #lookupAuto=\"matAutocomplete\" [displayWith]=\"entryToName\">\r\n @for (entry of entries$ | async; track entry) {\r\n <mat-option [value]=\"entry\" (onSelectionChange)=\"pickEntry(entry)\">\r\n {{ entry?.value }}\r\n </mat-option>\r\n }\r\n </mat-autocomplete>\r\n\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [placeholder]=\"label()\"\r\n [formControl]=\"lookup\"\r\n [matAutocomplete]=\"lookupAuto\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n (click)=\"clear()\"\r\n [disabled]=\"!entry()\"\r\n matTooltip=\"Clear\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n</form>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
571
582
  }
572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: LookupPinComponent, decorators: [{
583
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: LookupPinComponent, decorators: [{
573
584
  type: Component,
574
585
  args: [{ selector: 'cadmus-lookup-pin', imports: [
575
586
  FormsModule,
@@ -589,6 +600,630 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImpor
589
600
  args: ['indexLookupDefinitions']
590
601
  }] }] });
591
602
 
603
+ /**
604
+ * A label rendering function which removes from a label
605
+ * all the characters past the last colon, trimming the result.
606
+ * This is a typical rendering when dealing with hierarchical
607
+ * thesaurus entries, e.g. "furniture: table: color", where
608
+ * we can shorten the label to just "color", as "furniture"
609
+ * and "table" are its ancestors.
610
+ */
611
+ const renderLabelFromLastColon = (label) => {
612
+ if (!label) {
613
+ return label;
614
+ }
615
+ const i = label.lastIndexOf(':');
616
+ return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;
617
+ };
618
+ /**
619
+ * A static paged tree store service for thesaurus entries.
620
+ * This builds the tree nodes from the thesaurus entries, assuming
621
+ * that entry IDs are hierarchical and separated by dots (.).
622
+ */
623
+ class StaticThesPagedTreeStoreService {
624
+ _renderLabel;
625
+ _nodes = [];
626
+ _built = false;
627
+ _entries;
628
+ constructor(entries, _renderLabel) {
629
+ this._renderLabel = _renderLabel;
630
+ // assign a number to each entry for stable IDs
631
+ this._entries = entries.map((entry, index) => ({
632
+ ...entry,
633
+ n: index + 1,
634
+ }));
635
+ }
636
+ ensureNodes() {
637
+ // lazily build the nodes only once
638
+ if (this._built) {
639
+ return;
640
+ }
641
+ // map where key is node.id and value is max x value for that parent
642
+ // (0 is used for the virtual root)
643
+ const xMap = new Map();
644
+ for (const entry of this._entries) {
645
+ const hasDot = entry.id.includes('.');
646
+ const keyParts = entry.id.split('.');
647
+ // create the node
648
+ const node = {
649
+ id: entry.n,
650
+ label: hasDot && this._renderLabel
651
+ ? this._renderLabel(entry.value)
652
+ : entry.value,
653
+ key: entry.id,
654
+ value: entry.value,
655
+ paging: { pageNumber: 0, pageCount: 0, total: 0 },
656
+ y: hasDot ? keyParts.length : 1,
657
+ x: 0, // will be set later
658
+ parentId: undefined, // will be set later
659
+ hasChildren: false, // will be set later
660
+ };
661
+ // if it has a dot, find its parent and set parentId
662
+ if (hasDot) {
663
+ // build the parent key
664
+ const parentKey = keyParts.slice(0, keyParts.length - 1).join('.');
665
+ // find the parent node with that key
666
+ const parentNode = this._nodes.find((n) => n.key === parentKey);
667
+ // if found, set parentId and x in child and hasChildren in parent
668
+ if (parentNode) {
669
+ node.parentId = parentNode.id;
670
+ parentNode.hasChildren = true;
671
+ if (xMap.has(parentNode.id)) {
672
+ xMap.set(parentNode.id, xMap.get(parentNode.id) + 1);
673
+ }
674
+ else {
675
+ xMap.set(parentNode.id, 1);
676
+ }
677
+ node.x = xMap.get(parentNode.id);
678
+ }
679
+ else {
680
+ // parent not found, treat as root
681
+ if (xMap.has(0)) {
682
+ xMap.set(0, xMap.get(0) + 1);
683
+ }
684
+ else {
685
+ xMap.set(0, 1);
686
+ }
687
+ node.x = xMap.get(0);
688
+ }
689
+ }
690
+ else {
691
+ // else it's a root node
692
+ if (xMap.has(0)) {
693
+ xMap.set(0, xMap.get(0) + 1);
694
+ }
695
+ else {
696
+ xMap.set(0, 1);
697
+ }
698
+ node.x = xMap.get(0);
699
+ }
700
+ this._nodes.push(node);
701
+ }
702
+ this._built = true;
703
+ }
704
+ /**
705
+ * Get the specified page of nodes.
706
+ * @param filter The filter.
707
+ * @param pageNumber The page number.
708
+ * @param pageSize The page size.
709
+ * @param hasMockRoot Whether the root node is a mock node. Not used here.
710
+ */
711
+ getNodes(filter, pageNumber, pageSize, hasMockRoot) {
712
+ this.ensureNodes();
713
+ // apply filtering
714
+ let nodes = this._nodes.filter((n) => {
715
+ if (filter.parentId !== undefined && filter.parentId !== null) {
716
+ if (n.parentId !== filter.parentId) {
717
+ return false;
718
+ }
719
+ }
720
+ else {
721
+ if (n.parentId) {
722
+ return false;
723
+ }
724
+ }
725
+ if (filter.label) {
726
+ const filterValue = filter.label.toLowerCase();
727
+ if (!n.label.toLowerCase().includes(filterValue)) {
728
+ return false;
729
+ }
730
+ }
731
+ return true;
732
+ });
733
+ // apply paging
734
+ const startIndex = (pageNumber - 1) * pageSize;
735
+ const endIndex = startIndex + pageSize;
736
+ const pagedNodes = nodes.slice(startIndex, endIndex);
737
+ // page and return
738
+ const paged = nodes.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
739
+ return of({
740
+ items: paged,
741
+ pageNumber: pageNumber,
742
+ pageSize: pageSize,
743
+ pageCount: Math.ceil(nodes.length / pageSize),
744
+ total: nodes.length,
745
+ });
746
+ }
747
+ }
748
+
749
+ /**
750
+ * A filter to be used for thesaurus paged tree browsers.
751
+ */
752
+ class ThesPagedTreeFilterComponent {
753
+ dialogRef = inject(MatDialogRef, {
754
+ optional: true,
755
+ });
756
+ data = inject(MAT_DIALOG_DATA, { optional: true });
757
+ /**
758
+ * The filter.
759
+ */
760
+ filter = model(...(ngDevMode ? [undefined, { debugName: "filter" }] : []));
761
+ wrapped = signal(false, ...(ngDevMode ? [{ debugName: "wrapped" }] : []));
762
+ label;
763
+ form;
764
+ constructor() {
765
+ const formBuilder = inject(FormBuilder);
766
+ const data = this.data;
767
+ // form
768
+ this.label = formBuilder.control(null);
769
+ this.form = formBuilder.group({
770
+ label: this.label,
771
+ });
772
+ // bind dialog data if any
773
+ if (this.dialogRef) {
774
+ this.wrapped.set(true);
775
+ if (data) {
776
+ this.filter.set(data.filter);
777
+ }
778
+ }
779
+ else {
780
+ this.wrapped.set(false);
781
+ }
782
+ // update form when filter changes
783
+ effect(() => {
784
+ this.updateForm(this.filter());
785
+ });
786
+ }
787
+ ngOnInit() {
788
+ this.updateForm(this.filter());
789
+ }
790
+ updateForm(filter) {
791
+ if (!filter) {
792
+ this.form.reset();
793
+ return;
794
+ }
795
+ this.label.setValue(filter.label ?? null);
796
+ this.form.markAsPristine();
797
+ }
798
+ getFilter() {
799
+ return {
800
+ label: this.label.value ?? undefined,
801
+ };
802
+ }
803
+ reset() {
804
+ this.form.reset();
805
+ this.filter.set(null);
806
+ this.dialogRef?.close(null);
807
+ }
808
+ apply() {
809
+ this.filter.set(this.getFilter());
810
+ this.dialogRef?.close(this.filter());
811
+ }
812
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
813
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: ThesPagedTreeFilterComponent, isStandalone: true, selector: "cadmus-thes-paged-tree-filter", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filter: "filterChange" }, ngImport: i0, template: "<form\r\n [formGroup]=\"form\"\r\n [style.margin.px]=\"wrapped() ? 16 : 0\"\r\n (submit)=\"apply()\"\r\n>\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <input matInput placeholder=\"label\" [formControl]=\"label\" />\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- buttons -->\r\n <button type=\"button\" mat-icon-button matTooltip=\"Reset\" (click)=\"reset()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Apply\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i6.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
814
+ }
815
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeFilterComponent, decorators: [{
816
+ type: Component,
817
+ args: [{ selector: 'cadmus-thes-paged-tree-filter', imports: [
818
+ ReactiveFormsModule,
819
+ MatButtonModule,
820
+ MatFormFieldModule,
821
+ MatInputModule,
822
+ MatIconModule,
823
+ MatTooltipModule,
824
+ ], template: "<form\r\n [formGroup]=\"form\"\r\n [style.margin.px]=\"wrapped() ? 16 : 0\"\r\n (submit)=\"apply()\"\r\n>\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <input matInput placeholder=\"label\" [formControl]=\"label\" />\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- buttons -->\r\n <button type=\"button\" mat-icon-button matTooltip=\"Reset\" (click)=\"reset()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Apply\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}\n"] }]
825
+ }], ctorParameters: () => [] });
826
+
827
+ class ThesPagedTreeBrowserComponent {
828
+ _dialog = inject(MatDialog);
829
+ _sub;
830
+ /**
831
+ * The service to use to load the nodes.
832
+ */
833
+ service = input(new StaticThesPagedTreeStoreService([], renderLabelFromLastColon), ...(ngDevMode ? [{ debugName: "service" }] : []));
834
+ /**
835
+ * Emitted when a node is clicked.
836
+ */
837
+ nodePick = output();
838
+ /**
839
+ * The store instance, built from the service.
840
+ */
841
+ store = computed(() => {
842
+ const service = this.service();
843
+ const store = new PagedTreeStore(service);
844
+ this.nodes$ = store.nodes$;
845
+ this.filter$ = store.filter$;
846
+ return store;
847
+ }, ...(ngDevMode ? [{ debugName: "store" }] : []));
848
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
849
+ debug = new FormControl(false, {
850
+ nonNullable: true,
851
+ });
852
+ hideLoc = new FormControl(false, {
853
+ nonNullable: true,
854
+ });
855
+ hideFilter = new FormControl(false, {
856
+ nonNullable: true,
857
+ });
858
+ filter$;
859
+ nodes$;
860
+ label = new FormControl(null);
861
+ form = new FormGroup({
862
+ label: this.label,
863
+ });
864
+ constructor() {
865
+ const store = this.store();
866
+ this.nodes$ = store.nodes$;
867
+ this.filter$ = store.filter$;
868
+ }
869
+ ngOnInit() {
870
+ if (!this.store().getNodes().length) {
871
+ this.loading.set(true);
872
+ this.store()
873
+ .setFilter({})
874
+ .finally(() => {
875
+ this.loading.set(false);
876
+ console.log('nodes loaded', this.store().getNodes());
877
+ });
878
+ }
879
+ }
880
+ ngOnDestroy() {
881
+ this._sub?.unsubscribe();
882
+ }
883
+ reset() {
884
+ this.loading.set(true);
885
+ this.store()
886
+ .reset()
887
+ .finally(() => {
888
+ this.loading.set(false);
889
+ });
890
+ }
891
+ onToggleExpanded(node) {
892
+ this.loading.set(true);
893
+ if (node.expanded) {
894
+ this.store()
895
+ .collapse(node.id)
896
+ .finally(() => {
897
+ this.loading.set(false);
898
+ });
899
+ }
900
+ else {
901
+ this.store()
902
+ .expand(node.id)
903
+ .finally(() => {
904
+ this.loading.set(false);
905
+ });
906
+ }
907
+ }
908
+ onPageChangeRequest(request) {
909
+ this.loading.set(true);
910
+ this.store()
911
+ .changePage(request.node.id, request.paging.pageNumber)
912
+ .finally(() => {
913
+ this.loading.set(false);
914
+ });
915
+ }
916
+ onFilterChange(filter) {
917
+ console.log('filter change', filter);
918
+ this.loading.set(true);
919
+ this.store()
920
+ .setFilter(filter || {})
921
+ .finally(() => {
922
+ this.loading.set(false);
923
+ });
924
+ }
925
+ onEditFilterRequest(node) {
926
+ const dialogRef = this._dialog.open(ThesPagedTreeFilterComponent, {
927
+ data: {
928
+ filter: node.filter,
929
+ },
930
+ });
931
+ dialogRef.afterClosed().subscribe((filter) => {
932
+ // undefined = user dismissed without changes
933
+ if (filter === null) {
934
+ this.store().setNodeFilter(node.id, null);
935
+ }
936
+ else if (filter) {
937
+ this.store().setNodeFilter(node.id, filter);
938
+ }
939
+ });
940
+ }
941
+ expandAll() {
942
+ this.store().expandAll();
943
+ }
944
+ collapseAll() {
945
+ this.store().collapseAll();
946
+ }
947
+ clear() {
948
+ this.store().clear();
949
+ }
950
+ onNodeClick(node) {
951
+ if (!node.hasChildren) {
952
+ this.nodePick.emit(node);
953
+ }
954
+ }
955
+ findLabels() {
956
+ if (!this.label.value) {
957
+ return;
958
+ }
959
+ this.store().findLabels(this.label.value);
960
+ }
961
+ removeHilites() {
962
+ this.store().removeHilites();
963
+ }
964
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeBrowserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
965
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesPagedTreeBrowserComponent, isStandalone: true, selector: "cadmus-thes-paged-tree-browser", inputs: { service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodePick: "nodePick" }, ngImport: i0, template: "<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\" class=\"form-row\">\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n }\r\n </mat-form-field>\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button (click)=\"removeHilites()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thes-paged-tree-filter\r\n [filter]=\"filter$ | async\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n\r\n <!-- tree -->\r\n <div id=\"tree\">\r\n <!-- progress -->\r\n @if (loading()) {\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n </div>\r\n }\r\n <!-- nodes -->\r\n @if (nodes$ | async; as nodes) {\r\n <div>\r\n @for (node of nodes; track node.id; let i = $index) {\r\n <div class=\"button-row\" [class.hilite]=\"node.hilite\">\r\n <pdb-browser-tree-node\r\n [node]=\"node\"\r\n [debug]=\"debug.value\"\r\n [paging]=\"\r\n node.expanded &&\r\n i + 1 < nodes.length &&\r\n nodes[i + 1].paging.pageCount > 1\r\n ? nodes[i + 1].paging\r\n : undefined\r\n \"\r\n [hideFilter]=\"hideFilter.value\"\r\n [hideLoc]=\"hideLoc.value\"\r\n (toggleExpandedRequest)=\"onToggleExpanded($any($event))\"\r\n (changePageRequest)=\"onPageChangeRequest($event)\"\r\n (editNodeFilterRequest)=\"onEditFilterRequest($any($event))\"\r\n />\r\n @if (!node.hasChildren) {\r\n <button type=\"button\" mat-icon-button (click)=\"onNodeClick(node)\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <div class=\"form-row\">\r\n <mat-checkbox [formControl]=\"debug\">debug</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideFilter\">no filter</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideLoc\">no loc.</mat-checkbox>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n (click)=\"collapseAll()\"\r\n style=\"margin-left: 24px\"\r\n >\r\n collapse\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.hilite{background-color:#ffffe0;border:2px solid gold;border-radius:6px;padding:2px 4px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: ThesPagedTreeFilterComponent, selector: "cadmus-thes-paged-tree-filter", inputs: ["filter"], outputs: ["filterChange"] }, { kind: "component", type: BrowserTreeNodeComponent, selector: "pdb-browser-tree-node", inputs: ["node", "paging", "debug", "hideLabel", "hideLoc", "hidePaging", "hideFilter", "indentSize", "rangeWidth"], outputs: ["toggleExpandedRequest", "changePageRequest", "editNodeFilterRequest"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
966
+ }
967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesPagedTreeBrowserComponent, decorators: [{
968
+ type: Component,
969
+ args: [{ selector: 'cadmus-thes-paged-tree-browser', imports: [
970
+ AsyncPipe,
971
+ ReactiveFormsModule,
972
+ MatButtonModule,
973
+ MatCheckboxModule,
974
+ MatFormFieldModule,
975
+ MatIconModule,
976
+ MatInputModule,
977
+ MatProgressBarModule,
978
+ MatTooltipModule,
979
+ ThesPagedTreeFilterComponent,
980
+ BrowserTreeNodeComponent,
981
+ ], template: "<div id=\"container\">\r\n <!-- filters -->\r\n <div id=\"filters\" class=\"form-row\">\r\n <form [formGroup]=\"form\" (submit)=\"findLabels()\" class=\"form-row\">\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n }\r\n </mat-form-field>\r\n <button type=\"submit\" mat-icon-button class=\"mat-primary\">\r\n <mat-icon>search</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button (click)=\"removeHilites()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </form>\r\n <fieldset>\r\n <legend>filter</legend>\r\n <cadmus-thes-paged-tree-filter\r\n [filter]=\"filter$ | async\"\r\n (filterChange)=\"onFilterChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n\r\n <!-- tree -->\r\n <div id=\"tree\">\r\n <!-- progress -->\r\n @if (loading()) {\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n </div>\r\n }\r\n <!-- nodes -->\r\n @if (nodes$ | async; as nodes) {\r\n <div>\r\n @for (node of nodes; track node.id; let i = $index) {\r\n <div class=\"button-row\" [class.hilite]=\"node.hilite\">\r\n <pdb-browser-tree-node\r\n [node]=\"node\"\r\n [debug]=\"debug.value\"\r\n [paging]=\"\r\n node.expanded &&\r\n i + 1 < nodes.length &&\r\n nodes[i + 1].paging.pageCount > 1\r\n ? nodes[i + 1].paging\r\n : undefined\r\n \"\r\n [hideFilter]=\"hideFilter.value\"\r\n [hideLoc]=\"hideLoc.value\"\r\n (toggleExpandedRequest)=\"onToggleExpanded($any($event))\"\r\n (changePageRequest)=\"onPageChangeRequest($event)\"\r\n (editNodeFilterRequest)=\"onEditFilterRequest($any($event))\"\r\n />\r\n @if (!node.hasChildren) {\r\n <button type=\"button\" mat-icon-button (click)=\"onNodeClick(node)\">\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <div class=\"form-row\">\r\n <mat-checkbox [formControl]=\"debug\">debug</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideFilter\">no filter</mat-checkbox>\r\n <mat-checkbox [formControl]=\"hideLoc\">no loc.</mat-checkbox>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n (click)=\"collapseAll()\"\r\n style=\"margin-left: 24px\"\r\n >\r\n collapse\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["form{margin:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:6em}fieldset{border:1px solid silver;border-radius:6px;padding:8px 16px;margin:8px 0}legend{color:silver}th{text-align:left;font-weight:400}#tag-selector{width:8em}.tag-chip{border:2px solid transparent;border-radius:6px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.hilite{background-color:#ffffe0;border:2px solid gold;border-radius:6px;padding:2px 4px}\n"] }]
982
+ }], ctorParameters: () => [] });
983
+
984
+ /**
985
+ * Thesaurus tree component.
986
+ * This component displays a set of hierarchical thesaurus entries
987
+ * in a tree, provided that each entry marks its hierarchy with
988
+ * dots. For instance, say you have the hierarchy "furniture" -
989
+ * "type" - "color". You might have an entry whose ID is
990
+ * "furniture.table.red", with a sibling "furniture.table.green",
991
+ * and a parent "furniture.table". This parent is there only to
992
+ * provide a label to the parent node, but only leaf nodes can be
993
+ * picked by the user. Whenever one is picked, the entryChange
994
+ * event is emitted. Note that even if you specify a label renderer
995
+ * function, the event always emits the original label.
996
+ */
997
+ class ThesaurusTreeComponent {
998
+ /**
999
+ * The thesaurus entries.
1000
+ */
1001
+ entries = input(...(ngDevMode ? [undefined, { debugName: "entries" }] : []));
1002
+ /**
1003
+ * The optional node label rendering function.
1004
+ */
1005
+ renderLabel = input(renderLabelFromLastColon, ...(ngDevMode ? [{ debugName: "renderLabel" }] : []));
1006
+ /**
1007
+ * Fired when a thesaurus entry is selected.
1008
+ */
1009
+ entryChange = output();
1010
+ /**
1011
+ * The tree store service, dependent on the current entries and renderLabel.
1012
+ */
1013
+ service = computed(() => {
1014
+ const entries = this.entries();
1015
+ return new StaticThesPagedTreeStoreService(entries || [], this.renderLabel());
1016
+ }, ...(ngDevMode ? [{ debugName: "service" }] : []));
1017
+ /**
1018
+ * The filter component class to use.
1019
+ */
1020
+ filterComponent = ThesPagedTreeFilterComponent;
1021
+ onNodePick(node) {
1022
+ // only allow selection of leaf nodes (nodes without children)
1023
+ if (!node.hasChildren) {
1024
+ // find the original entry
1025
+ const entry = this.entries()?.find((e) => e.id === node.key);
1026
+ if (entry) {
1027
+ this.entryChange.emit(entry);
1028
+ }
1029
+ }
1030
+ }
1031
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesaurusTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1032
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesaurusTreeComponent, isStandalone: true, selector: "cadmus-thesaurus-tree", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, renderLabel: { classPropertyName: "renderLabel", publicName: "renderLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<div>\r\n <!-- tree -->\r\n @if (service() && entries()?.length) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thes-paged-tree-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}.filter-field{width:100%;margin-bottom:1rem}.tree-container{border:1px solid #e0e0e0;border-radius:4px;overflow:auto;max-height:500px}.tree-wrapper{border:1px solid #e0e0e0;border-radius:4px;overflow:hidden;background:#fff}.no-entries{text-align:center;padding:2rem;color:#666;font-style:italic;border:1px solid #e0e0e0;border-radius:4px;background:#f9f9f9}.no-entries p{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ThesPagedTreeBrowserComponent, selector: "cadmus-thes-paged-tree-browser", inputs: ["service"], outputs: ["nodePick"] }] });
1033
+ }
1034
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
1035
+ type: Component,
1036
+ args: [{ selector: 'cadmus-thesaurus-tree', imports: [FormsModule, ReactiveFormsModule, ThesPagedTreeBrowserComponent], template: "<div>\r\n <!-- tree -->\r\n @if (service() && entries()?.length) {\r\n <div class=\"tree-wrapper\">\r\n <cadmus-thes-paged-tree-browser\r\n [service]=\"service()\"\r\n (nodePick)=\"onNodePick($event)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}.filter-field{width:100%;margin-bottom:1rem}.tree-container{border:1px solid #e0e0e0;border-radius:4px;overflow:auto;max-height:500px}.tree-wrapper{border:1px solid #e0e0e0;border-radius:4px;overflow:hidden;background:#fff}.no-entries{text-align:center;padding:2rem;color:#666;font-style:italic;border:1px solid #e0e0e0;border-radius:4px;background:#f9f9f9}.no-entries p{margin:0}\n"] }]
1037
+ }] });
1038
+
1039
+ /**
1040
+ * The prefix added to custom entries' IDs.
1041
+ */
1042
+ const CUSTOM_ENTRY_PREFIX = '$';
1043
+ /**
1044
+ * A picker component for thesaurus entries.
1045
+ * This component allows picking one or more entries from a given thesaurus.
1046
+ * In its collapsed state, it shows the picked entries as chips; when
1047
+ * expanded, it shows the thesaurus tree to pick from. Custom entries
1048
+ * (not in the thesaurus) can be optionally allowed.
1049
+ */
1050
+ class ThesEntriesPickerComponent {
1051
+ /**
1052
+ * The thesaurus entries to pick from (required).
1053
+ */
1054
+ availableEntries = input.required(...(ngDevMode ? [{ debugName: "availableEntries" }] : []));
1055
+ /**
1056
+ * The picked entries.
1057
+ */
1058
+ entries = model([], ...(ngDevMode ? [{ debugName: "entries" }] : []));
1059
+ /**
1060
+ * True to show the entries with labels shortened according to
1061
+ * their hierarchy.
1062
+ */
1063
+ hierarchicLabels = input(false, ...(ngDevMode ? [{ debugName: "hierarchicLabels" }] : []));
1064
+ /**
1065
+ * True to automatically sort entries (disables drag-and-drop).
1066
+ * When false, entries can be manually reordered via drag-and-drop.
1067
+ */
1068
+ autoSort = input(false, ...(ngDevMode ? [{ debugName: "autoSort" }] : []));
1069
+ /**
1070
+ * True to allow custom values (not in the entries list).
1071
+ */
1072
+ allowCustom = input(false, ...(ngDevMode ? [{ debugName: "allowCustom" }] : []));
1073
+ /**
1074
+ * The minimum number of entries to pick.
1075
+ */
1076
+ minEntries = input(0, ...(ngDevMode ? [{ debugName: "minEntries" }] : []));
1077
+ /**
1078
+ * The maximum number of entries to pick (0=unlimited).
1079
+ */
1080
+ maxEntries = input(0, ...(ngDevMode ? [{ debugName: "maxEntries" }] : []));
1081
+ /**
1082
+ * True when the picker is expanded (showing the entries list).
1083
+ */
1084
+ expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
1085
+ /**
1086
+ * The message to show when there are no picked entries.
1087
+ */
1088
+ emptyMessage = input('no entries', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : []));
1089
+ /**
1090
+ * The number of remaining entries that can be picked (0=unlimited).
1091
+ * This is displayed only if maxEntries > 1.
1092
+ */
1093
+ remaining = computed(() => {
1094
+ if (this.maxEntries() > 0) {
1095
+ return this.maxEntries() - this.entries().length;
1096
+ }
1097
+ return 0;
1098
+ }, ...(ngDevMode ? [{ debugName: "remaining" }] : []));
1099
+ id;
1100
+ value;
1101
+ form;
1102
+ constructor(formBuilder) {
1103
+ this.id = formBuilder.control('', {
1104
+ validators: [Validators.required, Validators.maxLength(100)],
1105
+ nonNullable: true,
1106
+ });
1107
+ this.value = formBuilder.control('', {
1108
+ validators: [Validators.required, Validators.maxLength(500)],
1109
+ nonNullable: true,
1110
+ });
1111
+ this.form = formBuilder.group({
1112
+ id: this.id,
1113
+ value: this.value,
1114
+ });
1115
+ // if auto-sort is turned on and we have entries, sort them
1116
+ effect(() => {
1117
+ // only track autoSort() changes, not entries()
1118
+ const shouldSort = this.autoSort();
1119
+ if (shouldSort) {
1120
+ // use untracked to read entries without creating a dependency
1121
+ const currentEntries = untracked(() => this.entries());
1122
+ if (currentEntries.length > 1) {
1123
+ const entries = [...currentEntries];
1124
+ this.sortEntries(entries);
1125
+ this.entries.set(entries);
1126
+ }
1127
+ }
1128
+ }, { allowSignalWrites: true });
1129
+ }
1130
+ // need arrow function to use 'this'
1131
+ renderLabel = (label) => {
1132
+ return this.hierarchicLabels() ? renderLabelFromLastColon(label) : label;
1133
+ };
1134
+ sortEntries(entries) {
1135
+ entries.sort((a, b) => {
1136
+ const aIsCustom = a.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;
1137
+ const bIsCustom = b.id?.startsWith(CUSTOM_ENTRY_PREFIX) ?? false;
1138
+ if (aIsCustom !== bIsCustom) {
1139
+ // place custom entries after non-custom ones
1140
+ return aIsCustom ? 1 : -1;
1141
+ }
1142
+ // same kind: sort by label/value
1143
+ return a.value.localeCompare(b.value);
1144
+ });
1145
+ }
1146
+ onEntryChange(entry) {
1147
+ // check if already present
1148
+ if (this.entries().some((e) => e.id === entry.id)) {
1149
+ return;
1150
+ }
1151
+ // check if limit is reached
1152
+ if (this.maxEntries() && this.entries().length >= this.maxEntries()) {
1153
+ return;
1154
+ }
1155
+ const entries = [...this.entries()];
1156
+ entries.push(entry);
1157
+ if (this.autoSort()) {
1158
+ this.sortEntries(entries);
1159
+ }
1160
+ this.entries.set(entries);
1161
+ }
1162
+ addCustomEntry() {
1163
+ if (this.form.invalid) {
1164
+ return;
1165
+ }
1166
+ // create the custom entry
1167
+ const customEntry = {
1168
+ id: CUSTOM_ENTRY_PREFIX + this.id.value,
1169
+ value: this.value.value,
1170
+ };
1171
+ // check if already present
1172
+ if (this.entries().some((e) => e.id === customEntry.id)) {
1173
+ return;
1174
+ }
1175
+ // check if limit is reached
1176
+ if (this.maxEntries() && this.entries().length >= this.maxEntries()) {
1177
+ return;
1178
+ }
1179
+ const entries = [...this.entries()];
1180
+ entries.push(customEntry);
1181
+ if (this.autoSort()) {
1182
+ this.sortEntries(entries);
1183
+ }
1184
+ this.entries.set(entries);
1185
+ this.form.reset();
1186
+ }
1187
+ removeEntry(entry) {
1188
+ const entries = [...this.entries().filter((e) => e.id !== entry.id)];
1189
+ this.entries.set(entries);
1190
+ }
1191
+ clear() {
1192
+ this.entries.set([]);
1193
+ // if min > 0, expand the picker
1194
+ if (this.minEntries() > 0 && !this.expanded()) {
1195
+ setTimeout(() => {
1196
+ this.expanded.set(true);
1197
+ }, 0);
1198
+ }
1199
+ }
1200
+ onDrop(event) {
1201
+ const entries = [...this.entries()];
1202
+ moveItemInArray(entries, event.previousIndex, event.currentIndex);
1203
+ this.entries.set(entries);
1204
+ }
1205
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesEntriesPickerComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1206
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: ThesEntriesPickerComponent, isStandalone: true, selector: "cadmus-thes-entries-picker", inputs: { availableEntries: { classPropertyName: "availableEntries", publicName: "availableEntries", isSignal: true, isRequired: true, transformFunction: null }, entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, hierarchicLabels: { classPropertyName: "hierarchicLabels", publicName: "hierarchicLabels", isSignal: true, isRequired: false, transformFunction: null }, autoSort: { classPropertyName: "autoSort", publicName: "autoSort", isSignal: true, isRequired: false, transformFunction: null }, allowCustom: { classPropertyName: "allowCustom", publicName: "allowCustom", isSignal: true, isRequired: false, transformFunction: null }, minEntries: { classPropertyName: "minEntries", publicName: "minEntries", isSignal: true, isRequired: false, transformFunction: null }, maxEntries: { classPropertyName: "maxEntries", publicName: "maxEntries", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entries: "entriesChange", expanded: "expandedChange" }, ngImport: i0, template: "<div id=\"container\">\r\n <!-- picked entries -->\r\n <div id=\"picked\" class=\"form-row\">\r\n <!-- count -->\r\n <span class=\"nr\" [class.error]=\"entries().length < minEntries()\">{{\r\n entries().length\r\n }}</span>\r\n <!-- max-->\r\n @if (maxEntries() > 1) {\r\n <span class=\"muted\">/{{ maxEntries() }}</span>\r\n @if (remaining()) {\r\n <span class=\"muted\">: -{{ remaining() }}</span>\r\n } }\r\n <!-- min -->\r\n @if (minEntries()) {\r\n <!-- min with error -->\r\n @if (entries().length < minEntries()) {\r\n <span class=\"error\"> (min {{ minEntries() }})</span>\r\n }\r\n <!-- min without error -->\r\n @else {\r\n <span class=\"muted\"> (min {{ minEntries() }})</span>\r\n } }\r\n <!-- list -->\r\n <mat-chip-listbox\r\n [cdkDropListDisabled]=\"autoSort()\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"chip-list\"\r\n >\r\n @for (e of entries(); track e.id; let idx = $index) {\r\n <div class=\"chip-wrapper\">\r\n <mat-chip-option\r\n [cdkDragDisabled]=\"autoSort()\"\r\n cdkDrag\r\n [class.error]=\"!allowCustom() && e.id.startsWith('$')\"\r\n >\r\n {{ renderLabel(e.value) }}\r\n <button\r\n type=\"button\"\r\n matChipRemove\r\n (click)=\"removeEntry(e)\"\r\n aria-label=\"Remove entry\"\r\n >\r\n <mat-icon class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-chip-option>\r\n </div>\r\n } @empty {\r\n <span class=\"muted empty-message\">{{ emptyMessage() }}</span>\r\n }\r\n </mat-chip-listbox>\r\n\r\n <!-- clear -->\r\n @if (entries().length > 0) {\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove all entries\"\r\n (click)=\"clear()\"\r\n [disabled]=\"entries().length === 0\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n }\r\n <!-- toggler -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Toggle picker\"\r\n (click)=\"expanded.set(!expanded())\"\r\n >\r\n @if (expanded()) {\r\n <mat-icon class=\"mat-primary\">publish</mat-icon>\r\n } @if (!expanded()) {\r\n <mat-icon class=\"mat-primary\">get_app</mat-icon>\r\n }\r\n </button>\r\n </div>\r\n\r\n <!-- entries picker -->\r\n <div id=\"picker\">\r\n <mat-expansion-panel\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"expanded.set($event)\"\r\n >\r\n <div>\r\n <fieldset>\r\n <legend>available</legend>\r\n <cadmus-thesaurus-tree\r\n [entries]=\"availableEntries()\"\r\n [renderLabel]=\"renderLabel\"\r\n (entryChange)=\"onEntryChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n @if (allowCustom()) {\r\n <div>\r\n <form [formGroup]=\"form\" (submit)=\"addCustomEntry()\">\r\n <fieldset>\r\n <legend>custom</legend>\r\n <div class=\"form-row\">\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"id\"\r\n placeholder=\"ID\"\r\n />\r\n </mat-form-field>\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"value\"\r\n placeholder=\"label\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Add custom entry\"\r\n [disabled]=\"\r\n !form.valid ||\r\n (maxEntries() > 0 && entries().length >= maxEntries())\r\n \"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n </div>\r\n }\r\n </mat-expansion-panel>\r\n </div>\r\n</div>\r\n", styles: ["#container{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.error{color:#8b0000}.nr{font-weight:700}.muted{color:gray}fieldset{border:1px solid silver;border-radius:8px;padding:8px 16px}.chip-list{display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding:4px}.chip-wrapper{display:inline-flex;position:relative;margin:2px}.chip-list mat-chip-option:not([cdkDragDisabled]){cursor:grab}.chip-list mat-chip-option:not([cdkDragDisabled]):active{cursor:grabbing}.chip-list mat-chip-option[cdkDragDisabled]{cursor:default}.chip-list .empty-message{margin-left:0}.chip-list mat-chip-option.mat-mdc-chip-selected{background-color:inherit}.chip-list mat-chip-option:not(.error).mat-mdc-chip-selected{background-color:#e0e0e0}mat-chip-option.error{background-color:#ffebee!important;border:1px solid darkred}.cdk-drag-preview{opacity:.95;box-shadow:0 8px 20px #0006;transform:rotate(3deg)}.drag-placeholder{width:4px;background:#1976d2;border-radius:2px;height:36px;box-shadow:0 0 8px #1976d299;animation:pulse .5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:.6;transform:scaleY(1)}50%{opacity:1;transform:scaleY(1.1)}}.chip-list .cdk-drag-placeholder{opacity:0;width:4px;min-width:4px}.chip-wrapper{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper{will-change:transform}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ThesaurusTreeComponent, selector: "cadmus-thesaurus-tree", inputs: ["entries", "renderLabel"], outputs: ["entryChange"] }] });
1207
+ }
1208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ThesEntriesPickerComponent, decorators: [{
1209
+ type: Component,
1210
+ args: [{ selector: 'cadmus-thes-entries-picker', imports: [
1211
+ ReactiveFormsModule,
1212
+ CdkDropList,
1213
+ CdkDrag,
1214
+ MatChipListbox,
1215
+ MatChipOption,
1216
+ MatChipRemove,
1217
+ MatExpansionPanel,
1218
+ MatFormField,
1219
+ MatIconButton,
1220
+ MatIcon,
1221
+ MatInput,
1222
+ MatTooltip,
1223
+ ThesaurusTreeComponent,
1224
+ ], template: "<div id=\"container\">\r\n <!-- picked entries -->\r\n <div id=\"picked\" class=\"form-row\">\r\n <!-- count -->\r\n <span class=\"nr\" [class.error]=\"entries().length < minEntries()\">{{\r\n entries().length\r\n }}</span>\r\n <!-- max-->\r\n @if (maxEntries() > 1) {\r\n <span class=\"muted\">/{{ maxEntries() }}</span>\r\n @if (remaining()) {\r\n <span class=\"muted\">: -{{ remaining() }}</span>\r\n } }\r\n <!-- min -->\r\n @if (minEntries()) {\r\n <!-- min with error -->\r\n @if (entries().length < minEntries()) {\r\n <span class=\"error\"> (min {{ minEntries() }})</span>\r\n }\r\n <!-- min without error -->\r\n @else {\r\n <span class=\"muted\"> (min {{ minEntries() }})</span>\r\n } }\r\n <!-- list -->\r\n <mat-chip-listbox\r\n [cdkDropListDisabled]=\"autoSort()\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"chip-list\"\r\n >\r\n @for (e of entries(); track e.id; let idx = $index) {\r\n <div class=\"chip-wrapper\">\r\n <mat-chip-option\r\n [cdkDragDisabled]=\"autoSort()\"\r\n cdkDrag\r\n [class.error]=\"!allowCustom() && e.id.startsWith('$')\"\r\n >\r\n {{ renderLabel(e.value) }}\r\n <button\r\n type=\"button\"\r\n matChipRemove\r\n (click)=\"removeEntry(e)\"\r\n aria-label=\"Remove entry\"\r\n >\r\n <mat-icon class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-chip-option>\r\n </div>\r\n } @empty {\r\n <span class=\"muted empty-message\">{{ emptyMessage() }}</span>\r\n }\r\n </mat-chip-listbox>\r\n\r\n <!-- clear -->\r\n @if (entries().length > 0) {\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove all entries\"\r\n (click)=\"clear()\"\r\n [disabled]=\"entries().length === 0\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n }\r\n <!-- toggler -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Toggle picker\"\r\n (click)=\"expanded.set(!expanded())\"\r\n >\r\n @if (expanded()) {\r\n <mat-icon class=\"mat-primary\">publish</mat-icon>\r\n } @if (!expanded()) {\r\n <mat-icon class=\"mat-primary\">get_app</mat-icon>\r\n }\r\n </button>\r\n </div>\r\n\r\n <!-- entries picker -->\r\n <div id=\"picker\">\r\n <mat-expansion-panel\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"expanded.set($event)\"\r\n >\r\n <div>\r\n <fieldset>\r\n <legend>available</legend>\r\n <cadmus-thesaurus-tree\r\n [entries]=\"availableEntries()\"\r\n [renderLabel]=\"renderLabel\"\r\n (entryChange)=\"onEntryChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n @if (allowCustom()) {\r\n <div>\r\n <form [formGroup]=\"form\" (submit)=\"addCustomEntry()\">\r\n <fieldset>\r\n <legend>custom</legend>\r\n <div class=\"form-row\">\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"id\"\r\n placeholder=\"ID\"\r\n />\r\n </mat-form-field>\r\n <mat-form-field>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [formControl]=\"value\"\r\n placeholder=\"label\"\r\n />\r\n </mat-form-field>\r\n <button\r\n type=\"submit\"\r\n mat-icon-button\r\n matTooltip=\"Add custom entry\"\r\n [disabled]=\"\r\n !form.valid ||\r\n (maxEntries() > 0 && entries().length >= maxEntries())\r\n \"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n </div>\r\n }\r\n </mat-expansion-panel>\r\n </div>\r\n</div>\r\n", styles: ["#container{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.error{color:#8b0000}.nr{font-weight:700}.muted{color:gray}fieldset{border:1px solid silver;border-radius:8px;padding:8px 16px}.chip-list{display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding:4px}.chip-wrapper{display:inline-flex;position:relative;margin:2px}.chip-list mat-chip-option:not([cdkDragDisabled]){cursor:grab}.chip-list mat-chip-option:not([cdkDragDisabled]):active{cursor:grabbing}.chip-list mat-chip-option[cdkDragDisabled]{cursor:default}.chip-list .empty-message{margin-left:0}.chip-list mat-chip-option.mat-mdc-chip-selected{background-color:inherit}.chip-list mat-chip-option:not(.error).mat-mdc-chip-selected{background-color:#e0e0e0}mat-chip-option.error{background-color:#ffebee!important;border:1px solid darkred}.cdk-drag-preview{opacity:.95;box-shadow:0 8px 20px #0006;transform:rotate(3deg)}.drag-placeholder{width:4px;background:#1976d2;border-radius:2px;height:36px;box-shadow:0 0 8px #1976d299;animation:pulse .5s ease-in-out infinite}@keyframes pulse{0%,to{opacity:.6;transform:scaleY(1)}50%{opacity:1;transform:scaleY(1.1)}}.chip-list .cdk-drag-placeholder{opacity:0;width:4px;min-width:4px}.chip-wrapper{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .chip-wrapper{will-change:transform}\n"] }]
1225
+ }], ctorParameters: () => [{ type: i1$1.FormBuilder }] });
1226
+
592
1227
  var PartBadgeType;
593
1228
  (function (PartBadgeType) {
594
1229
  PartBadgeType[PartBadgeType["partAndRole"] = 0] = "partAndRole";
@@ -703,245 +1338,14 @@ class PartBadgeComponent {
703
1338
  }
704
1339
  this.contrastColor.set(this._colorService.getContrastColor(this.color()));
705
1340
  }
706
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: PartBadgeComponent, deps: [{ token: i1$2.FacetService }, { token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
707
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: PartBadgeComponent, isStandalone: true, selector: "cadmus-part-badge", inputs: { badgeType: { classPropertyName: "badgeType", publicName: "badgeType", isSignal: true, isRequired: false, transformFunction: null }, typeThesaurus: { classPropertyName: "typeThesaurus", publicName: "typeThesaurus", isSignal: true, isRequired: false, transformFunction: null }, facetDefinition: { classPropertyName: "facetDefinition", publicName: "facetDefinition", isSignal: true, isRequired: false, transformFunction: null }, partTypeIds: { classPropertyName: "partTypeIds", publicName: "partTypeIds", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (badgeType() !== 2) {\r\n<span\r\n class=\"part-badge\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n>\r\n {{ typeName() }}\r\n</span>\r\n} @if (badgeType() !== 1 && roleName()) {\r\n<span class=\"role-badge\">\r\n {{ roleName() }}\r\n</span>\r\n}\r\n", styles: [".part-badge{padding:4px;border-radius:6px}.role-badge{padding:4px;border:1px solid silver;border-radius:6px}\n"] });
1341
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: PartBadgeComponent, deps: [{ token: i1$2.FacetService }, { token: ColorService }], target: i0.ɵɵFactoryTarget.Component });
1342
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: PartBadgeComponent, isStandalone: true, selector: "cadmus-part-badge", inputs: { badgeType: { classPropertyName: "badgeType", publicName: "badgeType", isSignal: true, isRequired: false, transformFunction: null }, typeThesaurus: { classPropertyName: "typeThesaurus", publicName: "typeThesaurus", isSignal: true, isRequired: false, transformFunction: null }, facetDefinition: { classPropertyName: "facetDefinition", publicName: "facetDefinition", isSignal: true, isRequired: false, transformFunction: null }, partTypeIds: { classPropertyName: "partTypeIds", publicName: "partTypeIds", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (badgeType() !== 2) {\r\n<span\r\n class=\"part-badge\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n>\r\n {{ typeName() }}\r\n</span>\r\n} @if (badgeType() !== 1 && roleName()) {\r\n<span class=\"role-badge\">\r\n {{ roleName() }}\r\n</span>\r\n}\r\n", styles: [".part-badge{padding:4px;border-radius:6px}.role-badge{padding:4px;border:1px solid silver;border-radius:6px}\n"] });
708
1343
  }
709
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: PartBadgeComponent, decorators: [{
1344
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: PartBadgeComponent, decorators: [{
710
1345
  type: Component,
711
1346
  args: [{ selector: 'cadmus-part-badge', template: "@if (badgeType() !== 2) {\r\n<span\r\n class=\"part-badge\"\r\n [style.background-color]=\"color()\"\r\n [style.color]=\"contrastColor()\"\r\n>\r\n {{ typeName() }}\r\n</span>\r\n} @if (badgeType() !== 1 && roleName()) {\r\n<span class=\"role-badge\">\r\n {{ roleName() }}\r\n</span>\r\n}\r\n", styles: [".part-badge{padding:4px;border-radius:6px}.role-badge{padding:4px;border:1px solid silver;border-radius:6px}\n"] }]
712
1347
  }], ctorParameters: () => [{ type: i1$2.FacetService }, { type: ColorService }] });
713
1348
 
714
- /**
715
- * A label rendering function which removes from a label
716
- * all the characters past the last colon, trimming the result.
717
- * This is a typical rendering when dealing with hierarchical
718
- * thesaurus entries, e.g. "furniture: table: color", where
719
- * we can shorten the label to just "color", as "furniture"
720
- * and "table" are its ancestors.
721
- */
722
- const renderLabelFromLastColon = (label) => {
723
- if (!label) {
724
- return label;
725
- }
726
- const i = label.lastIndexOf(':');
727
- return i > -1 && i + 1 < label.length ? label.substring(i + 1).trim() : label;
728
- };
729
- /**
730
- * Thesaurus tree component.
731
- * This component displays a set of hierarchical thesaurus entries
732
- * in a tree, provided that each entry marks its hierarchy with
733
- * dots. For instance, say you have the hierarchy "furniture" -
734
- * "type" - "color". You might have an entry whose ID is
735
- * "furniture.table.red", with a sibling "furniture.table.green",
736
- * and a parent "furniture.table". This parent is there only to
737
- * provide a label to the parent node, but only leaf nodes can be
738
- * picked by the user. Whenever one is picked, the entryChange
739
- * event is emitted. Note that even if you specify a label renderer
740
- * function, the event always emits the original label.
741
- */
742
- class ThesaurusTreeComponent {
743
- /**
744
- * The thesaurus entries.
745
- */
746
- entries = input(...(ngDevMode ? [undefined, { debugName: "entries" }] : []));
747
- /**
748
- * The label for the root node.
749
- */
750
- rootLabel = input('-', ...(ngDevMode ? [{ debugName: "rootLabel" }] : []));
751
- /**
752
- * The optional node label rendering function.
753
- */
754
- renderLabel = input(...(ngDevMode ? [undefined, { debugName: "renderLabel" }] : []));
755
- /**
756
- * Fired when a thesaurus entry is selected.
757
- */
758
- entryChange = output();
759
- root;
760
- // TODO: use childrenAccessor: https://material.angular.io/cdk/tree/examples
761
- treeControl;
762
- treeDataSource;
763
- filter;
764
- form;
765
- foundNodes;
766
- hasChildren = (index, node) => {
767
- return node && node.children && node.children.length > 0;
768
- };
769
- isRoot = (index, node) => {
770
- return node && node.id === '@root';
771
- };
772
- constructor(formBuilder) {
773
- // tree
774
- this.treeControl = new NestedTreeControl((node) => node.children);
775
- this.treeDataSource = new MatTreeNestedDataSource();
776
- this.root = { id: '@root', label: '-', children: [] };
777
- // filter
778
- this.filter = formBuilder.control(null);
779
- this.form = formBuilder.group({
780
- filter: this.filter,
781
- });
782
- effect(() => {
783
- this.initTree(this.entries());
784
- });
785
- }
786
- ngOnInit() {
787
- this.initTree();
788
- }
789
- initTree(entries) {
790
- this.foundNodes = undefined;
791
- this.root = this.buildTreeModel(entries || []);
792
- this.treeDataSource.data = [this.root];
793
- // https://github.com/angular/components/issues/12469
794
- this.treeControl.dataNodes = this.treeDataSource.data;
795
- }
796
- getLabel(label) {
797
- const renderer = this.renderLabel();
798
- return renderer ? renderer(label) : label;
799
- }
800
- addNode(entry, separator, root) {
801
- const components = entry.id.split(separator);
802
- // walk the tree up to the last existing component
803
- let i = 0;
804
- let node = root;
805
- const idParts = [];
806
- // for each component:
807
- while (i < components.length) {
808
- idParts.push(components[i]);
809
- // stop walking when the node has no more children
810
- if (!node.children) {
811
- break;
812
- }
813
- // find target among children
814
- const targetId = idParts.join(separator);
815
- const existing = node.children.find((c) => {
816
- return c.id === targetId;
817
- });
818
- if (existing) {
819
- node = existing;
820
- i++;
821
- }
822
- else {
823
- break;
824
- }
825
- }
826
- // node is now the last existing component; use it as the ancestor
827
- // for all the remaining components (starting from i)
828
- while (i < components.length) {
829
- if (!node.children) {
830
- node.children = [];
831
- }
832
- const isLast = i + 1 === components.length;
833
- const label = isLast ? entry.value : components[i];
834
- const child = {
835
- label: isLast ? this.getLabel(label) : label,
836
- id: isLast ? entry.id : idParts.join(separator),
837
- parent: node,
838
- children: [],
839
- };
840
- if (label !== child.label) {
841
- child.originalLabel = label;
842
- }
843
- node.children.push(child);
844
- node = child;
845
- i++;
846
- }
847
- }
848
- /**
849
- * Build a tree model from a list of name=value pairs,
850
- * where each value can include one or more components separated by
851
- * the specified separator.
852
- * @param entries The entries to add.
853
- * @param separator string The separator string to use for values.
854
- */
855
- buildTreeModel(entries, separator = '.') {
856
- const root = {
857
- id: '@root',
858
- label: this.rootLabel() || '-',
859
- };
860
- if (!entries) {
861
- return root;
862
- }
863
- entries.forEach((entry) => {
864
- this.addNode(entry, separator, root);
865
- });
866
- return root;
867
- }
868
- onTreeNodeClick(node) {
869
- if (node.children && node.children.length > 0) {
870
- return;
871
- }
872
- this.entryChange.emit({
873
- id: node.id,
874
- value: node.originalLabel || node.label,
875
- });
876
- }
877
- expandAll() {
878
- this.treeControl.expandAll();
879
- }
880
- collapseAll() {
881
- this.treeControl.collapseAll();
882
- }
883
- expandFromNode(node) {
884
- while (node.parent) {
885
- node = node.parent;
886
- this.treeControl.expand(node);
887
- }
888
- }
889
- expandMatchingNodes(node, filter, found) {
890
- if (node.label.toLowerCase().includes(filter)) {
891
- found.push(node);
892
- this.expandFromNode(node);
893
- }
894
- if (node.children?.length) {
895
- node.children.forEach((child) => {
896
- this.expandMatchingNodes(child, filter, found);
897
- });
898
- }
899
- }
900
- find() {
901
- if (!this.filter.value?.length) {
902
- return;
903
- }
904
- this.treeControl.collapseAll();
905
- const foundNodes = [];
906
- this.expandMatchingNodes(this.treeDataSource.data[0], this.filter.value.toLowerCase(), foundNodes);
907
- this.foundNodes = foundNodes;
908
- }
909
- resetFilter() {
910
- this.filter.reset();
911
- this.foundNodes = undefined;
912
- }
913
- isFoundNode(node) {
914
- if (!this.foundNodes) {
915
- return false;
916
- }
917
- return this.foundNodes?.length > 0 && this.foundNodes.indexOf(node) > -1;
918
- }
919
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
920
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: ThesaurusTreeComponent, isStandalone: true, selector: "cadmus-thesaurus-tree", inputs: { entries: { classPropertyName: "entries", publicName: "entries", isSignal: true, isRequired: false, transformFunction: null }, rootLabel: { classPropertyName: "rootLabel", publicName: "rootLabel", isSignal: true, isRequired: false, transformFunction: null }, renderLabel: { classPropertyName: "renderLabel", publicName: "renderLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { entryChange: "entryChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"find()\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Expand all\"\r\n (click)=\"expandAll()\"\r\n >\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Collapse all\"\r\n (click)=\"collapseAll()\"\r\n >\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <mat-form-field>\r\n <mat-label>find</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button type=\"button\" matSuffix mat-icon-button (click)=\"resetFilter()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n @if (foundNodes) {\r\n <span\r\n [class.found-count]=\"foundNodes.length\"\r\n [class.not-found-count]=\"foundNodes.length === 0\"\r\n >{{ foundNodes.length }}</span\r\n >\r\n }\r\n</form>\r\n<mat-tree\r\n [dataSource]=\"treeDataSource\"\r\n [treeControl]=\"treeControl\"\r\n class=\"th-tree\"\r\n>\r\n <!-- leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle>\r\n <li>\r\n <div class=\"mat-tree-node\">\r\n <a\r\n mat-button\r\n (click)=\"onTreeNodeClick(node)\"\r\n [class.hilite]=\"isFoundNode(node)\"\r\n >\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n </li>\r\n </mat-tree-node>\r\n\r\n <!-- root node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: isRoot\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n {{ node.label }}\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </mat-nested-tree-node>\r\n\r\n <!-- parent node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: hasChildren\">\r\n <li class=\"tree-container\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n <a mat-button (click)=\"onTreeNodeClick(node)\">\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n</mat-tree>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "component", type: MatAnchor, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }] });
921
- }
922
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ThesaurusTreeComponent, decorators: [{
923
- type: Component,
924
- args: [{ selector: 'cadmus-thesaurus-tree', imports: [
925
- FormsModule,
926
- ReactiveFormsModule,
927
- MatIconButton,
928
- MatTooltip,
929
- MatIcon,
930
- MatFormField,
931
- MatLabel,
932
- MatInput,
933
- MatSuffix,
934
- NgClass,
935
- MatTree,
936
- MatTreeNodeDef,
937
- MatTreeNode,
938
- MatTreeNodeToggle,
939
- MatAnchor,
940
- MatNestedTreeNode,
941
- MatTreeNodeOutlet,
942
- ], template: "<form [formGroup]=\"form\" (submit)=\"find()\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Expand all\"\r\n (click)=\"expandAll()\"\r\n >\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Collapse all\"\r\n (click)=\"collapseAll()\"\r\n >\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <mat-form-field>\r\n <mat-label>find</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button type=\"button\" matSuffix mat-icon-button (click)=\"resetFilter()\">\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n @if (foundNodes) {\r\n <span\r\n [class.found-count]=\"foundNodes.length\"\r\n [class.not-found-count]=\"foundNodes.length === 0\"\r\n >{{ foundNodes.length }}</span\r\n >\r\n }\r\n</form>\r\n<mat-tree\r\n [dataSource]=\"treeDataSource\"\r\n [treeControl]=\"treeControl\"\r\n class=\"th-tree\"\r\n>\r\n <!-- leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle>\r\n <li>\r\n <div class=\"mat-tree-node\">\r\n <a\r\n mat-button\r\n (click)=\"onTreeNodeClick(node)\"\r\n [class.hilite]=\"isFoundNode(node)\"\r\n >\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n </li>\r\n </mat-tree-node>\r\n\r\n <!-- root node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: isRoot\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n {{ node.label }}\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </mat-nested-tree-node>\r\n\r\n <!-- parent node -->\r\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: hasChildren\">\r\n <li class=\"tree-container\">\r\n <div class=\"mat-tree-node\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTreeNodeToggle\r\n [attr.aria-label]=\"'Toggle ' + node.label\"\r\n >\r\n <mat-icon>\r\n {{ treeControl.isExpanded(node) ? \"expand_more\" : \"chevron_right\" }}\r\n </mat-icon>\r\n </button>\r\n <a mat-button (click)=\"onTreeNodeClick(node)\">\r\n {{ node.label }}\r\n </a>\r\n </div>\r\n <ul class=\"tree-nested-node\">\r\n @if (treeControl.isExpanded(node)) {\r\n <div>\r\n <ng-container matTreeNodeOutlet></ng-container>\r\n </div>\r\n }\r\n </ul>\r\n </li>\r\n </mat-nested-tree-node>\r\n</mat-tree>\r\n", styles: [".th-tree-progress-bar{margin-left:30px}.th-tree-nested-node{padding-left:30px}mat-tree{margin-left:40px}.mat-tree-node{padding:0;background-color:#fff}.mat-nested-tree-node{top:-24px}ul,li{list-style:none;margin:0;padding:0}li.th-tree-container{border-bottom:0}ul{padding-left:40px}li{padding-left:40px;border:1px dotted grey;border-width:0 0 1px 1px;position:relative;top:-24px}li.mat-tree-node,li div{margin:0;position:relative;top:24px}li ul{border-top:1px dotted grey;margin-left:-40px;padding-left:60px}.mat-nested-tree-node:last-child ul{border-left:1px solid white;margin-left:-41px}.mat-mdc-icon-button{z-index:100}span.found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#0cc078;border-radius:6px}span.not-found-count{margin:0 4px;padding:2px 4px;color:#fff;background-color:#fb6962;border-radius:6px}.hilite{background-color:#fdfd96}\n"] }]
943
- }], ctorParameters: () => [{ type: i1$1.FormBuilder }] });
944
-
945
1349
  /**
946
1350
  * Base class for part/fragment editors dumb components.
947
1351
  * The model type is the templated argument T.
@@ -1173,10 +1577,10 @@ class ModelEditorComponentBase {
1173
1577
  // the form is no more dirty
1174
1578
  this.form.markAsPristine();
1175
1579
  }
1176
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ModelEditorComponentBase, deps: [{ token: i1$3.AuthJwtService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1177
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: ModelEditorComponentBase, isStandalone: false, selector: "ng-component", inputs: { identity: { classPropertyName: "identity", publicName: "identity", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", dirtyChange: "dirtyChange", editorClose: "editorClose" }, ngImport: i0, template: '', isInline: true });
1580
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ModelEditorComponentBase, deps: [{ token: i1$3.AuthJwtService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1581
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.3", type: ModelEditorComponentBase, isStandalone: false, selector: "ng-component", inputs: { identity: { classPropertyName: "identity", publicName: "identity", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", dirtyChange: "dirtyChange", editorClose: "editorClose" }, ngImport: i0, template: '', isInline: true });
1178
1582
  }
1179
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: ModelEditorComponentBase, decorators: [{
1583
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: ModelEditorComponentBase, decorators: [{
1180
1584
  type: Component,
1181
1585
  args: [{
1182
1586
  template: '',
@@ -1258,10 +1662,10 @@ class UserRefLookupService {
1258
1662
  getName(item) {
1259
1663
  return item?.user?.userName;
1260
1664
  }
1261
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: UserRefLookupService, deps: [{ token: i1$2.UserService }], target: i0.ɵɵFactoryTarget.Injectable });
1262
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: UserRefLookupService, providedIn: 'root' });
1665
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, deps: [{ token: i1$2.UserService }], target: i0.ɵɵFactoryTarget.Injectable });
1666
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, providedIn: 'root' });
1263
1667
  }
1264
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: UserRefLookupService, decorators: [{
1668
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: UserRefLookupService, decorators: [{
1265
1669
  type: Injectable,
1266
1670
  args: [{
1267
1671
  providedIn: 'root',
@@ -1325,5 +1729,5 @@ const extractPristineChanges = (control) => {
1325
1729
  * Generated bundle index. Do not edit.
1326
1730
  */
1327
1731
 
1328
- export { CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
1732
+ export { CUSTOM_ENTRY_PREFIX, CloseSaveButtonsComponent, ColorService, CustomValidators, DecoratedTokenTextComponent, ErrorListComponent, FacetBadgeComponent, FlagsBadgeComponent, JsonValidators, LayerHintsComponent, LookupPinComponent, ModelEditorComponentBase, PartBadgeComponent, PartBadgeType, StaticThesPagedTreeStoreService, ThesEntriesPickerComponent, ThesPagedTreeBrowserComponent, ThesaurusTreeComponent, UserRefLookupService, extractPristineChanges, extractTouchedChanges, getPartIdName, renderLabelFromLastColon };
1329
1733
  //# sourceMappingURL=myrmidon-cadmus-ui.mjs.map