@yuuvis/client-framework 3.11.1 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/fesm2022/yuuvis-client-framework-actions.mjs +7 -2
  2. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  3. package/fesm2022/yuuvis-client-framework-forms.mjs +315 -29
  4. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +4 -3
  6. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +2 -2
  8. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +1 -1
  10. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-object-versions.mjs +1 -1
  12. package/fesm2022/yuuvis-client-framework-object-versions.mjs.map +1 -1
  13. package/fesm2022/yuuvis-client-framework-query-list.mjs +123 -5
  14. package/fesm2022/yuuvis-client-framework-query-list.mjs.map +1 -1
  15. package/fesm2022/yuuvis-client-framework-renderer.mjs +9 -0
  16. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
  17. package/fesm2022/yuuvis-client-framework-tile-list.mjs +18 -7
  18. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  19. package/lib/assets/i18n/de.json +10 -7
  20. package/lib/assets/i18n/en.json +23 -20
  21. package/package.json +5 -5
  22. package/types/yuuvis-client-framework-forms.d.ts +110 -3
  23. package/types/yuuvis-client-framework-query-list.d.ts +44 -1
  24. package/types/yuuvis-client-framework-tile-list.d.ts +12 -2
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "yuv.pwa.update.cancel": "Später",
3
3
  "yuv.pwa.update.confirm": "Neu laden",
4
- "yuv.pwa.update.message": "Eine neue Version der Anwendung ist verfügbar. Jetzt neu laden, um zu aktualisieren?",
4
+ "yuv.pwa.update.message": "Eine neue Version der Anwendung ist verfügbar. Möchten Sie jetzt neu laden, um zu aktualisieren?",
5
5
  "yuv.pwa.update.title": "Update verfügbar",
6
- "yuv.pwa.update.unrecoverable.message": "Die Anwendung muss neu geladen werden, um fortzufahren.",
6
+ "yuv.pwa.update.unrecoverable.message": "Bitte laden Sie die Anwendung neu, um fortzufahren.",
7
7
  "yuv.session.expires.message": "Ihre Sitzung läuft in {{seconds}} Sekunden ab.",
8
8
  "yuv.session.expires.title": "Sitzung läuft ab",
9
9
  "yuv.session.extend.action": "Sitzung verlängern",
@@ -49,10 +49,12 @@
49
49
  "yuv.form.element.data.grid.row.button.actions.tooltip": "Aktionsmenü öffnen",
50
50
  "yuv.form.element.datetime.calendar.cancel": "Abbrechen",
51
51
  "yuv.form.element.datetime.calendar.select": "Auswählen",
52
- "yuv.form.element.catalog.option.none": "Keine Auswahl",
52
+ "yuv.form.element.catalog.option.none": "Nichts ausgewählt",
53
53
  "yuv.form.element.datetime.calendar.today": "Heute",
54
54
  "yuv.form.element.organization-set.classify.icon.title": "Gruppe",
55
55
  "yuv.form.element.organization.classify.icon.title": "Benutzer",
56
+ "yuv.form.element.reference.classify.icon.title": "Referenz",
57
+ "yuv.form.element.reference.open.title": "Referenziertes Objekt öffnen",
56
58
  "yuv.form.element.range-select-date.custom.overlay.button.apply": "Anwenden",
57
59
  "yuv.form.element.range-select-date.custom.overlay.title": "Benutzerdefinierter Zeitraum",
58
60
  "yuv.form.element.range-select-date.option.any": "Beliebiges Datum",
@@ -135,6 +137,7 @@
135
137
  "yuv.object-versions.tabs.indexdata.title": "Metadaten",
136
138
  "yuv.audit.label.create.metadata": "Objekt wurde erstellt",
137
139
  "yuv.audit.label.create.metadata.withcontent": "Objekt wurde mit Dokumentdatei erstellt",
140
+ "yuv.audit.label.create.relationship": "Beziehung wurde erstellt",
138
141
  "yuv.audit.label.create.tag": "Tag wurde erstellt",
139
142
  "yuv.audit.label.delete": "Objekt wurde gelöscht",
140
143
  "yuv.audit.label.delete.content": "Dokumentdatei wurde gelöscht",
@@ -172,10 +175,10 @@
172
175
  "yuv.smart-search.condition.mark-dynamic": "Als auszufüllendes Feld festlegen",
173
176
  "yuv.smart-search.condition.remove": "Bedingung entfernen",
174
177
  "yuv.smart-search.condition.unmark-dynamic": "Aus auszufüllenden Feldern entfernen",
175
- "yuv.smart-search.condition.unset-value": "Wert fehlt",
178
+ "yuv.smart-search.condition.unset-value": "Kein Wert gesetzt",
176
179
  "yuv.smart-search.confirm": "Bestätigen",
177
- "yuv.smart-search.mode.empty": "Keine auszufüllenden Felder. Markiere Bedingungen mit dem Blitz-Symbol, um sie hier hinzuzufügen.",
178
- "yuv.smart-search.mode.essentials": "Wesentliches",
180
+ "yuv.smart-search.mode.empty": "Keine auszufüllenden Felder. Markieren Sie Bedingungen mit dem Blitz-Symbol, um sie hier hinzuzufügen.",
181
+ "yuv.smart-search.mode.essentials": "Kompakt",
179
182
  "yuv.smart-search.mode.full": "Vollständige Suche",
180
183
  "yuv.smart-search.mode.label": "Suchmodus",
181
184
  "yuv.smart-search.date-preset.this-month": "Dieser Monat",
@@ -185,7 +188,7 @@
185
188
  "yuv.smart-search.field.change": "Feld ändern",
186
189
  "yuv.smart-search.field.pick": "Feld auswählen…",
187
190
  "yuv.smart-search.fulltext.placeholder": "In Metadaten und/oder Inhalt suchen…",
188
- "yuv.smart-search.fulltext.scope.all": "In Metadaten & Inhalt",
191
+ "yuv.smart-search.fulltext.scope.all": "Metadaten & Inhalt",
189
192
  "yuv.smart-search.fulltext.scope.content": "Nur Inhalt",
190
193
  "yuv.smart-search.fulltext.scope.label": "Wo soll gesucht werden",
191
194
  "yuv.smart-search.fulltext.scope.metadata": "Nur Metadaten",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "yuv.pwa.update.cancel": "Later",
3
3
  "yuv.pwa.update.confirm": "Reload",
4
- "yuv.pwa.update.message": "A new version of the application is available. Reload now to update?",
4
+ "yuv.pwa.update.message": "A new version of the application is available. Do you want to reload now to update the application?",
5
5
  "yuv.pwa.update.title": "Update available",
6
- "yuv.pwa.update.unrecoverable.message": "The application needs to be reloaded to continue.",
7
- "yuv.session.expires.message": "Your session will expire in {{seconds}} seconds.",
8
- "yuv.session.expires.title": "Session expiring",
6
+ "yuv.pwa.update.unrecoverable.message": "Please reload the application to continue.",
7
+ "yuv.session.expires.message": "Your session will expire in {{seconds}} second(s).",
8
+ "yuv.session.expires.title": "Session is about to expire",
9
9
  "yuv.session.extend.action": "Extend session",
10
10
  "yuv.action-menu.action.copy.dms.object.description": "",
11
11
  "yuv.action-menu.action.copy.dms.object.label": "Copy",
@@ -53,6 +53,8 @@
53
53
  "yuv.form.element.datetime.calendar.today": "Today",
54
54
  "yuv.form.element.organization-set.classify.icon.title": "Group",
55
55
  "yuv.form.element.organization.classify.icon.title": "User",
56
+ "yuv.form.element.reference.classify.icon.title": "Reference",
57
+ "yuv.form.element.reference.open.title": "Open referenced object",
56
58
  "yuv.form.element.range-select-date.custom.overlay.button.apply": "Apply",
57
59
  "yuv.form.element.range-select-date.custom.overlay.title": "User-defined time period",
58
60
  "yuv.form.element.range-select-date.option.any": "Any date",
@@ -72,7 +74,7 @@
72
74
  "yuv.form.element.range-select-filesize.option.verylarge": "Very large (>100 MB)",
73
75
  "yuv.object-metadata.button.save": "Save",
74
76
  "yuv.audit.fetch.error": "Unable to load history entries",
75
- "yuv.audit.label.paging": "Pagination",
77
+ "yuv.audit.label.paging": "Page navigation",
76
78
  "yuv.audit.label.paging.current": "Page {{page}}",
77
79
  "yuv.audit.label.paging.next": "jump to next page",
78
80
  "yuv.audit.label.paging.prev": "jump to previous page",
@@ -135,6 +137,7 @@
135
137
  "yuv.object-versions.tabs.indexdata.title": "Metadata",
136
138
  "yuv.audit.label.create.metadata": "Object was created",
137
139
  "yuv.audit.label.create.metadata.withcontent": "Object was created with document file",
140
+ "yuv.audit.label.create.relationship": "Relationship was created",
138
141
  "yuv.audit.label.create.tag": "Tag was created",
139
142
  "yuv.audit.label.delete": "Object was deleted",
140
143
  "yuv.audit.label.delete.content": "Document file was deleted",
@@ -146,7 +149,7 @@
146
149
  "yuv.audit.label.get.metadata": "Metadata was read",
147
150
  "yuv.audit.label.get.rendition.pdf": "PDF rendition was requested",
148
151
  "yuv.audit.label.get.rendition.text": "Text rendition was requested",
149
- "yuv.audit.label.get.rendition.thumbnail": "Thumbnail view was requested",
152
+ "yuv.audit.label.get.rendition.thumbnail": "Thumbnail was requested",
150
153
  "yuv.audit.label.update.content": "Document file was changed",
151
154
  "yuv.audit.label.update.metadata": "Metadata was changed",
152
155
  "yuv.audit.label.update.metadata.withcontent": "Metadata and document file were changed",
@@ -163,46 +166,46 @@
163
166
  "yuv.simple-search.submit": "Start search",
164
167
  "yuv.smart-search.add-condition": "Add condition",
165
168
  "yuv.smart-search.add-group": "Add group",
166
- "yuv.smart-search.add-type": "Find…",
169
+ "yuv.smart-search.add-type": "Search...",
167
170
  "yuv.smart-search.cancel": "Cancel",
168
171
  "yuv.smart-search.combinator.and": "AND",
169
172
  "yuv.smart-search.combinator.or": "OR",
170
173
  "yuv.smart-search.combinator.as-well-as": "as well as",
171
174
  "yuv.smart-search.condition.edit-aria": "Edit condition: {{label}}",
172
- "yuv.smart-search.condition.mark-dynamic": "Make this a fill-out field",
175
+ "yuv.smart-search.condition.mark-dynamic": "Make this an input field",
173
176
  "yuv.smart-search.condition.remove": "Remove condition",
174
- "yuv.smart-search.condition.unmark-dynamic": "Remove from fill-out fields",
175
- "yuv.smart-search.condition.unset-value": "value missing",
177
+ "yuv.smart-search.condition.unmark-dynamic": "Remove from input fields",
178
+ "yuv.smart-search.condition.unset-value": "Value not set",
176
179
  "yuv.smart-search.confirm": "Confirm",
177
- "yuv.smart-search.mode.empty": "No fill-out fields. Mark conditions with the bolt icon to add them here.",
180
+ "yuv.smart-search.mode.empty": "No input fields available. Mark conditions with the lightning icon to add them here.",
178
181
  "yuv.smart-search.mode.essentials": "Essentials",
179
- "yuv.smart-search.mode.full": "Full Form",
182
+ "yuv.smart-search.mode.full": "Full search",
180
183
  "yuv.smart-search.mode.label": "Search mode",
181
184
  "yuv.smart-search.date-preset.this-month": "This month",
182
185
  "yuv.smart-search.date-preset.this-week": "This week",
183
186
  "yuv.smart-search.date-preset.this-year": "This year",
184
187
  "yuv.smart-search.date-preset.today": "Today",
185
188
  "yuv.smart-search.field.change": "Change field",
186
- "yuv.smart-search.field.pick": "Pick a field",
187
- "yuv.smart-search.fulltext.placeholder": "Search across metadata and/or content",
188
- "yuv.smart-search.fulltext.scope.all": "In metadata & content",
189
+ "yuv.smart-search.field.pick": "Select field...",
190
+ "yuv.smart-search.fulltext.placeholder": "Search in metadata and/or content...",
191
+ "yuv.smart-search.fulltext.scope.all": "Metadata & content",
189
192
  "yuv.smart-search.fulltext.scope.content": "Content only",
190
193
  "yuv.smart-search.fulltext.scope.label": "Where to search",
191
194
  "yuv.smart-search.fulltext.scope.metadata": "Metadata only",
192
195
  "yuv.smart-search.fulltext.types.all": "All types",
193
196
  "yuv.smart-search.fulltext.types.label": "Limit to types",
194
- "yuv.smart-search.operator.change": "Change operator",
197
+ "yuv.smart-search.operator.change": "Modify operator",
195
198
  "yuv.smart-search.operator.empty": "is empty",
196
199
  "yuv.smart-search.operator.eq-false": "= false",
197
200
  "yuv.smart-search.operator.eq-true": "= true",
198
201
  "yuv.smart-search.operator.has": "has",
199
- "yuv.smart-search.operator.like": "like",
202
+ "yuv.smart-search.operator.like": "similar",
200
203
  "yuv.smart-search.operator.not-empty": "is not empty",
201
- "yuv.smart-search.operator.select": "Select operator",
204
+ "yuv.smart-search.operator.select": "Select operator...",
202
205
  "yuv.smart-search.type.confirm": "Confirm types",
203
206
  "yuv.smart-search.type.remove": "Remove type",
204
207
  "yuv.smart-search.type.remove-draft": "Remove selected type",
205
- "yuv.smart-search.value.enter": "Enter value",
208
+ "yuv.smart-search.value.enter": "Enter value...",
206
209
  "yuv.sort.ascending": "Ascending",
207
210
  "yuv.sort.descending": "Descending",
208
211
  "yuv.sort.tooltip": "Sort",
@@ -215,7 +218,7 @@
215
218
  "yuv.tile-config.slot.action.headline": "Actions",
216
219
  "yuv.tile-config.slot.badges.headline": "Badges",
217
220
  "yuv.tile-config.slot.icon.headline": "Icon",
218
- "yuv.tile-config.slot.property.headline": "Attribute",
221
+ "yuv.tile-config.slot.property.headline": "Attributes",
219
222
  "yuv.tile-config.title": "Hit list configuration for {{bucket}}",
220
223
  "yuv.tile-config.trigger.tooltip": "Hit list configuration",
221
224
  "yuv.tile-list.item.actions-menu.button.tooltip": "Open actions menu",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuuvis/client-framework",
3
- "version": "3.11.1",
3
+ "version": "3.13.0",
4
4
  "author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -8,16 +8,16 @@
8
8
  "@angular/common": "^21.2.9",
9
9
  "@angular/core": "^21.2.9",
10
10
  "angular-gridster2": "^21.0.1",
11
- "@yuuvis/client-core": "^3.11.1",
12
- "@yuuvis/client-shell-core": "^3.11.1",
13
- "@yuuvis/client-components": "^3.11.1",
11
+ "@yuuvis/client-core": "^3.13.0",
12
+ "@yuuvis/client-shell-core": "^3.13.0",
13
+ "@yuuvis/client-components": "^3.13.0",
14
14
  "ng-dynamic-component": "^10.8.2",
15
15
  "modern-normalize": "^3.0.1"
16
16
  },
17
17
  "dependencies": {
18
18
  "@angular/material": "^21.2.7",
19
19
  "@ngrx/signals": "^21.1.0",
20
- "@yuuvis/material": "^3.11.1",
20
+ "@yuuvis/material": "^3.13.0",
21
21
  "@yuuvis/media-viewer": "^3.0.6",
22
22
  "angular-split": "^20.0.0",
23
23
  "vis-network": "^10.0.2",
@@ -1,5 +1,5 @@
1
1
  import * as _angular_forms from '@angular/forms';
2
- import { ControlValueAccessor, FormControl, Validator, FormGroup, ValidationErrors, AbstractControl } from '@angular/forms';
2
+ import { ControlValueAccessor, FormControl, Validator, FormGroup, AbstractControl } from '@angular/forms';
3
3
  import * as _angular_core from '@angular/core';
4
4
  import { OnInit, OnDestroy, ElementRef, WritableSignal, AfterViewInit } from '@angular/core';
5
5
  import { AbstractMatFormField } from '@yuuvis/client-framework/common';
@@ -320,7 +320,6 @@ declare class NumberRangeComponent extends AbstractMatFormField<RangeValue> impl
320
320
  declare class NumberComponent extends AbstractMatFormField<number> implements ControlValueAccessor, OnInit, OnDestroy {
321
321
  #private;
322
322
  readonly translate: TranslateService;
323
- validationErrors: ValidationErrors[];
324
323
  transformPipe: LocaleNumberPipe | FileSizePipe;
325
324
  innerCtrl: FormControl<string | null>;
326
325
  ngControl: _angular_forms.NgControl | null;
@@ -560,6 +559,114 @@ declare class RangeSelectFilesizeComponent extends AbstractMatFormField<RangeSel
560
559
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<RangeSelectFilesizeComponent, "yuv-range-select-filesize", never, { "ranges": { "alias": "ranges"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
561
560
  }
562
561
 
562
+ /**
563
+ * A resolved reference to a dms object, used internally by the
564
+ * {@link ReferenceComponent} to render chips and suggestions.
565
+ */
566
+ interface ReferenceEntry {
567
+ /** object id of the referenced dms object (the value that gets stored) */
568
+ id: string;
569
+ /** object type id of the referenced object (used to resolve the owning app) */
570
+ objectTypeId: string;
571
+ /** resolved display title (falls back to the id) */
572
+ title: string;
573
+ /** raw field data of the referenced object (passed to the open handler) */
574
+ data: Record<string, unknown>;
575
+ /** set when the id could not be resolved (deleted or no permission) */
576
+ notFound?: boolean;
577
+ }
578
+
579
+ /**
580
+ * Form input for references to other dms objects. As the user types, a CMIS
581
+ * fulltext search (narrowed to the allowed target types from the field's
582
+ * `id:reference[...]` classification) provides suggestions. The selected object
583
+ * id(s) are stored; on load they are resolved back to display chips.
584
+ *
585
+ * ## Label retrieval
586
+ *
587
+ * The chip label shown for a referenced object is its resolved object-config
588
+ * title, not a raw property. Both search hits and objects resolved on load are
589
+ * turned into a {@link ReferenceEntry} by `#toEntryFromDms`, which asks
590
+ * {@link ObjectConfigService.getResolvedObjectConfig} for the title of the
591
+ * object's data. The tricky part is picking the right config: reference targets
592
+ * are usually secondary object types (SOTs) applied to a generic primary type,
593
+ * and the title-defining config is keyed by the SOT's virtual config id (colons
594
+ * replaced by dots, e.g. `appCasem.caseDocument`) inside the owning app's
595
+ * bucket — not under the primary object type id. `#resolveConfigType` therefore
596
+ * probes each allowed target type the hit actually carries (as primary type or
597
+ * SOT), trying the dotted and raw config ids, and uses the first bucket that
598
+ * defines one; it falls back to the primary object type's default config, and
599
+ * ultimately to the raw object id when no title can be resolved. Objects that
600
+ * cannot be fetched at all (e.g. deleted or access-denied) become `notFound`
601
+ * entries labelled with their id.
602
+ *
603
+ * ## Opening a reference entry
604
+ *
605
+ * A chip can be opened only when a loaded feature app claims responsibility for
606
+ * the referenced object's type. `#openAppId` maps the entry's `objectTypeId` to
607
+ * an owning app id via {@link ObjectConfigService.getAppIdForType}, and
608
+ * `canOpen` gates the action on {@link ShellService.canOpenObjectFor} (and on the
609
+ * entry not being `notFound`) — this drives whether the chip is rendered as an
610
+ * openable link. Invoking `open` delegates to {@link ShellService.openObject},
611
+ * passing the app id and the entry's cached `data` so the app can route to /
612
+ * display the object without an extra fetch.
613
+ *
614
+ * @example
615
+ * <yuv-reference [multiselect]="true" [classifications]="['id:reference[appCasem:correctionDocument]']" />
616
+ */
617
+ declare class ReferenceComponent extends AbstractMatFormField<string | string[] | undefined> implements ControlValueAccessor, OnInit, OnDestroy {
618
+ #private;
619
+ busy: _angular_core.WritableSignal<boolean>;
620
+ acFormControl: FormControl<AutocompleteItem<unknown> | AutocompleteItem<unknown>[] | null | undefined>;
621
+ ngControl: _angular_forms.NgControl | null;
622
+ _innerValue: ReferenceEntry[];
623
+ set innerValue(iv: ReferenceEntry[]);
624
+ get innerValue(): ReferenceEntry[];
625
+ autocompleteRes: AutocompleteItem[];
626
+ /**
627
+ * Possibles values are `EDIT` (default),`SEARCH`,`CREATE`. In search situation validation of the form element will be turned off, so you are able to enter search terms that do not meet the elements validators.
628
+ */
629
+ situation: _angular_core.InputSignal<string | undefined>;
630
+ /**
631
+ * Indicator that multiple references could be selected, they will be rendered as chips (default: false).
632
+ */
633
+ multiselect: _angular_core.InputSignal<boolean>;
634
+ /**
635
+ * Additional semantics for the form element. The `id:reference[...]` classification
636
+ * restricts the suggestions to the target types listed in the brackets.
637
+ */
638
+ classifications: _angular_core.InputSignal<string[] | undefined>;
639
+ /**
640
+ * Will prevent the input from being changed (default: false)
641
+ */
642
+ readonly: _angular_core.InputSignal<boolean>;
643
+ /**
644
+ * Minimal number of characters to trigger the search (default: 2)
645
+ */
646
+ minChars: _angular_core.InputSignal<number>;
647
+ /**
648
+ * Maximal number of suggestions for the given search term (default: 10)
649
+ */
650
+ maxSuggestions: _angular_core.InputSignal<number>;
651
+ propagateChange: (_: any) => void;
652
+ writeValue(value: string | string[]): void;
653
+ registerOnChange(fn: any): void;
654
+ registerOnTouched(fn: any): void;
655
+ setDisabledState?(isDisabled: boolean): void;
656
+ private propagate;
657
+ /** Resolve stored object ids back to display entries. */
658
+ resolveFn(ids: string[]): void;
659
+ autocompleteFn(query: string): void;
660
+ /** Whether the referenced object can be opened by a loaded app. */
661
+ canOpen(entry: ReferenceEntry): boolean;
662
+ /** Open the referenced object via the owning app's registered open handler. */
663
+ open(entry: ReferenceEntry): void;
664
+ ngOnInit(): void;
665
+ ngOnDestroy(): void;
666
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ReferenceComponent, never>;
667
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ReferenceComponent, "yuv-reference", never, { "situation": { "alias": "situation"; "required": false; "isSignal": true; }; "multiselect": { "alias": "multiselect"; "required": false; "isSignal": true; }; "classifications": { "alias": "classifications"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "minChars": { "alias": "minChars"; "required": false; "isSignal": true; }; "maxSuggestions": { "alias": "maxSuggestions"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
668
+ }
669
+
563
670
  /**
564
671
  * Creates form input for strings. Based on the input values different kinds of inputs will be generated.
565
672
  *
@@ -668,5 +775,5 @@ declare class FormUtils {
668
775
  static getErrorState(control: AbstractControl): boolean;
669
776
  }
670
777
 
671
- export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
778
+ export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, ReferenceComponent, StringComponent, YuvFormsModule };
672
779
  export type { RangeSelectDateValue, RangeSelectFilesizeValue };
@@ -305,6 +305,24 @@ declare class QueryListComponent<T = any> {
305
305
  * Re-evaluates automatically whenever any of the three sources change.
306
306
  */
307
307
  resultItems: _angular_core.Signal<T[]>;
308
+ /**
309
+ * Object IDs of the currently selected rows — the id-based source of truth for the
310
+ * visual selection.
311
+ *
312
+ * The inner list tracks selection by positional index, which becomes meaningless the
313
+ * moment a re-query reorders or replaces the rendered rows (the `@for` reuses/recreates
314
+ * the projected item directives, so index-based visual state points at the wrong — or
315
+ * detached — directives). When `idProperty` is set, the inner list is switched into
316
+ * `selfHandleSelection` mode and each row's `[selected]` is bound to this set instead, so
317
+ * Angular re-applies the correct selection by ID on every render — a multi-selection then
318
+ * survives sort, page changes, and refreshes. Kept in sync from every committed selection
319
+ * via `onInnerItemSelect()`.
320
+ */
321
+ selectedIds: _angular_core.WritableSignal<Set<string>>;
322
+ /** Whether this component drives the inner list's selection visuals via each row's id-based
323
+ * `[selected]` binding (and thus the inner list should not write them imperatively). Enabled
324
+ * whenever an `idProperty` is configured — the prerequisite for id-based selection. */
325
+ idSelection: _angular_core.Signal<boolean>;
308
326
  /**
309
327
  * Indicates whether a search request is currently in flight.
310
328
  *
@@ -320,6 +338,25 @@ declare class QueryListComponent<T = any> {
320
338
  constructor();
321
339
  /** Resolves the tracking key for a result item in the `@for` loop. */
322
340
  trackItem(item: T, index: number): unknown;
341
+ /**
342
+ * Whether the given row is part of the current selection, resolved by ID.
343
+ *
344
+ * Bound to each row's `[selected]` in the template so the visual selection is driven by
345
+ * {@link selectedIds} (id-based) rather than the inner list's positional state. This is
346
+ * what makes a multi-selection survive a re-query/reorder.
347
+ */
348
+ isRowSelected(item: T): boolean;
349
+ /**
350
+ * Choke point for every committed selection emitted by the inner list.
351
+ *
352
+ * Translates the positional indices into object IDs against the currently rendered
353
+ * `resultItems()` and stores them in {@link selectedIds}, then re-emits the original
354
+ * indices via `itemSelect` so existing consumers are unaffected. Keeping the id set in
355
+ * sync here (rather than in each caller) means clicks, keyboard, drag-select, and
356
+ * programmatic selection all feed the same source of truth. A no-op passthrough when no
357
+ * `idProperty` is configured (the inner list then owns the visual selection as before).
358
+ */
359
+ onInnerItemSelect(indices: number[]): void;
323
360
  /**
324
361
  * Handles a single click on a list item.
325
362
  *
@@ -341,10 +378,16 @@ declare class QueryListComponent<T = any> {
341
378
  * to trigger a secondary action (e.g. opening a detail panel or navigating to a route)
342
379
  * that is distinct from the primary single-click selection.
343
380
  *
381
+ * When a modifier key (Ctrl/Shift/Meta) is held, the double-click is instead treated as a
382
+ * selection gesture: while the user is rapidly building a multi-selection, two quick clicks
383
+ * on the same row are easily coalesced by the browser into a `dblclick`. Emitting the
384
+ * double-click action then would navigate away / open a preview and tear down the whole
385
+ * multi-selection. So we toggle selection for that item and suppress the double-click action.
386
+ *
344
387
  * Called from the template via `ClickDoubleDirective`. Not intended for external callers.
345
388
  *
346
389
  * @param idx Zero-based index of the double-clicked item.
347
- * @param event The originating mouse event (unused, kept for directive compatibility).
390
+ * @param event The originating mouse event; its modifier flags decide open-vs-select.
348
391
  */
349
392
  onItemDoubleClick(idx: number, event: MouseEvent): void;
350
393
  /**
@@ -713,6 +713,11 @@ declare class PropertySelectComponent {
713
713
  objectTypeFields: TypeProperty[];
714
714
  query: _angular_core.WritableSignal<string | null>;
715
715
  objectType: _angular_core.InputSignal<VirtualObjectType | undefined>;
716
+ /**
717
+ * Property IDs that should not be offered for selection. These are added on
718
+ * top of the always-excluded system/base fields (see `#excludeFields`).
719
+ */
720
+ excludeProperties: _angular_core.InputSignal<string[]>;
716
721
  filteredObjectTypeFields: _angular_core.Signal<TypeProperty[]>;
717
722
  objectTypesEffect: _angular_core.EffectRef;
718
723
  selectedProperty: _angular_core.InputSignal<ObjectConfigProperty | undefined>;
@@ -724,7 +729,7 @@ declare class PropertySelectComponent {
724
729
  private getObjectTypeFields;
725
730
  private _getLabel;
726
731
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PropertySelectComponent, never>;
727
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PropertySelectComponent, "yuv-tile-property-select", never, { "objectType": { "alias": "objectType"; "required": false; "isSignal": true; }; "selectedProperty": { "alias": "selectedProperty"; "required": false; "isSignal": true; }; }, { "propertySelect": "propertySelect"; }, never, never, true, never>;
732
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PropertySelectComponent, "yuv-tile-property-select", never, { "objectType": { "alias": "objectType"; "required": false; "isSignal": true; }; "excludeProperties": { "alias": "excludeProperties"; "required": false; "isSignal": true; }; "selectedProperty": { "alias": "selectedProperty"; "required": false; "isSignal": true; }; }, { "propertySelect": "propertySelect"; }, never, never, true, never>;
728
733
  }
729
734
 
730
735
  declare class TileConfigTriggerComponent {
@@ -760,6 +765,11 @@ declare class TileConfigComponent {
760
765
  bucketLabel: _angular_core.InputSignal<string | undefined>;
761
766
  configTypes: _angular_core.InputSignal<VirtualObjectType[] | undefined>;
762
767
  configFlavors: _angular_core.InputSignal<ObjectFlavor[]>;
768
+ /**
769
+ * Property IDs that should not be offered for selection in the property
770
+ * slots. Added on top of the always-excluded system/base fields.
771
+ */
772
+ excludeProperties: _angular_core.InputSignal<string[]>;
763
773
  get configChanged(): boolean;
764
774
  types: Signal<InnerType[]>;
765
775
  save: _angular_core.OutputEmitterRef<void>;
@@ -785,7 +795,7 @@ declare class TileConfigComponent {
785
795
  cancelConfig(): void;
786
796
  getTypeLabel(typeId: string): string;
787
797
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TileConfigComponent, never>;
788
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileConfigComponent, "yuv-tile-config", never, { "bucket": { "alias": "bucket"; "required": false; "isSignal": true; }; "bucketLabel": { "alias": "bucketLabel"; "required": false; "isSignal": true; }; "configTypes": { "alias": "configTypes"; "required": false; "isSignal": true; }; "configFlavors": { "alias": "configFlavors"; "required": false; "isSignal": true; }; }, { "save": "save"; "canceled": "canceled"; }, never, never, true, never>;
798
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileConfigComponent, "yuv-tile-config", never, { "bucket": { "alias": "bucket"; "required": false; "isSignal": true; }; "bucketLabel": { "alias": "bucketLabel"; "required": false; "isSignal": true; }; "configTypes": { "alias": "configTypes"; "required": false; "isSignal": true; }; "configFlavors": { "alias": "configFlavors"; "required": false; "isSignal": true; }; "excludeProperties": { "alias": "excludeProperties"; "required": false; "isSignal": true; }; }, { "save": "save"; "canceled": "canceled"; }, never, never, true, never>;
789
799
  }
790
800
 
791
801
  /**