@dragonworks/ngx-dashboard 20.3.2 → 21.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
2
1
|
import * as i0 from '@angular/core';
|
|
3
2
|
import { signal, computed, ChangeDetectionStrategy, Component, inject, Injectable, InjectionToken, input, model, output, viewChild, ViewContainerRef, DestroyRef, Renderer2, effect, viewChildren, ElementRef, afterNextRender, PLATFORM_ID, untracked } from '@angular/core';
|
|
4
3
|
import { signalStoreFeature, withState, withMethods, patchState, withComputed, signalStore, withProps } from '@ngrx/signals';
|
|
@@ -20,10 +19,11 @@ import { MatMenuTrigger, MatMenuModule } from '@angular/material/menu';
|
|
|
20
19
|
import * as i3 from '@angular/material/divider';
|
|
21
20
|
import { MatDividerModule } from '@angular/material/divider';
|
|
22
21
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
22
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
23
23
|
|
|
24
24
|
// Auto-generated by scripts/generate-versions.js
|
|
25
25
|
// Do not edit manually
|
|
26
|
-
const NGX_DASHBOARD_VERSION = '
|
|
26
|
+
const NGX_DASHBOARD_VERSION = '21.1.0';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Maximum number of columns supported by the grid.
|
|
@@ -208,6 +208,8 @@ const DEFAULT_RESERVED_SPACE = {
|
|
|
208
208
|
left: 0
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
+
/** Sentinel widget type ID for unresolved/unknown widget types */
|
|
212
|
+
const UNKNOWN_WIDGET_TYPEID = '__internal/unknown-widget';
|
|
211
213
|
function createFactoryFromComponent(component) {
|
|
212
214
|
return {
|
|
213
215
|
...component.metadata,
|
|
@@ -223,7 +225,7 @@ function createFactoryFromComponent(component) {
|
|
|
223
225
|
|
|
224
226
|
class UnknownWidgetComponent {
|
|
225
227
|
static metadata = {
|
|
226
|
-
widgetTypeid:
|
|
228
|
+
widgetTypeid: UNKNOWN_WIDGET_TYPEID,
|
|
227
229
|
name: $localize `:@@ngx.dashboard.unknown.widget.name:Unknown Widget`,
|
|
228
230
|
description: $localize `:@@ngx.dashboard.unknown.widget.description:Fallback widget for unknown widget types`,
|
|
229
231
|
svgIcon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="currentColor"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240Zm40 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z"/></svg>',
|
|
@@ -240,14 +242,14 @@ class UnknownWidgetComponent {
|
|
|
240
242
|
dashboardGetState() {
|
|
241
243
|
return this.state();
|
|
242
244
|
}
|
|
243
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
244
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
245
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: UnknownWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
246
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: UnknownWidgetComponent, isStandalone: true, selector: "lib-unknown-widget", ngImport: i0, template: `
|
|
245
247
|
<div class="unknown-widget-container" [matTooltip]="tooltipText()">
|
|
246
248
|
<mat-icon class="unknown-widget-icon">error_outline</mat-icon>
|
|
247
249
|
</div>
|
|
248
250
|
`, isInline: true, styles: [".unknown-widget-container{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background-color:var(--mat-sys-error);border-radius:8px;container-type:size}.unknown-widget-icon{color:var(--mat-sys-on-error);font-size:clamp(12px,75cqmin,68px);width:clamp(12px,75cqmin,68px);height:clamp(12px,75cqmin,68px)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
249
251
|
}
|
|
250
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: UnknownWidgetComponent, decorators: [{
|
|
251
253
|
type: Component,
|
|
252
254
|
args: [{ selector: 'lib-unknown-widget', imports: [MatIconModule, MatTooltipModule], template: `
|
|
253
255
|
<div class="unknown-widget-container" [matTooltip]="tooltipText()">
|
|
@@ -346,10 +348,10 @@ class DashboardService {
|
|
|
346
348
|
}
|
|
347
349
|
}
|
|
348
350
|
}
|
|
349
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
350
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
351
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
352
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardService, providedIn: 'root' });
|
|
351
353
|
}
|
|
352
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
354
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardService, decorators: [{
|
|
353
355
|
type: Injectable,
|
|
354
356
|
args: [{
|
|
355
357
|
providedIn: 'root',
|
|
@@ -566,10 +568,36 @@ const initialWidgetManagementState = {
|
|
|
566
568
|
widgetsById: {},
|
|
567
569
|
};
|
|
568
570
|
const withWidgetManagement = () => signalStoreFeature(withState(initialWidgetManagementState),
|
|
569
|
-
// Computed cells array -
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
571
|
+
// Computed cells array with self-healing for late-registered widget types.
|
|
572
|
+
// When loadDashboard() runs before all widget types are registered, unresolved
|
|
573
|
+
// cells get an unknown fallback factory. This computed transparently re-resolves
|
|
574
|
+
// them when new types register, so templates see real widgets replace placeholders.
|
|
575
|
+
withComputed((store) => {
|
|
576
|
+
const dashboardService = inject(DashboardService);
|
|
577
|
+
return {
|
|
578
|
+
cells: computed(() => {
|
|
579
|
+
const widgets = Object.values(store.widgetsById());
|
|
580
|
+
const hasUnresolved = widgets.some((cell) => cell.widgetFactory.widgetTypeid === UNKNOWN_WIDGET_TYPEID);
|
|
581
|
+
// Fast path: skip widgetTypes() dependency when all widgets are resolved.
|
|
582
|
+
// This is safe because registerWidgetType() prevents re-registration of
|
|
583
|
+
// existing types, so once healed, a widget's factory cannot change.
|
|
584
|
+
if (!hasUnresolved)
|
|
585
|
+
return widgets;
|
|
586
|
+
// Establishes reactive dependency on registration changes
|
|
587
|
+
dashboardService.widgetTypes();
|
|
588
|
+
return widgets.map((cell) => {
|
|
589
|
+
if (cell.widgetFactory.widgetTypeid === UNKNOWN_WIDGET_TYPEID &&
|
|
590
|
+
cell.widgetTypeid) {
|
|
591
|
+
const resolvedFactory = dashboardService.getFactory(cell.widgetTypeid);
|
|
592
|
+
if (resolvedFactory.widgetTypeid !== UNKNOWN_WIDGET_TYPEID) {
|
|
593
|
+
return { ...cell, widgetFactory: resolvedFactory };
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return cell;
|
|
597
|
+
});
|
|
598
|
+
}),
|
|
599
|
+
};
|
|
600
|
+
}), withMethods((store) => ({
|
|
573
601
|
addWidget(cell) {
|
|
574
602
|
const widgetKey = WidgetIdUtils.toString(cell.widgetId);
|
|
575
603
|
patchState(store, {
|
|
@@ -606,6 +634,7 @@ withComputed((store) => ({
|
|
|
606
634
|
col,
|
|
607
635
|
rowSpan: 1,
|
|
608
636
|
colSpan: 1,
|
|
637
|
+
widgetTypeid: widgetFactory.widgetTypeid,
|
|
609
638
|
widgetFactory,
|
|
610
639
|
widgetState,
|
|
611
640
|
};
|
|
@@ -902,6 +931,10 @@ const withResize = () => signalStoreFeature(withState(initialResizeState), withM
|
|
|
902
931
|
},
|
|
903
932
|
})));
|
|
904
933
|
|
|
934
|
+
/** Returns the intended widget type ID, falling back to the factory's type ID */
|
|
935
|
+
function effectiveWidgetTypeid(cell) {
|
|
936
|
+
return cell.widgetTypeid ?? cell.widgetFactory.widgetTypeid;
|
|
937
|
+
}
|
|
905
938
|
const initialState = {
|
|
906
939
|
dashboardId: '',
|
|
907
940
|
};
|
|
@@ -981,8 +1014,8 @@ withMethods((store) => ({
|
|
|
981
1014
|
}
|
|
982
1015
|
// Collect widget types in use for shared state collection
|
|
983
1016
|
const activeWidgetTypes = new Set(widgetsToExport
|
|
984
|
-
.filter((cell) => cell
|
|
985
|
-
.map((cell) => cell
|
|
1017
|
+
.filter((cell) => effectiveWidgetTypeid(cell) !== UNKNOWN_WIDGET_TYPEID)
|
|
1018
|
+
.map((cell) => effectiveWidgetTypeid(cell)));
|
|
986
1019
|
// Collect shared states from DashboardService
|
|
987
1020
|
const sharedStatesMap = store.dashboardService.collectSharedStates(activeWidgetTypes);
|
|
988
1021
|
const sharedStates = sharedStatesMap.size > 0
|
|
@@ -995,7 +1028,7 @@ withMethods((store) => ({
|
|
|
995
1028
|
columns: exportColumns,
|
|
996
1029
|
gutterSize: store.gutterSize(),
|
|
997
1030
|
cells: widgetsToExport
|
|
998
|
-
.filter((cell) => cell
|
|
1031
|
+
.filter((cell) => effectiveWidgetTypeid(cell) !== UNKNOWN_WIDGET_TYPEID)
|
|
999
1032
|
.map((cell) => {
|
|
1000
1033
|
const cellIdString = CellIdUtils.toString(cell.cellId);
|
|
1001
1034
|
const currentState = liveWidgetStates.get(cellIdString);
|
|
@@ -1008,7 +1041,7 @@ withMethods((store) => ({
|
|
|
1008
1041
|
rowSpan: cell.rowSpan,
|
|
1009
1042
|
colSpan: cell.colSpan,
|
|
1010
1043
|
flat: cell.flat,
|
|
1011
|
-
widgetTypeid: cell
|
|
1044
|
+
widgetTypeid: effectiveWidgetTypeid(cell),
|
|
1012
1045
|
widgetState: currentState !== undefined ? currentState : cell.widgetState,
|
|
1013
1046
|
};
|
|
1014
1047
|
}),
|
|
@@ -1034,6 +1067,7 @@ withMethods((store) => ({
|
|
|
1034
1067
|
rowSpan: cellData.rowSpan,
|
|
1035
1068
|
colSpan: cellData.colSpan,
|
|
1036
1069
|
flat: cellData.flat,
|
|
1070
|
+
widgetTypeid: cellData.widgetTypeid,
|
|
1037
1071
|
widgetFactory: factory,
|
|
1038
1072
|
widgetState: cellData.widgetState,
|
|
1039
1073
|
};
|
|
@@ -1089,145 +1123,144 @@ class CellSettingsDialogComponent {
|
|
|
1089
1123
|
};
|
|
1090
1124
|
this.dialogRef.close(newData);
|
|
1091
1125
|
}
|
|
1092
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1093
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
1094
|
-
<h2 mat-dialog-title i18n="@@ngx.dashboard.cell.settings.title">
|
|
1095
|
-
Cell Display Settings
|
|
1096
|
-
</h2>
|
|
1097
|
-
<mat-dialog-content>
|
|
1098
|
-
<p class="cell-info" i18n="@@ngx.dashboard.cell.settings.cellId">
|
|
1099
|
-
Cell ID: <strong>{{ data.id }}</strong>
|
|
1100
|
-
</p>
|
|
1101
|
-
|
|
1102
|
-
<div class="radio-group">
|
|
1103
|
-
<mat-radio-group [(ngModel)]="selectedMode" name="displayMode">
|
|
1104
|
-
<mat-radio-button value="normal">
|
|
1105
|
-
<div class="radio-option">
|
|
1106
|
-
<div
|
|
1107
|
-
class="option-title"
|
|
1108
|
-
i18n="@@ngx.dashboard.cell.settings.mode.normal"
|
|
1109
|
-
>
|
|
1110
|
-
Normal
|
|
1111
|
-
</div>
|
|
1112
|
-
<div
|
|
1113
|
-
class="option-description"
|
|
1114
|
-
i18n="@@ngx.dashboard.cell.settings.mode.normal.description"
|
|
1115
|
-
>
|
|
1116
|
-
Standard cell display with full content visibility
|
|
1117
|
-
</div>
|
|
1118
|
-
</div>
|
|
1119
|
-
</mat-radio-button>
|
|
1120
|
-
|
|
1121
|
-
<mat-radio-button value="flat">
|
|
1122
|
-
<div class="radio-option">
|
|
1123
|
-
<div
|
|
1124
|
-
class="option-title"
|
|
1125
|
-
i18n="@@ngx.dashboard.cell.settings.mode.flat"
|
|
1126
|
-
>
|
|
1127
|
-
Flat
|
|
1128
|
-
</div>
|
|
1129
|
-
<div
|
|
1130
|
-
class="option-description"
|
|
1131
|
-
i18n="@@ngx.dashboard.cell.settings.mode.flat.description"
|
|
1132
|
-
>
|
|
1133
|
-
Simplified display with reduced visual emphasis
|
|
1134
|
-
</div>
|
|
1135
|
-
</div>
|
|
1136
|
-
</mat-radio-button>
|
|
1137
|
-
</mat-radio-group>
|
|
1138
|
-
</div>
|
|
1139
|
-
</mat-dialog-content>
|
|
1140
|
-
<mat-dialog-actions align="end">
|
|
1141
|
-
<button
|
|
1142
|
-
mat-button
|
|
1143
|
-
(click)="onCancel()"
|
|
1144
|
-
i18n="@@ngx.dashboard.common.cancel"
|
|
1145
|
-
>
|
|
1146
|
-
Cancel
|
|
1147
|
-
</button>
|
|
1148
|
-
<button
|
|
1149
|
-
mat-flat-button
|
|
1150
|
-
(click)="save()"
|
|
1151
|
-
[disabled]="selectedMode === currentMode"
|
|
1152
|
-
i18n="@@ngx.dashboard.common.apply"
|
|
1153
|
-
>
|
|
1154
|
-
Apply
|
|
1155
|
-
</button>
|
|
1156
|
-
</mat-dialog-actions>
|
|
1157
|
-
`, isInline: true, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden;padding-top:.5rem}.cell-info{margin:0 0 1.5rem;padding-bottom:1rem}.radio-group{width:100%}mat-radio-group{display:block}mat-radio-button{width:100%;display:block;margin-bottom:1rem}mat-radio-button:last-child{margin-bottom:0}.radio-option{margin-left:.75rem;padding:.25rem 0}.option-title{display:block;margin-bottom:.25rem}.option-description{display:block}\n"], dependencies: [{ kind: "ngmodule", type:
|
|
1126
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellSettingsDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1127
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: CellSettingsDialogComponent, isStandalone: true, selector: "lib-cell-settings-dialog", ngImport: i0, template: `
|
|
1128
|
+
<h2 mat-dialog-title i18n="@@ngx.dashboard.cell.settings.title">
|
|
1129
|
+
Cell Display Settings
|
|
1130
|
+
</h2>
|
|
1131
|
+
<mat-dialog-content>
|
|
1132
|
+
<p class="cell-info" i18n="@@ngx.dashboard.cell.settings.cellId">
|
|
1133
|
+
Cell ID: <strong>{{ data.id }}</strong>
|
|
1134
|
+
</p>
|
|
1135
|
+
|
|
1136
|
+
<div class="radio-group">
|
|
1137
|
+
<mat-radio-group [(ngModel)]="selectedMode" name="displayMode">
|
|
1138
|
+
<mat-radio-button value="normal">
|
|
1139
|
+
<div class="radio-option">
|
|
1140
|
+
<div
|
|
1141
|
+
class="option-title"
|
|
1142
|
+
i18n="@@ngx.dashboard.cell.settings.mode.normal"
|
|
1143
|
+
>
|
|
1144
|
+
Normal
|
|
1145
|
+
</div>
|
|
1146
|
+
<div
|
|
1147
|
+
class="option-description"
|
|
1148
|
+
i18n="@@ngx.dashboard.cell.settings.mode.normal.description"
|
|
1149
|
+
>
|
|
1150
|
+
Standard cell display with full content visibility
|
|
1151
|
+
</div>
|
|
1152
|
+
</div>
|
|
1153
|
+
</mat-radio-button>
|
|
1154
|
+
|
|
1155
|
+
<mat-radio-button value="flat">
|
|
1156
|
+
<div class="radio-option">
|
|
1157
|
+
<div
|
|
1158
|
+
class="option-title"
|
|
1159
|
+
i18n="@@ngx.dashboard.cell.settings.mode.flat"
|
|
1160
|
+
>
|
|
1161
|
+
Flat
|
|
1162
|
+
</div>
|
|
1163
|
+
<div
|
|
1164
|
+
class="option-description"
|
|
1165
|
+
i18n="@@ngx.dashboard.cell.settings.mode.flat.description"
|
|
1166
|
+
>
|
|
1167
|
+
Simplified display with reduced visual emphasis
|
|
1168
|
+
</div>
|
|
1169
|
+
</div>
|
|
1170
|
+
</mat-radio-button>
|
|
1171
|
+
</mat-radio-group>
|
|
1172
|
+
</div>
|
|
1173
|
+
</mat-dialog-content>
|
|
1174
|
+
<mat-dialog-actions align="end">
|
|
1175
|
+
<button
|
|
1176
|
+
mat-button
|
|
1177
|
+
(click)="onCancel()"
|
|
1178
|
+
i18n="@@ngx.dashboard.common.cancel"
|
|
1179
|
+
>
|
|
1180
|
+
Cancel
|
|
1181
|
+
</button>
|
|
1182
|
+
<button
|
|
1183
|
+
mat-flat-button
|
|
1184
|
+
(click)="save()"
|
|
1185
|
+
[disabled]="selectedMode === currentMode"
|
|
1186
|
+
i18n="@@ngx.dashboard.common.apply"
|
|
1187
|
+
>
|
|
1188
|
+
Apply
|
|
1189
|
+
</button>
|
|
1190
|
+
</mat-dialog-actions>
|
|
1191
|
+
`, isInline: true, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden;padding-top:.5rem}.cell-info{margin:0 0 1.5rem;padding-bottom:1rem}.radio-group{width:100%}mat-radio-group{display:block}mat-radio-button{width:100%;display:block;margin-bottom:1rem}mat-radio-button:last-child{margin-bottom:0}.radio-option{margin-left:.75rem;padding:.25rem 0}.option-title{display:block;margin-bottom:.25rem}.option-description{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i4$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1158
1192
|
}
|
|
1159
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1193
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellSettingsDialogComponent, decorators: [{
|
|
1160
1194
|
type: Component,
|
|
1161
|
-
args: [{ selector: 'lib-cell-settings-dialog',
|
|
1162
|
-
CommonModule,
|
|
1195
|
+
args: [{ selector: 'lib-cell-settings-dialog', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
1163
1196
|
FormsModule,
|
|
1164
1197
|
MatDialogModule,
|
|
1165
1198
|
MatButtonModule,
|
|
1166
|
-
MatRadioModule
|
|
1167
|
-
], template: `
|
|
1168
|
-
<h2 mat-dialog-title i18n="@@ngx.dashboard.cell.settings.title">
|
|
1169
|
-
Cell Display Settings
|
|
1170
|
-
</h2>
|
|
1171
|
-
<mat-dialog-content>
|
|
1172
|
-
<p class="cell-info" i18n="@@ngx.dashboard.cell.settings.cellId">
|
|
1173
|
-
Cell ID: <strong>{{ data.id }}</strong>
|
|
1174
|
-
</p>
|
|
1175
|
-
|
|
1176
|
-
<div class="radio-group">
|
|
1177
|
-
<mat-radio-group [(ngModel)]="selectedMode" name="displayMode">
|
|
1178
|
-
<mat-radio-button value="normal">
|
|
1179
|
-
<div class="radio-option">
|
|
1180
|
-
<div
|
|
1181
|
-
class="option-title"
|
|
1182
|
-
i18n="@@ngx.dashboard.cell.settings.mode.normal"
|
|
1183
|
-
>
|
|
1184
|
-
Normal
|
|
1185
|
-
</div>
|
|
1186
|
-
<div
|
|
1187
|
-
class="option-description"
|
|
1188
|
-
i18n="@@ngx.dashboard.cell.settings.mode.normal.description"
|
|
1189
|
-
>
|
|
1190
|
-
Standard cell display with full content visibility
|
|
1191
|
-
</div>
|
|
1192
|
-
</div>
|
|
1193
|
-
</mat-radio-button>
|
|
1194
|
-
|
|
1195
|
-
<mat-radio-button value="flat">
|
|
1196
|
-
<div class="radio-option">
|
|
1197
|
-
<div
|
|
1198
|
-
class="option-title"
|
|
1199
|
-
i18n="@@ngx.dashboard.cell.settings.mode.flat"
|
|
1200
|
-
>
|
|
1201
|
-
Flat
|
|
1202
|
-
</div>
|
|
1203
|
-
<div
|
|
1204
|
-
class="option-description"
|
|
1205
|
-
i18n="@@ngx.dashboard.cell.settings.mode.flat.description"
|
|
1206
|
-
>
|
|
1207
|
-
Simplified display with reduced visual emphasis
|
|
1208
|
-
</div>
|
|
1209
|
-
</div>
|
|
1210
|
-
</mat-radio-button>
|
|
1211
|
-
</mat-radio-group>
|
|
1212
|
-
</div>
|
|
1213
|
-
</mat-dialog-content>
|
|
1214
|
-
<mat-dialog-actions align="end">
|
|
1215
|
-
<button
|
|
1216
|
-
mat-button
|
|
1217
|
-
(click)="onCancel()"
|
|
1218
|
-
i18n="@@ngx.dashboard.common.cancel"
|
|
1219
|
-
>
|
|
1220
|
-
Cancel
|
|
1221
|
-
</button>
|
|
1222
|
-
<button
|
|
1223
|
-
mat-flat-button
|
|
1224
|
-
(click)="save()"
|
|
1225
|
-
[disabled]="selectedMode === currentMode"
|
|
1226
|
-
i18n="@@ngx.dashboard.common.apply"
|
|
1227
|
-
>
|
|
1228
|
-
Apply
|
|
1229
|
-
</button>
|
|
1230
|
-
</mat-dialog-actions>
|
|
1199
|
+
MatRadioModule
|
|
1200
|
+
], template: `
|
|
1201
|
+
<h2 mat-dialog-title i18n="@@ngx.dashboard.cell.settings.title">
|
|
1202
|
+
Cell Display Settings
|
|
1203
|
+
</h2>
|
|
1204
|
+
<mat-dialog-content>
|
|
1205
|
+
<p class="cell-info" i18n="@@ngx.dashboard.cell.settings.cellId">
|
|
1206
|
+
Cell ID: <strong>{{ data.id }}</strong>
|
|
1207
|
+
</p>
|
|
1208
|
+
|
|
1209
|
+
<div class="radio-group">
|
|
1210
|
+
<mat-radio-group [(ngModel)]="selectedMode" name="displayMode">
|
|
1211
|
+
<mat-radio-button value="normal">
|
|
1212
|
+
<div class="radio-option">
|
|
1213
|
+
<div
|
|
1214
|
+
class="option-title"
|
|
1215
|
+
i18n="@@ngx.dashboard.cell.settings.mode.normal"
|
|
1216
|
+
>
|
|
1217
|
+
Normal
|
|
1218
|
+
</div>
|
|
1219
|
+
<div
|
|
1220
|
+
class="option-description"
|
|
1221
|
+
i18n="@@ngx.dashboard.cell.settings.mode.normal.description"
|
|
1222
|
+
>
|
|
1223
|
+
Standard cell display with full content visibility
|
|
1224
|
+
</div>
|
|
1225
|
+
</div>
|
|
1226
|
+
</mat-radio-button>
|
|
1227
|
+
|
|
1228
|
+
<mat-radio-button value="flat">
|
|
1229
|
+
<div class="radio-option">
|
|
1230
|
+
<div
|
|
1231
|
+
class="option-title"
|
|
1232
|
+
i18n="@@ngx.dashboard.cell.settings.mode.flat"
|
|
1233
|
+
>
|
|
1234
|
+
Flat
|
|
1235
|
+
</div>
|
|
1236
|
+
<div
|
|
1237
|
+
class="option-description"
|
|
1238
|
+
i18n="@@ngx.dashboard.cell.settings.mode.flat.description"
|
|
1239
|
+
>
|
|
1240
|
+
Simplified display with reduced visual emphasis
|
|
1241
|
+
</div>
|
|
1242
|
+
</div>
|
|
1243
|
+
</mat-radio-button>
|
|
1244
|
+
</mat-radio-group>
|
|
1245
|
+
</div>
|
|
1246
|
+
</mat-dialog-content>
|
|
1247
|
+
<mat-dialog-actions align="end">
|
|
1248
|
+
<button
|
|
1249
|
+
mat-button
|
|
1250
|
+
(click)="onCancel()"
|
|
1251
|
+
i18n="@@ngx.dashboard.common.cancel"
|
|
1252
|
+
>
|
|
1253
|
+
Cancel
|
|
1254
|
+
</button>
|
|
1255
|
+
<button
|
|
1256
|
+
mat-flat-button
|
|
1257
|
+
(click)="save()"
|
|
1258
|
+
[disabled]="selectedMode === currentMode"
|
|
1259
|
+
i18n="@@ngx.dashboard.common.apply"
|
|
1260
|
+
>
|
|
1261
|
+
Apply
|
|
1262
|
+
</button>
|
|
1263
|
+
</mat-dialog-actions>
|
|
1231
1264
|
`, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden;padding-top:.5rem}.cell-info{margin:0 0 1.5rem;padding-bottom:1rem}.radio-group{width:100%}mat-radio-group{display:block}mat-radio-button{width:100%;display:block;margin-bottom:1rem}mat-radio-button:last-child{margin-bottom:0}.radio-option{margin-left:.75rem;padding:.25rem 0}.option-title{display:block;margin-bottom:.25rem}.option-description{display:block}\n"] }]
|
|
1232
1265
|
}], ctorParameters: () => [] });
|
|
1233
1266
|
|
|
@@ -1248,10 +1281,10 @@ class DefaultCellSettingsDialogProvider extends CellSettingsDialogProvider {
|
|
|
1248
1281
|
const result = await firstValueFrom(dialogRef.afterClosed());
|
|
1249
1282
|
return result;
|
|
1250
1283
|
}
|
|
1251
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1252
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1284
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultCellSettingsDialogProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
1285
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultCellSettingsDialogProvider, providedIn: 'root' });
|
|
1253
1286
|
}
|
|
1254
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultCellSettingsDialogProvider, decorators: [{
|
|
1255
1288
|
type: Injectable,
|
|
1256
1289
|
args: [{
|
|
1257
1290
|
providedIn: 'root',
|
|
@@ -1283,10 +1316,10 @@ class CellContextMenuService {
|
|
|
1283
1316
|
hide() {
|
|
1284
1317
|
this.#activeMenu.set(null);
|
|
1285
1318
|
}
|
|
1286
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1287
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1319
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellContextMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1320
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellContextMenuService });
|
|
1288
1321
|
}
|
|
1289
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellContextMenuService, decorators: [{
|
|
1290
1323
|
type: Injectable
|
|
1291
1324
|
}] });
|
|
1292
1325
|
|
|
@@ -1571,19 +1604,19 @@ class CellComponent {
|
|
|
1571
1604
|
// Fall back to stored state if widget doesn't implement dashboardGetState
|
|
1572
1605
|
return this.widgetState();
|
|
1573
1606
|
}
|
|
1574
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1575
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1607
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1608
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: CellComponent, isStandalone: true, selector: "lib-cell", inputs: { widgetId: { classPropertyName: "widgetId", publicName: "widgetId", isSignal: true, isRequired: true, transformFunction: null }, cellId: { classPropertyName: "cellId", publicName: "cellId", isSignal: true, isRequired: true, transformFunction: null }, widgetFactory: { classPropertyName: "widgetFactory", publicName: "widgetFactory", isSignal: true, isRequired: false, transformFunction: null }, widgetState: { classPropertyName: "widgetState", publicName: "widgetState", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: false, transformFunction: null }, flat: { classPropertyName: "flat", publicName: "flat", isSignal: true, isRequired: false, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, rowSpan: { classPropertyName: "rowSpan", publicName: "rowSpan", isSignal: true, isRequired: false, transformFunction: null }, colSpan: { classPropertyName: "colSpan", publicName: "colSpan", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { row: "rowChange", column: "columnChange", dragStart: "dragStart", dragEnd: "dragEnd", edit: "edit", delete: "delete", settings: "settings", resizeStart: "resizeStart", resizeMove: "resizeMove", resizeEnd: "resizeEnd" }, host: { properties: { "style.grid-row": "gridRowStyle()", "style.grid-column": "gridColumnStyle()", "class.is-dragging": "isDragging()", "class.drag-active": "isDragActive()", "class.flat": "flat() === true" } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "<!-- cell.component.html -->\n<div\n class=\"cell\"\n [class.is-resizing]=\"isResizing()\"\n [class.flat]=\"flat() === true\"\n [draggable]=\"draggable()\"\n (dragstart)=\"onDragStart($event)\"\n (dragend)=\"onDragEnd()\"\n (contextmenu)=\"onContextMenu($event)\"\n>\n <div class=\"content-area\">\n <ng-template #container></ng-template>\n </div>\n @if (isEditMode() && !isDragging()) {\n <!-- Right resize handle -->\n <div\n class=\"resize-handle resize-handle--right\"\n (mousedown)=\"onResizeStart($event, 'horizontal')\"\n >\n <div class=\"resize-handle-line\"></div>\n </div>\n <!-- Bottom resize handle -->\n <div\n class=\"resize-handle resize-handle--bottom\"\n (mousedown)=\"onResizeStart($event, 'vertical')\"\n >\n <div class=\"resize-handle-line\"></div>\n </div>\n }\n</div>\n\n@if (isResizing()) {\n<div class=\"resize-preview\" i18n=\"@@ngx.dashboard.cell.resize.dimensions\">\n {{ resizeData()?.previewColSpan ?? colSpan() }} \u00D7\n {{ resizeData()?.previewRowSpan ?? rowSpan() }}\n</div>\n}\n", styles: [":host{display:block;width:100%;height:100%;position:relative;z-index:1;container-type:inline-size}:host(.drag-active):not(.is-dragging){pointer-events:none}:host(.is-dragging){z-index:100;opacity:.5;pointer-events:none}:host(.is-dragging) .content-area{pointer-events:none}:host(:hover) .resize-handle{opacity:1}.cell{width:100%;height:100%;border-radius:4px;box-shadow:0 2px 6px #0000001a;padding:0;box-sizing:border-box;overflow:hidden;position:relative;container-type:inline-size}.cell:hover{box-shadow:0 4px 10px #00000026;transform:translateY(-2px)}.cell.flat{box-shadow:none;border:none}.cell.flat:hover{box-shadow:none;transform:none;border-color:#bdbdbd}.cell.resizing{-webkit-user-select:none;user-select:none}.content-area{width:100%;height:100%;overflow:auto;pointer-events:auto;position:relative;z-index:1}.content-area:hover{transform:initial}:host(:not(.is-dragging)) .cell.flat .content-area{pointer-events:auto}:host(:not(.is-dragging)) .cell.flat .content-area:hover{transform:initial}.resize-handle{position:absolute;z-index:20}.resize-handle--right{cursor:col-resize;width:16px;height:100%;right:-8px;top:0;display:flex;align-items:center;justify-content:center;opacity:0}.resize-handle--right:hover{opacity:1}.resize-handle--right:hover .resize-handle-line{background-color:var(--mat-sys-primary-container)}.resize-handle--bottom{cursor:row-resize;width:100%;height:16px;bottom:-8px;left:0;display:flex;align-items:center;justify-content:center;opacity:0}.resize-handle--bottom:hover{opacity:1}.resize-handle--bottom:hover .resize-handle-line{background-color:var(--mat-sys-primary-container)}.resize-handle-line{background-color:#0000001a}.resize-handle--right .resize-handle-line{width:8px;height:40px;border-radius:2px}.resize-handle--bottom .resize-handle-line{width:40px;height:8px;border-radius:2px}.resize-preview{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background-color:var(--mat-sys-primary);color:var(--mat-sys-on-primary);padding:4px 12px;border-radius:4px;font-size:14px;font-weight:500;pointer-events:none;z-index:30}.cell.is-resizing{opacity:.6}.cell.is-resizing .resize-handle{background-color:#2196f380}:root .cursor-col-resize{cursor:col-resize!important}:root .cursor-row-resize{cursor:row-resize!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1576
1609
|
}
|
|
1577
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1610
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellComponent, decorators: [{
|
|
1578
1611
|
type: Component,
|
|
1579
|
-
args: [{ selector: 'lib-cell', standalone: true, imports: [
|
|
1612
|
+
args: [{ selector: 'lib-cell', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1580
1613
|
'[style.grid-row]': 'gridRowStyle()',
|
|
1581
1614
|
'[style.grid-column]': 'gridColumnStyle()',
|
|
1582
1615
|
'[class.is-dragging]': 'isDragging()',
|
|
1583
1616
|
'[class.drag-active]': 'isDragActive()',
|
|
1584
1617
|
'[class.flat]': 'flat() === true',
|
|
1585
|
-
}, template: "<!-- cell.component.html -->\
|
|
1586
|
-
}], ctorParameters: () => [] });
|
|
1618
|
+
}, template: "<!-- cell.component.html -->\n<div\n class=\"cell\"\n [class.is-resizing]=\"isResizing()\"\n [class.flat]=\"flat() === true\"\n [draggable]=\"draggable()\"\n (dragstart)=\"onDragStart($event)\"\n (dragend)=\"onDragEnd()\"\n (contextmenu)=\"onContextMenu($event)\"\n>\n <div class=\"content-area\">\n <ng-template #container></ng-template>\n </div>\n @if (isEditMode() && !isDragging()) {\n <!-- Right resize handle -->\n <div\n class=\"resize-handle resize-handle--right\"\n (mousedown)=\"onResizeStart($event, 'horizontal')\"\n >\n <div class=\"resize-handle-line\"></div>\n </div>\n <!-- Bottom resize handle -->\n <div\n class=\"resize-handle resize-handle--bottom\"\n (mousedown)=\"onResizeStart($event, 'vertical')\"\n >\n <div class=\"resize-handle-line\"></div>\n </div>\n }\n</div>\n\n@if (isResizing()) {\n<div class=\"resize-preview\" i18n=\"@@ngx.dashboard.cell.resize.dimensions\">\n {{ resizeData()?.previewColSpan ?? colSpan() }} \u00D7\n {{ resizeData()?.previewRowSpan ?? rowSpan() }}\n</div>\n}\n", styles: [":host{display:block;width:100%;height:100%;position:relative;z-index:1;container-type:inline-size}:host(.drag-active):not(.is-dragging){pointer-events:none}:host(.is-dragging){z-index:100;opacity:.5;pointer-events:none}:host(.is-dragging) .content-area{pointer-events:none}:host(:hover) .resize-handle{opacity:1}.cell{width:100%;height:100%;border-radius:4px;box-shadow:0 2px 6px #0000001a;padding:0;box-sizing:border-box;overflow:hidden;position:relative;container-type:inline-size}.cell:hover{box-shadow:0 4px 10px #00000026;transform:translateY(-2px)}.cell.flat{box-shadow:none;border:none}.cell.flat:hover{box-shadow:none;transform:none;border-color:#bdbdbd}.cell.resizing{-webkit-user-select:none;user-select:none}.content-area{width:100%;height:100%;overflow:auto;pointer-events:auto;position:relative;z-index:1}.content-area:hover{transform:initial}:host(:not(.is-dragging)) .cell.flat .content-area{pointer-events:auto}:host(:not(.is-dragging)) .cell.flat .content-area:hover{transform:initial}.resize-handle{position:absolute;z-index:20}.resize-handle--right{cursor:col-resize;width:16px;height:100%;right:-8px;top:0;display:flex;align-items:center;justify-content:center;opacity:0}.resize-handle--right:hover{opacity:1}.resize-handle--right:hover .resize-handle-line{background-color:var(--mat-sys-primary-container)}.resize-handle--bottom{cursor:row-resize;width:100%;height:16px;bottom:-8px;left:0;display:flex;align-items:center;justify-content:center;opacity:0}.resize-handle--bottom:hover{opacity:1}.resize-handle--bottom:hover .resize-handle-line{background-color:var(--mat-sys-primary-container)}.resize-handle-line{background-color:#0000001a}.resize-handle--right .resize-handle-line{width:8px;height:40px;border-radius:2px}.resize-handle--bottom .resize-handle-line{width:40px;height:8px;border-radius:2px}.resize-preview{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background-color:var(--mat-sys-primary);color:var(--mat-sys-on-primary);padding:4px 12px;border-radius:4px;font-size:14px;font-weight:500;pointer-events:none;z-index:30}.cell.is-resizing{opacity:.6}.cell.is-resizing .resize-handle{background-color:#2196f380}:root .cursor-col-resize{cursor:col-resize!important}:root .cursor-row-resize{cursor:row-resize!important}\n"] }]
|
|
1619
|
+
}], ctorParameters: () => [], propDecorators: { widgetId: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetId", required: true }] }], cellId: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellId", required: true }] }], widgetFactory: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetFactory", required: false }] }], widgetState: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetState", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: false }] }], flat: [{ type: i0.Input, args: [{ isSignal: true, alias: "flat", required: false }] }], row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }, { type: i0.Output, args: ["rowChange"] }], column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }, { type: i0.Output, args: ["columnChange"] }], rowSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSpan", required: false }] }], colSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "colSpan", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], dragEnd: [{ type: i0.Output, args: ["dragEnd"] }], edit: [{ type: i0.Output, args: ["edit"] }], delete: [{ type: i0.Output, args: ["delete"] }], settings: [{ type: i0.Output, args: ["settings"] }], resizeStart: [{ type: i0.Output, args: ["resizeStart"] }], resizeMove: [{ type: i0.Output, args: ["resizeMove"] }], resizeEnd: [{ type: i0.Output, args: ["resizeEnd"] }], container: [{ type: i0.ViewChild, args: ['container', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
|
|
1587
1620
|
|
|
1588
1621
|
class DashboardViewerComponent {
|
|
1589
1622
|
#store = inject(DashboardStore);
|
|
@@ -1725,18 +1758,18 @@ class DashboardViewerComponent {
|
|
|
1725
1758
|
this.#mouseUpListener = undefined;
|
|
1726
1759
|
}
|
|
1727
1760
|
}
|
|
1728
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1729
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1761
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1762
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: DashboardViewerComponent, isStandalone: true, selector: "ngx-dashboard-viewer", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null }, enableSelection: { classPropertyName: "enableSelection", publicName: "enableSelection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionComplete: "selectionComplete" }, host: { properties: { "style.--rows": "rows()", "style.--columns": "columns()", "style.--gutter-size": "gutterSize()", "style.--gutters": "gutters()" } }, viewQueries: [{ propertyName: "cellComponents", predicate: CellComponent, descendants: true, isSignal: true }, { propertyName: "gridElement", first: true, predicate: ["gridElement"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Dashboard viewer - read-only grid -->\n<div class=\"grid top-grid\" #gridElement>\n @for (cell of cells(); track cell.widgetId) {\n <lib-cell\n class=\"grid-cell\"\n [widgetId]=\"cell.widgetId\"\n [cellId]=\"cell.cellId\"\n [isEditMode]=\"false\"\n [draggable]=\"false\"\n [row]=\"cell.row\"\n [column]=\"cell.col\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [flat]=\"cell.flat\"\n [widgetFactory]=\"cell.widgetFactory\"\n [widgetState]=\"cell.widgetState\"\n >\n </lib-cell>\n }\n</div>\n\n<!-- Selection overlay grid - mirror of main grid for cell selection -->\n@if (enableSelection()) {\n <div class=\"selection-overlay-grid\">\n @for (row of rowNumbers(); track row) {\n @for (col of colNumbers(); track col) {\n <div\n class=\"selection-ghost-cell\"\n [class.selected]=\"isCellSelected(row, col)\"\n [class.selecting]=\"isSelecting()\"\n [style.grid-row]=\"row\"\n [style.grid-column]=\"col\"\n (mousedown)=\"onGhostCellMouseDown($event, row, col)\"\n (mouseenter)=\"onGhostCellMouseEnter(row, col)\"\n ></div>\n }\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{--cell-size: calc( 100cqi / var(--columns) - var(--gutter-size) * var(--gutters) / var(--columns) );--tile-size: calc(var(--cell-size) + var(--gutter-size));--tile-offset: calc( var(--gutter-size) + var(--cell-size) + var(--gutter-size) / 2 );display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto;position:relative;background-color:var(--mat-sys-surface-container)}.grid{display:grid;gap:var(--gutter-size);padding:var(--gutter-size);width:100%;height:100%;box-sizing:border-box;grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size))}.grid-cell{pointer-events:none}.grid-cell:not(.flat){pointer-events:auto;cursor:default}.grid-cell:not(.flat) .content-area{pointer-events:none}.top-grid{z-index:2;pointer-events:none}.selection-overlay-grid{position:absolute;top:0;left:0;width:100%;height:100%;display:grid;gap:var(--gutter-size);padding:var(--gutter-size);grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size));z-index:5;pointer-events:auto;-webkit-user-select:none;user-select:none}.selection-ghost-cell{cursor:crosshair;transition:background-color .1s ease,border-radius .1s ease;border-radius:2px}.selection-ghost-cell:hover:not(.selecting){background-color:var(--mat-sys-primary);opacity:.08}.selection-ghost-cell.selected{background-color:var(--mat-sys-primary);opacity:.25;border-radius:4px}.selection-ghost-cell.selecting{cursor:crosshair}\n"], dependencies: [{ kind: "component", type: CellComponent, selector: "lib-cell", inputs: ["widgetId", "cellId", "widgetFactory", "widgetState", "isEditMode", "flat", "row", "column", "rowSpan", "colSpan", "draggable"], outputs: ["rowChange", "columnChange", "dragStart", "dragEnd", "edit", "delete", "settings", "resizeStart", "resizeMove", "resizeEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1730
1763
|
}
|
|
1731
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1764
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardViewerComponent, decorators: [{
|
|
1732
1765
|
type: Component,
|
|
1733
|
-
args: [{ selector: 'ngx-dashboard-viewer', standalone: true, imports: [CellComponent
|
|
1766
|
+
args: [{ selector: 'ngx-dashboard-viewer', standalone: true, imports: [CellComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1734
1767
|
'[style.--rows]': 'rows()',
|
|
1735
1768
|
'[style.--columns]': 'columns()',
|
|
1736
1769
|
'[style.--gutter-size]': 'gutterSize()',
|
|
1737
1770
|
'[style.--gutters]': 'gutters()',
|
|
1738
|
-
}, template: "<!-- Dashboard viewer - read-only grid -->\
|
|
1739
|
-
}], ctorParameters: () => [] });
|
|
1771
|
+
}, template: "<!-- Dashboard viewer - read-only grid -->\n<div class=\"grid top-grid\" #gridElement>\n @for (cell of cells(); track cell.widgetId) {\n <lib-cell\n class=\"grid-cell\"\n [widgetId]=\"cell.widgetId\"\n [cellId]=\"cell.cellId\"\n [isEditMode]=\"false\"\n [draggable]=\"false\"\n [row]=\"cell.row\"\n [column]=\"cell.col\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [flat]=\"cell.flat\"\n [widgetFactory]=\"cell.widgetFactory\"\n [widgetState]=\"cell.widgetState\"\n >\n </lib-cell>\n }\n</div>\n\n<!-- Selection overlay grid - mirror of main grid for cell selection -->\n@if (enableSelection()) {\n <div class=\"selection-overlay-grid\">\n @for (row of rowNumbers(); track row) {\n @for (col of colNumbers(); track col) {\n <div\n class=\"selection-ghost-cell\"\n [class.selected]=\"isCellSelected(row, col)\"\n [class.selecting]=\"isSelecting()\"\n [style.grid-row]=\"row\"\n [style.grid-column]=\"col\"\n (mousedown)=\"onGhostCellMouseDown($event, row, col)\"\n (mouseenter)=\"onGhostCellMouseEnter(row, col)\"\n ></div>\n }\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{--cell-size: calc( 100cqi / var(--columns) - var(--gutter-size) * var(--gutters) / var(--columns) );--tile-size: calc(var(--cell-size) + var(--gutter-size));--tile-offset: calc( var(--gutter-size) + var(--cell-size) + var(--gutter-size) / 2 );display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto;position:relative;background-color:var(--mat-sys-surface-container)}.grid{display:grid;gap:var(--gutter-size);padding:var(--gutter-size);width:100%;height:100%;box-sizing:border-box;grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size))}.grid-cell{pointer-events:none}.grid-cell:not(.flat){pointer-events:auto;cursor:default}.grid-cell:not(.flat) .content-area{pointer-events:none}.top-grid{z-index:2;pointer-events:none}.selection-overlay-grid{position:absolute;top:0;left:0;width:100%;height:100%;display:grid;gap:var(--gutter-size);padding:var(--gutter-size);grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size));z-index:5;pointer-events:auto;-webkit-user-select:none;user-select:none}.selection-ghost-cell{cursor:crosshair;transition:background-color .1s ease,border-radius .1s ease;border-radius:2px}.selection-ghost-cell:hover:not(.selecting){background-color:var(--mat-sys-primary);opacity:.08}.selection-ghost-cell.selected{background-color:var(--mat-sys-primary);opacity:.25;border-radius:4px}.selection-ghost-cell.selecting{cursor:crosshair}\n"] }]
|
|
1772
|
+
}], ctorParameters: () => [], propDecorators: { cellComponents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => CellComponent), { isSignal: true }] }], gridElement: [{ type: i0.ViewChild, args: ['gridElement', { isSignal: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], gutterSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterSize", required: false }] }], enableSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSelection", required: false }] }], selectionComplete: [{ type: i0.Output, args: ["selectionComplete"] }] } });
|
|
1740
1773
|
|
|
1741
1774
|
class CellContextMenuComponent {
|
|
1742
1775
|
menuTrigger = viewChild.required('menuTrigger', { read: MatMenuTrigger });
|
|
@@ -1811,8 +1844,8 @@ class CellContextMenuComponent {
|
|
|
1811
1844
|
this.menuService.hide();
|
|
1812
1845
|
}
|
|
1813
1846
|
}
|
|
1814
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1815
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1847
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1848
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: CellContextMenuComponent, isStandalone: true, selector: "lib-cell-context-menu", viewQueries: [{ propertyName: "menuTrigger", first: true, predicate: ["menuTrigger"], descendants: true, read: MatMenuTrigger, isSignal: true }], ngImport: i0, template: `
|
|
1816
1849
|
<!-- Hidden trigger for menu positioned at exact mouse coordinates
|
|
1817
1850
|
|
|
1818
1851
|
IMPORTANT: Angular Material applies its own positioning logic to menus,
|
|
@@ -1866,7 +1899,7 @@ class CellContextMenuComponent {
|
|
|
1866
1899
|
</mat-menu>
|
|
1867
1900
|
`, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1868
1901
|
}
|
|
1869
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1902
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CellContextMenuComponent, decorators: [{
|
|
1870
1903
|
type: Component,
|
|
1871
1904
|
args: [{ selector: 'lib-cell-context-menu', standalone: true, imports: [MatMenuModule, MatIconModule, MatDividerModule, MatButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1872
1905
|
<!-- Hidden trigger for menu positioned at exact mouse coordinates
|
|
@@ -1921,7 +1954,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
|
|
|
1921
1954
|
}
|
|
1922
1955
|
</mat-menu>
|
|
1923
1956
|
`, styles: [":host{display:contents}\n"] }]
|
|
1924
|
-
}], ctorParameters: () => [] });
|
|
1957
|
+
}], ctorParameters: () => [], propDecorators: { menuTrigger: [{ type: i0.ViewChild, args: ['menuTrigger', { ...{ read: MatMenuTrigger }, isSignal: true }] }] } });
|
|
1925
1958
|
|
|
1926
1959
|
/**
|
|
1927
1960
|
* Abstract provider for handling context menu events on empty dashboard cells.
|
|
@@ -1957,10 +1990,10 @@ class DefaultEmptyCellContextProvider extends EmptyCellContextProvider {
|
|
|
1957
1990
|
handleEmptyCellContext() {
|
|
1958
1991
|
// Default behavior: do nothing
|
|
1959
1992
|
}
|
|
1960
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1961
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1993
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultEmptyCellContextProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
1994
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultEmptyCellContextProvider, providedIn: 'root' });
|
|
1962
1995
|
}
|
|
1963
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1996
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DefaultEmptyCellContextProvider, decorators: [{
|
|
1964
1997
|
type: Injectable,
|
|
1965
1998
|
args: [{
|
|
1966
1999
|
providedIn: 'root',
|
|
@@ -2024,10 +2057,10 @@ class EmptyCellContextMenuService {
|
|
|
2024
2057
|
setLastSelection(widgetTypeId) {
|
|
2025
2058
|
this.#lastSelectedWidgetTypeId.set(widgetTypeId);
|
|
2026
2059
|
}
|
|
2027
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2028
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2060
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: EmptyCellContextMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2061
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: EmptyCellContextMenuService, providedIn: 'root' });
|
|
2029
2062
|
}
|
|
2030
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2063
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: EmptyCellContextMenuService, decorators: [{
|
|
2031
2064
|
type: Injectable,
|
|
2032
2065
|
args: [{
|
|
2033
2066
|
providedIn: 'root',
|
|
@@ -2142,10 +2175,10 @@ class WidgetListContextMenuProvider extends EmptyCellContextProvider {
|
|
|
2142
2175
|
'Ensure you are using a compatible version of the dashboard component.');
|
|
2143
2176
|
}
|
|
2144
2177
|
}
|
|
2145
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2146
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2178
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: WidgetListContextMenuProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
2179
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: WidgetListContextMenuProvider });
|
|
2147
2180
|
}
|
|
2148
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2181
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: WidgetListContextMenuProvider, decorators: [{
|
|
2149
2182
|
type: Injectable
|
|
2150
2183
|
}] });
|
|
2151
2184
|
|
|
@@ -2258,13 +2291,13 @@ class DropZoneComponent {
|
|
|
2258
2291
|
});
|
|
2259
2292
|
}
|
|
2260
2293
|
}
|
|
2261
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2262
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2294
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DropZoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2295
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: DropZoneComponent, isStandalone: true, selector: "lib-drop-zone", inputs: { row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, col: { classPropertyName: "col", publicName: "col", isSignal: true, isRequired: true, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null }, highlight: { classPropertyName: "highlight", publicName: "highlight", isSignal: true, isRequired: false, transformFunction: null }, highlightInvalid: { classPropertyName: "highlightInvalid", publicName: "highlightInvalid", isSignal: true, isRequired: false, transformFunction: null }, highlightResize: { classPropertyName: "highlightResize", publicName: "highlightResize", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragEnter: "dragEnter", dragExit: "dragExit", dragOver: "dragOver", dragDrop: "dragDrop" }, ngImport: i0, template: "<!-- drop-zone.component.html -->\n<div\n class=\"drop-zone\"\n [class.drop-zone--highlight]=\"highlight() && !highlightInvalid()\"\n [class.drop-zone--invalid]=\"highlightInvalid()\"\n [class.drop-zone--resize]=\"highlightResize()\"\n [style.grid-row]=\"row()\"\n [style.grid-column]=\"col()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n (contextmenu)=\"onContextMenu($event)\"\n>\n @if (editMode()) {\n <div class=\"edit-mode-cell-number\">\n {{ index() }}<br />\n {{ row() }},{{ col() }}\n </div>\n }\n</div>\n", styles: [".drop-zone{width:100%;height:100%;z-index:0;align-self:stretch;justify-self:stretch;display:block;box-sizing:border-box}.drop-zone--active,.drop-zone--highlight{background-color:#80808080}.drop-zone--invalid{background-color:light-dark(color-mix(in srgb,var(--mat-sys-error) 40%,white),color-mix(in srgb,var(--mat-sys-error) 80%,black))}.drop-zone--resize{background-color:#2196f34d;outline:1px solid rgba(33,150,243,.6)}.edit-mode-cell-number{font-size:10px;line-height:1.1;color:#64646499;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2263
2296
|
}
|
|
2264
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2297
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DropZoneComponent, decorators: [{
|
|
2265
2298
|
type: Component,
|
|
2266
|
-
args: [{ selector: 'lib-drop-zone', standalone: true, imports: [
|
|
2267
|
-
}] });
|
|
2299
|
+
args: [{ selector: 'lib-drop-zone', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- drop-zone.component.html -->\n<div\n class=\"drop-zone\"\n [class.drop-zone--highlight]=\"highlight() && !highlightInvalid()\"\n [class.drop-zone--invalid]=\"highlightInvalid()\"\n [class.drop-zone--resize]=\"highlightResize()\"\n [style.grid-row]=\"row()\"\n [style.grid-column]=\"col()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n (contextmenu)=\"onContextMenu($event)\"\n>\n @if (editMode()) {\n <div class=\"edit-mode-cell-number\">\n {{ index() }}<br />\n {{ row() }},{{ col() }}\n </div>\n }\n</div>\n", styles: [".drop-zone{width:100%;height:100%;z-index:0;align-self:stretch;justify-self:stretch;display:block;box-sizing:border-box}.drop-zone--active,.drop-zone--highlight{background-color:#80808080}.drop-zone--invalid{background-color:light-dark(color-mix(in srgb,var(--mat-sys-error) 40%,white),color-mix(in srgb,var(--mat-sys-error) 80%,black))}.drop-zone--resize{background-color:#2196f34d;outline:1px solid rgba(33,150,243,.6)}.edit-mode-cell-number{font-size:10px;line-height:1.1;color:#64646499;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;width:100%;height:100%}\n"] }]
|
|
2300
|
+
}], propDecorators: { row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], col: [{ type: i0.Input, args: [{ isSignal: true, alias: "col", required: true }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }], highlight: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlight", required: false }] }], highlightInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightInvalid", required: false }] }], highlightResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightResize", required: false }] }], editMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editMode", required: false }] }], dragEnter: [{ type: i0.Output, args: ["dragEnter"] }], dragExit: [{ type: i0.Output, args: ["dragExit"] }], dragOver: [{ type: i0.Output, args: ["dragOver"] }], dragDrop: [{ type: i0.Output, args: ["dragDrop"] }] } });
|
|
2268
2301
|
|
|
2269
2302
|
/**
|
|
2270
2303
|
* Context menu component for empty dashboard cells.
|
|
@@ -2362,135 +2395,134 @@ class EmptyCellContextMenuComponent {
|
|
|
2362
2395
|
sanitizeSvg(svg) {
|
|
2363
2396
|
return this.#sanitizer.bypassSecurityTrustHtml(svg);
|
|
2364
2397
|
}
|
|
2365
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2366
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2367
|
-
<!-- Hidden trigger for menu positioned at exact mouse coordinates
|
|
2368
|
-
|
|
2369
|
-
IMPORTANT: Angular Material applies its own positioning logic to menus,
|
|
2370
|
-
which by default offsets the menu from the trigger element to avoid overlap.
|
|
2371
|
-
To achieve precise positioning at mouse coordinates, we use these workarounds:
|
|
2372
|
-
|
|
2373
|
-
1. The trigger container is 1x1px (not 0x0) because Material needs a physical
|
|
2374
|
-
element to calculate position against. Zero-sized elements cause unpredictable
|
|
2375
|
-
positioning.
|
|
2376
|
-
|
|
2377
|
-
2. We use opacity:0 instead of visibility:hidden to keep the element in the
|
|
2378
|
-
layout flow while making it invisible.
|
|
2379
|
-
|
|
2380
|
-
3. The button itself is styled to 1x1px with no padding to serve as a precise
|
|
2381
|
-
anchor point for the menu.
|
|
2382
|
-
|
|
2383
|
-
4. The mat-menu uses [overlapTrigger]="true" to allow the menu to appear
|
|
2384
|
-
directly at the trigger position rather than offset from it.
|
|
2385
|
-
|
|
2386
|
-
This approach ensures the menu appears at the exact mouse coordinates passed
|
|
2387
|
-
from the empty cell context provider's right-click handler.
|
|
2388
|
-
-->
|
|
2389
|
-
<div
|
|
2390
|
-
style="position: fixed; width: 1px; height: 1px; opacity: 0; pointer-events: none;"
|
|
2391
|
-
[style]="menuPosition()">
|
|
2392
|
-
<button
|
|
2393
|
-
mat-button
|
|
2394
|
-
#menuTrigger="matMenuTrigger"
|
|
2395
|
-
[matMenuTriggerFor]="contextMenu"
|
|
2396
|
-
style="width: 1px; height: 1px; padding: 0; min-width: 0; line-height: 0;">
|
|
2397
|
-
</button>
|
|
2398
|
-
</div>
|
|
2399
|
-
|
|
2400
|
-
<!-- Context menu with widget list -->
|
|
2401
|
-
<mat-menu
|
|
2402
|
-
#contextMenu="matMenu"
|
|
2403
|
-
[overlapTrigger]="true"
|
|
2404
|
-
class="empty-cell-widget-menu">
|
|
2405
|
-
@for (item of menuItems(); track $index) {
|
|
2406
|
-
@if (item.divider) {
|
|
2407
|
-
<mat-divider></mat-divider>
|
|
2408
|
-
} @else {
|
|
2409
|
-
<button
|
|
2410
|
-
mat-menu-item
|
|
2411
|
-
(click)="executeAction(item)"
|
|
2412
|
-
[disabled]="item.disabled"
|
|
2413
|
-
[attr.aria-label]="item.label">
|
|
2414
|
-
@if (item.svgIcon) {
|
|
2415
|
-
<div class="widget-icon" [innerHTML]="sanitizeSvg(item.svgIcon)"></div>
|
|
2416
|
-
} @else if (item.icon) {
|
|
2417
|
-
<mat-icon>{{ item.icon }}</mat-icon>
|
|
2418
|
-
}
|
|
2419
|
-
{{ item.label }}
|
|
2420
|
-
</button>
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
|
-
</mat-menu>
|
|
2424
|
-
`, isInline: true, styles: [":host{display:contents}.empty-cell-widget-menu{max-height:400px;overflow-y:auto}.widget-icon{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;vertical-align:middle}.widget-icon :deep(svg){width:20px;height:20px;fill:currentColor}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }
|
|
2398
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: EmptyCellContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2399
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: EmptyCellContextMenuComponent, isStandalone: true, selector: "lib-empty-cell-context-menu", viewQueries: [{ propertyName: "menuTrigger", first: true, predicate: ["menuTrigger"], descendants: true, read: MatMenuTrigger, isSignal: true }], ngImport: i0, template: `
|
|
2400
|
+
<!-- Hidden trigger for menu positioned at exact mouse coordinates
|
|
2401
|
+
|
|
2402
|
+
IMPORTANT: Angular Material applies its own positioning logic to menus,
|
|
2403
|
+
which by default offsets the menu from the trigger element to avoid overlap.
|
|
2404
|
+
To achieve precise positioning at mouse coordinates, we use these workarounds:
|
|
2405
|
+
|
|
2406
|
+
1. The trigger container is 1x1px (not 0x0) because Material needs a physical
|
|
2407
|
+
element to calculate position against. Zero-sized elements cause unpredictable
|
|
2408
|
+
positioning.
|
|
2409
|
+
|
|
2410
|
+
2. We use opacity:0 instead of visibility:hidden to keep the element in the
|
|
2411
|
+
layout flow while making it invisible.
|
|
2412
|
+
|
|
2413
|
+
3. The button itself is styled to 1x1px with no padding to serve as a precise
|
|
2414
|
+
anchor point for the menu.
|
|
2415
|
+
|
|
2416
|
+
4. The mat-menu uses [overlapTrigger]="true" to allow the menu to appear
|
|
2417
|
+
directly at the trigger position rather than offset from it.
|
|
2418
|
+
|
|
2419
|
+
This approach ensures the menu appears at the exact mouse coordinates passed
|
|
2420
|
+
from the empty cell context provider's right-click handler.
|
|
2421
|
+
-->
|
|
2422
|
+
<div
|
|
2423
|
+
style="position: fixed; width: 1px; height: 1px; opacity: 0; pointer-events: none;"
|
|
2424
|
+
[style]="menuPosition()">
|
|
2425
|
+
<button
|
|
2426
|
+
mat-button
|
|
2427
|
+
#menuTrigger="matMenuTrigger"
|
|
2428
|
+
[matMenuTriggerFor]="contextMenu"
|
|
2429
|
+
style="width: 1px; height: 1px; padding: 0; min-width: 0; line-height: 0;">
|
|
2430
|
+
</button>
|
|
2431
|
+
</div>
|
|
2432
|
+
|
|
2433
|
+
<!-- Context menu with widget list -->
|
|
2434
|
+
<mat-menu
|
|
2435
|
+
#contextMenu="matMenu"
|
|
2436
|
+
[overlapTrigger]="true"
|
|
2437
|
+
class="empty-cell-widget-menu">
|
|
2438
|
+
@for (item of menuItems(); track $index) {
|
|
2439
|
+
@if (item.divider) {
|
|
2440
|
+
<mat-divider></mat-divider>
|
|
2441
|
+
} @else {
|
|
2442
|
+
<button
|
|
2443
|
+
mat-menu-item
|
|
2444
|
+
(click)="executeAction(item)"
|
|
2445
|
+
[disabled]="item.disabled"
|
|
2446
|
+
[attr.aria-label]="item.label">
|
|
2447
|
+
@if (item.svgIcon) {
|
|
2448
|
+
<div class="widget-icon" [innerHTML]="sanitizeSvg(item.svgIcon)"></div>
|
|
2449
|
+
} @else if (item.icon) {
|
|
2450
|
+
<mat-icon>{{ item.icon }}</mat-icon>
|
|
2451
|
+
}
|
|
2452
|
+
{{ item.label }}
|
|
2453
|
+
</button>
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
</mat-menu>
|
|
2457
|
+
`, isInline: true, styles: [":host{display:contents}.empty-cell-widget-menu{max-height:400px;overflow-y:auto}.widget-icon{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;vertical-align:middle}.widget-icon :deep(svg){width:20px;height:20px;fill:currentColor}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i3.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2425
2458
|
}
|
|
2426
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2459
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: EmptyCellContextMenuComponent, decorators: [{
|
|
2427
2460
|
type: Component,
|
|
2428
2461
|
args: [{ selector: 'lib-empty-cell-context-menu', standalone: true, imports: [
|
|
2429
2462
|
MatMenuModule,
|
|
2430
2463
|
MatIconModule,
|
|
2431
2464
|
MatDividerModule,
|
|
2432
|
-
MatButtonModule
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
style="
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
[
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
</mat-menu>
|
|
2465
|
+
MatButtonModule
|
|
2466
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
2467
|
+
<!-- Hidden trigger for menu positioned at exact mouse coordinates
|
|
2468
|
+
|
|
2469
|
+
IMPORTANT: Angular Material applies its own positioning logic to menus,
|
|
2470
|
+
which by default offsets the menu from the trigger element to avoid overlap.
|
|
2471
|
+
To achieve precise positioning at mouse coordinates, we use these workarounds:
|
|
2472
|
+
|
|
2473
|
+
1. The trigger container is 1x1px (not 0x0) because Material needs a physical
|
|
2474
|
+
element to calculate position against. Zero-sized elements cause unpredictable
|
|
2475
|
+
positioning.
|
|
2476
|
+
|
|
2477
|
+
2. We use opacity:0 instead of visibility:hidden to keep the element in the
|
|
2478
|
+
layout flow while making it invisible.
|
|
2479
|
+
|
|
2480
|
+
3. The button itself is styled to 1x1px with no padding to serve as a precise
|
|
2481
|
+
anchor point for the menu.
|
|
2482
|
+
|
|
2483
|
+
4. The mat-menu uses [overlapTrigger]="true" to allow the menu to appear
|
|
2484
|
+
directly at the trigger position rather than offset from it.
|
|
2485
|
+
|
|
2486
|
+
This approach ensures the menu appears at the exact mouse coordinates passed
|
|
2487
|
+
from the empty cell context provider's right-click handler.
|
|
2488
|
+
-->
|
|
2489
|
+
<div
|
|
2490
|
+
style="position: fixed; width: 1px; height: 1px; opacity: 0; pointer-events: none;"
|
|
2491
|
+
[style]="menuPosition()">
|
|
2492
|
+
<button
|
|
2493
|
+
mat-button
|
|
2494
|
+
#menuTrigger="matMenuTrigger"
|
|
2495
|
+
[matMenuTriggerFor]="contextMenu"
|
|
2496
|
+
style="width: 1px; height: 1px; padding: 0; min-width: 0; line-height: 0;">
|
|
2497
|
+
</button>
|
|
2498
|
+
</div>
|
|
2499
|
+
|
|
2500
|
+
<!-- Context menu with widget list -->
|
|
2501
|
+
<mat-menu
|
|
2502
|
+
#contextMenu="matMenu"
|
|
2503
|
+
[overlapTrigger]="true"
|
|
2504
|
+
class="empty-cell-widget-menu">
|
|
2505
|
+
@for (item of menuItems(); track $index) {
|
|
2506
|
+
@if (item.divider) {
|
|
2507
|
+
<mat-divider></mat-divider>
|
|
2508
|
+
} @else {
|
|
2509
|
+
<button
|
|
2510
|
+
mat-menu-item
|
|
2511
|
+
(click)="executeAction(item)"
|
|
2512
|
+
[disabled]="item.disabled"
|
|
2513
|
+
[attr.aria-label]="item.label">
|
|
2514
|
+
@if (item.svgIcon) {
|
|
2515
|
+
<div class="widget-icon" [innerHTML]="sanitizeSvg(item.svgIcon)"></div>
|
|
2516
|
+
} @else if (item.icon) {
|
|
2517
|
+
<mat-icon>{{ item.icon }}</mat-icon>
|
|
2518
|
+
}
|
|
2519
|
+
{{ item.label }}
|
|
2520
|
+
</button>
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
</mat-menu>
|
|
2492
2524
|
`, styles: [":host{display:contents}.empty-cell-widget-menu{max-height:400px;overflow-y:auto}.widget-icon{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;vertical-align:middle}.widget-icon :deep(svg){width:20px;height:20px;fill:currentColor}\n"] }]
|
|
2493
|
-
}], ctorParameters: () => [] });
|
|
2525
|
+
}], ctorParameters: () => [], propDecorators: { menuTrigger: [{ type: i0.ViewChild, args: ['menuTrigger', { ...{ read: MatMenuTrigger }, isSignal: true }] }] } });
|
|
2494
2526
|
|
|
2495
2527
|
// dashboard-editor.component.ts
|
|
2496
2528
|
class DashboardEditorComponent {
|
|
@@ -2597,19 +2629,18 @@ class DashboardEditorComponent {
|
|
|
2597
2629
|
this.#store.handleDrop(event.data, event.target);
|
|
2598
2630
|
// Note: Store handles all validation and error handling internally
|
|
2599
2631
|
}
|
|
2600
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2601
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2632
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2633
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: DashboardEditorComponent, isStandalone: true, selector: "ngx-dashboard-editor", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--rows": "rows()", "style.--columns": "columns()", "style.--gutter-size": "gutterSize()", "style.--gutters": "gutters()", "class.is-edit-mode": "true" } }, providers: [
|
|
2602
2634
|
CellContextMenuService,
|
|
2603
|
-
], viewQueries: [{ propertyName: "bottomGridRef", first: true, predicate: ["bottomGrid"], descendants: true, isSignal: true }, { propertyName: "dropZones", predicate: DropZoneComponent, descendants: true, isSignal: true }, { propertyName: "cellComponents", predicate: CellComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- dashboard-editor.component.html -->\
|
|
2635
|
+
], viewQueries: [{ propertyName: "bottomGridRef", first: true, predicate: ["bottomGrid"], descendants: true, isSignal: true }, { propertyName: "dropZones", predicate: DropZoneComponent, descendants: true, isSignal: true }, { propertyName: "cellComponents", predicate: CellComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- dashboard-editor.component.html -->\n<div class=\"grid-container\">\n <!-- Bottom grid with drop zones -->\n <div class=\"grid\" id=\"bottom-grid\" #bottomGrid>\n @for (position of dropzonePositions(); track position.id) {\n <lib-drop-zone\n class=\"drop-zone\"\n [row]=\"position.row\"\n [col]=\"position.col\"\n [index]=\"position.index\"\n [highlight]=\"highlightMap().has(createCellId(position.row, position.col))\"\n [highlightInvalid]=\"\n invalidHighlightMap().has(createCellId(position.row, position.col))\n \"\n [highlightResize]=\"\n resizePreviewMap().has(createCellId(position.row, position.col))\n \"\n [editMode]=\"true\"\n (dragEnter)=\"onDragEnter($event)\"\n (dragExit)=\"onDragExit()\"\n (dragOver)=\"onDragOver($event)\"\n (dragDrop)=\"onDragDrop($event)\"\n ></lib-drop-zone>\n }\n </div>\n\n <!-- Top grid with interactive cells -->\n <div class=\"grid\" id=\"top-grid\">\n @for (cell of cells(); track cell.widgetId) {\n <lib-cell\n class=\"grid-cell\"\n [widgetId]=\"cell.widgetId\"\n [cellId]=\"cell.cellId\"\n [isEditMode]=\"true\"\n [draggable]=\"true\"\n [row]=\"cell.row\"\n [column]=\"cell.col\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [flat]=\"cell.flat\"\n [widgetFactory]=\"cell.widgetFactory\"\n [widgetState]=\"cell.widgetState\"\n (dragStart)=\"onCellDragStart($event)\"\n (dragEnd)=\"dragEnd()\"\n (delete)=\"onCellDelete($event)\"\n (settings)=\"onCellSettings($event)\"\n (resizeStart)=\"onCellResizeStart($event)\"\n (resizeMove)=\"onCellResizeMove($event)\"\n (resizeEnd)=\"onCellResizeEnd($event)\"\n >\n </lib-cell>\n }\n </div>\n</div>\n\n<!-- Context menus -->\n<lib-cell-context-menu></lib-cell-context-menu>\n<lib-empty-cell-context-menu></lib-empty-cell-context-menu>\n", styles: ["@charset \"UTF-8\";:host{--cell-size: calc( 100cqi / var(--columns) - var(--gutter-size) * var(--gutters) / var(--columns) );--tile-size: calc(var(--cell-size) + var(--gutter-size));--tile-offset: calc( var(--gutter-size) + var(--cell-size) + var(--gutter-size) / 2 );display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto}:host .grid{background-image:linear-gradient(to right,rgba(100,100,100,.12) 1px,transparent 1px),linear-gradient(to bottom,rgba(100,100,100,.12) 1px,transparent 1px),linear-gradient(to bottom,rgba(100,100,100,.12) 1px,transparent 1px);background-size:var(--tile-size) var(--tile-size),var(--tile-size) var(--tile-size),100% 1px;background-position:var(--tile-offset) var(--tile-offset),var(--tile-offset) var(--tile-offset),bottom;background-repeat:repeat,repeat,no-repeat}.grid-container{position:relative;width:100%;height:100%}.grid{display:grid;gap:var(--gutter-size);padding:var(--gutter-size);position:absolute;inset:0;width:100%;height:100%;box-sizing:border-box;align-items:stretch;justify-items:stretch;grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size))}#bottom-grid{z-index:1}#top-grid{z-index:2;pointer-events:none}.grid-cell{pointer-events:auto}.grid-cell.is-dragging{pointer-events:none;opacity:.5}\n"], dependencies: [{ kind: "component", type: CellComponent, selector: "lib-cell", inputs: ["widgetId", "cellId", "widgetFactory", "widgetState", "isEditMode", "flat", "row", "column", "rowSpan", "colSpan", "draggable"], outputs: ["rowChange", "columnChange", "dragStart", "dragEnd", "edit", "delete", "settings", "resizeStart", "resizeMove", "resizeEnd"] }, { kind: "component", type: DropZoneComponent, selector: "lib-drop-zone", inputs: ["row", "col", "index", "highlight", "highlightInvalid", "highlightResize", "editMode"], outputs: ["dragEnter", "dragExit", "dragOver", "dragDrop"] }, { kind: "component", type: CellContextMenuComponent, selector: "lib-cell-context-menu" }, { kind: "component", type: EmptyCellContextMenuComponent, selector: "lib-empty-cell-context-menu" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2604
2636
|
}
|
|
2605
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2637
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardEditorComponent, decorators: [{
|
|
2606
2638
|
type: Component,
|
|
2607
2639
|
args: [{ selector: 'ngx-dashboard-editor', standalone: true, imports: [
|
|
2608
2640
|
CellComponent,
|
|
2609
|
-
CommonModule,
|
|
2610
2641
|
DropZoneComponent,
|
|
2611
2642
|
CellContextMenuComponent,
|
|
2612
|
-
EmptyCellContextMenuComponent
|
|
2643
|
+
EmptyCellContextMenuComponent
|
|
2613
2644
|
], providers: [
|
|
2614
2645
|
CellContextMenuService,
|
|
2615
2646
|
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
@@ -2618,8 +2649,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
|
|
|
2618
2649
|
'[style.--gutter-size]': 'gutterSize()',
|
|
2619
2650
|
'[style.--gutters]': 'gutters()',
|
|
2620
2651
|
'[class.is-edit-mode]': 'true', // Always in edit mode
|
|
2621
|
-
}, template: "<!-- dashboard-editor.component.html -->\
|
|
2622
|
-
}], ctorParameters: () => [] });
|
|
2652
|
+
}, template: "<!-- dashboard-editor.component.html -->\n<div class=\"grid-container\">\n <!-- Bottom grid with drop zones -->\n <div class=\"grid\" id=\"bottom-grid\" #bottomGrid>\n @for (position of dropzonePositions(); track position.id) {\n <lib-drop-zone\n class=\"drop-zone\"\n [row]=\"position.row\"\n [col]=\"position.col\"\n [index]=\"position.index\"\n [highlight]=\"highlightMap().has(createCellId(position.row, position.col))\"\n [highlightInvalid]=\"\n invalidHighlightMap().has(createCellId(position.row, position.col))\n \"\n [highlightResize]=\"\n resizePreviewMap().has(createCellId(position.row, position.col))\n \"\n [editMode]=\"true\"\n (dragEnter)=\"onDragEnter($event)\"\n (dragExit)=\"onDragExit()\"\n (dragOver)=\"onDragOver($event)\"\n (dragDrop)=\"onDragDrop($event)\"\n ></lib-drop-zone>\n }\n </div>\n\n <!-- Top grid with interactive cells -->\n <div class=\"grid\" id=\"top-grid\">\n @for (cell of cells(); track cell.widgetId) {\n <lib-cell\n class=\"grid-cell\"\n [widgetId]=\"cell.widgetId\"\n [cellId]=\"cell.cellId\"\n [isEditMode]=\"true\"\n [draggable]=\"true\"\n [row]=\"cell.row\"\n [column]=\"cell.col\"\n [rowSpan]=\"cell.rowSpan\"\n [colSpan]=\"cell.colSpan\"\n [flat]=\"cell.flat\"\n [widgetFactory]=\"cell.widgetFactory\"\n [widgetState]=\"cell.widgetState\"\n (dragStart)=\"onCellDragStart($event)\"\n (dragEnd)=\"dragEnd()\"\n (delete)=\"onCellDelete($event)\"\n (settings)=\"onCellSettings($event)\"\n (resizeStart)=\"onCellResizeStart($event)\"\n (resizeMove)=\"onCellResizeMove($event)\"\n (resizeEnd)=\"onCellResizeEnd($event)\"\n >\n </lib-cell>\n }\n </div>\n</div>\n\n<!-- Context menus -->\n<lib-cell-context-menu></lib-cell-context-menu>\n<lib-empty-cell-context-menu></lib-empty-cell-context-menu>\n", styles: ["@charset \"UTF-8\";:host{--cell-size: calc( 100cqi / var(--columns) - var(--gutter-size) * var(--gutters) / var(--columns) );--tile-size: calc(var(--cell-size) + var(--gutter-size));--tile-offset: calc( var(--gutter-size) + var(--cell-size) + var(--gutter-size) / 2 );display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto}:host .grid{background-image:linear-gradient(to right,rgba(100,100,100,.12) 1px,transparent 1px),linear-gradient(to bottom,rgba(100,100,100,.12) 1px,transparent 1px),linear-gradient(to bottom,rgba(100,100,100,.12) 1px,transparent 1px);background-size:var(--tile-size) var(--tile-size),var(--tile-size) var(--tile-size),100% 1px;background-position:var(--tile-offset) var(--tile-offset),var(--tile-offset) var(--tile-offset),bottom;background-repeat:repeat,repeat,no-repeat}.grid-container{position:relative;width:100%;height:100%}.grid{display:grid;gap:var(--gutter-size);padding:var(--gutter-size);position:absolute;inset:0;width:100%;height:100%;box-sizing:border-box;align-items:stretch;justify-items:stretch;grid-template-columns:repeat(var(--columns),var(--cell-size));grid-template-rows:repeat(var(--rows),var(--cell-size))}#bottom-grid{z-index:1}#top-grid{z-index:2;pointer-events:none}.grid-cell{pointer-events:auto}.grid-cell.is-dragging{pointer-events:none;opacity:.5}\n"] }]
|
|
2653
|
+
}], ctorParameters: () => [], propDecorators: { bottomGridRef: [{ type: i0.ViewChild, args: ['bottomGrid', { isSignal: true }] }], dropZones: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => DropZoneComponent), { isSignal: true }] }], cellComponents: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => CellComponent), { isSignal: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], gutterSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterSize", required: false }] }] } });
|
|
2623
2654
|
|
|
2624
2655
|
// dashboard-bridge.service.ts
|
|
2625
2656
|
/**
|
|
@@ -2747,10 +2778,10 @@ class DashboardBridgeService {
|
|
|
2747
2778
|
getAllDashboards() {
|
|
2748
2779
|
return this.dashboards();
|
|
2749
2780
|
}
|
|
2750
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2751
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2781
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardBridgeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2782
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardBridgeService, providedIn: 'root' });
|
|
2752
2783
|
}
|
|
2753
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2784
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardBridgeService, decorators: [{
|
|
2754
2785
|
type: Injectable,
|
|
2755
2786
|
args: [{ providedIn: 'root' }]
|
|
2756
2787
|
}] });
|
|
@@ -2866,10 +2897,10 @@ class DashboardViewportService {
|
|
|
2866
2897
|
constrainedBy
|
|
2867
2898
|
};
|
|
2868
2899
|
}, ...(ngDevMode ? [{ debugName: "constraints" }] : []));
|
|
2869
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2870
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2900
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardViewportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2901
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardViewportService });
|
|
2871
2902
|
}
|
|
2872
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2903
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardViewportService, decorators: [{
|
|
2873
2904
|
type: Injectable
|
|
2874
2905
|
}], ctorParameters: () => [] });
|
|
2875
2906
|
|
|
@@ -3025,12 +3056,12 @@ class DashboardComponent {
|
|
|
3025
3056
|
this.#isPreservingStates = false;
|
|
3026
3057
|
}
|
|
3027
3058
|
}
|
|
3028
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3029
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
3059
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3060
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: DashboardComponent, isStandalone: true, selector: "ngx-dashboard", inputs: { dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: true, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null }, reservedSpace: { classPropertyName: "reservedSpace", publicName: "reservedSpace", isSignal: true, isRequired: false, transformFunction: null }, enableSelection: { classPropertyName: "enableSelection", publicName: "enableSelection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionComplete: "selectionComplete" }, host: { properties: { "style.--rows": "store.rows()", "style.--columns": "store.columns()", "style.--gutter-size": "store.gutterSize()", "style.--gutters": "store.columns() + 1", "class.is-edit-mode": "editMode()", "style.max-width.px": "viewport.constraints().maxWidth", "style.max-height.px": "viewport.constraints().maxHeight" } }, providers: [DashboardStore, DashboardViewportService], viewQueries: [{ propertyName: "dashboardEditor", first: true, predicate: DashboardEditorComponent, descendants: true, isSignal: true }, { propertyName: "dashboardViewer", first: true, predicate: DashboardViewerComponent, descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "<!-- dashboard.component.html -->\n<div class=\"grid-container\">\n @if (editMode()) {\n <!-- Full editor with drag & drop capabilities -->\n <ngx-dashboard-editor\n [rows]=\"store.rows()\"\n [columns]=\"store.columns()\"\n [gutterSize]=\"store.gutterSize()\"\n ></ngx-dashboard-editor>\n } @else {\n <!-- Read-only viewer -->\n <ngx-dashboard-viewer\n [rows]=\"store.rows()\"\n [columns]=\"store.columns()\"\n [gutterSize]=\"store.gutterSize()\"\n [enableSelection]=\"enableSelection()\"\n (selectionComplete)=\"selectionComplete.emit($event)\"\n ></ngx-dashboard-viewer>\n }\n</div>\n", styles: [":host{display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto}.grid-container{position:relative;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: DashboardViewerComponent, selector: "ngx-dashboard-viewer", inputs: ["rows", "columns", "gutterSize", "enableSelection"], outputs: ["selectionComplete"] }, { kind: "component", type: DashboardEditorComponent, selector: "ngx-dashboard-editor", inputs: ["rows", "columns", "gutterSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3030
3061
|
}
|
|
3031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3062
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DashboardComponent, decorators: [{
|
|
3032
3063
|
type: Component,
|
|
3033
|
-
args: [{ selector: 'ngx-dashboard', standalone: true, imports: [
|
|
3064
|
+
args: [{ selector: 'ngx-dashboard', standalone: true, imports: [DashboardViewerComponent, DashboardEditorComponent], providers: [DashboardStore, DashboardViewportService], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
3034
3065
|
'[style.--rows]': 'store.rows()',
|
|
3035
3066
|
'[style.--columns]': 'store.columns()',
|
|
3036
3067
|
'[style.--gutter-size]': 'store.gutterSize()',
|
|
@@ -3038,8 +3069,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
|
|
|
3038
3069
|
'[class.is-edit-mode]': 'editMode()',
|
|
3039
3070
|
'[style.max-width.px]': 'viewport.constraints().maxWidth',
|
|
3040
3071
|
'[style.max-height.px]': 'viewport.constraints().maxHeight',
|
|
3041
|
-
}, template: "<!-- dashboard.component.html -->\
|
|
3042
|
-
}], ctorParameters: () => [] });
|
|
3072
|
+
}, template: "<!-- dashboard.component.html -->\n<div class=\"grid-container\">\n @if (editMode()) {\n <!-- Full editor with drag & drop capabilities -->\n <ngx-dashboard-editor\n [rows]=\"store.rows()\"\n [columns]=\"store.columns()\"\n [gutterSize]=\"store.gutterSize()\"\n ></ngx-dashboard-editor>\n } @else {\n <!-- Read-only viewer -->\n <ngx-dashboard-viewer\n [rows]=\"store.rows()\"\n [columns]=\"store.columns()\"\n [gutterSize]=\"store.gutterSize()\"\n [enableSelection]=\"enableSelection()\"\n (selectionComplete)=\"selectionComplete.emit($event)\"\n ></ngx-dashboard-viewer>\n }\n</div>\n", styles: [":host{display:block;container-type:inline-size;box-sizing:border-box;aspect-ratio:var(--columns)/var(--rows);width:100%;height:auto}.grid-container{position:relative;width:100%;height:100%}\n"] }]
|
|
3073
|
+
}], ctorParameters: () => [], propDecorators: { dashboardData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardData", required: true }] }], editMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editMode", required: false }] }], reservedSpace: [{ type: i0.Input, args: [{ isSignal: true, alias: "reservedSpace", required: false }] }], enableSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSelection", required: false }] }], selectionComplete: [{ type: i0.Output, args: ["selectionComplete"] }], dashboardEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DashboardEditorComponent), { isSignal: true }] }], dashboardViewer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DashboardViewerComponent), { isSignal: true }] }] } });
|
|
3043
3074
|
|
|
3044
3075
|
// widget-list.component.ts
|
|
3045
3076
|
class WidgetListComponent {
|
|
@@ -3107,13 +3138,13 @@ class WidgetListComponent {
|
|
|
3107
3138
|
// Using $localize for the template pattern
|
|
3108
3139
|
return $localize `:@@ngx.dashboard.widget.list.item.ariaLabel:${widget.name} widget: ${widget.description}`;
|
|
3109
3140
|
}
|
|
3110
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3111
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
3141
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: WidgetListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3142
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: WidgetListComponent, isStandalone: true, selector: "ngx-dashboard-widget-list", inputs: { collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- widget-list.component.html -->\n<div\n class=\"widget-list\"\n role=\"list\"\n i18n-aria-label=\"@@ngx.dashboard.widget.list.available\"\n aria-label=\"Available widgets\"\n>\n @for (widget of widgets(); track widget.widgetTypeid) {\n <div\n class=\"widget-list-item\"\n [class.active]=\"activeWidget() === widget.widgetTypeid\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, widget)\"\n (dragend)=\"onDragEnd()\"\n role=\"listitem\"\n [attr.aria-grabbed]=\"activeWidget() === widget.widgetTypeid\"\n [attr.aria-label]=\"getWidgetAriaLabel(widget)\"\n [matTooltip]=\"widget.description\"\n [matTooltipDisabled]=\"!collapsed()\"\n matTooltipPosition=\"right\"\n tabindex=\"0\"\n >\n <div class=\"icon\" [innerHTML]=\"widget.safeSvgIcon\" aria-hidden=\"true\"></div>\n <div class=\"content\">\n <strong>{{ widget.name }}</strong>\n <small>{{ widget.description }}</small>\n </div>\n </div>\n }\n</div>\n", styles: [":host{background-color:var(--mat-sys-surface-container, #f5f5f5);container-type:inline-size}.widget-list{display:flex;flex-direction:column;gap:var(--mat-sys-spacing-2, 8px)}@container (max-width: 200px){.widget-list{gap:var(--mat-sys-spacing-1, 4px)}}@container (min-width: 400px){.widget-list{gap:var(--mat-sys-spacing-3, 12px)}}.widget-list-item{display:flex;align-items:start;gap:var(--mat-sys-spacing-3, 12px);background-color:var(--mat-sys-surface, #ffffff);border:1px solid var(--mat-sys-outline-variant, #c7c7c7);padding:var(--mat-sys-spacing-3, 12px);border-radius:var(--mat-sys-corner-small, 4px);cursor:grab;transition:background-color var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out),border-color var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out),box-shadow var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out);box-shadow:var(--mat-sys-elevation-level1, 0 1px 2px rgba(0, 0, 0, .05))}@container (max-width: 200px){.widget-list-item{padding:var(--mat-sys-spacing-2, 8px);gap:var(--mat-sys-spacing-2, 8px)}}@container (min-width: 400px){.widget-list-item{padding:var(--mat-sys-spacing-4, 16px);gap:var(--mat-sys-spacing-4, 16px)}}.widget-list-item .icon{width:clamp(20px,4vw,28px);height:clamp(20px,4vw,28px);flex-shrink:0;color:var(--mat-sys-on-surface-variant, #5f5f5f);transition:color var(--mat-sys-motion-duration-short2, .15s) var(--mat-sys-motion-easing-standard, ease-in-out)}.widget-list-item .icon ::ng-deep svg{width:100%;height:100%;display:block}.widget-list-item .content{display:flex;flex-direction:column;line-height:1.2;color:var(--mat-sys-on-surface, #1c1c1c);flex:1;min-width:0}.widget-list-item .content strong{color:var(--mat-sys-on-surface, #1c1c1c);font-weight:500;font-size:clamp(.875rem,2.5vw,1rem);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget-list-item .content small{color:var(--mat-sys-on-surface-variant, #5f5f5f);font-size:clamp(.75rem,2vw,.875rem);margin-top:var(--mat-sys-spacing-1, 4px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget-list-item:hover{background-color:var(--mat-sys-surface-container-low, #f0f0f0);box-shadow:var(--mat-sys-elevation-level2, 0 2px 4px rgba(0, 0, 0, .1))}.widget-list-item:hover .icon{color:var(--mat-sys-on-surface, #1c1c1c)}.widget-list-item:active{cursor:grabbing;background-color:var(--mat-sys-surface-container, #f5f5f5)}.widget-list-item.active{background-color:var(--mat-sys-primary-container, #e6f2ff);border-color:var(--mat-sys-primary, #1976d2);color:var(--mat-sys-on-primary-container, #004a99)}.widget-list-item.active .content strong{color:var(--mat-sys-on-primary-container, #004a99)}.widget-list-item.active .content small{color:var(--mat-sys-on-primary-container, #004a99);opacity:.8}.widget-list-item.active .icon{color:var(--mat-sys-on-primary-container, #004a99)}.drag-ghost{position:absolute;top:0;left:0;z-index:9999;margin:0;pointer-events:none;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:var(--mat-sys-surface, #ffffff);border:1px solid var(--mat-sys-outline-variant, #c7c7c7);border-radius:var(--mat-sys-corner-small, 4px);box-shadow:var(--mat-sys-elevation-level3, 0 4px 6px rgba(0, 0, 0, .15));opacity:.8}.drag-ghost .icon{display:flex;align-items:center;justify-content:center;color:var(--mat-sys-on-surface-variant, #5f5f5f);opacity:.6}.drag-ghost .icon ::ng-deep svg{display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3112
3143
|
}
|
|
3113
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3144
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: WidgetListComponent, decorators: [{
|
|
3114
3145
|
type: Component,
|
|
3115
|
-
args: [{ selector: 'ngx-dashboard-widget-list', standalone: true, imports: [MatTooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- widget-list.component.html -->\
|
|
3116
|
-
}] });
|
|
3146
|
+
args: [{ selector: 'ngx-dashboard-widget-list', standalone: true, imports: [MatTooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- widget-list.component.html -->\n<div\n class=\"widget-list\"\n role=\"list\"\n i18n-aria-label=\"@@ngx.dashboard.widget.list.available\"\n aria-label=\"Available widgets\"\n>\n @for (widget of widgets(); track widget.widgetTypeid) {\n <div\n class=\"widget-list-item\"\n [class.active]=\"activeWidget() === widget.widgetTypeid\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, widget)\"\n (dragend)=\"onDragEnd()\"\n role=\"listitem\"\n [attr.aria-grabbed]=\"activeWidget() === widget.widgetTypeid\"\n [attr.aria-label]=\"getWidgetAriaLabel(widget)\"\n [matTooltip]=\"widget.description\"\n [matTooltipDisabled]=\"!collapsed()\"\n matTooltipPosition=\"right\"\n tabindex=\"0\"\n >\n <div class=\"icon\" [innerHTML]=\"widget.safeSvgIcon\" aria-hidden=\"true\"></div>\n <div class=\"content\">\n <strong>{{ widget.name }}</strong>\n <small>{{ widget.description }}</small>\n </div>\n </div>\n }\n</div>\n", styles: [":host{background-color:var(--mat-sys-surface-container, #f5f5f5);container-type:inline-size}.widget-list{display:flex;flex-direction:column;gap:var(--mat-sys-spacing-2, 8px)}@container (max-width: 200px){.widget-list{gap:var(--mat-sys-spacing-1, 4px)}}@container (min-width: 400px){.widget-list{gap:var(--mat-sys-spacing-3, 12px)}}.widget-list-item{display:flex;align-items:start;gap:var(--mat-sys-spacing-3, 12px);background-color:var(--mat-sys-surface, #ffffff);border:1px solid var(--mat-sys-outline-variant, #c7c7c7);padding:var(--mat-sys-spacing-3, 12px);border-radius:var(--mat-sys-corner-small, 4px);cursor:grab;transition:background-color var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out),border-color var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out),box-shadow var(--mat-sys-motion-duration-medium2, .3s) var(--mat-sys-motion-easing-standard, ease-in-out);box-shadow:var(--mat-sys-elevation-level1, 0 1px 2px rgba(0, 0, 0, .05))}@container (max-width: 200px){.widget-list-item{padding:var(--mat-sys-spacing-2, 8px);gap:var(--mat-sys-spacing-2, 8px)}}@container (min-width: 400px){.widget-list-item{padding:var(--mat-sys-spacing-4, 16px);gap:var(--mat-sys-spacing-4, 16px)}}.widget-list-item .icon{width:clamp(20px,4vw,28px);height:clamp(20px,4vw,28px);flex-shrink:0;color:var(--mat-sys-on-surface-variant, #5f5f5f);transition:color var(--mat-sys-motion-duration-short2, .15s) var(--mat-sys-motion-easing-standard, ease-in-out)}.widget-list-item .icon ::ng-deep svg{width:100%;height:100%;display:block}.widget-list-item .content{display:flex;flex-direction:column;line-height:1.2;color:var(--mat-sys-on-surface, #1c1c1c);flex:1;min-width:0}.widget-list-item .content strong{color:var(--mat-sys-on-surface, #1c1c1c);font-weight:500;font-size:clamp(.875rem,2.5vw,1rem);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget-list-item .content small{color:var(--mat-sys-on-surface-variant, #5f5f5f);font-size:clamp(.75rem,2vw,.875rem);margin-top:var(--mat-sys-spacing-1, 4px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget-list-item:hover{background-color:var(--mat-sys-surface-container-low, #f0f0f0);box-shadow:var(--mat-sys-elevation-level2, 0 2px 4px rgba(0, 0, 0, .1))}.widget-list-item:hover .icon{color:var(--mat-sys-on-surface, #1c1c1c)}.widget-list-item:active{cursor:grabbing;background-color:var(--mat-sys-surface-container, #f5f5f5)}.widget-list-item.active{background-color:var(--mat-sys-primary-container, #e6f2ff);border-color:var(--mat-sys-primary, #1976d2);color:var(--mat-sys-on-primary-container, #004a99)}.widget-list-item.active .content strong{color:var(--mat-sys-on-primary-container, #004a99)}.widget-list-item.active .content small{color:var(--mat-sys-on-primary-container, #004a99);opacity:.8}.widget-list-item.active .icon{color:var(--mat-sys-on-primary-container, #004a99)}.drag-ghost{position:absolute;top:0;left:0;z-index:9999;margin:0;pointer-events:none;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:var(--mat-sys-surface, #ffffff);border:1px solid var(--mat-sys-outline-variant, #c7c7c7);border-radius:var(--mat-sys-corner-small, 4px);box-shadow:var(--mat-sys-elevation-level3, 0 4px 6px rgba(0, 0, 0, .15));opacity:.8}.drag-ghost .icon{display:flex;align-items:center;justify-content:center;color:var(--mat-sys-on-surface-variant, #5f5f5f);opacity:.6}.drag-ghost .icon ::ng-deep svg{display:block}\n"] }]
|
|
3147
|
+
}], propDecorators: { collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }] } });
|
|
3117
3148
|
|
|
3118
3149
|
/*
|
|
3119
3150
|
* Public API Surface of ngx-dashboard
|