@openmfp/ngx 0.18.4 → 0.18.6

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.
@@ -32,6 +32,12 @@ import { Dialog } from '@fundamental-ngx/ui5-webcomponents/dialog';
32
32
  import { Title } from '@fundamental-ngx/ui5-webcomponents/title';
33
33
  import '@ui5/webcomponents-icons/dist/search.js';
34
34
  import { debounceTime, distinctUntilChanged, map, filter } from 'rxjs';
35
+ import '@ui5/webcomponents-icons/dist/resize-corner.js';
36
+ import '@ui5/webcomponents-icons/dist/alert.js';
37
+ import { List } from '@fundamental-ngx/ui5-webcomponents/list';
38
+ import { ListItemCustom } from '@fundamental-ngx/ui5-webcomponents/list-item-custom';
39
+ import { Switch } from '@fundamental-ngx/ui5-webcomponents/switch';
40
+ import { GridStackEngine } from 'gridstack/dist/gridstack-engine';
35
41
  import { DomSanitizer } from '@angular/platform-browser';
36
42
  import { Menu } from '@fundamental-ngx/ui5-webcomponents/menu';
37
43
  import { MenuItem } from '@fundamental-ngx/ui5-webcomponents/menu-item';
@@ -40,14 +46,10 @@ import '@ui5/webcomponents-icons/dist/action-settings.js';
40
46
  import '@ui5/webcomponents-icons/dist/menu2.js';
41
47
  import '@ui5/webcomponents-icons/dist/user-edit.js';
42
48
  import { GridstackComponent, GridstackItemComponent } from 'gridstack/dist/angular';
43
- import '@ui5/webcomponents-icons/dist/resize-corner.js';
44
- import '@ui5/webcomponents-icons/dist/alert.js';
45
- import { List } from '@fundamental-ngx/ui5-webcomponents/list';
46
- import { ListItemCustom } from '@fundamental-ngx/ui5-webcomponents/list-item-custom';
47
- import { Switch } from '@fundamental-ngx/ui5-webcomponents/switch';
48
49
  import { Card } from '@fundamental-ngx/ui5-webcomponents/card';
49
50
  import { CardHeader } from '@fundamental-ngx/ui5-webcomponents/card-header';
50
51
  import { ListItemStandard } from '@fundamental-ngx/ui5-webcomponents/list-item-standard';
52
+ import '@ui5/webcomponents-icons/dist/overflow.js';
51
53
 
52
54
  const getResourceValueByJsonPath = (resource, field) => {
53
55
  const property = field.jsonPathExpression || field.property;
@@ -1127,6 +1129,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
1127
1129
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"card\" data-testid=\"generic-table-card\">\n <div class=\"card__header\">\n <div class=\"card__title\">\n @if (header(); as header) {\n {{ header }}\n @if (headerTooltip(); as tooltip) {\n <ui5-icon\n class=\"card__info-icon\"\n name=\"hint\"\n [accessibleName]=\"tooltip\"\n [showTooltip]=\"true\"\n />\n }\n }\n </div>\n <div class=\"card__actions\">\n @if (resourcesSearchable()) {\n <ui5-input\n class=\"card__search-input\"\n data-testid=\"generic-table-card-search-input\"\n [formControl]=\"searchControl\"\n [placeholder]=\"searchPlaceholder()\"\n [showClearIcon]=\"true\"\n >\n <ui5-icon\n class=\"card__search-icon\"\n data-testid=\"generic-table-card-search-icon\"\n name=\"search\"\n slot=\"icon\"\n [accessibleName]=\"searchButtonConfig()?.tooltip ?? 'Search'\"\n [showTooltip]=\"true\"\n (click)=\"submitSearch()\"\n />\n </ui5-input>\n }\n @if (createFormConfig()) {\n <ui5-button\n class=\"card__create-btn\"\n data-testid=\"generic-table-card-create-btn\"\n [accessibleName]=\"\n createButtonConfig()?.text ||\n createButtonConfig()?.tooltip ||\n 'Create'\n \"\n [design]=\"createButtonConfig()?.design ?? 'Transparent'\"\n [icon]=\"createButtonConfig()?.icon ?? 'add'\"\n [tooltip]=\"createButtonConfig()?.tooltip\"\n (click)=\"openCreateDialog()\"\n >\n {{ createButtonConfig()?.text ?? '' }}\n </ui5-button>\n }\n </div>\n </div>\n\n @if (hasFilterTabs()) {\n <mfp-filter-tabs\n [tabs]=\"filterTabs()\"\n (tabChanged)=\"onFilterTabChanged($event)\"\n />\n }\n\n <div class=\"card__body\">\n @if (tableConfig(); as config) {\n <mfp-declarative-table\n [columns]=\"effectiveColumns()\"\n [currentPage]=\"config.currentPage ?? 1\"\n [hasMore]=\"config.hasMore ?? false\"\n [height]=\"config.height\"\n [loadMode]=\"config.loadMode ?? 'button'\"\n [loadMoreButtonText]=\"config.loadMoreButtonText ?? 'Load More'\"\n [paginationLimit]=\"config.paginationLimit ?? 5\"\n [resources]=\"resources()\"\n [totalItemsCount]=\"config.totalItemsCount\"\n (buttonClick)=\"onButtonClick($event)\"\n (loadMoreResources)=\"loadMoreResources.emit()\"\n (pageChange)=\"pageChange.emit($event)\"\n (paginationLimitChanged)=\"paginationLimitChanged.emit($event)\"\n (tableRowClicked)=\"tableRowClicked.emit($event)\"\n />\n }\n </div>\n</div>\n\n@if (createDialogOpen()) {\n @let config = createFormConfig();\n <ui5-dialog\n data-testid=\"generic-table-card-create-dialog\"\n [accessibleName]=\"config?.title ?? 'Create'\"\n [open]=\"true\"\n (ui5BeforeClose)=\"createDialogOpen.set(false)\"\n >\n <div class=\"dialog__header\" slot=\"header\">\n <ui5-title level=\"H5\">{{ config?.title ?? 'Create' }}</ui5-title>\n </div>\n <div class=\"dialog__body\">\n <mfp-declarative-form\n #createForm\n [fieldErrors]=\"createFormState().fieldErrors ?? {}\"\n [fields]=\"resolvedCreateFields()\"\n (fieldChange)=\"onCreateFieldChange($event)\"\n (formSubmit)=\"onCreateSubmit($event)\"\n />\n </div>\n <div class=\"dialog__footer\" slot=\"footer\">\n <ui5-button\n data-testid=\"generic-table-card-create-confirm\"\n design=\"Emphasized\"\n [disabled]=\"hasErrors(createFormState())\"\n (click)=\"createForm.submit()\"\n >\n {{ config?.confirmLabel ?? 'Save' }}\n </ui5-button>\n <ui5-button\n data-testid=\"generic-table-card-create-cancel\"\n design=\"Transparent\"\n (click)=\"closeCreateDialog()\"\n >\n {{ config?.cancelLabel ?? 'Cancel' }}\n </ui5-button>\n </div>\n </ui5-dialog>\n}\n\n@if (editDialogOpen()) {\n @let config = editFormConfig();\n <ui5-dialog\n data-testid=\"generic-table-card-edit-dialog\"\n [accessibleName]=\"config?.title ?? 'Edit'\"\n [open]=\"true\"\n (ui5BeforeClose)=\"editDialogOpen.set(false)\"\n >\n <div class=\"dialog__header\" slot=\"header\">\n <ui5-title level=\"H5\">{{ config?.title ?? 'Edit' }}</ui5-title>\n </div>\n <div class=\"dialog__body\">\n <mfp-declarative-form\n #editForm\n [fieldErrors]=\"editFormState().fieldErrors ?? {}\"\n [fields]=\"resolvedEditFields()\"\n [initialValues]=\"editInitialValue()\"\n (fieldChange)=\"onEditFieldChange($event)\"\n (formSubmit)=\"onEditSubmit($event)\"\n />\n </div>\n <div class=\"dialog__footer\" slot=\"footer\">\n <ui5-button\n data-testid=\"generic-table-card-edit-confirm\"\n design=\"Emphasized\"\n [disabled]=\"hasErrors(editFormState())\"\n (click)=\"editForm.submit()\"\n >\n {{ config?.confirmLabel ?? 'Edit' }}\n </ui5-button>\n <ui5-button\n data-testid=\"generic-table-card-edit-cancel\"\n design=\"Transparent\"\n (click)=\"closeEditDialog()\"\n >\n {{ config?.cancelLabel ?? 'Cancel' }}\n </ui5-button>\n </div>\n </ui5-dialog>\n}\n\n@if (deleteConfirmationConfig(); as config) {\n <ui5-dialog\n data-testid=\"generic-table-card-delete-dialog\"\n [accessibleName]=\"config.title ?? 'Confirm Delete'\"\n [open]=\"deleteDialogOpen()\"\n (ui5BeforeClose)=\"deleteDialogOpen.set(false)\"\n >\n <div class=\"dialog__header\" slot=\"header\">\n <ui5-title level=\"H5\">{{ config.title ?? 'Confirm Delete' }}</ui5-title>\n </div>\n @if (config.message) {\n <div class=\"dialog__body\">\n <p class=\"dialog__message\">{{ config.message }}</p>\n </div>\n }\n <div class=\"dialog__footer\" slot=\"footer\">\n <ui5-button\n data-testid=\"generic-table-card-delete-confirm\"\n design=\"Negative\"\n (click)=\"onDeleteSubmit()\"\n >\n {{ config.confirmLabel ?? 'Delete' }}\n </ui5-button>\n <ui5-button\n data-testid=\"generic-table-card-delete-cancel\"\n design=\"Transparent\"\n (click)=\"closeDeleteDialog()\"\n >\n {{ config.cancelLabel ?? 'Cancel' }}\n </ui5-button>\n </div>\n </ui5-dialog>\n}\n", styles: [":host{display:block}.card{display:flex;flex-direction:column;border:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);border-radius:16px;background:var(--sapGroup_TitleBackground, #fff)}.card__header{display:flex;align-items:center;justify-content:space-between;min-height:3rem;padding:0 1rem}.card__title{color:var(--sapTile_TitleTextColor);text-overflow:ellipsis;font-family:var(--Font-Family-sapFontFamily, 72);font-size:var(--Font-Size-sapFontHeader6Size, 16px);font-style:normal;font-weight:700;line-height:normal;display:flex;align-items:center}.card__actions{display:flex;align-items:center;gap:.5rem}.card__info-icon{color:var(--sapButton_IconColor, #0070f2);margin-left:.5rem}.card__search-icon{cursor:pointer}.card__create-btn{min-width:auto;color:var(--sapButton_IconColor, #0070f2)}.card__body{flex:1;overflow:auto}.dialog__header{display:flex;align-items:flex-start;padding:.75rem 1rem}.dialog__body{margin:-1rem;min-width:320px;padding:1rem}.dialog__message{padding:1rem;margin:0;font-size:.875rem;max-width:320px}.dialog__footer{display:flex;justify-content:space-between;align-items:center;gap:.5rem;padding:.5rem 1rem;margin:0 -1rem;width:100%}\n"] }]
1128
1130
  }], ctorParameters: () => [], propDecorators: { resources: [{ type: i0.Input, args: [{ isSignal: true, alias: "resources", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], createFormState: [{ type: i0.Input, args: [{ isSignal: true, alias: "createFormState", required: false }] }], editFormState: [{ type: i0.Input, args: [{ isSignal: true, alias: "editFormState", required: false }] }], actionButtonClick: [{ type: i0.Output, args: ["actionButtonClick"] }], tableRowClicked: [{ type: i0.Output, args: ["tableRowClicked"] }], loadMoreResources: [{ type: i0.Output, args: ["loadMoreResources"] }], paginationLimitChanged: [{ type: i0.Output, args: ["paginationLimitChanged"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], searchChanged: [{ type: i0.Output, args: ["searchChanged"] }], createFieldChange: [{ type: i0.Output, args: ["createFieldChange"] }], editFieldChange: [{ type: i0.Output, args: ["editFieldChange"] }], createSubmit: [{ type: i0.Output, args: ["createSubmit"] }], editSubmit: [{ type: i0.Output, args: ["editSubmit"] }], deleteSubmit: [{ type: i0.Output, args: ["deleteSubmit"] }], filterTabChanged: [{ type: i0.Output, args: ["filterTabChanged"] }] } });
1129
1131
 
1132
+ /** Default engine breakpoints: 14/12/8/1 columns (matches main). */
1133
+ const DASHBOARD_BREAKPOINTS = [
1134
+ { w: 4000, c: 14, layout: 'compact' },
1135
+ { w: 1439, c: 12, layout: 'compact' },
1136
+ { w: 1023, c: 8, layout: 'compact' },
1137
+ { w: 599, c: 1, layout: 'list' },
1138
+ ];
1139
+ /** zFlow engine breakpoints: 4/4/4/1 columns. */
1140
+ const ZFLOW_DASHBOARD_BREAKPOINTS = [
1141
+ { w: 4000, c: 4, layout: 'compact' },
1142
+ { w: 1439, c: 4, layout: 'compact' },
1143
+ { w: 1023, c: 4, layout: 'compact' },
1144
+ { w: 599, c: 1, layout: 'list' },
1145
+ ];
1146
+ const XL_PAGE = 1440;
1147
+
1148
+ const COMPACT_BREAKPOINT = 726;
1149
+ const CELL_HEIGHT = 10;
1150
+ const DASHBOARD_CARD_DRAG_ORIGIN_CLASS = 'mfp-dashboard-card-drag-origin';
1151
+ const DASHBOARD_CARD_DRAG_ORIGIN_SELECTOR = `.${DASHBOARD_CARD_DRAG_ORIGIN_CLASS}`;
1152
+
1130
1153
  var unsavedChanges$1 = "Nicht gespeicherte Änderungen";
1131
1154
  var editCards$1 = "Karten bearbeiten";
1132
1155
  var editView$1 = "Ansicht bearbeiten";
@@ -1357,6 +1380,8 @@ class DashboardCard {
1357
1380
  removeCard = output();
1358
1381
  i18n = inject(DashboardI18nService);
1359
1382
  i18nKeys = DASHBOARD_I18N_KEYS;
1383
+ componentHostClasses = `component-host ${DASHBOARD_CARD_DRAG_ORIGIN_CLASS}`;
1384
+ cardBodyClasses = `card__body ${DASHBOARD_CARD_DRAG_ORIGIN_CLASS}`;
1360
1385
  gridColumn = computed(() => {
1361
1386
  const width = this.card().w ?? 12;
1362
1387
  return this.createGridTrack(this.card().x, width);
@@ -1406,27 +1431,16 @@ class DashboardCard {
1406
1431
  return `${start + 1} / span ${span}`;
1407
1432
  }
1408
1433
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DashboardCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1409
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DashboardCard, isStandalone: true, selector: "mfp-dashboard-card", inputs: { card: { classPropertyName: "card", publicName: "card", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removeCard: "removeCard" }, host: { properties: { "style.grid-column": "gridColumn()", "style.grid-row": "gridRow()" } }, viewQueries: [{ propertyName: "host", first: true, predicate: ["elementHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (card().component) {\n <div class=\"component-card\" [attr.data-testid]=\"'dashboard-card-' + card().id\" [class.component-card--editing]=\"editMode()\">\n @if (editMode()) {\n <div class=\"remove-wrapper\">\n <ui5-button\n class=\"card__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-card-' + card().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_CARD) +\n ': ' +\n (card().label || card().component)\n \"\n (click)=\"removeCard.emit()\"\n />\n </div>\n <ui5-icon\n aria-hidden=\"true\"\n class=\"card__resize-indicator\"\n name=\"resize-corner\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.RESIZABLE)\"\n />\n }\n <div\n class=\"component-host\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <div #elementHost></div>\n </div>\n </div>\n} @else {\n <div class=\"card\" [attr.data-testid]=\"'dashboard-card-' + card().id\">\n <div\n class=\"card__body\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: [":host{display:block;min-width:0;min-height:0;overflow:visible}.card__remove{position:absolute;top:0;right:-.5rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.remove-wrapper{position:sticky;height:.5rem;top:0;right:0;z-index:10}.component-card{position:relative;height:100%;overflow:visible;isolation:isolate;padding-inline-start:var(--mfp_cardContainerPadding, 10px);padding-inline-end:var(--mfp_cardContainerPadding, 10px)}.component-card--editing{cursor:grab}.component-card--editing:hover{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}.component-card--editing:hover .card__resize-indicator{opacity:1}:host-context(.ui-draggable-dragging) .component-card--editing{cursor:grabbing!important}:host-context(.ui-draggable-dragging) .component-card--editing{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}:host-context(.ui-draggable-dragging) .component-card--editing .card__resize-indicator{opacity:1}.component-host{position:relative;height:100%}.card__resize-indicator{position:absolute;right:calc(var(--mfp_cardContainerPadding, 10px) + 4px);bottom:4px;width:1rem;height:1rem;pointer-events:none;opacity:0;transition:opacity .12s ease-out;color:var(--sapHighlightColor, #0070f2);z-index:9}.card{position:relative;display:flex;flex-direction:column;height:100%;border:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);border-radius:.5rem;background:var(--sapBackgroundColor, #fff);overflow:visible}.card__header{padding:.75rem 1rem;font-weight:600;border-bottom:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);background:var(--sapGroup_TitleBackground, #f5f5f5)}.card__body{flex:1;padding:1rem;overflow:auto}\n"], dependencies: [{ kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }, { kind: "component", type: Icon, selector: "ui5-icon, [ui5-icon]", inputs: ["design", "name", "accessibleName", "showTooltip", "mode"], outputs: ["ui5Click"], exportAs: ["ui5Icon"] }] });
1434
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DashboardCard, isStandalone: true, selector: "mfp-dashboard-card", inputs: { card: { classPropertyName: "card", publicName: "card", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removeCard: "removeCard" }, host: { properties: { "style.grid-column": "gridColumn()", "style.grid-row": "gridRow()" } }, viewQueries: [{ propertyName: "host", first: true, predicate: ["elementHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (card().component) {\n <div class=\"component-card\" [attr.data-testid]=\"'dashboard-card-' + card().id\" [class.component-card--editing]=\"editMode()\">\n @if (editMode()) {\n <div class=\"remove-wrapper\">\n <ui5-button\n class=\"card__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-card-' + card().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_CARD) +\n ': ' +\n (card().label || card().component)\n \"\n (click)=\"removeCard.emit()\"\n />\n </div>\n <ui5-icon\n aria-hidden=\"true\"\n class=\"card__resize-indicator\"\n name=\"resize-corner\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.RESIZABLE)\"\n />\n }\n <div\n [class]=\"componentHostClasses\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <div #elementHost></div>\n </div>\n </div>\n} @else {\n <div class=\"card\" [attr.data-testid]=\"'dashboard-card-' + card().id\">\n <div\n [class]=\"cardBodyClasses\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: [":host{display:block;min-width:0;min-height:0;overflow:visible}.card__remove{position:absolute;top:0;right:-.5rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.remove-wrapper{position:sticky;height:.5rem;top:0;right:0;z-index:10}.component-card{position:relative;height:100%;overflow:visible;isolation:isolate;padding-inline-start:var(--mfp_cardContainerPadding, 10px);padding-inline-end:var(--mfp_cardContainerPadding, 10px)}.component-card--editing{cursor:grab}.component-card--editing:hover{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}.component-card--editing:hover .card__resize-indicator{opacity:1}:host-context(.ui-draggable-dragging) .component-card--editing{cursor:grabbing!important}:host-context(.ui-draggable-dragging) .component-card--editing{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}:host-context(.ui-draggable-dragging) .component-card--editing .card__resize-indicator{opacity:1}:host-context(.zflow-dragging) .remove-wrapper{opacity:0;pointer-events:none}.component-host{position:relative;height:100%}.card__resize-indicator{position:absolute;right:calc(var(--mfp_cardContainerPadding, 10px) + 4px);bottom:4px;width:1rem;height:1rem;pointer-events:none;opacity:0;transition:opacity .12s ease-out;color:var(--sapHighlightColor, #0070f2);z-index:9}.card{position:relative;display:flex;flex-direction:column;height:100%;border:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);border-radius:.5rem;background:var(--sapBackgroundColor, #fff);overflow:visible}.card__header{padding:.75rem 1rem;font-weight:600;border-bottom:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);background:var(--sapGroup_TitleBackground, #f5f5f5)}.card__body{flex:1;padding:1rem;overflow:auto}\n"], dependencies: [{ kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }, { kind: "component", type: Icon, selector: "ui5-icon, [ui5-icon]", inputs: ["design", "name", "accessibleName", "showTooltip", "mode"], outputs: ["ui5Click"], exportAs: ["ui5Icon"] }] });
1410
1435
  }
1411
1436
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DashboardCard, decorators: [{
1412
1437
  type: Component,
1413
1438
  args: [{ selector: 'mfp-dashboard-card', imports: [Button, Icon], encapsulation: ViewEncapsulation.Emulated, host: {
1414
1439
  '[style.grid-column]': 'gridColumn()',
1415
1440
  '[style.grid-row]': 'gridRow()',
1416
- }, template: "@if (card().component) {\n <div class=\"component-card\" [attr.data-testid]=\"'dashboard-card-' + card().id\" [class.component-card--editing]=\"editMode()\">\n @if (editMode()) {\n <div class=\"remove-wrapper\">\n <ui5-button\n class=\"card__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-card-' + card().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_CARD) +\n ': ' +\n (card().label || card().component)\n \"\n (click)=\"removeCard.emit()\"\n />\n </div>\n <ui5-icon\n aria-hidden=\"true\"\n class=\"card__resize-indicator\"\n name=\"resize-corner\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.RESIZABLE)\"\n />\n }\n <div\n class=\"component-host\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <div #elementHost></div>\n </div>\n </div>\n} @else {\n <div class=\"card\" [attr.data-testid]=\"'dashboard-card-' + card().id\">\n <div\n class=\"card__body\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: [":host{display:block;min-width:0;min-height:0;overflow:visible}.card__remove{position:absolute;top:0;right:-.5rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.remove-wrapper{position:sticky;height:.5rem;top:0;right:0;z-index:10}.component-card{position:relative;height:100%;overflow:visible;isolation:isolate;padding-inline-start:var(--mfp_cardContainerPadding, 10px);padding-inline-end:var(--mfp_cardContainerPadding, 10px)}.component-card--editing{cursor:grab}.component-card--editing:hover{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}.component-card--editing:hover .card__resize-indicator{opacity:1}:host-context(.ui-draggable-dragging) .component-card--editing{cursor:grabbing!important}:host-context(.ui-draggable-dragging) .component-card--editing{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}:host-context(.ui-draggable-dragging) .component-card--editing .card__resize-indicator{opacity:1}.component-host{position:relative;height:100%}.card__resize-indicator{position:absolute;right:calc(var(--mfp_cardContainerPadding, 10px) + 4px);bottom:4px;width:1rem;height:1rem;pointer-events:none;opacity:0;transition:opacity .12s ease-out;color:var(--sapHighlightColor, #0070f2);z-index:9}.card{position:relative;display:flex;flex-direction:column;height:100%;border:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);border-radius:.5rem;background:var(--sapBackgroundColor, #fff);overflow:visible}.card__header{padding:.75rem 1rem;font-weight:600;border-bottom:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);background:var(--sapGroup_TitleBackground, #f5f5f5)}.card__body{flex:1;padding:1rem;overflow:auto}\n"] }]
1441
+ }, template: "@if (card().component) {\n <div class=\"component-card\" [attr.data-testid]=\"'dashboard-card-' + card().id\" [class.component-card--editing]=\"editMode()\">\n @if (editMode()) {\n <div class=\"remove-wrapper\">\n <ui5-button\n class=\"card__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-card-' + card().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_CARD) +\n ': ' +\n (card().label || card().component)\n \"\n (click)=\"removeCard.emit()\"\n />\n </div>\n <ui5-icon\n aria-hidden=\"true\"\n class=\"card__resize-indicator\"\n name=\"resize-corner\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.RESIZABLE)\"\n />\n }\n <div\n [class]=\"componentHostClasses\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <div #elementHost></div>\n </div>\n </div>\n} @else {\n <div class=\"card\" [attr.data-testid]=\"'dashboard-card-' + card().id\">\n <div\n [class]=\"cardBodyClasses\"\n [style.pointer-events]=\"editMode() ? 'none' : 'auto'\"\n >\n <ng-content />\n </div>\n </div>\n}\n", styles: [":host{display:block;min-width:0;min-height:0;overflow:visible}.card__remove{position:absolute;top:0;right:-.5rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.remove-wrapper{position:sticky;height:.5rem;top:0;right:0;z-index:10}.component-card{position:relative;height:100%;overflow:visible;isolation:isolate;padding-inline-start:var(--mfp_cardContainerPadding, 10px);padding-inline-end:var(--mfp_cardContainerPadding, 10px)}.component-card--editing{cursor:grab}.component-card--editing:hover{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}.component-card--editing:hover .card__resize-indicator{opacity:1}:host-context(.ui-draggable-dragging) .component-card--editing{cursor:grabbing!important}:host-context(.ui-draggable-dragging) .component-card--editing{--sapTile_BorderColor: var(--sapHighlightColor, #0070f2);--sapGroup_ContentBorderColor: var(--sapHighlightColor, #0070f2)}:host-context(.ui-draggable-dragging) .component-card--editing .card__resize-indicator{opacity:1}:host-context(.zflow-dragging) .remove-wrapper{opacity:0;pointer-events:none}.component-host{position:relative;height:100%}.card__resize-indicator{position:absolute;right:calc(var(--mfp_cardContainerPadding, 10px) + 4px);bottom:4px;width:1rem;height:1rem;pointer-events:none;opacity:0;transition:opacity .12s ease-out;color:var(--sapHighlightColor, #0070f2);z-index:9}.card{position:relative;display:flex;flex-direction:column;height:100%;border:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);border-radius:.5rem;background:var(--sapBackgroundColor, #fff);overflow:visible}.card__header{padding:.75rem 1rem;font-weight:600;border-bottom:1px solid var(--sapGroup_ContentBorderColor, #d9d9d9);background:var(--sapGroup_TitleBackground, #f5f5f5)}.card__body{flex:1;padding:1rem;overflow:auto}\n"] }]
1417
1442
  }], ctorParameters: () => [], propDecorators: { card: [{ type: i0.Input, args: [{ isSignal: true, alias: "card", required: true }] }], editMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editMode", required: false }] }], removeCard: [{ type: i0.Output, args: ["removeCard"] }], host: [{ type: i0.ViewChild, args: ['elementHost', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
1418
1443
 
1419
- /** Single source of truth for grid + section breakpoints (TypeScript half). */
1420
- const DASHBOARD_BREAKPOINTS = [
1421
- { w: 4000, c: 14, layout: 'compact' },
1422
- { w: 1439, c: 12, layout: 'compact' },
1423
- { w: 1023, c: 8, layout: 'compact' },
1424
- { w: 599, c: 1, layout: 'list' },
1425
- ];
1426
-
1427
- const COMPACT_BREAKPOINT = 726;
1428
- const CELL_HEIGHT = 10;
1429
-
1430
1444
  /**
1431
1445
  * Confirmation popup shown when the user tries to abandon edit mode while
1432
1446
  * there are unsaved dashboard changes. Emits `confirm` when the user accepts
@@ -1549,7 +1563,7 @@ class DashboardSection {
1549
1563
  removeSection = output();
1550
1564
  removeCard = output();
1551
1565
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DashboardSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
1552
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DashboardSection, isStandalone: true, selector: "mfp-dashboard-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removeSection: "removeSection", removeCard: "removeCard" }, host: { properties: { "style.grid-column": "section().w === undefined || section().w === 12 ? \"1 / -1\" : \"span \" + section().w" } }, ngImport: i0, template: "<div\n class=\"section\"\n [attr.data-testid]=\"'dashboard-section-' + section().id\"\n [class.section--edit]=\"editMode() && section().editable !== false\"\n>\n @if (editMode() && section().editable !== false) {\n <ui5-button\n class=\"section__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-section-' + section().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_SECTION) +\n ': ' +\n (section().title || section().id)\n \"\n (click)=\"removeSection.emit()\"\n />\n }\n @if (section().title) {\n <div class=\"section__header\">\n <span class=\"section__title\" [attr.data-testid]=\"'dashboard-section-' + section().id + '-title'\">{{ section().title }}</span>\n </div>\n }\n <div class=\"section__grid\" [style.--cols]=\"columns() ?? null\">\n @for (card of cards(); track card.id) {\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode() && section().editable !== false\"\n (removeCard)=\"removeCard.emit($any(card.id))\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;min-width:0}.section{position:relative;display:flex;flex-direction:column;border:1px solid transparent;border-top:none;border-radius:0 0 .5rem .5rem;padding-top:1.25rem}.section--edit{border-color:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__remove{position:absolute;top:-.75rem;right:-.75rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.section__header{position:absolute;top:0;left:0;right:0;transform:translateY(-50%);display:flex;align-items:center;pointer-events:none}.section__header:before,.section__header:after{content:\"\";flex:1;height:1px;background:transparent}.section__header:before{max-width:.75rem;flex:0 0 .75rem}.section--edit .section__header:before,.section--edit .section__header:after{background:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__title{font-size:1rem;font-weight:600;color:var(--sapTextColor, #fff);padding:0 .5rem;white-space:nowrap;pointer-events:all}.section__grid{display:grid;grid-auto-rows:var(--row-height, 10px);column-gap:var(--column-gap, 0px);row-gap:var(--row-gap, 0px);grid-template-columns:repeat(var(--cols, 14),1fr)}@container mfp-dashboard (max-width: 599px){.section__grid{grid-template-columns:repeat(var(--cols, 1),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.section__grid{grid-template-columns:repeat(var(--cols, 8),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.section__grid{grid-template-columns:repeat(var(--cols, 12),1fr)}}\n"], dependencies: [{ kind: "component", type: DashboardCard, selector: "mfp-dashboard-card", inputs: ["card", "editMode"], outputs: ["removeCard"] }, { kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }] });
1566
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DashboardSection, isStandalone: true, selector: "mfp-dashboard-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removeSection: "removeSection", removeCard: "removeCard" }, host: { properties: { "style.grid-column": "section().w === undefined || section().w === 12 ? \"1 / -1\" : \"span \" + section().w" } }, ngImport: i0, template: "<div\n class=\"section\"\n [attr.data-testid]=\"'dashboard-section-' + section().id\"\n [class.section--edit]=\"editMode() && section().editable !== false\"\n>\n @if (editMode() && section().editable !== false) {\n <ui5-button\n class=\"section__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-section-' + section().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_SECTION) +\n ': ' +\n (section().title || section().id)\n \"\n (click)=\"removeSection.emit()\"\n />\n }\n @if (section().title) {\n <div class=\"section__header\">\n <span class=\"section__title\" [attr.data-testid]=\"'dashboard-section-' + section().id + '-title'\">{{ section().title }}</span>\n </div>\n }\n <div class=\"section__grid\" [style.--cols]=\"columns() ?? null\">\n @for (card of cards(); track card.id) {\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode() && section().editable !== false\"\n (removeCard)=\"removeCard.emit($any(card.id))\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;min-width:0}.section{position:relative;display:flex;flex-direction:column;border:1px solid transparent;border-top:none;border-radius:0 0 .5rem .5rem;padding-top:1.25rem}.section--edit{border-color:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__remove{position:absolute;top:-.75rem;right:-.75rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.section__header{position:absolute;top:0;left:0;right:0;transform:translateY(-50%);display:flex;align-items:center;pointer-events:none}.section__header:before,.section__header:after{content:\"\";flex:1;height:1px;background:transparent}.section__header:before{max-width:.75rem;flex:0 0 .75rem}.section--edit .section__header:before,.section--edit .section__header:after{background:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__title{font-size:1rem;font-weight:600;color:var(--sapTextColor, #fff);padding:0 .5rem;white-space:nowrap;pointer-events:all}.section__grid{display:grid;grid-auto-rows:var(--row-height, 10px);column-gap:var(--column-gap, 0px);row-gap:var(--row-gap, 0px);grid-template-columns:repeat(var(--cols, var(--dashboard-cols-xl, 14)),1fr)}@container mfp-dashboard (max-width: 599px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-sm, 1)),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-md, 8)),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-lg, 12)),1fr)}}\n"], dependencies: [{ kind: "component", type: DashboardCard, selector: "mfp-dashboard-card", inputs: ["card", "editMode"], outputs: ["removeCard"] }, { kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }] });
1553
1567
  }
1554
1568
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DashboardSection, decorators: [{
1555
1569
  type: Component,
@@ -1565,7 +1579,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
1565
1579
  // cover 12 of 14 columns, leaving a dead 2-col gutter on the right and
1566
1580
  // squeezing the cards inside it relative to the outer grid's units.
1567
1581
  '[style.grid-column]': 'section().w === undefined || section().w === 12 ? "1 / -1" : "span " + section().w',
1568
- }, template: "<div\n class=\"section\"\n [attr.data-testid]=\"'dashboard-section-' + section().id\"\n [class.section--edit]=\"editMode() && section().editable !== false\"\n>\n @if (editMode() && section().editable !== false) {\n <ui5-button\n class=\"section__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-section-' + section().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_SECTION) +\n ': ' +\n (section().title || section().id)\n \"\n (click)=\"removeSection.emit()\"\n />\n }\n @if (section().title) {\n <div class=\"section__header\">\n <span class=\"section__title\" [attr.data-testid]=\"'dashboard-section-' + section().id + '-title'\">{{ section().title }}</span>\n </div>\n }\n <div class=\"section__grid\" [style.--cols]=\"columns() ?? null\">\n @for (card of cards(); track card.id) {\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode() && section().editable !== false\"\n (removeCard)=\"removeCard.emit($any(card.id))\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;min-width:0}.section{position:relative;display:flex;flex-direction:column;border:1px solid transparent;border-top:none;border-radius:0 0 .5rem .5rem;padding-top:1.25rem}.section--edit{border-color:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__remove{position:absolute;top:-.75rem;right:-.75rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.section__header{position:absolute;top:0;left:0;right:0;transform:translateY(-50%);display:flex;align-items:center;pointer-events:none}.section__header:before,.section__header:after{content:\"\";flex:1;height:1px;background:transparent}.section__header:before{max-width:.75rem;flex:0 0 .75rem}.section--edit .section__header:before,.section--edit .section__header:after{background:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__title{font-size:1rem;font-weight:600;color:var(--sapTextColor, #fff);padding:0 .5rem;white-space:nowrap;pointer-events:all}.section__grid{display:grid;grid-auto-rows:var(--row-height, 10px);column-gap:var(--column-gap, 0px);row-gap:var(--row-gap, 0px);grid-template-columns:repeat(var(--cols, 14),1fr)}@container mfp-dashboard (max-width: 599px){.section__grid{grid-template-columns:repeat(var(--cols, 1),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.section__grid{grid-template-columns:repeat(var(--cols, 8),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.section__grid{grid-template-columns:repeat(var(--cols, 12),1fr)}}\n"] }]
1582
+ }, template: "<div\n class=\"section\"\n [attr.data-testid]=\"'dashboard-section-' + section().id\"\n [class.section--edit]=\"editMode() && section().editable !== false\"\n>\n @if (editMode() && section().editable !== false) {\n <ui5-button\n class=\"section__remove\"\n design=\"Default\"\n icon=\"decline\"\n [attr.data-testid]=\"'dashboard-section-' + section().id + '-remove'\"\n [accessibleName]=\"\n i18n.getTranslation(i18nKeys.REMOVE_SECTION) +\n ': ' +\n (section().title || section().id)\n \"\n (click)=\"removeSection.emit()\"\n />\n }\n @if (section().title) {\n <div class=\"section__header\">\n <span class=\"section__title\" [attr.data-testid]=\"'dashboard-section-' + section().id + '-title'\">{{ section().title }}</span>\n </div>\n }\n <div class=\"section__grid\" [style.--cols]=\"columns() ?? null\">\n @for (card of cards(); track card.id) {\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode() && section().editable !== false\"\n (removeCard)=\"removeCard.emit($any(card.id))\"\n />\n }\n </div>\n</div>\n", styles: [":host{display:block;min-width:0}.section{position:relative;display:flex;flex-direction:column;border:1px solid transparent;border-top:none;border-radius:0 0 .5rem .5rem;padding-top:1.25rem}.section--edit{border-color:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__remove{position:absolute;top:-.75rem;right:-.75rem;z-index:10;border-radius:50%!important;width:1.25rem!important;height:1.25rem!important;min-width:unset!important;padding:0!important;font-size:.625rem!important}.section__header{position:absolute;top:0;left:0;right:0;transform:translateY(-50%);display:flex;align-items:center;pointer-events:none}.section__header:before,.section__header:after{content:\"\";flex:1;height:1px;background:transparent}.section__header:before{max-width:.75rem;flex:0 0 .75rem}.section--edit .section__header:before,.section--edit .section__header:after{background:var(--sapGroup_ContentBorderColor, #d9d9d9)}.section__title{font-size:1rem;font-weight:600;color:var(--sapTextColor, #fff);padding:0 .5rem;white-space:nowrap;pointer-events:all}.section__grid{display:grid;grid-auto-rows:var(--row-height, 10px);column-gap:var(--column-gap, 0px);row-gap:var(--row-gap, 0px);grid-template-columns:repeat(var(--cols, var(--dashboard-cols-xl, 14)),1fr)}@container mfp-dashboard (max-width: 599px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-sm, 1)),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-md, 8)),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.section__grid{grid-template-columns:repeat(var(--cols, var(--dashboard-cols-lg, 12)),1fr)}}\n"] }]
1569
1583
  }], propDecorators: { section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], editMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editMode", required: false }] }], removeSection: [{ type: i0.Output, args: ["removeSection"] }], removeCard: [{ type: i0.Output, args: ["removeCard"] }] } });
1570
1584
 
1571
1585
  /**
@@ -1593,11 +1607,398 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
1593
1607
  args: [{ selector: 'mfp-unsaved-changes-dialog', imports: [Button, Dialog, Title], encapsulation: ViewEncapsulation.ShadowDom, template: "<ui5-dialog data-testid=\"dashboard-unsaved-changes-dialog\" state=\"Critical\" [open]=\"open()\" (ui5BeforeClose)=\"cancelled.emit()\">\n <div class=\"unsaved-changes-dialog__header\" slot=\"header\">\n <ui5-title level=\"H5\">{{ i18n.getTranslation(i18nKeys.UNSAVED_CHANGES) }}</ui5-title>\n </div>\n <div class=\"unsaved-changes-dialog__body\">\n {{ i18n.getTranslation(i18nKeys.UNSAVED_NAV_BODY) }}\n </div>\n <div class=\"unsaved-changes-dialog__footer\" slot=\"footer\">\n <ui5-button data-testid=\"dashboard-unsaved-changes-save-btn\" design=\"Emphasized\" (click)=\"save.emit()\">{{ i18n.getTranslation(i18nKeys.SAVE) }}</ui5-button>\n <ui5-button data-testid=\"dashboard-unsaved-changes-discard-btn\" design=\"Transparent\" (click)=\"discard.emit()\">{{ i18n.getTranslation(i18nKeys.DISCARD) }}</ui5-button>\n <ui5-button data-testid=\"dashboard-unsaved-changes-cancel-btn\" design=\"Transparent\" (click)=\"cancelled.emit()\">{{ i18n.getTranslation(i18nKeys.CANCEL) }}</ui5-button>\n </div>\n</ui5-dialog>\n", styles: [":host{display:contents}.unsaved-changes-dialog__header{display:flex;align-items:center;width:100%;padding:.75rem 0}.unsaved-changes-dialog__body{padding:0 0 1rem;min-width:360px;max-width:32rem}.unsaved-changes-dialog__footer{display:flex;justify-content:flex-end;align-items:center;width:100%;gap:.5rem}\n"] }]
1594
1608
  }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], discard: [{ type: i0.Output, args: ["discard"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
1595
1609
 
1610
+ function getAllowedResizeWidths(maxWidth, columnCount, minWidth = 1, effectiveMax = columnCount) {
1611
+ return [1, 2, maxWidth]
1612
+ .map((w) => Math.min(Math.max(w, minWidth), columnCount))
1613
+ .filter((w, i, list) => list.indexOf(w) === i && w <= effectiveMax)
1614
+ .sort((a, b) => a - b);
1615
+ }
1616
+ function resolveResizeWidthStep(rawWidth, maxWidth, columnCount, minWidth = 1, effectiveMax = columnCount) {
1617
+ const allowed = getAllowedResizeWidths(maxWidth, columnCount, minWidth, effectiveMax);
1618
+ if (!allowed.length) {
1619
+ return effectiveMax;
1620
+ }
1621
+ return allowed.reduce((best, candidate) => {
1622
+ return Math.abs(candidate - rawWidth) <= Math.abs(best - rawWidth)
1623
+ ? candidate
1624
+ : best;
1625
+ }, allowed[0]);
1626
+ }
1627
+
1628
+ function hasZFlowOrder(nodes) {
1629
+ return nodes.some((n) => n.zFlowOrder !== undefined);
1630
+ }
1631
+ function syncNodeOrderFromLayout(nodes) {
1632
+ const sorted = [...nodes].sort(compareNodesByLayoutPosition);
1633
+ sorted.forEach((n, i) => {
1634
+ n.zFlowOrder = i;
1635
+ });
1636
+ }
1637
+ function seedNodeOrder(nodes) {
1638
+ if (hasZFlowOrder(nodes))
1639
+ return;
1640
+ syncNodeOrderFromLayout(nodes);
1641
+ }
1642
+ function sortNodesByZFlowOrder(nodes) {
1643
+ return [...nodes].sort((a, b) => {
1644
+ if (a.zFlowOrder !== undefined && b.zFlowOrder !== undefined) {
1645
+ return a.zFlowOrder - b.zFlowOrder;
1646
+ }
1647
+ if (a.zFlowOrder !== undefined)
1648
+ return -1;
1649
+ if (b.zFlowOrder !== undefined)
1650
+ return 1;
1651
+ const ay = a.y ?? 0;
1652
+ const by = b.y ?? 0;
1653
+ if (ay !== by)
1654
+ return ay - by;
1655
+ return (a.x ?? 0) - (b.x ?? 0);
1656
+ });
1657
+ }
1658
+ function compareNodesByLayoutPosition(a, b) {
1659
+ const ay = a.y ?? 0;
1660
+ const by = b.y ?? 0;
1661
+ if (ay !== by)
1662
+ return ay - by;
1663
+ return (a.x ?? 0) - (b.x ?? 0);
1664
+ }
1665
+ const PROJECTED_SLOT_OVERLAP_THRESHOLD = 0.5;
1666
+ function getZFlowRowHeight(nodes) {
1667
+ return Math.max(...nodes.map((n) => n.h ?? 1), 1);
1668
+ }
1669
+ function projectZFlowLayout(nodes, columnCount) {
1670
+ const result = [];
1671
+ let curX = 0;
1672
+ let curRow = 0;
1673
+ const rowHeight = getZFlowRowHeight(nodes);
1674
+ for (const node of nodes) {
1675
+ if (!node.id)
1676
+ continue;
1677
+ const w = Math.min(node.w ?? 1, columnCount);
1678
+ const h = node.h ?? rowHeight;
1679
+ if (curX > 0 && curX + w > columnCount) {
1680
+ curX = 0;
1681
+ curRow++;
1682
+ }
1683
+ result.push({
1684
+ id: node.id,
1685
+ row: curRow,
1686
+ x: curX,
1687
+ y: curRow * rowHeight,
1688
+ w,
1689
+ h,
1690
+ });
1691
+ curX += w;
1692
+ }
1693
+ return result;
1694
+ }
1695
+ function resolveDropRowFromRect(dragRectTopPx, dragRectHeightPx, rowHeightPx, rowCount, previousRow) {
1696
+ if (rowHeightPx <= 0 || rowCount <= 0)
1697
+ return previousRow;
1698
+ const clampedPreviousRow = Math.max(0, Math.min(previousRow, rowCount - 1));
1699
+ const dragBottomPx = dragRectTopPx + dragRectHeightPx;
1700
+ let bestRow = clampedPreviousRow;
1701
+ let bestOverlap = 0;
1702
+ for (let row = 0; row < rowCount; row++) {
1703
+ const rowTopPx = row * rowHeightPx;
1704
+ const rowBottomPx = rowTopPx + rowHeightPx;
1705
+ const overlap = Math.max(0, Math.min(dragBottomPx, rowBottomPx) - Math.max(dragRectTopPx, rowTopPx));
1706
+ if (overlap > bestOverlap) {
1707
+ bestOverlap = overlap;
1708
+ bestRow = row;
1709
+ }
1710
+ }
1711
+ return bestOverlap > 0 ? bestRow : clampedPreviousRow;
1712
+ }
1713
+ function resolveInsertionSlotFromRow(dragRectCenterXPx, rowNodes, sourceId, cellWidthPx) {
1714
+ const candidates = rowNodes.filter((n) => n.id !== sourceId);
1715
+ if (candidates.length === 0)
1716
+ return 0;
1717
+ for (let i = 0; i < candidates.length; i++) {
1718
+ const n = candidates[i];
1719
+ const nodeX = (n.x ?? 0) * cellWidthPx;
1720
+ const nodeW = (n.w ?? 1) * cellWidthPx;
1721
+ const nodeMid = nodeX + nodeW / 2;
1722
+ if (dragRectCenterXPx <= nodeMid)
1723
+ return i;
1724
+ }
1725
+ return candidates.length;
1726
+ }
1727
+ function reorderByInsertionSlot(orderedIds, sourceId, targetSlot) {
1728
+ const withoutSource = orderedIds.filter((id) => id !== sourceId);
1729
+ const clamped = Math.max(0, Math.min(targetSlot, withoutSource.length));
1730
+ withoutSource.splice(clamped, 0, sourceId);
1731
+ return withoutSource;
1732
+ }
1733
+ function resolveInsertionSlotFromProjectedRect(orderedNodes, sourceId, columnCount, dragRect, cellWidthPx, cellHeightPx, previousSlot) {
1734
+ if (cellWidthPx <= 0 || cellHeightPx <= 0) {
1735
+ return previousSlot;
1736
+ }
1737
+ const orderedIds = orderedNodes
1738
+ .filter((node) => node.id)
1739
+ .map((node) => node.id);
1740
+ const nodesById = new Map(orderedNodes
1741
+ .filter((node) => !!node.id)
1742
+ .map((node) => [node.id, node]));
1743
+ const idsWithoutSource = orderedIds.filter((id) => id !== sourceId);
1744
+ const sourceNode = nodesById.get(sourceId);
1745
+ if (!sourceNode)
1746
+ return previousSlot;
1747
+ let bestSlot = previousSlot;
1748
+ let bestOverlapRatio = 0;
1749
+ let bestProjectedSource;
1750
+ for (let slot = 0; slot <= idsWithoutSource.length; slot++) {
1751
+ const candidateIds = reorderByInsertionSlot(orderedIds, sourceId, slot);
1752
+ const candidateNodes = candidateIds
1753
+ .map((id) => nodesById.get(id))
1754
+ .filter((node) => !!node);
1755
+ const projectedSource = projectZFlowLayout(candidateNodes, columnCount).find((projected) => projected.id === sourceId);
1756
+ if (!projectedSource)
1757
+ continue;
1758
+ const overlapAreaPx = getRectOverlapAreaPx(dragRect, {
1759
+ leftPx: projectedSource.x * cellWidthPx,
1760
+ topPx: projectedSource.y * cellHeightPx,
1761
+ widthPx: projectedSource.w * cellWidthPx,
1762
+ heightPx: projectedSource.h * cellHeightPx,
1763
+ });
1764
+ const projectedAreaPx = projectedSource.w *
1765
+ cellWidthPx *
1766
+ projectedSource.h *
1767
+ cellHeightPx;
1768
+ const overlapRatio = projectedAreaPx > 0 ? overlapAreaPx / projectedAreaPx : 0;
1769
+ if (overlapRatio > bestOverlapRatio ||
1770
+ (overlapRatio === bestOverlapRatio &&
1771
+ bestProjectedSource &&
1772
+ isSameProjectedPosition(projectedSource, bestProjectedSource) &&
1773
+ slot > bestSlot)) {
1774
+ bestOverlapRatio = overlapRatio;
1775
+ bestProjectedSource = projectedSource;
1776
+ bestSlot = slot;
1777
+ }
1778
+ }
1779
+ if (bestOverlapRatio > PROJECTED_SLOT_OVERLAP_THRESHOLD)
1780
+ return bestSlot;
1781
+ return Math.max(0, Math.min(previousSlot, idsWithoutSource.length));
1782
+ }
1783
+ function isSameProjectedPosition(a, b) {
1784
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
1785
+ }
1786
+ function getRectOverlapAreaPx(a, b) {
1787
+ const overlapWidthPx = Math.max(0, Math.min(a.leftPx + a.widthPx, b.leftPx + b.widthPx) -
1788
+ Math.max(a.leftPx, b.leftPx));
1789
+ const overlapHeightPx = Math.max(0, Math.min(a.topPx + a.heightPx, b.topPx + b.heightPx) -
1790
+ Math.max(a.topPx, b.topPx));
1791
+ return overlapWidthPx * overlapHeightPx;
1792
+ }
1793
+ function applyProjectedLayout(nodes, projected) {
1794
+ for (const proj of projected) {
1795
+ const node = nodes.find((n) => n.id === proj.id);
1796
+ if (!node)
1797
+ continue;
1798
+ if (node.x !== proj.x ||
1799
+ node.y !== proj.y ||
1800
+ node.w !== proj.w ||
1801
+ node.h !== proj.h) {
1802
+ node.x = proj.x;
1803
+ node.y = proj.y;
1804
+ node.w = proj.w;
1805
+ node.h = proj.h;
1806
+ node._dirty = true;
1807
+ }
1808
+ }
1809
+ }
1810
+ function notifyEngine(engine) {
1811
+ engine._notify?.();
1812
+ }
1813
+
1814
+ class ZflowGridStackEngine extends GridStackEngine {
1815
+ moveNodeCheck(node, opts) {
1816
+ if (opts.resizing) {
1817
+ return this.moveNodeCheckWithSteppedResize(node, opts);
1818
+ }
1819
+ if (node._moving && !opts.nested) {
1820
+ return this.moveNodeCheckWithZFlowDrag(node, opts);
1821
+ }
1822
+ return super.moveNodeCheck(node, opts);
1823
+ }
1824
+ moveNodeCheckWithSteppedResize(node, opts) {
1825
+ if (!node.id || opts.w === undefined)
1826
+ return super.moveNodeCheck(node, opts);
1827
+ const nodes = this.nodes;
1828
+ const sourceNode = nodes.find((n) => n.id === node.id);
1829
+ if (!sourceNode)
1830
+ return super.moveNodeCheck(node, opts);
1831
+ syncNodeOrderFromLayout(nodes);
1832
+ const snapshot = this.takeLayoutSnapshot(nodes);
1833
+ const effectiveMax = this.column - (sourceNode.x ?? 0);
1834
+ const nextWidth = resolveResizeWidthStep(opts.w, sourceNode.maxW ?? this.column, this.column, sourceNode.minW ?? 1, effectiveMax);
1835
+ sourceNode.w = nextWidth;
1836
+ opts.w = nextWidth;
1837
+ opts.x = sourceNode.x;
1838
+ opts.y = sourceNode.y;
1839
+ opts.h = sourceNode.h;
1840
+ const ordered = sortNodesByZFlowOrder(nodes);
1841
+ const projected = projectZFlowLayout(ordered, this.column);
1842
+ applyProjectedLayout(nodes, projected);
1843
+ const changed = this.markLayoutChangesDirty(snapshot);
1844
+ if (!changed)
1845
+ return false;
1846
+ notifyEngine(this);
1847
+ return true;
1848
+ }
1849
+ commitZFlowLayout() {
1850
+ const nodes = this.nodes;
1851
+ seedNodeOrder(nodes);
1852
+ const snapshot = this.takeLayoutSnapshot(nodes);
1853
+ const ordered = sortNodesByZFlowOrder(nodes);
1854
+ const projected = projectZFlowLayout(ordered, this.column);
1855
+ applyProjectedLayout(nodes, projected);
1856
+ const changed = this.markLayoutChangesDirty(snapshot);
1857
+ if (!changed)
1858
+ return false;
1859
+ notifyEngine(this);
1860
+ return true;
1861
+ }
1862
+ syncZFlowOrderFromLayout() {
1863
+ syncNodeOrderFromLayout(this.nodes);
1864
+ }
1865
+ takeLayoutSnapshot(nodes) {
1866
+ return nodes.map((n) => ({
1867
+ node: n,
1868
+ x: n.x,
1869
+ y: n.y,
1870
+ w: n.w,
1871
+ h: n.h,
1872
+ }));
1873
+ }
1874
+ markLayoutChangesDirty(snapshot) {
1875
+ let changed = false;
1876
+ for (const { node, x, y, w, h } of snapshot) {
1877
+ if (node.x === x && node.y === y && node.w === w && node.h === h) {
1878
+ continue;
1879
+ }
1880
+ node._dirty = true;
1881
+ changed = true;
1882
+ }
1883
+ return changed;
1884
+ }
1885
+ moveNodeCheckWithZFlowDrag(node, opts) {
1886
+ if (!node.id)
1887
+ return super.moveNodeCheck(node, opts);
1888
+ const nodes = this.nodes;
1889
+ seedNodeOrder(nodes);
1890
+ const ordered = sortNodesByZFlowOrder(nodes);
1891
+ const orderedIds = ordered.filter((n) => n.id).map((n) => n.id);
1892
+ const rect = opts.rect;
1893
+ const cellWidth = opts.cellWidth ?? 1;
1894
+ const cellHeight = opts.cellHeight ?? 60;
1895
+ const rowHeight = getZFlowRowHeight(ordered);
1896
+ const rowHeightPx = rowHeight * cellHeight;
1897
+ const projected = projectZFlowLayout(ordered, this.column);
1898
+ const rowCount = projected.length > 0 ? Math.max(...projected.map((p) => p.row)) + 1 : 1;
1899
+ const sourceNode = nodes.find((n) => n.id === node.id);
1900
+ const sourceProjected = projected.find((p) => p.id === node.id);
1901
+ const previousRow = sourceProjected?.row ?? 0;
1902
+ let targetRow;
1903
+ if (rect) {
1904
+ const rectTop = rect.top ?? rect.y ?? 0;
1905
+ const rectHeight = rect.height ??
1906
+ rect.h ??
1907
+ rowHeightPx;
1908
+ targetRow = resolveDropRowFromRect(rectTop, rectHeight, rowHeightPx, rowCount, previousRow);
1909
+ }
1910
+ else {
1911
+ targetRow = Math.floor((opts.y ?? sourceNode?.y ?? 0) / rowHeight);
1912
+ }
1913
+ targetRow = Math.max(0, Math.min(targetRow, rowCount - 1));
1914
+ const rowNodes = projected
1915
+ .filter((p) => p.row === targetRow)
1916
+ .map((p) => ({ id: p.id, x: p.x, w: p.w }));
1917
+ const idsWithoutSource = orderedIds.filter((id) => id !== node.id);
1918
+ let absoluteSlot;
1919
+ if (rect) {
1920
+ const rectLeft = rect.left ?? rect.x ?? 0;
1921
+ const rectTop = rect.top ?? rect.y ?? 0;
1922
+ const rectWidth = rect.width ?? rect.w ?? cellWidth;
1923
+ const rectHeight = rect.height ??
1924
+ rect.h ??
1925
+ rowHeightPx;
1926
+ absoluteSlot = resolveInsertionSlotFromProjectedRect(ordered, node.id, this.column, {
1927
+ leftPx: rectLeft,
1928
+ topPx: rectTop,
1929
+ widthPx: rectWidth,
1930
+ heightPx: rectHeight,
1931
+ }, cellWidth, cellHeight, orderedIds.indexOf(node.id));
1932
+ }
1933
+ else {
1934
+ const targetX = opts.x ?? sourceNode?.x ?? 0;
1935
+ const insertionSlotInRow = rowNodes.filter((n) => {
1936
+ const proj = projected.find((p) => p.id === n.id);
1937
+ return proj && proj.x <= targetX && n.id !== node.id;
1938
+ }).length;
1939
+ const rowIdsWithoutSource = rowNodes
1940
+ .filter((n) => n.id && n.id !== node.id)
1941
+ .map((n) => n.id);
1942
+ if (rowIdsWithoutSource.length === 0) {
1943
+ absoluteSlot = orderedIds.indexOf(node.id);
1944
+ }
1945
+ else {
1946
+ const firstRowIdxInFull = idsWithoutSource.indexOf(rowIdsWithoutSource[0]);
1947
+ absoluteSlot = firstRowIdxInFull + insertionSlotInRow;
1948
+ }
1949
+ }
1950
+ absoluteSlot = Math.max(0, Math.min(absoluteSlot, idsWithoutSource.length));
1951
+ const newOrderedIds = reorderByInsertionSlot(orderedIds, node.id, absoluteSlot);
1952
+ const orderChanged = newOrderedIds.some((id, i) => id !== orderedIds[i]);
1953
+ if (!orderChanged)
1954
+ return false;
1955
+ newOrderedIds.forEach((id, idx) => {
1956
+ const n = nodes.find((nn) => nn.id === id);
1957
+ if (n)
1958
+ n.zFlowOrder = idx;
1959
+ });
1960
+ const projectedSource = projectZFlowLayout(sortNodesByZFlowOrder(nodes), this.column).find((projected) => projected.id === node.id);
1961
+ if (projectedSource) {
1962
+ node.x = projectedSource.x;
1963
+ node.y = projectedSource.y;
1964
+ node.w = projectedSource.w;
1965
+ node.h = projectedSource.h;
1966
+ node._dirty = true;
1967
+ notifyEngine(this);
1968
+ }
1969
+ return true;
1970
+ }
1971
+ }
1972
+
1973
+ const getColumns = (breakpoints) => breakpoints.map((bp) => bp.c).reverse();
1974
+ const ENGINE_PROFILES = {
1975
+ zFlow: {
1976
+ engineClass: ZflowGridStackEngine,
1977
+ breakpoints: ZFLOW_DASHBOARD_BREAKPOINTS,
1978
+ sectionColumns: [1, 2, 3, 3],
1979
+ fixedCardHeight: true,
1980
+ xlWidthSwap: true,
1981
+ renderOriginPosition: true,
1982
+ },
1983
+ default: {
1984
+ engineClass: undefined,
1985
+ breakpoints: DASHBOARD_BREAKPOINTS,
1986
+ sectionColumns: getColumns(DASHBOARD_BREAKPOINTS),
1987
+ fixedCardHeight: false,
1988
+ xlWidthSwap: false,
1989
+ renderOriginPosition: false,
1990
+ },
1991
+ };
1992
+
1596
1993
  document.body.classList.add('ui5-content-density-compact');
1597
1994
  class Dashboard {
1598
1995
  static registerAngularComponents(componentTypes) {
1599
1996
  addComponentToRegistry(componentTypes);
1600
1997
  }
1998
+ hostEl = inject((ElementRef));
1999
+ injector = inject(Injector);
2000
+ sanitizer = inject(DomSanitizer);
2001
+ i18n = inject(DashboardI18nService);
1601
2002
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
1602
2003
  sections = model([], ...(ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []));
1603
2004
  cards = model([], ...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
@@ -1606,20 +2007,18 @@ class Dashboard {
1606
2007
  saved = output();
1607
2008
  actionButtonClick = output();
1608
2009
  unsavedChangesChange = output();
2010
+ i18nKeys = DASHBOARD_I18N_KEYS;
2011
+ /** True once the user has dragged/resized any grid item while in edit mode. */
2012
+ gridDirty = signal(false, ...(ngDevMode ? [{ debugName: "gridDirty" }] : /* istanbul ignore next */ []));
2013
+ isXLPage = signal(true, ...(ngDevMode ? [{ debugName: "isXLPage" }] : /* istanbul ignore next */ []));
1609
2014
  editMode = signal(false, ...(ngDevMode ? [{ debugName: "editMode" }] : /* istanbul ignore next */ []));
1610
2015
  compactToolbar = signal(false, ...(ngDevMode ? [{ debugName: "compactToolbar" }] : /* istanbul ignore next */ []));
1611
2016
  toolbarMenuOpen = signal(false, ...(ngDevMode ? [{ debugName: "toolbarMenuOpen" }] : /* istanbul ignore next */ []));
1612
- /** True once the user has dragged/resized any grid item while in edit mode. */
1613
- gridDirty = signal(false, ...(ngDevMode ? [{ debugName: "gridDirty" }] : /* istanbul ignore next */ []));
2017
+ cardDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "cardDialogOpen" }] : /* istanbul ignore next */ []));
2018
+ discardDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "discardDialogOpen" }] : /* istanbul ignore next */ []));
2019
+ unsavedNavDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "unsavedNavDialogOpen" }] : /* istanbul ignore next */ []));
1614
2020
  backgroundImageHeight = signal(null, ...(ngDevMode ? [{ debugName: "backgroundImageHeight" }] : /* istanbul ignore next */ []));
1615
- /** JSON snapshots of sections/cards taken on entering edit mode, used to detect changes. */
1616
- sectionsSnapshotJson = '';
1617
- cardsSnapshotJson = '';
1618
- /**
1619
- * True when the user is in edit mode AND has made any change (sections/cards
1620
- * mutated, or grid items moved/resized). Resets when entering edit mode and
1621
- * after save/cancel.
1622
- */
2021
+ dragOriginStyle = signal(null, ...(ngDevMode ? [{ debugName: "dragOriginStyle" }] : /* istanbul ignore next */ []));
1623
2022
  hasUnsavedChanges = computed(() => {
1624
2023
  if (!this.editMode())
1625
2024
  return false;
@@ -1628,16 +2027,6 @@ class Dashboard {
1628
2027
  return (JSON.stringify(this.sections()) !== this.sectionsSnapshotJson ||
1629
2028
  JSON.stringify(this.cards()) !== this.cardsSnapshotJson);
1630
2029
  }, ...(ngDevMode ? [{ debugName: "hasUnsavedChanges" }] : /* istanbul ignore next */ []));
1631
- sectionsSnapshot = [];
1632
- cardsSnapshot = [];
1633
- gridStackItems = viewChild.required('grid');
1634
- addCardBtn = viewChild('editCardsBtn', ...(ngDevMode ? [{ debugName: "addCardBtn" }] : /* istanbul ignore next */ []));
1635
- resizeObserver;
1636
- hostEl = inject((ElementRef));
1637
- injector = inject(Injector);
1638
- sanitizer = inject(DomSanitizer);
1639
- i18n = inject(DashboardI18nService);
1640
- i18nKeys = DASHBOARD_I18N_KEYS;
1641
2030
  safeTitle = computed(() => {
1642
2031
  const clean = this.sanitizer.sanitize(SecurityContext.HTML, this.config().title) ?? '';
1643
2032
  return this.sanitizer.bypassSecurityTrustHtml(clean);
@@ -1649,6 +2038,52 @@ class Dashboard {
1649
2038
  const clean = this.sanitizer.sanitize(SecurityContext.HTML, desc) ?? '';
1650
2039
  return this.sanitizer.bypassSecurityTrustHtml(clean);
1651
2040
  }, ...(ngDevMode ? [{ debugName: "safeDescription" }] : /* istanbul ignore next */ []));
2041
+ engineProfile = computed(() => this.config().zFlow ? ENGINE_PROFILES.zFlow : ENGINE_PROFILES.default, ...(ngDevMode ? [{ debugName: "engineProfile" }] : /* istanbul ignore next */ []));
2042
+ gridStackEngine = computed(() => this.engineProfile().engineClass, ...(ngDevMode ? [{ debugName: "gridStackEngine" }] : /* istanbul ignore next */ []));
2043
+ gridBreakpoints = computed(() => [
2044
+ ...this.engineProfile().breakpoints,
2045
+ ], ...(ngDevMode ? [{ debugName: "gridBreakpoints" }] : /* istanbul ignore next */ []));
2046
+ columnVars = computed(() => {
2047
+ const [sm, md, lg, xl] = this.engineProfile().sectionColumns;
2048
+ return {
2049
+ '--dashboard-cols-sm': sm,
2050
+ '--dashboard-cols-md': md,
2051
+ '--dashboard-cols-lg': lg,
2052
+ '--dashboard-cols-xl': xl,
2053
+ };
2054
+ }, ...(ngDevMode ? [{ debugName: "columnVars" }] : /* istanbul ignore next */ []));
2055
+ customActions = computed(() => this.config().customActions ?? [], ...(ngDevMode ? [{ debugName: "customActions" }] : /* istanbul ignore next */ []));
2056
+ addedCardsIds = computed(() => new Set(this.cards().map((c) => c.id)), ...(ngDevMode ? [{ debugName: "addedCardsIds" }] : /* istanbul ignore next */ []));
2057
+ editViewButton = computed(() => ({
2058
+ icon: 'action-settings',
2059
+ design: 'Transparent',
2060
+ tooltip: this.i18n.getTranslation(DASHBOARD_I18N_KEYS.EDIT_VIEW),
2061
+ text: '',
2062
+ ...this.config().buttonsSettings?.editViewButton,
2063
+ }), ...(ngDevMode ? [{ debugName: "editViewButton" }] : /* istanbul ignore next */ []));
2064
+ editCardsButton = computed(() => ({
2065
+ icon: '',
2066
+ design: 'Default',
2067
+ tooltip: '',
2068
+ text: this.i18n.getTranslation(DASHBOARD_I18N_KEYS.EDIT_CARDS),
2069
+ ...this.config().buttonsSettings?.editCardsButton,
2070
+ }), ...(ngDevMode ? [{ debugName: "editCardsButton" }] : /* istanbul ignore next */ []));
2071
+ sectionCards = computed(() => {
2072
+ const all = this.cards();
2073
+ return (sectionId) => all.filter((c) => c.sectionId === sectionId);
2074
+ }, ...(ngDevMode ? [{ debugName: "sectionCards" }] : /* istanbul ignore next */ []));
2075
+ looseCards = linkedSignal(() => {
2076
+ const loose = this.cards().filter((c) => !c.sectionId);
2077
+ const cardHeight = this.config().zFlow?.cardHeight;
2078
+ if (!this.engineProfile().fixedCardHeight || cardHeight === undefined)
2079
+ return loose;
2080
+ return loose.map((c) => ({
2081
+ ...c,
2082
+ h: cardHeight,
2083
+ maxH: cardHeight,
2084
+ minH: cardHeight,
2085
+ }));
2086
+ }, ...(ngDevMode ? [{ debugName: "looseCards" }] : /* istanbul ignore next */ []));
1652
2087
  gridOptions = computed(() => ({
1653
2088
  cellHeight: CELL_HEIGHT,
1654
2089
  sizeToContent: true,
@@ -1657,15 +2092,23 @@ class Dashboard {
1657
2092
  marginBottom: 0,
1658
2093
  marginLeft: 0,
1659
2094
  marginRight: 0,
2095
+ engineClass: this.gridStackEngine(),
1660
2096
  columnOpts: {
1661
- // Source of truth: ../models/breakpoints.ts (paired with
1662
- // ../models/_breakpoints.scss for the section grid's container queries).
1663
- breakpoints: [...DASHBOARD_BREAKPOINTS],
2097
+ // Source of truth: ../constants/breakpoints.ts active profile's
2098
+ // breakpoints (paired with ../constants/_breakpoints.scss for the
2099
+ // section grid's container queries via --dashboard-cols-* CSS vars).
2100
+ breakpoints: this.gridBreakpoints(),
1664
2101
  },
1665
2102
  }), ...(ngDevMode ? [{ debugName: "gridOptions" }] : /* istanbul ignore next */ []));
1666
- cardDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "cardDialogOpen" }] : /* istanbul ignore next */ []));
1667
- discardDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "discardDialogOpen" }] : /* istanbul ignore next */ []));
1668
- unsavedNavDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "unsavedNavDialogOpen" }] : /* istanbul ignore next */ []));
2103
+ /** JSON snapshots of sections/cards taken on entering edit mode, used to detect changes. */
2104
+ sectionsSnapshotJson = '';
2105
+ cardsSnapshotJson = '';
2106
+ sectionsSnapshot = [];
2107
+ cardsSnapshot = [];
2108
+ gridStack = viewChild.required('grid');
2109
+ addCardBtn = viewChild('editCardsBtn', ...(ngDevMode ? [{ debugName: "addCardBtn" }] : /* istanbul ignore next */ []));
2110
+ resizeObserver;
2111
+ cardsPosition = new Map();
1669
2112
  /** Callback that resumes the intercepted navigation once the user resolves the dialog. */
1670
2113
  pendingNavigation = null;
1671
2114
  /** beforeunload handler kept on instance so add/removeEventListener pair up. */
@@ -1677,29 +2120,6 @@ class Dashboard {
1677
2120
  event.returnValue = '';
1678
2121
  }
1679
2122
  };
1680
- customActions = computed(() => this.config().customActions ?? [], ...(ngDevMode ? [{ debugName: "customActions" }] : /* istanbul ignore next */ []));
1681
- addedCardsIds = computed(() => new Set(this.cards().map((c) => c.id)), ...(ngDevMode ? [{ debugName: "addedCardsIds" }] : /* istanbul ignore next */ []));
1682
- editViewButton = computed(() => ({
1683
- icon: 'action-settings',
1684
- design: 'Transparent',
1685
- tooltip: this.i18n.getTranslation(DASHBOARD_I18N_KEYS.EDIT_VIEW),
1686
- text: '',
1687
- ...this.config().buttonsSettings?.editViewButton,
1688
- }), ...(ngDevMode ? [{ debugName: "editViewButton" }] : /* istanbul ignore next */ []));
1689
- editCardsButton = computed(() => ({
1690
- icon: '',
1691
- design: 'Default',
1692
- tooltip: '',
1693
- text: this.i18n.getTranslation(DASHBOARD_I18N_KEYS.EDIT_CARDS),
1694
- ...this.config().buttonsSettings?.editCardsButton,
1695
- }), ...(ngDevMode ? [{ debugName: "editCardsButton" }] : /* istanbul ignore next */ []));
1696
- sectionCards = computed(() => {
1697
- const all = this.cards();
1698
- return (sectionId) => all.filter((c) => c.sectionId === sectionId);
1699
- }, ...(ngDevMode ? [{ debugName: "sectionCards" }] : /* istanbul ignore next */ []));
1700
- cardsPosition = new Map();
1701
- looseCards = linkedSignal(() => this.cards().filter((c) => !c.sectionId), ...(ngDevMode ? [{ debugName: "looseCards" }] : /* istanbul ignore next */ []));
1702
- newGridStackNodes = [];
1703
2123
  constructor() {
1704
2124
  effect(() => {
1705
2125
  this.unsavedChangesChange.emit(this.hasUnsavedChanges());
@@ -1726,6 +2146,7 @@ class Dashboard {
1726
2146
  this.resizeObserver = new ResizeObserver((entries) => {
1727
2147
  const width = entries[0]?.contentRect.width ?? 0;
1728
2148
  this.compactToolbar.set(width < COMPACT_BREAKPOINT);
2149
+ this.changeCardSettingsForXlPage(width);
1729
2150
  });
1730
2151
  this.resizeObserver.observe(this.hostEl.nativeElement);
1731
2152
  window.addEventListener('beforeunload', this.beforeUnloadHandler);
@@ -1864,7 +2285,7 @@ class Dashboard {
1864
2285
  this.cards.update((list) => list.filter((c) => c.id !== id));
1865
2286
  if (wasLooseCard) {
1866
2287
  afterNextRender(() => {
1867
- this.gridStackItems().grid?.compact('compact', false);
2288
+ this.gridStack().grid?.compact('compact', false);
1868
2289
  }, { injector: this.injector });
1869
2290
  }
1870
2291
  }
@@ -1881,6 +2302,26 @@ class Dashboard {
1881
2302
  });
1882
2303
  this.closeCardPanel();
1883
2304
  }
2305
+ onDragStart(event) {
2306
+ this.getZFlowEngine()?.syncZFlowOrderFromLayout();
2307
+ if (!this.engineProfile().renderOriginPosition) {
2308
+ return;
2309
+ }
2310
+ const el = event.el;
2311
+ const gridEl = this.gridStack().el;
2312
+ const gridRect = gridEl.getBoundingClientRect();
2313
+ const elRect = el.getBoundingClientRect();
2314
+ this.dragOriginStyle.set({
2315
+ top: `${elRect.top - gridRect.top}px`,
2316
+ left: `${elRect.left - gridRect.left}px`,
2317
+ width: `${elRect.width}px`,
2318
+ height: `${elRect.height}px`,
2319
+ });
2320
+ }
2321
+ onDragStop() {
2322
+ this.getZFlowEngine()?.commitZFlowLayout();
2323
+ this.dragOriginStyle.set(null);
2324
+ }
1884
2325
  onGridChange() {
1885
2326
  if (this.editMode()) {
1886
2327
  this.gridDirty.set(true);
@@ -1899,15 +2340,50 @@ class Dashboard {
1899
2340
  });
1900
2341
  }
1901
2342
  updateCardsPositions() {
1902
- const gridStackNodes = this.gridStackItems()
2343
+ const gridStackNodes = this.gridStack()
1903
2344
  .gridstackItems?.toArray()
1904
2345
  .map((node) => node.options);
1905
2346
  if (gridStackNodes) {
1906
2347
  this.saveCardsPosition(gridStackNodes);
1907
2348
  }
1908
2349
  }
2350
+ getZFlowEngine() {
2351
+ const engine = this.gridStack().grid?.engine;
2352
+ return engine instanceof ZflowGridStackEngine ? engine : null;
2353
+ }
2354
+ updateCardsForBreakpoint(updateCard) {
2355
+ this.getZFlowEngine()?.syncZFlowOrderFromLayout();
2356
+ this.cards.set(this.cards().map(updateCard));
2357
+ afterNextRender(() => {
2358
+ this.getZFlowEngine()?.commitZFlowLayout();
2359
+ }, { injector: this.injector });
2360
+ }
2361
+ changeCardSettingsForXlPage(width) {
2362
+ if (!this.engineProfile().xlWidthSwap)
2363
+ return;
2364
+ if (width >= XL_PAGE) {
2365
+ if (!this.isXLPage()) {
2366
+ this.isXLPage.set(true);
2367
+ this.updateCardsForBreakpoint((c) => ({
2368
+ ...c,
2369
+ w: c.w === 4 ? 3 : c.w,
2370
+ maxW: c.maxW === 4 ? 3 : c.maxW,
2371
+ }));
2372
+ }
2373
+ }
2374
+ else {
2375
+ if (this.isXLPage()) {
2376
+ this.isXLPage.set(false);
2377
+ this.updateCardsForBreakpoint((c) => ({
2378
+ ...c,
2379
+ w: c.w === 3 ? 4 : c.w,
2380
+ maxW: c.maxW === 3 ? 4 : c.maxW,
2381
+ }));
2382
+ }
2383
+ }
2384
+ }
1909
2385
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: Dashboard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1910
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: Dashboard, isStandalone: true, selector: "mfp-dashboard", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, availableCards: { classPropertyName: "availableCards", publicName: "availableCards", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sections: "sectionsChange", cards: "cardsChange", saved: "saved", actionButtonClick: "actionButtonClick", unsavedChangesChange: "unsavedChangesChange" }, host: { properties: { "style.background-image": "config().backgroundImageUrl ? \"url(\" + config().backgroundImageUrl + \")\" : null", "style.background-size": "backgroundImageHeight() ? \"100% \" + backgroundImageHeight() + \"px\" : \"100% auto\"" } }, providers: [DashboardI18nService], viewQueries: [{ propertyName: "gridStackItems", first: true, predicate: ["grid"], descendants: true, isSignal: true }, { propertyName: "addCardBtn", first: true, predicate: ["editCardsBtn"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mfp-dashboard\" data-testid=\"dashboard\">\n <div class=\"mfp-dashboard__topbar\">\n <div class=\"mfp-dashboard__topbar-row\">\n <div class=\"mfp-dashboard__header\">\n <div class=\"mfp-dashboard__title-row\">\n @if (config().title) {\n <ui5-title level=\"H3\" size=\"H3\" wrapping-type=\"Normal\" data-testid=\"dashboard-title\">\n <span [innerHTML]=\"safeTitle()\"></span>\n </ui5-title>\n }\n @if (hasUnsavedChanges()) {\n <div class=\"mfp-dashboard__unsaved-changes\" role=\"status\">\n <ui5-icon\n class=\"mfp-dashboard__unsaved-changes-icon\"\n name=\"user-edit\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\"\n />\n <span class=\"mfp-dashboard__unsaved-changes-text\">{{\n i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\n }}</span>\n </div>\n }\n </div>\n @if (config().description) {\n <ui5-title level=\"H5\" size=\"H5\" wrapping-type=\"Normal\" data-testid=\"dashboard-description\">\n <span\n class=\"mfp-dashboard__description\"\n [innerHTML]=\"safeDescription()\"\n ></span>\n </ui5-title>\n }\n </div>\n\n <div class=\"mfp-dashboard__toolbar\">\n @if (editMode()) {\n <ui5-button\n #editCardsBtn\n id=\"edit-cards-btn\"\n data-testid=\"dashboard-edit-cards-btn\"\n [accessibleName]=\"\n editCardsButton().text ||\n editCardsButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_CARDS)\n \"\n [design]=\"editCardsButton().design\"\n [icon]=\"editCardsButton().icon\"\n [tooltip]=\"editCardsButton().tooltip\"\n (click)=\"openCardPanel()\"\n >{{ editCardsButton().text }}</ui5-button\n >\n } @else if (compactToolbar()) {\n <ui5-button\n #menuBtn\n data-testid=\"dashboard-toolbar-menu-btn\"\n design=\"Transparent\"\n icon=\"menu2\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n [tooltip]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n (click)=\"toolbarMenuOpen.update((v) => !v)\"\n />\n <ui5-menu\n data-testid=\"dashboard-toolbar-menu\"\n [open]=\"toolbarMenuOpen()\"\n [opener]=\"menuBtn.element\"\n (ui5Close)=\"toolbarMenuOpen.set(false)\"\n (ui5ItemClick)=\"\n onMenuItemClick(\n $any($event).detail.item.dataset['action'],\n $event\n )\n \"\n (ui5Open)=\"toolbarMenuOpen.set(true)\"\n >\n @if (config().editButtonFirst && config().editable) {\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n @if (customActions().length) {\n <ui5-menu-separator />\n }\n }\n @for (action of customActions(); track action.action) {\n <ui5-menu-item\n [attr.data-action]=\"action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [icon]=\"action.icon ?? ''\"\n [text]=\"action.text ?? ''\"\n />\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-menu-separator />\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n }\n </ui5-menu>\n } @else {\n @if (config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n @for (action of customActions(); track action.action) {\n <ui5-button\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [accessibleName]=\"action.text || action.tooltip || action.action\"\n [design]=\"action.design ?? 'Default'\"\n [endIcon]=\"action?.endIcon\"\n [icon]=\"action.icon ?? ''\"\n [tooltip]=\"action.tooltip ?? ''\"\n (click)=\"\n actionButtonClick.emit({ event: $event, action: action })\n \"\n >{{ action.text }}</ui5-button\n >\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n }\n </div>\n </div>\n\n <div class=\"mfp-dashboard__subheader\">\n <ng-content select=\"[slot=dashboard-subheader]\" />\n </div>\n </div>\n\n <div class=\"mfp-sections-container\">\n @for (section of sections(); track section.id) {\n <mfp-dashboard-section\n [cards]=\"sectionCards()(section.id)\"\n [editMode]=\"editMode()\"\n [section]=\"section\"\n (removeCard)=\"removeCard($event)\"\n (removeSection)=\"removeSection(section.id)\"\n />\n }\n </div>\n\n <gridstack\n #grid\n data-testid=\"dashboard-grid\"\n [options]=\"gridOptions()\"\n (addedCB)=\"onGridChange()\"\n (changeCB)=\"onGridChange()\"\n (removedCB)=\"onGridChange()\"\n >\n @for (card of looseCards(); track card.id) {\n <gridstack-item [options]=\"card\">\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode()\"\n (removeCard)=\"removeCard($any(card.id))\"\n />\n </gridstack-item>\n }\n </gridstack>\n\n</div>\n@if (editMode()) {\n <div class=\"mfp-dashboard__edit-bar\">\n <ui5-button data-testid=\"dashboard-save-btn\" design=\"Emphasized\" (click)=\"saveEdit()\">{{\n i18n.getTranslation(i18nKeys.SAVE)\n }}</ui5-button>\n <ui5-button data-testid=\"dashboard-cancel-btn\" design=\"Transparent\" (click)=\"cancelEdit()\">{{\n i18n.getTranslation(i18nKeys.CANCEL)\n }}</ui5-button>\n </div>\n}\n\n<mfp-edit-cards-dialog\n [addedCardsIds]=\"addedCardsIds()\"\n [availableCards]=\"availableCards()\"\n [open]=\"cardDialogOpen()\"\n (cancelled)=\"closeCardPanel()\"\n (confirm)=\"onCardsEdited($event)\"\n/>\n\n<mfp-discard-changes-dialog\n [open]=\"discardDialogOpen()\"\n (cancelled)=\"cancelDiscard()\"\n (confirm)=\"confirmDiscard()\"\n/>\n\n<mfp-unsaved-changes-dialog\n [open]=\"unsavedNavDialogOpen()\"\n (cancelled)=\"onUnsavedNavCancel()\"\n (discard)=\"onUnsavedNavDiscard()\"\n (save)=\"onUnsavedNavSave()\"\n/>\n", styles: [".grid-stack{position:relative}.grid-stack-placeholder>.placeholder-content{background-color:#0000001a;margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0;top:0;width:var(--gs-column-width);height:var(--gs-cell-height)}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item{right:0}.grid-stack>.grid-stack-item>.grid-stack-item-content,.grid-stack>.grid-stack-placeholder>.placeholder-content{top:var(--gs-item-margin-top);right:var(--gs-item-margin-right);bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;user-select:none;z-index:100}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"%23666\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewBox=\"0 0 20 20\"><path d=\"m10 3 2 2H8l2-2v14l-2-2h4l-2 2\"/></svg>');background-repeat:no-repeat;background-position:center;z-index:101}.grid-stack-item>.ui-resizable-ne{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:var(--gs-item-margin-top);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:var(--gs-item-margin-top);left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:var(--gs-item-margin-top);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px;right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:var(--gs-item-margin-bottom);right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px;left:var(--gs-item-margin-left)}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,right,top}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px #0003;opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,right .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,right 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y=\"0\"]{top:0}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item[gs-x=\"0\"]{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item[gs-x=\"0\"]{right:0}.grid-stack-placeholder .placeholder-content{border-radius:16px;height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2)!important;width:calc(100% - 20px);left:10px!important}mfp-dashboard,mfp-wc-dashboard{display:block;flex:1;margin:0;padding:0;min-height:100%;background:var(--sapShellColor, #354a5e);background-size:100% auto;background-position:top center;background-repeat:no-repeat;background-attachment:local}.mfp-dashboard{padding:calc(var(--sapShell_Space_XL, 3rem) - 10px);container-type:inline-size;container-name:mfp-dashboard}.mfp-sections-container{display:grid;grid-auto-rows:auto;align-content:start;gap:1rem;grid-template-columns:repeat(14,1fr)}@container mfp-dashboard (max-width: 599px){.mfp-sections-container{grid-template-columns:repeat(1,1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.mfp-sections-container{grid-template-columns:repeat(8,1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.mfp-sections-container{grid-template-columns:repeat(12,1fr)}}.mfp-dashboard__topbar{grid-column:1/-1;align-self:start;display:flex;flex-direction:column;gap:1rem;padding-bottom:3rem;width:100%;min-width:0}.mfp-dashboard__topbar-row{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:0 10px}.mfp-dashboard__header{display:flex;flex-direction:column;gap:.25rem}.mfp-dashboard__title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.mfp-dashboard__unsaved-changes{display:inline-flex;align-items:center;gap:.375rem}.mfp-dashboard__unsaved-changes-icon{width:16px;height:16px;color:var(--sapContent_MarkerIconColor)}.mfp-dashboard__unsaved-changes-text{color:var(--sapContent_LabelColor);text-shadow:0 0 2px var(--sapContent_ContrastTextShadow, #fff);font-family:var(--sapFontFamily);font-size:var(--sapFontSize, 14px);font-style:normal;font-weight:400;line-height:normal}.mfp-dashboard__description{font-weight:400;font-family:var(--sapFontFamily)}.mfp-dashboard__description b,.mfp-dashboard__description strong{font-family:var(--sapFontBoldFamily)}.mfp-dashboard__toolbar{flex-shrink:0;display:flex;gap:.5rem}.mfp-dashboard__subheader{display:flex;align-items:center;gap:1rem}.mfp-dashboard__edit-bar{position:fixed;bottom:20px;left:16px;right:16px;z-index:1000;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:7px 16px;background:var(--sapPageFooter_Background, white);border-radius:var(--sapElement_BorderCornerRadius, 12px);box-shadow:0 0 0 1px #2235487a,0 2px 8px #2235484d;box-sizing:border-box;overflow:hidden}@media screen and (min-width:0px)and (max-width:599px){.mfp-dashboard{padding:calc(var(--sapShell_Space_S, 1rem) - 10px)}}@media screen and (min-width:600px)and (max-width:1023px){.mfp-dashboard{padding:calc(var(--sapShell_Space_M, 2rem) - 10px)}}@media screen and (min-width:1024px)and (max-width:1439px){.mfp-dashboard{padding:calc(var(--sapShell_Space_L, 2rem) - 10px)}}.grid-stack.grid-stack-dragging,.grid-stack.grid-stack-dragging *{cursor:grabbing!important}.grid-stack:has(.ui-resizable-resizing),.grid-stack:has(.ui-resizable-resizing) *{cursor:nwse-resize!important}.grid-stack-item>.ui-resizable-handle{background-image:none!important}\n"], dependencies: [{ kind: "component", type: GridstackComponent, selector: "gridstack", inputs: ["options", "isEmpty"], outputs: ["addedCB", "changeCB", "disableCB", "dragCB", "dragStartCB", "dragStopCB", "droppedCB", "enableCB", "removedCB", "resizeCB", "resizeStartCB", "resizeStopCB"] }, { kind: "component", type: GridstackItemComponent, selector: "gridstack-item", inputs: ["options"] }, { kind: "component", type: DiscardChangesDialog, selector: "mfp-discard-changes-dialog", inputs: ["open"], outputs: ["confirm", "cancelled"] }, { kind: "component", type: EditCardsDialog, selector: "mfp-edit-cards-dialog", inputs: ["availableCards", "addedCardsIds", "open"], outputs: ["confirm", "cancelled"] }, { kind: "component", type: UnsavedChangesDialog, selector: "mfp-unsaved-changes-dialog", inputs: ["open"], outputs: ["save", "discard", "cancelled"] }, { kind: "component", type: DashboardSection, selector: "mfp-dashboard-section", inputs: ["section", "cards", "columns", "editMode"], outputs: ["removeSection", "removeCard"] }, { kind: "component", type: DashboardCard, selector: "mfp-dashboard-card", inputs: ["card", "editMode"], outputs: ["removeCard"] }, { kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }, { kind: "component", type: Icon, selector: "ui5-icon, [ui5-icon]", inputs: ["design", "name", "accessibleName", "showTooltip", "mode"], outputs: ["ui5Click"], exportAs: ["ui5Icon"] }, { kind: "component", type: Menu, selector: "ui5-menu, [ui5-menu]", inputs: ["headerText", "open", "placement", "horizontalAlign", "loading", "loadingDelay", "opener"], outputs: ["ui5ItemClick", "ui5BeforeOpen", "ui5Open", "ui5BeforeClose", "ui5Close"], exportAs: ["ui5Menu"] }, { kind: "component", type: MenuItem, selector: "ui5-menu-item, [ui5-menu-item]", inputs: ["text", "additionalText", "icon", "disabled", "loading", "loadingDelay", "accessibleName", "tooltip", "checked", "accessibilityAttributes", "type", "navigated", "highlight", "selected"], outputs: ["ui5BeforeOpen", "ui5Open", "ui5BeforeClose", "ui5Close", "ui5Check", "ui5DetailClick"], exportAs: ["ui5MenuItem"] }, { kind: "component", type: MenuSeparator, selector: "ui5-menu-separator, [ui5-menu-separator]", exportAs: ["ui5MenuSeparator"] }, { kind: "component", type: Title, selector: "ui5-title, [ui5-title]", inputs: ["wrappingType", "level", "size"], exportAs: ["ui5Title"] }], encapsulation: i0.ViewEncapsulation.None });
2386
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: Dashboard, isStandalone: true, selector: "mfp-dashboard", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, availableCards: { classPropertyName: "availableCards", publicName: "availableCards", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sections: "sectionsChange", cards: "cardsChange", saved: "saved", actionButtonClick: "actionButtonClick", unsavedChangesChange: "unsavedChangesChange" }, host: { properties: { "style.background-image": "config().backgroundImageUrl ? \"url(\" + config().backgroundImageUrl + \")\" : null", "style.background-size": "backgroundImageHeight() ? \"100% \" + backgroundImageHeight() + \"px\" : \"100% auto\"" } }, providers: [DashboardI18nService], viewQueries: [{ propertyName: "gridStack", first: true, predicate: ["grid"], descendants: true, isSignal: true }, { propertyName: "addCardBtn", first: true, predicate: ["editCardsBtn"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mfp-dashboard\" data-testid=\"dashboard\" [style]=\"columnVars()\" [class.edit]=\"editMode()\">\n <div class=\"mfp-dashboard__topbar\">\n <div class=\"mfp-dashboard__topbar-row\">\n <div class=\"mfp-dashboard__header\">\n <div class=\"mfp-dashboard__title-row\">\n @if (config().title) {\n <ui5-title data-testid=\"dashboard-title\" level=\"H3\" size=\"H3\" wrapping-type=\"Normal\">\n <span [innerHTML]=\"safeTitle()\"></span>\n </ui5-title>\n }\n @if (hasUnsavedChanges()) {\n <div class=\"mfp-dashboard__unsaved-changes\" role=\"status\">\n <ui5-icon\n class=\"mfp-dashboard__unsaved-changes-icon\"\n name=\"user-edit\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\"\n />\n <span class=\"mfp-dashboard__unsaved-changes-text\">{{\n i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\n }}</span>\n </div>\n }\n </div>\n @if (config().description) {\n <ui5-title data-testid=\"dashboard-description\" level=\"H5\" size=\"H5\" wrapping-type=\"Normal\">\n <span\n class=\"mfp-dashboard__description\"\n [innerHTML]=\"safeDescription()\"\n ></span>\n </ui5-title>\n }\n </div>\n\n <div class=\"mfp-dashboard__toolbar\">\n @if (editMode()) {\n <ui5-button\n #editCardsBtn\n data-testid=\"dashboard-edit-cards-btn\"\n id=\"edit-cards-btn\"\n [accessibleName]=\"\n editCardsButton().text ||\n editCardsButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_CARDS)\n \"\n [design]=\"editCardsButton().design\"\n [icon]=\"editCardsButton().icon\"\n [tooltip]=\"editCardsButton().tooltip\"\n (click)=\"openCardPanel()\"\n >{{ editCardsButton().text }}</ui5-button\n >\n } @else if (compactToolbar()) {\n <ui5-button\n #menuBtn\n data-testid=\"dashboard-toolbar-menu-btn\"\n design=\"Transparent\"\n icon=\"menu2\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n [tooltip]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n (click)=\"toolbarMenuOpen.update((v) => !v)\"\n />\n <ui5-menu\n data-testid=\"dashboard-toolbar-menu\"\n [open]=\"toolbarMenuOpen()\"\n [opener]=\"menuBtn.element\"\n (ui5Close)=\"toolbarMenuOpen.set(false)\"\n (ui5ItemClick)=\"\n onMenuItemClick(\n $any($event).detail.item.dataset['action'],\n $event\n )\n \"\n (ui5Open)=\"toolbarMenuOpen.set(true)\"\n >\n @if (config().editButtonFirst && config().editable) {\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n @if (customActions().length) {\n <ui5-menu-separator />\n }\n }\n @for (action of customActions(); track action.action) {\n <ui5-menu-item\n [attr.data-action]=\"action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [icon]=\"action.icon ?? ''\"\n [text]=\"action.text ?? ''\"\n />\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-menu-separator />\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n }\n </ui5-menu>\n } @else {\n @if (config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n @for (action of customActions(); track action.action) {\n <ui5-button\n [accessibleName]=\"action.text || action.tooltip || action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [design]=\"action.design ?? 'Default'\"\n [endIcon]=\"action?.endIcon\"\n [icon]=\"action.icon ?? ''\"\n [tooltip]=\"action.tooltip ?? ''\"\n (click)=\"\n actionButtonClick.emit({ event: $event, action: action })\n \"\n >{{ action.text }}</ui5-button\n >\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n }\n </div>\n </div>\n\n <div class=\"mfp-dashboard__subheader\">\n <ng-content select=\"[slot=dashboard-subheader]\" />\n </div>\n </div>\n\n <div class=\"mfp-sections-container\">\n @for (section of sections(); track section.id) {\n <mfp-dashboard-section\n [cards]=\"sectionCards()(section.id)\"\n [editMode]=\"editMode()\"\n [section]=\"section\"\n (removeCard)=\"removeCard($event)\"\n (removeSection)=\"removeSection(section.id)\"\n />\n }\n </div>\n\n <gridstack\n #grid\n data-testid=\"dashboard-grid\"\n [class.zflow-dragging]=\"!!dragOriginStyle()\"\n [options]=\"gridOptions()\"\n (addedCB)=\"onGridChange()\"\n (changeCB)=\"onGridChange()\"\n (dragStartCB)=\"onDragStart($event)\"\n (dragStopCB)=\"onDragStop()\"\n (removedCB)=\"onGridChange()\"\n >\n @if (dragOriginStyle()) {\n <div class=\"mfp-dashboard__drag-origin-placeholder\" [style]=\"dragOriginStyle()\"></div>\n }\n @for (card of looseCards(); track card.id) {\n <gridstack-item [options]=\"card\">\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode()\"\n (removeCard)=\"removeCard($any(card.id))\"\n />\n </gridstack-item>\n }\n </gridstack>\n\n</div>\n@if (editMode()) {\n <div class=\"mfp-dashboard__edit-bar\">\n <ui5-button data-testid=\"dashboard-save-btn\" design=\"Emphasized\" (click)=\"saveEdit()\">{{\n i18n.getTranslation(i18nKeys.SAVE)\n }}</ui5-button>\n <ui5-button data-testid=\"dashboard-cancel-btn\" design=\"Transparent\" (click)=\"cancelEdit()\">{{\n i18n.getTranslation(i18nKeys.CANCEL)\n }}</ui5-button>\n </div>\n}\n\n<mfp-edit-cards-dialog\n [addedCardsIds]=\"addedCardsIds()\"\n [availableCards]=\"availableCards()\"\n [open]=\"cardDialogOpen()\"\n (cancelled)=\"closeCardPanel()\"\n (confirm)=\"onCardsEdited($event)\"\n/>\n\n<mfp-discard-changes-dialog\n [open]=\"discardDialogOpen()\"\n (cancelled)=\"cancelDiscard()\"\n (confirm)=\"confirmDiscard()\"\n/>\n\n<mfp-unsaved-changes-dialog\n [open]=\"unsavedNavDialogOpen()\"\n (cancelled)=\"onUnsavedNavCancel()\"\n (discard)=\"onUnsavedNavDiscard()\"\n (save)=\"onUnsavedNavSave()\"\n/>\n", styles: [".grid-stack{position:relative}.grid-stack-placeholder>.placeholder-content{background-color:#0000001a;margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0;top:0;width:var(--gs-column-width);height:var(--gs-cell-height)}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item{right:0}.grid-stack>.grid-stack-item>.grid-stack-item-content,.grid-stack>.grid-stack-placeholder>.placeholder-content{top:var(--gs-item-margin-top);right:var(--gs-item-margin-right);bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;user-select:none;z-index:100}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"%23666\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewBox=\"0 0 20 20\"><path d=\"m10 3 2 2H8l2-2v14l-2-2h4l-2 2\"/></svg>');background-repeat:no-repeat;background-position:center;z-index:101}.grid-stack-item>.ui-resizable-ne{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:var(--gs-item-margin-top);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:var(--gs-item-margin-top);left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:var(--gs-item-margin-top);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px;right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:var(--gs-item-margin-bottom);right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px;left:var(--gs-item-margin-left)}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,right,top}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px #0003;opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,right .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,right 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y=\"0\"]{top:0}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item[gs-x=\"0\"]{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item[gs-x=\"0\"]{right:0}.grid-stack-placeholder{z-index:2;pointer-events:none}.grid-stack-placeholder .placeholder-content{border-radius:16px;height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2 - 2px)!important;width:calc(100% - 19px);left:8px!important;background:var(--sapContent_Selected_Hover_Background, #E3F0FF);border:1px solid var(--sapContent_DragAndDropActiveColor, #0064D9);z-index:2!important}mfp-dashboard,mfp-wc-dashboard{display:block;flex:1;margin:0;padding:0;min-height:100%;background:var(--sapShellColor, #354a5e);background-size:100% auto;background-position:top center;background-repeat:no-repeat;background-attachment:local}.mfp-dashboard{padding:calc(var(--sapShell_Space_XL, 3rem) - 10px);container-type:inline-size;container-name:mfp-dashboard}.mfp-dashboard.edit{padding-bottom:60px}.mfp-sections-container{display:grid;grid-auto-rows:auto;align-content:start;gap:1rem;grid-template-columns:repeat(var(--dashboard-cols-xl, 14),1fr)}@container mfp-dashboard (max-width: 599px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-sm, 1),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-md, 8),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-lg, 12),1fr)}}.mfp-dashboard__topbar{grid-column:1/-1;align-self:start;display:flex;flex-direction:column;gap:1rem;padding-bottom:3rem;width:100%;min-width:0}.mfp-dashboard__topbar-row{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:0 10px}.mfp-dashboard__header{display:flex;flex-direction:column;gap:.25rem}.mfp-dashboard__title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.mfp-dashboard__unsaved-changes{display:inline-flex;align-items:center;gap:.375rem}.mfp-dashboard__unsaved-changes-icon{width:16px;height:16px;color:var(--sapContent_MarkerIconColor)}.mfp-dashboard__unsaved-changes-text{color:var(--sapContent_LabelColor);text-shadow:0 0 2px var(--sapContent_ContrastTextShadow, #fff);font-family:var(--sapFontFamily);font-size:var(--sapFontSize, 14px);font-style:normal;font-weight:400;line-height:normal}.mfp-dashboard__description{font-weight:400;font-family:var(--sapFontFamily)}.mfp-dashboard__description b,.mfp-dashboard__description strong{font-family:var(--sapFontBoldFamily)}.mfp-dashboard__toolbar{flex-shrink:0;display:flex;gap:.5rem}.mfp-dashboard__subheader{display:flex;align-items:center;gap:1rem}.mfp-dashboard__edit-bar{position:fixed;bottom:20px;left:16px;right:16px;z-index:1000;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:7px 16px;background:var(--sapPageFooter_Background, white);border-radius:var(--sapElement_BorderCornerRadius, 12px);box-shadow:0 0 0 1px #2235487a,0 2px 8px #2235484d;box-sizing:border-box;overflow:hidden}@media screen and (min-width:0px)and (max-width:599px){.mfp-dashboard{padding:calc(var(--sapShell_Space_S, 1rem) - 10px)}}@media screen and (min-width:600px)and (max-width:1023px){.mfp-dashboard{padding:calc(var(--sapShell_Space_M, 2rem) - 10px)}}@media screen and (min-width:1024px)and (max-width:1439px){.mfp-dashboard{padding:calc(var(--sapShell_Space_L, 2rem) - 10px)}}.grid-stack.grid-stack-dragging,.grid-stack.grid-stack-dragging *{cursor:grabbing!important}.mfp-dashboard__drag-origin-placeholder{position:absolute;pointer-events:none;z-index:1}.mfp-dashboard__drag-origin-placeholder:before{content:\"\";height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2 - 2px)!important;width:calc(100% - 19px);left:8px!important;position:absolute;background:var(--sapNeutralColor, #6a6d75);border-radius:16px;opacity:.3}gridstack{position:relative}.grid-stack:has(.ui-resizable-resizing),.grid-stack:has(.ui-resizable-resizing) *{cursor:nwse-resize!important}.grid-stack-item>.ui-resizable-handle{background-image:none!important}\n"], dependencies: [{ kind: "component", type: GridstackComponent, selector: "gridstack", inputs: ["options", "isEmpty"], outputs: ["addedCB", "changeCB", "disableCB", "dragCB", "dragStartCB", "dragStopCB", "droppedCB", "enableCB", "removedCB", "resizeCB", "resizeStartCB", "resizeStopCB"] }, { kind: "component", type: GridstackItemComponent, selector: "gridstack-item", inputs: ["options"] }, { kind: "component", type: DiscardChangesDialog, selector: "mfp-discard-changes-dialog", inputs: ["open"], outputs: ["confirm", "cancelled"] }, { kind: "component", type: EditCardsDialog, selector: "mfp-edit-cards-dialog", inputs: ["availableCards", "addedCardsIds", "open"], outputs: ["confirm", "cancelled"] }, { kind: "component", type: UnsavedChangesDialog, selector: "mfp-unsaved-changes-dialog", inputs: ["open"], outputs: ["save", "discard", "cancelled"] }, { kind: "component", type: DashboardSection, selector: "mfp-dashboard-section", inputs: ["section", "cards", "columns", "editMode"], outputs: ["removeSection", "removeCard"] }, { kind: "component", type: DashboardCard, selector: "mfp-dashboard-card", inputs: ["card", "editMode"], outputs: ["removeCard"] }, { kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }, { kind: "component", type: Icon, selector: "ui5-icon, [ui5-icon]", inputs: ["design", "name", "accessibleName", "showTooltip", "mode"], outputs: ["ui5Click"], exportAs: ["ui5Icon"] }, { kind: "component", type: Menu, selector: "ui5-menu, [ui5-menu]", inputs: ["headerText", "open", "placement", "horizontalAlign", "loading", "loadingDelay", "opener"], outputs: ["ui5ItemClick", "ui5BeforeOpen", "ui5Open", "ui5BeforeClose", "ui5Close"], exportAs: ["ui5Menu"] }, { kind: "component", type: MenuItem, selector: "ui5-menu-item, [ui5-menu-item]", inputs: ["text", "additionalText", "icon", "disabled", "loading", "loadingDelay", "accessibleName", "tooltip", "checked", "accessibilityAttributes", "type", "navigated", "highlight", "selected"], outputs: ["ui5BeforeOpen", "ui5Open", "ui5BeforeClose", "ui5Close", "ui5Check", "ui5DetailClick"], exportAs: ["ui5MenuItem"] }, { kind: "component", type: MenuSeparator, selector: "ui5-menu-separator, [ui5-menu-separator]", exportAs: ["ui5MenuSeparator"] }, { kind: "component", type: Title, selector: "ui5-title, [ui5-title]", inputs: ["wrappingType", "level", "size"], exportAs: ["ui5Title"] }], encapsulation: i0.ViewEncapsulation.None });
1911
2387
  }
1912
2388
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: Dashboard, decorators: [{
1913
2389
  type: Component,
@@ -1928,8 +2404,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
1928
2404
  ], providers: [DashboardI18nService], encapsulation: ViewEncapsulation.None, host: {
1929
2405
  '[style.background-image]': 'config().backgroundImageUrl ? "url(" + config().backgroundImageUrl + ")" : null',
1930
2406
  '[style.background-size]': 'backgroundImageHeight() ? "100% " + backgroundImageHeight() + "px" : "100% auto"',
1931
- }, template: "<div class=\"mfp-dashboard\" data-testid=\"dashboard\">\n <div class=\"mfp-dashboard__topbar\">\n <div class=\"mfp-dashboard__topbar-row\">\n <div class=\"mfp-dashboard__header\">\n <div class=\"mfp-dashboard__title-row\">\n @if (config().title) {\n <ui5-title level=\"H3\" size=\"H3\" wrapping-type=\"Normal\" data-testid=\"dashboard-title\">\n <span [innerHTML]=\"safeTitle()\"></span>\n </ui5-title>\n }\n @if (hasUnsavedChanges()) {\n <div class=\"mfp-dashboard__unsaved-changes\" role=\"status\">\n <ui5-icon\n class=\"mfp-dashboard__unsaved-changes-icon\"\n name=\"user-edit\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\"\n />\n <span class=\"mfp-dashboard__unsaved-changes-text\">{{\n i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\n }}</span>\n </div>\n }\n </div>\n @if (config().description) {\n <ui5-title level=\"H5\" size=\"H5\" wrapping-type=\"Normal\" data-testid=\"dashboard-description\">\n <span\n class=\"mfp-dashboard__description\"\n [innerHTML]=\"safeDescription()\"\n ></span>\n </ui5-title>\n }\n </div>\n\n <div class=\"mfp-dashboard__toolbar\">\n @if (editMode()) {\n <ui5-button\n #editCardsBtn\n id=\"edit-cards-btn\"\n data-testid=\"dashboard-edit-cards-btn\"\n [accessibleName]=\"\n editCardsButton().text ||\n editCardsButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_CARDS)\n \"\n [design]=\"editCardsButton().design\"\n [icon]=\"editCardsButton().icon\"\n [tooltip]=\"editCardsButton().tooltip\"\n (click)=\"openCardPanel()\"\n >{{ editCardsButton().text }}</ui5-button\n >\n } @else if (compactToolbar()) {\n <ui5-button\n #menuBtn\n data-testid=\"dashboard-toolbar-menu-btn\"\n design=\"Transparent\"\n icon=\"menu2\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n [tooltip]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n (click)=\"toolbarMenuOpen.update((v) => !v)\"\n />\n <ui5-menu\n data-testid=\"dashboard-toolbar-menu\"\n [open]=\"toolbarMenuOpen()\"\n [opener]=\"menuBtn.element\"\n (ui5Close)=\"toolbarMenuOpen.set(false)\"\n (ui5ItemClick)=\"\n onMenuItemClick(\n $any($event).detail.item.dataset['action'],\n $event\n )\n \"\n (ui5Open)=\"toolbarMenuOpen.set(true)\"\n >\n @if (config().editButtonFirst && config().editable) {\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n @if (customActions().length) {\n <ui5-menu-separator />\n }\n }\n @for (action of customActions(); track action.action) {\n <ui5-menu-item\n [attr.data-action]=\"action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [icon]=\"action.icon ?? ''\"\n [text]=\"action.text ?? ''\"\n />\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-menu-separator />\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n }\n </ui5-menu>\n } @else {\n @if (config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n @for (action of customActions(); track action.action) {\n <ui5-button\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [accessibleName]=\"action.text || action.tooltip || action.action\"\n [design]=\"action.design ?? 'Default'\"\n [endIcon]=\"action?.endIcon\"\n [icon]=\"action.icon ?? ''\"\n [tooltip]=\"action.tooltip ?? ''\"\n (click)=\"\n actionButtonClick.emit({ event: $event, action: action })\n \"\n >{{ action.text }}</ui5-button\n >\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n }\n </div>\n </div>\n\n <div class=\"mfp-dashboard__subheader\">\n <ng-content select=\"[slot=dashboard-subheader]\" />\n </div>\n </div>\n\n <div class=\"mfp-sections-container\">\n @for (section of sections(); track section.id) {\n <mfp-dashboard-section\n [cards]=\"sectionCards()(section.id)\"\n [editMode]=\"editMode()\"\n [section]=\"section\"\n (removeCard)=\"removeCard($event)\"\n (removeSection)=\"removeSection(section.id)\"\n />\n }\n </div>\n\n <gridstack\n #grid\n data-testid=\"dashboard-grid\"\n [options]=\"gridOptions()\"\n (addedCB)=\"onGridChange()\"\n (changeCB)=\"onGridChange()\"\n (removedCB)=\"onGridChange()\"\n >\n @for (card of looseCards(); track card.id) {\n <gridstack-item [options]=\"card\">\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode()\"\n (removeCard)=\"removeCard($any(card.id))\"\n />\n </gridstack-item>\n }\n </gridstack>\n\n</div>\n@if (editMode()) {\n <div class=\"mfp-dashboard__edit-bar\">\n <ui5-button data-testid=\"dashboard-save-btn\" design=\"Emphasized\" (click)=\"saveEdit()\">{{\n i18n.getTranslation(i18nKeys.SAVE)\n }}</ui5-button>\n <ui5-button data-testid=\"dashboard-cancel-btn\" design=\"Transparent\" (click)=\"cancelEdit()\">{{\n i18n.getTranslation(i18nKeys.CANCEL)\n }}</ui5-button>\n </div>\n}\n\n<mfp-edit-cards-dialog\n [addedCardsIds]=\"addedCardsIds()\"\n [availableCards]=\"availableCards()\"\n [open]=\"cardDialogOpen()\"\n (cancelled)=\"closeCardPanel()\"\n (confirm)=\"onCardsEdited($event)\"\n/>\n\n<mfp-discard-changes-dialog\n [open]=\"discardDialogOpen()\"\n (cancelled)=\"cancelDiscard()\"\n (confirm)=\"confirmDiscard()\"\n/>\n\n<mfp-unsaved-changes-dialog\n [open]=\"unsavedNavDialogOpen()\"\n (cancelled)=\"onUnsavedNavCancel()\"\n (discard)=\"onUnsavedNavDiscard()\"\n (save)=\"onUnsavedNavSave()\"\n/>\n", styles: [".grid-stack{position:relative}.grid-stack-placeholder>.placeholder-content{background-color:#0000001a;margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0;top:0;width:var(--gs-column-width);height:var(--gs-cell-height)}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item{right:0}.grid-stack>.grid-stack-item>.grid-stack-item-content,.grid-stack>.grid-stack-placeholder>.placeholder-content{top:var(--gs-item-margin-top);right:var(--gs-item-margin-right);bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;user-select:none;z-index:100}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"%23666\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewBox=\"0 0 20 20\"><path d=\"m10 3 2 2H8l2-2v14l-2-2h4l-2 2\"/></svg>');background-repeat:no-repeat;background-position:center;z-index:101}.grid-stack-item>.ui-resizable-ne{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:var(--gs-item-margin-top);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:var(--gs-item-margin-top);left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:var(--gs-item-margin-top);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px;right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:var(--gs-item-margin-bottom);right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px;left:var(--gs-item-margin-left)}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,right,top}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px #0003;opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,right .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,right 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y=\"0\"]{top:0}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item[gs-x=\"0\"]{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item[gs-x=\"0\"]{right:0}.grid-stack-placeholder .placeholder-content{border-radius:16px;height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2)!important;width:calc(100% - 20px);left:10px!important}mfp-dashboard,mfp-wc-dashboard{display:block;flex:1;margin:0;padding:0;min-height:100%;background:var(--sapShellColor, #354a5e);background-size:100% auto;background-position:top center;background-repeat:no-repeat;background-attachment:local}.mfp-dashboard{padding:calc(var(--sapShell_Space_XL, 3rem) - 10px);container-type:inline-size;container-name:mfp-dashboard}.mfp-sections-container{display:grid;grid-auto-rows:auto;align-content:start;gap:1rem;grid-template-columns:repeat(14,1fr)}@container mfp-dashboard (max-width: 599px){.mfp-sections-container{grid-template-columns:repeat(1,1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.mfp-sections-container{grid-template-columns:repeat(8,1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.mfp-sections-container{grid-template-columns:repeat(12,1fr)}}.mfp-dashboard__topbar{grid-column:1/-1;align-self:start;display:flex;flex-direction:column;gap:1rem;padding-bottom:3rem;width:100%;min-width:0}.mfp-dashboard__topbar-row{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:0 10px}.mfp-dashboard__header{display:flex;flex-direction:column;gap:.25rem}.mfp-dashboard__title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.mfp-dashboard__unsaved-changes{display:inline-flex;align-items:center;gap:.375rem}.mfp-dashboard__unsaved-changes-icon{width:16px;height:16px;color:var(--sapContent_MarkerIconColor)}.mfp-dashboard__unsaved-changes-text{color:var(--sapContent_LabelColor);text-shadow:0 0 2px var(--sapContent_ContrastTextShadow, #fff);font-family:var(--sapFontFamily);font-size:var(--sapFontSize, 14px);font-style:normal;font-weight:400;line-height:normal}.mfp-dashboard__description{font-weight:400;font-family:var(--sapFontFamily)}.mfp-dashboard__description b,.mfp-dashboard__description strong{font-family:var(--sapFontBoldFamily)}.mfp-dashboard__toolbar{flex-shrink:0;display:flex;gap:.5rem}.mfp-dashboard__subheader{display:flex;align-items:center;gap:1rem}.mfp-dashboard__edit-bar{position:fixed;bottom:20px;left:16px;right:16px;z-index:1000;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:7px 16px;background:var(--sapPageFooter_Background, white);border-radius:var(--sapElement_BorderCornerRadius, 12px);box-shadow:0 0 0 1px #2235487a,0 2px 8px #2235484d;box-sizing:border-box;overflow:hidden}@media screen and (min-width:0px)and (max-width:599px){.mfp-dashboard{padding:calc(var(--sapShell_Space_S, 1rem) - 10px)}}@media screen and (min-width:600px)and (max-width:1023px){.mfp-dashboard{padding:calc(var(--sapShell_Space_M, 2rem) - 10px)}}@media screen and (min-width:1024px)and (max-width:1439px){.mfp-dashboard{padding:calc(var(--sapShell_Space_L, 2rem) - 10px)}}.grid-stack.grid-stack-dragging,.grid-stack.grid-stack-dragging *{cursor:grabbing!important}.grid-stack:has(.ui-resizable-resizing),.grid-stack:has(.ui-resizable-resizing) *{cursor:nwse-resize!important}.grid-stack-item>.ui-resizable-handle{background-image:none!important}\n"] }]
1932
- }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }, { type: i0.Output, args: ["sectionsChange"] }], cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: false }] }, { type: i0.Output, args: ["cardsChange"] }], availableCards: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableCards", required: false }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], saved: [{ type: i0.Output, args: ["saved"] }], actionButtonClick: [{ type: i0.Output, args: ["actionButtonClick"] }], unsavedChangesChange: [{ type: i0.Output, args: ["unsavedChangesChange"] }], gridStackItems: [{ type: i0.ViewChild, args: ['grid', { isSignal: true }] }], addCardBtn: [{ type: i0.ViewChild, args: ['editCardsBtn', { isSignal: true }] }] } });
2407
+ }, template: "<div class=\"mfp-dashboard\" data-testid=\"dashboard\" [style]=\"columnVars()\" [class.edit]=\"editMode()\">\n <div class=\"mfp-dashboard__topbar\">\n <div class=\"mfp-dashboard__topbar-row\">\n <div class=\"mfp-dashboard__header\">\n <div class=\"mfp-dashboard__title-row\">\n @if (config().title) {\n <ui5-title data-testid=\"dashboard-title\" level=\"H3\" size=\"H3\" wrapping-type=\"Normal\">\n <span [innerHTML]=\"safeTitle()\"></span>\n </ui5-title>\n }\n @if (hasUnsavedChanges()) {\n <div class=\"mfp-dashboard__unsaved-changes\" role=\"status\">\n <ui5-icon\n class=\"mfp-dashboard__unsaved-changes-icon\"\n name=\"user-edit\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\"\n />\n <span class=\"mfp-dashboard__unsaved-changes-text\">{{\n i18n.getTranslation(i18nKeys.UNSAVED_CHANGES)\n }}</span>\n </div>\n }\n </div>\n @if (config().description) {\n <ui5-title data-testid=\"dashboard-description\" level=\"H5\" size=\"H5\" wrapping-type=\"Normal\">\n <span\n class=\"mfp-dashboard__description\"\n [innerHTML]=\"safeDescription()\"\n ></span>\n </ui5-title>\n }\n </div>\n\n <div class=\"mfp-dashboard__toolbar\">\n @if (editMode()) {\n <ui5-button\n #editCardsBtn\n data-testid=\"dashboard-edit-cards-btn\"\n id=\"edit-cards-btn\"\n [accessibleName]=\"\n editCardsButton().text ||\n editCardsButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_CARDS)\n \"\n [design]=\"editCardsButton().design\"\n [icon]=\"editCardsButton().icon\"\n [tooltip]=\"editCardsButton().tooltip\"\n (click)=\"openCardPanel()\"\n >{{ editCardsButton().text }}</ui5-button\n >\n } @else if (compactToolbar()) {\n <ui5-button\n #menuBtn\n data-testid=\"dashboard-toolbar-menu-btn\"\n design=\"Transparent\"\n icon=\"menu2\"\n [accessibleName]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n [tooltip]=\"i18n.getTranslation(i18nKeys.ACTIONS)\"\n (click)=\"toolbarMenuOpen.update((v) => !v)\"\n />\n <ui5-menu\n data-testid=\"dashboard-toolbar-menu\"\n [open]=\"toolbarMenuOpen()\"\n [opener]=\"menuBtn.element\"\n (ui5Close)=\"toolbarMenuOpen.set(false)\"\n (ui5ItemClick)=\"\n onMenuItemClick(\n $any($event).detail.item.dataset['action'],\n $event\n )\n \"\n (ui5Open)=\"toolbarMenuOpen.set(true)\"\n >\n @if (config().editButtonFirst && config().editable) {\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n @if (customActions().length) {\n <ui5-menu-separator />\n }\n }\n @for (action of customActions(); track action.action) {\n <ui5-menu-item\n [attr.data-action]=\"action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [icon]=\"action.icon ?? ''\"\n [text]=\"action.text ?? ''\"\n />\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-menu-separator />\n <ui5-menu-item\n data-action=\"edit-view\"\n data-testid=\"dashboard-action-edit-view\"\n [icon]=\"editViewButton().icon\"\n [text]=\"\n editViewButton().text ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n />\n }\n </ui5-menu>\n } @else {\n @if (config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n @for (action of customActions(); track action.action) {\n <ui5-button\n [accessibleName]=\"action.text || action.tooltip || action.action\"\n [attr.data-testid]=\"'dashboard-action-' + action.action\"\n [design]=\"action.design ?? 'Default'\"\n [endIcon]=\"action?.endIcon\"\n [icon]=\"action.icon ?? ''\"\n [tooltip]=\"action.tooltip ?? ''\"\n (click)=\"\n actionButtonClick.emit({ event: $event, action: action })\n \"\n >{{ action.text }}</ui5-button\n >\n }\n @if (!config().editButtonFirst && config().editable) {\n <ui5-button\n data-testid=\"dashboard-edit-view-btn\"\n [accessibleName]=\"\n editViewButton().text ||\n editViewButton().tooltip ||\n i18n.getTranslation(i18nKeys.EDIT_VIEW)\n \"\n [design]=\"editViewButton().design\"\n [icon]=\"editViewButton().icon\"\n [tooltip]=\"editViewButton().tooltip\"\n (click)=\"enterEditMode()\"\n >{{ editViewButton().text }}</ui5-button\n >\n }\n }\n </div>\n </div>\n\n <div class=\"mfp-dashboard__subheader\">\n <ng-content select=\"[slot=dashboard-subheader]\" />\n </div>\n </div>\n\n <div class=\"mfp-sections-container\">\n @for (section of sections(); track section.id) {\n <mfp-dashboard-section\n [cards]=\"sectionCards()(section.id)\"\n [editMode]=\"editMode()\"\n [section]=\"section\"\n (removeCard)=\"removeCard($event)\"\n (removeSection)=\"removeSection(section.id)\"\n />\n }\n </div>\n\n <gridstack\n #grid\n data-testid=\"dashboard-grid\"\n [class.zflow-dragging]=\"!!dragOriginStyle()\"\n [options]=\"gridOptions()\"\n (addedCB)=\"onGridChange()\"\n (changeCB)=\"onGridChange()\"\n (dragStartCB)=\"onDragStart($event)\"\n (dragStopCB)=\"onDragStop()\"\n (removedCB)=\"onGridChange()\"\n >\n @if (dragOriginStyle()) {\n <div class=\"mfp-dashboard__drag-origin-placeholder\" [style]=\"dragOriginStyle()\"></div>\n }\n @for (card of looseCards(); track card.id) {\n <gridstack-item [options]=\"card\">\n <mfp-dashboard-card\n [card]=\"card\"\n [editMode]=\"editMode()\"\n (removeCard)=\"removeCard($any(card.id))\"\n />\n </gridstack-item>\n }\n </gridstack>\n\n</div>\n@if (editMode()) {\n <div class=\"mfp-dashboard__edit-bar\">\n <ui5-button data-testid=\"dashboard-save-btn\" design=\"Emphasized\" (click)=\"saveEdit()\">{{\n i18n.getTranslation(i18nKeys.SAVE)\n }}</ui5-button>\n <ui5-button data-testid=\"dashboard-cancel-btn\" design=\"Transparent\" (click)=\"cancelEdit()\">{{\n i18n.getTranslation(i18nKeys.CANCEL)\n }}</ui5-button>\n </div>\n}\n\n<mfp-edit-cards-dialog\n [addedCardsIds]=\"addedCardsIds()\"\n [availableCards]=\"availableCards()\"\n [open]=\"cardDialogOpen()\"\n (cancelled)=\"closeCardPanel()\"\n (confirm)=\"onCardsEdited($event)\"\n/>\n\n<mfp-discard-changes-dialog\n [open]=\"discardDialogOpen()\"\n (cancelled)=\"cancelDiscard()\"\n (confirm)=\"confirmDiscard()\"\n/>\n\n<mfp-unsaved-changes-dialog\n [open]=\"unsavedNavDialogOpen()\"\n (cancelled)=\"onUnsavedNavCancel()\"\n (discard)=\"onUnsavedNavDiscard()\"\n (save)=\"onUnsavedNavSave()\"\n/>\n", styles: [".grid-stack{position:relative}.grid-stack-placeholder>.placeholder-content{background-color:#0000001a;margin:0;position:absolute;width:auto;z-index:0!important}.grid-stack>.grid-stack-item{position:absolute;padding:0;top:0;width:var(--gs-column-width);height:var(--gs-cell-height)}.grid-stack>.grid-stack-item>.grid-stack-item-content{margin:0;position:absolute;width:auto;overflow-x:hidden;overflow-y:auto}.grid-stack>.grid-stack-item.size-to-content:not(.size-to-content-max)>.grid-stack-item-content{overflow-y:hidden}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item{right:0}.grid-stack>.grid-stack-item>.grid-stack-item-content,.grid-stack>.grid-stack-placeholder>.placeholder-content{top:var(--gs-item-margin-top);right:var(--gs-item-margin-right);bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-handle{position:absolute;font-size:.1px;display:block;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;user-select:none;z-index:100}.grid-stack-item.ui-resizable-autohide>.ui-resizable-handle,.grid-stack-item.ui-resizable-disabled>.ui-resizable-handle{display:none}.grid-stack-item>.ui-resizable-ne,.grid-stack-item>.ui-resizable-nw,.grid-stack-item>.ui-resizable-se,.grid-stack-item>.ui-resizable-sw{background-image:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"%23666\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewBox=\"0 0 20 20\"><path d=\"m10 3 2 2H8l2-2v14l-2-2h4l-2 2\"/></svg>');background-repeat:no-repeat;background-position:center;z-index:101}.grid-stack-item>.ui-resizable-ne{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-sw{transform:rotate(45deg)}.grid-stack-item>.ui-resizable-nw{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-se{transform:rotate(-45deg)}.grid-stack-item>.ui-resizable-nw{cursor:nw-resize;width:20px;height:20px;top:var(--gs-item-margin-top);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-n{cursor:n-resize;height:10px;top:var(--gs-item-margin-top);left:25px;right:25px}.grid-stack-item>.ui-resizable-ne{cursor:ne-resize;width:20px;height:20px;top:var(--gs-item-margin-top);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-e{cursor:e-resize;width:10px;top:15px;bottom:15px;right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-se{cursor:se-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);right:var(--gs-item-margin-right)}.grid-stack-item>.ui-resizable-s{cursor:s-resize;height:10px;left:25px;bottom:var(--gs-item-margin-bottom);right:25px}.grid-stack-item>.ui-resizable-sw{cursor:sw-resize;width:20px;height:20px;bottom:var(--gs-item-margin-bottom);left:var(--gs-item-margin-left)}.grid-stack-item>.ui-resizable-w{cursor:w-resize;width:10px;top:15px;bottom:15px;left:var(--gs-item-margin-left)}.grid-stack-item.ui-draggable-dragging>.ui-resizable-handle{display:none!important}.grid-stack-item.ui-draggable-dragging{will-change:left,right,top}.grid-stack-item.ui-resizable-resizing{will-change:width,height}.ui-draggable-dragging,.ui-resizable-resizing{z-index:10000}.ui-draggable-dragging>.grid-stack-item-content,.ui-resizable-resizing>.grid-stack-item-content{box-shadow:1px 4px 6px #0003;opacity:.8}.grid-stack-animate,.grid-stack-animate .grid-stack-item{transition:left .3s,right .3s,top .3s,height .3s,width .3s}.grid-stack-animate .grid-stack-item.grid-stack-placeholder,.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack-animate .grid-stack-item.ui-resizable-resizing{transition:left 0s,right 0s,top 0s,height 0s,width 0s}.grid-stack>.grid-stack-item[gs-y=\"0\"]{top:0}.grid-stack:not(.grid-stack-rtl)>.grid-stack-item[gs-x=\"0\"]{left:0}.grid-stack.grid-stack-rtl>.grid-stack-item[gs-x=\"0\"]{right:0}.grid-stack-placeholder{z-index:2;pointer-events:none}.grid-stack-placeholder .placeholder-content{border-radius:16px;height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2 - 2px)!important;width:calc(100% - 19px);left:8px!important;background:var(--sapContent_Selected_Hover_Background, #E3F0FF);border:1px solid var(--sapContent_DragAndDropActiveColor, #0064D9);z-index:2!important}mfp-dashboard,mfp-wc-dashboard{display:block;flex:1;margin:0;padding:0;min-height:100%;background:var(--sapShellColor, #354a5e);background-size:100% auto;background-position:top center;background-repeat:no-repeat;background-attachment:local}.mfp-dashboard{padding:calc(var(--sapShell_Space_XL, 3rem) - 10px);container-type:inline-size;container-name:mfp-dashboard}.mfp-dashboard.edit{padding-bottom:60px}.mfp-sections-container{display:grid;grid-auto-rows:auto;align-content:start;gap:1rem;grid-template-columns:repeat(var(--dashboard-cols-xl, 14),1fr)}@container mfp-dashboard (max-width: 599px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-sm, 1),1fr)}}@container mfp-dashboard (min-width: 600px) and (max-width: 1023px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-md, 8),1fr)}}@container mfp-dashboard (min-width: 1024px) and (max-width: 1439px){.mfp-sections-container{grid-template-columns:repeat(var(--dashboard-cols-lg, 12),1fr)}}.mfp-dashboard__topbar{grid-column:1/-1;align-self:start;display:flex;flex-direction:column;gap:1rem;padding-bottom:3rem;width:100%;min-width:0}.mfp-dashboard__topbar-row{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:0 10px}.mfp-dashboard__header{display:flex;flex-direction:column;gap:.25rem}.mfp-dashboard__title-row{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}.mfp-dashboard__unsaved-changes{display:inline-flex;align-items:center;gap:.375rem}.mfp-dashboard__unsaved-changes-icon{width:16px;height:16px;color:var(--sapContent_MarkerIconColor)}.mfp-dashboard__unsaved-changes-text{color:var(--sapContent_LabelColor);text-shadow:0 0 2px var(--sapContent_ContrastTextShadow, #fff);font-family:var(--sapFontFamily);font-size:var(--sapFontSize, 14px);font-style:normal;font-weight:400;line-height:normal}.mfp-dashboard__description{font-weight:400;font-family:var(--sapFontFamily)}.mfp-dashboard__description b,.mfp-dashboard__description strong{font-family:var(--sapFontBoldFamily)}.mfp-dashboard__toolbar{flex-shrink:0;display:flex;gap:.5rem}.mfp-dashboard__subheader{display:flex;align-items:center;gap:1rem}.mfp-dashboard__edit-bar{position:fixed;bottom:20px;left:16px;right:16px;z-index:1000;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:7px 16px;background:var(--sapPageFooter_Background, white);border-radius:var(--sapElement_BorderCornerRadius, 12px);box-shadow:0 0 0 1px #2235487a,0 2px 8px #2235484d;box-sizing:border-box;overflow:hidden}@media screen and (min-width:0px)and (max-width:599px){.mfp-dashboard{padding:calc(var(--sapShell_Space_S, 1rem) - 10px)}}@media screen and (min-width:600px)and (max-width:1023px){.mfp-dashboard{padding:calc(var(--sapShell_Space_M, 2rem) - 10px)}}@media screen and (min-width:1024px)and (max-width:1439px){.mfp-dashboard{padding:calc(var(--sapShell_Space_L, 2rem) - 10px)}}.grid-stack.grid-stack-dragging,.grid-stack.grid-stack-dragging *{cursor:grabbing!important}.mfp-dashboard__drag-origin-placeholder{position:absolute;pointer-events:none;z-index:1}.mfp-dashboard__drag-origin-placeholder:before{content:\"\";height:calc(100% - 30px);top:calc(var(--gs-item-margin-top) * 2 - 2px)!important;width:calc(100% - 19px);left:8px!important;position:absolute;background:var(--sapNeutralColor, #6a6d75);border-radius:16px;opacity:.3}gridstack{position:relative}.grid-stack:has(.ui-resizable-resizing),.grid-stack:has(.ui-resizable-resizing) *{cursor:nwse-resize!important}.grid-stack-item>.ui-resizable-handle{background-image:none!important}\n"] }]
2408
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }, { type: i0.Output, args: ["sectionsChange"] }], cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: false }] }, { type: i0.Output, args: ["cardsChange"] }], availableCards: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableCards", required: false }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], saved: [{ type: i0.Output, args: ["saved"] }], actionButtonClick: [{ type: i0.Output, args: ["actionButtonClick"] }], unsavedChangesChange: [{ type: i0.Output, args: ["unsavedChangesChange"] }], gridStack: [{ type: i0.ViewChild, args: ['grid', { isSignal: true }] }], addCardBtn: [{ type: i0.ViewChild, args: ['editCardsBtn', { isSignal: true }] }] } });
1933
2409
 
1934
2410
  class VisitedServiceCard {
1935
2411
  serviceType = input.required(...(ngDevMode ? [{ debugName: "serviceType" }] : /* istanbul ignore next */ []));
@@ -2024,9 +2500,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
2024
2500
  args: [{ selector: 'mfp-whats-new', imports: [List, ListItemStandard, Title], encapsulation: ViewEncapsulation.ShadowDom, template: "<div class=\"whats-new\">\n <ui5-title class=\"whats-new__title\" level=\"H5\">What's New</ui5-title>\n <ui5-list class=\"whats-new__list\" separators=\"Inner\">\n @for (item of headlines; track item.title) {\n <ui5-li [description]=\"item.description\" [icon]=\"item.icon\">\n {{ item.title }}\n </ui5-li>\n }\n </ui5-list>\n</div>\n", styles: [":host{display:block;height:100%}.whats-new{display:flex;flex-direction:column;height:100%;background:var(--sapTile_Background, #fff);border-radius:var(--_ui5_card_border-radius, .5rem);border:var(--_ui5_card_border, 1px solid var(--sapTile_BorderColor, #e5e5e5));box-shadow:var(--_ui5_card_box_shadow, var(--sapContent_Shadow0));overflow:hidden}.whats-new__title{padding:1rem 1rem .5rem;flex-shrink:0}.whats-new__list{flex:1;overflow-y:auto}\n"] }]
2025
2501
  }] });
2026
2502
 
2503
+ class MockCard {
2504
+ title = input('Card Name', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
2505
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MockCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
2506
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: MockCard, isStandalone: true, selector: "mfp-mock-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"mock-card\">\n <div class=\"mock-card__header\">\n <ui5-title class=\"mock-card__title\" level=\"H5\">{{ title() }}</ui5-title>\n <ui5-button\n accessibleName=\"More actions\"\n class=\"mock-card__menu\"\n design=\"Transparent\"\n icon=\"overflow\"\n />\n </div>\n <div class=\"mock-card__body\"></div>\n</div>\n", styles: [":host{display:block;height:100%}.mock-card{display:flex;flex-direction:column;height:100%;background:var(--sapTile_Background, #fff);border-radius:12px;border:var(--_ui5_card_border, 1px solid var(--sapTile_BorderColor, #e5e5e5));box-shadow:var(--_ui5_card_box_shadow, var(--sapContent_Shadow0));overflow:hidden}.mock-card__header{display:flex;align-items:center;justify-content:space-between;padding:.75rem .5rem .75rem 1rem;flex-shrink:0}.mock-card__title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mock-card__menu{flex-shrink:0}.mock-card__body{flex:1;min-height:20rem}\n"], dependencies: [{ kind: "component", type: Button, selector: "ui5-button, [ui5-button]", inputs: ["design", "disabled", "icon", "endIcon", "submits", "tooltip", "accessibleName", "accessibleNameRef", "accessibilityAttributes", "accessibleDescription", "type", "accessibleRole", "loading", "loadingDelay"], outputs: ["ui5Click"], exportAs: ["ui5Button"] }, { kind: "component", type: Title, selector: "ui5-title, [ui5-title]", inputs: ["wrappingType", "level", "size"], exportAs: ["ui5Title"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
2507
+ }
2508
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MockCard, decorators: [{
2509
+ type: Component,
2510
+ args: [{ selector: 'mfp-mock-card', imports: [Button, Title], encapsulation: ViewEncapsulation.ShadowDom, template: "<div class=\"mock-card\">\n <div class=\"mock-card__header\">\n <ui5-title class=\"mock-card__title\" level=\"H5\">{{ title() }}</ui5-title>\n <ui5-button\n accessibleName=\"More actions\"\n class=\"mock-card__menu\"\n design=\"Transparent\"\n icon=\"overflow\"\n />\n </div>\n <div class=\"mock-card__body\"></div>\n</div>\n", styles: [":host{display:block;height:100%}.mock-card{display:flex;flex-direction:column;height:100%;background:var(--sapTile_Background, #fff);border-radius:12px;border:var(--_ui5_card_border, 1px solid var(--sapTile_BorderColor, #e5e5e5));box-shadow:var(--_ui5_card_box_shadow, var(--sapContent_Shadow0));overflow:hidden}.mock-card__header{display:flex;align-items:center;justify-content:space-between;padding:.75rem .5rem .75rem 1rem;flex-shrink:0}.mock-card__title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mock-card__menu{flex-shrink:0}.mock-card__body{flex:1;min-height:20rem}\n"] }]
2511
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }] } });
2512
+
2027
2513
  /**
2028
2514
  * Generated bundle index. Do not edit.
2029
2515
  */
2030
2516
 
2031
- export { BooleanValue, CARD_TYPES, Dashboard, DeclarativeForm, DeclarativeTable, DeclarativeTableCard, Favorites, LinkValue, ResourceField, SecretValue, ServiceStatusCard, TagListValue, VisitedServiceCard, WhatsNew };
2517
+ export { BooleanValue, CARD_TYPES, Dashboard, DeclarativeForm, DeclarativeTable, DeclarativeTableCard, Favorites, LinkValue, MockCard, ResourceField, SecretValue, ServiceStatusCard, TagListValue, VisitedServiceCard, WhatsNew };
2032
2518
  //# sourceMappingURL=openmfp-ngx.mjs.map