@fundamental-ngx/platform 0.65.1-rc.9 → 0.65.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.
Files changed (63) hide show
  1. package/fesm2022/fundamental-ngx-platform-approval-flow.mjs +40 -40
  2. package/fesm2022/fundamental-ngx-platform-approval-flow.mjs.map +1 -1
  3. package/fesm2022/fundamental-ngx-platform-button.mjs +7 -7
  4. package/fesm2022/fundamental-ngx-platform-dynamic-page.mjs +50 -51
  5. package/fesm2022/fundamental-ngx-platform-dynamic-page.mjs.map +1 -1
  6. package/fesm2022/fundamental-ngx-platform-feed-input.mjs +8 -8
  7. package/fesm2022/fundamental-ngx-platform-feed-input.mjs.map +1 -1
  8. package/fesm2022/fundamental-ngx-platform-form.mjs +321 -321
  9. package/fesm2022/fundamental-ngx-platform-form.mjs.map +1 -1
  10. package/fesm2022/fundamental-ngx-platform-icon-tab-bar.mjs +64 -64
  11. package/fesm2022/fundamental-ngx-platform-link.mjs +7 -7
  12. package/fesm2022/fundamental-ngx-platform-list.mjs +59 -59
  13. package/fesm2022/fundamental-ngx-platform-menu-button.mjs +7 -7
  14. package/fesm2022/fundamental-ngx-platform-menu.mjs +13 -13
  15. package/fesm2022/fundamental-ngx-platform-message-popover.mjs +688 -34
  16. package/fesm2022/fundamental-ngx-platform-message-popover.mjs.map +1 -1
  17. package/fesm2022/fundamental-ngx-platform-object-marker.mjs +7 -7
  18. package/fesm2022/fundamental-ngx-platform-object-status.mjs +10 -10
  19. package/fesm2022/fundamental-ngx-platform-page-footer.mjs +7 -7
  20. package/fesm2022/fundamental-ngx-platform-panel.mjs +16 -16
  21. package/fesm2022/fundamental-ngx-platform-search-field.mjs +19 -20
  22. package/fesm2022/fundamental-ngx-platform-search-field.mjs.map +1 -1
  23. package/fesm2022/fundamental-ngx-platform-settings-generator.mjs +34 -34
  24. package/fesm2022/fundamental-ngx-platform-shared.mjs +28 -28
  25. package/fesm2022/fundamental-ngx-platform-slider.mjs +8 -8
  26. package/fesm2022/fundamental-ngx-platform-slider.mjs.map +1 -1
  27. package/fesm2022/fundamental-ngx-platform-smart-filter-bar.mjs +34 -34
  28. package/fesm2022/fundamental-ngx-platform-smart-filter-bar.mjs.map +1 -1
  29. package/fesm2022/fundamental-ngx-platform-split-menu-button.mjs +7 -7
  30. package/fesm2022/fundamental-ngx-platform-table-helpers.mjs +82 -82
  31. package/fesm2022/fundamental-ngx-platform-table.mjs +136 -136
  32. package/fesm2022/fundamental-ngx-platform-table.mjs.map +1 -1
  33. package/fesm2022/fundamental-ngx-platform-value-help-dialog.mjs +29 -29
  34. package/fesm2022/fundamental-ngx-platform-value-help-dialog.mjs.map +1 -1
  35. package/fesm2022/fundamental-ngx-platform-variant-management.mjs +19 -19
  36. package/fesm2022/fundamental-ngx-platform-variant-management.mjs.map +1 -1
  37. package/fesm2022/fundamental-ngx-platform-wizard-generator.mjs +43 -43
  38. package/fesm2022/fundamental-ngx-platform-wizard-generator.mjs.map +1 -1
  39. package/fesm2022/fundamental-ngx-platform.mjs +4 -5
  40. package/fesm2022/fundamental-ngx-platform.mjs.map +1 -1
  41. package/package.json +5 -13
  42. package/schematics/ng-add/index.js +1 -1
  43. package/schematics/package.json +1 -1
  44. package/types/fundamental-ngx-platform-approval-flow.d.ts +1 -1
  45. package/types/fundamental-ngx-platform-dynamic-page.d.ts +1 -1
  46. package/types/fundamental-ngx-platform-form.d.ts +11 -11
  47. package/types/fundamental-ngx-platform-icon-tab-bar.d.ts +1 -1
  48. package/types/fundamental-ngx-platform-list.d.ts +1 -1
  49. package/types/fundamental-ngx-platform-message-popover.d.ts +253 -9
  50. package/types/fundamental-ngx-platform-panel.d.ts +1 -1
  51. package/types/fundamental-ngx-platform-settings-generator.d.ts +2 -2
  52. package/types/fundamental-ngx-platform-shared.d.ts +3 -3
  53. package/types/fundamental-ngx-platform-smart-filter-bar.d.ts +1 -1
  54. package/types/fundamental-ngx-platform-table-helpers.d.ts +5 -5
  55. package/types/fundamental-ngx-platform-wizard-generator.d.ts +2 -2
  56. package/types/fundamental-ngx-platform.d.ts +0 -1
  57. package/fesm2022/fundamental-ngx-platform-message-view.mjs +0 -170
  58. package/fesm2022/fundamental-ngx-platform-message-view.mjs.map +0 -1
  59. package/fesm2022/fundamental-ngx-platform-messages-shared.mjs +0 -803
  60. package/fesm2022/fundamental-ngx-platform-messages-shared.mjs.map +0 -1
  61. package/message-view/README.md +0 -88
  62. package/types/fundamental-ngx-platform-message-view.d.ts +0 -70
  63. package/types/fundamental-ngx-platform-messages-shared.d.ts +0 -306
@@ -1,803 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, Input, Optional, Directive, signal, ContentChildren, Inject, ViewEncapsulation, ChangeDetectionStrategy, Component, EventEmitter, inject, DOCUMENT, ElementRef, ViewChild, Output, computed, NgModule } from '@angular/core';
3
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import * as i1 from '@angular/forms';
5
- import { FormGroup, ControlContainer } from '@angular/forms';
6
- import { FD_FORM_FIELD_CONTROL } from '@fundamental-ngx/cdk/forms';
7
- import { Subject, Subscription, startWith, switchMap, filter, zip, debounceTime } from 'rxjs';
8
- import { CdkScrollable } from '@angular/cdk/overlay';
9
- import { NgTemplateOutlet } from '@angular/common';
10
- import * as i1$1 from '@fundamental-ngx/cdk/utils';
11
- import { resizeObservable, ClickedDirective, TabbableElementService, countBy, mergeWith } from '@fundamental-ngx/cdk/utils';
12
- import { LinkComponent } from '@fundamental-ngx/core/link';
13
- import * as i2 from '@fundamental-ngx/core/list';
14
- import { ListModule } from '@fundamental-ngx/core/list';
15
- import { ObjectStatusComponent } from '@fundamental-ngx/core/object-status';
16
- import { ScrollbarDirective } from '@fundamental-ngx/core/scrollbar';
17
- import { TextComponent } from '@fundamental-ngx/core/text';
18
- import { FdTranslatePipe } from '@fundamental-ngx/i18n';
19
- import { getFormState } from '@fundamental-ngx/platform/form';
20
-
21
- const FDP_MESSAGE_POPOVER_DEFAULT_CONFIG = {
22
- errors: {
23
- email: 'platformMessagePopover.defaultErrors.email',
24
- max: 'platformMessagePopover.defaultErrors.max',
25
- maxlength: 'platformMessagePopover.defaultErrors.maxLength',
26
- min: 'platformMessagePopover.defaultErrors.min',
27
- minlength: 'platformMessagePopover.defaultErrors.minLength',
28
- pattern: 'platformMessagePopover.defaultErrors.pattern',
29
- required: 'platformMessagePopover.defaultErrors.required',
30
- requiredTrue: 'platformMessagePopover.defaultErrors.requiredTrue'
31
- }
32
- };
33
- const FDP_MESSAGE_POPOVER_CONFIG = new InjectionToken('FdpMessagePopoverConfig');
34
-
35
- class MessagePopoverFormItemDirective {
36
- /** @hidden */
37
- constructor(elementRef, control) {
38
- this.elementRef = elementRef;
39
- this.control = control;
40
- }
41
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagePopoverFormItemDirective, deps: [{ token: i0.ElementRef }, { token: i1.NgControl, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
42
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.2.1", type: MessagePopoverFormItemDirective, isStandalone: true, selector: "[fdpMessagePopoverFormItem]", inputs: { label: ["fdpMessagePopoverFormItem", "label"], errorTypes: "errorTypes" }, ngImport: i0 }); }
43
- }
44
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagePopoverFormItemDirective, decorators: [{
45
- type: Directive,
46
- args: [{
47
- selector: '[fdpMessagePopoverFormItem]'
48
- }]
49
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.NgControl, decorators: [{
50
- type: Optional
51
- }] }], propDecorators: { label: [{
52
- type: Input,
53
- args: ['fdpMessagePopoverFormItem']
54
- }], errorTypes: [{
55
- type: Input
56
- }] } });
57
-
58
- /**
59
- * Converts Object Status into Message Popover State
60
- * @param status Object status
61
- * @returns Message Popover State.
62
- */
63
- function convertFormStateToMessagePopoverState(state) {
64
- switch (state) {
65
- case 'error':
66
- return 'negative';
67
- case 'warning':
68
- return 'critical';
69
- case 'default':
70
- return 'neutral';
71
- default:
72
- return state;
73
- }
74
- }
75
- /**
76
- * Converts Form State into Object status type.
77
- * @param type Form state.
78
- * @returns `ObjectStatus` type.
79
- */
80
- function convertFormState(type) {
81
- switch (type) {
82
- case 'success':
83
- return 'positive';
84
- case 'error':
85
- return 'negative';
86
- case 'warning':
87
- return 'critical';
88
- case 'information':
89
- return 'informative';
90
- default:
91
- return 'neutral';
92
- }
93
- }
94
- /**
95
- * Maps message type to icon name.
96
- * @param type Message type (error, success, warning, information, default).
97
- * @returns Icon name for the given message type.
98
- */
99
- function getIconForMessageType(type) {
100
- switch (type) {
101
- case 'error':
102
- return 'error';
103
- case 'success':
104
- return 'sys-enter-2';
105
- case 'warning':
106
- return 'alert';
107
- case 'information':
108
- return 'information';
109
- default:
110
- return 'sys-help-2';
111
- }
112
- }
113
-
114
- class MessagePopoverFormWrapperComponent {
115
- /**
116
- * User-passed forms.
117
- */
118
- set forms(forms) {
119
- if (!forms) {
120
- return;
121
- }
122
- if (!Array.isArray(forms)) {
123
- forms = [forms];
124
- }
125
- this._ngForms = forms;
126
- this._startListeningForErrors();
127
- }
128
- /** User-passed form fields. */
129
- set formFields(value) {
130
- this._formFields = value;
131
- this._listenToFormFieldErrors(value);
132
- }
133
- get formFields() {
134
- return this._formFields;
135
- }
136
- /** @hidden */
137
- constructor(_destroyRef, _config) {
138
- this._destroyRef = _destroyRef;
139
- this._config = _config;
140
- /** Message Popover instance. */
141
- this.messagePopover$ = new Subject();
142
- /**
143
- * Error models Signal. Emitted when form submitted and contains invalid fields.
144
- */
145
- this.errors$ = signal([], /* @ts-ignore */
146
- ...(ngDevMode ? [{ debugName: "errors$" }] : /* istanbul ignore next */ []));
147
- /** @hidden */
148
- this._formFields = [];
149
- /** @hidden */
150
- this._ngForms = [];
151
- /** @hidden */
152
- this._formItemErrorsSubscription = new Subscription();
153
- /** @hidden */
154
- this._formSubmitted = false;
155
- }
156
- /** @hidden */
157
- ngAfterViewInit() {
158
- // Forms are passed via input property.
159
- if (this._ngForms.length > 0) {
160
- return;
161
- }
162
- this._projectedForm?.changes.pipe(startWith(null), takeUntilDestroyed(this._destroyRef)).subscribe(() => {
163
- this._ngForms = this._projectedForm.toArray();
164
- this._startListeningForErrors();
165
- });
166
- }
167
- /**
168
- * Sets Message Popover component instance.
169
- */
170
- setMessagePopover(messagePopover) {
171
- this.messagePopover$.next(messagePopover);
172
- // this.messagePopover = messagePopover;
173
- }
174
- /**
175
- * Programmatically add new form to array of forms.
176
- * @param forms
177
- */
178
- addForms(forms) {
179
- const formsArray = Array.isArray(forms) ? forms : [forms];
180
- this._ngForms.push(...formsArray);
181
- this._startListeningForErrors();
182
- }
183
- /**
184
- * Programmatically add new form fields to array of listened form fields.
185
- * @param formFields
186
- */
187
- addFormFields(formFields) {
188
- this._formFields.push(...formFields);
189
- this._listenToFormFieldErrors(this._formFields);
190
- }
191
- /** @hidden */
192
- ngOnDestroy() {
193
- this._formItemErrorsSubscription.unsubscribe();
194
- }
195
- /**
196
- * @hidden
197
- * Listens to the form submission and collects form control errors.
198
- */
199
- _startListeningForErrors() {
200
- if (!this._ngForms) {
201
- return;
202
- }
203
- this._formErrorsSubscription?.unsubscribe();
204
- this.errors$.set([]);
205
- const formSubmitEvents = this._ngForms.map((form) => form.ngSubmit.pipe(switchMap(() => form.statusChanges.pipe(startWith(form.status), filter((status) => status.toLowerCase() !== 'pending')))));
206
- this._formErrorsSubscription = zip(...formSubmitEvents)
207
- .pipe(takeUntilDestroyed(this._destroyRef))
208
- .subscribe(() => {
209
- this._formSubmitted = true;
210
- const errors = this._directiveItems.length > 0 ? this._collectPlainFormData() : this._collectAdvancedFormData();
211
- this.errors$.set(errors);
212
- });
213
- this._listenToFormFieldErrors(this._projectedFormFieldControls.toArray());
214
- this._projectedFormFieldControls?.changes.subscribe(() => {
215
- this._listenToFormFieldErrors(this._projectedFormFieldControls.toArray());
216
- });
217
- }
218
- /** @hidden */
219
- _listenToFormFieldErrors(fields) {
220
- this._formItemErrorsSubscription.unsubscribe();
221
- this._formItemErrorsSubscription = new Subscription();
222
- fields?.forEach((field) => {
223
- this._formItemErrorsSubscription.add(field.formField?.errorsChange$.subscribe(() => {
224
- if (!this._formSubmitted) {
225
- return;
226
- }
227
- const errors = this._directiveItems.length > 0
228
- ? this._collectPlainFormData()
229
- : this._collectAdvancedFormData();
230
- this.errors$.set(errors);
231
- }));
232
- });
233
- }
234
- /** @hidden */
235
- _collectPlainFormData() {
236
- const errors = [
237
- {
238
- errors: []
239
- }
240
- ];
241
- const fields = this._directiveItems.toArray();
242
- this._ngForms.forEach((form) => {
243
- Object.keys(form.form.controls).forEach((controlName) => {
244
- const control = form.form.get(controlName);
245
- const field = fields.find((formField) => formField.control?.name === controlName);
246
- if (!control?.errors || !field) {
247
- return;
248
- }
249
- const configErrors = Object.keys(this._config.errors);
250
- Object.keys(control.errors)
251
- .filter((error) => configErrors.includes(error))
252
- .forEach((errorKey) => {
253
- const errorObj = control.errors[errorKey];
254
- const errorTextModel = this._getConfigErrorModel(errorKey, field.errorTypes);
255
- const errorConfig = field?.errorTypes ? field?.errorTypes[errorKey] : null;
256
- const errorState = errorConfig && this._isAdvancedError(errorConfig) && errorConfig.type
257
- ? errorConfig.type
258
- : 'error';
259
- const error = {
260
- name: controlName,
261
- type: errorTextModel.type,
262
- state: convertFormState(errorState),
263
- fieldName: field?.label ?? '',
264
- element: field?.elementRef,
265
- heading: {
266
- type: 'string',
267
- error: errorObj,
268
- message: errorTextModel.heading
269
- },
270
- description: {
271
- type: 'string',
272
- error: errorObj,
273
- message: errorTextModel.description
274
- },
275
- errors: control.errors
276
- };
277
- errors[0].errors.push(error);
278
- });
279
- });
280
- });
281
- return errors;
282
- }
283
- /** @hidden */
284
- _collectAdvancedFormData() {
285
- let errors = [];
286
- const fields = this.formFields.length > 0 ? this.formFields : this._projectedFormFieldControls.toArray();
287
- /**
288
- * Iterates over form controls to collect their errors.
289
- * @param form Form Group or a collection of Form Groups.
290
- */
291
- const iterateOverForm = (form) => {
292
- if (Array.isArray(form)) {
293
- form.forEach((formGroup) => {
294
- errors = iterateOverForm(formGroup);
295
- });
296
- return errors;
297
- }
298
- Object.keys(form.controls).forEach((controlName) => {
299
- const control = form.get(controlName);
300
- const field = fields.find((formField) => formField.id === controlName);
301
- if (control instanceof FormGroup) {
302
- errors = iterateOverForm(control);
303
- }
304
- if (!control?.errors || !field) {
305
- return;
306
- }
307
- Object.keys(control.errors).forEach((errorKey) => {
308
- const errorDirective = field.formField?.groupedErrors.find((groupedError) => groupedError.directive.error === errorKey);
309
- const groupName = this._getGroupName(field?.formField);
310
- const error = this._getErrorModel(controlName, groupName, control, field, errorKey, errorDirective, control.errors[errorKey]);
311
- let errorGroupIndex = errors.findIndex((errorGroup) => errorGroup.group === groupName);
312
- if (errorGroupIndex === -1) {
313
- errorGroupIndex =
314
- errors.push({
315
- group: groupName,
316
- errors: []
317
- }) - 1;
318
- }
319
- const group = errors[errorGroupIndex];
320
- group.errors.push(error);
321
- });
322
- });
323
- return errors;
324
- };
325
- return iterateOverForm(this._ngForms.map((form) => form.form));
326
- }
327
- /**
328
- * @hidden
329
- * Creates error model
330
- */
331
- _getErrorModel(controlName, groupName, control, field, errorKey, errorDirective, error) {
332
- let state = 'error';
333
- const configError = this._config.errors[errorKey];
334
- if (errorDirective?.directive.type) {
335
- state = errorDirective.directive.type;
336
- }
337
- else if (this._isAdvancedError(configError)) {
338
- state = configError.type;
339
- }
340
- return {
341
- name: controlName,
342
- type: state,
343
- state: convertFormState(state),
344
- group: groupName,
345
- fieldName: field?.formField?.label ?? '',
346
- heading: this._getErrorText(field, errorDirective, 'heading', errorKey, error),
347
- description: this._getErrorText(field, errorDirective, 'description', errorKey, error),
348
- errors: control.errors,
349
- formField: field,
350
- element: field?.elementRef
351
- };
352
- }
353
- /**
354
- * @hidden
355
- * Creates error text based on the type of the error.
356
- * @param field Form Field Control.
357
- * @param errorDirective Optional Error directive
358
- * @param section Section where text should be rendered.
359
- * @param errorKey
360
- * @param error
361
- */
362
- _getErrorText(field, errorDirective, section = 'heading', errorKey, error) {
363
- const errorTextObj = {
364
- error: errorDirective?.error,
365
- type: errorDirective?.directive ? 'directive' : field?.formField?.i18Strings ? 'templateRef' : 'string'
366
- };
367
- if (errorTextObj.type === 'string') {
368
- const errorTextModel = this._getConfigErrorModel(errorKey);
369
- errorTextObj.error = error;
370
- errorTextObj.message = errorTextModel[section];
371
- return errorTextObj;
372
- }
373
- if (errorDirective?.directive) {
374
- errorTextObj.message =
375
- section === 'heading'
376
- ? (errorDirective.directive._headingTemplateRef ?? errorDirective.directive._descriptionTemplateRef)
377
- : errorDirective.directive._descriptionTemplateRef;
378
- return errorTextObj;
379
- }
380
- errorTextObj.message = field?.formField?.i18Strings ?? null;
381
- return errorTextObj;
382
- }
383
- /** @hidden */
384
- _getGroupName(formField) {
385
- const parts = [];
386
- if (formField?.formGroupContainer?.mainTitle) {
387
- parts.push(formField.formGroupContainer.mainTitle);
388
- }
389
- if (formField?.formFieldGroup?.label) {
390
- parts.push(formField.formFieldGroup.label);
391
- }
392
- return parts.join(', ');
393
- }
394
- /** @hidden */
395
- _getConfigErrorModel(errorKey, customErrorTypes) {
396
- const configError = customErrorTypes && customErrorTypes[errorKey] ? customErrorTypes[errorKey] : this._config.errors[errorKey];
397
- const isPlainError = !this._isAdvancedError(configError);
398
- const errorType = isPlainError ? 'error' : configError.type;
399
- const headingMessage = isPlainError ? configError : configError.heading;
400
- const descriptionMessage = isPlainError ? undefined : configError.description;
401
- return {
402
- type: errorType,
403
- heading: headingMessage,
404
- description: descriptionMessage
405
- };
406
- }
407
- /** @hidden */
408
- _isAdvancedError(error) {
409
- return !!error && typeof error !== 'string';
410
- }
411
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagePopoverFormWrapperComponent, deps: [{ token: i0.DestroyRef }, { token: FDP_MESSAGE_POPOVER_CONFIG }], target: i0.ɵɵFactoryTarget.Component }); }
412
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.2.1", type: MessagePopoverFormWrapperComponent, isStandalone: true, selector: "fdp-message-popover-form-wrapper", inputs: { forms: "forms", formFields: "formFields" }, queries: [{ propertyName: "_projectedForm", predicate: ControlContainer, descendants: true }, { propertyName: "_projectedFormFieldControls", predicate: FD_FORM_FIELD_CONTROL, descendants: true }, { propertyName: "_directiveItems", predicate: MessagePopoverFormItemDirective, descendants: true }], exportAs: ["messagePopoverWrapper"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
413
- }
414
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagePopoverFormWrapperComponent, decorators: [{
415
- type: Component,
416
- args: [{
417
- selector: 'fdp-message-popover-form-wrapper',
418
- template: `<ng-content></ng-content>`,
419
- exportAs: 'messagePopoverWrapper',
420
- changeDetection: ChangeDetectionStrategy.OnPush,
421
- encapsulation: ViewEncapsulation.None
422
- }]
423
- }], ctorParameters: () => [{ type: i0.DestroyRef }, { type: undefined, decorators: [{
424
- type: Inject,
425
- args: [FDP_MESSAGE_POPOVER_CONFIG]
426
- }] }], propDecorators: { _projectedForm: [{
427
- type: ContentChildren,
428
- args: [ControlContainer, { descendants: true }]
429
- }], _projectedFormFieldControls: [{
430
- type: ContentChildren,
431
- args: [FD_FORM_FIELD_CONTROL, { descendants: true }]
432
- }], _directiveItems: [{
433
- type: ContentChildren,
434
- args: [MessagePopoverFormItemDirective, { descendants: true }]
435
- }], forms: [{
436
- type: Input
437
- }], formFields: [{
438
- type: Input
439
- }] } });
440
-
441
- const ANIMATION_EASING = 'cubic-bezier(0, 0, 0.2, 1)';
442
- const ANIMATION_DURATION = 100;
443
- class MessagesListComponent {
444
- /** Current Message Popover screen. Can be either `list` or `details`. */
445
- set currentScreen(value) {
446
- const prev = this._currentScreen;
447
- this._currentScreen = value;
448
- if (prev && prev !== value) {
449
- this._animateScreenTransition(value);
450
- }
451
- }
452
- get currentScreen() {
453
- return this._currentScreen;
454
- }
455
- /** @hidden */
456
- constructor(_destroyRef, _tabbableService, _document) {
457
- this._destroyRef = _destroyRef;
458
- this._tabbableService = _tabbableService;
459
- this._document = _document;
460
- /** Event emitted when user clicks on error entry containing additional description. */
461
- this.openDetails = new EventEmitter();
462
- /** Event emitted when user clicks on error entry and item's element should be focused. */
463
- this.focusItem = new EventEmitter();
464
- /** Event emitted when user clicks on the field link to focus on the field itself. */
465
- this.closePopover = new EventEmitter();
466
- /** @hidden */
467
- this._currentScreen = 'list';
468
- /** @hidden */
469
- this._activeListElement = null;
470
- /** @hidden */
471
- this._listAnimation = null;
472
- /** @hidden */
473
- this._detailsAnimation = null;
474
- /** @hidden */
475
- this._translatePipe = inject(FdTranslatePipe);
476
- /** @hidden */
477
- this._additionalInfoText = this._translatePipe.transform('platformMessageView.additionalInformation');
478
- this._destroyRef.onDestroy(() => {
479
- this._listAnimation?.cancel();
480
- this._listAnimation = null;
481
- this._detailsAnimation?.cancel();
482
- this._detailsAnimation = null;
483
- });
484
- }
485
- /** @hidden */
486
- ngAfterViewInit() {
487
- resizeObservable(this.detailsView.nativeElement)
488
- .pipe(debounceTime(20), takeUntilDestroyed(this._destroyRef))
489
- .subscribe(() => {
490
- const { height } = this.detailsView.nativeElement.getBoundingClientRect();
491
- this.listSection.nativeElement.style.minHeight = `${height}px`;
492
- });
493
- }
494
- /** @hidden */
495
- showDetails(entry) {
496
- this._activeListElement = this._document.activeElement;
497
- if (!entry.description.message) {
498
- this._focusElement(undefined, entry);
499
- return;
500
- }
501
- this.currentScreen = 'details';
502
- this.openDetails.emit(entry);
503
- }
504
- /** @hidden */
505
- _focusElement(event, item) {
506
- if (!item?.element?.nativeElement) {
507
- return;
508
- }
509
- event?.stopImmediatePropagation();
510
- this.closePopover.emit(false);
511
- this.focusItem.emit(item);
512
- setTimeout(() => {
513
- const tabbableElement = this._tabbableService.getTabbableElement(item.element?.nativeElement);
514
- tabbableElement?.focus();
515
- });
516
- }
517
- /** @hidden Map message type to icon name */
518
- getIconForType(type) {
519
- return getIconForMessageType(type);
520
- }
521
- /** @hidden Get heading text for fd-text component */
522
- getHeadingText(item) {
523
- if (item.heading.type === 'string' && typeof item.heading.message === 'string') {
524
- return item.heading.message;
525
- }
526
- return '';
527
- }
528
- /** @hidden Get announcement text for screen reader when navigating to details */
529
- getAnnouncementText(entry) {
530
- let headingText = '';
531
- if (entry.heading.type === 'string' && entry.heading.message) {
532
- headingText = typeof entry.heading.message === 'string' ? entry.heading.message : '';
533
- }
534
- const additionalInfoText = this._additionalInfoText();
535
- return headingText ? `${headingText}. ${additionalInfoText}` : '';
536
- }
537
- /** @hidden Animate the transition between list and details screens. */
538
- _animateScreenTransition(screen) {
539
- const listEl = this.listSection?.nativeElement;
540
- const detailsEl = this.detailsSection?.nativeElement;
541
- if (!listEl || !detailsEl) {
542
- return;
543
- }
544
- this._listAnimation?.cancel();
545
- this._detailsAnimation?.cancel();
546
- if (screen === 'details') {
547
- this._animateListToDetails(listEl, detailsEl);
548
- }
549
- else {
550
- this._animateDetailsToList(listEl, detailsEl);
551
- }
552
- }
553
- /** @hidden Slide list out left, details in from right. */
554
- _animateListToDetails(listEl, detailsEl) {
555
- if (typeof listEl.animate !== 'function') {
556
- this._focusDetailsView();
557
- return;
558
- }
559
- this._listAnimation = listEl.animate([
560
- { transform: 'translateX(0)', opacity: 1 },
561
- { transform: 'translateX(-50px)', opacity: 0 }
562
- ], { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, fill: 'forwards' });
563
- this._detailsAnimation = detailsEl.animate([
564
- { transform: 'translateX(50px)', opacity: 0 },
565
- { transform: 'translateX(0)', opacity: 1 }
566
- ], { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, fill: 'forwards' });
567
- this._detailsAnimation.finished
568
- .then(() => {
569
- this._detailsAnimation = null;
570
- this._focusDetailsView();
571
- })
572
- .catch(() => {
573
- this._detailsAnimation = null;
574
- });
575
- }
576
- /** @hidden Slide details out right, list in from left. */
577
- _animateDetailsToList(listEl, detailsEl) {
578
- if (typeof listEl.animate !== 'function') {
579
- return;
580
- }
581
- this._detailsAnimation = detailsEl.animate([
582
- { transform: 'translateX(0)', opacity: 1 },
583
- { transform: 'translateX(50px)', opacity: 0 }
584
- ], { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, fill: 'forwards' });
585
- this._listAnimation = listEl.animate([
586
- { transform: 'translateX(-50px)', opacity: 0 },
587
- { transform: 'translateX(0)', opacity: 1 }
588
- ], { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, fill: 'forwards' });
589
- this._listAnimation.finished
590
- .then(() => {
591
- this._listAnimation = null;
592
- if (this._activeListElement) {
593
- this._activeListElement.focus();
594
- this._activeListElement = null;
595
- }
596
- })
597
- .catch(() => {
598
- this._listAnimation = null;
599
- });
600
- }
601
- /** @hidden Focus the first interactive element in the details view. */
602
- _focusDetailsView() {
603
- if (!this.detailsView?.nativeElement) {
604
- return;
605
- }
606
- // Try to find the first tabbable element in the details view
607
- const firstTabbable = this._tabbableService.getTabbableElement(this.detailsView.nativeElement);
608
- if (firstTabbable) {
609
- firstTabbable.focus();
610
- }
611
- }
612
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagesListComponent, deps: [{ token: i0.DestroyRef }, { token: i1$1.TabbableElementService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
613
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.2.1", type: MessagesListComponent, isStandalone: true, selector: "fdp-messages-list", inputs: { currentScreen: "currentScreen", filteredErrors: "filteredErrors", currentEntry: "currentEntry" }, outputs: { openDetails: "openDetails", focusItem: "focusItem", closePopover: "closePopover" }, host: { classAttribute: "fd-message-popover__view-container" }, providers: [TabbableElementService, FdTranslatePipe], viewQueries: [{ propertyName: "listView", first: true, predicate: ["listView"], descendants: true, read: ElementRef }, { propertyName: "detailsView", first: true, predicate: ["detailsView"], descendants: true, read: ElementRef }, { propertyName: "listSection", first: true, predicate: ["listSection"], descendants: true, read: ElementRef }, { propertyName: "detailsSection", first: true, predicate: ["detailsSection"], descendants: true, read: ElementRef }], ngImport: i0, template: "<ng-template #headingTemplate let-item>\n <ng-template #directiveHeading>\n <ng-template\n [ngTemplateOutlet]=\"item.heading.message || item.description.message\"\n [ngTemplateOutletContext]=\"{ $implicit: item.heading.error }\"\n ></ng-template>\n </ng-template>\n <ng-template #i18nHeading>\n <ng-template\n [ngTemplateOutlet]=\"item.heading.message\"\n [ngTemplateOutletContext]=\"{ $implicit: item.errors }\"\n ></ng-template>\n </ng-template>\n <ng-template #stringHeading>\n {{ (item.heading.message | fdTranslate: { error: item.heading.error } : item.heading.message)() }}\n </ng-template>\n <ng-template\n [ngTemplateOutlet]=\"\n item.heading.type === 'directive'\n ? directiveHeading\n : item.heading.type === 'string'\n ? stringHeading\n : i18nHeading\n \"\n ></ng-template>\n</ng-template>\n<ng-template #descriptionTemplate let-item>\n <ng-template #directiveDescription>\n <ng-template\n [ngTemplateOutlet]=\"item.description.message!\"\n [ngTemplateOutletContext]=\"{ $implicit: item.description.error }\"\n ></ng-template>\n </ng-template>\n <ng-template #i18nDescription>\n <ng-template\n [ngTemplateOutlet]=\"item.description.message!\"\n [ngTemplateOutletContext]=\"{ $implicit: item.errors }\"\n ></ng-template>\n </ng-template>\n <ng-template #stringDescription>\n {{ (item.description.message | fdTranslate: { error: item.description.error } : item.description.message)() }}\n </ng-template>\n <ng-template\n [ngTemplateOutlet]=\"\n item.description.type === 'directive'\n ? directiveDescription\n : item.description.type === 'string'\n ? stringDescription\n : i18nDescription\n \"\n ></ng-template>\n</ng-template>\n<div class=\"fd-message-view\">\n <!-- Screen reader announcement region for details view navigation -->\n <div aria-live=\"assertive\" aria-atomic=\"true\" class=\"fd-message-view__sr-only\">\n @if (currentScreen === 'details' && currentEntry) {\n {{ getAnnouncementText(currentEntry) }}\n }\n </div>\n <section\n #listSection\n class=\"fd-message-view__list\"\n [class.fd-message-view__list--hidden]=\"currentScreen === 'details'\"\n [attr.inert]=\"currentScreen === 'details' ? '' : null\"\n [attr.aria-hidden]=\"currentScreen === 'details'\"\n tabindex=\"-1\"\n fd-scrollbar\n >\n <ul #listView fd-list class=\"message-popover__list fd-list--message-view\" [navigationIndicator]=\"true\">\n @for (group of filteredErrors; track group) {\n @if (group.group) {\n <li fd-list-group-header>\n <span fd-list-title>{{ group.group }}</span>\n </li>\n }\n @for (item of group.errors; track item; let i = $index) {\n <li\n fd-list-item\n [tabindex]=\"i === 0 ? 0 : -1\"\n [byline]=\"true\"\n [counter]=\"item.aggregatedMessages!\"\n (fdkClicked)=\"showDetails(item)\"\n >\n <ng-template #itemIcon>\n <span\n fd-object-status\n class=\"fd-list__icon\"\n [status]=\"item.state\"\n [glyph]=\"getIconForType(item.type)\"\n ></span>\n </ng-template>\n <ng-template #listSubtitle>\n @if (item.heading.type === 'string' && item.heading.message) {\n <fd-text\n [text]=\"getHeadingText(item)\"\n [maxLines]=\"3\"\n [expandable]=\"true\"\n (fdkClicked)=\"$event.stopPropagation()\"\n ></fd-text>\n } @else {\n <span fd-list-subline>\n <ng-template\n [ngTemplateOutlet]=\"headingTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-template>\n </span>\n }\n </ng-template>\n @if (item.element && !!item.description.message) {\n <span fd-list-link [navigationIndicator]=\"!!item.description.message\">\n <ng-template [ngTemplateOutlet]=\"itemIcon\"></ng-template>\n <span fd-list-content>\n <span fd-list-title>\n <a tabindex=\"0\" fd-link (fdkClicked)=\"_focusElement($event, item)\">\n {{ item.fieldName }}\n </a>\n </span>\n <ng-template [ngTemplateOutlet]=\"listSubtitle\"></ng-template>\n </span>\n </span>\n } @else {\n <a fd-list-link [navigationIndicator]=\"!!item.description.message\">\n <ng-template [ngTemplateOutlet]=\"itemIcon\"></ng-template>\n <span fd-list-content>\n <span fd-list-title>{{ item.fieldName }}</span>\n <ng-template [ngTemplateOutlet]=\"listSubtitle\"></ng-template>\n </span>\n </a>\n }\n </li>\n }\n }\n </ul>\n </section>\n <section\n #detailsSection\n class=\"fd-message-view__details\"\n [class.fd-message-view__details--visible]=\"currentScreen === 'details'\"\n [attr.inert]=\"currentScreen === 'list' ? '' : null\"\n [attr.aria-hidden]=\"currentScreen === 'list'\"\n >\n <div #detailsView>\n @if (currentEntry) {\n <span class=\"fd-message-view__details-title\">\n <span\n fd-object-status\n class=\"fd-message-view__icon\"\n [status]=\"currentEntry.state\"\n [glyph]=\"getIconForType(currentEntry.type)\"\n ></span>\n <ng-template\n [ngTemplateOutlet]=\"headingTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: currentEntry }\"\n ></ng-template>\n </span>\n @if (currentEntry.subtitle) {\n <span class=\"fd-message-view__details-subtitle\">\n {{ currentEntry.subtitle }}\n </span>\n }\n @if (currentEntry.description.message) {\n <span class=\"fd-message-view__details-description\">\n <ng-template\n [ngTemplateOutlet]=\"descriptionTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: currentEntry }\"\n ></ng-template>\n </span>\n }\n @if (currentEntry.link) {\n <span class=\"fd-message-view__details-link\">\n @if (currentEntry.link.href) {\n <a\n fd-link\n [attr.href]=\"currentEntry.link.href\"\n [attr.target]=\"currentEntry.link.target || '_blank'\"\n >\n {{ currentEntry.link.text }}\n </a>\n } @else {\n <a fd-link tabindex=\"0\" (fdkClicked)=\"currentEntry.link.callback?.()\">\n {{ currentEntry.link.text }}\n </a>\n }\n </span>\n }\n }\n </div>\n </section>\n</div>\n", styles: [".fd-message-view__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fd-message-view__details-subtitle{display:block;color:var(--sapContent_LabelColor);margin-block-start:.25rem;margin-block-end:.5rem}.message-popover__list.fd-list--navigation-indication .fd-list__link--navigation-indicator:after{min-width:3rem}.fd-list__content fd-text{display:block;width:100%}.fd-list__content fd-text .fd-text{white-space:normal;margin:0;padding:0;line-height:normal}.fd-list__content fd-text .fd-text__lineclamp{display:block;line-height:normal}.fd-list__content fd-text .fd-text__link--more{pointer-events:auto}.fd-list__content fd-text .fd-text__link--more:hover{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ScrollbarDirective, selector: "[fdScrollbar], [fd-scrollbar]", inputs: ["noHorizontalScroll", "noVerticalScroll", "alwaysVisible"] }, { kind: "ngmodule", type: ListModule }, { kind: "component", type: i2.ListComponent, selector: "[fd-list], [fdList]", inputs: ["dropdownMode", "multiInputMode", "mobileMode", "hasMessage", "noBorder", "navigationIndicator", "selection", "keyboardSupport", "byline", "subline", "theme", "unreadIndicator", "role", "settingsList", "settingsListFooter", "notification", "searchResultsList"], outputs: ["focusEscapeList"] }, { kind: "component", type: i2.ListItemComponent, selector: "[fdListItem] ,[fd-list-item]", inputs: ["selected", "noData", "action", "interactive", "growing", "counter", "counterRole", "counterAriaLabel", "active", "unread", "byline", "ariaRole", "id", "preventClick", "settingsListTpl", "suggestion"], outputs: ["keyDown"], exportAs: ["fdListItem"] }, { kind: "directive", type: i2.ListTitleDirective, selector: "[fd-list-title], [fdListTitle]", inputs: ["wrap", "truncate", "scope"] }, { kind: "directive", type: i2.ListGroupHeaderDirective, selector: "[fdListGroupHeader], [fd-list-group-header]", inputs: ["nativeElementId"], outputs: ["keyDown"] }, { kind: "directive", type: i2.ListLinkDirective, selector: "[fd-list-link], [fdListLink]", inputs: ["navigationIndicator", "navigated", "focusable"] }, { kind: "directive", type: i2.ListContentDirective, selector: "[fdListContent], [fd-list-content]", inputs: ["twoCol"] }, { kind: "directive", type: i2.ListSublineDirective, selector: "[fdListSubline], [fd-list-subline]", inputs: ["truncate"] }, { kind: "component", type: ObjectStatusComponent, selector: "[fd-object-status]", inputs: ["status", "statusMessage", "glyph", "glyphFont", "label", "ariaLabel", "glyphAriaLabel", "indicationColor", "clickable", "inverted", "large", "secondaryIndication", "textTemplate", "ariaRoleDescription"] }, { kind: "component", type: LinkComponent, selector: "[fdLink], [fd-link]", inputs: ["emphasized", "disabled", "inverted", "subtle", "undecorated", "touchTarget"] }, { kind: "directive", type: ClickedDirective, selector: "[fdkClicked]", outputs: ["fdkClicked"] }, { kind: "component", type: TextComponent, selector: "fd-text", inputs: ["text", "maxLines", "whitespaces", "hyphenation", "expandable", "isCollapsed", "subline"], outputs: ["isCollapsedChange"] }, { kind: "pipe", type: FdTranslatePipe, name: "fdTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
614
- }
615
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: MessagesListComponent, decorators: [{
616
- type: Component,
617
- args: [{ selector: 'fdp-messages-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [TabbableElementService, FdTranslatePipe], host: {
618
- class: 'fd-message-popover__view-container'
619
- }, imports: [
620
- NgTemplateOutlet,
621
- CdkScrollable,
622
- ScrollbarDirective,
623
- ListModule,
624
- ObjectStatusComponent,
625
- LinkComponent,
626
- FdTranslatePipe,
627
- ClickedDirective,
628
- TextComponent
629
- ], template: "<ng-template #headingTemplate let-item>\n <ng-template #directiveHeading>\n <ng-template\n [ngTemplateOutlet]=\"item.heading.message || item.description.message\"\n [ngTemplateOutletContext]=\"{ $implicit: item.heading.error }\"\n ></ng-template>\n </ng-template>\n <ng-template #i18nHeading>\n <ng-template\n [ngTemplateOutlet]=\"item.heading.message\"\n [ngTemplateOutletContext]=\"{ $implicit: item.errors }\"\n ></ng-template>\n </ng-template>\n <ng-template #stringHeading>\n {{ (item.heading.message | fdTranslate: { error: item.heading.error } : item.heading.message)() }}\n </ng-template>\n <ng-template\n [ngTemplateOutlet]=\"\n item.heading.type === 'directive'\n ? directiveHeading\n : item.heading.type === 'string'\n ? stringHeading\n : i18nHeading\n \"\n ></ng-template>\n</ng-template>\n<ng-template #descriptionTemplate let-item>\n <ng-template #directiveDescription>\n <ng-template\n [ngTemplateOutlet]=\"item.description.message!\"\n [ngTemplateOutletContext]=\"{ $implicit: item.description.error }\"\n ></ng-template>\n </ng-template>\n <ng-template #i18nDescription>\n <ng-template\n [ngTemplateOutlet]=\"item.description.message!\"\n [ngTemplateOutletContext]=\"{ $implicit: item.errors }\"\n ></ng-template>\n </ng-template>\n <ng-template #stringDescription>\n {{ (item.description.message | fdTranslate: { error: item.description.error } : item.description.message)() }}\n </ng-template>\n <ng-template\n [ngTemplateOutlet]=\"\n item.description.type === 'directive'\n ? directiveDescription\n : item.description.type === 'string'\n ? stringDescription\n : i18nDescription\n \"\n ></ng-template>\n</ng-template>\n<div class=\"fd-message-view\">\n <!-- Screen reader announcement region for details view navigation -->\n <div aria-live=\"assertive\" aria-atomic=\"true\" class=\"fd-message-view__sr-only\">\n @if (currentScreen === 'details' && currentEntry) {\n {{ getAnnouncementText(currentEntry) }}\n }\n </div>\n <section\n #listSection\n class=\"fd-message-view__list\"\n [class.fd-message-view__list--hidden]=\"currentScreen === 'details'\"\n [attr.inert]=\"currentScreen === 'details' ? '' : null\"\n [attr.aria-hidden]=\"currentScreen === 'details'\"\n tabindex=\"-1\"\n fd-scrollbar\n >\n <ul #listView fd-list class=\"message-popover__list fd-list--message-view\" [navigationIndicator]=\"true\">\n @for (group of filteredErrors; track group) {\n @if (group.group) {\n <li fd-list-group-header>\n <span fd-list-title>{{ group.group }}</span>\n </li>\n }\n @for (item of group.errors; track item; let i = $index) {\n <li\n fd-list-item\n [tabindex]=\"i === 0 ? 0 : -1\"\n [byline]=\"true\"\n [counter]=\"item.aggregatedMessages!\"\n (fdkClicked)=\"showDetails(item)\"\n >\n <ng-template #itemIcon>\n <span\n fd-object-status\n class=\"fd-list__icon\"\n [status]=\"item.state\"\n [glyph]=\"getIconForType(item.type)\"\n ></span>\n </ng-template>\n <ng-template #listSubtitle>\n @if (item.heading.type === 'string' && item.heading.message) {\n <fd-text\n [text]=\"getHeadingText(item)\"\n [maxLines]=\"3\"\n [expandable]=\"true\"\n (fdkClicked)=\"$event.stopPropagation()\"\n ></fd-text>\n } @else {\n <span fd-list-subline>\n <ng-template\n [ngTemplateOutlet]=\"headingTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-template>\n </span>\n }\n </ng-template>\n @if (item.element && !!item.description.message) {\n <span fd-list-link [navigationIndicator]=\"!!item.description.message\">\n <ng-template [ngTemplateOutlet]=\"itemIcon\"></ng-template>\n <span fd-list-content>\n <span fd-list-title>\n <a tabindex=\"0\" fd-link (fdkClicked)=\"_focusElement($event, item)\">\n {{ item.fieldName }}\n </a>\n </span>\n <ng-template [ngTemplateOutlet]=\"listSubtitle\"></ng-template>\n </span>\n </span>\n } @else {\n <a fd-list-link [navigationIndicator]=\"!!item.description.message\">\n <ng-template [ngTemplateOutlet]=\"itemIcon\"></ng-template>\n <span fd-list-content>\n <span fd-list-title>{{ item.fieldName }}</span>\n <ng-template [ngTemplateOutlet]=\"listSubtitle\"></ng-template>\n </span>\n </a>\n }\n </li>\n }\n }\n </ul>\n </section>\n <section\n #detailsSection\n class=\"fd-message-view__details\"\n [class.fd-message-view__details--visible]=\"currentScreen === 'details'\"\n [attr.inert]=\"currentScreen === 'list' ? '' : null\"\n [attr.aria-hidden]=\"currentScreen === 'list'\"\n >\n <div #detailsView>\n @if (currentEntry) {\n <span class=\"fd-message-view__details-title\">\n <span\n fd-object-status\n class=\"fd-message-view__icon\"\n [status]=\"currentEntry.state\"\n [glyph]=\"getIconForType(currentEntry.type)\"\n ></span>\n <ng-template\n [ngTemplateOutlet]=\"headingTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: currentEntry }\"\n ></ng-template>\n </span>\n @if (currentEntry.subtitle) {\n <span class=\"fd-message-view__details-subtitle\">\n {{ currentEntry.subtitle }}\n </span>\n }\n @if (currentEntry.description.message) {\n <span class=\"fd-message-view__details-description\">\n <ng-template\n [ngTemplateOutlet]=\"descriptionTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: currentEntry }\"\n ></ng-template>\n </span>\n }\n @if (currentEntry.link) {\n <span class=\"fd-message-view__details-link\">\n @if (currentEntry.link.href) {\n <a\n fd-link\n [attr.href]=\"currentEntry.link.href\"\n [attr.target]=\"currentEntry.link.target || '_blank'\"\n >\n {{ currentEntry.link.text }}\n </a>\n } @else {\n <a fd-link tabindex=\"0\" (fdkClicked)=\"currentEntry.link.callback?.()\">\n {{ currentEntry.link.text }}\n </a>\n }\n </span>\n }\n }\n </div>\n </section>\n</div>\n", styles: [".fd-message-view__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fd-message-view__details-subtitle{display:block;color:var(--sapContent_LabelColor);margin-block-start:.25rem;margin-block-end:.5rem}.message-popover__list.fd-list--navigation-indication .fd-list__link--navigation-indicator:after{min-width:3rem}.fd-list__content fd-text{display:block;width:100%}.fd-list__content fd-text .fd-text{white-space:normal;margin:0;padding:0;line-height:normal}.fd-list__content fd-text .fd-text__lineclamp{display:block;line-height:normal}.fd-list__content fd-text .fd-text__link--more{pointer-events:auto}.fd-list__content fd-text .fd-text__link--more:hover{text-decoration:underline}\n"] }]
630
- }], ctorParameters: () => [{ type: i0.DestroyRef }, { type: i1$1.TabbableElementService }, { type: Document, decorators: [{
631
- type: Inject,
632
- args: [DOCUMENT]
633
- }] }], propDecorators: { currentScreen: [{
634
- type: Input
635
- }], filteredErrors: [{
636
- type: Input
637
- }], currentEntry: [{
638
- type: Input
639
- }], openDetails: [{
640
- type: Output
641
- }], focusItem: [{
642
- type: Output
643
- }], closePopover: [{
644
- type: Output
645
- }], listView: [{
646
- type: ViewChild,
647
- args: ['listView', { read: ElementRef }]
648
- }], detailsView: [{
649
- type: ViewChild,
650
- args: ['detailsView', { read: ElementRef }]
651
- }], listSection: [{
652
- type: ViewChild,
653
- args: ['listSection', { read: ElementRef }]
654
- }], detailsSection: [{
655
- type: ViewChild,
656
- args: ['detailsSection', { read: ElementRef }]
657
- }] } });
658
-
659
- /**
660
- * Abstract base class for message list components (MessagePopover and MessageView).
661
- * Contains shared logic for managing error states, filtering, and navigation between list/detail views.
662
- */
663
- class MessageListShared {
664
- constructor() {
665
- /** Event emits when user clicks on error entry and item's element needs to be focused. */
666
- this.focusItem = new EventEmitter();
667
- /** Current message popover screen. Can be `list` or `details`. */
668
- this.currentScreen = 'list';
669
- /** Current error entry. */
670
- this.currentEntry = null;
671
- /** @hidden */
672
- this._currentErrorType = signal('all', /* @ts-ignore */
673
- ...(ngDevMode ? [{ debugName: "_currentErrorType" }] : /* istanbul ignore next */ []));
674
- /** @hidden */
675
- this._errorTypes$ = computed(() => {
676
- const countedErrors = this.countedErrors$();
677
- const errorTypes = Object.keys(countedErrors);
678
- return errorTypes.map((errorType) => ({
679
- group: errorType,
680
- count: countedErrors[errorType],
681
- state: convertFormState(errorType)
682
- }));
683
- }, /* @ts-ignore */
684
- ...(ngDevMode ? [{ debugName: "_errorTypes$" }] : /* istanbul ignore next */ []));
685
- /** @hidden */
686
- this._priorityStateItemsCount$ = computed(() => this.countedErrors$()[this._priorityFormState$()] || 0, /* @ts-ignore */
687
- ...(ngDevMode ? [{ debugName: "_priorityStateItemsCount$" }] : /* istanbul ignore next */ []));
688
- /** @hidden */
689
- this._priorityFormState$ = computed(() => {
690
- const countedErrors = this.countedErrors$();
691
- const errorTypes = Object.keys(countedErrors);
692
- return getFormState(errorTypes);
693
- }, /* @ts-ignore */
694
- ...(ngDevMode ? [{ debugName: "_priorityFormState$" }] : /* istanbul ignore next */ []));
695
- /** @hidden */
696
- this._priorityState$ = computed(() => convertFormStateToMessagePopoverState(this._priorityFormState$()), /* @ts-ignore */
697
- ...(ngDevMode ? [{ debugName: "_priorityState$" }] : /* istanbul ignore next */ []));
698
- /** @hidden */
699
- this._filteredErrors$ = computed(() => {
700
- const groupedErrors = this.groupedErrors$();
701
- const errorType = this._currentErrorType();
702
- if (errorType === 'all') {
703
- return groupedErrors;
704
- }
705
- const filteredErrors = [];
706
- groupedErrors.forEach((group) => {
707
- const errors = group.errors.filter((error) => error.type === errorType);
708
- if (errors.length === 0) {
709
- return;
710
- }
711
- filteredErrors.push({
712
- group: group.group,
713
- errors
714
- });
715
- });
716
- return filteredErrors;
717
- }, /* @ts-ignore */
718
- ...(ngDevMode ? [{ debugName: "_filteredErrors$" }] : /* istanbul ignore next */ []));
719
- /** @hidden */
720
- this.groupedErrors$ = computed(() => this.wrapper$()?.errors$() || [], /* @ts-ignore */
721
- ...(ngDevMode ? [{ debugName: "groupedErrors$" }] : /* istanbul ignore next */ []));
722
- /** @hidden */
723
- this.wrapper$ = signal(null, /* @ts-ignore */
724
- ...(ngDevMode ? [{ debugName: "wrapper$" }] : /* istanbul ignore next */ []));
725
- /** @hidden */
726
- this.countedErrors$ = computed(() => {
727
- const allErrors = this.groupedErrors$().flatMap((group) => group.errors);
728
- return countBy(allErrors, 'type');
729
- }, /* @ts-ignore */
730
- ...(ngDevMode ? [{ debugName: "countedErrors$" }] : /* istanbul ignore next */ []));
731
- }
732
- /** @hidden */
733
- showList() {
734
- this.currentScreen = 'list';
735
- this.currentEntry = null;
736
- }
737
- /** @hidden */
738
- showDetails(entry) {
739
- this.currentScreen = 'details';
740
- this.currentEntry = entry;
741
- }
742
- }
743
-
744
- /**
745
- * @deprecated
746
- * Use direct imports of components and directives.
747
- */
748
- class PlatformMessagesSharedModule {
749
- /**
750
- * Method allows users to apply custom configuration.
751
- * @param config Object containing error definitions.
752
- */
753
- static withConfig(config) {
754
- const customConfig = mergeWith(FDP_MESSAGE_POPOVER_DEFAULT_CONFIG, config, (obj, src) => {
755
- if (typeof obj === 'object' && !Array.isArray(obj)) {
756
- return Object.assign(obj, src);
757
- }
758
- else if (Array.isArray(obj)) {
759
- return obj.concat(src);
760
- }
761
- else {
762
- return src;
763
- }
764
- });
765
- return {
766
- ngModule: PlatformMessagesSharedModule,
767
- providers: [
768
- {
769
- provide: FDP_MESSAGE_POPOVER_CONFIG,
770
- useValue: customConfig
771
- }
772
- ]
773
- };
774
- }
775
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: PlatformMessagesSharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
776
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.2.1", ngImport: i0, type: PlatformMessagesSharedModule, imports: [MessagePopoverFormWrapperComponent, MessagesListComponent, MessagePopoverFormItemDirective], exports: [MessagePopoverFormWrapperComponent, MessagesListComponent, MessagePopoverFormItemDirective] }); }
777
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: PlatformMessagesSharedModule, providers: [
778
- {
779
- provide: FDP_MESSAGE_POPOVER_CONFIG,
780
- useValue: FDP_MESSAGE_POPOVER_DEFAULT_CONFIG
781
- }
782
- ], imports: [MessagesListComponent] }); }
783
- }
784
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: PlatformMessagesSharedModule, decorators: [{
785
- type: NgModule,
786
- args: [{
787
- imports: [MessagePopoverFormWrapperComponent, MessagesListComponent, MessagePopoverFormItemDirective],
788
- exports: [MessagePopoverFormWrapperComponent, MessagesListComponent, MessagePopoverFormItemDirective],
789
- providers: [
790
- {
791
- provide: FDP_MESSAGE_POPOVER_CONFIG,
792
- useValue: FDP_MESSAGE_POPOVER_DEFAULT_CONFIG
793
- }
794
- ]
795
- }]
796
- }] });
797
-
798
- /**
799
- * Generated bundle index. Do not edit.
800
- */
801
-
802
- export { FDP_MESSAGE_POPOVER_CONFIG, FDP_MESSAGE_POPOVER_DEFAULT_CONFIG, MessageListShared, MessagePopoverFormItemDirective, MessagePopoverFormWrapperComponent, MessagesListComponent, PlatformMessagesSharedModule, convertFormState, convertFormStateToMessagePopoverState, getIconForMessageType };
803
- //# sourceMappingURL=fundamental-ngx-platform-messages-shared.mjs.map