@eherve/angular-material-section-tabs 0.0.0-stage → 22.0.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.
@@ -0,0 +1,1680 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, ErrorHandler, EventEmitter, Inject, Injectable, InjectionToken, Input, LOCALE_ID, NgModule, Output, ViewEncapsulation, booleanAttribute, inject, reflectComponentType } from "@angular/core";
3
+ import * as i1 from "@angular/common";
4
+ import { CommonModule, formatDate } from "@angular/common";
5
+ import * as i3 from "@angular/material/button";
6
+ import { MatButtonModule } from "@angular/material/button";
7
+ import * as i6 from "@angular/material/core";
8
+ import { MatRippleModule } from "@angular/material/core";
9
+ import * as i4 from "@angular/material/icon";
10
+ import { MatIconModule } from "@angular/material/icon";
11
+ import * as i5 from "@angular/material/menu";
12
+ import { MatMenuModule } from "@angular/material/menu";
13
+ import * as i7 from "@angular/material/slide-toggle";
14
+ import { MatSlideToggleModule } from "@angular/material/slide-toggle";
15
+ import * as i8 from "@angular/material/tooltip";
16
+ import { MatTooltipModule } from "@angular/material/tooltip";
17
+ import { Subject, Subscription } from "rxjs";
18
+ import { animate, group, query, style, transition, trigger } from "@angular/animations";
19
+ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
20
+ const SECTION_SELECTION_HANDLER = new InjectionToken("SECTION_SELECTION_HANDLER");
21
+ var SectionTabContentDirective = class SectionTabContentDirective {
22
+ templateRef;
23
+ constructor(templateRef) {
24
+ this.templateRef = templateRef;
25
+ }
26
+ static ɵfac = i0.ɵɵngDeclareFactory({
27
+ minVersion: "12.0.0",
28
+ version: "22.2.1",
29
+ ngImport: i0,
30
+ type: SectionTabContentDirective,
31
+ deps: [{ token: i0.TemplateRef }],
32
+ target: i0.ɵɵFactoryTarget.Directive
33
+ });
34
+ static ɵdir = i0.ɵɵngDeclareDirective({
35
+ minVersion: "14.0.0",
36
+ version: "22.2.1",
37
+ type: SectionTabContentDirective,
38
+ isStandalone: false,
39
+ selector: "ng-template[appSectionTabContent]",
40
+ ngImport: i0
41
+ });
42
+ };
43
+ i0.ɵɵngDeclareClassMetadata({
44
+ minVersion: "12.0.0",
45
+ version: "22.2.1",
46
+ ngImport: i0,
47
+ type: SectionTabContentDirective,
48
+ decorators: [{
49
+ type: Directive,
50
+ args: [{
51
+ selector: "ng-template[appSectionTabContent]",
52
+ standalone: false
53
+ }]
54
+ }],
55
+ ctorParameters: () => [{ type: i0.TemplateRef }]
56
+ });
57
+ var SectionTabLabelDirective = class SectionTabLabelDirective {
58
+ templateRef;
59
+ constructor(templateRef) {
60
+ this.templateRef = templateRef;
61
+ }
62
+ static ɵfac = i0.ɵɵngDeclareFactory({
63
+ minVersion: "12.0.0",
64
+ version: "22.2.1",
65
+ ngImport: i0,
66
+ type: SectionTabLabelDirective,
67
+ deps: [{ token: i0.TemplateRef }],
68
+ target: i0.ɵɵFactoryTarget.Directive
69
+ });
70
+ static ɵdir = i0.ɵɵngDeclareDirective({
71
+ minVersion: "14.0.0",
72
+ version: "22.2.1",
73
+ type: SectionTabLabelDirective,
74
+ isStandalone: false,
75
+ selector: "ng-template[appSectionTabLabel]",
76
+ ngImport: i0
77
+ });
78
+ };
79
+ i0.ɵɵngDeclareClassMetadata({
80
+ minVersion: "12.0.0",
81
+ version: "22.2.1",
82
+ ngImport: i0,
83
+ type: SectionTabLabelDirective,
84
+ decorators: [{
85
+ type: Directive,
86
+ args: [{
87
+ selector: "ng-template[appSectionTabLabel]",
88
+ standalone: false
89
+ }]
90
+ }],
91
+ ctorParameters: () => [{ type: i0.TemplateRef }]
92
+ });
93
+ var SectionTabComponent = class SectionTabComponent {
94
+ type = "button";
95
+ queryParamValue;
96
+ disabled = false;
97
+ done;
98
+ total;
99
+ totalMax;
100
+ progress = true;
101
+ statusColor = "#607286";
102
+ statusColorDone;
103
+ statusColorTotal;
104
+ labelDirective;
105
+ contentDirective;
106
+ stateChanges = new Subject();
107
+ ngOnChanges() {
108
+ this.stateChanges.next();
109
+ }
110
+ ngOnDestroy() {
111
+ this.stateChanges.complete();
112
+ }
113
+ static ɵfac = i0.ɵɵngDeclareFactory({
114
+ minVersion: "12.0.0",
115
+ version: "22.2.1",
116
+ ngImport: i0,
117
+ type: SectionTabComponent,
118
+ deps: [],
119
+ target: i0.ɵɵFactoryTarget.Component
120
+ });
121
+ static ɵcmp = i0.ɵɵngDeclareComponent({
122
+ minVersion: "16.1.0",
123
+ version: "22.2.1",
124
+ type: SectionTabComponent,
125
+ isStandalone: false,
126
+ selector: "app-section-tab",
127
+ inputs: {
128
+ type: "type",
129
+ queryParamValue: "queryParamValue",
130
+ disabled: [
131
+ "disabled",
132
+ "disabled",
133
+ booleanAttribute
134
+ ],
135
+ done: "done",
136
+ total: "total",
137
+ totalMax: "totalMax",
138
+ progress: "progress",
139
+ statusColor: "statusColor",
140
+ statusColorDone: "statusColorDone",
141
+ statusColorTotal: "statusColorTotal"
142
+ },
143
+ queries: [{
144
+ propertyName: "labelDirective",
145
+ first: true,
146
+ predicate: SectionTabLabelDirective,
147
+ descendants: true
148
+ }, {
149
+ propertyName: "contentDirective",
150
+ first: true,
151
+ predicate: SectionTabContentDirective,
152
+ descendants: true
153
+ }],
154
+ usesOnChanges: true,
155
+ ngImport: i0,
156
+ template: "",
157
+ isInline: true,
158
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
159
+ });
160
+ };
161
+ i0.ɵɵngDeclareClassMetadata({
162
+ minVersion: "12.0.0",
163
+ version: "22.2.1",
164
+ ngImport: i0,
165
+ type: SectionTabComponent,
166
+ decorators: [{
167
+ type: Component,
168
+ args: [{
169
+ selector: "app-section-tab",
170
+ template: "",
171
+ changeDetection: ChangeDetectionStrategy.OnPush,
172
+ standalone: false
173
+ }]
174
+ }],
175
+ propDecorators: {
176
+ type: [{ type: Input }],
177
+ queryParamValue: [{ type: Input }],
178
+ disabled: [{
179
+ type: Input,
180
+ args: [{ transform: booleanAttribute }]
181
+ }],
182
+ done: [{ type: Input }],
183
+ total: [{ type: Input }],
184
+ totalMax: [{ type: Input }],
185
+ progress: [{ type: Input }],
186
+ statusColor: [{ type: Input }],
187
+ statusColorDone: [{ type: Input }],
188
+ statusColorTotal: [{ type: Input }],
189
+ labelDirective: [{
190
+ type: ContentChild,
191
+ args: [SectionTabLabelDirective]
192
+ }],
193
+ contentDirective: [{
194
+ type: ContentChild,
195
+ args: [SectionTabContentDirective]
196
+ }]
197
+ }
198
+ });
199
+ var SectionTabsIntl = class SectionTabsIntl {
200
+ changes = new Subject();
201
+ messages = {
202
+ sections: "Sections",
203
+ emptySections: "Aucune section à afficher",
204
+ emptyComponents: "Aucun composant configuré",
205
+ emptyFields: "Aucun champ renseigné",
206
+ emptyFieldsDescription: "Activez l'affichage des champs vides pour voir les informations attendues.",
207
+ showEmptyFields: "Afficher les champs vides"
208
+ };
209
+ static ɵfac = i0.ɵɵngDeclareFactory({
210
+ minVersion: "12.0.0",
211
+ version: "22.2.1",
212
+ ngImport: i0,
213
+ type: SectionTabsIntl,
214
+ deps: [],
215
+ target: i0.ɵɵFactoryTarget.Injectable
216
+ });
217
+ static ɵprov = i0.ɵɵngDeclareInjectable({
218
+ minVersion: "12.0.0",
219
+ version: "22.2.1",
220
+ ngImport: i0,
221
+ type: SectionTabsIntl,
222
+ providedIn: "root"
223
+ });
224
+ };
225
+ i0.ɵɵngDeclareClassMetadata({
226
+ minVersion: "12.0.0",
227
+ version: "22.2.1",
228
+ ngImport: i0,
229
+ type: SectionTabsIntl,
230
+ decorators: [{
231
+ type: Injectable,
232
+ args: [{ providedIn: "root" }]
233
+ }]
234
+ });
235
+ var SectionTabsFooterDirective = class SectionTabsFooterDirective {
236
+ templateRef;
237
+ constructor(templateRef) {
238
+ this.templateRef = templateRef;
239
+ }
240
+ static ɵfac = i0.ɵɵngDeclareFactory({
241
+ minVersion: "12.0.0",
242
+ version: "22.2.1",
243
+ ngImport: i0,
244
+ type: SectionTabsFooterDirective,
245
+ deps: [{ token: i0.TemplateRef }],
246
+ target: i0.ɵɵFactoryTarget.Directive
247
+ });
248
+ static ɵdir = i0.ɵɵngDeclareDirective({
249
+ minVersion: "14.0.0",
250
+ version: "22.2.1",
251
+ type: SectionTabsFooterDirective,
252
+ isStandalone: false,
253
+ selector: "ng-template[appSectionTabsFooter]",
254
+ ngImport: i0
255
+ });
256
+ };
257
+ i0.ɵɵngDeclareClassMetadata({
258
+ minVersion: "12.0.0",
259
+ version: "22.2.1",
260
+ ngImport: i0,
261
+ type: SectionTabsFooterDirective,
262
+ decorators: [{
263
+ type: Directive,
264
+ args: [{
265
+ selector: "ng-template[appSectionTabsFooter]",
266
+ standalone: false
267
+ }]
268
+ }],
269
+ ctorParameters: () => [{ type: i0.TemplateRef }]
270
+ });
271
+ var SectionTabsMenuHeaderDirective = class SectionTabsMenuHeaderDirective {
272
+ templateRef;
273
+ constructor(templateRef) {
274
+ this.templateRef = templateRef;
275
+ }
276
+ static ɵfac = i0.ɵɵngDeclareFactory({
277
+ minVersion: "12.0.0",
278
+ version: "22.2.1",
279
+ ngImport: i0,
280
+ type: SectionTabsMenuHeaderDirective,
281
+ deps: [{ token: i0.TemplateRef }],
282
+ target: i0.ɵɵFactoryTarget.Directive
283
+ });
284
+ static ɵdir = i0.ɵɵngDeclareDirective({
285
+ minVersion: "14.0.0",
286
+ version: "22.2.1",
287
+ type: SectionTabsMenuHeaderDirective,
288
+ isStandalone: false,
289
+ selector: "ng-template[appSectionTabsMenuHeader]",
290
+ ngImport: i0
291
+ });
292
+ };
293
+ i0.ɵɵngDeclareClassMetadata({
294
+ minVersion: "12.0.0",
295
+ version: "22.2.1",
296
+ ngImport: i0,
297
+ type: SectionTabsMenuHeaderDirective,
298
+ decorators: [{
299
+ type: Directive,
300
+ args: [{
301
+ selector: "ng-template[appSectionTabsMenuHeader]",
302
+ standalone: false
303
+ }]
304
+ }],
305
+ ctorParameters: () => [{ type: i0.TemplateRef }]
306
+ });
307
+ const sectionTabsSlideTopTransitions = [query(":enter, :leave", style({
308
+ position: "absolute",
309
+ inset: 0,
310
+ width: "100%",
311
+ height: "100%",
312
+ overflow: "auto"
313
+ }), { optional: true }), group([query(":enter", [style({
314
+ opacity: 0,
315
+ transform: "translateY(100%)"
316
+ }), animate(".3s ease-out", style({
317
+ opacity: 1,
318
+ transform: "translateY(0%)"
319
+ }))], { optional: true }), query(":leave", [style({
320
+ opacity: 1,
321
+ transform: "translateY(0%)"
322
+ }), animate(".3s ease-out", style({
323
+ opacity: 0,
324
+ transform: "translateY(-100%)"
325
+ }))], { optional: true })])];
326
+ const sectionTabsSlideBottomTransitions = [query(":enter, :leave", style({
327
+ position: "absolute",
328
+ inset: 0,
329
+ width: "100%",
330
+ height: "100%",
331
+ overflow: "auto"
332
+ }), { optional: true }), group([query(":enter", [style({
333
+ opacity: 0,
334
+ transform: "translateY(-100%)"
335
+ }), animate(".3s ease-out", style({
336
+ opacity: 1,
337
+ transform: "translateY(0%)"
338
+ }))], { optional: true }), query(":leave", [style({
339
+ opacity: 1,
340
+ transform: "translateY(0%)"
341
+ }), animate(".3s ease-out", style({
342
+ opacity: 0,
343
+ transform: "translateY(100%)"
344
+ }))], { optional: true })])];
345
+ var SectionTabsComponent = class SectionTabsComponent {
346
+ static nextId = 0;
347
+ selectedIndex = 0;
348
+ queryParamKey;
349
+ selectedIndexChange = new EventEmitter();
350
+ tabComponents;
351
+ menuHeaderDirective;
352
+ footerDirective;
353
+ intl = inject(SectionTabsIntl);
354
+ instanceId = `section-tabs-${SectionTabsComponent.nextId++}`;
355
+ tabItems = [];
356
+ activeTabItems = [];
357
+ selectedTabItem;
358
+ menuHeaderTemplate;
359
+ footerTemplate;
360
+ changeDetectorRef = inject(ChangeDetectorRef);
361
+ handler = inject(SECTION_SELECTION_HANDLER, { optional: true });
362
+ errorHandler = inject(ErrorHandler);
363
+ handlerSubscription;
364
+ handlerGeneration = 0;
365
+ externalValue = null;
366
+ subscriptions = new Subscription();
367
+ tabStateSubscriptions = new Subscription();
368
+ contentInitialized = false;
369
+ ngAfterContentInit() {
370
+ this.contentInitialized = true;
371
+ this.subscriptions.add(this.intl.changes.subscribe(() => this.changeDetectorRef.markForCheck()));
372
+ this.refreshProjectedTemplates();
373
+ this.refreshTabItems();
374
+ this.synchronizeSelectionWithQueryParameter();
375
+ this.bindSelectionHandler();
376
+ this.subscriptions.add(this.tabComponents.changes.subscribe(() => this.handleTabsChange()));
377
+ }
378
+ ngOnChanges(changes) {
379
+ if (!this.contentInitialized) return;
380
+ if (changes["queryParamKey"]) {
381
+ this.bindSelectionHandler();
382
+ this.synchronizeSelectionWithQueryParameter();
383
+ return;
384
+ }
385
+ if (!changes["selectedIndex"]) return;
386
+ this.synchronizeSelectionWithQueryParameter();
387
+ }
388
+ ngOnDestroy() {
389
+ this.handlerGeneration++;
390
+ this.handlerSubscription?.unsubscribe();
391
+ this.subscriptions.unsubscribe();
392
+ this.tabStateSubscriptions.unsubscribe();
393
+ }
394
+ selectTab(tabItem) {
395
+ if (!this.isSelectableTabItem(tabItem)) return;
396
+ this.applySelectedIndex(tabItem.index, true);
397
+ this.updateQueryParameter(tabItem);
398
+ }
399
+ handleTabsChange() {
400
+ this.refreshProjectedTemplates();
401
+ this.refreshTabItems();
402
+ this.synchronizeSelectionWithQueryParameter();
403
+ }
404
+ handleTabStateChange() {
405
+ this.refreshTabItems(false);
406
+ this.synchronizeSelectionWithQueryParameter();
407
+ }
408
+ refreshProjectedTemplates() {
409
+ this.menuHeaderTemplate = this.menuHeaderDirective?.templateRef;
410
+ this.footerTemplate = this.footerDirective?.templateRef;
411
+ }
412
+ refreshTabItems(refreshSubscriptions = true) {
413
+ const tabs = this.tabComponents?.toArray() ?? [];
414
+ this.tabItems = this.buildTabItems(tabs);
415
+ if (refreshSubscriptions) this.refreshTabStateSubscriptions(tabs);
416
+ }
417
+ buildTabItems(tabs) {
418
+ let buttonIndex = 0;
419
+ return tabs.map((tab, renderIndex) => {
420
+ const index = tab.type === "separator" ? -1 : buttonIndex++;
421
+ return this.buildTabItem(tab, index, renderIndex);
422
+ });
423
+ }
424
+ refreshTabStateSubscriptions(tabs) {
425
+ this.tabStateSubscriptions.unsubscribe();
426
+ const subscription = new Subscription();
427
+ tabs.forEach((tab) => {
428
+ subscription.add(tab.stateChanges.subscribe(() => this.handleTabStateChange()));
429
+ });
430
+ this.tabStateSubscriptions = subscription;
431
+ }
432
+ buildTabItem(tab, index, renderIndex) {
433
+ const isButton = tab.type === "button";
434
+ return {
435
+ tab,
436
+ type: tab.type,
437
+ index,
438
+ renderIndex,
439
+ queryParamValue: isButton ? tab.queryParamValue : void 0,
440
+ selected: isButton && index === this.selectedIndex,
441
+ disabled: isButton && tab.disabled,
442
+ buttonId: `${this.instanceId}-button-${renderIndex}`,
443
+ panelId: `${this.instanceId}-panel-${renderIndex}`,
444
+ statusDoneLabel: isButton ? this.buildDoneLabel(tab.done) : void 0,
445
+ statusTotalLabel: isButton ? this.buildTotalLabel(tab.done, tab.total, tab.totalMax) : void 0,
446
+ progress: tab.progress && isButton ? this.buildProgress(tab.done, tab.total) : void 0,
447
+ labelTemplate: tab.labelDirective?.templateRef,
448
+ contentTemplate: isButton ? tab.contentDirective?.templateRef : void 0
449
+ };
450
+ }
451
+ synchronizeSelectionWithQueryParameter() {
452
+ const queryParamValue = this.getQueryParameterValue();
453
+ if (queryParamValue === null) {
454
+ this.applySelectedIndex(this.selectedIndex, false);
455
+ return;
456
+ }
457
+ const queryParamTabItem = this.tabItems.find((tabItem) => tabItem.queryParamValue === queryParamValue);
458
+ if (!queryParamTabItem || !this.isSelectableTabItem(queryParamTabItem)) {
459
+ this.applySelectedIndex(this.selectedIndex, false);
460
+ return;
461
+ }
462
+ this.applySelectedIndex(queryParamTabItem.index, true);
463
+ }
464
+ bindSelectionHandler() {
465
+ const generation = ++this.handlerGeneration;
466
+ this.handlerSubscription?.unsubscribe();
467
+ this.externalValue = null;
468
+ const key = this.queryParamKey;
469
+ if (!this.handler || !key?.trim()) return;
470
+ try {
471
+ this.handlerSubscription = this.handler.observe(key).subscribe({
472
+ next: (value) => {
473
+ if (generation !== this.handlerGeneration) return;
474
+ this.externalValue = value;
475
+ this.synchronizeSelectionWithQueryParameter();
476
+ this.changeDetectorRef.markForCheck();
477
+ },
478
+ error: (error) => {
479
+ if (generation === this.handlerGeneration) this.errorHandler.handleError(error);
480
+ }
481
+ });
482
+ } catch (error) {
483
+ this.errorHandler.handleError(error);
484
+ }
485
+ }
486
+ getQueryParameterValue() {
487
+ return this.externalValue;
488
+ }
489
+ updateQueryParameter(tabItem) {
490
+ const key = this.queryParamKey;
491
+ const value = tabItem.queryParamValue;
492
+ if (!this.handler || !key?.trim() || value === void 0 || value === this.externalValue) return;
493
+ try {
494
+ const result = this.handler.select(key, value);
495
+ if (result) Promise.resolve(result).catch((error) => this.errorHandler.handleError(error));
496
+ } catch (error) {
497
+ this.errorHandler.handleError(error);
498
+ }
499
+ }
500
+ buildDoneLabel(done) {
501
+ return this.hasCounterValue(done) ? `${done}` : void 0;
502
+ }
503
+ buildTotalLabel(done, total, totalMax) {
504
+ if (!this.hasCounterValue(done) || !this.hasCounterValue(total)) return void 0;
505
+ return `/${this.buildDisplayedTotal(total, totalMax)}`;
506
+ }
507
+ buildDisplayedTotal(total, totalMax) {
508
+ const numericTotal = this.toNumericCounter(total);
509
+ const numericTotalMax = this.toNumericCounter(totalMax);
510
+ if (numericTotal !== void 0 && numericTotalMax !== void 0 && numericTotal > numericTotalMax) return `+${numericTotalMax}`;
511
+ return `${total}`;
512
+ }
513
+ toNumericCounter(value) {
514
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
515
+ if (typeof value !== "string" || value.trim() === "") return void 0;
516
+ const numericValue = Number(value);
517
+ return Number.isFinite(numericValue) ? numericValue : void 0;
518
+ }
519
+ buildProgress(done, total) {
520
+ if (typeof done !== "number" || typeof total !== "number" || total <= 0) return void 0;
521
+ return Math.min(Math.max(done / total * 100, 0), 100);
522
+ }
523
+ hasCounterValue(value) {
524
+ return value !== void 0 && value !== null && value !== "";
525
+ }
526
+ applySelectedIndex(index, emitChange) {
527
+ const selectedIndex = this.getSafeSelectedIndex(index);
528
+ if (selectedIndex === void 0) {
529
+ this.clearSelection();
530
+ return;
531
+ }
532
+ const selectionChanged = this.selectedIndex !== selectedIndex || this.selectedTabItem?.index !== selectedIndex;
533
+ this.selectedIndex = selectedIndex;
534
+ this.refreshSelection();
535
+ if (emitChange && selectionChanged) this.selectedIndexChange.emit(selectedIndex);
536
+ }
537
+ getSafeSelectedIndex(index) {
538
+ const selectableTabItems = this.getSelectableTabItems();
539
+ const requestedTabItem = selectableTabItems.find((tabItem) => tabItem.index === index);
540
+ if (requestedTabItem && !requestedTabItem.disabled) return requestedTabItem.index;
541
+ return selectableTabItems.find((tabItem) => !tabItem.disabled)?.index;
542
+ }
543
+ refreshSelection() {
544
+ this.tabItems = this.tabItems.map((tabItem) => ({
545
+ ...tabItem,
546
+ selected: this.isButtonTabItem(tabItem) && tabItem.index === this.selectedIndex
547
+ }));
548
+ this.selectedTabItem = this.tabItems.find((tabItem) => tabItem.selected);
549
+ this.activeTabItems = this.selectedTabItem ? [this.selectedTabItem] : [];
550
+ }
551
+ clearSelection() {
552
+ this.tabItems = this.tabItems.map((tabItem) => ({
553
+ ...tabItem,
554
+ selected: false
555
+ }));
556
+ this.selectedTabItem = void 0;
557
+ this.activeTabItems = [];
558
+ }
559
+ getSelectableTabItems() {
560
+ return this.tabItems.filter((tabItem) => this.isButtonTabItem(tabItem));
561
+ }
562
+ isSelectableTabItem(tabItem) {
563
+ return this.isButtonTabItem(tabItem) && !tabItem.disabled;
564
+ }
565
+ isButtonTabItem(tabItem) {
566
+ return tabItem.type === "button";
567
+ }
568
+ static ɵfac = i0.ɵɵngDeclareFactory({
569
+ minVersion: "12.0.0",
570
+ version: "22.2.1",
571
+ ngImport: i0,
572
+ type: SectionTabsComponent,
573
+ deps: [],
574
+ target: i0.ɵɵFactoryTarget.Component
575
+ });
576
+ static ɵcmp = i0.ɵɵngDeclareComponent({
577
+ minVersion: "17.0.0",
578
+ version: "22.2.1",
579
+ type: SectionTabsComponent,
580
+ isStandalone: false,
581
+ selector: "app-section-tabs",
582
+ inputs: {
583
+ selectedIndex: "selectedIndex",
584
+ queryParamKey: "queryParamKey"
585
+ },
586
+ outputs: { selectedIndexChange: "selectedIndexChange" },
587
+ queries: [
588
+ {
589
+ propertyName: "menuHeaderDirective",
590
+ first: true,
591
+ predicate: SectionTabsMenuHeaderDirective,
592
+ descendants: true
593
+ },
594
+ {
595
+ propertyName: "footerDirective",
596
+ first: true,
597
+ predicate: SectionTabsFooterDirective,
598
+ descendants: true
599
+ },
600
+ {
601
+ propertyName: "tabComponents",
602
+ predicate: SectionTabComponent,
603
+ descendants: true
604
+ }
605
+ ],
606
+ usesOnChanges: true,
607
+ ngImport: i0,
608
+ template: "<!-- @format -->\n\n<div class=\"section-tabs\">\n <aside\n class=\"section-tabs__sidebar\"\n [attr.aria-label]=\"intl.messages.sections\"\n >\n <div class=\"section-tabs__sidebar-card\">\n @if (menuHeaderTemplate) {\n <div class=\"section-tabs__sidebar-title\">\n <ng-container *ngTemplateOutlet=\"menuHeaderTemplate\"></ng-container>\n </div>\n }\n\n <nav\n class=\"section-tabs__sidebar-list\"\n role=\"tablist\"\n aria-orientation=\"vertical\"\n >\n @for (tabItem of tabItems; track tabItem.tab) {\n @if (tabItem.type === \"separator\") {\n <div class=\"section-tabs__sidebar-separator\" role=\"presentation\">\n @if (tabItem.labelTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.labelTemplate\"\n ></ng-container>\n }\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"section-tabs__sidebar-item\"\n role=\"tab\"\n [id]=\"tabItem.buttonId\"\n [class.active]=\"tabItem.selected\"\n [disabled]=\"tabItem.disabled\"\n [attr.aria-selected]=\"tabItem.selected\"\n [attr.aria-controls]=\"tabItem.panelId\"\n (click)=\"selectTab(tabItem)\"\n >\n <div class=\"section-tabs__label-header\">\n <div class=\"section-tabs__label-title\">\n @if (tabItem.labelTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.labelTemplate\"\n ></ng-container>\n }\n </div>\n\n @if (tabItem.statusDoneLabel) {\n <span\n class=\"section-tabs__mini-chip\"\n [style.color]=\"tabItem.tab.statusColor\"\n [style.--section-tab-done-color]=\"\n tabItem.tab.statusColorDone\n \"\n [style.--section-tab-total-color]=\"\n tabItem.tab.statusColorTotal\n \"\n >\n <span class=\"section-tabs__mini-chip-done\">{{\n tabItem.statusDoneLabel\n }}</span>\n @if (tabItem.statusTotalLabel) {\n <span class=\"section-tabs__mini-chip-total\">{{\n tabItem.statusTotalLabel\n }}</span>\n }\n </span>\n }\n </div>\n\n @if (tabItem.progress !== undefined) {\n <div class=\"section-tabs__progress\" aria-hidden=\"true\">\n <span [style.width.%]=\"tabItem.progress\"></span>\n </div>\n }\n </button>\n }\n }\n </nav>\n\n @if (footerTemplate) {\n <footer class=\"section-tabs__sidebar-footer\">\n <ng-container *ngTemplateOutlet=\"footerTemplate\"></ng-container>\n </footer>\n }\n </div>\n </aside>\n\n <div class=\"section-tabs__content\">\n <div\n class=\"section-tabs__content-viewport\"\n [@sectionTabsContentTransition]=\"selectedIndex\"\n >\n @for (tabItem of activeTabItems; track tabItem.tab) {\n <section\n class=\"section-tabs__content-panel\"\n role=\"tabpanel\"\n [id]=\"tabItem.panelId\"\n [attr.aria-labelledby]=\"tabItem.buttonId\"\n >\n @if (tabItem.contentTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.contentTemplate\"\n ></ng-container>\n }\n </section>\n }\n </div>\n </div>\n</div>\n",
609
+ styles: ["app-section-tabs{display:block;height:100%;min-width:0;min-height:0}app-section-tabs .section-tabs{height:100%;min-height:0;display:grid;grid-template-columns:280px minmax(0,1fr);align-items:stretch;background:var(--ngx-mat-section-tabs-background, #f4f6f8);color:var(--ngx-mat-section-tabs-text, #15324a)}app-section-tabs .section-tabs__sidebar{min-width:0;min-height:0;display:flex;position:sticky;top:8px;z-index:100;overflow:hidden;margin:8px}app-section-tabs .section-tabs__sidebar-card{min-width:0;min-height:0;display:flex;flex:1 1 auto;flex-direction:column;box-sizing:border-box;border:1px solid #d9e0e7;border-radius:8px;box-shadow:none;overflow:hidden;background:#fff}app-section-tabs .section-tabs__sidebar-title{padding:16px 8px 0;font-size:.9rem;font-weight:600;letter-spacing:.06em;color:#1d3447;text-transform:uppercase}app-section-tabs .section-tabs__sidebar-separator{width:100%;box-sizing:border-box;padding:8px 4px 4px;color:#1d3447;font-size:.9rem;font-weight:600;letter-spacing:.06em;line-height:1.2;text-transform:uppercase}app-section-tabs .section-tabs__sidebar-list{min-width:0;min-height:0;display:flex;flex:1 1 auto;flex-direction:column;gap:6px;padding:8px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}app-section-tabs .section-tabs__sidebar-item{width:100%;display:flex;flex-direction:column;gap:10px;border:1px solid transparent;border-radius:8px;background:transparent;padding:12px;text-align:left;color:inherit;cursor:pointer;transition:border-color .16s ease-out,background-color .16s ease-out,opacity .16s ease-out}app-section-tabs .section-tabs__sidebar-item:hover:not(:disabled),app-section-tabs .section-tabs__sidebar-item:focus-visible{background:#f6f8fa}app-section-tabs .section-tabs__sidebar-item.active{border-color:#98a9ba;background:#eef3f7}app-section-tabs .section-tabs__sidebar-item:disabled{cursor:default;opacity:.45}app-section-tabs .section-tabs__label-header{min-width:0;display:flex;justify-content:space-between;align-items:center;gap:12px}app-section-tabs .section-tabs__label-title{min-width:0;display:flex;flex:1 1 auto;align-items:center;gap:8px;color:#111827;font-weight:700}app-section-tabs .section-tabs__label-title>mat-icon,app-section-tabs .section-tabs__label-title>.mat-icon{order:-1;flex:0 0 auto;color:#6b7280}app-section-tabs .section-tabs__label-title>span,app-section-tabs .section-tabs__label-title>strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}app-section-tabs .section-tabs__label-title>mat-chip,app-section-tabs .section-tabs__label-title>mat-chip-row,app-section-tabs .section-tabs__label-title>.mat-mdc-chip,app-section-tabs .section-tabs__label-title>.section-tabs__label-chip{order:100;margin-left:auto}app-section-tabs .section-tabs__mini-chip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;min-height:28px;padding:0 10px;border-radius:8px;background:#eef3f7;color:#607286;font-size:.82rem;font-weight:600}app-section-tabs .section-tabs__mini-chip-done{color:var(--section-tab-done-color, inherit)}app-section-tabs .section-tabs__mini-chip-total{color:var(--section-tab-total-color, inherit)}app-section-tabs .section-tabs__progress{height:4px;border-radius:8px;background:#d6dce2;overflow:hidden}app-section-tabs .section-tabs__progress span{display:block;height:100%;border-radius:8px;background:var(--ngx-mat-section-tabs-primary, #324c60)}app-section-tabs .section-tabs__sidebar-footer{flex:0 0 auto;padding:12px 18px 18px;border-top:1px solid #edf1f4}app-section-tabs .section-tabs__content{min-width:0;min-height:0;height:100%}app-section-tabs .section-tabs__content-viewport{position:relative;height:100%;min-height:0;overflow:hidden}app-section-tabs .section-tabs__content-panel{height:100%;min-height:0;display:flex;flex-direction:column;overflow:auto;box-sizing:border-box}app-section-tabs .section-tabs__content-panel .section-tabs-card,app-section-tabs .section-tabs__content-panel .mat-mdc-card{border-radius:8px;box-shadow:none;overflow:hidden;background:#fff;border:1px solid #d9e0e7}app-section-tabs .section-tabs__content-panel .section-card.active,app-section-tabs .section-tabs__content-panel mat-card.active,app-section-tabs .section-tabs__content-panel .mat-mdc-card.active{border-color:#a7b8c8}app-section-tabs .section-tabs__content-panel .card-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;padding:18px 18px 12px;border-bottom:1px solid #e7ecf0}app-section-tabs .section-tabs__content-panel .card-header h3,app-section-tabs .section-tabs__content-panel mat-card-title{margin:0;color:#15324a;font-size:1.15rem;font-weight:600}app-section-tabs .section-tabs__content-panel .card-header p,app-section-tabs .section-tabs__content-panel mat-card-subtitle{margin:4px 0 0;color:#66768a;font-size:.95rem}app-section-tabs .section-tabs__content-panel .mini-chip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;min-height:28px;padding:0 10px;border-radius:8px;background:#eef3f7;color:#607286;font-size:.82rem;font-weight:600}app-section-tabs .section-tabs__content-panel .field-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:repeat(2,minmax(0,1fr))}app-section-tabs .section-tabs__content-panel .field-cell{min-height:84px;display:flex;flex-direction:column;justify-content:start;gap:6px;padding:14px 16px;border-right:1px solid #e7ecf0;border-bottom:1px solid #e7ecf0;box-sizing:border-box}app-section-tabs .section-tabs__content-panel .field-cell.wide{grid-column:span 2}app-section-tabs .section-tabs__content-panel .field-cell.empty{background:#fafbfd}app-section-tabs .section-tabs__content-panel .field-label{color:#5f6f82;font-size:.92rem}app-section-tabs .section-tabs__content-panel .field-value{color:#15324a;font-size:1rem;font-weight:600;line-height:1.25}app-section-tabs .section-tabs__content-panel .empty-state{display:flex;align-items:center;gap:14px;padding:18px;color:#5f6f82}app-section-tabs .section-tabs__content-panel .empty-state mat-icon{color:#8d98a5}app-section-tabs .section-tabs__content-panel .empty-state strong,app-section-tabs .section-tabs__content-panel .empty-state span{display:block}@media(max-width:1400px){app-section-tabs .section-tabs__content-panel .field-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(max-width:1100px){app-section-tabs .section-tabs{grid-template-columns:1fr}app-section-tabs .section-tabs__sidebar{position:static;overflow:hidden}app-section-tabs .section-tabs__content{padding-left:8px;box-sizing:border-box}app-section-tabs .section-tabs__content,app-section-tabs .section-tabs__content-viewport,app-section-tabs .section-tabs__content-panel{height:auto}app-section-tabs .section-tabs__content-panel .field-grid,app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:720px){app-section-tabs .section-tabs__content-panel .field-grid,app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:1fr}app-section-tabs .section-tabs__content-panel .field-cell.wide{grid-column:span 1}}\n"],
610
+ dependencies: [{
611
+ kind: "directive",
612
+ type: i1.NgTemplateOutlet,
613
+ selector: "[ngTemplateOutlet]",
614
+ inputs: [
615
+ "ngTemplateOutletContext",
616
+ "ngTemplateOutlet",
617
+ "ngTemplateOutletInjector"
618
+ ]
619
+ }],
620
+ animations: [trigger("sectionTabsContentTransition", [transition(":increment", sectionTabsSlideTopTransitions), transition(":decrement", sectionTabsSlideBottomTransitions)])],
621
+ changeDetection: i0.ChangeDetectionStrategy.Eager,
622
+ encapsulation: i0.ViewEncapsulation.None
623
+ });
624
+ };
625
+ i0.ɵɵngDeclareClassMetadata({
626
+ minVersion: "12.0.0",
627
+ version: "22.2.1",
628
+ ngImport: i0,
629
+ type: SectionTabsComponent,
630
+ decorators: [{
631
+ type: Component,
632
+ args: [{
633
+ selector: "app-section-tabs",
634
+ standalone: false,
635
+ encapsulation: ViewEncapsulation.None,
636
+ changeDetection: ChangeDetectionStrategy.Eager,
637
+ animations: [trigger("sectionTabsContentTransition", [transition(":increment", sectionTabsSlideTopTransitions), transition(":decrement", sectionTabsSlideBottomTransitions)])],
638
+ template: "<!-- @format -->\n\n<div class=\"section-tabs\">\n <aside\n class=\"section-tabs__sidebar\"\n [attr.aria-label]=\"intl.messages.sections\"\n >\n <div class=\"section-tabs__sidebar-card\">\n @if (menuHeaderTemplate) {\n <div class=\"section-tabs__sidebar-title\">\n <ng-container *ngTemplateOutlet=\"menuHeaderTemplate\"></ng-container>\n </div>\n }\n\n <nav\n class=\"section-tabs__sidebar-list\"\n role=\"tablist\"\n aria-orientation=\"vertical\"\n >\n @for (tabItem of tabItems; track tabItem.tab) {\n @if (tabItem.type === \"separator\") {\n <div class=\"section-tabs__sidebar-separator\" role=\"presentation\">\n @if (tabItem.labelTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.labelTemplate\"\n ></ng-container>\n }\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"section-tabs__sidebar-item\"\n role=\"tab\"\n [id]=\"tabItem.buttonId\"\n [class.active]=\"tabItem.selected\"\n [disabled]=\"tabItem.disabled\"\n [attr.aria-selected]=\"tabItem.selected\"\n [attr.aria-controls]=\"tabItem.panelId\"\n (click)=\"selectTab(tabItem)\"\n >\n <div class=\"section-tabs__label-header\">\n <div class=\"section-tabs__label-title\">\n @if (tabItem.labelTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.labelTemplate\"\n ></ng-container>\n }\n </div>\n\n @if (tabItem.statusDoneLabel) {\n <span\n class=\"section-tabs__mini-chip\"\n [style.color]=\"tabItem.tab.statusColor\"\n [style.--section-tab-done-color]=\"\n tabItem.tab.statusColorDone\n \"\n [style.--section-tab-total-color]=\"\n tabItem.tab.statusColorTotal\n \"\n >\n <span class=\"section-tabs__mini-chip-done\">{{\n tabItem.statusDoneLabel\n }}</span>\n @if (tabItem.statusTotalLabel) {\n <span class=\"section-tabs__mini-chip-total\">{{\n tabItem.statusTotalLabel\n }}</span>\n }\n </span>\n }\n </div>\n\n @if (tabItem.progress !== undefined) {\n <div class=\"section-tabs__progress\" aria-hidden=\"true\">\n <span [style.width.%]=\"tabItem.progress\"></span>\n </div>\n }\n </button>\n }\n }\n </nav>\n\n @if (footerTemplate) {\n <footer class=\"section-tabs__sidebar-footer\">\n <ng-container *ngTemplateOutlet=\"footerTemplate\"></ng-container>\n </footer>\n }\n </div>\n </aside>\n\n <div class=\"section-tabs__content\">\n <div\n class=\"section-tabs__content-viewport\"\n [@sectionTabsContentTransition]=\"selectedIndex\"\n >\n @for (tabItem of activeTabItems; track tabItem.tab) {\n <section\n class=\"section-tabs__content-panel\"\n role=\"tabpanel\"\n [id]=\"tabItem.panelId\"\n [attr.aria-labelledby]=\"tabItem.buttonId\"\n >\n @if (tabItem.contentTemplate) {\n <ng-container\n *ngTemplateOutlet=\"tabItem.contentTemplate\"\n ></ng-container>\n }\n </section>\n }\n </div>\n </div>\n</div>\n",
639
+ styles: ["app-section-tabs{display:block;height:100%;min-width:0;min-height:0}app-section-tabs .section-tabs{height:100%;min-height:0;display:grid;grid-template-columns:280px minmax(0,1fr);align-items:stretch;background:var(--ngx-mat-section-tabs-background, #f4f6f8);color:var(--ngx-mat-section-tabs-text, #15324a)}app-section-tabs .section-tabs__sidebar{min-width:0;min-height:0;display:flex;position:sticky;top:8px;z-index:100;overflow:hidden;margin:8px}app-section-tabs .section-tabs__sidebar-card{min-width:0;min-height:0;display:flex;flex:1 1 auto;flex-direction:column;box-sizing:border-box;border:1px solid #d9e0e7;border-radius:8px;box-shadow:none;overflow:hidden;background:#fff}app-section-tabs .section-tabs__sidebar-title{padding:16px 8px 0;font-size:.9rem;font-weight:600;letter-spacing:.06em;color:#1d3447;text-transform:uppercase}app-section-tabs .section-tabs__sidebar-separator{width:100%;box-sizing:border-box;padding:8px 4px 4px;color:#1d3447;font-size:.9rem;font-weight:600;letter-spacing:.06em;line-height:1.2;text-transform:uppercase}app-section-tabs .section-tabs__sidebar-list{min-width:0;min-height:0;display:flex;flex:1 1 auto;flex-direction:column;gap:6px;padding:8px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}app-section-tabs .section-tabs__sidebar-item{width:100%;display:flex;flex-direction:column;gap:10px;border:1px solid transparent;border-radius:8px;background:transparent;padding:12px;text-align:left;color:inherit;cursor:pointer;transition:border-color .16s ease-out,background-color .16s ease-out,opacity .16s ease-out}app-section-tabs .section-tabs__sidebar-item:hover:not(:disabled),app-section-tabs .section-tabs__sidebar-item:focus-visible{background:#f6f8fa}app-section-tabs .section-tabs__sidebar-item.active{border-color:#98a9ba;background:#eef3f7}app-section-tabs .section-tabs__sidebar-item:disabled{cursor:default;opacity:.45}app-section-tabs .section-tabs__label-header{min-width:0;display:flex;justify-content:space-between;align-items:center;gap:12px}app-section-tabs .section-tabs__label-title{min-width:0;display:flex;flex:1 1 auto;align-items:center;gap:8px;color:#111827;font-weight:700}app-section-tabs .section-tabs__label-title>mat-icon,app-section-tabs .section-tabs__label-title>.mat-icon{order:-1;flex:0 0 auto;color:#6b7280}app-section-tabs .section-tabs__label-title>span,app-section-tabs .section-tabs__label-title>strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}app-section-tabs .section-tabs__label-title>mat-chip,app-section-tabs .section-tabs__label-title>mat-chip-row,app-section-tabs .section-tabs__label-title>.mat-mdc-chip,app-section-tabs .section-tabs__label-title>.section-tabs__label-chip{order:100;margin-left:auto}app-section-tabs .section-tabs__mini-chip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;min-height:28px;padding:0 10px;border-radius:8px;background:#eef3f7;color:#607286;font-size:.82rem;font-weight:600}app-section-tabs .section-tabs__mini-chip-done{color:var(--section-tab-done-color, inherit)}app-section-tabs .section-tabs__mini-chip-total{color:var(--section-tab-total-color, inherit)}app-section-tabs .section-tabs__progress{height:4px;border-radius:8px;background:#d6dce2;overflow:hidden}app-section-tabs .section-tabs__progress span{display:block;height:100%;border-radius:8px;background:var(--ngx-mat-section-tabs-primary, #324c60)}app-section-tabs .section-tabs__sidebar-footer{flex:0 0 auto;padding:12px 18px 18px;border-top:1px solid #edf1f4}app-section-tabs .section-tabs__content{min-width:0;min-height:0;height:100%}app-section-tabs .section-tabs__content-viewport{position:relative;height:100%;min-height:0;overflow:hidden}app-section-tabs .section-tabs__content-panel{height:100%;min-height:0;display:flex;flex-direction:column;overflow:auto;box-sizing:border-box}app-section-tabs .section-tabs__content-panel .section-tabs-card,app-section-tabs .section-tabs__content-panel .mat-mdc-card{border-radius:8px;box-shadow:none;overflow:hidden;background:#fff;border:1px solid #d9e0e7}app-section-tabs .section-tabs__content-panel .section-card.active,app-section-tabs .section-tabs__content-panel mat-card.active,app-section-tabs .section-tabs__content-panel .mat-mdc-card.active{border-color:#a7b8c8}app-section-tabs .section-tabs__content-panel .card-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;padding:18px 18px 12px;border-bottom:1px solid #e7ecf0}app-section-tabs .section-tabs__content-panel .card-header h3,app-section-tabs .section-tabs__content-panel mat-card-title{margin:0;color:#15324a;font-size:1.15rem;font-weight:600}app-section-tabs .section-tabs__content-panel .card-header p,app-section-tabs .section-tabs__content-panel mat-card-subtitle{margin:4px 0 0;color:#66768a;font-size:.95rem}app-section-tabs .section-tabs__content-panel .mini-chip{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;min-height:28px;padding:0 10px;border-radius:8px;background:#eef3f7;color:#607286;font-size:.82rem;font-weight:600}app-section-tabs .section-tabs__content-panel .field-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:repeat(2,minmax(0,1fr))}app-section-tabs .section-tabs__content-panel .field-cell{min-height:84px;display:flex;flex-direction:column;justify-content:start;gap:6px;padding:14px 16px;border-right:1px solid #e7ecf0;border-bottom:1px solid #e7ecf0;box-sizing:border-box}app-section-tabs .section-tabs__content-panel .field-cell.wide{grid-column:span 2}app-section-tabs .section-tabs__content-panel .field-cell.empty{background:#fafbfd}app-section-tabs .section-tabs__content-panel .field-label{color:#5f6f82;font-size:.92rem}app-section-tabs .section-tabs__content-panel .field-value{color:#15324a;font-size:1rem;font-weight:600;line-height:1.25}app-section-tabs .section-tabs__content-panel .empty-state{display:flex;align-items:center;gap:14px;padding:18px;color:#5f6f82}app-section-tabs .section-tabs__content-panel .empty-state mat-icon{color:#8d98a5}app-section-tabs .section-tabs__content-panel .empty-state strong,app-section-tabs .section-tabs__content-panel .empty-state span{display:block}@media(max-width:1400px){app-section-tabs .section-tabs__content-panel .field-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(max-width:1100px){app-section-tabs .section-tabs{grid-template-columns:1fr}app-section-tabs .section-tabs__sidebar{position:static;overflow:hidden}app-section-tabs .section-tabs__content{padding-left:8px;box-sizing:border-box}app-section-tabs .section-tabs__content,app-section-tabs .section-tabs__content-viewport,app-section-tabs .section-tabs__content-panel{height:auto}app-section-tabs .section-tabs__content-panel .field-grid,app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:720px){app-section-tabs .section-tabs__content-panel .field-grid,app-section-tabs .section-tabs__content-panel .field-grid.compact{grid-template-columns:1fr}app-section-tabs .section-tabs__content-panel .field-cell.wide{grid-column:span 1}}\n"]
640
+ }]
641
+ }],
642
+ propDecorators: {
643
+ selectedIndex: [{ type: Input }],
644
+ queryParamKey: [{ type: Input }],
645
+ selectedIndexChange: [{ type: Output }],
646
+ tabComponents: [{
647
+ type: ContentChildren,
648
+ args: [SectionTabComponent, { descendants: true }]
649
+ }],
650
+ menuHeaderDirective: [{
651
+ type: ContentChild,
652
+ args: [SectionTabsMenuHeaderDirective]
653
+ }],
654
+ footerDirective: [{
655
+ type: ContentChild,
656
+ args: [SectionTabsFooterDirective]
657
+ }]
658
+ }
659
+ });
660
+ var SectionTabsDisplayResponsiveGridDirective = class SectionTabsDisplayResponsiveGridDirective {
661
+ elementRef;
662
+ grid;
663
+ sectionTabsDisplayResponsiveGridEnabled = true;
664
+ initialized = false;
665
+ resizeObserver;
666
+ mutationObserver;
667
+ constructor(elementRef) {
668
+ this.elementRef = elementRef;
669
+ }
670
+ ngAfterViewInit() {
671
+ this.initialized = true;
672
+ this.refreshObserver();
673
+ this.applyLayout();
674
+ }
675
+ ngOnChanges(_changes) {
676
+ if (!this.initialized) return;
677
+ this.refreshObserver();
678
+ this.applyLayout();
679
+ }
680
+ ngOnDestroy() {
681
+ this.resizeObserver?.disconnect();
682
+ this.mutationObserver?.disconnect();
683
+ }
684
+ refreshObserver() {
685
+ this.resizeObserver?.disconnect();
686
+ this.mutationObserver?.disconnect();
687
+ this.resizeObserver = void 0;
688
+ this.mutationObserver = void 0;
689
+ if (!this.sectionTabsDisplayResponsiveGridEnabled) return;
690
+ if (typeof ResizeObserver !== "undefined") {
691
+ this.resizeObserver = new ResizeObserver(() => this.applyLayout());
692
+ this.resizeObserver.observe(this.elementRef.nativeElement);
693
+ }
694
+ if (typeof MutationObserver !== "undefined") {
695
+ this.mutationObserver = new MutationObserver(() => this.applyLayout());
696
+ this.observeMutations();
697
+ }
698
+ }
699
+ observeMutations() {
700
+ this.mutationObserver?.observe(this.elementRef.nativeElement, { childList: true });
701
+ }
702
+ applyLayout() {
703
+ const element = this.elementRef.nativeElement;
704
+ const configuredColumns = this.normalizePositiveInteger(this.grid?.columns, 1);
705
+ if (!this.sectionTabsDisplayResponsiveGridEnabled) {
706
+ element.style.removeProperty("--section-tabs-display-grid-effective-columns");
707
+ this.restoreConfiguredSpans(configuredColumns);
708
+ return;
709
+ }
710
+ const availableWidth = this.getContentWidth(element);
711
+ if (availableWidth <= 0) return;
712
+ const gap = this.getGap(element);
713
+ const minColumnWidth = this.measureCssLength(this.grid?.minColumnWidth || "0px", element);
714
+ const effectiveColumns = this.resolveEffectiveColumns(configuredColumns, availableWidth, gap, minColumnWidth);
715
+ element.style.setProperty("--section-tabs-display-grid-effective-columns", `${effectiveColumns}`);
716
+ this.applyResponsiveSpans(effectiveColumns);
717
+ }
718
+ applyResponsiveSpans(columns) {
719
+ const rows = [];
720
+ let currentRow = [];
721
+ let occupiedColumns = 0;
722
+ const flushRow = () => {
723
+ if (!currentRow.length) return;
724
+ rows.push(currentRow);
725
+ currentRow = [];
726
+ occupiedColumns = 0;
727
+ };
728
+ for (const child of Array.from(this.elementRef.nativeElement.children)) {
729
+ if (!(child instanceof HTMLElement)) continue;
730
+ if (child.classList.contains("section-tabs-display__grid-break")) {
731
+ flushRow();
732
+ continue;
733
+ }
734
+ const originalSpan = this.readOriginalSpan(child, columns);
735
+ const span = Math.min(originalSpan, columns);
736
+ if (occupiedColumns > 0 && occupiedColumns + span > columns) {
737
+ flushRow();
738
+ rows.push([{
739
+ element: child,
740
+ span: columns
741
+ }]);
742
+ continue;
743
+ }
744
+ currentRow.push({
745
+ element: child,
746
+ span
747
+ });
748
+ occupiedColumns += span;
749
+ if (occupiedColumns === columns) flushRow();
750
+ }
751
+ flushRow();
752
+ for (const row of rows) {
753
+ const singleItem = row.length === 1 ? row[0] : void 0;
754
+ if (singleItem && singleItem.span < columns) singleItem.span = columns;
755
+ row.forEach((item) => item.element.style.setProperty("grid-column", `span ${item.span}`));
756
+ }
757
+ }
758
+ restoreConfiguredSpans(columns) {
759
+ for (const child of Array.from(this.elementRef.nativeElement.children)) {
760
+ if (!(child instanceof HTMLElement) || child.classList.contains("section-tabs-display__grid-break")) continue;
761
+ child.style.setProperty("grid-column", `span ${this.readOriginalSpan(child, columns)}`);
762
+ }
763
+ }
764
+ readOriginalSpan(element, columns) {
765
+ const value = element.style.getPropertyValue("--section-tabs-display-item-col-span");
766
+ return Math.min(this.normalizePositiveInteger(Number(value), 1), columns);
767
+ }
768
+ resolveEffectiveColumns(configuredColumns, availableWidth, gap, minColumnWidth) {
769
+ if (configuredColumns <= 1 || minColumnWidth <= 0) return configuredColumns;
770
+ const fittingColumns = Math.floor((availableWidth + gap) / (minColumnWidth + gap));
771
+ return Math.max(1, Math.min(configuredColumns, fittingColumns));
772
+ }
773
+ getContentWidth(element) {
774
+ const styles = getComputedStyle(element);
775
+ const horizontalPadding = this.parsePixelValue(styles.paddingLeft) + this.parsePixelValue(styles.paddingRight);
776
+ return Math.max(0, element.clientWidth - horizontalPadding);
777
+ }
778
+ getGap(element) {
779
+ const styles = getComputedStyle(element);
780
+ return this.parsePixelValue(styles.columnGap === "normal" ? "0px" : styles.columnGap);
781
+ }
782
+ measureCssLength(value, element) {
783
+ if (!value || value === "0" || value === "0px") return 0;
784
+ this.mutationObserver?.disconnect();
785
+ const probe = element.ownerDocument.createElement("div");
786
+ probe.style.position = "absolute";
787
+ probe.style.visibility = "hidden";
788
+ probe.style.pointerEvents = "none";
789
+ probe.style.width = value;
790
+ probe.style.height = "0";
791
+ element.appendChild(probe);
792
+ const width = probe.getBoundingClientRect().width;
793
+ probe.remove();
794
+ this.observeMutations();
795
+ return width;
796
+ }
797
+ parsePixelValue(value) {
798
+ const parsed = Number.parseFloat(value);
799
+ return Number.isFinite(parsed) ? parsed : 0;
800
+ }
801
+ normalizePositiveInteger(value, fallback) {
802
+ if (!Number.isFinite(value) || Number(value) <= 0) return fallback;
803
+ return Math.max(1, Math.floor(Number(value)));
804
+ }
805
+ static ɵfac = i0.ɵɵngDeclareFactory({
806
+ minVersion: "12.0.0",
807
+ version: "22.2.1",
808
+ ngImport: i0,
809
+ type: SectionTabsDisplayResponsiveGridDirective,
810
+ deps: [{ token: i0.ElementRef }],
811
+ target: i0.ɵɵFactoryTarget.Directive
812
+ });
813
+ static ɵdir = i0.ɵɵngDeclareDirective({
814
+ minVersion: "14.0.0",
815
+ version: "22.2.1",
816
+ type: SectionTabsDisplayResponsiveGridDirective,
817
+ isStandalone: false,
818
+ selector: "[appSectionTabsDisplayResponsiveGrid]",
819
+ inputs: {
820
+ grid: ["appSectionTabsDisplayResponsiveGrid", "grid"],
821
+ sectionTabsDisplayResponsiveGridEnabled: "sectionTabsDisplayResponsiveGridEnabled"
822
+ },
823
+ usesOnChanges: true,
824
+ ngImport: i0
825
+ });
826
+ };
827
+ i0.ɵɵngDeclareClassMetadata({
828
+ minVersion: "12.0.0",
829
+ version: "22.2.1",
830
+ ngImport: i0,
831
+ type: SectionTabsDisplayResponsiveGridDirective,
832
+ decorators: [{
833
+ type: Directive,
834
+ args: [{
835
+ selector: "[appSectionTabsDisplayResponsiveGrid]",
836
+ standalone: false
837
+ }]
838
+ }],
839
+ ctorParameters: () => [{ type: i0.ElementRef }],
840
+ propDecorators: {
841
+ grid: [{
842
+ type: Input,
843
+ args: ["appSectionTabsDisplayResponsiveGrid"]
844
+ }],
845
+ sectionTabsDisplayResponsiveGridEnabled: [{ type: Input }]
846
+ }
847
+ });
848
+ var SectionTabsDisplayComponent = class SectionTabsDisplayComponent {
849
+ locale;
850
+ intl;
851
+ componentInputNamesByType = /* @__PURE__ */ new WeakMap();
852
+ pickDeclaredComponentInputs(component, inputs) {
853
+ if (!component || !inputs) return {};
854
+ const declaredInputNames = this.getDeclaredComponentInputNames(component);
855
+ if (!declaredInputNames.size) return {};
856
+ return Object.entries(inputs).reduce((filteredInputs, [name, value]) => {
857
+ if (declaredInputNames.has(name)) filteredInputs[name] = value;
858
+ return filteredInputs;
859
+ }, {});
860
+ }
861
+ getDeclaredComponentInputNames(component) {
862
+ const cachedInputNames = this.componentInputNamesByType.get(component);
863
+ if (cachedInputNames) return cachedInputNames;
864
+ const componentMirror = reflectComponentType(component);
865
+ const inputNames = new Set(componentMirror?.inputs.map((input) => input.templateName) ?? []);
866
+ this.componentInputNamesByType.set(component, inputNames);
867
+ return inputNames;
868
+ }
869
+ options;
870
+ selectedIndex = 0;
871
+ queryParamKey;
872
+ menuHeader;
873
+ showEmptyFields;
874
+ selectedIndexChange = new EventEmitter();
875
+ showEmptyFieldsChange = new EventEmitter();
876
+ viewModel = {
877
+ sections: [],
878
+ empty: true
879
+ };
880
+ showEmptyFieldsState = false;
881
+ showEmptyFieldsToggle = false;
882
+ showEmptyFieldsLabel = "";
883
+ emptyFieldsStateInitialized = false;
884
+ lastOptionShowEmptyFields;
885
+ constructor(locale, intl, changeDetector, destroyRef) {
886
+ this.locale = locale;
887
+ this.intl = intl;
888
+ this.intl.changes.pipe(takeUntilDestroyed(destroyRef)).subscribe(() => {
889
+ this.syncEmptyFieldsLabel();
890
+ changeDetector.markForCheck();
891
+ });
892
+ }
893
+ ngOnChanges() {
894
+ this.syncEmptyFieldsOptions();
895
+ this.viewModel = this.buildViewModel();
896
+ }
897
+ onSelectedIndexChange(index) {
898
+ this.selectedIndex = index;
899
+ this.selectedIndexChange.emit(index);
900
+ }
901
+ onShowEmptyFieldsChange(checked) {
902
+ this.showEmptyFieldsState = checked;
903
+ this.showEmptyFieldsChange.emit(checked);
904
+ this.viewModel = this.buildViewModel();
905
+ }
906
+ onClickFieldItem(fieldItem) {
907
+ if (typeof fieldItem.onClick === "function") fieldItem.onClick(fieldItem.value);
908
+ }
909
+ syncEmptyFieldsLabel() {
910
+ this.showEmptyFieldsLabel = this.options?.showEmptyFieldsLabel ?? this.intl.messages.showEmptyFields;
911
+ }
912
+ syncEmptyFieldsOptions() {
913
+ this.syncEmptyFieldsLabel();
914
+ this.showEmptyFieldsToggle = this.options?.showEmptyFieldsToggle ?? false;
915
+ const optionShowEmptyFields = this.options?.showEmptyFields;
916
+ if (this.showEmptyFields !== void 0) {
917
+ this.showEmptyFieldsState = this.showEmptyFields;
918
+ this.emptyFieldsStateInitialized = true;
919
+ this.lastOptionShowEmptyFields = optionShowEmptyFields;
920
+ return;
921
+ }
922
+ if (!this.emptyFieldsStateInitialized || optionShowEmptyFields !== this.lastOptionShowEmptyFields) {
923
+ this.showEmptyFieldsState = optionShowEmptyFields ?? false;
924
+ this.emptyFieldsStateInitialized = true;
925
+ this.lastOptionShowEmptyFields = optionShowEmptyFields;
926
+ }
927
+ }
928
+ buildViewModel() {
929
+ const renderSections = (this.options?.sections ?? []).filter((section) => this.isVisible(section.visible)).map((section) => this.buildSection(section));
930
+ return {
931
+ sections: renderSections,
932
+ empty: renderSections.length === 0
933
+ };
934
+ }
935
+ buildSection(section) {
936
+ const cardBuildResult = this.buildCardItems(section);
937
+ const completion = this.resolveCompletion(section.completion, () => {
938
+ return this.calculateSectionCompletion(cardBuildResult.cards);
939
+ });
940
+ const preserveRows = this.hasRowSpan(section.cards);
941
+ return {
942
+ id: section.id,
943
+ queryParamValue: section.queryParamValue ?? section.id,
944
+ source: section,
945
+ responsiveGrid: !preserveRows,
946
+ label: section.label,
947
+ icon: section.icon,
948
+ tooltip: section.tooltip,
949
+ sectionMode: section.sectionMode ?? "default",
950
+ cardCount: cardBuildResult.cards.length,
951
+ gridStyles: this.buildGridStyles(section.grid, preserveRows),
952
+ items: cardBuildResult.items,
953
+ done: completion.done,
954
+ total: completion.total
955
+ };
956
+ }
957
+ buildCardItems(section) {
958
+ const cards = [];
959
+ return {
960
+ items: (section.cards ?? []).flatMap((card, index) => {
961
+ if (!this.isVisible(card.visible)) return [];
962
+ const cardItems = [];
963
+ const renderCard = this.buildCard(card, section);
964
+ cards.push(renderCard);
965
+ if (card.layout?.breakBefore) cardItems.push({
966
+ id: `${card.id || index}-before`,
967
+ type: "break"
968
+ });
969
+ cardItems.push(renderCard);
970
+ if (card.layout?.breakAfter) cardItems.push({
971
+ id: `${card.id || index}-after`,
972
+ type: "break"
973
+ });
974
+ return cardItems;
975
+ }),
976
+ cards
977
+ };
978
+ }
979
+ buildCard(card, section) {
980
+ const kind = this.getCardKind(card);
981
+ const renderFields = kind === "fields" ? this.buildFields(section, card) : [];
982
+ const completion = this.resolveCompletion(card.completion, () => {
983
+ return this.calculateFieldsCompletion(renderFields);
984
+ });
985
+ const preserveRows = this.hasRowSpan(card.fields);
986
+ return {
987
+ actions: card.actions,
988
+ id: card.id,
989
+ type: "card",
990
+ source: card,
991
+ responsiveGrid: !preserveRows,
992
+ label: card.label,
993
+ icon: card.icon,
994
+ tooltip: card.tooltip,
995
+ kind,
996
+ component: card.component,
997
+ componentInputs: this.pickDeclaredComponentInputs(card.component, kind === "component" ? this.buildCardComponentInputs(section, card) : void 0),
998
+ gridStyles: this.buildGridStyles(card.grid, preserveRows),
999
+ styles: this.buildLayoutStyles(card.layout, section.grid),
1000
+ classes: this.buildLayoutClasses(card.layout),
1001
+ items: this.buildVisibleFieldItems(renderFields),
1002
+ completion
1003
+ };
1004
+ }
1005
+ buildFields(section, card) {
1006
+ return (card.fields ?? []).flatMap((field, index) => {
1007
+ if (!this.isVisible(field.visible)) return [];
1008
+ const fieldId = this.buildFieldId(card, field, index);
1009
+ return [this.buildField(fieldId, section, card, field)];
1010
+ });
1011
+ }
1012
+ buildVisibleFieldItems(fields) {
1013
+ return fields.flatMap((field) => {
1014
+ if (!this.shouldRenderField(field)) return [];
1015
+ const items = [];
1016
+ if (field.source.layout?.breakBefore) items.push({
1017
+ id: `${field.id}-before`,
1018
+ type: "break"
1019
+ });
1020
+ items.push(field);
1021
+ if (field.source.layout?.breakAfter) items.push({
1022
+ id: `${field.id}-after`,
1023
+ type: "break"
1024
+ });
1025
+ return items;
1026
+ });
1027
+ }
1028
+ buildField(id, section, card, field) {
1029
+ const value = this.getPathValue(this.options?.data, field.path);
1030
+ const selectOption = field.kind === "select" ? this.findSelectOption(value, field.options) : void 0;
1031
+ const color = field.color ?? selectOption?.color;
1032
+ const filled = this.isFilled(value);
1033
+ const displayValue = this.formatFieldValue(field, value, selectOption);
1034
+ const chipsValue = field.kind === "chips" ? this.buildChipViewModels(field, value) : [];
1035
+ const componentInputs = this.pickDeclaredComponentInputs(field.component, this.buildFieldComponentInputs(section, card, field, value));
1036
+ return {
1037
+ id,
1038
+ type: "field",
1039
+ source: field,
1040
+ label: field.label,
1041
+ labelAction: field.labelAction,
1042
+ kind: field.kind,
1043
+ value,
1044
+ filled,
1045
+ displayValue,
1046
+ chipsValue,
1047
+ color,
1048
+ suffix: field.kind === "text" ? field.suffix : void 0,
1049
+ component: field.component,
1050
+ componentInputs,
1051
+ styles: this.buildLayoutStyles(field.layout, card.grid),
1052
+ classes: {
1053
+ ...this.buildLayoutClasses(field.layout),
1054
+ "section-tabs-display__field-cell--empty": !filled
1055
+ },
1056
+ onClick: field.onClick
1057
+ };
1058
+ }
1059
+ buildFieldComponentInputs(section, card, field, value) {
1060
+ const context = {
1061
+ data: this.options?.data,
1062
+ value,
1063
+ field,
1064
+ card,
1065
+ section,
1066
+ options: this.options
1067
+ };
1068
+ return {
1069
+ data: context.data,
1070
+ record: context.data,
1071
+ value: context.value,
1072
+ field: context.field,
1073
+ card: context.card,
1074
+ section: context.section,
1075
+ options: context.options,
1076
+ ...field.componentInputs ?? {}
1077
+ };
1078
+ }
1079
+ buildCardComponentInputs(section, card) {
1080
+ const value = this.getPathValue(this.options?.data, card.path ?? "");
1081
+ const context = {
1082
+ data: this.options?.data,
1083
+ value,
1084
+ card,
1085
+ section,
1086
+ options: this.options
1087
+ };
1088
+ return {
1089
+ data: context.data,
1090
+ record: context.data,
1091
+ value: context.value,
1092
+ card: context.card,
1093
+ section: context.section,
1094
+ options: context.options,
1095
+ ...card.componentInputs ?? {}
1096
+ };
1097
+ }
1098
+ buildFieldId(card, field, index) {
1099
+ return `${card.id}-${field.path || field.label || index}-${index}`;
1100
+ }
1101
+ buildGridStyles(grid, preserveRows = false) {
1102
+ const columns = this.normalizePositiveInteger(grid?.columns, 1);
1103
+ const minColumnWidth = grid?.minColumnWidth || "0px";
1104
+ return {
1105
+ "--section-tabs-display-grid-columns": `${columns}`,
1106
+ "--section-tabs-display-grid-gap": grid?.gap || "12px",
1107
+ "--section-tabs-display-grid-min-column-width": minColumnWidth,
1108
+ "--section-tabs-display-grid-track-min-column-width": preserveRows ? minColumnWidth : "0px"
1109
+ };
1110
+ }
1111
+ buildLayoutStyles(layout, grid) {
1112
+ const styles = { ...layout?.styles ?? {} };
1113
+ const columns = this.normalizePositiveInteger(grid?.columns, 1);
1114
+ const colSpan = Math.min(this.normalizePositiveInteger(layout?.colSpan, 1), columns);
1115
+ const rowSpan = this.normalizePositiveInteger(layout?.rowSpan);
1116
+ styles["--section-tabs-display-item-col-span"] = `${colSpan}`;
1117
+ styles["grid-column"] = `span ${colSpan}`;
1118
+ if (rowSpan) styles["grid-row"] = `span ${rowSpan}`;
1119
+ return styles;
1120
+ }
1121
+ hasRowSpan(items) {
1122
+ return (items ?? []).some((item) => this.normalizePositiveInteger(item.layout?.rowSpan, 1) > 1);
1123
+ }
1124
+ buildLayoutClasses(layout) {
1125
+ const classes = { "section-tabs-display__item--break-before": !!layout?.breakBefore };
1126
+ if (layout?.classes) layout.classes.split(" ").forEach((c) => classes[c] = true);
1127
+ return classes;
1128
+ }
1129
+ resolveCompletion(source, fallbackFactory) {
1130
+ if (source === false || source?.disabled) return { enabled: false };
1131
+ const fallback = fallbackFactory();
1132
+ const doneOverride = this.resolveExplicitCounter(source?.done, source?.donePath);
1133
+ const totalOverride = this.resolveExplicitCounter(source?.total, source?.totalPath);
1134
+ if (!(this.hasCounterValue(doneOverride) || this.hasCounterValue(totalOverride)) && fallback.total <= 0) return { enabled: false };
1135
+ const done = this.hasCounterValue(doneOverride) ? doneOverride : fallback.done;
1136
+ const total = this.hasCounterValue(totalOverride) ? totalOverride : fallback.total;
1137
+ const enabled = this.hasCounterValue(done) || this.hasCounterValue(total);
1138
+ return {
1139
+ enabled,
1140
+ done: enabled ? done : void 0,
1141
+ total: enabled ? total : void 0,
1142
+ label: enabled ? this.buildCompletionLabel(done, total) : void 0
1143
+ };
1144
+ }
1145
+ calculateFieldsCompletion(fields) {
1146
+ return fields.reduce((completion, field) => {
1147
+ completion.total += 1;
1148
+ if (field.filled) completion.done += 1;
1149
+ return completion;
1150
+ }, {
1151
+ done: 0,
1152
+ total: 0
1153
+ });
1154
+ }
1155
+ calculateSectionCompletion(cards) {
1156
+ return cards.reduce((completion, card) => {
1157
+ if (!card.completion.enabled) return completion;
1158
+ if (typeof card.completion.done === "number") completion.done += card.completion.done;
1159
+ if (typeof card.completion.total === "number") completion.total += card.completion.total;
1160
+ return completion;
1161
+ }, {
1162
+ done: 0,
1163
+ total: 0
1164
+ });
1165
+ }
1166
+ resolveExplicitCounter(value, path) {
1167
+ if (this.hasCounterValue(value)) return value;
1168
+ if (path) return this.getPathValue(this.options?.data, path);
1169
+ }
1170
+ buildCompletionLabel(done, total) {
1171
+ if (!this.hasCounterValue(done)) return void 0;
1172
+ if (!this.hasCounterValue(total)) return `${done}`;
1173
+ return `${done}/${total}`;
1174
+ }
1175
+ hasCounterValue(value) {
1176
+ return value !== null && value !== void 0 && value !== "";
1177
+ }
1178
+ isVisible(predicate) {
1179
+ return predicate ? predicate(this.options?.data) : true;
1180
+ }
1181
+ shouldRenderField(field) {
1182
+ if (this.showEmptyFieldsState) return true;
1183
+ if (field.kind === "component") return true;
1184
+ return field.filled;
1185
+ }
1186
+ getCardKind(card) {
1187
+ return card.kind ?? (card.component ? "component" : "fields");
1188
+ }
1189
+ formatFieldValue(field, value, selectOption) {
1190
+ if (!this.isFilled(value)) return "—";
1191
+ if (field.kind === "text" && !field.suffix && this.isSafeHtmlValue(value)) return value;
1192
+ switch (field.kind) {
1193
+ case "number": return this.formatNumberValue(value, field);
1194
+ case "date": return this.formatDateValue(value, field.dateFormat);
1195
+ case "select": return selectOption?.label ?? this.formatUnknownValue(value);
1196
+ default: return this.formatTextValue(value, field.suffix);
1197
+ }
1198
+ }
1199
+ formatTextValue(value, suffix) {
1200
+ const displayValue = this.formatUnknownValue(value);
1201
+ return suffix ? `${displayValue}${suffix}` : displayValue;
1202
+ }
1203
+ formatNumberValue(value, field) {
1204
+ const numberValue = Number(value);
1205
+ if (!Number.isFinite(numberValue)) return this.formatUnknownValue(value);
1206
+ const formattedValue = new Intl.NumberFormat(this.locale, {
1207
+ minimumFractionDigits: field.decimal,
1208
+ maximumFractionDigits: field.decimal
1209
+ }).format(numberValue);
1210
+ return field.unit ? `${formattedValue} ${field.unit}` : formattedValue;
1211
+ }
1212
+ formatDateValue(value, dateFormat) {
1213
+ try {
1214
+ return formatDate(value, dateFormat || "dd/MM/yyyy", this.locale);
1215
+ } catch {
1216
+ return this.formatUnknownValue(value);
1217
+ }
1218
+ }
1219
+ buildChipViewModels(field, value) {
1220
+ return this.normalizeChipItems(value).map((item, index) => {
1221
+ return {
1222
+ label: this.resolveChipLabel(item, field.chips),
1223
+ trackValue: this.resolveChipTrackValue(item, field.chips, index),
1224
+ icon: field.chips?.icon,
1225
+ color: this.resolveChipColor(item, field.chips)
1226
+ };
1227
+ }).filter((chip) => !!chip.label);
1228
+ }
1229
+ normalizeChipItems(value) {
1230
+ if (!this.isFilled(value)) return [];
1231
+ return Array.isArray(value) ? value : [value];
1232
+ }
1233
+ resolveChipLabel(item, chips) {
1234
+ if (chips?.labelPath) return this.formatOptionalValue(this.getPathValue(item, chips.labelPath));
1235
+ if (this.isPrimitiveValue(item)) return this.formatOptionalValue(item);
1236
+ return this.formatOptionalValue(this.getPathValue(item, "label") ?? this.getPathValue(item, "name") ?? this.getPathValue(item, "title") ?? this.getPathValue(item, "displayName") ?? this.getPathValue(item, "fullname") ?? this.getPathValue(item, "_id") ?? this.getPathValue(item, "id"));
1237
+ }
1238
+ resolveChipTrackValue(item, chips, index) {
1239
+ if (chips?.trackByPath) return this.getPathValue(item, chips.trackByPath) ?? index;
1240
+ if (this.isPrimitiveValue(item)) return item ?? index;
1241
+ return this.getPathValue(item, "_id") ?? this.getPathValue(item, "id") ?? this.resolveChipLabel(item, chips) ?? index;
1242
+ }
1243
+ resolveChipColor(item, chips) {
1244
+ if (chips?.colorPath) return this.formatOptionalValue(this.getPathValue(item, chips.colorPath)) || void 0;
1245
+ return chips?.color;
1246
+ }
1247
+ formatOptionalValue(value) {
1248
+ if (value === null || value === void 0 || value === "") return "";
1249
+ return `${value}`;
1250
+ }
1251
+ isSafeHtmlValue(value) {
1252
+ return typeof value === "object" && value !== null && Object.prototype.hasOwnProperty.call(value, "changingThisBreaksApplicationSecurity");
1253
+ }
1254
+ formatUnknownValue(value) {
1255
+ if (Array.isArray(value)) return value.map((item) => this.formatUnknownValue(item)).join(", ");
1256
+ if (typeof value === "object" && value !== null) return JSON.stringify(value);
1257
+ return `${value}`;
1258
+ }
1259
+ findSelectOption(value, options) {
1260
+ return options?.find((option) => this.areValuesEqual(option.value, value));
1261
+ }
1262
+ areValuesEqual(first, second) {
1263
+ if (first === second) return true;
1264
+ if (this.isPrimitiveValue(first) || this.isPrimitiveValue(second)) return false;
1265
+ try {
1266
+ return JSON.stringify(first) === JSON.stringify(second);
1267
+ } catch {
1268
+ return false;
1269
+ }
1270
+ }
1271
+ getPathValue(data, path) {
1272
+ if (!path) return data;
1273
+ return this.parsePath(path).reduce((current, pathPart) => {
1274
+ if (current === null || current === void 0) return void 0;
1275
+ return current[pathPart];
1276
+ }, data);
1277
+ }
1278
+ parsePath(path) {
1279
+ return path.replace(/\[(\d+|"[^"]+"|'[^']+')\]/g, (_match, value) => `.${value.replace(/["']/g, "")}`).split(".").filter((pathPart) => !!pathPart);
1280
+ }
1281
+ normalizePositiveInteger(value, fallback) {
1282
+ const numberValue = Number(value ?? fallback);
1283
+ if (!Number.isFinite(numberValue) || numberValue <= 0) return fallback;
1284
+ return Math.floor(numberValue);
1285
+ }
1286
+ isFilled(value) {
1287
+ if (value === null || value === void 0 || value === "") return false;
1288
+ if (Array.isArray(value)) return value.length > 0;
1289
+ return true;
1290
+ }
1291
+ isPrimitiveValue(value) {
1292
+ return value === null || typeof value !== "object" && typeof value !== "function";
1293
+ }
1294
+ static ɵfac = i0.ɵɵngDeclareFactory({
1295
+ minVersion: "12.0.0",
1296
+ version: "22.2.1",
1297
+ ngImport: i0,
1298
+ type: SectionTabsDisplayComponent,
1299
+ deps: [
1300
+ { token: LOCALE_ID },
1301
+ { token: SectionTabsIntl },
1302
+ { token: i0.ChangeDetectorRef },
1303
+ { token: i0.DestroyRef }
1304
+ ],
1305
+ target: i0.ɵɵFactoryTarget.Component
1306
+ });
1307
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1308
+ minVersion: "17.0.0",
1309
+ version: "22.2.1",
1310
+ type: SectionTabsDisplayComponent,
1311
+ isStandalone: false,
1312
+ selector: "app-section-tabs-display",
1313
+ inputs: {
1314
+ options: "options",
1315
+ selectedIndex: "selectedIndex",
1316
+ queryParamKey: "queryParamKey",
1317
+ menuHeader: "menuHeader",
1318
+ showEmptyFields: "showEmptyFields"
1319
+ },
1320
+ outputs: {
1321
+ selectedIndexChange: "selectedIndexChange",
1322
+ showEmptyFieldsChange: "showEmptyFieldsChange"
1323
+ },
1324
+ usesOnChanges: true,
1325
+ ngImport: i0,
1326
+ template: "<!-- @format -->\n\n@if (viewModel.empty) {\n <div class=\"section-tabs-display__empty\">\n <strong>{{ intl.messages.emptySections }}</strong>\n </div>\n} @else {\n <app-section-tabs\n class=\"section-tabs-display\"\n [selectedIndex]=\"selectedIndex\"\n [queryParamKey]=\"queryParamKey\"\n (selectedIndexChange)=\"onSelectedIndexChange($event)\">\n @if (menuHeader) {\n <ng-template appSectionTabsMenuHeader>\n <div class=\"section-tabs-display__menu-header\">\n <span>{{ menuHeader }}</span>\n </div>\n </ng-template>\n }\n\n @if (showEmptyFieldsToggle) {\n <ng-template appSectionTabsFooter>\n <mat-slide-toggle [checked]=\"showEmptyFieldsState\" (change)=\"onShowEmptyFieldsChange($event.checked)\">\n <span [innerHTML]=\"showEmptyFieldsLabel\"></span>\n </mat-slide-toggle>\n </ng-template>\n }\n\n @for (section of viewModel.sections; track section.id) {\n <app-section-tab [done]=\"section.done\" [total]=\"section.total\" [queryParamValue]=\"section.queryParamValue\">\n <ng-template appSectionTabLabel>\n @if (section.icon) {\n <mat-icon [attr.title]=\"section.tooltip\">{{ section.icon }}</mat-icon>\n }\n <span [attr.title]=\"section.tooltip\" [innerHTML]=\"section.label\"></span>\n </ng-template>\n\n <ng-template appSectionTabContent>\n <div\n class=\"section-tabs-display__section\"\n [class.section-tabs-display__section--single-card]=\"section.sectionMode === 'single-card'\"\n [class.section-tabs-display__section--single-card-only]=\"\n section.sectionMode === 'single-card' && section.cardCount === 1\n \"\n [class.section-tabs-display__section--single-card-multiple]=\"\n section.sectionMode === 'single-card' && section.cardCount > 1\n \"\n [ngStyle]=\"section.gridStyles\"\n [appSectionTabsDisplayResponsiveGrid]=\"section.source.grid\"\n [sectionTabsDisplayResponsiveGridEnabled]=\"section.responsiveGrid\">\n @for (cardItem of section.items; track cardItem.id) {\n @if (cardItem.type === 'break') {\n <div class=\"section-tabs-display__grid-break\" aria-hidden=\"true\"></div>\n } @else {\n <article\n class=\"section-tabs-display__card section-tabs-card\"\n [ngClass]=\"cardItem.classes\"\n [ngStyle]=\"cardItem.styles\">\n <header class=\"section-tabs-display__card-header card-header\">\n <div class=\"section-tabs-display__card-title\">\n @if (cardItem.icon) {\n <mat-icon [attr.title]=\"cardItem.tooltip\">{{ cardItem.icon }}</mat-icon>\n }\n <h3 [attr.title]=\"cardItem.tooltip\" [innerHTML]=\"cardItem.label\"></h3>\n </div>\n\n @if (cardItem.completion.label) {\n <span class=\"section-tabs-display__completion-chip mini-chip\">{{\n cardItem.completion.label\n }}</span>\n }\n\n @if (cardItem.actions?.length) {\n <div class=\"section-tabs-display__card-actions\">\n @for (action of cardItem.actions; track action.id || action.label || action.icon || $index) {\n @if (action.menuOptions?.length) {\n @if (action.type === 'button') {\n <button\n mat-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n [matMenuTriggerFor]=\"displayCardActionMenu\">\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n } @else {\n <button\n mat-icon-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n [matMenuTriggerFor]=\"displayCardActionMenu\">\n <mat-icon>{{ action.icon || 'more_vert' }}</mat-icon>\n </button>\n }\n\n <mat-menu #displayCardActionMenu=\"matMenu\">\n @for (option of action.menuOptions; track option.id) {\n <button\n mat-menu-item\n type=\"button\"\n [disabled]=\"option.disabled\"\n [matTooltip]=\"option.tooltip || ''\"\n [attr.aria-label]=\"option.ariaLabel || option.label\"\n (click)=\"option.handle()\">\n @if (option.icon) {\n <mat-icon>{{ option.icon }}</mat-icon>\n }\n <span>{{ option.label }}</span>\n </button>\n }\n </mat-menu>\n } @else if (action.type === 'button') {\n <button\n mat-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n (click)=\"action.handle()\">\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n } @else {\n <button\n mat-icon-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n (click)=\"action.handle()\">\n <mat-icon>{{ action.icon }}</mat-icon>\n </button>\n }\n }\n </div>\n }\n </header>\n\n @if (cardItem.kind === 'component') {\n <div class=\"section-tabs-display__component-card\">\n @if (cardItem.component) {\n <ng-container\n *ngComponentOutlet=\"cardItem.component; inputs: cardItem.componentInputs\"></ng-container>\n } @else {\n <div class=\"section-tabs-display__empty-state empty-state\">\n <mat-icon aria-hidden=\"true\">extension_off</mat-icon>\n <div>\n <strong>{{ intl.messages.emptyComponents }}</strong>\n </div>\n </div>\n }\n </div>\n } @else {\n <div\n class=\"section-tabs-display__field-grid\"\n [ngStyle]=\"cardItem.gridStyles\"\n [appSectionTabsDisplayResponsiveGrid]=\"cardItem.source.grid\"\n [sectionTabsDisplayResponsiveGridEnabled]=\"cardItem.responsiveGrid\">\n @for (fieldItem of cardItem.items; track fieldItem.id) {\n @if (fieldItem.type === 'break') {\n <div class=\"section-tabs-display__grid-break\" aria-hidden=\"true\"></div>\n } @else {\n <div\n class=\"section-tabs-display__field-cell field-cell\"\n [ngClass]=\"fieldItem.classes\"\n [ngStyle]=\"fieldItem.styles\"\n [class.has-click]=\"!!fieldItem.onClick\"\n matRipple\n [matRippleDisabled]=\"!fieldItem.onClick\"\n (click)=\"onClickFieldItem(fieldItem)\">\n @if (fieldItem.kind === 'component') {\n @if (fieldItem.component) {\n <ng-container\n *ngComponentOutlet=\"\n fieldItem.component;\n inputs: fieldItem.componentInputs\n \"></ng-container>\n }\n } @else {\n <span class=\"section-tabs-display__field-label-row\">\n <span\n class=\"section-tabs-display__field-label field-label\"\n [innerHTML]=\"fieldItem.label\"></span>\n @if (fieldItem.labelAction; as action) {\n <button\n type=\"button\"\n class=\"section-tabs-display__field-label-action\"\n data-field-label-action\n [disabled]=\"action.disabled\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-pressed]=\"action.active\"\n (click)=\"action.onClick(); $event.stopPropagation()\">\n {{ action.active ? '★' : '☆' }}\n </button>\n }\n </span>\n\n @if (fieldItem.kind === 'chips') {\n <div class=\"section-tabs-display__chips\">\n @for (chip of fieldItem.chipsValue; track chip.trackValue) {\n <span class=\"section-tabs-display__chip\" [style.color]=\"chip.color\">\n @if (chip.icon) {\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n }\n <span [innerHTML]=\"chip.label\"></span>\n </span>\n } @empty {\n <span class=\"section-tabs-display__field-value field-value\">—</span>\n }\n </div>\n } @else {\n <span\n class=\"section-tabs-display__field-value field-value\"\n [style.color]=\"fieldItem.color\"\n [innerHTML]=\"fieldItem.displayValue\">\n </span>\n }\n }\n </div>\n }\n <!-- } @empty {\n <div class=\"section-tabs-display__empty-state empty-state\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <div>\n <strong>{{ intl.messages.emptyFields }}</strong>\n <span>{{ intl.messages.emptyFieldsDescription }}</span>\n </div>\n </div> -->\n }\n </div>\n }\n </article>\n }\n }\n </div>\n </ng-template>\n </app-section-tab>\n }\n </app-section-tabs>\n}\n",
1327
+ styles: [".section-tabs-display__field-label-row{display:inline-flex;align-items:center;gap:4px}.section-tabs-display__field-label-action{border:0;background:transparent;color:#bb8b14;cursor:pointer;font-size:1.1rem;line-height:1;padding:0}.section-tabs-display__field-label-action:disabled{cursor:default;opacity:.6}app-section-tabs-display{display:block;height:100%;min-width:0;min-height:0}.section-tabs-display{display:block;height:100%;min-width:0;min-height:0}.section-tabs-display__empty{height:100%;min-height:160px;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border:1px dashed #cbd5df;border-radius:8px;background:#f8fafc;color:#607286}.section-tabs-display__section{display:grid;grid-template-columns:repeat(var(--section-tabs-display-grid-effective-columns, var(--section-tabs-display-grid-columns, 1)),minmax(var(--section-tabs-display-grid-track-min-column-width, 0px),1fr));gap:var(--section-tabs-display-grid-gap, 12px);align-items:start;align-content:start;grid-auto-flow:row;grid-auto-rows:max-content;flex:0 0 auto;width:100%;max-width:100%;min-width:0;box-sizing:border-box;padding:8px 8px 8px 0}.section-tabs-display__section--single-card{height:100%;min-height:0;grid-template-columns:minmax(0,1fr);grid-auto-rows:100%;align-items:stretch;align-content:start}.section-tabs-display__section--single-card>.section-tabs-display__grid-break{display:none}.section-tabs-display__section--single-card>.section-tabs-display__card{grid-column:1/-1!important;grid-row:auto!important;height:100%!important;min-height:0}.section-tabs-display__section--single-card>.section-tabs-display__card>.section-tabs-display__component-card,.section-tabs-display__section--single-card>.section-tabs-display__card>.section-tabs-display__field-grid{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}.section-tabs-display__section--single-card-only{overflow:hidden}.section-tabs-display__section--single-card-multiple{overflow:visible}.section-tabs-display__card{min-width:0;max-width:100%;min-height:0;height:auto;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box;border:1px solid #d9e0e7;border-radius:8px;background:#fff}.section-tabs-display__card-header{flex:0 0 auto}.section-tabs-display__card-title{min-width:0;display:flex;align-items:center;gap:10px}.section-tabs-display__card-title mat-icon,.section-tabs-display__card-title .mat-icon{flex:0 0 auto;color:#6b7280}.section-tabs-display__card-title h3{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__completion-chip{flex:0 0 auto}.section-tabs-display__component-card{min-width:0;min-height:0;height:100%}.section-tabs-display__field-grid{display:grid;grid-template-columns:repeat(var(--section-tabs-display-grid-effective-columns, var(--section-tabs-display-grid-columns, 1)),minmax(var(--section-tabs-display-grid-track-min-column-width, 0px),1fr));align-items:start;align-content:start;gap:var(--section-tabs-display-grid-gap, 0px);width:100%;max-width:100%;min-width:0}.section-tabs-display__section>.section-tabs-display__card,.section-tabs-display__field-grid>.section-tabs-display__field-cell{min-width:0;max-width:100%}.section-tabs-display__field-cell{min-width:0}.section-tabs-display__field-cell.has-click{cursor:pointer}.section-tabs-display__field-cell.has-click:hover{background-color:#0000000a}.section-tabs-display__field-cell--empty{opacity:.72}.section-tabs-display__field-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__field-value{min-width:0;overflow-wrap:anywhere}.section-tabs-display__empty-state{grid-column:1/-1}.section-tabs-display__grid-break{grid-column:1/-1;width:100%;height:0;min-height:0;overflow:hidden}.section-tabs-display__item--break-before{grid-column-start:1}.section-tabs-display__chips{min-width:0;display:flex;flex-flow:row wrap;gap:8px}.section-tabs-display__chip{min-width:0;max-width:100%;display:inline-flex;align-items:center;gap:8px;padding:4px 10px;border-radius:999px;background:var(--ngx-mat-section-tabs-display-background, #f3f6f9);color:var(--ngx-mat-section-tabs-display-primary, #123047);font-size:12px;font-weight:600;line-height:1.2}.section-tabs-display__chip mat-icon,.section-tabs-display__chip .mat-icon{flex:0 0 auto;--mat-icon-size: 16px}.section-tabs-display__chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__card-actions{display:inline-flex;align-items:center;gap:4px;margin-left:auto}.section-tabs-display__card-action{color:var(--action-color, inherit)}.section-tabs-display__card-action.mat-mdc-icon-button{padding:6px;--mat-icon-button-icon-size: 20px;--mat-icon-button-state-layer-size: 32px}.section-tabs-display__card-action.mat-mdc-icon-button mat-icon{--mat-icon-size: 20px}.section-tabs-display__card-action.mat-mdc-button{min-width:0;height:32px;padding:0 10px;font-size:.85rem;line-height:32px}\n"],
1328
+ dependencies: [
1329
+ {
1330
+ kind: "directive",
1331
+ type: i1.NgClass,
1332
+ selector: "[ngClass]",
1333
+ inputs: ["class", "ngClass"]
1334
+ },
1335
+ {
1336
+ kind: "directive",
1337
+ type: i1.NgComponentOutlet,
1338
+ selector: "[ngComponentOutlet]",
1339
+ inputs: [
1340
+ "ngComponentOutlet",
1341
+ "ngComponentOutletInputs",
1342
+ "ngComponentOutletInjector",
1343
+ "ngComponentOutletEnvironmentInjector",
1344
+ "ngComponentOutletContent",
1345
+ "ngComponentOutletNgModule"
1346
+ ],
1347
+ exportAs: ["ngComponentOutlet"]
1348
+ },
1349
+ {
1350
+ kind: "directive",
1351
+ type: i1.NgStyle,
1352
+ selector: "[ngStyle]",
1353
+ inputs: ["ngStyle"]
1354
+ },
1355
+ {
1356
+ kind: "component",
1357
+ type: i3.MatButton,
1358
+ 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] ",
1359
+ inputs: ["matButton"],
1360
+ exportAs: ["matButton", "matAnchor"]
1361
+ },
1362
+ {
1363
+ kind: "component",
1364
+ type: i3.MatIconButton,
1365
+ selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]",
1366
+ exportAs: ["matButton", "matAnchor"]
1367
+ },
1368
+ {
1369
+ kind: "component",
1370
+ type: i4.MatIcon,
1371
+ selector: "mat-icon",
1372
+ inputs: [
1373
+ "color",
1374
+ "inline",
1375
+ "svgIcon",
1376
+ "fontSet",
1377
+ "fontIcon"
1378
+ ],
1379
+ exportAs: ["matIcon"]
1380
+ },
1381
+ {
1382
+ kind: "component",
1383
+ type: i5.MatMenu,
1384
+ selector: "mat-menu",
1385
+ inputs: [
1386
+ "backdropClass",
1387
+ "aria-label",
1388
+ "aria-labelledby",
1389
+ "aria-describedby",
1390
+ "xPosition",
1391
+ "yPosition",
1392
+ "overlapTrigger",
1393
+ "hasBackdrop",
1394
+ "class",
1395
+ "classList"
1396
+ ],
1397
+ outputs: ["closed", "close"],
1398
+ exportAs: ["matMenu"]
1399
+ },
1400
+ {
1401
+ kind: "component",
1402
+ type: i5.MatMenuItem,
1403
+ selector: "[mat-menu-item]",
1404
+ inputs: [
1405
+ "role",
1406
+ "disabled",
1407
+ "disabledInteractive",
1408
+ "disableRipple"
1409
+ ],
1410
+ exportAs: ["matMenuItem"]
1411
+ },
1412
+ {
1413
+ kind: "directive",
1414
+ type: i5.MatMenuTrigger,
1415
+ selector: "[mat-menu-trigger-for], [matMenuTriggerFor]",
1416
+ inputs: [
1417
+ "mat-menu-trigger-for",
1418
+ "matMenuTriggerFor",
1419
+ "matMenuTriggerData",
1420
+ "matMenuTriggerRestoreFocus"
1421
+ ],
1422
+ outputs: [
1423
+ "menuOpened",
1424
+ "onMenuOpen",
1425
+ "menuClosed",
1426
+ "onMenuClose"
1427
+ ],
1428
+ exportAs: ["matMenuTrigger"]
1429
+ },
1430
+ {
1431
+ kind: "directive",
1432
+ type: i6.MatRipple,
1433
+ selector: "[mat-ripple], [matRipple]",
1434
+ inputs: [
1435
+ "matRippleColor",
1436
+ "matRippleUnbounded",
1437
+ "matRippleCentered",
1438
+ "matRippleRadius",
1439
+ "matRippleAnimation",
1440
+ "matRippleDisabled",
1441
+ "matRippleTrigger"
1442
+ ],
1443
+ exportAs: ["matRipple"]
1444
+ },
1445
+ {
1446
+ kind: "component",
1447
+ type: i7.MatSlideToggle,
1448
+ selector: "mat-slide-toggle",
1449
+ inputs: [
1450
+ "name",
1451
+ "id",
1452
+ "labelPosition",
1453
+ "aria-label",
1454
+ "aria-labelledby",
1455
+ "aria-describedby",
1456
+ "required",
1457
+ "color",
1458
+ "disabled",
1459
+ "fullWidth",
1460
+ "disableRipple",
1461
+ "tabIndex",
1462
+ "checked",
1463
+ "hideIcon",
1464
+ "disabledInteractive"
1465
+ ],
1466
+ outputs: ["change", "toggleChange"],
1467
+ exportAs: ["matSlideToggle"]
1468
+ },
1469
+ {
1470
+ kind: "directive",
1471
+ type: i8.MatTooltip,
1472
+ selector: "[matTooltip]",
1473
+ inputs: [
1474
+ "matTooltipPosition",
1475
+ "matTooltipPositionAtOrigin",
1476
+ "matTooltipDisabled",
1477
+ "matTooltipShowDelay",
1478
+ "matTooltipHideDelay",
1479
+ "matTooltipTouchGestures",
1480
+ "matTooltip",
1481
+ "matTooltipClass"
1482
+ ],
1483
+ exportAs: ["matTooltip"]
1484
+ },
1485
+ {
1486
+ kind: "component",
1487
+ type: SectionTabsComponent,
1488
+ selector: "app-section-tabs",
1489
+ inputs: ["selectedIndex", "queryParamKey"],
1490
+ outputs: ["selectedIndexChange"]
1491
+ },
1492
+ {
1493
+ kind: "component",
1494
+ type: SectionTabComponent,
1495
+ selector: "app-section-tab",
1496
+ inputs: [
1497
+ "type",
1498
+ "queryParamValue",
1499
+ "disabled",
1500
+ "done",
1501
+ "total",
1502
+ "totalMax",
1503
+ "progress",
1504
+ "statusColor",
1505
+ "statusColorDone",
1506
+ "statusColorTotal"
1507
+ ]
1508
+ },
1509
+ {
1510
+ kind: "directive",
1511
+ type: SectionTabLabelDirective,
1512
+ selector: "ng-template[appSectionTabLabel]"
1513
+ },
1514
+ {
1515
+ kind: "directive",
1516
+ type: SectionTabContentDirective,
1517
+ selector: "ng-template[appSectionTabContent]"
1518
+ },
1519
+ {
1520
+ kind: "directive",
1521
+ type: SectionTabsMenuHeaderDirective,
1522
+ selector: "ng-template[appSectionTabsMenuHeader]"
1523
+ },
1524
+ {
1525
+ kind: "directive",
1526
+ type: SectionTabsFooterDirective,
1527
+ selector: "ng-template[appSectionTabsFooter]"
1528
+ },
1529
+ {
1530
+ kind: "directive",
1531
+ type: SectionTabsDisplayResponsiveGridDirective,
1532
+ selector: "[appSectionTabsDisplayResponsiveGrid]",
1533
+ inputs: ["appSectionTabsDisplayResponsiveGrid", "sectionTabsDisplayResponsiveGridEnabled"]
1534
+ }
1535
+ ],
1536
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1537
+ });
1538
+ };
1539
+ i0.ɵɵngDeclareClassMetadata({
1540
+ minVersion: "12.0.0",
1541
+ version: "22.2.1",
1542
+ ngImport: i0,
1543
+ type: SectionTabsDisplayComponent,
1544
+ decorators: [{
1545
+ type: Component,
1546
+ args: [{
1547
+ selector: "app-section-tabs-display",
1548
+ changeDetection: ChangeDetectionStrategy.OnPush,
1549
+ standalone: false,
1550
+ template: "<!-- @format -->\n\n@if (viewModel.empty) {\n <div class=\"section-tabs-display__empty\">\n <strong>{{ intl.messages.emptySections }}</strong>\n </div>\n} @else {\n <app-section-tabs\n class=\"section-tabs-display\"\n [selectedIndex]=\"selectedIndex\"\n [queryParamKey]=\"queryParamKey\"\n (selectedIndexChange)=\"onSelectedIndexChange($event)\">\n @if (menuHeader) {\n <ng-template appSectionTabsMenuHeader>\n <div class=\"section-tabs-display__menu-header\">\n <span>{{ menuHeader }}</span>\n </div>\n </ng-template>\n }\n\n @if (showEmptyFieldsToggle) {\n <ng-template appSectionTabsFooter>\n <mat-slide-toggle [checked]=\"showEmptyFieldsState\" (change)=\"onShowEmptyFieldsChange($event.checked)\">\n <span [innerHTML]=\"showEmptyFieldsLabel\"></span>\n </mat-slide-toggle>\n </ng-template>\n }\n\n @for (section of viewModel.sections; track section.id) {\n <app-section-tab [done]=\"section.done\" [total]=\"section.total\" [queryParamValue]=\"section.queryParamValue\">\n <ng-template appSectionTabLabel>\n @if (section.icon) {\n <mat-icon [attr.title]=\"section.tooltip\">{{ section.icon }}</mat-icon>\n }\n <span [attr.title]=\"section.tooltip\" [innerHTML]=\"section.label\"></span>\n </ng-template>\n\n <ng-template appSectionTabContent>\n <div\n class=\"section-tabs-display__section\"\n [class.section-tabs-display__section--single-card]=\"section.sectionMode === 'single-card'\"\n [class.section-tabs-display__section--single-card-only]=\"\n section.sectionMode === 'single-card' && section.cardCount === 1\n \"\n [class.section-tabs-display__section--single-card-multiple]=\"\n section.sectionMode === 'single-card' && section.cardCount > 1\n \"\n [ngStyle]=\"section.gridStyles\"\n [appSectionTabsDisplayResponsiveGrid]=\"section.source.grid\"\n [sectionTabsDisplayResponsiveGridEnabled]=\"section.responsiveGrid\">\n @for (cardItem of section.items; track cardItem.id) {\n @if (cardItem.type === 'break') {\n <div class=\"section-tabs-display__grid-break\" aria-hidden=\"true\"></div>\n } @else {\n <article\n class=\"section-tabs-display__card section-tabs-card\"\n [ngClass]=\"cardItem.classes\"\n [ngStyle]=\"cardItem.styles\">\n <header class=\"section-tabs-display__card-header card-header\">\n <div class=\"section-tabs-display__card-title\">\n @if (cardItem.icon) {\n <mat-icon [attr.title]=\"cardItem.tooltip\">{{ cardItem.icon }}</mat-icon>\n }\n <h3 [attr.title]=\"cardItem.tooltip\" [innerHTML]=\"cardItem.label\"></h3>\n </div>\n\n @if (cardItem.completion.label) {\n <span class=\"section-tabs-display__completion-chip mini-chip\">{{\n cardItem.completion.label\n }}</span>\n }\n\n @if (cardItem.actions?.length) {\n <div class=\"section-tabs-display__card-actions\">\n @for (action of cardItem.actions; track action.id || action.label || action.icon || $index) {\n @if (action.menuOptions?.length) {\n @if (action.type === 'button') {\n <button\n mat-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n [matMenuTriggerFor]=\"displayCardActionMenu\">\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n } @else {\n <button\n mat-icon-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n [matMenuTriggerFor]=\"displayCardActionMenu\">\n <mat-icon>{{ action.icon || 'more_vert' }}</mat-icon>\n </button>\n }\n\n <mat-menu #displayCardActionMenu=\"matMenu\">\n @for (option of action.menuOptions; track option.id) {\n <button\n mat-menu-item\n type=\"button\"\n [disabled]=\"option.disabled\"\n [matTooltip]=\"option.tooltip || ''\"\n [attr.aria-label]=\"option.ariaLabel || option.label\"\n (click)=\"option.handle()\">\n @if (option.icon) {\n <mat-icon>{{ option.icon }}</mat-icon>\n }\n <span>{{ option.label }}</span>\n </button>\n }\n </mat-menu>\n } @else if (action.type === 'button') {\n <button\n mat-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n (click)=\"action.handle()\">\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n } @else {\n <button\n mat-icon-button\n type=\"button\"\n class=\"section-tabs-display__card-action\"\n [style.--action-color]=\"action.color\"\n [disabled]=\"action.disabled\"\n [matTooltip]=\"action.tooltip || ''\"\n [attr.aria-label]=\"action.ariaLabel || action.label || action.icon\"\n (click)=\"action.handle()\">\n <mat-icon>{{ action.icon }}</mat-icon>\n </button>\n }\n }\n </div>\n }\n </header>\n\n @if (cardItem.kind === 'component') {\n <div class=\"section-tabs-display__component-card\">\n @if (cardItem.component) {\n <ng-container\n *ngComponentOutlet=\"cardItem.component; inputs: cardItem.componentInputs\"></ng-container>\n } @else {\n <div class=\"section-tabs-display__empty-state empty-state\">\n <mat-icon aria-hidden=\"true\">extension_off</mat-icon>\n <div>\n <strong>{{ intl.messages.emptyComponents }}</strong>\n </div>\n </div>\n }\n </div>\n } @else {\n <div\n class=\"section-tabs-display__field-grid\"\n [ngStyle]=\"cardItem.gridStyles\"\n [appSectionTabsDisplayResponsiveGrid]=\"cardItem.source.grid\"\n [sectionTabsDisplayResponsiveGridEnabled]=\"cardItem.responsiveGrid\">\n @for (fieldItem of cardItem.items; track fieldItem.id) {\n @if (fieldItem.type === 'break') {\n <div class=\"section-tabs-display__grid-break\" aria-hidden=\"true\"></div>\n } @else {\n <div\n class=\"section-tabs-display__field-cell field-cell\"\n [ngClass]=\"fieldItem.classes\"\n [ngStyle]=\"fieldItem.styles\"\n [class.has-click]=\"!!fieldItem.onClick\"\n matRipple\n [matRippleDisabled]=\"!fieldItem.onClick\"\n (click)=\"onClickFieldItem(fieldItem)\">\n @if (fieldItem.kind === 'component') {\n @if (fieldItem.component) {\n <ng-container\n *ngComponentOutlet=\"\n fieldItem.component;\n inputs: fieldItem.componentInputs\n \"></ng-container>\n }\n } @else {\n <span class=\"section-tabs-display__field-label-row\">\n <span\n class=\"section-tabs-display__field-label field-label\"\n [innerHTML]=\"fieldItem.label\"></span>\n @if (fieldItem.labelAction; as action) {\n <button\n type=\"button\"\n class=\"section-tabs-display__field-label-action\"\n data-field-label-action\n [disabled]=\"action.disabled\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-pressed]=\"action.active\"\n (click)=\"action.onClick(); $event.stopPropagation()\">\n {{ action.active ? '★' : '☆' }}\n </button>\n }\n </span>\n\n @if (fieldItem.kind === 'chips') {\n <div class=\"section-tabs-display__chips\">\n @for (chip of fieldItem.chipsValue; track chip.trackValue) {\n <span class=\"section-tabs-display__chip\" [style.color]=\"chip.color\">\n @if (chip.icon) {\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n }\n <span [innerHTML]=\"chip.label\"></span>\n </span>\n } @empty {\n <span class=\"section-tabs-display__field-value field-value\">—</span>\n }\n </div>\n } @else {\n <span\n class=\"section-tabs-display__field-value field-value\"\n [style.color]=\"fieldItem.color\"\n [innerHTML]=\"fieldItem.displayValue\">\n </span>\n }\n }\n </div>\n }\n <!-- } @empty {\n <div class=\"section-tabs-display__empty-state empty-state\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <div>\n <strong>{{ intl.messages.emptyFields }}</strong>\n <span>{{ intl.messages.emptyFieldsDescription }}</span>\n </div>\n </div> -->\n }\n </div>\n }\n </article>\n }\n }\n </div>\n </ng-template>\n </app-section-tab>\n }\n </app-section-tabs>\n}\n",
1551
+ styles: [".section-tabs-display__field-label-row{display:inline-flex;align-items:center;gap:4px}.section-tabs-display__field-label-action{border:0;background:transparent;color:#bb8b14;cursor:pointer;font-size:1.1rem;line-height:1;padding:0}.section-tabs-display__field-label-action:disabled{cursor:default;opacity:.6}app-section-tabs-display{display:block;height:100%;min-width:0;min-height:0}.section-tabs-display{display:block;height:100%;min-width:0;min-height:0}.section-tabs-display__empty{height:100%;min-height:160px;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border:1px dashed #cbd5df;border-radius:8px;background:#f8fafc;color:#607286}.section-tabs-display__section{display:grid;grid-template-columns:repeat(var(--section-tabs-display-grid-effective-columns, var(--section-tabs-display-grid-columns, 1)),minmax(var(--section-tabs-display-grid-track-min-column-width, 0px),1fr));gap:var(--section-tabs-display-grid-gap, 12px);align-items:start;align-content:start;grid-auto-flow:row;grid-auto-rows:max-content;flex:0 0 auto;width:100%;max-width:100%;min-width:0;box-sizing:border-box;padding:8px 8px 8px 0}.section-tabs-display__section--single-card{height:100%;min-height:0;grid-template-columns:minmax(0,1fr);grid-auto-rows:100%;align-items:stretch;align-content:start}.section-tabs-display__section--single-card>.section-tabs-display__grid-break{display:none}.section-tabs-display__section--single-card>.section-tabs-display__card{grid-column:1/-1!important;grid-row:auto!important;height:100%!important;min-height:0}.section-tabs-display__section--single-card>.section-tabs-display__card>.section-tabs-display__component-card,.section-tabs-display__section--single-card>.section-tabs-display__card>.section-tabs-display__field-grid{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}.section-tabs-display__section--single-card-only{overflow:hidden}.section-tabs-display__section--single-card-multiple{overflow:visible}.section-tabs-display__card{min-width:0;max-width:100%;min-height:0;height:auto;display:flex;flex-direction:column;overflow:hidden;box-sizing:border-box;border:1px solid #d9e0e7;border-radius:8px;background:#fff}.section-tabs-display__card-header{flex:0 0 auto}.section-tabs-display__card-title{min-width:0;display:flex;align-items:center;gap:10px}.section-tabs-display__card-title mat-icon,.section-tabs-display__card-title .mat-icon{flex:0 0 auto;color:#6b7280}.section-tabs-display__card-title h3{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__completion-chip{flex:0 0 auto}.section-tabs-display__component-card{min-width:0;min-height:0;height:100%}.section-tabs-display__field-grid{display:grid;grid-template-columns:repeat(var(--section-tabs-display-grid-effective-columns, var(--section-tabs-display-grid-columns, 1)),minmax(var(--section-tabs-display-grid-track-min-column-width, 0px),1fr));align-items:start;align-content:start;gap:var(--section-tabs-display-grid-gap, 0px);width:100%;max-width:100%;min-width:0}.section-tabs-display__section>.section-tabs-display__card,.section-tabs-display__field-grid>.section-tabs-display__field-cell{min-width:0;max-width:100%}.section-tabs-display__field-cell{min-width:0}.section-tabs-display__field-cell.has-click{cursor:pointer}.section-tabs-display__field-cell.has-click:hover{background-color:#0000000a}.section-tabs-display__field-cell--empty{opacity:.72}.section-tabs-display__field-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__field-value{min-width:0;overflow-wrap:anywhere}.section-tabs-display__empty-state{grid-column:1/-1}.section-tabs-display__grid-break{grid-column:1/-1;width:100%;height:0;min-height:0;overflow:hidden}.section-tabs-display__item--break-before{grid-column-start:1}.section-tabs-display__chips{min-width:0;display:flex;flex-flow:row wrap;gap:8px}.section-tabs-display__chip{min-width:0;max-width:100%;display:inline-flex;align-items:center;gap:8px;padding:4px 10px;border-radius:999px;background:var(--ngx-mat-section-tabs-display-background, #f3f6f9);color:var(--ngx-mat-section-tabs-display-primary, #123047);font-size:12px;font-weight:600;line-height:1.2}.section-tabs-display__chip mat-icon,.section-tabs-display__chip .mat-icon{flex:0 0 auto;--mat-icon-size: 16px}.section-tabs-display__chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-tabs-display__card-actions{display:inline-flex;align-items:center;gap:4px;margin-left:auto}.section-tabs-display__card-action{color:var(--action-color, inherit)}.section-tabs-display__card-action.mat-mdc-icon-button{padding:6px;--mat-icon-button-icon-size: 20px;--mat-icon-button-state-layer-size: 32px}.section-tabs-display__card-action.mat-mdc-icon-button mat-icon{--mat-icon-size: 20px}.section-tabs-display__card-action.mat-mdc-button{min-width:0;height:32px;padding:0 10px;font-size:.85rem;line-height:32px}\n"]
1552
+ }]
1553
+ }],
1554
+ ctorParameters: () => [
1555
+ {
1556
+ type: void 0,
1557
+ decorators: [{
1558
+ type: Inject,
1559
+ args: [LOCALE_ID]
1560
+ }]
1561
+ },
1562
+ { type: SectionTabsIntl },
1563
+ { type: i0.ChangeDetectorRef },
1564
+ { type: i0.DestroyRef }
1565
+ ],
1566
+ propDecorators: {
1567
+ options: [{
1568
+ type: Input,
1569
+ args: [{ required: true }]
1570
+ }],
1571
+ selectedIndex: [{ type: Input }],
1572
+ queryParamKey: [{ type: Input }],
1573
+ menuHeader: [{ type: Input }],
1574
+ showEmptyFields: [{ type: Input }],
1575
+ selectedIndexChange: [{ type: Output }],
1576
+ showEmptyFieldsChange: [{ type: Output }]
1577
+ }
1578
+ });
1579
+ const declarations = [
1580
+ SectionTabsComponent,
1581
+ SectionTabComponent,
1582
+ SectionTabsDisplayComponent,
1583
+ SectionTabLabelDirective,
1584
+ SectionTabContentDirective,
1585
+ SectionTabsMenuHeaderDirective,
1586
+ SectionTabsFooterDirective,
1587
+ SectionTabsDisplayResponsiveGridDirective
1588
+ ];
1589
+ var SectionTabsModule = class SectionTabsModule {
1590
+ static ɵfac = i0.ɵɵngDeclareFactory({
1591
+ minVersion: "12.0.0",
1592
+ version: "22.2.1",
1593
+ ngImport: i0,
1594
+ type: SectionTabsModule,
1595
+ deps: [],
1596
+ target: i0.ɵɵFactoryTarget.NgModule
1597
+ });
1598
+ static ɵmod = i0.ɵɵngDeclareNgModule({
1599
+ minVersion: "14.0.0",
1600
+ version: "22.2.1",
1601
+ ngImport: i0,
1602
+ type: SectionTabsModule,
1603
+ declarations: [
1604
+ SectionTabsComponent,
1605
+ SectionTabComponent,
1606
+ SectionTabsDisplayComponent,
1607
+ SectionTabLabelDirective,
1608
+ SectionTabContentDirective,
1609
+ SectionTabsMenuHeaderDirective,
1610
+ SectionTabsFooterDirective,
1611
+ SectionTabsDisplayResponsiveGridDirective
1612
+ ],
1613
+ imports: [
1614
+ CommonModule,
1615
+ MatButtonModule,
1616
+ MatIconModule,
1617
+ MatMenuModule,
1618
+ MatRippleModule,
1619
+ MatSlideToggleModule,
1620
+ MatTooltipModule
1621
+ ],
1622
+ exports: [
1623
+ SectionTabsComponent,
1624
+ SectionTabComponent,
1625
+ SectionTabsDisplayComponent,
1626
+ SectionTabLabelDirective,
1627
+ SectionTabContentDirective,
1628
+ SectionTabsMenuHeaderDirective,
1629
+ SectionTabsFooterDirective
1630
+ ]
1631
+ });
1632
+ static ɵinj = i0.ɵɵngDeclareInjector({
1633
+ minVersion: "12.0.0",
1634
+ version: "22.2.1",
1635
+ ngImport: i0,
1636
+ type: SectionTabsModule,
1637
+ imports: [
1638
+ CommonModule,
1639
+ MatButtonModule,
1640
+ MatIconModule,
1641
+ MatMenuModule,
1642
+ MatRippleModule,
1643
+ MatSlideToggleModule,
1644
+ MatTooltipModule
1645
+ ]
1646
+ });
1647
+ };
1648
+ i0.ɵɵngDeclareClassMetadata({
1649
+ minVersion: "12.0.0",
1650
+ version: "22.2.1",
1651
+ ngImport: i0,
1652
+ type: SectionTabsModule,
1653
+ decorators: [{
1654
+ type: NgModule,
1655
+ args: [{
1656
+ declarations,
1657
+ imports: [
1658
+ CommonModule,
1659
+ MatButtonModule,
1660
+ MatIconModule,
1661
+ MatMenuModule,
1662
+ MatRippleModule,
1663
+ MatSlideToggleModule,
1664
+ MatTooltipModule
1665
+ ],
1666
+ exports: [
1667
+ SectionTabsComponent,
1668
+ SectionTabComponent,
1669
+ SectionTabsDisplayComponent,
1670
+ SectionTabLabelDirective,
1671
+ SectionTabContentDirective,
1672
+ SectionTabsMenuHeaderDirective,
1673
+ SectionTabsFooterDirective
1674
+ ]
1675
+ }]
1676
+ }]
1677
+ });
1678
+ export { SECTION_SELECTION_HANDLER, SectionTabComponent, SectionTabContentDirective, SectionTabLabelDirective, SectionTabsComponent, SectionTabsDisplayComponent, SectionTabsFooterDirective, SectionTabsIntl, SectionTabsMenuHeaderDirective, SectionTabsModule, sectionTabsSlideBottomTransitions, sectionTabsSlideTopTransitions };
1679
+
1680
+ //# sourceMappingURL=eherve-angular-material-section-tabs.mjs.map