@ogidor/dashboard 1.0.10 → 1.0.12
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.
- package/app/app.module.d.ts +1 -1
- package/app/dashboard.component.d.ts +29 -15
- package/esm2020/app/app.module.mjs +6 -2
- package/esm2020/app/dashboard.component.mjs +294 -93
- package/fesm2015/ogidor-dashboard.mjs +300 -93
- package/fesm2015/ogidor-dashboard.mjs.map +1 -1
- package/fesm2020/ogidor-dashboard.mjs +298 -93
- package/fesm2020/ogidor-dashboard.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Directive, EventEmitter, TemplateRef, Component, ChangeDetectionStrategy, Input, Output, ViewChild, ContentChild, Injectable, NgModule } from '@angular/core';
|
|
2
|
+
import { Directive, EventEmitter, TemplateRef, Component, ChangeDetectionStrategy, Input, Output, ViewChild, ContentChild, Injectable, Pipe, HostListener, NgModule } from '@angular/core';
|
|
3
3
|
import { BrowserModule } from '@angular/platform-browser';
|
|
4
4
|
import * as i2 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
@@ -887,43 +887,54 @@ const DEFAULT_THEME = {
|
|
|
887
887
|
accentColor: '#0a84ff',
|
|
888
888
|
dangerColor: '#ff453a',
|
|
889
889
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
890
|
-
// Header / Tabs
|
|
891
890
|
tabsContainerColor: 'rgba(44,44,46,0.6)',
|
|
892
891
|
tabActiveColor: '#3a3a3c',
|
|
893
892
|
tabActiveTextColor: '#ffffff',
|
|
894
893
|
tabHoverTextColor: '#e5e5ea',
|
|
895
894
|
addWidgetButtonTextColor: '#ffffff',
|
|
896
|
-
// Pop-out
|
|
897
895
|
popoutTitleColor: '#ffffff',
|
|
898
|
-
// Widget card
|
|
899
896
|
widgetTitleColor: '#ffffff',
|
|
900
897
|
dragHandleColor: 'rgba(255,255,255,0.2)',
|
|
901
898
|
widgetBorderColor: 'rgba(255,255,255,0.07)',
|
|
902
899
|
widgetButtonBgColor: 'rgba(255,255,255,0.07)',
|
|
903
900
|
widgetButtonColor: 'rgba(255,255,255,0.5)',
|
|
904
|
-
// Grid
|
|
905
901
|
placeholderColor: '#0a84ff',
|
|
906
902
|
resizeHandleColor: 'rgba(255,255,255,0.25)',
|
|
907
903
|
};
|
|
904
|
+
class OverflowActivePipe {
|
|
905
|
+
transform(pages, activePageId) {
|
|
906
|
+
return pages.some(p => p.id === activePageId);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
OverflowActivePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OverflowActivePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
910
|
+
OverflowActivePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: OverflowActivePipe, name: "overflowActive" });
|
|
911
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OverflowActivePipe, decorators: [{
|
|
912
|
+
type: Pipe,
|
|
913
|
+
args: [{ name: 'overflowActive' }]
|
|
914
|
+
}] });
|
|
908
915
|
class DashboardComponent {
|
|
909
|
-
constructor(stateService) {
|
|
916
|
+
constructor(stateService, cdr, zone) {
|
|
910
917
|
this.stateService = stateService;
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
* The consumer should open their own dialog and call `stateService.addWidget(...)`.
|
|
914
|
-
*/
|
|
918
|
+
this.cdr = cdr;
|
|
919
|
+
this.zone = zone;
|
|
915
920
|
this.addWidgetRequested = new EventEmitter();
|
|
916
|
-
/**
|
|
917
|
-
* Emits the Widget when the user clicks the edit (pen) icon on a card.
|
|
918
|
-
* The consumer should open their own edit UI and call `stateService.updateWidget(...)`.
|
|
919
|
-
*/
|
|
920
921
|
this.editWidgetRequested = new EventEmitter();
|
|
921
922
|
this.resolvedTheme = Object.assign({}, DEFAULT_THEME);
|
|
922
923
|
this.wrapperStyles = {};
|
|
923
924
|
this.pages = [];
|
|
925
|
+
this.visiblePages = [];
|
|
926
|
+
this.hiddenCount = 0;
|
|
924
927
|
this.activePageId = '';
|
|
925
928
|
this.isPoppedOut = false;
|
|
929
|
+
this.tabSwitcherOpen = false;
|
|
926
930
|
this.subs = new Subscription();
|
|
931
|
+
// Reserved space for the overflow "+N" button and the add "+" button (px)
|
|
932
|
+
this.OVERFLOW_BTN_W = 80;
|
|
933
|
+
this.ADD_BTN_W = 52;
|
|
934
|
+
this.GAP = 6;
|
|
935
|
+
this.PADDING = 12; // 6px each side
|
|
936
|
+
// Cache of measured tab widths (including gap) indexed by page position
|
|
937
|
+
this._tabWidthCache = [];
|
|
927
938
|
}
|
|
928
939
|
ngOnChanges(changes) {
|
|
929
940
|
if (changes['theme'] || changes['initialLayout'])
|
|
@@ -945,19 +956,38 @@ class DashboardComponent {
|
|
|
945
956
|
this.isPoppedOut = true;
|
|
946
957
|
this.subs.add(this.stateService.pages$.subscribe(pages => {
|
|
947
958
|
this.pages = pages;
|
|
959
|
+
this._tabWidthCache = []; // invalidate cache — page list changed
|
|
948
960
|
if (this.isPoppedOut && hash) {
|
|
949
|
-
|
|
950
|
-
if (target)
|
|
961
|
+
if (pages.find(p => p.id === hash))
|
|
951
962
|
this.stateService.setActivePage(hash);
|
|
952
963
|
}
|
|
953
964
|
this.updateActivePage();
|
|
965
|
+
this.recalcVisibleTabs();
|
|
966
|
+
// Second pass after Angular has rendered the updated tab elements
|
|
967
|
+
setTimeout(() => this.recalcVisibleTabs());
|
|
954
968
|
}));
|
|
955
969
|
this.subs.add(this.stateService.activePageId$.subscribe(id => {
|
|
956
970
|
this.activePageId = id;
|
|
957
971
|
this.updateActivePage();
|
|
958
972
|
}));
|
|
959
973
|
}
|
|
960
|
-
|
|
974
|
+
ngAfterViewInit() {
|
|
975
|
+
if (!this.tabsTrackRef)
|
|
976
|
+
return;
|
|
977
|
+
this.zone.runOutsideAngular(() => {
|
|
978
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
979
|
+
this.zone.run(() => this.recalcVisibleTabs());
|
|
980
|
+
});
|
|
981
|
+
this.resizeObserver.observe(this.tabsTrackRef.nativeElement);
|
|
982
|
+
});
|
|
983
|
+
// Initial measurement pass now that the DOM is ready
|
|
984
|
+
setTimeout(() => this.recalcVisibleTabs());
|
|
985
|
+
}
|
|
986
|
+
ngOnDestroy() {
|
|
987
|
+
var _a;
|
|
988
|
+
this.subs.unsubscribe();
|
|
989
|
+
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
990
|
+
}
|
|
961
991
|
onItemChanged(widget) {
|
|
962
992
|
this.stateService.updateWidgetPosition(this.activePageId, widget.id, widget.x, widget.y, widget.cols, widget.rows);
|
|
963
993
|
}
|
|
@@ -978,6 +1008,85 @@ class DashboardComponent {
|
|
|
978
1008
|
this.stateService.popOutPage(pageId);
|
|
979
1009
|
}
|
|
980
1010
|
serializeLayout() { return this.stateService.serializeLayout(); }
|
|
1011
|
+
openTabSwitcher() { this.tabSwitcherOpen = true; }
|
|
1012
|
+
closeTabSwitcher() { this.tabSwitcherOpen = false; }
|
|
1013
|
+
onEscapeKey() { this.closeTabSwitcher(); }
|
|
1014
|
+
onSwitcherSelect(pageId) {
|
|
1015
|
+
this.stateService.setActivePage(pageId);
|
|
1016
|
+
this.closeTabSwitcher();
|
|
1017
|
+
}
|
|
1018
|
+
onSwitcherPopOut(event, pageId) {
|
|
1019
|
+
event.stopPropagation();
|
|
1020
|
+
this.stateService.popOutPage(pageId);
|
|
1021
|
+
this.closeTabSwitcher();
|
|
1022
|
+
}
|
|
1023
|
+
onSwitcherRemove(event, pageId) {
|
|
1024
|
+
event.stopPropagation();
|
|
1025
|
+
if (confirm('Remove this workspace?')) {
|
|
1026
|
+
this.stateService.removePage(pageId);
|
|
1027
|
+
if (this.pages.length <= 1)
|
|
1028
|
+
this.closeTabSwitcher();
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
onSwitcherAdd() {
|
|
1032
|
+
const name = prompt('Workspace name:', `Workspace ${this.pages.length + 1}`);
|
|
1033
|
+
if (name)
|
|
1034
|
+
this.stateService.addPage(name);
|
|
1035
|
+
}
|
|
1036
|
+
recalcVisibleTabs() {
|
|
1037
|
+
if (!this.tabsTrackRef || !this.pages.length) {
|
|
1038
|
+
this.visiblePages = this.pages;
|
|
1039
|
+
this.hiddenCount = 0;
|
|
1040
|
+
this.cdr.markForCheck();
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const track = this.tabsTrackRef.nativeElement;
|
|
1044
|
+
const trackW = track.clientWidth;
|
|
1045
|
+
// Space always consumed by the add "+" button + padding
|
|
1046
|
+
const baseReserved = this.ADD_BTN_W + this.GAP + this.PADDING;
|
|
1047
|
+
// Space needed for the overflow "+N" button when shown
|
|
1048
|
+
const overflowSlot = this.OVERFLOW_BTN_W + this.GAP;
|
|
1049
|
+
// Measure each real tab element currently in the DOM.
|
|
1050
|
+
// The DOM always renders all visiblePages tabs, so we may not have all tabs
|
|
1051
|
+
// measured yet — fall back to the previous measured cache or a generous estimate.
|
|
1052
|
+
const tabEls = Array.from(track.querySelectorAll('.tab'));
|
|
1053
|
+
// Build a width map by index (only covers currently visible tabs)
|
|
1054
|
+
const measuredWidths = this.pages.map((_, i) => {
|
|
1055
|
+
var _a;
|
|
1056
|
+
const el = tabEls[i];
|
|
1057
|
+
return el ? el.getBoundingClientRect().width + this.GAP : (_a = this._tabWidthCache[i]) !== null && _a !== void 0 ? _a : 150 + this.GAP;
|
|
1058
|
+
});
|
|
1059
|
+
// Update cache for next call
|
|
1060
|
+
tabEls.forEach((el, i) => {
|
|
1061
|
+
this._tabWidthCache[i] = el.getBoundingClientRect().width + this.GAP;
|
|
1062
|
+
});
|
|
1063
|
+
// How much space the tabs need in total (no overflow button)
|
|
1064
|
+
const totalNeeded = measuredWidths.reduce((s, w) => s + w, 0) - this.GAP; // remove trailing gap
|
|
1065
|
+
if (totalNeeded <= trackW - baseReserved) {
|
|
1066
|
+
// Everything fits — show all
|
|
1067
|
+
this.visiblePages = this.pages;
|
|
1068
|
+
this.hiddenCount = 0;
|
|
1069
|
+
}
|
|
1070
|
+
else {
|
|
1071
|
+
// Not everything fits — fill as many as possible while always leaving room for overflow btn
|
|
1072
|
+
const budget = trackW - baseReserved - overflowSlot;
|
|
1073
|
+
let used = 0;
|
|
1074
|
+
let count = 0;
|
|
1075
|
+
for (let i = 0; i < this.pages.length; i++) {
|
|
1076
|
+
used += measuredWidths[i];
|
|
1077
|
+
if (used - this.GAP <= budget) { // -GAP: last item has no trailing gap
|
|
1078
|
+
count++;
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
count = Math.max(1, count);
|
|
1085
|
+
this.visiblePages = this.pages.slice(0, count);
|
|
1086
|
+
this.hiddenCount = this.pages.length - count;
|
|
1087
|
+
}
|
|
1088
|
+
this.cdr.markForCheck();
|
|
1089
|
+
}
|
|
981
1090
|
applyTheme() {
|
|
982
1091
|
var _a;
|
|
983
1092
|
this.resolvedTheme = Object.assign(Object.assign({}, DEFAULT_THEME), ((_a = this.theme) !== null && _a !== void 0 ? _a : {}));
|
|
@@ -1009,48 +1118,41 @@ class DashboardComponent {
|
|
|
1009
1118
|
this.activePage = this.pages.find(p => p.id === this.activePageId);
|
|
1010
1119
|
}
|
|
1011
1120
|
}
|
|
1012
|
-
DashboardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, deps: [{ token: DashboardStateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1013
|
-
DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DashboardComponent, selector: "app-dashboard", inputs: { initialLayout: "initialLayout", theme: "theme" }, outputs: { addWidgetRequested: "addWidgetRequested", editWidgetRequested: "editWidgetRequested" }, queries: [{ propertyName: "cellTemplate", first: true, predicate: GridCellDirective, descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: `
|
|
1014
|
-
<!--
|
|
1015
|
-
POPPED-OUT MODE
|
|
1016
|
-
══════════════════════════════════════════════════════════ -->
|
|
1121
|
+
DashboardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, deps: [{ token: DashboardStateService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
1122
|
+
DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DashboardComponent, selector: "app-dashboard", inputs: { initialLayout: "initialLayout", theme: "theme" }, outputs: { addWidgetRequested: "addWidgetRequested", editWidgetRequested: "editWidgetRequested" }, host: { listeners: { "document:keydown.escape": "onEscapeKey()" } }, queries: [{ propertyName: "cellTemplate", first: true, predicate: GridCellDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "tabsTrackRef", first: true, predicate: ["tabsTrack"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
1123
|
+
<!-- POPPED-OUT MODE -->
|
|
1017
1124
|
<ng-container *ngIf="isPoppedOut; else normalMode">
|
|
1018
1125
|
<div class="popout-wrapper" [ngStyle]="wrapperStyles">
|
|
1019
1126
|
<header class="popout-header">
|
|
1020
1127
|
<span class="popout-title">{{ activePage?.name }}</span>
|
|
1021
1128
|
</header>
|
|
1022
|
-
<
|
|
1023
|
-
<
|
|
1024
|
-
<
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
>
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1035
|
-
</ng-container>
|
|
1036
|
-
</app-widget-renderer>
|
|
1037
|
-
</ng-template>
|
|
1038
|
-
</app-grid>
|
|
1039
|
-
</div>
|
|
1129
|
+
<app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
|
|
1130
|
+
<ng-template gridCell let-widget="widget">
|
|
1131
|
+
<app-widget-renderer [widget]="widget" [theme]="resolvedTheme"
|
|
1132
|
+
(editRequested)="editWidgetRequested.emit($event)"
|
|
1133
|
+
(removeRequested)="onRemoveWidget($event)">
|
|
1134
|
+
<ng-container *ngIf="cellTemplate"
|
|
1135
|
+
[ngTemplateOutlet]="cellTemplate"
|
|
1136
|
+
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1137
|
+
</ng-container>
|
|
1138
|
+
</app-widget-renderer>
|
|
1139
|
+
</ng-template>
|
|
1140
|
+
</app-grid>
|
|
1040
1141
|
</div>
|
|
1041
1142
|
</ng-container>
|
|
1042
1143
|
|
|
1043
|
-
<!--
|
|
1044
|
-
NORMAL MODE
|
|
1045
|
-
══════════════════════════════════════════════════════════ -->
|
|
1144
|
+
<!-- NORMAL MODE -->
|
|
1046
1145
|
<ng-template #normalMode>
|
|
1047
1146
|
<div class="dashboard-wrapper" [ngStyle]="wrapperStyles">
|
|
1048
1147
|
<main class="main-content">
|
|
1049
1148
|
|
|
1050
1149
|
<header class="dashboard-header">
|
|
1051
|
-
|
|
1150
|
+
|
|
1151
|
+
<!-- Tab bar -->
|
|
1152
|
+
<div class="tabs-track" #tabsTrack>
|
|
1153
|
+
<!-- Visible tabs -->
|
|
1052
1154
|
<div
|
|
1053
|
-
*ngFor="let page of
|
|
1155
|
+
*ngFor="let page of visiblePages"
|
|
1054
1156
|
class="tab"
|
|
1055
1157
|
[class.active]="page.id === activePageId"
|
|
1056
1158
|
(click)="onSelectPage(page.id)"
|
|
@@ -1063,30 +1165,81 @@ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
|
|
|
1063
1165
|
<i class="la la-times"></i>
|
|
1064
1166
|
</button>
|
|
1065
1167
|
</div>
|
|
1168
|
+
|
|
1169
|
+
<!-- Overflow button — shown only when there are hidden tabs -->
|
|
1170
|
+
<button
|
|
1171
|
+
*ngIf="hiddenCount > 0"
|
|
1172
|
+
class="btn-overflow"
|
|
1173
|
+
(click)="openTabSwitcher()"
|
|
1174
|
+
title="Show all workspaces"
|
|
1175
|
+
>
|
|
1176
|
+
<span>+{{ hiddenCount }}</span>
|
|
1177
|
+
<i class="la la-th-large"></i>
|
|
1178
|
+
</button>
|
|
1179
|
+
|
|
1180
|
+
<!-- Add page button -->
|
|
1066
1181
|
<button class="btn-add-page" (click)="onAddPage()" title="New workspace">
|
|
1067
1182
|
<i class="la la-plus"></i>
|
|
1068
1183
|
</button>
|
|
1069
1184
|
</div>
|
|
1070
1185
|
|
|
1071
|
-
<!-- Add Widget button — consumer decides what happens -->
|
|
1072
1186
|
<button class="btn-add-widget" (click)="addWidgetRequested.emit()" title="Add widget">
|
|
1073
1187
|
<i class="la la-plus"></i>
|
|
1074
1188
|
<span>Add Widget</span>
|
|
1075
1189
|
</button>
|
|
1190
|
+
|
|
1076
1191
|
</header>
|
|
1077
1192
|
|
|
1193
|
+
<!-- ── Tab-switcher overlay (Chrome mobile style) ── -->
|
|
1194
|
+
<div class="tab-switcher-overlay" *ngIf="tabSwitcherOpen" (click)="closeTabSwitcher()">
|
|
1195
|
+
<div class="tab-switcher-sheet" (click)="$event.stopPropagation()">
|
|
1196
|
+
|
|
1197
|
+
<div class="tab-switcher-header">
|
|
1198
|
+
<span class="tab-switcher-title">{{ pages.length }} Workspace{{ pages.length !== 1 ? 's' : '' }}</span>
|
|
1199
|
+
<button class="tab-switcher-close-btn" (click)="closeTabSwitcher()" title="Close">
|
|
1200
|
+
<i class="la la-times"></i>
|
|
1201
|
+
</button>
|
|
1202
|
+
</div>
|
|
1203
|
+
|
|
1204
|
+
<div class="tab-switcher-grid">
|
|
1205
|
+
<div
|
|
1206
|
+
*ngFor="let page of pages"
|
|
1207
|
+
class="tab-card"
|
|
1208
|
+
[class.active]="page.id === activePageId"
|
|
1209
|
+
(click)="onSwitcherSelect(page.id)"
|
|
1210
|
+
>
|
|
1211
|
+
<div class="tab-card-icon">
|
|
1212
|
+
<i class="la la-th-large"></i>
|
|
1213
|
+
</div>
|
|
1214
|
+
<span class="tab-card-name">{{ page.name }}</span>
|
|
1215
|
+
<div class="tab-card-actions">
|
|
1216
|
+
<button class="tab-card-btn tab-card-popout" (click)="onSwitcherPopOut($event, page.id)" title="Open in new window">
|
|
1217
|
+
<i class="la la-external-link-alt"></i>
|
|
1218
|
+
</button>
|
|
1219
|
+
<button class="tab-card-btn tab-card-remove" *ngIf="pages.length > 1" (click)="onSwitcherRemove($event, page.id)" title="Close">
|
|
1220
|
+
<i class="la la-times"></i>
|
|
1221
|
+
</button>
|
|
1222
|
+
</div>
|
|
1223
|
+
</div>
|
|
1224
|
+
</div>
|
|
1225
|
+
|
|
1226
|
+
<div class="tab-switcher-footer">
|
|
1227
|
+
<button class="tab-switcher-add-btn" (click)="onSwitcherAdd()">
|
|
1228
|
+
<i class="la la-plus"></i>
|
|
1229
|
+
<span>New Workspace</span>
|
|
1230
|
+
</button>
|
|
1231
|
+
</div>
|
|
1232
|
+
|
|
1233
|
+
</div>
|
|
1234
|
+
</div>
|
|
1235
|
+
|
|
1078
1236
|
<div class="grid-container">
|
|
1079
1237
|
<app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
|
|
1080
1238
|
<ng-template gridCell let-widget="widget">
|
|
1081
|
-
<app-widget-renderer
|
|
1082
|
-
[widget]="widget"
|
|
1083
|
-
[theme]="resolvedTheme"
|
|
1239
|
+
<app-widget-renderer [widget]="widget" [theme]="resolvedTheme"
|
|
1084
1240
|
(editRequested)="editWidgetRequested.emit($event)"
|
|
1085
|
-
(removeRequested)="onRemoveWidget($event)"
|
|
1086
|
-
|
|
1087
|
-
<!-- Stamp consumer's cell template (if provided) inside the card body -->
|
|
1088
|
-
<ng-container
|
|
1089
|
-
*ngIf="cellTemplate"
|
|
1241
|
+
(removeRequested)="onRemoveWidget($event)">
|
|
1242
|
+
<ng-container *ngIf="cellTemplate"
|
|
1090
1243
|
[ngTemplateOutlet]="cellTemplate"
|
|
1091
1244
|
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1092
1245
|
</ng-container>
|
|
@@ -1098,50 +1251,43 @@ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", ver
|
|
|
1098
1251
|
</main>
|
|
1099
1252
|
</div>
|
|
1100
1253
|
</ng-template>
|
|
1101
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05)}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;
|
|
1254
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05);position:relative}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid rgba(255,255,255,.06);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-track{display:flex;align-items:center;gap:6px;flex:1;min-width:0;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow:hidden}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:background .2s,color .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:rgba(255,255,255,.05)}.tab-name{white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.18)}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.btn-overflow{display:inline-flex;align-items:center;gap:5px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.12);border-radius:20px;padding:7px 13px;cursor:pointer;font-size:13px;font-weight:600;color:var(--dash-tab-active-text);white-space:nowrap;flex-shrink:0;transition:background .2s,border-color .2s}.btn-overflow:hover{background:rgba(10,132,255,.18);border-color:var(--dash-accent-color);color:var(--dash-accent-color)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 14px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.tab-switcher-overlay{position:absolute;inset:0;z-index:1000;background:rgba(0,0,0,.55);backdrop-filter:blur(4px);display:flex;align-items:flex-start;justify-content:center;padding-top:60px;animation:overlay-in .18s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.tab-switcher-sheet{background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.08);border-radius:24px;width:min(520px,calc(100% - 32px));max-height:calc(100% - 80px);display:flex;flex-direction:column;overflow:hidden;animation:sheet-in .22s cubic-bezier(.32,1.2,.5,1)}@keyframes sheet-in{0%{transform:translateY(-16px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.tab-switcher-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0}.tab-switcher-title{font-size:15px;font-weight:700;color:var(--dash-tab-active-text)}.tab-switcher-close-btn{background:rgba(255,255,255,.07);border:none;color:var(--dash-fore-color);width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:background .15s,color .15s}.tab-switcher-close-btn:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.tab-switcher-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px;padding:16px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.15) transparent}.tab-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 12px 12px;border-radius:16px;background:var(--dash-card-bg);border:1.5px solid transparent;cursor:pointer;transition:border-color .15s,background .15s,transform .12s;position:relative}.tab-card:hover{background:rgba(255,255,255,.06);transform:translateY(-2px)}.tab-card.active{border-color:var(--dash-accent-color);background:rgba(10,132,255,.12)}.tab-card-icon{width:44px;height:44px;border-radius:12px;background:rgba(255,255,255,.07);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--dash-fore-color)}.tab-card.active .tab-card-icon{background:rgba(10,132,255,.25);color:var(--dash-accent-color)}.tab-card-name{font-size:13px;font-weight:500;color:var(--dash-tab-active-text);text-align:center;word-break:break-word;line-height:1.3}.tab-card-actions{display:flex;gap:4px;opacity:0;transition:opacity .15s}.tab-card:hover .tab-card-actions{opacity:1}.tab-card-btn{background:rgba(255,255,255,.07);border:none;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:12px;color:var(--dash-fore-color);transition:background .15s,color .15s}.tab-card-popout:hover{background:rgba(10,132,255,.25);color:var(--dash-accent-color)}.tab-card-remove:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.tab-switcher-footer{padding:12px 16px 16px;border-top:1px solid rgba(255,255,255,.06);flex-shrink:0}.tab-switcher-add-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:11px 20px;border-radius:16px;background:rgba(10,132,255,.15);border:1.5px dashed rgba(10,132,255,.4);color:var(--dash-accent-color);font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s}.tab-switcher-add-btn:hover{background:rgba(10,132,255,.25);border-color:var(--dash-accent-color)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: WidgetRendererComponent, selector: "app-widget-renderer", inputs: ["widget", "theme"], outputs: ["editRequested", "removeRequested"] }, { kind: "component", type: CustomGridComponent, selector: "app-grid", inputs: ["widgets", "columns", "gap", "rowHeight", "minItemCols", "minItemRows"], outputs: ["itemChanged", "layoutChanged"] }, { kind: "directive", type: GridCellDirective, selector: "[gridCell]" }] });
|
|
1102
1255
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, decorators: [{
|
|
1103
1256
|
type: Component,
|
|
1104
1257
|
args: [{ selector: 'app-dashboard', template: `
|
|
1105
|
-
<!--
|
|
1106
|
-
POPPED-OUT MODE
|
|
1107
|
-
══════════════════════════════════════════════════════════ -->
|
|
1258
|
+
<!-- POPPED-OUT MODE -->
|
|
1108
1259
|
<ng-container *ngIf="isPoppedOut; else normalMode">
|
|
1109
1260
|
<div class="popout-wrapper" [ngStyle]="wrapperStyles">
|
|
1110
1261
|
<header class="popout-header">
|
|
1111
1262
|
<span class="popout-title">{{ activePage?.name }}</span>
|
|
1112
1263
|
</header>
|
|
1113
|
-
<
|
|
1114
|
-
<
|
|
1115
|
-
<
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
>
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1126
|
-
</ng-container>
|
|
1127
|
-
</app-widget-renderer>
|
|
1128
|
-
</ng-template>
|
|
1129
|
-
</app-grid>
|
|
1130
|
-
</div>
|
|
1264
|
+
<app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
|
|
1265
|
+
<ng-template gridCell let-widget="widget">
|
|
1266
|
+
<app-widget-renderer [widget]="widget" [theme]="resolvedTheme"
|
|
1267
|
+
(editRequested)="editWidgetRequested.emit($event)"
|
|
1268
|
+
(removeRequested)="onRemoveWidget($event)">
|
|
1269
|
+
<ng-container *ngIf="cellTemplate"
|
|
1270
|
+
[ngTemplateOutlet]="cellTemplate"
|
|
1271
|
+
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1272
|
+
</ng-container>
|
|
1273
|
+
</app-widget-renderer>
|
|
1274
|
+
</ng-template>
|
|
1275
|
+
</app-grid>
|
|
1131
1276
|
</div>
|
|
1132
1277
|
</ng-container>
|
|
1133
1278
|
|
|
1134
|
-
<!--
|
|
1135
|
-
NORMAL MODE
|
|
1136
|
-
══════════════════════════════════════════════════════════ -->
|
|
1279
|
+
<!-- NORMAL MODE -->
|
|
1137
1280
|
<ng-template #normalMode>
|
|
1138
1281
|
<div class="dashboard-wrapper" [ngStyle]="wrapperStyles">
|
|
1139
1282
|
<main class="main-content">
|
|
1140
1283
|
|
|
1141
1284
|
<header class="dashboard-header">
|
|
1142
|
-
|
|
1285
|
+
|
|
1286
|
+
<!-- Tab bar -->
|
|
1287
|
+
<div class="tabs-track" #tabsTrack>
|
|
1288
|
+
<!-- Visible tabs -->
|
|
1143
1289
|
<div
|
|
1144
|
-
*ngFor="let page of
|
|
1290
|
+
*ngFor="let page of visiblePages"
|
|
1145
1291
|
class="tab"
|
|
1146
1292
|
[class.active]="page.id === activePageId"
|
|
1147
1293
|
(click)="onSelectPage(page.id)"
|
|
@@ -1154,30 +1300,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1154
1300
|
<i class="la la-times"></i>
|
|
1155
1301
|
</button>
|
|
1156
1302
|
</div>
|
|
1303
|
+
|
|
1304
|
+
<!-- Overflow button — shown only when there are hidden tabs -->
|
|
1305
|
+
<button
|
|
1306
|
+
*ngIf="hiddenCount > 0"
|
|
1307
|
+
class="btn-overflow"
|
|
1308
|
+
(click)="openTabSwitcher()"
|
|
1309
|
+
title="Show all workspaces"
|
|
1310
|
+
>
|
|
1311
|
+
<span>+{{ hiddenCount }}</span>
|
|
1312
|
+
<i class="la la-th-large"></i>
|
|
1313
|
+
</button>
|
|
1314
|
+
|
|
1315
|
+
<!-- Add page button -->
|
|
1157
1316
|
<button class="btn-add-page" (click)="onAddPage()" title="New workspace">
|
|
1158
1317
|
<i class="la la-plus"></i>
|
|
1159
1318
|
</button>
|
|
1160
1319
|
</div>
|
|
1161
1320
|
|
|
1162
|
-
<!-- Add Widget button — consumer decides what happens -->
|
|
1163
1321
|
<button class="btn-add-widget" (click)="addWidgetRequested.emit()" title="Add widget">
|
|
1164
1322
|
<i class="la la-plus"></i>
|
|
1165
1323
|
<span>Add Widget</span>
|
|
1166
1324
|
</button>
|
|
1325
|
+
|
|
1167
1326
|
</header>
|
|
1168
1327
|
|
|
1328
|
+
<!-- ── Tab-switcher overlay (Chrome mobile style) ── -->
|
|
1329
|
+
<div class="tab-switcher-overlay" *ngIf="tabSwitcherOpen" (click)="closeTabSwitcher()">
|
|
1330
|
+
<div class="tab-switcher-sheet" (click)="$event.stopPropagation()">
|
|
1331
|
+
|
|
1332
|
+
<div class="tab-switcher-header">
|
|
1333
|
+
<span class="tab-switcher-title">{{ pages.length }} Workspace{{ pages.length !== 1 ? 's' : '' }}</span>
|
|
1334
|
+
<button class="tab-switcher-close-btn" (click)="closeTabSwitcher()" title="Close">
|
|
1335
|
+
<i class="la la-times"></i>
|
|
1336
|
+
</button>
|
|
1337
|
+
</div>
|
|
1338
|
+
|
|
1339
|
+
<div class="tab-switcher-grid">
|
|
1340
|
+
<div
|
|
1341
|
+
*ngFor="let page of pages"
|
|
1342
|
+
class="tab-card"
|
|
1343
|
+
[class.active]="page.id === activePageId"
|
|
1344
|
+
(click)="onSwitcherSelect(page.id)"
|
|
1345
|
+
>
|
|
1346
|
+
<div class="tab-card-icon">
|
|
1347
|
+
<i class="la la-th-large"></i>
|
|
1348
|
+
</div>
|
|
1349
|
+
<span class="tab-card-name">{{ page.name }}</span>
|
|
1350
|
+
<div class="tab-card-actions">
|
|
1351
|
+
<button class="tab-card-btn tab-card-popout" (click)="onSwitcherPopOut($event, page.id)" title="Open in new window">
|
|
1352
|
+
<i class="la la-external-link-alt"></i>
|
|
1353
|
+
</button>
|
|
1354
|
+
<button class="tab-card-btn tab-card-remove" *ngIf="pages.length > 1" (click)="onSwitcherRemove($event, page.id)" title="Close">
|
|
1355
|
+
<i class="la la-times"></i>
|
|
1356
|
+
</button>
|
|
1357
|
+
</div>
|
|
1358
|
+
</div>
|
|
1359
|
+
</div>
|
|
1360
|
+
|
|
1361
|
+
<div class="tab-switcher-footer">
|
|
1362
|
+
<button class="tab-switcher-add-btn" (click)="onSwitcherAdd()">
|
|
1363
|
+
<i class="la la-plus"></i>
|
|
1364
|
+
<span>New Workspace</span>
|
|
1365
|
+
</button>
|
|
1366
|
+
</div>
|
|
1367
|
+
|
|
1368
|
+
</div>
|
|
1369
|
+
</div>
|
|
1370
|
+
|
|
1169
1371
|
<div class="grid-container">
|
|
1170
1372
|
<app-grid [widgets]="activePage?.widgets || []" (itemChanged)="onItemChanged($event)">
|
|
1171
1373
|
<ng-template gridCell let-widget="widget">
|
|
1172
|
-
<app-widget-renderer
|
|
1173
|
-
[widget]="widget"
|
|
1174
|
-
[theme]="resolvedTheme"
|
|
1374
|
+
<app-widget-renderer [widget]="widget" [theme]="resolvedTheme"
|
|
1175
1375
|
(editRequested)="editWidgetRequested.emit($event)"
|
|
1176
|
-
(removeRequested)="onRemoveWidget($event)"
|
|
1177
|
-
|
|
1178
|
-
<!-- Stamp consumer's cell template (if provided) inside the card body -->
|
|
1179
|
-
<ng-container
|
|
1180
|
-
*ngIf="cellTemplate"
|
|
1376
|
+
(removeRequested)="onRemoveWidget($event)">
|
|
1377
|
+
<ng-container *ngIf="cellTemplate"
|
|
1181
1378
|
[ngTemplateOutlet]="cellTemplate"
|
|
1182
1379
|
[ngTemplateOutletContext]="{ widget: widget }">
|
|
1183
1380
|
</ng-container>
|
|
@@ -1189,8 +1386,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1189
1386
|
</main>
|
|
1190
1387
|
</div>
|
|
1191
1388
|
</ng-template>
|
|
1192
|
-
`, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05)}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;
|
|
1193
|
-
}], ctorParameters: function () { return [{ type: DashboardStateService }]; }, propDecorators: { initialLayout: [{
|
|
1389
|
+
`, styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;--dash-tabs-container-color: rgba(44,44,46,.6);--dash-tab-active-color: #3a3a3c;--dash-tab-active-text: #ffffff;--dash-tab-hover-text: #e5e5ea;--dash-add-widget-text: #ffffff;--dash-popout-title-color: #ffffff;--dash-widget-title-color: #ffffff;--dash-drag-handle-color: rgba(255,255,255,.2);--dash-widget-border-color: rgba(255,255,255,.07);--dash-widget-btn-bg: rgba(255,255,255,.07);--dash-widget-btn-color: rgba(255,255,255,.5);--dash-placeholder-color: #0a84ff;--dash-resize-handle-color: rgba(255,255,255,.25)}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.05);position:relative}.popout-wrapper{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.popout-header{display:flex;align-items:center;margin-bottom:16px;padding:10px 18px;background:var(--dash-panel-bg);border-radius:20px;border:1px solid rgba(255,255,255,.06);flex-shrink:0}.popout-title{font-size:16px;font-weight:700;color:var(--dash-popout-title-color)}.popout-wrapper app-grid{flex:1;min-height:0;overflow:auto}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px;flex-shrink:0}.tabs-track{display:flex;align-items:center;gap:6px;flex:1;min-width:0;background:var(--dash-tabs-container-color);backdrop-filter:blur(10px);border-radius:25px;padding:6px;overflow:hidden}.tab{display:flex;align-items:center;gap:4px;padding:8px 14px 8px 18px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);white-space:nowrap;flex-shrink:0;transition:background .2s,color .2s}.tab.active{background:var(--dash-tab-active-color);color:var(--dash-tab-active-text)}.tab:hover:not(.active){color:var(--dash-tab-hover-text);background:rgba(255,255,255,.05)}.tab-name{white-space:nowrap}.tab-action{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:11px;cursor:pointer;opacity:0;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.tab:hover .tab-action{opacity:1}.tab-popout:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.18)}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.btn-overflow{display:inline-flex;align-items:center;gap:5px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.12);border-radius:20px;padding:7px 13px;cursor:pointer;font-size:13px;font-weight:600;color:var(--dash-tab-active-text);white-space:nowrap;flex-shrink:0;transition:background .2s,border-color .2s}.btn-overflow:hover{background:rgba(10,132,255,.18);border-color:var(--dash-accent-color);color:var(--dash-accent-color)}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 14px;cursor:pointer;border-radius:20px;flex-shrink:0;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.tab-switcher-overlay{position:absolute;inset:0;z-index:1000;background:rgba(0,0,0,.55);backdrop-filter:blur(4px);display:flex;align-items:flex-start;justify-content:center;padding-top:60px;animation:overlay-in .18s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.tab-switcher-sheet{background:var(--dash-panel-bg);border:1px solid rgba(255,255,255,.08);border-radius:24px;width:min(520px,calc(100% - 32px));max-height:calc(100% - 80px);display:flex;flex-direction:column;overflow:hidden;animation:sheet-in .22s cubic-bezier(.32,1.2,.5,1)}@keyframes sheet-in{0%{transform:translateY(-16px) scale(.97);opacity:0}to{transform:translateY(0) scale(1);opacity:1}}.tab-switcher-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0}.tab-switcher-title{font-size:15px;font-weight:700;color:var(--dash-tab-active-text)}.tab-switcher-close-btn{background:rgba(255,255,255,.07);border:none;color:var(--dash-fore-color);width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:background .15s,color .15s}.tab-switcher-close-btn:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.tab-switcher-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px;padding:16px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.15) transparent}.tab-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px 12px 12px;border-radius:16px;background:var(--dash-card-bg);border:1.5px solid transparent;cursor:pointer;transition:border-color .15s,background .15s,transform .12s;position:relative}.tab-card:hover{background:rgba(255,255,255,.06);transform:translateY(-2px)}.tab-card.active{border-color:var(--dash-accent-color);background:rgba(10,132,255,.12)}.tab-card-icon{width:44px;height:44px;border-radius:12px;background:rgba(255,255,255,.07);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--dash-fore-color)}.tab-card.active .tab-card-icon{background:rgba(10,132,255,.25);color:var(--dash-accent-color)}.tab-card-name{font-size:13px;font-weight:500;color:var(--dash-tab-active-text);text-align:center;word-break:break-word;line-height:1.3}.tab-card-actions{display:flex;gap:4px;opacity:0;transition:opacity .15s}.tab-card:hover .tab-card-actions{opacity:1}.tab-card-btn{background:rgba(255,255,255,.07);border:none;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:12px;color:var(--dash-fore-color);transition:background .15s,color .15s}.tab-card-popout:hover{background:rgba(10,132,255,.25);color:var(--dash-accent-color)}.tab-card-remove:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.tab-switcher-footer{padding:12px 16px 16px;border-top:1px solid rgba(255,255,255,.06);flex-shrink:0}.tab-switcher-add-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:11px 20px;border-radius:16px;background:rgba(10,132,255,.15);border:1.5px dashed rgba(10,132,255,.4);color:var(--dash-accent-color);font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s}.tab-switcher-add-btn:hover{background:rgba(10,132,255,.25);border-color:var(--dash-accent-color)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:var(--dash-add-widget-text);font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:opacity .2s,transform .15s}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.main-content .grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}app-grid{background:transparent;display:block;height:100%;width:100%}\n"] }]
|
|
1390
|
+
}], ctorParameters: function () { return [{ type: DashboardStateService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { initialLayout: [{
|
|
1194
1391
|
type: Input
|
|
1195
1392
|
}], theme: [{
|
|
1196
1393
|
type: Input
|
|
@@ -1201,15 +1398,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1201
1398
|
}], cellTemplate: [{
|
|
1202
1399
|
type: ContentChild,
|
|
1203
1400
|
args: [GridCellDirective, { read: TemplateRef }]
|
|
1401
|
+
}], tabsTrackRef: [{
|
|
1402
|
+
type: ViewChild,
|
|
1403
|
+
args: ['tabsTrack']
|
|
1404
|
+
}], onEscapeKey: [{
|
|
1405
|
+
type: HostListener,
|
|
1406
|
+
args: ['document:keydown.escape']
|
|
1204
1407
|
}] } });
|
|
1205
1408
|
|
|
1206
1409
|
class DashboardModule {
|
|
1207
1410
|
}
|
|
1208
1411
|
DashboardModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1209
1412
|
DashboardModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: DashboardModule, declarations: [DashboardComponent,
|
|
1413
|
+
OverflowActivePipe,
|
|
1210
1414
|
WidgetRendererComponent,
|
|
1211
1415
|
CustomGridComponent,
|
|
1212
1416
|
GridCellDirective], imports: [CommonModule], exports: [DashboardComponent,
|
|
1417
|
+
OverflowActivePipe,
|
|
1213
1418
|
WidgetRendererComponent,
|
|
1214
1419
|
CustomGridComponent,
|
|
1215
1420
|
GridCellDirective] });
|
|
@@ -1219,6 +1424,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1219
1424
|
args: [{
|
|
1220
1425
|
declarations: [
|
|
1221
1426
|
DashboardComponent,
|
|
1427
|
+
OverflowActivePipe,
|
|
1222
1428
|
WidgetRendererComponent,
|
|
1223
1429
|
CustomGridComponent,
|
|
1224
1430
|
GridCellDirective,
|
|
@@ -1229,6 +1435,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1229
1435
|
providers: [DashboardStateService],
|
|
1230
1436
|
exports: [
|
|
1231
1437
|
DashboardComponent,
|
|
1438
|
+
OverflowActivePipe,
|
|
1232
1439
|
WidgetRendererComponent,
|
|
1233
1440
|
CustomGridComponent,
|
|
1234
1441
|
GridCellDirective,
|
|
@@ -1260,5 +1467,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
1260
1467
|
* Generated bundle index. Do not edit.
|
|
1261
1468
|
*/
|
|
1262
1469
|
|
|
1263
|
-
export { AppModule, CustomGridComponent, DashboardComponent, DashboardModule, DashboardStateService, GridCellDirective, WidgetRendererComponent };
|
|
1470
|
+
export { AppModule, CustomGridComponent, DashboardComponent, DashboardModule, DashboardStateService, GridCellDirective, OverflowActivePipe, WidgetRendererComponent };
|
|
1264
1471
|
//# sourceMappingURL=ogidor-dashboard.mjs.map
|